<commit_before>import Ember from 'ember';

var initialPaginationParams = { 'page': 1, 'perPage': 15 };

var ContentListRouteMixin = Ember.Mixin.create({
  paginationParams: null,
  contentModelType: null,

  model: function() {
    var site = this.modelFor('site');
    var params = Ember.merge({ 'site': site.get('id') }, initialPaginationParams);

    this.set('paginationParams', params);

    if (this.get('contentModelType') === null) {
      Ember.assert('Content model type must be set.');
    }

    // 1. Caching resultPromise permits to avoid sending a request to server everytime we transition into this route
    // 2. Using filter() allows the template to auto-update when new models are pulled in from the server
    var resultPromise = this.get('resultPromise') || this.store.filter(this.get('contentModelType'), params, function () {
      // nothing to filter
      return true;
    });

    this.set('resultPromise', resultPromise);

    return resultPromise;
  },

  setupController: function (controller, model) {
    this._super(controller, model);

    // setup pagination controller mixin
    controller.setupPagination(this.get('contentModelType', this.paginationParams));
  }
});

export default ContentListRouteMixin;
<commit_msg>Fixes broken pagination<commit_after>import Ember from 'ember';

var initialPaginationParams = { 'page': 1, 'perPage': 15 };

var ContentListRouteMixin = Ember.Mixin.create({
  paginationParams: null,
  contentModelType: null,

  model: function() {
    var site = this.modelFor('site');
    var params = Ember.merge({ 'site': site.get('id') }, initialPaginationParams);

    this.set('paginationParams', params);

    if (this.get('contentModelType') === null) {
      Ember.assert('Content model type must be set.');
    }

    // 1. Caching resultPromise permits to avoid sending a request to server everytime we transition into this route
    // 2. Using filter() allows the template to auto-update when new models are pulled in from the server
    var resultPromise = this.get('resultPromise') || this.store.filter(this.get('contentModelType'), params, function () {
      // nothing to filter
      return true;
    });

    this.set('resultPromise', resultPromise);

    return resultPromise;
  },

  setupController: function (controller, model) {
    this._super(controller, model);

    // setup pagination controller mixin
    controller.setupPagination(this.get('contentModelType'), this.get('paginationParams'));
  }
});

export default ContentListRouteMixin;
<|endoftext|>


<commit_before>/**
 	enyo.Spotlight.Decorator.GridList kind definition

 	TODO: This is a copy of List decorator.
	Ideally, we should be able to inherit decorators from parent kinds and simply override functions that are specific to the overridden decorator
 */

enyo.kind({
	name: 'enyo.Spotlight.Decorator.GridList',

	statics: {
		decorates: enyo.GridList,

		_getNodeParent: function(oSender, n) {
			if (oSender.$.generator.hasNode()) {
				return oSender.$.generator.node.querySelector('[data-enyo-index="' + n + '"]');
			}
		},

		_getNode: function(oSender, n) {
			if (oSender.$.generator.hasNode()) {
				return oSender.$.generator.node.querySelector('[data-enyo-index="' + n + '"] > .moon-gridlist-item');
			}
		},

		_focusNode: function(oSender, n) {
			enyo.Spotlight.Util.addClass(this._getNode(oSender, n), 'spotlight');
		},

		_blurNode: function(oSender, n) {
			enyo.Spotlight.Util.removeClass(this._getNode(oSender, n), 'spotlight');
		},

		_getCurrent: function(oSender) {
			if (typeof oSender._nCurrentSpotlightItem == 'undefined') {
				return 0;
			}
			return oSender._nCurrentSpotlightItem;
		},

		_setCurrent: function(oSender, n, bScrollIntoView) {
			var nCurrent = this._getCurrent(oSender);

			if (nCurrent !== null) {
				this._blurNode(oSender, nCurrent);
			}

			if (n !== null) {
				this._focusNode(oSender, n);
				oSender._nCurrentSpotlightItem = n;
				if (bScrollIntoView) {
					oSender.scrollIntoView({
						hasNode	: function() { return true; },
						node	: this._getNodeParent(oSender, n)
					}, false);
				}
				enyo.Spotlight.Util.dispatchEvent('onSpotlightItemFocus', {index: n}, oSender);
			}
			enyo.Spotlight.Util.removeClass(oSender.node, 'spotlight');
		},

		/******************************/

		onSpotlightFocus: function(oSender, oEvent) {
			this._setCurrent(oSender, this._getCurrent(oSender), false);
			enyo.Spotlight.Util.removeClass(oSender.node, 'spotlight');
			return true;
		},

		onSpotlightBlur: function(oSender, oEvent) {
			this._setCurrent(oSender, null, true);
			enyo.Spotlight.Util.removeClass(oSender.node, 'spotlight');
			return true;
		},

		onSpotlightSelect: function(oSender, oEvent) {
			if (this._getCurrent(oSender) !== null) {
				enyo.Spotlight.Util.dispatchEvent('ontap', {index: this._getCurrent(oSender)}, oSender.$.generator.$.selection);
				this._setCurrent(oSender, this._getCurrent(oSender), true);
			} else {
				this._setCurrent(oSender, 0, true);
			}
			enyo.Spotlight.Util.removeClass(oSender.node, 'spotlight');
			return false;
		},

		onSpotlightDown: function(oSender, oEvent) {
			//Jump one row down (increment index by itemsPerRow)
			var nCurrent = this._getCurrent(oSender);
			if (nCurrent === null) { return; }
			var nNew = nCurrent + oSender.itemsPerRow;
			if (nNew < oSender.getCount() - 1) {
				this._setCurrent(oSender, nNew, true);
				return false;
			}
			this._setCurrent(oSender, null, true);
			return true;
		},

		onSpotlightUp: function(oSender, oEvent) {
			//Jump one row up (decrement index by itemsPerRow)
			var nCurrent = this._getCurrent(oSender);
			if (nCurrent === null) { return; }
			var nNew = nCurrent - oSender.itemsPerRow;
			if (nNew > 0) {
				this._setCurrent(oSender, nNew, true);
				return false;
			}
			this._setCurrent(oSender, null, true);
			return true;
		},

		onSpotlightLeft: function(oSender, oEvent) {
			var nCurrent = this._getCurrent(oSender);
			if (nCurrent === null) { return; }
			if (nCurrent > 0) {
				this._setCurrent(oSender, nCurrent - 1, true);
				return false;
			}
			this._setCurrent(oSender, null, true);
			return true;
		},

		onSpotlightRight: function(oSender, oEvent) {
			var nCurrent = this._getCurrent(oSender);
			if (nCurrent === null) { return; }
			if (nCurrent < oSender.getCount() - 1) {
				this._setCurrent(oSender, nCurrent + 1, true);
				return false;
			}
			this._setCurrent(oSender, null, true);
			return true;
		},

		onSpotlightPoint: function(oSender, oEvent) {
			this._setCurrent(oSender, oEvent.index);
			return true;
		}
	}
});<commit_msg>Scrolling into view of a spotlighted node should only happen if it is not already in view<commit_after>/**
 	enyo.Spotlight.Decorator.GridList kind definition

 	TODO: This is a copy of List decorator.
	Ideally, we should be able to inherit decorators from parent kinds and simply override functions that are specific to the overridden decorator
 */

enyo.kind({
	name: 'enyo.Spotlight.Decorator.GridList',

	statics: {
		decorates: enyo.GridList,

		_getNodeParent: function(oSender, n) {
			if (oSender.$.generator.hasNode()) {
				return oSender.$.generator.node.querySelector('[data-enyo-index="' + n + '"]');
			}
		},

		_getNode: function(oSender, n) {
			if (oSender.$.generator.hasNode()) {
				return oSender.$.generator.node.querySelector('[data-enyo-index="' + n + '"] > .moon-gridlist-item');
			}
		},

		_focusNode: function(oSender, n) {
			enyo.Spotlight.Util.addClass(this._getNode(oSender, n), 'spotlight');
		},

		_blurNode: function(oSender, n) {
			enyo.Spotlight.Util.removeClass(this._getNode(oSender, n), 'spotlight');
		},

		_getCurrent: function(oSender) {
			if (typeof oSender._nCurrentSpotlightItem == 'undefined') {
				return 0;
			}
			return oSender._nCurrentSpotlightItem;
		},

		_setCurrent: function(oSender, n, bScrollIntoView) {
			var nCurrent = this._getCurrent(oSender);

			if (nCurrent !== null) {
				this._blurNode(oSender, nCurrent);
			}

			if (n !== null) {
				this._focusNode(oSender, n);
				oSender._nCurrentSpotlightItem = n;
				if (bScrollIntoView) {
					var nd = this._getNodeParent(oSender, n);
					if (!oSender.$.strategy.isInView(nd)) {
						oSender.scrollIntoView({
							hasNode	: function() { return true; },
							node	: nd
							}, false);
					}
				}
				enyo.Spotlight.Util.dispatchEvent('onSpotlightItemFocus', {index: n}, oSender);
			}
			enyo.Spotlight.Util.removeClass(oSender.node, 'spotlight');
		},

		/******************************/

		onSpotlightFocus: function(oSender, oEvent) {
			this._setCurrent(oSender, this._getCurrent(oSender), false);
			enyo.Spotlight.Util.removeClass(oSender.node, 'spotlight');
			return true;
		},

		onSpotlightBlur: function(oSender, oEvent) {
			this._setCurrent(oSender, null, true);
			enyo.Spotlight.Util.removeClass(oSender.node, 'spotlight');
			return true;
		},

		onSpotlightSelect: function(oSender, oEvent) {
			if (this._getCurrent(oSender) !== null) {
				enyo.Spotlight.Util.dispatchEvent('ontap', {index: this._getCurrent(oSender)}, oSender.$.generator.$.selection);
				this._setCurrent(oSender, this._getCurrent(oSender), true);
			} else {
				this._setCurrent(oSender, 0, true);
			}
			enyo.Spotlight.Util.removeClass(oSender.node, 'spotlight');
			return false;
		},

		onSpotlightDown: function(oSender, oEvent) {
			//Jump one row down (increment index by itemsPerRow)
			var nCurrent = this._getCurrent(oSender);
			if (nCurrent === null) { return; }
			var nNew = nCurrent + oSender.itemsPerRow;
			if (nNew < oSender.getCount() - 1) {
				this._setCurrent(oSender, nNew, true);
				return false;
			}
			this._setCurrent(oSender, null, true);
			return true;
		},

		onSpotlightUp: function(oSender, oEvent) {
			//Jump one row up (decrement index by itemsPerRow)
			var nCurrent = this._getCurrent(oSender);
			if (nCurrent === null) { return; }
			var nNew = nCurrent - oSender.itemsPerRow;
			if (nNew > 0) {
				this._setCurrent(oSender, nNew, true);
				return false;
			}
			this._setCurrent(oSender, null, true);
			return true;
		},

		onSpotlightLeft: function(oSender, oEvent) {
			var nCurrent = this._getCurrent(oSender);
			if (nCurrent === null) { return; }
			if (nCurrent > 0) {
				this._setCurrent(oSender, nCurrent - 1, true);
				return false;
			}
			this._setCurrent(oSender, null, true);
			return true;
		},

		onSpotlightRight: function(oSender, oEvent) {
			var nCurrent = this._getCurrent(oSender);
			if (nCurrent === null) { return; }
			if (nCurrent < oSender.getCount() - 1) {
				this._setCurrent(oSender, nCurrent + 1, true);
				return false;
			}
			this._setCurrent(oSender, null, true);
			return true;
		},

		onSpotlightPoint: function(oSender, oEvent) {
			this._setCurrent(oSender, oEvent.index);
			return true;
		}
	}
});<|endoftext|>


<commit_before>// Copyright (c) 2012-2017, Simon Brand
// Copyright (c) 2017, Marc Poulhiès - Kalray Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

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

    var FontScale = require('fontscale');
    var monaco = require('monaco');
    var options = require('options');
    var Toggles = require('toggles');
    var _ = require('underscore');

    require('selectize');

    function GccDump(hub, container, state) {
        this.container = container;
        this.eventHub = hub.createEventHub();
        this.domRoot = container.getElement();
        this.domRoot.html($('#gccdump').html());
        this.filters = new Toggles(this.domRoot.find('.dump-filters'), state);

        this._currentDecorations = [];

        // until we get our first result from compilation backend with all fields,
        // disable UI callbacks.
        this.uiIsReady = false;
        // disable filter buttons
        this.domRoot.find('.dump-filters').find('.btn')
            .each(function () {
                $(this).addClass('disabled');
            });

        this.gccDumpEditor = monaco.editor.create(this.domRoot.find(".monaco-placeholder")[0], {
            value: "",
            scrollBeyondLastLine: false,
            readOnly: true,
            glyphMargin: true,
            quickSuggestions: false,
            fixedOverflowWidgets: true,
            minimap: {
                maxColumn: 80
            },
            lineNumbersMinChars: 3
        });

        var selectize = this.domRoot.find(".gccdump-pass-picker").selectize({
            sortField: 'name',
            valueField: 'name',
            labelField: 'name',
            searchField: ['name'],
            options: [],
            items: [],
        });

        this.selectize  = selectize[0].selectize;
        this.selectize.disable();

        // this is used to save internal state.
        this.state = {};

        this.state._compilerid = state._compilerid;
        this.state._compilerName = state._compilerName;
        this.state._editorid = state._editorid;

        this.fontScale = new FontScale(this.domRoot, state, this.gccDumpEditor);
        this.fontScale.on('change', _.bind(this.updateState, this));

        this.eventHub.on('compileResult', this.onCompileResult, this);
        this.eventHub.on('compiler', this.onCompiler, this);
        this.eventHub.on('compilerClose', this.onCompilerClose, this);
        this.eventHub.on('settingsChange', this.onSettingsChange, this);

        this.eventHub.emit('gccDumpViewOpened', this.state._compilerid);
        this.eventHub.emit('requestSettings');
        this.container.on('destroy', function () {
            this.eventHub.emit("gccDumpViewClosed", this.state._compilerid);
            this.eventHub.unsubscribe();
            this.gccDumpEditor.dispose();
        }, this);

        container.on('resize', this.resize, this);
        container.on('shown', this.resize, this);

        if (state && state.selectedPass) {
            this.state.selectedPass = state.selectedPass;
            this.eventHub.emit('gccDumpPassSelected',
                               this.state._compilerid,
                               state.selectedPass,
                               false);
        }

	this.eventHub.emit('gccDumpFiltersChanged',
                           this.state._compilerid,
                           this.getEffectiveFilters(),
                           false);

        this.saveState();
        this.setTitle();

        // UI is ready, request compilation to get passes list and
        // current output (if any)
        this.eventHub.emit('gccDumpUIInit', this.state._compilerid);
    }

    GccDump.prototype.onUiReady = function () {
        this.filters.on('change', _.bind(this.onFilterChange, this));
        this.selectize.on('change', _.bind(this.onPassSelect, this));

        // enable drop down menu and buttons
        this.selectize.enable();
        this.domRoot.find('.dump-filters').find('.btn')
            .each(function () {
                $(this).removeClass('disabled');
            });
    };

    GccDump.prototype.onPassSelect = function (passId) {
        if (this.inhibitPassSelect !== true) {
            this.eventHub.emit('gccDumpPassSelected',
                               this.state._compilerid,
                               passId,
                               true);
        }
        this.state.selectedPass = passId;
        this.saveState();
    };

    // TODO: de-dupe with compiler etc
    GccDump.prototype.resize = function () {
        var topBarHeight = this.domRoot.find(".top-bar").outerHeight(true);
        this.gccDumpEditor.layout({
            width: this.domRoot.width(),
            height: this.domRoot.height() - topBarHeight
        });
    };

    // Called after result from new compilation received
    // if gccDumpOutput is false, cleans the select menu
    GccDump.prototype.updatePass = function (filters, selectize, gccDumpOutput) {
        var passes = gccDumpOutput ? gccDumpOutput.all : [];

        // we are changing selectize but don't want any callback to
        // trigger new compilation
        this.inhibitPassSelect = true;

        _.each(selectize.options, function(p) {
            if (passes.indexOf(p.name) === -1) {
                selectize.removeOption(p.name);
            }
        }, this);

        _.each(passes, function(p) {
            selectize.addOption({
                name: p,
            });
        }, this);

        if (gccDumpOutput.selectedPass && gccDumpOutput.selectedPass !== "") {
            selectize.addItem(gccDumpOutput.selectedPass ,true);
        } else {
            selectize.clear(true);
        }

        this.eventHub.emit('gccDumpPassSelected',
                           this.state._compilerid,
                           gccDumpOutput.selectedPass,
                           false);

        this.inhibitPassSelect = false;
    };

    GccDump.prototype.onCompileResult = function (id, compiler, result) {
        if (this.state._compilerid === id) {

	    // ignore spurious result when :
	    // - UI is disabled
	    // - some state has been restored
	    // - result does not have an gccdump info
	    //
	    // This happens when restoring a state and some builds are
	    // executed by another part of the code before we had the
	    // chance to set all our parameters : results are coming
	    // back without any dump info.
            if (!this.uiIsReady &&
		this.state.selectedPass !== "" &&
		(!result.hasGccDumpOutput ||
		 result.gccDumpOutput.selectedPass === "")) {
		// wait for correct build job:
		// We should get something back from what has been
		// requested earlier at the end of GccDump().
		return;
	    }

            if (result.hasGccDumpOutput) {
                var currOutput = result.gccDumpOutput.currentPassOutput;

                // if result contains empty selected pass, probably means
                // we requested an invalid/outdated pass.
                if (result.gccDumpOutput.selectedPass === "") {
                    this.selectize.clear(true);
                    this.state.selectedPass = "";
                }
                this.updatePass(this.filters, this.selectize, result.gccDumpOutput);
                this.showGccDumpResults(currOutput);
            } else {
                this.selectize.clear(true);
                this.state.selectedPass = "";
                this.updatePass(this.filters, this.selectize, false);
                this.showGccDumpResults("<no output>");
            }
            // enable UI on first compilation
            if (!this.uiIsReady) {
                this.uiIsReady = true;
                this.onUiReady();
            }

            this.saveState();
        }
    };

    GccDump.prototype.setTitle = function () {
        this.container.setTitle(this.state._compilerName + " GCC Tree/RTL Viewer (Editor #" + this.state._editorid + ", Compiler #" + this.state._compilerid + ")");
    };

    GccDump.prototype.showGccDumpResults = function (results) {
        this.gccDumpEditor.setValue(results);
    };

    GccDump.prototype.onCompiler = function (id, compiler, options, editorid) {
        if (id === this.state._compilerid) {
            this._compilerName = compiler ? compiler.name : '';
            this.state._editorid = editorid;
            this.setTitle();
        }
    };

    GccDump.prototype.onCompilerClose = function (id) {
        if (id === this.state._compilerid) {
            // We can't immediately close as an outer loop somewhere in GoldenLayout is iterating over
            // the hierarchy. We can't modify while it's being iterated over.
            _.defer(function (self) {
                self.container.close();
            }, this);
        }
    };

    GccDump.prototype.getEffectiveFilters = function () {
        return this.filters.get();
    };

    GccDump.prototype.onFilterChange = function () {
        this.saveState();

        if (this.inhibitPassSelect !== true) {
            this.eventHub.emit('gccDumpFiltersChanged',
                               this.state._compilerid,
                               this.getEffectiveFilters(),
                               true);
        }
    };

    GccDump.prototype.saveState = function () {
        this.container.setState(this.currentState());
    };

    GccDump.prototype.currentState = function () {
        var filters = this.getEffectiveFilters();
        return {
            _compilerid: this.state._compilerid,
            _editorid: this.state._editorid,
            _compilerName: this.state._compilerName,

            selectedPass : this.state.selectedPass,
            treeDump : filters.treeDump,
            rtlDump: filters.rtlDump
        };
    };

    GccDump.prototype.updateState = function () {
    };

    GccDump.prototype.onSettingsChange = function (newSettings) {
        this.gccDumpEditor.updateOptions({
            minimap: {
                enabled: newSettings.showMinimap
            }
        });
    };

    return {
        GccDump: GccDump
    };
});
<commit_msg>Save FontScale between GCCDump sessions<commit_after>// Copyright (c) 2012-2017, Simon Brand
// Copyright (c) 2017, Marc Poulhiès - Kalray Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

define(function (require) {
    'use strict';

    var FontScale = require('fontscale');
    var monaco = require('monaco');
    var options = require('options');
    var Toggles = require('toggles');
    var _ = require('underscore');

    require('selectize');

    function GccDump(hub, container, state) {
        this.container = container;
        this.eventHub = hub.createEventHub();
        this.domRoot = container.getElement();
        this.domRoot.html($('#gccdump').html());
        this.filters = new Toggles(this.domRoot.find('.dump-filters'), state);

        this._currentDecorations = [];

        // until we get our first result from compilation backend with all fields,
        // disable UI callbacks.
        this.uiIsReady = false;
        // disable filter buttons
        this.domRoot.find('.dump-filters').find('.btn')
            .each(function () {
                $(this).addClass('disabled');
            });

        this.gccDumpEditor = monaco.editor.create(this.domRoot.find('.monaco-placeholder')[0], {
            value: '',
            scrollBeyondLastLine: false,
            readOnly: true,
            glyphMargin: true,
            quickSuggestions: false,
            fixedOverflowWidgets: true,
            minimap: {
                maxColumn: 80
            },
            lineNumbersMinChars: 3
        });

        var selectize = this.domRoot.find('.gccdump-pass-picker').selectize({
            sortField: 'name',
            valueField: 'name',
            labelField: 'name',
            searchField: ['name'],
            options: [],
            items: []
        });

        this.selectize = selectize[0].selectize;
        this.selectize.disable();

        // this is used to save internal state.
        this.state = {};

        this.state._compilerid = state._compilerid;
        this.state._compilerName = state._compilerName;
        this.state._editorid = state._editorid;

        this.fontScale = new FontScale(this.domRoot, state, this.gccDumpEditor);
        this.fontScale.on('change', _.bind(this.saveState, this));

        this.eventHub.on('compileResult', this.onCompileResult, this);
        this.eventHub.on('compiler', this.onCompiler, this);
        this.eventHub.on('compilerClose', this.onCompilerClose, this);
        this.eventHub.on('settingsChange', this.onSettingsChange, this);

        this.eventHub.emit('gccDumpViewOpened', this.state._compilerid);
        this.eventHub.emit('requestSettings');
        this.container.on('destroy', function () {
            this.eventHub.emit('gccDumpViewClosed', this.state._compilerid);
            this.eventHub.unsubscribe();
            this.gccDumpEditor.dispose();
        }, this);

        container.on('resize', this.resize, this);
        container.on('shown', this.resize, this);

        if (state && state.selectedPass) {
            this.state.selectedPass = state.selectedPass;
            this.eventHub.emit('gccDumpPassSelected',
                this.state._compilerid,
                state.selectedPass,
                false);
        }

        this.eventHub.emit('gccDumpFiltersChanged',
            this.state._compilerid,
            this.getEffectiveFilters(),
            false);

        this.saveState();
        this.setTitle();

        // UI is ready, request compilation to get passes list and
        // current output (if any)
        this.eventHub.emit('gccDumpUIInit', this.state._compilerid);
    }

    GccDump.prototype.onUiReady = function () {
        this.filters.on('change', _.bind(this.onFilterChange, this));
        this.selectize.on('change', _.bind(this.onPassSelect, this));

        // enable drop down menu and buttons
        this.selectize.enable();
        this.domRoot.find('.dump-filters').find('.btn')
            .each(function () {
                $(this).removeClass('disabled');
            });
    };

    GccDump.prototype.onPassSelect = function (passId) {
        if (this.inhibitPassSelect !== true) {
            this.eventHub.emit('gccDumpPassSelected',
                this.state._compilerid,
                passId,
                true);
        }
        this.state.selectedPass = passId;
        this.saveState();
    };

    // TODO: de-dupe with compiler etc
    GccDump.prototype.resize = function () {
        var topBarHeight = this.domRoot.find('.top-bar').outerHeight(true);
        this.gccDumpEditor.layout({
            width: this.domRoot.width(),
            height: this.domRoot.height() - topBarHeight
        });
    };

    // Called after result from new compilation received
    // if gccDumpOutput is false, cleans the select menu
    GccDump.prototype.updatePass = function (filters, selectize, gccDumpOutput) {
        var passes = gccDumpOutput ? gccDumpOutput.all : [];

        // we are changing selectize but don't want any callback to
        // trigger new compilation
        this.inhibitPassSelect = true;

        _.each(selectize.options, function (p) {
            if (passes.indexOf(p.name) === -1) {
                selectize.removeOption(p.name);
            }
        }, this);

        _.each(passes, function (p) {
            selectize.addOption({
                name: p
            });
        }, this);

        if (gccDumpOutput.selectedPass && gccDumpOutput.selectedPass !== '') {
            selectize.addItem(gccDumpOutput.selectedPass, true);
        } else {
            selectize.clear(true);
        }

        this.eventHub.emit('gccDumpPassSelected',
            this.state._compilerid,
            gccDumpOutput.selectedPass,
            false);

        this.inhibitPassSelect = false;
    };

    GccDump.prototype.onCompileResult = function (id, compiler, result) {
        if (this.state._compilerid === id) {

            // ignore spurious result when :
            // - UI is disabled
            // - some state has been restored
            // - result does not have an gccdump info
            //
            // This happens when restoring a state and some builds are
            // executed by another part of the code before we had the
            // chance to set all our parameters : results are coming
            // back without any dump info.
            if (!this.uiIsReady &&
                this.state.selectedPass !== '' &&
                (!result.hasGccDumpOutput ||
                    result.gccDumpOutput.selectedPass === '')) {
                // wait for correct build job:
                // We should get something back from what has been
                // requested earlier at the end of GccDump().
                return;
            }

            if (result.hasGccDumpOutput) {
                var currOutput = result.gccDumpOutput.currentPassOutput;

                // if result contains empty selected pass, probably means
                // we requested an invalid/outdated pass.
                if (result.gccDumpOutput.selectedPass === '') {
                    this.selectize.clear(true);
                    this.state.selectedPass = '';
                }
                this.updatePass(this.filters, this.selectize, result.gccDumpOutput);
                this.showGccDumpResults(currOutput);
            } else {
                this.selectize.clear(true);
                this.state.selectedPass = '';
                this.updatePass(this.filters, this.selectize, false);
                this.showGccDumpResults('<no output>');
            }
            // enable UI on first compilation
            if (!this.uiIsReady) {
                this.uiIsReady = true;
                this.onUiReady();
            }

            this.saveState();
        }
    };

    GccDump.prototype.setTitle = function () {
        this.container.setTitle(this.state._compilerName + ' GCC Tree/RTL Viewer (Editor #' + this.state._editorid + ', Compiler #' + this.state._compilerid + ')');
    };

    GccDump.prototype.showGccDumpResults = function (results) {
        this.gccDumpEditor.setValue(results);
    };

    GccDump.prototype.onCompiler = function (id, compiler, options, editorid) {
        if (id === this.state._compilerid) {
            this._compilerName = compiler ? compiler.name : '';
            this.state._editorid = editorid;
            this.setTitle();
        }
    };

    GccDump.prototype.onCompilerClose = function (id) {
        if (id === this.state._compilerid) {
            // We can't immediately close as an outer loop somewhere in GoldenLayout is iterating over
            // the hierarchy. We can't modify while it's being iterated over.
            _.defer(function (self) {
                self.container.close();
            }, this);
        }
    };

    GccDump.prototype.getEffectiveFilters = function () {
        return this.filters.get();
    };

    GccDump.prototype.onFilterChange = function () {
        this.saveState();

        if (this.inhibitPassSelect !== true) {
            this.eventHub.emit('gccDumpFiltersChanged',
                this.state._compilerid,
                this.getEffectiveFilters(),
                true);
        }
    };

    GccDump.prototype.saveState = function () {
        var state = this.currentState();
        this.container.setState(state);
        this.fontScale.addState(state);
    };

    GccDump.prototype.currentState = function () {
        var filters = this.getEffectiveFilters();
        return {
            _compilerid: this.state._compilerid,
            _editorid: this.state._editorid,
            _compilerName: this.state._compilerName,

            selectedPass: this.state.selectedPass,
            treeDump: filters.treeDump,
            rtlDump: filters.rtlDump
        };
    };

    GccDump.prototype.onSettingsChange = function (newSettings) {
        this.gccDumpEditor.updateOptions({
            minimap: {
                enabled: newSettings.showMinimap
            }
        });
    };

    return {
        GccDump: GccDump
    };
});
<|endoftext|>


<commit_before>function renderThingCompass(canvas) {
    var ctx = canvas.getContext('2d');

    var centerX = canvas.width / 2;
    var centerY = canvas.height / 2;

    var lineColour = '#80AEFF';
    var glowColour = 'white';

    var radius = centerX < centerY ? centerX + 50 : centerY + 50;

    var minTilt = 0.33;

    if (motionData.compassHeading)
        var heading = motionData.gyroCompass * Math.PI / 180;
    else
        var heading = 0;

    // *** Transform ***
    var rotation = heading;
    var tilt = motionData.tiltFB * Math.PI / 180;
    var cs = Math.cos(rotation), sn = Math.sin(rotation);
    var h = Math.cos(tilt) > minTilt ? Math.cos(tilt) : minTilt;
    var a = cs, b = -sn, c = centerX;
    var d = h * sn, e = h * cs, f = centerY + centerY/2;

    ctx.save();
    ctx.setTransform(a, d, b, e, c, f);
    ctx.save();

    // *** Ellipse ticks****
    var nTicks = 128;
    var tickAngle = 2 * Math.PI / nTicks;

    ctx.save();
    ctx.lineCap = 'hard';
    ctx.beginPath();
    ctx.setLineDash([4, 10]);
    ctx.lineWidth = 10;
    ctx.strokeStyle = lineColour;
    ctx.arc(0, 0, radius, 0, 2 * Math.PI, false);
    ctx.stroke();
    ctx.restore();

    ctx.beginPath();
    ctx.lineWidth = 5;
    for (var i = 0; i < 4; i++) {
        ctx.rotate(Math.PI / 2);
        ctx.moveTo(0, radius - 15);
        ctx.lineTo(0, radius);
    }
    ctx.stroke();
    ctx.restore();

    // *** Crosshair ***
    var crosshairSize = 5;

    ctx.save();
    ctx.moveTo(0, -crosshairSize);
    ctx.lineTo(0, crosshairSize);
    ctx.moveTo(-crosshairSize, 0);
    ctx.lineTo(crosshairSize, 0);
    ctx.lineWidth = 2;
    ctx.strokeStyle = lineColour;
    //ctx.shadowColor = glowColour;
    //ctx.shadowBlur = 5;
    ctx.stroke();
    ctx.restore();

    // *** North, East, South, West labels ****
    var NESWLabels = ['N', 'E', 'S', 'W'];
    var labelOffset = radius + 10;

    ctx.font = '22pt Calibri'
    ctx.textAlign = 'center';
    ctx.fillStyle = '#dbe8ff';

    ctx.save();
    ctx.fillText(NESWLabels[0], 0, -labelOffset); // North
    ctx.rotate(Math.PI / 2);
    ctx.fillText(NESWLabels[1], 0, -labelOffset); // East
    ctx.rotate(Math.PI);
    ctx.fillText(NESWLabels[3], 0, -labelOffset);  // West
    ctx.rotate(3 * Math.PI / 2);
    ctx.fillText(NESWLabels[2], 0, -labelOffset); // South
    ctx.restore();

    ctx.restore();

    // *** Top marker ***
    ctx.save();
    var rotation = 0;
    var cs = Math.cos(rotation), sn = Math.sin(rotation);
    var a = cs, b = -sn;
    var d = h * sn, e = h * cs;
    ctx.setTransform(a, d, b, e, c, f);

    var markerSize = 10;

    ctx.save();
    ctx.lineWidth = 4;
    ctx.strokeStyle = 'red';
    //ctx.shadowColor = 'red';
    //ctx.shadowBlur = 15;
    ctx.beginPath();
    ctx.moveTo(0, -radius - markerSize / 2);
    ctx.lineTo(0, -radius + markerSize / 2);
    ctx.stroke();
    ctx.restore();

    // *** Ball ***
    var maxG = 4;

    ctx.save();
    var ballSize = 5;
    var ballX = (motionData.xRaw) / (maxG * 9.81) * radius;
    var ballY = -(motionData.yRaw) / (maxG * 9.81) * radius;

    ctx.beginPath();
    ctx.fillStyle = lineColour;
    ctx.arc(ballX, ballY, ballSize, 0, 2 * Math.PI, false);
    ctx.fill();

    var xMax = (motionData.xRecentMax) / (maxG * 9.81) * radius;
    var yMax = -(motionData.yRecentMax) / (maxG * 9.81) * radius;

    if (xMax !== 0 && yMax !== 0 && (motionData.xRecentMax > 4 || motionData.yRecentMax > 4)) {
        ctx.beginPath();
        ctx.fillStyle = 'white';
        //ctx.shadowColor = 'white';
        //ctx.shadowBlur = 15;
        ctx.arc(xMax, yMax, ballSize, 0, 2 * Math.PI, false);
        ctx.fill();
    }

    ctx.restore();

    var nRings = 4;

    for (var i = 1; i < nRings; i++) {
        ctx.beginPath();
        ctx.arc(0, 0, radius / nRings * i, 0, 2 * Math.PI, false);
        ctx.lineWidth = 1;
        ctx.setLineDash([5,15]);
        ctx.strokeStyle = 'rgba(128, 174, 255, 0.5)';
        ctx.stroke();
    }

    ctx.restore();
}

/////////////////////////////////////////////////////////////////////

function gradientFromList(ctx, x1, y1, x2, y2, colorList) {
    if (colorList.length < 1)
        return;

    var gradient = ctx.createLinearGradient(x1, y1, x2, y2);

    gradient.addColorStop(0, colorList[0]);
    for (var i = 1; i < colorList.length; i++) {
        gradient.addColorStop((i + 1) / colorList.length, colorList[i]);
    }
    return gradient;
}

/////////////////////////////////////////////////////////////////////

function drawGMeter(ctx, percentFullA, percentFullB, x, y, width, height, tickLineDash, backgroundGradient, barGradientA, barGradientB) {
    // background
    //ctx.fillStyle = gradientFromList(ctx, 0, y, 0, y + height, ['#2F2F2F', '#000']);
    //ctx.fillRect(x - width / 2, y, width, height);
    ctx.fillStyle = gradientFromList(ctx, 0, y, 0, y + height, ['#2F2F2F', '#000']);
    ctx.fillRect(x - width / 2, y, width, height);

    // secondary bar
    ctx.fillStyle = gradientFromList(ctx, 0, y, 0, y + height, ['#700000']);
    ctx.fillRect(x,  y + 3, percentFullB * width / 2, height - 6);

    // primary bar
    ctx.fillStyle = gradientFromList(ctx, 0, y, 0, y + height, ['#aec7cc']);
    ctx.fillRect(x,  y + 3, percentFullA * width / 2, height - 6);

    // ticks
    ctx.save();
    ctx.setLineDash(tickLineDash);
    ctx.lineWidth = height;
    ctx.strokeStyle = barGradientA;
    ctx.beginPath();

    ctx.moveTo(x            , y + height / 2);
    ctx.lineTo(x + width / 2, y + height / 2);

    ctx.moveTo(x            , y + height / 2);
    ctx.lineTo(x - width / 2, y + height / 2);

    ctx.stroke();
    ctx.restore();
}

/////////////////////////////////////////////////////////////////////

function clearCanvas(ctx) {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}

/////////////////////////////////////////////////////////////////////

function resetCanvas(canvas) {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}

/////////////////////////////////////////////////////////////////////

function renderFrame(ctx) {
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;

    clearCanvas(ctx);

    // -- Draw horizontal 'G' meter --
    drawGMeter(
        ctx,
        motionState.xRaw / 9.81 / gMeterProperties.maxReading,
        motionState.xRecentMax / 9.81 / gMeterProperties.maxReading,
        w / 2,
        h - 35,
        gMeterProperties.width,
        gMeterProperties.height,
        [1, (gMeterProperties.width / 2 / gMeterProperties.maxReading) - 1]
    );

    previousMotionState = motionDataClone(motionState);

    window.requestAnimationFrame(function () {
        renderFrame(ctx);
    });
}

/////////////////////////////////////////////////////////////////////

var canvasContext;
var motionState = MotionData;
var previousMotionState = motionState;

var gMeterProperties;

function initDashboard() {
    var canvas = document.getElementById('compass');
    var canvasContext = canvas.getContext('2d');

    gMeterProperties = {
        width: 400,
        height: 20,
        maxReading: 2.1
    };

    motionStartListeners(motionState);

    resetCanvas(canvas);
    window.addEventListener('resize', function() {
        resetCanvas(canvas);
    });

    window.requestAnimationFrame(function () {
        renderFrame(canvasContext);
    });
}
<commit_msg>Changed G-meter ticks to white<commit_after>function renderThingCompass(canvas) {
    var ctx = canvas.getContext('2d');

    var centerX = canvas.width / 2;
    var centerY = canvas.height / 2;

    var lineColour = '#80AEFF';
    var glowColour = 'white';

    var radius = centerX < centerY ? centerX + 50 : centerY + 50;

    var minTilt = 0.33;

    if (motionData.compassHeading)
        var heading = motionData.gyroCompass * Math.PI / 180;
    else
        var heading = 0;

    // *** Transform ***
    var rotation = heading;
    var tilt = motionData.tiltFB * Math.PI / 180;
    var cs = Math.cos(rotation), sn = Math.sin(rotation);
    var h = Math.cos(tilt) > minTilt ? Math.cos(tilt) : minTilt;
    var a = cs, b = -sn, c = centerX;
    var d = h * sn, e = h * cs, f = centerY + centerY/2;

    ctx.save();
    ctx.setTransform(a, d, b, e, c, f);
    ctx.save();

    // *** Ellipse ticks****
    var nTicks = 128;
    var tickAngle = 2 * Math.PI / nTicks;

    ctx.save();
    ctx.lineCap = 'hard';
    ctx.beginPath();
    ctx.setLineDash([4, 10]);
    ctx.lineWidth = 10;
    ctx.strokeStyle = lineColour;
    ctx.arc(0, 0, radius, 0, 2 * Math.PI, false);
    ctx.stroke();
    ctx.restore();

    ctx.beginPath();
    ctx.lineWidth = 5;
    for (var i = 0; i < 4; i++) {
        ctx.rotate(Math.PI / 2);
        ctx.moveTo(0, radius - 15);
        ctx.lineTo(0, radius);
    }
    ctx.stroke();
    ctx.restore();

    // *** Crosshair ***
    var crosshairSize = 5;

    ctx.save();
    ctx.moveTo(0, -crosshairSize);
    ctx.lineTo(0, crosshairSize);
    ctx.moveTo(-crosshairSize, 0);
    ctx.lineTo(crosshairSize, 0);
    ctx.lineWidth = 2;
    ctx.strokeStyle = lineColour;
    //ctx.shadowColor = glowColour;
    //ctx.shadowBlur = 5;
    ctx.stroke();
    ctx.restore();

    // *** North, East, South, West labels ****
    var NESWLabels = ['N', 'E', 'S', 'W'];
    var labelOffset = radius + 10;

    ctx.font = '22pt Calibri'
    ctx.textAlign = 'center';
    ctx.fillStyle = '#dbe8ff';

    ctx.save();
    ctx.fillText(NESWLabels[0], 0, -labelOffset); // North
    ctx.rotate(Math.PI / 2);
    ctx.fillText(NESWLabels[1], 0, -labelOffset); // East
    ctx.rotate(Math.PI);
    ctx.fillText(NESWLabels[3], 0, -labelOffset);  // West
    ctx.rotate(3 * Math.PI / 2);
    ctx.fillText(NESWLabels[2], 0, -labelOffset); // South
    ctx.restore();

    ctx.restore();

    // *** Top marker ***
    ctx.save();
    var rotation = 0;
    var cs = Math.cos(rotation), sn = Math.sin(rotation);
    var a = cs, b = -sn;
    var d = h * sn, e = h * cs;
    ctx.setTransform(a, d, b, e, c, f);

    var markerSize = 10;

    ctx.save();
    ctx.lineWidth = 4;
    ctx.strokeStyle = 'red';
    //ctx.shadowColor = 'red';
    //ctx.shadowBlur = 15;
    ctx.beginPath();
    ctx.moveTo(0, -radius - markerSize / 2);
    ctx.lineTo(0, -radius + markerSize / 2);
    ctx.stroke();
    ctx.restore();

    // *** Ball ***
    var maxG = 4;

    ctx.save();
    var ballSize = 5;
    var ballX = (motionData.xRaw) / (maxG * 9.81) * radius;
    var ballY = -(motionData.yRaw) / (maxG * 9.81) * radius;

    ctx.beginPath();
    ctx.fillStyle = lineColour;
    ctx.arc(ballX, ballY, ballSize, 0, 2 * Math.PI, false);
    ctx.fill();

    var xMax = (motionData.xRecentMax) / (maxG * 9.81) * radius;
    var yMax = -(motionData.yRecentMax) / (maxG * 9.81) * radius;

    if (xMax !== 0 && yMax !== 0 && (motionData.xRecentMax > 4 || motionData.yRecentMax > 4)) {
        ctx.beginPath();
        ctx.fillStyle = 'white';
        //ctx.shadowColor = 'white';
        //ctx.shadowBlur = 15;
        ctx.arc(xMax, yMax, ballSize, 0, 2 * Math.PI, false);
        ctx.fill();
    }

    ctx.restore();

    var nRings = 4;

    for (var i = 1; i < nRings; i++) {
        ctx.beginPath();
        ctx.arc(0, 0, radius / nRings * i, 0, 2 * Math.PI, false);
        ctx.lineWidth = 1;
        ctx.setLineDash([5,15]);
        ctx.strokeStyle = 'rgba(128, 174, 255, 0.5)';
        ctx.stroke();
    }

    ctx.restore();
}

/////////////////////////////////////////////////////////////////////

function gradientFromList(ctx, x1, y1, x2, y2, colorList) {
    if (colorList.length < 1)
        return;

    var gradient = ctx.createLinearGradient(x1, y1, x2, y2);

    gradient.addColorStop(0, colorList[0]);
    for (var i = 1; i < colorList.length; i++) {
        gradient.addColorStop((i + 1) / colorList.length, colorList[i]);
    }
    return gradient;
}

/////////////////////////////////////////////////////////////////////

function drawGMeter(ctx, percentFullA, percentFullB, x, y, width, height, tickLineDash, backgroundGradient, barGradientA, barGradientB) {
    // background
    //ctx.fillStyle = gradientFromList(ctx, 0, y, 0, y + height, ['#2F2F2F', '#000']);
    //ctx.fillRect(x - width / 2, y, width, height);
    ctx.fillStyle = gradientFromList(ctx, 0, y, 0, y + height, ['#2F2F2F', '#000']);
    ctx.fillRect(x - width / 2, y, width, height);

    // secondary bar
    ctx.fillStyle = gradientFromList(ctx, 0, y, 0, y + height, ['#700000']);
    ctx.fillRect(x,  y + 3, percentFullB * width / 2, height - 6);

    // primary bar
    ctx.fillStyle = gradientFromList(ctx, 0, y, 0, y + height, ['#aec7cc']);
    ctx.fillRect(x,  y + 3, percentFullA * width / 2, height - 6);

    // ticks
    ctx.save();
    ctx.setLineDash(tickLineDash);
    ctx.lineWidth = height;
    ctx.strokeStyle = '#f5f5f5';
    ctx.beginPath();

    ctx.moveTo(x            , y + height / 2);
    ctx.lineTo(x + width / 2, y + height / 2);

    ctx.moveTo(x            , y + height / 2);
    ctx.lineTo(x - width / 2, y + height / 2);

    ctx.stroke();
    ctx.restore();
}

/////////////////////////////////////////////////////////////////////

function clearCanvas(ctx) {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}

/////////////////////////////////////////////////////////////////////

function resetCanvas(canvas) {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}

/////////////////////////////////////////////////////////////////////

function renderFrame(ctx) {
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;

    clearCanvas(ctx);

    // -- Draw horizontal 'G' meter --
    drawGMeter(
        ctx,
        motionState.xRaw / 9.81 / gMeterProperties.maxReading,
        motionState.xRecentMax / 9.81 / gMeterProperties.maxReading,
        w / 2,
        h - 35,
        gMeterProperties.width,
        gMeterProperties.height,
        [1, (gMeterProperties.width / 2 / gMeterProperties.maxReading) - 1]
    );

    previousMotionState = motionDataClone(motionState);

    window.requestAnimationFrame(function () {
        renderFrame(ctx);
    });
}

/////////////////////////////////////////////////////////////////////

var canvasContext;
var motionState = MotionData;
var previousMotionState = motionState;

var gMeterProperties;

function initDashboard() {
    var canvas = document.getElementById('compass');
    var canvasContext = canvas.getContext('2d');

    gMeterProperties = {
        width: 400,
        height: 20,
        maxReading: 2.1
    };

    motionStartListeners(motionState);

    resetCanvas(canvas);
    window.addEventListener('resize', function() {
        resetCanvas(canvas);
    });

    window.requestAnimationFrame(function () {
        renderFrame(canvasContext);
    });
}
<|endoftext|>


<commit_before>/*
    Copyright 2014 UW Information Technology, University of Washington

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    Changes:

    =================================================================

*/

// H = Handlebars, $ = jQuery
(function (H, $) {

    window.spacescout_favorites = window.spacescout_favorites || {
        k: {
            'favorites_count_container': '.favorites_count_container',
            'favorites_count_template': '#favorites_count',
            'favorites_card_container': '.favorites_card_container',
            'favorites_card_template': '#favorites_card'
        },

        favorites: undefined,

        update_count: function () {
            var self = this,
                source = $(self.k.favorites_count_template),
                template;

            if (source.length) {
                template = H.compile(source.html().trim());
                $(this.k.favorites_count_container).each(function () {
                    $(this).html(template({count: self.favorites.length}));
                });
            }
        },

        update_search_result: function () {
            var self = this,
                detail_node = $('div[id^=detail_container_]'),
                detail_id = detail_node.length ? parseInt(detail_node.prop('id').match(/^detail_container_(\d+)$/)[1]) : null;

            $('button .space-detail-fav').each(function () {
                var node = $(this),
                    id = parseInt(node.parent().prop('id'));

                if (self.is_favorite(id)) {
                    node.show();
                    if (id == detail_id) {
                        $('.space-detail-fav', detail_node).addClass('space-detail-fav-set');
                    }
                } else {
                    node.hide();
                    if (id == detail_id) {
                        $('.space-detail-fav', detail_node).removeClass('space-detail-fav-set');
                    }
                }
            });
        },

        update_cards: function (on_card_load, on_finish) {
            var container = $(this.k.favorites_card_container),
                source, template;

            if (container.length == 1 && $.isArray(this.favorites)) {
                source = $(this.k.favorites_card_template).html();
                template = H.compile(source);
                self = this;

                $.each(this.favorites, function () {
                    var spot = $('spot_' + this.id),
                        type = [], card;

                    if ($.isArray(this.type)) {
                        $.each(this.type, function () {
                            type.push(gettext(this));
                        });
                    }

                    this.type = type.join(', ');
                    this.extended_info.noise_level = gettext(this.extended_info.noise_level);
                    this.extended_info.food_nearby = gettext(this.extended_info.food_nearby);
                    this.has_reservation_notes = !!this.extended_info.reservation_notes;
                    this.has_notes = ( this.extended_info.access_notes || this.has_reservation_notes );
                    this.has_resources = ( this.extended_info.has_computers || this.extended_info.has_displays || this.extended_info.has_outlets || this.extended_info.has_printing || this.extended_info.has_projector || this.extended_info.has_scanner || this.extended_info.has_whiteboards );

                    card = $(template(this));

                    if (spot.length == 0) {
                        card.insertBefore('#space-detail-blank', container);
                    }

                    if (on_card_load) {
                        on_card_load.apply(self, [card, this]);
                    }
                });

                if (on_finish) {
                    on_finish.apply(self, []);
                }

            }
        },

        load: function (on_card_load, on_finish) {
            var self = this;

            $.ajax({
                url: 'api/v1/user/me/favorites',
                success: function (data) {
                    self.favorites = data ? data : [];
                    self.update(on_card_load, on_finish);
                },
                error: function (xhr, textStatus, errorThrown) {
                    console.log('Unable to load favorites: ' + xhr.responseText);
                }
            });
        },

        update: function (on_card_load, on_finished) {
            this.update_count();
            this.update_search_result();
            this.update_cards(on_card_load, on_finished);
        },

        is_favorite: function (id) {
            var fav = false;

            if (this.favorites) {
                fav = (this.index(id) >= 0);
            } else {
                $.ajax({
                    url: 'api/v1/user/me/favorite/' + id,
                    type: "GET",
                    async: false,
                    success: function (data) {
                        fav = data;
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        console.log('Unable to get favorite: ' + xhr.responseText);
                    }
                });
            }

            return fav;
        },

        index: function (id) {
            var i;

            if (this.favorites) {
                for (i = 0; i < this.favorites.length; i += 1) {
                    if (this.favorites[i].id == id) {
                        return i;
                    }
                }
            }

            return -1;
        },

        toggle: function (id, on_set, on_clear) {
            if (this.is_favorite(id)) {
                this.clear(id, on_clear);
            } else {
                this.set(id, on_set);
            }

            this.update_count();
        },

        set: function (id, on_set) {
            var self = this;

            if (!this.is_favorite(id)) {
                $.ajax({
                    url: 'api/v1/user/me/favorite/' + id,
                    dataType: 'json',
                    contentType: "application/json",
                    data: JSON.stringify({}),
                    type: "PUT",
                    success: function (data) {
                        if (self.favorites) {
                            self.favorites.push({
                                id: id,
                                incomplete: true
                            });
                        }

                        self.update_count();
                        if (on_set) {
                            on_set.call();
                        }
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        console.log('Unable to set favorite: ' + xhr.responseText);
                    }
                });
            }
        },

        clear: function (id, on_clear) {
            var self = this;

            $.ajax({
                url: 'api/v1/user/me/favorite/' + id,
                dataType: 'json',
                type: "DELETE",
                success: function (data) {
                    if (self.favorites) {
                        var index = self.index(id);

                        if (index >= 0) {
                            self.favorites.splice(index, 1);
                        }
                    }

                    self.update_count();
                    if (on_clear) {
                        on_clear.call();
                    }
                },
                error: function (xhr, textStatus, errorThrown) {
                    console.log('Unable to unset favorite: ' + xhr.responseText);
                }
            });
        }
    };

    if ($('.favorites_nav').length > 0) {
        window.spacescout_favorites.load(function (card, fav) {
            var now = new Date(),
                hour = now.getHours(),
                minute = now.getMinutes(),
                day = weekday_from_day(now.getDay()).toLowerCase(),
                formatted = 'Closed',
                o, c;

            if (fav.available_hours[day].length > 0) {
                $.each(fav.available_hours[day], function() {
                    this[0] = this[0].replace(/^0+/, '');
                    this[1] = this[1].replace(/^0+/, '');
                    o = this[0].split(':');
                    c = this[1].split(':');

                    if ((hour > parseInt(o[0]) && hour < parseInt(c[0]))
                        || (hour == parseInt(o[0]) && minute > parseInt(o[1]))
                        || (hour == parseInt(c[0]) && minute < parseInt(c[1]))) {
                        $('.space-detail-is-open', card).show();
                    }
                });

                formatted = to12Hour(fav.available_hours[day]).join(", ");
            }

            $('.space-info-hours-today span', card).html(formatted);

            $('.space-info-more-detail a', card).click(function (e) {
                var more_div = $(e.target).parent();

                more_div.slideUp('fast');
                more_div.next().slideDown('fast');
            });

            $('.space-info-less-detail a', card).click(function (e) {
                var ul = $(e.target).closest('ul');

                ul.slideUp('fast');
                ul.prev().slideDown('fast');
            });

            $('.space-detail-fav', card).tooltip({ placement: 'right',
                                                   title: 'Remove this space from Favorites' });
            $('.space-detail-fav', card).click(function (e) {
                var id = parseInt($(this).attr('data-id'));
                var container = $(this).closest('.space-detail-container');
                var tooltip = $(this).tooltip('hide');

                window.spacescout_favorites.clear(id, function () {
                    container.hide({ effect: 'fade', duration: 800,  complete: function () { this.remove(); } });
                });
            });

            var bld_code = fav.location.building_name.match(/.*\(([A-Z ]+)\)( [a-zA-Z]+)?$/);
            if (bld_code) {
                $('.space-detail-building', card).html(bld_code[1] + (bld_code[2] ? bld_code[2] : ''));
            } else {
                $('.space-detail-building', card).html(fav.location.building_name);
            }

            // Load image carousel
            if (fav.hasOwnProperty('images') && fav.images.length > 0) {
                var template = H.compile($('#images_template').html());
                var data = [];
                $.each(fav.images, function () {
                    data.push({ id: fav.id, image_id: this.id });
                });

                $('.carousel-inner', card).html(template({ data: data }));
            } else {
                var template = H.compile($('#no_images_template').html());
                $('.carousel-inner', card).html(template({ static_url: window.spacescout_static_url }));
            }

            if (fav.has_reservation_notes) {
                var url = fav.extended_info.reservation_notes.match(/(http:\/\/[^\s]+)/);

                if (url) {
                   var template = H.compile($('#reservation_cue').html());
                   $('.space-info-reservation-cue', card).html(template({ url: url[1] })).show();
                }
            }
        },
        function () {
            initializeCarousel();
            initMapCarouselButtons();
        });
    }

})(Handlebars, jQuery);

<commit_msg>Accidental global variable<commit_after>/*
    Copyright 2014 UW Information Technology, University of Washington

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    Changes:

    =================================================================

*/

// H = Handlebars, $ = jQuery
(function (H, $) {

    window.spacescout_favorites = window.spacescout_favorites || {
        k: {
            'favorites_count_container': '.favorites_count_container',
            'favorites_count_template': '#favorites_count',
            'favorites_card_container': '.favorites_card_container',
            'favorites_card_template': '#favorites_card'
        },

        favorites: undefined,

        update_count: function () {
            var self = this,
                source = $(self.k.favorites_count_template),
                template;

            if (source.length) {
                template = H.compile(source.html().trim());
                $(this.k.favorites_count_container).each(function () {
                    $(this).html(template({count: self.favorites.length}));
                });
            }
        },

        update_search_result: function () {
            var self = this,
                detail_node = $('div[id^=detail_container_]'),
                detail_id = detail_node.length ? parseInt(detail_node.prop('id').match(/^detail_container_(\d+)$/)[1]) : null;

            $('button .space-detail-fav').each(function () {
                var node = $(this),
                    id = parseInt(node.parent().prop('id'));

                if (self.is_favorite(id)) {
                    node.show();
                    if (id == detail_id) {
                        $('.space-detail-fav', detail_node).addClass('space-detail-fav-set');
                    }
                } else {
                    node.hide();
                    if (id == detail_id) {
                        $('.space-detail-fav', detail_node).removeClass('space-detail-fav-set');
                    }
                }
            });
        },

        update_cards: function (on_card_load, on_finish) {
            var container = $(this.k.favorites_card_container),
                source, template;

            if (container.length == 1 && $.isArray(this.favorites)) {
                source = $(this.k.favorites_card_template).html();
                template = H.compile(source);
                var self = this;

                $.each(this.favorites, function () {
                    var spot = $('spot_' + this.id),
                        type = [], card;

                    if ($.isArray(this.type)) {
                        $.each(this.type, function () {
                            type.push(gettext(this));
                        });
                    }

                    this.type = type.join(', ');
                    this.extended_info.noise_level = gettext(this.extended_info.noise_level);
                    this.extended_info.food_nearby = gettext(this.extended_info.food_nearby);
                    this.has_reservation_notes = !!this.extended_info.reservation_notes;
                    this.has_notes = ( this.extended_info.access_notes || this.has_reservation_notes );
                    this.has_resources = ( this.extended_info.has_computers || this.extended_info.has_displays || this.extended_info.has_outlets || this.extended_info.has_printing || this.extended_info.has_projector || this.extended_info.has_scanner || this.extended_info.has_whiteboards );

                    card = $(template(this));

                    if (spot.length == 0) {
                        card.insertBefore('#space-detail-blank', container);
                    }

                    if (on_card_load) {
                        on_card_load.apply(self, [card, this]);
                    }
                });

                if (on_finish) {
                    on_finish.apply(self, []);
                }

            }
        },

        load: function (on_card_load, on_finish) {
            var self = this;

            $.ajax({
                url: 'api/v1/user/me/favorites',
                success: function (data) {
                    self.favorites = data ? data : [];
                    self.update(on_card_load, on_finish);
                },
                error: function (xhr, textStatus, errorThrown) {
                    console.log('Unable to load favorites: ' + xhr.responseText);
                }
            });
        },

        update: function (on_card_load, on_finished) {
            this.update_count();
            this.update_search_result();
            this.update_cards(on_card_load, on_finished);
        },

        is_favorite: function (id) {
            var fav = false;

            if (this.favorites) {
                fav = (this.index(id) >= 0);
            } else {
                $.ajax({
                    url: 'api/v1/user/me/favorite/' + id,
                    type: "GET",
                    async: false,
                    success: function (data) {
                        fav = data;
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        console.log('Unable to get favorite: ' + xhr.responseText);
                    }
                });
            }

            return fav;
        },

        index: function (id) {
            var i;

            if (this.favorites) {
                for (i = 0; i < this.favorites.length; i += 1) {
                    if (this.favorites[i].id == id) {
                        return i;
                    }
                }
            }

            return -1;
        },

        toggle: function (id, on_set, on_clear) {
            if (this.is_favorite(id)) {
                this.clear(id, on_clear);
            } else {
                this.set(id, on_set);
            }

            this.update_count();
        },

        set: function (id, on_set) {
            var self = this;

            if (!this.is_favorite(id)) {
                $.ajax({
                    url: 'api/v1/user/me/favorite/' + id,
                    dataType: 'json',
                    contentType: "application/json",
                    data: JSON.stringify({}),
                    type: "PUT",
                    success: function (data) {
                        if (self.favorites) {
                            self.favorites.push({
                                id: id,
                                incomplete: true
                            });
                        }

                        self.update_count();
                        if (on_set) {
                            on_set.call();
                        }
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        console.log('Unable to set favorite: ' + xhr.responseText);
                    }
                });
            }
        },

        clear: function (id, on_clear) {
            var self = this;

            $.ajax({
                url: 'api/v1/user/me/favorite/' + id,
                dataType: 'json',
                type: "DELETE",
                success: function (data) {
                    if (self.favorites) {
                        var index = self.index(id);

                        if (index >= 0) {
                            self.favorites.splice(index, 1);
                        }
                    }

                    self.update_count();
                    if (on_clear) {
                        on_clear.call();
                    }
                },
                error: function (xhr, textStatus, errorThrown) {
                    console.log('Unable to unset favorite: ' + xhr.responseText);
                }
            });
        }
    };

    if ($('.favorites_nav').length > 0) {
        window.spacescout_favorites.load(function (card, fav) {
            var now = new Date(),
                hour = now.getHours(),
                minute = now.getMinutes(),
                day = weekday_from_day(now.getDay()).toLowerCase(),
                formatted = 'Closed',
                o, c;

            if (fav.available_hours[day].length > 0) {
                $.each(fav.available_hours[day], function() {
                    this[0] = this[0].replace(/^0+/, '');
                    this[1] = this[1].replace(/^0+/, '');
                    o = this[0].split(':');
                    c = this[1].split(':');

                    if ((hour > parseInt(o[0]) && hour < parseInt(c[0]))
                        || (hour == parseInt(o[0]) && minute > parseInt(o[1]))
                        || (hour == parseInt(c[0]) && minute < parseInt(c[1]))) {
                        $('.space-detail-is-open', card).show();
                    }
                });

                formatted = to12Hour(fav.available_hours[day]).join(", ");
            }

            $('.space-info-hours-today span', card).html(formatted);

            $('.space-info-more-detail a', card).click(function (e) {
                var more_div = $(e.target).parent();

                more_div.slideUp('fast');
                more_div.next().slideDown('fast');
            });

            $('.space-info-less-detail a', card).click(function (e) {
                var ul = $(e.target).closest('ul');

                ul.slideUp('fast');
                ul.prev().slideDown('fast');
            });

            $('.space-detail-fav', card).tooltip({ placement: 'right',
                                                   title: 'Remove this space from Favorites' });
            $('.space-detail-fav', card).click(function (e) {
                var id = parseInt($(this).attr('data-id'));
                var container = $(this).closest('.space-detail-container');
                var tooltip = $(this).tooltip('hide');

                window.spacescout_favorites.clear(id, function () {
                    container.hide({ effect: 'fade', duration: 800,  complete: function () { this.remove(); } });
                });
            });

            var bld_code = fav.location.building_name.match(/.*\(([A-Z ]+)\)( [a-zA-Z]+)?$/);
            if (bld_code) {
                $('.space-detail-building', card).html(bld_code[1] + (bld_code[2] ? bld_code[2] : ''));
            } else {
                $('.space-detail-building', card).html(fav.location.building_name);
            }

            // Load image carousel
            if (fav.hasOwnProperty('images') && fav.images.length > 0) {
                var template = H.compile($('#images_template').html());
                var data = [];
                $.each(fav.images, function () {
                    data.push({ id: fav.id, image_id: this.id });
                });

                $('.carousel-inner', card).html(template({ data: data }));
            } else {
                var template = H.compile($('#no_images_template').html());
                $('.carousel-inner', card).html(template({ static_url: window.spacescout_static_url }));
            }

            if (fav.has_reservation_notes) {
                var url = fav.extended_info.reservation_notes.match(/(http:\/\/[^\s]+)/);

                if (url) {
                   var template = H.compile($('#reservation_cue').html());
                   $('.space-info-reservation-cue', card).html(template({ url: url[1] })).show();
                }
            }
        },
        function () {
            initializeCarousel();
            initMapCarouselButtons();
        });
    }

})(Handlebars, jQuery);

<|endoftext|>