<commit_before>(function(define, undefined) {
    'use strict';
    define([
        'gettext',
        'jquery',
        'underscore',
        'common/js/components/views/tabbed_view',
        'edx-ui-toolkit/js/utils/html-utils',
        'js/student_account/views/account_section_view',
        'text!templates/student_account/account_settings.underscore'
    ], function(gettext, $, _, TabbedView, HtmlUtils, AccountSectionView, accountSettingsTemplate) {
        var AccountSettingsView = TabbedView.extend({

            navLink: '.account-nav-link',
            activeTab: 'aboutTabSections',
            accountSettingsTabs: [
                {
                    name: 'aboutTabSections',
                    id: 'about-tab',
                    label: gettext('Account Information'),
                    class: 'active',
                    tabindex: 0,
                    selected: true,
                    expanded: true
                },
                {
                    name: 'accountsTabSections',
                    id: 'accounts-tab',
                    label: gettext('Linked Accounts'),
                    tabindex: -1,
                    selected: false,
                    expanded: false
            ],
            events: {
                'click .account-nav-link': 'switchTab',
                'click #nicecheck': 'nicecheck',
                'keydown .account-nav-link': 'keydownHandler'
            },

            initialize: function(options) {
                this.options = options;
                _.bindAll(this, 'render', 'switchTab', 'renderFields', 'setActiveTab', 'showLoadingError');
            },

            render: function() {
                var tabName,
                    view = this;
                HtmlUtils.setHtml(this.$el, HtmlUtils.template(accountSettingsTemplate)({
                    accountSettingsTabs: this.accountSettingsTabs
                }));
                _.each(view.accountSettingsTabs, function(tab) {
                    tabName = tab.name;
                    view.renderSection(view.options.tabSections[tabName], tabName, tab.label);
                });
                return this;
            },

            nicecheck: function(e) {
                if(confirm(gettext("Once you have verified your name, you can not cancel it. Do you want to proceed?"))){
                    window.open('', 'popupNICE', 'width=450, height=550, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbar=no');
                    document.form2.target = "popupNICE";
                    document.form2.submit();
                }
            },

            switchTab: function(e) {
                var $currentTab,
                    $accountNavLink = $('.account-nav-link');

                if (e) {
                    e.preventDefault();
                    $currentTab = $(e.target);
                    this.activeTab = $currentTab.data('name');

                    _.each(this.$('.account-settings-tabpanels'), function(tabPanel) {
                        $(tabPanel).addClass('hidden');
                    });

                    $('#' + this.activeTab + '-tabpanel').removeClass('hidden');

                    $accountNavLink.attr('tabindex', -1);
                    $accountNavLink.attr('aria-selected', false);
                    $accountNavLink.attr('aria-expanded', false);

                    $currentTab.attr('tabindex', 0);
                    $currentTab.attr('aria-selected', true);
                    $currentTab.attr('aria-expanded', true);

                    $(this.navLink).removeClass('active');
                    $currentTab.addClass('active');
                }
            },

            setActiveTab: function() {
                this.switchTab();
            },

            renderSection: function(tabSections, tabName, tabLabel) {
                var accountSectionView = new AccountSectionView({
                    tabName: tabName,
                    tabLabel: tabLabel,
                    sections: tabSections,
                    el: '#' + tabName + '-tabpanel'
                });

                accountSectionView.render();
            },

            renderFields: function () {
                var view = this;
                view.$('.ui-loading-indicator').addClass('is-hidden');

                _.each(view.$('.account-settings-section-body'), function (sectionEl, index) {
                    _.each(view.options.tabSections[view.activeTab][index].fields, function (field) {
                        if (field.view.enabled) {
                            $(sectionEl).append(field.view.render().el);
                        }
                    });

                    if(view.$('.account-settings-section-body').size() == 2 && index == 0){
                        var html = "";
                        html += "
";
                        html += "
";
                        html += "        회원탈퇴";
                        html += "        <button class='u-field-link u-field-link-title-password ' id='secession-btn' aria-describedby='u-field-message-help-password'>회원탈퇴하기</button>";
                        html += "
";
                        html += "
";

                        $(sectionEl).append(html);
                    }
                });

                return this;
            },

            showLoadingError: function() {
                this.$('.ui-loading-error').removeClass('is-hidden');
            }
        });

        return AccountSettingsView;
    });
}).call(this, define || RequireJS.define);
<commit_msg>debug account_settings_view.js merge error<commit_after>(function(define, undefined) {
    'use strict';
    define([
        'gettext',
        'jquery',
        'underscore',
        'common/js/components/views/tabbed_view',
        'edx-ui-toolkit/js/utils/html-utils',
        'js/student_account/views/account_section_view',
        'text!templates/student_account/account_settings.underscore'
    ], function(gettext, $, _, TabbedView, HtmlUtils, AccountSectionView, accountSettingsTemplate) {
        var AccountSettingsView = TabbedView.extend({

            navLink: '.account-nav-link',
            activeTab: 'aboutTabSections',
            accountSettingsTabs: [
                {
                    name: 'aboutTabSections',
                    id: 'about-tab',
                    label: gettext('Account Information'),
                    class: 'active',
                    tabindex: 0,
                    selected: true,
                    expanded: true
                },
                {
                    name: 'accountsTabSections',
                    id: 'accounts-tab',
                    label: gettext('Linked Accounts'),
                    tabindex: -1,
                    selected: false,
                    expanded: false
                }
            ],
            events: {
                'click .account-nav-link': 'switchTab',
                'click #nicecheck': 'nicecheck',
                'keydown .account-nav-link': 'keydownHandler'
            },

            initialize: function(options) {
                this.options = options;
                _.bindAll(this, 'render', 'switchTab', 'renderFields', 'setActiveTab', 'showLoadingError');
            },

            render: function() {
                var tabName,
                    view = this;
                HtmlUtils.setHtml(this.$el, HtmlUtils.template(accountSettingsTemplate)({
                    accountSettingsTabs: this.accountSettingsTabs
                }));
                _.each(view.accountSettingsTabs, function(tab) {
                    tabName = tab.name;
                    view.renderSection(view.options.tabSections[tabName], tabName, tab.label);
                });
                return this;
            },

            nicecheck: function(e) {
                if(confirm(gettext("Once you have verified your name, you can not cancel it. Do you want to proceed?"))){
                    window.open('', 'popupNICE', 'width=450, height=550, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbar=no');
                    document.form2.target = "popupNICE";
                    document.form2.submit();
                }
            },

            switchTab: function(e) {
                var $currentTab,
                    $accountNavLink = $('.account-nav-link');

                if (e) {
                    e.preventDefault();
                    $currentTab = $(e.target);
                    this.activeTab = $currentTab.data('name');

                    _.each(this.$('.account-settings-tabpanels'), function(tabPanel) {
                        $(tabPanel).addClass('hidden');
                    });

                    $('#' + this.activeTab + '-tabpanel').removeClass('hidden');

                    $accountNavLink.attr('tabindex', -1);
                    $accountNavLink.attr('aria-selected', false);
                    $accountNavLink.attr('aria-expanded', false);

                    $currentTab.attr('tabindex', 0);
                    $currentTab.attr('aria-selected', true);
                    $currentTab.attr('aria-expanded', true);

                    $(this.navLink).removeClass('active');
                    $currentTab.addClass('active');
                }
            },

            setActiveTab: function() {
                this.switchTab();
            },

            renderSection: function(tabSections, tabName, tabLabel) {
                var accountSectionView = new AccountSectionView({
                    tabName: tabName,
                    tabLabel: tabLabel,
                    sections: tabSections,
                    el: '#' + tabName + '-tabpanel'
                });

                accountSectionView.render();
            },

            renderFields: function () {
                var view = this;
                view.$('.ui-loading-indicator').addClass('is-hidden');

                _.each(view.$('.account-settings-section-body'), function (sectionEl, index) {
                    _.each(view.options.tabSections[view.activeTab][index].fields, function (field) {
                        if (field.view.enabled) {
                            $(sectionEl).append(field.view.render().el);
                        }
                    });

                    if(view.$('.account-settings-section-body').size() == 2 && index == 0){
                        var html = "";
                        html += "
";
                        html += "
";
                        html += "        회원탈퇴";
                        html += "        <button class='u-field-link u-field-link-title-password ' id='secession-btn' aria-describedby='u-field-message-help-password'>회원탈퇴하기</button>";
                        html += "
";
                        html += "
";

                        $(sectionEl).append(html);
                    }
                });

                return this;
            },

            showLoadingError: function() {
                this.$('.ui-loading-error').removeClass('is-hidden');
            }
        });

        return AccountSettingsView;
    });
}).call(this, define || RequireJS.define);
<|endoftext|>


<commit_before>// Globals.
var GM_config = GM_getConfig();

var GM_stringBundle = Components
    .classes["@mozilla.org/intl/stringbundle;1"]
    .getService(Components.interfaces.nsIStringBundleService)
    .createBundle("chrome://greasemonkey/locale/gm-manage.properties");
function GM_string(key) { return GM_stringBundle.GetStringFromName(key); }

(function() {
// Override some built-in functions, with a closure reference to the original
// function, to either handle or delegate the call.
var _origShowView = showView;
showView = function(aView) {
  if ('userscripts' == aView) {
    greasemonkeyAddons.showView();
  } else {
    _origShowView(aView);
  }
};

var _origBuildContextMenu = buildContextMenu;
buildContextMenu = function(aEvent) {
  if ('userscripts' == gView) {
    greasemonkeyAddons.buildContextMenu(aEvent);
  } else {
    _origBuildContextMenu(aEvent);
  }
};

// Set up an "observer" on the config, to keep the displayed items up to date
// with their actual state.
var config = GM_config;
window.addEventListener("load", function() {
  config.addObserver(observer);
}, false);
window.addEventListener("unload", function() {
  config.removeObserver(observer);
}, false);

var observer = {
  notifyEvent: function(script, event, data) {
    // if the currently open tab is not the userscripts tab, then ignore event.
    if (gView != 'userscripts') return;

    if (event == "install") {
      var item = greasemonkeyAddons.addScriptToList(script);
      gExtensionsView.selectedItem = item;
      return;
    }

    var listbox = gExtensionsView;
    var node;
    var scriptId = script.namespace + script.name;
    for (var i = 0; node = listbox.childNodes[i]; i++) {
      if (node.getAttribute('addonId') == scriptId) {
        break;
      }
    }
    if (!node) return;

    switch (event) {
      case "edit-enabled":
        node.setAttribute('isDisabled', !data);
        break;
      case "uninstall":
        listbox.removeChild(node);
        break;
      case "move":
        listbox.removeChild(node);
        listbox.insertBefore(node, listbox.childNodes[data]);
        break;
    }
  }
};
})();

// Set event listeners.
window.addEventListener('load', function() {
  greasemonkeyAddons.onAddonSelect();
  gExtensionsView.addEventListener(
      'select', greasemonkeyAddons.onAddonSelect, false);

  // Work-around for Stylish compatibility, which does not update gView in
  // its overridden showView() function.
  var stylishRadio = document.getElementById('userstyles-view');
  if (stylishRadio) {
    stylishRadio.addEventListener(
        'command',
        function() { gView = 'userstyles' },
        false);
  }
}, false);

var greasemonkeyAddons = {
  showView: function() {
    if ('userscripts' == gView) return;
    updateLastSelected('userscripts');
    gView='userscripts';

    // Update any possibly modified scripts.
    GM_config.updateModifiedScripts();

    // Hide the native controls that don't work in the user scripts view.
    function $(id) { return document.getElementById(id); }
    function hide(el) { el=$(el); el && (el.hidden=true); }
    var elementIds=[
      'searchPanel', 'installFileButton', 'checkUpdatesAllButton',
      'skipDialogButton', 'themePreviewArea', 'themeSplitter',
      'showUpdateInfoButton', 'hideUpdateInfoButton',
      'installUpdatesAllButton',
      // Stylish injects these elements.
      'copy-style-info', 'new-style'];
    elementIds.forEach(hide);

    var getMore = document.getElementById('getMore');
    getMore.setAttribute('getMoreURL', 'http://userscripts.org/');
    getMore.hidden = false;
    getMore.value = 'Get User Scripts';

    greasemonkeyAddons.fillList();
    gExtensionsView.selectedItem = gExtensionsView.children[0];
    // The setTimeout() here is for timing, to make sure the selection above
    // has really happened.
    setTimeout(greasemonkeyAddons.onAddonSelect, 0);
  },

  fillList: function() {
    var config = GM_config;
    var listbox = gExtensionsView;

    // Remove any pre-existing contents.
    while (listbox.firstChild) {
      listbox.removeChild(listbox.firstChild);
    }

    // Add a list item for each script.
    for (var i = 0, script = null; script = config.scripts[i]; i++) {
      greasemonkeyAddons.addScriptToList(script);
    }
  },

  listitemForScript: function(script) {
    var item = document.createElement('richlistitem');
    item.setAttribute('class', 'userscript');
    // Fake this for now.
    var id = script.namespace + script.name;
    // Setting these attributes inherits the values into the same place they
    // would go for extensions.
    item.setAttribute('addonId', id);
    item.setAttribute('name', script.name);
    item.setAttribute('description', script.description);
    item.setAttribute('id', 'urn:greasemonkey:item:'+id);
    item.setAttribute('isDisabled', !script.enabled);
    // These hide extension-specific bits we don't want to display.
    item.setAttribute('blocklisted', 'false');
    item.setAttribute('blocklistedsoft', 'false');
    item.setAttribute('compatible', 'true');
    item.setAttribute('locked', 'false');
    item.setAttribute('providesUpdatesSecurely', 'true');
    item.setAttribute('satisfiesDependencies', 'true');
    item.setAttribute('type', nsIUpdateItem.TYPE_EXTENSION);
    return item;
  },

  addScriptToList: function(script, beforeNode) {
    var item = greasemonkeyAddons.listitemForScript(script);
    gExtensionsView.insertBefore(item, beforeNode || null);
    return item;
  },

  findSelectedScript: function() {
    if (!gExtensionsView.selectedItem) return null;
    var scripts = GM_config.scripts;
    var selectedScriptId = gExtensionsView.selectedItem.getAttribute('addonId');
    for (var i = 0, script = null; script = scripts[i]; i++) {
      if (selectedScriptId == script.namespace + script.name) {
        return script;
      }
    }
    return null;
  },

  onAddonSelect: function(aEvent) {
    // We do all this work here, because the elements we want to change do
    // not exist until the item is selected.

    if (!gExtensionsView.selectedItem) return;
    if ('userscripts' != gView) return;
    var script = greasemonkeyAddons.findSelectedScript();

    // Remove/change the anonymous nodes we don't want.
    var item = gExtensionsView.selectedItem;
    var button;

    // Replace 'preferences' with 'edit'.
    button = item.ownerDocument.getAnonymousElementByAttribute(
        item, 'command', 'cmd_options');
    if (!button) return;
    button.setAttribute('label', GM_string('Edit'));
    button.setAttribute('accesskey', GM_string('Edit.accesskey'));
    button.setAttribute('tooltiptext', GM_string('Edit.tooltip'));
    button.setAttribute('command', 'cmd_userscript_edit');
    button.setAttribute('disabled', 'false');

    // Rewire enable, disable, uninstall.
    button = item.ownerDocument.getAnonymousElementByAttribute(
        item, 'command', 'cmd_enable');
    if (!button) return;
    button.setAttribute('tooltiptext', GM_string('Enable.tooltip'));
    button.setAttribute('command', 'cmd_userscript_enable');
    button.setAttribute('disabled', 'false');

    button = item.ownerDocument.getAnonymousElementByAttribute(
        item, 'command', 'cmd_disable');
    if (!button) return;
    button.setAttribute('tooltiptext', GM_string('Disable.tooltip'));
    button.setAttribute('command', 'cmd_userscript_disable');
    button.setAttribute('disabled', 'false');

    button = item.ownerDocument.getAnonymousElementByAttribute(
        item, 'command', 'cmd_uninstall');
    if (!button) return;
    button.setAttribute('tooltiptext', GM_string('Uninstall.tooltip'));
    button.setAttribute('command', 'cmd_userscript_uninstall');
    button.setAttribute('disabled', 'false');
  },

  doCommand: function(command) {
    var script = greasemonkeyAddons.findSelectedScript();
    if (!script) {
      dump("greasemonkeyAddons.doCommand() could not find selected script.\n");
      return;
    }

    var selectedListitem = gExtensionsView.selectedItem;
    switch (command) {
    case 'cmd_userscript_edit':
      GM_openInEditor(script);
      break;
    case 'cmd_userscript_enable':
      script.enabled = true;
      break;
    case 'cmd_userscript_disable':
      script.enabled = false;
      break;
    case 'cmd_userscript_move_down':
      GM_config.move(script, 1);
      break;
    case 'cmd_userscript_move_bottom':
      GM_config.move(script, GM_config.scripts.length);
      break;
    case 'cmd_userscript_move_up':
      GM_config.move(script, -1);
      break;
    case 'cmd_userscript_move_top':
      GM_config.move(script, -1 * GM_config.scripts.length);
      break;
    case 'cmd_userscript_sort':
      function scriptCmp(a, b) { return a.name < b.name ? -1 : 1; }
      GM_config._scripts.sort(scriptCmp);
      GM_config._save();
      greasemonkeyAddons.fillList();
      break;
    case 'cmd_userscript_uninstall':
      GM_config.uninstall(script);
      break;
    }
  },

  buildContextMenu: function(aEvent) {
    var script = greasemonkeyAddons.findSelectedScript();
    if (!script) {
      dump("greasemonkeyAddons.buildContextMenu() could not find selected script.\n");
      return;
    }

    var popup = document.getElementById('addonContextMenu');
    while (popup.hasChildNodes()) {
      popup.removeChild(popup.firstChild);
    }

    function addMenuItem(label, command) {
      var menuitem = document.createElement('menuitem');
      menuitem.setAttribute('label', GM_string(label));
      menuitem.setAttribute('accesskey', GM_string(label+'.accesskey'));
      menuitem.setAttribute('command', command);
      popup.appendChild(menuitem);
    }

    addMenuItem('Edit', 'cmd_userscript_edit');
    if (script.enabled) {
      addMenuItem('Disable', 'cmd_userscript_disable');
    } else {
      addMenuItem('Enable', 'cmd_userscript_enable');
    }
    addMenuItem('Uninstall', 'cmd_userscript_uninstall');

    popup.appendChild(document.createElement('menuseparator'));

    addMenuItem('Move Up', 'cmd_userscript_move_up');
    addMenuItem('Move Down', 'cmd_userscript_move_down');
    addMenuItem('Move To Top', 'cmd_userscript_move_top');
    addMenuItem('Move To Bottom', 'cmd_userscript_move_bottom');

    popup.appendChild(document.createElement('menuseparator'));

    addMenuItem('Sort Scripts', 'cmd_userscript_sort');
  }
};
<commit_msg>Disable context menu items that won't work.<commit_after>// Globals.
var GM_config = GM_getConfig();

var GM_stringBundle = Components
    .classes["@mozilla.org/intl/stringbundle;1"]
    .getService(Components.interfaces.nsIStringBundleService)
    .createBundle("chrome://greasemonkey/locale/gm-manage.properties");
function GM_string(key) { return GM_stringBundle.GetStringFromName(key); }

(function() {
// Override some built-in functions, with a closure reference to the original
// function, to either handle or delegate the call.
var _origShowView = showView;
showView = function(aView) {
  if ('userscripts' == aView) {
    greasemonkeyAddons.showView();
  } else {
    _origShowView(aView);
  }
};

var _origBuildContextMenu = buildContextMenu;
buildContextMenu = function(aEvent) {
  if ('userscripts' == gView) {
    greasemonkeyAddons.buildContextMenu(aEvent);
  } else {
    _origBuildContextMenu(aEvent);
  }
};

// Set up an "observer" on the config, to keep the displayed items up to date
// with their actual state.
var config = GM_config;
window.addEventListener("load", function() {
  config.addObserver(observer);
}, false);
window.addEventListener("unload", function() {
  config.removeObserver(observer);
}, false);

var observer = {
  notifyEvent: function(script, event, data) {
    // if the currently open tab is not the userscripts tab, then ignore event.
    if (gView != 'userscripts') return;

    if (event == "install") {
      var item = greasemonkeyAddons.addScriptToList(script);
      gExtensionsView.selectedItem = item;
      return;
    }

    var listbox = gExtensionsView;
    var node;
    var scriptId = script.namespace + script.name;
    for (var i = 0; node = listbox.childNodes[i]; i++) {
      if (node.getAttribute('addonId') == scriptId) {
        break;
      }
    }
    if (!node) return;

    switch (event) {
      case "edit-enabled":
        node.setAttribute('isDisabled', !data);
        break;
      case "uninstall":
        listbox.removeChild(node);
        break;
      case "move":
        listbox.removeChild(node);
        listbox.insertBefore(node, listbox.childNodes[data]);
        break;
    }
  }
};
})();

// Set event listeners.
window.addEventListener('load', function() {
  greasemonkeyAddons.onAddonSelect();
  gExtensionsView.addEventListener(
      'select', greasemonkeyAddons.onAddonSelect, false);

  // Work-around for Stylish compatibility, which does not update gView in
  // its overridden showView() function.
  var stylishRadio = document.getElementById('userstyles-view');
  if (stylishRadio) {
    stylishRadio.addEventListener(
        'command',
        function() { gView = 'userstyles' },
        false);
  }
}, false);

var greasemonkeyAddons = {
  showView: function() {
    if ('userscripts' == gView) return;
    updateLastSelected('userscripts');
    gView='userscripts';

    // Update any possibly modified scripts.
    GM_config.updateModifiedScripts();

    // Hide the native controls that don't work in the user scripts view.
    function $(id) { return document.getElementById(id); }
    function hide(el) { el=$(el); el && (el.hidden=true); }
    var elementIds=[
      'searchPanel', 'installFileButton', 'checkUpdatesAllButton',
      'skipDialogButton', 'themePreviewArea', 'themeSplitter',
      'showUpdateInfoButton', 'hideUpdateInfoButton',
      'installUpdatesAllButton',
      // Stylish injects these elements.
      'copy-style-info', 'new-style'];
    elementIds.forEach(hide);

    var getMore = document.getElementById('getMore');
    getMore.setAttribute('getMoreURL', 'http://userscripts.org/');
    getMore.hidden = false;
    getMore.value = 'Get User Scripts';

    greasemonkeyAddons.fillList();
    gExtensionsView.selectedItem = gExtensionsView.children[0];
    // The setTimeout() here is for timing, to make sure the selection above
    // has really happened.
    setTimeout(greasemonkeyAddons.onAddonSelect, 0);
  },

  fillList: function() {
    var config = GM_config;
    var listbox = gExtensionsView;

    // Remove any pre-existing contents.
    while (listbox.firstChild) {
      listbox.removeChild(listbox.firstChild);
    }

    // Add a list item for each script.
    for (var i = 0, script = null; script = config.scripts[i]; i++) {
      greasemonkeyAddons.addScriptToList(script);
    }
  },

  listitemForScript: function(script) {
    var item = document.createElement('richlistitem');
    item.setAttribute('class', 'userscript');
    // Fake this for now.
    var id = script.namespace + script.name;
    // Setting these attributes inherits the values into the same place they
    // would go for extensions.
    item.setAttribute('addonId', id);
    item.setAttribute('name', script.name);
    item.setAttribute('description', script.description);
    item.setAttribute('id', 'urn:greasemonkey:item:'+id);
    item.setAttribute('isDisabled', !script.enabled);
    // These hide extension-specific bits we don't want to display.
    item.setAttribute('blocklisted', 'false');
    item.setAttribute('blocklistedsoft', 'false');
    item.setAttribute('compatible', 'true');
    item.setAttribute('locked', 'false');
    item.setAttribute('providesUpdatesSecurely', 'true');
    item.setAttribute('satisfiesDependencies', 'true');
    item.setAttribute('type', nsIUpdateItem.TYPE_EXTENSION);
    return item;
  },

  addScriptToList: function(script, beforeNode) {
    var item = greasemonkeyAddons.listitemForScript(script);
    gExtensionsView.insertBefore(item, beforeNode || null);
    return item;
  },

  findSelectedScript: function() {
    if (!gExtensionsView.selectedItem) return null;
    var scripts = GM_config.scripts;
    var selectedScriptId = gExtensionsView.selectedItem.getAttribute('addonId');
    for (var i = 0, script = null; script = scripts[i]; i++) {
      if (selectedScriptId == script.namespace + script.name) {
        return script;
      }
    }
    return null;
  },

  onAddonSelect: function(aEvent) {
    // We do all this work here, because the elements we want to change do
    // not exist until the item is selected.

    if (!gExtensionsView.selectedItem) return;
    if ('userscripts' != gView) return;
    var script = greasemonkeyAddons.findSelectedScript();

    // Remove/change the anonymous nodes we don't want.
    var item = gExtensionsView.selectedItem;
    var button;

    // Replace 'preferences' with 'edit'.
    button = item.ownerDocument.getAnonymousElementByAttribute(
        item, 'command', 'cmd_options');
    if (!button) return;
    button.setAttribute('label', GM_string('Edit'));
    button.setAttribute('accesskey', GM_string('Edit.accesskey'));
    button.setAttribute('tooltiptext', GM_string('Edit.tooltip'));
    button.setAttribute('command', 'cmd_userscript_edit');
    button.setAttribute('disabled', 'false');

    // Rewire enable, disable, uninstall.
    button = item.ownerDocument.getAnonymousElementByAttribute(
        item, 'command', 'cmd_enable');
    if (!button) return;
    button.setAttribute('tooltiptext', GM_string('Enable.tooltip'));
    button.setAttribute('command', 'cmd_userscript_enable');
    button.setAttribute('disabled', 'false');

    button = item.ownerDocument.getAnonymousElementByAttribute(
        item, 'command', 'cmd_disable');
    if (!button) return;
    button.setAttribute('tooltiptext', GM_string('Disable.tooltip'));
    button.setAttribute('command', 'cmd_userscript_disable');
    button.setAttribute('disabled', 'false');

    button = item.ownerDocument.getAnonymousElementByAttribute(
        item, 'command', 'cmd_uninstall');
    if (!button) return;
    button.setAttribute('tooltiptext', GM_string('Uninstall.tooltip'));
    button.setAttribute('command', 'cmd_userscript_uninstall');
    button.setAttribute('disabled', 'false');
  },

  doCommand: function(command) {
    var script = greasemonkeyAddons.findSelectedScript();
    if (!script) {
      dump("greasemonkeyAddons.doCommand() could not find selected script.\n");
      return;
    }

    var selectedListitem = gExtensionsView.selectedItem;
    switch (command) {
    case 'cmd_userscript_edit':
      GM_openInEditor(script);
      break;
    case 'cmd_userscript_enable':
      script.enabled = true;
      break;
    case 'cmd_userscript_disable':
      script.enabled = false;
      break;
    case 'cmd_userscript_move_down':
      GM_config.move(script, 1);
      break;
    case 'cmd_userscript_move_bottom':
      GM_config.move(script, GM_config.scripts.length);
      break;
    case 'cmd_userscript_move_up':
      GM_config.move(script, -1);
      break;
    case 'cmd_userscript_move_top':
      GM_config.move(script, -1 * GM_config.scripts.length);
      break;
    case 'cmd_userscript_sort':
      function scriptCmp(a, b) { return a.name < b.name ? -1 : 1; }
      GM_config._scripts.sort(scriptCmp);
      GM_config._save();
      greasemonkeyAddons.fillList();
      break;
    case 'cmd_userscript_uninstall':
      GM_config.uninstall(script);
      break;
    }
  },

  buildContextMenu: function(aEvent) {
    var script = greasemonkeyAddons.findSelectedScript();
    if (!script) {
      dump("greasemonkeyAddons.buildContextMenu() could not find selected script.\n");
      return;
    }

    var popup = document.getElementById('addonContextMenu');
    while (popup.hasChildNodes()) {
      popup.removeChild(popup.firstChild);
    }

    function forceDisabled(aEvent) {
      if ('disabled' != aEvent.attrName) return;
      if ('true' == aEvent.newValue) return;
      aEvent.target.setAttribute('disabled', 'true');
    }
    function addMenuItem(label, command, enabled) {
      var menuitem = document.createElement('menuitem');
      menuitem.setAttribute('label', GM_string(label));
      menuitem.setAttribute('accesskey', GM_string(label+'.accesskey'));
      menuitem.setAttribute('command', command);

      if ('undefined' == typeof enabled) enabled = true;
      if (!enabled) {
        menuitem.setAttribute('disabled', 'true');
        // Something is un-setting the disabled attribute.  Work around that,
        // this way for now.
        menuitem.addEventListener('DOMAttrModified', forceDisabled, true);
      }

      popup.appendChild(menuitem);
    }

    addMenuItem('Edit', 'cmd_userscript_edit');
    if (script.enabled) {
      addMenuItem('Disable', 'cmd_userscript_disable');
    } else {
      addMenuItem('Enable', 'cmd_userscript_enable');
    }
    addMenuItem('Uninstall', 'cmd_userscript_uninstall');

    popup.appendChild(document.createElement('menuseparator'));

    var selectedItem = gExtensionsView.selectedItem;
    addMenuItem('Move Up', 'cmd_userscript_move_up',
        !!selectedItem.previousSibling);
    addMenuItem('Move Down', 'cmd_userscript_move_down',
        !!selectedItem.nextSibling);
    addMenuItem('Move To Top', 'cmd_userscript_move_top',
        !!selectedItem.previousSibling);
    addMenuItem('Move To Bottom', 'cmd_userscript_move_bottom',
        !!selectedItem.nextSibling);

    popup.appendChild(document.createElement('menuseparator'));

    addMenuItem('Sort Scripts', 'cmd_userscript_sort',
        gExtensionsView.itemCount > 1);
  }
};
<|endoftext|>


<commit_before>/**
 * DOM utility
 *
 * Exports handy methods to work with DOM elements
 */

function getElements(parent, selector) {
  return Array.prototype.slice.call(parent.querySelectorAll(selector))
}

/**
 * Returns true if element has given className
 *
 * @param  {HTMLElement} element
 * @return {Boolean}
 * @return {void}
 */
function hasClass(element, className) {
  return element.className.split(' ').indexOf(className) !== -1
}

/**
 * Removes class from element if it currently has it
 *
 * @param  {HTMLElement} element
 * @param  {String} className
 * @return {void}
 */
function removeClass(element, className) {
  if (!hasClass(element, className)) { return }

  let classNames = element.className.split(' ')

  classNames.splice(classNames.indexOf(className), 1)
  element.className = classNames.join(' ')
}

/**
 * Adds class to element if doesn't currently have it
 *
 * @param  {HTMLElement} element
 * @param  {String} className
 * @return {void}
 */
function addClass(element, className) {
  if (hasClass(element, className)) { return }

  element.className += ' ' + className
}

/**
 * Toggles class on element - adds it or removes it if a state value is passed
 * depending wether it's truthy of not
 *
 * @param  {HTMLElement} element
 * @param  {String} className
 * @param  {Boolean=} state
 * @return {void}
 */
function toggleClass(element, className, state = null) {
  state = typeof state === 'boolean' ? state : !hasClass(element, className)

  let fn = state ? addClass : removeClass

  fn(element, className)
}

module.exports = { getElements, hasClass, addClass, removeClass, toggleClass}<commit_msg>Document DOM util<commit_after>/**
 * DOM utility
 *
 * Exports handy methods to work with DOM elements
 */

 /**
  * Get elements matching given selector in Array forma as opposed to NodesList
  *
  * @param  {String} selector
  * @param  {DOMNode=} parent
  * @return {[DOMNode]}
  */
function getElements(selector, parent = document) {
  return Array.prototype.slice.call(parent.querySelectorAll(selector))
}

/**
 * Returns true if element has given className
 *
 * @param  {HTMLElement} element
 * @return {Boolean}
 * @return {void}
 */
function hasClass(element, className) {
  return element.className.split(' ').indexOf(className) !== -1
}

/**
 * Removes class from element if it currently has it
 *
 * @param  {HTMLElement} element
 * @param  {String} className
 * @return {void}
 */
function removeClass(element, className) {
  if (!hasClass(element, className)) { return }

  let classNames = element.className.split(' ')

  classNames.splice(classNames.indexOf(className), 1)
  element.className = classNames.join(' ')
}

/**
 * Adds class to element if doesn't currently have it
 *
 * @param  {HTMLElement} element
 * @param  {String} className
 * @return {void}
 */
function addClass(element, className) {
  if (hasClass(element, className)) { return }

  element.className += ' ' + className
}

/**
 * Toggles class on element - adds it or removes it if a state value is passed
 * depending wether it's truthy of not
 *
 * @param  {HTMLElement} element
 * @param  {String} className
 * @param  {Boolean=} state
 * @return {void}
 */
function toggleClass(element, className, state = null) {
  state = typeof state === 'boolean' ? state : !hasClass(element, className)

  let fn = state ? addClass : removeClass

  fn(element, className)
}

module.exports = { getElements, hasClass, addClass, removeClass, toggleClass}<|endoftext|>


<commit_before>var _ = require("underscore");

Parse.Cloud.define("searchAll", function(request, response) {
	var Scope = {
		All: 0,
		Users: 1,
		Posts: 2,
		Albums: 3,
		Groups: 4
	};
	var filter = request.params.filter;
	var probe = request.params.probe;
	var user = request.user;
	var searchResults = [];
	var promises = [];
	function getQuery(className) {
		return new Parse.Query(Parse.Object.extend(className));
	}
	if (filter == Scope.All || filter == Scope.Posts) {
		// search posts and photos from roll
		function queryPostField(field) {
			var query = getQuery("Post");
			query.equalTo("createdBy", user).matches("title", "(?i)" + probe).matches("title", "(?i)" + probe);
			return query.find();
		}
		var tagQuery = getQuery("Tag");
		tagQuery.matches("name", "(?i)" + probe)
		//promises.push(tagQuery);		//TODO: This isn't right. Must find posts that contain these tags
		promises.push(queryPostField("title"));
		promises.push(queryPostField("notes"));
	}
	if (filter == Scope.All || filter == Scope.Albums || filter == Scope.Groups) {
		// search groups and albums
		function queryAlbumGroupField(type, field) {
			var query = getQuery("Album");
			query.equalTo("type", type);
			if (type == "album")
				query.equalTo("createdBy", user);
			query.matches(field,  "(?i)" + probe);
			return query.find()
		}
		if (filter != Scope.Groups) {
			promises.push(queryAlbumGroupField("album", "title"));
			promises.push(queryAlbumGroupField("album", "notes"));
		}
		if (filter != Scope.Albums) {
			promises.push(queryAlbumGroupField("group", "title"));
			promises.push(queryAlbumGroupField("group", "notes"));
		}
	}
	if (filter == Scope.All || filter == Scope.Users) {
		// search users
		function queryUserField(field) {
			var query = getQuery("_User");
			query.matches(field,  "(?i)" + probe);
			return query.find();
		}
		promises.push(queryUserField("username"));
		promises.push(queryUserField("email"));
		promises.push(queryUserField("name"));
	}
	Parse.Promise.when(promises).then(function(results) {
		var finalResults = [];
		try {
			_.each(results, function accum(r) { finalResults = finalResults.concat(r) });
			console.log(JSON.stringify(finalResults[0]));
			finalResults = _.sortBy(_.uniq(finalResults, function (a) { return a["objectId"] }), function(a) { return Date.parse(a["createdAt"]) }).reverse();
		}
		catch (e) {
			console.log(e);
		}
		response.success(finalResults);
	});
});
<commit_msg>Search in back end<commit_after>var _ = require("underscore");

Parse.Cloud.define("searchAll", function(request, response) {
	var Scope = {
		All: 0,
		Users: 1,
		Posts: 2,
		Albums: 3,
		Groups: 4
	};
	var filter = request.params.filter;
	var probe = request.params.probe;
	var user = request.user;
	var searchResults = [];
	var promises = [];
	function getQuery(className) {
		return new Parse.Query(Parse.Object.extend(className));
	}
	if (filter == Scope.All || filter == Scope.Posts) {
		// search posts and photos from roll
		function queryPostField(field) {
			var query = getQuery("Post");
			query.equalTo("createdBy", user).matches("title", "(?i)" + probe).matches("title", "(?i)" + probe);
			return query.find();
		}
		var tagQuery = getQuery("Tag");
		tagQuery.matches("name", "(?i)" + probe)
		//promises.push(tagQuery);		//TODO: This isn't right. Must find posts that contain these tags
		promises.push(queryPostField("title"));
		promises.push(queryPostField("notes"));
	}
	if (filter == Scope.All || filter == Scope.Albums || filter == Scope.Groups) {
		// search groups and albums
		function queryAlbumGroupField(type, field) {
			var query = getQuery("Album");
			query.equalTo("type", type);
			if (type == "album")
				query.equalTo("createdBy", user);
			query.matches(field,  "(?i)" + probe);
			return query.find()
		}
		if (filter != Scope.Groups) {
			promises.push(queryAlbumGroupField("album", "title"));
			promises.push(queryAlbumGroupField("album", "notes"));
		}
		if (filter != Scope.Albums) {
			promises.push(queryAlbumGroupField("group", "title"));
			promises.push(queryAlbumGroupField("group", "notes"));
		}
	}
	if (filter == Scope.All || filter == Scope.Users) {
		// search users
		function queryUserField(field) {
			var query = getQuery("_User");
			query.matches(field,  "(?i)" + probe);
			return query.find();
		}
		promises.push(queryUserField("username"));
		promises.push(queryUserField("email"));
		promises.push(queryUserField("name"));
	}
	Parse.Promise.when(promises).then(function(results) {
		var finalResults = [];
		try {
			_.each(results, function accum(r) { finalResults = finalResults.concat(r) });
			console.log(JSON.stringify(finalResults[0]));
			finalResults = _.sortBy(_.uniq(finalResults, function (a) { console.log(a["objectId"]); return a["objectId"] }), function(a) { return Date.parse(a["createdAt"]) }).reverse();
		}
		catch (e) {
			console.log(e);
		}
		response.success(finalResults);
	});
});
<|endoftext|>


<commit_before>Components.utils.import('chrome://greasemonkey-modules/content/constants.js');
Components.utils.import('chrome://greasemonkey-modules/content/miscapis.js');
Components.utils.import('chrome://greasemonkey-modules/content/prefmanager.js');
Components.utils.import('chrome://greasemonkey-modules/content/script.js');
Components.utils.import('chrome://greasemonkey-modules/content/third-party/MatchPattern.js');
Components.utils.import('chrome://greasemonkey-modules/content/util.js');

function Config() {
  this._saveTimer = null;
  this._scripts = null;
  this._configFile = GM_util.scriptDir();
  this._configFile.append("config.xml");
  this._globalExcludes = JSON.parse(GM_prefRoot.getValue("globalExcludes"));
  this._observers = [];
}

Config.prototype.GM_GUID = "{e4a8a97b-f2ed-450b-b12d-ee082ba24781}";

Config.prototype.initialize = function() {
  this._updateVersion();
  this._load();
};

Config.prototype.addObserver = function(observer, script) {
  var observers = script ? script._observers : this._observers;
  observers.push(observer);
};

Config.prototype.removeObserver = function(observer, script) {
  var observers = script ? script._observers : this._observers;
  var index = observers.indexOf(observer);
  if (index == -1) throw new Error("Observer not found");
  observers.splice(index, 1);
},

Config.prototype._notifyObservers = function(script, event, data) {
  var observers = this._observers.concat(script._observers);
  for (var i = 0, observer; observer = observers[i]; i++) {
    observer.notifyEvent(script, event, data);
  }
};

Config.prototype._changed = function(script, event, data, dontSave) {
  if (!dontSave) {
    this._save();
  }

  this._notifyObservers(script, event, data);
};

Config.prototype.installIsUpdate = function(script) {
  return this._find(script) > -1;
};

Config.prototype._find = function(aScript) {
  for (var i = 0, script; script = this._scripts[i]; i++) {
    if (script.id == aScript.id) {
      return i;
    }
  }

  return -1;
};

Config.prototype._load = function() {
  var domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
      .createInstance(Components.interfaces.nsIDOMParser);

  var configContents = "<UserScriptConfig/>";
  if (this._configFile.exists()) {
    configContents = GM_util.getContents(this._configFile);
  }
  var doc = domParser.parseFromString(configContents, "text/xml");
  var nodes = doc.evaluate("/UserScriptConfig/Script", doc, null,
      7 /* XPathResult.ORDERED_NODE_SNAPSHOT_TYPE */,
      null);

  this._scripts = [];
  for (var i=0, node=null; node=nodes.snapshotItem(i); i++) {
    try {
      var script = new Script(node);
    } catch (e) {
      // If parsing the script node failed, fail gracefully by skipping it.
      GM_util.logError(e, false, e.fileName, e.lineNumber);
      continue;
    }
    if (script.allFilesExist()) {
      this._scripts.push(script);
    } else {
      // TODO: Add a user prompt to restore the missing script here?
      // Perhaps sometime after update works, and we know where to
      // download the script from?
      node.parentNode.removeChild(node);
      this._changed(script, "missing-removed", null);
    }
  }
};

Config.prototype._save = function(saveNow) {
  // If we have not explicitly been told to save now, then defer execution
  // via a timer, to avoid locking up the UI.
  if (!saveNow) {
    // Reduce work in the case of many changes near to each other in time.
    if (this._saveTimer) {
      this._saveTimer.cancel(this._saveTimer);
    }

    this._saveTimer = Components.classes["@mozilla.org/timer;1"]
        .createInstance(Components.interfaces.nsITimer);

    // dereference 'this' for the closure
    var _save = GM_util.hitch(this, "_save");

    this._saveTimer.initWithCallback(
        {'notify': function() { _save(true); }}, 250,
        Components.interfaces.nsITimer.TYPE_ONE_SHOT);
    return;
  }

  var doc = Components.classes["@mozilla.org/xmlextras/domparser;1"]
      .createInstance(Components.interfaces.nsIDOMParser)
      .parseFromString("<UserScriptConfig></UserScriptConfig>", "text/xml");

  for (var i = 0, scriptObj; scriptObj = this._scripts[i]; i++) {
    doc.firstChild.appendChild(doc.createTextNode("\n\t"));
    doc.firstChild.appendChild(scriptObj.toConfigNode(doc));
  }

  doc.firstChild.appendChild(doc.createTextNode("\n"));

  var domSerializer = Components
      .classes["@mozilla.org/xmlextras/xmlserializer;1"]
      .createInstance(Components.interfaces.nsIDOMSerializer);
  GM_util.writeToFile(domSerializer.serializeToString(doc), this._configFile);
};

Config.prototype.install = function(script, oldScript, tempDir) {
  var existingIndex = this._find(oldScript || script);
  if (!oldScript) oldScript = this.scripts[existingIndex];

  if (oldScript) {
    // Save the old script's state.
    script._enabled = oldScript.enabled;
    script.userExcludes = oldScript.userExcludes;
    script.userMatches = oldScript.userMatches;
    script.userIncludes = oldScript.userIncludes;

    // Uninstall the old script.
    this.uninstall(oldScript, true);
  }

  script._dependhash = GM_util.sha1(script._rawMeta);
  script._installTime = new Date().getTime();

  this._scripts.push(script);

  if (existingIndex > -1) {
    this.move(script, existingIndex - this._scripts.length + 1);
  }

  if (oldScript) {
    this._changed(script, 'modified', oldScript.id);
  } else {
    this._changed(script, 'install', existingIndex);
  }
};

Config.prototype.uninstall = function(script, forUpdate) {
  if ('undefined' == typeof(forUpdate)) forUpdate = false;

  var idx = this._find(script);
  this._scripts.splice(idx, 1);
  script.uninstall(forUpdate);
};

/**
 * Moves an installed user script to a new position in the array of installed scripts.
 *
 * @param script The script to be moved.
 * @param destination Can be either (a) a numeric offset for the script to be
 *                    moved by, or (b) another installed script to which
 *                    position the script will be moved.
 */
Config.prototype.move = function(script, destination) {
  var from = this._scripts.indexOf(script);
  var to = -1;

  // Make sure the user script is installed
  if (from == -1) return;

  if (typeof destination == "number") { // if destination is an offset
    to = from + destination;
    to = Math.max(0, to);
    to = Math.min(this._scripts.length - 1, to);
  } else { // if destination is a script object
    to = this._scripts.indexOf(destination);
  }

  if (to == -1) return;

  var tmp = this._scripts.splice(from, 1)[0];
  this._scripts.splice(to, 0, tmp);
  this._changed(script, "move", to);
},

Config.prototype.__defineGetter__('globalExcludes',
function Config_getGlobalExcludes() { return this._globalExcludes.concat(); }
);

Config.prototype.__defineSetter__('globalExcludes',
function Config_setGlobalExcludes(val) {
  this._globalExcludes = val.concat();
  GM_prefRoot.setValue("globalExcludes", JSON.stringify(this._globalExcludes));
});

Config.prototype.__defineGetter__('scripts',
function Config_getScripts() { return this._scripts.concat(); }
);

Config.prototype.getMatchingScripts = function(testFunc) {
  return this._scripts.filter(testFunc);
};

Config.prototype.updateModifiedScripts = function(
    aWhen, aUrl, aWindowId, aBrowser
) {
  // Find any updated scripts or scripts with delayed injection
  var scripts = this.getMatchingScripts(
      function (script) {
        return script.runAt == aWhen
            && (script.isModified() || 0 != script.pendingExec.length);
      });
  if (0 == scripts.length) return;

  for (var i = 0, script; script = scripts[i]; i++) {
    if (0 == script.pendingExec.length) {
      var scope = {};
      Components.utils.import('chrome://greasemonkey-modules/content/parseScript.js', scope);
      var parsedScript = scope.parse(
          script.textContent, GM_util.uriFromUrl(script.downloadURL));
      // TODO: Show PopupNotifications about parse error(s)?
      script.updateFromNewScript(parsedScript, aUrl, aWindowId, aBrowser);
    } else {
      // We are already downloading dependencies for this script
      // so add its window to the list
      script.pendingExec.push({
        'browser': aBrowser,
        'url': aUrl,
        'windowId': aWindowId
      });
    }
  }

  this._save();
};

Config.prototype.getScriptById = function(scriptId) {
  for (var i = 0, script = null; script = this.scripts[i]; i++) {
    if (scriptId == script.id) {
      return script;
    }
  }
};

/**
 * Checks whether the version has changed since the last run and performs
 * any necessary upgrades.
 */
Config.prototype._updateVersion = function() {
  Components.utils.import("resource://gre/modules/AddonManager.jsm");
  AddonManager.getAddonByID(this.GM_GUID, GM_util.hitch(this, function(addon) {
    var oldVersion = GM_prefRoot.getValue("version");
    var newVersion = addon.version;

    // Update the stored current version so we don't do this work again.
    GM_prefRoot.setValue("version", newVersion);

    if ("0.0" == oldVersion) {
      // This is the first launch.  Show the welcome screen.
      var chromeWin = GM_util.getBrowserWindow();
      // If we found it, use it to open a welcome tab.
      if (chromeWin && chromeWin.gBrowser) {
        var url = 'http://www.greasespot.net/p/welcome.html'
            + '?utm_source=xpi&utm_medium=xpi&utm_campaign=welcome'
            + '&utm_content=' + newVersion;
        // the setTimeout makes sure we do not execute too early -- sometimes
        // the window isn't quite ready to add a tab yet
        chromeWin.setTimeout(chromeWin.GM_BrowserUI.openTab, 100, url);
      }
    }

    if ('3.2' == newVersion && oldVersion != newVersion) {
      var tmp_dir = Components
          .classes['@mozilla.org/file/directory_service;1']
          .getService(Components.interfaces.nsIProperties)
          .get('TmpD', Components.interfaces.nsIFile);
      // #2069 Clean up stray temp directories.
      for (var i = 1; ; i++) {
        var file = tmp_dir.clone();
        file.append('gm-temp' + i);
        if (file.exists()) {
          dump('Removing temp dir: ' + file.path + '\n');
          file.remove(true);
        } else {
          break;
        }
      }
    }
  }));
};
<commit_msg>The 'use strict' - after installing a script - throws the warning<commit_after>Components.utils.import('chrome://greasemonkey-modules/content/constants.js');
Components.utils.import('chrome://greasemonkey-modules/content/miscapis.js');
Components.utils.import('chrome://greasemonkey-modules/content/prefmanager.js');
Components.utils.import('chrome://greasemonkey-modules/content/script.js');
Components.utils.import('chrome://greasemonkey-modules/content/third-party/MatchPattern.js');
Components.utils.import('chrome://greasemonkey-modules/content/util.js');

function Config() {
  this._saveTimer = null;
  this._scripts = null;
  this._configFile = GM_util.scriptDir();
  this._configFile.append("config.xml");
  this._globalExcludes = JSON.parse(GM_prefRoot.getValue("globalExcludes"));
  this._observers = [];
}

Config.prototype.GM_GUID = "{e4a8a97b-f2ed-450b-b12d-ee082ba24781}";

Config.prototype.initialize = function() {
  this._updateVersion();
  this._load();
};

Config.prototype.addObserver = function(observer, script) {
  var observers = script ? script._observers : this._observers;
  observers.push(observer);
};

Config.prototype.removeObserver = function(observer, script) {
  var observers = script ? script._observers : this._observers;
  var index = observers.indexOf(observer);
  if (index == -1) throw new Error("Observer not found");
  observers.splice(index, 1);
},

Config.prototype._notifyObservers = function(script, event, data) {
  var observers = this._observers.concat(script._observers);
  for (var i = 0, observer; observer = observers[i]; i++) {
    observer.notifyEvent(script, event, data);
  }
};

Config.prototype._changed = function(script, event, data, dontSave) {
  if (!dontSave) {
    this._save();
  }

  this._notifyObservers(script, event, data);
};

Config.prototype.installIsUpdate = function(script) {
  return this._find(script) > -1;
};

Config.prototype._find = function(aScript) {
  for (var i = 0, script; script = this._scripts[i]; i++) {
    if (script.id == aScript.id) {
      return i;
    }
  }

  return -1;
};

Config.prototype._load = function() {
  var domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
      .createInstance(Components.interfaces.nsIDOMParser);

  var configContents = "<UserScriptConfig/>";
  if (this._configFile.exists()) {
    configContents = GM_util.getContents(this._configFile);
  }
  var doc = domParser.parseFromString(configContents, "text/xml");
  var nodes = doc.evaluate("/UserScriptConfig/Script", doc, null,
      7 /* XPathResult.ORDERED_NODE_SNAPSHOT_TYPE */,
      null);

  this._scripts = [];
  for (var i=0, node=null; node=nodes.snapshotItem(i); i++) {
    try {
      var script = new Script(node);
    } catch (e) {
      // If parsing the script node failed, fail gracefully by skipping it.
      GM_util.logError(e, false, e.fileName, e.lineNumber);
      continue;
    }
    if (script.allFilesExist()) {
      this._scripts.push(script);
    } else {
      // TODO: Add a user prompt to restore the missing script here?
      // Perhaps sometime after update works, and we know where to
      // download the script from?
      node.parentNode.removeChild(node);
      this._changed(script, "missing-removed", null);
    }
  }
};

Config.prototype._save = function(saveNow) {
  // If we have not explicitly been told to save now, then defer execution
  // via a timer, to avoid locking up the UI.
  if (!saveNow) {
    // Reduce work in the case of many changes near to each other in time.
    if (this._saveTimer) {
      this._saveTimer.cancel(this._saveTimer);
    }

    this._saveTimer = Components.classes["@mozilla.org/timer;1"]
        .createInstance(Components.interfaces.nsITimer);

    // dereference 'this' for the closure
    var _save = GM_util.hitch(this, "_save");

    this._saveTimer.initWithCallback(
        {'notify': function() { _save(true); }}, 250,
        Components.interfaces.nsITimer.TYPE_ONE_SHOT);
    return;
  }

  var doc = Components.classes["@mozilla.org/xmlextras/domparser;1"]
      .createInstance(Components.interfaces.nsIDOMParser)
      .parseFromString("<UserScriptConfig></UserScriptConfig>", "text/xml");

  for (var i = 0, scriptObj; scriptObj = this._scripts[i]; i++) {
    doc.firstChild.appendChild(doc.createTextNode("\n\t"));
    doc.firstChild.appendChild(scriptObj.toConfigNode(doc));
  }

  doc.firstChild.appendChild(doc.createTextNode("\n"));

  var domSerializer = Components
      .classes["@mozilla.org/xmlextras/xmlserializer;1"]
      .createInstance(Components.interfaces.nsIDOMSerializer);
  GM_util.writeToFile(domSerializer.serializeToString(doc), this._configFile);
};

Config.prototype.install = function(script, oldScript, tempDir) {
  var existingIndex = this._find(oldScript || script);
  if (!oldScript && (existingIndex > -1)) {
    oldScript = this.scripts[existingIndex];
  }

  if (oldScript) {
    // Save the old script's state.
    script._enabled = oldScript.enabled;
    script.userExcludes = oldScript.userExcludes;
    script.userMatches = oldScript.userMatches;
    script.userIncludes = oldScript.userIncludes;

    // Uninstall the old script.
    this.uninstall(oldScript, true);
  }

  script._dependhash = GM_util.sha1(script._rawMeta);
  script._installTime = new Date().getTime();

  this._scripts.push(script);

  if (existingIndex > -1) {
    this.move(script, existingIndex - this._scripts.length + 1);
  }

  if (oldScript) {
    this._changed(script, 'modified', oldScript.id);
  } else {
    this._changed(script, 'install', existingIndex);
  }
};

Config.prototype.uninstall = function(script, forUpdate) {
  if ('undefined' == typeof(forUpdate)) forUpdate = false;

  var idx = this._find(script);
  if (idx > -1) {
    this._scripts.splice(idx, 1);
    script.uninstall(forUpdate);
  }
};

/**
 * Moves an installed user script to a new position in the array of installed scripts.
 *
 * @param script The script to be moved.
 * @param destination Can be either (a) a numeric offset for the script to be
 *                    moved by, or (b) another installed script to which
 *                    position the script will be moved.
 */
Config.prototype.move = function(script, destination) {
  var from = this._scripts.indexOf(script);
  var to = -1;

  // Make sure the user script is installed
  if (from == -1) return;

  if (typeof destination == "number") { // if destination is an offset
    to = from + destination;
    to = Math.max(0, to);
    to = Math.min(this._scripts.length - 1, to);
  } else { // if destination is a script object
    to = this._scripts.indexOf(destination);
  }

  if (to == -1) return;

  var tmp = this._scripts.splice(from, 1)[0];
  this._scripts.splice(to, 0, tmp);
  this._changed(script, "move", to);
},

Config.prototype.__defineGetter__('globalExcludes',
function Config_getGlobalExcludes() { return this._globalExcludes.concat(); }
);

Config.prototype.__defineSetter__('globalExcludes',
function Config_setGlobalExcludes(val) {
  this._globalExcludes = val.concat();
  GM_prefRoot.setValue("globalExcludes", JSON.stringify(this._globalExcludes));
});

Config.prototype.__defineGetter__('scripts',
function Config_getScripts() { return this._scripts.concat(); }
);

Config.prototype.getMatchingScripts = function(testFunc) {
  return this._scripts.filter(testFunc);
};

Config.prototype.updateModifiedScripts = function(
    aWhen, aUrl, aWindowId, aBrowser
) {
  // Find any updated scripts or scripts with delayed injection
  var scripts = this.getMatchingScripts(
      function (script) {
        return script.runAt == aWhen
            && (script.isModified() || 0 != script.pendingExec.length);
      });
  if (0 == scripts.length) return;

  for (var i = 0, script; script = scripts[i]; i++) {
    if (0 == script.pendingExec.length) {
      var scope = {};
      Components.utils.import('chrome://greasemonkey-modules/content/parseScript.js', scope);
      var parsedScript = scope.parse(
          script.textContent, GM_util.uriFromUrl(script.downloadURL));
      // TODO: Show PopupNotifications about parse error(s)?
      script.updateFromNewScript(parsedScript, aUrl, aWindowId, aBrowser);
    } else {
      // We are already downloading dependencies for this script
      // so add its window to the list
      script.pendingExec.push({
        'browser': aBrowser,
        'url': aUrl,
        'windowId': aWindowId
      });
    }
  }

  this._save();
};

Config.prototype.getScriptById = function(scriptId) {
  for (var i = 0, script = null; script = this.scripts[i]; i++) {
    if (scriptId == script.id) {
      return script;
    }
  }
};

/**
 * Checks whether the version has changed since the last run and performs
 * any necessary upgrades.
 */
Config.prototype._updateVersion = function() {
  Components.utils.import("resource://gre/modules/AddonManager.jsm");
  AddonManager.getAddonByID(this.GM_GUID, GM_util.hitch(this, function(addon) {
    var oldVersion = GM_prefRoot.getValue("version");
    var newVersion = addon.version;

    // Update the stored current version so we don't do this work again.
    GM_prefRoot.setValue("version", newVersion);

    if ("0.0" == oldVersion) {
      // This is the first launch.  Show the welcome screen.
      var chromeWin = GM_util.getBrowserWindow();
      // If we found it, use it to open a welcome tab.
      if (chromeWin && chromeWin.gBrowser) {
        var url = 'http://www.greasespot.net/p/welcome.html'
            + '?utm_source=xpi&utm_medium=xpi&utm_campaign=welcome'
            + '&utm_content=' + newVersion;
        // the setTimeout makes sure we do not execute too early -- sometimes
        // the window isn't quite ready to add a tab yet
        chromeWin.setTimeout(chromeWin.GM_BrowserUI.openTab, 100, url);
      }
    }

    if ('3.2' == newVersion && oldVersion != newVersion) {
      var tmp_dir = Components
          .classes['@mozilla.org/file/directory_service;1']
          .getService(Components.interfaces.nsIProperties)
          .get('TmpD', Components.interfaces.nsIFile);
      // #2069 Clean up stray temp directories.
      for (var i = 1; ; i++) {
        var file = tmp_dir.clone();
        file.append('gm-temp' + i);
        if (file.exists()) {
          dump('Removing temp dir: ' + file.path + '\n');
          file.remove(true);
        } else {
          break;
        }
      }
    }
  }));
};
<|endoftext|>


<commit_before>"use strict";

var pipeline = require( '../lib/pipeline' );
var filters  = require( './filters'       );
var database = require( './database'      );
var mailer   = require( './mailer'        );
var fs       = require( 'fs'              );

exports.setup = function () {

    app.get( '/api/1.0/login', loginHandler );

    app.put( '/api/1.0/register', registerHandler );

    app.post( '/api/1.0/change-password', changePassword );

    app.post( '/api/1.0/users', updateUser);

    app.post( '/api/1.0/recover-password', recoverPassword );

    app.post( '/api/1.0/forgot-password', forgotPassword );

    app.post( '/api/1.0/verify-email', verifyEmail );
};

function loginHandler( req, res ) {
    var loginPipeline = new pipeline();

    loginPipeline
        .pipe( filters.authenticationFilter )
        .pipe( filters.responseAddUser );

    var additionaldataFunc = app.get( 'bridge-ext' ).additionaldataFunc;

    loginPipeline.execute( req, function ( resBody, err ) {

        if ( err ) {
            res.status( err.StatusCode );
            res.send( {
                "message": err.Message,
                "content": {}
            } );
            return;
        }

        if ( _.isFunction( additionaldataFunc ) ) {
            resBody.user.additionalData = additionaldataFunc( req, resBody );
        } else {
            resBody.user.additionalData = {};
        }

        res.status( 200 );
        res.send( resBody );
    } );
}

function registerHandler( req, res ) {
    var registerPipeline = new pipeline();

    registerPipeline.pipe( filters.registrationDataVaildation )
        .pipe( filters.registrationAuthenticationFilter );

    if ( req.body.dontCommitToDB !== true ) {
        registerPipeline.pipe( database.registerUser );
    }

    registerPipeline.execute( req, function ( resBody, err ) {

        if ( err != null ) {

            app.get( 'logger' ).verbose( {
                req: req.body,
                status: err.StatusCode,
                err: err.Message
            } );

            res.status( err.StatusCode );
            res.send( {
                content: {
                    message: err.Message
                }
            });
            return;
        }

        app.get( 'logger' ).verbose( {
            req: req.body,
            status: 200,
            res: resBody
        } );

        resBody.content.message = "Registration Sucessful";

        res.status( 200 );
        res.send( resBody );

        return;
    } );
}

function changePassword( req, res ) {

    var cpPipeline = new pipeline();

    cpPipeline
        .pipe( filters.authenticationFilter )
        .pipe( database.changePassword );

    cpPipeline.execute( req, function ( resBody, err ) {
        if ( err != null ) {

            res.status( err.StatusCode );

            app.get( 'logger' ).verbose( {
                req: req.body,
                status: err.StatusCode,
                err: err.Message
            } );

            res.send( err );
            return;
        }

        res.status( 200 );
        res.send( resBody );
    } );
}

function recoverPassword( req, res ) {

}

function forgotPassword( req, res ) {

    fs.readFile( app.get( 'BridgeConfig' ).templates.recoverPasswordTemplatePath, function(err, data){

        if ( err ) {
            app.get( 'logger' ).warn( "Error reading template file for forgot password. Error: ", err );
            res.status( 500 );
            return;
        }

        // TODO fill templates with values

        res.status( 200 );
    } );

}

function verifyEmail( req, res ) {
    var userHash = req.content.message;

    var verifyPipeline = new pipeline();

    verifyPipeline.pipe( database.verifyEmail );

    verifyPipeline.execute(req, function(resBody, err){

        if ( err ) {
            res.status( err.StatusCode );

            app.get( 'logger' ).debug( {
                req: req.body,
                status: err.StatusCode,
                err: err.Message
            } );

            res.send({
                content: {
                    message: err.Message
                }
            });
        }

        res.status( 200 );
        res.send( resBody );

        return;

    });
}

function updateUser( req, res ) {
    var uUPipeline = new pipeline();

    uUPipeline
        .pipe( filters.authenticationFilter )
        .pipe( database.changePassword );

    uUPipeline.execute( req, function ( resBody, err ) {
        if ( err != null ) {

            res.status( err.StatusCode );

            app.get( 'logger' ).verbose( {
                req: req.body,
                status: err.StatusCode,
                err: err.Message
            } );

            res.send( err );
            return;
        }

        res.status( 200 );
        res.send( resBody );
    } );
}
<commit_msg>fixing fancy pants route<commit_after>"use strict";

var pipeline = require( '../lib/pipeline' );
var filters  = require( './filters'       );
var database = require( './database'      );
var mailer   = require( './mailer'        );
var fs       = require( 'fs'              );

exports.setup = function () {

    app.get( '/api/1.0/login', loginHandler );

    app.put( '/api/1.0/users', registerHandler );

    app.post( '/api/1.0/change-password', changePassword );

    app.post( '/api/1.0/users', updateUser);

    app.post( '/api/1.0/recover-password', recoverPassword );

    app.post( '/api/1.0/forgot-password', forgotPassword );

    app.post( '/api/1.0/verify-email', verifyEmail );
};

function loginHandler( req, res ) {
    var loginPipeline = new pipeline();

    loginPipeline
        .pipe( filters.authenticationFilter )
        .pipe( filters.responseAddUser );

    var additionaldataFunc = app.get( 'bridge-ext' ).additionaldataFunc;

    loginPipeline.execute( req, function ( resBody, err ) {

        if ( err ) {
            res.status( err.StatusCode );
            res.send( {
                "message": err.Message,
                "content": {}
            } );
            return;
        }

        if ( _.isFunction( additionaldataFunc ) ) {
            resBody.user.additionalData = additionaldataFunc( req, resBody );
        } else {
            resBody.user.additionalData = {};
        }

        res.status( 200 );
        res.send( resBody );
    } );
}

function registerHandler( req, res ) {
    var registerPipeline = new pipeline();

    registerPipeline.pipe( filters.registrationDataVaildation )
        .pipe( filters.registrationAuthenticationFilter );

    if ( req.body.dontCommitToDB !== true ) {
        registerPipeline.pipe( database.registerUser );
    }

    registerPipeline.execute( req, function ( resBody, err ) {

        if ( err != null ) {

            app.get( 'logger' ).verbose( {
                req: req.body,
                status: err.StatusCode,
                err: err.Message
            } );

            res.status( err.StatusCode );
            res.send( {
                content: {
                    message: err.Message
                }
            });
            return;
        }

        app.get( 'logger' ).verbose( {
            req: req.body,
            status: 200,
            res: resBody
        } );

        resBody.content.message = "Registration Sucessful";

        res.status( 200 );
        res.send( resBody );

        return;
    } );
}

function changePassword( req, res ) {

    var cpPipeline = new pipeline();

    cpPipeline
        .pipe( filters.authenticationFilter )
        .pipe( database.changePassword );

    cpPipeline.execute( req, function ( resBody, err ) {
        if ( err != null ) {

            res.status( err.StatusCode );

            app.get( 'logger' ).verbose( {
                req: req.body,
                status: err.StatusCode,
                err: err.Message
            } );

            res.send( err );
            return;
        }

        res.status( 200 );
        res.send( resBody );
    } );
}

function recoverPassword( req, res ) {

}

function forgotPassword( req, res ) {

    fs.readFile( app.get( 'BridgeConfig' ).templates.recoverPasswordTemplatePath, function(err, data){

        if ( err ) {
            app.get( 'logger' ).warn( "Error reading template file for forgot password. Error: ", err );
            res.status( 500 );
            return;
        }

        // TODO fill templates with values

        res.status( 200 );
    } );

}

function verifyEmail( req, res ) {
    var userHash = req.content.message;

    var verifyPipeline = new pipeline();

    verifyPipeline.pipe( database.verifyEmail );

    verifyPipeline.execute(req, function(resBody, err){

        if ( err ) {
            res.status( err.StatusCode );

            app.get( 'logger' ).debug( {
                req: req.body,
                status: err.StatusCode,
                err: err.Message
            } );

            res.send({
                content: {
                    message: err.Message
                }
            });
        }

        res.status( 200 );
        res.send( resBody );

        return;

    });
}

function updateUser( req, res ) {
    var uUPipeline = new pipeline();

    uUPipeline
        .pipe( filters.authenticationFilter )
        .pipe( database.changePassword );

    uUPipeline.execute( req, function ( resBody, err ) {
        if ( err != null ) {

            res.status( err.StatusCode );

            app.get( 'logger' ).verbose( {
                req: req.body,
                status: err.StatusCode,
                err: err.Message
            } );

            res.send( err );
            return;
        }

        res.status( 200 );
        res.send( resBody );
    } );
}
<|endoftext|>


<commit_before>import mobx from 'mobx';

let logDisposer = null;

export function setLogLevel(newLevel) {
    if (newLevel === true && !logDisposer) {
        console.log("The output of the MobX logger is optimized for Chrome");
        logDisposer = mobx.spy(logger);
    } else if (newLevel === false && logDisposer) {
        logDisposer();
        logDisposer = null;
    }
}

function logger(change) {
    if (change.spyReportEnd === true) {
        if (typeof change.time === "number") {
            log("%ctotal time: %sms", "color:gray", change.time);
        }
        console.groupEnd();
    } else {
        const logNext = change.spyReportStart === true ? group : log;
        switch (change.type) {
            case 'action':
                // name, target, arguments, fn
                logNext(`%caction '%s' %s`, 'color:blue', change.name, autoWrap("(", getNameForThis(change.target)));
                log(change.arguments);
                // dir({
                //     fn: change.fn,
                //     target: change.target
                // });
                trace();
                break;
            case 'transaction':
                // name, target
                logNext(`%ctransaction '%s' %s`, 'color:gray', change.name, autoWrap("(", getNameForThis(change.target)));
                break;
            case 'scheduled-reaction':
                // object
                logNext(`%cscheduled async reaction '%s'`, 'color:green', observableName(change.object));
                break;
            case 'reaction':
                // object, fn
                logNext(`%creaction '%s'`, 'color:green', observableName(change.object));
                // dir({
                //     fn: change.fn
                // });
                trace();
                break;
            case 'compute':
                // object, target, fn
                group(`%ccomputed '%s' %s`, 'color:green', observableName(change.object), autoWrap("(", getNameForThis(change.target)));
                // dir({
                //    fn: change.fn,
                //    target: change.target
                // });
                groupEnd();
                break;
            case 'error':
                // message
                logNext('%cerror: %s', 'color:red', change.message);
                trace();
                closeGroupsOnError();
                break;
            case 'update':
                // (array) object, index, newValue, oldValue
                // (map, obbject) object, name, newValue, oldValue
                // (value) object, newValue, oldValue
                if (mobx.isObservableArray(change.object)) {
                    logNext("updated '%s[%s]': %s (was: %s)", observableName(change.object), change.index, formatValue(change.newValue), formatValue(change.oldValue));
                } else if (mobx.isObservableObject(change.object)) {
                    logNext("updated '%s.%s': %s (was: %s)", observableName(change.object), change.name, formatValue(change.newValue), formatValue(change.oldValue));
                } else {
                    logNext("updated '%s': %s (was: %s)", observableName(change.object), change.name, formatValue(change.newValue), formatValue(change.oldValue));
                }
                dir({
                    newValue: change.newValue,
                    oldValue: change.oldValue
                });
                trace();
                break;
            case 'splice':
                // (array) object, index, added, removed, addedCount, removedCount
                logNext("spliced '%s': index %d, added %d, removed %d", observableName(change.object), change.index, change.addedCount, change.removedCount);
                dir({
                    added: change.added,
                    removed: change.removed
                });
                trace();
                break;
            case 'add':
                // (map, object) object, name, newValue
                logNext("set '%s.%s': %s", observableName(change.object), change.name, formatValue(change.newValue));
                dir({
                    newValue: change.newValue
                });
                trace();
                break;
            case 'delete':
                // (map) object, name, oldValue
                logNext("removed '%s.%s' (was %s)", observableName(change.object), change.name, formatValue(change.oldValue));
                dir({
                    oldValue: change.oldValue
                });
                trace();
                break;
            case 'create':
                // (value) object, newValue
                logNext("set '%s': %s", observableName(change.object), formatValue(change.newValue));
                dir({
                    newValue: change.newValue
                });
                trace();
                break;
            default:
                // generic fallback for future events
                logNext(change.type);
                dir(change);
                break;
        }
    }
}

const consoleSupportsGroups = typeof console.groupCollapsed === "function";
let currentDepth = 0;

function group() {
    // TODO: firefox does not support formatting in groupStart methods..
    console[consoleSupportsGroups ? "groupCollapsed" : "log"].apply(console, arguments);
    currentDepth++;
}

function groupEnd() {
    currentDepth--;
    if (consoleSupportsGroups)
        console.groupEnd();
}

function log() {
    console.log.apply(console, arguments);
}

function dir() {
    console.dir.apply(console, arguments);
}

function trace() {
    // TODO: needs wrapping in firefox?
    console.trace("stack"); // TODO: use stacktrace.js or similar and strip off unrelevant stuff?
}

function closeGroupsOnError() {
    for (let i = 0, m = currentDepth; i < m; i++)
        groupEnd();
}

const closeToken = {
    "\"" : "\"",
    "'" : "'",
    "(" : ")",
    "[" : "]",
    "<" : "]",
    "#" : ""
}

function autoWrap(token, value) {
    if (!value)
        return "";
    return (token || "") + value + (closeToken[token] || "");
}

function observableName(object) {
    return mobx.extras.getDebugName(object);
}

function formatValue(value) {
    if (isPrimitive(value)) {
        if (typeof value === "string" && value.length > 100)
            return value.substr(0, 97) + "..."
        return value;
    } else
        return autoWrap("(", getNameForThis(value));
}

function getNameForThis(who) {
    if (who === null || who === undefined) {
        return "";
    } else if (who && typeof who === "object") {
	    if (who && who.$mobx) {
		    return who.$mobx.name;
        } else if (who.constructor) {
            return who.constructor.name || "object";
        }
	}
	return `${typeof who}`;
}

function isPrimitive(value) {
	return value === null || value === undefined || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
}<commit_msg>Don't show warning in Chrome<commit_after>import mobx from 'mobx';

let logDisposer = null;

export function setLogLevel(newLevel) {
    if (newLevel === true && !logDisposer) {
        if (typeof navigator !== 'undefined' && navigator.userAgent.indexOf('Chrome') === -1) {
            console.warn("The output of the MobX logger is optimized for Chrome");
        }
        logDisposer = mobx.spy(logger);
    } else if (newLevel === false && logDisposer) {
        logDisposer();
        logDisposer = null;
    }
}

function logger(change) {
    if (change.spyReportEnd === true) {
        if (typeof change.time === "number") {
            log("%ctotal time: %sms", "color:gray", change.time);
        }
        console.groupEnd();
    } else {
        const logNext = change.spyReportStart === true ? group : log;
        switch (change.type) {
            case 'action':
                // name, target, arguments, fn
                logNext(`%caction '%s' %s`, 'color:blue', change.name, autoWrap("(", getNameForThis(change.target)));
                log(change.arguments);
                // dir({
                //     fn: change.fn,
                //     target: change.target
                // });
                trace();
                break;
            case 'transaction':
                // name, target
                logNext(`%ctransaction '%s' %s`, 'color:gray', change.name, autoWrap("(", getNameForThis(change.target)));
                break;
            case 'scheduled-reaction':
                // object
                logNext(`%cscheduled async reaction '%s'`, 'color:green', observableName(change.object));
                break;
            case 'reaction':
                // object, fn
                logNext(`%creaction '%s'`, 'color:green', observableName(change.object));
                // dir({
                //     fn: change.fn
                // });
                trace();
                break;
            case 'compute':
                // object, target, fn
                group(`%ccomputed '%s' %s`, 'color:green', observableName(change.object), autoWrap("(", getNameForThis(change.target)));
                // dir({
                //    fn: change.fn,
                //    target: change.target
                // });
                groupEnd();
                break;
            case 'error':
                // message
                logNext('%cerror: %s', 'color:red', change.message);
                trace();
                closeGroupsOnError();
                break;
            case 'update':
                // (array) object, index, newValue, oldValue
                // (map, obbject) object, name, newValue, oldValue
                // (value) object, newValue, oldValue
                if (mobx.isObservableArray(change.object)) {
                    logNext("updated '%s[%s]': %s (was: %s)", observableName(change.object), change.index, formatValue(change.newValue), formatValue(change.oldValue));
                } else if (mobx.isObservableObject(change.object)) {
                    logNext("updated '%s.%s': %s (was: %s)", observableName(change.object), change.name, formatValue(change.newValue), formatValue(change.oldValue));
                } else {
                    logNext("updated '%s': %s (was: %s)", observableName(change.object), change.name, formatValue(change.newValue), formatValue(change.oldValue));
                }
                dir({
                    newValue: change.newValue,
                    oldValue: change.oldValue
                });
                trace();
                break;
            case 'splice':
                // (array) object, index, added, removed, addedCount, removedCount
                logNext("spliced '%s': index %d, added %d, removed %d", observableName(change.object), change.index, change.addedCount, change.removedCount);
                dir({
                    added: change.added,
                    removed: change.removed
                });
                trace();
                break;
            case 'add':
                // (map, object) object, name, newValue
                logNext("set '%s.%s': %s", observableName(change.object), change.name, formatValue(change.newValue));
                dir({
                    newValue: change.newValue
                });
                trace();
                break;
            case 'delete':
                // (map) object, name, oldValue
                logNext("removed '%s.%s' (was %s)", observableName(change.object), change.name, formatValue(change.oldValue));
                dir({
                    oldValue: change.oldValue
                });
                trace();
                break;
            case 'create':
                // (value) object, newValue
                logNext("set '%s': %s", observableName(change.object), formatValue(change.newValue));
                dir({
                    newValue: change.newValue
                });
                trace();
                break;
            default:
                // generic fallback for future events
                logNext(change.type);
                dir(change);
                break;
        }
    }
}

const consoleSupportsGroups = typeof console.groupCollapsed === "function";
let currentDepth = 0;

function group() {
    // TODO: firefox does not support formatting in groupStart methods..
    console[consoleSupportsGroups ? "groupCollapsed" : "log"].apply(console, arguments);
    currentDepth++;
}

function groupEnd() {
    currentDepth--;
    if (consoleSupportsGroups)
        console.groupEnd();
}

function log() {
    console.log.apply(console, arguments);
}

function dir() {
    console.dir.apply(console, arguments);
}

function trace() {
    // TODO: needs wrapping in firefox?
    console.trace("stack"); // TODO: use stacktrace.js or similar and strip off unrelevant stuff?
}

function closeGroupsOnError() {
    for (let i = 0, m = currentDepth; i < m; i++)
        groupEnd();
}

const closeToken = {
    "\"" : "\"",
    "'" : "'",
    "(" : ")",
    "[" : "]",
    "<" : "]",
    "#" : ""
}

function autoWrap(token, value) {
    if (!value)
        return "";
    return (token || "") + value + (closeToken[token] || "");
}

function observableName(object) {
    return mobx.extras.getDebugName(object);
}

function formatValue(value) {
    if (isPrimitive(value)) {
        if (typeof value === "string" && value.length > 100)
            return value.substr(0, 97) + "..."
        return value;
    } else
        return autoWrap("(", getNameForThis(value));
}

function getNameForThis(who) {
    if (who === null || who === undefined) {
        return "";
    } else if (who && typeof who === "object") {
	    if (who && who.$mobx) {
		    return who.$mobx.name;
        } else if (who.constructor) {
            return who.constructor.name || "object";
        }
	}
	return `${typeof who}`;
}

function isPrimitive(value) {
	return value === null || value === undefined || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { isArray, includes, isEmpty } from 'lodash';

import DefaultIcon from '../../assets/images/media/na.svg';

import {
  StyledMediaPreviewList,
  MediaPreviewFile,
  MediaPreviewImage,
  MediaPreviewItem,
  MediaPreviewText,
} from './StyledMediaPreviewList';

function MediaPreviewList({ hoverable, files }) {
  const IMAGE_PREVIEW_COUNT = 3;
  const getFileType = fileName => fileName.split('.').slice(-1)[0];
  const getSrc = fileURL =>
    fileURL.startsWith('/') ? `${strapi.backendURL}${fileURL}` : fileURL;

  const renderImage = image => {
    const { name, size, url } = image;

    if (size > 2000) {
      return renderFile(image);
    }

    return (
      <MediaPreviewImage className={hoverable ? 'hoverable' : ''}>

          <img src={getSrc(url)} alt={`${name}`} />

        <img src={getSrc(url)} alt={`${name}`} />
      </MediaPreviewImage>
    );
  };

  const renderFile = file => {
    const { mime, name } = file;
    const fileType = includes(mime, 'image') ? 'image' : getFileType(name);

    return (
      <MediaPreviewFile className={hoverable ? 'hoverable' : ''}>

          {fileType}
          <i className={`fa fa-file-${fileType}-o`} />

        {name}
      </MediaPreviewFile>
    );
  };

  const renderItem = file => {
    const { mime } = file;

    return (
      <React.Fragment key={JSON.stringify(file)}>
        {includes(mime, 'image') ? renderImage(file) : renderFile(file)}
      </React.Fragment>
    );
  };

  const renderText = count => {
    return (
      <MediaPreviewText>

          +{count}

      </MediaPreviewText>
    );
  };

  const renderMultipleItems = files => {
    return files.map((file, index) => {
      return (
        <React.Fragment key={JSON.stringify(file)}>
          {index === IMAGE_PREVIEW_COUNT &&
          files.length > IMAGE_PREVIEW_COUNT + 1
            ? renderText(files.length - IMAGE_PREVIEW_COUNT)
            : renderItem(file)}
        </React.Fragment>
      );
    });
  };

  return !!files && !isEmpty(files) ? (

  ) : (
    <MediaPreviewItem>

    </MediaPreviewItem>
  );
}

MediaPreviewList.defaultProps = {
  hoverable: true,
  files: null,
};

MediaPreviewList.propTypes = {
  hoverable: PropTypes.bool,
  files: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
};

export default MediaPreviewList;
<commit_msg>reviews feedback<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { isArray, includes, isEmpty } from 'lodash';

import DefaultIcon from '../../assets/images/media/na.svg';

import {
  StyledMediaPreviewList,
  MediaPreviewFile,
  MediaPreviewImage,
  MediaPreviewItem,
  MediaPreviewText,
} from './StyledMediaPreviewList';

const IMAGE_PREVIEW_COUNT = 3;

function MediaPreviewList({ hoverable, files }) {
  const getFileType = fileName => fileName.split('.').slice(-1)[0];
  const getSrc = fileURL =>
    fileURL.startsWith('/') ? `${strapi.backendURL}${fileURL}` : fileURL;

  const renderImage = image => {
    const { name, size, url } = image;

    if (size > 2000) {
      return renderFile(image);
    }

    return (
      <MediaPreviewImage className={hoverable ? 'hoverable' : ''}>

          <img src={getSrc(url)} alt={`${name}`} />

        <img src={getSrc(url)} alt={`${name}`} />
      </MediaPreviewImage>
    );
  };

  const renderFile = file => {
    const { mime, name } = file;
    const fileType = includes(mime, 'image') ? 'image' : getFileType(name);

    return (
      <MediaPreviewFile className={hoverable ? 'hoverable' : ''}>

          {fileType}
          <i className={`fa fa-file-${fileType}-o`} />

        {name}
      </MediaPreviewFile>
    );
  };

  const renderItem = file => {
    const { mime } = file;

    return (
      <React.Fragment key={JSON.stringify(file)}>
        {includes(mime, 'image') ? renderImage(file) : renderFile(file)}
      </React.Fragment>
    );
  };

  const renderText = count => {
    return (
      <MediaPreviewText>

          +{count}

      </MediaPreviewText>
    );
  };

  const renderMultipleItems = files => {
    return files.map((file, index) => {
      return (
        <React.Fragment key={JSON.stringify(file)}>
          {index === IMAGE_PREVIEW_COUNT &&
          files.length > IMAGE_PREVIEW_COUNT + 1
            ? renderText(files.length - IMAGE_PREVIEW_COUNT)
            : renderItem(file)}
        </React.Fragment>
      );
    });
  };

  return !!files && !isEmpty(files) ? (

  ) : (
    <MediaPreviewItem>

    </MediaPreviewItem>
  );
}

MediaPreviewList.defaultProps = {
  hoverable: true,
  files: null,
};

MediaPreviewList.propTypes = {
  hoverable: PropTypes.bool,
  files: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
};

export default MediaPreviewList;
<|endoftext|>