<commit_before>/*
 * Copyright (C) 2014 TopCoder Inc., All Rights Reserved.
 */

'use strict';

var angular = require('angular');

// @todo Should be an angular depdency
var jqTransform = require('jqTransform');
var jqueryui = require('jquery-ui');

module.exports = angular.module('broker.directives', [])
  // custom select control
  .directive('dropDown', [function() {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        $(element).click(function() {
          $(".drop-down-active").removeClass("drop-down-active");
          $(this).next().addClass("drop-down-active");
          $(".drop-down-box:not(.drop-down-active)").hide();
          $(".drop-down-active").toggle();
          if (attrs.fixArrow) {
            var w = $(element).width() - 16;
            $('.drop-down-active .icon-arrow').css({left: w + "px"});
          }
          return false;
        });
      }
    };
  }])
  // expand menu item in left sidebar
  .directive('expandArrow', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        var $ele = $(element);
        $ele.find(".arrows").click(function() {
          $ele.toggleClass("current");
          if ($ele.hasClass("current")) {
            $(this).removeClass("arrow-right").addClass("arrow-down");
          } else {
            $(this).removeClass("arrow-down").addClass("arrow-right");
          }
        });
      }
    };
  }])
  // fix left sidebar height
  .directive('fixSidebar', ["fixSidebar", function(fixSidebar) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        scope.$watch(function() {
          return $(element).height();
        }, function(newValue, oldValue) {
          if (newValue !== oldValue) {
            fixSidebar();
          }
        });
        element.ready(function() {
          fixSidebar();
        });
      }
    };
  }])
  // set proper class to main content if sidebar is expanded or collapsed
  .directive('setWidth', ["$rootScope", function($rootScope) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        var checkClass = function() {
          if ($rootScope.sideBarExpanded) {
            $(element).addClass("left-184").removeClass("left-74");
          } else {
            $(element).removeClass("left-184").addClass("left-74");
          }
        };
        checkClass();
        $rootScope.$watch("sideBarExpanded", function(oldVal, newVal) {
          if (oldVal !== newVal) {
            checkClass();
          }
        });
      }
    };
  }])
  // expand or collapse left sidebar after arrow click
  .directive('toggleSidebar', ["$rootScope", function($rootScope) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        var $ele = $(element);
        $ele.find(".side-arrow").click(function() {
          $ele.toggleClass('absolute-nav');
          if ($ele.hasClass("absolute-nav")) {
            $ele.find("ul li").removeClass("current");
            $ele.find("ul li a.li-links span.arrow-down")
              .removeClass("arrow-down")
              .addClass("arrow-right");
            $rootScope.sideBarExpanded = false;
          } else {
            $rootScope.sideBarExpanded = true;
          }
          $rootScope.$apply();
        });
      }
    };
  }])
  // transform form controls
  .directive('jqtransform', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        element.ready(function() {
          $(element).jqTransform({imgPath: '/images/forms/'});
        });
      }
    };
  }])
  // custom date picker
  .directive('datepicker', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        var $ele = $(element);
        $ele.datepicker({
          dateFormat: "mm/dd/yy"
        });
        $ele.next(".date-icon").click(function() {
          $ele.trigger("click").focus();
        });
      }
    };
  }])
  // iterate through all boxes and fix height
  .directive('fixBoxesHeight', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        element.ready(function() {
          var maxHeight = 0,
            $boxes = $(element).find('.boxes');
          $boxes.each(function() {
            maxHeight = Math.max(maxHeight, $(this).height());
          });
          $boxes.height(maxHeight);
        });
      }
    };
  }])
  // display table with project orders
  .directive('ordersTable', [function() {
    return {
      restrict: 'E',
      scope: {
        orders: "="
      },
      templateUrl: '/partials/common/orders-table.html'
    };
  }])
  // display box with service details
  .directive('serviceBox', [function() {
    return {
      restrict: 'E',
      scope: {
        service: "="
      },
      templateUrl: '/partials/common/service-box.html'
    };
  }])
  // show grid or list view
  .directive('switchViewButtons', ["fixSidebar", function(fixSidebar) {
    return {
      restrict: 'E',
      template: [
        '',
        '',
        '',
        ''
      ].join(""),
      scope: {
        gridView: "=",
        listView: "="
      },
      link: function(scope, element) {
        scope.showList = function() {
          $(scope.gridView).hide();
          $(scope.listView).show();
          $(element).find(".js-list-btn").addClass('btn-active');
          $(element).find(".js-grid-btn").removeClass('btn-active');
          fixSidebar();
        };
        scope.showGrid = function() {
          $(scope.gridView).show();
          $(scope.listView).hide();
          $(element).find(".js-grid-btn").addClass('btn-active');
          $(element).find(".js-list-btn").removeClass('btn-active');
          fixSidebar();
        };
      }
    };
  }])
  // show category (blue print, webservices, applications) in marketplace view
  .directive('marketplaceItems', [function() {
    return {
      restrict: 'E',
      templateUrl: '/partials/common/marketplace-items.html',
      transclude: true,
      scope: {
        items: "="
      },
      link: function(scope) {
        scope.tab = "featured";
      }
    };
  }])
  // show tooltip on mouse over
  .directive('tooltip', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        $(element).tooltip({
          tooltipClass: "icon-arrow",
          position: {
            my: "left-23 top",
            at: "center bottom+24"
          }
        });
      }
    };
  }])
  // popup with X icon for dashboard
  .directive('alertPopup', ["fixSidebar", function(fixSidebar) {
    return {
      restrict: 'E',
      scope: {
        msg: "="
      },
      transclude: true,
      template: '

',
      link: function(scope, element) {
        $(element).find('.close').click(function() {
          $(element).remove();
          fixSidebar();
        });
      }
    };
  }])
  // animate graphs
  .directive('animateKnob', ["$interval", function($interval) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        element.ready(function() {
          var $element = $(element);
          var intervalId = null;
          var animate = function() {
            var targetValue = parseInt($element.attr("data-target-value"));
            if (!targetValue) {
              return;
            }
            $element.knob({
              'draw': function() {
                var $this = $(this.i);
                $this.val(this.cv + '%');
                $this.css({
                  "font-family": "SourceSansPro_Regular",
                  "font-size": "42px",
                  "color": "#0a4684",
                  "font-weight": "normal",
                  "display": "inline-block"
                });
                $this.on("focus", function() {
                  $this.parent().click();
                });
              }
            });
            if (intervalId) {
              $interval.cancel(intervalId);
              intervalId = null;
            }
            var currentValue = 0;
            intervalId = $interval(function() {
              currentValue += 1;
              $element.val(currentValue).trigger('change');
              if (currentValue === targetValue) {
                $interval.cancel(intervalId);
                intervalId = null;
              }
              if (currentValue === 100) {
                $element.css({
                  "width": "101px",
                  "margin-left": "-127px"
                });
              }
            }, 10);
          };
          animate();
          scope.$watch("selectedStatistic", function(newValue, oldValue) {
            if (newValue !== oldValue) {
              animate();
            }
          });
        });
      }
    };
  }]);<commit_msg>Hooking directives up to templateCache<commit_after>/*
 * Copyright (C) 2014 TopCoder Inc., All Rights Reserved.
 */

'use strict';

var angular = require('angular');

// @todo Should be an angular depdency
var jqTransform = require('jqTransform');
var jqueryui = require('jquery-ui');

module.exports = angular.module('broker.directives', [])
  // custom select control
  .directive('dropDown', [function() {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        $(element).click(function() {
          $(".drop-down-active").removeClass("drop-down-active");
          $(this).next().addClass("drop-down-active");
          $(".drop-down-box:not(.drop-down-active)").hide();
          $(".drop-down-active").toggle();
          if (attrs.fixArrow) {
            var w = $(element).width() - 16;
            $('.drop-down-active .icon-arrow').css({left: w + "px"});
          }
          return false;
        });
      }
    };
  }])
  // expand menu item in left sidebar
  .directive('expandArrow', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        var $ele = $(element);
        $ele.find(".arrows").click(function() {
          $ele.toggleClass("current");
          if ($ele.hasClass("current")) {
            $(this).removeClass("arrow-right").addClass("arrow-down");
          } else {
            $(this).removeClass("arrow-down").addClass("arrow-right");
          }
        });
      }
    };
  }])
  // fix left sidebar height
  .directive('fixSidebar', ["fixSidebar", function(fixSidebar) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        scope.$watch(function() {
          return $(element).height();
        }, function(newValue, oldValue) {
          if (newValue !== oldValue) {
            fixSidebar();
          }
        });
        element.ready(function() {
          fixSidebar();
        });
      }
    };
  }])
  // set proper class to main content if sidebar is expanded or collapsed
  .directive('setWidth', ["$rootScope", function($rootScope) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        var checkClass = function() {
          if ($rootScope.sideBarExpanded) {
            $(element).addClass("left-184").removeClass("left-74");
          } else {
            $(element).removeClass("left-184").addClass("left-74");
          }
        };
        checkClass();
        $rootScope.$watch("sideBarExpanded", function(oldVal, newVal) {
          if (oldVal !== newVal) {
            checkClass();
          }
        });
      }
    };
  }])
  // expand or collapse left sidebar after arrow click
  .directive('toggleSidebar', ["$rootScope", function($rootScope) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        var $ele = $(element);
        $ele.find(".side-arrow").click(function() {
          $ele.toggleClass('absolute-nav');
          if ($ele.hasClass("absolute-nav")) {
            $ele.find("ul li").removeClass("current");
            $ele.find("ul li a.li-links span.arrow-down")
              .removeClass("arrow-down")
              .addClass("arrow-right");
            $rootScope.sideBarExpanded = false;
          } else {
            $rootScope.sideBarExpanded = true;
          }
          $rootScope.$apply();
        });
      }
    };
  }])
  // transform form controls
  .directive('jqtransform', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        element.ready(function() {
          $(element).jqTransform({imgPath: '/images/forms/'});
        });
      }
    };
  }])
  // custom date picker
  .directive('datepicker', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        var $ele = $(element);
        $ele.datepicker({
          dateFormat: "mm/dd/yy"
        });
        $ele.next(".date-icon").click(function() {
          $ele.trigger("click").focus();
        });
      }
    };
  }])
  // iterate through all boxes and fix height
  .directive('fixBoxesHeight', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        element.ready(function() {
          var maxHeight = 0,
            $boxes = $(element).find('.boxes');
          $boxes.each(function() {
            maxHeight = Math.max(maxHeight, $(this).height());
          });
          $boxes.height(maxHeight);
        });
      }
    };
  }])
  // display table with project orders
  .directive('ordersTable', [function($templateCache) {
    return {
      restrict: 'E',
      scope: {
        orders: "="
      },
      templateUrl: '/partials/common/orders-table.html'
    };
  }])
  // display box with service details
  .directive('serviceBox', [function($templateCache) {
    return {
      restrict: 'E',
      scope: {
        service: "="
      },
      templateUrl: '/partials/common/service-box.html'
    };
  }])
  // show grid or list view
  .directive('switchViewButtons', ["fixSidebar", function(fixSidebar) {
    return {
      restrict: 'E',
      template: [
        '',
        '',
        '',
        ''
      ].join(""),
      scope: {
        gridView: "=",
        listView: "="
      },
      link: function(scope, element) {
        scope.showList = function() {
          $(scope.gridView).hide();
          $(scope.listView).show();
          $(element).find(".js-list-btn").addClass('btn-active');
          $(element).find(".js-grid-btn").removeClass('btn-active');
          fixSidebar();
        };
        scope.showGrid = function() {
          $(scope.gridView).show();
          $(scope.listView).hide();
          $(element).find(".js-grid-btn").addClass('btn-active');
          $(element).find(".js-list-btn").removeClass('btn-active');
          fixSidebar();
        };
      }
    };
  }])
  // show category (blue print, webservices, applications) in marketplace view
  .directive('marketplaceItems', [function($templateCache) {
    return {
      restrict: 'E',
      templateUrl: '/partials/common/marketplace-items.html',
      transclude: true,
      scope: {
        items: "="
      },
      link: function(scope) {
        scope.tab = "featured";
      }
    };
  }])
  // show tooltip on mouse over
  .directive('tooltip', [function() {
    return {
      restrict: 'A',
      link: function(scope, element) {
        $(element).tooltip({
          tooltipClass: "icon-arrow",
          position: {
            my: "left-23 top",
            at: "center bottom+24"
          }
        });
      }
    };
  }])
  // popup with X icon for dashboard
  .directive('alertPopup', ["fixSidebar", function(fixSidebar) {
    return {
      restrict: 'E',
      scope: {
        msg: "="
      },
      transclude: true,
      template: '

',
      link: function(scope, element) {
        $(element).find('.close').click(function() {
          $(element).remove();
          fixSidebar();
        });
      }
    };
  }])
  // animate graphs
  .directive('animateKnob', ["$interval", function($interval) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        element.ready(function() {
          var $element = $(element);
          var intervalId = null;
          var animate = function() {
            var targetValue = parseInt($element.attr("data-target-value"));
            if (!targetValue) {
              return;
            }
            $element.knob({
              'draw': function() {
                var $this = $(this.i);
                $this.val(this.cv + '%');
                $this.css({
                  "font-family": "SourceSansPro_Regular",
                  "font-size": "42px",
                  "color": "#0a4684",
                  "font-weight": "normal",
                  "display": "inline-block"
                });
                $this.on("focus", function() {
                  $this.parent().click();
                });
              }
            });
            if (intervalId) {
              $interval.cancel(intervalId);
              intervalId = null;
            }
            var currentValue = 0;
            intervalId = $interval(function() {
              currentValue += 1;
              $element.val(currentValue).trigger('change');
              if (currentValue === targetValue) {
                $interval.cancel(intervalId);
                intervalId = null;
              }
              if (currentValue === 100) {
                $element.css({
                  "width": "101px",
                  "margin-left": "-127px"
                });
              }
            }, 10);
          };
          animate();
          scope.$watch("selectedStatistic", function(newValue, oldValue) {
            if (newValue !== oldValue) {
              animate();
            }
          });
        });
      }
    };
  }]);<|endoftext|>


<commit_before>const fs = require('fs')
const eventHandler = evnt => require(`../events/${evnt}.js`)
const log = require('./logger.js')
const config = require('../config.json')
const storage = require('./storage.js')
const pageControls = require('./pageControls.js')
const EVENT_HANDLERS = {
  guildCreate: guildCreateHandler,
  guildDelete: guildDeleteHandler,
  channelDelete: channelDeleteHandler,
  roleUpdate: roleUpdateHandler,
  roleDelete: roleDeleteHandler,
  guildUpdate: guildUpdateHandler,
  messageReactionAdd: messageReactionAddHandler,
  messageReactionRemove: messageReactionRemoveHandler,
  message: messageHandler
}
let cmdsExtension
if (fs.existsSync('./settings/commands.js')) {
  try { cmdsExtension = require('../settings/commands.js') } catch (e) { console.log(`Error: Unable to load commands extension file. Reason:\n`, e) }
  fs.watchFile('./settings/commands.js', (cur, prev) => {
    delete require.cache[require.resolve('../settings/commands.js')]
    try {
      cmdsExtension = require('../settings/commands.js')
      console.log(`Commands extension file has been updated`)
    } catch (e) {
      console.log(`Commands extension file was changed, but could not be updated. Reason:\n`, e)
    }
  })
}

function guildCreateHandler (guild) {
  eventHandler('guildCreate')(storage.bot, guild)
}

function guildDeleteHandler (guild) {
  eventHandler('guildDelete')(storage.bot, guild)
}

function channelDeleteHandler (channel) {
  eventHandler('channelDelete')(channel)
}

function roleUpdateHandler (oldRole, newRole) {
  if (oldRole.name === newRole.name) return
  eventHandler('roleUpdate')(storage.bot, oldRole, newRole)
}

function roleDeleteHandler (role) {
  eventHandler('roleDelete')(storage.bot, role)
}

function guildUpdateHandler (oldGuild, newGuild) {
  if (newGuild.name === oldGuild.name) return
  eventHandler('guildUpdate')(storage.bot, oldGuild, newGuild)
}

function messageReactionAddHandler (msgReaction, user) {
  if ((msgReaction.emoji.name !== '▶' && msgReaction.emoji.name !== '◀') || user.bot || !pageControls.has(msgReaction.message.id)) return
  eventHandler('messageReactionAdd')(storage.bot, msgReaction, user)
}

function messageReactionRemoveHandler (msgReaction, user) {
  if ((msgReaction.emoji.name !== '▶' && msgReaction.emoji.name !== '◀') || user.bot || !pageControls.has(msgReaction.message.id)) return
  eventHandler('messageReactionRemove')(storage.bot, msgReaction, user)
}

function messageHandler (message) {
  eventHandler('message')(storage.bot, message, config.bot.enableCommands === true ? null : true)
  try { if (cmdsExtension) cmdsExtension(storage.bot, message) } catch (e) {}
}

exports.createManagers = () => {
  for (var eventName in EVENT_HANDLERS) {
    if (eventName !== 'message') storage.bot.on(eventName, EVENT_HANDLERS[eventName])
  }
}

exports.enableCommands = () => {
  storage.bot.on('message', messageHandler)
  if (config.bot.enableCommands !== false) log.general.info(`${storage.bot.shard && storage.bot.shard.count > 0 ? 'SH ' + storage.bot.shard.id + ' ' : ''}Commands have been enabled`)
}

exports.disableAll = () => {
  for (var eventName in EVENT_HANDLERS) storage.bot.removeListener(eventName, EVENT_HANDLERS[eventName])
}
<commit_msg>Replace console.log with logger function, resolved #61<commit_after>const fs = require('fs')
const eventHandler = evnt => require(`../events/${evnt}.js`)
const log = require('./logger.js')
const config = require('../config.json')
const storage = require('./storage.js')
const pageControls = require('./pageControls.js')
const EVENT_HANDLERS = {
  guildCreate: guildCreateHandler,
  guildDelete: guildDeleteHandler,
  channelDelete: channelDeleteHandler,
  roleUpdate: roleUpdateHandler,
  roleDelete: roleDeleteHandler,
  guildUpdate: guildUpdateHandler,
  messageReactionAdd: messageReactionAddHandler,
  messageReactionRemove: messageReactionRemoveHandler,
  message: messageHandler
}
let cmdsExtension
if (fs.existsSync('./settings/commands.js')) {
  try { cmdsExtension = require('../settings/commands.js') } catch (e) { log.general.error(`Unable to load commands extension file`, e) }
  fs.watchFile('./settings/commands.js', (cur, prev) => {
    delete require.cache[require.resolve('../settings/commands.js')]
    try {
      cmdsExtension = require('../settings/commands.js')
      log.general.success(`Commands extension file has been updated`)
    } catch (e) {
      log.general.error(`Commands extension file was changed, but could not be updated`, e)
    }
  })
}

function guildCreateHandler (guild) {
  eventHandler('guildCreate')(storage.bot, guild)
}

function guildDeleteHandler (guild) {
  eventHandler('guildDelete')(storage.bot, guild)
}

function channelDeleteHandler (channel) {
  eventHandler('channelDelete')(channel)
}

function roleUpdateHandler (oldRole, newRole) {
  if (oldRole.name === newRole.name) return
  eventHandler('roleUpdate')(storage.bot, oldRole, newRole)
}

function roleDeleteHandler (role) {
  eventHandler('roleDelete')(storage.bot, role)
}

function guildUpdateHandler (oldGuild, newGuild) {
  if (newGuild.name === oldGuild.name) return
  eventHandler('guildUpdate')(storage.bot, oldGuild, newGuild)
}

function messageReactionAddHandler (msgReaction, user) {
  if ((msgReaction.emoji.name !== '▶' && msgReaction.emoji.name !== '◀') || user.bot || !pageControls.has(msgReaction.message.id)) return
  eventHandler('messageReactionAdd')(storage.bot, msgReaction, user)
}

function messageReactionRemoveHandler (msgReaction, user) {
  if ((msgReaction.emoji.name !== '▶' && msgReaction.emoji.name !== '◀') || user.bot || !pageControls.has(msgReaction.message.id)) return
  eventHandler('messageReactionRemove')(storage.bot, msgReaction, user)
}

function messageHandler (message) {
  eventHandler('message')(storage.bot, message, config.bot.enableCommands === true ? null : true)
  try { if (cmdsExtension) cmdsExtension(storage.bot, message) } catch (e) {}
}

exports.createManagers = () => {
  for (var eventName in EVENT_HANDLERS) {
    if (eventName !== 'message') storage.bot.on(eventName, EVENT_HANDLERS[eventName])
  }
}

exports.enableCommands = () => {
  storage.bot.on('message', messageHandler)
  if (config.bot.enableCommands !== false) log.general.info(`${storage.bot.shard && storage.bot.shard.count > 0 ? 'SH ' + storage.bot.shard.id + ' ' : ''}Commands have been enabled`)
}

exports.disableAll = () => {
  for (var eventName in EVENT_HANDLERS) storage.bot.removeListener(eventName, EVENT_HANDLERS[eventName])
}
<|endoftext|>


<commit_before>/*
 * Loady module
 * https://github.com/softwarespot/loady
 * Author: softwarespot
 * Licensed under the MIT license
 * Version: 0.1.0
 *
 * Loady module - Load external JavaScript file(s) and append it to the head of the current document
 * Note: This is NOT a replacement for module loaders available on the market
 */
; // jshint ignore:line
((global, name, iLoader, undefined) => {
    // Constants

    // Public API
    const _loadyAPI = (sourceFiles, callback) => {
        // Create an instance of the internal loader class
        const loady = new iLoader();

        // Load the source file(s)
        loady.load(sourceFiles, callback);
    };

    // Store a 'module' reference
    const module = global.module;

    // Store a 'define' reference
    const define = global.define;

    if (module !== undefined && module.exports) {
        // Node.js Module
        module.exports = _loadyAPI;
    } else if (typeof define === 'function' && define.amd) {
        // AMD Module
        global.define(name, [], _loadyAPI);
    }

    // Check if Loady has already been registered beforehand and if so, throw an error
    if (global[name] !== undefined) {
        throw new Error('Loady appears to be already registered with the global object, therefore the module has not be registered.');
    }

    // Append the Loady API to the global object reference
    global[name] = _loadyAPI;

})(window, 'loady', (global) => { // Can't be 'this' with babelJS, as it gets set to 'undefined'
    // Constants

    // Version number of the module
    const VERSION = '0.1.0';

    const _dataAttributes = {
        SOURCE_FILE: 'data-loady-sourcefile'
    };

    // Store the document object reference
    const document = global.document;

    // Store the first head node
    const _head = document.head || document.getElementsByTagName('head')[0];

    // Regular expression to strip the JS extension
    const _reJsExtension = /\.js$/;

    // Store previously loaded source file(s)
    const _storageFiles = [];

    // Store the state of the source file(s) i.e. true or false
    const _storageState = [];

    // Return strings of toString() found on the Object prototype
    // Based on the implementation by lodash inc. is* function as well
    const _objectStrings = {
        FUNCTION: '[object Function]',
        GENERATOR: '[object GeneratorFunction]',
        STRING: '[object String]'
    };

    // Store the toString method
    const _objectToString = global.Object.prototype.toString;

    /**
     * Check if a variable is an array datatype
     *
     * @param {mixed} value Value to check
     * @returns {boolean} True the value is an array datatype; otherwise, false
     */
    const isArray = global.Array.isArray;

    /**
     * Check if a variable is a function datatype
     *
     * @param {mixed} value Value to check
     * @returns {boolean} True the value is a function datatype; otherwise, false
     */
    function isFunction(value) {
        const tag = isObject(value) ? _objectToString.call(value) : '';
        return tag === _objectStrings.FUNCTION || tag === _objectStrings.GENERATOR;
    }

    /**
     * Check if a variable is an object
     *
     * @param {mixed} value Value to check
     * @returns {boolean} True the value is an object; otherwise, false
     */
    function isObject(value) {
        // Store the typeof value
        const type = typeof value;

        // !!value is basically checking if value is not 'truthy' e.g. null or zero and then inverts that boolean value
        // So, !'Some test' is false and then inverting false is true. There if value contains 'something', continue
        return !!value && (type === 'object' || type === 'function');
    }

    /**
     * Check if a variable is a string datatype
     *
     * @param {mixed} value Value to check
     * @returns {boolean} True the value is a string datatype; otherwise, false
     */
    function isString(value) {
        return typeof value === 'string' || _objectToString.call(value) === _objectStrings.STRING;
    }

    /**
     * ILoader class
     */
    return class ILoader {
        /**
         * Constructor for the class
         *
         * @return {undefined}
         */
        constructor() {
            this.destroy();
        }

        /**
         * Tidy up resources i.e. good housekeeping
         *
         * @return {undefined}
         */
        destroy() {
            // Final callback function after all scripts have been loaded successfully or not
            this._callback = null;

            // Currently loaded total count
            //
            // Note: The loaded count is set to -1, due to this.onCompleted incrementing by 1 and checking against this._length,
            // which right now is set to 0. So this is utilised during pre-checks
            this._loaded = -1;

            // An array of successfully loaded source file(s)
            this._called = null;

            // An array of source file(s) initially passed to the module
            this._files = null;

            // Length of the source file(s) initially passed to the module
            this._length = 0;
        }

        /**
         * Load an array of source file(s)
         *
         * @param {array} sourceFiles An array of source file(s). Note: .js is optional and will be appended if not present
         * @param {function} callback Callback function to invoke on completion successful or not.
         * The arguments passed to the callback function is an array of loaded scripts and a success parameter of either true or false
         * @return {undefined}
         */
        load(sourceFiles, callback) {
            // Destroy the previous contents
            this.destroy();

            // This is the only error thrown, due to a callback being required
            if (!isFunction(callback)) {
                throw new global.Error('Loady: The callback function argument is not a valid function type.');
            }

            // Coerce as an array if the source file is a string
            if (isString(sourceFiles)) {
                sourceFiles = [sourceFiles];
            }

            // Set the callback function property
            this._callback = callback;

            // Check if the source file(s) argument is not an array
            if (!isArray(sourceFiles)) {
                this.onCompleted(false);
                return;
            }

            // Check if any values exist in the array
            if (sourceFiles.length === 0) {
                this.onCompleted(false);
                return;
            }

            // Set to 0, as now all the important pre-checks have passed
            this._loaded = 0;
            this._called = [];
            this._files = sourceFiles;
            this._length = sourceFiles.length;

            for (let i = 0, length = this._length; i < length; i++) {
                let sourceFile = sourceFiles[i];
                // Strip and append .js to the source file
                sourceFile = sourceFile.replace(_reJsExtension, '') + '.js';

                const index = _storageFiles.indexOf(sourceFile);
                if (index !== -1) {
                    this.onCompleted(_storageState[index]);
                    continue;
                }

                // Load the script file and append to the current document
                this.loadScript(sourceFile);
            }
        }

        /**
         * Load a script and append to the first HEAD node in the DOM
         *
         * @param {string} sourceFile Script source location that can be absolute or relative
         * @return {undefined}
         */
        loadScript(sourceFile) {
            const node = document.createElement('SCRIPT');
            node.src = sourceFile;
            // node.text = file;

            // node.type = 'text/javascript';
            // node.charset = 'utf-8';

            node.async = true;

            node.setAttribute(_dataAttributes.SOURCE_FILE, sourceFile);

            // Attach events
            // Note: Bind is used to 'bind' to the context of 'this' i.e. the current object
            node.addEventListener('load', this.onLoad.bind(this), false);
            node.addEventListener('error', this.onLoad.bind(this), false);

            // Append to the HEAD node
            _head.appendChild(node);

            // Push to the internal storage
            _storageFiles.push(sourceFile);
        }

        /**
         * Increment the loaded scripts property and invoke the callback function on completion
         *
         * @param {boolean} isSuccess Whether the request was successful or not
         * @return {undefined}
         */
        onCompleted(isSuccess) {
            // If not equal to the boolean type and true, then automatically assume as false
            if (isSuccess !== true) {
                isSuccess = false;
            }

            // Increment the loaded total count
            this._loaded++;

            if (this._length === this._loaded) {
                this._callback.apply(this, [this._called, isSuccess]);
                this.destroy();
            }
        }

        /**
         * The 'load' or 'error' callback function for the event listeners
         *
         * @param {event} event Event object passed by the event listener
         * @return {undefined}
         */
        onLoad(event) {
            // Store the type of event and whether it was a 'load' or 'error' type event
            const type = event.type;
            const isLoaded = type === 'load';

            if (isLoaded || type === 'error') {
                const node = event.currentTarget || event.srcElement;
                if (!node) {
                    return;
                }

                // Remove assigned events
                node.removeEventListener('load', this.onLoad, false);
                node.removeEventListener('error', this.onLoad, false);

                // Push the state of the source file. If loaded will be true; otherwise, false
                _storageState.push(isLoaded);

                // Display details about the inserted SCRIPT node and script
                if (isLoaded) {
                    // Get the source file directly from the data-* attribute
                    const sourceFile = node.getAttribute(_dataAttributes.SOURCE_FILE);

                    // Push to the successfully loaded scripts
                    this._called.push(sourceFile);
                }

                this.onCompleted(true);
            }
        }

        /**
         * Get the version number of the module
         *
         * @return {string} Module version number
         */
        getVersion() {
            return VERSION;
        }
    };

}(window)); // Can't be 'this' with babelJS, as it gets set to 'undefined'
<commit_msg>Fixed typo<commit_after>/*
 * Loady module
 * https://github.com/softwarespot/loady
 * Author: softwarespot
 * Licensed under the MIT license
 * Version: 0.1.0
 *
 * Loady module - Load external JavaScript file(s) and append it to the head of the current document
 * Note: This is NOT a replacement for module loaders available on the market
 */
; // jshint ignore:line
((global, name, iLoader, undefined) => {
    // Constants

    // Public API
    const _loadyAPI = (sourceFiles, callback) => {
        // Create an instance of the internal loader class
        const loady = new iLoader();

        // Load the source file(s)
        loady.load(sourceFiles, callback);
    };

    // Store a 'module' reference
    const module = global.module;

    // Store a 'define' reference
    const define = global.define;

    if (module !== undefined && module.exports) {
        // Node.js Module
        module.exports = _loadyAPI;
    } else if (typeof define === 'function' && define.amd) {
        // AMD Module
        global.define(name, [], _loadyAPI);
    }

    // Check if Loady has already been registered beforehand and if so, throw an error
    if (global[name] !== undefined) {
        throw new Error('Loady appears to be already registered with the global object, therefore the module has not been registered.');
    }

    // Append the Loady API to the global object reference
    global[name] = _loadyAPI;

})(window, 'loady', (global) => { // Can't be 'this' with babelJS, as it gets set to 'undefined'
    // Constants

    // Version number of the module
    const VERSION = '0.1.0';

    const _dataAttributes = {
        SOURCE_FILE: 'data-loady-sourcefile'
    };

    // Store the document object reference
    const document = global.document;

    // Store the first head node
    const _head = document.head || document.getElementsByTagName('head')[0];

    // Regular expression to strip the JS extension
    const _reJsExtension = /\.js$/;

    // Store previously loaded source file(s)
    const _storageFiles = [];

    // Store the state of the source file(s) i.e. true or false
    const _storageState = [];

    // Return strings of toString() found on the Object prototype
    // Based on the implementation by lodash inc. is* function as well
    const _objectStrings = {
        FUNCTION: '[object Function]',
        GENERATOR: '[object GeneratorFunction]',
        STRING: '[object String]'
    };

    // Store the toString method
    const _objectToString = global.Object.prototype.toString;

    /**
     * Check if a variable is an array datatype
     *
     * @param {mixed} value Value to check
     * @returns {boolean} True the value is an array datatype; otherwise, false
     */
    const isArray = global.Array.isArray;

    /**
     * Check if a variable is a function datatype
     *
     * @param {mixed} value Value to check
     * @returns {boolean} True the value is a function datatype; otherwise, false
     */
    function isFunction(value) {
        const tag = isObject(value) ? _objectToString.call(value) : '';
        return tag === _objectStrings.FUNCTION || tag === _objectStrings.GENERATOR;
    }

    /**
     * Check if a variable is an object
     *
     * @param {mixed} value Value to check
     * @returns {boolean} True the value is an object; otherwise, false
     */
    function isObject(value) {
        // Store the typeof value
        const type = typeof value;

        // !!value is basically checking if value is not 'truthy' e.g. null or zero and then inverts that boolean value
        // So, !'Some test' is false and then inverting false is true. There if value contains 'something', continue
        return !!value && (type === 'object' || type === 'function');
    }

    /**
     * Check if a variable is a string datatype
     *
     * @param {mixed} value Value to check
     * @returns {boolean} True the value is a string datatype; otherwise, false
     */
    function isString(value) {
        return typeof value === 'string' || _objectToString.call(value) === _objectStrings.STRING;
    }

    /**
     * ILoader class
     */
    return class ILoader {
        /**
         * Constructor for the class
         *
         * @return {undefined}
         */
        constructor() {
            this.destroy();
        }

        /**
         * Tidy up resources i.e. good housekeeping
         *
         * @return {undefined}
         */
        destroy() {
            // Final callback function after all scripts have been loaded successfully or not
            this._callback = null;

            // Currently loaded total count
            //
            // Note: The loaded count is set to -1, due to this.onCompleted incrementing by 1 and checking against this._length,
            // which right now is set to 0. So this is utilised during pre-checks
            this._loaded = -1;

            // An array of successfully loaded source file(s)
            this._called = null;

            // An array of source file(s) initially passed to the module
            this._files = null;

            // Length of the source file(s) initially passed to the module
            this._length = 0;
        }

        /**
         * Load an array of source file(s)
         *
         * @param {array} sourceFiles An array of source file(s). Note: .js is optional and will be appended if not present
         * @param {function} callback Callback function to invoke on completion successful or not.
         * The arguments passed to the callback function is an array of loaded scripts and a success parameter of either true or false
         * @return {undefined}
         */
        load(sourceFiles, callback) {
            // Destroy the previous contents
            this.destroy();

            // This is the only error thrown, due to a callback being required
            if (!isFunction(callback)) {
                throw new global.Error('Loady: The callback function argument is not a valid function type.');
            }

            // Coerce as an array if the source file is a string
            if (isString(sourceFiles)) {
                sourceFiles = [sourceFiles];
            }

            // Set the callback function property
            this._callback = callback;

            // Check if the source file(s) argument is not an array
            if (!isArray(sourceFiles)) {
                this.onCompleted(false);
                return;
            }

            // Check if any values exist in the array
            if (sourceFiles.length === 0) {
                this.onCompleted(false);
                return;
            }

            // Set to 0, as now all the important pre-checks have passed
            this._loaded = 0;
            this._called = [];
            this._files = sourceFiles;
            this._length = sourceFiles.length;

            for (let i = 0, length = this._length; i < length; i++) {
                let sourceFile = sourceFiles[i];
                // Strip and append .js to the source file
                sourceFile = sourceFile.replace(_reJsExtension, '') + '.js';

                const index = _storageFiles.indexOf(sourceFile);
                if (index !== -1) {
                    this.onCompleted(_storageState[index]);
                    continue;
                }

                // Load the script file and append to the current document
                this.loadScript(sourceFile);
            }
        }

        /**
         * Load a script and append to the first HEAD node in the DOM
         *
         * @param {string} sourceFile Script source location that can be absolute or relative
         * @return {undefined}
         */
        loadScript(sourceFile) {
            const node = document.createElement('SCRIPT');
            node.src = sourceFile;
            // node.text = file;

            // node.type = 'text/javascript';
            // node.charset = 'utf-8';

            node.async = true;

            node.setAttribute(_dataAttributes.SOURCE_FILE, sourceFile);

            // Attach events
            // Note: Bind is used to 'bind' to the context of 'this' i.e. the current object
            node.addEventListener('load', this.onLoad.bind(this), false);
            node.addEventListener('error', this.onLoad.bind(this), false);

            // Append to the HEAD node
            _head.appendChild(node);

            // Push to the internal storage
            _storageFiles.push(sourceFile);
        }

        /**
         * Increment the loaded scripts property and invoke the callback function on completion
         *
         * @param {boolean} isSuccess Whether the request was successful or not
         * @return {undefined}
         */
        onCompleted(isSuccess) {
            // If not equal to the boolean type and true, then automatically assume as false
            if (isSuccess !== true) {
                isSuccess = false;
            }

            // Increment the loaded total count
            this._loaded++;

            if (this._length === this._loaded) {
                this._callback.apply(this, [this._called, isSuccess]);
                this.destroy();
            }
        }

        /**
         * The 'load' or 'error' callback function for the event listeners
         *
         * @param {event} event Event object passed by the event listener
         * @return {undefined}
         */
        onLoad(event) {
            // Store the type of event and whether it was a 'load' or 'error' type event
            const type = event.type;
            const isLoaded = type === 'load';

            if (isLoaded || type === 'error') {
                const node = event.currentTarget || event.srcElement;
                if (!node) {
                    return;
                }

                // Remove assigned events
                node.removeEventListener('load', this.onLoad, false);
                node.removeEventListener('error', this.onLoad, false);

                // Push the state of the source file. If loaded will be true; otherwise, false
                _storageState.push(isLoaded);

                // Display details about the inserted SCRIPT node and script
                if (isLoaded) {
                    // Get the source file directly from the data-* attribute
                    const sourceFile = node.getAttribute(_dataAttributes.SOURCE_FILE);

                    // Push to the successfully loaded scripts
                    this._called.push(sourceFile);
                }

                this.onCompleted(true);
            }
        }

        /**
         * Get the version number of the module
         *
         * @return {string} Module version number
         */
        getVersion() {
            return VERSION;
        }
    };

}(window)); // Can't be 'this' with babelJS, as it gets set to 'undefined'
<|endoftext|>


<commit_before>/***** BEGIN LICENSE BLOCK ***** {{{
Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@gmx.net>

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
}}} ***** END LICENSE BLOCK *****/

/** @scope modules */

// Do NOT create instances of this class yourself, use the helper method
// mappings.add() instead
function Map(modes, cmds, description, action, extraInfo) //{{{
{
    if (!modes || (!cmds || !cmds.length) || !action)
        return null;

    if (!extraInfo)
        extraInfo = {};

    this.modes = modes;
    // only store keysyms with uppercase modifier strings
    this.names = cmds.map(function (cmd) cmd.replace(/[casm]-/g, String.toUpperCase));
    this.action = action;

    this.flags = extraInfo.flags || 0;
    this.description = description || "";
    this.rhs = extraInfo.rhs || null;
    this.noremap = extraInfo.noremap || false;
    this.silent = extraInfo.silent || false;
};

Map.prototype = {

    hasName: function (name)
    {
        return this.names.indexOf(name) >= 0;
    },

    execute: function (motion, count, argument)
    {
        let args = [];

        if (this.flags & Mappings.flags.MOTION)
            args.push(motion);
        if (this.flags & Mappings.flags.COUNT)
            args.push(count);
        if (this.flags & Mappings.flags.ARGUMENT)
            args.push(argument);

        let self = this;
        // FIXME: Kludge.
        if (this.names[0] != ".")
            mappings.repeat = function () self.action.apply(self, args);

        return this.action.apply(this, args);
    }

}; //}}}

/**
 * @instance mappings
 */
function Mappings() //{{{
{
    ////////////////////////////////////////////////////////////////////////////////
    ////////////////////// PRIVATE SECTION /////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    var main = []; // default mappings
    var user = []; // user created mappings

    for (let mode in modes)
    {
        main[mode] = [];
        user[mode] = [];
    }

    function addMap(map, userMap)
    {
        let where = userMap ? user : main;
        map.modes.forEach(function (mode) {
                if (!(mode in where))
                    where[mode] = [];
                where[mode].push(map);
        });
    }

    function getMap(mode, cmd, stack)
    {
        let maps = stack[mode] || [];

        for (let [,map] in Iterator(maps))
        {
            if (map.hasName(cmd))
                return map;
        }

        return null;
    }

    function removeMap(mode, cmd)
    {
        let maps = user[mode] || [];
        let names;

        for (let [i, map] in Iterator(maps))
        {
            for (let [j, name] in Iterator(map.names))
            {
                if (name == cmd)
                {
                    map.names.splice(j, 1);
                    if (map.names.length == 0)
                        maps.splice(i, 1);
                    return;
                }
            }
        }
    }

    function expandLeader(keyString) keyString.replace(/<Leader>/i, mappings.getMapLeader())

    // Return all mappings present in all @modes
    function mappingsIterator(modes, stack)
    {
        modes = modes.slice();
        return (map for ([i, map] in Iterator(stack[modes.shift()]))
            if (modes.every(function (mode) stack[mode].some(
                        function (m) m.rhs == map.rhs && m.names[0] == map.names[0]))))
    }

    function addMapCommands(ch, modes, modeDescription)
    {
        // 0 args -> list all maps
        // 1 arg  -> list the maps starting with args
        // 2 args -> map arg1 to arg*
        function map(args, mode, noremap)
        {
            if (!args.length)
            {
                mappings.list(mode);
                return;
            }

            // ?:\s+ <- don't remember; (...)? optional = rhs
            let [lhs, rhs] = args;

            if (!rhs) // list the mapping
            {
                mappings.list(mode, expandLeader(lhs));
            }
            else
            {
                for (let [,m] in Iterator(mode))
                {
                    mappings.addUserMap([m], [lhs],
                            "User defined mapping",
                            function (count) { events.feedkeys((count > 1 ? count : "") + this.rhs, this.noremap, this.silent); },
                            {
                                flags: Mappings.flags.COUNT,
                                rhs: rhs,
                                noremap: !!noremap,
                                silent: "<silent>" in args
                            });
                }
            }
        }

        modeDescription = modeDescription ? " in " + modeDescription + " mode" : "";

        const opts = {
                completer: function (context, args) completion.userMapping(context, args, modes),
                options: [
                    [["<silent>", "<Silent>"],  commands.OPTION_NOARG]
                ],
                literal: 1,
                serial: function ()
                {
                    let noremap = this.name.indexOf("noremap") > -1;
                    return [
                        {
                            command: this.name,
                            options: map.silent ? { "<silent>": null } : {},
                            arguments: [map.names[0]],
                            literalArg: map.rhs
                        }
                        for (map in mappingsIterator(modes, user))
                        if (map.rhs && map.noremap == noremap)
                    ]
                }
        };

        commands.add([ch ? ch + "m[ap]" : "map"],
            "Map a key sequence" + modeDescription,
            function (args) { map(args, modes, false); },
            opts);

        commands.add([ch + "no[remap]"],
            "Map a key sequence without remapping keys" + modeDescription,
            function (args) { map(args, modes, true); },
            opts);

        commands.add([ch + "mapc[lear]"],
            "Remove all mappings" + modeDescription,
            function () { modes.forEach(function (mode) { mappings.removeAll(mode); }); },
            { argCount: "0" });

        commands.add([ch + "unm[ap]"],
            "Remove a mapping" + modeDescription,
            function (args)
            {
                args = args[0];

                let found = false;
                for (let [,mode] in Iterator(modes))
                {
                    if (mappings.hasMap(mode, args))
                    {
                        mappings.remove(mode, args);
                        found = true;
                    }
                }
                if (!found)
                    liberator.echoerr("E31: No such mapping");
            },
            {
                argCount: "1",
                completer: function (context, args) completion.userMapping(context, args, modes)
            });
    }

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// COMMANDS ////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    addMapCommands("",  [modes.NORMAL], "");
    addMapCommands("c", [modes.COMMAND_LINE], "command line");
    addMapCommands("i", [modes.INSERT, modes.TEXTAREA], "insert");
    if (liberator.has("mail"))
        addMapCommands("m", [modes.MESSAGE], "message");

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// PUBLIC SECTION //////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    liberator.registerObserver("load_completion", function ()
    {
        completion.setFunctionCompleter(mappings.get,
        [
            null,
            function (context, obj, args)
            {
                let mode = args[0]
                return util.Array.flatten(
                [
                    [[name, map.description] for ([i, name] in Iterator(map.names))]
                    for ([i, map] in Iterator(user[mode].concat(main[mode])))
                ])
            }
        ]);
    });

    // FIXME:
    Mappings.flags = {
        ALLOW_EVENT_ROUTING: 1 << 0, // if set, return true inside the map command to pass the event further to Firefox
        MOTION:              1 << 1,
        COUNT:               1 << 2,
        ARGUMENT:            1 << 3
    };

    return {

        // NOTE: just normal mode for now
        __iterator__: function () mappingsIterator([modes.NORMAL], main),

        // used by :mkvimperatorrc to save mappings
        getUserIterator: function (mode) mappingsIterator(mode, user),

        add: function (modes, keys, description, action, extra)
        {
            addMap(new Map(modes, keys, description, action, extra), false);
        },

        addUserMap: function (modes, keys, description, action, extra)
        {
            keys = keys.map(expandLeader);
            let map = new Map(modes, keys, description || "User defined mapping", action, extra);

            // remove all old mappings to this key sequence
            for (let [,name] in Iterator(map.names))
            {
                for (let [,mode] in Iterator(map.modes))
                    removeMap(mode, name);
            }

            addMap(map, true);
        },

        get: function (mode, cmd)
        {
            mode = mode || modes.NORMAL;
            return getMap(mode, cmd, user) || getMap(mode, cmd, main);
        },

        getDefault: function (mode, cmd)
        {
            mode = mode || modes.NORMAL;
            return getMap(mode, cmd, main);
        },

        // returns an array of mappings with names which START with "cmd" (but are NOT "cmd")
        getCandidates: function (mode, cmd)
        {
            let mappings = user[mode].concat(main[mode]);
            let matches = [];

            for (let [,map] in Iterator(mappings))
            {
                for (let [,name] in Iterator(map.names))
                {
                    if (name.indexOf(cmd) == 0 && name.length > cmd.length)
                    {
                        // for < only return a candidate if it doesn't look like a <c-x> mapping
                        if (cmd != "<" || !/^<.+>/.test(name))
                            matches.push(map);
                    }
                }
            }

            return matches;
        },

        getMapLeader: function ()
        {
            let leaderRef = liberator.variableReference("mapleader");
            return leaderRef[0] ? leaderRef[0][leaderRef[1]] : "\\";
        },

        // returns whether the user added a custom user map
        hasMap: function (mode, cmd)
        {
            return user[mode].some(function (map) map.hasName(cmd));
        },

        remove: function (mode, cmd)
        {
            removeMap(mode, cmd);
        },

        removeAll: function (mode)
        {
            user[mode] = [];
        },

        list: function (modes, filter)
        {
            let modeSign = "";
            modes.forEach(function (mode)
            {
                if (mode == modes.NORMAL)
                    modeSign += "n";
                if ((mode == modes.INSERT || mode == modes.TEXTAREA) && modeSign.indexOf("i") == -1)
                    modeSign += "i";
                if (mode == modes.COMMAND_LINE)
                    modeSign += "c";
                if (mode == modes.MESSAGRE)
                    modeSign += "m";
            });

            let maps = mappingsIterator(modes, user);
            if (filter)
                maps = [map for (map in maps) if (map.names[0] == filter)];

            let list =

                    {
                        template.map(maps, function (map)
                            template.map(map.names, function (name)

                                {modeSign} {name}
                                {map.noremap ? "*" : " "}
                                {map.rhs || "function () { ... }"}

))
                    }

;

            // TODO: Move this to an ItemList to show this automatically
            if (list.*.length() == list.text().length())
            {
                liberator.echomsg("No mapping found");
                return;
            }
            commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
        }

    };
    //}}}
}; //}}}

// vim: set fdm=marker sw=4 ts=4 et:
<commit_msg>Add Player mode :pmap commands.<commit_after>/***** BEGIN LICENSE BLOCK ***** {{{
Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@gmx.net>

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
}}} ***** END LICENSE BLOCK *****/

/** @scope modules */

// Do NOT create instances of this class yourself, use the helper method
// mappings.add() instead
function Map(modes, cmds, description, action, extraInfo) //{{{
{
    if (!modes || (!cmds || !cmds.length) || !action)
        return null;

    if (!extraInfo)
        extraInfo = {};

    this.modes = modes;
    // only store keysyms with uppercase modifier strings
    this.names = cmds.map(function (cmd) cmd.replace(/[casm]-/g, String.toUpperCase));
    this.action = action;

    this.flags = extraInfo.flags || 0;
    this.description = description || "";
    this.rhs = extraInfo.rhs || null;
    this.noremap = extraInfo.noremap || false;
    this.silent = extraInfo.silent || false;
};

Map.prototype = {

    hasName: function (name)
    {
        return this.names.indexOf(name) >= 0;
    },

    execute: function (motion, count, argument)
    {
        let args = [];

        if (this.flags & Mappings.flags.MOTION)
            args.push(motion);
        if (this.flags & Mappings.flags.COUNT)
            args.push(count);
        if (this.flags & Mappings.flags.ARGUMENT)
            args.push(argument);

        let self = this;
        // FIXME: Kludge.
        if (this.names[0] != ".")
            mappings.repeat = function () self.action.apply(self, args);

        return this.action.apply(this, args);
    }

}; //}}}

/**
 * @instance mappings
 */
function Mappings() //{{{
{
    ////////////////////////////////////////////////////////////////////////////////
    ////////////////////// PRIVATE SECTION /////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    var main = []; // default mappings
    var user = []; // user created mappings

    for (let mode in modes)
    {
        main[mode] = [];
        user[mode] = [];
    }

    function addMap(map, userMap)
    {
        let where = userMap ? user : main;
        map.modes.forEach(function (mode) {
                if (!(mode in where))
                    where[mode] = [];
                where[mode].push(map);
        });
    }

    function getMap(mode, cmd, stack)
    {
        let maps = stack[mode] || [];

        for (let [,map] in Iterator(maps))
        {
            if (map.hasName(cmd))
                return map;
        }

        return null;
    }

    function removeMap(mode, cmd)
    {
        let maps = user[mode] || [];
        let names;

        for (let [i, map] in Iterator(maps))
        {
            for (let [j, name] in Iterator(map.names))
            {
                if (name == cmd)
                {
                    map.names.splice(j, 1);
                    if (map.names.length == 0)
                        maps.splice(i, 1);
                    return;
                }
            }
        }
    }

    function expandLeader(keyString) keyString.replace(/<Leader>/i, mappings.getMapLeader())

    // Return all mappings present in all @modes
    function mappingsIterator(modes, stack)
    {
        modes = modes.slice();
        return (map for ([i, map] in Iterator(stack[modes.shift()]))
            if (modes.every(function (mode) stack[mode].some(
                        function (m) m.rhs == map.rhs && m.names[0] == map.names[0]))))
    }

    function addMapCommands(ch, modes, modeDescription)
    {
        // 0 args -> list all maps
        // 1 arg  -> list the maps starting with args
        // 2 args -> map arg1 to arg*
        function map(args, mode, noremap)
        {
            if (!args.length)
            {
                mappings.list(mode);
                return;
            }

            // ?:\s+ <- don't remember; (...)? optional = rhs
            let [lhs, rhs] = args;

            if (!rhs) // list the mapping
            {
                mappings.list(mode, expandLeader(lhs));
            }
            else
            {
                for (let [,m] in Iterator(mode))
                {
                    mappings.addUserMap([m], [lhs],
                            "User defined mapping",
                            function (count) { events.feedkeys((count > 1 ? count : "") + this.rhs, this.noremap, this.silent); },
                            {
                                flags: Mappings.flags.COUNT,
                                rhs: rhs,
                                noremap: !!noremap,
                                silent: "<silent>" in args
                            });
                }
            }
        }

        modeDescription = modeDescription ? " in " + modeDescription + " mode" : "";

        const opts = {
                completer: function (context, args) completion.userMapping(context, args, modes),
                options: [
                    [["<silent>", "<Silent>"],  commands.OPTION_NOARG]
                ],
                literal: 1,
                serial: function ()
                {
                    let noremap = this.name.indexOf("noremap") > -1;
                    return [
                        {
                            command: this.name,
                            options: map.silent ? { "<silent>": null } : {},
                            arguments: [map.names[0]],
                            literalArg: map.rhs
                        }
                        for (map in mappingsIterator(modes, user))
                        if (map.rhs && map.noremap == noremap)
                    ]
                }
        };

        commands.add([ch ? ch + "m[ap]" : "map"],
            "Map a key sequence" + modeDescription,
            function (args) { map(args, modes, false); },
            opts);

        commands.add([ch + "no[remap]"],
            "Map a key sequence without remapping keys" + modeDescription,
            function (args) { map(args, modes, true); },
            opts);

        commands.add([ch + "mapc[lear]"],
            "Remove all mappings" + modeDescription,
            function () { modes.forEach(function (mode) { mappings.removeAll(mode); }); },
            { argCount: "0" });

        commands.add([ch + "unm[ap]"],
            "Remove a mapping" + modeDescription,
            function (args)
            {
                args = args[0];

                let found = false;
                for (let [,mode] in Iterator(modes))
                {
                    if (mappings.hasMap(mode, args))
                    {
                        mappings.remove(mode, args);
                        found = true;
                    }
                }
                if (!found)
                    liberator.echoerr("E31: No such mapping");
            },
            {
                argCount: "1",
                completer: function (context, args) completion.userMapping(context, args, modes)
            });
    }

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// COMMANDS ////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    addMapCommands("",  [modes.NORMAL], "");
    addMapCommands("c", [modes.COMMAND_LINE], "command line");
    addMapCommands("i", [modes.INSERT, modes.TEXTAREA], "insert");
    // FIXME
    if (liberator.has("mail"))
        addMapCommands("m", [modes.MESSAGE], "message");
    if (liberator.has("player"))
        addMapCommands("p", [modes.PLAYER], "player");

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// PUBLIC SECTION //////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    liberator.registerObserver("load_completion", function ()
    {
        completion.setFunctionCompleter(mappings.get,
        [
            null,
            function (context, obj, args)
            {
                let mode = args[0]
                return util.Array.flatten(
                [
                    [[name, map.description] for ([i, name] in Iterator(map.names))]
                    for ([i, map] in Iterator(user[mode].concat(main[mode])))
                ])
            }
        ]);
    });

    // FIXME:
    Mappings.flags = {
        ALLOW_EVENT_ROUTING: 1 << 0, // if set, return true inside the map command to pass the event further to Firefox
        MOTION:              1 << 1,
        COUNT:               1 << 2,
        ARGUMENT:            1 << 3
    };

    return {

        // NOTE: just normal mode for now
        __iterator__: function () mappingsIterator([modes.NORMAL], main),

        // used by :mkvimperatorrc to save mappings
        getUserIterator: function (mode) mappingsIterator(mode, user),

        add: function (modes, keys, description, action, extra)
        {
            addMap(new Map(modes, keys, description, action, extra), false);
        },

        addUserMap: function (modes, keys, description, action, extra)
        {
            keys = keys.map(expandLeader);
            let map = new Map(modes, keys, description || "User defined mapping", action, extra);

            // remove all old mappings to this key sequence
            for (let [,name] in Iterator(map.names))
            {
                for (let [,mode] in Iterator(map.modes))
                    removeMap(mode, name);
            }

            addMap(map, true);
        },

        get: function (mode, cmd)
        {
            mode = mode || modes.NORMAL;
            return getMap(mode, cmd, user) || getMap(mode, cmd, main);
        },

        getDefault: function (mode, cmd)
        {
            mode = mode || modes.NORMAL;
            return getMap(mode, cmd, main);
        },

        // returns an array of mappings with names which START with "cmd" (but are NOT "cmd")
        getCandidates: function (mode, cmd)
        {
            let mappings = user[mode].concat(main[mode]);
            let matches = [];

            for (let [,map] in Iterator(mappings))
            {
                for (let [,name] in Iterator(map.names))
                {
                    if (name.indexOf(cmd) == 0 && name.length > cmd.length)
                    {
                        // for < only return a candidate if it doesn't look like a <c-x> mapping
                        if (cmd != "<" || !/^<.+>/.test(name))
                            matches.push(map);
                    }
                }
            }

            return matches;
        },

        getMapLeader: function ()
        {
            let leaderRef = liberator.variableReference("mapleader");
            return leaderRef[0] ? leaderRef[0][leaderRef[1]] : "\\";
        },

        // returns whether the user added a custom user map
        hasMap: function (mode, cmd)
        {
            return user[mode].some(function (map) map.hasName(cmd));
        },

        remove: function (mode, cmd)
        {
            removeMap(mode, cmd);
        },

        removeAll: function (mode)
        {
            user[mode] = [];
        },

        list: function (modes, filter)
        {
            let modeSign = "";
            modes.forEach(function (mode)
            {
                if (mode == modes.NORMAL)
                    modeSign += "n";
                if ((mode == modes.INSERT || mode == modes.TEXTAREA) && modeSign.indexOf("i") == -1)
                    modeSign += "i";
                if (mode == modes.COMMAND_LINE)
                    modeSign += "c";
                if (mode == modes.MESSAGRE)
                    modeSign += "m";
            });

            let maps = mappingsIterator(modes, user);
            if (filter)
                maps = [map for (map in maps) if (map.names[0] == filter)];

            let list =

                    {
                        template.map(maps, function (map)
                            template.map(map.names, function (name)

                                {modeSign} {name}
                                {map.noremap ? "*" : " "}
                                {map.rhs || "function () { ... }"}

))
                    }

;

            // TODO: Move this to an ItemList to show this automatically
            if (list.*.length() == list.text().length())
            {
                liberator.echomsg("No mapping found");
                return;
            }
            commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
        }

    };
    //}}}
}; //}}}

// vim: set fdm=marker sw=4 ts=4 et:
<|endoftext|>


<commit_before>// macro-navigator
// simplify driving the browser to registered locations/states
"use strict";

function Navigator (options) {
    if (!options.driver) {
        throw new Error("Driver not found");
    }
    this.driver = options.driver;
}
module.exports = Navigator;
<commit_msg>purge old navigator<commit_after><|endoftext|>


<commit_before>describe('waypoint-once', function () {

	beforeEach(function (done) {

		JSWaypoints.register_selector('#paragraph_20');
		JSWaypoints.register_selector('#paragraph_40');
		window.location.hash = 'paragraph_20';

		setTimeout(function () {
			done();
		}, 1000);

	});

	it('added to element when it becomes visible', function () {
		console.log(document.querySelector('#paragraph_20').className.split(/\s+/));
		expect(document.querySelector('#paragraph_20').className.split(/\s+/)).toContain('waypoint-once');
	});

	it('element below the viewport does not get waypoint-once class', function () {
		expect(document.querySelector('#paragraph_40').className.split(/\s+/)).not.toContain('waypoint-once');
	});

});
<commit_msg>Tests for what happens when scrolling back to the top of the page<commit_after>describe('waypoint-once', function () {

	beforeEach(function (done) {

		JSWaypoints.register_selector('#paragraph_20');
		JSWaypoints.register_selector('#paragraph_40');
		window.location.hash = 'paragraph_20';

		setTimeout(function () {
			done();
		}, 1000);

	});

	it('added to element when it becomes visible', function () {
		console.log(document.querySelector('#paragraph_20').className.split(/\s+/));
		expect(document.querySelector('#paragraph_20').className.split(/\s+/)).toContain('waypoint-once');
	});

	it('element below the viewport does not get waypoint-once class', function () {
		expect(document.querySelector('#paragraph_40').className.split(/\s+/)).not.toContain('waypoint-once');
	});

});

describe('waypoint-visible', function () {

	beforeEach(function (done) {

		JSWaypoints.register_selector('#paragraph_20');
		JSWaypoints.register_selector('#paragraph_40');
		window.location.hash = 'paragraph_20';

		setTimeout(function () {
			done();
		}, 1000);

	});

	it('added to element when it becomes visible', function () {
		console.log(document.querySelector('#paragraph_20').className.split(/\s+/));
		expect(document.querySelector('#paragraph_20').className.split(/\s+/)).toContain('waypoint-visible');
	});

	it('element below the viewport does not get waypoint-visible class', function () {
		expect(document.querySelector('#paragraph_40').className.split(/\s+/)).not.toContain('waypoint-visible');
	});

});

describe('no longer visible', function () {

	beforeEach(function (done) {

		JSWaypoints.register_selector('#paragraph_20');
		JSWaypoints.register_selector('#paragraph_40');
		window.location.hash = 'paragraph_20';

		// Give arrive a chance to run
		setTimeout(function () {

			window.location.hash = 'paragraph_1';

			// Give arrive a chance to run again
			setTimeout(function () {
				done();
			}, 1000);

		}, 1000);

	});

	it('removed from element when no longer visible', function () {
		expect(document.querySelector('#paragraph_20').className.split(/\s+/)).not.toContain('waypoint-visible');
	});

	it('still has waypoint-once', function () {
		expect(document.querySelector('#paragraph_20').className.split(/\s+/)).toContain('waypoint-once');
	});

	it('element below the viewport never had waypoint-visible class', function () {
		expect(document.querySelector('#paragraph_40').className.split(/\s+/)).not.toContain('waypoint-visible');
	});

});<|endoftext|>


<commit_before>var util = require('../lib/test-utils.js');
var expect = require('chai').expect;

describe('fs.utimes', function() {
  beforeEach(util.setup);
  afterEach(util.cleanup);

  it('should be a function', function() {
    var fs = util.fs();
    expect(fs.utimes).to.be.a('function');
  });

  it('should error when atime is negative', function(done) {
    var fs = util.fs();

    fs.writeFile('/testfile', '', function(error) {
      if (error) throw error;

      fs.utimes('/testfile', -1, Date.now(), function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EINVAL');
        done();
      });
    });
  });

  it('should error when mtime is negative', function(done) {
    var fs = util.fs();

    fs.writeFile('/testfile', '', function(error) {
      if (error) throw error;

      fs.utimes('/testfile', Date.now(), -1, function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EINVAL');
        done();
      });
    });
  });

  it('should error when atime is as invalid number', function(done) {
    var fs = util.fs();

    fs.writeFile('/testfile', '', function (error) {
      if (error) throw error;

      fs.utimes('/testfile', 'invalid datetime', Date.now(), function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EINVAL');
        done();
      });
    });
  });

  it('should error when path does not exist', function(done) {
    var fs = util.fs();
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.utimes('/pathdoesnotexist', atime, mtime, function (error) {
      expect(error).to.exist;
      expect(error.code).to.equal('ENOENT');
      done();
    });
  });

  it('should error when mtime is an invalid number', function(done) {
    var fs = util.fs();

    fs.writeFile('/testfile', '', function (error) {
      if (error) throw error;

      fs.utimes('/testfile', Date.now(), 'invalid datetime', function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EINVAL');
        done();
      });
    });
  });

  it('should error when file descriptor is invalid', function(done) {
    var fs = util.fs();
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.futimes(1, atime, mtime, function (error) {
      expect(error).to.exist;
      expect(error.code).to.equal('EBADF');
      done();
    });
  });

  it('should change atime and mtime of a file path', function(done) {
    var fs = util.fs();
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.writeFile('/testfile', '', function (error) {
      if (error) throw error;

      fs.utimes('/testfile', atime, mtime, function (error) {
        expect(error).not.to.exist;

        fs.stat('/testfile', function (error, stat) {
          expect(error).not.to.exist;
          expect(stat.mtime).to.equal(mtime);
          done();
        });
      });
    });
  });

  it ('should change atime and mtime for a valid file descriptor', function(done) {
    var fs = util.fs();
    var ofd;
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.open('/testfile', 'w', function (error, result) {
      if (error) throw error;

      ofd = result;
      fs.futimes(ofd, atime, mtime, function (error) {
        expect(error).not.to.exist;

        fs.fstat(ofd, function (error, stat) {
          expect(error).not.to.exist;
          expect(stat.mtime).to.equal(mtime);
          done();
        });
      });
    });
  });

  it('should update atime and mtime of directory path', function(done) {
    var fs = util.fs();
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.mkdir('/testdir', function (error) {
      if (error) throw error;

      fs.utimes('/testdir', atime, mtime, function (error) {
        expect(error).not.to.exist;

        fs.stat('/testdir', function (error, stat) {
          expect(error).not.to.exist;
          expect(stat.mtime).to.equal(mtime);
          done();
        });
      });
    });
  });

  it('should update atime and mtime using current time if arguments are null', function(done) {
    var fs = util.fs();

    fs.writeFile('/myfile', '', function (error) {
      if (error) throw error;

      var then = Date.now();
      fs.utimes('/myfile', null, null, function (error) {
        expect(error).not.to.exist;

        fs.stat('/myfile', function (error, stat) {
          expect(error).not.to.exist;
          // Note: testing estimation as time may differ by a couple of milliseconds
          // This number should be increased if tests are on slow systems
          var delta = Date.now() - then;
          expect(then - stat.atime).to.be.at.most(delta);
          expect(then - stat.mtime).to.be.at.most(delta);
          done();
        });
      });
    });
  });
});
<commit_msg>Add tests for fs.promises utimes function #527 (#540)<commit_after>var util = require('../lib/test-utils.js');
var expect = require('chai').expect;

describe('fs.utimes', function() {
  beforeEach(util.setup);
  afterEach(util.cleanup);

  it('should be a function', function() {
    var fs = util.fs();
    expect(fs.utimes).to.be.a('function');
  });

  it('should error when atime is negative', function(done) {
    var fs = util.fs();

    fs.writeFile('/testfile', '', function(error) {
      if (error) throw error;

      fs.utimes('/testfile', -1, Date.now(), function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EINVAL');
        done();
      });
    });
  });

  it('should error when mtime is negative', function(done) {
    var fs = util.fs();

    fs.writeFile('/testfile', '', function(error) {
      if (error) throw error;

      fs.utimes('/testfile', Date.now(), -1, function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EINVAL');
        done();
      });
    });
  });

  it('should error when atime is as invalid number', function(done) {
    var fs = util.fs();

    fs.writeFile('/testfile', '', function (error) {
      if (error) throw error;

      fs.utimes('/testfile', 'invalid datetime', Date.now(), function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EINVAL');
        done();
      });
    });
  });

  it('should error when path does not exist', function(done) {
    var fs = util.fs();
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.utimes('/pathdoesnotexist', atime, mtime, function (error) {
      expect(error).to.exist;
      expect(error.code).to.equal('ENOENT');
      done();
    });
  });

  it('should error when mtime is an invalid number', function(done) {
    var fs = util.fs();

    fs.writeFile('/testfile', '', function (error) {
      if (error) throw error;

      fs.utimes('/testfile', Date.now(), 'invalid datetime', function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EINVAL');
        done();
      });
    });
  });

  it('should error when file descriptor is invalid', function(done) {
    var fs = util.fs();
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.futimes(1, atime, mtime, function (error) {
      expect(error).to.exist;
      expect(error.code).to.equal('EBADF');
      done();
    });
  });

  it('should change atime and mtime of a file path', function(done) {
    var fs = util.fs();
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.writeFile('/testfile', '', function (error) {
      if (error) throw error;

      fs.utimes('/testfile', atime, mtime, function (error) {
        expect(error).not.to.exist;

        fs.stat('/testfile', function (error, stat) {
          expect(error).not.to.exist;
          expect(stat.mtime).to.equal(mtime);
          done();
        });
      });
    });
  });

  it ('should change atime and mtime for a valid file descriptor', function(done) {
    var fs = util.fs();
    var ofd;
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.open('/testfile', 'w', function (error, result) {
      if (error) throw error;

      ofd = result;
      fs.futimes(ofd, atime, mtime, function (error) {
        expect(error).not.to.exist;

        fs.fstat(ofd, function (error, stat) {
          expect(error).not.to.exist;
          expect(stat.mtime).to.equal(mtime);
          done();
        });
      });
    });
  });

  it('should update atime and mtime of directory path', function(done) {
    var fs = util.fs();
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    fs.mkdir('/testdir', function (error) {
      if (error) throw error;

      fs.utimes('/testdir', atime, mtime, function (error) {
        expect(error).not.to.exist;

        fs.stat('/testdir', function (error, stat) {
          expect(error).not.to.exist;
          expect(stat.mtime).to.equal(mtime);
          done();
        });
      });
    });
  });

  it('should update atime and mtime using current time if arguments are null', function(done) {
    var fs = util.fs();

    fs.writeFile('/myfile', '', function (error) {
      if (error) throw error;

      var then = Date.now();
      fs.utimes('/myfile', null, null, function (error) {
        expect(error).not.to.exist;

        fs.stat('/myfile', function (error, stat) {
          expect(error).not.to.exist;
          // Note: testing estimation as time may differ by a couple of milliseconds
          // This number should be increased if tests are on slow systems
          var delta = Date.now() - then;
          expect(then - stat.atime).to.be.at.most(delta);
          expect(then - stat.mtime).to.be.at.most(delta);
          done();
        });
      });
    });
  });
});

describe('fs.promises.utimes', function () {
  beforeEach(util.setup);
  afterEach(util.cleanup);

  it('should be a function', function () {
    var fs = util.fs().promises;
    expect(fs.utimes).to.be.a('function');
  });

  it('should return a promise', function() {
    var fs = util.fs().promises;
    expect(fs.utimes()).to.be.a('Promise');
  });

  it('should error when atime is negative', function () {
    var fs = util.fs().promises;
    return fs.writeFile('/testfile', '')
      .then(function () {
        fs.utimes('/testfile', -1, Date.now())
          .catch(function (error) {
            expect(error).to.exist;
            expect(error.code).to.equal('EINVAL');
          });
      })
      .catch(function (error) {
        throw error;
      });
  });

  it('should error when mtime is negative', function () {
    var fs = util.fs().promises;

    return fs.writeFile('/testfile', '')
      .then(function () {
        fs.utimes('/testfile', Date.now(), -1)
          .catch(function (error) {
            expect(error).to.exist;
            expect(error.code).to.equal('EINVAL');
          });
      })
      .catch(function (error) {
        throw error;
      });
  });

  it('should error when mtime is an invalid number', function () {
    var fs = util.fs().promises;

    return fs.writeFile('/testfile', '')
      .then(function () {
        fs.utimes('/testfile', Date.now(), 'invalid datetime')
          .catch(function (error) {
            expect(error).to.exist;
            expect(error.code).to.equal('EINVAL');
          });
      })
      .catch(function (error) {
        throw error;
      });
  });

  it('should error when file descriptor is invalid', function () {
    var fs = util.fs().promises;
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    return fs.futimes(1, atime, mtime)
      .catch(function (error) {
        expect(error).to.exist;
        expect(error.code).to.equal('EBADF');
      });
  });

  it('should change atime and mtime of a file path', function () {
    var fs = util.fs().promises;
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    return fs.writeFile('/testfile', '')
      .then(function () {
        fs.utimes('/testfile', atime, mtime)
          .then(function () {
            fs.stat('/testfile')
              .then(function (stat) {
                expect(stat.mtime).to.equal(mtime);
              })
              .catch(function (error) {
                expect(error).not.to.exist;
              });
          })
          .catch(function (error) {
            expect(error).not.to.exist;
          });
      })
      .catch(function (error) {
        throw error;
      });
  });

  it('should change atime and mtime for a valid file descriptor', function () {
    var fs = util.fs().promises;
    var ofd;
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    return fs.open('/testfile', 'w')
      .then(function (result) {
        ofd = result;
        fs.futimes(ofd, atime, mtime)
          .then(function () {
            fs.fstat(ofd)
              .then(function (stat) {
                expect(stat.mtime).to.equal(mtime);
              })
              .catch(function (error) {
                expect(error).not.to.exist;
              });
          })
          .catch(function (error) {
            expect(error).not.to.exist;
          });
      })
      .catch(function (error) {
        throw error;
      });
  });

  it('should update atime and mtime of directory path', function () {
    var fs = util.fs().promises;
    var atime = Date.parse('1 Oct 2000 15:33:22');
    var mtime = Date.parse('30 Sep 2000 06:43:54');

    return fs.mkdir('/testdir')
      .then(function () {
        fs.utimes('/testdir', atime, mtime)
          .then(function () {
            fs.stat('/testdir')
              .then(function (stat) {
                expect(stat.mtime).to.equal(mtime);
              })
              .catch(function (error) {
                expect(error).not.to.exist;
              });
          })
          .catch(function (error) {
            expect(error).not.to.exist;
          });
      })
      .catch(function (error) {
        throw error;
      });
  });

  it('should update atime and mtime using current time if arguments are null', function () {
    var fs = util.fs().promises;

    return fs.writeFile('/myfile', '')
      .then(function () {
        var then = Date.now();
        fs.utimes('/myfile', null, null)
          .then(function () {
            fs.stat('/myfile')
              .then(function (stat) {
                // Note: testing estimation as time may differ by a couple of milliseconds
                // This number should be increased if tests are on slow systems
                var delta = Date.now() - then;
                expect(then - stat.atime).to.be.at.most(delta);
                expect(then - stat.mtime).to.be.at.most(delta);
              })
              .catch(function (error) {
                expect(error).not.to.exist;
              });
          })
          .catch(function (error) {
            expect(error).not.to.exist;
          });
      })
      .catch(function (error) {
        throw error;
      });
  });
});
<|endoftext|>


<commit_before>import React from "react";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import injectSheet from "react-jss";
import { Grid, Row, Col } from "react-bootstrap/lib";
import { Link } from "react-router-dom";
import { Helmet } from "react-helmet";

import ArticleHeader from "./ArticleHeader";
import ArticleBody from "./ArticleBody";
import RecommendedRow from "./RecommendedRow";
import CommentThread from "../../comments/components/CommentThread";
import NotFoundPage from "../../core/components/NotFoundPage";
import { getArticleFromRequestedSlug, getArticleMedia } from "../selectors";
import { openSubscriptionModal } from "../../accounts/actions";
import { openLightbox } from "../../core/actions";

import SimpleSlider from "./SimpleSlider";

const styles = {
  ArticlePage: {
    marginTop: "80px",
  },
  descriptionRow: {
    marginBottom: "24px",
  },
  description: {
    border: "1px solid #ddd",
    borderStyle: "solid none", // only top-bottom borders
    color: "#000",
    fontFamily: "Minion Pro",
    fontSize: "16px",
    padding: "12px 0 13px",
  },
  subscribe: {
    color: "#3572b7",
    "&:active": {
      color: "#3572b7",
    },
    "&:focus": {
      color: "#3572b7",
    },
    "&:hover": {
      color: "#3572b7",
      cursor: "pointer",
    },
  },
  "@media (max-width: 1199px)": {
    ArticlePage: {
      padding: "0 8%",
    },
  },
  "@media (max-width: 991px)": {
    ArticlePage: {
      padding: 0,
    },
    descriptionRow: {
      padding: "0 10%",
    },
  },
  "@media (max-width: 767px)": {
    descriptionRow: {
      padding: "0 2%",
    },
  },
};

const ArticlePage = ({
  classes,
  article,
  section,
  sections,
  media,
  openSubscriptionModal,
  allMediaTemporarily,
  openLightbox,
}) => {
  return <button style={{ margin: "100px" }} onClick={openLightbox} />;
  return (
    <SimpleSlider media={Object.values(allMediaTemporarily).slice(1, 5)} />
  );
  if (!article) {
    return <NotFoundPage />;
  }
  return (
    <Grid fluid className={classes.ArticlePage}>
      <Helmet titleTemplate="%s | The Stuyvesant Spectator">
        <title>{article.title}</title>
        <meta />
      </Helmet>
      <ArticleHeader article={article} section={section} />
      <ArticleBody content={article.content} media={media} />
      <Row className={classes.descriptionRow}>
        <Col xs={12} sm={12} md={9} lg={9} className={classes.description}>
          The Pulse of the Student Body:

            Subscribe

           to The Stuyvesant Spectator’s biweekly newsletter.
        </Col>
        <Col xsHidden smHidden md={3} lg={3} />
      </Row>
      <RecommendedRow
        section={section.parentId ? sections[section.parentId] : section}
      />
      <CommentThread article={article} />
    </Grid>
  );
};

const mapStateToProps = (state, ownProps) => ({
  article: getArticleFromRequestedSlug(state, ownProps),
  sections: state.sections.sections,
  media: getArticleMedia(state, ownProps),
  allMediaTemporarily: state.media.media,
});

const mapDispatchToProps = dispatch => {
  return bindActionCreators({ openSubscriptionModal, openLightbox }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(
  injectSheet(styles)(ArticlePage),
);
<commit_msg>lightbox children<commit_after>import React from "react";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import injectSheet from "react-jss";
import { Grid, Row, Col } from "react-bootstrap/lib";
import { Link } from "react-router-dom";
import { Helmet } from "react-helmet";

import ArticleHeader from "./ArticleHeader";
import ArticleBody from "./ArticleBody";
import RecommendedRow from "./RecommendedRow";
import CommentThread from "../../comments/components/CommentThread";
import NotFoundPage from "../../core/components/NotFoundPage";
import { getArticleFromRequestedSlug, getArticleMedia } from "../selectors";
import { openSubscriptionModal } from "../../accounts/actions";
import { openLightbox } from "../../core/actions";

import SimpleSlider from "./SimpleSlider";
import { Lightbox } from "../../core/components";

const styles = {
  ArticlePage: {
    marginTop: "80px",
  },
  descriptionRow: {
    marginBottom: "24px",
  },
  description: {
    border: "1px solid #ddd",
    borderStyle: "solid none", // only top-bottom borders
    color: "#000",
    fontFamily: "Minion Pro",
    fontSize: "16px",
    padding: "12px 0 13px",
  },
  subscribe: {
    color: "#3572b7",
    "&:active": {
      color: "#3572b7",
    },
    "&:focus": {
      color: "#3572b7",
    },
    "&:hover": {
      color: "#3572b7",
      cursor: "pointer",
    },
  },
  "@media (max-width: 1199px)": {
    ArticlePage: {
      padding: "0 8%",
    },
  },
  "@media (max-width: 991px)": {
    ArticlePage: {
      padding: 0,
    },
    descriptionRow: {
      padding: "0 10%",
    },
  },
  "@media (max-width: 767px)": {
    descriptionRow: {
      padding: "0 2%",
    },
  },
};

const ArticlePage = ({
  classes,
  article,
  section,
  sections,
  media,
  openSubscriptionModal,
  allMediaTemporarily,
  openLightbox,
}) => {
  return (

      <Lightbox>
        <SimpleSlider media={Object.values(allMediaTemporarily).slice(1, 5)}/>
      </Lightbox>
      <button style={{ margin: "100px" }} onClick={openLightbox}>lightbox</button>;

  )
  if (!article) {
    return <NotFoundPage />;
  }
  return (
    <Grid fluid className={classes.ArticlePage}>
      <Helmet titleTemplate="%s | The Stuyvesant Spectator">
        <title>{article.title}</title>
        <meta />
      </Helmet>
      <ArticleHeader article={article} section={section} />
      <ArticleBody content={article.content} media={media} />
      <Row className={classes.descriptionRow}>
        <Col xs={12} sm={12} md={9} lg={9} className={classes.description}>
          The Pulse of the Student Body:

            Subscribe

           to The Stuyvesant Spectator’s biweekly newsletter.
        </Col>
        <Col xsHidden smHidden md={3} lg={3} />
      </Row>
      <RecommendedRow
        section={section.parentId ? sections[section.parentId] : section}
      />
      <CommentThread article={article} />
    </Grid>
  );
};

const mapStateToProps = (state, ownProps) => ({
  article: getArticleFromRequestedSlug(state, ownProps),
  sections: state.sections.sections,
  media: getArticleMedia(state, ownProps),
  allMediaTemporarily: state.media.media,
});

const mapDispatchToProps = dispatch => {
  return bindActionCreators({ openSubscriptionModal, openLightbox }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(
  injectSheet(styles)(ArticlePage),
);
<|endoftext|>