<commit_before>/*globals define, _, WebGMEGlobal*/
/*jshint browser: true*/

define([
    'js/logger',
    'js/Constants',
    'js/RegistryKeys',
    'js/PanelBase/PanelBase',
    'js/Utils/ComponentSettings',
    'text!/api/visualizers'
], function (
    Logger,
    CONSTANTS,
    REGISTRY_KEYS,
    PanelBase,
    ComponentSettings,
    VisualizersJSON
) {
    'use strict';

    var VisualizerIds,
        AutoVizPanel;

    VisualizersJSON = JSON.parse(VisualizersJSON)
        .filter(viz => viz.panel.indexOf('/AutoVizPanel') === -1);
    VisualizerIds = VisualizersJSON.map(viz => viz.id);

    // This visualizer simply checks the validVisualizers in the given node
    // and loads the appropriate visualizer.
    //
    // It is very similar to the "Visualizer" in the core WebGME library
    // except it is completely UI-less
    AutoVizPanel = function (layoutManager, params) {
        var options = {};
        options[PanelBase.OPTIONS.LOGGER_INSTANCE_NAME] = 'AutoViz';
        PanelBase.call(this, options);

        this._layoutManager = layoutManager;
        this._params = params;
        // Add setting for embedded behavior
        this._params.embedded = true;

        this._activePanel = null;
        this._activePanelId = null;
        this._activeProject = null;
        this.currentNode = null;
        this._panels = {};

        this._territoryId = null;
        this._client = params.client;

        this.config = {
            preloadIds: [],
            visualizerOverrides: {}
        };
        ComponentSettings.resolveWithWebGMEGlobal(this.config, AutoVizPanel.getComponentId());
        this.preloadId = 0;

        //initialize event handlers
        this._initialize();
        this.preloadNext();

        this.logger.debug('ctor finished');
    };

    AutoVizPanel.getComponentId = function() {
        return 'AutoViz';
    };

    AutoVizPanel.prototype.preloadNext = function() {
        var panelId,
            panelIndex = -1;

        // Load the next visualizer id
        while (this.preloadId < this.config.preloadIds.length && panelIndex === -1) {
            panelId = this.config.preloadIds[this.preloadId++];
            panelIndex = VisualizerIds.indexOf(panelId);
        }

        if (panelIndex !== -1) {
            this.getPanel(VisualizersJSON[panelIndex].panel, this.preloadNext.bind(this));
        }
    };

    AutoVizPanel.prototype._initialize = function() {
        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
            (model, id) => {
                var currentProject = this._client.getActiveProjectName(),
                    refresh = this._activeProject !== currentProject ||
                        !this.currentNode || this.currentNode.getId() !== id;

                if (refresh) {
                    if (this._activeProject !== currentProject) {
                        this.logger.debug(`Project changed: ${this._activeProject} -> ${currentProject}`);
                    }
                    this.logger.debug(`Loading node "${id}"`);
                    this.selectedObjectChanged(id);
                    this._activeProject = currentProject;
                }
            });

        this._defaultPanelIndex = 0;
        for (var i = VisualizersJSON.length; i--;) {
            if (VisualizersJSON[i].default) {
                this._defaultPanelIndex = i;
            }
        }
    };

    AutoVizPanel.prototype.TERRITORY_RULE = {children: 0};
    AutoVizPanel.prototype.selectedObjectChanged = function(nodeId) {
        if (this._territoryId) {
            this._client.removeUI(this._territoryId);
        }

        if (typeof nodeId === 'string') {
            this._territoryId = this._client.addUI(this, events => {
                this.logger.debug(`Received ${events.length} events`);
                this._eventCallback(events);
            });
            this.logger.debug(`AutoViz current territory id is ${this._territoryId}`);

            this._selfPatterns = {};
            this._selfPatterns[nodeId] = this.TERRITORY_RULE;
            this.logger.debug(`updating territory: ${JSON.stringify(this._selfPatterns)}`);
            this._client.updateTerritory(this._territoryId, this._selfPatterns);
        }
    };

    AutoVizPanel.prototype._eventCallback = function(events) {
        var event = events.find(e => e.etype === CONSTANTS.TERRITORY_EVENT_LOAD),
            currentId = event ? event.eid : null,
            newNode;

        if (event) {
            this.logger.info(`received event for node "${currentId}"`);
            newNode = this._client.getNode(currentId);
            if (!this.currentNode || this.currentNode !== newNode) {
                this.currentNode = newNode;
                this.update();
            }
        }
    };

    // Update the active panel
    AutoVizPanel.prototype.update = function() {
        var panelId,
            panelIndex;

        panelId = this.getPanelId();

        // If the panel id does not exist or is undefined, set it to the defaultId
        panelIndex = VisualizerIds.indexOf(panelId);
        if (panelIndex === -1) {
            panelIndex = this._defaultPanelIndex;
        }

        this.logger.info(`setting active panel to ${panelId}`);
        this.setPanel(VisualizersJSON[panelIndex], () => {
            if (this._activePanel.control &&
                this._activePanel.control.selectedObjectChanged) {
                this.logger.info('invoking selectedObjectChanged on active panel');
                this._activePanel.control.selectedObjectChanged(this.currentNode.getId());
            }
        });
    };

    AutoVizPanel.prototype.getPanelId = function() {
        var base = this._client.getNode(this.currentNode.getMetaTypeId()),
            baseType = base && base.getAttribute('name');

        // If currentNode is the root node, use "" as the baseType
        if (this.currentNode.getId() === CONSTANTS.PROJECT_ROOT_ID) {
            baseType = '';
        }

        if (this.config.visualizerOverrides[baseType]) {
            return this.config.visualizerOverrides[baseType];
        }

        return (this.currentNode.getRegistry(REGISTRY_KEYS.VALID_VISUALIZERS) || '')
            .split(' ')
            .shift();
    };

    AutoVizPanel.prototype.setPanel = function(panelDesc, cb) {
        var self = this;

        // Load the panel
        this.getPanel(panelDesc.panel, function(panel) {
            if (self._activePanel) {
                self._activePanel.destroy();
                self._activePanel.$pEl.remove();
            }
            self._layoutManager.addPanel('activePanel', panel, 'center');
            self._activePanel = panel;
            // set read only
            self._activePanel.setReadOnly(self.isReadOnly());
            self._activePanelId = panelDesc.id;
            cb();
        });

        this._activePanelId = panelDesc.id;
    };

    AutoVizPanel.prototype.getPanel = function(panelPath, callback) {
        var self = this;

        if (this._panels[panelPath]) {
            callback(new this._panels[panelPath](this._layoutManager, this._params));
        } else {
            require([panelPath], function (PanelClass) {
                var panel = new PanelClass(self._layoutManager, self._params);
                self._panels[panelPath] = PanelClass;
                callback(panel);
            },
            function(err) {
                self.logger.error('Failed to download "' + err.requireModules[0] + '"');
            });

        }
    };

    AutoVizPanel.prototype._forwardFn = function(fn, args) {
        if (this._activePanel) {
            return this._activePanel[fn].apply(this._activePanel, args);
        }
    };

    _.extend(AutoVizPanel.prototype, PanelBase.prototype);

    // Pass through functions
    AutoVizPanel.prototype.setSize = function() {
        return this._forwardFn('setSize', arguments);
    };

    AutoVizPanel.prototype.destroy = function() {
        return this._forwardFn('destroy', arguments);
    };

    AutoVizPanel.prototype.clear = function() {
        return this._forwardFn('clear', arguments);
    };

    AutoVizPanel.prototype.afterAppend = function() {
        return this._forwardFn('afterAppend', arguments);
    };

    AutoVizPanel.prototype.setReadOnly = function() {
        PanelBase.prototype.setReadOnly.apply(this, arguments);
        return this._forwardFn('setReadOnly', arguments);
    };

    AutoVizPanel.prototype.isReadOnly = function() {
        return PanelBase.prototype.isReadOnly.apply(this, arguments);
    };

    AutoVizPanel.prototype.onReadOnlyChanged = function() {
        PanelBase.prototype.onReadOnlyChanged.apply(this, arguments);
        return this._forwardFn('onReadOnlyChanged', arguments);
    };

    return AutoVizPanel;
});
<commit_msg>Don't instantiate viz in getPanel. Fixes #30 (#31)<commit_after>/*globals define, _, WebGMEGlobal*/
/*jshint browser: true*/

define([
    'js/logger',
    'js/Constants',
    'js/RegistryKeys',
    'js/PanelBase/PanelBase',
    'js/Utils/ComponentSettings',
    'text!/api/visualizers'
], function (
    Logger,
    CONSTANTS,
    REGISTRY_KEYS,
    PanelBase,
    ComponentSettings,
    VisualizersJSON
) {
    'use strict';

    var VisualizerIds,
        AutoVizPanel;

    VisualizersJSON = JSON.parse(VisualizersJSON)
        .filter(viz => viz.panel.indexOf('/AutoVizPanel') === -1);
    VisualizerIds = VisualizersJSON.map(viz => viz.id);

    // This visualizer simply checks the validVisualizers in the given node
    // and loads the appropriate visualizer.
    //
    // It is very similar to the "Visualizer" in the core WebGME library
    // except it is completely UI-less
    AutoVizPanel = function (layoutManager, params) {
        var options = {};
        options[PanelBase.OPTIONS.LOGGER_INSTANCE_NAME] = 'AutoViz';
        PanelBase.call(this, options);

        this._layoutManager = layoutManager;
        this._params = params;
        // Add setting for embedded behavior
        this._params.embedded = true;

        this._activePanel = null;
        this._activePanelId = null;
        this._activeProject = null;
        this.currentNode = null;
        this._panels = {};

        this._territoryId = null;
        this._client = params.client;

        this.config = {
            preloadIds: [],
            visualizerOverrides: {}
        };
        ComponentSettings.resolveWithWebGMEGlobal(this.config, AutoVizPanel.getComponentId());
        this.preloadId = 0;

        //initialize event handlers
        this._initialize();
        this.preloadNext();

        this.logger.debug('ctor finished');
    };

    AutoVizPanel.getComponentId = function() {
        return 'AutoViz';
    };

    AutoVizPanel.prototype.preloadNext = function() {
        var panelId,
            panelIndex = -1;

        // Load the next visualizer id
        while (this.preloadId < this.config.preloadIds.length && panelIndex === -1) {
            panelId = this.config.preloadIds[this.preloadId++];
            panelIndex = VisualizerIds.indexOf(panelId);
        }

        if (panelIndex !== -1) {
            this.getPanel(VisualizersJSON[panelIndex].panel, this.preloadNext.bind(this));
        }
    };

    AutoVizPanel.prototype._initialize = function() {
        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
            (model, id) => {
                var currentProject = this._client.getActiveProjectName(),
                    refresh = this._activeProject !== currentProject ||
                        !this.currentNode || this.currentNode.getId() !== id;

                if (refresh) {
                    if (this._activeProject !== currentProject) {
                        this.logger.debug(`Project changed: ${this._activeProject} -> ${currentProject}`);
                    }
                    this.logger.debug(`Loading node "${id}"`);
                    this.selectedObjectChanged(id);
                    this._activeProject = currentProject;
                }
            });

        this._defaultPanelIndex = 0;
        for (var i = VisualizersJSON.length; i--;) {
            if (VisualizersJSON[i].default) {
                this._defaultPanelIndex = i;
            }
        }
    };

    AutoVizPanel.prototype.TERRITORY_RULE = {children: 0};
    AutoVizPanel.prototype.selectedObjectChanged = function(nodeId) {
        if (this._territoryId) {
            this._client.removeUI(this._territoryId);
        }

        if (typeof nodeId === 'string') {
            this._territoryId = this._client.addUI(this, events => {
                this.logger.debug(`Received ${events.length} events`);
                this._eventCallback(events);
            });
            this.logger.debug(`AutoViz current territory id is ${this._territoryId}`);

            this._selfPatterns = {};
            this._selfPatterns[nodeId] = this.TERRITORY_RULE;
            this.logger.debug(`updating territory: ${JSON.stringify(this._selfPatterns)}`);
            this._client.updateTerritory(this._territoryId, this._selfPatterns);
        }
    };

    AutoVizPanel.prototype._eventCallback = function(events) {
        var event = events.find(e => e.etype === CONSTANTS.TERRITORY_EVENT_LOAD),
            currentId = event ? event.eid : null,
            newNode;

        if (event) {
            this.logger.info(`received event for node "${currentId}"`);
            newNode = this._client.getNode(currentId);
            if (!this.currentNode || this.currentNode !== newNode) {
                this.currentNode = newNode;
                this.update();
            }
        }
    };

    // Update the active panel
    AutoVizPanel.prototype.update = function() {
        var panelId,
            panelIndex;

        panelId = this.getPanelId();

        // If the panel id does not exist or is undefined, set it to the defaultId
        panelIndex = VisualizerIds.indexOf(panelId);
        if (panelIndex === -1) {
            panelIndex = this._defaultPanelIndex;
        }

        this.logger.info(`setting active panel to ${panelId}`);
        this.setPanel(VisualizersJSON[panelIndex], () => {
            if (this._activePanel.control &&
                this._activePanel.control.selectedObjectChanged) {
                this.logger.info('invoking selectedObjectChanged on active panel');
                this._activePanel.control.selectedObjectChanged(this.currentNode.getId());
            }
        });
    };

    AutoVizPanel.prototype.getPanelId = function() {
        var base = this._client.getNode(this.currentNode.getMetaTypeId()),
            baseType = base && base.getAttribute('name');

        // If currentNode is the root node, use "" as the baseType
        if (this.currentNode.getId() === CONSTANTS.PROJECT_ROOT_ID) {
            baseType = '';
        }

        if (this.config.visualizerOverrides[baseType]) {
            return this.config.visualizerOverrides[baseType];
        }

        return (this.currentNode.getRegistry(REGISTRY_KEYS.VALID_VISUALIZERS) || '')
            .split(' ')
            .shift();
    };

    AutoVizPanel.prototype.setPanel = function(panelDesc, cb) {
        var self = this;

        // Load the panel
        this.getPanel(panelDesc.panel, function(PanelClass) {
            if (self._activePanel) {
                self._activePanel.destroy();
                self._activePanel.$pEl.remove();
            }
            var panel = new PanelClass(self._layoutManager, self._params);
            self._layoutManager.addPanel('activePanel', panel, 'center');
            self._activePanel = panel;
            // set read only
            self._activePanel.setReadOnly(self.isReadOnly());
            self._activePanelId = panelDesc.id;
            cb();
        });

        this._activePanelId = panelDesc.id;
    };

    AutoVizPanel.prototype.getPanel = function(panelPath, callback) {
        var self = this;

        if (this._panels[panelPath]) {
            callback(this._panels[panelPath]);
        } else {
            require([panelPath], function (PanelClass) {
                self._panels[panelPath] = PanelClass;
                callback(PanelClass);
            },
            function(err) {
                self.logger.error('Failed to download "' + err.requireModules[0] + '"');
            });

        }
    };

    AutoVizPanel.prototype._forwardFn = function(fn, args) {
        if (this._activePanel) {
            return this._activePanel[fn].apply(this._activePanel, args);
        }
    };

    _.extend(AutoVizPanel.prototype, PanelBase.prototype);

    // Pass through functions
    AutoVizPanel.prototype.setSize = function() {
        return this._forwardFn('setSize', arguments);
    };

    AutoVizPanel.prototype.destroy = function() {
        return this._forwardFn('destroy', arguments);
    };

    AutoVizPanel.prototype.clear = function() {
        return this._forwardFn('clear', arguments);
    };

    AutoVizPanel.prototype.afterAppend = function() {
        return this._forwardFn('afterAppend', arguments);
    };

    AutoVizPanel.prototype.setReadOnly = function() {
        PanelBase.prototype.setReadOnly.apply(this, arguments);
        return this._forwardFn('setReadOnly', arguments);
    };

    AutoVizPanel.prototype.isReadOnly = function() {
        return PanelBase.prototype.isReadOnly.apply(this, arguments);
    };

    AutoVizPanel.prototype.onReadOnlyChanged = function() {
        PanelBase.prototype.onReadOnlyChanged.apply(this, arguments);
        return this._forwardFn('onReadOnlyChanged', arguments);
    };

    return AutoVizPanel;
});
<|endoftext|>


<commit_before>// TODO store all visited subreddits as strings in an array
// TODO store { subreddit: visit count } dictionary for sorting

// Load the data at startup
chrome.omnibox.onInputStarted.addListener(
  function() {
    console.log("Extension loaded");
  }
);

// This event is fired each time the user updates the text in the omnibox,
// as long as the extension's keyword mode is still active.
chrome.omnibox.onInputChanged.addListener(
  function(text, suggest) {
    console.log('inputChanged: ' + text);
    suggest([
      {content: text + " one", description: "the first one"},
      {content: text + " number two", description: "the second entry"}
    ]);
  });

// This event is fired with the user accepts the input in the omnibox.
chrome.omnibox.onInputEntered.addListener(
  function(subreddit) {
    chrome.tabs.getSelected(null, function(tab){
      var url = "https://reddit.com/r/" + subreddit;
      console.log("Redirecting to: " + url);
      chrome.tabs.update(tab.id, {url: url});
    })
  });
<commit_msg>Now counts are stored, as are visited subreddits<commit_after>// TODO remove alerts for production?

// important variables
var storage = chrome.storage.sync;
var SUBS = "subs";

var subs = [];  // list of all subreddits
var counts = {};  // subreddit => visit count

// Mark subreddit as visited
function saveSubreddit(subreddit) {
  // Add if not already in subreddit list
  if(-1 == subs.indexOf(subreddit)) {
    subs.push(subreddit);
  }
  var data = {};
  data[SUBS] = subs;
  storage.set(data, function() {
    if(chrome.runtime.lastError) {
      console.error(chrome.runtime.lastError);
      alert(chrome.runtime.lastError);
    }
  });

  // Get the current visit count for the subreddit
  storage.get(subreddit, function(items) {
    var count = items[subreddit];
    if(undefined === count) {
      count = 0;
    }

    count++;

    // Save the incremented visit count for the subreddit
    counts[subreddit] = count;
    var data = {};
    data[subreddit] = count;
    storage.set(data, function() {
      if(chrome.runtime.lastError) {
        console.error(chrome.runtime.lastError);
        alert(chrome.runtime.lastError);
      }
    });
  });
}

function loadData() {
  storage.get(SUBS, function(items) {
    subs = items[SUBS];
    if(undefined === subs) {
      subs = [];
    }
  });
}

// Load the data at startup
chrome.omnibox.onInputStarted.addListener(
  function() {
    loadData();
  }
);

// This event is fired each time the user updates the text in the omnibox,
// as long as the extension's keyword mode is still active.
chrome.omnibox.onInputChanged.addListener(
  function(text, suggest) {
    console.log('inputChanged: ' + text);
    // TODO add smart suggestions
    // TODO match substring
    // TODO match fuzzy substrings
    // TODO sort by closeness
    var suggestions = [];
    for (var subreddit in counts) {
      suggestions.push({
        content: subreddit,
        description: subreddit + "(" + counts[subreddit] + ")"
      });
    }

    // Sort by visit count
    suggestions.sort(function(a,b) {
      if(counts[a.content] < counts[b.content])
        return 1;
      else if(counts[a.content] > counts[b.content])
        return -1;
      else
        return 0;
    });
    suggest(suggestions);
  });

// This event is fired with the user accepts the input in the omnibox.
chrome.omnibox.onInputEntered.addListener(
  function(subreddit) {
    chrome.tabs.getSelected(null, function(tab){
      var url = "https://reddit.com/r/" + subreddit;
      console.log("Redirecting to: " + url);
      chrome.tabs.update(tab.id, {url: url});

      // Add subreddit to visited-subreddit list
      saveSubreddit(subreddit);
    })
  });
<|endoftext|>


<commit_before>/* eslint max-nested-callbacks: 0  */

// ヘッダーのキーの小文字化
// JSONのパース
// ショートハンド

import { __util, ffetch } from '../sources/ffetch';

describe('__createFullUrl()', () => {
  describe('should generating a full url using base, param and query', () => {
    [
      {
        base: '/path/to/api/page/:page',
        param: { page: 1 },
        query: { order: ['published_at', 'id'], filter: 'open' },
        joined: '/path/to/api/page/1?order=published_at&order=id&filter=open',
      },
      {
        base: '/path/to/api/article/:articleId/comment/:commentId',
        param: { articleId: 23, commentId: 1045 },
        query: { for_admin: 'true' },
        joined: '/path/to/api/article/23/comment/1045?for_admin=true',
      },
      {
        base: '/path/to/api/article/:articleId/comment/:commentId',
        param: { articleId: 23, commentId: 1045 },
        query: {},
        joined: '/path/to/api/article/23/comment/1045',
      },
      {
        base: '/path/to/api',
        param: {},
        query: { order: ['published_at', 'id'], filter: 'open' },
        joined: '/path/to/api?order=published_at&order=id&filter=open',
      },
      {
        base: '/path/to/api',
        param: {},
        query: {},
        joined: '/path/to/api',
      },
      {
        base: '/path/to/api',
        /* eslint-disable no-undefined */
        param: undefined,
        query: undefined,
        /* eslint-enable no-undefined */
        joined: '/path/to/api',
      },
    ].forEach(({ base, param, query, joined }, i) => {
      it(`case ${i}`, () => {
        expect(__util.__createFullUrl(base, param, query)).to.be(joined);
      });
    });
  });
});

describe('ffetch()', () => {
  it('__createFullUrl() is called when call ffetch()', () => {
    const cached = __util.__createFullUrl;
    const mock = (...args) => {
      expect(args[0]).to.be('/path/to/api/article/:articleId');
      expect(args[1]).to.eql({ articleId: 23 });
      expect(args[2]).to.eql({ for_admin: 'true' });
    };

    __util.__createFullUrl = mock;

    ffetch('/path/to/api/article/:articleId', {
      method: 'GET',
      param: { articleId: 23 },
      query: { for_admin: 'true' },
    });

    __util.__createFullUrl = cached;
  });
});
<commit_msg>Add a test<commit_after>/* eslint max-nested-callbacks: 0  */

// ヘッダーのキーの小文字化
// JSONのパース
// ショートハンド

import { __util, ffetch } from '../sources/ffetch';

describe('__createFullUrl()', () => {
  describe('should generating a full url using base, param and query', () => {
    [
      {
        base: '/path/to/api/page/:page',
        param: { page: 1 },
        query: { order: ['published_at', 'id'], filter: 'open' },
        joined: '/path/to/api/page/1?order=published_at&order=id&filter=open',
      },
      {
        base: '/path/to/api/article/:articleId/comment/:commentId',
        param: { articleId: 23, commentId: 1045 },
        query: { for_admin: 'true' },
        joined: '/path/to/api/article/23/comment/1045?for_admin=true',
      },
      {
        base: '/path/to/api/article/:articleId/comment/:commentId',
        param: { articleId: 23, commentId: 1045 },
        query: {},
        joined: '/path/to/api/article/23/comment/1045',
      },
      {
        base: '/path/to/api',
        param: {},
        query: { order: ['published_at', 'id'], filter: 'open' },
        joined: '/path/to/api?order=published_at&order=id&filter=open',
      },
      {
        base: '/path/to/api',
        param: {},
        query: {},
        joined: '/path/to/api',
      },
      {
        base: '/path/to/api',
        /* eslint-disable no-undefined */
        param: undefined,
        query: undefined,
        /* eslint-enable no-undefined */
        joined: '/path/to/api',
      },
    ].forEach(({ base, param, query, joined }, i) => {
      it(`case ${i}`, () => {
        expect(__util.__createFullUrl(base, param, query)).to.be(joined);
      });
    });
  });

  it('__createFullUrl() is called when call ffetch()', () => {
    const cached = __util.__createFullUrl;
    const mock = (...args) => {
      expect(args[0]).to.be('/path/to/api/article/:articleId');
      expect(args[1]).to.eql({ articleId: 23 });
      expect(args[2]).to.eql({ for_admin: 'true' });
    };

    __util.__createFullUrl = mock;

    ffetch('/path/to/api/article/:articleId', {
      method: 'GET',
      param: { articleId: 23 },
      query: { for_admin: 'true' },
    });

    __util.__createFullUrl = cached;
  });
});

describe('ffetch()', () => {
  describe('should stringify body and add a header when body is JSON', () => {
    [
      {
        input: {
          header: {
            accept: 'text/html, text/plain, application/json',
          },
          body: {
            foo: 'bar',
            baz: 'quz',
          },
        },
        output: {
          header: {
            accept: 'text/html, text/plain, application/json',
            'content-type': 'application/json',
          },
          body: '{"foo":"bar","baz":"quz"}',
        },
      },
      {
        input: {
          header: {},
          body: ['foo', 'bar', 'buz'],
        },
        output: {
          header: {
            'content-type': 'application/json',
          },
          body: '["foo","bar","buz"]',
        },
      },
      {
        input: {},
        output: {
          header: {},
          /* eslint-disable no-undefined */
          body: undefined,
          /* eslint-enable no-undefined */
        },
      },
    ].forEach(({ input, output }, i) => {
      it(`case ${i}`, () => {
        const cached = global.fetch;
        const mock = (url, options) => {
          expect(options.header).to.eql(output.header);
          expect(options.body).to.eql(output.body);
        };

        global.fetch = mock;

        ffetch('/path/to/api', {
          method: 'GET',
          header: input.header,
          body: input.body,
        });

        global.fetch = cached;
      });
    });
  });
});
<|endoftext|>


<commit_before>const Game = require('./game');
const FlashTower = require('./flash-tower');
const SimpleTower = require('./simple-tower');
const ImageLoader = require('./image-loader');
const $ = require('jquery');

let game = new Game();
let board = game.board;
let towers = game.getTowers();
let currentTile = null;
let lastTile = null;

var mouseDown = false;
$(document).mousedown(function() {
    mouseDown = true;
}).mouseup(function() {
    mouseDown = false;
});

let canvas = document.getElementById('game-canvas');
let ctx = canvas.getContext('2d');

let simpleTowerButton = document.getElementById('simple-tower');
let flashTowerButton = document.getElementById('flash-tower');
let towerButtons = $('.tower-button');

let startButton = document.getElementById('start');
let numberOfLives = document.getElementById('number-of-lives');
let moneyAmount = document.getElementById('money-amount');

let imageLoader = new ImageLoader();
let images = imageLoader.init();

function drawBoard(ctx) {
  for (let { type, x, y } of board.tiles) {
    ctx.drawImage(images[type], x, y);
  }
}

function drawEnemies(ctx) {
  for (let enemy of game.retrieveAliveEnemies()) {
    if (enemy.constructor.name === 'SimpleEnemy'){
      ctx.drawImage(images.simpleEnemy, enemy.x, enemy.y);
    } else {
      ctx.drawImage(images.quickEnemy, enemy.x, enemy.y);
    }
  }
}

function drawTowers(ctx) {
  for (let tileTower of game.getTowerTiles()) {
    if (tileTower.tower.constructor.name === 'SimpleTower'){
      ctx.drawImage(images.simpleTower, tileTower.x, tileTower.y);
    } else {
      ctx.drawImage(images.flashTower, tileTower.x, tileTower.y);
    }
  }
}

function updateNumberOfLives() { numberOfLives.innerHTML = game.lives; }

function updateMoneyAmount() { moneyAmount.innerHTML = game.monies; }

function updateTowerButtons() {
  for (let i = 0; i < towerButtons.length; i ++) {
    let towerPrice = parseInt($(towerButtons[i]).find('.tower-price').text().substr(1));
    let currentMonies = game.monies;
    let towerButtonState = $(towerButtons[i]).attr('class').split(' ')[1];

    if (towerPrice <= currentMonies && towerButtonState === 'inactive') {
      $(towerButtons[i]).addClass('active');
      $(towerButtons[i]).removeClass('inactive');
    } else if (towerPrice > currentMonies && towerButtonState === 'active') {
      $(towerButtons[i]).removeClass('active');
      $(towerButtons[i]).addClass('inactive');
    }
  }
}

function nextTick() {
  updateTowerButtons();
  game.removeEnemiesOffRight();
  updateNumberOfLives();
  game.redirectEnemies();
  game.retrieveAliveEnemies().forEach(enemy => enemy.move());
  towers.forEach(tower => tower.shoot(game.retrieveAliveEnemiesOnBoard()));
  game.rewardMonies();
  updateMoneyAmount();
}

// Start game loop - before enemies are called
requestAnimationFrame(startLoop);
let gameNotStarted = true;

function startLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  updateTowerButtons();
  updateNumberOfLives();
  updateMoneyAmount();
  drawBoard(ctx);
  drawTowers(ctx);
  if (mouseDown) { drawTowerRange(ctx); }
  if (gameNotStarted) { requestAnimationFrame(startLoop); }
}

//  Main game loop
function gameLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  drawBoard(ctx);
  drawEnemies(ctx);
  drawTowers(ctx);
  if (mouseDown) { drawTowerRange(ctx); }
  nextTick();

  if (game.checkStatus() === 'ongoing'){
    requestAnimationFrame(gameLoop);
  } else if (game.checkStatus() === 'lose'){
    requestAnimationFrame(gameLose);
  } else if (game.checkStatus() === 'win'){
    requestAnimationFrame(gameWin);
  }
}

function gameLose() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.font = "48px sans-serif";
  ctx.fillText("You lost!", 300, 200);
}

function gameWin() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.font = "48px sans-serif";
  ctx.fillText("You won!", 300, 200);
}

//click events, need somewhere to live.
function getPosition(event) {
  return { x: event.x - canvas.offsetLeft, y: event.y - canvas.offsetTop };
}

function selectTile(event) {
  let clickPosition = getPosition(event);
  lastTile = currentTile;
  currentTile = board.getClickedTile(clickPosition.x, clickPosition.y);

  if (tileIsABuildTile(currentTile) && tileIsAHighlightedBuildTile(lastTile)) {
    lastTile.type = 'buildTile';
    currentTile.type = 'buildTileHighlighted';
    $('#tower-prompt').show();
    $('#click-build-site-prompt').hide();
  } else if (tileIsAHighlightedBuildTile(lastTile) && !tileIsABuildTile(currentTile)) {
    lastTile.type = 'buildTile';
    $('#tower-prompt').hide();
    $('#click-build-site-prompt').show();
  } else if (tileIsABuildTile(currentTile) && currentTile.vacant) {
    currentTile.type = 'buildTileHighlighted';
    $('#tower-prompt').show();
    $('#click-build-site-prompt').hide();
  }
}

function assignSimpleTower() {
  let simpleTower = new SimpleTower({ x: currentTile.centerX(), y: currentTile.centerY() });

  if (tileIsAHighlightedBuildTile(currentTile) && canAffordTower(simpleTower.price)) {
    currentTile.addTower(simpleTower);
    currentTile.type = 'buildTile';
    $('#tower-prompt').hide();
    $('#click-build-site-prompt').show();
    towers = game.getTowers();
    game.monies -= simpleTower.price;
  }
}

function assignFlashTower() {
  let flashTower = new FlashTower({ x: currentTile.centerX(), y: currentTile.centerY() });

  if (tileIsAHighlightedBuildTile(currentTile) && canAffordTower(flashTower.price)) {
    currentTile.addTower(flashTower);
    currentTile.type = 'buildTile';
    $('#tower-prompt').hide();
    $('#click-build-site-prompt').show();
    towers = game.getTowers();
    game.monies -= flashTower.price;
  }
}

function canAffordTower(price) {
  return game.monies >= price;
}

function tileIsABuildTile(tile) {
  return tile && tile.type === 'buildTile';
}

function tileIsAHighlightedBuildTile(tile) {
  return tile && tile.type === 'buildTileHighlighted';
}

function tileHasATower(tile) {
  return tile.tower !== undefined;
}

function drawTowerRange(ctx) {
  if (tileIsABuildTile(currentTile) && tileHasATower(currentTile)) {
    ctx.beginPath();
    ctx.arc(currentTile.centerX(), currentTile.centerY(), 100, 0, 2 * Math.PI, false);
    ctx.stroke();
  }
}

canvas.addEventListener("mousedown", selectTile);
simpleTowerButton.addEventListener("click", assignSimpleTower);
flashTowerButton.addEventListener("click", assignFlashTower);
startButton.addEventListener("click", function() {
  gameNotStarted = false;
  requestAnimationFrame(gameLoop);
});
<commit_msg>Disable the start button after it has been clicked. Will need to figure out how to re-enable it when going to the next level<commit_after>const Game = require('./game');
const FlashTower = require('./flash-tower');
const SimpleTower = require('./simple-tower');
const ImageLoader = require('./image-loader');
const $ = require('jquery');

let game = new Game();
let board = game.board;
let towers = game.getTowers();
let currentTile = null;
let lastTile = null;

var mouseDown = false;
$(document).mousedown(function() {
    mouseDown = true;
}).mouseup(function() {
    mouseDown = false;
});

let canvas = document.getElementById('game-canvas');
let ctx = canvas.getContext('2d');

let simpleTowerButton = document.getElementById('simple-tower');
let flashTowerButton = document.getElementById('flash-tower');
let towerButtons = $('.tower-button');

let startButton = document.getElementById('start');
let numberOfLives = document.getElementById('number-of-lives');
let moneyAmount = document.getElementById('money-amount');

let imageLoader = new ImageLoader();
let images = imageLoader.init();

function drawBoard(ctx) {
  for (let { type, x, y } of board.tiles) {
    ctx.drawImage(images[type], x, y);
  }
}

function drawEnemies(ctx) {
  for (let enemy of game.retrieveAliveEnemies()) {
    if (enemy.constructor.name === 'SimpleEnemy'){
      ctx.drawImage(images.simpleEnemy, enemy.x, enemy.y);
    } else {
      ctx.drawImage(images.quickEnemy, enemy.x, enemy.y);
    }
  }
}

function drawTowers(ctx) {
  for (let tileTower of game.getTowerTiles()) {
    if (tileTower.tower.constructor.name === 'SimpleTower'){
      ctx.drawImage(images.simpleTower, tileTower.x, tileTower.y);
    } else {
      ctx.drawImage(images.flashTower, tileTower.x, tileTower.y);
    }
  }
}

function updateNumberOfLives() { numberOfLives.innerHTML = game.lives; }

function updateMoneyAmount() { moneyAmount.innerHTML = game.monies; }

function updateTowerButtons() {
  for (let i = 0; i < towerButtons.length; i ++) {
    let towerPrice = parseInt($(towerButtons[i]).find('.tower-price').text().substr(1));
    let currentMonies = game.monies;
    let towerButtonState = $(towerButtons[i]).attr('class').split(' ')[1];

    if (towerPrice <= currentMonies && towerButtonState === 'inactive') {
      $(towerButtons[i]).addClass('active');
      $(towerButtons[i]).removeClass('inactive');
    } else if (towerPrice > currentMonies && towerButtonState === 'active') {
      $(towerButtons[i]).removeClass('active');
      $(towerButtons[i]).addClass('inactive');
    }
  }
}

function nextTick() {
  updateTowerButtons();
  game.removeEnemiesOffRight();
  updateNumberOfLives();
  game.redirectEnemies();
  game.retrieveAliveEnemies().forEach(enemy => enemy.move());
  towers.forEach(tower => tower.shoot(game.retrieveAliveEnemiesOnBoard()));
  game.rewardMonies();
  updateMoneyAmount();
}

// Start game loop - before enemies are called
requestAnimationFrame(startLoop);
let gameNotStarted = true;

function startLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  updateTowerButtons();
  updateNumberOfLives();
  updateMoneyAmount();
  drawBoard(ctx);
  drawTowers(ctx);
  if (mouseDown) { drawTowerRange(ctx); }
  if (gameNotStarted) { requestAnimationFrame(startLoop); }
}

//  Main game loop
function gameLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  drawBoard(ctx);
  drawEnemies(ctx);
  drawTowers(ctx);
  if (mouseDown) { drawTowerRange(ctx); }
  nextTick();

  if (game.checkStatus() === 'ongoing'){
    requestAnimationFrame(gameLoop);
  } else if (game.checkStatus() === 'lose'){
    requestAnimationFrame(gameLose);
  } else if (game.checkStatus() === 'win'){
    requestAnimationFrame(gameWin);
  }
}

function gameLose() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.font = "48px sans-serif";
  ctx.fillText("You lost!", 300, 200);
}

function gameWin() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.font = "48px sans-serif";
  ctx.fillText("You won!", 300, 200);
}

//click events, need somewhere to live.
function getPosition(event) {
  return { x: event.x - canvas.offsetLeft, y: event.y - canvas.offsetTop };
}

function selectTile(event) {
  let clickPosition = getPosition(event);
  lastTile = currentTile;
  currentTile = board.getClickedTile(clickPosition.x, clickPosition.y);

  if (tileIsABuildTile(currentTile) && tileIsAHighlightedBuildTile(lastTile)) {
    lastTile.type = 'buildTile';
    currentTile.type = 'buildTileHighlighted';
    $('#tower-prompt').show();
    $('#click-build-site-prompt').hide();
  } else if (tileIsAHighlightedBuildTile(lastTile) && !tileIsABuildTile(currentTile)) {
    lastTile.type = 'buildTile';
    $('#tower-prompt').hide();
    $('#click-build-site-prompt').show();
  } else if (tileIsABuildTile(currentTile) && currentTile.vacant) {
    currentTile.type = 'buildTileHighlighted';
    $('#tower-prompt').show();
    $('#click-build-site-prompt').hide();
  }
}

function assignSimpleTower() {
  let simpleTower = new SimpleTower({ x: currentTile.centerX(), y: currentTile.centerY() });

  if (tileIsAHighlightedBuildTile(currentTile) && canAffordTower(simpleTower.price)) {
    currentTile.addTower(simpleTower);
    currentTile.type = 'buildTile';
    $('#tower-prompt').hide();
    $('#click-build-site-prompt').show();
    towers = game.getTowers();
    game.monies -= simpleTower.price;
  }
}

function assignFlashTower() {
  let flashTower = new FlashTower({ x: currentTile.centerX(), y: currentTile.centerY() });

  if (tileIsAHighlightedBuildTile(currentTile) && canAffordTower(flashTower.price)) {
    currentTile.addTower(flashTower);
    currentTile.type = 'buildTile';
    $('#tower-prompt').hide();
    $('#click-build-site-prompt').show();
    towers = game.getTowers();
    game.monies -= flashTower.price;
  }
}

function canAffordTower(price) {
  return game.monies >= price;
}

function tileIsABuildTile(tile) {
  return tile && tile.type === 'buildTile';
}

function tileIsAHighlightedBuildTile(tile) {
  return tile && tile.type === 'buildTileHighlighted';
}

function tileHasATower(tile) {
  return tile.tower !== undefined;
}

function drawTowerRange(ctx) {
  if (tileIsABuildTile(currentTile) && tileHasATower(currentTile)) {
    ctx.beginPath();
    ctx.arc(currentTile.centerX(), currentTile.centerY(), 100, 0, 2 * Math.PI, false);
    ctx.stroke();
  }
}

canvas.addEventListener("mousedown", selectTile);
simpleTowerButton.addEventListener("click", assignSimpleTower);
flashTowerButton.addEventListener("click", assignFlashTower);
startButton.addEventListener("click", function() {
  gameNotStarted = false;
  $(startButton).attr('disabled', 'disabled');
  requestAnimationFrame(gameLoop);
});
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var ga_site = 'https://google-admin.corp.google.com';
var default_site = 'https://pantheon.corp.google.com/';
// var default_site = 'http://localhost:4567/';
var site = null;
var re = /(.*)\?project=(.*)\&token=(.*)/i

function refresh(token_link) {
  // proceed if token_link is not null
  if (token_link) {
    var match = token_link.match(re);
    // regexp matched groups start with index 1
    var project = match[2];
    var new_token = match[3];
    // alert(project);
    // alert(new_token);

    // loop through all tabs start with $site in current window
    chrome.tabs.query({url: site+'*', currentWindow: true}, function (tabs) {
      // since the extension click works only on a $site tab
      // there always will be one or more tabs whose url starts with $site
      for (var j = 0; j < tabs.length; ++j) {
        var tab = tabs[j];
        var tab_match = tab.url.match(re);

        if (tab_match) {
          // only refresh the tabs whose url related to token_link's $project
          if (tab_match[2] == project) {
            var new_url = tab_match[1]+'?project='+project+'&token='+new_token;
            chrome.tabs.update(tab.id, {url: new_url});
            // chrome.tabs.reload(tabs[j].id);
          }
        }
      }
    });
  } else {
    alert('No token link found.');
  }
}

// captured the token link from the source page, assign it to a local variable
chrome.extension.onRequest.addListener(function(link) {
  // alert('site:'+site);
  refresh(link);
});

chrome.browserAction.onClicked.addListener(function (tab) { //Fired when User Clicks ICON
  // get the stored site from storage
  chrome.storage.sync.get({
    site: default_site, // if no site parameter stored, use the default one
  }, function(stored) {
    site = stored.site;

    // Inspect whether the place where user clicked matches with our site
    if (tab.url.indexOf(ga_site) != -1) {
      chrome.tabs.executeScript(tab.id, {
          file: "token_link.js",
          allFrames: true,
      });
    } else {
      alert('The active tab MUST be: '+ga_site);
    }
  });
});
<commit_msg>wording change<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var ga_site = 'https://google-admin.corp.google.com';
var default_site = 'https://pantheon.corp.google.com/';
// var default_site = 'http://localhost:4567/';
var site = null;
var re = /(.*)\?project=(.*)\&token=(.*)/i

function refresh(token_link) {
  // proceed if token_link is not null
  if (token_link) {
    var match = token_link.match(re);
    // regexp matched groups start with index 1
    var project = match[2];
    var new_token = match[3];
    // alert(project);
    // alert(new_token);

    // loop through all tabs start with $site in current window
    chrome.tabs.query({url: site+'*', currentWindow: true}, function (tabs) {
      // since the extension click works only on a $site tab
      // there always will be one or more tabs whose url starts with $site
      for (var j = 0; j < tabs.length; ++j) {
        var tab = tabs[j];
        var tab_match = tab.url.match(re);

        if (tab_match) {
          // only refresh the tabs whose url related to token_link's $project
          if (tab_match[2] == project) {
            var new_url = tab_match[1]+'?project='+project+'&token='+new_token;
            chrome.tabs.update(tab.id, {url: new_url});
            // chrome.tabs.reload(tabs[j].id);
          }
        }
      }
    });
  } else {
    alert('No token link found.');
  }
}

// captured the token link from the source page, assign it to a local variable
chrome.extension.onRequest.addListener(function(link) {
  // alert('site:'+site);
  refresh(link);
});

chrome.browserAction.onClicked.addListener(function (tab) { //Fired when User Clicks ICON
  // get the stored site from storage
  chrome.storage.sync.get({
    site: default_site, // if no site parameter stored, use the default one
  }, function(stored) {
    site = stored.site;

    // Inspect whether the place where user clicked matches with our site
    if (tab.url.indexOf(ga_site) != -1) {
      chrome.tabs.executeScript(tab.id, {
          file: "token_link.js",
          allFrames: true,
      });
    } else {
      alert("Current tab's URL must be "+ga_site);
    }
  });
});
<|endoftext|>


<commit_before>import Router from 'koa-router'
import User from '../models/users'
import jwt from 'jsonwebtoken'

const router = new Router({ prefix: '/users' })

router.get('/',
  async (ctx) => {
    try {
      const users = User.find({}, '-password')
      ctx.body = users
    } catch(err) {
      this.throw(err, 500)
    }
  }
)

router.get('/:id',
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id, '-password')
      if(!user) {
        this.throw(404)
      }
      ctx.body = user
    } catch(err) {
      this.throw(err, 500)
    }
  }
)

router.post('/',
  async (ctx) => {
    const user = new User(ctx.request.body.user)
    try {
      await user.save()
      const token = jwt.sign({ id: user.id }, config.token)

      delete user.password

      ctx.body = {
        user,
        token
      }
    } catch(err) {
      ctx.throw(422, err)
    }
  }
)

router.put('/:id',
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id)

      if(!user) {
        throw new Error({ status: 404 })
      }

      Object.assign(user, ctx.request.body.user)

      await user.save()

      ctx.body = 200
    } catch (err) {
      ctx.throw(404)
    }
  }
)

router.delete('/:id',
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id)

      if(!user) {
        throw new Error({ status: 404 })
      }

      await user.remove()

      ctx.body = 200
    } catch (err) {
      ctx.throw(404)
    }
  }
)

export default router
<commit_msg>Remove password and salt from response<commit_after>import Router from 'koa-router'
import User from '../models/users'
import config from '../../config/config'
import jwt from 'jsonwebtoken'

const router = new Router({ prefix: '/users' })

router.get('/',
  async (ctx) => {
    try {
      const users = User.find({}, '-password -salt')
      ctx.body = users
    } catch(err) {
      this.throw(err, 500)
    }
  }
)

router.get('/:id',
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id, '-password -salt')
      if(!user) {
        this.throw(404)
      }
      ctx.body = user
    } catch(err) {
      this.throw(err, 500)
    }
  }
)

router.post('/',
  async (ctx) => {
    const user = new User(ctx.request.body.user)
    try {
      await user.save()
      const token = jwt.sign({ id: user.id }, config.token)

      const response = user.toJSON()

      delete response.password
      delete response.salt

      ctx.body = {
        user: response,
        token
      }
    } catch(err) {
      ctx.throw(422, err)
    }
  }
)

router.put('/:id',
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id)

      if(!user) {
        throw new Error({ status: 404 })
      }

      Object.assign(user, ctx.request.body.user)

      await user.save()

      ctx.body = 200
    } catch (err) {
      ctx.throw(404)
    }
  }
)

router.delete('/:id',
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id)

      if(!user) {
        throw new Error({ status: 404 })
      }

      await user.remove()

      ctx.body = 200
    } catch (err) {
      ctx.throw(404)
    }
  }
)

export default router
<|endoftext|>


<commit_before>Ext.define('devilry_nodeadmin.view.aggregatedstudentview.AggregatedStudentInfoOverview' ,{
  extend: 'Ext.container.Container',
  alias: 'widget.aggregatedstudentinfo',
  cls: 'bootstrap',
  title: 'Aggregated Student Info',

  store: 'AggregatedStudentInfoStore',

  layout: 'fit',
  padding: '40',
  autoScroll: true,

  items: [{
    xtype: 'box',
    itemId: 'AggregatedStudentInfoBox',
    //html: '
 Hello World
',
    tpl: ['
Aggregert Studentinformasjon
',
          '
{data.user.displayname} / {data.user.username}
',
              '<tpl for="data.grouped_by_hierarky">',
                      '
 {long_name}
',
                      '<tpl for="periods">',
                          '
 {long_name}
',
                      '</tpl>',
              '</tpl>',
              {

                help: function(rec) {
                  console.log(rec);

                }

              }]

  }]

});
<commit_msg>* Listing of student info<commit_after>Ext.define('devilry_nodeadmin.view.aggregatedstudentview.AggregatedStudentInfoOverview' ,{
  extend: 'Ext.container.Container',
  alias: 'widget.aggregatedstudentinfo',
  cls: 'bootstrap',
  title: 'Aggregated Student Info',

  store: 'AggregatedStudentInfoStore',

  layout: 'fit',
  padding: '40',
  autoScroll: true,

  items: [{
    xtype: 'box',
    itemId: 'AggregatedStudentInfoBox',
    //html: '
 Hello World
',
    tpl: ['
Aggregert Studentinformasjon
',
          '
{data.user.displayname} / {data.user.username}
',
              '<tpl for="data.grouped_by_hierarky">',
                      '
 {long_name}
',
                      '<tpl for="periods">',
                          '
 {long_name}
',
                          '<tpl for="assignments">',
                              '
 {long_name}
',
                              '<tpl for="groups">',
                                  '
 {status}
',
                                  '<tpl if="active_feedback">',
                                      '<tpl if="active_feedback.feedback.is_passing_grade">',
                                          '
 Approved
',
                                      '<tpl else>',
                                          '
 Not Approved
',
                                      '</tpl>',
                                  '</tpl>',
                              '</tpl>',
                          '</tpl>',
                      '</tpl>',
               '</tpl>',
              {

                help: function(rec) {
                  console.log("TPL: " + rec);

                }

              }]

  }]

});
<|endoftext|>


<commit_before>'use strict';

let Attributes = require('./Attributes');
let Error      = require('../Error');

/**
 * Light
 *
 * Light object
 */
class Light {
  /**
   * Constructor
   *
   * @param {Object} attributes Attributes
   * @param {Object} state      State
   */
  constructor(attributes, state) {
    this.attributes = new Attributes(attributes);
    this.state      = new Attributes(state);
  }

  /**
   * Get light id
   *
   * @return {string} Light id
   */
  get id() {
    return this.attributes.get('id');
  }

  /**
   * Get name
   *
   * @return {string} Name
   */
  get name() {
    return this.attributes.get('name');
  }

  /**
   * Set name
   *
   * @param {string} name Name
   */
  set name(name) {
    this.attributes.set('name', String(name));
  }

  /**
   * Get type
   *
   * @return {string} Type
   */
  get type() {
    return this.attributes.get('type');
  }

  /**
   * Get unique id
   *
   * @return {string} Unique id
   */
  get uniqueId() {
    return this.attributes.get('uniqueId');
  }

  /**
   * Get manufacturer
   *
   * @return {string} Manufacturer
   */
  get manufacturer() {
    return this.attributes.get('manufacturer');
  }

  /**
   * Get model id
   *
   * @return {string} Model id
   */
  get modelId() {
    return this.attributes.get('modelId');
  }

  /**
   * Get software version
   *
   * @return {string} Software version
   */
  get softwareVersion() {
    return this.attributes.get('softwareVersion');
  }

  /**
   * Get on
   *
   * @return {bool} True if on, false if not
   */
  get on() {
    return Boolean(this.state.get('on'));
  }

  /**
   * Set on
   *
   * @param {bool} value True for on, false if not
   */
  set on(value) {
    this.state.set('on', Boolean(value));
  }

  /**
   * Get reachable
   *
   * @return {bool} Reachable
   */
  get reachable() {
    return this.state.get('reachable');
  }

  /**
   * Get brightness
   *
   * @return {int} Brightness
   */
  get brightness() {
    return this.state.get('brightness');
  }

  /**
   * Set brightness
   *
   * @param {int} brightness Brightness
   */
  set brightness(brightness) {
    this.state.set('brightness', Number(brightness));
  }

  /**
   * Get color mode
   *
   * @return {string} Color mode
   */
  get colorMode() {
    return this.state.get('colorMode');
  }

  /**
   * Get hue
   *
   * @return {int} Hue
   */
  get hue() {
    return this.state.get('hue');
  }

  /**
   * Set hue
   *
   * @param {int} hue Hue
   */
  set hue(hue) {
    this.state.set('hue', Number(hue));
  }

  /**
   * Get saturation
   *
   * @return {int} Saturation
   */
  get saturation() {
    return this.state.get('saturation');
  }

  /**
   * Set saturation
   *
   * @param {int} saturation Saturation
   */
  set saturation(saturation) {
    this.state.set('saturation', Number(saturation));
  }

  /**
   * Get x/y
   *
   * @return {array} X/Y
   */
  get xy() {
    return this.state.get('xy');
  }

  /**
   * Set x/y
   *
   * @param {array} xy X/Y
   */
  set xy(xy) {
    this.state.set('xy', xy);
  }

  /**
   * Get color temperature
   *
   * @return {int} Temperature
   */
  get colorTemp() {
    return this.state.get('colorTemp');
  }

  /**
   * Set color temperature
   *
   * @param {int} temp Temperature
   */
  set colorTemp(temp) {
    this.state.set('colorTemp', Number(temp));
  }

  /**
   * Get transition time
   *
   * @return {int} Transition time
   */
  get transitionTime() {
    return this.state.get('transitionTime') / 10;
  }

  /**
   * Set transition time
   *
   * @param {int} time Time in seconds
   */
  set transitionTime(time) {
    this.state.set('transitionTime', Number(time) * 10);
  }

  /**
   * Get alert
   *
   * @return {string} Alert
   */
  get alert() {
    return this.state.get('alert');
  }

  /**
   * Set alert
   *
   * @param {string} mode Mode
   */
  set alert(mode) {
    this.state.set('alert', String(mode));
  }

  /**
   * Get effect
   *
   * @return {string} Effect
   */
  get effect() {
    return this.state.get('effect');
  }

  /**
   * Set effect
   *
   * @param {string} effect Effect
   */
  set effect(effect) {
    this.state.set('effect', String(effect));
  }

  /**
   * To string
   *
   * @return {string} Id
   */
  toString() {
    return this.id;
  }
}

module.exports = Light;
<commit_msg>GitHub #24 - Add support for retrieving light model<commit_after>'use strict';

let Attributes        = require('./Attributes');
let Error             = require('../Error');
let LightModelFactory = require('../LightModel/Factory');

/**
 * Light
 *
 * Light object
 */
class Light {
  /**
   * Constructor
   *
   * @param {Object} attributes Attributes
   * @param {Object} state      State
   */
  constructor(attributes, state) {
    this.attributes = new Attributes(attributes);
    this.state      = new Attributes(state);
  }

  /**
   * Get light id
   *
   * @return {string} Light id
   */
  get id() {
    return this.attributes.get('id');
  }

  /**
   * Get name
   *
   * @return {string} Name
   */
  get name() {
    return this.attributes.get('name');
  }

  /**
   * Set name
   *
   * @param {string} name Name
   */
  set name(name) {
    this.attributes.set('name', String(name));
  }

  /**
   * Get type
   *
   * @return {string} Type
   */
  get type() {
    return this.attributes.get('type');
  }

  /**
   * Get unique id
   *
   * @return {string} Unique id
   */
  get uniqueId() {
    return this.attributes.get('uniqueId');
  }

  /**
   * Get manufacturer
   *
   * @return {string} Manufacturer
   */
  get manufacturer() {
    return this.attributes.get('manufacturer');
  }

  /**
   * Get model id
   *
   * @return {string} Model id
   */
  get modelId() {
    return this.attributes.get('modelId');
  }

  /**
   * Get model
   *
   * Lazy loads model for the light
   *
   * @return {LightModel} Light model
   */
  get model() {
    if (this.lightModel === undefined) {
      this.lightModel = LightModelFactory.createLightModel(this.modelId);
    }

    return this.lightModel;
  }

  /**
   * Get software version
   *
   * @return {string} Software version
   */
  get softwareVersion() {
    return this.attributes.get('softwareVersion');
  }

  /**
   * Get on
   *
   * @return {bool} True if on, false if not
   */
  get on() {
    return Boolean(this.state.get('on'));
  }

  /**
   * Set on
   *
   * @param {bool} value True for on, false if not
   */
  set on(value) {
    this.state.set('on', Boolean(value));
  }

  /**
   * Get reachable
   *
   * @return {bool} Reachable
   */
  get reachable() {
    return this.state.get('reachable');
  }

  /**
   * Get brightness
   *
   * @return {int} Brightness
   */
  get brightness() {
    return this.state.get('brightness');
  }

  /**
   * Set brightness
   *
   * @param {int} brightness Brightness
   */
  set brightness(brightness) {
    this.state.set('brightness', Number(brightness));
  }

  /**
   * Get color mode
   *
   * @return {string} Color mode
   */
  get colorMode() {
    return this.state.get('colorMode');
  }

  /**
   * Get hue
   *
   * @return {int} Hue
   */
  get hue() {
    return this.state.get('hue');
  }

  /**
   * Set hue
   *
   * @param {int} hue Hue
   */
  set hue(hue) {
    this.state.set('hue', Number(hue));
  }

  /**
   * Get saturation
   *
   * @return {int} Saturation
   */
  get saturation() {
    return this.state.get('saturation');
  }

  /**
   * Set saturation
   *
   * @param {int} saturation Saturation
   */
  set saturation(saturation) {
    this.state.set('saturation', Number(saturation));
  }

  /**
   * Get x/y
   *
   * @return {array} X/Y
   */
  get xy() {
    return this.state.get('xy');
  }

  /**
   * Set x/y
   *
   * @param {array} xy X/Y
   */
  set xy(xy) {
    this.state.set('xy', xy);
  }

  /**
   * Get color temperature
   *
   * @return {int} Temperature
   */
  get colorTemp() {
    return this.state.get('colorTemp');
  }

  /**
   * Set color temperature
   *
   * @param {int} temp Temperature
   */
  set colorTemp(temp) {
    this.state.set('colorTemp', Number(temp));
  }

  /**
   * Get transition time
   *
   * @return {int} Transition time
   */
  get transitionTime() {
    return this.state.get('transitionTime') / 10;
  }

  /**
   * Set transition time
   *
   * @param {int} time Time in seconds
   */
  set transitionTime(time) {
    this.state.set('transitionTime', Number(time) * 10);
  }

  /**
   * Get alert
   *
   * @return {string} Alert
   */
  get alert() {
    return this.state.get('alert');
  }

  /**
   * Set alert
   *
   * @param {string} mode Mode
   */
  set alert(mode) {
    this.state.set('alert', String(mode));
  }

  /**
   * Get effect
   *
   * @return {string} Effect
   */
  get effect() {
    return this.state.get('effect');
  }

  /**
   * Set effect
   *
   * @param {string} effect Effect
   */
  set effect(effect) {
    this.state.set('effect', String(effect));
  }

  /**
   * To string
   *
   * @return {string} Id
   */
  toString() {
    return this.id;
  }
}

module.exports = Light;
<|endoftext|>


<commit_before>// Load in our dependencies
var async = require('async');
var which = require('which');
var _gm = require('gm');
var Canvas = require('./canvas');

// Determine if GraphicsMagick exists on our `PATH`
var gmExists = false;
try {
  gmExists = !!which.sync('gm');
} catch (e) {
  // Ignore errors for `gm` not existing
}

// Define our engine constructor
function Gmsmith(options) {
  this.gm = _gm;
  var useImageMagick = options.hasOwnProperty('imagemagick') ? options.imagemagick : !gmExists;
  if (useImageMagick) {
    this.gm = _gm.subClass({imageMagick: true});
  }
}
Gmsmith.specVersion = '2.0.0';
Gmsmith.prototype = {
  createCanvas: function (width, height) {
    // Generate our canvas and then callback with it in a bit
    var canvas = new Canvas(width, height, this);
    return canvas;
  },
  createImage: function (file, callback) {
    // If the file is an object (i.e. a vinyl object)
    if (typeof file === 'object') {
      // If it's not null, warn the users about loading excess content
      if (!file.isNull()) {
        console.warn('`gmsmith` doesn\'t support in-memory content ' +
          'but we saw in-memory content for "' + file.path + '". ' +
          'This can be disabled via `read: false` in `gulp.src`');
      }

      // Use the file path from the vinyl object
      file = file.path;
    }

    // Create the image
    var img = this.gm(file);

    // In series...
    async.waterfall([
      // Grab the size
      function getImgSize (cb) {
        img.size(cb);
      },
      function saveImgSize (size, cb) {
        // Create a structure for preserving the height and width of the image
        var imgFile = {
          height: size.height,
          width: size.width,
          file: file
        };

        // Callback with the imgFile
        cb(null, imgFile);
      }
    ], callback);
  },
  createImages: function (files, callback) {
    // Map the files into their image counterparts
    // DEV: Magic number of 10 to prevent file descriptor overuse
    // This does not affect perf -- 12 seconds with 300, 11.5 with 10 for 2000 images (derp)
    async.mapLimit(files, 10, this.createImage.bind(this), callback);
  }
};

// Export the engine
module.exports = Gmsmith;
<commit_msg>Default options to {} to avoid an exception when it's not passed in<commit_after>// Load in our dependencies
var async = require('async');
var which = require('which');
var _gm = require('gm');
var Canvas = require('./canvas');

// Determine if GraphicsMagick exists on our `PATH`
var gmExists = false;
try {
  gmExists = !!which.sync('gm');
} catch (e) {
  // Ignore errors for `gm` not existing
}

// Define our engine constructor
function Gmsmith(options) {
  options = options || {};
  this.gm = _gm;
  var useImageMagick = options.hasOwnProperty('imagemagick') ? options.imagemagick : !gmExists;
  if (useImageMagick) {
    this.gm = _gm.subClass({imageMagick: true});
  }
}
Gmsmith.specVersion = '2.0.0';
Gmsmith.prototype = {
  createCanvas: function (width, height) {
    // Generate our canvas and then callback with it in a bit
    var canvas = new Canvas(width, height, this);
    return canvas;
  },
  createImage: function (file, callback) {
    // If the file is an object (i.e. a vinyl object)
    if (typeof file === 'object') {
      // If it's not null, warn the users about loading excess content
      if (!file.isNull()) {
        console.warn('`gmsmith` doesn\'t support in-memory content ' +
          'but we saw in-memory content for "' + file.path + '". ' +
          'This can be disabled via `read: false` in `gulp.src`');
      }

      // Use the file path from the vinyl object
      file = file.path;
    }

    // Create the image
    var img = this.gm(file);

    // In series...
    async.waterfall([
      // Grab the size
      function getImgSize (cb) {
        img.size(cb);
      },
      function saveImgSize (size, cb) {
        // Create a structure for preserving the height and width of the image
        var imgFile = {
          height: size.height,
          width: size.width,
          file: file
        };

        // Callback with the imgFile
        cb(null, imgFile);
      }
    ], callback);
  },
  createImages: function (files, callback) {
    // Map the files into their image counterparts
    // DEV: Magic number of 10 to prevent file descriptor overuse
    // This does not affect perf -- 12 seconds with 300, 11.5 with 10 for 2000 images (derp)
    async.mapLimit(files, 10, this.createImage.bind(this), callback);
  }
};

// Export the engine
module.exports = Gmsmith;
<|endoftext|>


<commit_before>function getQWiki(info,tab) {

  // console.log("Word " + info.selectionText + " was clicked.");

  chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
      chrome.tabs.sendMessage(tabs[0].id , info.selectionText, function(response) {
    	// console.log("in resp");
      });
 	  }
  );

}

chrome.contextMenus.create({
  title: "QWiki: %s",
  contexts:["selection"],
  onclick: getQWiki
});<commit_msg>background.js: added message passing when command is recieved<commit_after>// send message to inject.js when option is selected from context menu
function getQWiki(info,tab) {

  // console.log("Word " + info.selectionText + " was clicked.");

  chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
      chrome.tabs.sendMessage(tabs[0].id , info.selectionText, function(response) {
      // console.log("in resp");
      });
    }
  );

}

// create an option in the context menu
chrome.contextMenus.create({
  title: "QWiki: %s",
  contexts:["selection"],
  onclick: getQWiki
});

// trigger when hotkey command is pressed
chrome.commands.onCommand.addListener(function(cmd){

  console.log("command:", cmd);

  chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
      // console.log("tabs", tabs);
      chrome.tabs.sendMessage(tabs[0].id , {action: "SendIt"}, function(response) {
    	 // console.log("in resp");
      });
 	  }
  );

});<|endoftext|>


<commit_before>/**
 *
 * @param {Integer} defaultCategoryId
 * @param {Function} eventsChangedCallback
 * @constructor
 */
var RcmEventManager = function (defaultCategoryId, eventsChangedCallback) {

    /**
     * Always refers to this object unlike the 'this' JS variable;
     *
     * @type {RcmEventManager}
     */
    var me = this;

    var eventsUrl = '/rcm-event-calender/events'

    var categories = [];
    /**
     */
    this.addEvent = function(){
        me.showEventPropertiesDialog(
            'New Event',
            {
                categoryId:defaultCategoryId,
                title:'',
                text:'',
                startDate:'',
                endDate:'',
                mapAddress:''
            },
            function(event, okButton){
                $.ajax({
                    url: eventsUrl,
                    type: 'POST',
                    data: event,
                    success: function(response) {
                        eventsChangedCallback();
                        okButton.dialog('close');
                    },
                    error:me.handleAjaxError
                });
            }
        );
    };

    this.handleAjaxError = function(){
        $().confirm(
            'There was a problem. Please Try again.'
        )
    }

    /**
     *
     * @param {Integer} eventId
     */
    this.deleteEvent = function(eventId){
        me.getEvent(
            eventId,
            function(event){
                $().confirm(
                    'Delete this event?

' + event.title,
                    function(){
                        $.ajax({
                            url: eventsUrl + '/' + eventId,
                            type: 'DELETE',
                            success: function(response) {
                                eventsChangedCallback();
                            },
                            error:me.handleAjaxError
                        });
                    }
                )
            }
        )
    };

    /**
     *
     * @param {Integer} eventId
     */
    this.editEvent = function(eventId){
        me.getEvent(
            eventId,
            function(event){
                me.showEventPropertiesDialog(
                    'Edit Event',
                    event,
                    function(event, okButton){
                        $.ajax({
                            url: eventsUrl + '/' + eventId,
                            type: 'PUT',
                            data: event,
                            success: function(response) {
                                eventsChangedCallback();
                                okButton.dialog('close');
                            },
                            error:me.handleAjaxError
                        });
                    }
                );
            }
        );
    }

    this.getEvent = function(eventId, callback){
        $.getJSON(
            eventsUrl + '/' + eventId,
                function(response) {
                callback(response)
            }
        ).error(me.handleAjaxError);
    }

    /**
     *
     * @param {Function} okCallback
     * @param {String} formTitle
     * @param {Object} [event]
     */
    this.showEventPropertiesDialog = function(formTitle, event, okCallback){
        var form = $('<form></form>').addClass('simple');
        form.addSelect('categoryId', 'Event Category', categories, event.categoryId);
        form.addInput('title', 'Title', event.title);
        form.addRichEdit('text', 'Text', event.text);
        form.addInput('startDate', 'Start Date (YYYY-MM-DD)', event.startDate);
        form.addInput('endDate', 'End Date (YYYY-MM-DD)', event.endDate);
        form.addInput('mapAddress', 'Map Address', event.mapAddress);

        form.dialog({
            title:formTitle,
            modal:true,
            width:620,
            buttons:{
                Cancel:function () {
                    $(this).dialog("close");
                },
                Ok:function () {

                    //Get user-entered data from form
                    event.categoryId= form.find('[name=categoryId]').val();
                    event.title= form.find('[name=title]').val();
                    event.startDate = form.find('[name=startDate]').val();
                    event.endDate = form.find('[name=endDate]').val();
                    event.mapAddress= form.find('[name=mapAddress]').val();

                    var editorId = form.find('.text').attr('id');
                    event.text = CKEDITOR.instances[editorId].getData();

                    okCallback(event,$(this));
                }
            }
        });
    }

    this.requestCategories = function(){
        $.getJSON(
            '/rcm-event-calender/categories',
            function(result) {
                categories=[];
                $.each(result, function(){
                    categories[this.categoryId]=this.name;
                });
            }
        );
    }

    this.requestCategories();

    this.getCategories = function(){
        return categories;
    }
};<commit_msg>event calender - fix default dates<commit_after>/**
 *
 * @param {Integer} defaultCategoryId
 * @param {Function} eventsChangedCallback
 * @constructor
 */
var RcmEventManager = function (defaultCategoryId, eventsChangedCallback) {

    /**
     * Always refers to this object unlike the 'this' JS variable;
     *
     * @type {RcmEventManager}
     */
    var me = this;

    var eventsUrl = '/rcm-event-calender/events'

    var categories = [];
    /**
     */
    this.addEvent = function(){
        me.showEventPropertiesDialog(
            'New Event',
            {
                categoryId:defaultCategoryId,
                title:'',
                text:'',
                startDate:me.getToday(),
                endDate:me.getToday(),
                mapAddress:''
            },
            function(event, okButton){
                $.ajax({
                    url: eventsUrl,
                    type: 'POST',
                    data: event,
                    success: function(response) {
                        eventsChangedCallback();
                        okButton.dialog('close');
                    },
                    error:me.handleAjaxError
                });
            }
        );
    };

    this.getToday = function(){
        var today = new Date();
        return today.getFullYear() + '-' + today.getMonth()+1 + '-'
            + today.getDate();
    }

    this.handleAjaxError = function(){
        $().confirm(
            'There was a problem. Please Try again.'
        )
    }

    /**
     *
     * @param {Integer} eventId
     */
    this.deleteEvent = function(eventId){
        me.getEvent(
            eventId,
            function(event){
                $().confirm(
                    'Delete this event?

' + event.title,
                    function(){
                        $.ajax({
                            url: eventsUrl + '/' + eventId,
                            type: 'DELETE',
                            success: function(response) {
                                eventsChangedCallback();
                            },
                            error:me.handleAjaxError
                        });
                    }
                )
            }
        )
    };

    /**
     *
     * @param {Integer} eventId
     */
    this.editEvent = function(eventId){
        me.getEvent(
            eventId,
            function(event){
                me.showEventPropertiesDialog(
                    'Edit Event',
                    event,
                    function(event, okButton){
                        $.ajax({
                            url: eventsUrl + '/' + eventId,
                            type: 'PUT',
                            data: event,
                            success: function(response) {
                                eventsChangedCallback();
                                okButton.dialog('close');
                            },
                            error:me.handleAjaxError
                        });
                    }
                );
            }
        );
    }

    this.getEvent = function(eventId, callback){
        $.getJSON(
            eventsUrl + '/' + eventId,
                function(response) {
                callback(response)
            }
        ).error(me.handleAjaxError);
    }

    /**
     *
     * @param {Function} okCallback
     * @param {String} formTitle
     * @param {Object} [event]
     */
    this.showEventPropertiesDialog = function(formTitle, event, okCallback){
        var form = $('<form></form>').addClass('simple');
        form.addSelect('categoryId', 'Event Category', categories, event.categoryId);
        form.addInput('title', 'Title', event.title);
        form.addRichEdit('text', 'Text', event.text);
        form.addInput('startDate', 'Start Date (YYYY-MM-DD)', event.startDate);
        form.addInput('endDate', 'End Date (YYYY-MM-DD)', event.endDate);
        form.addInput('mapAddress', 'Map Address', event.mapAddress);

        form.dialog({
            title:formTitle,
            modal:true,
            width:620,
            buttons:{
                Cancel:function () {
                    $(this).dialog("close");
                },
                Ok:function () {

                    //Get user-entered data from form
                    event.categoryId= form.find('[name=categoryId]').val();
                    event.title= form.find('[name=title]').val();
                    event.startDate = form.find('[name=startDate]').val();
                    event.endDate = form.find('[name=endDate]').val();
                    event.mapAddress= form.find('[name=mapAddress]').val();

                    var editorId = form.find('.text').attr('id');
                    event.text = CKEDITOR.instances[editorId].getData();

                    okCallback(event,$(this));
                }
            }
        });
    }

    this.requestCategories = function(){
        $.getJSON(
            '/rcm-event-calender/categories',
            function(result) {
                categories=[];
                $.each(result, function(){
                    categories[this.categoryId]=this.name;
                });
            }
        );
    }

    this.requestCategories();

    this.getCategories = function(){
        return categories;
    }
};<|endoftext|>