<commit_before>'use strict';

const OPTIONS_PAGE = 'html/options.html';

/**
 * @exports newtaboverride
 */
const newtaboverride = {
  parseVersion (version) {
    const x = version.split('.');
    const major = parseInt(x[0]) || 0;
    const minor = parseInt(x[1]) || 0;
    const patch = parseInt(x[2]) || 0;

    return { major, minor, patch }
  },

  /**
   * Fired when the extension is first installed, when the extension is updated to a new version or when the browser
   * is updated to a new version. We want to show a badge on our toolbar icon when the extension is first installed
   * or if an older version is detected.
   *
   * @param {runtime.OnInstalledReason} details - details.reason contains the reason why this event is being dispatched
   *
   * @returns {void}
   */
  onInstalledHandler (details) {
    if (details.reason === 'install') {
      browser.browserAction.setBadgeText({ text : '★' });
    }

    if (details.reason === 'update') {
      if (newtaboverride.parseVersion(details.previousVersion).major < 7) {
        browser.runtime.openOptionsPage();
        browser.storage.local.set({show_compat_notice : true});
      }
      else {
        browser.storage.local.set({show_compat_notice : false});
      }
    }
  },

  /**
   * Fired whenever the user changes the input, after the user has started interacting with the add-on by entering
   * its keyword in the address bar and then pressing the space key.
   *
   * @param {string} input - user input in the address bar, not including the add-on's keyword itself or the space
   *                 after the keyword

   *                 Supported value: settings
   * @param {function} suggest - a callback function that the event listener can call to supply suggestions for the
   *                   address bar's drop-down list
   *
   * @returns {void}
   */
  showOmniboxSuggestions (input, suggest) {
    const availableCommands = ['settings'];
    const suggestions = [];

    for (const command of availableCommands) {
      if (command.indexOf(input) !== -1) {
        suggestions.push({
          content : command,
          description : browser.i18n.getMessage('omnibox_command_' + command)
        });
      }

      if (suggestions.length === 0) {
        suggestions.push({
          content : 'settings',
          description : browser.i18n.getMessage('omnibox_command_settings')
        });
      }
    }

    suggest(suggestions);
  },

  /**
   * Fired when the user has selected one of the suggestions the add-on has added to the address bar's drop-down list.
   *
   * @param {string} input - this is the value that the user selected
   *
   * @returns {void}
   */
  callOmniboxAction (input) {
    switch (input) {
      case 'settings':
      default:
        newtaboverride.openUserInterfaceInCurrentTab();
    }
  },

  /**
   * Fired when the toolbar icon is clicked. This method is used to open the user interface in a new tab or to switch
   * to the tab with the user interface if the user interface is already opened.
   *
   * @returns {void}
   */
  openUserInterface () {
    const url = browser.extension.getURL(OPTIONS_PAGE);

    browser.browserAction.setBadgeText({ text : '' });
    browser.tabs.query({}, (tabs) => {
      let tabId = null;

      for (const tab of tabs) {
        if (tab.url === url) {
          tabId = tab.id;
          break;
        }
      }

      if (tabId) {
        browser.tabs.update(tabId, { active : true });
      }
      else {
        browser.tabs.create({ url });
      }
    });
  },

  /**
   * This method is used to open the user interface in the current tab. It's used for the omnibox suggestions.
   *
   * @returns {void}
   */
  openUserInterfaceInCurrentTab () {
    browser.tabs.update(null, { url : browser.extension.getURL(OPTIONS_PAGE) });
  }
};

browser.browserAction.onClicked.addListener(newtaboverride.openUserInterface);
browser.omnibox.onInputChanged.addListener(newtaboverride.showOmniboxSuggestions);
browser.omnibox.onInputEntered.addListener(newtaboverride.callOmniboxAction);
browser.omnibox.setDefaultSuggestion({ description : browser.i18n.getMessage('omnibox_default_description') });
browser.runtime.onInstalled.addListener(newtaboverride.onInstalledHandler);
<commit_msg>updated comment<commit_after>'use strict';

const OPTIONS_PAGE = 'html/options.html';

/**
 * @exports newtaboverride
 */
const newtaboverride = {
  parseVersion (version) {
    const x = version.split('.');
    const major = parseInt(x[0]) || 0;
    const minor = parseInt(x[1]) || 0;
    const patch = parseInt(x[2]) || 0;

    return { major, minor, patch }
  },

  /**
   * Fired when the extension is first installed, when the extension is updated to a new version or when the browser
   * is updated to a new version. We want to show a badge on our toolbar icon when the extension is first installed
   * or. If the legacy version of this add-on was installed we want to open the options page.
   *
   * @param {runtime.OnInstalledReason} details - details.reason contains the reason why this event is being dispatched
   *
   * @returns {void}
   */
  onInstalledHandler (details) {
    if (details.reason === 'install') {
      browser.browserAction.setBadgeText({ text : '★' });
    }

    if (details.reason === 'update') {
      if (newtaboverride.parseVersion(details.previousVersion).major < 7) {
        browser.runtime.openOptionsPage();
        browser.storage.local.set({show_compat_notice : true});
      }
      else {
        browser.storage.local.set({show_compat_notice : false});
      }
    }
  },

  /**
   * Fired whenever the user changes the input, after the user has started interacting with the add-on by entering
   * its keyword in the address bar and then pressing the space key.
   *
   * @param {string} input - user input in the address bar, not including the add-on's keyword itself or the space
   *                 after the keyword

   *                 Supported value: settings
   * @param {function} suggest - a callback function that the event listener can call to supply suggestions for the
   *                   address bar's drop-down list
   *
   * @returns {void}
   */
  showOmniboxSuggestions (input, suggest) {
    const availableCommands = ['settings'];
    const suggestions = [];

    for (const command of availableCommands) {
      if (command.indexOf(input) !== -1) {
        suggestions.push({
          content : command,
          description : browser.i18n.getMessage('omnibox_command_' + command)
        });
      }

      if (suggestions.length === 0) {
        suggestions.push({
          content : 'settings',
          description : browser.i18n.getMessage('omnibox_command_settings')
        });
      }
    }

    suggest(suggestions);
  },

  /**
   * Fired when the user has selected one of the suggestions the add-on has added to the address bar's drop-down list.
   *
   * @param {string} input - this is the value that the user selected
   *
   * @returns {void}
   */
  callOmniboxAction (input) {
    switch (input) {
      case 'settings':
      default:
        newtaboverride.openUserInterfaceInCurrentTab();
    }
  },

  /**
   * Fired when the toolbar icon is clicked. This method is used to open the user interface in a new tab or to switch
   * to the tab with the user interface if the user interface is already opened.
   *
   * @returns {void}
   */
  openUserInterface () {
    const url = browser.extension.getURL(OPTIONS_PAGE);

    browser.browserAction.setBadgeText({ text : '' });
    browser.tabs.query({}, (tabs) => {
      let tabId = null;

      for (const tab of tabs) {
        if (tab.url === url) {
          tabId = tab.id;
          break;
        }
      }

      if (tabId) {
        browser.tabs.update(tabId, { active : true });
      }
      else {
        browser.tabs.create({ url });
      }
    });
  },

  /**
   * This method is used to open the user interface in the current tab. It's used for the omnibox suggestions.
   *
   * @returns {void}
   */
  openUserInterfaceInCurrentTab () {
    browser.tabs.update(null, { url : browser.extension.getURL(OPTIONS_PAGE) });
  }
};

browser.browserAction.onClicked.addListener(newtaboverride.openUserInterface);
browser.omnibox.onInputChanged.addListener(newtaboverride.showOmniboxSuggestions);
browser.omnibox.onInputEntered.addListener(newtaboverride.callOmniboxAction);
browser.omnibox.setDefaultSuggestion({ description : browser.i18n.getMessage('omnibox_default_description') });
browser.runtime.onInstalled.addListener(newtaboverride.onInstalledHandler);
<|endoftext|>


<commit_before>// DOM Library Utilites
$.parseUrlQuery = function (url) {
    var query = {}, i, params, param;
    if (url.indexOf('?') >= 0) url = url.split('?')[1];
    else return query;
    params = url.split('&');
    for (i = 0; i < params.length; i++) {
        param = params[i].split('=');
        query[param[0]] = param[1];
    }
    return query;
};
$.isArray = function (arr) {
    if (Object.prototype.toString.apply(arr) === '[object Array]') return true;
    else return false;
};
$.each = function (obj, callback) {
    if (typeof obj !== 'object') return;
    if (!callback) return;
    var i, prop;
    if ($.isArray(obj) || obj instanceof Dom7) {
        // Array
        for (i = 0; i < obj.length; i++) {
            callback(i, obj[i]);
        }
    }
    else {
        // Object
        for (prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                callback(prop, obj[prop]);
            }
        }
    }
};
$.unique = function (arr) {
    var unique = [];
    for (var i = 0; i < arr.length; i++) {
        if (unique.indexOf(arr[i]) === -1) unique.push(arr[i]);
    }
    return unique;
};
$.serializeObject = $.param = function (obj, parents) {
    if (typeof obj === 'string') return obj;
    var resultArray = [];
    var separator = '&';
    parents = parents || [];
    var newParents;
    function var_name(name) {
        if (parents.length > 0) {
            var _parents = '';
            for (var j = 0; j < parents.length; j++) {
                if (j === 0) _parents += parents[j];
                else _parents += '[' + encodeURIComponent(parents[j]) + ']';
            }
            return _parents + '[' + encodeURIComponent(name) + ']';
        }
        else {
            return encodeURIComponent(name);
        }
    }
    function var_value(value) {
        return encodeURIComponent(value);
    }
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            var toPush;
            if ($.isArray(obj[prop])) {
                toPush = [];
                for (var i = 0; i < obj[prop].length; i ++) {
                    if (!$.isArray(obj[prop][i]) && typeof obj[prop][i] === 'object') {
                        newParents = parents.slice();
                        newParents.push(prop);
                        newParents.push(i + '');
                        toPush.push($.serializeObject(obj[prop][i], newParents));
                    }
                    else {
                        toPush.push(var_name(prop) + '[]=' + var_value(obj[prop][i]));
                    }

                }
                if (toPush.length > 0) resultArray.push(toPush.join(separator));
            }
            else if (typeof obj[prop] === 'object') {
                // Object, convert to named array
                newParents = parents.slice();
                newParents.push(prop);
                toPush = $.serializeObject(obj[prop], newParents);
                if (toPush !== '') resultArray.push(toPush);
            }
            else if (typeof obj[prop] !== 'undefined' && obj[prop] !== '') {
                // Should be string or plain value
                resultArray.push(var_name(prop) + '=' + var_value(obj[prop]));
            }
        }
    }
    return resultArray.join(separator);
};
$.toCamelCase = function (string) {
    return string.toLowerCase().replace(/-(.)/g, function(match, group1) {
        return group1.toUpperCase();
    });
};
$.dataset = function (el) {
    return $(el).dataset();
};
$.getTranslate = function (el, axis) {
    var matrix, curTransform, curStyle, transformMatrix;

    // automatic axis detection
    if (typeof axis === 'undefined') {
        axis = 'x';
    }

    curStyle = window.getComputedStyle(el, null);
    if (window.WebKitCSSMatrix) {
        curTransform = curStyle.transform || curStyle.webkitTransform;
        if (curTransform.split(',').length > 6) {
            curTransform = curTransform.split(', ').map(function(a){
                return a.replace(',','.');
            }).join(', ');
        }
        // Some old versions of Webkit choke when 'none' is passed; pass
        // empty string instead in this case
        transformMatrix = new WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
    }
    else {
        transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform  || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
        matrix = transformMatrix.toString().split(',');
    }

    if (axis === 'x') {
        //Latest Chrome and webkits Fix
        if (window.WebKitCSSMatrix)
            curTransform = transformMatrix.m41;
        //Crazy IE10 Matrix
        else if (matrix.length === 16)
            curTransform = parseFloat(matrix[12]);
        //Normal Browsers
        else
            curTransform = parseFloat(matrix[4]);
    }
    if (axis === 'y') {
        //Latest Chrome and webkits Fix
        if (window.WebKitCSSMatrix)
            curTransform = transformMatrix.m42;
        //Crazy IE10 Matrix
        else if (matrix.length === 16)
            curTransform = parseFloat(matrix[13]);
        //Normal Browsers
        else
            curTransform = parseFloat(matrix[5]);
    }

    return curTransform || 0;
};

$.requestAnimationFrame = function (callback) {
    if (window.requestAnimationFrame) return window.requestAnimationFrame(callback);
    else if (window.webkitRequestAnimationFrame) return window.webkitRequestAnimationFrame(callback);
    else if (window.mozRequestAnimationFrame) return window.mozRequestAnimationFrame(callback);
    else {
        return window.setTimeout(callback, 1000 / 60);
    }
};
$.cancelAnimationFrame = function (id) {
    if (window.cancelAnimationFrame) return window.cancelAnimationFrame(id);
    else if (window.webkitCancelAnimationFrame) return window.webkitCancelAnimationFrame(id);
    else if (window.mozCancelAnimationFrame) return window.mozCancelAnimationFrame(id);
    else {
        return window.clearTimeout(id);
    }
};
$.supportTouch = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);

// Link to prototype
$.fn = Dom7.prototype;

// Plugins
$.fn.scrollTo = function (left, top, duration, easing, callback) {
    if (arguments.length === 4 && typeof easing === 'function') {
        callback = easing;
        easing = undefined;
    }
    return this.each(function () {
        var el = this;
        var currentTop, currentLeft, maxTop, maxLeft, newTop, newLeft, scrollTop, scrollLeft;
        var animateTop = top > 0 || top === 0;
        var animateLeft = left > 0 || left === 0;
        if (typeof easing === 'undefined') {
            easing = 'swing';
        }
        if (animateTop) {
            currentTop = el.scrollTop;
            if (!duration) {
                el.scrollTop = top;
            }
        }
        if (animateLeft) {
            currentLeft = el.scrollLeft;
            if (!duration) {
                el.scrollLeft = left;
            }
        }
        if (!duration) return;
        if (animateTop) {
            maxTop = el.scrollHeight - el.offsetHeight;
            newTop = Math.max(Math.min(top, maxTop), 0);
        }
        if (animateLeft) {
            maxLeft = el.scrollWidth - el.offsetWidth;
            newLeft = Math.max(Math.min(left, maxLeft), 0);
        }
        var startTime = null;
        if (animateTop && newTop === currentTop) animateTop = false;
        if (animateLeft && newLeft === currentLeft) animateLeft = false;
        function render(time) {
            if (time === undefined) {
                time = new Date().getTime();
            }
            if (startTime === null) {
                startTime = time;
            }
            var doneLeft, doneTop, done;
            var progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
            var easeProgress = easing === 'linear' ? progress : (0.5 - Math.cos( progress * Math.PI ) / 2);
            if (animateTop) scrollTop = currentTop + (easeProgress * (newTop - currentTop));
            if (animateLeft) scrollLeft = currentLeft + (easeProgress * (newLeft - currentLeft));
            if (animateTop && newTop > currentTop && scrollTop >= newTop)  {
                el.scrollTop = newTop;
                done = true;
            }
            if (animateTop && newTop < currentTop && scrollTop <= newTop)  {
                el.scrollTop = newTop;
                done = true;
            }

            if (animateLeft && newLeft > currentLeft && scrollLeft >= newLeft)  {
                el.scrollLeft = newLeft;
                done = true;
            }
            if (animateLeft && newLeft < currentLeft && scrollLeft <= newLeft)  {
                el.scrollLeft = newLeft;
                done = true;
            }

            if (done) {
                if (callback) callback();
                return;
            }
            if (animateTop) el.scrollTop = scrollTop;
            if (animateLeft) el.scrollLeft = scrollLeft;
            $.requestAnimationFrame(render);
        }
        $.requestAnimationFrame(render);
    });
};
$.fn.scrollTop = function (top, duration, easing, callback) {
    if (arguments.length === 3 && typeof easing === 'function') {
        callback = easing;
        easing = undefined;
    }
    var dom = this;
    if (typeof top === 'undefined') {
        if (dom.length > 0) return dom[0].scrollTop;
        else return null;
    }
    return dom.scrollTo(undefined, top, duration, easing, callback);
};
$.fn.scrollLeft = function (left, duration, easing, callback) {
    if (arguments.length === 3 && typeof easing === 'function') {
        callback = easing;
        easing = undefined;
    }
    var dom = this;
    if (typeof left === 'undefined') {
        if (dom.length > 0) return dom[0].scrollLeft;
        else return null;
    }
    return dom.scrollTo(left, undefined, duration, easing, callback);
};<commit_msg>获取url参数问题的修改<commit_after>// DOM Library Utilites
$.parseUrlQuery = function (url) {
   var url = url || location.href;
    var query = {}, i, params, param;

    if(typeof url === 'string' && url.length)  {
        url = (url.indexOf('#') > -1) ? url.split('#')[0] : url;
        if(url.indexOf('?') > -1) url = url.split('?')[1];
        else return query;

        params = url.split('&');
        for(i = 0; i < params.length; i ++) {
            param = params[i].split('=');
            query[param[0]] = param[1];
        }
    }
    return query;
};
$.isArray = function (arr) {
    if (Object.prototype.toString.apply(arr) === '[object Array]') return true;
    else return false;
};
$.each = function (obj, callback) {
    if (typeof obj !== 'object') return;
    if (!callback) return;
    var i, prop;
    if ($.isArray(obj) || obj instanceof Dom7) {
        // Array
        for (i = 0; i < obj.length; i++) {
            callback(i, obj[i]);
        }
    }
    else {
        // Object
        for (prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                callback(prop, obj[prop]);
            }
        }
    }
};
$.unique = function (arr) {
    var unique = [];
    for (var i = 0; i < arr.length; i++) {
        if (unique.indexOf(arr[i]) === -1) unique.push(arr[i]);
    }
    return unique;
};
$.serializeObject = $.param = function (obj, parents) {
    if (typeof obj === 'string') return obj;
    var resultArray = [];
    var separator = '&';
    parents = parents || [];
    var newParents;
    function var_name(name) {
        if (parents.length > 0) {
            var _parents = '';
            for (var j = 0; j < parents.length; j++) {
                if (j === 0) _parents += parents[j];
                else _parents += '[' + encodeURIComponent(parents[j]) + ']';
            }
            return _parents + '[' + encodeURIComponent(name) + ']';
        }
        else {
            return encodeURIComponent(name);
        }
    }
    function var_value(value) {
        return encodeURIComponent(value);
    }
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            var toPush;
            if ($.isArray(obj[prop])) {
                toPush = [];
                for (var i = 0; i < obj[prop].length; i ++) {
                    if (!$.isArray(obj[prop][i]) && typeof obj[prop][i] === 'object') {
                        newParents = parents.slice();
                        newParents.push(prop);
                        newParents.push(i + '');
                        toPush.push($.serializeObject(obj[prop][i], newParents));
                    }
                    else {
                        toPush.push(var_name(prop) + '[]=' + var_value(obj[prop][i]));
                    }

                }
                if (toPush.length > 0) resultArray.push(toPush.join(separator));
            }
            else if (typeof obj[prop] === 'object') {
                // Object, convert to named array
                newParents = parents.slice();
                newParents.push(prop);
                toPush = $.serializeObject(obj[prop], newParents);
                if (toPush !== '') resultArray.push(toPush);
            }
            else if (typeof obj[prop] !== 'undefined' && obj[prop] !== '') {
                // Should be string or plain value
                resultArray.push(var_name(prop) + '=' + var_value(obj[prop]));
            }
        }
    }
    return resultArray.join(separator);
};
$.toCamelCase = function (string) {
    return string.toLowerCase().replace(/-(.)/g, function(match, group1) {
        return group1.toUpperCase();
    });
};
$.dataset = function (el) {
    return $(el).dataset();
};
$.getTranslate = function (el, axis) {
    var matrix, curTransform, curStyle, transformMatrix;

    // automatic axis detection
    if (typeof axis === 'undefined') {
        axis = 'x';
    }

    curStyle = window.getComputedStyle(el, null);
    if (window.WebKitCSSMatrix) {
        curTransform = curStyle.transform || curStyle.webkitTransform;
        if (curTransform.split(',').length > 6) {
            curTransform = curTransform.split(', ').map(function(a){
                return a.replace(',','.');
            }).join(', ');
        }
        // Some old versions of Webkit choke when 'none' is passed; pass
        // empty string instead in this case
        transformMatrix = new WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
    }
    else {
        transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform  || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
        matrix = transformMatrix.toString().split(',');
    }

    if (axis === 'x') {
        //Latest Chrome and webkits Fix
        if (window.WebKitCSSMatrix)
            curTransform = transformMatrix.m41;
        //Crazy IE10 Matrix
        else if (matrix.length === 16)
            curTransform = parseFloat(matrix[12]);
        //Normal Browsers
        else
            curTransform = parseFloat(matrix[4]);
    }
    if (axis === 'y') {
        //Latest Chrome and webkits Fix
        if (window.WebKitCSSMatrix)
            curTransform = transformMatrix.m42;
        //Crazy IE10 Matrix
        else if (matrix.length === 16)
            curTransform = parseFloat(matrix[13]);
        //Normal Browsers
        else
            curTransform = parseFloat(matrix[5]);
    }

    return curTransform || 0;
};

$.requestAnimationFrame = function (callback) {
    if (window.requestAnimationFrame) return window.requestAnimationFrame(callback);
    else if (window.webkitRequestAnimationFrame) return window.webkitRequestAnimationFrame(callback);
    else if (window.mozRequestAnimationFrame) return window.mozRequestAnimationFrame(callback);
    else {
        return window.setTimeout(callback, 1000 / 60);
    }
};
$.cancelAnimationFrame = function (id) {
    if (window.cancelAnimationFrame) return window.cancelAnimationFrame(id);
    else if (window.webkitCancelAnimationFrame) return window.webkitCancelAnimationFrame(id);
    else if (window.mozCancelAnimationFrame) return window.mozCancelAnimationFrame(id);
    else {
        return window.clearTimeout(id);
    }
};
$.supportTouch = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);

// Link to prototype
$.fn = Dom7.prototype;

// Plugins
$.fn.scrollTo = function (left, top, duration, easing, callback) {
    if (arguments.length === 4 && typeof easing === 'function') {
        callback = easing;
        easing = undefined;
    }
    return this.each(function () {
        var el = this;
        var currentTop, currentLeft, maxTop, maxLeft, newTop, newLeft, scrollTop, scrollLeft;
        var animateTop = top > 0 || top === 0;
        var animateLeft = left > 0 || left === 0;
        if (typeof easing === 'undefined') {
            easing = 'swing';
        }
        if (animateTop) {
            currentTop = el.scrollTop;
            if (!duration) {
                el.scrollTop = top;
            }
        }
        if (animateLeft) {
            currentLeft = el.scrollLeft;
            if (!duration) {
                el.scrollLeft = left;
            }
        }
        if (!duration) return;
        if (animateTop) {
            maxTop = el.scrollHeight - el.offsetHeight;
            newTop = Math.max(Math.min(top, maxTop), 0);
        }
        if (animateLeft) {
            maxLeft = el.scrollWidth - el.offsetWidth;
            newLeft = Math.max(Math.min(left, maxLeft), 0);
        }
        var startTime = null;
        if (animateTop && newTop === currentTop) animateTop = false;
        if (animateLeft && newLeft === currentLeft) animateLeft = false;
        function render(time) {
            if (time === undefined) {
                time = new Date().getTime();
            }
            if (startTime === null) {
                startTime = time;
            }
            var doneLeft, doneTop, done;
            var progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
            var easeProgress = easing === 'linear' ? progress : (0.5 - Math.cos( progress * Math.PI ) / 2);
            if (animateTop) scrollTop = currentTop + (easeProgress * (newTop - currentTop));
            if (animateLeft) scrollLeft = currentLeft + (easeProgress * (newLeft - currentLeft));
            if (animateTop && newTop > currentTop && scrollTop >= newTop)  {
                el.scrollTop = newTop;
                done = true;
            }
            if (animateTop && newTop < currentTop && scrollTop <= newTop)  {
                el.scrollTop = newTop;
                done = true;
            }

            if (animateLeft && newLeft > currentLeft && scrollLeft >= newLeft)  {
                el.scrollLeft = newLeft;
                done = true;
            }
            if (animateLeft && newLeft < currentLeft && scrollLeft <= newLeft)  {
                el.scrollLeft = newLeft;
                done = true;
            }

            if (done) {
                if (callback) callback();
                return;
            }
            if (animateTop) el.scrollTop = scrollTop;
            if (animateLeft) el.scrollLeft = scrollLeft;
            $.requestAnimationFrame(render);
        }
        $.requestAnimationFrame(render);
    });
};
$.fn.scrollTop = function (top, duration, easing, callback) {
    if (arguments.length === 3 && typeof easing === 'function') {
        callback = easing;
        easing = undefined;
    }
    var dom = this;
    if (typeof top === 'undefined') {
        if (dom.length > 0) return dom[0].scrollTop;
        else return null;
    }
    return dom.scrollTo(undefined, top, duration, easing, callback);
};
$.fn.scrollLeft = function (left, duration, easing, callback) {
    if (arguments.length === 3 && typeof easing === 'function') {
        callback = easing;
        easing = undefined;
    }
    var dom = this;
    if (typeof left === 'undefined') {
        if (dom.length > 0) return dom[0].scrollLeft;
        else return null;
    }
    return dom.scrollTo(left, undefined, duration, easing, callback);
};<|endoftext|>


<commit_before>import component from 'kompo';
const {construct} = component;

import {addClasses, create} from 'kompo-util';

export default construct('a', function({
    defaultClass,
    classes,
    checked,
    callback,
    label
}) {
    this.href = '#';
    this.classList.add(defaultClass);
    addClasses(this, classes);

    const props = this.kompo.props;

    this.textContent = label;

    setCheck(this, checked);

    this.addEventListener('click', e => {
        e.preventDefault();
        toggle(props, this);
        if (callback) callback(e);
    });
}, {
    defaultClass: 'o-Check',
    classes: [],
    checked: false,
    checkedClass: 'o-Check--checked',
    callback: undefined,
    label: ''
});

function toggle(props, el) {
    if (props.checked) {
        el.classList.remove(props.checkedClass);
        props.checked = false;
    } else {
        el.classList.add(props.checkedClass);
        props.checked = true;
    }
}

export function setCheck(check, b) {
    const props = check.kompo.props;

    if (b === true) {
        check.classList.add(props.checkedClass);
        props.checked = true;
    } else {
        check.classList.remove(props.checkedClass);
        props.checked = false;
    }

}

export function isChecked(check) {
    return check.kompo.props.checked;
}
<commit_msg>Added checked param to check callback<commit_after>import component from 'kompo';
const {construct} = component;

import {addClasses, create} from 'kompo-util';

export default construct('a', function({
    defaultClass,
    classes,
    checked,
    callback,
    label
}) {
    this.href = '#';
    this.classList.add(defaultClass);
    addClasses(this, classes);

    const props = this.kompo.props;

    this.textContent = label;

    setCheck(this, checked);

    this.addEventListener('click', e => {
        e.preventDefault();
        toggle(props, this);
        if (callback) callback(e, props.checked);
    });
}, {
    defaultClass: 'o-Check',
    classes: [],
    checked: false,
    checkedClass: 'o-Check--checked',
    callback: undefined,
    label: ''
});

function toggle(props, el) {
    if (props.checked) {
        el.classList.remove(props.checkedClass);
        props.checked = false;
    } else {
        el.classList.add(props.checkedClass);
        props.checked = true;
    }
}

export function setCheck(check, b) {
    const props = check.kompo.props;

    if (b === true) {
        check.classList.add(props.checkedClass);
        props.checked = true;
    } else {
        check.classList.remove(props.checkedClass);
        props.checked = false;
    }

}

export function isChecked(check) {
    return check.kompo.props.checked;
}
<|endoftext|>


<commit_before>{
	"Menu principal": "Main menu",
	"Emprunter": "Borrow",
	"Emprunter un livre": "Borrow a book",
	"Retourner": "Return",
	"Retourner un livre": "Return a book",
	"Rechercher": "Search",
	"Rechercher un livre": "Search a book",
	"Valider [Entrée]": "Validate [Enter]",
	"OK": "OK",
	"Annuler [Echap]": "Cancel [Esc]",
	"Annuler": "Cancel",
	"Gérer les livres (inventaire) et les lecteurs (utilisateurs)": "Manage books (inventory) and readers (users)",
	"Basé sur ": "Based on ",
	"Début": "Begin",
	"Fin": "End",
	"Livre": "Book",
	"Lecteur": "Reader",
	"Emprunts": "Borrows",
	"Nouvel emprunt": "New borrowing",
	"Taper l'identifiant du livre à emprunter (ISBN ou Titre)": "Type requested book id (ISBN or Title)",
	"Taper le nom ou la classe du lecteur": "Type reader name or classroom",
	"Ajouter un emprunt (sortir un livre)": "Add a borrowing (borrow a book)",
	"Rendre un livre (retour en bibliothèque)": "Return a book (put back in library)",
	"Rechercher un emprunt": "Search borrowing",
	"Lister": "List",
	"Liste des emprunts (livres sortis)": "List borrowings (books out)",
	"Retour": "Return",
	"Livre et emprunteur (ISBN, Titre, Nom, Classe)": "Book and reader (ISBN, Title, Name, Classroom)",
	"Numéro ISBN": "ISBN Number",
	"Titre": "Title",
	"Auteur": "Author",
	"Description (Synopsis)": "Description (Synopsis)",
	"Titre, Auteur, Description": "Title, Author, Description",
	"Gérer": "Manage",
	"Livres": "Books",
	"Ajouter": "Add",
	"Ajouter un livre (exemplaire)": "Add a book (new copy)",
	"Liste des livres (exemplaires)": "Book list (copies)",
	"Gérer les livres (inventaire)": "Manage books (inventory)",
	"Lecteurs": "Readers",
	"Gérer les lecteurs (emprunteurs)": "Manage readers (borrowers)",
	"Liste": "List",
	"Liste des livres": "Books List",
	"ISBN": "ISBN",
	"Description": "Description",
	"Modifier": "Modify",
	"Supprimer": "Remove",
	"Nouveau": "New",
	"Nom": "Name",
	"Téléphone": "Phone",
	"Commentaire": "Comment",
	"Nom, Compte, Commentaires": "Name, Classroom, Comment",
	"Ajouter un lecteur (emprunteur)": "Add a reader(borrower)",
	"Liste des lecteurs (emprunteurs)": "List readers (borrowers)",
	"Rechercher un lecteur (emprunteur)": "Search a reader (borrower)",
	"Fiche": "File",
	"Veuillez remplir le formulaire": "Please fill in form",
	"Recherche": "Search",
	"Liste des lecteurs": "Readers List",
	"Aucun lecteur dans la liste.": "No reader found.",
	"Aucun livre dans l'inventaire.": "No book found.",
	"Aucun emprunt en cours.": "No borrowing found.",
	"Veuillez saisir le livre et le lecteur": "Please enter book and borrower information",
	"Série": "Serie",
	"Invalid value : REQUIRED field \"%s\" can't store value %s": "Invalid value : REQUIRED field \"%s\" can't store value %s",
	"Gérer les emprunts": "Borrowing Management",
	"Prénom": "First Name",
	"Catégorie": "Classroom",
	"Classification": "Classification",
	"Ajouter une nouvelle fiche": "Add a new record",
	"Modifier la fiche #%s": "Modify record #%s",
	"Supprimer la fiche #%s": "Delete record #%s",
	"Exemplaires : %d": "Copies : %d",
	"Ex.": "Copies"
}
<commit_msg>i18n support<commit_after>{
	"Menu principal": "Main menu",
	"Emprunter": "Borrow",
	"Emprunter un livre": "Borrow a book",
	"Retourner": "Return",
	"Retourner un livre": "Return a book",
	"Rechercher": "Search",
	"Rechercher un livre": "Search a book",
	"Valider [Entrée]": "Validate [Enter]",
	"OK": "OK",
	"Annuler [Echap]": "Cancel [Esc]",
	"Annuler": "Cancel",
	"Gérer les livres (inventaire) et les lecteurs (utilisateurs)": "Manage books (inventory) and readers (users)",
	"Basé sur ": "Based on ",
	"Début": "Begin",
	"Fin": "End",
	"Livre": "Book",
	"Lecteur": "Reader",
	"Emprunts": "Borrows",
	"Nouvel emprunt": "New borrowing",
	"Taper l'identifiant du livre à emprunter (ISBN ou Titre)": "Type requested book id (ISBN or Title)",
	"Taper le nom ou la classe du lecteur": "Type reader name or classroom",
	"Ajouter un emprunt (sortir un livre)": "Add a borrowing (borrow a book)",
	"Rendre un livre (retour en bibliothèque)": "Return a book (put back in library)",
	"Rechercher un emprunt": "Search borrowing",
	"Lister": "List",
	"Liste des emprunts (livres sortis)": "List borrowings (books out)",
	"Retour": "Return",
	"Livre et emprunteur (ISBN, Titre, Nom, Classe)": "Book and reader (ISBN, Title, Name, Classroom)",
	"Numéro ISBN": "ISBN Number",
	"Titre": "Title",
	"Auteur": "Author",
	"Description (Synopsis)": "Description (Synopsis)",
	"Titre, Auteur, Description": "Title, Author, Description",
	"Gérer": "Manage",
	"Livres": "Books",
	"Ajouter": "Add",
	"Ajouter un livre (exemplaire)": "Add a book (new copy)",
	"Liste des livres (exemplaires)": "Book list (copies)",
	"Gérer les livres (inventaire)": "Manage books (inventory)",
	"Lecteurs": "Readers",
	"Gérer les lecteurs (emprunteurs)": "Manage readers (borrowers)",
	"Liste": "List",
	"Liste des livres": "Books List",
	"ISBN": "ISBN",
	"Description": "Description",
	"Modifier": "Modify",
	"Supprimer": "Remove",
	"Nouveau": "New",
	"Nom": "Name",
	"Téléphone": "Phone",
	"Commentaire": "Comment",
	"Nom, Compte, Commentaires": "Name, Classroom, Comment",
	"Ajouter un lecteur (emprunteur)": "Add a reader(borrower)",
	"Liste des lecteurs (emprunteurs)": "List readers (borrowers)",
	"Rechercher un lecteur (emprunteur)": "Search a reader (borrower)",
	"Fiche": "File",
	"Veuillez remplir le formulaire": "Please fill in form",
	"Recherche": "Search",
	"Liste des lecteurs": "Readers List",
	"Aucun lecteur dans la liste.": "No reader found.",
	"Aucun livre dans l'inventaire.": "No book found.",
	"Aucun emprunt en cours.": "No borrowing found.",
	"Veuillez saisir le livre et le lecteur": "Please enter book and borrower information",
	"Série": "Serie",
	"Invalid value : REQUIRED field \"%s\" can't store value %s": "Invalid value : REQUIRED field \"%s\" can't store value %s",
	"Gérer les emprunts": "Borrowing Management",
	"Prénom": "First Name",
	"Catégorie": "Classroom",
	"Classification": "Classification",
	"Ajouter une nouvelle fiche": "Add a new record",
	"Modifier la fiche #%s": "Modify record #%s",
	"Supprimer la fiche #%s": "Delete record #%s",
	"Exemplaires : %d": "Copies : %d",
	"Ex.": "Copies",
	"Livre #": "Book #",
	"Lecteur #": "Reader #"
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies
 */
var path = require('path'),
  mongoose = require('mongoose'),
  Customer = mongoose.model('Customer'),
  errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));

/**
 * Create an customer
 */
exports.create = function (req, res) {
  var customer = new Customer(req.body);
  customer.user = req.user;

  customer.save(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json(customer);
    }
  });
};

/**
 * Show the current customer
 */
exports.read = function (req, res) {
  // convert mongoose document to JSON
  var customer = req.customer ? req.customer.toJSON() : {};

  // Add a custom field to the Customer, for determining if the current User is the "owner".
  // NOTE: This field is NOT persisted to the database, since it doesn't exist in the Customer model.
  customer.isCurrentUserOwner = !!(req.user && customer.user && customer.user._id.toString() === req.user._id.toString());

  res.json(customer);
};

/**
 * Update an customer
 */
exports.update = function (req, res) {
  var customer = req.customer;

  customer.title = req.body.title;
  customer.content = req.body.content;

  customer.save(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json(customer);
    }
  });
};

/**
 * Delete an customer
 */
exports.delete = function (req, res) {
  var customer = req.customer;

  customer.remove(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json(customer);
    }
  });
};

/**
 * List of Customers
 */
exports.list = function (req, res) {
  Customer.find({ 'user[type]': req.user.ObjectId }).sort('-created').populate('user', 'displayName').exec(function (err, customers) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json(customers);
    }
  });
};

/**
 * Customer middleware
 */
exports.customerByID = function (req, res, next, id) {

  if (!mongoose.Types.ObjectId.isValid(id)) {
    return res.status(400).send({
      message: 'Customer is invalid'
    });
  }

  Customer.findById(id).populate('user', 'displayName').exec(function (err, customer) {
    if (err) {
      return next(err);
    } else if (!customer) {
      return res.status(404).send({
        message: 'No customer with that identifier has been found'
      });
    }
    req.customer = customer;
    next();
  });
};
<commit_msg>fix bug - a user can only retrieve the customers he has created<commit_after>'use strict';

/**
 * Module dependencies
 */
var path = require('path'),
  mongoose = require('mongoose'),
  Customer = mongoose.model('Customer'),
  errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));

/**
 * Create an customer
 */
exports.create = function (req, res) {
  var customer = new Customer(req.body);
  customer.user = req.user;

  customer.save(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json(customer);
    }
  });
};

/**
 * Show the current customer
 */
exports.read = function (req, res) {
  // convert mongoose document to JSON
  var customer = req.customer ? req.customer.toJSON() : {};

  // Add a custom field to the Customer, for determining if the current User is the "owner".
  // NOTE: This field is NOT persisted to the database, since it doesn't exist in the Customer model.
  customer.isCurrentUserOwner = !!(req.user && customer.user && customer.user._id.toString() === req.user._id.toString());

  res.json(customer);
};

/**
 * Update an customer
 */
exports.update = function (req, res) {
  var customer = req.customer;

  customer.title = req.body.title;
  customer.content = req.body.content;

  customer.save(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json(customer);
    }
  });
};

/**
 * Delete an customer
 */
exports.delete = function (req, res) {
  var customer = req.customer;

  customer.remove(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json(customer);
    }
  });
};

/**
 * List of Customers
 */
exports.list = function (req, res) {
  Customer.find({ 'user': req.user._id }).sort('-created').populate('user', 'displayName').exec(function (err, customers) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.json(customers);
    }
  });
};

/**
 * Customer middleware
 */
exports.customerByID = function (req, res, next, id) {

  if (!mongoose.Types.ObjectId.isValid(id)) {
    return res.status(400).send({
      message: 'Customer is invalid'
    });
  }

  Customer.findById(id).populate('user', 'displayName').exec(function (err, customer) {
    if (err) {
      return next(err);
    } else if (!customer) {
      return res.status(404).send({
        message: 'No customer with that identifier has been found'
      });
    }
    req.customer = customer;
    next();
  });
};
<|endoftext|>


<commit_before>Ext.namespace('Vps.Auto');
Vps.Auto.SyncTreePanel = Ext.extend(Vps.Binding.AbstractPanel, {

    layout: 'fit',

    initComponent : function()
    {
        if (this.autoLoad !== false) {
            this.autoLoad = true;
        } else {
            delete this.autoLoad;
        }

        this.addEvents(
            'selectionchange',
            'editaction',
            'addaction'
        );
        this.actions['delete'] = new Ext.Action({
            text    : trlVps('Delete'),
            handler : this.onDelete,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.add = new Ext.Action({
            text    : trlVps('Add'),
            handler : this.onAdd,
            cls     : 'x-btn-text-icon',
            scope   : this
        });
        this.actions.edit = new Ext.Action({
            text    : trlVps('Edit'),
            handler : this.onEdit,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.invisible = new Ext.Action({
            text    : trlVps('Toggle Visibility'),
            handler : this.onVisible,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.reload = new Ext.Action({
            text    : '',
            handler : function () { this.tree.getRootNode().reload(); },
            icon    : '/assets/silkicons/arrow_rotate_clockwise.png',
            cls     : 'x-btn-icon',
            tooltip : trlVps('Reload'),
            scope   : this
        });

        Vps.Auto.SyncTreePanel.superclass.initComponent.call(this);
    },
    doAutoLoad : function()
    {
        //autoLoad kann in der zwischenzeit abgeschaltet werden, zB wenn
        //wir in einem Binding sind
        if (!this.autoLoad) return;
        this.loadMeta();
    },

    loadMeta: function()
    {
        Ext.Ajax.request({
            mask: true,
            url: this.controllerUrl + '/json-meta',
            params: this.baseParams,
            success: this.onMetaChange,
            scope: this
        });
    },

    onMetaChange: function(response, options, meta) {
        this.icons = meta.icons;
        for (var i in this.icons) {
            if (i in this.actions) {
                this.actions[i].initialConfig.icon = this.icons[i];
            }
        }

        // Toolbar
        if (meta.buttons.each == undefined) { // Abfrage nötig, falls keine Buttons geliefert
            var tbar = [];
            for (var button in meta.buttons) {
                tbar.add(this.getAction(button));
            }
        }

        // Tree
        var baseParams = this.baseParams != undefined ? this.baseParams : {};
        if (this.openedId != undefined) { baseParams.openedId = this.openedId; }
        this.tree = new Ext.tree.TreePanel({
            border      : false,
//            animate     : true,
            loader      : new Ext.tree.TreeLoader({
                baseParams  : baseParams,
                dataUrl     : this.controllerUrl + '/json-data'
            }),
            enableDD    : meta.enableDD,
            autoScroll: true,
            rootVisible : meta.rootVisible,
            tbar        : tbar,
            dropConfig  : meta.dropConfig
        });

        this.tree.setRootNode(
            new Ext.tree.AsyncTreeNode({
                text: meta.rootText,
                id: '0',
                allowDrag: false
            })
        );

        this.tree.getSelectionModel().on('selectionchange', this.onSelectionchange, this);
        this.tree.getSelectionModel().on('beforeselect', function(selModel, newNode, oldNode) {
            return this.fireEvent('beforeselectionchange', newNode.attributes.id);
        }, this);
        this.tree.on('beforenodedrop', this.onMove, this);
        this.tree.on('collapsenode', this.onCollapseNode, this);
        this.tree.on('expandnode', this.onExpandNode, this);

        this.tree.on('load', function(node) {
            if (this.openedId == node.id) {
                node.select();
            }
            return true;
        }, this);

        this.relayEvents(this.tree, ['click', 'dblclick']);

        this.add(this.tree);
        this.doLayout();

        this.tree.getRootNode().expand();
        if (meta.rootVisible) {
            this.tree.getRootNode().ui.iconNode.style.backgroundImage = 'url(' + meta.icons.root + ')';
            this.tree.getRootNode().select();
        }

        if (!this.editDialog && meta.editDialog) {
            this.editDialog = meta.editDialog;
        }
        if (this.editDialog && !(this.editDialog instanceof Vps.Auto.Form.Window)) {
            this.editDialog = new Vps.Auto.Form.Window(meta.editDialog);
        }
        if (this.editDialog) {
            this.editDialog.on('datachange', function(o) {
                if (o.data.addedId != undefined) {
                    id = o.data.addedId;
                } else {
                    id = this.tree.getSelectionModel().getSelectedNode().id;
                }
                this.onSave(id);
            }, this);
            this.tree.on('dblclick', function(grid, rowIndex) {
                this.onEdit();
            }, this);
            if (this.editDialog.applyBaseParams) {
                this.editDialog.applyBaseParams(this.getBaseParams());
            }
        }

        this.fireEvent('loaded', this.tree);
    },

    onEdit : function (o, e) {
        var node = this.tree.getSelectionModel().getSelectedNode();
        if (!node.id) return;
        if (this.editDialog != undefined) {
            this.editDialog.showEdit(node.id);
        } else {
            this.fireEvent('editaction', node);
        }
    },

    onAdd: function (o, e) {
        if (this.editDialog != undefined) {
            this.editDialog.getAutoForm().applyBaseParams({
                parent_id: this.getSelectedId()
            });
            this.editDialog.showAdd();
        } else {
            this.fireEvent('addaction', this.tree.getSelectionModel().getSelectedNode());
        }
    },

    onSave : function (id)
    {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-node-data',
            params: Ext.apply({node:id}, this.getBaseParams()),
            success: function(response, options, result) {
                this.onSaved(result.data);
            },
            scope: this
        })
    },

    onSelectionchange: function (selModel, node) {
        if (node && node.id != 0) {
            this.getAction('edit').enable();
            this.getAction('invisible').enable();
            this.getAction('delete').enable();
        } else {
            this.getAction('edit').disable();
            this.getAction('invisible').disable();
            this.getAction('delete').disable();
        }
        this.fireEvent('selectionchange', node);
    },

    onDelete: function (o, e) {
        Ext.MessageBox.confirm(trlVps('Delete'), trlVps('Do you really want to delete this entry:\n\n"') + this.tree.getSelectionModel().getSelectedNode().text + '"',
            function  (button) {
                if (button == 'yes') {
                    Ext.Ajax.request({
                        url: this.controllerUrl + '/json-delete',
                        params: Ext.apply({id:this.getSelectedId()}, this.getBaseParams()),
                        success: function(response, options, result) {
                            this.onDeleted(result);
                        },
                        scope: this
                    });
                }
            },
            this
        );
    },

    onMove : function(dropEvent){
        var params = this.getBaseParams()
        params.source = dropEvent.dropNode.id;
        params.target = dropEvent.target.id;
        params.point = dropEvent.point;
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-move',
            params: params,
            success: function(response, options, result) {
                var parent = this.tree.getNodeById(result.parent);
                var node = this.tree.getNodeById(result.node);
                var before = this.tree.getNodeById(result.before);
                parent.insertBefore(node, before);
                parent.expand();
            },
            failure: function(r) {
                this.tree.getRootNode().reload();
            },
            scope: this
        });
        dropEvent.dropStatus = true;
        dropEvent.cancel = true;
        return true;
    },

    onCollapseNode : function(node) {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-collapse',
            params: Ext.apply({id:node.id}, this.getBaseParams())
        });
    },

    onExpandNode : function(node) {
        if (node.attributes.children && node.attributes.children.length > 0) {
            Ext.Ajax.request({
                url: this.controllerUrl + '/json-expand',
                params: Ext.apply({id:node.id}, this.getBaseParams())
            });
        }
    },

    onVisible : function (o, e) {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-visible',
            params: Ext.apply({id:this.getSelectedId()}, this.getBaseParams()),
            success: function(response, options, result) {
                node = this.tree.getNodeById(result.id);
                node.attributes.visible = result.visible;
                this.setVisible(node);
            },
            scope: this
        })
    },

    setVisible : function (node) {
        if (node.attributes.visible) {
            node.ui.iconNode.style.backgroundImage = 'url(' + this.icons['default'] + ')';
        } else {
            node.ui.iconNode.style.backgroundImage = 'url(' + this.icons['invisible'] + ')';
        }
    },

    getTree : function() {
        return this.tree;
    },
    getSelectionModel : function() {
        if (!this.getTree()) return null;
        return this.getTree().getSelectionModel();
    },
    getSelectedNode : function() {
        if (!this.getSelectionModel()) return null;
        return this.getSelectionModel().getSelectedNode();
    },

    //für AbstractPanel
    getSelectedId: function() {
        var s = this.getSelectedNode();
        if (s) return s.id;
        return null;
    },

    //für AbstractPanel
    selectId: function(id) {
        if (id) {
            if (this.getTree()) {
                var n = this.getTree().getNodeById(id);
                if (n) {
                    n.select();
                }
            } else {
                this.openedId = id;
            }
        } else {
            var m = this.getSelectionModel();
            if (m) m.clearSelections();
        }
    },

    onSaved : function (response)
    {
        this.tree.getRootNode().reload();
    },

    onDeleted: function (response) {
        this.tree.getRootNode().reload();
    },

    setBaseParams : function(baseParams) {
        Vps.Auto.SyncTreePanel.superclass.setBaseParams.apply(this, arguments);
        if (this.editDialog && this.editDialog.setBaseParams) {
            this.editDialog.setBaseParams(baseParams);
        }
    },
    applyBaseParams : function(baseParams) {
        Vps.Auto.SyncTreePanel.superclass.applyBaseParams.apply(this, arguments);
        if (this.editDialog && this.editDialog.applyBaseParams) {
            this.editDialog.applyBaseParams(baseParams);
        }
    }

});
Ext.reg('vps.autotreesync', Vps.Auto.SyncTreePanel);
<commit_msg>JS-Bugfix AutoTree bei Verschieben unter Root<commit_after>Ext.namespace('Vps.Auto');
Vps.Auto.SyncTreePanel = Ext.extend(Vps.Binding.AbstractPanel, {

    layout: 'fit',

    initComponent : function()
    {
        if (this.autoLoad !== false) {
            this.autoLoad = true;
        } else {
            delete this.autoLoad;
        }

        this.addEvents(
            'selectionchange',
            'editaction',
            'addaction'
        );
        this.actions['delete'] = new Ext.Action({
            text    : trlVps('Delete'),
            handler : this.onDelete,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.add = new Ext.Action({
            text    : trlVps('Add'),
            handler : this.onAdd,
            cls     : 'x-btn-text-icon',
            scope   : this
        });
        this.actions.edit = new Ext.Action({
            text    : trlVps('Edit'),
            handler : this.onEdit,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.invisible = new Ext.Action({
            text    : trlVps('Toggle Visibility'),
            handler : this.onVisible,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.reload = new Ext.Action({
            text    : '',
            handler : function () { this.tree.getRootNode().reload(); },
            icon    : '/assets/silkicons/arrow_rotate_clockwise.png',
            cls     : 'x-btn-icon',
            tooltip : trlVps('Reload'),
            scope   : this
        });

        Vps.Auto.SyncTreePanel.superclass.initComponent.call(this);
    },
    doAutoLoad : function()
    {
        //autoLoad kann in der zwischenzeit abgeschaltet werden, zB wenn
        //wir in einem Binding sind
        if (!this.autoLoad) return;
        this.loadMeta();
    },

    loadMeta: function()
    {
        Ext.Ajax.request({
            mask: true,
            url: this.controllerUrl + '/json-meta',
            params: this.baseParams,
            success: this.onMetaChange,
            scope: this
        });
    },

    onMetaChange: function(response, options, meta) {
        this.icons = meta.icons;
        for (var i in this.icons) {
            if (i in this.actions) {
                this.actions[i].initialConfig.icon = this.icons[i];
            }
        }

        // Toolbar
        if (meta.buttons.each == undefined) { // Abfrage nötig, falls keine Buttons geliefert
            var tbar = [];
            for (var button in meta.buttons) {
                tbar.add(this.getAction(button));
            }
        }

        // Tree
        var baseParams = this.baseParams != undefined ? this.baseParams : {};
        if (this.openedId != undefined) { baseParams.openedId = this.openedId; }
        this.tree = new Ext.tree.TreePanel({
            border      : false,
//            animate     : true,
            loader      : new Ext.tree.TreeLoader({
                baseParams  : baseParams,
                dataUrl     : this.controllerUrl + '/json-data'
            }),
            enableDD    : meta.enableDD,
            autoScroll: true,
            rootVisible : meta.rootVisible,
            tbar        : tbar,
            dropConfig  : meta.dropConfig
        });

        this.tree.setRootNode(
            new Ext.tree.AsyncTreeNode({
                text: meta.rootText,
                id: '0',
                allowDrag: false
            })
        );

        this.tree.getSelectionModel().on('selectionchange', this.onSelectionchange, this);
        this.tree.getSelectionModel().on('beforeselect', function(selModel, newNode, oldNode) {
            return this.fireEvent('beforeselectionchange', newNode.attributes.id);
        }, this);
        this.tree.on('beforenodedrop', this.onMove, this);
        this.tree.on('collapsenode', this.onCollapseNode, this);
        this.tree.on('expandnode', this.onExpandNode, this);

        this.tree.on('load', function(node) {
            if (this.openedId == node.id) {
                node.select();
            }
            return true;
        }, this);

        this.relayEvents(this.tree, ['click', 'dblclick']);

        this.add(this.tree);
        this.doLayout();

        this.tree.getRootNode().expand();
        if (meta.rootVisible) {
            this.tree.getRootNode().ui.iconNode.style.backgroundImage = 'url(' + meta.icons.root + ')';
            this.tree.getRootNode().select();
        }

        if (!this.editDialog && meta.editDialog) {
            this.editDialog = meta.editDialog;
        }
        if (this.editDialog && !(this.editDialog instanceof Vps.Auto.Form.Window)) {
            this.editDialog = new Vps.Auto.Form.Window(meta.editDialog);
        }
        if (this.editDialog) {
            this.editDialog.on('datachange', function(o) {
                if (o.data.addedId != undefined) {
                    id = o.data.addedId;
                } else {
                    id = this.tree.getSelectionModel().getSelectedNode().id;
                }
                this.onSave(id);
            }, this);
            this.tree.on('dblclick', function(grid, rowIndex) {
                this.onEdit();
            }, this);
            if (this.editDialog.applyBaseParams) {
                this.editDialog.applyBaseParams(this.getBaseParams());
            }
        }

        this.fireEvent('loaded', this.tree);
    },

    onEdit : function (o, e) {
        var node = this.tree.getSelectionModel().getSelectedNode();
        if (!node.id) return;
        if (this.editDialog != undefined) {
            this.editDialog.showEdit(node.id);
        } else {
            this.fireEvent('editaction', node);
        }
    },

    onAdd: function (o, e) {
        if (this.editDialog != undefined) {
            this.editDialog.getAutoForm().applyBaseParams({
                parent_id: this.getSelectedId()
            });
            this.editDialog.showAdd();
        } else {
            this.fireEvent('addaction', this.tree.getSelectionModel().getSelectedNode());
        }
    },

    onSave : function (id)
    {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-node-data',
            params: Ext.apply({node:id}, this.getBaseParams()),
            success: function(response, options, result) {
                this.onSaved(result.data);
            },
            scope: this
        })
    },

    onSelectionchange: function (selModel, node) {
        if (node && node.id != 0) {
            this.getAction('edit').enable();
            this.getAction('invisible').enable();
            this.getAction('delete').enable();
        } else {
            this.getAction('edit').disable();
            this.getAction('invisible').disable();
            this.getAction('delete').disable();
        }
        this.fireEvent('selectionchange', node);
    },

    onDelete: function (o, e) {
        Ext.MessageBox.confirm(trlVps('Delete'), trlVps('Do you really want to delete this entry:\n\n"') + this.tree.getSelectionModel().getSelectedNode().text + '"',
            function  (button) {
                if (button == 'yes') {
                    Ext.Ajax.request({
                        url: this.controllerUrl + '/json-delete',
                        params: Ext.apply({id:this.getSelectedId()}, this.getBaseParams()),
                        success: function(response, options, result) {
                            this.onDeleted(result);
                        },
                        scope: this
                    });
                }
            },
            this
        );
    },

    onMove : function(dropEvent){
        var params = this.getBaseParams()
        params.source = dropEvent.dropNode.id;
        params.target = dropEvent.target.id;
        params.point = dropEvent.point;
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-move',
            params: params,
            success: function(response, options, result) {
                if (result.parent) {
                    var parent = this.tree.getNodeById(result.parent);
                } else {
                    var parent = this.tree.getRootNode();
                }
                var node = this.tree.getNodeById(result.node);
                var before = this.tree.getNodeById(result.before);
                parent.insertBefore(node, before);
                parent.expand();
            },
            failure: function(r) {
                this.tree.getRootNode().reload();
            },
            scope: this
        });
        dropEvent.dropStatus = true;
        dropEvent.cancel = true;
        return true;
    },

    onCollapseNode : function(node) {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-collapse',
            params: Ext.apply({id:node.id}, this.getBaseParams())
        });
    },

    onExpandNode : function(node) {
        if (node.attributes.children && node.attributes.children.length > 0) {
            Ext.Ajax.request({
                url: this.controllerUrl + '/json-expand',
                params: Ext.apply({id:node.id}, this.getBaseParams())
            });
        }
    },

    onVisible : function (o, e) {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-visible',
            params: Ext.apply({id:this.getSelectedId()}, this.getBaseParams()),
            success: function(response, options, result) {
                node = this.tree.getNodeById(result.id);
                node.attributes.visible = result.visible;
                this.setVisible(node);
            },
            scope: this
        })
    },

    setVisible : function (node) {
        if (node.attributes.visible) {
            node.ui.iconNode.style.backgroundImage = 'url(' + this.icons['default'] + ')';
        } else {
            node.ui.iconNode.style.backgroundImage = 'url(' + this.icons['invisible'] + ')';
        }
    },

    getTree : function() {
        return this.tree;
    },
    getSelectionModel : function() {
        if (!this.getTree()) return null;
        return this.getTree().getSelectionModel();
    },
    getSelectedNode : function() {
        if (!this.getSelectionModel()) return null;
        return this.getSelectionModel().getSelectedNode();
    },

    //für AbstractPanel
    getSelectedId: function() {
        var s = this.getSelectedNode();
        if (s) return s.id;
        return null;
    },

    //für AbstractPanel
    selectId: function(id) {
        if (id) {
            if (this.getTree()) {
                var n = this.getTree().getNodeById(id);
                if (n) {
                    n.select();
                }
            } else {
                this.openedId = id;
            }
        } else {
            var m = this.getSelectionModel();
            if (m) m.clearSelections();
        }
    },

    onSaved : function (response)
    {
        this.tree.getRootNode().reload();
    },

    onDeleted: function (response) {
        this.tree.getRootNode().reload();
    },

    setBaseParams : function(baseParams) {
        Vps.Auto.SyncTreePanel.superclass.setBaseParams.apply(this, arguments);
        if (this.editDialog && this.editDialog.setBaseParams) {
            this.editDialog.setBaseParams(baseParams);
        }
    },
    applyBaseParams : function(baseParams) {
        Vps.Auto.SyncTreePanel.superclass.applyBaseParams.apply(this, arguments);
        if (this.editDialog && this.editDialog.applyBaseParams) {
            this.editDialog.applyBaseParams(baseParams);
        }
    }

});
Ext.reg('vps.autotreesync', Vps.Auto.SyncTreePanel);
<|endoftext|>


<commit_before>/**
 Copyright (c) 2016,2017, Klaus Landsdorf (http://bianco-royal.de/)
 All rights reserved.
 node-red-contrib-modbus - The BSD 3-Clause License

 @author Klaus Landsdorf (Bianco Royal)
 **/
/**
 * Modbus Server node.
 * @module NodeRedModbusServer
 *
 * @param RED
 */
module.exports = function (RED) {
  'use strict'
  let stampit = require('stampit')
  let modbus = require('jsmodbus')
  let mbBasics = require('./modbus-basics')
  let internalDebugLog = require('debug')('node_red_contrib_modbus')

  function ModbusServer (config) {
    RED.nodes.createNode(this, config)
    let bufferFactor = 8

    this.name = config.name
    this.logEnabled = config.logEnabled
    this.serverPort = parseInt(config.serverPort)
    this.responseDelay = parseInt(config.responseDelay)
    this.delayUnit = config.delayUnit

    this.coilsBufferSize = parseInt(config.coilsBufferSize * bufferFactor)
    this.holdingBufferSize = parseInt(config.holdingBufferSize * bufferFactor)
    this.inputBufferSize = parseInt(config.inputBufferSize * bufferFactor)

    let node = this

    node.server = null

    setNodeStatusTo('initialized')

    function verboseWarn (logMessage) {
      if (RED.settings.verbose) {
        node.warn((node.name) ? node.name + ': ' + logMessage : 'Modbus response: ' + logMessage)
      }
    }

    function verboseLog (logMessage) {
      if (RED.settings.verbose) {
        internalDebugLog(logMessage)
      }
    }

    function setNodeStatusTo (statusValue) {
      if (mbBasics.statusLog) {
        verboseLog('server status: ' + statusValue)
      }

      let fillValue = 'red'
      let shapeValue = 'dot'

      switch (statusValue) {
        case 'initialized':
          fillValue = 'green'
          shapeValue = 'ring'
          break

        case 'active':
          fillValue = 'green'
          shapeValue = 'dot'
          break

        default:
          if (!statusValue || statusValue === 'waiting') {
            fillValue = 'blue'
            statusValue = 'waiting ...'
          }
          break
      }

      node.status({fill: fillValue, shape: shapeValue, text: statusValue})
    }

    let modbusLogLevel = 'warn'
    if (RED.settings.verbose) {
      modbusLogLevel = 'debug'
    }

    let ModbusServer = stampit().refs({
      'logLabel': 'ModbusServer',
      'logLevel': modbusLogLevel,
      'logEnabled': node.logEnabled,
      'port': node.serverPort,
      'responseDelay': mbBasics.calc_rateByUnit(node.responseDelay, node.delayUnit),
      'coils': Buffer.alloc(node.coilsBufferSize, 0),
      'holding': Buffer.alloc(node.holdingBufferSize, 0),
      'input': Buffer.alloc(node.inputBufferSize, 0)
    })
      .compose(modbus.server.tcp.complete)
      .init(function () {
        let init = function () {
          this.coils.fill(0)
          this.holding.fill(0)
          this.input.fill(0)
        }.bind(this)
        init()
      })

    verboseLog('starting modbus server')

    try {
      node.server = ModbusServer()
    } catch (err) {
      verboseWarn(err)
      setNodeStatusTo('error')
    }

    if (node.server != null) {
      verboseLog('modbus server started')
      setNodeStatusTo('active')
    } else {
      verboseWarn("modbus server isn't ready")
      setNodeStatusTo('error')
    }

    node.on('input', function (msg) {
      verboseLog('Input:' + msg)

      node.send(buildMessage(msg, node.server.getHolding(), node.server.getCoils(), node.server.getInput()))
    })

    function buildMessage (msg, modbusHolding, modbusCoils, modbusInput) {
      return [
        {type: 'holding', message: msg, payload: modbusHolding},
        {type: 'coils', message: msg, payload: modbusCoils},
        {type: 'input', message: msg, payload: modbusInput}
      ]
    }

    node.on('close', function () {
      setNodeStatusTo('closed')
      node.server.close()
      node.server = null
    })
  }

  RED.nodes.registerType('modbus-server', ModbusServer)
}
<commit_msg><commit_after>/**
 Copyright (c) 2016,2017, Klaus Landsdorf (http://bianco-royal.de/)
 All rights reserved.
 node-red-contrib-modbus - The BSD 3-Clause License

 @author Klaus Landsdorf (Bianco Royal)
 **/
/**
 * Modbus Server node.
 * @module NodeRedModbusServer
 *
 * @param RED
 */
module.exports = function (RED) {
  'use strict'
  let stampit = require('stampit')
  let modbus = require('node-modbus')
  let mbBasics = require('./modbus-basics')
  let internalDebugLog = require('debug')('node_red_contrib_modbus')

  function ModbusServer (config) {
    RED.nodes.createNode(this, config)
    let bufferFactor = 8

    this.name = config.name
    this.logEnabled = config.logEnabled
    this.serverPort = parseInt(config.serverPort)
    this.responseDelay = parseInt(config.responseDelay)
    this.delayUnit = config.delayUnit

    this.coilsBufferSize = parseInt(config.coilsBufferSize * bufferFactor)
    this.holdingBufferSize = parseInt(config.holdingBufferSize * bufferFactor)
    this.inputBufferSize = parseInt(config.inputBufferSize * bufferFactor)

    let node = this

    node.server = null

    setNodeStatusTo('initialized')

    function verboseWarn (logMessage) {
      if (RED.settings.verbose) {
        node.warn((node.name) ? node.name + ': ' + logMessage : 'Modbus response: ' + logMessage)
      }
    }

    function verboseLog (logMessage) {
      if (RED.settings.verbose) {
        internalDebugLog(logMessage)
      }
    }

    function setNodeStatusTo (statusValue) {
      if (mbBasics.statusLog) {
        verboseLog('server status: ' + statusValue)
      }

      let fillValue = 'red'
      let shapeValue = 'dot'

      switch (statusValue) {
        case 'initialized':
          fillValue = 'green'
          shapeValue = 'ring'
          break

        case 'active':
          fillValue = 'green'
          shapeValue = 'dot'
          break

        default:
          if (!statusValue || statusValue === 'waiting') {
            fillValue = 'blue'
            statusValue = 'waiting ...'
          }
          break
      }

      node.status({fill: fillValue, shape: shapeValue, text: statusValue})
    }

    let modbusLogLevel = 'warn'
    if (RED.settings.verbose) {
      modbusLogLevel = 'debug'
    }

    let ModbusServer = stampit().refs({
      'logLabel': 'ModbusServer',
      'logLevel': modbusLogLevel,
      'logEnabled': node.logEnabled,
      'port': node.serverPort,
      'responseDelay': mbBasics.calc_rateByUnit(node.responseDelay, node.delayUnit),
      'coils': Buffer.alloc(node.coilsBufferSize, 0),
      'holding': Buffer.alloc(node.holdingBufferSize, 0),
      'input': Buffer.alloc(node.inputBufferSize, 0)
    })
      .compose(modbus.server.tcp.complete)
      .init(function () {
        let init = function () {
          this.coils.fill(0)
          this.holding.fill(0)
          this.input.fill(0)
        }.bind(this)
        init()
      })

    verboseLog('starting modbus server')

    try {
      node.server = ModbusServer()
    } catch (err) {
      verboseWarn(err)
      setNodeStatusTo('error')
    }

    if (node.server != null) {
      verboseLog('modbus server started')
      setNodeStatusTo('active')
    } else {
      verboseWarn("modbus server isn't ready")
      setNodeStatusTo('error')
    }

    node.on('input', function (msg) {
      verboseLog('Input:' + msg)

      node.send(buildMessage(msg, node.server.getHolding(), node.server.getCoils(), node.server.getInput()))
    })

    function buildMessage (msg, modbusHolding, modbusCoils, modbusInput) {
      return [
        {type: 'holding', message: msg, payload: modbusHolding},
        {type: 'coils', message: msg, payload: modbusCoils},
        {type: 'input', message: msg, payload: modbusInput}
      ]
    }

    node.on('close', function () {
      setNodeStatusTo('closed')
      node.server.close()
      node.server = null
    })
  }

  RED.nodes.registerType('modbus-server', ModbusServer)
}
<|endoftext|>


<commit_before>
;(function( FooFighter ){

'use strict';

function GameAI ( gameState ){
    this.gameState = gameState;
    this.game = gameState.game;
    this.init();
}

var proto = GameAI.prototype;

proto.init = function(){
    this.bindEvents();
};

proto.bindEvents = function(){
    var vent = this.gameState.vent;
    console.log(this);
    vent.on('start', this.start.bind(this));
    vent.on('update', this.checkCollisions.bind(this));
};

proto.start = function(){
    setInterval(this.createAsteroid.bind(this), 1000);
};

proto.createAsteroid = function(){
    var foo = new FooFighter.Asteroid(this.gameState).create();
};

proto.checkCollisions = function(){

};

FooFighter.GameAI = GameAI;

})(FooFighter);
<commit_msg>keep track of asteroids in game state<commit_after>
;(function( FooFighter ){

'use strict';

function GameAI ( gameState ){
    this.gameState = gameState;
    this.game = gameState.game;
    this.init();
}

var proto = GameAI.prototype;

proto.init = function(){
    this.gameState.asteroids = [];
    this.bindEvents();
};

proto.bindEvents = function(){
    var vent = this.gameState.vent;
    console.log(this);
    vent.on('start', this.start.bind(this));
    vent.on('update', this.checkCollisions.bind(this));
};

proto.start = function(){
    setInterval(this.createAsteroid.bind(this), 1000);
};

proto.createAsteroid = function(){
    var asteroids = this.gameState.asteroids;
    asteroids.push(
        new FooFighter.Asteroid(this.gameState).create()
    );
};

proto.checkCollisions = function(){

};

FooFighter.GameAI = GameAI;

})(FooFighter);
<|endoftext|>


<commit_before>'use strict'

const Config = require('../config.json')
const Fetcher = require('./Fetcher')
const GitHubAuth = require('./GitHubAuth')

const REPO_URL_PREFIX = 'https://api.github.com/repos/'

function getTask(data) {
  const repoUrl = data.repository_url
  const repository = repoUrl.slice(REPO_URL_PREFIX.length)
  const repositoryOwner = repository.split('/')[0]
  const type = typeof data.pull_request === 'object' ? 'pull' : 'issue'
  let apiUrl = data.url
  if (type === 'pull') {
    apiUrl = apiUrl.replace(/\/issues\//, '/pulls/')
  }
  return {
    storageKey: `${type}-${data.id}`,
    id: data.id,
    type,
    title: data.title,
    body: data.body,
    state: data.state,
    createdAt: data.created_at,
    updatedAt: data.updated_at,
    closedAt: data.closed_at,
    isPullRequest: type === 'pull',
    repositoryApiUrl: repoUrl,
    url: data.html_url,
    apiUrl,
    number: data.number,
    repository,
    repositoryOwner,
    repositoryOwnerUrl: `https://github.com/${repositoryOwner}`,
    repositoryOwnerAvatar: `https://github.com/${repositoryOwner}.png?size=30`,
    user: data.user.login,
    userUrl: data.user.html_url,
    userAvatar: `https://github.com/${data.user.login}.png?size=16`,
    userType: data.user.type,
  }
}

class GitHub extends Fetcher {
  constructor(token) {
    super()
    this.token = token
  }

  // https://developer.github.com/v3/activity/notifications/#list-your-notifications
  getNotifications(sinceDate) {
    let date = sinceDate
    if (typeof date === 'undefined') {
      date = new Date()
      date.setDate(date.getDate() - 31)
    }
    const dateStr = date.toISOString()
    return this.get(`notifications?since=${encodeURIComponent(dateStr)}`,
                    { fetchAll: true }).then(result => result.json)
  }

  // https://developer.github.com/v3/search/#search-issues
  getTasks(query = Config.searchQuery) {
    const urlPath = `search/issues?q=${encodeURIComponent(query)}`
    return this.getTasksFromUrl(urlPath)
  }

  getTasksFromUrl(urlPath) {
    return this.get(urlPath).then(result => {
      const { json, nextUrl } = result
      return { tasks: json.items.map(d => getTask(d)), nextUrl,
               currentUrl: urlPath }
    })
  }

  // https://developer.github.com/v3/users/#get-the-authenticated-user
  getCurrentUser() {
    return this.get('user').then(result => result.json)
  }

  // https://developer.github.com/v3/activity/notifications/#mark-a-thread-as-read
  markAsRead(url) {
    return this.patch(url, { ignoreBody: true })
  }

  patch(relativeOrAbsoluteUrl, opts) {
    let url = relativeOrAbsoluteUrl
    if (url.indexOf('http') !== 0) {
      url = `${Config.githubApiUrl}/${relativeOrAbsoluteUrl}`
    }
    const options = opts || {}
    options.headers = this.getHeaders()
    return super.patch(url, options)
  }

  getHeaders() {
    if (!this.token) {
      this.token = GitHubAuth.getToken()
    }
    return {
      Accept: 'application/vnd.github.v3+json',
      Authorization: `token ${this.token}`,
    }
  }

  get(path, args = {}) {
    const url = this.getFullUrl(path)
    const opts = { headers: this.getHeaders() }
    return new Promise((resolve, reject) => super.get(url, opts).then(res => {
      const combinedJson = this.combineJson(res.json, args.previousJson)
      const nextUrl = this.getNextUrl(res.headers)
      if (nextUrl && args.fetchAll) {
        return this.get(nextUrl, { previousJson: combinedJson }).
            then(resolve).catch(reject)
      }
      return resolve({ json: combinedJson, nextUrl })
    }).catch(reject))
  }

  combineJson(json1, json2) {
    if (typeof json2 === 'undefined') {
      return json1
    }
    const is1Array = json1.constructor.name === 'Array'
    const is2Array = json2.constructor.name === 'Array'
    if (is1Array && is2Array) {
      return json1.concat(json2)
    }
    return Object.assign({}, json1, json2)
  }

  getFullUrl(relativeOrAbsoluteUrl) {
    if (relativeOrAbsoluteUrl.indexOf('http') !== 0) {
      return `${Config.githubApiUrl}/${relativeOrAbsoluteUrl}`
    }
    return relativeOrAbsoluteUrl
  }

  getNextUrl(headers) {
    const link = headers.get('Link')
    if (!link) {
      return null
    }
    return this.getNextUrlFromLink(link)
  }

  // Sample input:
  // Link: <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=15>; rel="next",
  // <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last",
  // <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=1>; rel="first",
  // <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=13>; rel="prev"
  //
  // Sample output:
  // https://api.github.com/search/code?q=addClass+user%3Amozilla&page=15
  getNextUrlFromLink(link) {
    const urlsAndRels = link.split(',')
    let nextUrl
    urlsAndRels.forEach(str => {
      const urlAndRel = str.trim().split('; ')
      if (urlAndRel[1] === 'rel="next"') {
        const urlInBrackets = urlAndRel[0]
        nextUrl = urlInBrackets.slice(1, urlInBrackets.length - 1)
        return
      }
    })
    return nextUrl
  }
}

module.exports = GitHub
<commit_msg>Limit tasks to 30 per page<commit_after>'use strict'

const Config = require('../config.json')
const Fetcher = require('./Fetcher')
const GitHubAuth = require('./GitHubAuth')

const REPO_URL_PREFIX = 'https://api.github.com/repos/'

function getTask(data) {
  const repoUrl = data.repository_url
  const repository = repoUrl.slice(REPO_URL_PREFIX.length)
  const repositoryOwner = repository.split('/')[0]
  const type = typeof data.pull_request === 'object' ? 'pull' : 'issue'
  let apiUrl = data.url
  if (type === 'pull') {
    apiUrl = apiUrl.replace(/\/issues\//, '/pulls/')
  }
  return {
    storageKey: `${type}-${data.id}`,
    id: data.id,
    type,
    title: data.title,
    body: data.body,
    state: data.state,
    createdAt: data.created_at,
    updatedAt: data.updated_at,
    closedAt: data.closed_at,
    isPullRequest: type === 'pull',
    repositoryApiUrl: repoUrl,
    url: data.html_url,
    apiUrl,
    number: data.number,
    repository,
    repositoryOwner,
    repositoryOwnerUrl: `https://github.com/${repositoryOwner}`,
    repositoryOwnerAvatar: `https://github.com/${repositoryOwner}.png?size=30`,
    user: data.user.login,
    userUrl: data.user.html_url,
    userAvatar: `https://github.com/${data.user.login}.png?size=16`,
    userType: data.user.type,
  }
}

class GitHub extends Fetcher {
  constructor(token) {
    super()
    this.token = token
  }

  // https://developer.github.com/v3/activity/notifications/#list-your-notifications
  getNotifications(sinceDate) {
    let date = sinceDate
    if (typeof date === 'undefined') {
      date = new Date()
      date.setDate(date.getDate() - 31)
    }
    const dateStr = date.toISOString()
    return this.get(`notifications?since=${encodeURIComponent(dateStr)}`,
                    { fetchAll: true }).then(result => result.json)
  }

  // https://developer.github.com/v3/search/#search-issues
  getTasks(query = Config.searchQuery) {
    const params = `?per_page=30&q=${encodeURIComponent(query)}`
    const url = `${Config.githubApiUrl}/search/issues${params}`
    return this.getTasksFromUrl(url)
  }

  getTasksFromUrl(url) {
    return this.get(url).then(result => {
      const { json, nextUrl } = result
      return { tasks: json.items.map(d => getTask(d)), nextUrl,
               currentUrl: url }
    })
  }

  // https://developer.github.com/v3/users/#get-the-authenticated-user
  getCurrentUser() {
    return this.get('user').then(result => result.json)
  }

  // https://developer.github.com/v3/activity/notifications/#mark-a-thread-as-read
  markAsRead(url) {
    return this.patch(url, { ignoreBody: true })
  }

  patch(relativeOrAbsoluteUrl, opts) {
    let url = relativeOrAbsoluteUrl
    if (url.indexOf('http') !== 0) {
      url = `${Config.githubApiUrl}/${relativeOrAbsoluteUrl}`
    }
    const options = opts || {}
    options.headers = this.getHeaders()
    return super.patch(url, options)
  }

  getHeaders() {
    if (!this.token) {
      this.token = GitHubAuth.getToken()
    }
    return {
      Accept: 'application/vnd.github.v3+json',
      Authorization: `token ${this.token}`,
    }
  }

  get(path, args = {}) {
    const url = this.getFullUrl(path)
    const opts = { headers: this.getHeaders() }
    return new Promise((resolve, reject) => super.get(url, opts).then(res => {
      const combinedJson = this.combineJson(res.json, args.previousJson)
      const nextUrl = this.getNextUrl(res.headers)
      if (nextUrl && args.fetchAll) {
        return this.get(nextUrl, { previousJson: combinedJson }).
            then(resolve).catch(reject)
      }
      return resolve({ json: combinedJson, nextUrl })
    }).catch(reject))
  }

  combineJson(json1, json2) {
    if (typeof json2 === 'undefined') {
      return json1
    }
    const is1Array = json1.constructor.name === 'Array'
    const is2Array = json2.constructor.name === 'Array'
    if (is1Array && is2Array) {
      return json1.concat(json2)
    }
    return Object.assign({}, json1, json2)
  }

  getFullUrl(relativeOrAbsoluteUrl) {
    if (relativeOrAbsoluteUrl.indexOf('http') !== 0) {
      return `${Config.githubApiUrl}/${relativeOrAbsoluteUrl}`
    }
    return relativeOrAbsoluteUrl
  }

  getNextUrl(headers) {
    const link = headers.get('Link')
    if (!link) {
      return null
    }
    return this.getNextUrlFromLink(link)
  }

  // Sample input:
  // Link: <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=15>; rel="next",
  // <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last",
  // <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=1>; rel="first",
  // <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=13>; rel="prev"
  //
  // Sample output:
  // https://api.github.com/search/code?q=addClass+user%3Amozilla&page=15
  getNextUrlFromLink(link) {
    const urlsAndRels = link.split(',')
    let nextUrl
    urlsAndRels.forEach(str => {
      const urlAndRel = str.trim().split('; ')
      if (urlAndRel[1] === 'rel="next"') {
        const urlInBrackets = urlAndRel[0]
        nextUrl = urlInBrackets.slice(1, urlInBrackets.length - 1)
        return
      }
    })
    return nextUrl
  }
}

module.exports = GitHub
<|endoftext|>


<commit_before>/**
 * Basic status object, containing null for all properties.
 */
const defaultStatus = {
  issueKey: null,
  link: null,
  origin: null,
  result: null,
  timestamp: null
};

const StatusResult = {
  SUCCESS: 'success',
  FAILURE: 'failure',
  RUNNING: 'running',
  UNKNOWN: 'unknown',
};

module.exports = function(attributes){
  return Object.assign({}, defaultStatus, attributes);
};

module.exports.StatusResult = StatusResult;
<commit_msg>Make status result all caps<commit_after>/**
 * Basic status object, containing null for all properties.
 */
const defaultStatus = {
  issueKey: null,
  link: null,
  origin: null,
  result: null,
  timestamp: null
};

const StatusResult = {
  SUCCESS: 'SUCCESS',
  FAILURE: 'FAILURE',
  RUNNING: 'RUNNING',
  UNKNOWN: 'UNKNOWN',
};

module.exports = function(attributes){
  return Object.assign({}, defaultStatus, attributes);
};

module.exports.StatusResult = StatusResult;
<|endoftext|>