<commit_before>/**
 * FIELDS
 *
 * Angular-powered input components go into this file.
 */

var webutil = require('../util/web');

var module = angular.module('fields', []);

/**
 * Combobox input element.
 *
 * Adds a autocomplete-like dropdown to an input element.
 *
 * @param {string} rpCombobox Pass a function that takes a string and returns
 *   the matching autocompletions.
 */
module.directive('rpCombobox', [function () {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function (scope, el, attrs, ngModel) {
      var keyCursor = -1;

      el.wrap('
');
      el.attr('autocomplete', 'off');
      var cplEl = $('

').hide();
      el.parent().append(cplEl);
      if (attrs.rpComboboxSmall) {
        el.parent().addClass("rp-combobox-small");
      }

      // Explicit select button
      if (attrs.rpComboboxSelect) {
        var selectEl = $('
').appendTo(el.parent());
        selectEl.addClass('select');
        selectEl.mousedown(function (e) {
          e.preventDefault();
        });
        selectEl.click(function () {
          var complFn = scope.$eval(attrs.rpCombobox);
          if ("function" !== typeof complFn) {
            var options = complFn;
            complFn = webutil.queryFromOptions(complFn);
            scope.$watch(options, function(value) {
              setCompletions(complFn());
            });
          }
          setCompletions(complFn());
          if (cplEl.is(':visible')) {
            el.blur();
          } else {
            setCompletions(complFn());
            el.focus();
          }
        });
      }

      // Listen for keyboard keydown events
      el.keydown(function (e) {
        // "Up/Down" key press
        if (e.which === 38 || e.which === 40) {
          if (!cplEl.children().length) {
            updateCompletions();
          }
          e.preventDefault();

          // Move cursor (highlighted option) up/down
          if (e.which === 38) keyCursor--;
          else keyCursor++;

          updateKeyCursor();
        }

        // "Enter" key press (select the option)
        else if (e.which === 13) {
          var curEl = cplEl.find('li.cursor');
          if (cplEl.is(':visible')) {
            e.preventDefault();
          }
          if (cplEl.find('li').length === 1) {
            // Only one completion, we'll assume that's the one they want
            selectCompletion(cplEl.find('li'));
          } else if (curEl.length === 1) {
            selectCompletion(curEl);
          }
        }

        // "ESC" key press
        else if (e.which === 27) {
          // Hide the options list
          setVisible(false);
        }
      });

      // Listen for keyboard keyup events to enable binding
      el.keyup(function(e) {
        // Ignore Left, up, right, down
        if (e.which >= 37 && e.which <= 40) return;
        // Ignore Enter, Esc
        if (e.which === 13 || e.which === 27) return;

        // Any other keypress should update completions list
        updateCompletions();
      });

      el.focus(function() {
        keyCursor = -1;
        triggerCompletions();
      });

      el.blur(function() {
        setVisible(false);
      });

      cplEl.mousedown(function (e) {
        e.preventDefault();
      });

      function setVisible(to) {
        el.parent()[to ? 'addClass' : 'removeClass']('active');
        cplEl[to ? 'fadeIn' : 'fadeOut']('fast');
      }

      /**
       * Update completions list
       */
      function updateCompletions() {
        var match = ngModel.$viewValue, // Input value
            completions = [], re = null,
            complFn, valueOption;

        // Query function. This should return the full options list
        complFn = scope.$eval(attrs.rpCombobox);

        // Uses the default query function, if it's not defined
        if ("function" !== typeof complFn) {
          complFn = webutil.queryFromOptions(complFn);
        }

        if ("string" === typeof match && match.length) {
          // Escape field value
          var escaped = webutil.escapeRegExp(match);
          // Build the regex for completion list lookup
          re = new RegExp('('+escaped+')', 'i');

          completions = complFn(match, re);
        }

        // Value as option
        if (attrs.rpComboboxValueAsOption && match.length) {
          var prefix = attrs.rpComboboxValueAsOptionPrefix;

          valueOption = (prefix && 0 !== match.indexOf(prefix))
            ? prefix + match
            : match;

          completions.push(valueOption);
        }

        // Value as ripple name
        if (attrs.rpComboboxValueAsRippleName && match.length) { // TODO Don't do a client check in validators
          valueOption = (0 !== match.indexOf('~'))
            ? '~' + match
            : match;

          if (webutil.isRippleName(valueOption)) {
            completions.push(valueOption);
          }
        }

        // By fading out without updating the completions we get a smoother effect
        if (!completions.length) {
          setVisible(false);
          return;
        }

        setCompletions(completions, re);
        triggerCompletions();
      }

      function setCompletions(completions, re) {
        cplEl.empty();
        keyCursor = -1;
        completions.forEach(function (completion) {
          var additional = '';

          if ("string" === typeof completion) {
            val = completion;
          } else {
            val = completion.name;

            if (completion.additional) {
              additional = '' + completion.additional + '';
            }
          }

          if (re) val = val.replace(re, '$1');
          var completionHtml = $('
' + val + '' + additional + '
');
          el.parent().find('.completions').append(completionHtml);
        });
      }

      function triggerCompletions() {
        var cplEls = cplEl.children();
        var visible = !!cplEls.length;
        if (cplEls.length === 1 &&
            cplEls.eq(0).text() === el.val()) {
          visible = false;
        }
        setVisible(visible);
      }

      // Update the cursor (highlight selected option)
      function updateKeyCursor() {
        var opts = cplEl.find('li');
        keyCursor = Math.max(keyCursor, 0);
        keyCursor = Math.min(keyCursor, opts.length - 1);
        opts.removeClass('cursor');
        opts.eq(keyCursor).addClass('cursor');
      }

      function selectCompletion(liEl) {
        var val = $(liEl).find('.val').text();
        scope.$apply(function () {
          el.val(val);
          ngModel.$setViewValue(val);
          setVisible(false);
          el.blur();
        });
      }

      function escape(str) {
        return str
          .replace(/&/g, '&')
          .replace(/</g, '<')
          .replace(/>/g, '>')
          .replace(/"/g, '"')
          .replace(/'/g, ''');
      }

      cplEl.on('click', 'li', function () {
        selectCompletion(this);
      });
    }
  };
}]);

/**
 * Datepicker
 */
module.directive('rpDatepicker', [function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, element, attr, ngModel) {
      attr.$observe('rpDatepicker', function() {
        var dp = $(element).datepicker();
        dp.on('changeDate', function(e) {
          scope.$apply(function () {
            ngModel.$setViewValue(e.date.getMonth() ? e.date : new Date(e.date));
          });
        });
        scope.$watch(attr.ngModel,function() {
          var update = ngModel.$viewValue;

          function falsy(v) {return v == '0' || v == 'false'; }

          if (!falsy(attr.ignoreInvalidUpdate) &&
               (update == null ||
                 (update instanceof Date && isNaN(update.getYear())) )) {
              return;
            } else {
              dp.datepicker('setValue', update)
                .datepicker('update');
            }
        });
      });
    }
  };
}]);

module.directive('fileUploadButton', function() {
  return {
    require: '^ngModel',
    link: function(scope, element, attributes) {
      var el = angular.element(element);

      var button = el.children()[0];

      el.css({
        'position': 'relative',
        'margin-bottom': 14
      });

      var fileInput = angular.element('<input type="file" ng-model="walletfile" nwsaveas="wallet.txt" />');

      fileInput.bind('change', function () {
          scope.$apply(attributes.fileUploadButton);
      });

      fileInput.css({
        position: 'absolute',
        top: 0,
        left: 0,
        'z-index': '2',
        width: '100%',
        height: '100%',
        opacity: '0',
        cursor: 'pointer'
      });

      el.append(fileInput);
    }
  };
});

<commit_msg>[FIX] Send: fix on Enter behaviour  (RT-2624)<commit_after>/**
 * FIELDS
 *
 * Angular-powered input components go into this file.
 */

var webutil = require('../util/web');

var module = angular.module('fields', []);

/**
 * Combobox input element.
 *
 * Adds a autocomplete-like dropdown to an input element.
 *
 * @param {string} rpCombobox Pass a function that takes a string and returns
 *   the matching autocompletions.
 */
module.directive('rpCombobox', [function () {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function (scope, el, attrs, ngModel) {
      var keyCursor = -1;

      el.wrap('
');
      el.attr('autocomplete', 'off');
      var cplEl = $('

').hide();
      el.parent().append(cplEl);
      if (attrs.rpComboboxSmall) {
        el.parent().addClass("rp-combobox-small");
      }

      // Explicit select button
      if (attrs.rpComboboxSelect) {
        var selectEl = $('
').appendTo(el.parent());
        selectEl.addClass('select');
        selectEl.mousedown(function (e) {
          e.preventDefault();
        });
        selectEl.click(function () {
          var complFn = scope.$eval(attrs.rpCombobox);
          if ("function" !== typeof complFn) {
            var options = complFn;
            complFn = webutil.queryFromOptions(complFn);
            scope.$watch(options, function(value) {
              setCompletions(complFn());
            });
          }
          setCompletions(complFn());
          if (cplEl.is(':visible')) {
            el.blur();
          } else {
            setCompletions(complFn());
            el.focus();
          }
        });
      }

      // Listen for keyboard keydown events
      el.keydown(function (e) {
        // "Up/Down" key press
        if (e.which === 38 || e.which === 40) {
          if (!cplEl.children().length) {
            updateCompletions();
          }
          e.preventDefault();

          // Move cursor (highlighted option) up/down
          if (e.which === 38) keyCursor--;
          else keyCursor++;

          updateKeyCursor();
        }

        // "Enter" key press (select the option)
        else if (e.which === 13) {
          var curEl = cplEl.find('li.cursor');
          if (cplEl.is(':visible')) {
            e.preventDefault();

            if (cplEl.find('li').length === 1) {
              // Only one completion, we'll assume that's the one they want
              selectCompletion(cplEl.find('li'));
            } else if (curEl.length === 1) {
              selectCompletion(curEl);
            }
          }
        }

        // "ESC" key press
        else if (e.which === 27) {
          // Hide the options list
          setVisible(false);
        }
      });

      // Listen for keyboard keyup events to enable binding
      el.keyup(function(e) {
        // Ignore Left, up, right, down
        if (e.which >= 37 && e.which <= 40) return;
        // Ignore Enter, Esc
        if (e.which === 13 || e.which === 27) return;

        // Any other keypress should update completions list
        updateCompletions();
      });

      el.focus(function() {
        keyCursor = -1;
        triggerCompletions();
      });

      el.blur(function() {
        setVisible(false);
      });

      cplEl.mousedown(function (e) {
        e.preventDefault();
      });

      function setVisible(to) {
        el.parent()[to ? 'addClass' : 'removeClass']('active');
        cplEl[to ? 'fadeIn' : 'fadeOut']('fast');
      }

      /**
       * Update completions list
       */
      function updateCompletions() {
        var match = ngModel.$viewValue, // Input value
            completions = [], re = null,
            complFn, valueOption;

        // Query function. This should return the full options list
        complFn = scope.$eval(attrs.rpCombobox);

        // Uses the default query function, if it's not defined
        if ("function" !== typeof complFn) {
          complFn = webutil.queryFromOptions(complFn);
        }

        if ("string" === typeof match && match.length) {
          // Escape field value
          var escaped = webutil.escapeRegExp(match);
          // Build the regex for completion list lookup
          re = new RegExp('('+escaped+')', 'i');

          completions = complFn(match, re);
        }

        // Value as option
        if (attrs.rpComboboxValueAsOption && match.length) {
          var prefix = attrs.rpComboboxValueAsOptionPrefix;

          valueOption = (prefix && 0 !== match.indexOf(prefix))
            ? prefix + match
            : match;

          completions.push(valueOption);
        }

        // Value as ripple name
        if (attrs.rpComboboxValueAsRippleName && match.length) { // TODO Don't do a client check in validators
          valueOption = (0 !== match.indexOf('~'))
            ? '~' + match
            : match;

          if (webutil.isRippleName(valueOption)) {
            completions.push(valueOption);
          }
        }

        // By fading out without updating the completions we get a smoother effect
        if (!completions.length) {
          setVisible(false);
          return;
        }

        setCompletions(completions, re);
        triggerCompletions();
      }

      function setCompletions(completions, re) {
        cplEl.empty();
        keyCursor = -1;
        completions.forEach(function (completion) {
          var additional = '';

          if ("string" === typeof completion) {
            val = completion;
          } else {
            val = completion.name;

            if (completion.additional) {
              additional = '' + completion.additional + '';
            }
          }

          if (re) val = val.replace(re, '$1');
          var completionHtml = $('
' + val + '' + additional + '
');
          el.parent().find('.completions').append(completionHtml);
        });
      }

      function triggerCompletions() {
        var cplEls = cplEl.children();
        var visible = !!cplEls.length;
        if (cplEls.length === 1 &&
            cplEls.eq(0).text() === el.val()) {
          visible = false;
        }
        setVisible(visible);
      }

      // Update the cursor (highlight selected option)
      function updateKeyCursor() {
        var opts = cplEl.find('li');
        keyCursor = Math.max(keyCursor, 0);
        keyCursor = Math.min(keyCursor, opts.length - 1);
        opts.removeClass('cursor');
        opts.eq(keyCursor).addClass('cursor');
      }

      function selectCompletion(liEl) {
        var val = $(liEl).find('.val').text();
        scope.$apply(function () {
          el.val(val);
          ngModel.$setViewValue(val);
          setVisible(false);
          el.blur();
        });
      }

      function escape(str) {
        return str
          .replace(/&/g, '&')
          .replace(/</g, '<')
          .replace(/>/g, '>')
          .replace(/"/g, '"')
          .replace(/'/g, ''');
      }

      cplEl.on('click', 'li', function () {
        selectCompletion(this);
      });
    }
  };
}]);

/**
 * Datepicker
 */
module.directive('rpDatepicker', [function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, element, attr, ngModel) {
      attr.$observe('rpDatepicker', function() {
        var dp = $(element).datepicker();
        dp.on('changeDate', function(e) {
          scope.$apply(function () {
            ngModel.$setViewValue(e.date.getMonth() ? e.date : new Date(e.date));
          });
        });
        scope.$watch(attr.ngModel,function() {
          var update = ngModel.$viewValue;

          function falsy(v) {return v == '0' || v == 'false'; }

          if (!falsy(attr.ignoreInvalidUpdate) &&
               (update == null ||
                 (update instanceof Date && isNaN(update.getYear())) )) {
              return;
            } else {
              dp.datepicker('setValue', update)
                .datepicker('update');
            }
        });
      });
    }
  };
}]);

module.directive('fileUploadButton', function() {
  return {
    require: '^ngModel',
    link: function(scope, element, attributes) {
      var el = angular.element(element);

      var button = el.children()[0];

      el.css({
        'position': 'relative',
        'margin-bottom': 14
      });

      var fileInput = angular.element('<input type="file" ng-model="walletfile" nwsaveas="wallet.txt" />');

      fileInput.bind('change', function () {
          scope.$apply(attributes.fileUploadButton);
      });

      fileInput.css({
        position: 'absolute',
        top: 0,
        left: 0,
        'z-index': '2',
        width: '100%',
        height: '100%',
        opacity: '0',
        cursor: 'pointer'
      });

      el.append(fileInput);
    }
  };
});

<|endoftext|>


<commit_before>import $ from 'jquery';

class PopoverUI {
  constructor($node, options) {
    this.$node = $node;
    this.options = $.extend({}, {
      title: '',
      content: '',
      target: options.container,
      trigger: 'hover focus',
      placement: 'bottom',
    }, options);

    // create popover node
    this.$popover = $([
      '
',
        '
',
        '
',
      '
',
    ].join(''));

    // define event
    if (this.options.trigger !== 'manual') {
      const showCallback = this.show.bind(this);
      const hideCallback = this.hide.bind(this);
      const toggleCallback = this.toggle.bind(this);
      this.options.trigger.split(' ').forEach(function(eventName) {
        if (eventName === 'hover') {
          $node.off('mouseenter').on('mouseenter', showCallback);
          $node.off('mouseleave').on('mouseleave', hideCallback);
        } else if (eventName === 'click') {
          $node.on('click', toggleCallback);
        } else if (eventName === 'focus') {
          $node.on('focus', showCallback);
          $node.on('blur', hideCallback);
        }
      });
    }
  }

  show() {
    const $node = this.$node;
    const offset = $node.offset();
    debugger;
    const targetOffset = $(this.options.target).offset();
    offset.top -= targetOffset.top;
    offset.left -= targetOffset.left;

    const $popover = this.$popover;
    const content = this.options.content || $node.data('content');
    const placement = $node.data('placement') || this.options.placement;
    const dist = 6;

    $popover.addClass(placement);
    $popover.addClass('in');
    $popover.find('.note-popover-content').html(content);
    $popover.appendTo(this.options.target);

    const nodeWidth = $node.outerWidth();
    const nodeHeight = $node.outerHeight();
    const popoverWidth = $popover.outerWidth();
    const popoverHeight = $popover.outerHeight();

    if (placement === 'bottom') {
      $popover.css({
        top: offset.top + nodeHeight + dist,
        left: offset.left + (nodeWidth / 2 - popoverWidth / 2),
      });
    } else if (placement === 'top') {
      $popover.css({
        top: offset.top - popoverHeight - dist,
        left: offset.left + (nodeWidth / 2 - popoverWidth / 2),
      });
    } else if (placement === 'left') {
      $popover.css({
        top: offset.top + (nodeHeight / 2 - popoverHeight / 2),
        left: offset.left - popoverWidth - dist,
      });
    } else if (placement === 'right') {
      $popover.css({
        top: offset.top + (nodeHeight / 2 - popoverHeight / 2),
        left: offset.left + nodeWidth + dist,
      });
    }
  }

  hide() {
    this.$popover.removeClass('in');
    this.$popover.remove();
  }

  toggle() {
    if (this.$popover.hasClass('in')) {
      this.hide();
    } else {
      this.show();
    }
  }
}

export default PopoverUI;
<commit_msg>Remove obsoleted code<commit_after><|endoftext|>


<commit_before>YUI.add("model-list-tweets", function(Y) {
    "use strict";

    var tristis = Y.namespace("Tristis"),
        models  = Y.namespace("Tristis.Models"),

        Tweets;

    Tweets = Y.Base.create("tweets", Y.LazyModelList, [
        Y.namespace("Extensions").ModelListMore
    ], {
        sync : function(action, options, done) {
            var args = {},
                last;

            if(action === "more") {
                last = this.item(this.size() - 1);

                if(last) {
                    args.since_id = last.id_str;
                }
            }

            // TODO: Make list/home agnostic somehow. Config-based?
            tristis.twitter.get("lists/statuses", Y.merge({
                list_id     : this.get("list_id"),
                // TODO: configurable?
                include_rts : true,
                count       : 50
            }, args), done);
        },

        comparator : function(model) {
            return Date.parse(model.created_at);
        }
    }, {
        ATTRS : {
            list_id : null
        }
    });

    models.Tweets = Tweets;

}, "@VERSION@", {
    requires : [
        // YUI
        "base-build",
        "lazy-model-list",

        // Extensions
        "extension-model-list-more"
    ]
});
<commit_msg>Make Tweets model list generic<commit_after>YUI.add("model-list-tweets", function(Y) {
    "use strict";

    var tristis = Y.namespace("Tristis"),
        models  = Y.namespace("Tristis.Models"),

        Tweets;

    Tweets = Y.Base.create("tweets", Y.LazyModelList, [
        Y.namespace("Extensions").ModelListMore
    ], {
        sync : function(action, options, done) {
            var args = {},
                last;

            if(action === "more") {
                last = this.item(this.size() - 1);

                if(last) {
                    args.since_id = last.id_str;
                }
            }

            args = Y.merge(
                { count : 50 },
                this.get("config") || {},
                args
            );

            tristis.twitter.get(this.get("api"), args, done);
        },

        // Sort tweets by date
        comparator : function(model) {
            return Date.parse(model.created_at);
        },

        // Sort tweets by newest first
        _compare : function(a, b) {
            return b - a;
        }
    }, {
        ATTRS : {
            api     : null,
            config  : null
        }
    });

    models.Tweets = Tweets;

}, "@VERSION@", {
    requires : [
        // YUI
        "base-build",
        "lazy-model-list",

        // Extensions
        "extension-model-list-more"
    ]
});
<|endoftext|>


<commit_before>(function (Plugins, Utils, Set, undefined) {
  'use strict';

  // Plugin constructor and defaults
  // -------------------------------

  var Collision = function (element, options, planner) {
    var SPLITTING = 0
      , OLDEST_ON_LEFT = 1;

    function _manager (card, dom, exclude) {
      var collisionGroup = _findCollisions(dom);

      if (!!exclude) {
        collisionGroup.left.discard(dom);
        collisionGroup.split.discard(dom);
        _removeCollisionEffects(collisionGroup.all.items());
      }

      _resolveCollisions(dom, collisionGroup);
    }

    function _findCollisions (dom) {
      var stack = []
        , items = new Set()
        , split = new Set()
        , left = new Set()
        , currentNode
        , sibling
        , cardId;

      stack.push(dom);

      while(stack.length > 0) {
        currentNode = stack.shift();

        cardId = parseInt(currentNode.getAttribute('data-id'), 10);
        sibling = dom.parentElement.parentElement.querySelectorAll('.planner-card:not(.dragged):not([data-id="' + cardId + '"])');

        for (var i = 0; i < sibling.length; i++) {
          if (_collisionsDetector(currentNode, sibling[i])) {
            var rule = _collisionRule(currentNode, sibling[i]);

            if (rule === SPLITTING) {
              if (!split.in(sibling[i])) {
                split.update([currentNode, sibling[i]]);
                items.update([currentNode, sibling[i]]);
                stack.push(sibling[i]);
              }

            } else {
              if (!left.in(sibling[i])) {
                left.update([currentNode, sibling[i]]);
                items.update([currentNode, sibling[i]]);
                stack.push(sibling[i]);
              }
            }
          }
        }
      }

      // Put there all collision types
      return {
        all: items,
        split: split,
        left: left
      };
    }

    function _resolveCollisions (dom, collisionGroup) {
      var split = collisionGroup.split.items()
        , left = collisionGroup.left.items()
        , startingPosition = Utils.offset(dom.parentNode).left
        , columnWidth = dom.parentNode.offsetWidth
        , currentLeft
        , currentWidth
        , splittingOffset
        , i;

      // Put there all collision resolvers
      // ---------------------------------

      if (split.length > 0) {
        var splittingWidth = columnWidth / split.length;

        for (i = 0; i < split.length; i++) {
          split[i].style.width = splittingWidth + 'px';
          split[i].style.left = startingPosition + (splittingWidth * i) + 'px';
        }
      }

      if (left.length > 0) {
        left.sort(_orderOldestLeft);
        left.shift();

        for (i = 0; i < left.length; i++) {
          // Preserve current styles if set (ex: this card is in conflict with one card for SPLITTING
          // and with another one with OLDEST_ON_LEFT

          if (!!left[i].style.left) {
            // Removing 'px' suffix for left and width style
            var elementLeft = left[i].style.left
              , elementWidth = left[i].style.width;

            elementLeft = elementLeft.substring(0, elementLeft.length - 2);
            elementWidth = elementWidth.substring(0, elementWidth.length - 2);

            currentLeft = parseInt(elementLeft, 10);
            currentWidth = parseInt(elementWidth, 10);
          } else {
            currentLeft = startingPosition;
            currentWidth = left[i].offsetWidth;
          }

          // Add a splitting offset if this card is splitted
          splittingOffset = columnWidth / currentWidth * options.collisionOffset;

          // TODO: Bug here! splittingOffset is wrong
          left[i].style.left = currentLeft + options.collisionOffset + 'px';
          left[i].style.width = left[i].offsetWidth - splittingOffset + 'px';
        }
      }
    }

    // Collisions and rules
    // --------------------

    function _collisionsDetector (firstDom, secondDom) {
      var min = parseInt(firstDom.getAttribute('data-start'), 10)
        , max = parseInt(firstDom.getAttribute('data-end'), 10)
        , currentMin = parseInt(secondDom.getAttribute('data-start'), 10)
        , currentMax = parseInt(secondDom.getAttribute('data-end'), 10);

      if (min >= currentMin && min <= currentMax || max >= currentMin && max <= currentMax) {
        return true;
      } else {
        return currentMin >= min && currentMax <= max || currentMin >= min && currentMax <= max;
      }
    }

    function _collisionRule (firstDom, secondDom) {
      var firstMin = parseInt(firstDom.getAttribute('data-start'), 10)
        , secondMin = parseInt(secondDom.getAttribute('data-start'), 10);

      // Put there all collision rules
      // -----------------------------

      // Check if two elements have the same time (or time + 1)
      if (firstMin === secondMin || firstMin === secondMin + 1 || secondMin === firstMin + 1) {
        return SPLITTING;
      } else {
        return OLDEST_ON_LEFT;
      }
    }

    // Helpers
    // -------

    function _removeCollisionEffects (doms) {
      for (var i = 0; i < doms.length; i++) {
        doms[i].style.left = '';
        doms[i].style.width = '';
      }
    }

    function _orderOldestLeft (firstDom, secondDom) {
      var firstDomMin = parseInt(firstDom.getAttribute('data-start'), 10)
        , secondDomMin = parseInt(secondDom.getAttribute('data-start'), 10);

      return firstDomMin - secondDomMin;
    }

    // TODO: use this event AND a generic "drawingDone" otherwise there are too many (useless) conflict management
    planner.events.subscribe('cardDomDrawn', _manager);
    planner.events.subscribe('/card/actions/dragged', _manager);
  };

  Collision.DEFAULTS = {
    collisionOffset: 5
  };

  // Register this plugin to plugins list
  // ------------------------------------

  Plugins.register('collision', Collision);

})(Planner.Plugins, Planner.Utils, Ds.Set);
<commit_msg>fixed offsetLeft for mobile interaction<commit_after>(function (Plugins, Utils, Set, undefined) {
  'use strict';

  // Plugin constructor and defaults
  // -------------------------------

  var Collision = function (element, options, planner) {
    var SPLITTING = 0
      , OLDEST_ON_LEFT = 1;

    function _manager (card, dom, exclude) {
      var collisionGroup = _findCollisions(dom);

      if (!!exclude) {
        collisionGroup.left.discard(dom);
        collisionGroup.split.discard(dom);
        _removeCollisionEffects(collisionGroup.all.items());
      }

      _resolveCollisions(dom, collisionGroup);
    }

    function _findCollisions (dom) {
      var stack = []
        , items = new Set()
        , split = new Set()
        , left = new Set()
        , currentNode
        , sibling
        , cardId;

      stack.push(dom);

      while(stack.length > 0) {
        currentNode = stack.shift();

        cardId = parseInt(currentNode.getAttribute('data-id'), 10);
        sibling = dom.parentElement.parentElement.querySelectorAll('.planner-card:not(.dragged):not([data-id="' + cardId + '"])');

        for (var i = 0; i < sibling.length; i++) {
          if (_collisionsDetector(currentNode, sibling[i])) {
            var rule = _collisionRule(currentNode, sibling[i]);

            if (rule === SPLITTING) {
              if (!split.in(sibling[i])) {
                split.update([currentNode, sibling[i]]);
                items.update([currentNode, sibling[i]]);
                stack.push(sibling[i]);
              }

            } else {
              if (!left.in(sibling[i])) {
                left.update([currentNode, sibling[i]]);
                items.update([currentNode, sibling[i]]);
                stack.push(sibling[i]);
              }
            }
          }
        }
      }

      // Put there all collision types
      return {
        all: items,
        split: split,
        left: left
      };
    }

    function _resolveCollisions (dom, collisionGroup) {
      var split = collisionGroup.split.items()
        , left = collisionGroup.left.items()
        , startingPosition = dom.offsetLeft
        , columnWidth = dom.parentNode.offsetWidth
        , currentLeft
        , currentWidth
        , splittingOffset
        , i;

      // Put there all collision resolvers
      // ---------------------------------

      if (split.length > 0) {
        var splittingWidth = columnWidth / split.length;

        for (i = 0; i < split.length; i++) {
          split[i].style.width = splittingWidth + 'px';
          split[i].style.left = startingPosition + (splittingWidth * i) + 'px';
        }
      }

      if (left.length > 0) {
        left.sort(_orderOldestLeft);
        left.shift();

        for (i = 0; i < left.length; i++) {
          // Preserve current styles if set (ex: this card is in conflict with one card for SPLITTING
          // and with another one with OLDEST_ON_LEFT

          if (!!left[i].style.left) {
            // Removing 'px' suffix for left and width style
            var elementLeft = left[i].style.left
              , elementWidth = left[i].style.width;

            elementLeft = elementLeft.substring(0, elementLeft.length - 2);
            elementWidth = elementWidth.substring(0, elementWidth.length - 2);

            currentLeft = parseInt(elementLeft, 10);
            currentWidth = parseInt(elementWidth, 10);
          } else {
            currentLeft = startingPosition - options.marginAdjustment;
            currentWidth = left[i].offsetWidth;
          }

          // Add a splitting offset if this card is splitted
          splittingOffset = columnWidth / currentWidth * options.collisionOffset;

          // TODO: Bug here! splittingOffset is wrong
          left[i].style.left = currentLeft + options.collisionOffset + 'px';
          left[i].style.width = left[i].offsetWidth - splittingOffset + 'px';
        }
      }
    }

    // Collisions and rules
    // --------------------

    function _collisionsDetector (firstDom, secondDom) {
      var min = parseInt(firstDom.getAttribute('data-start'), 10)
        , max = parseInt(firstDom.getAttribute('data-end'), 10)
        , currentMin = parseInt(secondDom.getAttribute('data-start'), 10)
        , currentMax = parseInt(secondDom.getAttribute('data-end'), 10);

      if (min >= currentMin && min <= currentMax || max >= currentMin && max <= currentMax) {
        return true;
      } else {
        return currentMin >= min && currentMax <= max || currentMin >= min && currentMax <= max;
      }
    }

    function _collisionRule (firstDom, secondDom) {
      var firstMin = parseInt(firstDom.getAttribute('data-start'), 10)
        , secondMin = parseInt(secondDom.getAttribute('data-start'), 10);

      // Put there all collision rules
      // -----------------------------

      // Check if two elements have the same time (or time + 1)
      if (firstMin === secondMin || firstMin === secondMin + 1 || secondMin === firstMin + 1) {
        return SPLITTING;
      } else {
        return OLDEST_ON_LEFT;
      }
    }

    // Helpers
    // -------

    function _removeCollisionEffects (doms) {
      for (var i = 0; i < doms.length; i++) {
        doms[i].style.left = '';
        doms[i].style.width = '';
      }
    }

    function _orderOldestLeft (firstDom, secondDom) {
      var firstDomMin = parseInt(firstDom.getAttribute('data-start'), 10)
        , secondDomMin = parseInt(secondDom.getAttribute('data-start'), 10);

      return firstDomMin - secondDomMin;
    }

    // TODO: use this event AND a generic "drawingDone" otherwise there are too many (useless) conflict management
    planner.events.subscribe('cardDomDrawn', _manager);
    planner.events.subscribe('/card/actions/dragged', _manager);
  };

  Collision.DEFAULTS = {
    marginAdjustment: 3,
    collisionOffset: 5
  };

  // Register this plugin to plugins list
  // ------------------------------------

  Plugins.register('collision', Collision);

})(Planner.Plugins, Planner.Utils, Ds.Set);
<|endoftext|>


<commit_before>module.exports = {
    logo: 'src/assets/protondrive.svg',
    favicons: {
        appName: 'Proton Drive',
        appDescription:
            'Proton Drive allows you to securely store and share your sensitive documents and access them anywhere.',
        developerName: 'Proton Technologies AG',
        developerURL: 'https://github.com/ProtonMail/proton-drive',
        background: '#262a33',
        theme_color: '#262a33',
    },
};
<commit_msg>ProtonDrive renaming reverted.<commit_after>module.exports = {
    logo: 'src/assets/protondrive.svg',
    favicons: {
        appName: 'ProtonDrive',
        appDescription:
            'ProtonDrive allows you to securely store and share your sensitive documents and access them anywhere.',
        developerName: 'Proton Technologies AG',
        developerURL: 'https://github.com/ProtonMail/proton-drive',
        background: '#262a33',
        theme_color: '#262a33',
    },
};
<|endoftext|>


<commit_before>const chalk = require('chalk')
const path = require('path')
const { URL } = require('url')

const port = process.env.PORT || process.env.npm_package_config_nuxt_port || 3000
const host = process.env.HOST || process.env.npm_package_config_nuxt_host || 'localhost'

module.exports = function nuxtAxios (moduleOptions) {
  // Apply defaults
  const options = Object.assign({
    baseURL: process.env.API_URL || `http://${host}:${port}/api`,
    browserBaseURL: null,
    credentials: true,
    proxyHeaders: true
  }, this.options.axios, moduleOptions)

  if (process.env.API_URL) {
    options.baseURL = process.env.API_URL
  }

  if (process.env.API_URL_BROWSER) {
    options.browserBaseURL = process.env.API_URL_BROWSER
  }

  if (!options.browserBaseURL) {
    const url = new URL(options.baseURL)
    const sameHost = url.host === `${host}:${port}`
    options.browserBaseURL = sameHost ? url.pathname : options.url
  }

  // Register plugin
  this.addPlugin({
    src: path.resolve(__dirname, 'plugin.js'),
    options
  })

  /* eslint-disable no-console */
  console.log(`[AXIOS] Base URL: ${chalk.green(options.baseURL)} , Browser: ${chalk.green(options.browserBaseURL)}`)
}

module.exports.meta = require('./package.json')
<commit_msg>chore(axios): Extra assignment<commit_after>const chalk = require('chalk')
const path = require('path')
const { URL } = require('url')

const port = process.env.PORT || process.env.npm_package_config_nuxt_port || 3000
const host = process.env.HOST || process.env.npm_package_config_nuxt_host || 'localhost'

module.exports = function nuxtAxios (moduleOptions) {
  // Apply defaults
  const options = Object.assign({
    baseURL: `http://${host}:${port}/api`,
    browserBaseURL: null,
    credentials: true,
    proxyHeaders: true
  }, this.options.axios, moduleOptions)

  if (process.env.API_URL) {
    options.baseURL = process.env.API_URL
  }

  if (process.env.API_URL_BROWSER) {
    options.browserBaseURL = process.env.API_URL_BROWSER
  }

  if (!options.browserBaseURL) {
    const url = new URL(options.baseURL)
    const sameHost = url.host === `${host}:${port}`
    options.browserBaseURL = sameHost ? url.pathname : options.url
  }

  // Register plugin
  this.addPlugin({
    src: path.resolve(__dirname, 'plugin.js'),
    options
  })

  /* eslint-disable no-console */
  console.log(`[AXIOS] Base URL: ${chalk.green(options.baseURL)} , Browser: ${chalk.green(options.browserBaseURL)}`)
}

module.exports.meta = require('./package.json')
<|endoftext|>


<commit_before>import React from 'react';
import {Table, Column, Cell, ColumnGroup} from 'fixed-data-table';
import Immutable from 'immutable';
import _ from 'underscore';
import messages from "../lang/messages";
import Selector from './selector';
import CellRenderer from './cellRenderer';

function defaultProps() {
	return {
		className: '',
		cols: [],
		data: [],
		uniqueId: _.uniqueId('propertable-'),
		afterSort: null,
		afterSelect: null,
		selectable: true,
		selected: null,
		rowHeight: 50,
		idField: null,
		msgs: messages
	};
}

function hasNested(cols) {
	let result = false;

	if (cols.size) {
		cols.forEach((c) => {
			if (c.get('children') && c.get('children').size) {
				result = true;
				return false;
			}
		});
	}

	return result;
}

class ProperTable extends React.Component {
	static get defaultProps() {
		return defaultProps();
	}

	constructor(props) {
		super(props);

		let initialData = this.prepareData();

		this.hasFixedColumns = false;

		this.state = {
			cols: Immutable.fromJS(this.props.cols),
			data: initialData.data,
			indexed: initialData.indexed,
			rawdata: initialData.rawdata,
			sort: null,
			allSelected: false,
			selection: []
		};
	}

	prepareData() {
		let data = Immutable.fromJS(this.props.data), index = 0;
		let indexed = [], parsed = [];

		parsed = data.map(row => {
			if (!row.get('_properId',false)) {
				row = row.set('_properId', _.uniqueId());
			}
			if (!row.get('_selected',false)) {
				row = row.set('_selected', false);
			}

			row = row.set('_rowIndex', index++);

			return row;
		});

		indexed = _.indexBy(parsed.toJSON(), '_properId');

		return {
			rawdata: data,
			data: parsed,
			index: indexed
		};
	}

	initData() {
		let newdata = this.prepareData();

		this.setState(newData);
	}

	parseColumn(colData, isChildren = false, hasNested = false) {
		let col = null, colname = null, extraProps = {
			width: 100,
			fixed: false
		};

		colname = colData.name || _.uniqueId('col-');

		if (typeof colData.children == 'undefined' || !colData.children.length) {

			if (colData.width) {
				extraProps.width = colData.width;
			}

			if (!colData.width && !colData.maxWidth) {
				extraProps.flexGrow = colData.flex || 1;
			}

			if (typeof colData.fixed !== 'undefined') {
				extraProps.fixed = colData.fixed;
			}

			col = <Column
				columnKey={_.uniqueId(colname)}
				key={_.uniqueId(colname)}
				header={<Cell className="propertable-hcell">{colData.label}</Cell>}
				cell={<CellRenderer data={this.state.data} colData={colData} col={colData.field} />}
				allowCellsRecycling
				align='center'
				{...extraProps}
			/>;

			if (!isChildren && hasNested) {
				col = <ColumnGroup key={_.uniqueId(colname+'-group')} fixed={extraProps.fixed}>{col}</ColumnGroup>
			}
		} else {
			let inner = colData.children.map((c) => this.parseColumn(c, true));

			if (typeof colData.fixed !== 'undefined') {
				extraProps.fixed = colData.fixed;
			}

			col = <ColumnGroup
				columnKey={_.uniqueId(colname)}
				key={_.uniqueId(colname)}
				header={<Cell>{colData.label}</Cell>}
				{...extraProps}
			>
				{inner}
			</ColumnGroup>;
		}

		return col;
	}

	buildTable() {
		let columns = [], isNested = hasNested(this.state.cols), selColumn = null;

		if (this.props.selectable == 'multiple') {
			let somethingSelected = this.state.selection.length > 0;

			selColumn = <Column
				columnKey={_.uniqueId('selector-')}
				key={_.uniqueId('selector-')}
				header={<Selector
					onClick={this.handleSelectAll.bind(this)}
					somethingSelected={somethingSelected}
					allSelected={this.state.allSelected}
				/>}
				cell={<Selector
					data={this.state.data}
				/>}
				allowCellsRecycling
				width={50}
				fixed
			/>

			if (isNested) {
				selColumn = <ColumnGroup fixed key={_.uniqueId('selector-group-')}>{selColumn}</ColumnGroup>;
			}

			columns.push(selColumn);
		}

		this.state.cols.forEach((col) => {
			columns.push(this.parseColumn(col.toJSON(), false, isNested));
		});

		return columns;
	}

	handleSelectAll(e) {
		let somethingSelected = this.state.selection.length > 0;
		let allSelected = this.state.allSelected;
		let newSelection = [];

		if (!allSelected) {
			newSelection = _.keys(this.state.indexed);
		}

		this.triggerSelection(newSelection.sort());
	}

	handleRowClick(e, rowIndex) {
		let clickedId = this.state.data.get(rowIndex).get('_properId');

		this.toggleSelected(clickedId);
	}

	toggleSelected(properId) {
		let selection = _.clone(this.state.selection);

		if (_.indexOf(selection, properId.toString()) != -1) {
			selection = _.without(selection, properId);
		} else {
			if (this.props.selectable == 'multiple') {
				selection.push(properId);
			} else {
				selection = [properId];
			}
		}

		this.triggerSelection(selection.sort());
	}

	componentWillUpdate(nextProps, nextState) {
		if (!_.isEqual(nextState.selection, this.state.selection)) {
			this.updateSelectionData(nextState.selection);
		}
	}

	updateSelectionData(newSelection) {
		let newData = this.state.data.map((row) => {
			let rdata = row.toJSON();

			rdata._selected = _.indexOf(newSelection, rdata._properId) >= 0;

			return Immutable.fromJS(rdata);
		});

		let newIndexed = _.indexBy(newData.toJSON(), '_properId');

		this.setState({
			data: newData,
			indexed: newIndexed
		});
	}

	triggerSelection(newSelection = []) {
		if (!_.isEqual(newSelection, this.state.selection)) {
			this.setState({
				selection: newSelection,
				allSelected: newSelection.length == this.state.data.size
			}, this.sendSelection);
		}
	}

	sendSelection() {
		if (typeof this.props.afterSelect == 'function') {
			let {selection, indexed, rawdata} = this.state;
			let output = [];

			output = _.map(selection, (pId) => {
				let rowIndex = indexed[pId]._rowIndex;

				return rawdata.get(rowIndex).toJSON();
			});

			if (this.props.selectable === true) {
				output = output[0];
			}

			this.props.afterSelect(output);
		}
	}

	getRowClassName(index) {
		let addClass = 'propertable-row';
		let selected = this.state.data.get(index).get('_selected');

		if (selected) {
			addClass += ' selected';
		}

		return addClass;
	}

	render() {
		let content =
{this.props.msgs.empty}

		let tableContent = null;

		if (this.state.data === null) {
			content =
{this.props.msgs.loading}

		}

		if (this.state.data && this.state.data.size) {
			tableContent = this.buildTable();

			content =

				{tableContent}

;
		}

		return
{content}
;
	}
}

export default ProperTable;
<commit_msg>adding column resizing feature<commit_after>import React from 'react';
import {Table, Column, Cell, ColumnGroup} from 'fixed-data-table';
import Immutable from 'immutable';
import _ from 'underscore';
import messages from "../lang/messages";
import Selector from './selector';
import CellRenderer from './cellRenderer';

function defaultProps() {
	return {
		className: '',
		cols: [],
		data: [],
		uniqueId: _.uniqueId('propertable-'),
		afterSort: null,
		afterSelect: null,
		selectable: true,
		selected: null,
		rowHeight: 50,
		idField: null,
		msgs: messages
	};
}

function hasNested(cols) {
	let result = false;

	if (cols.size) {
		cols.forEach((c) => {
			if (c.get('children') && c.get('children').size) {
				result = true;
				return false;
			}
		});
	}

	return result;
}

class ProperTable extends React.Component {
	static get defaultProps() {
		return defaultProps();
	}

	constructor(props) {
		super(props);

		let initialData = this.prepareData();

		this.hasFixedColumns = false;

		this.state = {
			cols: Immutable.fromJS(this.props.cols),
			data: initialData.data,
			indexed: initialData.indexed,
			rawdata: initialData.rawdata,
			sort: null,
			sizes: Immutable.fromJS({}),
			allSelected: false,
			selection: []
		};
	}

	prepareData() {
		let data = Immutable.fromJS(this.props.data), index = 0;
		let indexed = [], parsed = [];

		parsed = data.map(row => {
			if (!row.get('_properId',false)) {
				row = row.set('_properId', _.uniqueId());
			}
			if (!row.get('_selected',false)) {
				row = row.set('_selected', false);
			}

			row = row.set('_rowIndex', index++);

			return row;
		});

		indexed = _.indexBy(parsed.toJSON(), '_properId');

		return {
			rawdata: data,
			data: parsed,
			index: indexed
		};
	}

	initData() {
		let newdata = this.prepareData();

		this.setState(newData);
	}

	parseColumn(colData, isChildren = false, hasNested = false) {
		let col = null, colname = null, extraProps = {
			width: 100,
			fixed: false,
			isResizable: true
		};

		colname = colData.name || _.uniqueId('col-');

		if (this.state.sizes.get(colname)) {
			colData.width = this.state.sizes.get(colname);
			colData.flex = 0;
		}

		if (colData.width) {
			extraProps.width = colData.width;
		}

		if (!colData.width && !colData.maxWidth) {
			extraProps.flexGrow = 1;

			if (typeof colData.flex != 'undefined') {
				extraProps.flexGrow = colData.flex;
			}
		}

		if (typeof colData.fixed !== 'undefined') {
			extraProps.fixed = colData.fixed;
		}

		if (typeof colData.isResizable !== 'undefined') {
			extraProps.isResizable = colData.isResizable;
		}

		if (typeof colData.children == 'undefined' || !colData.children.length) {
			col = <Column
				columnKey={colname}
				key={_.uniqueId(colname)}
				header={<Cell className="propertable-hcell">{colData.label}</Cell>}
				cell={<CellRenderer data={this.state.data} colData={colData} col={colData.field} />}
				allowCellsRecycling
				align='center'
				{...extraProps}
			/>;

			if (!isChildren && hasNested) {
				col = <ColumnGroup key={_.uniqueId(colname+'-group')} fixed={extraProps.fixed}>{col}</ColumnGroup>
			}
		} else {
			let inner = colData.children.map((c) => this.parseColumn(c, true));

			col = <ColumnGroup
				columnKey={colname}
				key={_.uniqueId(colname)}
				header={<Cell>{colData.label}</Cell>}
				{...extraProps}
			>
				{inner}
			</ColumnGroup>;
		}

		return col;
	}

	buildTable() {
		let columns = [], isNested = hasNested(this.state.cols), selColumn = null;

		if (this.props.selectable == 'multiple') {
			let somethingSelected = this.state.selection.length > 0;

			selColumn = <Column
				columnKey={_.uniqueId('selector-')}
				key={_.uniqueId('selector-')}
				header={<Selector
					onClick={this.handleSelectAll.bind(this)}
					somethingSelected={somethingSelected}
					allSelected={this.state.allSelected}
				/>}
				cell={<Selector
					data={this.state.data}
				/>}
				allowCellsRecycling
				width={50}
				fixed
			/>

			if (isNested) {
				selColumn = <ColumnGroup fixed key={_.uniqueId('selector-group-')}>{selColumn}</ColumnGroup>;
			}

			columns.push(selColumn);
		}

		this.state.cols.forEach((col) => {
			columns.push(this.parseColumn(col.toJSON(), false, isNested));
		});

		return columns;
	}

	handleSelectAll(e) {
		let somethingSelected = this.state.selection.length > 0;
		let allSelected = this.state.allSelected;
		let newSelection = [];

		if (!allSelected) {
			newSelection = _.keys(this.state.indexed);
		}

		this.triggerSelection(newSelection.sort());
	}

	handleRowClick(e, rowIndex) {
		let clickedId = this.state.data.get(rowIndex).get('_properId');

		this.toggleSelected(clickedId);
	}

	toggleSelected(properId) {
		let selection = _.clone(this.state.selection);

		if (_.indexOf(selection, properId.toString()) != -1) {
			selection = _.without(selection, properId);
		} else {
			if (this.props.selectable == 'multiple') {
				selection.push(properId);
			} else {
				selection = [properId];
			}
		}

		this.triggerSelection(selection.sort());
	}

	componentWillUpdate(nextProps, nextState) {
		if (!_.isEqual(nextState.selection, this.state.selection)) {
			this.updateSelectionData(nextState.selection);
		}
	}

	updateSelectionData(newSelection) {
		let newData = this.state.data.map((row) => {
			let rdata = row.toJSON();

			rdata._selected = _.indexOf(newSelection, rdata._properId) >= 0;

			return Immutable.fromJS(rdata);
		});

		let newIndexed = _.indexBy(newData.toJSON(), '_properId');

		this.setState({
			data: newData,
			indexed: newIndexed
		});
	}

	triggerSelection(newSelection = []) {
		if (!_.isEqual(newSelection, this.state.selection)) {
			this.setState({
				selection: newSelection,
				allSelected: newSelection.length == this.state.data.size
			}, this.sendSelection);
		}
	}

	sendSelection() {
		if (typeof this.props.afterSelect == 'function') {
			let {selection, indexed, rawdata} = this.state;
			let output = [];

			output = _.map(selection, (pId) => {
				let rowIndex = indexed[pId]._rowIndex;

				return rawdata.get(rowIndex).toJSON();
			});

			if (this.props.selectable === true) {
				output = output[0];
			}

			this.props.afterSelect(output);
		}
	}

	getRowClassName(index) {
		let addClass = 'propertable-row';
		let selected = this.state.data.get(index).get('_selected');

		if (selected) {
			addClass += ' selected';
		}

		return addClass;
	}

	onResize(width, column) {
		let sizes = this.state.sizes;
		let newsizes = sizes.set(column, width);

		this.setState({sizes: newsizes});
	}

	render() {
		let content =
{this.props.msgs.empty}

		let tableContent = null;

		if (this.state.data === null) {
			content =
{this.props.msgs.loading}

		}

		if (this.state.data && this.state.data.size) {
			tableContent = this.buildTable();

			content =

				{tableContent}

;
		}

		return
{content}
;
	}
}

export default ProperTable;
<|endoftext|>


<commit_before>"use strict";

var dagreD3 = require('dagre-d3');
var d3 = require('d3');

/*

Given a JSON object with the knowledge data, create a graph object which
will be rendered by dagre-d3.

json: TODO describe what the json should look like

*/
var createGraph = function(json) {
  var graph = new dagreD3.Digraph();
  // Add all the concepts as nodes
  json.concepts.forEach(function(concept) {
    graph.addNode(concept.id, {
     label: concept.name,
     concept: concept,
    });
  });
  // Check each concept for dependencies and add them as edges
  json.concepts.forEach(function(concept) {
    if (Array.isArray(concept.dependencies)) {
      concept.dependencies.forEach(function(dep) {
        // Add an edge from the dependency to the concept with a null edge ID
        graph.addEdge(null, dep, concept.id);
      });
    } else {
      // Dependencies is undefine/not an array and we'll figure out what to do with it later
    }
  });
  return graph;
};

/*

Creates the points for the paths that make up the edges
Offsets the in/out edges to above/below given nodes

Replaces the default dagre-d3 PositionEdgePaths function
*/
function positionEdgePaths(g, svgEdgePaths) {
  var interpolate = this._edgeInterpolate,
      tension = this._edgeTension;

  function calcPoints(e) {
    var value = g.edge(e);
    var source = g.node(g.incidentNodes(e)[0]);
    var target = g.node(g.incidentNodes(e)[1]);
    var points = value.points.slice();

    var p0 = points.length === 0 ? target : points[0];
    var p1 = points.length === 0 ? source : points[points.length - 1];

    points.unshift(nodePosition(source, p0));
    points.push(nodePosition(target, p1));

    return d3.svg.line()
      .x(function(d) { return d.x; })
      .y(function(d) { return d.y; })
      .interpolate(interpolate)
      .tension(tension)
      (points);
  }

  svgEdgePaths.filter('.enter').selectAll('path')
      .attr('d', calcPoints);

  this._transition(svgEdgePaths.selectAll('path'))
      .attr('d', calcPoints)
      .style('opacity', 1);
}

function nodePosition(node, point) {
  var x = node.x;
  var y = node.y;
  var r = 25;

  var dx = point.x - x;
  var dy = point.y - y;

  // Length of the line from the circle to the point
  var l = Math.sqrt(dx*dx + dy*dy);
  // Unit values
  var dxu = dx/l;
  var dyu = dy/l;

  // Offset above/below depending whether the line is up or down
  var offset = ((dy > 0) ? 1 : -1) * node.height/4;

  return {x: x + dxu*r, y: y + offset + dyu*r};
}

/*

Adds entry and exit points for edges into concept elements

Used in addition to the default node rendering function

*/
function drawEntryExit(graph, nodes) {
  var kg = this;

  // Add enter/above
  var enter = nodes.insert('circle', 'rect')
    .attr('r', 25)
    .attr('cy', function() {
      return -nodes.selectAll('rect').attr('height')/2;
    });

  // Add dependency to this concept if entry point is clicked
  enter.on('click', function(conceptId) {
    // Get concept clicked on
    var concept = graph.node(conceptId).concept;

    // Create a new concept
    var newConcept = {
      id: "node-"+graph.nodes().length,
      name: '',
      dependencies: [],
    };

    // Add it to the graph
    kg.addConcept({
      concept: newConcept,
      dependents: [concept.id],
    });
  });

  // Add exit/below
  var exit = nodes.insert('circle', 'rect')
    .attr('r', 25)
    .attr('cy', function() {
      return nodes.selectAll('rect').attr('height')/2;
    });

  return nodes;
}

/*

The knowledgeGraph object is the public API for the knowledge-graph library

*/
var knowledgeGraph = new function() {
/*

Create a knowledge graph display that layouts out the entire graph.

config: an object that contains the data about the graph and various other
options
The available options are:
  graph: a JSON object that contains the graph data

*/
this.create = function(config) {
  // Create the directed graph
  var graph = this.graph = createGraph(config.graph);

  // Create an element on the page for us to render our graph in
  var element = this.element = d3.select('body').append('svg');

  // Use dagre-d3 to render the graph
  var renderer = this.renderer = new dagreD3.Renderer();

  // Update the way edges are positioned
  renderer.layout().rankSep(100);
  renderer.positionEdgePaths(positionEdgePaths);

  // Add enter/exit circles
  var kg = this;
  var drawNodes = renderer.drawNodes();
  renderer.drawNodes(function(graph, element) {
    var nodes = drawNodes(graph, element);
    drawEntryExit.call(kg, graph, nodes);

    return nodes;
  });

  // Display the graph
  this.render();
};

/*
Adds a concept to the graph and then updates the graph rendering

config:
  concept: The concept object to add
  dependents: A list of concepts dependent on this one
*/
this.addConcept = function(config) {
  var kg = this;

  // Add node to the graph
  this.graph.addNode(config.concept.id, {
    label: config.concept.name,
    concept: config.concept,
  });

  // Add dependent edges to the graph
  config.dependents.forEach(function(dep) {
    if (dep.dependencies) {
      dep.dependencies.push(config.concept.id);
    } else {
      dep.dependencies = [config.concept.id];
    }

    kg.graph.addEdge(null, config.concept.id, dep);
  });

  // Add dependency edges to the graph
  config.concept.dependencies.forEach(function(dep) {
    kg.graph.addEdge(null, dep, config.concept.id);
  });

  // Update the graph display
  this.render();
};

/*

Renders/rerenders the graph elements

*/
this.render = function() {
  // Run the renderer
  this.renderer.run(this.graph, this.element);

  // Don't add another element for the zoom
  this.renderer.zoomSetup(function(graph, element) {
    this.element = element;
    return element;
  });
};

  return this;
}();

global.knowledgeGraph = knowledgeGraph;
module.exports = knowledgeGraph;
<commit_msg>Added transistions for changes in the graph<commit_after>"use strict";

var dagreD3 = require('dagre-d3');
var d3 = require('d3');

/*

Given a JSON object with the knowledge data, create a graph object which
will be rendered by dagre-d3.

json: TODO describe what the json should look like

*/
var createGraph = function(json) {
  var graph = new dagreD3.Digraph();
  // Add all the concepts as nodes
  json.concepts.forEach(function(concept) {
    graph.addNode(concept.id, {
     label: concept.name,
     concept: concept,
    });
  });
  // Check each concept for dependencies and add them as edges
  json.concepts.forEach(function(concept) {
    if (Array.isArray(concept.dependencies)) {
      concept.dependencies.forEach(function(dep) {
        // Add an edge from the dependency to the concept with a null edge ID
        graph.addEdge(null, dep, concept.id);
      });
    } else {
      // Dependencies is undefine/not an array and we'll figure out what to do with it later
    }
  });
  return graph;
};

/*

Creates the points for the paths that make up the edges
Offsets the in/out edges to above/below given nodes

Replaces the default dagre-d3 PositionEdgePaths function
*/
function positionEdgePaths(g, svgEdgePaths) {
  var interpolate = this._edgeInterpolate,
      tension = this._edgeTension;

  function calcPoints(e) {
    var value = g.edge(e);
    var source = g.node(g.incidentNodes(e)[0]);
    var target = g.node(g.incidentNodes(e)[1]);
    var points = value.points.slice();

    var p0 = points.length === 0 ? target : points[0];
    var p1 = points.length === 0 ? source : points[points.length - 1];

    points.unshift(nodePosition(source, p0));
    points.push(nodePosition(target, p1));

    return d3.svg.line()
      .x(function(d) { return d.x; })
      .y(function(d) { return d.y; })
      .interpolate(interpolate)
      .tension(tension)
      (points);
  }

  svgEdgePaths.filter('.enter').selectAll('path')
      .attr('d', calcPoints);

  this._transition(svgEdgePaths.selectAll('path'))
      .attr('d', calcPoints)
      .style('opacity', 1);
}

function nodePosition(node, point) {
  var x = node.x;
  var y = node.y;
  var r = 25;

  var dx = point.x - x;
  var dy = point.y - y;

  // Length of the line from the circle to the point
  var l = Math.sqrt(dx*dx + dy*dy);
  // Unit values
  var dxu = dx/l;
  var dyu = dy/l;

  // Offset above/below depending whether the line is up or down
  var offset = ((dy > 0) ? 1 : -1) * node.height/4;

  return {x: x + dxu*r, y: y + offset + dyu*r};
}

/*

Adds entry and exit points for edges into concept elements

Used in addition to the default node rendering function

*/
function drawEntryExit(graph, nodes) {
  var kg = this;

  // Add enter/above
  var enter = nodes.insert('circle', 'rect')
    .attr('r', 25)
    .attr('cy', function() {
      return -nodes.selectAll('rect').attr('height')/2;
    });

  // Add dependency to this concept if entry point is clicked
  enter.on('click', function(conceptId) {
    // Get concept clicked on
    var concept = graph.node(conceptId).concept;

    // Create a new concept
    var newConcept = {
      id: "node-"+graph.nodes().length,
      name: '',
      dependencies: [],
    };

    // Add it to the graph
    kg.addConcept({
      concept: newConcept,
      dependents: [concept.id],
    });
  });

  // Add exit/below
  var exit = nodes.insert('circle', 'rect')
    .attr('r', 25)
    .attr('cy', function() {
      return nodes.selectAll('rect').attr('height')/2;
    });

  return nodes;
}

/*

The knowledgeGraph object is the public API for the knowledge-graph library

*/
var knowledgeGraph = new function() {
/*

Create a knowledge graph display that layouts out the entire graph.

config: an object that contains the data about the graph and various other
options
The available options are:
  graph: a JSON object that contains the graph data

*/
this.create = function(config) {
  // Create the directed graph
  var graph = this.graph = createGraph(config.graph);

  // Create an element on the page for us to render our graph in
  var element = this.element = d3.select('body').append('svg');

  // Use dagre-d3 to render the graph
  var renderer = this.renderer = new dagreD3.Renderer();

  // Update the way edges are positioned
  renderer.layout().rankSep(100);
  renderer.positionEdgePaths(positionEdgePaths);

  // Add transitions for graph updates
  renderer.transition(function(selection) {
    return selection
      .transition()
        .duration(500);
  });

  // Add enter/exit circles
  var kg = this;
  var drawNodes = renderer.drawNodes();
  renderer.drawNodes(function(graph, element) {
    var nodes = drawNodes(graph, element);
    drawEntryExit.call(kg, graph, nodes);

    return nodes;
  });

  // Display the graph
  this.render();
};

/*
Adds a concept to the graph and then updates the graph rendering

config:
  concept: The concept object to add
  dependents: A list of concepts dependent on this one
*/
this.addConcept = function(config) {
  var kg = this;

  // Add node to the graph
  this.graph.addNode(config.concept.id, {
    label: config.concept.name,
    concept: config.concept,
  });

  // Add dependent edges to the graph
  config.dependents.forEach(function(dep) {
    if (dep.dependencies) {
      dep.dependencies.push(config.concept.id);
    } else {
      dep.dependencies = [config.concept.id];
    }

    kg.graph.addEdge(null, config.concept.id, dep);
  });

  // Add dependency edges to the graph
  config.concept.dependencies.forEach(function(dep) {
    kg.graph.addEdge(null, dep, config.concept.id);
  });

  // Update the graph display
  this.render();
};

/*

Renders/rerenders the graph elements

*/
this.render = function() {
  // Run the renderer
  this.renderer.run(this.graph, this.element);

  // Don't add another element for the zoom
  this.renderer.zoomSetup(function(graph, element) {
    this.element = element;
    return element;
  });
};

  return this;
}();

global.knowledgeGraph = knowledgeGraph;
module.exports = knowledgeGraph;
<|endoftext|>


<commit_before>#ifndef __lang_Enumerable__
#define __lang_Enumerable__

#comment Use macros to produce different version of the code bellow,
#comment depending on wether SET_ITERATOR is set or not.
#ifdef SET_ITERATOR
#comment The field 'name' on the 'bind' object is set to the iterator before
#comment iteration. We can call it directly instead using #call.
#comment This leads to better performance (2x on Firefox), and even more  on
#comment legacy browsers where we can avoid the emulated Function.call.
#define ITERATOR(ITER, BIND, VALUE, KEY, SELF, NAME) BIND.NAME(VALUE, KEY, SELF)
#define ITERATE(ITER, NAME) Base.iterate(ITER, NAME)
#else // !SET_ITERATOR
#comment Call the iterator funciton on the bind object through Function.call.
#comment This is cleanear but slower than the SET_ITERATOR hack.
#define ITERATOR(ITER, BIND, VALUE, KEY, SELF, NAME) ITER.call(BIND, VALUE, KEY, SELF)
#define ITERATE(ITER, NAME) Base.iterate(ITER)
#endif // !SET_ITERATOR

////////////////////////////////////////////////////////////////////////////////
// Enumerable

/**
 * A special constant, to be thrown by closures passed to each()
 * Inspired by Prototype.js
 *
 * $continue is not implemented, as the same functionality can achieved
 * by using return in the closure. In prototype, the implementation of $continue
 * also leads to a huge speed decrease, as the closure is wrapped in another
 * closure that does nothing else than handling $continue.
 */
$break = {};

/**
 * The Enumerable interface. To add enumerable functionality to any prototype,
 * just use Constructor.inject(Enumerable);
 * This adds the function .each() that can handle both arrays (detected through
 * .length) and dictionaries (if it's not an array, enumerating with for-in).
 */
Enumerable = new function() {
	/**
	 * Converts the passed function to an iterate-function.
	 * This is part of an optimization that is based on the observation that
	 * calling the iterator through bind.__iterate is faster than using iter.apply()
	 * each time.
	 * So iterate wraps the passed function in a closure that sets the __iterate
	 * function (defined by name) on the bind object and then calls the original
	 * function, restoring the original state after it returns.
	 * This is used in many places in Enumerable, each place defining its own
	 * name for the iterate function, so there are no clashes if calls are nested.
	 */
#ifdef SET_ITERATOR
	Base.iterate = function(fn, name) {
#else
	Base.iterate = function(fn) {
#endif
#if defined(SET_ITERATOR) && defined(DONT_ENUM)
		// dontEnum all set iterators once and for all on browsers:
		Base.prototype.dontEnum(true, name);
#endif // APPLY_ITERATOR && DONT_ENUM
		return function(iter, bind) {
			// Convert the argument to an iterator function. If none is specified,
			// the identity function is returned.
			// This supports regular expressions, normal functions, which are
			// returned unmodified, and values to compare to.
			// Wherever this private function is used in the Enumerable functions
			// bellow, a RegExp object, a Function or null may be passed.
			if (!iter) iter = function(val) { return val };
			else if (typeof iter != 'function') iter = function(val) { return val == iter };
			/* FOR RegExp support, used this:
			else switch ($typeof(iter)) {
				case 'function': break;
				case 'regexp': iter = function(val) { return iter.test(val) }; break;
				default: iter = function(val) { return val == iter };
			}
			*/
			if (!bind) bind = this;
#ifdef SET_ITERATOR
			// Backup previous value of the field, and set iterator.
			var prev = bind[name];
			bind[name] = iter;
#ifdef HELMA
			// On Helma, we can only dontEnum once the property is defined.
			bind.dontEnum(name);
#endif // HELMA
#endif// !SET_ITERATOR
			// Interesting benchmark observation: The loops seem execute
			// faster when called on the object (this), so outsource to
			// the above functions each_Array / each_Object here.
			// pass this twice, so it can be recieved as 'that' in the iterating
			// functions, to be passed to the iterator (and being able to use
			// 'this' in .each differently)
#ifdef SET_ITERATOR
			// Allways restore previous value in the end.
			try { return fn.call(this, iter, bind, this); }
			finally { bind[name] = prev; }
#else // !SET_ITERATOR
			return fn.call(this, iter, bind, this);
#endif// !SET_ITERATOR
		};
	};

	var each_Array = Array.prototype.forEach || function(iter, bind) {
		for (var i = 0, j = this.length; i < j; ++i)
			ITERATOR(iter, bind, this[i], i, this, __each);
	};

	var each_Object = function(iter, bind) {
#ifdef DONT_ENUM
		// We use for-in here, but need to filter out what should not be iterated.
		// Object#dontEnum defines a method to flag such a fields, and Object#has
		// a way to find out for any given key if it is enumerable or not.
		// The loop here uses an inline version of Object#has (See Core).
		var entries = this._dontEnum || {};
		for (var i in this) {
			var val = this[i], entry = entries[i];
			// Skip dontEnum fields.
			// This line here is similar to Base.prototype.has
			if (!entry || entry.allow && entry.object[i] !== this[i])
				ITERATOR(iter, bind, val, i, this, __each);
		}
#elif !defined(HELMA)
		// We use for-in here, but need to filter out what should not be iterated.
		// The loop here uses an inline version of Object#has (See Core).
		for (var i in this) {
			var val = this[i];
			if (val !== this.__proto__[i]AND_NAME_IS_VISIBLE(i))
				ITERATOR(iter, bind, val, i, this, __each);
		}
#else // HELMA
		// No need to check when not extending Object and when on Helma as
		// dontEnum is always used to hide fields there.
		for (var i in this)
			ITERATOR(iter, bind, this[i], i, this, __each);
#endif
	};

	return {
		HIDE
		_generics: true,

		/**
		 * The core of all Enumerable functions. TODO: document
		 */
		each: ITERATE(function(iter, bind) {
			try { (this.length != null ? each_Array : each_Object).call(this, iter, bind); }
			catch (e) { if (e !== $break) throw e; }
			return bind;
		}, '__each'),

		/**
		 * Searches the list for the first element where the condition of the
		 * passed iterator is met and returns its key.
		 */
		findKey: ITERATE(function(iter, bind, that) {
			return this.each(function(val, key) {
				if (ITERATOR(iter, bind, val, key, that, __find)) {
					this.key = key;
					throw $break;
				}
			}, { key: null }).key;
		}, '__find'),

		find: function(iter, bind) {
			return this[this.findKey(iter, bind)];
		},

		removeKey: function(key) {
			var val = this[key];
			delete this[key];
			return val;
		},

		/**
		 * Removes an element. Find is used to find the element fullfilling the
		 * criteria, then removeKey is called, which has a different implementation
		 * for Array.
		 */
		remove: function(iter) {
			var key = this.findKey(iter);
			if (key != null) return this.removeKey(key);
		},

		/**
		 * Returns true if the condition defined by the passed iterator is true
		 * for one or more of the elements, false otherwise.
		 * If no iterator is passed, the value is used directly.
		 * This is compatible with JS 1.5's .some, but adds more flexibility
		 * regarding iterators (as defined in iterate())
		 */
		some: ITERATE(function(iter, bind) {
			return this.findKey(iter, bind) != null;
		}, '__some'),

		/**
		 * Returns true if the condition defined by the passed iterator is true
		 * for	all elements, false otherwise.
		 * If no iterator is passed, the value is used directly.
		 * This is compatible with JS 1.5's .every, but adds more flexibility
		 * regarding iterators (as defined in iterate())
		 */
		every: ITERATE(function(iter, bind, that) {
			return this.findKey(function(val, i) {
				// as "this" is not used for anything else, use it for bind,
				// so that lookups on the object are faster (according to
				// benchmarking)
				return !ITERATOR(iter, this, val, i, that, __every);
			}, bind) == null;
		}, '__every'),

		/**
		 * Collects the result of the given iterator applied to each of the
		 * elements in an array and returns it.
		 * If no iterator is passed, the value is used directly.
		 * This is compatible with JS 1.5's .map, but adds more flexibility
		 * regarding iterators (as defined in iterate())
		 */
		map: ITERATE(function(iter, bind, that) {
			return this.each(function(val, i) {
				this[this.length] = ITERATOR(iter, bind, val, i, that, __map);
			}, []);
		}, '__map'),

		/**
		 * Collects all elements for which the condition of the passed iterator
		 * or regular expression is true.
		 * This is compatible with JS 1.5's .filter, but adds more flexibility
		 * regarding iterators (as defined in iterate())
		 * TODO: consider collect: similar to filter, but collects the returned
		 * elements if they are != null.
		 * TOOD: See if collect and filter could be joined somehow
		 */
		filter: ITERATE(function(iter, bind, that) {
			return this.each(function(val, i) {
				if (ITERATOR(iter, bind, val, i, that, __filter))
					this[this.length] = val;
			}, []);
		}, '__filter'),

		/**
		 * Returns the maximum value of the result of the passed iterator
		 * applied to each element.
		 * If no iterator is passed, the value is used directly.
		 */
		max: ITERATE(function(iter, bind, that) {
			return this.each(function(val, i) {
				val = ITERATOR(iter, bind, val, i, that, __max);
				if (val >= (this.max || val)) this.max = val;
			}, {}).max;
		}, '__max'),

		/**
		 * Returns the minimum value of the result of the passed iterator
		 * applied to each element.
		 * If no iterator is passed, the value is used directly.
		 */
		min: ITERATE(function(iter, bind, that) {
			return this.each(function(val, i) {
				val = ITERATOR(iter, bind, val, i, that, __min);
				if (val <= (this.min || val)) this.min = val;
			}, {}).min;
		}, '__min'),

		/**
		 * Collects the values of the given property of each of the elements
		 * in an array and returns it.
		 */
		pluck: function(prop) {
			return this.map(function(val) {
				return val[prop];
			});
		},

		/**
		 * Sorts the elements depending on the outcome of the passed iterator
		 * and returns the sorted list in an array.
		 * Inspired by Prototype.js
		 */
		sortBy: ITERATE(function(iter, bind, that) {
			return this.map(function(val, i) {
				return { value: val, compare: ITERATOR(iter, bind, val, i, that, __sortBy) };
			}, bind).sort(function(left, right) {
				var a = left.compare, b = right.compare;
				return a < b ? -1 : a > b ? 1 : 0;
			}).pluck('value');
		}, '__sortBy'),

		/**
		 * Converts the Enumerable to a normal array.
		 */
		toArray: function() {
			return this.map();
		}
	};
}

#endif // __lang_Enumerable__<commit_msg>Erase set iterators again.<commit_after>#ifndef __lang_Enumerable__
#define __lang_Enumerable__

#comment Use macros to produce different version of the code bellow,
#comment depending on wether SET_ITERATOR is set or not.
#ifdef SET_ITERATOR
#comment The field 'name' on the 'bind' object is set to the iterator before
#comment iteration. We can call it directly instead using #call.
#comment This leads to better performance (2x on Firefox), and even more  on
#comment legacy browsers where we can avoid the emulated Function.call.
#define ITERATOR(ITER, BIND, VALUE, KEY, SELF, NAME) BIND.NAME(VALUE, KEY, SELF)
#define ITERATE(ITER, NAME) Base.iterate(ITER, NAME)
#else // !SET_ITERATOR
#comment Call the iterator funciton on the bind object through Function.call.
#comment This is cleanear but slower than the SET_ITERATOR hack.
#define ITERATOR(ITER, BIND, VALUE, KEY, SELF, NAME) ITER.call(BIND, VALUE, KEY, SELF)
#define ITERATE(ITER, NAME) Base.iterate(ITER)
#endif // !SET_ITERATOR

////////////////////////////////////////////////////////////////////////////////
// Enumerable

/**
 * A special constant, to be thrown by closures passed to each()
 * Inspired by Prototype.js
 *
 * $continue is not implemented, as the same functionality can achieved
 * by using return in the closure. In prototype, the implementation of $continue
 * also leads to a huge speed decrease, as the closure is wrapped in another
 * closure that does nothing else than handling $continue.
 */
$break = {};

/**
 * The Enumerable interface. To add enumerable functionality to any prototype,
 * just use Constructor.inject(Enumerable);
 * This adds the function .each() that can handle both arrays (detected through
 * .length) and dictionaries (if it's not an array, enumerating with for-in).
 */
Enumerable = new function() {
	/**
	 * Converts the passed function to an iterate-function.
	 * This is part of an optimization that is based on the observation that
	 * calling the iterator through bind.__iterate is faster than using iter.apply()
	 * each time.
	 * So iterate wraps the passed function in a closure that sets the __iterate
	 * function (defined by name) on the bind object and then calls the original
	 * function, restoring the original state after it returns.
	 * This is used in many places in Enumerable, each place defining its own
	 * name for the iterate function, so there are no clashes if calls are nested.
	 */
#ifdef SET_ITERATOR
	Base.iterate = function(fn, name) {
#else
	Base.iterate = function(fn) {
#endif
#if defined(SET_ITERATOR) && defined(DONT_ENUM)
		// dontEnum all set iterators once and for all on browsers:
		Base.prototype.dontEnum(true, name);
#endif // APPLY_ITERATOR && DONT_ENUM
		return function(iter, bind) {
			// Convert the argument to an iterator function. If none is specified,
			// the identity function is returned.
			// This supports regular expressions, normal functions, which are
			// returned unmodified, and values to compare to.
			// Wherever this private function is used in the Enumerable functions
			// bellow, a RegExp object, a Function or null may be passed.
			if (!iter) iter = function(val) { return val };
			else if (typeof iter != 'function') iter = function(val) { return val == iter };
			/* FOR RegExp support, used this:
			else switch ($typeof(iter)) {
				case 'function': break;
				case 'regexp': iter = function(val) { return iter.test(val) }; break;
				default: iter = function(val) { return val == iter };
			}
			*/
			if (!bind) bind = this;
#ifdef SET_ITERATOR
			// Backup previous value of the field, and set iterator.
			var prev = bind[name];
			bind[name] = iter;
#ifdef HELMA
			// On Helma, we can only dontEnum once the property is defined.
			bind.dontEnum(name);
#endif // HELMA
#endif// !SET_ITERATOR
			// Interesting benchmark observation: The loops seem execute
			// faster when called on the object (this), so outsource to
			// the above functions each_Array / each_Object here.
			// pass this twice, so it can be recieved as 'that' in the iterating
			// functions, to be passed to the iterator (and being able to use
			// 'this' in .each differently)
#ifdef SET_ITERATOR
			// Allways restore previous value in the end.
			try { return fn.call(this, iter, bind, this); }
			finally { prev ? bind[name] = prev : delete bind[name] }
#else // !SET_ITERATOR
			return fn.call(this, iter, bind, this);
#endif// !SET_ITERATOR
		};
	};

	var each_Array = Array.prototype.forEach || function(iter, bind) {
		for (var i = 0, j = this.length; i < j; ++i)
			ITERATOR(iter, bind, this[i], i, this, __each);
	};

	var each_Object = function(iter, bind) {
#ifdef DONT_ENUM
		// We use for-in here, but need to filter out what should not be iterated.
		// Object#dontEnum defines a method to flag such a fields, and Object#has
		// a way to find out for any given key if it is enumerable or not.
		// The loop here uses an inline version of Object#has (See Core).
		var entries = this._dontEnum || {};
		for (var i in this) {
			var val = this[i], entry = entries[i];
			// Skip dontEnum fields.
			// This line here is similar to Base.prototype.has
			if (!entry || entry.allow && entry.object[i] !== this[i])
				ITERATOR(iter, bind, val, i, this, __each);
		}
#elif !defined(HELMA)
		// We use for-in here, but need to filter out what should not be iterated.
		// The loop here uses an inline version of Object#has (See Core).
		for (var i in this) {
			var val = this[i];
			if (val !== this.__proto__[i]AND_NAME_IS_VISIBLE(i))
				ITERATOR(iter, bind, val, i, this, __each);
		}
#else // HELMA
		// No need to check when not extending Object and when on Helma as
		// dontEnum is always used to hide fields there.
		for (var i in this)
			ITERATOR(iter, bind, this[i], i, this, __each);
#endif
	};

	return {
		HIDE
		_generics: true,

		/**
		 * The core of all Enumerable functions. TODO: document
		 */
		each: ITERATE(function(iter, bind) {
			try { (this.length != null ? each_Array : each_Object).call(this, iter, bind); }
			catch (e) { if (e !== $break) throw e; }
			return bind;
		}, '__each'),

		/**
		 * Searches the list for the first element where the condition of the
		 * passed iterator is met and returns its key.
		 */
		findKey: ITERATE(function(iter, bind, that) {
			return this.each(function(val, key) {
				if (ITERATOR(iter, bind, val, key, that, __find)) {
					this.key = key;
					throw $break;
				}
			}, { key: null }).key;
		}, '__find'),

		find: function(iter, bind) {
			return this[this.findKey(iter, bind)];
		},

		removeKey: function(key) {
			var val = this[key];
			delete this[key];
			return val;
		},

		/**
		 * Removes an element. Find is used to find the element fullfilling the
		 * criteria, then removeKey is called, which has a different implementation
		 * for Array.
		 */
		remove: function(iter) {
			var key = this.findKey(iter);
			if (key != null) return this.removeKey(key);
		},

		/**
		 * Returns true if the condition defined by the passed iterator is true
		 * for one or more of the elements, false otherwise.
		 * If no iterator is passed, the value is used directly.
		 * This is compatible with JS 1.5's .some, but adds more flexibility
		 * regarding iterators (as defined in iterate())
		 */
		some: ITERATE(function(iter, bind) {
			return this.findKey(iter, bind) != null;
		}, '__some'),

		/**
		 * Returns true if the condition defined by the passed iterator is true
		 * for	all elements, false otherwise.
		 * If no iterator is passed, the value is used directly.
		 * This is compatible with JS 1.5's .every, but adds more flexibility
		 * regarding iterators (as defined in iterate())
		 */
		every: ITERATE(function(iter, bind, that) {
			return this.findKey(function(val, i) {
				// as "this" is not used for anything else, use it for bind,
				// so that lookups on the object are faster (according to
				// benchmarking)
				return !ITERATOR(iter, this, val, i, that, __every);
			}, bind) == null;
		}, '__every'),

		/**
		 * Collects the result of the given iterator applied to each of the
		 * elements in an array and returns it.
		 * If no iterator is passed, the value is used directly.
		 * This is compatible with JS 1.5's .map, but adds more flexibility
		 * regarding iterators (as defined in iterate())
		 */
		map: ITERATE(function(iter, bind, that) {
			return this.each(function(val, i) {
				this[this.length] = ITERATOR(iter, bind, val, i, that, __map);
			}, []);
		}, '__map'),

		/**
		 * Collects all elements for which the condition of the passed iterator
		 * or regular expression is true.
		 * This is compatible with JS 1.5's .filter, but adds more flexibility
		 * regarding iterators (as defined in iterate())
		 * TODO: consider collect: similar to filter, but collects the returned
		 * elements if they are != null.
		 * TOOD: See if collect and filter could be joined somehow
		 */
		filter: ITERATE(function(iter, bind, that) {
			return this.each(function(val, i) {
				if (ITERATOR(iter, bind, val, i, that, __filter))
					this[this.length] = val;
			}, []);
		}, '__filter'),

		/**
		 * Returns the maximum value of the result of the passed iterator
		 * applied to each element.
		 * If no iterator is passed, the value is used directly.
		 */
		max: ITERATE(function(iter, bind, that) {
			return this.each(function(val, i) {
				val = ITERATOR(iter, bind, val, i, that, __max);
				if (val >= (this.max || val)) this.max = val;
			}, {}).max;
		}, '__max'),

		/**
		 * Returns the minimum value of the result of the passed iterator
		 * applied to each element.
		 * If no iterator is passed, the value is used directly.
		 */
		min: ITERATE(function(iter, bind, that) {
			return this.each(function(val, i) {
				val = ITERATOR(iter, bind, val, i, that, __min);
				if (val <= (this.min || val)) this.min = val;
			}, {}).min;
		}, '__min'),

		/**
		 * Collects the values of the given property of each of the elements
		 * in an array and returns it.
		 */
		pluck: function(prop) {
			return this.map(function(val) {
				return val[prop];
			});
		},

		/**
		 * Sorts the elements depending on the outcome of the passed iterator
		 * and returns the sorted list in an array.
		 * Inspired by Prototype.js
		 */
		sortBy: ITERATE(function(iter, bind, that) {
			return this.map(function(val, i) {
				return { value: val, compare: ITERATOR(iter, bind, val, i, that, __sortBy) };
			}, bind).sort(function(left, right) {
				var a = left.compare, b = right.compare;
				return a < b ? -1 : a > b ? 1 : 0;
			}).pluck('value');
		}, '__sortBy'),

		/**
		 * Converts the Enumerable to a normal array.
		 */
		toArray: function() {
			return this.map();
		}
	};
}

#endif // __lang_Enumerable__<|endoftext|>


<commit_before>/*
Language: nginx
Author: Peter Leonov <gojpeg@yandex.ru>
*/

hljs.LANGUAGES.nginx = {
  defaultMode: {
    lexems: [hljs.UNDERSCORE_IDENT_RE],
    contains: ['comment', 'string', 'regexp', 'number', 'variable', 'built_in'],
    keywords: {access_log: 1, add_after_body: 1, add_before_body: 1, add_header: 1, addition_types: 1, aio: 1, alias: 1, allow: 1, ancient_browser: 1, ancient_browser_value: 1, auth_basic: 1, auth_basic_user_file: 1, autoindex: 1, autoindex_exact_size: 1, autoindex_localtime: 1, 'break': 1, charset: 1, charset_map: 1, charset_types: 1, client_body_buffer_size: 1, client_body_in_file_only: 1, client_body_in_single_buffer: 1, client_body_temp_path: 1, client_body_timeout: 1, client_header_buffer_size: 1, client_header_timeout: 1, client_max_body_size: 1, create_full_put_path: 1, crit: 1, daemon: 1, dav_access: 1, dav_methods: 1, debug: 1, default_type: 1, deny: 1, directio: 1, directio_alignment: 1, empty_gif: 1, env: 1, error: 1, error_page: 1, expires: 1, fastcgi_buffer_size: 1, fastcgi_buffers: 1, fastcgi_cache: 1, fastcgi_cache_key: 1, fastcgi_cache_min_uses: 1, fastcgi_cache_path: 1, fastcgi_cache_valid: 1, fastcgi_connect_timeout: 1, fastcgi_hide_header: 1, fastcgi_ignore_client_abort: 1, fastcgi_ignore_headers: 1, fastcgi_index: 1, fastcgi_intercept_errors: 1, fastcgi_next_upstream: 1, fastcgi_param: 1, fastcgi_pass: 1, fastcgi_pass_header: 1, fastcgi_read_timeout: 1, fastcgi_redirect_errors: 1, fastcgi_send_timeout: 1, fastcgi_split_path_info: 1, fastcgi_store: 1, fastcgi_store_access: 1, fastcgi_temp_path: 1, flv: 1, geo: 1, geoip_city: 1, geoip_country: 1, gzip: 1, gzip_buffers: 1, gzip_comp_level: 1, gzip_disable: 1, gzip_http_version: 1, gzip_min_length: 1, gzip_proxied: 1, gzip_static: 1, gzip_types: 1, gzip_vary: 1, 'if': 1, if_modified_since: 1, image_filter: 1, image_filter_buffer: 1, image_filter_jpeg_quality: 1, image_filter_transparency: 1, include: 1, index: 1, info: 1, internal: 1, ip_hash: 1, keepalive_requests: 1, keepalive_timeout: 1, large_client_header_buffers: 1, limit_conn: 1, limit_conn_log_level: 1, limit_except: 1, limit_rate: 1, limit_rate_after: 1, limit_req: 1, limit_req_log_level: 1, limit_req_zone: 1, limit_zone: 1, listen: 1, location: 1, log_format: 1, log_not_found: 1, log_subrequest: 1, map: 1, map_hash_bucket_size: 1, map_hash_max_size: 1, master_process: 1, memcached_buffer_size: 1, memcached_connect_timeout: 1, memcached_next_upstream: 1, memcached_pass: 1, memcached_read_timeout: 1, memcached_send_timeout: 1, merge_slashes: 1, min_delete_depth: 1, modern_browser: 1, modern_browser_value: 1, msie_padding: 1, msie_refresh: 1, notice: 1, open_file_cache: 1, open_file_cache_errors: 1, open_file_cache_min_uses: 1, open_file_cache_valid: 1, open_log_file_cache: 1, optimize_server_names: 1, override_charset: 1, perl: 1, perl_modules: 1, perl_require: 1, perl_set: 1, pid: 1, port_in_redirect: 1, proxy_buffer_size: 1, proxy_buffering: 1, proxy_buffers: 1, proxy_cache: 1, proxy_cache_key: 1, proxy_cache_min_uses: 1, proxy_cache_path: 1, proxy_cache_use_stale: 1, proxy_cache_valid: 1, proxy_connect_timeout: 1, proxy_hide_header: 1, proxy_ignore_client_abort: 1, proxy_ignore_headers: 1, proxy_intercept_errors: 1, proxy_next_upstream: 1, proxy_pass: 1, proxy_pass_header: 1, proxy_read_timeout: 1, proxy_redirect: 1, proxy_redirect_errors: 1, proxy_send_timeout: 1, proxy_set_header: 1, proxy_ssl_session_reuse: 1, proxy_store: 1, proxy_store_access: 1, proxy_temp_path: 1, random_index: 1, read_ahead: 1, real_ip_header: 1, recursive_error_pages: 1, reset_timedout_connection: 1, resolver: 1, resolver_timeout: 1, 'return': 1, rewrite: 1, root: 1, satisfy: 1, satisfy_any: 1, secure_link_secret: 1, send_timeout: 1, sendfile: 1, server: 1, server: 1, server_name: 1, server_name_in_redirect: 1, server_names_hash_bucket_size: 1, server_names_hash_max_size: 1, server_tokens: 1, set: 1, set_real_ip_from: 1, source_charset: 1, ssl: 1, ssl_certificate: 1, ssl_certificate_key: 1, ssl_ciphers: 1, ssl_client_certificate: 1, ssl_crl: 1, ssl_dhparam: 1, ssl_engine: 1, ssl_prefer_server_ciphers: 1, ssl_protocols: 1, ssl_session_cache: 1, ssl_session_timeout: 1, ssl_verify_client: 1, ssl_verify_depth: 1, sub_filter: 1, sub_filter_once: 1, sub_filter_types: 1, tcp_nodelay: 1, tcp_nopush: 1, timer_resolution: 1, try_files: 1, types: 1, underscores_in_headers: 1, uninitialized_variable_warn: 1, upstream: 1, user: 1, userid: 1, userid_domain: 1, userid_expires: 1, userid_name: 1, userid_p3p: 1, userid_path: 1, userid_service: 1, valid_referers: 1, warn: 1, worker_priority: 1, worker_processes: 1, worker_rlimit_core: 1, worker_rlimit_nofile: 1, working_directory: 1, xml_entities: 1, xslt_stylesheet: 1, xslt_types: 1, server: 1, location: 1, http: 1, proxy_send_lowat: 1, proxy_busy_buffers_size: 1, proxy_temp_file_write_size: 1, output_buffers: 1, postpone_output: 1, send_lowat: 1, lingering_time: 1, lingering_timeout: 1, error_log: 1, events: 1, connections: 1, use: 1}
  },
  modes: [
    hljs.HASH_COMMENT_MODE,
    {
        className: 'location',
        begin: '\\blocation\\b', end: '$|{'
    },
    // variables (like in perl)
    {
        className: 'variable',
        begin: '\\$\\d', end: '^'
    },
    // ${...} is not yet implemented
    // {
    //     className: 'variable',
    //     begin: '\\${', end: '}'
    // },
    {
        className: 'variable',
        begin: '[\\$\\@][_a-zA-Z][_a-zA-Z0-9]*', end: '^'
    },
    {
      className: 'built_in',
      begin: '\\b(on|off|yes|no|none|true|false|debug|info|notice|warn|error|crit|kqueue|rtsig|epoll|select|poll|permanent|redirect)\\b', end: '^',
    },
    {
      className: 'number',
      begin: '\\b\\d+[kKmMgGdshdwy]*\\b', end: '^',
      relevance: 0
    },
    {
        className: 'string',
        begin: '"', end: '"',
        contains: ['escape', 'variable'],
        relevance: 0
    },
    {
        className: 'string',
        begin: "'", end: "'",
        contains: ['escape', 'variable'],
        relevance: 0
    },
    {
        className: 'string',
        begin: "\\s/", end: "\\s|;",
        contains: ['escape', 'variable']
    },
    {
        className: 'regexp',
        begin: "\\s\\^", end: "\\s|{|;",
        contains: ['escape', 'variable']
    },
    {
        className: 'regexp',
        begin: "~\\*?\\s+", end: "\\s|{|;",
        contains: ['escape', 'variable']
    },
    {
        className: 'regexp',
        begin: "\\*(\\.[a-z\\-]+)+", end: "^",
        contains: ['escape', 'variable']
    },
    {
        className: 'regexp',
        begin: "([a-z\\-]+\\.)+\\*", end: "^",
        contains: ['escape', 'variable']
    },
    hljs.BACKSLASH_ESCAPE
  ]
};
<commit_msg>special mode in nginx to avoid detailed parsing of http hosts<commit_after>/*
Language: nginx
Author: Peter Leonov <gojpeg@yandex.ru>
*/

hljs.LANGUAGES.nginx = {
  defaultMode: {
    lexems: [hljs.UNDERSCORE_IDENT_RE],
    contains: ['comment', 'string', 'regexp', 'number', 'variable', 'built_in', 'http'],
    keywords: {access_log: 1, add_after_body: 1, add_before_body: 1, add_header: 1, addition_types: 1, aio: 1, alias: 1, allow: 1, ancient_browser: 1, ancient_browser_value: 1, auth_basic: 1, auth_basic_user_file: 1, autoindex: 1, autoindex_exact_size: 1, autoindex_localtime: 1, 'break': 1, charset: 1, charset_map: 1, charset_types: 1, client_body_buffer_size: 1, client_body_in_file_only: 1, client_body_in_single_buffer: 1, client_body_temp_path: 1, client_body_timeout: 1, client_header_buffer_size: 1, client_header_timeout: 1, client_max_body_size: 1, create_full_put_path: 1, crit: 1, daemon: 1, dav_access: 1, dav_methods: 1, debug: 1, default_type: 1, deny: 1, directio: 1, directio_alignment: 1, empty_gif: 1, env: 1, error: 1, error_page: 1, expires: 1, fastcgi_buffer_size: 1, fastcgi_buffers: 1, fastcgi_cache: 1, fastcgi_cache_key: 1, fastcgi_cache_min_uses: 1, fastcgi_cache_path: 1, fastcgi_cache_valid: 1, fastcgi_connect_timeout: 1, fastcgi_hide_header: 1, fastcgi_ignore_client_abort: 1, fastcgi_ignore_headers: 1, fastcgi_index: 1, fastcgi_intercept_errors: 1, fastcgi_next_upstream: 1, fastcgi_param: 1, fastcgi_pass: 1, fastcgi_pass_header: 1, fastcgi_read_timeout: 1, fastcgi_redirect_errors: 1, fastcgi_send_timeout: 1, fastcgi_split_path_info: 1, fastcgi_store: 1, fastcgi_store_access: 1, fastcgi_temp_path: 1, flv: 1, geo: 1, geoip_city: 1, geoip_country: 1, gzip: 1, gzip_buffers: 1, gzip_comp_level: 1, gzip_disable: 1, gzip_http_version: 1, gzip_min_length: 1, gzip_proxied: 1, gzip_static: 1, gzip_types: 1, gzip_vary: 1, 'if': 1, if_modified_since: 1, image_filter: 1, image_filter_buffer: 1, image_filter_jpeg_quality: 1, image_filter_transparency: 1, include: 1, index: 1, info: 1, internal: 1, ip_hash: 1, keepalive_requests: 1, keepalive_timeout: 1, large_client_header_buffers: 1, limit_conn: 1, limit_conn_log_level: 1, limit_except: 1, limit_rate: 1, limit_rate_after: 1, limit_req: 1, limit_req_log_level: 1, limit_req_zone: 1, limit_zone: 1, listen: 1, location: 1, log_format: 1, log_not_found: 1, log_subrequest: 1, map: 1, map_hash_bucket_size: 1, map_hash_max_size: 1, master_process: 1, memcached_buffer_size: 1, memcached_connect_timeout: 1, memcached_next_upstream: 1, memcached_pass: 1, memcached_read_timeout: 1, memcached_send_timeout: 1, merge_slashes: 1, min_delete_depth: 1, modern_browser: 1, modern_browser_value: 1, msie_padding: 1, msie_refresh: 1, notice: 1, open_file_cache: 1, open_file_cache_errors: 1, open_file_cache_min_uses: 1, open_file_cache_valid: 1, open_log_file_cache: 1, optimize_server_names: 1, override_charset: 1, perl: 1, perl_modules: 1, perl_require: 1, perl_set: 1, pid: 1, port_in_redirect: 1, proxy_buffer_size: 1, proxy_buffering: 1, proxy_buffers: 1, proxy_cache: 1, proxy_cache_key: 1, proxy_cache_min_uses: 1, proxy_cache_path: 1, proxy_cache_use_stale: 1, proxy_cache_valid: 1, proxy_connect_timeout: 1, proxy_hide_header: 1, proxy_ignore_client_abort: 1, proxy_ignore_headers: 1, proxy_intercept_errors: 1, proxy_next_upstream: 1, proxy_pass: 1, proxy_pass_header: 1, proxy_read_timeout: 1, proxy_redirect: 1, proxy_redirect_errors: 1, proxy_send_timeout: 1, proxy_set_header: 1, proxy_ssl_session_reuse: 1, proxy_store: 1, proxy_store_access: 1, proxy_temp_path: 1, random_index: 1, read_ahead: 1, real_ip_header: 1, recursive_error_pages: 1, reset_timedout_connection: 1, resolver: 1, resolver_timeout: 1, 'return': 1, rewrite: 1, root: 1, satisfy: 1, satisfy_any: 1, secure_link_secret: 1, send_timeout: 1, sendfile: 1, server: 1, server: 1, server_name: 1, server_name_in_redirect: 1, server_names_hash_bucket_size: 1, server_names_hash_max_size: 1, server_tokens: 1, set: 1, set_real_ip_from: 1, source_charset: 1, ssl: 1, ssl_certificate: 1, ssl_certificate_key: 1, ssl_ciphers: 1, ssl_client_certificate: 1, ssl_crl: 1, ssl_dhparam: 1, ssl_engine: 1, ssl_prefer_server_ciphers: 1, ssl_protocols: 1, ssl_session_cache: 1, ssl_session_timeout: 1, ssl_verify_client: 1, ssl_verify_depth: 1, sub_filter: 1, sub_filter_once: 1, sub_filter_types: 1, tcp_nodelay: 1, tcp_nopush: 1, timer_resolution: 1, try_files: 1, types: 1, underscores_in_headers: 1, uninitialized_variable_warn: 1, upstream: 1, user: 1, userid: 1, userid_domain: 1, userid_expires: 1, userid_name: 1, userid_p3p: 1, userid_path: 1, userid_service: 1, valid_referers: 1, warn: 1, worker_priority: 1, worker_processes: 1, worker_rlimit_core: 1, worker_rlimit_nofile: 1, working_directory: 1, xml_entities: 1, xslt_stylesheet: 1, xslt_types: 1, server: 1, location: 1, http: 1, proxy_send_lowat: 1, proxy_busy_buffers_size: 1, proxy_temp_file_write_size: 1, output_buffers: 1, postpone_output: 1, send_lowat: 1, lingering_time: 1, lingering_timeout: 1, error_log: 1, events: 1, connections: 1, use: 1}
  },
  modes: [
    hljs.HASH_COMMENT_MODE,
    {
        className: 'location',
        begin: '\\blocation\\b', end: '$|{'
    },
    // variables (like in perl)
    {
        className: 'variable',
        begin: '\\$\\d', end: '^'
    },
    // ${...} is not yet implemented
    // {
    //     className: 'variable',
    //     begin: '\\${', end: '}'
    // },
    {
        className: 'variable',
        begin: '[\\$\\@][_a-zA-Z][_a-zA-Z0-9]*', end: '^'
    },
    {
      className: 'built_in',
      begin: '\\b(on|off|yes|no|none|true|false|debug|info|notice|warn|error|crit|kqueue|rtsig|epoll|select|poll|permanent|redirect)\\b', end: '^',
    },
    {
      className: 'number',
      begin: '\\b\\d+[kKmMgGdshdwy]*\\b', end: '^',
      relevance: 0
    },
    {
      className: 'http',
      begin: 'http://.*?/', end: '^', noMarkup: true,
      relevance: 0
    },
    {
        className: 'string',
        begin: '"', end: '"',
        contains: ['escape', 'variable'],
        relevance: 0
    },
    {
        className: 'string',
        begin: "'", end: "'",
        contains: ['escape', 'variable'],
        relevance: 0
    },
    {
        className: 'string',
        begin: "\\s/", end: "\\s|;",
        contains: ['escape', 'variable']
    },
    {
        className: 'regexp',
        begin: "\\s\\^", end: "\\s|{|;",
        contains: ['escape', 'variable']
    },
    {
        className: 'regexp',
        begin: "~\\*?\\s+", end: "\\s|{|;",
        contains: ['escape', 'variable']
    },
    {
        className: 'regexp',
        begin: "\\*(\\.[a-z\\-]+)+", end: "^",
        contains: ['escape', 'variable']
    },
    {
        className: 'regexp',
        begin: "([a-z\\-]+\\.)+\\*", end: "^",
        contains: ['escape', 'variable']
    },
    hljs.BACKSLASH_ESCAPE
  ]
};
<|endoftext|>