<commit_before>// use this scoping hack in order to hide objects defined inside the branch
// with the 'let' statement from the global scope.
(function() {
  let Cc = Components.classes;
  let Ci = Components.interfaces;

  let prompts = Cc['@mozilla.org/embedcomp/prompt-service;1'].getService(Ci.nsIPromptService);
  let adban = Cc['@ad-ban.appspot.com/adban;1'].getService().wrappedJSObject;
  let logging = adban.logging;
  let pref_branch = adban.pref_branch;

  let $ = function(id) {
    return document.getElementById(id);
  };

  let _ = function(id, params) {
    const adban_strings = $('adban-strings');
    if (params) {
      return adban_strings.getFormattedString(id, params);
    }
    return adban_strings.getString(id);
  };

  let getCurrentSiteUrl = function() {
    let current_site_url = $('urlbar').value;
    if (current_site_url) {
      // normalize the url for the consumption by adban component.
      if (current_site_url.indexOf('://') == -1) {
        current_site_url = 'http://' + current_site_url;
      }
      current_site_url += '/';
    }
    return current_site_url;
  };

  let conditionalAlert = function(alert_name, msg) {
    alert_name = 'alert-states.' + alert_name;
    if (pref_branch.prefHasUserValue(alert_name) &&
        pref_branch.getBoolPref(alert_name)) {
      logging.info('the alert [%s] is disabled in preferences', alert_name);
      return;
    }
    const state_obj = {
        value: false,
    };
    prompts.alertCheck(window, 'AdBan', msg, _('dont-show-this-message-again'), state_obj);
    if (state_obj.value) {
      logging.info('disabling the alert [%s] in preferences', alert_name);
      pref_branch.setBoolPref(alert_name, true);
    }
  };

  let setupToolbarButtons = function() {
    const nav_bar = $('nav-bar');
    if (!nav_bar) {
      logging.warning('there is no navigation bar in the current window');
      return;
    }
    if ($('adban-toolbarbutton')) {
      logging.warning('the adban-toolbarbutton is already installed');
      return;
    }

    logging.info('adding adban buttons to navigation bar');
    nav_bar.insertItem('adban-toolbarbutton', null, null, false);

    // this 'magic' is necessary for FF, which can't properly handle
    // toolbar.insertItem().
    // See http://forums.mozillazine.org/viewtopic.php?t=189667 .
    nav_bar.setAttribute('currentset', nav_bar.currentSet);
    document.persist('nav-bar', 'currentset');
    logging.info('adban buttons must be added to navigation bar');
  };

  let processDocumentEventHandler = function(e) {
    if (e.type == 'DOMContentLoaded') {
      adban.processDocument(e.originalTarget);
    }
  };

  let enableDocumentsProcessing = function() {
    logging.info('subscribing to DOMContentLoaded event on gBrowser. state_listener_id=[%s]', state_listener_id);
    gBrowser.addEventListener('DOMContentLoaded', processDocumentEventHandler, true);
  };

  let disableDocumentsProcessing = function() {
    logging.info('unsubscribing from DOMContentLoaded event on gBrowser. state_listener_id=[%s]', state_listener_id);
    gBrowser.removeEventListener('DOMContentLoaded', processDocumentEventHandler, true);
  };

  let onStateChange = function() {
    const cmd_stop = $('adban-cmd-stop');
    const cmd_start = $('adban-cmd-start');
    const toolbarbutton = $('adban-toolbarbutton');
    if (adban.isActive()) {
      cmd_start.setAttribute('disabled', 'true');
      cmd_stop.removeAttribute('disabled');
      if (toolbarbutton) {
        toolbarbutton.removeAttribute('adban-disabled');
      }
      enableDocumentsProcessing();
    }
    else {
      cmd_stop.setAttribute('disabled', 'true');
      cmd_start.removeAttribute('disabled');
      if (toolbarbutton) {
        toolbarbutton.setAttribute('adban-disabled', 'true');
      }
      disableDocumentsProcessing();
    }
  };

  let onMenuPopup = function() {
    const cmd_add_per_site_whitelist = $('adban-cmd-add-per-site-whitelist');
    const cmd_remove_per_site_whitelist = $('adban-cmd-remove-per-site-whitelist');
    const current_site_url = getCurrentSiteUrl();
    const has_per_site_whitelist = adban.hasPerSiteWhitelist(current_site_url);
    if (has_per_site_whitelist == null) {
      cmd_add_per_site_whitelist.setAttribute('disabled', 'true');
      cmd_remove_per_site_whitelist.setAttribute('disabled', 'true');
    }
    else if (has_per_site_whitelist) {
      cmd_add_per_site_whitelist.setAttribute('disabled', 'true');
      cmd_remove_per_site_whitelist.removeAttribute('disabled');
    }
    else {
      cmd_remove_per_site_whitelist.setAttribute('disabled', 'true');
      cmd_add_per_site_whitelist.removeAttribute('disabled');
    }
  };

  let cmdComplaint = function() {
    const complaint_callback = function(site_url, comment) {
      const success_callback = function() {
        conditionalAlert('complaint-sent', _('complaint-sent', [site_url]));
      };
      const failure_callback = function(error) {
        conditionalAlert('complaint-send-error', _('complaint-send-error', [site_url, error]));
      };
      adban.sendUrlComplaint(site_url, comment, success_callback, failure_callback);
    };

    // Don't use $('urlbar').value as initial_site_url, since this value can be broken.
    // For example, Chrome likes cutting url scheme, while Opera 11 cuts query parameters
    // from the urlbar.
    const initial_site_url = gBrowser.currentURI.spec;
    const complaint_window = openDialog('chrome://adban/content/report-ads-dialog.xul',
        'adban-complaint-window', '', complaint_callback, initial_site_url);
    complaint_window.focus();
  };

  let cmdStop = function() {
    adban.stop();
    conditionalAlert('adban-stopped', _('adban-stopped'));
  };

  let cmdStart = function() {
    adban.start();
    conditionalAlert('adban-started', _('adban-started'));
  };

  let cmdAddPerSiteWhitelist = function() {
    const current_site_url = getCurrentSiteUrl();
    adban.addPerSiteWhitelist(current_site_url);
  };

  let cmdRemovePerSiteWhitelist = function() {
    const current_site_url = getCurrentSiteUrl();
    adban.removePerSiteWhitelist(current_site_url);
  };

  let cmdHelp = function() {
    adban.openTab('help', adban.HELP_URL);
  };

  let cmdDonate = function() {
    adban.openTab('donate', adban.DONATE_URL);
  };

  let cmdRecommend = function() {
    adban.openTab('recommend', adban.RECOMMEND_URL);
  };

  let cmdReportBug = function() {
    adban.openTab('report-bug', adban.REPORT_BUG_URL);
  };

  let state_listener_id;
  let is_initially_active;

  let init = function() {
    logging.info('initializing browser-overlay');
    window.removeEventListener('load', init, false);

    $('adban-menupopup').addEventListener('popupshowing', onMenuPopup, false);
    $('adban-toolbarbutton-menupopup').addEventListener('popupshowing', onMenuPopup, false);

    $('adban-cmd-complaint').addEventListener('command', cmdComplaint, false);
    $('adban-cmd-stop').addEventListener('command', cmdStop, false);
    $('adban-cmd-start').addEventListener('command', cmdStart, false);
    $('adban-cmd-add-per-site-whitelist').addEventListener('command', cmdAddPerSiteWhitelist, false);
    $('adban-cmd-remove-per-site-whitelist').addEventListener('command', cmdRemovePerSiteWhitelist, false);
    $('adban-cmd-help').addEventListener('command', cmdHelp, false);
    $('adban-cmd-donate').addEventListener('command', cmdDonate, false);
    $('adban-cmd-recommend').addEventListener('command', cmdRecommend, false);
    $('adban-cmd-report-bug').addEventListener('command', cmdReportBug, false);

    const state_change_results = adban.subscribeToStateChange(onStateChange);
    state_listener_id = state_change_results[0];
    is_initially_active = state_change_results[1];

    // defer first run verification due to FF bug, which prevents from
    // toolbar updating immediately in the window.onload event handler.
    // Read more at http://blog.pearlcrescent.com/archives/24 .
    const first_run_callback = function() {
      if (!pref_branch.prefHasUserValue('first-run')) {
        logging.info('first run of AdBan');
        adban.firstRun();
        setupToolbarButtons();
        pref_branch.setBoolPref('first-run', true);
        pref_branch.setBoolPref('toolbarbutton-installed', true);

        // open help page only after a delay, otherwise it won't
        // be opened under FF3.6 due to unknown reason.
        setTimeout(cmdHelp, 2000);
      }
      else if (!pref_branch.prefHasUserValue('toolbarbutton-installed')) {
        logging.info('installing adban-toolbarbutton for the user of the previous AdBan version');
        setupToolbarButtons();
        pref_branch.setBoolPref('toolbarbutton-installed', true);
      }

      onStateChange(is_initially_active);
    };
    adban.executeDeferred(first_run_callback);

    window.addEventListener('unload', shutdown, false);
    logging.info('browser-overlay has been initialized. state_listener_id=[%s]', state_listener_id);
  };

  let shutdown = function() {
    logging.info('shutting down browser-overlay. state_listener_id=[%s]', state_listener_id);
    window.removeEventListener('unload', shutdown, false);

    if (adban.isActive()) {
      disableDocumentsProcessing();
    }

    adban.unsubscribeFromStateChange(state_listener_id);

    $('adban-cmd-complaint').removeEventListener('command', cmdComplaint, false);
    $('adban-cmd-stop').removeEventListener('command', cmdStop, false);
    $('adban-cmd-start').removeEventListener('command', cmdStart, false);
    $('adban-cmd-add-per-site-whitelist').removeEventListener('command', cmdAddPerSiteWhitelist, false);
    $('adban-cmd-remove-per-site-whitelist').removeEventListener('command', cmdRemovePerSiteWhitelist, false);
    $('adban-cmd-help').removeEventListener('command', cmdHelp, false);
    $('adban-cmd-donate').removeEventListener('command', cmdDonate, false);
    $('adban-cmd-recommend').removeEventListener('command', cmdRecommend, false);
    $('adban-cmd-report-bug').removeEventListener('command', cmdReportBug, false);

    $('adban-menupopup').removeEventListener('popupshowing', onMenuPopup, false);
    $('adban-toolbarbutton-menupopup').removeEventListener('popupshowing', onMenuPopup, false);

    logging.info('browser-overlay has been shut down. state_listener_id=[%s]', state_listener_id);
  };

  window.addEventListener('load', init, false);
})();

<commit_msg>add event listener to adban-toolbarbutton-menupopup only after the adban-menupopup is installed on a toolbar<commit_after>// use this scoping hack in order to hide objects defined inside the branch
// with the 'let' statement from the global scope.
(function() {
  let Cc = Components.classes;
  let Ci = Components.interfaces;

  let prompts = Cc['@mozilla.org/embedcomp/prompt-service;1'].getService(Ci.nsIPromptService);
  let adban = Cc['@ad-ban.appspot.com/adban;1'].getService().wrappedJSObject;
  let logging = adban.logging;
  let pref_branch = adban.pref_branch;

  let $ = function(id) {
    return document.getElementById(id);
  };

  let _ = function(id, params) {
    const adban_strings = $('adban-strings');
    if (params) {
      return adban_strings.getFormattedString(id, params);
    }
    return adban_strings.getString(id);
  };

  let getCurrentSiteUrl = function() {
    let current_site_url = $('urlbar').value;
    if (current_site_url) {
      // normalize the url for the consumption by adban component.
      if (current_site_url.indexOf('://') == -1) {
        current_site_url = 'http://' + current_site_url;
      }
      current_site_url += '/';
    }
    return current_site_url;
  };

  let conditionalAlert = function(alert_name, msg) {
    alert_name = 'alert-states.' + alert_name;
    if (pref_branch.prefHasUserValue(alert_name) &&
        pref_branch.getBoolPref(alert_name)) {
      logging.info('the alert [%s] is disabled in preferences', alert_name);
      return;
    }
    const state_obj = {
        value: false,
    };
    prompts.alertCheck(window, 'AdBan', msg, _('dont-show-this-message-again'), state_obj);
    if (state_obj.value) {
      logging.info('disabling the alert [%s] in preferences', alert_name);
      pref_branch.setBoolPref(alert_name, true);
    }
  };

  let setupToolbarButtons = function() {
    const nav_bar = $('nav-bar');
    if (!nav_bar) {
      logging.warning('there is no navigation bar in the current window');
      return;
    }
    if ($('adban-toolbarbutton')) {
      logging.warning('the adban-toolbarbutton is already installed');
      return;
    }

    logging.info('adding adban buttons to navigation bar');
    nav_bar.insertItem('adban-toolbarbutton', null, null, false);

    // this 'magic' is necessary for FF, which can't properly handle
    // toolbar.insertItem().
    // See http://forums.mozillazine.org/viewtopic.php?t=189667 .
    nav_bar.setAttribute('currentset', nav_bar.currentSet);
    document.persist('nav-bar', 'currentset');
    logging.info('adban buttons must be added to navigation bar');
  };

  let processDocumentEventHandler = function(e) {
    if (e.type == 'DOMContentLoaded') {
      adban.processDocument(e.originalTarget);
    }
  };

  let enableDocumentsProcessing = function() {
    logging.info('subscribing to DOMContentLoaded event on gBrowser. state_listener_id=[%s]', state_listener_id);
    gBrowser.addEventListener('DOMContentLoaded', processDocumentEventHandler, true);
  };

  let disableDocumentsProcessing = function() {
    logging.info('unsubscribing from DOMContentLoaded event on gBrowser. state_listener_id=[%s]', state_listener_id);
    gBrowser.removeEventListener('DOMContentLoaded', processDocumentEventHandler, true);
  };

  let onStateChange = function() {
    const cmd_stop = $('adban-cmd-stop');
    const cmd_start = $('adban-cmd-start');
    const toolbarbutton = $('adban-toolbarbutton');
    if (adban.isActive()) {
      cmd_start.setAttribute('disabled', 'true');
      cmd_stop.removeAttribute('disabled');
      if (toolbarbutton) {
        toolbarbutton.removeAttribute('adban-disabled');
      }
      enableDocumentsProcessing();
    }
    else {
      cmd_stop.setAttribute('disabled', 'true');
      cmd_start.removeAttribute('disabled');
      if (toolbarbutton) {
        toolbarbutton.setAttribute('adban-disabled', 'true');
      }
      disableDocumentsProcessing();
    }
  };

  let onMenuPopup = function() {
    const cmd_add_per_site_whitelist = $('adban-cmd-add-per-site-whitelist');
    const cmd_remove_per_site_whitelist = $('adban-cmd-remove-per-site-whitelist');
    const current_site_url = getCurrentSiteUrl();
    const has_per_site_whitelist = adban.hasPerSiteWhitelist(current_site_url);
    if (has_per_site_whitelist == null) {
      cmd_add_per_site_whitelist.setAttribute('disabled', 'true');
      cmd_remove_per_site_whitelist.setAttribute('disabled', 'true');
    }
    else if (has_per_site_whitelist) {
      cmd_add_per_site_whitelist.setAttribute('disabled', 'true');
      cmd_remove_per_site_whitelist.removeAttribute('disabled');
    }
    else {
      cmd_remove_per_site_whitelist.setAttribute('disabled', 'true');
      cmd_add_per_site_whitelist.removeAttribute('disabled');
    }
  };

  let cmdComplaint = function() {
    const complaint_callback = function(site_url, comment) {
      const success_callback = function() {
        conditionalAlert('complaint-sent', _('complaint-sent', [site_url]));
      };
      const failure_callback = function(error) {
        conditionalAlert('complaint-send-error', _('complaint-send-error', [site_url, error]));
      };
      adban.sendUrlComplaint(site_url, comment, success_callback, failure_callback);
    };

    // Don't use $('urlbar').value as initial_site_url, since this value can be broken.
    // For example, Chrome likes cutting url scheme, while Opera 11 cuts query parameters
    // from the urlbar.
    const initial_site_url = gBrowser.currentURI.spec;
    const complaint_window = openDialog('chrome://adban/content/report-ads-dialog.xul',
        'adban-complaint-window', '', complaint_callback, initial_site_url);
    complaint_window.focus();
  };

  let cmdStop = function() {
    adban.stop();
    conditionalAlert('adban-stopped', _('adban-stopped'));
  };

  let cmdStart = function() {
    adban.start();
    conditionalAlert('adban-started', _('adban-started'));
  };

  let cmdAddPerSiteWhitelist = function() {
    const current_site_url = getCurrentSiteUrl();
    adban.addPerSiteWhitelist(current_site_url);
  };

  let cmdRemovePerSiteWhitelist = function() {
    const current_site_url = getCurrentSiteUrl();
    adban.removePerSiteWhitelist(current_site_url);
  };

  let cmdHelp = function() {
    adban.openTab('help', adban.HELP_URL);
  };

  let cmdDonate = function() {
    adban.openTab('donate', adban.DONATE_URL);
  };

  let cmdRecommend = function() {
    adban.openTab('recommend', adban.RECOMMEND_URL);
  };

  let cmdReportBug = function() {
    adban.openTab('report-bug', adban.REPORT_BUG_URL);
  };

  let state_listener_id;
  let is_initially_active;

  let init = function() {
    logging.info('initializing browser-overlay');
    window.removeEventListener('load', init, false);

    $('adban-cmd-complaint').addEventListener('command', cmdComplaint, false);
    $('adban-cmd-stop').addEventListener('command', cmdStop, false);
    $('adban-cmd-start').addEventListener('command', cmdStart, false);
    $('adban-cmd-add-per-site-whitelist').addEventListener('command', cmdAddPerSiteWhitelist, false);
    $('adban-cmd-remove-per-site-whitelist').addEventListener('command', cmdRemovePerSiteWhitelist, false);
    $('adban-cmd-help').addEventListener('command', cmdHelp, false);
    $('adban-cmd-donate').addEventListener('command', cmdDonate, false);
    $('adban-cmd-recommend').addEventListener('command', cmdRecommend, false);
    $('adban-cmd-report-bug').addEventListener('command', cmdReportBug, false);

    const state_change_results = adban.subscribeToStateChange(onStateChange);
    state_listener_id = state_change_results[0];
    is_initially_active = state_change_results[1];

    // defer first run verification due to FF bug, which prevents from
    // toolbar updating immediately in the window.onload event handler.
    // Read more at http://blog.pearlcrescent.com/archives/24 .
    const first_run_callback = function() {
      if (!pref_branch.prefHasUserValue('first-run')) {
        logging.info('first run of AdBan');
        adban.firstRun();
        setupToolbarButtons();
        pref_branch.setBoolPref('first-run', true);
        pref_branch.setBoolPref('toolbarbutton-installed', true);

        // open help page only after a delay, otherwise it won't
        // be opened under FF3.6 due to unknown reason.
        setTimeout(cmdHelp, 2000);
      }
      else if (!pref_branch.prefHasUserValue('toolbarbutton-installed')) {
        logging.info('installing adban-toolbarbutton for the user of the previous AdBan version');
        setupToolbarButtons();
        pref_branch.setBoolPref('toolbarbutton-installed', true);
      }

      $('adban-menupopup').addEventListener('popupshowing', onMenuPopup, false);
      if ($('adban-toolbarbutton')) {
        $('adban-toolbarbutton-menupopup').addEventListener('popupshowing', onMenuPopup, false);
      }

      onStateChange(is_initially_active);
    };
    adban.executeDeferred(first_run_callback);

    window.addEventListener('unload', shutdown, false);
    logging.info('browser-overlay has been initialized. state_listener_id=[%s]', state_listener_id);
  };

  let shutdown = function() {
    logging.info('shutting down browser-overlay. state_listener_id=[%s]', state_listener_id);
    window.removeEventListener('unload', shutdown, false);

    if (adban.isActive()) {
      disableDocumentsProcessing();
    }

    adban.unsubscribeFromStateChange(state_listener_id);

    $('adban-menupopup').removeEventListener('popupshowing', onMenuPopup, false);
    if ($('adban-toolbarbutton')) {
      $('adban-toolbarbutton-menupopup').removeEventListener('popupshowing', onMenuPopup, false);
    }

    $('adban-cmd-complaint').removeEventListener('command', cmdComplaint, false);
    $('adban-cmd-stop').removeEventListener('command', cmdStop, false);
    $('adban-cmd-start').removeEventListener('command', cmdStart, false);
    $('adban-cmd-add-per-site-whitelist').removeEventListener('command', cmdAddPerSiteWhitelist, false);
    $('adban-cmd-remove-per-site-whitelist').removeEventListener('command', cmdRemovePerSiteWhitelist, false);
    $('adban-cmd-help').removeEventListener('command', cmdHelp, false);
    $('adban-cmd-donate').removeEventListener('command', cmdDonate, false);
    $('adban-cmd-recommend').removeEventListener('command', cmdRecommend, false);
    $('adban-cmd-report-bug').removeEventListener('command', cmdReportBug, false);

    logging.info('browser-overlay has been shut down. state_listener_id=[%s]', state_listener_id);
  };

  window.addEventListener('load', init, false);
})();

<|endoftext|>


<commit_before>/**
* F7 Build Configuration
* Don't modify this file!
* If you want to build custom version of F7, just put build-config-custom.js with the required configuration in this folder. Or build it using command line:
* $ npm run build:prod -- --config path/to/config.js --output path/to/output/folder
*/

const config = {
  target: 'universal',
  rtl: false,
  components: [
    // Modals
    'dialog',
    'popup',
    'login-screen',
    'popover',
    'actions',
    'sheet',
    'toast',

    // Loaders
    'preloader',
    'progressbar',

    // List Components
    'sortable',
    'swipeout',
    'accordion',
    'contacts-list',
    'virtual-list',
    'list-index',

    // Timeline
    'timeline',

    // Tabs
    'tabs',

    // Panel
    'panel',

    // Card
    'card',

    // Chip
    'chip',

    // Form Components
    'form',
    'input',
    'checkbox',
    'radio',
    'toggle',
    'range',
    'stepper',
    'smart-select',

    // Grid
    'grid',

    // Pickers
    'calendar',
    'picker',

    // Page Components
    'infinite-scroll',
    'pull-to-refresh',
    'lazy',

    // Data table
    'data-table',

    // FAB
    'fab',

    // Searchbar
    'searchbar',

    // Messages
    'messages',
    'messagebar',

    // Swiper
    'swiper',

    // Photo Browser
    'photo-browser',

    // Notifications
    'notification',

    // Autocomplete
    'autocomplete',

    // Tooltip
    'tooltip',

    // Gauge
    'gauge',

    // VI Video Ads
    'vi',

    // Typography
    'typography',
  ],
  darkTheme: true,
  themes: [
    'ios',
    'md',
  ],
  ios: {
    themeColor: '#007aff',
    colors: {
      red: '#ff3b30',
      green: '#4cd964',
      blue: '#007aff',
      pink: '#ff2d55',
      yellow: '#ffcc00',
      orange: '#ff9500',
      gray: '#8e8e93',
      white: '#ffffff',
      black: '#000000',
      /*
      purple: '#5856d6',
      deeppurple: '#673ab7',
      indigo: '#3f51b5',
      lightblue: '#5ac8fa',
      cyan: '#00bcd4',
      teal: '#009688',
      lightgreen: '#8bc34a',
      lime: '#cddc39',
      amber: '#ffc107',
      deeporange: '#ff5722',
      brown: '#795548',
      bluegray: '#607d8b',
      */
    },
  },
  md: {
    themeColor: '#2196f3',
    colors: {
      red: '#f44336',
      green: '#4caf50',
      blue: '#2196f3',
      pink: '#e91e63',
      yellow: '#ffeb3b',
      orange: '#ff9800',
      gray: '#9e9e9e',
      white: '#ffffff',
      black: '#000000',
      /*
      purple: '#9c27b0',
      deeppurple: '#673ab7',
      indigo: '#3f51b5',
      lightblue: '#03a9f4',
      cyan: '#00bcd4',
      teal: '#009688',
      lightgreen: '#8bc34a',
      lime: '#cddc39',
      amber: '#ffc107',
      deeporange: '#ff5722',
      brown: '#795548',
      bluegray: '#607d8b',
      */
    },
  },
};

module.exports = config;
<commit_msg>Core: fix custom build config info<commit_after>/**
* F7 Build Configuration
* Don't modify this file!
* If you want to build custom version of F7, just put build-config-custom.js with the required configuration in this folder. Or build it using command line:
* $ npm run build-core:prod -- --config path/to/config.js --output path/to/output/folder
*/

const config = {
  target: 'universal',
  rtl: false,
  components: [
    // Modals
    'dialog',
    'popup',
    'login-screen',
    'popover',
    'actions',
    'sheet',
    'toast',

    // Loaders
    'preloader',
    'progressbar',

    // List Components
    'sortable',
    'swipeout',
    'accordion',
    'contacts-list',
    'virtual-list',
    'list-index',

    // Timeline
    'timeline',

    // Tabs
    'tabs',

    // Panel
    'panel',

    // Card
    'card',

    // Chip
    'chip',

    // Form Components
    'form',
    'input',
    'checkbox',
    'radio',
    'toggle',
    'range',
    'stepper',
    'smart-select',

    // Grid
    'grid',

    // Pickers
    'calendar',
    'picker',

    // Page Components
    'infinite-scroll',
    'pull-to-refresh',
    'lazy',

    // Data table
    'data-table',

    // FAB
    'fab',

    // Searchbar
    'searchbar',

    // Messages
    'messages',
    'messagebar',

    // Swiper
    'swiper',

    // Photo Browser
    'photo-browser',

    // Notifications
    'notification',

    // Autocomplete
    'autocomplete',

    // Tooltip
    'tooltip',

    // Gauge
    'gauge',

    // VI Video Ads
    'vi',

    // Typography
    'typography',
  ],
  darkTheme: true,
  themes: [
    'ios',
    'md',
  ],
  ios: {
    themeColor: '#007aff',
    colors: {
      red: '#ff3b30',
      green: '#4cd964',
      blue: '#007aff',
      pink: '#ff2d55',
      yellow: '#ffcc00',
      orange: '#ff9500',
      gray: '#8e8e93',
      white: '#ffffff',
      black: '#000000',
      /*
      purple: '#5856d6',
      deeppurple: '#673ab7',
      indigo: '#3f51b5',
      lightblue: '#5ac8fa',
      cyan: '#00bcd4',
      teal: '#009688',
      lightgreen: '#8bc34a',
      lime: '#cddc39',
      amber: '#ffc107',
      deeporange: '#ff5722',
      brown: '#795548',
      bluegray: '#607d8b',
      */
    },
  },
  md: {
    themeColor: '#2196f3',
    colors: {
      red: '#f44336',
      green: '#4caf50',
      blue: '#2196f3',
      pink: '#e91e63',
      yellow: '#ffeb3b',
      orange: '#ff9800',
      gray: '#9e9e9e',
      white: '#ffffff',
      black: '#000000',
      /*
      purple: '#9c27b0',
      deeppurple: '#673ab7',
      indigo: '#3f51b5',
      lightblue: '#03a9f4',
      cyan: '#00bcd4',
      teal: '#009688',
      lightgreen: '#8bc34a',
      lime: '#cddc39',
      amber: '#ffc107',
      deeporange: '#ff5722',
      brown: '#795548',
      bluegray: '#607d8b',
      */
    },
  },
};

module.exports = config;
<|endoftext|>


<commit_before>var ObsSvg = {

    roof_base: '/roof/',
    roof_idbase: 'roof_',
    tele_base: '/telescope/',
    tele_idbase: 'telespope_',
    obsSvgs: [],

    addObs: function (name) {
        ObsSvg.obsSvgs.push(document.getElementById(name).contentDocument);
        log("Initializing observatory svg " + name);
    },

    translateRoof: function (percentOpen) {
        for (i=0; i<ObsSvg.obsSvgs.length; i++) {
            var roof = ObsSvg.obsSvgs[i].getElementById("roof");
            roof.setAttribute("transform", 'translate(' + 290*(1-percentOpen/100) + ',0)' );
        }
    },

    rotateTelescope: function (degrees) {
    	// You have to rotate the telescope down from the vertical,
	// but we always store and pass in degrees up from the horizontal.
        var transform  = 'translate(535,210) rotate(' + (90-degrees) + ') translate(-535,-210)';

        for (i=0; i<ObsSvg.obsSvgs.length; i++) {
            var telescope = ObsSvg.obsSvgs[i].getElementById("telescope");
            telescope.setAttribute("transform", transform);
        }
    },

    rotateTelescopeDeclination: function (declination) {
        var degrees  = (declination - 42.5);
        ObsSvg.rotateTelescope(degrees) ;
    },

};
<commit_msg>change to ObsSvg.rotateTelescopeDeclincation so that it converts to declination properly<commit_after>var ObsSvg = {

    roof_base: '/roof/',
    roof_idbase: 'roof_',
    tele_base: '/telescope/',
    tele_idbase: 'telespope_',
    obsSvgs: [],

    addObs: function (name) {
        ObsSvg.obsSvgs.push(document.getElementById(name).contentDocument);
        log("Initializing observatory svg " + name);
    },

    translateRoof: function (percentOpen) {
        for (i=0; i<ObsSvg.obsSvgs.length; i++) {
            var roof = ObsSvg.obsSvgs[i].getElementById("roof");
            roof.setAttribute("transform", 'translate(' + 290*(1-percentOpen/100) + ',0)' );
        }
    },

    rotateTelescope: function (degrees) {
    	// You have to rotate the telescope down from the vertical,
	    // but we always store and pass in degrees up from the horizontal.
        var transform  = 'translate(535,210) rotate(' + (90-degrees) + ') translate(-535,-210)';

        for (i=0; i<ObsSvg.obsSvgs.length; i++) {
            var telescope = ObsSvg.obsSvgs[i].getElementById("telescope");
            telescope.setAttribute("transform", transform);
        }
    },

    rotateTelescopeDeclination: function (declination) {
        var degrees  = (parseFloat(declination) + 42.5);
        ObsSvg.rotateTelescope(degrees) ;
    },

};
<|endoftext|>


<commit_before>angular.module('arBlog')
.controller('PostsCtrl',[
	'$scope',
	'posts',
	'$window',
	function($scope,posts,$window){
		$scope.posts = posts.posts;
		//empty object that will receive form field data
		$scope.post = {};
		//message for showing in form
		$scope.what = 'New Post';
		//success msg for post created
		$scope.created = false;

		$scope.addOrEditPost = function(){
			posts.create($scope.post)
			//clear form fields
			$scope.post = {};
			$scope.created = 'Post successfuly created';
		};

		//for confirmation before delete is necessary a directive...
		$scope.removePost = function(post){
			posts.delete(post);
		};
	}
]);<commit_msg>confirm before delete post<commit_after>angular.module('arBlog')
.controller('PostsCtrl',[
	'$scope',
	'posts',
	'$window',
	function($scope,posts,$window){
		$scope.posts = posts.posts;
		//empty object that will receive form field data
		$scope.post = {};
		//message for showing in form
		$scope.what = 'New Post';
		//success msg for post created
		$scope.created = false;

		$scope.addOrEditPost = function(){
			posts.create($scope.post)
			//clear form fields
			$scope.post = {};
			$scope.created = 'Post successfuly created';
		};

		$scope.removePost = function(post){
			if(confirm('are you sure?')){
				posts.delete(post);
			}
		};
	}
]);<|endoftext|>


<commit_before>module.exports = function(Backbone, _, SearchShop) {
  return Backbone.View.extend({
    el: $('body'), // attaches `this.el` to an existing element.

    events: {
      'click a.addItem': 'addToCart',
      'click a.removeItem': 'removeFromCart',
      'click li.search-tab a': 'switchTab',
      'click #toggleCart': 'toggleCartPopover'
    },

    initialize: function(){
      // fixes loss of context for 'this' within methods.
      _.bindAll(this, 'render', 'switchTab', 'addToCart', 'toggleCartPopover');
      this.render(); // not all views are self-rendering. This one is.
    },

    render: function(){
      console.log('render opplist view.');
    },

    // TODO - review if this is the right placement.
    toggleCartPopover: function(e) {
      $('#toggleCart').popover('toggle');
      return false;
    },

    addToCart: function(e) {
      // TODO HACK -- instantiate the model
      var oppInstance = new SearchShop.Model.OppModel({
        benefitName: $(e.currentTarget).data('bname'),
        benefitType: $(e.currentTarget).data('btype')
      });
      SearchShop.cart.add(oppInstance);
      $(e.currentTarget)
        .text('remove')
        .removeClass('addItem')
        .addClass('removeItem');
      return false;
    },

    removeFromCart: function(e) {
      var oppInstance = new SearchShop.Model.OppModel({
        benefitName: $(e.currentTarget).data('bname'),
        benefitType: $(e.currentTarget).data('btype')
      });

      SearchShop.cart.remove(oppInstance);
      $(e.currentTarget)
        .text('add')
        .removeClass('removeItem')
        .addClass('addItem');
      return false;
    },

    switchTab: function(e) {
      var targetId = $(e.currentTarget).attr('id');
      $('.search-tabs .active').removeClass('active');
      $(e.currentTarget).parent().addClass('active');
      if (targetId == 'all') {
        $('.opportunities-container').children().each(function(index, element){
          $(element).show();
        });
      }
      else {
        $('.opportunities-container').children().each(function(index, element){
          $(element).hide()
        });
        $('.' + targetId + '-container').show();
      }
    }
  });
}
<commit_msg>Translating cart actions.<commit_after>module.exports = function(Backbone, _, SearchShop) {
  return Backbone.View.extend({
    el: $('body'), // attaches `this.el` to an existing element.

    events: {
      'click a.addItem': 'addToCart',
      'click a.removeItem': 'removeFromCart',
      'click li.search-tab a': 'switchTab',
      'click #toggleCart': 'toggleCartPopover'
    },

    initialize: function(){
      // fixes loss of context for 'this' within methods.
      _.bindAll(this, 'render', 'switchTab', 'addToCart', 'toggleCartPopover');
      this.render(); // not all views are self-rendering. This one is.
    },

    render: function(){
      console.log('render opplist view.');
    },

    // TODO - review if this is the right placement.
    toggleCartPopover: function(e) {
      $('#toggleCart').popover('toggle');
      return false;
    },

    addToCart: function(e) {
      // TODO HACK -- instantiate the model
      var oppInstance = new SearchShop.Model.OppModel({
        benefitName: $(e.currentTarget).data('bname'),
        benefitType: $(e.currentTarget).data('btype')
      });
      SearchShop.cart.add(oppInstance);
      $(e.currentTarget)
        .text('eliminar')
        .removeClass('addItem')
        .addClass('removeItem');
      return false;
    },

    removeFromCart: function(e) {
      var oppInstance = new SearchShop.Model.OppModel({
        benefitName: $(e.currentTarget).data('bname'),
        benefitType: $(e.currentTarget).data('btype')
      });

      SearchShop.cart.remove(oppInstance);
      $(e.currentTarget)
        .text('aggregar')
        .removeClass('removeItem')
        .addClass('addItem');
      return false;
    },

    switchTab: function(e) {
      var targetId = $(e.currentTarget).attr('id');
      $('.search-tabs .active').removeClass('active');
      $(e.currentTarget).parent().addClass('active');
      if (targetId == 'all') {
        $('.opportunities-container').children().each(function(index, element){
          $(element).show();
        });
      }
      else {
        $('.opportunities-container').children().each(function(index, element){
          $(element).hide()
        });
        $('.' + targetId + '-container').show();
      }
    }
  });
}
<|endoftext|>


<commit_before>/*
 * Guide.js
 * https://github.com/TheLeanMachine/Guide.js
 *
 * Copyright (c) 2013 Kai Hoelscher
 * Licensed under the MIT license.
 */

// TODO: [BUG]     ...
// TODO: [TEST]    activate() and deactivate() AND
// TODO: [TEST]    Module exporting(?), e.g. for require.js
// TODO: [FEATURE] Provide HTML template for Guide
// TODO: [FEATURE] Render parameters? (etc. where to render: Position clockwise? Relative to center?)
// TODO: [FEATURE] New Guide type: GuidedTour() ...at first, just a collection of Guiders
// TODO: [FEATURE] Guide parsing from JSON
// TODO: [REFACTOR] expose concrete 'classes' instead of generic 'newGuide()' method: HelpBox, GuidedTour,...
// TODO: [REFACTOR] Rename: validate*() -> throwIfNot*() / check*()
(function (undefined) { // we always get 'undefined' here, since this code is directly invoked without arguments!

  //
  // 'constants'
  //
  var GLOBAL_CONTEXT = this; // 'window' in the browser, or 'global' on the server (see very bottom of this file)

  var GUIDES = [];

  var GUIDE_TYPES = {
    SIMPLE_HELP_BOX: 'simple_help_box'
  };

  var COMMONJS_AVAILABLE = (typeof module !== 'undefined' && module.exports); // checks for node.js, too

  /*global ender:false */
  var ENDER_AVAILABLE = typeof ender === 'undefined';

  /*global define:false */
  var REQUIREJS_AVAILABLE = (typeof define === "function") && define.amd;

  var DOC_URL = 'https://github.com/TheLeanMachine/Guide.js/blob/master/README.md';

  /**
   * Creates a new Guide based on the passed configuration.
   * @param guideConfig TODO doc
   */
  function newGuide(guideConfig) {
    var guide;

    try {
      guide = createGuideByType(guideConfig);
      GUIDES.push(guide);
      return guide;
    } catch(err) {
      logError('Unable to load Guide: ' + err.message);
      return new EmptyGuide();
    }
  }

  function createGuideByType(guideConfig) {
    throwIfInvalidConfig(guideConfig);

    return new HelpBoxGuide(guideConfig);
  }

  function throwIfInvalidConfig(guideConfig) {
    throwIfNotDefined(guideConfig, '"guideConfig" must not be empty.');
    throwIfNoObject(guideConfig, '"guideConfig" must be of type "Object".');
    throwIfInvalidGuideType(guideConfig, '"guideConfig.type" is not defined or is an unknown type.');
    // TODO validateRenderAdaptor(...) - instance check etc.
  }

  function EmptyGuide() {
    // TODO implement Guide interface (activate(), ...)

    this.isLoaded = function() { return false; };
  }

  /**
   * A simple help box that gets displayed for a certain amount of time.
   * @param guideConfig TODO doc
   * @constructor
   */
  function HelpBoxGuide(guideConfig) {
    var renderAdapter = guideConfig.renderAdapter;
    var targetCssId = guideConfig.renderTarget;

    /**
     * Triggers the Guide to do its work: Display a help box, start a tour with Guiders etc.
     */
    function activate() { // TODO rename to 'augment()' or sth. else?

      var buttonCssId = guideConfig.renderTrigger;
      var content = guideConfig.text;
      var fadeOutMillis = guideConfig.fadeOutMillis;
      var displayDuration = guideConfig.displayDuration;

      renderAdapter.renderTo(targetCssId, content, buttonCssId, displayDuration, fadeOutMillis);
    }

    // TODO add doc
    function deactivate() {
      renderAdapter.hide(targetCssId); // naive implementation
    }

    function isLoaded() {
      return true;
    }

    this.activate = activate;
    this.deactivate = deactivate;
    this.isLoaded = isLoaded;
  }

  // TODO add doc
  function JQueryRenderAdapter($) {
    var helpBoxCssId = 'myTestHelpBox';

    // TODO add doc
    function renderTo(renderTarget, content, displayDuration, fadeOutMillis) {
      var helpBox;

      $(renderTarget).prepend('

Immediate Help!
' + content + '
');
      helpBox = renderTarget + " div.helpBox";
      setTimeout(function() {
        $(helpBox).fadeOut(fadeOutMillis);
      }, displayDuration);
    }

    function hide() {
      $('#' + helpBoxCssId).hide();
    }

    this.renderTo = renderTo;
    this.hide = hide;
  }

  /**
   * Deactivates all Guides (ATM this means to hide them).
   */
  function deactivateAll() {
    forEachIn(GUIDES, function(guide) {
      guide.deactivate();
    });
  }

  /**
   * Activates all Guides (ATM this means to display them, again).
   */
  function activateAll() {
    forEachIn(GUIDES, function(guide) {
      guide.activate();
    });
  }

  /**
   * Creates a new Guide from a JSON definition.
   * @param jsonGuide the JSON representing the Guide for the website to be augmented
   */
  function parseGuideFromJson(jsonGuide) {
    logError('Not yet implemented.');
  }

  //
  // Helper functions
  //
  function forEachIn(array, fn) {
    var i;

    for (i=0; i<array.length; ++i) {
      fn(array[i]);
    }
  }

  function objectHasPropertyWithValue(obj, val) {
    var key;
    for (key in obj) {
      if (obj.hasOwnProperty(key) && obj[key] === val) {
        return true;
      }
    }
    return false;
  }

  function throwIfInvalidGuideType(guideConfig, msg) {
    if(!guideConfig.type || !objectHasPropertyWithValue(GUIDE_TYPES, guideConfig.type)) {
      throwError(msg);
    }
  }

  function throwIfNotDefined(variable, msg) {
    if (!variable) {
      throwError(msg);
    }
  }

  function throwIfNoObject(obj, msg) {
    if (!isObject(obj)) {
      throwError(msg);
    }
  }

  function isObject(obj) {
    return obj === Object(obj);
  }

  function isArray(obj) {
    return Array.isArray || Object.prototype.toString.call(obj) === '[object Array]';
  }

  function isFunction(fn) {
    return Object.prototype.toString.call(fn) === '[object Function]';
  }

  // TODO add isString(str)
/*

 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
 each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
 _['is' + name] = function(obj) {
 return toString.call(obj) == '[object ' + name + ']';
 };
 });
*/

  function logError(msg) {
    /*global console:false */
    if (GLOBAL_CONTEXT.console) {
     GLOBAL_CONTEXT.console.log('[ERROR] ' + msg);
    }
  }

  function throwError(msg) {
    throw new Error(msg + ' - Check the API docs at ' + DOC_URL);
  }

  /**
   * The API to be exported by this library.
   */
  function GuideJsApi() {
    // variables
    this.version = '0.0.1';
    this.GUIDE_TYPES = GUIDE_TYPES;
    this.JQueryRenderAdapter = JQueryRenderAdapter;

    // methods
    this.loadGuide = newGuide;
    this.activateAll = activateAll;
    this.deactivateAll = deactivateAll;
    this.parseGuideFromJson = parseGuideFromJson;
  }

  //
  // Exporting Guide.js
  //

  if (COMMONJS_AVAILABLE) {
    module.exports = new GuideJsApi();
  }
  if (ENDER_AVAILABLE) {
    // add `guide` as a global object via a string identifier,
    // for Closure Compiler "advanced" mode
    GLOBAL_CONTEXT['GuideJs'] = new GuideJsApi();
  }
  if (REQUIREJS_AVAILABLE) {
    /*global define:false */
    define([], function () {
      return new GuideJsApi();
    });
  }
}).call(this); // setting 'this' to the global context<commit_msg>Introduce factory method for HelpBoxGuide<commit_after>/*
 * Guide.js
 * https://github.com/TheLeanMachine/Guide.js
 *
 * Copyright (c) 2013 Kai Hoelscher
 * Licensed under the MIT license.
 */

// TODO: [BUG] ...
// TODO: [TEST] activate() and deactivate() AND
// TODO: [TEST] Module exporting(?), e.g. for require.js
// TODO: [FEATURE] Provide HTML template for Guide
// TODO: [FEATURE] Render parameters? (etc. where to render: Position clockwise? Relative to center?)
// TODO: [FEATURE] New Guide type: GuidedTour() ...at first, just a collection of Guiders
// TODO: [FEATURE] Implement DefaultRenderAdapter that natively renders the helpbox (via HTML API?) ????
// TODO: [FEATURE] Guide parsing from JSON
// TODO: [REFACTOR] expose concrete 'classes' instead of generic 'newGuide()' method: HelpBox, GuidedTour,...
// TODO: [REFACTOR] Rename: validate*() -> throwIfNot*() / check*()
// TODO: [VALIDATION] Args of createHelpBoxGuide() -> set to reasonable defaults otherwise
(function (undefined) { // we always get 'undefined' here, since this code is directly invoked without arguments!

  //
  // 'constants'
  //
  var GLOBAL_CONTEXT = this; // 'window' in the browser, or 'global' on the server (see very bottom of this file)

  var GUIDES = [];

  var GUIDE_TYPES = {
    SIMPLE_HELP_BOX: 'simple_help_box'
  };

  var COMMONJS_AVAILABLE = (typeof module !== 'undefined' && module.exports); // checks for node.js, too

  /*global ender:false */
  var ENDER_AVAILABLE = typeof ender === 'undefined';

  /*global define:false */
  var REQUIREJS_AVAILABLE = (typeof define === "function") && define.amd;

  var DOC_URL = 'https://github.com/TheLeanMachine/Guide.js/blob/master/README.md';

  /**
   * Creates a new Guide based on the passed configuration.
   * @param guideConfig TODO doc
   */
  function newGuide(guideConfig) {
    var guide;

    try {
      guide = createGuideByType(guideConfig);
      GUIDES.push(guide);
      return guide;
    } catch(err) {
      logError('Unable to load Guide: ' + err.message);
      return new EmptyGuide();
    }
  }

  function createGuideByType(guideConfig) {
    throwIfInvalidConfig(guideConfig);

    return new HelpBoxGuide(guideConfig);
  }

  function throwIfInvalidConfig(guideConfig) {
    throwIfNotDefined(guideConfig, '"guideConfig" must not be empty.');
    throwIfNoObject(guideConfig, '"guideConfig" must be of type "Object".');
    throwIfInvalidGuideType(guideConfig, '"guideConfig.type" is not defined or is an unknown type.');
    // TODO validateRenderAdaptor(...) - instance check etc.
  }

  function EmptyGuide() {
    // TODO implement Guide interface (activate(), ...)

    this.isLoaded = function() { return false; };
  }

  /**
   * Factory method for creating new {@link HelpBoxGuide} instances.
   *
   * @param guideConfig TODO doc
   */
  function createHelpBoxGuide(guideConfig) {
    var defaultText = 'This is the default text of a HelpBoxGuide';
    var defaultDisplayDuration = 1000;
    var defaultFadeOutMillis = 150;

    var validConfig = {
      renderAdapter: guideConfig.renderAdapter,
      renderTarget: guideConfig.renderTarget,
      text: (guideConfig.text) ? guideConfig.text : defaultText,
      displayDuration: (guideConfig.displayDuration) ? guideConfig.displayDuration : defaultDisplayDuration,
      fadeOutMillis: (guideConfig.fadeOutMillis) ? guideConfig.displayDuration : defaultFadeOutMillis
    };

    return new HelpBoxGuide(validConfig);
  }

  /**
   * A simple help box that gets displayed for a certain amount of time.
   * @param guideConfig TODO doc
   * @constructor
   */
  function HelpBoxGuide(guideConfig) {
    var renderAdapter = guideConfig.renderAdapter;
    var targetCssId = guideConfig.renderTarget;

    /**
     * Triggers the Guide to do its work: Display a help box, start a tour with Guiders etc.
     */
    function activate() { // TODO rename to 'augment()' or sth. else?

      var buttonCssId = guideConfig.renderTrigger;
      var content = guideConfig.text;
      var fadeOutMillis = guideConfig.fadeOutMillis;
      var displayDuration = guideConfig.displayDuration;

      renderAdapter.renderTo(targetCssId, content, buttonCssId, displayDuration, fadeOutMillis);
    }

    // TODO add doc
    function deactivate() {
      renderAdapter.hide(targetCssId); // naive implementation
    }

    function isLoaded() {
      return true;
    }

    this.activate = activate;
    this.deactivate = deactivate;
    this.isLoaded = isLoaded;
  }

  // TODO add doc
  function JQueryRenderAdapter($) {
    var helpBoxCssId = 'myTestHelpBox';

    // TODO add doc
    function renderTo(renderTarget, content, displayDuration, fadeOutMillis) {
      var helpBox;

      $(renderTarget).prepend('

Immediate Help!
' + content + '
');
      helpBox = renderTarget + " div.helpBox";
      setTimeout(function() {
        $(helpBox).fadeOut(fadeOutMillis);
      }, displayDuration);
    }

    function hide() {
      $('#' + helpBoxCssId).hide();
    }

    this.renderTo = renderTo;
    this.hide = hide;
  }

  /**
   * Deactivates all Guides (ATM this means to hide them).
   */
  function deactivateAll() {
    forEachIn(GUIDES, function(guide) {
      guide.deactivate();
    });
  }

  /**
   * Activates all Guides (ATM this means to display them, again).
   */
  function activateAll() {
    forEachIn(GUIDES, function(guide) {
      guide.activate();
    });
  }

  /**
   * Creates a new Guide from a JSON definition.
   * @param jsonGuide the JSON representing the Guide for the website to be augmented
   */
  function parseGuideFromJson(jsonGuide) {
    logError('Not yet implemented.');
  }

  //
  // Helper functions
  //
  function forEachIn(array, fn) {
    var i;

    for (i=0; i<array.length; ++i) {
      fn(array[i]);
    }
  }

  function objectHasPropertyWithValue(obj, val) {
    var key;
    for (key in obj) {
      if (obj.hasOwnProperty(key) && obj[key] === val) {
        return true;
      }
    }
    return false;
  }

  function throwIfInvalidGuideType(guideConfig, msg) {
    if(!guideConfig.type || !objectHasPropertyWithValue(GUIDE_TYPES, guideConfig.type)) {
      throwError(msg);
    }
  }

  function throwIfNotDefined(variable, msg) {
    if (!variable) {
      throwError(msg);
    }
  }

  function throwIfNoObject(obj, msg) {
    if (!isObject(obj)) {
      throwError(msg);
    }
  }

  function isObject(obj) {
    return obj === Object(obj);
  }

  function isArray(obj) {
    return Array.isArray || Object.prototype.toString.call(obj) === '[object Array]';
  }

  function isFunction(fn) {
    return Object.prototype.toString.call(fn) === '[object Function]';
  }

  // TODO add isString(str)
/*

 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
 each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
 _['is' + name] = function(obj) {
 return toString.call(obj) == '[object ' + name + ']';
 };
 });
*/

  function logError(msg) {
    /*global console:false */
    if (GLOBAL_CONTEXT.console) {
     GLOBAL_CONTEXT.console.log('[ERROR] ' + msg);
    }
  }

  function throwError(msg) {
    throw new Error(msg + ' - Check the API docs at ' + DOC_URL);
  }

  /**
   * The API to be exported by this library.
   */
  function GuideJsApi() {
    // variables
    this.version = '0.0.1';
    this.GUIDE_TYPES = GUIDE_TYPES;
    this.JQueryRenderAdapter = JQueryRenderAdapter;

    // methods
    this.createHelpBoxGuide = createHelpBoxGuide;
    this.loadGuide = newGuide;
    this.activateAll = activateAll;
    this.deactivateAll = deactivateAll;
    this.parseGuideFromJson = parseGuideFromJson;
  }

  //
  // Exporting Guide.js
  //

  if (COMMONJS_AVAILABLE) {
    module.exports = new GuideJsApi();
  }
  if (ENDER_AVAILABLE) {
    // add `guide` as a global object via a string identifier,
    // for Closure Compiler "advanced" mode
    GLOBAL_CONTEXT['GuideJs'] = new GuideJsApi();
  }
  if (REQUIREJS_AVAILABLE) {
    /*global define:false */
    define([], function () {
      return new GuideJsApi();
    });
  }
}).call(this); // setting 'this' to the global context<|endoftext|>


<commit_before>/**
 * @module proact-streams
 */

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 *
 * This method is capable of creating various `source` streams.
 *
 * For example if the method is called like that:
 * ```
 *  var stream = ProAct.stream();
 * ```
 *
 * A sourceless stream will be created, but it will be possible to invoke `trigger*` on it:
 * ```
 *  stream.trigger(val);
 *  stream.triggerErr(new Error());
 *  stream.triggerClose();
 * ```
 *
 * The method can be called with a subscribe function too:
 * ```
 *  var stream = ProAct.stream(function (source) {
 *    // ... logic using the source - the source is a stream, that has trigger/triggerErr/triggerClose
 *    $('.sel').on('click.myClick', function (e) {
 *      source.trigger(e);
 *    });
 *
 *    return function () {
 *      // unsubscribing logic
 *      $('.sel').off('click.myClick');
 *    };
 *  });
 * ```
 *
 * So subscribe/unsubscribe to an even source can be programmed using this method.
 *
 * The first argument can be a string too and if that's the case, {{#crossLink "ProAct.Stream"}}{{/crossLink}}'s
 * `fromString` method will be used for the stream construction.
 *
 * @for ProAct
 * @method stream
 * @static
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function stream (subscribe, transformations, source, queueName) {
  var stream;
  if (!subscribe) {
    stream = new ProAct.Stream(queueName, source, transformations);
  } else if (P.U.isFunction(subscribe)) {
    stream = new ProAct.SubscribableStream(subscribe, queueName, source, transformations);
  } else if (P.U.isString(subscribe)) {
    stream = Stream.fromString(subscribe, slice.call(arguments, 1));
  }

  stream.trigger = StreamUtil.trigger;
  stream.triggerErr = StreamUtil.triggerErr;
  stream.triggerClose= StreamUtil.triggerClose;

  return stream;
}
ProAct.stream = stream;

/**
 * Creates a closed {{#crossLink "ProAct.Stream"}}{{/crossLink}}.
 *
 * @for ProAct
 * @method closed
 * @static
 * @return {ProAct.Stream}
 *      A closed {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function closed () {
  return P.stream().close();
}
ProAct.closed = P.never = closed;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits the passed "value" once and then closes.
 *
Example:

 *

    var stream = ProAct.timeout(1000, 7);
    stream.on(function (v) {
      console.log(v);
    });

   // This will print '7' after 1s and will close.

 *

 *
 * @for ProAct
 * @method timeout
 * @static
 * @param {Number} timeout
 *      The time to wait (in milliseconds) before emitting the value and close.
 * @param {Object} value
 *      The value to emit.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function timeout (timeout, value) {
  var stream = P.stream();

  window.setTimeout(function () {
    stream.trigger(value);
    stream.close();
  }, timeout);

  return stream;
}
ProAct.timeout = ProAct.later = timeout;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits the passed "value" over and over again at given time interval.
 *
Example:

 *

    var stream = ProAct.interval(1000, 7);
    stream.on(function (v) {
      console.log(v);
    });

   // This will print one number on every 1s and the numbers will be 7,7,7,7,7....

 *

 *
 * @for ProAct
 * @method interval
 * @static
 * @param {Number} interval
 *      The time in milliseconds on which the value will be emitted.
 * @param {Object} value
 *      The value to emit.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function interval (interval, value) {
  var stream = P.stream();

  window.setInterval(function () {
    stream.trigger(value);
  }, interval);

  return stream;
}
ProAct.interval = interval;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits values of the passed vals array on the passed interval milliseconds.
 *

 *  When every value is emitted through the stream it is closed.
 *

 *
Example:

 *

    var stream = ProAct.seq(1000, [4, 5]);
    stream.on(function (v) {
      console.log(v);
    });

   // This will print one number on every 1s and the numbers will be 4 5 and the stream will be closed.

 *

 *
 * @for ProAct
 * @method seq
 * @static
 * @param {Number} interval
 *      The time in milliseconds on which a value of the passed vals array will be emitted.
 * @param {Array} vals
 *      The array containing the values to be emitted on the passed interval.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function seq (interval, vals) {
  var stream = P.stream(),
      operation;

  if (vals.length > 0) {
    operation = function () {
      var value = vals.shift();
      stream.trigger(value);

      if (vals.length === 0) {
        stream.close();
      } else {
        window.setTimeout(operation, interval);
      }
    };
    window.setTimeout(operation, interval);
  }

  return stream;
}
ProAct.seq = seq;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits values of the passed vals array on the passed interval.
 *

 *  When every value is emitted through the stream they are emitted again and again and so on...
 *

 *
Example:

 *

    var stream = ProAct.repeat(1000, [4, 5]);
    stream.on(function (v) {
      console.log(v);
    });

   // This will print one number on every 1s and the numbers will be 4 5 4 5 4 5 4 5 4 5 .. and so on

 *

 *
 * @for ProAct
 * @method interval
 * @static
 * @param {Number} interval
 *      The time in milliseconds on which a value of the passed vals array will be emitted.
 * @param {Array} vals
 *      The array containing the values to be emitted on the passed interval.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function repeat (interval, vals) {
  var stream = P.stream(), i = 0;

  if (vals.length > 0) {
    window.setInterval(function () {
      if (i === vals.length) {
        i = 0;
      }

      var value = vals[i++];
      stream.trigger(value);
    }, interval);
  }

  return stream;
}
ProAct.repeat = repeat;

/**
 * The {{#crossLink "ProAct/fromInvoke:method"}}{{/crossLink}} creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits the result of the passed
 * func argument on every interval milliseconds.
 *

 *  If func returns {{#crossLink "ProAct/closed:method"}}{{/crossLink}} the stream is closed.
 *

 *
Example:

 *

    var stream = ProAct.fromInvoke(1000, function () {
      return 5;
    });
    stream.on(function (v) {
      console.log(v);
    });

    // After 1s we'll see '5' in the log, after 2s we'll see a second '5' in the log and so on...

 *

 *
 * @for ProAct
 * @method fromInvoke
 * @static
 * @param {Number} interval
 *      The interval on which func will be called and its returned value will
 *      be triggered into the stream.
 * @param {Function} func
 *      The function to invoke in order to get the value to trigger into the stream.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function fromInvoke (interval, func) {
  var stream = P.stream(), id;

  id = window.setInterval(function () {
    var value = func.call();

    if (value !== ProAct.close) {
      stream.trigger(value);
    } else {
      stream.close();
      window.clearInterval(id);
    }

  }, interval);

  return stream;
}
ProAct.fromInvoke = fromInvoke;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits the result of an action that uses a callback
 * to notify that it is finished.
 *
 * This can be used to create streams from http requests for example.
 *
 * Example:
 * ```
 *  var stream = ProAct.fromCallback(action);
 *  stream.on(function (v) {
 *    console.log(v);
 *  });
 *
 * ```
 *
 * @for ProAct
 * @method fromCallback
 * @static
 * @param {Function} callbackCaller
 *      The action that receives a callback.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function fromCallback (callbackCaller) {
  var stream = P.stream();

  callbackCaller(function (result) {
    stream.trigger(result);
    stream.close();
  });

  return stream;
}

ProAct.fromCallback = fromCallback;

attachers = {
  addEventListener: 'removeEventListener',
  addListener: 'removeListener',
  on: 'off'
};
attacherKeys = Object.keys(attachers);

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}} with source an evet emitter or dispatcher,
 * it can be used with jQuery for example for example.
 *
 * Example:
 * ```
 *  var stream = ProAct.fromEventDispatcher($('.some-input'), 'keydown');
 *  stream.on(function (e) {
 *    console.log(e.which);
 *  });
 *
 * ```
 *
 * @for ProAct
 * @method fromEventDispatcher
 * @static
 * @param {Object} target
 *      The event dispatcher, can be a jQuery button, or a DOM element, or somethnig like that.
 * @param {String} eventType
 *      The type of the event - for example 'click'.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function fromEventDispatcher (target, eventType) {
  var i, ln = attacherKeys.length,
      on, off,
      attacher, current;

  for (i = 0; i < ln; i++) {
    attacher = attacherKeys[i];
    current = target[attacher];

    if (current && P.U.isFunction(current)) {
      on = attacher;
      off = attachers[attacher];
      break;
    }
  }

  if (on === undefined) {
    return null;
  }

  return new ProAct.SubscribableStream(function (stream) {
    target[on](eventType, stream.trigger);

    return function (stream) {
      target[off](eventType, stream.trigger);
    };
  });
}

ProAct.fromEventDispatcher = fromEventDispatcher;

<commit_msg>Added parameter to the doc.<commit_after>/**
 * @module proact-streams
 */

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 *
 * This method is capable of creating various `source` streams.
 *
 * For example if the method is called like that:
 * ```
 *  var stream = ProAct.stream();
 * ```
 *
 * A sourceless stream will be created, but it will be possible to invoke `trigger*` on it:
 * ```
 *  stream.trigger(val);
 *  stream.triggerErr(new Error());
 *  stream.triggerClose();
 * ```
 *
 * The method can be called with a subscribe function too:
 * ```
 *  var stream = ProAct.stream(function (source) {
 *    // ... logic using the source - the source is a stream, that has trigger/triggerErr/triggerClose
 *    $('.sel').on('click.myClick', function (e) {
 *      source.trigger(e);
 *    });
 *
 *    return function () {
 *      // unsubscribing logic
 *      $('.sel').off('click.myClick');
 *    };
 *  });
 * ```
 *
 * So subscribe/unsubscribe to an even source can be programmed using this method.
 *
 * The first argument can be a string too and if that's the case, {{#crossLink "ProAct.Stream"}}{{/crossLink}}'s
 * `fromString` method will be used for the stream construction.
 *
 * @for ProAct
 * @method stream
 * @param {String|Function} subscribe
 * @static
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function stream (subscribe, transformations, source, queueName) {
  var stream;
  if (!subscribe) {
    stream = new ProAct.Stream(queueName, source, transformations);
  } else if (P.U.isFunction(subscribe)) {
    stream = new ProAct.SubscribableStream(subscribe, queueName, source, transformations);
  } else if (P.U.isString(subscribe)) {
    stream = Stream.fromString(subscribe, slice.call(arguments, 1));
  }

  stream.trigger = StreamUtil.trigger;
  stream.triggerErr = StreamUtil.triggerErr;
  stream.triggerClose= StreamUtil.triggerClose;

  return stream;
}
ProAct.stream = stream;

/**
 * Creates a closed {{#crossLink "ProAct.Stream"}}{{/crossLink}}.
 *
 * @for ProAct
 * @method closed
 * @static
 * @return {ProAct.Stream}
 *      A closed {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function closed () {
  return P.stream().close();
}
ProAct.closed = P.never = closed;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits the passed "value" once and then closes.
 *
Example:

 *

    var stream = ProAct.timeout(1000, 7);
    stream.on(function (v) {
      console.log(v);
    });

   // This will print '7' after 1s and will close.

 *

 *
 * @for ProAct
 * @method timeout
 * @static
 * @param {Number} timeout
 *      The time to wait (in milliseconds) before emitting the value and close.
 * @param {Object} value
 *      The value to emit.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function timeout (timeout, value) {
  var stream = P.stream();

  window.setTimeout(function () {
    stream.trigger(value);
    stream.close();
  }, timeout);

  return stream;
}
ProAct.timeout = ProAct.later = timeout;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits the passed "value" over and over again at given time interval.
 *
Example:

 *

    var stream = ProAct.interval(1000, 7);
    stream.on(function (v) {
      console.log(v);
    });

   // This will print one number on every 1s and the numbers will be 7,7,7,7,7....

 *

 *
 * @for ProAct
 * @method interval
 * @static
 * @param {Number} interval
 *      The time in milliseconds on which the value will be emitted.
 * @param {Object} value
 *      The value to emit.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function interval (interval, value) {
  var stream = P.stream();

  window.setInterval(function () {
    stream.trigger(value);
  }, interval);

  return stream;
}
ProAct.interval = interval;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits values of the passed vals array on the passed interval milliseconds.
 *

 *  When every value is emitted through the stream it is closed.
 *

 *
Example:

 *

    var stream = ProAct.seq(1000, [4, 5]);
    stream.on(function (v) {
      console.log(v);
    });

   // This will print one number on every 1s and the numbers will be 4 5 and the stream will be closed.

 *

 *
 * @for ProAct
 * @method seq
 * @static
 * @param {Number} interval
 *      The time in milliseconds on which a value of the passed vals array will be emitted.
 * @param {Array} vals
 *      The array containing the values to be emitted on the passed interval.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function seq (interval, vals) {
  var stream = P.stream(),
      operation;

  if (vals.length > 0) {
    operation = function () {
      var value = vals.shift();
      stream.trigger(value);

      if (vals.length === 0) {
        stream.close();
      } else {
        window.setTimeout(operation, interval);
      }
    };
    window.setTimeout(operation, interval);
  }

  return stream;
}
ProAct.seq = seq;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits values of the passed vals array on the passed interval.
 *

 *  When every value is emitted through the stream they are emitted again and again and so on...
 *

 *
Example:

 *

    var stream = ProAct.repeat(1000, [4, 5]);
    stream.on(function (v) {
      console.log(v);
    });

   // This will print one number on every 1s and the numbers will be 4 5 4 5 4 5 4 5 4 5 .. and so on

 *

 *
 * @for ProAct
 * @method interval
 * @static
 * @param {Number} interval
 *      The time in milliseconds on which a value of the passed vals array will be emitted.
 * @param {Array} vals
 *      The array containing the values to be emitted on the passed interval.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function repeat (interval, vals) {
  var stream = P.stream(), i = 0;

  if (vals.length > 0) {
    window.setInterval(function () {
      if (i === vals.length) {
        i = 0;
      }

      var value = vals[i++];
      stream.trigger(value);
    }, interval);
  }

  return stream;
}
ProAct.repeat = repeat;

/**
 * The {{#crossLink "ProAct/fromInvoke:method"}}{{/crossLink}} creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits the result of the passed
 * func argument on every interval milliseconds.
 *

 *  If func returns {{#crossLink "ProAct/closed:method"}}{{/crossLink}} the stream is closed.
 *

 *
Example:

 *

    var stream = ProAct.fromInvoke(1000, function () {
      return 5;
    });
    stream.on(function (v) {
      console.log(v);
    });

    // After 1s we'll see '5' in the log, after 2s we'll see a second '5' in the log and so on...

 *

 *
 * @for ProAct
 * @method fromInvoke
 * @static
 * @param {Number} interval
 *      The interval on which func will be called and its returned value will
 *      be triggered into the stream.
 * @param {Function} func
 *      The function to invoke in order to get the value to trigger into the stream.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function fromInvoke (interval, func) {
  var stream = P.stream(), id;

  id = window.setInterval(function () {
    var value = func.call();

    if (value !== ProAct.close) {
      stream.trigger(value);
    } else {
      stream.close();
      window.clearInterval(id);
    }

  }, interval);

  return stream;
}
ProAct.fromInvoke = fromInvoke;

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}}, which emits the result of an action that uses a callback
 * to notify that it is finished.
 *
 * This can be used to create streams from http requests for example.
 *
 * Example:
 * ```
 *  var stream = ProAct.fromCallback(action);
 *  stream.on(function (v) {
 *    console.log(v);
 *  });
 *
 * ```
 *
 * @for ProAct
 * @method fromCallback
 * @static
 * @param {Function} callbackCaller
 *      The action that receives a callback.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function fromCallback (callbackCaller) {
  var stream = P.stream();

  callbackCaller(function (result) {
    stream.trigger(result);
    stream.close();
  });

  return stream;
}

ProAct.fromCallback = fromCallback;

attachers = {
  addEventListener: 'removeEventListener',
  addListener: 'removeListener',
  on: 'off'
};
attacherKeys = Object.keys(attachers);

/**
 * Creates a {{#crossLink "ProAct.Stream"}}{{/crossLink}} with source an evet emitter or dispatcher,
 * it can be used with jQuery for example for example.
 *
 * Example:
 * ```
 *  var stream = ProAct.fromEventDispatcher($('.some-input'), 'keydown');
 *  stream.on(function (e) {
 *    console.log(e.which);
 *  });
 *
 * ```
 *
 * @for ProAct
 * @method fromEventDispatcher
 * @static
 * @param {Object} target
 *      The event dispatcher, can be a jQuery button, or a DOM element, or somethnig like that.
 * @param {String} eventType
 *      The type of the event - for example 'click'.
 * @return {ProAct.Stream}
 *      A {{#crossLink "ProAct.Stream"}}{{/crossLink}} instance.
 */
function fromEventDispatcher (target, eventType) {
  var i, ln = attacherKeys.length,
      on, off,
      attacher, current;

  for (i = 0; i < ln; i++) {
    attacher = attacherKeys[i];
    current = target[attacher];

    if (current && P.U.isFunction(current)) {
      on = attacher;
      off = attachers[attacher];
      break;
    }
  }

  if (on === undefined) {
    return null;
  }

  return new ProAct.SubscribableStream(function (stream) {
    target[on](eventType, stream.trigger);

    return function (stream) {
      target[off](eventType, stream.trigger);
    };
  });
}

ProAct.fromEventDispatcher = fromEventDispatcher;

<|endoftext|>


<commit_before>const DrawCard = require('../../drawcard.js');

class MantraOfWater extends DrawCard {
    setupCardAbilities(ability) {
    }
}

MantraOfWater.id = 'mantra-of-water'; // This is a guess at what the id might be - please check it!!!

module.exports = MantraOfWater;
<commit_msg>Implemented Mantra of Water<commit_after>const DrawCard = require('../../drawcard.js');

class MantraOfWater extends DrawCard {
    setupCardAbilities(ability) {
        this.reaction({
            when: {
                onConflictDeclared: event => event.conflictRing === 'water' && event.conflict.attackingPlayer !== this.controller
            },
            target: {
                cardType: 'character',
                cardCondition: card => card.location === 'play area' && (card.hasTrait('monk') || card.attachments.any(card => card.hasTrait('monk'))) && card.bowed
            },
            handler: context => {
                this.game.addMessage('{0} plays {1} to ready {2} and draw a card', this.controller, this, context.target);
                this.controller.readyCard(context.target);
                this.controller.drawCardsToHand(1);
            }
        });
    }
}

MantraOfWater.id = 'mantra-of-water';

module.exports = MantraOfWater;
<|endoftext|>


<commit_before>// # Ghost Server
// Handles the creation of an HTTP Server for Ghost
var Promise = require('bluebird'),
    chalk = require('chalk'),
    fs = require('fs'),
    semver = require('semver'),
    packageInfo = require('../../package.json'),
    errors = require('./errors'),
    config = require('./config');

/**
 * ## GhostServer
 * @constructor
 * @param {Object} rootApp - parent express instance
 */
function GhostServer(rootApp) {
    this.rootApp = rootApp;
    this.httpServer = null;
    this.connections = {};
    this.connectionId = 0;
    this.upgradeWarning = setTimeout(this.logUpgradeWarning.bind(this), 5000);

    // Expose config module for use externally.
    this.config = config;
}

/**
 * ## Public API methods
 *
 * ### Start
 * Starts the ghost server listening on the configured port.
 * Alternatively you can pass in your own express instance and let Ghost
 * start listening for you.
 * @param  {Object} externalApp - Optional express app instance.
 * @return {Promise} Resolves once Ghost has started
 */
GhostServer.prototype.start = function (externalApp) {
    var self = this,
        rootApp = externalApp ? externalApp : self.rootApp;

    return new Promise(function (resolve) {
        var socketConfig = config.getSocket();

        if (socketConfig) {
            // Make sure the socket is gone before trying to create another
            try {
                fs.unlinkSync(socketConfig.path);
            } catch (e) {
                // We can ignore this.
            }

            self.httpServer = rootApp.listen(socketConfig.path);

            fs.chmod(socketConfig.path, socketConfig.permissions);
        } else {
            self.httpServer = rootApp.listen(
                config.server.port,
                config.server.host
            );
        }

        self.httpServer.on('error', function (error) {
            if (error.errno === 'EADDRINUSE') {
                errors.logError(
                    '(EADDRINUSE) Cannot start Ghost.',
                    'Port ' + config.server.port + ' is already in use by another program.',
                    'Is another Ghost instance already running?'
                );
            } else {
                errors.logError(
                    '(Code: ' + error.errno + ')',
                    'There was an error starting your server.',
                    'Please use the error code above to search for a solution.'
                );
            }
            process.exit(-1);
        });
        self.httpServer.on('connection', self.connection.bind(self));
        self.httpServer.on('listening', function () {
            self.logStartMessages();
            clearTimeout(self.upgradeWarning);
            resolve(self);
        });
    });
};

/**
 * ### Stop
 * Returns a promise that will be fulfilled when the server stops. If the server has not been started,
 * the promise will be fulfilled immediately
 * @returns {Promise} Resolves once Ghost has stopped
 */
GhostServer.prototype.stop = function () {
    var self = this;

    return new Promise(function (resolve) {
        if (self.httpServer === null) {
            resolve(self);
        } else {
            self.httpServer.close(function () {
                self.httpServer = null;
                self.logShutdownMessages();
                resolve(self);
            });

            self.closeConnections();
        }
    });
};

/**
 * ### Restart
 * Restarts the ghost application
 * @returns {Promise} Resolves once Ghost has restarted
 */
GhostServer.prototype.restart = function () {
    return this.stop().then(this.start.bind(this));
};

/**
 * ### Hammertime
 * To be called after `stop`
 */
GhostServer.prototype.hammertime = function () {
    console.log(chalk.green('Can\'t touch this'));

    return Promise.resolve(this);
};

/**
 * ## Private (internal) methods
 *
 * ### Connection
 * @param {Object} socket
 */
GhostServer.prototype.connection = function (socket) {
    var self = this;

    self.connectionId += 1;
    socket._ghostId = self.connectionId;

    socket.on('close', function () {
        delete self.connections[this._ghostId];
    });

    self.connections[socket._ghostId] = socket;
};

/**
 * ### Close Connections
 * Most browsers keep a persistent connection open to the server, which prevents the close callback of
 * httpServer from returning. We need to destroy all connections manually.
 */
GhostServer.prototype.closeConnections = function () {
    var self = this;

    Object.keys(self.connections).forEach(function (socketId) {
        var socket = self.connections[socketId];

        if (socket) {
            socket.destroy();
        }
    });
};

/**
 * ### Log Start Messages
 */
GhostServer.prototype.logStartMessages = function () {
    // Tell users if their node version is not supported, and exit
    if (!semver.satisfies(process.versions.node, packageInfo.engines.node) &&
        !semver.satisfies(process.versions.node, packageInfo.engines.iojs)) {
        console.log(
            chalk.red('\nERROR: Unsupported version of Node'),
            chalk.red('\nGhost needs Node version'),
            chalk.yellow(packageInfo.engines.node),
            chalk.red('you are using version'),
            chalk.yellow(process.versions.node),
            chalk.green('\nPlease go to http://nodejs.org to get a supported version')
        );

        process.exit(0);
    }

    // Startup & Shutdown messages
    if (process.env.NODE_ENV === 'production') {
        console.log(
            chalk.green('Ghost is running...'),
            '\nYour blog is now available on',
            config.url,
            chalk.gray('\nCtrl+C to shut down')
        );
    } else {
        console.log(
            chalk.green('Ghost is running in ' + process.env.NODE_ENV + '...'),
            '\nListening on',
                config.getSocket() || config.server.host + ':' + config.server.port,
            '\nUrl configured as:',
            config.url,
            chalk.gray('\nCtrl+C to shut down')
        );
    }

    function shutdown() {
        console.log(chalk.red('\nGhost has shut down'));
        if (process.env.NODE_ENV === 'production') {
            console.log(
                '\nYour blog is now offline'
            );
        } else {
            console.log(
                '\nGhost was running for',
                Math.round(process.uptime()),
                'seconds'
            );
        }
        process.exit(0);
    }
    // ensure that Ghost exits correctly on Ctrl+C and SIGTERM
    process.
        removeAllListeners('SIGINT').on('SIGINT', shutdown).
        removeAllListeners('SIGTERM').on('SIGTERM', shutdown);
};

/**
 * ### Log Shutdown Messages
 */
GhostServer.prototype.logShutdownMessages = function () {
    console.log(chalk.red('Ghost is closing connections'));
};

/**
 * ### Log Upgrade Warning
 * Warning that the API for the node module version of Ghost changed in 0.5.2
 *
 * *This should be removed soon*
 */
GhostServer.prototype.logUpgradeWarning = function () {
    errors.logWarn(
        'Ghost no longer starts automatically when using it as an npm module.',
        'If you\'re seeing this message, you may need to update your custom code.',
        'Please see the docs at http://tinyurl.com/npm-upgrade for more information.'
    );
};

module.exports = GhostServer;
<commit_msg>disable log message for BAE<commit_after>// # Ghost Server
// Handles the creation of an HTTP Server for Ghost
var Promise = require('bluebird'),
    chalk = require('chalk'),
    fs = require('fs'),
    semver = require('semver'),
    packageInfo = require('../../package.json'),
    errors = require('./errors'),
    config = require('./config');

/**
 * ## GhostServer
 * @constructor
 * @param {Object} rootApp - parent express instance
 */
function GhostServer(rootApp) {
    this.rootApp = rootApp;
    this.httpServer = null;
    this.connections = {};
    this.connectionId = 0;
    this.upgradeWarning = setTimeout(this.logUpgradeWarning.bind(this), 5000);

    // Expose config module for use externally.
    this.config = config;
}

/**
 * ## Public API methods
 *
 * ### Start
 * Starts the ghost server listening on the configured port.
 * Alternatively you can pass in your own express instance and let Ghost
 * start listening for you.
 * @param  {Object} externalApp - Optional express app instance.
 * @return {Promise} Resolves once Ghost has started
 */
GhostServer.prototype.start = function (externalApp) {
    var self = this,
        rootApp = externalApp ? externalApp : self.rootApp;

    return new Promise(function (resolve) {
        var socketConfig = config.getSocket();

        if (socketConfig) {
            // Make sure the socket is gone before trying to create another
            try {
                fs.unlinkSync(socketConfig.path);
            } catch (e) {
                // We can ignore this.
            }

            self.httpServer = rootApp.listen(socketConfig.path);

            fs.chmod(socketConfig.path, socketConfig.permissions);
        } else {
            self.httpServer = rootApp.listen(
                config.server.port,
                config.server.host
            );
        }

        self.httpServer.on('error', function (error) {
            if (error.errno === 'EADDRINUSE') {
                errors.logError(
                    '(EADDRINUSE) Cannot start Ghost.',
                    'Port ' + config.server.port + ' is already in use by another program.',
                    'Is another Ghost instance already running?'
                );
            } else {
                errors.logError(
                    '(Code: ' + error.errno + ')',
                    'There was an error starting your server.',
                    'Please use the error code above to search for a solution.'
                );
            }
            process.exit(-1);
        });
        self.httpServer.on('connection', self.connection.bind(self));
        self.httpServer.on('listening', function () {
            //self.logStartMessages(); //this will crash BAE
            clearTimeout(self.upgradeWarning);
            resolve(self);
        });
    });
};

/**
 * ### Stop
 * Returns a promise that will be fulfilled when the server stops. If the server has not been started,
 * the promise will be fulfilled immediately
 * @returns {Promise} Resolves once Ghost has stopped
 */
GhostServer.prototype.stop = function () {
    var self = this;

    return new Promise(function (resolve) {
        if (self.httpServer === null) {
            resolve(self);
        } else {
            self.httpServer.close(function () {
                self.httpServer = null;
                self.logShutdownMessages();
                resolve(self);
            });

            self.closeConnections();
        }
    });
};

/**
 * ### Restart
 * Restarts the ghost application
 * @returns {Promise} Resolves once Ghost has restarted
 */
GhostServer.prototype.restart = function () {
    return this.stop().then(this.start.bind(this));
};

/**
 * ### Hammertime
 * To be called after `stop`
 */
GhostServer.prototype.hammertime = function () {
    console.log(chalk.green('Can\'t touch this'));

    return Promise.resolve(this);
};

/**
 * ## Private (internal) methods
 *
 * ### Connection
 * @param {Object} socket
 */
GhostServer.prototype.connection = function (socket) {
    var self = this;

    self.connectionId += 1;
    socket._ghostId = self.connectionId;

    socket.on('close', function () {
        delete self.connections[this._ghostId];
    });

    self.connections[socket._ghostId] = socket;
};

/**
 * ### Close Connections
 * Most browsers keep a persistent connection open to the server, which prevents the close callback of
 * httpServer from returning. We need to destroy all connections manually.
 */
GhostServer.prototype.closeConnections = function () {
    var self = this;

    Object.keys(self.connections).forEach(function (socketId) {
        var socket = self.connections[socketId];

        if (socket) {
            socket.destroy();
        }
    });
};

/**
 * ### Log Start Messages
 */
GhostServer.prototype.logStartMessages = function () {
    // Tell users if their node version is not supported, and exit
    if (!semver.satisfies(process.versions.node, packageInfo.engines.node) &&
        !semver.satisfies(process.versions.node, packageInfo.engines.iojs)) {
        console.log(
            chalk.red('\nERROR: Unsupported version of Node'),
            chalk.red('\nGhost needs Node version'),
            chalk.yellow(packageInfo.engines.node),
            chalk.red('you are using version'),
            chalk.yellow(process.versions.node),
            chalk.green('\nPlease go to http://nodejs.org to get a supported version')
        );

        process.exit(0);
    }

    // Startup & Shutdown messages
    if (process.env.NODE_ENV === 'production') {
        console.log(
            chalk.green('Ghost is running...'),
            '\nYour blog is now available on',
            config.url,
            chalk.gray('\nCtrl+C to shut down')
        );
    } else {
        console.log(
            chalk.green('Ghost is running in ' + process.env.NODE_ENV + '...'),
            '\nListening on',
                config.getSocket() || config.server.host + ':' + config.server.port,
            '\nUrl configured as:',
            config.url,
            chalk.gray('\nCtrl+C to shut down')
        );
    }

    function shutdown() {
        console.log(chalk.red('\nGhost has shut down'));
        if (process.env.NODE_ENV === 'production') {
            console.log(
                '\nYour blog is now offline'
            );
        } else {
            console.log(
                '\nGhost was running for',
                Math.round(process.uptime()),
                'seconds'
            );
        }
        process.exit(0);
    }
    // ensure that Ghost exits correctly on Ctrl+C and SIGTERM
    process.
        removeAllListeners('SIGINT').on('SIGINT', shutdown).
        removeAllListeners('SIGTERM').on('SIGTERM', shutdown);
};

/**
 * ### Log Shutdown Messages
 */
GhostServer.prototype.logShutdownMessages = function () {
    console.log(chalk.red('Ghost is closing connections'));
};

/**
 * ### Log Upgrade Warning
 * Warning that the API for the node module version of Ghost changed in 0.5.2
 *
 * *This should be removed soon*
 */
GhostServer.prototype.logUpgradeWarning = function () {
    errors.logWarn(
        'Ghost no longer starts automatically when using it as an npm module.',
        'If you\'re seeing this message, you may need to update your custom code.',
        'Please see the docs at http://tinyurl.com/npm-upgrade for more information.'
    );
};

module.exports = GhostServer;
<|endoftext|>


<commit_before>console.log('This would be the main JS file.');
<commit_msg>Delete main.js<commit_after><|endoftext|>