<commit_before>var Pontoon = (function (my) {
  return $.extend(true, my, {
    bugzilla: {

      /*
       * Retrieve bugs for the given locale and update bug count and tab content
       * using the provided elements and callbacks.
       *
       * Heavily inspired by the similar functionality available in Elmo.
       *
       * Source: https://github.com/mozilla/elmo/blob/master/apps/bugsy/static/bugsy/js/bugcount.js
       * Authors: Pike, peterbe, adngdb
       */
      getLocaleBugs: function (locale, container, tab, countCallback, errorCallback) {
        return $.ajax({
          url: 'https://bugzilla.mozilla.org/rest/bug',
          data: {
            'field0-0-0': 'component',
            'type0-0-0': 'regexp',
            'value0-0-0': '^' + locale + ' / ',
            'field0-0-1': 'cf_locale',
            'type0-0-1': 'regexp',
            'value0-0-1': '^' + locale + ' / ',
            'resolution': '---',
            'include_fields': 'id,summary,creation_time,last_change_time'
          },
          success: function(data) {
            if (data.bugs.length) {
              data.bugs.sort(function(l, r) {
                return l.last_change_time < r.last_change_time ? 1 : -1;
              });

              var tbody = $('
'),
                  formatter = new Intl.DateTimeFormat('en-GB', {
                    day: 'numeric',
                    month: 'long',
                    year: 'numeric'
                  });

              $.each(data.bugs, function(i, bug) {
                // Prevent malicious bug summary from executin JS code
                var summary = Pontoon.doNotRender(bug.summary);

                var tr = $('
', {
                  title: summary
                });

                $('', {
                  class: 'id',
                  html: '' + bug.id + ''
                }).appendTo(tr);

                $('', {
                  class: 'summary',
                  html: summary
                }).appendTo(tr);

                $('', {
                  class: 'last-changed',
                  html: formatter.format(new Date(bug.last_change_time))
                }).appendTo(tr);

                $('', {
                  class: 'date-created',
                  html: formatter.format(new Date(bug.creation_time))
                }).appendTo(tr);

                tbody.append(tr);
              });

              var table = $('
', {
                class: 'buglist striped',
                html: '
' +
                  '
' +
                    'ID	' +
                    'Summary	' +
                    'Last Changed	' +
                    'Date Created	' +
                  '
' +
                '
'
              }).append(tbody);

              container.append(table.show());

              var count = data.bugs.length;
              countCallback(tab, count);

            } else {
              contentCallback('Zarro Boogs Found.');
            }
          },
          error: function(error) {
            if (error.status === 0 && error.statusText !== 'abort') {
              contentCallback('Oops, something went wrong. We were unable to load the bugs. Please try again later.');
            }
          }
        });
      }

    }
  });
}(Pontoon || {}));
<commit_msg>Fix tab error callback<commit_after>var Pontoon = (function (my) {
  return $.extend(true, my, {
    bugzilla: {

      /*
       * Retrieve bugs for the given locale and update bug count and tab content
       * using the provided elements and callbacks.
       *
       * Heavily inspired by the similar functionality available in Elmo.
       *
       * Source: https://github.com/mozilla/elmo/blob/master/apps/bugsy/static/bugsy/js/bugcount.js
       * Authors: Pike, peterbe, adngdb
       */
      getLocaleBugs: function (locale, container, tab, countCallback, errorCallback) {
        return $.ajax({
          url: 'https://bugzilla.mozilla.org/rest/bug',
          data: {
            'field0-0-0': 'component',
            'type0-0-0': 'regexp',
            'value0-0-0': '^' + locale + ' / ',
            'field0-0-1': 'cf_locale',
            'type0-0-1': 'regexp',
            'value0-0-1': '^' + locale + ' / ',
            'resolution': '---',
            'include_fields': 'id,summary,creation_time,last_change_time'
          },
          success: function(data) {
            if (data.bugs.length) {
              data.bugs.sort(function(l, r) {
                return l.last_change_time < r.last_change_time ? 1 : -1;
              });

              var tbody = $('
'),
                  formatter = new Intl.DateTimeFormat('en-GB', {
                    day: 'numeric',
                    month: 'long',
                    year: 'numeric'
                  });

              $.each(data.bugs, function(i, bug) {
                // Prevent malicious bug summary from executin JS code
                var summary = Pontoon.doNotRender(bug.summary);

                var tr = $('
', {
                  title: summary
                });

                $('', {
                  class: 'id',
                  html: '' + bug.id + ''
                }).appendTo(tr);

                $('', {
                  class: 'summary',
                  html: summary
                }).appendTo(tr);

                $('', {
                  class: 'last-changed',
                  html: formatter.format(new Date(bug.last_change_time))
                }).appendTo(tr);

                $('', {
                  class: 'date-created',
                  html: formatter.format(new Date(bug.creation_time))
                }).appendTo(tr);

                tbody.append(tr);
              });

              var table = $('
', {
                class: 'buglist striped',
                html: '
' +
                  '
' +
                    'ID	' +
                    'Summary	' +
                    'Last Changed	' +
                    'Date Created	' +
                  '
' +
                '
'
              }).append(tbody);

              container.append(table.show());

              var count = data.bugs.length;
              countCallback(tab, count);

            } else {
              errorCallback('Zarro Boogs Found.');
            }
          },
          error: function(error) {
            if (error.status === 0 && error.statusText !== 'abort') {
              errorCallback('Oops, something went wrong. We were unable to load the bugs. Please try again later.');
            }
          }
        });
      }

    }
  });
}(Pontoon || {}));
<|endoftext|>


<commit_before>angular.module('App.ServerRoutes', [])

.factory('ServerRoutes', function(){
  //return an object of the routes
  return {
  	//change the routes once our server is deployed.
    sendContent: '/receivers/sendContent',
    getPending: '/pending/getPending',
    sendVote: '/pending/sendVote',
    getResults: '/results/getResults',
    getReceivers: '/receivers/getContacts',
    postContent: '/receivers/sendContent',
    logout: '/user/logout'
  };
});<commit_msg>(bug) add whitespace to serverRoutesFactory<commit_after>angular.module('App.ServerRoutes', [])

.factory('ServerRoutes', function(){
  //return an object of the routes
  return {
  	//change the routes once our server is deployed.
    sendContent: '/receivers/sendContent',
    getPending: '/pending/getPending',
    sendVote: '/pending/sendVote',
    getResults: '/results/getResults',
    getReceivers: '/receivers/getContacts',
    postContent: '/receivers/sendContent',
    logout: '/user/logout'
  };
});
<|endoftext|>


<commit_before>L.interpolatePosition = function(p1, p2, duration, t) {
    var k = t/duration;
    k = (k>0) ? k : 0;
    k = (k>1) ? 1 : k;
    return L.latLng(p1.lat + k*(p2.lat-p1.lat), p1.lng + k*(p2.lng-p1.lng));
};

L.Marker.MovingMarker = L.Marker.extend({

    //state constants
    statics: {
        notStartedState: 0,
        endedState: 1,
        pausedState: 2,
        runState: 3
    },

    options: {
        autostart: false,
        loop: false,

		},
	initialize: function (latlngs, durations,angles, options) {
        L.Marker.prototype.initialize.call(this, latlngs[0], options);
		this._latlngs = latlngs.map(function(e, index) {
		return L.latLng(e);
        });

        this._durations = durations;

        this._angles = angles;// newly coded
		this._currentDuration = 0;
        this._currentIndex = 0;
		this._currentAngle = 0;// newly coded

		this._state = L.Marker.MovingMarker.notStartedState;
        this._startTime = 0;
        this._startTimeStamp = 0;
        this._pauseStartTime = 0;
        this._animId = 0;
        this._animRequested = true;

        this._currentLine = [];
        this._pauseRequested = false;
    },

    isRunning: function() {

        return this._state === L.Marker.MovingMarker.runState;
    },

    isEnded: function() {
        return this._state === L.Marker.MovingMarker.endedState;
    },

    isStarted: function() {
        return this._state !== L.Marker.MovingMarker.notStartedState;
    },

    isPaused: function() {
        return this._state === L.Marker.MovingMarker.pausedState;
    },

	isPauseRequested : function(){

		return this._pauseRequested;

	},

    start: function() {
        if (this.isRunning()) {
            return;
        }

        if (this.isPaused()) {
            this.resume();
        } else {
            this._loadLine(0);

            this._startAnimation();
            this.fire('start');

        }
    },

    resume: function() {
        if (! this.isPaused()) {
            return;
        }
		this._pauseRequested = false;
        // update the current line
        this._currentLine[0] = this.getLatLng();
        this._currentDuration -= (this._pauseStartTime - this._startTime);
        this._currentAngle = (this._currentAngle); // newly coded
		this._startAnimation();
    },

    addLatLng: function(latlng, duration,angle) {
        this._latlngs.push(L.latLng(latlng));
        this._durations.push(duration);

    },

    moveTo: function(latlng, duration,angle) {

		this._stopAnimation();
        this._latlngs = [this.getLatLng(), L.latLng(latlng)];
        this._durations = [duration];
		this._angles = [angle];
        this._state = L.Marker.MovingMarker.notStartedState;
        this.start();
        this.options.loop = false;
    },

    addStation: function(pointIndex, duration) {
        if (pointIndex > this._latlngs.length - 2 || pointIndex < 1) {
            return;
        }
        var t = this._latlngs[pointIndex];
        this._latlngs.splice(pointIndex + 1, 0, t);
        this._durations.splice(pointIndex, 0, duration);

        //this._angles.splice(pointIndex,0,angle); // newly coded
    },

    _startAnimation: function() {
        this._startTime = Date.now();
        this._state = L.Marker.MovingMarker.runState;
        this._animId = L.Util.requestAnimFrame(function(timestamp) {
            this._startTimeStamp = timestamp;
            this._animate(timestamp);
        }, this, true );

		this._animRequested = true;

    },

    _resumeAnimation: function() {
        if (! this._animRequested ) {
            this._animId = L.Util.requestAnimFrame(function(timestamp) {
                this._animate(timestamp);
            }, this, true );
        }
    },

    _stopAnimation: function() {
        if (this._animRequested ) {
            L.Util.cancelAnimFrame(this._animId);
            this._animRequested = false;

        }
    },

    _loadLine: function(index) {
        this._currentIndex = index;
        this._currentDuration = this._durations[index];
		this._currentAngle = this._angles[index]; // newly coded
        this._currentLine = this._latlngs.slice(index, index + 2);
    },

    /**
     * Load the line where the marker is
     * @param  {Number} timestamp
     * @return {Number} elapsed time on the current line or null if
     * we reached the end or marker is at a station
     */
    _updateLine: function(timestamp) {
        //time elapsed since the last latlng
        var elapsedTime = timestamp - this._startTimeStamp;

        // not enough time to update the line
        if (elapsedTime <= this._currentDuration) {
            return elapsedTime;
        }/*
		if (elapsedTime <= this._currentAngle){
			return elapsedTime;
		}*/

        var lineIndex = this._currentIndex;
        var lineDuration = this._currentDuration;
		//var lineAngle = this._currentAngle; // newly coded

        while (elapsedTime > lineDuration) {
            //substract time of the current line
            elapsedTime -= lineDuration;
            lineIndex++;

            // test if we have reached the end of the polyline
            if (lineIndex >= this._latlngs.length - 1) {

                if (this.options.loop) {
                    lineIndex = 0;
                    this.fire('loop', {elapsedTime: elapsedTime});
                } else {
                    // place the marker at the end, else it would be at
                    // the last position
                    this.setLatLng(this._latlngs[this._latlngs.length-1]);
                    this.stop(elapsedTime);
                    return null;
                }
            }
            lineDuration = this._durations[lineIndex];

        }

        this._loadLine(lineIndex);
        this._startTimeStamp = timestamp - elapsedTime;
        this._startTime = Date.now() - elapsedTime;
        return elapsedTime;

    },

    _animate: function(timestamp, noRequestAnim) {
        // compute the time elapsed since the start of the line
        var elapsedTime;
        this._animRequested = false;

        //find the next line and compute the new elapsedTime
        elapsedTime = this._updateLine(timestamp);

        if (elapsedTime === null) {
            //we have reached the end
            return;

		this._animRequested = true;

        }

        // compute the position

			var p = L.interpolatePosition(this._currentLine[0],
            this._currentLine[1],
            this._currentDuration,

            elapsedTime);
			this.setLatLng(p);

        if (! noRequestAnim) {
			//console.log("New animated position : " + p);

			this._animId = L.Util.requestAnimFrame(this._animate, this, false);
            this._animRequested = true;

        }
        if(this._pauseRequested){
            L.Util.cancelAnimFrame(this._animId);
            //this._currentAngle = (this._currentAngle);
        }
		if (L.DomUtil.TRANSFORM) {
      // use the CSS transform rule if available
			this._icon.style[L.DomUtil.TRANSFORM] += ' rotate(' + this.angle + 'deg)';
    }

	this.angle = this._currentAngle; // newly coded
	//console.log(this._currentAngle);
	//console.log(this.options.angle);

    },

    onAdd: function (map) {
        L.Marker.prototype.onAdd.call(this, map);

        if (this.options.autostart && (! this.isStarted())) {
            this.start();
            return;
        }

        if (this.isRunning()) {
            this._resumeAnimation();
        }
    },

    onRemove: function(map) {
        L.Marker.prototype.onRemove.call(this, map);
        this._stopAnimation();
    },

    pause: function() {
        if (! this.isRunning()) {
            return;
        }
		//this._currentAngle = (this._currentAngle);
		this._pauseRequested = true;
		console.log('paused');
        this._pauseStartTime = Date.now();
        this._state = L.Marker.MovingMarker.pausedState;
        this._stopAnimation();
        //force animation to place the marker at the right place
        this._animate(this._startTimeStamp
            + (this._pauseStartTime - this._startTime), true);
    },

    stop: function(elapsedTime) {
        if (this.isEnded()) {
            return;
        }
		//
        this._stopAnimation();

        if (typeof(elapsedTime) === 'undefined') {
            //user call
            elapsedTime = 0;
            // force animation to place the marker at the right place
            this._animate(this._startTimeStamp
                + (Date.now() - this._startTime), true);
        }
        //this._state = L.Marker.MovingMarker.pausedState;
        this._state = L.Marker.MovingMarker.endedState;
        this.fire('end', {elapsedTime: elapsedTime});
    }

});

L.Marker.movingMarker = function (latlngs, duration,angle, options) {
    return new L.Marker.MovingMarker(latlngs, duration,angle,options);

	};

<commit_msg>Delete moving_marker_with_rotation.js<commit_after><|endoftext|>


<commit_before>Blend.defineClass('Blend.layout.container.Box', {
    extend: 'Blend.layout.container.Layout',
    requires: [
        'Blend.layout.utils.Box'
    ],
    align: 'start',
    pack: 'start',
    margin: 0,
    layoutContext: null,
    direction: null,
    handler: null,
    performLayout: function (force) {
        var me = this, ctx;
        force = force || false;
        if (force) {
            me.layoutContext = null;
        }
        ctx = me.getItemLayoutContexts();
        me.createLayoutContext();
        me.handler(me.containerEl, me.getElements(), ctx, me.layoutContext);
    },
    createLayoutContext: function () {
        var me = this;
        if (!me.layoutContext) {
            me.layoutContext = {
                pack: me.pack,
                align: me.align,
                margin: me.margin,
                direction: me.direction,
                bounds: Blend.Element.getBounds(me.containerEl),
                maxFlex: me._maxFlex
            };
        }
    },
    getItemLayoutContexts: function () {
        var me = this, ctx = [];
        me._maxFlex = 0;
        Blend.foreach(me.view.items, function (view) {
            if (view.flex) {
                me._maxFlex++;
            }
            ctx.push(view.getLayoutContext());
        });
        return ctx;
    }
});<commit_msg>Updated to layout its child views<commit_after>Blend.defineClass('Blend.layout.container.Box', {
    extend: 'Blend.layout.container.Layout',
    requires: [
        'Blend.layout.utils.Box'
    ],
    align: 'start',
    pack: 'start',
    margin: 0,
    layoutContext: null,
    direction: null,
    handler: null,
    performLayout: function (force) {
        var me = this, ctx;
        force = force || false;
        if (force) {
            me.layoutContext = null;
        }
        ctx = me.getItemLayoutContexts();
        me.createLayoutContext();
        me.handler(me.containerEl, me.getElements(), ctx, me.layoutContext);
        me.callParent.apply(me, arguments);
    },
    createLayoutContext: function () {
        var me = this;
        if (!me.layoutContext) {
            me.layoutContext = {
                pack: me.pack,
                align: me.align,
                margin: me.margin,
                direction: me.direction,
                bounds: Blend.Element.getBounds(me.containerEl),
                maxFlex: me._maxFlex
            };
        }
    },
    getItemLayoutContexts: function () {
        var me = this, ctx = [];
        me._maxFlex = 0;
        Blend.foreach(me.view.items, function (view) {
            if (view.flex) {
                me._maxFlex++;
            }
            ctx.push(view.getLayoutContext());
        });
        return ctx;
    }
});<|endoftext|>


<commit_before><commit_msg>Update draft.js<commit_after><|endoftext|>


<commit_before>angular.module(PKG.name + '.feature.etlapps')
  .config(function($stateProvider, $urlRouterProvider, MYAUTH_ROLE) {
    $stateProvider
      .state('etlapps', {
        url: '/etlapps',
        abstract: true,
        parent: 'apps',
        data: {
          authorizedRoles: MYAUTH_ROLE.all,
          highlightTab: 'development'
        },
        template: '<ui-view/>'
      })

        .state('etlapps.list', {
          url: '',
          templateUrl: '/assets/features/etlapps/templates/list.html'
        })

        .state('etlapps.list.create', {
          url: '/create',
          onEnter: function($bootstrapModal, $state) {
            $bootstrapModal.open({
              templateUrl: '/assets/features/etlapps/templates/create.html',
              size: 'lg',
              backdrop: true,
              keyboard: true,
              controller: 'ETLAppsCreateController'
            }).result.finally(function() {
              $state.go('etlapps.list');
            });
          }
        })

        .state('etlapps.detail', {
          url: '',
          template: '
 EtlApps detail
'
        })

  });
<commit_msg>Fixes routes for etl-apps feature for create/detail/list states<commit_after>angular.module(PKG.name + '.feature.etlapps')
  .config(function($stateProvider, $urlRouterProvider, MYAUTH_ROLE) {
    $stateProvider
      .state('etlapps', {
        url: '/etlapps',
        abstract: true,
        parent: 'apps',
        data: {
          authorizedRoles: MYAUTH_ROLE.all,
          highlightTab: 'development'
        },
        template: '<ui-view/>'
      })

        .state('etlapps.list', {
          url: '',
          templateUrl: '/assets/features/etlapps/templates/list.html',
          controller: 'EtlAppsListController'
        })

        .state('etlapps.create', {
          url: '/create',
          templateUrl: '/assets/features/etlapps/templates/create.html',
          controller: 'ETLAppsCreateController'
        })

        .state('etlapps.detail', {
          url: '/:etlappid',
          template: '
 EtlApps detail
'
        })

  });
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports) {
    "use strict";

    var Promise = require("bluebird"),
        _ = require("lodash");

    var descriptor = require("adapter/ps/descriptor"),
        ps = require("adapter/ps"),
        documentLib = require("adapter/lib/document"),
        historyLib = require("adapter/lib/history"),
        layerActions = require("./layers"),
        toolActions = require("./tools"),
        documentActions = require("./documents");

    var events = require("js/events"),
        locks = require("js/locks"),
        synchronization = require("js/util/synchronization"),
        log = require("js/util/log");

    /**
     * Photoshop command ID for "undo"
     * @type {number}
     * @const
     */
    var UNDO_NATIVE_MENU_COMMMAND_ID = 101;

    /**
     * Query the current history state for the current document
     *
     * @param {number} documentID document for which to query history
     * @param {boolean=} quiet If true, this will not dispatch a history event
     * @return {Promise}
     */
    var queryCurrentHistory = function (documentID, quiet) {
        return descriptor.get("historyState")
            .bind(this)
            .then(function (historyState) {
                var payload = {
                    source: "query",
                    documentID: documentID,
                    id: historyState.ID,
                    name: historyState.name,
                    totalStates: historyState.count,
                    currentState: historyState.itemIndex - 1 // convert to zero based index
                };

                if (!quiet) {
                    this.dispatch(events.history.PS_HISTORY_EVENT, payload);
                }
                return Promise.resolve(payload);
            });
    };
    queryCurrentHistory.reads = [locks.PS_DOC];
    queryCurrentHistory.writes = [locks.JS_HISTORY];
    queryCurrentHistory.modal = true;

    /**
     * Helper function to load a state from history store based on a count offset
     * and then to fix it up with the latest selection state, visibility state, and
     * then reset border policies
     *
     * @private
     * @param {number} documentID
     * @param {number} count
     * @return {Promise}
     */
    var _loadHistory = function (documentID, count) {
        return descriptor.getProperty(documentLib.referenceBy.id(documentID), "targetLayers")
            .bind(this)
            .catch(function () {
                // no targetLayers property means no document is open
                return [];
            })
            .then(function (targetLayers) {
                var selectedIndices = _.pluck(targetLayers, "_index");
                return this.dispatchAsync(events.history.LOAD_HISTORY_STATE, {
                    documentID: documentID,
                    count: count,
                    selectedIndices: selectedIndices
                });
            })
            .then(function () {
                var currentDocument = this.flux.store("application").getCurrentDocument(),
                    borderPromise = this.transfer(toolActions.resetBorderPolicies),
                    visibilityPromise = this.transfer(layerActions.resetLayerVisibility, currentDocument);

                return Promise.join(borderPromise, visibilityPromise);
            });
    };

    /**
     * Go forward or backward in the history state by playing the appropriate photoshop action
     * and either loading a state from the history store's cache, or calling updateDocument
     *
     * @private
     * @param {number} documentID
     * @param {number} count increment history state by this number, should be either 1 or -1
     * @return {Promise}
     */
    var _navigateHistory = function (documentID, count) {
        if (documentID === undefined) {
            documentID = this.flux.store("application").getCurrentDocumentID();
        }

        if (!documentID) {
            throw new Error("History changed without an open document");
        }

        var historyStore = this.flux.store("history"),
            historyPlayObject,
            hasNextState,
            hasNextStateCached;

        if (count === 1) {
            hasNextState = historyStore.hasNextState(documentID);
            hasNextStateCached = historyStore.hasNextStateCached(documentID);
            historyPlayObject = historyLib.stepForward;
        } else if (count === -1) {
            hasNextState = historyStore.hasPreviousState(documentID);
            hasNextStateCached = historyStore.hasPreviousStateCached(documentID);
            historyPlayObject = historyLib.stepBackward;
        } else {
            throw new Error("Count must be 1 or -1");
        }

        if (!hasNextState) {
            return Promise.resolve();
        }

        if (hasNextStateCached) {
            // play the undo/redo in photoshop, then fetch the current selection,
            // then load history state model from cache
            // It is desirable to pass the selectedIndices in the payload so that there is no "flash"
            // of the cached selection state, which occurs if we just pass control to updateSelection action
            return descriptor.playObject(historyPlayObject)
                .bind(this)
                .then(function () {
                    return _loadHistory.call(this, documentID, count);
                });
        } else {
            // If cached state is not available, we must wait for photoshop undo/redo to be complete
            // before calling history.incr/decr, and finally updateDocument
            log.debug("HISTORY CACHE MISS");
            return descriptor.playObject(historyPlayObject)
                .bind(this)
                .then(function () {
                    return this.dispatchAsync(events.history.ADJUST_HISTORY_STATE, {
                            documentID: documentID,
                            count: count });
                })
                .then(function () {
                    return this.transfer(documentActions.updateDocument);
                });
        }
    };

    /**
     * Navigate to the next (future) history state
     *
     * @param {number} documentID
     * @return {Promise}
     */
    var incrementHistory = function (documentID) {
        var modal = this.flux.store("tool").getModalToolState();

        if (modal) {
            // For now, don't support "redo" in modal text state
            // Currently we are not disabling this menu action correctly, so this is for safety
            return Promise.resolve();
        } else {
            return _navigateHistory.call(this, documentID, 1);
        }
    };
    incrementHistory.reads = [locks.JS_DOC, locks.JS_APP];
    incrementHistory.writes = [locks.JS_HISTORY, locks.JS_DOC, locks.PS_DOC];
    incrementHistory.transfers = [toolActions.resetBorderPolicies, "layers.resetLayerVisibility",
        "documents.updateDocument"];
    incrementHistory.modal = true;

    /**
     * Navigate to the previous history state
     * If we're in a modal text edit state, play the native UNDO command.
     * Otherwise use the history store
     *
     * @param {number} documentID
     * @return {Promise}
     */
    var decrementHistory = function (documentID) {
        var modal = this.flux.store("tool").getModalToolState();

        if (modal) {
            var payload = {
                commandId: UNDO_NATIVE_MENU_COMMMAND_ID,
                waitForCompletion: true
            };
            return ps.performMenuCommand(payload);
        } else {
            return _navigateHistory.call(this, documentID, -1);
        }
    };
    decrementHistory.reads = [locks.JS_DOC, locks.JS_APP];
    decrementHistory.writes = [locks.JS_HISTORY, locks.JS_DOC, locks.PS_DOC];
    decrementHistory.transfers = [toolActions.resetBorderPolicies, "layers.resetLayerVisibility",
        "documents.updateDocument"];
    decrementHistory.modal = true;

    /**
     * Revert to the document's last saved state.
     *
     * @return {Promise}
     */
    var revertCurrentDocument = function () {
        var historyStore = this.flux.store("history"),
            currentDocumentID = this.flux.store("application").getCurrentDocumentID(),
            clearOverlaysPromise = this.dispatchAsync(events.ui.TOGGLE_OVERLAYS, { enabled: false }),
            nextStateIndex = historyStore.lastSavedStateIndex(currentDocumentID),
            superPromise;

        if (nextStateIndex) {
            // use cached document, revert Ps in parallel
            superPromise = Promise.join(
                descriptor.playObject(historyLib.revert),
                this.dispatchAsync(events.history.LOAD_HISTORY_STATE_REVERT, { documentID: currentDocumentID }));
        } else {
            // If cached state is not available, we must wait for photoshop revert to complete
            // before adjusting history state, and finally updateDocument
            log.debug("HISTORY CACHE MISS - REVERT");
            superPromise = descriptor.playObject(historyLib.revert)
                .bind(this)
                .then(function () {
                    return this.dispatchAsync(events.history.DELETE_DOCUMENT_HISTORY,
                        { documentID: currentDocumentID });
                })
                .then(function () {
                    return this.transfer(documentActions.updateDocument);
                });
        }

        // Clear the overlays in parallel with the revert, and then re-enabled them when both complete
        return Promise.join(clearOverlaysPromise, superPromise)
            .bind(this)
            .then(function () {
                return this.dispatchAsync(events.ui.TOGGLE_OVERLAYS, { enabled: true });
            })
            .then(function () {
                return this.transfer(toolActions.resetBorderPolicies);
            });
    };
    revertCurrentDocument.reads = [locks.JS_APP];
    revertCurrentDocument.writes = [locks.JS_HISTORY, locks.JS_DOC, locks.PS_DOC, locks.JS_UI];
    revertCurrentDocument.transfers = ["documents.updateDocument", toolActions.resetBorderPolicies];
    revertCurrentDocument.post = [layerActions._verifyLayerIndex];
    revertCurrentDocument.modal = true;

    /**
     * Given a history state event from photoshop, dispatch a flux event for the history store
     *
     * @param {object} event a raw historyState event from photoshop
     * @return {Promise}
     */
    var handleHistoryState = function (event) {
        // This assumption of current document could be problematic
        // but would require a core change to include document ID
        var documentID = this.flux.store("application").getCurrentDocumentID();

        // Ignore if either there is no current document,
        // or if this history state is related to another document
        if (documentID === null || documentID !== event.documentID) {
            log.debug("Ignoring this historyState event, probably because it was for a non-current document");
            return Promise.resolve();
        }

        var payload = {
            source: "listener", // for human convenience
            documentID: documentID,
            id: event.ID,
            name: event.name,
            totalStates: event.historyStates + 1, // yes, seriously.
            currentState: event.currentHistoryState // seems to be zero-base already (unlike get historyState)
        };
        return this.dispatchAsync(events.history.PS_HISTORY_EVENT, payload);
    };
    handleHistoryState.reads = [locks.JS_DOC, locks.JS_APP];
    handleHistoryState.writes = [locks.JS_HISTORY];
    handleHistoryState.modal = true;

    /**
     * Given a history state event from photoshop that comes directly after a "select" event,
     * Interpret this event as cause to nuke history and update doc.  Ideally, we would be
     * able to intelligently step back through cached states, but because photoshop might emit these faster than
     * we can keep up with, things like "reset layer visibility" based on our intermediate cached states might fail
     *
     * @return {Promise}
     */
    var handleHistoryStateAfterSelect = function () {
        // This assumption of current document could be problematic
        // but would require a core change to include document ID
        var documentID = this.flux.store("application").getCurrentDocumentID();

        if (documentID === null) {
            return Promise.resolve();
        }

        return this.dispatchAsync(events.history.DELETE_DOCUMENT_HISTORY, { documentID: documentID })
            .then(function () {
                return this.transfer(documentActions.updateDocument);
            });
    };
    handleHistoryStateAfterSelect.reads = [locks.JS_DOC];
    handleHistoryStateAfterSelect.writes = [];
    handleHistoryStateAfterSelect.transfers = ["documents.updateDocument"];

    /**
     * Event handlers initialized in beforeStartup.
     *
     * @private
     * @type {function()}
     */
    var _historyStateHandler,
        _historySelectHandler;

    /**
     * String value of the most recent "select" event from photoshop.  Null if the event "expired"
     * @type {?string}
     */
    var _recentSelectEvent,
        _recentSelectTimer;

    /**
     * Register event listeners for step back/forward commands
     * @return {Promise}
     */
    var beforeStartup = function () {
        var debouncedHandleHistoryStateAfterSelect =
            synchronization.debounce(this.flux.actions.history.handleHistoryStateAfterSelect, this, 200);

        // We get these every time there is a new history state being created
        _historyStateHandler = function (event) {
            log.debug("History state event from photoshop (raw): currentState (index) %d, total states: %d",
                 event.currentHistoryState, event.historyStates);

            if (_recentSelectTimer) {
                // If a "select" event (undo/redo) was recently received, handle this event specially.
                // This will validate the event and attempt to incr/decr history
                window.clearTimeout(_recentSelectTimer);
                log.debug("History state event received, and there was a recent history select event: %s",
                    _recentSelectEvent);

                debouncedHandleHistoryStateAfterSelect();
                _recentSelectTimer = null;
                _recentSelectEvent = null;
            } else {
                // Handle this historyState event conventionally
                this.flux.actions.history.handleHistoryState(event);
            }
        }.bind(this);
        descriptor.addListener("historyState", _historyStateHandler);

        // We get these every time there is a "select" event of type historyState
        // This indicates an out of band undo/redo event that we try to handle
        _historySelectHandler = function (event) {
            var eventData = event["null"];
            if (eventData && eventData._ref === "historyState" && eventData._value) {
                log.debug("History SELECT event from photoshop _value: %s", eventData._value);

                _recentSelectEvent = eventData._value;
                _recentSelectTimer = window.setTimeout(function () {
                    // If we don't get a timely follow-up historyState event, then just handle it anyway
                    debouncedHandleHistoryStateAfterSelect();
                    _recentSelectEvent = null;
                    _recentSelectTimer = null;
                }, 700);
            }
        }.bind(this);
        descriptor.addListener("select", _historySelectHandler);

        return Promise.resolve();
    };
    beforeStartup.reads = [];
    beforeStartup.writes = [];

    /** @ignore */
    var onReset = function () {
        descriptor.removeListener("historyState", _historyStateHandler);
        descriptor.removeListener("select", _historySelectHandler);
        _recentSelectEvent = null;
        _recentSelectTimer = null;

        return Promise.resolve();
    };
    onReset.reads = [];
    onReset.writes = [];

    exports.queryCurrentHistory = queryCurrentHistory;
    exports.incrementHistory = incrementHistory;
    exports.decrementHistory = decrementHistory;
    exports.revertCurrentDocument = revertCurrentDocument;
    exports.handleHistoryState = handleHistoryState;
    exports.handleHistoryStateAfterSelect = handleHistoryStateAfterSelect;
    exports.beforeStartup = beforeStartup;
    exports.onReset = onReset;
});
<commit_msg>Remove capture of ID from historyState<commit_after>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports) {
    "use strict";

    var Promise = require("bluebird"),
        _ = require("lodash");

    var descriptor = require("adapter/ps/descriptor"),
        ps = require("adapter/ps"),
        documentLib = require("adapter/lib/document"),
        historyLib = require("adapter/lib/history"),
        layerActions = require("./layers"),
        toolActions = require("./tools"),
        documentActions = require("./documents");

    var events = require("js/events"),
        locks = require("js/locks"),
        synchronization = require("js/util/synchronization"),
        log = require("js/util/log");

    /**
     * Photoshop command ID for "undo"
     * @type {number}
     * @const
     */
    var UNDO_NATIVE_MENU_COMMMAND_ID = 101;

    /**
     * Query the current history state for the current document
     *
     * @param {number} documentID document for which to query history
     * @param {boolean=} quiet If true, this will not dispatch a history event
     * @return {Promise}
     */
    var queryCurrentHistory = function (documentID, quiet) {
        return descriptor.get("historyState")
            .bind(this)
            .then(function (historyState) {
                var payload = {
                    source: "query",
                    documentID: documentID,
                    id: historyState.ID,
                    name: historyState.name,
                    totalStates: historyState.count,
                    currentState: historyState.itemIndex - 1 // convert to zero based index
                };

                if (!quiet) {
                    this.dispatch(events.history.PS_HISTORY_EVENT, payload);
                }
                return Promise.resolve(payload);
            });
    };
    queryCurrentHistory.reads = [locks.PS_DOC];
    queryCurrentHistory.writes = [locks.JS_HISTORY];
    queryCurrentHistory.modal = true;

    /**
     * Helper function to load a state from history store based on a count offset
     * and then to fix it up with the latest selection state, visibility state, and
     * then reset border policies
     *
     * @private
     * @param {number} documentID
     * @param {number} count
     * @return {Promise}
     */
    var _loadHistory = function (documentID, count) {
        return descriptor.getProperty(documentLib.referenceBy.id(documentID), "targetLayers")
            .bind(this)
            .catch(function () {
                // no targetLayers property means no document is open
                return [];
            })
            .then(function (targetLayers) {
                var selectedIndices = _.pluck(targetLayers, "_index");
                return this.dispatchAsync(events.history.LOAD_HISTORY_STATE, {
                    documentID: documentID,
                    count: count,
                    selectedIndices: selectedIndices
                });
            })
            .then(function () {
                var currentDocument = this.flux.store("application").getCurrentDocument(),
                    borderPromise = this.transfer(toolActions.resetBorderPolicies),
                    visibilityPromise = this.transfer(layerActions.resetLayerVisibility, currentDocument);

                return Promise.join(borderPromise, visibilityPromise);
            });
    };

    /**
     * Go forward or backward in the history state by playing the appropriate photoshop action
     * and either loading a state from the history store's cache, or calling updateDocument
     *
     * @private
     * @param {number} documentID
     * @param {number} count increment history state by this number, should be either 1 or -1
     * @return {Promise}
     */
    var _navigateHistory = function (documentID, count) {
        if (documentID === undefined) {
            documentID = this.flux.store("application").getCurrentDocumentID();
        }

        if (!documentID) {
            throw new Error("History changed without an open document");
        }

        var historyStore = this.flux.store("history"),
            historyPlayObject,
            hasNextState,
            hasNextStateCached;

        if (count === 1) {
            hasNextState = historyStore.hasNextState(documentID);
            hasNextStateCached = historyStore.hasNextStateCached(documentID);
            historyPlayObject = historyLib.stepForward;
        } else if (count === -1) {
            hasNextState = historyStore.hasPreviousState(documentID);
            hasNextStateCached = historyStore.hasPreviousStateCached(documentID);
            historyPlayObject = historyLib.stepBackward;
        } else {
            throw new Error("Count must be 1 or -1");
        }

        if (!hasNextState) {
            return Promise.resolve();
        }

        if (hasNextStateCached) {
            // play the undo/redo in photoshop, then fetch the current selection,
            // then load history state model from cache
            // It is desirable to pass the selectedIndices in the payload so that there is no "flash"
            // of the cached selection state, which occurs if we just pass control to updateSelection action
            return descriptor.playObject(historyPlayObject)
                .bind(this)
                .then(function () {
                    return _loadHistory.call(this, documentID, count);
                });
        } else {
            // If cached state is not available, we must wait for photoshop undo/redo to be complete
            // before calling history.incr/decr, and finally updateDocument
            log.debug("HISTORY CACHE MISS");
            return descriptor.playObject(historyPlayObject)
                .bind(this)
                .then(function () {
                    return this.dispatchAsync(events.history.ADJUST_HISTORY_STATE, {
                            documentID: documentID,
                            count: count });
                })
                .then(function () {
                    return this.transfer(documentActions.updateDocument);
                });
        }
    };

    /**
     * Navigate to the next (future) history state
     *
     * @param {number} documentID
     * @return {Promise}
     */
    var incrementHistory = function (documentID) {
        var modal = this.flux.store("tool").getModalToolState();

        if (modal) {
            // For now, don't support "redo" in modal text state
            // Currently we are not disabling this menu action correctly, so this is for safety
            return Promise.resolve();
        } else {
            return _navigateHistory.call(this, documentID, 1);
        }
    };
    incrementHistory.reads = [locks.JS_DOC, locks.JS_APP];
    incrementHistory.writes = [locks.JS_HISTORY, locks.JS_DOC, locks.PS_DOC];
    incrementHistory.transfers = [toolActions.resetBorderPolicies, "layers.resetLayerVisibility",
        "documents.updateDocument"];
    incrementHistory.modal = true;

    /**
     * Navigate to the previous history state
     * If we're in a modal text edit state, play the native UNDO command.
     * Otherwise use the history store
     *
     * @param {number} documentID
     * @return {Promise}
     */
    var decrementHistory = function (documentID) {
        var modal = this.flux.store("tool").getModalToolState();

        if (modal) {
            var payload = {
                commandId: UNDO_NATIVE_MENU_COMMMAND_ID,
                waitForCompletion: true
            };
            return ps.performMenuCommand(payload);
        } else {
            return _navigateHistory.call(this, documentID, -1);
        }
    };
    decrementHistory.reads = [locks.JS_DOC, locks.JS_APP];
    decrementHistory.writes = [locks.JS_HISTORY, locks.JS_DOC, locks.PS_DOC];
    decrementHistory.transfers = [toolActions.resetBorderPolicies, "layers.resetLayerVisibility",
        "documents.updateDocument"];
    decrementHistory.modal = true;

    /**
     * Revert to the document's last saved state.
     *
     * @return {Promise}
     */
    var revertCurrentDocument = function () {
        var historyStore = this.flux.store("history"),
            currentDocumentID = this.flux.store("application").getCurrentDocumentID(),
            clearOverlaysPromise = this.dispatchAsync(events.ui.TOGGLE_OVERLAYS, { enabled: false }),
            nextStateIndex = historyStore.lastSavedStateIndex(currentDocumentID),
            superPromise;

        if (nextStateIndex) {
            // use cached document, revert Ps in parallel
            superPromise = Promise.join(
                descriptor.playObject(historyLib.revert),
                this.dispatchAsync(events.history.LOAD_HISTORY_STATE_REVERT, { documentID: currentDocumentID }));
        } else {
            // If cached state is not available, we must wait for photoshop revert to complete
            // before adjusting history state, and finally updateDocument
            log.debug("HISTORY CACHE MISS - REVERT");
            superPromise = descriptor.playObject(historyLib.revert)
                .bind(this)
                .then(function () {
                    return this.dispatchAsync(events.history.DELETE_DOCUMENT_HISTORY,
                        { documentID: currentDocumentID });
                })
                .then(function () {
                    return this.transfer(documentActions.updateDocument);
                });
        }

        // Clear the overlays in parallel with the revert, and then re-enabled them when both complete
        return Promise.join(clearOverlaysPromise, superPromise)
            .bind(this)
            .then(function () {
                return this.dispatchAsync(events.ui.TOGGLE_OVERLAYS, { enabled: true });
            })
            .then(function () {
                return this.transfer(toolActions.resetBorderPolicies);
            });
    };
    revertCurrentDocument.reads = [locks.JS_APP];
    revertCurrentDocument.writes = [locks.JS_HISTORY, locks.JS_DOC, locks.PS_DOC, locks.JS_UI];
    revertCurrentDocument.transfers = ["documents.updateDocument", toolActions.resetBorderPolicies];
    revertCurrentDocument.post = [layerActions._verifyLayerIndex];
    revertCurrentDocument.modal = true;

    /**
     * Given a history state event from photoshop, dispatch a flux event for the history store
     *
     * @param {object} event a raw historyState event from photoshop
     * @return {Promise}
     */
    var handleHistoryState = function (event) {
        // This assumption of current document could be problematic
        // but would require a core change to include document ID
        var documentID = this.flux.store("application").getCurrentDocumentID();

        // Ignore if either there is no current document,
        // or if this history state is related to another document
        if (documentID === null || documentID !== event.documentID) {
            log.debug("Ignoring this historyState event, probably because it was for a non-current document");
            return Promise.resolve();
        }

        var payload = {
            source: "listener", // for human convenience
            documentID: documentID,
            name: event.name,
            totalStates: event.historyStates + 1, // yes, seriously.
            currentState: event.currentHistoryState // seems to be zero-base already (unlike get historyState)
        };
        return this.dispatchAsync(events.history.PS_HISTORY_EVENT, payload);
    };
    handleHistoryState.reads = [locks.JS_DOC, locks.JS_APP];
    handleHistoryState.writes = [locks.JS_HISTORY];
    handleHistoryState.modal = true;

    /**
     * Given a history state event from photoshop that comes directly after a "select" event,
     * Interpret this event as cause to nuke history and update doc.  Ideally, we would be
     * able to intelligently step back through cached states, but because photoshop might emit these faster than
     * we can keep up with, things like "reset layer visibility" based on our intermediate cached states might fail
     *
     * @return {Promise}
     */
    var handleHistoryStateAfterSelect = function () {
        // This assumption of current document could be problematic
        // but would require a core change to include document ID
        var documentID = this.flux.store("application").getCurrentDocumentID();

        if (documentID === null) {
            return Promise.resolve();
        }

        return this.dispatchAsync(events.history.DELETE_DOCUMENT_HISTORY, { documentID: documentID })
            .then(function () {
                return this.transfer(documentActions.updateDocument);
            });
    };
    handleHistoryStateAfterSelect.reads = [locks.JS_DOC];
    handleHistoryStateAfterSelect.writes = [];
    handleHistoryStateAfterSelect.transfers = ["documents.updateDocument"];

    /**
     * Event handlers initialized in beforeStartup.
     *
     * @private
     * @type {function()}
     */
    var _historyStateHandler,
        _historySelectHandler;

    /**
     * String value of the most recent "select" event from photoshop.  Null if the event "expired"
     * @type {?string}
     */
    var _recentSelectEvent,
        _recentSelectTimer;

    /**
     * Register event listeners for step back/forward commands
     * @return {Promise}
     */
    var beforeStartup = function () {
        var debouncedHandleHistoryStateAfterSelect =
            synchronization.debounce(this.flux.actions.history.handleHistoryStateAfterSelect, this, 200);

        // We get these every time there is a new history state being created
        _historyStateHandler = function (event) {
            log.debug("History state event from photoshop (raw): currentState (index) %d, total states: %d",
                 event.currentHistoryState, event.historyStates);

            if (_recentSelectTimer) {
                // If a "select" event (undo/redo) was recently received, handle this event specially.
                // This will validate the event and attempt to incr/decr history
                window.clearTimeout(_recentSelectTimer);
                log.debug("History state event received, and there was a recent history select event: %s",
                    _recentSelectEvent);

                debouncedHandleHistoryStateAfterSelect();
                _recentSelectTimer = null;
                _recentSelectEvent = null;
            } else {
                // Handle this historyState event conventionally
                this.flux.actions.history.handleHistoryState(event);
            }
        }.bind(this);
        descriptor.addListener("historyState", _historyStateHandler);

        // We get these every time there is a "select" event of type historyState
        // This indicates an out of band undo/redo event that we try to handle
        _historySelectHandler = function (event) {
            var eventData = event["null"];
            if (eventData && eventData._ref === "historyState" && eventData._value) {
                log.debug("History SELECT event from photoshop _value: %s", eventData._value);

                _recentSelectEvent = eventData._value;
                _recentSelectTimer = window.setTimeout(function () {
                    // If we don't get a timely follow-up historyState event, then just handle it anyway
                    debouncedHandleHistoryStateAfterSelect();
                    _recentSelectEvent = null;
                    _recentSelectTimer = null;
                }, 700);
            }
        }.bind(this);
        descriptor.addListener("select", _historySelectHandler);

        return Promise.resolve();
    };
    beforeStartup.reads = [];
    beforeStartup.writes = [];

    /** @ignore */
    var onReset = function () {
        descriptor.removeListener("historyState", _historyStateHandler);
        descriptor.removeListener("select", _historySelectHandler);
        _recentSelectEvent = null;
        _recentSelectTimer = null;

        return Promise.resolve();
    };
    onReset.reads = [];
    onReset.writes = [];

    exports.queryCurrentHistory = queryCurrentHistory;
    exports.incrementHistory = incrementHistory;
    exports.decrementHistory = decrementHistory;
    exports.revertCurrentDocument = revertCurrentDocument;
    exports.handleHistoryState = handleHistoryState;
    exports.handleHistoryStateAfterSelect = handleHistoryStateAfterSelect;
    exports.beforeStartup = beforeStartup;
    exports.onReset = onReset;
});
<|endoftext|>


<commit_before>var FullScreenController = (function (document) {
    "use strict";

    function FullScreenController(screen) {
        this.screen = screen;

        this.isSupported = document.fullscreenEnabled || document.webkitFullscreenEnabled ||
        document.mozFullScreenEnabled || document.msFullscreenEnabled;
    }

    FullScreenController.prototype.request = function () {
        if (this.screen.requestFullscreen) {
            this.screen.requestFullscreen();
        } else if (this.screen.webkitRequestFullscreen) {
            this.screen.webkitRequestFullscreen();
        } else if (this.screen.mozRequestFullScreen) {
            this.screen.mozRequestFullScreen();
        } else if (this.screen.msRequestFullscreen) {
            this.screen.msRequestFullscreen();
        }
        return this.isFullScreen();
    };

    FullScreenController.prototype.isFullScreen = function () {
        return (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement ||
            document.msFullscreenElement) != null;
    };

    FullScreenController.prototype.isSupported = function () {
        return this.isSupported;
    };

    FullScreenController.prototype.exit = function () {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        }

        return !this.isFullScreen();
    };

    document.addEventListener("fullscreenchange", fullScreenDebugHandler);
    document.addEventListener("webkitfullscreenchange", fullScreenDebugHandler);
    document.addEventListener("mozfullscreenchange", fullScreenDebugHandler);
    document.addEventListener("MSFullscreenChange", fullScreenDebugHandler);
    document.addEventListener('MSFullscreenError', fullScreenDebugHandler);

    function fullScreenDebugHandler(event) {
        console.log(event.target);
        console.log('full screen event fired');
        var isFs = (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement ||
            document.msFullscreenElement) != null;
        console.log('is full screen: ' + isFs);
    }

    return FullScreenController;
})(window.document);<commit_msg>removing debug stuff refs #35 - handle orientation #core (cherry picked from commit 282adc1)<commit_after>var FullScreenController = (function (document) {
    "use strict";

    function FullScreenController(screen) {
        this.screen = screen;

        this.isSupported = document.fullscreenEnabled || document.webkitFullscreenEnabled ||
        document.mozFullScreenEnabled || document.msFullscreenEnabled;
    }

    FullScreenController.prototype.request = function () {
        if (this.screen.requestFullscreen) {
            this.screen.requestFullscreen();
        } else if (this.screen.webkitRequestFullscreen) {
            this.screen.webkitRequestFullscreen();
        } else if (this.screen.mozRequestFullScreen) {
            this.screen.mozRequestFullScreen();
        } else if (this.screen.msRequestFullscreen) {
            this.screen.msRequestFullscreen();
        }
        return this.isFullScreen();
    };

    FullScreenController.prototype.isFullScreen = function () {
        return (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement ||
            document.msFullscreenElement) != null;
    };

    FullScreenController.prototype.isSupported = function () {
        return this.isSupported;
    };

    FullScreenController.prototype.exit = function () {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        }

        return !this.isFullScreen();
    };

    return FullScreenController;
})(window.document);<|endoftext|>


<commit_before>import { statusConstants } from 'molecular-design-applications-shared';
import WorkflowRecord from '../records/workflow_record';
import actionConstants from '../constants/action_constants';

const initialState = new WorkflowRecord();

function workflow(state = initialState, action) {
  switch (action.type) {
    case actionConstants.INITIALIZE_WORKFLOW: {
      const workflowsDifferent = action.workflowId !== state.id;
      if (workflowsDifferent) {
        return new WorkflowRecord({
          fetching: true,
          fetchingError: null,
        });
      }

      const runsDifferent = action.runId !== state.run.id;
      if (runsDifferent) {
        return state.merge({
          fetching: true,
          fetchingError: null,
        });
      }

      return state.merge({
        fetching: true,
        fetchingError: null,
      });
    }

    case actionConstants.FETCHED_WORKFLOW:
      if (action.error) {
        return state.merge({
          fetching: false,
          fetchingError: action.error,
        });
      }
      return action.workflow;

    case actionConstants.FETCHED_RUN:
      if (action.error) {
        return state.merge({
          fetching: false,
          fetchingError: action.error,
        });
      }
      return action.workflow;

    case actionConstants.CLICK_RUN:
      return state.merge({
        fetching: true,
        fetchingError: null,
      });

    case actionConstants.RUN_SUBMITTED:
      if (action.err) {
        return state.set('workflowNodes', state.workflowNodes.map(
          workflowNode => workflowNode.set('status', statusConstants.IDLE))
        );
      }

      return state;

    case actionConstants.FETCHED_INPUT_PDB: {
      if (action.err) {
        return state.set('run', state.run.merge({
          fetchingPdbError: action.err,
          fetchingPdb: false,
        }));
      }

      return state.set('run', state.run.merge({
        fetchingPdb: false,
        fetchingPdbError: null,
        inputPdb: action.modelData,
      }));
    }

    case actionConstants.FETCHED_OUTPUT_PDB: {
      if (action.err) {
        return state.set('run', state.run.merge({
          fetchingPdbError: action.err,
          fetchingPdb: false,
        }));
      }

      return state.set('run', state.run.merge({
        fetchingPdb: false,
        fetchingPdbError: null,
        outputPdb: action.modelData,
      }));
    }

    case actionConstants.INPUT_FILE:
      return state.set('run', state.run.merge({
        inputFileError: null,
        inputFilePending: true,
        inputPdbUrl: '',
        inputPdb: '',
      }));

    case actionConstants.INPUT_FILE_COMPLETE:
      return state.set('run', state.run.merge({
        inputFilePending: false,
        inputFileError: action.err,
        inputPdbUrl: action.pdbUrl,
        inputPdb: action.pdb,
      }));

    case actionConstants.SUBMIT_PDB_ID:
      return state.set('run', state.run.merge({
        fetchingPdb: true,
        fetchingPdbError: null,
        inputPdbUrl: '',
        inputPdb: '',
      }));

    case actionConstants.FETCHED_PDB_BY_ID:
      return state.set('run', state.run.merge({
        fetchingPdb: false,
        fetchingPdbError: action.error,
        inputPdbUrl: action.pdbUrl,
        inputPdb: action.pdb,
      }));

    case actionConstants.SUBMIT_EMAIL:
      return state.set('run', state.run.set('email', action.email));

    case actionConstants.CLICK_CANCEL:
      return state.set('run', state.run.set('canceling', true));

    case actionConstants.SUBMITTED_CANCEL:
      if (action.err) {
        return state.set('run', state.run.set('canceling', false));
      }
      return state.set('run', state.run.merge({
        canceling: false,
        status: statusConstants.CANCELED,
      }));

    default:
      return state;
  }
}

export default workflow;
<commit_msg>Fix tests due to mistaken edit not in this PR<commit_after>import { statusConstants } from 'molecular-design-applications-shared';
import RunRecord from '../records/run_record';
import WorkflowRecord from '../records/workflow_record';
import actionConstants from '../constants/action_constants';

const initialState = new WorkflowRecord();

function workflow(state = initialState, action) {
  switch (action.type) {
    case actionConstants.INITIALIZE_WORKFLOW: {
      const workflowsDifferent = action.workflowId !== state.id;
      if (workflowsDifferent) {
        return new WorkflowRecord({
          fetching: true,
          fetchingError: null,
        });
      }

      const runsDifferent = action.runId !== state.run.id;
      if (runsDifferent) {
        return state.merge({
          fetching: true,
          fetchingError: null,
          run: new RunRecord(),
        });
      }

      return state.merge({
        fetching: true,
        fetchingError: null,
      });
    }

    case actionConstants.FETCHED_WORKFLOW:
      if (action.error) {
        return state.merge({
          fetching: false,
          fetchingError: action.error,
        });
      }
      return action.workflow;

    case actionConstants.FETCHED_RUN:
      if (action.error) {
        return state.merge({
          fetching: false,
          fetchingError: action.error,
        });
      }
      return action.workflow;

    case actionConstants.CLICK_RUN:
      return state.merge({
        fetching: true,
        fetchingError: null,
      });

    case actionConstants.RUN_SUBMITTED:
      if (action.err) {
        return state.set('workflowNodes', state.workflowNodes.map(
          workflowNode => workflowNode.set('status', statusConstants.IDLE))
        );
      }

      return state;

    case actionConstants.FETCHED_INPUT_PDB: {
      if (action.err) {
        return state.set('run', state.run.merge({
          fetchingPdbError: action.err,
          fetchingPdb: false,
        }));
      }

      return state.set('run', state.run.merge({
        fetchingPdb: false,
        fetchingPdbError: null,
        inputPdb: action.modelData,
      }));
    }

    case actionConstants.FETCHED_OUTPUT_PDB: {
      if (action.err) {
        return state.set('run', state.run.merge({
          fetchingPdbError: action.err,
          fetchingPdb: false,
        }));
      }

      return state.set('run', state.run.merge({
        fetchingPdb: false,
        fetchingPdbError: null,
        outputPdb: action.modelData,
      }));
    }

    case actionConstants.INPUT_FILE:
      return state.set('run', state.run.merge({
        inputFileError: null,
        inputFilePending: true,
        inputPdbUrl: '',
        inputPdb: '',
      }));

    case actionConstants.INPUT_FILE_COMPLETE:
      return state.set('run', state.run.merge({
        inputFilePending: false,
        inputFileError: action.err,
        inputPdbUrl: action.pdbUrl,
        inputPdb: action.pdb,
      }));

    case actionConstants.SUBMIT_PDB_ID:
      return state.set('run', state.run.merge({
        fetchingPdb: true,
        fetchingPdbError: null,
        inputPdbUrl: '',
        inputPdb: '',
      }));

    case actionConstants.FETCHED_PDB_BY_ID:
      return state.set('run', state.run.merge({
        fetchingPdb: false,
        fetchingPdbError: action.error,
        inputPdbUrl: action.pdbUrl,
        inputPdb: action.pdb,
      }));

    case actionConstants.SUBMIT_EMAIL:
      return state.set('run', state.run.set('email', action.email));

    case actionConstants.CLICK_CANCEL:
      return state.set('run', state.run.set('canceling', true));

    case actionConstants.SUBMITTED_CANCEL:
      if (action.err) {
        return state.set('run', state.run.set('canceling', false));
      }
      return state.set('run', state.run.merge({
        canceling: false,
        status: statusConstants.CANCELED,
      }));

    default:
      return state;
  }
}

export default workflow;
<|endoftext|>


<commit_before>'use strict';
const assert = require('assert');
const CompareUI = require('../modules/compare-ui.js');
const CompareUtil = require('../modules/compare-util.js');

describe('CompareUI', () => {
    const window = { navigator: { userAgent: 'na' } };
    const compareUtil = CompareUtil(window);
    const compareUI = CompareUI({ compareUtil });

    describe('ViewModel', () => {
        describe('Registry', () => {
            describe('register', () => {
                it('should append given new entry to internal array', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { hello: 'world' };
                    assert.strictEqual(registry.getEntry(0), undefined);
                    registry.register(ent0);

                    assert.strictEqual(registry.getEntry(0), ent0);
                });
                it('should return given entry', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = {};
                    const ret = registry.register(ent0);

                    assert.strictEqual(ret, ent0);
                });
                it('should assign ascending index for each entry', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    const ent1 = { name: 'world' };
                    registry.register(ent0);
                    registry.register(ent1);

                    assert.strictEqual(ent0.index, 0);
                    assert.strictEqual(ent1.index, 1);
                });
                it('should initialize some attributes', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    registry.register(ent0);

                    assert.strictEqual(ent0.element, null);
                    assert.strictEqual(typeof(ent0.ready), 'function');
                    assert.strictEqual(ent0.ready(), false);
                });
            });
            describe('update', () => {
                it('should make active image list', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    const ent1 = { name: 'world' };
                    registry.register(ent0);
                    registry.register(ent1);
                    ent1.element = {};
                    registry.update();

                    assert.strictEqual(registry.getImages().length, 1);
                    assert.strictEqual(registry.getImages()[0], ent1);
                });
            });
            describe('removeEntry', () => {
                it('should deactivate an active image', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    registry.register(ent0);
                    ent0.visible = true; // FIXME:
                    ent0.element = {};
                    registry.update();

                    assert.strictEqual(registry.getImages().length, 1);
                    registry.removeEntry(ent0.index);
                    registry.update();

                    assert.strictEqual(registry.getImages().length, 0);
                    assert.strictEqual(ent0.element, null);
                    assert.strictEqual(ent0.visible, false);
                });
            });
            describe('empty', () => {
                it('should return true if there are no active images', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    const ent1 = { name: 'world' };
                    registry.register(ent0);
                    registry.register(ent1);

                    ent1.element = {};
                    registry.update();
                    assert.strictEqual(registry.empty(), false);

                    ent1.element = null;
                    registry.update();
                    assert.strictEqual(registry.empty(), true);
                });
            });
            // TODO: add more
        });

        describe('singleViewMode', () => {
            it('should be inactive at initial state', () => {
                const model = compareUI.ViewModel();

                assert.strictEqual(model.singleViewMode.current(), null);
                assert.strictEqual(model.singleViewMode.last(), null);
                assert.strictEqual(model.singleViewMode.isActive(), false);
            });
            describe('start', () => {
                it('should start single view mode', () => {
                    const model = compareUI.ViewModel();
                    model.singleViewMode.start(5);

                    assert.strictEqual(model.singleViewMode.current(), 5);
                    assert.strictEqual(model.singleViewMode.isActive(), true);
                });
            });
            describe('stop', () => {
                it('should stop single view mode', () => {
                    const model = compareUI.ViewModel();
                    model.singleViewMode.start(5);
                    model.singleViewMode.stop();

                    assert.strictEqual(model.singleViewMode.current(), null);
                    assert.strictEqual(model.singleViewMode.isActive(), false);
                });
            });
            describe('current', () => {
                it('should return current image index if single view mode is active', () => {
                    const model = compareUI.ViewModel();
                    const ret1 = model.singleViewMode.current();
                    model.singleViewMode.start(3);
                    const ret2 = model.singleViewMode.current();

                    assert.strictEqual(ret1, null);
                    assert.strictEqual(ret2, 3);
                });
            });
            describe('last', () => {
                it('should return image index used in the last single view mode', () => {
                    const model = compareUI.ViewModel();
                    model.singleViewMode.start(3);
                    const ret1 = model.singleViewMode.last();
                    model.singleViewMode.stop();
                    const ret2 = model.singleViewMode.last();
                    model.singleViewMode.start(2);
                    const ret3 = model.singleViewMode.last();

                    assert.strictEqual(ret1, 3);
                    assert.strictEqual(ret2, 3);
                    assert.strictEqual(ret3, 2);
                });
            });
        });

        describe('layoutDirection', () => {
            describe('current', () => {
                it('should return null at initial state', () => {
                    const model = compareUI.ViewModel();
                    assert.strictEqual(model.layoutDirection.current(), null);
                });
                it('should return current state', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.alternate();
                    assert.strictEqual(model.layoutDirection.current(), 'x');
                });
            });
            describe('reset', () => {
                it('should set null', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.alternate();
                    model.layoutDirection.reset();
                    assert.strictEqual(model.layoutDirection.current(), null);
                });
            });
            describe('alternate', () => {
                it('should set valid values in rotation', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.alternate();
                    assert.strictEqual(model.layoutDirection.current(), 'x');
                    model.layoutDirection.alternate();
                    assert.strictEqual(model.layoutDirection.current(), 'y');
                    model.layoutDirection.alternate();
                    assert.strictEqual(model.layoutDirection.current(), 'x');
                });
            });
            describe('determineByAspect', () => {
                it('should set x if viewport is landscape-oriented', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.determineByAspect(1920, 1080);
                    assert.strictEqual(model.layoutDirection.current(), 'x');
                });
                it('should set y if viewport is portrait-oriented', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.determineByAspect(1000, 1500);
                    assert.strictEqual(model.layoutDirection.current(), 'y');
                });
            });
        });
    });
});
<commit_msg>Add test<commit_after>'use strict';
const assert = require('assert');
const CompareUI = require('../modules/compare-ui.js');
const CompareUtil = require('../modules/compare-util.js');

describe('CompareUI', () => {
    const window = { navigator: { userAgent: 'na' } };
    const compareUtil = CompareUtil(window);
    const compareUI = CompareUI({ compareUtil });

    describe('ViewModel', () => {
        describe('Registry', () => {
            describe('register', () => {
                it('should append given new entry to internal array', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { hello: 'world' };
                    assert.strictEqual(registry.getEntry(0), undefined);
                    registry.register(ent0);

                    assert.strictEqual(registry.getEntry(0), ent0);
                });
                it('should return given entry', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = {};
                    const ret = registry.register(ent0);

                    assert.strictEqual(ret, ent0);
                });
                it('should assign ascending index for each entry', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    const ent1 = { name: 'world' };
                    registry.register(ent0);
                    registry.register(ent1);

                    assert.strictEqual(ent0.index, 0);
                    assert.strictEqual(ent1.index, 1);
                });
                it('should initialize some attributes', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    registry.register(ent0);

                    assert.strictEqual(ent0.element, null);
                    assert.strictEqual(typeof(ent0.ready), 'function');
                    assert.strictEqual(ent0.ready(), false);
                });
            });
            describe('update', () => {
                it('should make active image list', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    const ent1 = { name: 'world' };
                    registry.register(ent0);
                    registry.register(ent1);
                    ent1.element = {};
                    registry.update();

                    assert.strictEqual(registry.getImages().length, 1);
                    assert.strictEqual(registry.getImages()[0], ent1);
                });
            });
            describe('removeEntry', () => {
                it('should deactivate an active image', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    registry.register(ent0);
                    ent0.visible = true; // FIXME:
                    ent0.element = {};
                    registry.update();

                    assert.strictEqual(registry.getImages().length, 1);
                    registry.removeEntry(ent0.index);
                    registry.update();

                    assert.strictEqual(registry.getImages().length, 0);
                    assert.strictEqual(ent0.element, null);
                    assert.strictEqual(ent0.visible, false);
                });
                it('should call onDidRemoveEntry callback', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const log = [];
                    registry.setOnDidRemoveEntry(() => { log.push('called'); });
                    const ent0 = { name: 'hello', element: {}, visible: true };
                    registry.register(ent0);
                    registry.removeEntry(ent0.index);
                    assert.deepStrictEqual(log, ['called']);
                });
            });
            describe('empty', () => {
                it('should return true if there are no active images', () => {
                    const registry = compareUI.ViewModel().Registry();
                    const ent0 = { name: 'hello' };
                    const ent1 = { name: 'world' };
                    registry.register(ent0);
                    registry.register(ent1);

                    ent1.element = {};
                    registry.update();
                    assert.strictEqual(registry.empty(), false);

                    ent1.element = null;
                    registry.update();
                    assert.strictEqual(registry.empty(), true);
                });
            });
            // TODO: add more
        });

        describe('singleViewMode', () => {
            it('should be inactive at initial state', () => {
                const model = compareUI.ViewModel();

                assert.strictEqual(model.singleViewMode.current(), null);
                assert.strictEqual(model.singleViewMode.last(), null);
                assert.strictEqual(model.singleViewMode.isActive(), false);
            });
            describe('start', () => {
                it('should start single view mode', () => {
                    const model = compareUI.ViewModel();
                    model.singleViewMode.start(5);

                    assert.strictEqual(model.singleViewMode.current(), 5);
                    assert.strictEqual(model.singleViewMode.isActive(), true);
                });
            });
            describe('stop', () => {
                it('should stop single view mode', () => {
                    const model = compareUI.ViewModel();
                    model.singleViewMode.start(5);
                    model.singleViewMode.stop();

                    assert.strictEqual(model.singleViewMode.current(), null);
                    assert.strictEqual(model.singleViewMode.isActive(), false);
                });
            });
            describe('current', () => {
                it('should return current image index if single view mode is active', () => {
                    const model = compareUI.ViewModel();
                    const ret1 = model.singleViewMode.current();
                    model.singleViewMode.start(3);
                    const ret2 = model.singleViewMode.current();

                    assert.strictEqual(ret1, null);
                    assert.strictEqual(ret2, 3);
                });
            });
            describe('last', () => {
                it('should return image index used in the last single view mode', () => {
                    const model = compareUI.ViewModel();
                    model.singleViewMode.start(3);
                    const ret1 = model.singleViewMode.last();
                    model.singleViewMode.stop();
                    const ret2 = model.singleViewMode.last();
                    model.singleViewMode.start(2);
                    const ret3 = model.singleViewMode.last();

                    assert.strictEqual(ret1, 3);
                    assert.strictEqual(ret2, 3);
                    assert.strictEqual(ret3, 2);
                });
            });
        });

        describe('layoutDirection', () => {
            describe('current', () => {
                it('should return null at initial state', () => {
                    const model = compareUI.ViewModel();
                    assert.strictEqual(model.layoutDirection.current(), null);
                });
                it('should return current state', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.alternate();
                    assert.strictEqual(model.layoutDirection.current(), 'x');
                });
            });
            describe('reset', () => {
                it('should set null', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.alternate();
                    model.layoutDirection.reset();
                    assert.strictEqual(model.layoutDirection.current(), null);
                });
            });
            describe('alternate', () => {
                it('should set valid values in rotation', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.alternate();
                    assert.strictEqual(model.layoutDirection.current(), 'x');
                    model.layoutDirection.alternate();
                    assert.strictEqual(model.layoutDirection.current(), 'y');
                    model.layoutDirection.alternate();
                    assert.strictEqual(model.layoutDirection.current(), 'x');
                });
            });
            describe('determineByAspect', () => {
                it('should set x if viewport is landscape-oriented', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.determineByAspect(1920, 1080);
                    assert.strictEqual(model.layoutDirection.current(), 'x');
                });
                it('should set y if viewport is portrait-oriented', () => {
                    const model = compareUI.ViewModel();
                    model.layoutDirection.determineByAspect(1000, 1500);
                    assert.strictEqual(model.layoutDirection.current(), 'y');
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>/**
 * @fileoverview This module provides generic logging support. It uses
 * Apache log4j by default,
 * but can be used with any Logging framework supported by
 * SLF4J.
 */

require('core/string');

var LoggerFactory = org.slf4j.LoggerFactory;

module.shared = true;
var configured = false;

/**
 * Logger class. This constructor is not exported, use this module's
 * {@link getLogger} to get a logger instance.
 * @param name
 * @constructor
 * @name Logger
 * @see getLogger
 */
function Logger(name) {

    var log = LoggerFactory.getLogger(name.replace(/\//g, '.'));

    /**
     * Log a debug message.
     */
    this.trace = function() {
        log.trace.apply(log, arguments);
    };

    this.debug = function() {
        log.debug.apply(log, arguments);
    };

    this.info = function() {
        log.info.apply(log, arguments);
    };

    this.warn = function() {
        log.warn.apply(log, arguments);
    };

    this.error = function() {
        log.error.apply(log, arguments);
    };

    this.isTraceEnabled = function() {
        return log.isTraceEnabled();
    };

    this.isDebugEnabled = function() {
        return log.isDebugEnabled();
    };

    this.isInfoEnabled = function() {
        return log.isInfoEnabled();
    };

    this.isWarnEnabled = function() {
        return log.isWarnEnabled();
    };

    this.isErrorEnabled = function() {
        return log.isErrorEnabled();
    };
}

/**
 * Configure log4j using the given file resource.
 * Make sure to set the reset property to true in the <log4j:configuration> header
 * e.g. <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' reset="true">
 */
var setConfig = exports.setConfig = function(resource) {
    var {path, url} = resource;
    var PropertyConfigurator = org.apache.log4j.PropertyConfigurator,
        DOMConfigurator = org.apache.log4j.xml.DOMConfigurator;
    var configurator = path.endsWith('.properties') || path.endsWith('.props') ?
                       PropertyConfigurator : DOMConfigurator;
    configurator.configure(url);
    try {
        configurator.configureAndWatch(path, 2000);
    } catch (e) {
        print("Error watching log configuration file:", e);
    }
    configured = true;
};

/**
 * Get a logger for the given name.
 * @param {string} name the name of the logger
 * @returns {Logger} a logger instance for the given name
 */
var getLogger = exports.getLogger = function(name) {
    if (!configured) {
        // getResource('foo').name gets us the absolute path to a local resource
        this.setConfig(getResource('config/log4j.properties'));
    }
    return new Logger(name);
};

<commit_msg>Make sure all arguments to log methods are converted to strings<commit_after>/**
 * @fileoverview This module provides generic logging support. It uses
 * Apache log4j by default,
 * but can be used with any Logging framework supported by
 * SLF4J.
 */

require('core/string');

var LoggerFactory = org.slf4j.LoggerFactory;

module.shared = true;
var configured = false;

/**
 * Logger class. This constructor is not exported, use this module's
 * {@link getLogger} to get a logger instance.
 * @param name
 * @constructor
 * @name Logger
 * @see getLogger
 */
function Logger(name) {

    var log = LoggerFactory.getLogger(name.replace(/\//g, '.'));

    /**
     * Log a debug message.
     */
    this.trace = function() {
        log.trace.apply(log, arguments.map(String));
    };

    this.debug = function() {
        log.debug.apply(log, arguments.map(String));
    };

    this.info = function() {
        log.info.apply(log, arguments.map(String));
    };

    this.warn = function() {
        log.warn.apply(log, arguments.map(String));
    };

    this.error = function() {
        log.error.apply(log, arguments.map(String));
    };

    this.isTraceEnabled = function() {
        return log.isTraceEnabled();
    };

    this.isDebugEnabled = function() {
        return log.isDebugEnabled();
    };

    this.isInfoEnabled = function() {
        return log.isInfoEnabled();
    };

    this.isWarnEnabled = function() {
        return log.isWarnEnabled();
    };

    this.isErrorEnabled = function() {
        return log.isErrorEnabled();
    };
}

/**
 * Configure log4j using the given file resource.
 * Make sure to set the reset property to true in the <log4j:configuration> header
 * e.g. <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' reset="true">
 */
var setConfig = exports.setConfig = function(resource) {
    var {path, url} = resource;
    var PropertyConfigurator = org.apache.log4j.PropertyConfigurator,
        DOMConfigurator = org.apache.log4j.xml.DOMConfigurator;
    var configurator = path.endsWith('.properties') || path.endsWith('.props') ?
                       PropertyConfigurator : DOMConfigurator;
    configurator.configure(url);
    try {
        configurator.configureAndWatch(path, 2000);
    } catch (e) {
        print("Error watching log configuration file:", e);
    }
    configured = true;
};

/**
 * Get a logger for the given name.
 * @param {string} name the name of the logger
 * @returns {Logger} a logger instance for the given name
 */
var getLogger = exports.getLogger = function(name) {
    if (!configured) {
        // getResource('foo').name gets us the absolute path to a local resource
        this.setConfig(getResource('config/log4j.properties'));
    }
    return new Logger(name);
};

<|endoftext|>