<commit_before>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * FeatureInfo component
 * Shows feature info.
 * @author Roy Braam
 */
Ext.define ("viewer.components.FeatureInfo",{
    extend: "viewer.components.Maptip",
    progressElement: null,
    /**
     * Overwrite constructor to set some other settings then maptip.
     */
    constructor: function (conf){
        conf.isPopup=true;
        //don't call maptip constructor but that of super maptip.
        viewer.components.Maptip.superclass.constructor.call(this, conf);
        this.initConfig(conf);
        //make the balloon
        this.balloon = new Balloon(this.getDiv(),this.getViewerController().mapComponent,"balloonFeatureInfo",this.width,this.height);
        //set the offset of the map
        var mapTopOffset=this.viewerController.getLayoutHeight('top_menu');
        if (mapTopOffset<0){
            mapTopOffset=0;
        }
        this.balloon.offsetY+=Number(mapTopOffset);
        //show close button and dont close on mouse out.
        this.balloon.closeOnMouseOut=false;
        this.balloon.showCloseButton=true;
        var me = this;
        this.balloon.close = function(){
            me.balloon.setContent("");
            me.balloon.hide();
            me.setMaptipEnabled(true);
        }
        //if topmenu height is in % then recalc on every resize.
        var topMenuLayout=this.viewerController.getLayout('top_menu');
        if (topMenuLayout.heightmeasure && topMenuLayout.heightmeasure =="%"){
            Ext.EventManager.onWindowResize(function(){
                me.onResize();
            }, this);
        }
        this.onResize();
        //listen to the on addlayer
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_LAYER_ADDED,this.onAddLayer,this);
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_LAYER_REMOVED,this.onLayerRemoved,this);
         //Add event when started the identify (clicked on the map)
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO,this.onFeatureInfoStart,this);
        //listen to a extent change
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_CHANGE_EXTENT,
        function(map,options){
            me.onChangeExtent(map,options);
        },this);
        return this;
    },
    /**
     * Event handler for when a layer is added to the map
     * @see event ON_LAYER_ADDED
     */
    onAddLayer: function(map,options){
        var mapLayer=options.layer;
        if (mapLayer==null)
            return;
        if (!this.isLayerConfigured(mapLayer)){
            return;
        }
        if(this.isSummaryLayer(mapLayer)){
            var appLayer=this.viewerController.app.appLayers[mapLayer.appLayerId];
            var layer = this.viewerController.app.services[appLayer.serviceId].layers[appLayer.layerName];
            //Store the current map extent for every maptip request.
            this.viewerController.mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO,function(map,options){
                this.setRequestExtent(map.getExtent());
            },this);
            //do server side getFeature.
            if (layer.hasFeatureType){
                this.addLayerInServerRequest(appLayer);
            }else{
                //TODO: add query layers to the map
                //listen to the onMaptipData
                mapLayer.addListener(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO_DATA,this.onMapData,this);
            }
        }
    },

    onLayerRemoved: function(map,options) {
        var mapLayer = options.layer;
        if (mapLayer==null)
            return;
        if(this.isSummaryLayer(mapLayer)){
            var appLayer=this.viewerController.app.appLayers[mapLayer.appLayerId];
            var layer = this.viewerController.app.services[appLayer.serviceId].layers[appLayer.layerName];
            if (layer.hasFeatureType && this.serverRequestLayers){
                Ext.Array.remove(this.serverRequestLayers, appLayer);
            }
        }

    },

    /**
     * Enable doing server requests.
     * @param appLayer the applayer
     */
    addLayerInServerRequest: function (appLayer){
        //first time register for event and make featureinfo ajax request handler.
        if (!this.serverRequestEnabled){
            this.viewerController.mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO,this.doServerRequest,this);
            this.featureInfo=Ext.create("viewer.FeatureInfo", {viewerController: this.viewerController});
            this.serverRequestEnabled = true;
        }
        if (this.serverRequestLayers ==null){
            this.serverRequestLayers=new Array();
        }
        Ext.Array.include(this.serverRequestLayers, appLayer);
    },
    /**
     * When a feature info starts.
     */
    onFeatureInfoStart: function(){
        this.viewerController.mapComponent.setWaitingCursor(true);
        this.balloon.setContent("");
        this.balloon.hide();
        this.setMaptipEnabled(false);
    },
    /**
     *
     */
    onDataReturned: function(options){
        var found=false;
        var data = options.data;
        for (var layerIndex in data){
            var layer=data[layerIndex];
            for (var index in layer.features){
                found=true;
                break;
            }
            if(found){
                break;
            }
        }
        if (!found){
            this.setMaptipEnabled(true);
        }
        this.callParent(arguments);
        this.viewerController.mapComponent.setWaitingCursor(false);
    },
    /**
     *Called when extent is changed, recalculate the position
     */
    onChangeExtent : function(map,options){
        if (this.worldPosition && options.extent){
            if (options.extent.isIn(this.worldPosition.x,this.worldPosition.y)){
                this.balloon.setPositionWorldCoords(this.worldPosition.x,this.worldPosition.y,false,this.getBrowserZoomRatio());
            }else{
                this.balloon.hide();
            }
        }
    },
    /**
     *
     */
     setMaptipEnabled: function (enable){
        var maptips= this.viewerController.getComponentsByClassName("viewer.components.Maptip");
        for (var i =0; i < maptips.length;i++){
            if (typeof maptips[i].setEnabled == 'function'){
                maptips[i].setEnabled(enable);
            }
        }
     }

});

<commit_msg>Check for requestable layers when turning on the waitingcursor. Fixes #83.<commit_after>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * FeatureInfo component
 * Shows feature info.
 * @author Roy Braam
 */
Ext.define ("viewer.components.FeatureInfo",{
    extend: "viewer.components.Maptip",
    progressElement: null,
    numRequestLayers:0,
    /**
     * Overwrite constructor to set some other settings then maptip.
     */
    constructor: function (conf){
        conf.isPopup=true;
        //don't call maptip constructor but that of super maptip.
        viewer.components.Maptip.superclass.constructor.call(this, conf);
        this.initConfig(conf);
        //make the balloon
        this.balloon = new Balloon(this.getDiv(),this.getViewerController().mapComponent,"balloonFeatureInfo",this.width,this.height);
        //set the offset of the map
        var mapTopOffset=this.viewerController.getLayoutHeight('top_menu');
        if (mapTopOffset<0){
            mapTopOffset=0;
        }
        this.balloon.offsetY+=Number(mapTopOffset);
        //show close button and dont close on mouse out.
        this.balloon.closeOnMouseOut=false;
        this.balloon.showCloseButton=true;
        var me = this;
        this.balloon.close = function(){
            me.balloon.setContent("");
            me.balloon.hide();
            me.setMaptipEnabled(true);
        }
        //if topmenu height is in % then recalc on every resize.
        var topMenuLayout=this.viewerController.getLayout('top_menu');
        if (topMenuLayout.heightmeasure && topMenuLayout.heightmeasure =="%"){
            Ext.EventManager.onWindowResize(function(){
                me.onResize();
            }, this);
        }
        this.onResize();
        //listen to the on addlayer
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_LAYER_ADDED,this.onAddLayer,this);
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_LAYER_REMOVED,this.onLayerRemoved,this);
         //Add event when started the identify (clicked on the map)
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO,this.onFeatureInfoStart,this);
        //listen to a extent change
        this.getViewerController().mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_CHANGE_EXTENT,
        function(map,options){
            me.onChangeExtent(map,options);
        },this);
        return this;
    },
    /**
     * Event handler for when a layer is added to the map
     * @see event ON_LAYER_ADDED
     */
    onAddLayer: function(map,options){
        var mapLayer=options.layer;
        if (mapLayer==null)
            return;
        if (!this.isLayerConfigured(mapLayer)){
            return;
        }
        if(this.isSummaryLayer(mapLayer)){
            var appLayer=this.viewerController.app.appLayers[mapLayer.appLayerId];
            var layer = this.viewerController.app.services[appLayer.serviceId].layers[appLayer.layerName];
            //Store the current map extent for every maptip request.
            this.viewerController.mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO,function(map,options){
                this.setRequestExtent(map.getExtent());
            },this);
            //do server side getFeature.
            if (layer.hasFeatureType){
                this.addLayerInServerRequest(appLayer);
            }else{
                //TODO: add query layers to the map
                //listen to the onMaptipData
                mapLayer.addListener(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO_DATA,this.onMapData,this);
            }
            this.numRequestLayers++;
        }
    },

    onLayerRemoved: function(map,options) {
        var mapLayer = options.layer;
        if (mapLayer==null)
            return;
        if(this.isSummaryLayer(mapLayer)){
            var appLayer=this.viewerController.app.appLayers[mapLayer.appLayerId];
            var layer = this.viewerController.app.services[appLayer.serviceId].layers[appLayer.layerName];
            if (layer.hasFeatureType && this.serverRequestLayers){
                Ext.Array.remove(this.serverRequestLayers, appLayer);
            }
            this.numRequestLayers--;
        }

    },

    /**
     * Enable doing server requests.
     * @param appLayer the applayer
     */
    addLayerInServerRequest: function (appLayer){
        //first time register for event and make featureinfo ajax request handler.
        if (!this.serverRequestEnabled){
            this.viewerController.mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_GET_FEATURE_INFO,this.doServerRequest,this);
            this.featureInfo=Ext.create("viewer.FeatureInfo", {viewerController: this.viewerController});
            this.serverRequestEnabled = true;
        }
        if (this.serverRequestLayers ==null){
            this.serverRequestLayers=new Array();
        }
        Ext.Array.include(this.serverRequestLayers, appLayer);
    },
    /**
     * When a feature info starts.
     */
    onFeatureInfoStart: function(){
        if(this.numRequestLayers > 0){
            this.viewerController.mapComponent.setWaitingCursor(true);
            this.balloon.setContent("");
            this.balloon.hide();
            this.setMaptipEnabled(false);
        }
    },
    /**
     *
     */
    onDataReturned: function(options){
        var found=false;
        var data = options.data;
        for (var layerIndex in data){
            var layer=data[layerIndex];
            for (var index in layer.features){
                found=true;
                break;
            }
            if(found){
                break;
            }
        }
        if (!found){
            this.setMaptipEnabled(true);
        }
        this.callParent(arguments);
        this.viewerController.mapComponent.setWaitingCursor(false);
    },
    /**
     *Called when extent is changed, recalculate the position
     */
    onChangeExtent : function(map,options){
        if (this.worldPosition && options.extent){
            if (options.extent.isIn(this.worldPosition.x,this.worldPosition.y)){
                this.balloon.setPositionWorldCoords(this.worldPosition.x,this.worldPosition.y,false,this.getBrowserZoomRatio());
            }else{
                this.balloon.hide();
            }
        }
    },
    /**
     *
     */
     setMaptipEnabled: function (enable){
        var maptips= this.viewerController.getComponentsByClassName("viewer.components.Maptip");
        for (var i =0; i < maptips.length;i++){
            if (typeof maptips[i].setEnabled == 'function'){
                maptips[i].setEnabled(enable);
            }
        }
     }

});

<|endoftext|>


<commit_before>/*!
 *  mindmaps - a HTML5 powered mind mapping application
 *  Copyright (C) 2011  David Richard
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Make sure this is the first file to be referenced in index.hml.
 */

// Use ECMA5 strict mode. see:
// http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
"use strict";

/**
 * @namespace Application wide namespace for mindmaps.
 */
var mindmaps = mindmaps || {};

/**
 * Start up. This function is executed when the DOM is loaded.
 */
$(function() {
  // take car of old browsers
  createECMA5Shims();
  createHTML5Shims();

  setupConsole();
  trackErrors();

  if (!mindmaps.DEBUG) {
    addUnloadHook();
  }

  // create a new app controller and go
  var appController = new mindmaps.ApplicationController();
  appController.go();
});

/**
 * Adds a confirmation dialog when the user navigates away from the app.
 */
function addUnloadHook () {
  window.onbeforeunload = function (e) {
    var msg = "Are you sure? Any unsaved progress will be lost."
      e = e || window.event;

    // For IE and Firefox prior to version 4
    if (e) {
      e.returnValue = msg;
    }

    // For Safari
    return msg;
  };
}

function trackErrors() {
  window.onerror = function(msg, url, line) {
    if (!window._gaq) {
      return;
    }

    // Track JS errors in GA.
    _gaq.push([ '_trackEvent', 'Error Log', msg, url + '_' + line ]);

    return false; // false prevents default error handling.
  };
}

// TODO make non global
/**
 * Initialize the console object.
 */
function setupConsole() {
  var noOp = function() {
  };

  // provide console object and dummy functions if not built-in
  var console = window.console || {};
  console.log = console.log || noOp;
  console.info = console.info || noOp;
  console.debug = console.debug || noOp;
  console.warn = console.warn || noOp;
  console.error = console.error || noOp;

  // turn all console.xx calls into no-ops when in production mode except
  // for errors, do an alert.
  if (!mindmaps.DEBUG) {
    console.debug = noOp;
    console.info = noOp;
    console.log = noOp;
    console.warn = noOp;
    console.error = function(s) {
      window.alert("Error: " + s);
    };
  }
}

/**
 * Creates ECMA5 shims if the browser does not implement them.
 */
function createECMA5Shims() {
  // from: https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js

  // ES-5 15.3.4.5
  // http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf
  if (!Function.prototype.bind) {
    var slice = Array.prototype.slice;
    Function.prototype.bind = function bind(that) { // .length is 1
      var target = this;
      if (typeof target.apply !== "function"
          || typeof target.call !== "function")
        return new TypeError();
      var args = slice.call(arguments);

      function bound() {

        if (this instanceof bound) {

          var self = Object.create(target.prototype);
          target.apply(self, args.concat(slice.call(arguments)));
          return self;
        } else {
          return target.call.apply(target, args.concat(slice
              .call(arguments)));
        }

      }
      bound.length = (typeof target === "function" ? Math.max(
          target.length - args.length, 0) : 0);
      return bound;
    };
  }

  // ES5 15.4.3.2
  if (!Array.isArray) {
    Array.isArray = function isArray(obj) {
      return Object.prototype.toString.call(obj) === "[object Array]";
    };
  }

  // ES5 15.4.4.18
  if (!Array.prototype.forEach) {
    Array.prototype.forEach = function forEach(block, thisObject) {
      var len = +this.length;
      for ( var i = 0; i < len; i++) {
        if (i in this) {
          block.call(thisObject, this[i], i, this);
        }
      }
    };
  }

  // ES5 15.4.4.19
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
  if (!Array.prototype.map) {
    Array.prototype.map = function map(fun /* , thisp */) {
      var len = +this.length;
      if (typeof fun !== "function")
        throw new TypeError();

      var res = new Array(len);
      var thisp = arguments[1];
      for ( var i = 0; i < len; i++) {
        if (i in this)
          res[i] = fun.call(thisp, this[i], i, this);
      }

      return res;
    };
  }

  // ES5 15.4.4.20
  if (!Array.prototype.filter) {
    Array.prototype.filter = function filter(block /* , thisp */) {
      var values = [];
      var thisp = arguments[1];
      for ( var i = 0; i < this.length; i++)
        if (block.call(thisp, this[i]))
          values.push(this[i]);
      return values;
    };
  }

  // ES5 15.4.4.16
  if (!Array.prototype.every) {
    Array.prototype.every = function every(block /* , thisp */) {
      var thisp = arguments[1];
      for ( var i = 0; i < this.length; i++)
        if (!block.call(thisp, this[i]))
          return false;
      return true;
    };
  }

  // ES5 15.4.4.17
  if (!Array.prototype.some) {
    Array.prototype.some = function some(block /* , thisp */) {
      var thisp = arguments[1];
      for ( var i = 0; i < this.length; i++)
        if (block.call(thisp, this[i]))
          return true;
      return false;
    };
  }

  // ES5 15.4.4.21
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
  if (!Array.prototype.reduce) {
    Array.prototype.reduce = function reduce(fun /* , initial */) {
      var len = +this.length;
      if (typeof fun !== "function")
        throw new TypeError();

      // no value to return if no initial value and an empty array
      if (len === 0 && arguments.length === 1)
        throw new TypeError();

      var i = 0;
      if (arguments.length >= 2) {
        var rv = arguments[1];
      } else {
        do {
          if (i in this) {
            rv = this[i++];
            break;
          }

          // if array contains no values, no initial value to return
          if (++i >= len)
            throw new TypeError();
        } while (true);
      }

      for (; i < len; i++) {
        if (i in this)
          rv = fun.call(null, rv, this[i], i, this);
      }

      return rv;
    };
  }

  // ES5 15.4.4.22
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
  if (!Array.prototype.reduceRight) {
    Array.prototype.reduceRight = function reduceRight(fun /* , initial */) {
      var len = +this.length;
      if (typeof fun !== "function")
        throw new TypeError();

      // no value to return if no initial value, empty array
      if (len === 0 && arguments.length === 1)
        throw new TypeError();

      var rv, i = len - 1;
      if (arguments.length >= 2) {
        rv = arguments[1];
      } else {
        do {
          if (i in this) {
            rv = this[i--];
            break;
          }

          // if array contains no values, no initial value to return
          if (--i < 0)
            throw new TypeError();
        } while (true);
      }

      for (; i >= 0; i--) {
        if (i in this)
          rv = fun.call(null, rv, this[i], i, this);
      }

      return rv;
    };
  }

  // ES5 15.4.4.14
  if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function indexOf(value /* , fromIndex */) {
      var length = this.length;
      if (!length)
        return -1;
      var i = arguments[1] || 0;
      if (i >= length)
        return -1;
      if (i < 0)
        i += length;
      for (; i < length; i++) {
        if (!(i in this))
          continue;
        if (value === this[i])
          return i;
      }
      return -1;
    };
  }

  // ES5 15.4.4.15
  if (!Array.prototype.lastIndexOf) {
    Array.prototype.lastIndexOf = function lastIndexOf(value) {
      var length = this.length;
      if (!length)
        return -1;
      var i = arguments[1] || length;
      if (i < 0)
        i += length;
      i = Math.min(i, length - 1);
      for (; i >= 0; i--) {
        if (!(i in this))
          continue;
        if (value === this[i])
          return i;
      }
      return -1;
    };
  }

  // ES5 15.9.4.4
  if (!Date.now) {
    Date.now = function now() {
      return new Date().getTime();
    };
  }
}

/**
 * Create shims for HTML5 functionality if not supported by browser.
 */
function createHTML5Shims() {
  // localstorage dummy (does nothing)
  if (typeof window.localStorage == 'undefined') {
    window.localStorage = {
      getItem : function() {
        return null;
      },
      setItem : function() {
      },
      clear : function() {
      },
      removeItem : function() {
      },
      length : 0,
      key : function() {
        return null;
      }
    };
  }
}
<commit_msg>Remove Event layerX, layerY deprecated warnings in webkit browsers<commit_after>/*!
 *  mindmaps - a HTML5 powered mind mapping application
 *  Copyright (C) 2011  David Richard
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Make sure this is the first file to be referenced in index.hml.
 */

// Use ECMA5 strict mode. see:
// http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
"use strict";

/**
 * @namespace Application wide namespace for mindmaps.
 */
var mindmaps = mindmaps || {};

/**
 * Start up. This function is executed when the DOM is loaded.
 */
$(function() {
  removeEventLayerXY();

  // take car of old browsers
  createECMA5Shims();
  createHTML5Shims();

  setupConsole();
  trackErrors();

  if (!mindmaps.DEBUG) {
    addUnloadHook();
  }

  // create a new app controller and go
  var appController = new mindmaps.ApplicationController();
  appController.go();
});

/**
 * Remove layerX and layerY from the jQuery event object, it causes heaps of deprecated
 * warnings in WebKit browsers.
 * See: http://stackoverflow.com/questions/7825448/webkit-issues-with-event-layerx-and-event-layery
 *
 * Can be removed when upgrading to jQuery 1.7+.
 */
function removeEventLayerXY() {
  // remove layerX and layerY
  var all = $.event.props,
  len = all.length,
  res = [];

  while (len--) {
    var el = all[len];
    if (el != 'layerX' && el != 'layerY') res.push(el);
  }
  $.event.props = res;
}

/**
* Adds a confirmation dialog when the user navigates away from the app.
*/
function addUnloadHook () {
  window.onbeforeunload = function (e) {
    var msg = "Are you sure? Any unsaved progress will be lost."
    e = e || window.event;

    // For IE and Firefox prior to version 4
    if (e) {
      e.returnValue = msg;
    }

    // For Safari
    return msg;
  };
}

function trackErrors() {
  window.onerror = function(msg, url, line) {
    if (!window._gaq) {
      return;
    }

    // Track JS errors in GA.
    _gaq.push([ '_trackEvent', 'Error Log', msg, url + '_' + line ]);

    return false; // false prevents default error handling.
  };
}

// TODO make non global
/**
* Initialize the console object.
*/
function setupConsole() {
  var noOp = function() {
  };

  // provide console object and dummy functions if not built-in
  var console = window.console || {};
  console.log = console.log || noOp;
  console.info = console.info || noOp;
  console.debug = console.debug || noOp;
  console.warn = console.warn || noOp;
  console.error = console.error || noOp;

  // turn all console.xx calls into no-ops when in production mode except
  // for errors, do an alert.
  if (!mindmaps.DEBUG) {
    console.debug = noOp;
    console.info = noOp;
    console.log = noOp;
    console.warn = noOp;
    console.error = function(s) {
      window.alert("Error: " + s);
    };
  }
}

/**
* Creates ECMA5 shims if the browser does not implement them.
*/
function createECMA5Shims() {
  // from: https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js

  // ES-5 15.3.4.5
  // http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf
  if (!Function.prototype.bind) {
    var slice = Array.prototype.slice;
    Function.prototype.bind = function bind(that) { // .length is 1
      var target = this;
      if (typeof target.apply !== "function"
      || typeof target.call !== "function")
      return new TypeError();
      var args = slice.call(arguments);

      function bound() {

        if (this instanceof bound) {

          var self = Object.create(target.prototype);
          target.apply(self, args.concat(slice.call(arguments)));
          return self;
        } else {
          return target.call.apply(target, args.concat(slice
            .call(arguments)));
        }

      }
      bound.length = (typeof target === "function" ? Math.max(
      target.length - args.length, 0) : 0);
      return bound;
    };
  }

  // ES5 15.4.3.2
  if (!Array.isArray) {
    Array.isArray = function isArray(obj) {
      return Object.prototype.toString.call(obj) === "[object Array]";
    };
  }

  // ES5 15.4.4.18
  if (!Array.prototype.forEach) {
    Array.prototype.forEach = function forEach(block, thisObject) {
      var len = +this.length;
      for ( var i = 0; i < len; i++) {
        if (i in this) {
          block.call(thisObject, this[i], i, this);
        }
      }
    };
  }

  // ES5 15.4.4.19
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
  if (!Array.prototype.map) {
    Array.prototype.map = function map(fun /* , thisp */) {
      var len = +this.length;
      if (typeof fun !== "function")
        throw new TypeError();

      var res = new Array(len);
      var thisp = arguments[1];
      for ( var i = 0; i < len; i++) {
        if (i in this)
          res[i] = fun.call(thisp, this[i], i, this);
      }

      return res;
    };
  }

  // ES5 15.4.4.20
  if (!Array.prototype.filter) {
    Array.prototype.filter = function filter(block /* , thisp */) {
      var values = [];
      var thisp = arguments[1];
      for ( var i = 0; i < this.length; i++)
        if (block.call(thisp, this[i]))
          values.push(this[i]);
        return values;
    };
  }

  // ES5 15.4.4.16
  if (!Array.prototype.every) {
    Array.prototype.every = function every(block /* , thisp */) {
      var thisp = arguments[1];
      for ( var i = 0; i < this.length; i++)
        if (!block.call(thisp, this[i]))
          return false;
        return true;
    };
  }

  // ES5 15.4.4.17
  if (!Array.prototype.some) {
    Array.prototype.some = function some(block /* , thisp */) {
      var thisp = arguments[1];
      for ( var i = 0; i < this.length; i++)
        if (block.call(thisp, this[i]))
          return true;
        return false;
    };
  }

  // ES5 15.4.4.21
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
  if (!Array.prototype.reduce) {
    Array.prototype.reduce = function reduce(fun /* , initial */) {
      var len = +this.length;
      if (typeof fun !== "function")
        throw new TypeError();

      // no value to return if no initial value and an empty array
      if (len === 0 && arguments.length === 1)
        throw new TypeError();

      var i = 0;
      if (arguments.length >= 2) {
        var rv = arguments[1];
      } else {
        do {
          if (i in this) {
            rv = this[i++];
            break;
          }

          // if array contains no values, no initial value to return
          if (++i >= len)
            throw new TypeError();
        } while (true);
      }

      for (; i < len; i++) {
        if (i in this)
          rv = fun.call(null, rv, this[i], i, this);
      }

      return rv;
    };
  }

  // ES5 15.4.4.22
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
  if (!Array.prototype.reduceRight) {
    Array.prototype.reduceRight = function reduceRight(fun /* , initial */) {
      var len = +this.length;
      if (typeof fun !== "function")
        throw new TypeError();

      // no value to return if no initial value, empty array
      if (len === 0 && arguments.length === 1)
        throw new TypeError();

      var rv, i = len - 1;
      if (arguments.length >= 2) {
        rv = arguments[1];
      } else {
        do {
          if (i in this) {
            rv = this[i--];
            break;
          }

          // if array contains no values, no initial value to return
          if (--i < 0)
            throw new TypeError();
        } while (true);
      }

      for (; i >= 0; i--) {
        if (i in this)
          rv = fun.call(null, rv, this[i], i, this);
      }

      return rv;
    };
  }

  // ES5 15.4.4.14
  if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function indexOf(value /* , fromIndex */) {
      var length = this.length;
      if (!length)
        return -1;
      var i = arguments[1] || 0;
      if (i >= length)
        return -1;
      if (i < 0)
        i += length;
      for (; i < length; i++) {
        if (!(i in this))
          continue;
        if (value === this[i])
          return i;
      }
      return -1;
    };
  }

  // ES5 15.4.4.15
  if (!Array.prototype.lastIndexOf) {
    Array.prototype.lastIndexOf = function lastIndexOf(value) {
      var length = this.length;
      if (!length)
        return -1;
      var i = arguments[1] || length;
      if (i < 0)
        i += length;
      i = Math.min(i, length - 1);
      for (; i >= 0; i--) {
        if (!(i in this))
          continue;
        if (value === this[i])
          return i;
      }
      return -1;
    };
  }

  // ES5 15.9.4.4
  if (!Date.now) {
    Date.now = function now() {
      return new Date().getTime();
    };
  }
}

/**
* Create shims for HTML5 functionality if not supported by browser.
*/
function createHTML5Shims() {
  // localstorage dummy (does nothing)
  if (typeof window.localStorage == 'undefined') {
    window.localStorage = {
      getItem : function() {
        return null;
      },
      setItem : function() {
      },
      clear : function() {
      },
      removeItem : function() {
      },
      length : 0,
      key : function() {
        return null;
      }
    };
  }
}
<|endoftext|>


<commit_before>define([
  'summernote/core/list'
], function (list) {
  /**
   * @class core.key
   *
   * Object for keycodes.
   *
   * @singleton
   * @alternateClassName key
   */
  var key = {
    /**
     * @method isEdit
     *
     * @param {Number} keyCode
     * @return {Boolean}
     */
    isEdit: function (keyCode) {
      return list.contains([8, 9, 13, 32], keyCode);
    },
    /**
     * @property {Object} nameFromCode
     * @property {String} nameFromCode.8
     * @property {String} nameFromCode.9
     * @property {String} nameFromCode.13
     * @property {String} nameFromCode.32
     * @property {String} nameFromCode.48
     * @property {String} nameFromCode.49
     */
    nameFromCode: {
      '8': 'BACKSPACE',
      '9': 'TAB',
      '13': 'ENTER',
      '32': 'SPACE',

      // Number: 0-9
      '48': 'NUM0',
      '49': 'NUM1',
      '50': 'NUM2',
      '51': 'NUM3',
      '52': 'NUM4',
      '53': 'NUM5',
      '54': 'NUM6',
      '55': 'NUM7',
      '56': 'NUM8',

      // Alphabet: a-z
      '66': 'B',
      '69': 'E',
      '73': 'I',
      '74': 'J',
      '75': 'K',
      '76': 'L',
      '82': 'R',
      '83': 'S',
      '85': 'U',
      '89': 'Y',
      '90': 'Z',

      '191': 'SLASH',
      '219': 'LEFTBRACKET',
      '220': 'BACKSLASH',
      '221': 'RIGHTBRACKET'
    }
  };

  return key;
});
<commit_msg>add jsduck<commit_after>define([
  'summernote/core/list'
], function (list) {
  /**
   * @class core.key
   *
   * Object for keycodes.
   *
   * @singleton
   * @alternateClassName key
   */
  var key = {
    /**
     * @method isEdit
     *
     * @param {Number} keyCode
     * @return {Boolean}
     */
    isEdit: function (keyCode) {
      return list.contains([8, 9, 13, 32], keyCode);
    },
    nameFromCode: {
      /** @property nameFromCode.8 */
      '8': 'BACKSPACE',
      '9': 'TAB',
      '13': 'ENTER',
      '32': 'SPACE',

      // Number: 0-9
      '48': 'NUM0',
      '49': 'NUM1',
      '50': 'NUM2',
      '51': 'NUM3',
      '52': 'NUM4',
      '53': 'NUM5',
      '54': 'NUM6',
      '55': 'NUM7',
      '56': 'NUM8',

      // Alphabet: a-z
      '66': 'B',
      '69': 'E',
      '73': 'I',
      '74': 'J',
      '75': 'K',
      '76': 'L',
      '82': 'R',
      '83': 'S',
      '85': 'U',
      '89': 'Y',
      '90': 'Z',

      '191': 'SLASH',
      '219': 'LEFTBRACKET',
      '220': 'BACKSLASH',
      '221': 'RIGHTBRACKET'
    }
  };

  return key;
});
<|endoftext|>


<commit_before>(function ($) {
	if ($.version !== '@@version') return;

	/**
	 * @callback beforeStartCallback
	 * @param {Deferred} deferred - The current deferred object.
	 */
	/**
	 * A factory function that returns a chainable utility object with methods to register multiple callbacks into callback queues, invoke callback queues,
	 * and relay the success or failure state of any synchronous or asynchronous function.
	 * @param {beforeStartCallback} beforeStart - A function that is called just before the constructor returns.
	 * @returns {Deferred}
	 */
	$.Deferred = function(beforeStart){
		var deferred = new Deferred();
		if ($.is.fn(beforeStart)){
			try {
				beforeStart(deferred);
			} catch (err) {
				deferred.reject(err);
			}
		}
		return deferred;
	};

	/**
	 * A chainable utility object with methods to register multiple callbacks into callback queues, invoke callback queues,
	 * and relay the success or failure state of any synchronous or asynchronous function.
	 * @returns {Deferred}
	 * @constructor
	 */
	function Deferred(){
		if (!(this instanceof Deferred)) return new Deferred();
		this._callbacks = [];
		this._state = 'pending';
	}

	/**
	 * Used internally by the object to set it's state and execute callbacks.
	 * @param {string} type - The type to apply, can be one of the following; "resolve", "reject" or "progress"
	 * @param {Array} args - The arguments to execute any callbacks with.
	 * @private
	 */
	Deferred.prototype.__apply__ = function(type, args){
		var self = this, finalize = type === 'resolve' || type === 'reject';
		if (finalize){
			if (type === 'reject'){
				this._state = 'rejected';
				this.then = function (resolve, reject) { reject.apply(self, args); };
			}
			if (type === 'resolve'){
				this._state = 'resolved';
				this.then = function (resolve) { resolve.apply(self, args); };
			}
			this.resolve = this.reject = this.notify = function () { throw new Error("Promise already completed"); };
		}
		function execute(reg, type, args){
			var callbacks = $.is.fn(reg[type]) ? [reg[type]] : ($.is.array(reg[type]) ? reg[type] : []);
			$.each(callbacks, function(i, callback){
				if ($.is.fn(callback)) callback.apply(self, args);
			});
		}
		function safe_execute(reg, type, args){
			try { execute(reg, type, args); }
			catch (err) { execute(reg, 'reject', [err]); }
		}
		$.each(this._callbacks, function(i, reg){
			safe_execute(reg, type, args);
		});
		if (finalize){
			$.each(this._callbacks, function(i, reg){
				safe_execute(reg, 'always', args);
			});
			this._callbacks = [];
		}
	};

	/**
	 * Determine the current state of a Deferred object, can be one of the following; "pending", "resolved" or "rejected"
	 * @returns {string}
	 */
	Deferred.prototype.state = function(){
		return this._state;
	};

	/**
	 * Resolve a Deferred object and call any doneCallbacks with the given args.
	 * @param {...*} args - Any number of arguments to supply to the doneCallbacks.
	 */
	Deferred.prototype.resolve = function(args){
		this.__apply__('resolve', Array.prototype.slice.call(arguments));
	};

	/**
	 * Reject a Deferred object and call any failCallbacks with the given args.
	 * @param {...*} args - Any number of arguments to supply to the failCallbacks.
	 */
	Deferred.prototype.reject = function(args){
		this.__apply__('reject', Array.prototype.slice.call(arguments));
	};

	/**
	 * Call the progressCallbacks on a Deferred object with the given args.
	 * @param {...*} args - Any number of arguments to supply to the progressCallbacks.
	 */
	Deferred.prototype.notify = function(args){
		this.__apply__('progress', Array.prototype.slice.call(arguments));
	};

	/**
	 * @callback alwaysCallback
	 * @param {...*} [args] - Any number of arguments to supply to the alwaysCallbacks.
	 */
	/**
	 * @callback doneCallback
	 * @param {...*} [args] - Any number of arguments to supply to the doneCallbacks.
	 */
	/**
	 * @callback failCallback
	 * @param {...*} [args] - Any number of arguments to supply to the failCallbacks.
	 */
	/**
	 * @callback progressCallback
	 * @param {...*} [args] - Any number of arguments to supply to the progressCallbacks.
	 */
	/**
	 * Add handlers to be called when the Deferred object is resolved, rejected, or still in progress.
	 * @param {(doneCallback|Array.<doneCallback>)} doneCallbacks - A function, or array of functions, called when the Deferred is resolved.
	 * @param {(failCallback|Array.<failCallback>)} failCallbacks - A function, or array of functions, called when the Deferred is rejected.
	 * @param {(progressCallback|Array.<progressCallback>)} progressCallbacks - A function, or array of functions, called when the Deferred notifies progress.
	 * @returns {Deferred}
	 */
	Deferred.prototype.then = function(doneCallbacks, failCallbacks, progressCallbacks){
		this._callbacks.push({resolve: doneCallbacks, reject: failCallbacks, progress: progressCallbacks});
		return this;
	};

	/**
	 * Add handlers to be called when the Deferred object is either resolved or rejected.
	 * @param {(alwaysCallback|Array.<alwaysCallback>)} alwaysCallbacks - A function, or array of functions, that is called when the Deferred is resolved or rejected.
	 * @returns {Deferred}
	 */
	Deferred.prototype.always = function(alwaysCallbacks){
		this._callbacks.push({always: alwaysCallbacks});
		return this;
	};

	/**
	 * Add handlers to be called when the Deferred object is resolved.
	 * @param {(doneCallback|Array.<doneCallback>)} doneCallbacks - A function, or array of functions, called when the Deferred is resolved.
	 * @returns {Deferred}
	 */
	Deferred.prototype.done = function(doneCallbacks){
		this._callbacks.push({resolve: doneCallbacks});
		return this;
	};

	/**
	 * Add handlers to be called when the Deferred object is rejected.
	 * @param {(failCallback|Array.<failCallback>)} failCallbacks - A function, or array of functions, called when the Deferred is rejected.
	 * @returns {Deferred}
	 */
	Deferred.prototype.fail = function(failCallbacks){
		this._callbacks.push({reject: failCallbacks});
		return this;
	};

	/**
	 * Add handlers to be called when the Deferred object generates progress notifications.
	 * @param {(progressCallback|Array.<progressCallback>)} progressCallbacks - A function, or array of functions, to be called when the Deferred generates progress notifications.
	 * @returns {Deferred}
	 */
	Deferred.prototype.progress = function(progressCallbacks){
		this._callbacks.push({progress: progressCallbacks});
		return this;
	};

	/**
	 * Provides a way to execute callback functions based on one or more Deferred objects that represent asynchronous events.
	 * @param {...Deferred} deferreds - One or more Deferred objects.
	 * @returns {Deferred|FooJitsu.Deferred}
	 */
	$.when = function(deferreds){
		var args = Array.prototype.slice.call(arguments);
		return $.Deferred(function(d){
			var expected = args.length, results = {length: 0};
			$.each(args, function(i, deferred){
				deferred.then(function(result){
					results.length++;
					results[i] = result;
					if (results.length === expected) d.resolve($.makeArray(results));
				}, function(err){
					d.reject(err);
				});
			});
		});
	};

})(FooJitsu);<commit_msg>Refactored $.Deferred to be a constructor rather than a factory. Removed error thrown when resolve/reject is called multiple times.<commit_after>(function ($) {
	if ($.version !== '@@version') return;

	/**
	 * @callback beforeStartCallback
	 * @param {FooJitsu.Deferred} deferred - The current deferred object.
	 */
	/**
	 * A chainable utility object with methods to register multiple callbacks into callback queues, invoke callback queues,
	 * and relay the success or failure state of any synchronous or asynchronous function.
	 * @param {beforeStartCallback} beforeStart - A function that is called just before the constructor returns.
	 * @returns {FooJitsu.Deferred}
	 * @constructor
	 */
	$.Deferred = function(beforeStart){
		if (!(this instanceof $.Deferred)) return new $.Deferred(beforeStart);
		this.__callbacks__ = [];
		this.currentState = 'pending';
		if ($.is.fn(beforeStart)){
			try {
				beforeStart(this);
			} catch (err) {
				this.reject(err);
			}
		}
	};

	/**
	 * Used internally by the object to set it's state and execute callbacks.
	 * @param {string} type - The type to apply, can be one of the following; "resolve", "reject" or "progress"
	 * @param {Array} args - The arguments to execute any callbacks with.
	 * @private
	 */
	$.Deferred.prototype.__apply__ = function(type, args){
		var self = this, finalize = type === 'resolve' || type === 'reject';
		if (finalize){
			if (type === 'reject'){
				this.currentState = 'rejected';
				this.then = function (resolve, reject) { reject.apply(self, args); };
			}
			if (type === 'resolve'){
				this.currentState = 'resolved';
				this.then = function (resolve) { resolve.apply(self, args); };
			}
		}
		function execute(reg, type, args){
			var callbacks = $.is.fn(reg[type]) ? [reg[type]] : ($.is.array(reg[type]) ? reg[type] : []);
			$.each(callbacks, function(i, callback){
				if ($.is.fn(callback)) callback.apply(self, args);
			});
		}
		function safe_execute(reg, type, args){
			try { execute(reg, type, args); }
			catch (err) { execute(reg, 'reject', [err]); }
		}
		$.each(this.__callbacks__, function(i, reg){
			safe_execute(reg, type, args);
		});
		if (finalize){
			$.each(this.__callbacks__, function(i, reg){
				safe_execute(reg, 'always', args);
			});
			this.__callbacks__ = [];
			this.resolve = this.reject = this.notify = $.noop;
		}
	};

	/**
	 * Determine the current state of a deferred object, can be one of the following; "pending", "resolved" or "rejected"
	 * @returns {string}
	 */
	$.Deferred.prototype.state = function(){
		return this.currentState;
	};

	/**
	 * Resolve a deferred object and call any doneCallbacks with the given args.
	 * @param {...*} args - Any number of arguments to supply to the doneCallbacks.
	 */
	$.Deferred.prototype.resolve = function(args){
		this.__apply__('resolve', Array.prototype.slice.call(arguments));
	};

	/**
	 * Reject a deferred object and call any failCallbacks with the given args.
	 * @param {...*} args - Any number of arguments to supply to the failCallbacks.
	 */
	$.Deferred.prototype.reject = function(args){
		this.__apply__('reject', Array.prototype.slice.call(arguments));
	};

	/**
	 * Call the progressCallbacks on a deferred object with the given args.
	 * @param {...*} args - Any number of arguments to supply to the progressCallbacks.
	 */
	$.Deferred.prototype.notify = function(args){
		this.__apply__('progress', Array.prototype.slice.call(arguments));
	};

	/**
	 * @callback alwaysCallback
	 * @param {...*} [args] - Any number of arguments to supply to the alwaysCallbacks.
	 */
	/**
	 * @callback doneCallback
	 * @param {...*} [args] - Any number of arguments to supply to the doneCallbacks.
	 */
	/**
	 * @callback failCallback
	 * @param {...*} [args] - Any number of arguments to supply to the failCallbacks.
	 */
	/**
	 * @callback progressCallback
	 * @param {...*} [args] - Any number of arguments to supply to the progressCallbacks.
	 */
	/**
	 * Add handlers to be called when the deferred object is resolved, rejected, or still in progress.
	 * @param {(doneCallback|Array.<doneCallback>)} doneCallbacks - A function, or array of functions, called when the deferred is resolved.
	 * @param {(failCallback|Array.<failCallback>)} failCallbacks - A function, or array of functions, called when the deferred is rejected.
	 * @param {(progressCallback|Array.<progressCallback>)} progressCallbacks - A function, or array of functions, called when the deferred notifies progress.
	 * @returns {FooJitsu.Deferred}
	 */
	$.Deferred.prototype.then = function(doneCallbacks, failCallbacks, progressCallbacks){
		this.__callbacks__.push({resolve: doneCallbacks, reject: failCallbacks, progress: progressCallbacks});
		return this;
	};

	/**
	 * Add handlers to be called when the deferred object is either resolved or rejected.
	 * @param {(alwaysCallback|Array.<alwaysCallback>)} alwaysCallbacks - A function, or array of functions, that is called when the deferred is resolved or rejected.
	 * @returns {FooJitsu.Deferred}
	 */
	$.Deferred.prototype.always = function(alwaysCallbacks){
		this.__callbacks__.push({always: alwaysCallbacks});
		return this;
	};

	/**
	 * Add handlers to be called when the deferred object is resolved.
	 * @param {(doneCallback|Array.<doneCallback>)} doneCallbacks - A function, or array of functions, called when the deferred is resolved.
	 * @returns {FooJitsu.Deferred}
	 */
	$.Deferred.prototype.done = function(doneCallbacks){
		this.__callbacks__.push({resolve: doneCallbacks});
		return this;
	};

	/**
	 * Add handlers to be called when the deferred object is rejected.
	 * @param {(failCallback|Array.<failCallback>)} failCallbacks - A function, or array of functions, called when the deferred is rejected.
	 * @returns {FooJitsu.Deferred}
	 */
	$.Deferred.prototype.fail = function(failCallbacks){
		this.__callbacks__.push({reject: failCallbacks});
		return this;
	};

	/**
	 * Add handlers to be called when the deferred object generates progress notifications.
	 * @param {(progressCallback|Array.<progressCallback>)} progressCallbacks - A function, or array of functions, to be called when the deferred generates progress notifications.
	 * @returns {FooJitsu.Deferred}
	 */
	$.Deferred.prototype.progress = function(progressCallbacks){
		this.__callbacks__.push({progress: progressCallbacks});
		return this;
	};

	/**
	 * Provides a way to execute callback functions based on one or more deferred objects that represent asynchronous events.
	 * @param {...FooJitsu.Deferred} deferreds - One or more deferred objects.
	 * @returns {FooJitsu.Deferred}
	 */
	$.when = function(deferreds){
		var args = Array.prototype.slice.call(arguments);
		return new $.Deferred(function(d){
			var expected = args.length, results = {length: 0};
			$.each(args, function(i, deferred){
				deferred.then(function(result){
					results.length++;
					results[i] = result;
					if (results.length === expected) d.resolve($.makeArray(results));
				}, function(err){
					d.reject(err);
				});
			});
		});
	};

})(FooJitsu);<|endoftext|>


<commit_before>doh = {

	// This is a temporary structure which points to the current data.
	_current:{
		group:null,
		groupIndex:-1,
		test:null,
		testIndex:-1
	},
	// A helper property, which stores a reference to a test group by name.
	_groupsByName:{},

	// Statistical data.
	_numTests:0, // The total number of tests.
	_numTestsExecuted:0, // Number of tests already executed.

	// Stats about the test results.
	_numErrors:0,
	_numFailures:0,

	//
	_isPaused:false,
	_defaultTimeout:1000,
	_testInFlight:false,

	// The groups must be an array, since an object does not necessarily maintain
	// it's order, but tests should be executed in the order as added.
	// This might become even more important when test dependencies will be added,
	// which means only execute test2 if test1 succeeded.
	_groups:[],

	_additionalGroupProperties:{
		numTestsExecuted:0,
		numFailures:0,
		numErrors:0
	},

	pause:function(){
		this._isPaused = true;
	},

	register:function(groupName, tests){
		// summary: Register the given tests to the group with the given name.
		// description: The tests are internally stored in "_groups", an array
		// 		which contains all the tests per group. The new tests are added
		// 		to the group with the given name, if it didnt exist yet it is created.
		var group = null;
		if (this._groupsByName[groupName]){
			group = this._groupsByName[groupName];
		} else {
			this._groups.push({name:groupName, tests:[]});
			group = this._groupsByName[groupName] = this._groups[this._groups.length-1];
		}
		for (var i=0, l=tests.length, t; i<l; i++){
			group.tests.push(tests[i]);
		}
		this._numTests += tests.length;
	},

	run:function(){
		if (this._current.group===null){
			this.ui.started();
		}
		this._isPaused = false;
		if (this._testInFlight){
			return;
		}
		this._runNextTest();
	},

	_MultipleAssertWrapper: (function(){
		function M(test){
			this._test = test;
			this._asserts = [];
		}

		M.prototype.run = function(){
			var asserts = this._asserts;
			var test = this._test;
			setTimeout(function(){
				var messages = [];
				for(var i = 0, assertion; (assertion = asserts[i]); i += 2){
					try{
						doh.assert[assertion].apply(doh.assert, asserts[i+1]);
					}catch(e){
						if(e instanceof doh.assert.Failure){
							messages.push("Assertion #" + (i/2+1) + " \u2013 " + e.message);
						}else{
							throw e;
						}
					}
				}

				if(messages.length){
					test.failure(messages.join("\n\n"));
				}else{
					test.success();
				}
			}, 1);
		};

		return M;
	}()),

	_getAssertWrapper:function(d){
		// summary: This returns an object which provides all the assert methods, and wraps a Deferred instance.
		// description: Why that? The interface for doh tests should be the same
		// 		for synchronous and asynchronous tests. The old version required
		// 		you to "know" and "think" when writing asynch tests, and the
		// 		assert methods had not been available directly when writing
		// 		asynchronous tests, you had to use doh.callback/errback.
		// 		This allows to ONLY use assert*() methods. See the selftests
		// 		for examples.
		var myT = {
			_assertClosure: function(method, args){
				// If the Deferred instance is already "done", means callback or errback
				// had already been called don't do it again.
				// This might be the case when e.g. the test timed out.
				if (d.fired > -1){
console.log('FIXXXXXME multiple asserts or timeout ... d.fired = ', d.fired, "GROUP and TEST: '", d.test.group.name, "' " , d.test.name);
					return;
				}
				try{
					var ret = doh.assert[method].apply(doh, args);
					d.callback(ret || true);
				}catch(e){
					d.errback(e);
				}
			},
			success: function(msg){
				// This function can be used to directly make a test succeed.
//TODO write selftest for it!!!!!!!!!
				d.test.result = msg;
				d.callback(msg);
			},
			failure: function(msg){
//TODO write selftest for it!!!!!!!!!
				d.errback(new doh.assert.Failure(msg));
			}
		};

		var multipleAssertsWrapper = new this._MultipleAssertWrapper(myT);

		myT.assertMultiple = function(){
			return multipleAssertsWrapper;
		};

		for (var methodName in doh.assert){
			if (methodName.indexOf("assert")===0){
				(function(methodName){
					myT[methodName] = function(){
						// Make sure the current callstack is worked off before
						// returning from any assert() method, we do this by
						// setTimeout(). The bug was that assert() didn't make the
						// test execute the return statement (if one was in there)
						// before the test ended, this fixes it.
						setTimeout(doh.util.hitch(myT, "_assertClosure", methodName, arguments), 1);
					}

					multipleAssertsWrapper[methodName] = function(){
						this._asserts.push(methodName, arguments);
						return this;
					};
				}(methodName));
			}
		}

		return myT;
	},

	_selectNextTest:function(){
		var c = this._current;
		// Is there a test left in this group?
		if (c.group && c.testIndex < c.group.tests.length-1){
			c.testIndex++;
		} else {
			// First test in the next group, if there is another group.
			if (c.groupIndex < this._groups.length-1){
				c.groupIndex++;
				c.group = this._groups[c.groupIndex];
				doh.util.mixin(c.group, this._additionalGroupProperties);
				this.ui.groupStarted(c.group);
				c.testIndex = 0;
			} else {
				this.ui.report();
				return false;
			}
		}
		c.test = c.group.tests[c.testIndex];
		return true;
	},

	_runNextTest:function(){
		// summary: Only called from internally after a test has finished.
		if (this._isPaused){
			return;
		}
		if (this._selectNextTest()){
			this._runTest();
		}
	},

	_runTest:function(){
		// summary: This executes the current test.
		// description: This method starts the "test" method of the test object
		// 		and finishes by setting the internal state "_testInFlight" to true,
		// 		which is resolved by the call to "_runNextTest()" which
		// 		automatically happens after the (asynchronous) test has "landed".
		var g = this._current.group,
			t = this._current.test;
		this.ui.testStarted(g, t);

		// let doh reference "this.group.thinger..." which can be set by
		// another test or group-level setUp function
		t.group = g;
		var deferred = new doh.Deferred(),
			assertWrapperObject = this._getAssertWrapper(deferred),
			setUpError = null;
		if(t.setUp){
			try{
				t.setUp(assertWrapperObject);
			}catch(setUpError){
				deferred.errback(new Error('setUp() threw an error: ' + setUpError));
			}
		}
		if(!t[this.config.testFunctionName]){
			t[this.config.testFunctionName] = function(){deferred.errback(new Error("Test missing."));}
		}
		deferred.groupName = g.name;
		deferred.test = t;

		deferred.addErrback(function(err){
			if (err instanceof doh.assert.Failure){
				g.numFailures++;
				doh._numFailures++;
				doh.ui.testFailure(g, t, err);
			} else {
				g.numErrors++;
				doh._numErrors++;
				doh.ui.testError(g, t, err);
			}
		});

		var retEnd = function(){
			t.endTime = new Date();
			g.numTestsExecuted++;
			doh._numTestsExecuted++;
			if(t.tearDown){
				try{ // Catching tearDown() errors won't make the entire suite stall.
					t.tearDown(assertWrapperObject);
				}catch(tearDownError){
// FIXXXME handle this case. But how? see TODO.txt for more comments.
				}
			}
			doh.ui.testFinished(g, t, deferred.results[0]);
			// Is this the last test in the current group?
			var c = doh._current;
			if (c.testIndex == c.group.tests.length-1){
				doh.ui.groupFinished(g);
			}
		}

		var timer = setTimeout(function(){
			deferred.errback(new Error("test timeout in " + t.name.toString()));
		}, t.timeout || doh._defaultTimeout);

		deferred.addBoth(function(){
			// Copy over the result if an asynchronous test has writte a result.
			// It must be available through the test object.
// TODO maybe copy over all additional properties, compare to which props assertWrapperObject had upon creation and what new ones had been added, pass them all to t.*
			if (assertWrapperObject.result){
				t.result = assertWrapperObject.result;
			}
			clearTimeout(timer);
			retEnd();
			doh._testInFlight = false;
			setTimeout(doh.util.hitch(doh, "_runNextTest"), 1);
		});
		this._testInFlight = true;

		if (!setUpError){
			t.startTime = new Date();
			try{
				t.result = t[this.config.testFunctionName](assertWrapperObject);
			}catch(err){
				deferred.errback(err);
			}
		}
	}
}
<commit_msg>Making successful multiple assertions visible by passing message to `test.success()`<commit_after>doh = {

	// This is a temporary structure which points to the current data.
	_current:{
		group:null,
		groupIndex:-1,
		test:null,
		testIndex:-1
	},
	// A helper property, which stores a reference to a test group by name.
	_groupsByName:{},

	// Statistical data.
	_numTests:0, // The total number of tests.
	_numTestsExecuted:0, // Number of tests already executed.

	// Stats about the test results.
	_numErrors:0,
	_numFailures:0,

	//
	_isPaused:false,
	_defaultTimeout:1000,
	_testInFlight:false,

	// The groups must be an array, since an object does not necessarily maintain
	// it's order, but tests should be executed in the order as added.
	// This might become even more important when test dependencies will be added,
	// which means only execute test2 if test1 succeeded.
	_groups:[],

	_additionalGroupProperties:{
		numTestsExecuted:0,
		numFailures:0,
		numErrors:0
	},

	pause:function(){
		this._isPaused = true;
	},

	register:function(groupName, tests){
		// summary: Register the given tests to the group with the given name.
		// description: The tests are internally stored in "_groups", an array
		// 		which contains all the tests per group. The new tests are added
		// 		to the group with the given name, if it didnt exist yet it is created.
		var group = null;
		if (this._groupsByName[groupName]){
			group = this._groupsByName[groupName];
		} else {
			this._groups.push({name:groupName, tests:[]});
			group = this._groupsByName[groupName] = this._groups[this._groups.length-1];
		}
		for (var i=0, l=tests.length, t; i<l; i++){
			group.tests.push(tests[i]);
		}
		this._numTests += tests.length;
	},

	run:function(){
		if (this._current.group===null){
			this.ui.started();
		}
		this._isPaused = false;
		if (this._testInFlight){
			return;
		}
		this._runNextTest();
	},

	_MultipleAssertWrapper: (function(){
		function M(test){
			this._test = test;
			this._asserts = [];
		}

		M.prototype.run = function(){
			var asserts = this._asserts;
			var test = this._test;
			setTimeout(function(){
				var messages = [];
				for(var i = 0, assertion; (assertion = asserts[i]); i += 2){
					try{
						doh.assert[assertion].apply(doh.assert, asserts[i+1]);
					}catch(e){
						if(e instanceof doh.assert.Failure){
							messages.push("Assertion #" + (i/2+1) + " \u2013 " + e.message);
						}else{
							throw e;
						}
					}
				}

				if(messages.length){
					test.failure(messages.join("\n\n"));
				}else{
					test.success(asserts.length + " assertions successful.");
				}
			}, 1);
		};

		return M;
	}()),

	_getAssertWrapper:function(d){
		// summary: This returns an object which provides all the assert methods, and wraps a Deferred instance.
		// description: Why that? The interface for doh tests should be the same
		// 		for synchronous and asynchronous tests. The old version required
		// 		you to "know" and "think" when writing asynch tests, and the
		// 		assert methods had not been available directly when writing
		// 		asynchronous tests, you had to use doh.callback/errback.
		// 		This allows to ONLY use assert*() methods. See the selftests
		// 		for examples.
		var myT = {
			_assertClosure: function(method, args){
				// If the Deferred instance is already "done", means callback or errback
				// had already been called don't do it again.
				// This might be the case when e.g. the test timed out.
				if (d.fired > -1){
console.log('FIXXXXXME multiple asserts or timeout ... d.fired = ', d.fired, "GROUP and TEST: '", d.test.group.name, "' " , d.test.name);
					return;
				}
				try{
					var ret = doh.assert[method].apply(doh, args);
					d.callback(ret || true);
				}catch(e){
					d.errback(e);
				}
			},
			success: function(msg){
				// This function can be used to directly make a test succeed.
//TODO write selftest for it!!!!!!!!!
				d.test.result = msg;
				d.callback(msg);
			},
			failure: function(msg){
//TODO write selftest for it!!!!!!!!!
				d.errback(new doh.assert.Failure(msg));
			}
		};

		var multipleAssertsWrapper = new this._MultipleAssertWrapper(myT);

		myT.assertMultiple = function(){
			return multipleAssertsWrapper;
		};

		for (var methodName in doh.assert){
			if (methodName.indexOf("assert")===0){
				(function(methodName){
					myT[methodName] = function(){
						// Make sure the current callstack is worked off before
						// returning from any assert() method, we do this by
						// setTimeout(). The bug was that assert() didn't make the
						// test execute the return statement (if one was in there)
						// before the test ended, this fixes it.
						setTimeout(doh.util.hitch(myT, "_assertClosure", methodName, arguments), 1);
					}

					multipleAssertsWrapper[methodName] = function(){
						this._asserts.push(methodName, arguments);
						return this;
					};
				}(methodName));
			}
		}

		return myT;
	},

	_selectNextTest:function(){
		var c = this._current;
		// Is there a test left in this group?
		if (c.group && c.testIndex < c.group.tests.length-1){
			c.testIndex++;
		} else {
			// First test in the next group, if there is another group.
			if (c.groupIndex < this._groups.length-1){
				c.groupIndex++;
				c.group = this._groups[c.groupIndex];
				doh.util.mixin(c.group, this._additionalGroupProperties);
				this.ui.groupStarted(c.group);
				c.testIndex = 0;
			} else {
				this.ui.report();
				return false;
			}
		}
		c.test = c.group.tests[c.testIndex];
		return true;
	},

	_runNextTest:function(){
		// summary: Only called from internally after a test has finished.
		if (this._isPaused){
			return;
		}
		if (this._selectNextTest()){
			this._runTest();
		}
	},

	_runTest:function(){
		// summary: This executes the current test.
		// description: This method starts the "test" method of the test object
		// 		and finishes by setting the internal state "_testInFlight" to true,
		// 		which is resolved by the call to "_runNextTest()" which
		// 		automatically happens after the (asynchronous) test has "landed".
		var g = this._current.group,
			t = this._current.test;
		this.ui.testStarted(g, t);

		// let doh reference "this.group.thinger..." which can be set by
		// another test or group-level setUp function
		t.group = g;
		var deferred = new doh.Deferred(),
			assertWrapperObject = this._getAssertWrapper(deferred),
			setUpError = null;
		if(t.setUp){
			try{
				t.setUp(assertWrapperObject);
			}catch(setUpError){
				deferred.errback(new Error('setUp() threw an error: ' + setUpError));
			}
		}
		if(!t[this.config.testFunctionName]){
			t[this.config.testFunctionName] = function(){deferred.errback(new Error("Test missing."));}
		}
		deferred.groupName = g.name;
		deferred.test = t;

		deferred.addErrback(function(err){
			if (err instanceof doh.assert.Failure){
				g.numFailures++;
				doh._numFailures++;
				doh.ui.testFailure(g, t, err);
			} else {
				g.numErrors++;
				doh._numErrors++;
				doh.ui.testError(g, t, err);
			}
		});

		var retEnd = function(){
			t.endTime = new Date();
			g.numTestsExecuted++;
			doh._numTestsExecuted++;
			if(t.tearDown){
				try{ // Catching tearDown() errors won't make the entire suite stall.
					t.tearDown(assertWrapperObject);
				}catch(tearDownError){
// FIXXXME handle this case. But how? see TODO.txt for more comments.
				}
			}
			doh.ui.testFinished(g, t, deferred.results[0]);
			// Is this the last test in the current group?
			var c = doh._current;
			if (c.testIndex == c.group.tests.length-1){
				doh.ui.groupFinished(g);
			}
		}

		var timer = setTimeout(function(){
			deferred.errback(new Error("test timeout in " + t.name.toString()));
		}, t.timeout || doh._defaultTimeout);

		deferred.addBoth(function(){
			// Copy over the result if an asynchronous test has writte a result.
			// It must be available through the test object.
// TODO maybe copy over all additional properties, compare to which props assertWrapperObject had upon creation and what new ones had been added, pass them all to t.*
			if (assertWrapperObject.result){
				t.result = assertWrapperObject.result;
			}
			clearTimeout(timer);
			retEnd();
			doh._testInFlight = false;
			setTimeout(doh.util.hitch(doh, "_runNextTest"), 1);
		});
		this._testInFlight = true;

		if (!setUpError){
			t.startTime = new Date();
			try{
				t.result = t[this.config.testFunctionName](assertWrapperObject);
			}catch(err){
				deferred.errback(err);
			}
		}
	}
}
<|endoftext|>


<commit_before>var k,
Keyboard = {

  config: {
      hidden: $("tr.hidden-xs-up"),
      keyboard: $("#viewer-modal"),
      search: $("#listr-search")
  },

    init: function() {
        m = this.config;
        this.events();
    },

    // Keyboard events
    events: function() {

      $(document).bind('keydown', function(event) {
        Keyboard.revealFiles();
      }).bind('keyup',function(){
          Keyboard.hideFiles();
      });

      $(document).bind('keyup', function(event) {
          Keyboard.playerControls();
      })

      $(document).bind('keyup', function(event) {
          Keyboard.focusSearch();
      })
    },

    // show hidden files
    revealFiles: function() {
        if( event.altKey ) {
            $(m.hidden).addClass( "reveal" ).removeClass( "hidden-xs-up");
            stripedRows();
        }
    },

    // hide hidden files again
    hideFiles: function() {
        $(m.hidden).removeClass( "reveal" ).addClass( "hidden-xs-up");
        stripedRows();
    },

    // focus search input
    focusSearch: function() {
        if (!viewer.hasClass('in')) {
         if (event.which === 70) {
             $(m.search).focus();
             $(document).scrollTop(0);
         }
        }
    },

    // Control HTML5 player
    playerControls: function() {
        // Only when modal is visible
        if (viewer.hasClass('in')) {

          // Fullscreen
          if (event.which === 70) {
            if (player.requestFullscreen) {
              player.requestFullscreen();
            } else if (player.msRequestFullscreen) {
              player.msRequestFullscreen();
            } else if (player.mozRequestFullScreen) {
              player.mozRequestFullScreen();
            } else if (player.webkitRequestFullscreen) {
              player.webkitRequestFullscreen();
            }
          }

          // Play/pause
          if (event.which === 32) {

            event.preventDefault();

            if (player.paused === false) {
              player.pause();
            } else {
              player.play();
            }
          }

          // Seek backward
          if (event.which === 37) {
            player.currentTime -= 1;
          }

          // Seek forward
          if (event.which === 39) {
            player.currentTime += 1;
          }

          // Rewind player
          if (event.which === 37 && event.shiftKey) {
            player.currentTime = 0;
          }

          // Increase volume
          if (event.which === 38) {
            player.volume += 0.1;
          }

          // Max volume
          if (event.which === 38 && event.shiftKey) {
            player.volume = 1;
          }

          // Decrease volume
          if (event.which === 40) {
            player.volume -= 0.1;
          }

          // Mute volume
          if (event.which === 40 && event.shiftKey) {
            player.volume = 0;
          }
        }
    }
};
<commit_msg>rename var; indent<commit_after>var K,
Keyboard = {

  config: {
      hidden: $("tr.hidden-xs-up"),
      keyboard: $("#viewer-modal"),
      search: $("#listr-search")
  },

  init: function() {
      K = this.config;
      this.events();
  },

  // Keyboard events
  events: function() {
    $(document).bind('keydown', function(event) {
      Keyboard.revealFiles();
    }).bind('keyup',function(){
        Keyboard.hideFiles();
    });

    $(document).bind('keyup', function(event) {
        Keyboard.playerControls();
    })

    $(document).bind('keyup', function(event) {
        Keyboard.focusSearch();
    })
  },

  // show hidden files
  revealFiles: function() {
      if( event.altKey ) {
          $(K.hidden).addClass( "reveal" ).removeClass( "hidden-xs-up");
          stripedRows();
      }
  },

  // hide hidden files again
  hideFiles: function() {
      $(K.hidden).removeClass( "reveal" ).addClass( "hidden-xs-up");
      stripedRows();
  },

  // focus search input
  focusSearch: function() {
      if (!viewer.hasClass('in')) {
        if (event.which === 70) {
            $(K.search).focus();
            $(document).scrollTop(0);
        }
      }
  },

  // Control HTML5 player
  playerControls: function() {
    // Only when modal is visible
    if (viewer.hasClass('in')) {

      // Fullscreen
      if (event.which === 70) {
        if (player.requestFullscreen) {
          player.requestFullscreen();
        } else if (player.msRequestFullscreen) {
          player.msRequestFullscreen();
        } else if (player.mozRequestFullScreen) {
          player.mozRequestFullScreen();
        } else if (player.webkitRequestFullscreen) {
          player.webkitRequestFullscreen();
        }
      }

      // Play/pause
      if (event.which === 32) {

        event.preventDefault();

        if (player.paused === false) {
          player.pause();
        } else {
          player.play();
        }
      }

      // Seek backward
      if (event.which === 37) {
        player.currentTime -= 1;
      }

      // Seek forward
      if (event.which === 39) {
        player.currentTime += 1;
      }

      // Rewind player
      if (event.which === 37 && event.shiftKey) {
        player.currentTime = 0;
      }

      // Increase volume
      if (event.which === 38) {
        player.volume += 0.1;
      }

      // Max volume
      if (event.which === 38 && event.shiftKey) {
        player.volume = 1;
      }

      // Decrease volume
      if (event.which === 40) {
        player.volume -= 0.1;
      }

      // Mute volume
      if (event.which === 40 && event.shiftKey) {
        player.volume = 0;
      }
    }
  }
};
<|endoftext|>


<commit_before>/**
 * launches _Main.main(:string[]):void invoked by jsx --run|--executable
 */
JSX.runMain = function (sourceFile, args) {
	var module = JSX.require(sourceFile);
	if (! module) {
		throw new Error("entry point module not found in " + sourceFile);
	}

	if (! module._Main) {
		throw new Error("entry point _Main not found in " + sourceFile);
	}
	if (! module._Main.main$AS) {
		throw new Error("entry point _Main.main(:string[]):void not found in " + sourceFile);
	}
	module._Main.main$AS(args);
};

/**
 * launches _Test#test*():void invoked by jsx --test
 */
JSX.runTests = function (sourceFile, tests) {
	var module = JSX.require(sourceFile);
	var testClass = module._Test$;

	if (!testClass) return; // skip if there's no test class

	if(tests.length === 0) {
		var p = testClass.prototype;
		for (var m in p) {
			if (p[m] instanceof Function
				&& /^test.*[$]$/.test(m)) {
				tests.push(m);
			}
		}
	}
	else { // set as process arguments
		tests = tests.map(function (name) {
			return name + "$"; // mangle for function test*():void
		});
	}

	var testCase = new testClass();

	if (testCase.beforeClass$AS != null)
		testCase.beforeClass$AS(tests);

	for (var i = 0; i < tests.length; ++i) {
		(function (method) {
			if (method in testCase) {
				testCase.run$SF$V$(method, function() { testCase[method](); });
			}
			else {
				throw new ReferenceError("No such test method: " + method);
			}
		}(tests[i]));
	}

	if (testCase.afterClass$ != null)
		testCase.afterClass$();
};
<commit_msg>use ReferenceError for entity not found error in launcher.js<commit_after>/**
 * launches _Main.main(:string[]):void invoked by jsx --run|--executable
 */
JSX.runMain = function (sourceFile, args) {
	var module = JSX.require(sourceFile);
	if (! module) {
		throw new ReferenceError("entry point module not found in " + sourceFile);
	}
	if (! module._Main) {
		throw new ReferenceError("entry point _Main not found in " + sourceFile);
	}
	if (! module._Main.main$AS) {
		throw new ReferenceError("entry point _Main.main(:string[]):void not found in " + sourceFile);
	}
	module._Main.main$AS(args);
};

/**
 * launches _Test#test*():void invoked by jsx --test
 */
JSX.runTests = function (sourceFile, tests) {
	var module = JSX.require(sourceFile);
	var testClass = module._Test$;

	if (!testClass) return; // skip if there's no test class

	if(tests.length === 0) {
		var p = testClass.prototype;
		for (var m in p) {
			if (p[m] instanceof Function
				&& /^test.*[$]$/.test(m)) {
				tests.push(m);
			}
		}
	}
	else { // set as process arguments
		tests = tests.map(function (name) {
			return name + "$"; // mangle for function test*():void
		});
	}

	var testCase = new testClass();

	if (testCase.beforeClass$AS != null)
		testCase.beforeClass$AS(tests);

	for (var i = 0; i < tests.length; ++i) {
		(function (method) {
			if (method in testCase) {
				testCase.run$SF$V$(method, function() { testCase[method](); });
			}
			else {
				throw new ReferenceError("No such test method: " + method);
			}
		}(tests[i]));
	}

	if (testCase.afterClass$ != null)
		testCase.afterClass$();
};
<|endoftext|>


<commit_before>/* safe.js - Building a safer world for Pebble.JS Developers
 *
 * This library provides wrapper around all the asynchronous handlers that developers
 * have access to so that error messages are caught and displayed nicely in the pebble tool
 * console.
 */

/* global __loader */

var ajax = require('ajax');

var safe = {};

/* The name of the concatenated file to translate */
safe.translateName = 'pebble-js-app.js';

safe.indent = '    ';

/* Translates a source line position to the originating file */
safe.translatePos = function(name, lineno, colno) {
  if (name === safe.translateName) {
    var pkg = __loader.getPackageByLineno(lineno);
    if (pkg) {
      name = pkg.filename;
      lineno -= pkg.lineno;
    }
  }
  return name + ':' + lineno + ':' + colno;
};

/* Translates an iOS stack tace line to node style */
safe.translateLineIOS = function(line, scope, name, lineno, colno) {
  var pos = safe.translatePos(name, lineno, colno);
  return safe.indent + 'at ' + (scope ? scope  + ' (' + pos + ')' : pos);
};

/* Matches (<scope> '@' )? <name> ':' <lineno> ':' <colno> */
var stackLineRegExp = /(?:([^\s@]+)@)?([^\s@:]+):(\d+):(\d+)/;

safe.translateStackIOS = function(stack) {
  var lines = stack.split('\n');
  for (var i = lines.length - 1; i >= 0; --i) {
    var line = lines[i];
    var m = line.match(stackLineRegExp);
    if (m) {
      line = lines[i] = safe.translateLineIOS.apply(this, m);
    }
    if (line.match(module.filename)) {
      lines.splice(--i, 2);
    }
  }
  return lines.join('\n');
};

safe.translateStackAndroid = function(stack) {
  var lines = stack.split('\n');
  for (var i = lines.length - 1; i >= 0; --i) {
    var line = lines[i];
    var m = line.match(/\?params=(.*):(\d+):(\d+)/);
    var name, lineno, colno;
    if (m) {
      name = JSON.parse(decodeURIComponent(m[1])).loadUrl.replace(/^.*\//, '');
      lineno = m[2];
      colno = m[3];
    } else {
      m = line.match(/^.*\/(.*?):(\d+):(\d+)/);
      if (m) {
        name = m[1];
        lineno = m[2];
        colno = m[3];
      }
    }
    if (name) {
      var pos = safe.translatePos(name, lineno, colno);
      if (line.match(/\(.*\)/)) {
        line = line.replace(/\(.*\)/, '(' + pos + ')');
      } else {
        line = line.replace(/[^\s\/]*\/.*$/, pos);
      }
      lines[i] = line;
    }
  }
  return lines.join('\n');
};

/* Translates a stack trace to the originating files */
safe.translateStack = function(stack) {
  if (stack.match('com.getpebble.android')) {
    return safe.translateStackAndroid(stack);
  } else {
    return safe.translateStackIOS(stack);
  }
};

safe.translateError = function(err) {
  var name = err.name;
  var message = err.message;
  var stack = err.stack;
  var result = ['JavaScript Error:'];
  if (message && (!stack || !stack.match(message))) {
    if (name && !message.match(message)) {
      message = name + ': ' + message;
    }
    result.push(message);
  }
  if (stack) {
    result.push(safe.translateStack(stack));
  }
  return result.join('\n');
};

/* We use this function to dump error messages to the console. */
safe.dumpError = function(err) {
  if (typeof err === 'object') {
      console.log(safe.translateError(err));
  } else {
    console.log('dumpError :: argument is not an object');
  }
};

/* Takes a function and return a new function with a call to it wrapped in a try/catch statement */
safe.protect = function(fn) {
  return function() {
    try {
      return fn.apply(this, arguments);
    }
    catch (err) {
      safe.dumpError(err);
    }
  };
};

/* Wrap event handlers added by Pebble.addEventListener */
var pblAddEventListener = Pebble.addEventListener;
Pebble.addEventListener = function(eventName, eventCallback) {
  pblAddEventListener.call(this, eventName, safe.protect(eventCallback));
};

var pblSendMessage = Pebble.sendAppMessage;
Pebble.sendAppMessage = function(message, success, failure) {
  return pblSendMessage.call(this, message, safe.protect(success), safe.protect(failure));
};

/* Wrap setTimeout and setInterval */
var originalSetTimeout = setTimeout;
window.setTimeout = function(callback, delay) {
  return originalSetTimeout(safe.protect(callback), delay);
};
var originalSetInterval = setInterval;
window.setInterval = function(callback, delay) {
  return originalSetInterval(safe.protect(callback), delay);
};

/* Wrap the success and failure callback of the ajax library */
ajax.onHandler = function(eventName, callback) {
  return safe.protect(callback);
};

/* Wrap the geolocation API Callbacks */
var watchPosition = navigator.geolocation.watchPosition;
navigator.geolocation.watchPosition = function(success, error, options) {
  return watchPosition.call(this, safe.protect(success), safe.protect(error), options);
};
var getCurrentPosition = navigator.geolocation.getCurrentPosition;
navigator.geolocation.getCurrentPosition = function(success, error, options) {
  return getCurrentPosition.call(this, safe.protect(success), safe.protect(error), options);
};

module.exports = safe;
<commit_msg>Fix safe.js translate stack android to translate only relevant lines<commit_after>/* safe.js - Building a safer world for Pebble.JS Developers
 *
 * This library provides wrapper around all the asynchronous handlers that developers
 * have access to so that error messages are caught and displayed nicely in the pebble tool
 * console.
 */

/* global __loader */

var ajax = require('ajax');

var safe = {};

/* The name of the concatenated file to translate */
safe.translateName = 'pebble-js-app.js';

safe.indent = '    ';

/* Translates a source line position to the originating file */
safe.translatePos = function(name, lineno, colno) {
  if (name === safe.translateName) {
    var pkg = __loader.getPackageByLineno(lineno);
    if (pkg) {
      name = pkg.filename;
      lineno -= pkg.lineno;
    }
  }
  return name + ':' + lineno + ':' + colno;
};

/* Translates an iOS stack tace line to node style */
safe.translateLineIOS = function(line, scope, name, lineno, colno) {
  var pos = safe.translatePos(name, lineno, colno);
  return safe.indent + 'at ' + (scope ? scope  + ' (' + pos + ')' : pos);
};

/* Matches (<scope> '@' )? <name> ':' <lineno> ':' <colno> */
var stackLineRegExp = /(?:([^\s@]+)@)?([^\s@:]+):(\d+):(\d+)/;

safe.translateStackIOS = function(stack) {
  var lines = stack.split('\n');
  for (var i = lines.length - 1; i >= 0; --i) {
    var line = lines[i];
    var m = line.match(stackLineRegExp);
    if (m) {
      line = lines[i] = safe.translateLineIOS.apply(this, m);
    }
    if (line.match(module.filename)) {
      lines.splice(--i, 2);
    }
  }
  return lines.join('\n');
};

safe.translateStackAndroid = function(stack) {
  var lines = stack.split('\n');
  for (var i = lines.length - 1; i > 0; --i) {
    var line = lines[i];
    var name, lineno, colno;
    if (line.match(/jskit_startup\.html/)) {
      lines.splice(i, 1);
    } else {
      var m = line.match(/^.*\/(.*?):(\d+):(\d+)/);
      if (m) {
        name = m[1];
        lineno = m[2];
        colno = m[3];
      }
    }
    if (name) {
      var pos = safe.translatePos(name, lineno, colno);
      console.log(pos, name, lineno, colno);
      if (line.match(/\(.*\)/)) {
        line = line.replace(/\(.*\)/, '(' + pos + ')');
      } else {
        line = line.replace(/[^\s\/]*\/.*$/, pos);
      }
      lines[i] = line;
    }
  }
  return lines.join('\n');
};

/* Translates a stack trace to the originating files */
safe.translateStack = function(stack) {
  if (stack.match('com.getpebble.android')) {
    return safe.translateStackAndroid(stack);
  } else {
    return safe.translateStackIOS(stack);
  }
};

safe.translateError = function(err) {
  var name = err.name;
  var message = err.message;
  var stack = err.stack;
  var result = ['JavaScript Error:'];
  if (message && (!stack || !stack.match(message))) {
    if (name && !message.match(message)) {
      message = name + ': ' + message;
    }
    result.push(message);
  }
  if (stack) {
    result.push(safe.translateStack(stack));
  }
  return result.join('\n');
};

/* We use this function to dump error messages to the console. */
safe.dumpError = function(err) {
  if (typeof err === 'object') {
      console.log(safe.translateError(err));
  } else {
    console.log('dumpError :: argument is not an object');
  }
};

/* Takes a function and return a new function with a call to it wrapped in a try/catch statement */
safe.protect = function(fn) {
  return function() {
    try {
      return fn.apply(this, arguments);
    }
    catch (err) {
      safe.dumpError(err);
    }
  };
};

/* Wrap event handlers added by Pebble.addEventListener */
var pblAddEventListener = Pebble.addEventListener;
Pebble.addEventListener = function(eventName, eventCallback) {
  pblAddEventListener.call(this, eventName, safe.protect(eventCallback));
};

var pblSendMessage = Pebble.sendAppMessage;
Pebble.sendAppMessage = function(message, success, failure) {
  return pblSendMessage.call(this, message, safe.protect(success), safe.protect(failure));
};

/* Wrap setTimeout and setInterval */
var originalSetTimeout = setTimeout;
window.setTimeout = function(callback, delay) {
  return originalSetTimeout(safe.protect(callback), delay);
};
var originalSetInterval = setInterval;
window.setInterval = function(callback, delay) {
  return originalSetInterval(safe.protect(callback), delay);
};

/* Wrap the success and failure callback of the ajax library */
ajax.onHandler = function(eventName, callback) {
  return safe.protect(callback);
};

/* Wrap the geolocation API Callbacks */
var watchPosition = navigator.geolocation.watchPosition;
navigator.geolocation.watchPosition = function(success, error, options) {
  return watchPosition.call(this, safe.protect(success), safe.protect(error), options);
};
var getCurrentPosition = navigator.geolocation.getCurrentPosition;
navigator.geolocation.getCurrentPosition = function(success, error, options) {
  return getCurrentPosition.call(this, safe.protect(success), safe.protect(error), options);
};

module.exports = safe;
<|endoftext|>


<commit_before>////////////
//Imports //
////////////

var fs = require("fs");
var handlebars = require("handlebars");

////////////////////
//Renderer Module //
////////////////////

/**
 * Get the contents of a file
 * @param  {String} filepath - Path to file
 * @return {Promise}         - Promise for file data
 */
function getFile(filepath) {
    var filePromise = new Promise(function (resolve, reject) {
        fs.readFile(filepath, "utf8", function (error, data) {
            if (error) reject(error);
            resolve(data);
        });
    });
    return filePromise;
}

/**
 * Generate a view from templates
 * @param  {Array}  - Array of template files in render order
 * @return {String} - View HTML
 */
function* _generateView(templateFiles, options) {
    var templates = yield Promise.all(templateFiles);

    var view = "", compiledTemplate;
    templates.forEach(function (template) {
        debugger;
        compiledTemplate = handlebars.compile(template);
        view += compiledTemplate(options);
    });
    return view;
}

/**
 * Handle rendering views
 * @param  {String}  - Name of template to render
 * @param  {Object}  - Options object
 * @return {Promise} - Promise for view
 */
function render(templateName, options) {
    if (options == undefined) {
        options = {};
    }

    var templates = [];
    switch (templateName) {
        case "home":
            templates = [
                getFile("./views/head.html"),
                getFile("./views/search.html")
            ];
            break;
        case "forecast":
            templates = [
                getFile("./views/head.html"),
                getFile("./views/forecast.html")
            ];
            break;
        case "error":
            templates = [
                getFile("./views/head.html"),
                getFile("./views/error.hbs"),
                getFile("./views/search.html")
            ];
            break;
    }

    var generator = _generateView(templates, options);

    var templatePromise = generator.next().value;
    var viewPromise = templatePromise.then(
        function onFulfilled(templates) {
            var view = generator.next(templates).value;
            return view;
        }
    );
    return Promise.resolve(viewPromise);
}

///////////////////
//Module Exports //
///////////////////

module.exports.css = getFile("./css/main.css");
module.exports.render = render;
<commit_msg>Removed 'debugger' statement<commit_after>////////////
//Imports //
////////////

var fs = require("fs");
var handlebars = require("handlebars");

////////////////////
//Renderer Module //
////////////////////

/**
 * Get the contents of a file
 * @param  {String} filepath - Path to file
 * @return {Promise}         - Promise for file data
 */
function getFile(filepath) {
    var filePromise = new Promise(function (resolve, reject) {
        fs.readFile(filepath, "utf8", function (error, data) {
            if (error) reject(error);
            resolve(data);
        });
    });
    return filePromise;
}

/**
 * Generate a view from templates
 * @param  {Array}  - Array of template files in render order
 * @return {String} - View HTML
 */
function* _generateView(templateFiles, options) {
    var templates = yield Promise.all(templateFiles);

    var view = "", compiledTemplate;
    templates.forEach(function (template) {
        compiledTemplate = handlebars.compile(template);
        view += compiledTemplate(options);
    });
    return view;
}

/**
 * Handle rendering views
 * @param  {String}  - Name of template to render
 * @param  {Object}  - Options object
 * @return {Promise} - Promise for view
 */
function render(templateName, options) {
    if (options == undefined) {
        options = {};
    }

    var templates = [];
    switch (templateName) {
        case "home":
            templates = [
                getFile("./views/head.html"),
                getFile("./views/search.html")
            ];
            break;
        case "forecast":
            templates = [
                getFile("./views/head.html"),
                getFile("./views/forecast.html")
            ];
            break;
        case "error":
            templates = [
                getFile("./views/head.html"),
                getFile("./views/error.hbs"),
                getFile("./views/search.html")
            ];
            break;
    }

    var generator = _generateView(templates, options);

    var templatePromise = generator.next().value;
    var viewPromise = templatePromise.then(
        function onFulfilled(templates) {
            var view = generator.next(templates).value;
            return view;
        }
    );
    return Promise.resolve(viewPromise);
}

///////////////////
//Module Exports //
///////////////////

module.exports.css = getFile("./css/main.css");
module.exports.render = render;
<|endoftext|>


<commit_before>const skills = require('./data/skills');
const inkipediaGear = require('./data/inkipediaGear');

function getOriginalGear(gear) {
    if (!gear)
        return;

    let originalGear = inkipediaGear[gear.kind].find(ig => ig.name == gear.name);

    if (!originalGear)
        return;

    return Object.assign({}, originalGear, { skill: skills[originalGear.skill] });
}

module.exports = {
    getOriginalGear,
}
<commit_msg>Improve original SplatNet gear name matching<commit_after>const skills = require('./data/skills');
const inkipediaGear = require('./data/inkipediaGear');

function getOriginalGear(gear) {
    if (!gear || !gear.name)
        return;

    let name = gear.name.toLowerCase().trim();

    let originalGear = inkipediaGear[gear.kind].find(ig => ig.name.toLowerCase() == name);

    if (!originalGear)
        return;

    return Object.assign({}, originalGear, { skill: skills[originalGear.skill] });
}

module.exports = {
    getOriginalGear,
}
<|endoftext|>