<commit_before>'use babel';

let Server;
let Client;
let Documentation;
let Helper;
let PackageConfig;
let Config;
let Type;
let Reference;
let Rename;
let _ = require('underscore-plus');

export default class Manager {

  constructor(provider) {

    this.initCalled = false;

    this.provider = provider;

    this.disposables = [];

    this.grammars = ['JavaScript'];

    this.clients = [];
    this.client = undefined;
    this.servers = [];
    this.server = undefined;

    this.editors = [];

    this.rename = undefined;
    this.type = undefined;
    this.reference = undefined;
    this.documentation = undefined;

    this.initialised = false;

    window.setTimeout(this.init.bind(this), 0);
  }

  init() {

    this.initCalled = true;

    Helper = require('./atom-ternjs-helper.coffee');
    PackageConfig = require('./atom-ternjs-package-config');
    Config = require('./atom-ternjs-config');

    this.helper = new Helper(this);
    this.packageConfig = new PackageConfig(this);
    this.config = new Config(this);
    this.provider.init(this);
    this.initServers();

    this.registerHelperCommands();

    this.disposables.push(atom.project.onDidChangePaths((paths) => {

      this.destroyServer(paths);
      this.checkPaths(paths);
      this.setActiveServerAndClient();
    }));
  }

  activate() {

    this.initialised = true;
    this.registerEvents();
    this.registerCommands();
  }

  destroyObject(object) {

    if (object) {

      object.destroy();
    }
    object = undefined;
  }

  destroy() {

    for (let server of this.servers) {

      server.destroy();
      server = undefined;
    }
    this.servers = [];

    for (let client of this.clients) {

      client = undefined;
    }
    this.clients = [];

    this.server = undefined;
    this.client = undefined;
    this.unregisterEventsAndCommands();
    this.provider = undefined;

    this.destroyObject(this.config);
    this.destroyObject(this.packageConfig);
    this.destroyObject(this.reference);
    this.destroyObject(this.rename);
    this.destroyObject(this.type);
    this.destroyObject(this.helper);

    this.initialised = false;
  }

  unregisterEventsAndCommands() {

    for (let disposable of this.disposables) {

      if (!disposable) {

        continue;
      }

      disposable.dispose();
    }

    this.disposables = [];
  }

  initServers() {

    let dirs = atom.project.getDirectories();

    if (dirs.length === 0) {

      return;
    }

    for (let dir of dirs) {

      dir = atom.project.relativizePath(dir.path)[0];

      if (this.helper.isDirectory(dir)) {

        this.startServer(dir);
      }
    }
  }

  startServer(dir) {

    if (!Server) {

      Server = require('./atom-ternjs-server');
    }

    if (this.getServerForProject(dir)) {

      return;
    }

    let client = this.getClientForProject(dir);

    if (!client) {

      if (!Client) {

        Client = require('./atom-ternjs-client');
      }

      let clientIdx = this.clients.push(new Client(this, dir)) - 1;
      client = this.clients[clientIdx];
    }

    this.servers.push(new Server(dir, client, this));

    if (this.servers.length === this.clients.length) {

      if (!this.initialised) {

        this.activate();
      }

      this.setActiveServerAndClient(dir);
    }
  }

  setActiveServerAndClient(URI) {

    if (!URI) {

      let activePane = atom.workspace.getActivePaneItem();

      if (activePane && activePane.getURI) {

        URI = activePane.getURI();

      } else {

        this.server = undefined;
        this.client = undefined;

        return;
      }
    }

    let dir = atom.project.relativizePath(URI)[0];
    let server = this.getServerForProject(dir);
    let client = this.getClientForProject(dir);

    if (server && client) {

      this.server = server;
      this.config.gatherData();
      this.client = client;

    } else {

      this.server = undefined;
      this.config.clear();
      this.client = undefined;
    }
  }

  checkPaths(paths) {

    for (let path of paths) {

      let dir = atom.project.relativizePath(path)[0];

      if (this.helper.isDirectory(dir)) {

        this.startServer(dir);
      }
    }
  }

  destroyServer(paths) {

    if (this.servers.length === 0) {

      return;
    }

    let serverIdx;

    for (let i = 0; i < this.servers.length; i++) {

      if (paths.indexOf(this.servers[i].projectDir) === -1) {

        serverIdx = i;
        break;
      }
    }

    if (serverIdx === undefined) {

      return;
    }

    let server = this.servers[serverIdx];
    let client = this.getClientForProject(server.projectDir);
    client = undefined;

    server.destroy();
    server = undefined;

    this.servers.splice(serverIdx, 1);
  }

  getServerForProject(projectDir) {

    for (let server of this.servers) {

      if (server.projectDir === projectDir) {

        return server;
      }
    }

    return false;
  }

  getClientForProject(projectDir) {

    for (let client of this.clients) {

      if (client.projectDir === projectDir) {

        return client;
      }
    }

    return false;
  }

  getEditor(editor) {

    for (let _editor of this.editors) {

      if (_editor.id === editor.id) {

        return _editor;
      }
    }
  }

  isValidEditor(editor) {

    if (!editor || !editor.getGrammar || editor.mini) {

      return;
    }

    if (!editor.getGrammar()) {

      return;
    }

    if (this.grammars.indexOf(editor.getGrammar().name) === -1) {

      return false;
    }

    return true;
  }

  onDidChangeCursorPosition(editor, e) {

    if (this.packageConfig.options.inlineFnCompletion) {

      if (!this.type) {

        Type = require('./atom-ternjs-type');
        this.type = new Type(this);
      }

      this.type.queryType(editor, e.cursor);
    }

    if (this.rename) {

      this.rename.hide();
    }
  }

  registerEvents() {

    this.disposables.push(atom.workspace.observeTextEditors((editor) => {

      if (!this.isValidEditor(editor)) {

        return;
      }

      // Register valid editor
      this.editors.push({

        id: editor.id,
        diffs: []
      });

      if (!this.initCalled) {

        this.init();
      }

      let editorView = atom.views.getView(editor);

      if (editorView) {

        this.disposables.push(editorView.addEventListener('click', (e) => {

          if (!e[this.helper.accessKey]) {

            return;
          }

          if (this.client) {

            this.client.definition();
          }
        }));
      }

      let scrollView;

      if (!editorView.shadowRoot) {

        scrollView = editorView.querySelector('.scroll-view');

      } else {

        scrollView = editorView.shadowRoot.querySelector('.scroll-view');
      }

      if (scrollView) {

        this.disposables.push(scrollView.addEventListener('mousemove', (e) => {

          if (!e[this.helper.accessKey]) {

            return;
          }

          if (e.target.classList.contains('line')) {

            return;
          }

          e.target.classList.add('atom-ternjs-hover');
        }));

        this.disposables.push(scrollView.addEventListener('mouseout', (e) => {

          e.target.classList.remove('atom-ternjs-hover');
        }));
      }

      this.disposables.push(editor.onDidChangeCursorPosition((e) => {

        if (this.type) {

          this.type.destroyOverlay();
        }

        if (this.documentation) {

          this.documentation.destroyOverlay();
        }
      }));

      this.disposables.push(editor.onDidChangeCursorPosition(_.debounce(this.onDidChangeCursorPosition.bind(this, editor), 300)));

      this.disposables.push(editor.getBuffer().onDidSave((e) => {

        if (this.client) {

          this.client.update(editor);
        }
      }));

      this.disposables.push(editor.getBuffer().onDidChange((e) => {

        this.getEditor(editor).diffs.push(e);
      }));
    }));

    this.disposables.push(atom.workspace.onDidChangeActivePaneItem((item) => {

      if (this.config) {

        this.config.clear();
      }

      if (this.type) {

        this.type.destroyOverlay();
      }

      if (this.rename) {

        this.rename.hide();
      }

      if (!this.isValidEditor(item)) {

        if (this.reference) {

          this.reference.hide();
        }

      } else {

        this.setActiveServerAndClient(item.getURI());
      }
    }));
  }

  registerHelperCommands() {

    this.disposables.push(atom.commands.add('atom-workspace', 'atom-ternjs:openConfig', (e) => {

      if (!this.config) {

        this.config = new Config(this);
      }

      this.config.show();
    }));
  }

  registerCommands() {

    this.disposables.push(atom.commands.add('atom-text-editor', 'core:cancel', (e) => {

      if (this.config) {

        this.config.hide();
      }

      if (this.type) {

        this.type.destroyOverlay();
      }

      if (this.rename) {

        this.rename.hide();
      }

      if (this.reference) {

        this.reference.hide();
      }

      if (this.documentation) {

        this.documentation.destroyOverlay();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:listFiles', (e) => {

      if (this.client) {

        this.client.files().then((data) => {

          console.dir(data);
        });
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:flush', (e) => {

      if (this.server) {

        this.server.flush();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:documentation', (e) => {

      if (!this.documentation) {

        Documentation = require('./atom-ternjs-documentation');
        this.documentation = new Documentation(this);
      }

      if (this.client) {

        this.documentation.request();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:references', (e) => {

      if (!this.reference) {

        Reference = require('./atom-ternjs-reference');
        this.reference = new Reference(this);
      }

      this.reference.findReference();
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:rename', (e) => {

      if (!this.rename) {

        Rename = require('./atom-ternjs-rename');
        this.rename = new Rename(this);
      }

      this.rename.show();
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:markerCheckpointBack', (e) => {

      if (this.helper) {

        this.helper.markerCheckpointBack();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:startCompletion', (e) => {

      if (this.provider) {

        this.provider.forceCompletion();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:definition', (e) => {

      if (this.client) {

        this.client.definition();
      }
    }));

    this.disposables.push(atom.commands.add('atom-workspace', 'atom-ternjs:restart', (e) => {

      this.restartServer();
    }));
  }

  restartServer() {

    if (!this.server) {

      return;
    }

    let dir = this.server.projectDir;
    let serverIdx;

    for (let i = 0; i < this.servers.length; i++) {

      if (dir === this.servers[i].projectDir) {

        serverIdx = i;
        break;
      }
    }

    if (this.server) {

      this.server.destroy();
    }

    this.server = undefined;
    this.servers.splice(serverIdx, 1);
    this.startServer(dir);
  }
}
<commit_msg>set initCalled to fals if destroy is called<commit_after>'use babel';

let Server;
let Client;
let Documentation;
let Helper;
let PackageConfig;
let Config;
let Type;
let Reference;
let Rename;
let _ = require('underscore-plus');

export default class Manager {

  constructor(provider) {

    this.initCalled = false;

    this.provider = provider;

    this.disposables = [];

    this.grammars = ['JavaScript'];

    this.clients = [];
    this.client = undefined;
    this.servers = [];
    this.server = undefined;

    this.editors = [];

    this.rename = undefined;
    this.type = undefined;
    this.reference = undefined;
    this.documentation = undefined;

    this.initialised = false;

    window.setTimeout(this.init.bind(this), 0);
  }

  init() {

    this.initCalled = true;

    Helper = require('./atom-ternjs-helper.coffee');
    PackageConfig = require('./atom-ternjs-package-config');
    Config = require('./atom-ternjs-config');

    this.helper = new Helper(this);
    this.packageConfig = new PackageConfig(this);
    this.config = new Config(this);
    this.provider.init(this);
    this.initServers();

    this.registerHelperCommands();

    this.disposables.push(atom.project.onDidChangePaths((paths) => {

      this.destroyServer(paths);
      this.checkPaths(paths);
      this.setActiveServerAndClient();
    }));
  }

  activate() {

    this.initialised = true;
    this.registerEvents();
    this.registerCommands();
  }

  destroyObject(object) {

    if (object) {

      object.destroy();
    }
    object = undefined;
  }

  destroy() {

    for (let server of this.servers) {

      server.destroy();
      server = undefined;
    }
    this.servers = [];

    for (let client of this.clients) {

      client = undefined;
    }
    this.clients = [];

    this.server = undefined;
    this.client = undefined;
    this.unregisterEventsAndCommands();
    this.provider = undefined;

    this.destroyObject(this.config);
    this.destroyObject(this.packageConfig);
    this.destroyObject(this.reference);
    this.destroyObject(this.rename);
    this.destroyObject(this.type);
    this.destroyObject(this.helper);

    this.initialised = false;
    this.initCalled = false;
  }

  unregisterEventsAndCommands() {

    for (let disposable of this.disposables) {

      if (!disposable) {

        continue;
      }

      disposable.dispose();
    }

    this.disposables = [];
  }

  initServers() {

    let dirs = atom.project.getDirectories();

    if (dirs.length === 0) {

      return;
    }

    for (let dir of dirs) {

      dir = atom.project.relativizePath(dir.path)[0];

      if (this.helper.isDirectory(dir)) {

        this.startServer(dir);
      }
    }
  }

  startServer(dir) {

    if (!Server) {

      Server = require('./atom-ternjs-server');
    }

    if (this.getServerForProject(dir)) {

      return;
    }

    let client = this.getClientForProject(dir);

    if (!client) {

      if (!Client) {

        Client = require('./atom-ternjs-client');
      }

      let clientIdx = this.clients.push(new Client(this, dir)) - 1;
      client = this.clients[clientIdx];
    }

    this.servers.push(new Server(dir, client, this));

    if (this.servers.length === this.clients.length) {

      if (!this.initialised) {

        this.activate();
      }

      this.setActiveServerAndClient(dir);
    }
  }

  setActiveServerAndClient(URI) {

    if (!URI) {

      let activePane = atom.workspace.getActivePaneItem();

      if (activePane && activePane.getURI) {

        URI = activePane.getURI();

      } else {

        this.server = undefined;
        this.client = undefined;

        return;
      }
    }

    let dir = atom.project.relativizePath(URI)[0];
    let server = this.getServerForProject(dir);
    let client = this.getClientForProject(dir);

    if (server && client) {

      this.server = server;
      this.config.gatherData();
      this.client = client;

    } else {

      this.server = undefined;
      this.config.clear();
      this.client = undefined;
    }
  }

  checkPaths(paths) {

    for (let path of paths) {

      let dir = atom.project.relativizePath(path)[0];

      if (this.helper.isDirectory(dir)) {

        this.startServer(dir);
      }
    }
  }

  destroyServer(paths) {

    if (this.servers.length === 0) {

      return;
    }

    let serverIdx;

    for (let i = 0; i < this.servers.length; i++) {

      if (paths.indexOf(this.servers[i].projectDir) === -1) {

        serverIdx = i;
        break;
      }
    }

    if (serverIdx === undefined) {

      return;
    }

    let server = this.servers[serverIdx];
    let client = this.getClientForProject(server.projectDir);
    client = undefined;

    server.destroy();
    server = undefined;

    this.servers.splice(serverIdx, 1);
  }

  getServerForProject(projectDir) {

    for (let server of this.servers) {

      if (server.projectDir === projectDir) {

        return server;
      }
    }

    return false;
  }

  getClientForProject(projectDir) {

    for (let client of this.clients) {

      if (client.projectDir === projectDir) {

        return client;
      }
    }

    return false;
  }

  getEditor(editor) {

    for (let _editor of this.editors) {

      if (_editor.id === editor.id) {

        return _editor;
      }
    }
  }

  isValidEditor(editor) {

    if (!editor || !editor.getGrammar || editor.mini) {

      return;
    }

    if (!editor.getGrammar()) {

      return;
    }

    if (this.grammars.indexOf(editor.getGrammar().name) === -1) {

      return false;
    }

    return true;
  }

  onDidChangeCursorPosition(editor, e) {

    if (this.packageConfig.options.inlineFnCompletion) {

      if (!this.type) {

        Type = require('./atom-ternjs-type');
        this.type = new Type(this);
      }

      this.type.queryType(editor, e.cursor);
    }

    if (this.rename) {

      this.rename.hide();
    }
  }

  registerEvents() {

    this.disposables.push(atom.workspace.observeTextEditors((editor) => {

      if (!this.isValidEditor(editor)) {

        return;
      }

      // Register valid editor
      this.editors.push({

        id: editor.id,
        diffs: []
      });

      if (!this.initCalled) {

        this.init();
      }

      let editorView = atom.views.getView(editor);

      if (editorView) {

        this.disposables.push(editorView.addEventListener('click', (e) => {

          if (!e[this.helper.accessKey]) {

            return;
          }

          if (this.client) {

            this.client.definition();
          }
        }));
      }

      let scrollView;

      if (!editorView.shadowRoot) {

        scrollView = editorView.querySelector('.scroll-view');

      } else {

        scrollView = editorView.shadowRoot.querySelector('.scroll-view');
      }

      if (scrollView) {

        this.disposables.push(scrollView.addEventListener('mousemove', (e) => {

          if (!e[this.helper.accessKey]) {

            return;
          }

          if (e.target.classList.contains('line')) {

            return;
          }

          e.target.classList.add('atom-ternjs-hover');
        }));

        this.disposables.push(scrollView.addEventListener('mouseout', (e) => {

          e.target.classList.remove('atom-ternjs-hover');
        }));
      }

      this.disposables.push(editor.onDidChangeCursorPosition((e) => {

        if (this.type) {

          this.type.destroyOverlay();
        }

        if (this.documentation) {

          this.documentation.destroyOverlay();
        }
      }));

      this.disposables.push(editor.onDidChangeCursorPosition(_.debounce(this.onDidChangeCursorPosition.bind(this, editor), 300)));

      this.disposables.push(editor.getBuffer().onDidSave((e) => {

        if (this.client) {

          this.client.update(editor);
        }
      }));

      this.disposables.push(editor.getBuffer().onDidChange((e) => {

        this.getEditor(editor).diffs.push(e);
      }));
    }));

    this.disposables.push(atom.workspace.onDidChangeActivePaneItem((item) => {

      if (this.config) {

        this.config.clear();
      }

      if (this.type) {

        this.type.destroyOverlay();
      }

      if (this.rename) {

        this.rename.hide();
      }

      if (!this.isValidEditor(item)) {

        if (this.reference) {

          this.reference.hide();
        }

      } else {

        this.setActiveServerAndClient(item.getURI());
      }
    }));
  }

  registerHelperCommands() {

    this.disposables.push(atom.commands.add('atom-workspace', 'atom-ternjs:openConfig', (e) => {

      if (!this.config) {

        this.config = new Config(this);
      }

      this.config.show();
    }));
  }

  registerCommands() {

    this.disposables.push(atom.commands.add('atom-text-editor', 'core:cancel', (e) => {

      if (this.config) {

        this.config.hide();
      }

      if (this.type) {

        this.type.destroyOverlay();
      }

      if (this.rename) {

        this.rename.hide();
      }

      if (this.reference) {

        this.reference.hide();
      }

      if (this.documentation) {

        this.documentation.destroyOverlay();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:listFiles', (e) => {

      if (this.client) {

        this.client.files().then((data) => {

          console.dir(data);
        });
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:flush', (e) => {

      if (this.server) {

        this.server.flush();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:documentation', (e) => {

      if (!this.documentation) {

        Documentation = require('./atom-ternjs-documentation');
        this.documentation = new Documentation(this);
      }

      if (this.client) {

        this.documentation.request();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:references', (e) => {

      if (!this.reference) {

        Reference = require('./atom-ternjs-reference');
        this.reference = new Reference(this);
      }

      this.reference.findReference();
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:rename', (e) => {

      if (!this.rename) {

        Rename = require('./atom-ternjs-rename');
        this.rename = new Rename(this);
      }

      this.rename.show();
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:markerCheckpointBack', (e) => {

      if (this.helper) {

        this.helper.markerCheckpointBack();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:startCompletion', (e) => {

      if (this.provider) {

        this.provider.forceCompletion();
      }
    }));

    this.disposables.push(atom.commands.add('atom-text-editor', 'atom-ternjs:definition', (e) => {

      if (this.client) {

        this.client.definition();
      }
    }));

    this.disposables.push(atom.commands.add('atom-workspace', 'atom-ternjs:restart', (e) => {

      this.restartServer();
    }));
  }

  restartServer() {

    if (!this.server) {

      return;
    }

    let dir = this.server.projectDir;
    let serverIdx;

    for (let i = 0; i < this.servers.length; i++) {

      if (dir === this.servers[i].projectDir) {

        serverIdx = i;
        break;
      }
    }

    if (this.server) {

      this.server.destroy();
    }

    this.server = undefined;
    this.servers.splice(serverIdx, 1);
    this.startServer(dir);
  }
}
<|endoftext|>


<commit_before>/**
 * Sitespeed.io - How speedy is your site? (http://www.sitespeed.io)
 * Copyright (c) 2014, Peter Hedenskog, Tobias Lidskog
 * and other contributors
 * Released under the Apache 2.0 License
 */
var Stats = require('fast-stats').Stats;
var util = require('../util/util');

/**
 * Create a aggregator that collects and aggregates statistics from web pages.
 * Each object needs to implement a processPage function that collects the data
 * for this aggregate.
 *
 * @param id - the ID of the aggregator, used for matching in rules & junit.
 * @param title - the title.
 * @param description -  a nice description on why and how for the aggregator.
 * @param type - what kind of aggregation is this? [timing,rule, pagemetric]
 * @param unit - the unit for the aggregator use one of [seconds|milliseconds|bytes|'']
 * @param decimals - how many decimals used when displaying the value
 * @param processPage - the function aggregating the data.
 */
function Aggregator(id, title, description, type, unit, decimals, processPage) {
  this.id = id;
  this.title = title;
  this.description = description;
  this.type = type;
  this.decimals = decimals;
  this.unit = unit;
  this.processPage = processPage;
  this.stats = new Stats();
}

Aggregator.prototype.generateResults = function() {
  return {
    id: this.id,
    title: this.title,
    desc: this.description,
    type: this.type,
    stats: util.getStatisticsObject(this.stats, this.decimals),
    unit: this.unit
  };
};

Aggregator.prototype.clear = function() {
  this.stats.reset();
};

module.exports = Aggregator;
<commit_msg>more comments<commit_after>/**
 * Sitespeed.io - How speedy is your site? (http://www.sitespeed.io)
 * Copyright (c) 2014, Peter Hedenskog, Tobias Lidskog
 * and other contributors
 * Released under the Apache 2.0 License
 */
var Stats = require('fast-stats').Stats;
var util = require('../util/util');

/**
 * Create a aggregator that collects and aggregates statistics from web pages.
 * Each object needs to implement a processPage function that collects the data
 * for this aggregate.
 *
 * @param id - the ID of the aggregator, used for matching in rules & junit.
 * @param title - the title.
 * @param description -  a nice description on why and how for the aggregator.
 * @param type - what kind of aggregation is this? [timing,rule, pagemetric]
 * @param unit - the unit for the aggregator use one of [seconds|milliseconds|bytes|'']
 * @param decimals - how many decimals used when displaying the value
 * @param processPage - the function aggregating the data.
 */
function Aggregator(id, title, description, type, unit, decimals, processPage) {
  this.id = id;
  this.title = title;
  this.description = description;
  this.type = type;
  this.decimals = decimals;
  this.unit = unit;
  this.processPage = processPage;
  this.key = id;
  this.stats = new Stats();
}

Aggregator.prototype.generateResults = function() {
  return {
    id: this.id,
    title: this.title,
    desc: this.description,
    type: this.type,
    stats: util.getStatisticsObject(this.stats, this.decimals),
    unit: this.unit,
    key: this.key
  };
};

/*
// Each aggretor needs to implement a processPage function
// that is called for every page & the data is picked up
// In this class, we just feed in the constructor
Aggregator.prototype.processPage = function(pageData) {
}
*/

Aggregator.prototype.clear = function() {
  this.stats.reset();
};

module.exports = Aggregator;
<|endoftext|>


<commit_before>/* eslint-disable */
import videojs from 'video.js';
import { version as VERSION } from './package.json';
import ConcreteButton from './ConcreteButton';
import ConcreteMenuItem from './ConcreteMenuItem';

// Default options for the plugin.
const defaults = {};

// Cross-compatibility for Video.js 5 and 6.
const registerPlugin = videojs.registerPlugin || videojs.plugin;

/**
 * VideoJS HLS Quality Selector Plugin class.
 */
class HlsQualitySelectorPlugin {
  /**
   * Plugin Constructor.
   *
   * @param {Player} player - The videojs player instance.
   * @param {Object} options - The plugin options.
   */
  constructor(player, options) {
    this.player = player;
    this.config = options;

    // Ensure dependencies are met
    if (!this.player.qualityLevels) {
      console.error(`Error: Missing video.js quality levels plugin (required) - videojs-hls-quality-selector`);
      return;
    }

    this.setupPlugin();
  }

  setupPlugin() {
    // Create the quality button.
    this.createQualityButton();

    // Hide quality selector by default
    this._qualityButton.hide();

    // Bind event listeners
    this.bindPlayerEvents();

    // Listen for source changes
    this.player.on('loadedmetadata', (e) => {
      this.updatePlugin();
    });
  }

  updatePlugin() {
    // If there is the HLS tech
    if (this.getHls()) {
      // Show quality selector
      this._qualityButton.show();
    } else {
      // Hide quality selector
      this._qualityButton.hide();
    }
  }

  /**
   * Returns HLS Plugin
   *
   * @return {*} - videojs-hls-contrib plugin.
   */
  getHls() {
    return this.player.tech({ IWillNotUseThisInPlugins: true }).vhs;
  }

  /**
   * Binds listener for quality level changes.
   */
  bindPlayerEvents() {
    this.player.qualityLevels().on('addqualitylevel', this.onAddQualityLevel.bind(this));
  }

  /**
   * Adds the quality menu button to the player control bar.
   */
  createQualityButton() {
    const player = this.player;

    this._qualityButton = new ConcreteButton(player);

    const placementIndex = player.controlBar.children().length - 2;
    const concreteButtonInstance = player.controlBar.addChild(
      this._qualityButton,
      { componentClass: 'qualitySelector' },
      this.config.placementIndex || placementIndex
    );

    concreteButtonInstance.addClass('vjs-quality-selector');
    if (!this.config.displayCurrentQuality) {
      const icon = ` ${this.config.vjsIconClass || 'vjs-icon-hd'}`;

      concreteButtonInstance.menuButton_.$('.vjs-icon-placeholder').className += icon;
    } else {
      this.setButtonInnerText('auto');
    }
    concreteButtonInstance.removeClass('vjs-hidden');
  }

  /**
   *Set inner button text.
   *
   * @param {string} text - the text to display in the button.
   */
  setButtonInnerText(text) {
    this._qualityButton.menuButton_.$('.vjs-icon-placeholder').innerHTML = text;
  }

  /**
   * Builds individual quality menu items.
   *
   * @param {Object} item - Individual quality menu item.
   * @return {ConcreteMenuItem} - Menu item
   */
  getQualityMenuItem(item) {
    const player = this.player;

    return new ConcreteMenuItem(player, item, this._qualityButton, this);
  }

  /**
   * Executed when a quality level is added from HLS playlist.
   */
  onAddQualityLevel() {
    const player = this.player;
    const qualityList = player.qualityLevels();
    const levels = qualityList.levels_ || [];
    const levelItems = [];

    for (let i = 0; i < levels.length; ++i) {
      if (
        !levelItems.filter((_existingItem) => {
          return _existingItem.item && _existingItem.item.value === levels[i].height;
        }).length
      ) {
        const levelItem = this.getQualityMenuItem.call(this, {
          label: levels[i].height + 'p',
          value: levels[i].height,
        });

        levelItems.push(levelItem);
      }
    }

    levelItems.sort((current, next) => {
      if (typeof current !== 'object' || typeof next !== 'object') {
        return -1;
      }
      if (current.item.value < next.item.value) {
        return -1;
      }
      if (current.item.value > next.item.value) {
        return 1;
      }
      return 0;
    });

    levelItems.push(
      this.getQualityMenuItem.call(this, {
        label: player.localize('Auto'),
        value: 'auto',
        selected: true,
      })
    );

    if (this._qualityButton) {
      this._qualityButton.createItems = function () {
        return levelItems;
      };
      this._qualityButton.update();
    }
  }

  /**
   * Sets quality (based on media height)
   *
   * @param {number} height - A number representing HLS playlist.
   */
  setQuality(height) {
    const qualityList = this.player.qualityLevels();

    // Set quality on plugin
    this._currentQuality = height;

    if (this.config.displayCurrentQuality) {
      this.setButtonInnerText(height === 'auto' ? height : `${height}p`);
    }

    for (let i = 0; i < qualityList.length; ++i) {
      const quality = qualityList[i];

      quality.enabled = quality.height === height || height === 'auto';
    }
    this._qualityButton.unpressButton();
  }

  /**
   * Return the current set quality or 'auto'
   *
   * @return {string} the currently set quality
   */
  getCurrentQuality() {
    return this._currentQuality || 'auto';
  }
}

/**
 * Function to invoke when the player is ready.
 *
 * This is a great place for your plugin to initialize itself. When this
 * function is called, the player will have its DOM and child components
 * in place.
 *
 * @function onPlayerReady
 * @param    {Player} player
 *           A Video.js player object.
 *
 * @param    {Object} [options={}]
 *           A plain object containing options for the plugin.
 */
const onPlayerReady = (player, options) => {
  player.addClass('vjs-hls-quality-selector');
  player.hlsQualitySelector = new HlsQualitySelectorPlugin(player, options);
};

/**
 * A video.js plugin.
 *
 * In the plugin function, the value of `this` is a video.js `Player`
 * instance. You cannot rely on the player being in a "ready" state here,
 * depending on how the plugin is invoked. This may or may not be important
 * to you; if not, remove the wait for "ready"!
 *
 * @function hlsQualitySelector
 * @param    {Object} [options={}]
 *           An object of options left to the plugin author to define.
 */
const hlsQualitySelector = function (options) {
  this.ready(() => {
    onPlayerReady(this, videojs.mergeOptions(defaults, options));
  });
};

// Register the plugin with video.js.
registerPlugin('hlsQualitySelector', hlsQualitySelector);

// Include the version number.
hlsQualitySelector.VERSION = VERSION;

export default hlsQualitySelector;
/* eslint-enable */
<commit_msg>rename getHls to getVhs<commit_after>/* eslint-disable */
import videojs from 'video.js';
import { version as VERSION } from './package.json';
import ConcreteButton from './ConcreteButton';
import ConcreteMenuItem from './ConcreteMenuItem';

// Default options for the plugin.
const defaults = {};

// Cross-compatibility for Video.js 5 and 6.
const registerPlugin = videojs.registerPlugin || videojs.plugin;

/**
 * VideoJS HLS Quality Selector Plugin class.
 */
class HlsQualitySelectorPlugin {
  /**
   * Plugin Constructor.
   *
   * @param {Player} player - The videojs player instance.
   * @param {Object} options - The plugin options.
   */
  constructor(player, options) {
    this.player = player;
    this.config = options;

    // Ensure dependencies are met
    if (!this.player.qualityLevels) {
      console.error(`Error: Missing video.js quality levels plugin (required) - videojs-hls-quality-selector`);
      return;
    }

    this.setupPlugin();
  }

  setupPlugin() {
    // Create the quality button.
    this.createQualityButton();

    // Hide quality selector by default
    this._qualityButton.hide();

    // Bind event listeners
    this.bindPlayerEvents();

    // Listen for source changes
    this.player.on('loadedmetadata', (e) => {
      this.updatePlugin();
    });
  }

  updatePlugin() {
    // If there is the VHS tech
    if (this.getVhs()) {
      // Show quality selector
      this._qualityButton.show();
    } else {
      // Hide quality selector
      this._qualityButton.hide();
    }
  }

  /**
   * Deprecated, returns VHS plugin
   *
   * @return {*} - videojs-http-streaming plugin.
   */
  getHls() {
    console.warn('hls-quality-selector: WARN: Using getHls options is deprecated. Use getVhs instead.')
    return this.getVhs();
  }

  /**
   * Returns VHS Plugin
   *
   * @return {*} - videojs-http-streaming plugin.
   */
  getVhs() {
    return this.player.tech({ IWillNotUseThisInPlugins: true }).vhs;
  }

  /**
   * Binds listener for quality level changes.
   */
  bindPlayerEvents() {
    this.player.qualityLevels().on('addqualitylevel', this.onAddQualityLevel.bind(this));
  }

  /**
   * Adds the quality menu button to the player control bar.
   */
  createQualityButton() {
    const player = this.player;

    this._qualityButton = new ConcreteButton(player);

    const placementIndex = player.controlBar.children().length - 2;
    const concreteButtonInstance = player.controlBar.addChild(
      this._qualityButton,
      { componentClass: 'qualitySelector' },
      this.config.placementIndex || placementIndex
    );

    concreteButtonInstance.addClass('vjs-quality-selector');
    if (!this.config.displayCurrentQuality) {
      const icon = ` ${this.config.vjsIconClass || 'vjs-icon-hd'}`;

      concreteButtonInstance.menuButton_.$('.vjs-icon-placeholder').className += icon;
    } else {
      this.setButtonInnerText('auto');
    }
    concreteButtonInstance.removeClass('vjs-hidden');
  }

  /**
   *Set inner button text.
   *
   * @param {string} text - the text to display in the button.
   */
  setButtonInnerText(text) {
    this._qualityButton.menuButton_.$('.vjs-icon-placeholder').innerHTML = text;
  }

  /**
   * Builds individual quality menu items.
   *
   * @param {Object} item - Individual quality menu item.
   * @return {ConcreteMenuItem} - Menu item
   */
  getQualityMenuItem(item) {
    const player = this.player;

    return new ConcreteMenuItem(player, item, this._qualityButton, this);
  }

  /**
   * Executed when a quality level is added from HLS playlist.
   */
  onAddQualityLevel() {
    const player = this.player;
    const qualityList = player.qualityLevels();
    const levels = qualityList.levels_ || [];
    const levelItems = [];

    for (let i = 0; i < levels.length; ++i) {
      if (
        !levelItems.filter((_existingItem) => {
          return _existingItem.item && _existingItem.item.value === levels[i].height;
        }).length
      ) {
        const levelItem = this.getQualityMenuItem.call(this, {
          label: levels[i].height + 'p',
          value: levels[i].height,
        });

        levelItems.push(levelItem);
      }
    }

    levelItems.sort((current, next) => {
      if (typeof current !== 'object' || typeof next !== 'object') {
        return -1;
      }
      if (current.item.value < next.item.value) {
        return -1;
      }
      if (current.item.value > next.item.value) {
        return 1;
      }
      return 0;
    });

    levelItems.push(
      this.getQualityMenuItem.call(this, {
        label: player.localize('Auto'),
        value: 'auto',
        selected: true,
      })
    );

    if (this._qualityButton) {
      this._qualityButton.createItems = function () {
        return levelItems;
      };
      this._qualityButton.update();
    }
  }

  /**
   * Sets quality (based on media height)
   *
   * @param {number} height - A number representing HLS playlist.
   */
  setQuality(height) {
    const qualityList = this.player.qualityLevels();

    // Set quality on plugin
    this._currentQuality = height;

    if (this.config.displayCurrentQuality) {
      this.setButtonInnerText(height === 'auto' ? height : `${height}p`);
    }

    for (let i = 0; i < qualityList.length; ++i) {
      const quality = qualityList[i];

      quality.enabled = quality.height === height || height === 'auto';
    }
    this._qualityButton.unpressButton();
  }

  /**
   * Return the current set quality or 'auto'
   *
   * @return {string} the currently set quality
   */
  getCurrentQuality() {
    return this._currentQuality || 'auto';
  }
}

/**
 * Function to invoke when the player is ready.
 *
 * This is a great place for your plugin to initialize itself. When this
 * function is called, the player will have its DOM and child components
 * in place.
 *
 * @function onPlayerReady
 * @param    {Player} player
 *           A Video.js player object.
 *
 * @param    {Object} [options={}]
 *           A plain object containing options for the plugin.
 */
const onPlayerReady = (player, options) => {
  player.addClass('vjs-hls-quality-selector');
  player.hlsQualitySelector = new HlsQualitySelectorPlugin(player, options);
};

/**
 * A video.js plugin.
 *
 * In the plugin function, the value of `this` is a video.js `Player`
 * instance. You cannot rely on the player being in a "ready" state here,
 * depending on how the plugin is invoked. This may or may not be important
 * to you; if not, remove the wait for "ready"!
 *
 * @function hlsQualitySelector
 * @param    {Object} [options={}]
 *           An object of options left to the plugin author to define.
 */
const hlsQualitySelector = function (options) {
  this.ready(() => {
    onPlayerReady(this, videojs.mergeOptions(defaults, options));
  });
};

// Register the plugin with video.js.
registerPlugin('hlsQualitySelector', hlsQualitySelector);

// Include the version number.
hlsQualitySelector.VERSION = VERSION;

export default hlsQualitySelector;
/* eslint-enable */
<|endoftext|>


<commit_before>var shuffle = require('shuffle-array');
const STATES = require('../models/states');
var models = require('../models/index');
var PostService = require('./../services/post.service');
var ZiviService = require('./../services/zivi.service');
var TelegramService = require('./../services/telegram.service');

var TIME_FOR_PREP;
var TIME_FOR_ACTION;
var TIME_FOR_REMINDER;
var TIME_FOR_IDLE;

var PostTimer = {};

PostTimer.checkAndNotify = function () {
  const now = new Date();
  if (!isWeekend(now)) {
    PostTimer.checkWithTime(now);
  }
};

PostTimer.checkWithTime = function (date, callback) {
  PostService.findCurrentState(function (post) {
    var expectedState = getStateForTime(date);
    var action = determineAction(date, post, expectedState);
    if (action) {
      console.info(' -- PostTimer: Changing state from', post.state, 'to', expectedState, 'at', date);
      action();
    }
    callback && callback(post, action, expectedState);
  });
};

function determineAction(date, post, expectedState) {
  var action;
  switch (post.state) {
    case STATES.IDLE:
      action = determineActionForIdleState(expectedState);
      break;
    case STATES.PREPARATION:
      action = determineActionForPrepState(expectedState);
      break;
    case STATES.ACTION:
      action = determineActionForActionState(date, post, expectedState);
      break;
    case STATES.REMINDER:
      action = determineActionForReminderState(expectedState);
      break;
  }
  return action;
}

var invokePreparationState = function () {
  return function () {
    PostService.startPreparationState(function (err, post) {
      TelegramService.sendZiviUpdateToUser(post.zivi, 'Congratulations! You are the selected Postler!');
      return console.log(' -- PostTimer: Changed to preparation state.');
    });
  };
};
function determineActionForIdleState(expectedState) {
  switch (expectedState) {
    case STATES.PREPARATION:
    case STATES.ACTION:
      return invokePreparationState();
  }
}

function determineActionForPrepState(expectedState) {
  // never do anything, just wait for somebody to accept, dismiss or reassign the post
  // it is not safe to assume that the post will actually be done if it is not accepted
}

function determineActionForActionState(date, post, expectedState) {
  if (isFifteenMinutesOrMoreAgo(date, post.timestamp)) {
    return function () {
      PostService.startReminderState(function () {
        return console.log(' -- PostTimer: Action state could possibly be done, but we don\'t  know, switching to reminder.');
      });
    };
  } else if (expectedState === STATES.PREPARATION) {
    return function () {
      PostService.justSetState(STATES.IDLE, function () {
        return console.log('-- PostTimer: Temporarily switching to idle to invoke new preparation.');
      });
    };
  }
}

function isFifteenMinutesOrMoreAgo(now, date) {
  return (now - date) >= 15 * 60 * 1000;
}

function determineActionForReminderState(expectedState) {
  switch (expectedState) {
    case STATES.PREPARATION:
      return function () {
        PostService.justSetState(STATES.IDLE, function () {
          return console.log(' -- PostTimer: Temporarily switching from reminder to idle because ' +
            'the next Postler will retrieve the yellow card anyways.');
        });
      };
    case STATES.ACTION:
      return invokePreparationState();
  }
}

function getStateForTime(date) {
  if (timeForIdle(date)) {
    return STATES.IDLE;
  } else if (timeForAction(date)) {
    return STATES.ACTION;
  } else if (timeForPrep(date)) {
    return STATES.PREPARATION;
  } else {
    return STATES.REMINDER;
  }
}

function timeForPrep(date) {
  return (date >= TIME_FOR_PREP[0] && date < TIME_FOR_ACTION[0]) || (date >= TIME_FOR_PREP[1] && date < TIME_FOR_ACTION[1]);
}

function timeForIdle(date) {
  return date < TIME_FOR_PREP[0] || date > TIME_FOR_IDLE[1] || (date >= TIME_FOR_IDLE[0] && date < TIME_FOR_PREP[1]);
}

function timeForAction(date) {
  return (date >= TIME_FOR_ACTION[0] && date < TIME_FOR_REMINDER[0]) || (date >= TIME_FOR_ACTION[1] && date < TIME_FOR_REMINDER[1]);
}

function initTimes() {

  TIME_FOR_PREP = [
    PostTimer.hourMinuteDateToday(10, 45),
    PostTimer.hourMinuteDateToday(14, 45)
  ];

  TIME_FOR_ACTION = [
    PostTimer.hourMinuteDateToday(11, 0),
    PostTimer.hourMinuteDateToday(15, 0)
  ];

  TIME_FOR_REMINDER = [
    PostTimer.hourMinuteDateToday(11, 15),
    PostTimer.hourMinuteDateToday(15, 15)
  ];

  TIME_FOR_IDLE = [
    PostTimer.hourMinuteDateToday(11, 30),
    PostTimer.hourMinuteDateToday(15, 30)
  ]
}

PostTimer.hourMinuteDateToday = function (hours, minutes) {
  var now = new Date();
  return new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, minutes, 0, 0)
};

function isWeekend(date) {
  return date.getDay() == /* Saturday */ 6 || date.getDay() == /* Sunday */ 0;
}

initTimes();
PostService.pushPostState();

module.exports = PostTimer;
<commit_msg>Remove unnecessary spacing from post.timer initTimes<commit_after>var shuffle = require('shuffle-array');
const STATES = require('../models/states');
var models = require('../models/index');
var PostService = require('./../services/post.service');
var ZiviService = require('./../services/zivi.service');
var TelegramService = require('./../services/telegram.service');

var TIME_FOR_PREP;
var TIME_FOR_ACTION;
var TIME_FOR_REMINDER;
var TIME_FOR_IDLE;

var PostTimer = {};

PostTimer.checkAndNotify = function () {
  const now = new Date();
  if (!isWeekend(now)) {
    PostTimer.checkWithTime(now);
  }
};

PostTimer.checkWithTime = function (date, callback) {
  PostService.findCurrentState(function (post) {
    var expectedState = getStateForTime(date);
    var action = determineAction(date, post, expectedState);
    if (action) {
      console.info(' -- PostTimer: Changing state from', post.state, 'to', expectedState, 'at', date);
      action();
    }
    callback && callback(post, action, expectedState);
  });
};

function determineAction(date, post, expectedState) {
  var action;
  switch (post.state) {
    case STATES.IDLE:
      action = determineActionForIdleState(expectedState);
      break;
    case STATES.PREPARATION:
      action = determineActionForPrepState(expectedState);
      break;
    case STATES.ACTION:
      action = determineActionForActionState(date, post, expectedState);
      break;
    case STATES.REMINDER:
      action = determineActionForReminderState(expectedState);
      break;
  }
  return action;
}

var invokePreparationState = function () {
  return function () {
    PostService.startPreparationState(function (err, post) {
      TelegramService.sendZiviUpdateToUser(post.zivi, 'Congratulations! You are the selected Postler!');
      return console.log(' -- PostTimer: Changed to preparation state.');
    });
  };
};
function determineActionForIdleState(expectedState) {
  switch (expectedState) {
    case STATES.PREPARATION:
    case STATES.ACTION:
      return invokePreparationState();
  }
}

function determineActionForPrepState(expectedState) {
  // never do anything, just wait for somebody to accept, dismiss or reassign the post
  // it is not safe to assume that the post will actually be done if it is not accepted
}

function determineActionForActionState(date, post, expectedState) {
  if (isFifteenMinutesOrMoreAgo(date, post.timestamp)) {
    return function () {
      PostService.startReminderState(function () {
        return console.log(' -- PostTimer: Action state could possibly be done, but we don\'t  know, switching to reminder.');
      });
    };
  } else if (expectedState === STATES.PREPARATION) {
    return function () {
      PostService.justSetState(STATES.IDLE, function () {
        return console.log('-- PostTimer: Temporarily switching to idle to invoke new preparation.');
      });
    };
  }
}

function isFifteenMinutesOrMoreAgo(now, date) {
  return (now - date) >= 15 * 60 * 1000;
}

function determineActionForReminderState(expectedState) {
  switch (expectedState) {
    case STATES.PREPARATION:
      return function () {
        PostService.justSetState(STATES.IDLE, function () {
          return console.log(' -- PostTimer: Temporarily switching from reminder to idle because ' +
            'the next Postler will retrieve the yellow card anyways.');
        });
      };
    case STATES.ACTION:
      return invokePreparationState();
  }
}

function getStateForTime(date) {
  if (timeForIdle(date)) {
    return STATES.IDLE;
  } else if (timeForAction(date)) {
    return STATES.ACTION;
  } else if (timeForPrep(date)) {
    return STATES.PREPARATION;
  } else {
    return STATES.REMINDER;
  }
}

function timeForPrep(date) {
  return (date >= TIME_FOR_PREP[0] && date < TIME_FOR_ACTION[0]) || (date >= TIME_FOR_PREP[1] && date < TIME_FOR_ACTION[1]);
}

function timeForIdle(date) {
  return date < TIME_FOR_PREP[0] || date > TIME_FOR_IDLE[1] || (date >= TIME_FOR_IDLE[0] && date < TIME_FOR_PREP[1]);
}

function timeForAction(date) {
  return (date >= TIME_FOR_ACTION[0] && date < TIME_FOR_REMINDER[0]) || (date >= TIME_FOR_ACTION[1] && date < TIME_FOR_REMINDER[1]);
}

function initTimes() {
  TIME_FOR_PREP = [
    PostTimer.hourMinuteDateToday(10, 45),
    PostTimer.hourMinuteDateToday(14, 45)
  ];
  TIME_FOR_ACTION = [
    PostTimer.hourMinuteDateToday(11, 0),
    PostTimer.hourMinuteDateToday(15, 0)
  ];
  TIME_FOR_REMINDER = [
    PostTimer.hourMinuteDateToday(11, 15),
    PostTimer.hourMinuteDateToday(15, 15)
  ];
  TIME_FOR_IDLE = [
    PostTimer.hourMinuteDateToday(11, 30),
    PostTimer.hourMinuteDateToday(15, 30)
  ];
}

PostTimer.hourMinuteDateToday = function (hours, minutes) {
  var now = new Date();
  return new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, minutes, 0, 0)
};

function isWeekend(date) {
  return date.getDay() == /* Saturday */ 6 || date.getDay() == /* Sunday */ 0;
}

initTimes();
PostService.pushPostState();

module.exports = PostTimer;
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp'),
    del = require('del'),
    concat = require('gulp-concat'),
    less = require('gulp-less'),
    smoosher = require('gulp-smoosher'),
    replace = require('gulp-replace'),
    uglify = require('gulp-uglify'),
    minifyCss = require('gulp-minify-css'),
    insert = require('gulp-insert'),
    runSequence = require('run-sequence'),
    minifyHtml = require('gulp-minify-html'),
    file = require('gulp-file'),
    fs = require('fs'),
    saveFile = require('gulp-savefile');

var settings = require('./wwwroot/app/settings.json'),
    pathConfig = require('./config/path.json'),
    includes = require('./config/includes.json');

var embedMedia = require('./modules/gulp-embed-media'),
    pathResolve = require('./modules/pathResolver').instance(pathConfig),
    appBuilder = require('./modules/appBuilder').instance(pathResolve, settings.source.moduleRootPath),
    fixGulp = require('./modules/fix-gulp'),
    fillContent = require('./modules/fill-content');

fixGulp(gulp);

// source files

var lessFiles = appBuilder.lessFiles();

var bowerScripts = pathResolve.bowerComponent(includes.bowerScripts);

var npmScripts = pathResolve.npmComponent(includes.npmScripts);

var bowerStyles = pathResolve.bowerComponent(includes.bowerStyles);

var fonts = pathResolve.bowerComponent(includes.bowerFonts);

var templates = appBuilder.templates();

var bowerTemplates = pathResolve.bowerComponent(includes.bowerTemplates);

var appScripts = appBuilder.scripts();

// constants

var thirdPartyJs = 'third-party.js';
var thirdPartyCss = 'third-party.css';

var mergedStylesCss = '/merged-styles.css';
var mergedScriptsJs = '/merged-scripts.js';

// dev tasks

gulp.task('clean', function (callback) {

    del(pathResolve.publicPath([
        '/lib',
        mergedStylesCss,
        mergedScriptsJs
    ]));

    callback();
});

gulp.task('scripts', function () {

    var libPath = pathResolve.publicPath('/lib');

    return gulp.src(bowerScripts.concat(npmScripts))
        .pipe(concat(thirdPartyJs))
        .pipe(gulp.dest(libPath));

});

gulp.task('templates', function () {

    return gulp.src(bowerTemplates)
        .pipe(gulp.dest(pathResolve.publicPath('/lib/templates')));
});

gulp.task('styles', function () {

    return gulp.src(bowerStyles)
        .pipe(concat(thirdPartyCss))
        .pipe(gulp.dest(pathResolve.publicPath('/lib/css')));
});

gulp.task('fonts', function () {

    var fontsPath = pathResolve.publicPath('/lib/fonts');

    return gulp.src(fonts)
        .pipe(gulp.dest(fontsPath));
});

gulp.task('less', function () {

    return gulp.src(lessFiles)
        .pipe(concat(mergedStylesCss))
        .pipe(less())
        .pipe(gulp.dest(pathResolve.publicPath()))
        .on('error', console.error);
});

gulp.task('merge', function () {

    return gulp.src(appScripts)
        .pipe(concat(mergedScriptsJs))
        .pipe(gulp.dest(pathResolve.publicPath()));;

});

gulp.task('default', function () {

    runSequence(
        'clean',
        'styles',
        'fonts',
        'scripts',
        'templates',
        'less',
        'merge'
    );
});

gulp.task('watch', function () {

    //less files
    gulp.watch(lessFiles, ['less']);
    console.log('Watching: ' + lessFiles);

    //angular app
    gulp.watch(appScripts, ['merge']);
    console.log('Watching: ' + appScripts);
});

var buildPath = pathResolve.publicPath('/build');
var contentPath = buildPath + '/content';
var tempBuild = buildPath + '/temp';

var html = buildPath + '/index.html';

var cssMinifyOptions = {
    processImportFrom : ['local'],
    keepSpecialComments : 0
};

var htmlMinifyOptions = {
    empty : true,
};

var embedMediaOptions = {
    baseDir : pathResolve.publicPath(),
    verbose : true
};

function createFile (name, contents) {

    return file(name, contents, { src : true });
}

// build tasks

gulp.task('build-clean', function (callback) {

    del(buildPath);

    callback();
});

gulp.task('build-index', function () {

    return gulp.src(pathResolve.publicPath('/index.html'))
        .pipe(gulp.dest(buildPath));
});

gulp.task('build-scripts', function () {

    return gulp.src(bowerScripts.concat(npmScripts))
        .pipe(concat(thirdPartyJs))
        .pipe(uglify())
        .pipe(gulp.dest(tempBuild + '/lib'));
});

gulp.task('build-source', function () {

    return gulp.src(appScripts)
        .pipe(concat(mergedScriptsJs))
        .pipe(uglify())
        .pipe(gulp.dest(tempBuild));;
});

gulp.task('build-styles', function () {

    return gulp.src(bowerStyles)
        .pipe(concat(thirdPartyCss))
        .pipe(minifyCss(cssMinifyOptions))
        .pipe(replace('../fonts/', './content/'))
        .pipe(gulp.dest(tempBuild + '/lib/css'));
});

gulp.task('build-fonts', function () {

    return gulp.src(fonts)
        .pipe(gulp.dest(contentPath));
});

gulp.task('build-less', function () {

    return gulp.src(lessFiles)
        .pipe(concat(mergedStylesCss))
        .pipe(less())
        .pipe(minifyCss(cssMinifyOptions))
        .pipe(gulp.dest(tempBuild));
});

gulp.task('build-copy-content', function () {

    return gulp.src(pathResolve.publicPath('/content/*'))
        .pipe(gulp.dest(contentPath));
});

gulp.task('build-templates', function () {

    function wrapTemplate (name, contents) {

        return '<script type="text/ng-template" id="' + name + '">\n' + contents + '\n</script>';
    }

    return gulp.src(templates.concat(bowerTemplates))
        .pipe(embedMedia(embedMediaOptions))
        .pipe(insert.transform(function (contents, file) {

            return wrapTemplate(file.path.split('\\').pop(), contents);
        }))
        .pipe(concat('templates'))
        .pipe(fillContent(html, 'templates'));
});

gulp.task('build-settings', function () {

    settings.templates.cached = true;
    var content = '<script> window.settings = ' + JSON.stringify(settings) + '; </script>';

    return createFile('settings.html', content)
        .pipe(fillContent(html, 'settings'));
});

gulp.task('build-merge', function () {

    return gulp.src(html)
        .pipe(embedMedia({
            baseDir : pathResolve.publicPath(),
            verbose : true,
            selectors : 'head link[rel="icon"]',
            attributes : 'href'
        }))
        .pipe(smoosher({
            base : tempBuild
        }))
        .pipe(minifyHtml(htmlMinifyOptions))
        .pipe(saveFile());
});

gulp.task('build-clear', function (callback) {

    del(tempBuild);

    callback();
});

gulp.task('build', function () {

    runSequence(
        'build-clean',
        'build-index',
        'build-scripts',
        'build-source',
        'build-styles',
        //'build-fonts',
        'build-less',
        'build-copy-content',
        'build-templates',
        'build-settings',
        'build-merge', 'build-clear'
    );
});<commit_msg>default task added to gulp watch<commit_after>'use strict';

var gulp = require('gulp'),
    del = require('del'),
    concat = require('gulp-concat'),
    less = require('gulp-less'),
    smoosher = require('gulp-smoosher'),
    replace = require('gulp-replace'),
    uglify = require('gulp-uglify'),
    minifyCss = require('gulp-minify-css'),
    insert = require('gulp-insert'),
    runSequence = require('run-sequence'),
    minifyHtml = require('gulp-minify-html'),
    file = require('gulp-file'),
    fs = require('fs'),
    saveFile = require('gulp-savefile');

var settings = require('./wwwroot/app/settings.json'),
    pathConfig = require('./config/path.json'),
    includes = require('./config/includes.json');

var embedMedia = require('./modules/gulp-embed-media'),
    pathResolve = require('./modules/pathResolver').instance(pathConfig),
    appBuilder = require('./modules/appBuilder').instance(pathResolve, settings.source.moduleRootPath),
    fixGulp = require('./modules/fix-gulp'),
    fillContent = require('./modules/fill-content');

fixGulp(gulp);

// source files

var lessFiles = appBuilder.lessFiles();

var bowerScripts = pathResolve.bowerComponent(includes.bowerScripts);

var npmScripts = pathResolve.npmComponent(includes.npmScripts);

var bowerStyles = pathResolve.bowerComponent(includes.bowerStyles);

var fonts = pathResolve.bowerComponent(includes.bowerFonts);

var templates = appBuilder.templates();

var bowerTemplates = pathResolve.bowerComponent(includes.bowerTemplates);

var appScripts = appBuilder.scripts();

// constants

var thirdPartyJs = 'third-party.js';
var thirdPartyCss = 'third-party.css';

var mergedStylesCss = '/merged-styles.css';
var mergedScriptsJs = '/merged-scripts.js';

// dev tasks

gulp.task('clean', function (callback) {

    del(pathResolve.publicPath([
        '/lib',
        mergedStylesCss,
        mergedScriptsJs
    ]));

    callback();
});

gulp.task('scripts', function () {

    var libPath = pathResolve.publicPath('/lib');

    return gulp.src(bowerScripts.concat(npmScripts))
        .pipe(concat(thirdPartyJs))
        .pipe(gulp.dest(libPath));

});

gulp.task('templates', function () {

    return gulp.src(bowerTemplates)
        .pipe(gulp.dest(pathResolve.publicPath('/lib/templates')));
});

gulp.task('styles', function () {

    return gulp.src(bowerStyles)
        .pipe(concat(thirdPartyCss))
        .pipe(gulp.dest(pathResolve.publicPath('/lib/css')));
});

gulp.task('fonts', function () {

    var fontsPath = pathResolve.publicPath('/lib/fonts');

    return gulp.src(fonts)
        .pipe(gulp.dest(fontsPath));
});

gulp.task('less', function () {

    return gulp.src(lessFiles)
        .pipe(concat(mergedStylesCss))
        .pipe(less())
        .pipe(gulp.dest(pathResolve.publicPath()))
        .on('error', console.error);
});

gulp.task('merge', function () {

    return gulp.src(appScripts)
        .pipe(concat(mergedScriptsJs))
        .pipe(gulp.dest(pathResolve.publicPath()));;

});

gulp.task('default', function () {

    runSequence(
        'clean',
        'styles',
        'fonts',
        'scripts',
        'templates',
        'less',
        'merge'
    );
});

gulp.task('watch', function () {

    //less files
    gulp.watch(lessFiles, ['less']);
    console.log('Watching: ' + lessFiles);

    //angular app
    gulp.watch(appScripts, ['merge']);
    console.log('Watching: ' + appScripts);

    //configuration files
    var buildSystemConfigs = './config/*.json';

    gulp.watch(buildSystemConfigs, ['default']);
    console.log('Watching: ' + buildSystemConfigs);

});

var buildPath = pathResolve.publicPath('/build');
var contentPath = buildPath + '/content';
var tempBuild = buildPath + '/temp';

var html = buildPath + '/index.html';

var cssMinifyOptions = {
    processImportFrom : ['local'],
    keepSpecialComments : 0
};

var htmlMinifyOptions = {
    empty : true,
};

var embedMediaOptions = {
    baseDir : pathResolve.publicPath(),
    verbose : true
};

function createFile (name, contents) {

    return file(name, contents, { src : true });
}

// build tasks

gulp.task('build-clean', function (callback) {

    del(buildPath);

    callback();
});

gulp.task('build-index', function () {

    return gulp.src(pathResolve.publicPath('/index.html'))
        .pipe(gulp.dest(buildPath));
});

gulp.task('build-scripts', function () {

    return gulp.src(bowerScripts.concat(npmScripts))
        .pipe(concat(thirdPartyJs))
        .pipe(uglify())
        .pipe(gulp.dest(tempBuild + '/lib'));
});

gulp.task('build-source', function () {

    return gulp.src(appScripts)
        .pipe(concat(mergedScriptsJs))
        .pipe(uglify())
        .pipe(gulp.dest(tempBuild));;
});

gulp.task('build-styles', function () {

    return gulp.src(bowerStyles)
        .pipe(concat(thirdPartyCss))
        .pipe(minifyCss(cssMinifyOptions))
        .pipe(replace('../fonts/', './content/'))
        .pipe(gulp.dest(tempBuild + '/lib/css'));
});

gulp.task('build-fonts', function () {

    return gulp.src(fonts)
        .pipe(gulp.dest(contentPath));
});

gulp.task('build-less', function () {

    return gulp.src(lessFiles)
        .pipe(concat(mergedStylesCss))
        .pipe(less())
        .pipe(minifyCss(cssMinifyOptions))
        .pipe(gulp.dest(tempBuild));
});

gulp.task('build-copy-content', function () {

    return gulp.src(pathResolve.publicPath('/content/*'))
        .pipe(gulp.dest(contentPath));
});

gulp.task('build-templates', function () {

    function wrapTemplate (name, contents) {

        return '<script type="text/ng-template" id="' + name + '">\n' + contents + '\n</script>';
    }

    return gulp.src(templates.concat(bowerTemplates))
        .pipe(embedMedia(embedMediaOptions))
        .pipe(insert.transform(function (contents, file) {

            return wrapTemplate(file.path.split('\\').pop(), contents);
        }))
        .pipe(concat('templates'))
        .pipe(fillContent(html, 'templates'));
});

gulp.task('build-settings', function () {

    settings.templates.cached = true;
    var content = '<script> window.settings = ' + JSON.stringify(settings) + '; </script>';

    return createFile('settings.html', content)
        .pipe(fillContent(html, 'settings'));
});

gulp.task('build-merge', function () {

    return gulp.src(html)
        .pipe(embedMedia({
            baseDir : pathResolve.publicPath(),
            verbose : true,
            selectors : 'head link[rel="icon"]',
            attributes : 'href'
        }))
        .pipe(smoosher({
            base : tempBuild
        }))
        .pipe(minifyHtml(htmlMinifyOptions))
        .pipe(saveFile());
});

gulp.task('build-clear', function (callback) {

    del(tempBuild);

    callback();
});

gulp.task('build', function () {

    runSequence(
        'build-clean',
        'build-index',
        'build-scripts',
        'build-source',
        'build-styles',
        //'build-fonts',
        'build-less',
        'build-copy-content',
        'build-templates',
        'build-settings',
        'build-merge', 'build-clear'
    );
});<|endoftext|>


<commit_before>gfw.ui.model.Wall = Backbone.Model.extend({

  defaults: {
    title: "Sign in",
    subtitle: "Didn't receive your password?",
    hidden: false,
    placeholder: "Enter password",
    mode: "login",
    button_title: "Sign in here",
    help: "Please enter your email address and we will send you an email with the site password"
  }

});

gfw.ui.view.Wall = gfw.ui.view.Widget.extend({

  className: 'wall',

  events: {

    "keyup input":   "_clearErrors",
    "click .invite": "_gotoInvite",
    "click .send":   "_send"

  },

  defaults: {
    speed: 250,
    minHeight: 15
  },

  initialize: function() {

    _.bindAll( this, "toggle", "_toggleMode", "_updateTitle", "_updateHelp", "_updateButtonTitle", "_updateSubtitle", "_updatePlaceholder" );

    this.options = _.extend(this.options, this.defaults);

    this.model = new gfw.ui.model.Wall();

    this.add_related_model(this.model);

    this.model.bind("change:hidden", this.toggle);

    this.model.bind("change:title",         this._updateTitle);
    this.model.bind("change:button_title",  this._updateButtonTitle);
    this.model.bind("change:subtitle",      this._updateSubtitle);
    this.model.bind("change:help",          this._updateHelp);
    this.model.bind("change:placeholder",   this._updatePlaceholder);
    this.model.bind("change:mode",          this._toggleMode);

    //this.model.bind("change:closed",    this.toggleOpen);
    //this.model.bind("change:draggable", this.toggleDraggable);

    this.$backdrop = $(".wall_backdrop");

    var template = $("#wall-template").html();

    this.template = new gfw.core.Template({
      template: template,
      type: 'mustache'
    });

  },

  _checkPass: function() {

    if (this.$el.find("input").val() == "gfw") {
      this.createCookie("pass", "gfw_c");
      this.hide();
    } else {
      this.$el.find(".input-field").addClass("error");
      this.$el.find(".input-field").find(".icon.error").fadeIn(250);
      this.$el.find(".input-field").find(".error_input_label").html("Password not valid");
      this.$el.find(".input-field").find(".error_input_label").fadeIn(250);
    }

  },

  hide: function() {
    this.$el.fadeOut(250);
    this.$backdrop.fadeOut(250);
  },

  _clearErrors: function() {

    this.$el.find(".input-field .icon.error").fadeOut(250);
    this.$el.find(".input-field").removeClass("error");
    this.$el.find(".input-field .error_input_label").fadeOut(250);
    this.$el.find(".input-field .error_input_label").html("");

  },

  _send: function(e) {
    var that = this;

    e.preventDefault();
    e.stopPropagation();

    var mode = this.model.get("mode");
    var error = false;

    if (mode == "request") {

      this._clearErrors();

      if (!validateEmail(this.$el.find("input").val())) {
        this.$el.find(".input-field").addClass("error");
        this.$el.find(".input-field").find(".icon.error").fadeIn(250);
        this.$el.find(".input-field").find(".error_input_label").html("Please enter a valid email");
        this.$el.find(".input-field").find(".error_input_label").fadeIn(250);

        error = true;
      }

      if (!error) {
        $.ajax({ type: "post", url: "/register", data: { email: this.$el.find("input").val() }, success: function() {
          that._setMode("thanks");
        }});
      }

  } else {
    this._checkPass();
  }

},

_gotoInvite: function(e) {
  e.preventDefault();
  e.stopPropagation();

  this._setMode("request");
},

_setMode: function(mode) {

  this._clearErrors();

  if (mode == "login") {
    this.model.set({ title: "Sign in", subtitle: "Don’t you have a password?", button_title: "Sign in", placeholder: "Enter password", mode: mode })
  } else if (mode == "request") {
    this.model.set({ title: "Request an invite", help: "Please, enter your email address to require access to the site", button_title: "Send", placeholder: "Enter your email", mode: mode })
  } else if (mode == "thanks") {
    this.model.set({ title: "Thank you :-)", help: "We sent you an email with the password to access the site", placeholder: "Enter password", button_title: "Sign in", mode: mode })
    this.$("input").val("");
  }

},

_toggleMode: function() {

  var mode = this.model.get("mode");

  if (mode == "login") {
    this.$(".invite").fadeIn(250);
    this.$(".help").fadeOut(250);;
  } else if (mode == "request") {
    this.$(".subtitle").fadeOut(250);;
    this.$(".help").fadeIn(250);
  } else if (mode == "thanks") {
    this.$(".subtitle").fadeOut(250);;
    this.$(".help").fadeIn(250);
  }

},

_updatePlaceholder: function() {
  this.$el.find("input[type='text']").attr("placeholder", this.model.get("placeholder"));
},

_updateHelp: function() {
  this.$el.find(".help").html(this.model.get("help"));
},

_updateSubtitle: function() {
  this.$el.find(".subtitle").html(this.model.get("subtitle"));
},

_updateButtonTitle: function() {
  this.$el.find(".send span").html(this.model.get("button_title"));
},

_updateTitle: function() {
  this.$el.find(".title").html(this.model.get("title"));
},

createCookie: function(name, value, days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    var expires = "; expires=" + date.toGMTString();
  } else var expires = "";
  document.cookie = escape(name) + "=" + escape(value) + expires + "; path=/";
},

readCookie:function(name) {
  var nameEQ = escape(name) + "=";
  var ca = document.cookie.split(';');
  for (var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') c = c.substring(1, c.length);
    if (c.indexOf(nameEQ) == 0) return unescape(c.substring(nameEQ.length, c.length));
  }
  return null;
},

eraseCookie: function(name) {
  createCookie(name, "", -1);
},

render: function() {
  var that = this;

  if (this.readCookie("pass") == 'gfw_c') return;

  this.$el.append(this.template.render( this.model.toJSON() ));

  this.$backdrop.fadeIn(250);
  this.$el.fadeIn(250);

  return this.$el;
}

});
<commit_msg>don't check cookie<commit_after>gfw.ui.model.Wall = Backbone.Model.extend({

  defaults: {
    title: "Sign in",
    subtitle: "Didn't receive your password?",
    hidden: false,
    placeholder: "Enter password",
    mode: "login",
    button_title: "Sign in here",
    help: "Please enter your email address and we will send you an email with the site password"
  }

});

gfw.ui.view.Wall = gfw.ui.view.Widget.extend({

  className: 'wall',

  events: {

    "keyup input":   "_clearErrors",
    "click .invite": "_gotoInvite",
    "click .send":   "_send"

  },

  defaults: {
    speed: 250,
    minHeight: 15
  },

  initialize: function() {

    _.bindAll( this, "toggle", "_toggleMode", "_updateTitle", "_updateHelp", "_updateButtonTitle", "_updateSubtitle", "_updatePlaceholder" );

    this.options = _.extend(this.options, this.defaults);

    this.model = new gfw.ui.model.Wall();

    this.add_related_model(this.model);

    this.model.bind("change:hidden", this.toggle);

    this.model.bind("change:title",         this._updateTitle);
    this.model.bind("change:button_title",  this._updateButtonTitle);
    this.model.bind("change:subtitle",      this._updateSubtitle);
    this.model.bind("change:help",          this._updateHelp);
    this.model.bind("change:placeholder",   this._updatePlaceholder);
    this.model.bind("change:mode",          this._toggleMode);

    //this.model.bind("change:closed",    this.toggleOpen);
    //this.model.bind("change:draggable", this.toggleDraggable);

    this.$backdrop = $(".wall_backdrop");

    var template = $("#wall-template").html();

    this.template = new gfw.core.Template({
      template: template,
      type: 'mustache'
    });

  },

  _checkPass: function() {

    if (this.$el.find("input").val() == "gfw") {
      this.createCookie("pass", "gfw_c");
      this.hide();
    } else {
      this.$el.find(".input-field").addClass("error");
      this.$el.find(".input-field").find(".icon.error").fadeIn(250);
      this.$el.find(".input-field").find(".error_input_label").html("Password not valid");
      this.$el.find(".input-field").find(".error_input_label").fadeIn(250);
    }

  },

  hide: function() {
    this.$el.fadeOut(250);
    this.$backdrop.fadeOut(250);
  },

  _clearErrors: function() {

    this.$el.find(".input-field .icon.error").fadeOut(250);
    this.$el.find(".input-field").removeClass("error");
    this.$el.find(".input-field .error_input_label").fadeOut(250);
    this.$el.find(".input-field .error_input_label").html("");

  },

  _send: function(e) {
    var that = this;

    e.preventDefault();
    e.stopPropagation();

    var mode = this.model.get("mode");
    var error = false;

    if (mode == "request") {

      this._clearErrors();

      if (!validateEmail(this.$el.find("input").val())) {
        this.$el.find(".input-field").addClass("error");
        this.$el.find(".input-field").find(".icon.error").fadeIn(250);
        this.$el.find(".input-field").find(".error_input_label").html("Please enter a valid email");
        this.$el.find(".input-field").find(".error_input_label").fadeIn(250);

        error = true;
      }

      if (!error) {
        $.ajax({ type: "post", url: "/register", data: { email: this.$el.find("input").val() }, success: function() {
          that._setMode("thanks");
        }});
      }

  } else {
    this._checkPass();
  }

},

_gotoInvite: function(e) {
  e.preventDefault();
  e.stopPropagation();

  this._setMode("request");
},

_setMode: function(mode) {

  this._clearErrors();

  if (mode == "login") {
    this.model.set({ title: "Sign in", subtitle: "Don’t you have a password?", button_title: "Sign in", placeholder: "Enter password", mode: mode })
  } else if (mode == "request") {
    this.model.set({ title: "Request an invite", help: "Please, enter your email address to require access to the site", button_title: "Send", placeholder: "Enter your email", mode: mode })
  } else if (mode == "thanks") {
    this.model.set({ title: "Thank you :-)", help: "We sent you an email with the password to access the site", placeholder: "Enter password", button_title: "Sign in", mode: mode })
    this.$("input").val("");
  }

},

_toggleMode: function() {

  var mode = this.model.get("mode");

  if (mode == "login") {
    this.$(".invite").fadeIn(250);
    this.$(".help").fadeOut(250);;
  } else if (mode == "request") {
    this.$(".subtitle").fadeOut(250);;
    this.$(".help").fadeIn(250);
  } else if (mode == "thanks") {
    this.$(".subtitle").fadeOut(250);;
    this.$(".help").fadeIn(250);
  }

},

_updatePlaceholder: function() {
  this.$el.find("input[type='text']").attr("placeholder", this.model.get("placeholder"));
},

_updateHelp: function() {
  this.$el.find(".help").html(this.model.get("help"));
},

_updateSubtitle: function() {
  this.$el.find(".subtitle").html(this.model.get("subtitle"));
},

_updateButtonTitle: function() {
  this.$el.find(".send span").html(this.model.get("button_title"));
},

_updateTitle: function() {
  this.$el.find(".title").html(this.model.get("title"));
},

createCookie: function(name, value, days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    var expires = "; expires=" + date.toGMTString();
  } else var expires = "";
  document.cookie = escape(name) + "=" + escape(value) + expires + "; path=/";
},

readCookie:function(name) {
  var nameEQ = escape(name) + "=";
  var ca = document.cookie.split(';');
  for (var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') c = c.substring(1, c.length);
    if (c.indexOf(nameEQ) == 0) return unescape(c.substring(nameEQ.length, c.length));
  }
  return null;
},

eraseCookie: function(name) {
  createCookie(name, "", -1);
},

render: function() {
  var that = this;

  //if (this.readCookie("pass") == 'gfw_c') return;

  this.$el.append(this.template.render( this.model.toJSON() ));

  this.$backdrop.fadeIn(250);
  this.$el.fadeIn(250);

  return this.$el;
}

});
<|endoftext|>


<commit_before>/**
 * Fallback Datasource
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
var Fallback = Function.inherits('Alchemy.Datasource', function Fallback(name, options) {
	// Call the parent constructor
	Fallback.super.call(this, name, options);
});

/**
 * Indicate this is part of the cache
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
Fallback.setProperty('has_offline_cache', true);

/**
 * Create a connection to the 2 databases
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
Fallback.decorateMethod(Blast.Decorators.memoize({ignore_arguments: true}), function connect() {

	var that = this,
	    tasks = [];

	// The "upper" or "local" datasource
	this.upper = Datasource.get(this.options.upper);

	// The "lower" or "remote" datasource
	this.lower = Datasource.get(this.options.lower);

	return Function.parallel(function doUpper(next) {
		// The upper datasource is needed
		that.upper.setup().done(next);
	}, function doLower(next) {
		// The lower one isn't necesarily needed
		that.lower.setup().done(function whenDone(err) {

			if (err) {
				console.warn('Failed to setup lower datasource', that.lower.name, err);
			}

			next();
		});
	}, null);

	return Function.parallel(tasks);
});

/**
 * Store the data in the local cache
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}   model
 * @param    {Object}  data
 * @param    {Object}  options
 */
Fallback.setMethod(function storeInUpperDatasource(model, data, options) {

	var that = this,
	    upper = that.upper;

	if (!options) {
		options = {};
	}

	return Function.series(function convertToDatasource(next) {
		upper.toDatasource(model, data, next);
	}, function addTempValues(next, result) {
		data = result;

		// Add time it was cached
		data._$cache_time = Date.now();

		// Also mark it as being a local save if needed
		if (options.local_save) {
			if (options.local_save === true) {
				time = Date.now();
			} else {
				time = options.local_save;
			}

			data._$local_save_time = time;

			// IndexedDB does not use indexes on booleans, so use a number!
			data._$needs_remote_save = 1;
		}

		// And mark is as having saved, too
		if (options.remote_save) {
			if (options.remote_save === true) {
				time = Date.now();
			} else {
				time = options.remote_save;
			}

			data._$remote_save_time = time;
			data._$needs_remote_save = undefined;
		}

		// @TODO: we're not actually setting the "updated" part here...
		// (when doing a local save)
		if (Blast.isBrowser && window.sessionStorage && data.updated) {
			window.sessionStorage[data._id] = Number(data.updated);
		}

		// Allow extraneous values (the ones we just added in this function)
		options.extraneous = true;

		if (options.create === false) {
			upper._update(model, data, options, savedOnUpper);
		} else {
			upper._create(model, data, options, savedOnUpper);
		}

		function savedOnUpper(err, result) {
			next(err, result);
		}

	}, function gotUpdateResult(next, result) {
		upper.toApp(model, null, options, result, next);
	}, function done(err, result) {

		if (err) {
			return;
		}

		return result.last();
	});
});

/**
 * Query the databases
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
Fallback.setMethod(function read(model, criteria, callback) {

	var that = this,
	    lower_criteria = criteria.clone(),
	    upper_criteria = criteria.clone();

	// Prepare both criteria
	lower_criteria.datasource = this.lower;
	upper_criteria.datasource = this.upper;

	Function.series(function doLowerRead(next) {

		if (criteria.options.only_local) {
			return next();
		}

		that.lower.read(model, lower_criteria, function done(err, result) {

			if (err) {
				console.log('Failed to read lower datasource: ' + err, err, criteria, model);
				return next();
			}

			next(null, result);
		});
	}, function checkUpperDatabase(next, lower) {

		// @TODO: Make sure we don't have any more recent data
		if (lower) {
			return next(null, lower);
		}

		if (!criteria.options.only_local) {
			console.log('Doing upper (local) read because lower (remote) failed...');
		}

		that.upper.read(model, upper_criteria, function done(err, result) {

			if (err) {
				return next(err);
			}

			next(null, result);
		});

	}, function done(err, result) {

		if (err) {
			return callback(err);
		}

		result = result[1];

		return callback(null, result);
	});
});

/**
 * Get data that needs to be synced
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}   model
 *
 * @return   {Pledge}
 */
Fallback.setMethod(function getRecordsToSync(model) {

	var that = this,
	    pledge = new Pledge,
	    criteria = model.find();

	criteria.where('_$needs_remote_save').equals(1);

	this.upper._read(model, criteria, function gotRecords(err, records) {

		if (err) {
			return pledge.reject(err);
		}

		pledge.resolve(records);
	});

	return pledge;
});

/**
 * Insert new data into the database
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}      model
 * @param    {Object}     data
 * @param    {Object}     options
 * @param    {Function}   callback
 *
 * @return   {Pledge}
 */
Fallback.setMethod(function create(model, data, options, callback) {
	return this.createOrUpdate('create', model, data, options, callback);
});

/**
 * Update new data into the database
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}      model
 * @param    {Object}     data
 * @param    {Object}     options
 * @param    {Function}   callback
 *
 * @return   {Pledge}
 */
Fallback.setMethod(function update(model, data, options, callback) {
	return this.createOrUpdate('update', model, data, options, callback);
});

/**
 * Insert new data into the database
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}      model
 * @param    {Object}     data
 * @param    {Object}     options
 * @param    {Function}   callback
 *
 * @return   {Pledge}
 */
Fallback.setMethod(function createOrUpdate(method, model, data, options, callback) {

	var that = this,
	    upper = this.upper,
	    lower = this.lower,
	    pledge,
	    saved_data;

	pledge = Function.series(function initialSave(next) {

		var tasks = {
			lower : function doLowerCreate(next) {
				lower[method](model, data, options, function createdLower(err, result) {
					next(null, {err: err, result: result});
				});
			},
			upper : function doUpperCreate(next) {

				var upper_options = Object.assign({}, options);

				if (method == 'create') {
					upper_options.create = true;
				} else {
					upper_options.create = false;
				}

				upper_options.local_save = true;
				upper_options.remote_save = false;

				that.storeInUpperDatasource(model, data, upper_options).done(function createdUpper(err, result) {
					next(null, {err: err, result: result});
				});
			}
		};

		Function.parallel(tasks, next);
	}, function updateLocal(next, result) {

		saved_data = result;

		// Did we have some kind of error in the lower db?
		// Then we should leave the 'needs_remote_save' fields as is in the upper one
		if (result.lower.err) {
			return next();
		}

		let upper_options = Object.assign({}, options);

		// This second storeInUpperDatasource is ALWAYS an update
		upper_options.create = false;
		upper_options.local_save = false;
		upper_options.remote_save = true;

		that.storeInUpperDatasource(model, data, upper_options).done(function adjustedUpper(err, result) {
			next(null, {err: err, result: result});
		});
	}, function doToApp(next) {

		if (saved_data.lower.result) {
			lower.toApp(model, null, options, saved_data.lower.result, next);
		} else {
			upper.toApp(model, null, options, saved_data.upper.result, next);
		}

	}, function done(err, result) {

		if (err) {
			return;
		}

		result = result.last();

		return result;
	});

	pledge.done(callback);

	return pledge;
});

/**
 * Ensure an index in the database
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
Fallback.setMethod(function _ensureIndex(model, index, callback) {

	var that = this,
	    pledge;

	pledge = Function.parallel(function doLowerCreate(next) {
		that.lower._ensureIndex(model, index, function ensuredLowerIndex(err, result) {
			next(null, {err: err, result: result});
		});
	}, function doUpperCreate(next) {
		that.upper._ensureIndex(model, index, function ensuredUpperIndex(err, result) {
			next(null, {err: err, result: result});
		});
	}, function done(err, result) {
		return null;
	});

	pledge.done(callback);

	return pledge;
});<commit_msg>Don't apply toApp on results from the remoteDatasource during a createOrUpdate<commit_after>/**
 * Fallback Datasource
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
var Fallback = Function.inherits('Alchemy.Datasource', function Fallback(name, options) {
	// Call the parent constructor
	Fallback.super.call(this, name, options);
});

/**
 * Indicate this is part of the cache
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
Fallback.setProperty('has_offline_cache', true);

/**
 * Create a connection to the 2 databases
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
Fallback.decorateMethod(Blast.Decorators.memoize({ignore_arguments: true}), function connect() {

	var that = this,
	    tasks = [];

	// The "upper" or "local" datasource
	this.upper = Datasource.get(this.options.upper);

	// The "lower" or "remote" datasource
	this.lower = Datasource.get(this.options.lower);

	return Function.parallel(function doUpper(next) {
		// The upper datasource is needed
		that.upper.setup().done(next);
	}, function doLower(next) {
		// The lower one isn't necesarily needed
		that.lower.setup().done(function whenDone(err) {

			if (err) {
				console.warn('Failed to setup lower datasource', that.lower.name, err);
			}

			next();
		});
	}, null);

	return Function.parallel(tasks);
});

/**
 * Store the data in the local cache
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}   model
 * @param    {Object}  data
 * @param    {Object}  options
 */
Fallback.setMethod(function storeInUpperDatasource(model, data, options) {

	var that = this,
	    upper = that.upper;

	if (!options) {
		options = {};
	}

	return Function.series(function convertToDatasource(next) {
		upper.toDatasource(model, data, next);
	}, function addTempValues(next, result) {
		data = result;

		// Add time it was cached
		data._$cache_time = Date.now();

		// Also mark it as being a local save if needed
		if (options.local_save) {
			if (options.local_save === true) {
				time = Date.now();
			} else {
				time = options.local_save;
			}

			data._$local_save_time = time;

			// IndexedDB does not use indexes on booleans, so use a number!
			data._$needs_remote_save = 1;
		}

		// And mark is as having saved, too
		if (options.remote_save) {
			if (options.remote_save === true) {
				time = Date.now();
			} else {
				time = options.remote_save;
			}

			data._$remote_save_time = time;
			data._$needs_remote_save = undefined;
		}

		// @TODO: we're not actually setting the "updated" part here...
		// (when doing a local save)
		if (Blast.isBrowser && window.sessionStorage && data.updated) {
			window.sessionStorage[data._id] = Number(data.updated);
		}

		// Allow extraneous values (the ones we just added in this function)
		options.extraneous = true;

		if (options.create === false) {
			upper._update(model, data, options, savedOnUpper);
		} else {
			upper._create(model, data, options, savedOnUpper);
		}

		function savedOnUpper(err, result) {
			next(err, result);
		}

	}, function gotUpdateResult(next, result) {
		upper.toApp(model, null, options, result, next);
	}, function done(err, result) {

		if (err) {
			return;
		}

		return result.last();
	});
});

/**
 * Query the databases
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
Fallback.setMethod(function read(model, criteria, callback) {

	var that = this,
	    lower_criteria = criteria.clone(),
	    upper_criteria = criteria.clone();

	// Prepare both criteria
	lower_criteria.datasource = this.lower;
	upper_criteria.datasource = this.upper;

	Function.series(function doLowerRead(next) {

		if (criteria.options.only_local) {
			return next();
		}

		that.lower.read(model, lower_criteria, function done(err, result) {

			if (err) {
				console.log('Failed to read lower datasource: ' + err, err, criteria, model);
				return next();
			}

			next(null, result);
		});
	}, function checkUpperDatabase(next, lower) {

		// @TODO: Make sure we don't have any more recent data
		if (lower) {
			return next(null, lower);
		}

		if (!criteria.options.only_local) {
			console.log('Doing upper (local) read because lower (remote) failed...');
		}

		that.upper.read(model, upper_criteria, function done(err, result) {

			if (err) {
				return next(err);
			}

			next(null, result);
		});

	}, function done(err, result) {

		if (err) {
			return callback(err);
		}

		result = result[1];

		return callback(null, result);
	});
});

/**
 * Get data that needs to be synced
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}   model
 *
 * @return   {Pledge}
 */
Fallback.setMethod(function getRecordsToSync(model) {

	var that = this,
	    pledge = new Pledge,
	    criteria = model.find();

	criteria.where('_$needs_remote_save').equals(1);

	this.upper._read(model, criteria, function gotRecords(err, records) {

		if (err) {
			return pledge.reject(err);
		}

		pledge.resolve(records);
	});

	return pledge;
});

/**
 * Insert new data into the database
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}      model
 * @param    {Object}     data
 * @param    {Object}     options
 * @param    {Function}   callback
 *
 * @return   {Pledge}
 */
Fallback.setMethod(function create(model, data, options, callback) {
	return this.createOrUpdate('create', model, data, options, callback);
});

/**
 * Update new data into the database
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}      model
 * @param    {Object}     data
 * @param    {Object}     options
 * @param    {Function}   callback
 *
 * @return   {Pledge}
 */
Fallback.setMethod(function update(model, data, options, callback) {
	return this.createOrUpdate('update', model, data, options, callback);
});

/**
 * Insert new data into the database
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @param    {Model}      model
 * @param    {Object}     data
 * @param    {Object}     options
 * @param    {Function}   callback
 *
 * @return   {Pledge}
 */
Fallback.setMethod(function createOrUpdate(method, model, data, options, callback) {

	var that = this,
	    upper = this.upper,
	    lower = this.lower,
	    pledge,
	    saved_data;

	pledge = Function.series(function initialSave(next) {

		var tasks = {
			lower : function doLowerCreate(next) {
				lower[method](model, data, options, function createdLower(err, result) {
					next(null, {err: err, result: result});
				});
			},
			upper : function doUpperCreate(next) {

				var upper_options = Object.assign({}, options);

				if (method == 'create') {
					upper_options.create = true;
				} else {
					upper_options.create = false;
				}

				upper_options.local_save = true;
				upper_options.remote_save = false;

				that.storeInUpperDatasource(model, data, upper_options).done(function createdUpper(err, result) {
					next(null, {err: err, result: result});
				});
			}
		};

		Function.parallel(tasks, next);
	}, function updateLocal(next, result) {

		saved_data = result;

		// Did we have some kind of error in the lower db?
		// Then we should leave the 'needs_remote_save' fields as is in the upper one
		if (result.lower.err) {
			return next();
		}

		let upper_options = Object.assign({}, options);

		// This second storeInUpperDatasource is ALWAYS an update
		upper_options.create = false;
		upper_options.local_save = false;
		upper_options.remote_save = true;

		that.storeInUpperDatasource(model, data, upper_options).done(function adjustedUpper(err, result) {
			next(null, {err: err, result: result});
		});
	}, function doToApp(next) {

		if (saved_data.lower.result) {
			next(null, saved_data.lower.result);
			// Lower data can already be a Document instance!
			// @TODO: add a check for that?
			//lower.toApp(model, null, options, saved_data.lower.result, next);
		} else {
			upper.toApp(model, null, options, saved_data.upper.result, next);
		}

	}, function done(err, result) {

		if (err) {
			return;
		}

		result = result.last();

		return result;
	});

	pledge.done(callback);

	return pledge;
});

/**
 * Ensure an index in the database
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 */
Fallback.setMethod(function _ensureIndex(model, index, callback) {

	var that = this,
	    pledge;

	pledge = Function.parallel(function doLowerCreate(next) {
		that.lower._ensureIndex(model, index, function ensuredLowerIndex(err, result) {
			next(null, {err: err, result: result});
		});
	}, function doUpperCreate(next) {
		that.upper._ensureIndex(model, index, function ensuredUpperIndex(err, result) {
			next(null, {err: err, result: result});
		});
	}, function done(err, result) {
		return null;
	});

	pledge.done(callback);

	return pledge;
});<|endoftext|>