<commit_before>define( ['dojo/_base/declare',
         'dojo/_base/array',
         'JBrowse/View/Track/Wiggle',
         'JBrowse/Util',
         'JBrowse/View/Track/_AlignmentsMixin',
         'JBrowse/Store/SeqFeature/SNPCoverage'
        ],
        function( declare, array, Wiggle, Util, AlignmentsMixin, SNPCoverageStore ) {

var dojof = Util.dojof;

return declare( [Wiggle, AlignmentsMixin],
{
    constructor: function() {
        // force conf variables that are meaningless for this kind of track, and maybe harmful
        delete this.config.bicolor_pivot;
        delete this.config.scale;
        delete this.config.align;

        this.store = new SNPCoverageStore({ store: this.store, browser: this.browser });
    },

    _defaultConfig: function() {
        return Util.deepUpdate(
            dojo.clone( this.inherited(arguments) ),
            {
                autoscale: 'local',
                min_score: 0
            }
        );
    },

    /*
     * Draw a set of features on the canvas.
     * @private
     */
    _drawFeatures: function( scale, leftBase, rightBase, block, canvas, features, featureRects, dataScale ) {
        var thisB = this;
        var context = canvas.getContext('2d');
        var canvasHeight = canvas.height;
        var toY = dojo.hitch( this, function( val ) {
           return canvasHeight * ( 1-dataScale.normalize.call(this, val) );
        });
        var originY = toY( dataScale.origin );

        // a canvas element below the histogram that will contain indicators of likely SNPs
        var snpCanvasHeight = parseInt( block.parentNode.style.height ) - canvas.height;
        var snpCanvas = dojo.create('canvas',
                                    {height: snpCanvasHeight,
                                     width: canvas.width,
                                     style: {
                                         cursor: 'default',
                                         width: "100%",
                                         height: snpCanvasHeight + "px"
                                     },
                                     innerHTML: 'Your web browser cannot display this type of track.',
                                     className: 'SNP-indicator-track'
                                 }, block);
        var snpContext = snpCanvas.getContext('2d');

        var negColor  = this.config.style.neg_color;
        var clipColor = this.config.style.clip_marker_color;
        var bgColor   = this.config.style.bg_color;
        var disableClipMarkers = this.config.disable_clip_markers;

        var drawRectangle = function(ID, yPos, height, fRect) {
            // draw the background color if we are configured to do so
            if( bgColor && yPos >= 0 ) {
                context.fillStyle = bgColor;
                context.fillRect( fRect.l, 0, fRect.w, canvasHeight );
            }

            if( yPos <= canvasHeight ) { // if the rectangle is visible at all
                context.fillStyle = thisB.colorForBase(ID);
                if( yPos <= originY ) {
                    // bar goes upward
                    context.fillRect( fRect.l, yPos, fRect.w, height);
                    if( !disableClipMarkers && yPos < 0 ) { // draw clip marker if necessary
                        context.fillStyle = clipColor || negColor;
                        context.fillRect( fRect.l, 0, fRect.w, 2 );
                    }
                }
                else {
                    // bar goes downward
                    context.fillRect( fRect.l, originY, fRect.w, height );
                    if( !disableClipMarkers && yPos >= canvasHeight ) { // draw clip marker if necessary
                        context.fillStyle = clipColor || thisB.colorForBase(ID);
                        context.fillRect( fRect.l, canvasHeight-3, fRect.w, 2 );
                    }
                }
            }
        };

        dojo.forEach( features, function(f,i) {
            var fRect = featureRects[i];
            var score = f.get('score');
            var totalHeight = score.total();

            // draw indicators of SNPs if base coverage is greater than 50% of total coverage
            score.forEach( function( count, category ) {
                if ( category != 'reference' && count > 0.5*totalHeight ) {
                    snpContext.beginPath();
                    snpContext.arc( fRect.l + 0.5*fRect.w,
                                    0.40*snpCanvas.height,
                                    0.20*snpCanvas.height,
                                    1.75 * Math.PI,
                                    1.25 * Math.PI,
                                    false);
                    snpContext.lineTo(fRect.l + 0.5*fRect.w, 0);
                    snpContext.closePath();
                    snpContext.fillStyle = thisB.colorForBase(category);
                    snpContext.fill();
                    snpContext.lineWidth = 1;
                    snpContext.strokeStyle = 'black';
                    snpContext.stroke();
                }
            });

            // Note: 'reference' is done first to ensure the grey part of the graph is on top
            drawRectangle( 'reference', toY(totalHeight), originY-toY( score.get('reference'))+1, fRect);
            totalHeight -= score.get('reference');

            score.forEach( function( count, category ) {
                if ( category != 'reference' ) {
                    drawRectangle( category, toY(totalHeight), originY-toY( count )+1, fRect);
                    totalHeight -= count;
                }
            });
        }, this );
    },

    /*
     * The following method is required to override the equivalent method in "WiggleBase.js"
     * It displays more complete data.
     */
    _showPixelValue: function( scoreDisplay, score ) {
        if( ! score )
            return false;

        function fmtNum( num ) {
            return parseFloat( num ).toPrecision(6).replace(/0+$/,'').replace(/\.$/,'');
        }

        if( score.snpsCounted ) {
            var total = score.total();
            var scoreSummary = '
';
            function pctString( count ) {
                return Math.round(count/total*100)+'%';
            }
            scoreSummary +=
                  '
'
                + (score.refBase ? score.refBase+'*' : 'Ref')
                + '	'
                + fmtNum( score.get('reference') )
                + '	'
                + pctString( score.get('reference') )
                + '
';

            score.forEach( function( count, category ) {
                if( category == 'reference' ) return;

                // if this count has more nested categories, do counts of those
                var subdistribution = '';
                if( count.forEach ) {
                    subdistribution = [];
                    count.forEach( function( count, category ) {
                        subdistribution.push( fmtNum(count) + ' '+category );
                    });
                    subdistribution = subdistribution.join(', ');
                    if( subdistribution )
                        subdistribution = '('+subdistribution+')';
                }

                category = { '*': 'del' }[category] || category;
                scoreSummary += '
'+category + '	' + fmtNum(count) + '	'
                                   +pctString(count)+'	'+subdistribution + '
';
            });
            scoreSummary += '
Total	'+fmtNum(total)+'
';
            scoreDisplay.innerHTML = scoreSummary+'
';
            return true;
        } else {
            scoreDisplay.innerHTML = '

Total	'+fmtNum(score)+'

';
            return true;
        }
    }
});
});<commit_msg>make SNPCoverage track inherit from Wiggle/XYPlot, not Wiggle placeholder<commit_after>define( ['dojo/_base/declare',
         'dojo/_base/array',
         'JBrowse/View/Track/Wiggle/XYPlot',
         'JBrowse/Util',
         'JBrowse/View/Track/_AlignmentsMixin',
         'JBrowse/Store/SeqFeature/SNPCoverage'
        ],
        function( declare, array, WiggleXY, Util, AlignmentsMixin, SNPCoverageStore ) {

var dojof = Util.dojof;

return declare( [WiggleXY, AlignmentsMixin],
{
    constructor: function() {
        // force conf variables that are meaningless for this kind of track, and maybe harmful
        delete this.config.bicolor_pivot;
        delete this.config.scale;
        delete this.config.align;

        this.store = new SNPCoverageStore({ store: this.store, browser: this.browser });
    },

    _defaultConfig: function() {
        return Util.deepUpdate(
            dojo.clone( this.inherited(arguments) ),
            {
                autoscale: 'local',
                min_score: 0
            }
        );
    },

    /*
     * Draw a set of features on the canvas.
     * @private
     */
    _drawFeatures: function( scale, leftBase, rightBase, block, canvas, features, featureRects, dataScale ) {
        var thisB = this;
        var context = canvas.getContext('2d');
        var canvasHeight = canvas.height;
        var toY = dojo.hitch( this, function( val ) {
           return canvasHeight * ( 1-dataScale.normalize.call(this, val) );
        });
        var originY = toY( dataScale.origin );

        // a canvas element below the histogram that will contain indicators of likely SNPs
        var snpCanvasHeight = parseInt( block.parentNode.style.height ) - canvas.height;
        var snpCanvas = dojo.create('canvas',
                                    {height: snpCanvasHeight,
                                     width: canvas.width,
                                     style: {
                                         cursor: 'default',
                                         width: "100%",
                                         height: snpCanvasHeight + "px"
                                     },
                                     innerHTML: 'Your web browser cannot display this type of track.',
                                     className: 'SNP-indicator-track'
                                 }, block);
        var snpContext = snpCanvas.getContext('2d');

        var negColor  = this.config.style.neg_color;
        var clipColor = this.config.style.clip_marker_color;
        var bgColor   = this.config.style.bg_color;
        var disableClipMarkers = this.config.disable_clip_markers;

        var drawRectangle = function(ID, yPos, height, fRect) {
            // draw the background color if we are configured to do so
            if( bgColor && yPos >= 0 ) {
                context.fillStyle = bgColor;
                context.fillRect( fRect.l, 0, fRect.w, canvasHeight );
            }

            if( yPos <= canvasHeight ) { // if the rectangle is visible at all
                context.fillStyle = thisB.colorForBase(ID);
                if( yPos <= originY ) {
                    // bar goes upward
                    context.fillRect( fRect.l, yPos, fRect.w, height);
                    if( !disableClipMarkers && yPos < 0 ) { // draw clip marker if necessary
                        context.fillStyle = clipColor || negColor;
                        context.fillRect( fRect.l, 0, fRect.w, 2 );
                    }
                }
                else {
                    // bar goes downward
                    context.fillRect( fRect.l, originY, fRect.w, height );
                    if( !disableClipMarkers && yPos >= canvasHeight ) { // draw clip marker if necessary
                        context.fillStyle = clipColor || thisB.colorForBase(ID);
                        context.fillRect( fRect.l, canvasHeight-3, fRect.w, 2 );
                    }
                }
            }
        };

        dojo.forEach( features, function(f,i) {
            var fRect = featureRects[i];
            var score = f.get('score');
            var totalHeight = score.total();

            // draw indicators of SNPs if base coverage is greater than 50% of total coverage
            score.forEach( function( count, category ) {
                if ( category != 'reference' && count > 0.5*totalHeight ) {
                    snpContext.beginPath();
                    snpContext.arc( fRect.l + 0.5*fRect.w,
                                    0.40*snpCanvas.height,
                                    0.20*snpCanvas.height,
                                    1.75 * Math.PI,
                                    1.25 * Math.PI,
                                    false);
                    snpContext.lineTo(fRect.l + 0.5*fRect.w, 0);
                    snpContext.closePath();
                    snpContext.fillStyle = thisB.colorForBase(category);
                    snpContext.fill();
                    snpContext.lineWidth = 1;
                    snpContext.strokeStyle = 'black';
                    snpContext.stroke();
                }
            });

            // Note: 'reference' is done first to ensure the grey part of the graph is on top
            drawRectangle( 'reference', toY(totalHeight), originY-toY( score.get('reference'))+1, fRect);
            totalHeight -= score.get('reference');

            score.forEach( function( count, category ) {
                if ( category != 'reference' ) {
                    drawRectangle( category, toY(totalHeight), originY-toY( count )+1, fRect);
                    totalHeight -= count;
                }
            });
        }, this );
    },

    /*
     * The following method is required to override the equivalent method in "WiggleBase.js"
     * It displays more complete data.
     */
    _showPixelValue: function( scoreDisplay, score ) {
        if( ! score )
            return false;

        function fmtNum( num ) {
            return parseFloat( num ).toPrecision(6).replace(/0+$/,'').replace(/\.$/,'');
        }

        if( score.snpsCounted ) {
            var total = score.total();
            var scoreSummary = '
';
            function pctString( count ) {
                return Math.round(count/total*100)+'%';
            }
            scoreSummary +=
                  '
'
                + (score.refBase ? score.refBase+'*' : 'Ref')
                + '	'
                + fmtNum( score.get('reference') )
                + '	'
                + pctString( score.get('reference') )
                + '
';

            score.forEach( function( count, category ) {
                if( category == 'reference' ) return;

                // if this count has more nested categories, do counts of those
                var subdistribution = '';
                if( count.forEach ) {
                    subdistribution = [];
                    count.forEach( function( count, category ) {
                        subdistribution.push( fmtNum(count) + ' '+category );
                    });
                    subdistribution = subdistribution.join(', ');
                    if( subdistribution )
                        subdistribution = '('+subdistribution+')';
                }

                category = { '*': 'del' }[category] || category;
                scoreSummary += '
'+category + '	' + fmtNum(count) + '	'
                                   +pctString(count)+'	'+subdistribution + '
';
            });
            scoreSummary += '
Total	'+fmtNum(total)+'
';
            scoreDisplay.innerHTML = scoreSummary+'
';
            return true;
        } else {
            scoreDisplay.innerHTML = '

Total	'+fmtNum(score)+'

';
            return true;
        }
    }
});
});<|endoftext|>


<commit_before>// Test opening a rich notebook, saving it, and reopening it again.
//
//toJSON fromJSON toJSON and do a string comparison

// this is just a copy of OutputArea.mime_mape_r in IPython/html/static/notebook/js/outputarea.js
mime =  {
        "text" : "text/plain",
        "html" : "text/html",
        "svg" : "image/svg+xml",
        "png" : "image/png",
        "jpeg" : "image/jpeg",
        "latex" : "text/latex",
        "json" : "application/json",
        "javascript" : "application/javascript",
    };

// helper function to ensure that the short_name is found in the toJSON
// represetnation, while the original in-memory cell retains its long mimetype
// name, and that fromJSON also gets its long mimetype name
function assert_has(short_name, json, result, result2) {
    long_name = mime[short_name];
    this.test.assertTrue(json[0].hasOwnProperty(short_name),
            'toJSON()   representation uses ' + short_name);
    this.test.assertTrue(result.hasOwnProperty(long_name),
            'toJSON()   original embeded JSON keeps ' + long_name);
    this.test.assertTrue(result2.hasOwnProperty(long_name),
            'fromJSON() embeded ' + short_name + ' gets mime key ' + long_name);
}

// helper function for checkout that the first two cells have a particular
// output_type (either 'pyout' or 'display_data'), and checks the to/fromJSON
// for a set of mimetype keys, using their short names ('javascript', 'text',
// 'png', etc).
function check_output_area(output_type, keys) {
    json = this.evaluate(function() {
        var json = IPython.notebook.get_cell(0).output_area.toJSON();
        // appended cell will initially be empty, lets add it some output
        var cell = IPython.notebook.get_cell(1).output_area.fromJSON(json);
        return json;
    });
    var result = this.get_output_cell(0);
    var result2 = this.get_output_cell(1);
    this.test.assertEquals(result.output_type, output_type,
        'testing ' + output_type + ' for ' + keys.join(' and '));

    for (var idx in keys) {
        assert_has.apply(this, [keys[idx], json, result, result2]);
    }
}

// helper function to clear the first two cells, set the text of and execute
// the first one
function clear_and_execute(that, code) {
    that.evaluate(function() {
        IPython.notebook.get_cell(0).clear_output();
        IPython.notebook.get_cell(1).clear_output();
    });
    that.set_cell_text(0, code);
    that.execute_cell(0);
}

casper.notebook_test(function () {
    this.evaluate(function () {
        var cell = IPython.notebook.get_cell(0);
        // "we have to make messes to find out who we are"
        cell.set_text([
            "%%javascript",
            "IPython.notebook.insert_cell_below('code')"
            ].join('\n')
            );

        cell.execute();
    });

    this.wait_for_output(0);

    this.then(function ( ) {
        var result = this.get_output_cell(0);
        var num_cells = this.get_cells_length();
        this.test.assertEquals(num_cells, 2, '%%javascript magic works');
        this.test.assertTrue(result.hasOwnProperty('application/javascript'),
            'testing JS embeded with mime key');
    });

    //this.thenEvaluate(function() { IPython.notebook.save_notebook(); });

    this.then(function ( ) {
        check_output_area.apply(this, ['display_data', ['javascript']]);

    });

    this.then(function() {
        clear_and_execute(this, '%lsmagic');
    });

    this.then(function () {
        check_output_area.apply(this, ['pyout', ['text', 'json']]);
    });

    this.then(function() {
        clear_and_execute(this,
            "x = %lsmagic\nfrom IPython.display import display; display(x)");
        this.execute_cell(0);
    });

    this.then(function ( ) {
        check_output_area.apply(this, ['display_data', ['text', 'json']]);
    });

    this.then(function() {
        clear_and_execute(this,
            "from IPython.display import Latex; Latex('$X^2$')");
    });

    this.then(function ( ) {
        check_output_area.apply(this, ['pyout', ['text', 'latex']]);
    });

    this.then(function() {
        clear_and_execute(this,
            "from IPython.display import Latex, display; display(Latex('$X^2$'))");
    });

    this.then(function ( ) {
        check_output_area.apply(this, ['display_data', ['text', 'latex']]);
    });

});
<commit_msg>tests for HTML mimetype<commit_after>// Test opening a rich notebook, saving it, and reopening it again.
//
//toJSON fromJSON toJSON and do a string comparison

// this is just a copy of OutputArea.mime_mape_r in IPython/html/static/notebook/js/outputarea.js
mime =  {
        "text" : "text/plain",
        "html" : "text/html",
        "svg" : "image/svg+xml",
        "png" : "image/png",
        "jpeg" : "image/jpeg",
        "latex" : "text/latex",
        "json" : "application/json",
        "javascript" : "application/javascript",
    };

// helper function to ensure that the short_name is found in the toJSON
// represetnation, while the original in-memory cell retains its long mimetype
// name, and that fromJSON also gets its long mimetype name
function assert_has(short_name, json, result, result2) {
    long_name = mime[short_name];
    this.test.assertTrue(json[0].hasOwnProperty(short_name),
            'toJSON()   representation uses ' + short_name);
    this.test.assertTrue(result.hasOwnProperty(long_name),
            'toJSON()   original embeded JSON keeps ' + long_name);
    this.test.assertTrue(result2.hasOwnProperty(long_name),
            'fromJSON() embeded ' + short_name + ' gets mime key ' + long_name);
}

// helper function for checkout that the first two cells have a particular
// output_type (either 'pyout' or 'display_data'), and checks the to/fromJSON
// for a set of mimetype keys, using their short names ('javascript', 'text',
// 'png', etc).
function check_output_area(output_type, keys) {
    json = this.evaluate(function() {
        var json = IPython.notebook.get_cell(0).output_area.toJSON();
        // appended cell will initially be empty, lets add it some output
        var cell = IPython.notebook.get_cell(1).output_area.fromJSON(json);
        return json;
    });
    var result = this.get_output_cell(0);
    var result2 = this.get_output_cell(1);
    this.test.assertEquals(result.output_type, output_type,
        'testing ' + output_type + ' for ' + keys.join(' and '));

    for (var idx in keys) {
        assert_has.apply(this, [keys[idx], json, result, result2]);
    }
}

// helper function to clear the first two cells, set the text of and execute
// the first one
function clear_and_execute(that, code) {
    that.evaluate(function() {
        IPython.notebook.get_cell(0).clear_output();
        IPython.notebook.get_cell(1).clear_output();
    });
    that.set_cell_text(0, code);
    that.execute_cell(0);
}

casper.notebook_test(function () {
    this.evaluate(function () {
        var cell = IPython.notebook.get_cell(0);
        // "we have to make messes to find out who we are"
        cell.set_text([
            "%%javascript",
            "IPython.notebook.insert_cell_below('code')"
            ].join('\n')
            );

        cell.execute();
    });

    this.wait_for_output(0);

    this.then(function ( ) {
        var result = this.get_output_cell(0);
        var num_cells = this.get_cells_length();
        this.test.assertEquals(num_cells, 2, '%%javascript magic works');
        this.test.assertTrue(result.hasOwnProperty('application/javascript'),
            'testing JS embeded with mime key');
    });

    //this.thenEvaluate(function() { IPython.notebook.save_notebook(); });

    this.then(function ( ) {
        check_output_area.apply(this, ['display_data', ['javascript']]);

    });

    this.then(function() {
        clear_and_execute(this, '%lsmagic');
    });

    this.then(function () {
        check_output_area.apply(this, ['pyout', ['text', 'json']]);
    });

    this.then(function() {
        clear_and_execute(this,
            "x = %lsmagic\nfrom IPython.display import display; display(x)");
        this.execute_cell(0);
    });

    this.then(function ( ) {
        check_output_area.apply(this, ['display_data', ['text', 'json']]);
    });

    this.then(function() {
        clear_and_execute(this,
            "from IPython.display import Latex; Latex('$X^2$')");
    });

    this.then(function ( ) {
        check_output_area.apply(this, ['pyout', ['text', 'latex']]);
    });

    this.then(function() {
        clear_and_execute(this,
            "from IPython.display import Latex, display; display(Latex('$X^2$'))");
    });

    this.then(function ( ) {
        check_output_area.apply(this, ['display_data', ['text', 'latex']]);
    });

    this.then(function() {
        clear_and_execute(this,
            "from IPython.display import HTML; HTML('it works!')");
    });

    this.then(function ( ) {
        check_output_area.apply(this, ['pyout', ['text', 'html']]);
    });

    this.then(function() {
        clear_and_execute(this,
            "from IPython.display import HTML, display; display(HTML('it works!'))");
    });

    this.then(function ( ) {
        check_output_area.apply(this, ['display_data', ['text', 'html']]);
    });

});
<|endoftext|>


<commit_before>/**
* TaskFeedController
* @namespace crowdsource.task-feed.controllers
 * @author dmorina
*/
(function () {
  'use strict';

  angular
    .module('crowdsource.task-feed.controllers')
    .controller('TaskFeedController', TaskFeedController);

  TaskFeedController.$inject = ['$window', '$location', '$scope', '$mdToast', 'TaskFeed',
    '$filter', 'Authentication', 'TaskWorker'];

  /**
  * @namespace TaskFeedController
  */
  function TaskFeedController($window, $location, $scope, $mdToast, TaskFeed,
    $filter, Authentication, TaskWorker) {
      var userAccount = Authentication.getAuthenticatedAccount();
      if (!userAccount) {
        $location.path('/login');
        return;
      }

      var self = this;
      self.toggleBookmark = toggleBookmark;
      self.projects = [];
      self.previewedModule = null;
      self.showPreview = showPreview;
      self.openTask = openTask;

      TaskFeed.getProjects().then(
        function success (data) {
            self.projects = data[0];
        },
        function error(errData) {
          self.error = errData[0].detail;
        }
      ).finally(function () {
        // pass
      });

      function toggleBookmark(project){
          project.is_bookmarked = !project.is_bookmarked;
      }
      function showPreview(module){
          self.previewedModule = module;
      }

      function openTask(module_id){
        TaskWorker.attemptAllocateTask(module_id).then(
        function success (data) {
            var task_id = data[0].task;
            $location.path('/task/'+task_id);
        },
        function error(errData) {
          $mdToast.showSimple('Error attempting task - ' + errData);
        }
        ).finally(function () {
        });
      }
  }

})();<commit_msg>show correct error message<commit_after>/**
* TaskFeedController
* @namespace crowdsource.task-feed.controllers
 * @author dmorina
*/
(function () {
  'use strict';

  angular
    .module('crowdsource.task-feed.controllers')
    .controller('TaskFeedController', TaskFeedController);

  TaskFeedController.$inject = ['$window', '$location', '$scope', '$mdToast', 'TaskFeed',
    '$filter', 'Authentication', 'TaskWorker'];

  /**
  * @namespace TaskFeedController
  */
  function TaskFeedController($window, $location, $scope, $mdToast, TaskFeed,
    $filter, Authentication, TaskWorker) {
      var userAccount = Authentication.getAuthenticatedAccount();
      if (!userAccount) {
        $location.path('/login');
        return;
      }

      var self = this;
      self.toggleBookmark = toggleBookmark;
      self.projects = [];
      self.previewedModule = null;
      self.showPreview = showPreview;
      self.openTask = openTask;

      TaskFeed.getProjects().then(
        function success (data) {
            self.projects = data[0];
        },
        function error(errData) {
          self.error = errData[0].detail;
        }
      ).finally(function () {
        // pass
      });

      function toggleBookmark(project){
          project.is_bookmarked = !project.is_bookmarked;
      }
      function showPreview(module){
          self.previewedModule = module;
      }

      function openTask(module_id){
        TaskWorker.attemptAllocateTask(module_id).then(
        function success (data) {
            var task_id = data[0].task;
            $location.path('/task/'+task_id);
        },
        function error(errData) {
          var err = errData[0]
          $mdToast.showSimple('Error attempting task - ' + JSON.stringify(err));
        }
        ).finally(function () {
        });
      }
  }

})();<|endoftext|>


<commit_before>/**
 * @package     hubzero-cms
 * @file        components/com_groups/assets/js/groups.jquery.js
 * @copyright   Copyright 2005-2015 HUBzero Foundation, LLC.
 * @license     http://opensource.org/licenses/MIT MIT
 */

//-----------------------------------------------------------
//  Ensure we have our namespace
//-----------------------------------------------------------
if (!HUB) {
	var HUB = {};
}

//----------------------------------------------------------
//  Members scripts
//----------------------------------------------------------
if (!jq) {
	var jq = $;
}

String.prototype.nohtml = function () {
	if (this.indexOf('?') == -1) {
		return this + '?no_html=1';
	} else {
		return this + '&no_html=1';
	}
};

HUB.ProjectPublicationsSelector = {
	jQuery: jq,
	selections: new Array(),

	initialize: function() {
		var $ = this.jQuery;

		var isMSIE = /*@cc_on!@*/0;

		var container = $('#pub-selector');

		if (container.length) {
			// Infinite scroll
			var opts = {
					navSelector  : '.list-footer',    // selector for the paged navigation
					nextSelector : '.list-footer .next a',  // selector for the NEXT link (to page 2)
					itemSelector : '#pub-selector li',     // selector for all items you'll retrieve
					binder: container,
					behavior: 'local',
					loading: {
						finishedMsg: 'No more records to load.'
					},
					path: function(index) {
						var path = $('.list-footer .next a').attr('href'),
							limit = $('#limit').val(),
							start = 0;
						if (path.match(/limit[-=]([0-9]*)/)) {
							limit = path.match(/limit[-=]([0-9]*)/).slice(1);
						}
						limit = limit ? limit : 25;
						start = path.match(/start[-=]([0-9]*)/).slice(1);
						return path.replace(/start[-=]([0-9]*)/, 'no_html=1&start=' + (limit * index - limit));
					},
					debug: true
				};

			container.infinitescroll(
				opts,
				function(newElements) {
					HUB.ProjectPublicationsSelector.showOddEven();
				}
			);

			var typedelay = (function(){
				var timer = 0;
				return function(callback, ms){
					clearTimeout(timer);
					timer = setTimeout(callback, ms);
				};
			})();

			$('#pub-search')
				.on('keyup', function (e) {
					var input = $(this);

					// Ad a slight delay so search only happens after
					// typing appears to stop (or pause, at least)
					typedelay(function(){
						if (!input.length) {
							return;
						}

						// Perform the search
						$.get($('.item-add').attr('href') + '&search=' + input.val(), {}, function(data){
							var results = $(data).find('#pub-selector-results').html();

							if (results) {
								// Disable infinite scroll
								container.infinitescroll('destroy');
								container.data('infinitescroll', null);

								// Add the results to the page
								$('#pub-selector-results').html(results);
								// Re-enable infinite scroll
								// This is ugly but done this way as the search results
								// will have its own pagination list. So, we need to force
								// infinite scrll to start over every time we get new results
								container = $('#pub-selector');
								opts.binder = container;
								container.infinitescroll(
									opts,
									function(newElements) {
										HUB.ProjectPublicationsSelector.showOddEven();
									}
								);
								HUB.ProjectPublicationsSelector.selector();
							}
						});
					}, 1000);
				});
		}

		// Enable selection
		HUB.ProjectPublicationsSelector.selector();

		// Enable save button
		HUB.ProjectPublicationsSelector.enableButton();
		HUB.ProjectPublicationsSelector.enableSave();

		// Make zebra coloring
		HUB.ProjectPublicationsSelector.showOddEven();
	},

	showOddEven: function ()
	{
		var $ = this.jQuery;

		var items = $('#pub-selector li');
		if (!items.length)
		{
			return false;
		}

		c = 1;
		var css = 'odd';
		items.each(function(i, item)
		{
			c++;

			$(item).removeClass('odd');
			$(item).removeClass('even')

			if (!$(item).hasClass('hidden'))
			{
				$(item).addClass(css);
				css = css == 'odd' ? 'even' : 'odd';
			}

		});
	},

	enableSave: function()
	{
		var $ = this.jQuery;
		var btn  = $('#b-filesave');
		var form = $('#select-form');

		if (!btn.length || !form.length)
		{
			return false;
		}

		// Send data
		btn.on('click', function(e)
		{
			e.preventDefault();

			if (!btn.hasClass('disabled'))
			{
				selections = HUB.ProjectPublicationsSelector.collectSelections(false);
				$('#selecteditems').val(selections);
				form.submit();
			}

		});
	},

	fadeMessage: function()
	{
		var $ = this.jQuery;

		if (!$('#status-box').length)
		{
			return false;
		}
		$("#status-box").animate({opacity:0.0}, 2000, function() {
		    $('#status-box').html('');
			$("#status-box").css('opacity', '1.0');
		});
	},

	enableButton: function()
	{
		var $ = this.jQuery;
		var btn = $('#b-filesave');
		var selection = $('#selecteditems').length ? $('#selecteditems').val() : '' ;

		if (!btn.length)
		{
			return false;
		}

		success = HUB.ProjectPublicationsSelector.checkProgress();
		if (success == true)
		{
			if (btn.hasClass('disabled'))
			{
				btn.removeClass('disabled');
			}
		}
		else
		{
			if (!btn.hasClass('disabled'))
			{
				btn.addClass('disabled');
			}
		}
	},

	checkProgress: function ()
	{
		var $ = this.jQuery;
		var success = false;

		checker = $('.selectedfilter').length;
		optional = $('.el-optional').length;

		// Check that we satisfy minimum/maximum requirements
		if (checker >= 1 || optional >= 1)
		{
			success = true;
		}

		return success;
	},

	selector: function ()
	{
		var $ = this.jQuery;
		var max = $('#maxitems').length ? $('#maxitems').val() : 1;

		if (!$('#pub-selector').length)
		{
			return false;
		}

		$('#pub-selector').selectable({
			filter: ".allowed",
			cancel: 'a',
			selected: function (event, ui)
			{
				// Prevent going over maximum
				numSelected = $('.selectedfilter').length;
				if (max == numSelected
					&& !$(ui.selected).hasClass('selectedfilter'))
				{
					// Remove filter from previously selected item(s)
					var popItem = $('.selectedfilter')[0];
					$(popItem).removeClass('selectedfilter');

					$(ui.selected).addClass('selectedfilter');

					// Nothing happens
					//$(ui.selected).removeClass('selectedfilter');
				}
				else if ($(ui.selected).hasClass('selectedfilter'))
				{
					$(ui.selected).removeClass('selectedfilter');
					// do unselected stuff
				}
				else
				{
					$(ui.selected).addClass('selectedfilter');
				}

				HUB.ProjectPublicationsSelector.enableButton();
			},
			unselected: function (event, ui)
			{
				$(ui.selected).removeClass('selectedfilter');
				HUB.ProjectPublicationsSelector.enableButton();
			}
		});

	},

	collectSelections: function(getArray)
	{
		var $ = this.jQuery;
		var items = $('.selectedfilter');
		var selections 	= new Array();
		var selString = '';

		if (items.length > 0)
		{
			items.each(function(i, item)
			{
				var id = $(item).attr('id').replace("choice-", "");
				var idx = HUB.Projects.getArrayIndex(id, selections);

				// Add
				if (idx == -1)
				{
					selections.push(id);
					selString = selString + id + ',';
				}
			});
		}

		return getArray ? selections : selString;
	}
};

jQuery(document).ready(function($){
	HUB.ProjectPublicationsSelector.initialize();
});

// Register the event
jQuery(document).on('ajaxLoad', HUB.ProjectPublicationsSelector.initialize);
<commit_msg>[PURR][#1352][PLG_PROJECTS_PUBLICATIONS] Check for existence of infinite scroll jQuery plugin before instantiating it<commit_after>/**
 * @package     hubzero-cms
 * @file        components/com_groups/assets/js/groups.jquery.js
 * @copyright   Copyright 2005-2015 HUBzero Foundation, LLC.
 * @license     http://opensource.org/licenses/MIT MIT
 */

//-----------------------------------------------------------
//  Ensure we have our namespace
//-----------------------------------------------------------
if (!HUB) {
	var HUB = {};
}

//----------------------------------------------------------
//  Members scripts
//----------------------------------------------------------
if (!jq) {
	var jq = $;
}

String.prototype.nohtml = function () {
	if (this.indexOf('?') == -1) {
		return this + '?no_html=1';
	} else {
		return this + '&no_html=1';
	}
};

HUB.ProjectPublicationsSelector = {
	jQuery: jq,
	selections: new Array(),

	initialize: function() {
		var $ = this.jQuery;

		var isMSIE = /*@cc_on!@*/0;

		var container = $('#pub-selector');

		if (container.length) {
			// Infinite scroll
			var opts = {
					navSelector  : '.list-footer',    // selector for the paged navigation
					nextSelector : '.list-footer .next a',  // selector for the NEXT link (to page 2)
					itemSelector : '#pub-selector li',     // selector for all items you'll retrieve
					binder: container,
					behavior: 'local',
					loading: {
						finishedMsg: 'No more records to load.'
					},
					path: function(index) {
						var path = $('.list-footer .next a').attr('href'),
							limit = $('#limit').val(),
							start = 0;
						if (path.match(/limit[-=]([0-9]*)/)) {
							limit = path.match(/limit[-=]([0-9]*)/).slice(1);
						}
						limit = limit ? limit : 25;
						start = path.match(/start[-=]([0-9]*)/).slice(1);
						return path.replace(/start[-=]([0-9]*)/, 'no_html=1&start=' + (limit * index - limit));
					},
					debug: true
				};

			if (jQuery().infinitescroll) {
				container.infinitescroll(
					opts,
					function(newElements) {
						HUB.ProjectPublicationsSelector.showOddEven();
					}
				);
			}

			var typedelay = (function(){
				var timer = 0;
				return function(callback, ms){
					clearTimeout(timer);
					timer = setTimeout(callback, ms);
				};
			})();

			$('#pub-search')
				.on('keyup', function (e) {
					var input = $(this);

					// Ad a slight delay so search only happens after
					// typing appears to stop (or pause, at least)
					typedelay(function(){
						if (!input.length) {
							return;
						}

						// Perform the search
						$.get($('.item-add').attr('href') + '&search=' + input.val(), {}, function(data){
							var results = $(data).find('#pub-selector-results').html();

							if (results && jQuery().infinitescroll) {
								// Disable infinite scroll
								container.infinitescroll('destroy');
								container.data('infinitescroll', null);

								// Add the results to the page
								$('#pub-selector-results').html(results);
								// Re-enable infinite scroll
								// This is ugly but done this way as the search results
								// will have its own pagination list. So, we need to force
								// infinite scrll to start over every time we get new results
								container = $('#pub-selector');
								opts.binder = container;
								container.infinitescroll(
									opts,
									function(newElements) {
										HUB.ProjectPublicationsSelector.showOddEven();
									}
								);
								HUB.ProjectPublicationsSelector.selector();
							}
						});
					}, 1000);
				});
		}

		// Enable selection
		HUB.ProjectPublicationsSelector.selector();

		// Enable save button
		HUB.ProjectPublicationsSelector.enableButton();
		HUB.ProjectPublicationsSelector.enableSave();

		// Make zebra coloring
		HUB.ProjectPublicationsSelector.showOddEven();
	},

	showOddEven: function ()
	{
		var $ = this.jQuery;

		var items = $('#pub-selector li');
		if (!items.length)
		{
			return false;
		}

		c = 1;
		var css = 'odd';
		items.each(function(i, item)
		{
			c++;

			$(item).removeClass('odd');
			$(item).removeClass('even')

			if (!$(item).hasClass('hidden'))
			{
				$(item).addClass(css);
				css = css == 'odd' ? 'even' : 'odd';
			}

		});
	},

	enableSave: function()
	{
		var $ = this.jQuery;
		var btn  = $('#b-filesave');
		var form = $('#select-form');

		if (!btn.length || !form.length)
		{
			return false;
		}

		// Send data
		btn.on('click', function(e)
		{
			e.preventDefault();

			if (!btn.hasClass('disabled'))
			{
				selections = HUB.ProjectPublicationsSelector.collectSelections(false);
				$('#selecteditems').val(selections);
				form.submit();
			}

		});
	},

	fadeMessage: function()
	{
		var $ = this.jQuery;

		if (!$('#status-box').length)
		{
			return false;
		}
		$("#status-box").animate({opacity:0.0}, 2000, function() {
		    $('#status-box').html('');
			$("#status-box").css('opacity', '1.0');
		});
	},

	enableButton: function()
	{
		var $ = this.jQuery;
		var btn = $('#b-filesave');
		var selection = $('#selecteditems').length ? $('#selecteditems').val() : '' ;

		if (!btn.length)
		{
			return false;
		}

		success = HUB.ProjectPublicationsSelector.checkProgress();
		if (success == true)
		{
			if (btn.hasClass('disabled'))
			{
				btn.removeClass('disabled');
			}
		}
		else
		{
			if (!btn.hasClass('disabled'))
			{
				btn.addClass('disabled');
			}
		}
	},

	checkProgress: function ()
	{
		var $ = this.jQuery;
		var success = false;

		checker = $('.selectedfilter').length;
		optional = $('.el-optional').length;

		// Check that we satisfy minimum/maximum requirements
		if (checker >= 1 || optional >= 1)
		{
			success = true;
		}

		return success;
	},

	selector: function ()
	{
		var $ = this.jQuery;
		var max = $('#maxitems').length ? $('#maxitems').val() : 1;

		if (!$('#pub-selector').length)
		{
			return false;
		}

		$('#pub-selector').selectable({
			filter: ".allowed",
			cancel: 'a',
			selected: function (event, ui)
			{
				// Prevent going over maximum
				numSelected = $('.selectedfilter').length;
				if (max == numSelected
					&& !$(ui.selected).hasClass('selectedfilter'))
				{
					// Remove filter from previously selected item(s)
					var popItem = $('.selectedfilter')[0];
					$(popItem).removeClass('selectedfilter');

					$(ui.selected).addClass('selectedfilter');

					// Nothing happens
					//$(ui.selected).removeClass('selectedfilter');
				}
				else if ($(ui.selected).hasClass('selectedfilter'))
				{
					$(ui.selected).removeClass('selectedfilter');
					// do unselected stuff
				}
				else
				{
					$(ui.selected).addClass('selectedfilter');
				}

				HUB.ProjectPublicationsSelector.enableButton();
			},
			unselected: function (event, ui)
			{
				$(ui.selected).removeClass('selectedfilter');
				HUB.ProjectPublicationsSelector.enableButton();
			}
		});

	},

	collectSelections: function(getArray)
	{
		var $ = this.jQuery;
		var items = $('.selectedfilter');
		var selections 	= new Array();
		var selString = '';

		if (items.length > 0)
		{
			items.each(function(i, item)
			{
				var id = $(item).attr('id').replace("choice-", "");
				var idx = HUB.Projects.getArrayIndex(id, selections);

				// Add
				if (idx == -1)
				{
					selections.push(id);
					selString = selString + id + ',';
				}
			});
		}

		return getArray ? selections : selString;
	}
};

jQuery(document).ready(function($){
	HUB.ProjectPublicationsSelector.initialize();
});

// Register the event
jQuery(document).on('ajaxLoad', HUB.ProjectPublicationsSelector.initialize);
<|endoftext|>


<commit_before>import Morph from "./Morph.js"

import d3 from 'src/external/d3.v4.js';

import { Graph } from 'src/client/triples/triples.js';
import * as drawTools from 'src/client/triples/drawTools.js';
import * as math from 'src/client/triples/math.js';

const MIN_MAGNIFICATION = 0.01;
const MAX_MAGNIFICATION = 4;

const NODE_BY_KNOT = new Map();
function getNodeByKnot(knot) {
  if(!NODE_BY_KNOT.has(knot)) {
    NODE_BY_KNOT.set(knot, new Node(knot));
  }
  return NODE_BY_KNOT.get(knot);
}

class RectangleTools {
  static distanceToBorder(rect, dx, dy) {
  	var width = rect.width(),
  		height = rect.height();

  	var innerDistance,
  		m_link = Math.abs(dy / dx),
  		m_rect = height / width;

  	if (m_link <= m_rect) {
  		var timesX = dx / (width / 2),
  			rectY = dy / timesX;
  		innerDistance = Math.sqrt(Math.pow(width / 2, 2) + Math.pow(rectY, 2));
  	} else {
  		var timesY = dy / (height / 2),
  			rectX = dx / timesY;
  		innerDistance = Math.sqrt(Math.pow(height / 2, 2) + Math.pow(rectX, 2));
  	}

  	return innerDistance;
  };
}

const cssClassesByFileType = {
  'png': ['image'],
  'PNG': ['image'],
  'jpg': ['image'],
  'svg': ['image'],
  'mp3': ['audio'],
  'mov': ['movie'],
  'mp4': ['movie'],
  'avi': ['movie'],
  'pptx': ['presentation'],
  'md': ['markdown'],
  'htm': ['html'],
  'html': ['html'],
  'json': ['data'],
  'csv': ['data']
}
const cssClassesByTagURL = {
  'https://lively4/dropbox/tag.md': ['tag'],
  'https://lively4/dropbox/is_a.md': ['is-a'],
  'https://lively4/dropbox/same_as.md': ['same-as'],
  'https://lively4/dropbox/contains.md': ['contains'],
}
class Node {
  static getCSSClassesByType(node) {

  }
  constructor(knot, label) {
    this.knot = knot;
    //this.r = ~~d3.randomUniform(8, 28)();
    this._radius = this.knot.content && this.knot.content.split ?
	    Math.min(this.knot.content.split(/\r?\n/).length, 100) :
	    40;
	 this._width = 60;
	 this._height = 20;
  }
  label() {
    return this.knot.label();
  }
  isTriple() {
    return this.knot.isTriple();
  }
  isExternal() {  return Graph.isExternalURL(new URL(this.knot.url)); }
  getKnot() { return this.knot; }

  draw(parentElement, additionalCssClasses) {
    let cssClasses;

    if(this.knot.isTriple()) {
      cssClasses = cssClassesByTagURL[this.knot.predicate.url] || ['white'];
    } else {
      const fileEnding = this.knot.url.split('#').shift().split('?').shift().split('.').pop();
      //lively.notify(fileEnding)
  		cssClasses = cssClassesByFileType[fileEnding] ?
  		  cssClassesByFileType[fileEnding] :
  		  (lively.notify(fileEnding), ['white']);
    }

	  // that.collectCssClasses();

		//that.nodeElement(parentElement);

		//if (additionalCssClasses instanceof Array) {
		//	cssClasses = cssClasses.concat(additionalCssClasses);
		//}

    if(this.knot.isTriple()) {
      drawTools.appendRectangularClass(parentElement, 60, 20, cssClasses, this.label());
    } else {
		  drawTools.appendCircularClass(parentElement, this.actualRadius(), cssClasses, this.label());
    }

		//that.postDrawActions(parentElement);
	}

	actualRadius() {
	  return this._radius;
	}
	width() { return this._width; }
	height() { return this._height; }
	distanceToBorder(dx, dy) { return this.isTriple() ?
	  RectangleTools.distanceToBorder(this, dx, dy) :
	  this.actualRadius();
	}
}

class Link extends Node {
  constructor(node) {
    super(node.getKnot());

    this._subject = getNodeByKnot(this.getKnot().subject);
    this._predicate = getNodeByKnot(this.getKnot().predicate);
    this._object = getNodeByKnot(this.getKnot().object);
    this._triple = getNodeByKnot(this.getKnot());

    this.frontPart = new LinkPart({
      source: this._subject,
      target: this._triple
    });
    this.backPart = new LinkPart({
      source: this._triple,
      target: this._object
    });
  }
  get subject() { return this._subject; }
  get predicate() { return this._predicate; }
  get object() { return this._object; }
  get triple() { return this._triple; }

  //TODO: support loops specially
  isLoop() {
    return this.subject === this.object;
  }
  linkParts() {
    return [this.frontPart, this.backPart];
  }

  draw(linkGroup, markerContainer) {
  	linkGroup.append("path")
  		//.classed("link-path", true)
  		//.classed(this.domain().cssClassOfNode(), true)
  		//.classed(this.range().cssClassOfNode(), true)
      //.classed(property.linkType(), true);
  }

  // TODO: if we are self-referencial: compute the number of self references from the graph
  loops() {
    return 3;
  }
}

class LinkPart {
  constructor({ source, target }) {
    this.source = source;
    this.target = target;
  }
}

export default class TripleNotes extends Morph {

  async initialize() {
    this.windowTitle = "Knot Explorer";

    let parentElement = this.get('#graph');
    var width,height;
    var chartWidth, chartHeight;
    var margin;
    var svg = d3.select(parentElement)
      .append("svg");
    var graphContainer = svg.append("g").classed("graphContainer", true);

    setSize();

    let graph = await Graph.getInstance();

    let knots = graph.knots;
    this.updateStatistics(knots);

    let nodes = knots.map(getNodeByKnot);
    let links = nodes
      .filter(node => node.isTriple())
      .map(node => new Link(node));

    let hiddenLinks = [];
		links.forEach(link => hiddenLinks = hiddenLinks.concat(link.linkParts()));

    drawChart({
      nodes,
      links,
      hiddenLinks
    });

    lively.addEventListener("triple-notes", this, "extent-changed", e => { setSize(); });

    function setSize() {
      width = parentElement.clientWidth;
      height = parentElement.clientHeight;
      //console.log(`%cwidth: ${width} height: ${height}`, 'font-size: 20pt')

      margin = {top:0, left:0, bottom:0, right:0 };

      chartWidth = width - (margin.left+margin.right)
      chartHeight = height - (margin.top+margin.bottom)

      //graphContainer.attr("width", width).attr("height", height)

      svg
        .attr("width", chartWidth)
        .attr("height", chartHeight)
        .attr("transform", "translate("+[margin.left, margin.top]+")");
    }

    function zoomed() {
      graphContainer.attr("transform", d3.event.transform);
    }

    svg.call(d3.zoom()
			.duration(150)
    	.scaleExtent([MIN_MAGNIFICATION, MAX_MAGNIFICATION])
      .on("zoom", zoomed));

    function drawChart({ nodes, links, hiddenLinks }) {

      var simulation = d3.forceSimulation()
        .force("link", d3.forceLink().id(d => d.index).distance(200))
        //.force("collide",d3.forceCollide(d => d.r + 8).iterations(16) )
        .force("charge", d3.forceManyBody().strength(node => node.isTriple() ? -190*0.5 : -190))
        .force("center", d3.forceCenter(chartWidth / 2, chartWidth / 2))
        .force("y", d3.forceY(0).strength(0.001))
        .force("x", d3.forceX(0).strength(0.001));

      let linkPartContainer = graphContainer.append("g").classed("linkPartContainer", true);
      var hiddenLinkElements = linkPartContainer.selectAll("line")
        .data(hiddenLinks).enter()
        .append("line")
        .style("stroke", "black")
        .style("stroke-opacity", 0.3)
        .style("stroke-width", 10);

      let nodeContainer = graphContainer.append("g").classed("nodeContainer", true);
      let nodeElements = nodeContainer.selectAll(".node")
        .data(nodes).enter()
        .append("g")
        .attr("class", "node")
        .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended))
          .on("dblclick", async node => {
            d3.event.stopPropagation();

            let knotView = await lively.openComponentInWindow("knot-view");
            knotView.loadKnotForURL(node.getKnot().url);
          });

      nodeElements.each(function (node) {
  			node.draw(d3.select(this));
      });

      nodeElements.append("text")
        .attr("class", "text")
        .style("text-anchor", "middle")
        .style("alignment-baseline", "middle")
        .text(d => d.label());

      let linkContainer = graphContainer.append("g").classed("linkContainer", true);
      let markerContainer = linkContainer.append("defs");
      createPropertyMarker(markerContainer);
      function createPropertyMarker(markerContainer) {
      	var marker = appendBasicMarker(markerContainer);
      	//marker.attr("refX", 12);
          var m1X = -12 ;
          var m1Y = 8 ;
          var m2X = -12;
          var m2Y = -8 ;
      	marker.append("path")
      		//.attr("d", "M0,-8L12,0L0,8Z")
              .attr("d", "M0,0L " + m1X + "," + m1Y + "L" + m2X + "," + m2Y + "L" + 0 + "," + 0 )
      		.classed("basic-triple-link", true);
      }

      function appendBasicMarker(markerContainer) {
      	return markerContainer.append("marker")
      		.datum({})
      		.attr("id", "triple-notes-basic-triple-link")

      		.attr("viewBox", "-14 -10 28 20")
      		.attr("markerWidth",10)
      		.attr("markerHeight", 10)
      		//.attr("markerUnits", "userSpaceOnUse")
      		.attr("orient", "auto");
      }

  		// Draw links
  		let linkGroups = linkContainer.selectAll(".link")
  			.data(links).enter()
  			.append("g")
  			.classed("link", true);

  		linkGroups.each(function (link) {
  		  d3.select(this).attr("marker-end", "url(#triple-notes-basic-triple-link)");
  			link.draw(d3.select(this), markerContainer);
  		});

  		// Select the path for direct access to receive a better performance
      let linkPathElements = linkGroups.selectAll("path");

      let curveFunction = d3.line()
  			.x(function (d) {
  				return d.x;
  			})
  			.y(function (d) {
  				return d.y;
  			})
        .curve(d3.curveNatural);
      function recalculatePositions() {
        nodeElements.attr("transform", d => "translate(" + d.x + "," + d.y + ")");

        hiddenLinkElements
          .attr("x1", d => d.source.x)
          .attr("y1", d => d.source.y)
          .attr("x2", d => d.target.x)
          .attr("y2", d => d.target.y);

    		// Set link paths and calculate additional information
    		linkPathElements.attr("d", function (link) {
    			if (link.isLoop()) {
    				return math.calculateLoopPath(link);
    			}
    			var curvePoint = link.triple;
    			var pathStart = math.calculateIntersection(curvePoint, link.subject, 1);
    			var pathEnd = math.calculateIntersection(curvePoint, link.object, 1);

    			return curveFunction([pathStart, curvePoint, pathEnd]);
        });
      }

      simulation
        .nodes(nodes)
        .on("tick", recalculatePositions);

      simulation.force("link")
        .links(hiddenLinks);

      function dragstarted(d) {
        if (!d3.event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
      }

      function dragged(d) {
        d.fx = d3.event.x;
        d.fy = d3.event.y;
      }

      function dragended(d) {
        if (!d3.event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
      }
    }
  }

  updateStatistics(knots) {
    this.get('#number-of-knots').innerHTML = knots.length;
    this.get('#number-of-triples').innerHTML = knots.filter(k => k.isTriple()).length;
  }
}<commit_msg>AUTO-COMMIT templates/triple-notes.js<commit_after>import Morph from "./Morph.js"

import d3 from 'src/external/d3.v4.js';

import { Graph } from 'src/client/triples/triples.js';
import * as drawTools from 'src/client/triples/drawTools.js';
import * as math from 'src/client/triples/math.js';

const MIN_MAGNIFICATION = 0.01;
const MAX_MAGNIFICATION = 4;

const NODE_BY_KNOT = new Map();
function getNodeByKnot(knot) {
  if(!NODE_BY_KNOT.has(knot)) {
    NODE_BY_KNOT.set(knot, new Node(knot));
  }
  return NODE_BY_KNOT.get(knot);
}

class RectangleTools {
  static distanceToBorder(rect, dx, dy) {
  	var width = rect.width(),
  		height = rect.height();

  	var innerDistance,
  		m_link = Math.abs(dy / dx),
  		m_rect = height / width;

  	if (m_link <= m_rect) {
  		var timesX = dx / (width / 2),
  			rectY = dy / timesX;
  		innerDistance = Math.sqrt(Math.pow(width / 2, 2) + Math.pow(rectY, 2));
  	} else {
  		var timesY = dy / (height / 2),
  			rectX = dx / timesY;
  		innerDistance = Math.sqrt(Math.pow(height / 2, 2) + Math.pow(rectX, 2));
  	}

  	return innerDistance;
  };
}

const cssClassesByFileType = {
  'png': ['image'],
  'PNG': ['image'],
  'jpg': ['image'],
  'svg': ['image'],
  'mp3': ['audio'],
  'mov': ['movie'],
  'mp4': ['movie'],
  'avi': ['movie'],
  'pptx': ['presentation'],
  'md': ['markdown'],
  'htm': ['html'],
  'html': ['html'],
  'json': ['data'],
  'csv': ['data']
}
const cssClassesByTagURL = {
  'https://lively4/dropbox/tag.md': ['tag'],
  'https://lively4/dropbox/is_a.md': ['is-a'],
  'https://lively4/dropbox/same_as.md': ['same-as'],
  'https://lively4/dropbox/contains.md': ['contains'],
}
class Node {
  static getCSSClassesByType(node) {

  }
  constructor(knot, label) {
    this.knot = knot;
    //this.r = ~~d3.randomUniform(8, 28)();
    this._radius = this.knot.content && this.knot.content.split ?
	    Math.min(this.knot.content.split(/\r?\n/).length, 100) :
	    40;
	 this._width = 60;
	 this._height = 20;
  }
  label() {
    return this.knot.label();
  }
  isTriple() {
    return this.knot.isTriple();
  }
  isExternal() {  return Graph.isExternalURL(new URL(this.knot.url)); }
  getKnot() { return this.knot; }

  draw(parentElement, additionalCssClasses) {
    let cssClasses;

    if(this.knot.isTriple()) {
      cssClasses = cssClassesByTagURL[this.knot.predicate.url] || ['white'];
      cssClasses.push('nostroke')
    } else {
      const fileEnding = this.knot.url.split('#').shift().split('?').shift().split('.').pop();
      //lively.notify(fileEnding)
  		cssClasses = cssClassesByFileType[fileEnding] ?
  		  cssClassesByFileType[fileEnding] :
  		  (lively.notify(fileEnding), ['white']);
    }

	  // that.collectCssClasses();

		//that.nodeElement(parentElement);

		//if (additionalCssClasses instanceof Array) {
		//	cssClasses = cssClasses.concat(additionalCssClasses);
		//}

    if(this.knot.isTriple()) {
      drawTools.appendRectangularClass(parentElement, 60, 20, cssClasses, this.label());
    } else {
		  drawTools.appendCircularClass(parentElement, this.actualRadius(), cssClasses, this.label());
    }

		//that.postDrawActions(parentElement);
	}

	actualRadius() {
	  return this._radius;
	}
	width() { return this._width; }
	height() { return this._height; }
	distanceToBorder(dx, dy) { return this.isTriple() ?
	  RectangleTools.distanceToBorder(this, dx, dy) :
	  this.actualRadius();
	}
}

class Link extends Node {
  constructor(node) {
    super(node.getKnot());

    this._subject = getNodeByKnot(this.getKnot().subject);
    this._predicate = getNodeByKnot(this.getKnot().predicate);
    this._object = getNodeByKnot(this.getKnot().object);
    this._triple = getNodeByKnot(this.getKnot());

    this.frontPart = new LinkPart({
      source: this._subject,
      target: this._triple
    });
    this.backPart = new LinkPart({
      source: this._triple,
      target: this._object
    });
  }
  get subject() { return this._subject; }
  get predicate() { return this._predicate; }
  get object() { return this._object; }
  get triple() { return this._triple; }

  //TODO: support loops specially
  isLoop() {
    return this.subject === this.object;
  }
  linkParts() {
    return [this.frontPart, this.backPart];
  }

  draw(linkGroup, markerContainer) {
  	linkGroup.append("path")
  		//.classed("link-path", true)
  		//.classed(this.domain().cssClassOfNode(), true)
  		//.classed(this.range().cssClassOfNode(), true)
      //.classed(property.linkType(), true);
  }

  // TODO: if we are self-referencial: compute the number of self references from the graph
  loops() {
    return 3;
  }
}

class LinkPart {
  constructor({ source, target }) {
    this.source = source;
    this.target = target;
  }
}

export default class TripleNotes extends Morph {

  async initialize() {
    this.windowTitle = "Knot Explorer";

    let parentElement = this.get('#graph');
    var width,height;
    var chartWidth, chartHeight;
    var margin;
    var svg = d3.select(parentElement)
      .append("svg");
    var graphContainer = svg.append("g").classed("graphContainer", true);

    setSize();

    let graph = await Graph.getInstance();

    let knots = graph.knots;
    this.updateStatistics(knots);

    let nodes = knots.map(getNodeByKnot);
    let links = nodes
      .filter(node => node.isTriple())
      .map(node => new Link(node));

    let hiddenLinks = [];
		links.forEach(link => hiddenLinks = hiddenLinks.concat(link.linkParts()));

    drawChart({
      nodes,
      links,
      hiddenLinks
    });

    lively.addEventListener("triple-notes", this, "extent-changed", e => { setSize(); });

    function setSize() {
      width = parentElement.clientWidth;
      height = parentElement.clientHeight;
      //console.log(`%cwidth: ${width} height: ${height}`, 'font-size: 20pt')

      margin = {top:0, left:0, bottom:0, right:0 };

      chartWidth = width - (margin.left+margin.right)
      chartHeight = height - (margin.top+margin.bottom)

      //graphContainer.attr("width", width).attr("height", height)

      svg
        .attr("width", chartWidth)
        .attr("height", chartHeight)
        .attr("transform", "translate("+[margin.left, margin.top]+")");
    }

    function zoomed() {
      graphContainer.attr("transform", d3.event.transform);
    }

    svg.call(d3.zoom()
			.duration(150)
    	.scaleExtent([MIN_MAGNIFICATION, MAX_MAGNIFICATION])
      .on("zoom", zoomed));

    function drawChart({ nodes, links, hiddenLinks }) {

      var simulation = d3.forceSimulation()
        .force("link", d3.forceLink().id(d => d.index).distance(200))
        //.force("collide",d3.forceCollide(d => d.r + 8).iterations(16) )
        .force("charge", d3.forceManyBody().strength(node => node.isTriple() ? -190*0.5 : -190))
        .force("center", d3.forceCenter(chartWidth / 2, chartWidth / 2))
        .force("y", d3.forceY(0).strength(0.001))
        .force("x", d3.forceX(0).strength(0.001));

      let linkPartContainer = graphContainer.append("g").classed("linkPartContainer", true);
      var hiddenLinkElements = linkPartContainer.selectAll("line")
        .data(hiddenLinks).enter()
        .append("line")
        .style("stroke", "black")
        .style("stroke-opacity", 0.3)
        .style("stroke-width", 10);

      let nodeContainer = graphContainer.append("g").classed("nodeContainer", true);
      let nodeElements = nodeContainer.selectAll(".node")
        .data(nodes).enter()
        .append("g")
        .attr("class", "node")
        .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended))
          .on("dblclick", async node => {
            d3.event.stopPropagation();

            let knotView = await lively.openComponentInWindow("knot-view");
            knotView.loadKnotForURL(node.getKnot().url);
          });

      nodeElements.each(function (node) {
  			node.draw(d3.select(this));
      });

      nodeElements.append("text")
        .attr("class", "text")
        .style("text-anchor", "middle")
        .style("alignment-baseline", "middle")
        .text(d => d.label());

      let linkContainer = graphContainer.append("g").classed("linkContainer", true);
      let markerContainer = linkContainer.append("defs");
      createPropertyMarker(markerContainer);
      function createPropertyMarker(markerContainer) {
      	var marker = appendBasicMarker(markerContainer);
      	//marker.attr("refX", 12);
          var m1X = -12 ;
          var m1Y = 8 ;
          var m2X = -12;
          var m2Y = -8 ;
      	marker.append("path")
      		//.attr("d", "M0,-8L12,0L0,8Z")
              .attr("d", "M0,0L " + m1X + "," + m1Y + "L" + m2X + "," + m2Y + "L" + 0 + "," + 0 )
      		.classed("basic-triple-link", true);
      }

      function appendBasicMarker(markerContainer) {
      	return markerContainer.append("marker")
      		.datum({})
      		.attr("id", "triple-notes-basic-triple-link")

      		.attr("viewBox", "-14 -10 28 20")
      		.attr("markerWidth",10)
      		.attr("markerHeight", 10)
      		//.attr("markerUnits", "userSpaceOnUse")
      		.attr("orient", "auto");
      }

  		// Draw links
  		let linkGroups = linkContainer.selectAll(".link")
  			.data(links).enter()
  			.append("g")
  			.classed("link", true);

  		linkGroups.each(function (link) {
  		  d3.select(this).attr("marker-end", "url(#triple-notes-basic-triple-link)");
  			link.draw(d3.select(this), markerContainer);
  		});

  		// Select the path for direct access to receive a better performance
      let linkPathElements = linkGroups.selectAll("path");

      let curveFunction = d3.line()
  			.x(function (d) {
  				return d.x;
  			})
  			.y(function (d) {
  				return d.y;
  			})
        .curve(d3.curveNatural);
      function recalculatePositions() {
        nodeElements.attr("transform", d => "translate(" + d.x + "," + d.y + ")");

        hiddenLinkElements
          .attr("x1", d => d.source.x)
          .attr("y1", d => d.source.y)
          .attr("x2", d => d.target.x)
          .attr("y2", d => d.target.y);

    		// Set link paths and calculate additional information
    		linkPathElements.attr("d", function (link) {
    			if (link.isLoop()) {
    				return math.calculateLoopPath(link);
    			}
    			var curvePoint = link.triple;
    			var pathStart = math.calculateIntersection(curvePoint, link.subject, 1);
    			var pathEnd = math.calculateIntersection(curvePoint, link.object, 1);

    			return curveFunction([pathStart, curvePoint, pathEnd]);
        });
      }

      simulation
        .nodes(nodes)
        .on("tick", recalculatePositions);

      simulation.force("link")
        .links(hiddenLinks);

      function dragstarted(d) {
        if (!d3.event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
      }

      function dragged(d) {
        d.fx = d3.event.x;
        d.fy = d3.event.y;
      }

      function dragended(d) {
        if (!d3.event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
      }
    }
  }

  updateStatistics(knots) {
    this.get('#number-of-knots').innerHTML = knots.length;
    this.get('#number-of-triples').innerHTML = knots.filter(k => k.isTriple()).length;
  }
}<|endoftext|>


<commit_before>// eslint-disable-next-line no-control-regex
const actionMessageRegex = /^\u0001ACTION ([^\u0001]+)\u0001$/;
const justinFanRegex = /^(justinfan)(\d+$)/;
const unescapeIRCRegex = /\\([sn:r\\])/g;
const escapeIRCRegex = /([ \n;\r\\])/g;
const ircEscapedChars = { s: ' ', n: '', ':': ';', r: '' };
const ircUnescapedChars = { ' ': 's', '\n': 'n', ';': ':', '\r': 'r' };
const _ = module.exports = {
	// Return the second value if the first value is undefined..
	get: (a, b) => typeof a === 'undefined' ? b : a,

	// Indirectly use hasOwnProperty
	hasOwn: (obj, key) => ({}).hasOwnProperty.call(obj, key),

	// Race a promise against a delay..
	promiseDelay: time => new Promise(resolve => setTimeout(resolve, time)),

	// Value is a finite number..
	isFinite: int => isFinite(int) && !isNaN(parseFloat(int)),

	// Parse string to number. Returns NaN if string can't be parsed to number..
	toNumber: (num, precision) => {
		if(num === null) {
			return 0;
		}
		const factor = Math.pow(10, _.isFinite(precision) ? precision : 0);
		return Math.round(num * factor) / factor;
	},

	// Value is an integer..
	isInteger: int => !isNaN(_.toNumber(int, 0)),

	// Value is a regex..
	isRegex: str => /[|\\^$*+?:#]/.test(str),

	// Value is a valid url..
	isURL: str => new RegExp('^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))\\.?)(?::\\d{2,5})?(?:[/?#]\\S*)?$', 'i').test(str),

	// Return a random justinfan username..
	justinfan: () => `justinfan${Math.floor((Math.random() * 80000) + 1000)}`,

	// Username is a justinfan username..
	isJustinfan: username => justinFanRegex.test(username),

	// Return a valid channel name..
	channel: str => {
		const channel = (str ? str : '').toLowerCase();
		return channel[0] === '#' ? channel : '#' + channel;
	},

	// Return a valid username..
	username: str => {
		const username = (str ? str : '').toLowerCase();
		return username[0] === '#' ? username.slice(1) : username;
	},

	// Return a valid token..
	token: str => str ? str.toLowerCase().replace('oauth:', '') : '',

	// Return a valid password..
	password: str => {
		const token = _.token(str);
		return token ? `oauth:${token}` : '';
	},

	actionMessage: msg => msg.match(actionMessageRegex),

	// Replace all occurences of a string using an object..
	replaceAll: (str, obj) => {
		if(str === null || typeof str === 'undefined') {
			return null;
		}
		for (const x in obj) {
			str = str.replace(new RegExp(x, 'g'), obj[x]);
		}
		return str;
	},

	unescapeHtml: safe =>
		safe.replace(/\\&amp\\;/g, '&')
		.replace(/\\&lt\\;/g, '<')
		.replace(/\\&gt\\;/g, '>')
		.replace(/\\&quot\\;/g, '"')
		.replace(/\\&#039\\;/g, '\''),

	// Escaping values:
	// http://ircv3.net/specs/core/message-tags-3.2.html#escaping-values
	unescapeIRC: msg => {
		if(!msg || typeof msg !== 'string' || !msg.includes('\\')) {
			return msg;
		}
		return msg.replace(
			unescapeIRCRegex,
			(m, p) => p in ircEscapedChars ? ircEscapedChars[p] : p
		);
	},

	escapeIRC: msg => {
		if(!msg || typeof msg !== 'string') {
			return msg;
		}
		return msg.replace(
			escapeIRCRegex,
			(m, p) => p in ircUnescapedChars ? `\\${ircUnescapedChars[p]}` : p
		);
	},

	// Add word to a string..
	addWord: (line, word) => line.length ? line + ' ' + word : line + word,

	// Split a line but try not to cut a word in half..
	splitLine: (input, length) => {
		let lastSpace = input.substring(0, length).lastIndexOf(' ');
		// No spaces found, split at the very end to avoid a loop..
		if(lastSpace === -1) {
			lastSpace = length - 1;
		}
		return [ input.substring(0, lastSpace), input.substring(lastSpace + 1) ];
	},

	// Extract a number from a string..
	extractNumber: str => {
		const parts = str.split(' ');
		for (let i = 0; i < parts.length; i++) {
			if(_.isInteger(parts[i])) {
				return ~~parts[i];
			}
		}
		return 0;
	},

	// Format the date..
	formatDate: date => {
		let hours = date.getHours();
		let mins  = date.getMinutes();

		hours = (hours < 10 ? '0' : '') + hours;
		mins = (mins < 10 ? '0' : '') + mins;
		return `${hours}:${mins}`;
	},

	// Inherit the prototype methods from one constructor into another..
	inherits: (ctor, superCtor) => {
		ctor.super_ = superCtor;
		const TempCtor = function () {};
		TempCtor.prototype = superCtor.prototype;
		ctor.prototype = new TempCtor();
		ctor.prototype.constructor = ctor;
	},

	// Return whether inside a Node application or not..
	isNode: () => {
		try {
			return typeof process === 'object' &&
				Object.prototype.toString.call(process) === '[object process]';
		} catch(e) {}
		return false;
	}
};
<commit_msg>utils: move static regex<commit_after>// eslint-disable-next-line no-control-regex
const actionMessageRegex = /^\u0001ACTION ([^\u0001]+)\u0001$/;
const justinFanRegex = /^(justinfan)(\d+$)/;
const unescapeIRCRegex = /\\([sn:r\\])/g;
const escapeIRCRegex = /([ \n;\r\\])/g;
const ircEscapedChars = { s: ' ', n: '', ':': ';', r: '' };
const ircUnescapedChars = { ' ': 's', '\n': 'n', ';': ':', '\r': 'r' };
const urlRegex = new RegExp('^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))\\.?)(?::\\d{2,5})?(?:[/?#]\\S*)?$', 'i');
const regexEmoteRegex = /[|\\^$*+?:#]/;
const _ = module.exports = {
	// Return the second value if the first value is undefined..
	get: (a, b) => typeof a === 'undefined' ? b : a,

	// Indirectly use hasOwnProperty
	hasOwn: (obj, key) => ({}).hasOwnProperty.call(obj, key),

	// Race a promise against a delay..
	promiseDelay: time => new Promise(resolve => setTimeout(resolve, time)),

	// Value is a finite number..
	isFinite: int => isFinite(int) && !isNaN(parseFloat(int)),

	// Parse string to number. Returns NaN if string can't be parsed to number..
	toNumber: (num, precision) => {
		if(num === null) {
			return 0;
		}
		const factor = Math.pow(10, _.isFinite(precision) ? precision : 0);
		return Math.round(num * factor) / factor;
	},

	// Value is an integer..
	isInteger: int => !isNaN(_.toNumber(int, 0)),

	// Value is a regex..
	isRegex: str => regexEmoteRegex.test(str),

	// Value is a valid url..
	isURL: str => urlRegex.test(str),

	// Return a random justinfan username..
	justinfan: () => `justinfan${Math.floor((Math.random() * 80000) + 1000)}`,

	// Username is a justinfan username..
	isJustinfan: username => justinFanRegex.test(username),

	// Return a valid channel name..
	channel: str => {
		const channel = (str ? str : '').toLowerCase();
		return channel[0] === '#' ? channel : '#' + channel;
	},

	// Return a valid username..
	username: str => {
		const username = (str ? str : '').toLowerCase();
		return username[0] === '#' ? username.slice(1) : username;
	},

	// Return a valid token..
	token: str => str ? str.toLowerCase().replace('oauth:', '') : '',

	// Return a valid password..
	password: str => {
		const token = _.token(str);
		return token ? `oauth:${token}` : '';
	},

	actionMessage: msg => msg.match(actionMessageRegex),

	// Replace all occurences of a string using an object..
	replaceAll: (str, obj) => {
		if(str === null || typeof str === 'undefined') {
			return null;
		}
		for (const x in obj) {
			str = str.replace(new RegExp(x, 'g'), obj[x]);
		}
		return str;
	},

	unescapeHtml: safe =>
		safe.replace(/\\&amp\\;/g, '&')
		.replace(/\\&lt\\;/g, '<')
		.replace(/\\&gt\\;/g, '>')
		.replace(/\\&quot\\;/g, '"')
		.replace(/\\&#039\\;/g, '\''),

	// Escaping values:
	// http://ircv3.net/specs/core/message-tags-3.2.html#escaping-values
	unescapeIRC: msg => {
		if(!msg || typeof msg !== 'string' || !msg.includes('\\')) {
			return msg;
		}
		return msg.replace(
			unescapeIRCRegex,
			(m, p) => p in ircEscapedChars ? ircEscapedChars[p] : p
		);
	},

	escapeIRC: msg => {
		if(!msg || typeof msg !== 'string') {
			return msg;
		}
		return msg.replace(
			escapeIRCRegex,
			(m, p) => p in ircUnescapedChars ? `\\${ircUnescapedChars[p]}` : p
		);
	},

	// Add word to a string..
	addWord: (line, word) => line.length ? line + ' ' + word : line + word,

	// Split a line but try not to cut a word in half..
	splitLine: (input, length) => {
		let lastSpace = input.substring(0, length).lastIndexOf(' ');
		// No spaces found, split at the very end to avoid a loop..
		if(lastSpace === -1) {
			lastSpace = length - 1;
		}
		return [ input.substring(0, lastSpace), input.substring(lastSpace + 1) ];
	},

	// Extract a number from a string..
	extractNumber: str => {
		const parts = str.split(' ');
		for (let i = 0; i < parts.length; i++) {
			if(_.isInteger(parts[i])) {
				return ~~parts[i];
			}
		}
		return 0;
	},

	// Format the date..
	formatDate: date => {
		let hours = date.getHours();
		let mins  = date.getMinutes();

		hours = (hours < 10 ? '0' : '') + hours;
		mins = (mins < 10 ? '0' : '') + mins;
		return `${hours}:${mins}`;
	},

	// Inherit the prototype methods from one constructor into another..
	inherits: (ctor, superCtor) => {
		ctor.super_ = superCtor;
		const TempCtor = function () {};
		TempCtor.prototype = superCtor.prototype;
		ctor.prototype = new TempCtor();
		ctor.prototype.constructor = ctor;
	},

	// Return whether inside a Node application or not..
	isNode: () => {
		try {
			return typeof process === 'object' &&
				Object.prototype.toString.call(process) === '[object process]';
		} catch(e) {}
		return false;
	}
};
<|endoftext|>


<commit_before>/*
 * This script automatically merges the Greenkeeper's commit.
 */

const { exec, getLastCommitAuthorEmail, getLastCommitAuthorName, getLastCommitSubject, getLastCommitsWithSameMessage } = require('../scripts/utils');

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

// The format of the log should be `--oneline`
const getSHAs = (log) => {
    return log.trim()
        .split('\n')
        .map((line) => {
            return line.trim().split(' ')[0];
        });
};

const main = async () => {
    const GIT_COMMIT_SUBJECT = await getLastCommitSubject();
    const COMMITS_TO_SQUASH = await getLastCommitsWithSameMessage();
    const GIT_GREENKEEPER_BRANCH = process.env.TRAVIS_BRANCH; // eslint-disable-line no-process-env
    const GIT_REPO_SLUG = process.env.TRAVIS_REPO_SLUG; // eslint-disable-line no-process-env
    const GIT_USER_EMAIL = await getLastCommitAuthorEmail();
    const GIT_USER_NAME = await getLastCommitAuthorName();

    await exec('Configure the Git user name.', `git config --global user.name "${GIT_USER_NAME}"`);
    await exec('Configure the Git user email.', `git config --global user.email "${GIT_USER_EMAIL}"`);

    await exec(`Set remote.`, `git remote set-branches origin master`);
    await exec('Fetch content from origin', 'git fetch origin --unshallow');

    /*
     * Greenkeeper updates each package in the monorepo with the same
     * dependency in different commits but the project style is only 1.
     *
     * Instead of rebase/squash, do a soft reset with the same commit
     * message.
     */
    await exec(`Soft reset latest ${COMMITS_TO_SQUASH} commits.`, `git reset --soft HEAD~${COMMITS_TO_SQUASH}`);
    const files = await exec(`Files changed.`, `git status`);

    console.log(files);

    await exec(`Create new commit.`, `git commit --message="${GIT_COMMIT_SUBJECT}"`);

    /*
     * The changes are in dettached mode, and couldn't find a way to
     * rebase correctly in master. Store the SHA to cherry-pick later
     */
    const log = await exec(`Latest log entry.`, `git log --oneline -n 1`);
    const latestSha = getSHAs(log)[0];

    await exec(`Switch to the 'master' branch.`, 'git checkout master');
    await exec(`Cherry-pick '${latestSha}' into 'master'.`, `git cherry-pick ${latestSha}`);

    await exec(`Push changes to 'master'.`, `git push git@github.com:${GIT_REPO_SLUG}.git master`);
    await exec(`Delete '${GIT_GREENKEEPER_BRANCH}' branch.`, `git push git@github.com:${GIT_REPO_SLUG}.git :${GIT_GREENKEEPER_BRANCH}`);
};

main();
<commit_msg>Chore: Escape "`" from the commit message<commit_after>/*
 * This script automatically merges the Greenkeeper's commit.
 */

const {
    exec,
    getLastCommitAuthorEmail,
    getLastCommitAuthorName,
    getLastCommitSubject,
    getLastCommitsWithSameMessage
} = require('../scripts/utils');

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

// The format of the log should be `--oneline`
const getSHAs = (log) => {
    return log.trim()
        .split('\n')
        .map((line) => {
            return line.trim().split(' ')[0];
        });
};

const main = async () => {
    const GIT_COMMIT_SUBJECT = (await getLastCommitSubject()).replace(/`/g, '\\`');
    const COMMITS_TO_SQUASH = await getLastCommitsWithSameMessage();
    const GIT_GREENKEEPER_BRANCH = process.env.TRAVIS_BRANCH; // eslint-disable-line no-process-env
    const GIT_REPO_SLUG = process.env.TRAVIS_REPO_SLUG; // eslint-disable-line no-process-env
    const GIT_USER_EMAIL = await getLastCommitAuthorEmail();
    const GIT_USER_NAME = await getLastCommitAuthorName();

    await exec('Configure the Git user name.', `git config --global user.name "${GIT_USER_NAME}"`);
    await exec('Configure the Git user email.', `git config --global user.email "${GIT_USER_EMAIL}"`);

    await exec(`Set remote.`, `git remote set-branches origin master`);
    await exec('Fetch content from origin', 'git fetch origin --unshallow');

    /*
     * Greenkeeper updates each package in the monorepo with the same
     * dependency in different commits but the project style is only 1.
     *
     * Instead of rebase/squash, do a soft reset with the same commit
     * message.
     */
    await exec(`Soft reset latest ${COMMITS_TO_SQUASH} commits.`, `git reset --soft HEAD~${COMMITS_TO_SQUASH}`);
    const files = await exec(`Files changed.`, `git status`);

    console.log(files);

    await exec(`Create new commit.`, `git commit --message="${GIT_COMMIT_SUBJECT}"`);

    /*
     * The changes are in dettached mode, and couldn't find a way to
     * rebase correctly in master. Store the SHA to cherry-pick later
     */
    const log = await exec(`Latest log entry.`, `git log --oneline -n 1`);
    const latestSha = getSHAs(log)[0];

    await exec(`Switch to the 'master' branch.`, 'git checkout master');
    await exec(`Cherry-pick '${latestSha}' into 'master'.`, `git cherry-pick ${latestSha}`);

    await exec(`Push changes to 'master'.`, `git push git@github.com:${GIT_REPO_SLUG}.git master`);
    await exec(`Delete '${GIT_GREENKEEPER_BRANCH}' branch.`, `git push git@github.com:${GIT_REPO_SLUG}.git :${GIT_GREENKEEPER_BRANCH}`);
};

main();
<|endoftext|>


<commit_before>'use strict';
const tools = require('../tools.js');

const adapterName = 'heos';
const searchDeviceType = 'urn:schemas-denon-com:device:ACT-Denon:1';

function addHeos(ip, data, options) {
    let instance;
    for (let j = 0; j < options.newInstances.length; j++) {
        if (options.newInstances[j].common && options.newInstances[j].common.name === adapterName) {
            instance = options.newInstances[j];
            break;
        }
    }
    if (!instance) {
        for (let i = 0; i < options.existingInstances.length; i++) {
            if (options.existingInstances[i].common && options.existingInstances[i].common.name === adapterName) {
                instance = JSON.parse(JSON.stringify(options.existingInstances[i])); // do not modify existing instance
                break;
            }
        }
    }

    if (!instance) {
        instance = {
            _id: tools.getNextInstanceID(adapterName, options),
            common: {
                name: adapterName,
                title: 'HEOS'
            },
            native: {
            },
            comment: {
                add: 'HEOS',
                advice: false,
                inputs: [
                    {
                        name: 'native.username',
                        def: '',
                        required: true,
                        type: 'username',
                        title: 'Username'
                    },
                    {
                        name: 'native.password',
                        def: '',
                        required: true,
                        type: 'password',
                        title: 'Password'
                    }
                ]
            }
        };
        options.newInstances.push(instance);
        return true;
    }
    return false;
}

function detect(ip, device, options, callback) {
    let foundInstance = false;

    device._upnp.forEach(upnp => {
        if (JSON.stringify(device._upnp).includes(searchDeviceType)) {
            options.log.debug("HEOS found: " + JSON.stringify(upnp));
            if (addHeos(ip, device, options)) {
                foundInstance = true;
            } else {
                options.log.debug("HEOS adapter already exists");
            }
        }
    });

    callback(null, foundInstance, ip);
}

exports.detect  = detect;
exports.type    = ['upnp'];
exports.timeout = 100;
<commit_msg>Update heos.js<commit_after>'use strict';
const tools = require('../tools.js');

const adapterName = 'heos';
const searchDeviceType = 'urn:schemas-denon-com:device:ACT-Denon:1';

function addHeos(ip, data, options) {
    let instance;
    for (let j = 0; j < options.newInstances.length; j++) {
        if (options.newInstances[j].common && options.newInstances[j].common.name === adapterName) {
            instance = options.newInstances[j];
            break;
        }
    }
    if (!instance) {
        for (let i = 0; i < options.existingInstances.length; i++) {
            if (options.existingInstances[i].common && options.existingInstances[i].common.name === adapterName) {
                instance = JSON.parse(JSON.stringify(options.existingInstances[i])); // do not modify existing instance
                break;
            }
        }
    }

    if (!instance) {
        instance = {
            _id: tools.getNextInstanceID(adapterName, options),
            common: {
                name: adapterName,
                title: 'HEOS'
            },
            native: {
            },
            comment: {
                add: 'HEOS',
                advice: false,
                inputs: [
                    {
                        name: 'native.username',
                        def: '',
                        required: true,
                        type: 'username',
                        title: 'Username'
                    },
                    {
                        name: 'native.password',
                        def: '',
                        required: true,
                        type: 'password',
                        title: 'Password'
                    }
                ]
            }
        };
        options.newInstances.push(instance);
        return true;
    }
    return false;
}

function detect(ip, device, options, callback) {
    let foundInstance = false;

    device._upnp.forEach(upnp => {
        if (JSON.stringify(device._upnp).includes(searchDeviceType)) {
            options.log.debug('HEOS found: ' + JSON.stringify(upnp));
            if (addHeos(ip, device, options)) {
                foundInstance = true;
            } else {
                options.log.debug("HEOS adapter already exists");
            }
        }
    });

    callback(null, foundInstance, ip);
}

exports.detect  = detect;
exports.type    = ['upnp'];
exports.timeout = 100;
<|endoftext|>


<commit_before>/**
 * map tab shown in cartodb admin
 */

cdb.open.PublicMapTab = cdb.admin.MapTab.extend({

  className: 'map',

  initialize: function() {
    this.template = this.getTemplate('table_public/views/maptab_public');
    this.map_enabled = false;
  },

  /**
   * map can't be loaded from the beggining, it needs the DOM to be loaded
   * so we wait until is actually shown to create the mapview and show it
   */
  enableMap: function() {

    var self = this;
    if(!this.map_enabled && !this.vis) {
      var div = this.$('#map');
      this.vis = new cdb.vis.Vis({ el: div });
      this.vis.load(this.options.vizjson, {
        search: true
      });
    }
  },

  clearMap: function() {
  },

  render: function() {
    this.$el.html(this.template());
    return this;
  }

});

<commit_msg>fixed #1551<commit_after>/**
 * map tab shown in cartodb admin
 */

cdb.open.PublicMapTab = cdb.admin.MapTab.extend({

  className: 'map',

  initialize: function() {
    this.template = this.getTemplate('table_public/views/maptab_public');
    this.map_enabled = false;
  },

  /**
   * map can't be loaded from the beggining, it needs the DOM to be loaded
   * so we wait until is actually shown to create the mapview and show it
   */
  enableMap: function() {

    var self = this;
    if(!this.map_enabled && !this.vis) {
      var div = this.$('#map');
      this.vis = new cdb.vis.Vis({ el: div });
      this.vis.load(this.options.vizjson, {
        search: true,
        no_cdn: cdb.config.get('debug')
      });
    }
  },

  clearMap: function() {
  },

  render: function() {
    this.$el.html(this.template());
    return this;
  }

});

<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var inherits = require('util').inherits;
var extend = require('xtend');
var setImmediate = require('timers').setImmediate;

var TChannelPeersBase = require('./peers_base.js');
var TChannelPeer = require('./peer');
var TChannelSelfPeer = require('./self_peer');

function TChannelRootPeers(channel, options) {
    TChannelPeersBase.call(this, channel, options);
    this.allocPeerEvent = this.defineEvent('allocPeer');
    this.peerOptions = this.options.peerOptions || {};
    this.selfPeer = null;
}

inherits(TChannelRootPeers, TChannelPeersBase);

TChannelRootPeers.prototype.close = function close(callback) {
    var self = this;

    var peers = self.values();
    if (self.selfPeer) {
        peers.push(self.selfPeer);
    }
    TChannelPeersBase.prototype.close.call(self, peers, callback);
};

TChannelRootPeers.prototype.sanitySweep =
function sanitySweep(callback) {
    var self = this;

    if (!self.selfPeer) {
        TChannelPeersBase.prototype.sanitySweep.call(self, callback);
        return;
    }

    nextConn(self.selfPeer.connections, 0, function connSweepDone(err) {
        if (err) {
            callback(err);
            return;
        }

        TChannelPeersBase.prototype.sanitySweep.call(self, callback);
    });

    function nextConn(connections, index, cb) {
        if (index >= connections.length) {
            cb(null);
            return;
        }

        var connection = connections[index];
        connection.ops.sanitySweep(function opsSweepDone() {
            setImmediate(deferNextConn);
        });

        function deferNextConn() {
            nextConn(connections, index + 1, cb);
        }
    }
};

TChannelRootPeers.prototype.getSelfPeer = function getSelfPeer() {
    var self = this;

    if (!self.selfPeer) {
        self.selfPeer = new TChannelSelfPeer(self.channel);
    }
    return self.selfPeer;
};

TChannelRootPeers.prototype.add = function add(hostPort, options) {
    /*eslint max-statements: [2, 25]*/
    var self = this;

    var peer = self._map[hostPort];
    if (peer) {
        return peer;
    }

    if (hostPort === self.channel.hostPort) {
        return self.getSelfPeer();
    }

    options = options || extend({}, self.peerOptions);
    options.preferConnectionDirection = self.preferConnectionDirection;
    peer = new TChannelPeer(self.channel, hostPort, options);
    self.allocPeerEvent.emit(self, peer);

    self._map[hostPort] = peer;
    self._keys.push(hostPort);

    return peer;
};

TChannelRootPeers.prototype.clear = function clear() {
    var self = this;

    var names = Object.keys(self.channel.subChannels);
    for (var i = 0; i < names.length; i++) {
        var subChannel = self.channel.subChannels[names[i]];
        subChannel.peers.clear();
    }

    self._map = Object.create(null);
    self._keys = [];
};

TChannelRootPeers.prototype._delete = function _del(peer) {
    var self = this;

    var names = Object.keys(self.channel.subChannels);
    for (var i = 0; i < names.length; i++) {
        var subChannel = self.channel.subChannels[names[i]];
        subChannel.peers._delete(peer);
    }

    delete self._map[peer.hostPort];
    var index = self._keys.indexOf(peer.hostPort);
    popout(self._keys, index);
};

TChannelRootPeers.prototype.choosePeer = function choosePeer(req) {
    return null;
};

function popout(array, i) {
    if (!array.length) {
        return;
    }

    var j = array.length - 1;
    if (i !== j) {
        var tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
    array.pop();
}

module.exports = TChannelRootPeers;
<commit_msg>root_peers: remove SelfPeer references<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var inherits = require('util').inherits;
var extend = require('xtend');

var TChannelPeersBase = require('./peers_base.js');
var TChannelPeer = require('./peer');

function TChannelRootPeers(channel, options) {
    TChannelPeersBase.call(this, channel, options);
    this.allocPeerEvent = this.defineEvent('allocPeer');
    this.peerOptions = this.options.peerOptions || {};
}

inherits(TChannelRootPeers, TChannelPeersBase);

TChannelRootPeers.prototype.close = function close(callback) {
    var self = this;

    var peers = self.values();
    TChannelPeersBase.prototype.close.call(self, peers, callback);
};

TChannelRootPeers.prototype.add = function add(hostPort, options) {
    /*eslint max-statements: [2, 25]*/
    var self = this;

    var peer = self._map[hostPort];
    if (peer) {
        return peer;
    }

    options = options || extend({}, self.peerOptions);
    options.preferConnectionDirection = self.preferConnectionDirection;
    peer = new TChannelPeer(self.channel, hostPort, options);
    self.allocPeerEvent.emit(self, peer);

    self._map[hostPort] = peer;
    self._keys.push(hostPort);

    return peer;
};

TChannelRootPeers.prototype.clear = function clear() {
    var self = this;

    var names = Object.keys(self.channel.subChannels);
    for (var i = 0; i < names.length; i++) {
        var subChannel = self.channel.subChannels[names[i]];
        subChannel.peers.clear();
    }

    self._map = Object.create(null);
    self._keys = [];
};

TChannelRootPeers.prototype._delete = function _del(peer) {
    var self = this;

    var names = Object.keys(self.channel.subChannels);
    for (var i = 0; i < names.length; i++) {
        var subChannel = self.channel.subChannels[names[i]];
        subChannel.peers._delete(peer);
    }

    delete self._map[peer.hostPort];
    var index = self._keys.indexOf(peer.hostPort);
    popout(self._keys, index);
};

TChannelRootPeers.prototype.choosePeer = function choosePeer(req) {
    return null;
};

function popout(array, i) {
    if (!array.length) {
        return;
    }

    var j = array.length - 1;
    if (i !== j) {
        var tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
    array.pop();
}

module.exports = TChannelRootPeers;
<|endoftext|>


<commit_before>
	//google api keyinizi aşağıya girdikten sonra script çalışır
	$(function(){
		$.ARamaYap = {
			GetStringDuration: function (string){
				var array=string.match(/(\d+)(?=[MHS])/ig)||[],
				formatted=array.map(function(item)
				{
					if(item.length<2) return '0'+item;return item;
				}).join(':');
				 return formatted;
			},

			SerializeQuerySearch: function (query,pagetoken){

			var NextPage='&pageToken='+pagetoken,
				aranan=query,
				Max = 16,
				JSONurl= 'https://www.googleapis.com/youtube/v3/search?part=snippet&q='+aranan+'&key='+key+'&maxResults='+Max+'&type=video'+NextPage,
				sonuc = $("#sonuc"),
				key  = 'sizin google api key';
			sonuc.empty();

			$.getJSON(JSONurl ,function(data){

				var sayilrle=data.nextPageToken;$("._bpls[page-token=next]").attr("id",sayilrle);

			$.each(data.items,function(i,item){var kod=item.id.videoId,isim=item.snippet.title;
				$(".Results").empty();$("._bpls[page-token=next]").show();
				$.getJSON('https://www.googleapis.com/youtube/v3/videos?id='+kod+'&part=contentDetails&key'+key,function(data){

					$.each(data.items,function(i,item){

					var string=item.contentDetails.duration,
						formatted= $.ARamaYap.GetStringDuration(string),
						ne = '
'+isim+''+formatted+'
';

					sonuc.append(ne);

					});
				});

				return true});
			});
			}
		}
	});

	$(document).ready(function(){

		$('#test_arama').keyup(function(){

			var query = $(this).val();
			console.log(query); //test edelim.
			$.ARamaYap.SerializeQuerySearch(query,"");

		});

	});

<commit_msg>Update youtube.search.js<commit_after>
	//google api keyinizi aşağıya girdikten sonra script çalışır
	$(function(){
		$.ARamaYap = {
			GetStringDuration: function (string){
				var array=string.match(/(\d+)(?=[MHS])/ig)||[],
				formatted=array.map(function(item)
				{
					if(item.length<2) return '0'+item;return item;
				}).join(':');
				 return formatted;
			},

			SerializeQuerySearch: function (query,pagetoken){

			var NextPage='&pageToken='+pagetoken,
				aranan=query,
				Max = 16,
				key  = 'sizin google api key',
				JSONurl= 'https://www.googleapis.com/youtube/v3/search?part=snippet&q='+aranan+'&key='+key+'&maxResults='+Max+'&type=video'+NextPage,
				sonuc = $("#sonuc");
			sonuc.empty();

			$.getJSON(JSONurl ,function(data){

				var sayilrle=data.nextPageToken;$("._bpls[page-token=next]").attr("id",sayilrle);

			$.each(data.items,function(i,item){var kod=item.id.videoId,isim=item.snippet.title;
				$(".Results").empty();$("._bpls[page-token=next]").show();
				$.getJSON('https://www.googleapis.com/youtube/v3/videos?id='+kod+'&part=contentDetails&key'+key,function(data){

					$.each(data.items,function(i,item){

					var string=item.contentDetails.duration,
						formatted= $.ARamaYap.GetStringDuration(string),
						ne = '
'+isim+''+formatted+'
';

					sonuc.append(ne);

					});
				});

				return true});
			});
			}
		}
	});

	$(document).ready(function(){

		$('#test_arama').keyup(function(){

			var query = $(this).val();
			console.log(query); //test edelim.
			$.ARamaYap.SerializeQuerySearch(query,"");

		});

	});

<|endoftext|>