<commit_before>'use strict';

var _ = require('lodash');
var View = require('atom-space-pen-views').View;
var cscompatability = require('./cscompatability');
var GoogleAnalytics = require('./google-analytics');
var Convert = require('ansi-to-html');

module.exports = (function() {
  function BuildView() {
    View.apply(this, arguments);
    this.titleLoop = [
      'Building',
      'Building.',
      'Building..',
      'Building...'
    ];
    this.titleLoopIndex = 0;
    this.a2h = new Convert();
    this.monocle = false;
    // this.attach();

    atom.config.observe('build.panelVisibility', this.visibleFromConfig.bind(this));
    atom.config.observe('build.monocleHeight', this.heightFromConfig.bind(this));
    atom.config.observe('build.minimizedHeight', this.heightFromConfig.bind(this));

    atom.commands.add('atom-workspace', 'build:toggle-panel', this.toggle.bind(this));
  }

  cscompatability.extends(BuildView, View);

  BuildView.content = function() {
    BuildView.div({ tabIndex: -1, class: 'build tool-panel panel-bottom native-key-bindings' }, function() {
      BuildView.div({ class: 'btn-container pull-right' }, function() {
        BuildView.button({ class: 'btn btn-default icon icon-x', outlet: 'closeButton', click: 'close' });
        BuildView.button({ class: 'btn btn-default icon icon-chevron-up', outlet: 'monocleButton', click: 'toggleMonocle' });
        BuildView.button({ class: 'btn btn-default icon icon-trashcan new-row', outlet: 'clearButton', click: 'clear' });
        BuildView.button({ class: 'btn btn-default icon icon-zap', outlet: 'triggerButton', click: 'build', title: 'Build current project' });
      });

      BuildView.div(function() {
        BuildView.ol({ class: 'output panel-body', outlet: 'output' });
      });

      BuildView.div(function() {
        BuildView.h1({ class: 'title panel-heading', outlet: 'title' }, 'Ready');
      });
    });
  };

  BuildView.prototype.attach = function(force) {
    if (!force) {
      switch (atom.config.get('build.panelVisibility')) {
        case 'Hidden':
        case 'Show on Error':
          return;
      }
    }

    if (this.panel) {
      this.panel.destroy();
    }
    this.panel = atom.workspace.addBottomPanel({ item: this });
    this.height = this.output.offset().top + this.output.height();
  };

  BuildView.prototype.detach = function(force) {
    force = force || false;
    if (atom.views.getView(atom.workspace)) {
      atom.views.getView(atom.workspace).focus();
    }
    if (this.panel && (force || 'Keep Visible' !== atom.config.get('build.panelVisibility'))) {
      this.panel.destroy();
      this.panel = null;
    }
  };

  BuildView.prototype.isAttached = function() {
    return !!this.panel;
  };

  BuildView.prototype.heightFromConfig = function(val) {
    if (this.monocle) {
      this.setHeightPercent(atom.config.get('build.monocleHeight'));
    } else {
      this.setHeightPercent(atom.config.get('build.minimizedHeight'));
    }
  };

  BuildView.prototype.visibleFromConfig = function(val) {
    switch (val) {
      case 'Toggle':
      case 'Show on Error':
        if (!this.title.hasClass('error')) {
          this.detach();
        }
        break;
      //
      // case 'Keep Visible':
      //   this.attach();
      //   break;
    }
  };

  BuildView.prototype.reset = function() {
    clearTimeout(this.titleTimer);
    this.titleTimer = 0;
    this.title.removeClass('success error warning');
    this.output.empty();
    this.title.text('Cleared.');
    this.detach();
  };

  BuildView.prototype.updateTitle = function() {
    this.title.text(this.titleLoop[this.titleLoopIndex]);
    this.titleLoopIndex = (this.titleLoopIndex + 1) % this.titleLoop.length;
    this.titleTimer = setTimeout(this.updateTitle.bind(this), 200);
  };

  BuildView.prototype.close = function(event, element) {
    this.detach(true);
  };

  BuildView.prototype.toggle = function(event, element) {
    GoogleAnalytics.sendEvent('view', 'panel toggled');
    this.isAttached() ?  this.detach(true) : this.attach(true);
  };

  BuildView.prototype.clear = function(event, element) {
    this.reset();
    this.attach();
  };

  BuildView.prototype.build = function(event, element) {
    atom.commands.dispatch(atom.views.getView(atom.workspace), 'build:trigger');
  };

  BuildView.prototype.setHeightPercent = function(percent) {
    var newHeight = percent * this.height;
    this.output.css('height', newHeight + 'px');
  };

  BuildView.prototype.toggleMonocle = function(event, element) {
    GoogleAnalytics.sendEvent('view', 'monocle toggled');
    if (!this.monocle) {
      this.setHeightPercent(atom.config.get('build.monocleHeight'));
      this.monocleButton.removeClass('icon-chevron-up').addClass('icon-chevron-down');
    } else {
      this.setHeightPercent(atom.config.get('build.minimizedHeight'));
      this.monocleButton.removeClass('icon-chevron-down').addClass('icon-chevron-up');
    }
    this.monocle = !this.monocle;
  };

  BuildView.prototype.buildStarted = function() {
    this.reset();
    this.attach();
    if (atom.config.get('build.stealFocus')) {
      this.focus();
    }
    this.updateTitle();
  };

  BuildView.prototype.buildFinished = function(success) {
    if (!success) {
      var force = (atom.config.get('build.panelVisibility') === 'Show on Error');
      this.attach(force);
    }
    this.title.text(success ? 'Build finished.' : 'Build failed.');
    this.title.addClass(success ? 'success' : 'error');
    clearTimeout(this.titleTimer);
  };

  BuildView.prototype.buildAbortInitiated = function() {
    this.title.text('Build process termination imminent...');
    clearTimeout(this.titleTimer);
    this.title.addClass('error');
  };

  BuildView.prototype.buildAborted = function() {
    this.title.text('Aborted!');
  };

  BuildView.prototype.append = function(line) {
    line = _.escape(line.toString());
    this.output.append('
' + (this.a2h.toHtml(line)) + '
');
    this.output.scrollTop(this.output[0].scrollHeight);
  };

  return BuildView;
})();
<commit_msg>remove comments<commit_after>'use strict';

var _ = require('lodash');
var View = require('atom-space-pen-views').View;
var cscompatability = require('./cscompatability');
var GoogleAnalytics = require('./google-analytics');
var Convert = require('ansi-to-html');

module.exports = (function() {
  function BuildView() {
    View.apply(this, arguments);
    this.titleLoop = [
      'Building',
      'Building.',
      'Building..',
      'Building...'
    ];
    this.titleLoopIndex = 0;
    this.a2h = new Convert();
    this.monocle = false;

    atom.config.observe('build.panelVisibility', this.visibleFromConfig.bind(this));
    atom.config.observe('build.monocleHeight', this.heightFromConfig.bind(this));
    atom.config.observe('build.minimizedHeight', this.heightFromConfig.bind(this));

    atom.commands.add('atom-workspace', 'build:toggle-panel', this.toggle.bind(this));
  }

  cscompatability.extends(BuildView, View);

  BuildView.content = function() {
    BuildView.div({ tabIndex: -1, class: 'build tool-panel panel-bottom native-key-bindings' }, function() {
      BuildView.div({ class: 'btn-container pull-right' }, function() {
        BuildView.button({ class: 'btn btn-default icon icon-x', outlet: 'closeButton', click: 'close' });
        BuildView.button({ class: 'btn btn-default icon icon-chevron-up', outlet: 'monocleButton', click: 'toggleMonocle' });
        BuildView.button({ class: 'btn btn-default icon icon-trashcan new-row', outlet: 'clearButton', click: 'clear' });
        BuildView.button({ class: 'btn btn-default icon icon-zap', outlet: 'triggerButton', click: 'build', title: 'Build current project' });
      });

      BuildView.div(function() {
        BuildView.ol({ class: 'output panel-body', outlet: 'output' });
      });

      BuildView.div(function() {
        BuildView.h1({ class: 'title panel-heading', outlet: 'title' }, 'Ready');
      });
    });
  };

  BuildView.prototype.attach = function(force) {
    if (!force) {
      switch (atom.config.get('build.panelVisibility')) {
        case 'Hidden':
        case 'Show on Error':
          return;
      }
    }

    if (this.panel) {
      this.panel.destroy();
    }
    this.panel = atom.workspace.addBottomPanel({ item: this });
    this.height = this.output.offset().top + this.output.height();
  };

  BuildView.prototype.detach = function(force) {
    force = force || false;
    if (atom.views.getView(atom.workspace)) {
      atom.views.getView(atom.workspace).focus();
    }
    if (this.panel && (force || 'Keep Visible' !== atom.config.get('build.panelVisibility'))) {
      this.panel.destroy();
      this.panel = null;
    }
  };

  BuildView.prototype.isAttached = function() {
    return !!this.panel;
  };

  BuildView.prototype.heightFromConfig = function(val) {
    if (this.monocle) {
      this.setHeightPercent(atom.config.get('build.monocleHeight'));
    } else {
      this.setHeightPercent(atom.config.get('build.minimizedHeight'));
    }
  };

  BuildView.prototype.visibleFromConfig = function(val) {
    switch (val) {
      case 'Toggle':
      case 'Show on Error':
        if (!this.title.hasClass('error')) {
          this.detach();
        }
        break;
    }
  };

  BuildView.prototype.reset = function() {
    clearTimeout(this.titleTimer);
    this.titleTimer = 0;
    this.title.removeClass('success error warning');
    this.output.empty();
    this.title.text('Cleared.');
    this.detach();
  };

  BuildView.prototype.updateTitle = function() {
    this.title.text(this.titleLoop[this.titleLoopIndex]);
    this.titleLoopIndex = (this.titleLoopIndex + 1) % this.titleLoop.length;
    this.titleTimer = setTimeout(this.updateTitle.bind(this), 200);
  };

  BuildView.prototype.close = function(event, element) {
    this.detach(true);
  };

  BuildView.prototype.toggle = function(event, element) {
    GoogleAnalytics.sendEvent('view', 'panel toggled');
    this.isAttached() ?  this.detach(true) : this.attach(true);
  };

  BuildView.prototype.clear = function(event, element) {
    this.reset();
    this.attach();
  };

  BuildView.prototype.build = function(event, element) {
    atom.commands.dispatch(atom.views.getView(atom.workspace), 'build:trigger');
  };

  BuildView.prototype.setHeightPercent = function(percent) {
    var newHeight = percent * this.height;
    this.output.css('height', newHeight + 'px');
  };

  BuildView.prototype.toggleMonocle = function(event, element) {
    GoogleAnalytics.sendEvent('view', 'monocle toggled');
    if (!this.monocle) {
      this.setHeightPercent(atom.config.get('build.monocleHeight'));
      this.monocleButton.removeClass('icon-chevron-up').addClass('icon-chevron-down');
    } else {
      this.setHeightPercent(atom.config.get('build.minimizedHeight'));
      this.monocleButton.removeClass('icon-chevron-down').addClass('icon-chevron-up');
    }
    this.monocle = !this.monocle;
  };

  BuildView.prototype.buildStarted = function() {
    this.reset();
    this.attach();
    if (atom.config.get('build.stealFocus')) {
      this.focus();
    }
    this.updateTitle();
  };

  BuildView.prototype.buildFinished = function(success) {
    if (!success) {
      var force = (atom.config.get('build.panelVisibility') === 'Show on Error');
      this.attach(force);
    }
    this.title.text(success ? 'Build finished.' : 'Build failed.');
    this.title.addClass(success ? 'success' : 'error');
    clearTimeout(this.titleTimer);
  };

  BuildView.prototype.buildAbortInitiated = function() {
    this.title.text('Build process termination imminent...');
    clearTimeout(this.titleTimer);
    this.title.addClass('error');
  };

  BuildView.prototype.buildAborted = function() {
    this.title.text('Aborted!');
  };

  BuildView.prototype.append = function(line) {
    line = _.escape(line.toString());
    this.output.append('
' + (this.a2h.toHtml(line)) + '
');
    this.output.scrollTop(this.output[0].scrollHeight);
  };

  return BuildView;
})();
<|endoftext|>


<commit_before>'use strict';
(function (module) {
  var Bar = {};

  Bar.allBars = [];

//I have a feeling we need to refactor this still -nikko
  function Business(opts){
    opts.forEach(function(element){
      this[keys] = element[keys];
    },this);
  }

  Bar.requestData = function(){
    $.ajax({
      type: 'GET',
      url: '/yelp/v3/businesses/search?categories=bars&term=dogs%20allowed&location=seattle',
      success: function(data) {
        Bar.allBars = data;
        console.table(Bar.allBars);

      }
    });
  };
  module.Bar = Bar;
})(window);
<commit_msg>have contsructor working the way we need it to<commit_after>'use strict';
(function (module) {
  var Bar = {};

  Bar.allBars = [];

//I have a feeling we need to refactor this still -nikko
  function Business(opts){
    Object.keys(opts).forEach(function(element,index){
      this[element] = opts[element];
      this.name = opts[index].name;
      this.location = {
        latitude: this.latitude = opts[index].coordinates.latitude,
        longitude: this.longitude = opts[index].coordinates.longitude
      };
      // this.displayAddress = opts[index].display_address[0] + ' ' +  opts[index].display_address[1] + ' ' + opts[index].display_address[2];
      this.address = opts[index].location.display_address;
      this.phone = opts[index].display_phone;
      this.image = opts[index].image_url;
      this.price = opts[index].price;
      this.rating = opts[index].rating;
      this.currentlyOpen = opts[index].is_closed;
    },this);
  }

  Bar.requestData = function(){
    $.ajax({
      type: 'GET',
      url: '/yelp/v3/businesses/search?categories=bars&term=dogs%20allowed&location=seattle&limit=50',
      success: function(data) {
        var bar = new Business(data.businesses);
        Bar.allBars.push(bar);
        console.table(Bar.allBars);

      }
    });
  };
  module.Bar = Bar;
})(window);
<|endoftext|>


<commit_before>(function(){
  var BrowserStack = {};

  function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
        results = regex.exec(location.search);
    return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  }

  // Tiny Ajax Post
  var post = function (url, json, cb) {
    var req;

    if (window.ActiveXObject)
      req = new ActiveXObject('Microsoft.XMLHTTP');
    else if (window.XMLHttpRequest)
      req = new XMLHttpRequest();
    else
      throw "Strider: No ajax"

    req.onreadystatechange = function () {
      if (req.readyState==4)
        cb(req.responseText);
    };
    var data;
    if(window.CircularJSON) {
      data = window.CircularJSON.stringify(json);
    } else {
      data = JSON.stringify(json);
    }
    req.open("POST", url, true);
    req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    req.setRequestHeader('X-Browser-String', BrowserStack.browser_string);
    req.setRequestHeader('X-Worker-UUID', BrowserStack.worker_uuid);
    req.setRequestHeader('Content-type', 'application/json');
    req.send(data);
  }

  var browserstack_console = console || window.console || {};
  browserstack_console.log = function () {
    var args = BrowserStack.util.toArray(arguments).map(BrowserStack.util.inspect);
    post('/_log/', { arguments: args }, function () {});
  };
  browserstack_console.warn = function () {
    var args = BrowserStack.util.toArray(arguments).map(BrowserStack.util.inspect);
    post('/_log/', { arguments: args }, function () {});
  };

  BrowserStack.post = post;
  BrowserStack.getParameterByName = getParameterByName;

  BrowserStack.browser_string = getParameterByName('_browser_string');
  BrowserStack.worker_uuid = getParameterByName('_worker_key');

  window.BrowserStack = BrowserStack;
  window.console = browserstack_console;
  console = browserstack_console;
})();
<commit_msg>Fix bad console assignment<commit_after>(function(){
  var BrowserStack = {};

  function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
        results = regex.exec(location.search);
    return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  }

  // Tiny Ajax Post
  var post = function (url, json, cb) {
    var req;

    if (window.ActiveXObject)
      req = new ActiveXObject('Microsoft.XMLHTTP');
    else if (window.XMLHttpRequest)
      req = new XMLHttpRequest();
    else
      throw "Strider: No ajax"

    req.onreadystatechange = function () {
      if (req.readyState==4)
        cb(req.responseText);
    };
    var data;
    if(window.CircularJSON) {
      data = window.CircularJSON.stringify(json);
    } else {
      data = JSON.stringify(json);
    }
    req.open("POST", url, true);
    req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    req.setRequestHeader('X-Browser-String', BrowserStack.browser_string);
    req.setRequestHeader('X-Worker-UUID', BrowserStack.worker_uuid);
    req.setRequestHeader('Content-type', 'application/json');
    req.send(data);
  }

  // Change some console method to capture the logs.
  // This must not replace the console object itself so that other console methods
  //  from the browser or added by the tested application remain unaffected.
  // https://github.com/browserstack/browserstack-runner/pull/199
  var browserstack_console = window.console || {};
  browserstack_console.log = function () {
    var args = BrowserStack.util.toArray(arguments).map(BrowserStack.util.inspect);
    post('/_log/', { arguments: args }, function () {});
  };
  browserstack_console.warn = function () {
    var args = BrowserStack.util.toArray(arguments).map(BrowserStack.util.inspect);
    post('/_log/', { arguments: args }, function () {});
  };

  BrowserStack.post = post;
  BrowserStack.getParameterByName = getParameterByName;

  BrowserStack.browser_string = getParameterByName('_browser_string');
  BrowserStack.worker_uuid = getParameterByName('_worker_key');

  window.BrowserStack = BrowserStack;
  // If the browser didn't have a console object (old IE), then this will create it.
  // Otherwise this is a no-op as it will assign the same object it already held.
  window.console = browserstack_console;
})();
<|endoftext|>


<commit_before>'use strict';

describe('topology', function() {
  var Y, NS, views,
      TestModule, modA, state,
      container, topo,
      models,
      db;

  before(function(done) {
    Y = YUI(GlobalConfig).use(['juju-topology',
                               'd3-components',
                               'node',
                               'node-event-simulate'],
    function(Y) {
      NS = Y.namespace('d3');
      views = Y.namespace('juju.views');
      models = Y.namespace('juju.models');

      TestModule = Y.Base.create('TestModule', NS.Module, [], {
        events: {
          scene: { '.thing': {click: 'decorateThing'}},
          d3: {'.target': {click: 'targetTarget'}},
          yui: {
            cancel: 'cancelHandler'
          }
        },

        decorateThing: function(evt) {
          state.thing = 'decorated';
        },

        targetTarget: function(evt) {
          state.targeted = true;
        },

        cancelHandler: function(evt) {
          state.cancelled = true;
        }
      });

      done();
    });
  });

  beforeEach(function() {
    container = Y.Node.create('<div/>')
                 .setStyle('visibility', 'hidden')
                 .append(Y.Node.create('<button/>')
                 .addClass('thing'))
                 .append(Y.Node.create('<button/>')
                 .addClass('target'));
    state = {};
  });

  afterEach(function() {
    container.remove();
    container.destroy();
    if (topo) {
      topo.unbind();
    }
    if (db) {
      db.destroy();
    }
  });

  it('should be able to create a topology with default modules', function() {
    topo = new views.Topology();
    topo.setAttrs({container: container});
    topo.addModule(TestModule);
    topo.render();

    // Verify that we have built the default scene.
    Y.Lang.isValue(topo.vis).should.equal(true);
  });

  function createStandardTopo() {
    db = new models.Database();
    topo = new views.Topology();
    topo.setAttrs({container: container, db: db});
    topo.addModule(views.ServiceModule);
    topo.addModule(views.RelationModule);
    topo.addModule(views.PanZoomModule);
    topo.addModule(views.ViewportModule);
    return topo;
  }

  it('should be able to create a topology with standard env view modules',
     function() {
       topo = createStandardTopo();
       topo.render();
       // Verify that we have built the default scene.
       Y.Lang.isValue(topo.vis).should.equal(true);
     });

  it('should prevent the Juju GUI service from being destroyed', function() {
    var service = {
      charm: 'cs:precise/juju-gui-7'
    };
    var fauxTopo = {
      get: function() {
        return null;
      },
      serviceForBox: function() {
        return service;
      }
    };
    // The context is used to do the destroying, so if it does not have the
    // destroy method, an exception will be raised if the service would be
    // destroyed.
    var context = {
      get: function(name) {
        if (name === 'component') {
          return fauxTopo;
        }
      }
    };
    topo.events.ServiceModule.scene['.destroy-service'].click.callback(
        undefined, context);
  });
});

describe('service menu', function() {
  var Y, views;

  before(function(done) {
    Y = YUI(GlobalConfig).use(['juju-topology'], function(Y) {
      views = Y.namespace('juju.views');
      done();
    });
  });

  it('should disable the "Destroy" menu for the Juju GUI service', function() {
    var service = {
      charm: 'cs:precise/juju-gui-7'
    };
    var addedClassName;
    var menu = {
      hasClass: function() {
        return false;
      },
      addClass: function() {},
      one: function() {
        return {
          addClass: function(className) {
            addedClassName = className;
          }
        };
      }
    };
    var fauxView = {
      get: function(name) {
        if (name === 'container') {
          return {one: function() { return menu; }};
        } else if (name === 'component') {
          return {set: function() {}};
        }
      },
      updateServiceMenuLocation: function() {}
    };
    var view = new views.ServiceModule();
    view.service_click_actions.toggleServiceMenu(
        service, fauxView, undefined);
    assert.equal(addedClassName, 'disabled');
  });

});
<commit_msg>Fix failing test.<commit_after>'use strict';

describe('topology', function() {
  var Y, NS, views,
      TestModule, modA, state,
      container, topo,
      models,
      db;

  before(function(done) {
    Y = YUI(GlobalConfig).use(['juju-topology',
                               'd3-components',
                               'node',
                               'node-event-simulate'],
    function(Y) {
      NS = Y.namespace('d3');
      views = Y.namespace('juju.views');
      models = Y.namespace('juju.models');

      TestModule = Y.Base.create('TestModule', NS.Module, [], {
        events: {
          scene: { '.thing': {click: 'decorateThing'}},
          d3: {'.target': {click: 'targetTarget'}},
          yui: {
            cancel: 'cancelHandler'
          }
        },

        decorateThing: function(evt) {
          state.thing = 'decorated';
        },

        targetTarget: function(evt) {
          state.targeted = true;
        },

        cancelHandler: function(evt) {
          state.cancelled = true;
        }
      });

      done();
    });
  });

  beforeEach(function() {
    container = Y.Node.create('<div/>')
                 .setStyle('visibility', 'hidden')
                 .append(Y.Node.create('<button/>')
                 .addClass('thing'))
                 .append(Y.Node.create('<button/>')
                 .addClass('target'));
    state = {};
  });

  afterEach(function() {
    container.remove();
    container.destroy();
    if (topo) {
      topo.unbind();
    }
    if (db) {
      db.destroy();
    }
  });

  it('should be able to create a topology with default modules', function() {
    topo = new views.Topology();
    topo.setAttrs({container: container});
    topo.addModule(TestModule);
    topo.render();

    // Verify that we have built the default scene.
    Y.Lang.isValue(topo.vis).should.equal(true);
  });

  function createStandardTopo() {
    db = new models.Database();
    topo = new views.Topology();
    topo.setAttrs({container: container, db: db});
    topo.addModule(views.ServiceModule);
    topo.addModule(views.RelationModule);
    topo.addModule(views.PanZoomModule);
    topo.addModule(views.ViewportModule);
    return topo;
  }

  it('should be able to create a topology with standard env view modules',
     function() {
       topo = createStandardTopo();
       topo.render();
       // Verify that we have built the default scene.
       Y.Lang.isValue(topo.vis).should.equal(true);
     });

  it('should prevent the Juju GUI service from being destroyed', function() {
    var service = {
      charm: 'cs:precise/juju-gui-7'
    };
    var fauxTopo = {
      get: function() {
        return null;
      },
      serviceForBox: function() {
        return service;
      }
    };
    // The context is used to do the destroying, so if it does not have the
    // destroy method, an exception will be raised if the service would be
    // destroyed.
    var context = {
      get: function(name) {
        if (name === 'component') {
          return fauxTopo;
        }
      }
    };
    topo.events.ServiceModule.scene['.destroy-service'].click.callback(
        undefined, context);
  });
});

describe('service menu', function() {
  var Y, views;

  before(function(done) {
    Y = YUI(GlobalConfig).use(['juju-topology'], function(Y) {
      views = Y.namespace('juju.views');
      done();
    });
  });

  it('should disable the "Destroy" menu for the Juju GUI service', function() {
    var service = {
      charm: 'cs:precise/juju-gui-7'
    };
    var addedClassName;
    var menu = {
      hasClass: function() {
        return false;
      },
      addClass: function() {},
      one: function() {
        return {
          addClass: function(className) {
            addedClassName = className;
          }
        };
      }
    };
    var fauxView = {
      get: function(name) {
        if (name === 'container') {
          return {one: function() { return menu; }};
        } else if (name === 'component') {
          return { set: function() {},
                   serviceForBox: function(box) { return service;}
                 };
        }
      },
      updateServiceMenuLocation: function() {}
    };
    var view = new views.ServiceModule();
    view.service_click_actions.toggleServiceMenu(
        service, fauxView, undefined);
    assert.equal(addedClassName, 'disabled');
  });

});
<|endoftext|>


<commit_before>"use strict";

class gsuiMixer {
	constructor() {
		const root = gsuiMixer.template.cloneNode( true ),
			addBtn = root.querySelector( ".gsuiMixer-addChan" );

		this.rootElement = root;
		this._pmain = root.querySelector( ".gsuiMixer-panMain" );
		this._pchannels = root.querySelector( ".gsuiMixer-panChannels" );
		this._channels = {};
		this._chanSelected = null;
		this.oninput =
		this.onchange =
		this.onaddChan =
		this.ondeleteChan =
		this.onupdateChan =
		this.onselectChan = () => {};
		this._maxId =
		this._maxOrder = 0;
		this._analyserW =
		this._analyserH = 10;
		addBtn.onclick = this._onclickAddChan.bind( this );
		this.data = this._proxInit();
		this.empty();
	}

	attached() {
		const pan = this._pchannels;

		this._attached = true;
		pan.style.bottom = pan.clientHeight - pan.offsetHeight + "px";
		Object.entries( this.data ).forEach( ( [ id, obj ] ) => {
			const html = this._channels[ id ];

			html.pan.attached();
			html.gain.attached();
			this.onaddChan( id, obj );
		} );
		this.resized();
	}
	resized() {
		const chans = Object.values( this._channels ),
			bcr = chans[ 0 ].analyser.rootElement.getBoundingClientRect(),
			w = bcr.width,
			h = bcr.height;

		this._analyserW = w;
		this._analyserH = h;
		chans.forEach( html => html.analyser.setResolution( w, h ) );
	}
	updateAudioData( id, ldata, rdata ) {
		this._channels[ id ].analyser.draw( ldata, rdata );
	}
	empty() {
		const main = {
				order: 0,
				toggle: true,
				name: "",
				gain: 1,
				pan: 0,
			};

		Object.keys( this.data ).forEach( id => {
			if ( id !== "main" ) {
				delete this.data[ id ];
			}
		} );
		if ( this.data.main ) {
			Object.assign( this.data.main, main );
		} else {
			this.data.main = main;
		}
		this.selectChan( "main" );
	}
	selectChan( id ) {
		const chan = this._channels[ id ].root,
			pchan = this._channels[ this._chanSelected ];

		pchan && pchan.root.classList.remove( "gsuiMixer-selected" );
		chan.classList.add( "gsuiMixer-selected" );
		this._chanSelected = id;
		this._updateChanConnections();
		this.onselectChan( id );
	}

	// events:
	_oninput( id, prop, val ) {
		this.oninput( id, prop, val );
	}
	_onchange( id, prop, val ) {
		this.data[ id ][ prop ] = val;
		this.onchange( { [ id ]: { [ prop ]: val } } );
	}
	_onclickToggleChan( id ) {
		this._onchange( id, "toggle", !this.data[ id ].toggle );
	}
	_onclickAddChan() {
		const id = this._maxId + 1,
			obj = {
				dest: "main",
				toggle: true,
				order: this._maxOrder + 1,
				name: `chan ${ this._pchannels.children.length }`,
				gain: 1,
				pan: 0,
			};

		this.data[ id ] = obj;
		this.onchange( { [ id ]: obj } );
	}
	_onclickDeleteChan( id ) {
		const obj = { [ id ]: undefined };

		Object.entries( this.data ).forEach( kv => {
			if ( kv[ 1 ].dest === id ) {
				obj[ kv[ 0 ] ] = { dest: "main" };
				this.data[ kv[ 0 ] ].dest = "main";
			}
		} );
		delete this.data[ id ];
		this.onchange( obj );
	}

	// private:
	_updateChanConnections() {
		const selId = this._chanSelected;

		if ( selId ) {
			const data = this.data,
				chanDest = data[ selId ].dest,
				chan = this._channels[ selId ];
			let rdOnce = false;

			Object.entries( data ).forEach( ( [ id, chan ] ) => {
				const conn = this._channels[ id ].connect.classList,
					lu = id === chanDest,
					rd = chan.dest === selId;

				conn.remove(
					"gsuiMixerChannel-leftdown",
					"gsuiMixerChannel-rightup" );
				conn.toggle( "gsuiMixerChannel-leftup", lu );
				conn.toggle( "gsuiMixerChannel-rightdown", rd );
				rdOnce = rdOnce || rd;
			} );
			chan.connect.classList.toggle( "gsuiMixerChannel-leftdown", selId !== "main" );
			chan.connect.classList.toggle( "gsuiMixerChannel-rightup", rdOnce );
		}
	}
	_getChan( id ) {
		return Array.from( this._channels ).find( chan => {
			if ( chan.dataset.id === id ) {
				return true;
			}
		} );
	}
	_getNextChan( el, dir ) {
		const sibling = el[ dir ];

		return sibling && "id" in sibling.dataset ? sibling : null;
	}
	_addChan( id, obj ) {
		const root = gsuiMixer.channelTemplate.cloneNode( true ),
			qs = n => root.querySelector( `.gsuiMixerChannel-${ n }` ),
			pan = new gsuiSlider(),
			gain = new gsuiSlider(),
			canvas = qs( "analyser" ),
			html = { root, pan, gain,
				name: qs( "name" ),
				connect: qs( "connect" ),
				analyser: new gsuiAnalyser(),
			};

		this._channels[ id ] = html;
		root.dataset.id = id;
		qs( "pan" ).append( pan.rootElement );
		qs( "gain" ).append( gain.rootElement );
		html.analyser.setCanvas( canvas );
		html.analyser.setResolution( 32, 224 );
		pan.options( {
			max: 1,
			min: -1,
			step: .001,
			type: "circular",
			strokeWidth: 3,
		} );
		gain.options( {
			max: 1,
			min: 0,
			step: .001,
			type: "linear-y",
		} );
		pan.oninput = this._oninput.bind( this, id, "pan" );
		gain.oninput = this._oninput.bind( this, id, "gain" );
		pan.onchange = this._onchange.bind( this, id, "pan" );
		gain.onchange = this._onchange.bind( this, id, "gain" );
		canvas.onclick =
		qs( "nameWrap" ).onclick = this.selectChan.bind( this, id );
		qs( "toggle" ).onclick = this._onclickToggleChan.bind( this, id );
		qs( "delete" ).onclick = this._onclickDeleteChan.bind( this, id );
		html.connect.onclick = this._setChanDest.bind( this, id );
		( this._pmain.firstElementChild
			? this._pchannels
			: this._pmain ).append( root );
		if ( this._attached ) {
			pan.attached();
			gain.attached();
			html.analyser.setResolution( this._analyserW, this._analyserH );
		}
		this._updateChanConnections();
	}
	_deleteChan( id ) {
		const el = this._channels[ id ].root;

		if ( id === this._chanSelected ) {
			const next = this._getNextChan( el, "nextElementSibling" );

			if ( next ) {
				this.selectChan( next.dataset.id );
			} else {
				const prev = this._getNextChan( el, "previousElementSibling" );

				this.selectChan( prev ? prev.dataset.id : "main" );
			}
		}
		delete this._channels[ id ];
		el.remove();
	}
	_setChanDest( destId ) {
		const id = this._chanSelected;

		if ( id !== "main" &&
			id !== destId &&
			this.data[ id ].dest !== destId
		) {
			this._onchange( id, "dest", destId );
			this._updateChanConnections();
		}
	}
	_updateChan( id, prop, val ) {
		const el = this._channels[ id ];

		switch ( prop ) {
			case "pan": el.pan.setValue( val ); break;
			case "gain": el.gain.setValue( val ); break;
			case "name": el.name.textContent = val; break;
			case "dest": this._updateChanConnections(); break;
			case "order": el.root.style.order = val; break;
			case "toggle": el.root.classList.toggle( "gsuiMixerChannel-muted", !val ); break;
		}
	}

	// proxy:
	_proxInit() {
		return new Proxy( {}, {
			set: this._proxAddChan.bind( this ),
			deleteProperty: this._proxDeleteChan.bind( this ),
		} );
	}
	_proxAddChan( tar, id, obj ) {
		this._proxDeleteChan( tar, id );
		return this.__proxAddChan( tar, id, obj );
	}
	_proxDeleteChan( tar, id ) {
		if ( id in tar ) {
			delete tar[ id ];
			this._deleteChan( id );
			this.ondeleteChan( id );
		}
		return true;
	}
	__proxAddChan( tar, id, obj ) {
		const tarchan = {
				toggle: true,
				order: 0,
				name: "",
				gain: 0,
				pan: 0,
			},
			_ = id !== "main" ? ( tarchan.dest = "main" ) : null,
			updateChan = this._proxUpdateChan.bind( this, id ),
			chan = new Proxy( Object.seal( tarchan ), { set: updateChan } );

		tar[ id ] = chan;
		this._maxId = Math.max( this._maxId, id ) || 0; // 1.
		this._maxOrder = Math.max( this._maxOrder, obj.order );
		this._addChan( id, chan );
		this.onaddChan( id, chan );
		chan.pan = obj.pan;
		chan.gain = obj.gain;
		chan.name = obj.name;
		chan.toggle = obj.toggle;
		chan.order = obj.order;
		if ( obj.dest ) {
			chan.dest = obj.dest;
		}
		return true;
	}
	_proxUpdateChan( id, tar, prop, val ) {
		tar[ prop ] = val;
		this._updateChan( id, prop, val );
		this.onupdateChan( id, prop, val );
		return true;
	}
}

gsuiMixer.template = document.querySelector( "#gsuiMixer-template" );
gsuiMixer.template.remove();
gsuiMixer.template.removeAttribute( "id" );

gsuiMixer.channelTemplate = document.querySelector( "#gsuiMixerChannel-template" );
gsuiMixer.channelTemplate.remove();
gsuiMixer.channelTemplate.removeAttribute( "id" );

/*
1.	Why `|| 0` after Math.max ?
	Because the ID of the main channel is "main".
*/
<commit_msg>gsuiMixer: simplify the use of gsuiAnalyser<commit_after>"use strict";

class gsuiMixer {
	constructor() {
		const root = gsuiMixer.template.cloneNode( true ),
			addBtn = root.querySelector( ".gsuiMixer-addChan" );

		this.rootElement = root;
		this._pmain = root.querySelector( ".gsuiMixer-panMain" );
		this._pchannels = root.querySelector( ".gsuiMixer-panChannels" );
		this._channels = {};
		this._chanSelected = null;
		this.oninput =
		this.onchange =
		this.onaddChan =
		this.ondeleteChan =
		this.onupdateChan =
		this.onselectChan = () => {};
		this._maxId =
		this._maxOrder = 0;
		this._analyserH = 10;
		addBtn.onclick = this._onclickAddChan.bind( this );
		this.data = this._proxInit();
		this.empty();
	}

	attached() {
		const pan = this._pchannels;

		this._attached = true;
		pan.style.bottom = pan.clientHeight - pan.offsetHeight + "px";
		Object.entries( this.data ).forEach( ( [ id, obj ] ) => {
			const html = this._channels[ id ];

			html.pan.attached();
			html.gain.attached();
			this.onaddChan( id, obj );
		} );
		this.resized();
	}
	resized() {
		const chans = Object.values( this._channels ),
			h = chans[ 0 ].analyser.rootElement.getBoundingClientRect().height;

		this._analyserH = h;
		chans.forEach( html => html.analyser.setResolution( h ) );
	}
	updateAudioData( id, ldata, rdata ) {
		this._channels[ id ].analyser.draw( ldata, rdata );
	}
	empty() {
		const main = {
				order: 0,
				toggle: true,
				name: "",
				gain: 1,
				pan: 0,
			};

		Object.keys( this.data ).forEach( id => {
			if ( id !== "main" ) {
				delete this.data[ id ];
			}
		} );
		if ( this.data.main ) {
			Object.assign( this.data.main, main );
		} else {
			this.data.main = main;
		}
		this.selectChan( "main" );
	}
	selectChan( id ) {
		const chan = this._channels[ id ].root,
			pchan = this._channels[ this._chanSelected ];

		pchan && pchan.root.classList.remove( "gsuiMixer-selected" );
		chan.classList.add( "gsuiMixer-selected" );
		this._chanSelected = id;
		this._updateChanConnections();
		this.onselectChan( id );
	}

	// events:
	_oninput( id, prop, val ) {
		this.oninput( id, prop, val );
	}
	_onchange( id, prop, val ) {
		this.data[ id ][ prop ] = val;
		this.onchange( { [ id ]: { [ prop ]: val } } );
	}
	_onclickToggleChan( id ) {
		this._onchange( id, "toggle", !this.data[ id ].toggle );
	}
	_onclickAddChan() {
		const id = this._maxId + 1,
			obj = {
				dest: "main",
				toggle: true,
				order: this._maxOrder + 1,
				name: `chan ${ this._pchannels.children.length }`,
				gain: 1,
				pan: 0,
			};

		this.data[ id ] = obj;
		this.onchange( { [ id ]: obj } );
	}
	_onclickDeleteChan( id ) {
		const obj = { [ id ]: undefined };

		Object.entries( this.data ).forEach( kv => {
			if ( kv[ 1 ].dest === id ) {
				obj[ kv[ 0 ] ] = { dest: "main" };
				this.data[ kv[ 0 ] ].dest = "main";
			}
		} );
		delete this.data[ id ];
		this.onchange( obj );
	}

	// private:
	_updateChanConnections() {
		const selId = this._chanSelected;

		if ( selId ) {
			const data = this.data,
				chanDest = data[ selId ].dest,
				chan = this._channels[ selId ];
			let rdOnce = false;

			Object.entries( data ).forEach( ( [ id, chan ] ) => {
				const conn = this._channels[ id ].connect.classList,
					lu = id === chanDest,
					rd = chan.dest === selId;

				conn.remove(
					"gsuiMixerChannel-leftdown",
					"gsuiMixerChannel-rightup" );
				conn.toggle( "gsuiMixerChannel-leftup", lu );
				conn.toggle( "gsuiMixerChannel-rightdown", rd );
				rdOnce = rdOnce || rd;
			} );
			chan.connect.classList.toggle( "gsuiMixerChannel-leftdown", selId !== "main" );
			chan.connect.classList.toggle( "gsuiMixerChannel-rightup", rdOnce );
		}
	}
	_getChan( id ) {
		return Array.from( this._channels ).find( chan => {
			if ( chan.dataset.id === id ) {
				return true;
			}
		} );
	}
	_getNextChan( el, dir ) {
		const sibling = el[ dir ];

		return sibling && "id" in sibling.dataset ? sibling : null;
	}
	_addChan( id, obj ) {
		const root = gsuiMixer.channelTemplate.cloneNode( true ),
			qs = n => root.querySelector( `.gsuiMixerChannel-${ n }` ),
			pan = new gsuiSlider(),
			gain = new gsuiSlider(),
			canvas = qs( "analyser" ),
			html = { root, pan, gain,
				name: qs( "name" ),
				connect: qs( "connect" ),
				analyser: new gsuiAnalyser(),
			};

		this._channels[ id ] = html;
		root.dataset.id = id;
		qs( "pan" ).append( pan.rootElement );
		qs( "gain" ).append( gain.rootElement );
		html.analyser.setCanvas( canvas );
		pan.options( {
			max: 1,
			min: -1,
			step: .001,
			type: "circular",
			strokeWidth: 3,
		} );
		gain.options( {
			max: 1,
			min: 0,
			step: .001,
			type: "linear-y",
		} );
		pan.oninput = this._oninput.bind( this, id, "pan" );
		gain.oninput = this._oninput.bind( this, id, "gain" );
		pan.onchange = this._onchange.bind( this, id, "pan" );
		gain.onchange = this._onchange.bind( this, id, "gain" );
		canvas.onclick =
		qs( "nameWrap" ).onclick = this.selectChan.bind( this, id );
		qs( "toggle" ).onclick = this._onclickToggleChan.bind( this, id );
		qs( "delete" ).onclick = this._onclickDeleteChan.bind( this, id );
		html.connect.onclick = this._setChanDest.bind( this, id );
		( this._pmain.firstElementChild
			? this._pchannels
			: this._pmain ).append( root );
		if ( this._attached ) {
			pan.attached();
			gain.attached();
			html.analyser.setResolution( this._analyserH );
		}
		this._updateChanConnections();
	}
	_deleteChan( id ) {
		const el = this._channels[ id ].root;

		if ( id === this._chanSelected ) {
			const next = this._getNextChan( el, "nextElementSibling" );

			if ( next ) {
				this.selectChan( next.dataset.id );
			} else {
				const prev = this._getNextChan( el, "previousElementSibling" );

				this.selectChan( prev ? prev.dataset.id : "main" );
			}
		}
		delete this._channels[ id ];
		el.remove();
	}
	_setChanDest( destId ) {
		const id = this._chanSelected;

		if ( id !== "main" &&
			id !== destId &&
			this.data[ id ].dest !== destId
		) {
			this._onchange( id, "dest", destId );
			this._updateChanConnections();
		}
	}
	_updateChan( id, prop, val ) {
		const el = this._channels[ id ];

		switch ( prop ) {
			case "pan": el.pan.setValue( val ); break;
			case "gain": el.gain.setValue( val ); break;
			case "name": el.name.textContent = val; break;
			case "dest": this._updateChanConnections(); break;
			case "order": el.root.style.order = val; break;
			case "toggle": el.root.classList.toggle( "gsuiMixerChannel-muted", !val ); break;
		}
	}

	// proxy:
	_proxInit() {
		return new Proxy( {}, {
			set: this._proxAddChan.bind( this ),
			deleteProperty: this._proxDeleteChan.bind( this ),
		} );
	}
	_proxAddChan( tar, id, obj ) {
		this._proxDeleteChan( tar, id );
		return this.__proxAddChan( tar, id, obj );
	}
	_proxDeleteChan( tar, id ) {
		if ( id in tar ) {
			delete tar[ id ];
			this._deleteChan( id );
			this.ondeleteChan( id );
		}
		return true;
	}
	__proxAddChan( tar, id, obj ) {
		const tarchan = {
				toggle: true,
				order: 0,
				name: "",
				gain: 0,
				pan: 0,
			},
			_ = id !== "main" ? ( tarchan.dest = "main" ) : null,
			updateChan = this._proxUpdateChan.bind( this, id ),
			chan = new Proxy( Object.seal( tarchan ), { set: updateChan } );

		tar[ id ] = chan;
		this._maxId = Math.max( this._maxId, id ) || 0; // 1.
		this._maxOrder = Math.max( this._maxOrder, obj.order );
		this._addChan( id, chan );
		this.onaddChan( id, chan );
		chan.pan = obj.pan;
		chan.gain = obj.gain;
		chan.name = obj.name;
		chan.toggle = obj.toggle;
		chan.order = obj.order;
		if ( obj.dest ) {
			chan.dest = obj.dest;
		}
		return true;
	}
	_proxUpdateChan( id, tar, prop, val ) {
		tar[ prop ] = val;
		this._updateChan( id, prop, val );
		this.onupdateChan( id, prop, val );
		return true;
	}
}

gsuiMixer.template = document.querySelector( "#gsuiMixer-template" );
gsuiMixer.template.remove();
gsuiMixer.template.removeAttribute( "id" );

gsuiMixer.channelTemplate = document.querySelector( "#gsuiMixerChannel-template" );
gsuiMixer.channelTemplate.remove();
gsuiMixer.channelTemplate.removeAttribute( "id" );

/*
1.	Why `|| 0` after Math.max ?
	Because the ID of the main channel is "main".
*/
<|endoftext|>


<commit_before>"use strict";

class gsuiTrack {
	constructor() {
		const root = gsuiTrack.template.cloneNode( true );

		this.rootElement = root;
		this.rowElement = root.querySelector( ".gsui-row" );
		this.rowElement.remove();
		this.uiToggle = new gsuiToggle();
		this.uiSpan = new gsuiSpanEditable();
		root.append( this.uiToggle.rootElement, this.uiSpan.rootElement );

		this.onchange = () => {};
		this.uiSpan.onchange = name => this.onchange( { name } );
		this.uiToggle.onchange = toggle => this.onchange( { toggle } );
		this.data = new Proxy( Object.seal( {
			name: "",
			toggle: true
		} ), { set: this._setProp.bind( this ) } );
		this.data.toggle = true;
	}

	remove() {
		this.rootElement.remove();
		this.rowElement.remove();
	}
	setPlaceholder( p ) {
		this.uiSpan.setPlaceholder( p );
	}

	// private:
	_setProp( tar, prop, val ) {
		if ( prop in tar ) {
			tar[ prop ] = val;
			this[ prop === "name" ? "_setName" : "_setToggle" ]( val );
		}
		return true;
	}
	_setName( name ) {
		this.uiSpan.setValue( name );
	}
	_setToggle( b ) {
		this.rootElement.classList.toggle( "gsui-mute", !b );
		this.rowElement.classList.toggle( "gsui-mute", !b );
		this.uiToggle.toggle( b );
	}
}

gsuiTrack.template = document.querySelector( "#gsuiTrack-template" );
gsuiTrack.template.remove();
gsuiTrack.template.removeAttribute( "id" );
<commit_msg>gsuiTrack: add 'order' attribute<commit_after>"use strict";

class gsuiTrack {
	constructor() {
		const root = gsuiTrack.template.cloneNode( true );

		this.rootElement = root;
		this.rowElement = root.querySelector( ".gsui-row" );
		this.rowElement.remove();
		this.uiToggle = new gsuiToggle();
		this.uiSpan = new gsuiSpanEditable();
		root.append( this.uiToggle.rootElement, this.uiSpan.rootElement );

		this.onchange = () => {};
		this.uiSpan.onchange = name => this.onchange( { name } );
		this.uiToggle.onchange = toggle => this.onchange( { toggle } );
		this.data = new Proxy( Object.seal( {
			order: 0,
			name: "",
			toggle: true
		} ), { set: this._setProp.bind( this ) } );
		this.data.toggle = true;
	}

	remove() {
		this.rootElement.remove();
		this.rowElement.remove();
	}
	setPlaceholder( p ) {
		this.uiSpan.setPlaceholder( p );
	}

	// private:
	_setProp( tar, prop, val ) {
		tar[ prop ] = val;
		switch ( prop ) {
			case "name": this._setName( val ); break;
			case "toggle": this._setToggle( val ); break;
		}
		return true;
	}
	_setName( name ) {
		this.uiSpan.setValue( name );
	}
	_setToggle( b ) {
		this.rootElement.classList.toggle( "gsui-mute", !b );
		this.rowElement.classList.toggle( "gsui-mute", !b );
		this.uiToggle.toggle( b );
	}
}

gsuiTrack.template = document.querySelector( "#gsuiTrack-template" );
gsuiTrack.template.remove();
gsuiTrack.template.removeAttribute( "id" );
<|endoftext|>


<commit_before>// Includes
var addIf = require('./addIf.js');
var options = require('../options.js');
var promise = require('../util/promise.js');

// Define
function wrap (type, index, func) {
  var cache = options.cache;
  if (cache[type].expire > 0) {
    return promise(function (resolve, reject) {
      addIf(cache, type, index, {
        done: resolve,
        add: function (done) {
          return promise(func).then(done);
        }
      });
    });
  } else {
    return promise(func);
  }
}

module.exports = function (type, index, func) {
  return wrap(type, index, func);
};
<commit_msg>Catch errors<commit_after>// Includes
var addIf = require('./addIf.js');
var options = require('../options.js');
var promise = require('../util/promise.js');

// Define
function wrap (type, index, func) {
  var cache = options.cache;
  if (cache[type].expire > 0) {
    return promise(function (resolve, reject) {
      addIf(cache, type, index, {
        done: resolve,
        add: function (done) {
          return promise(func).then(done).catch(reject);
        }
      });
    });
  } else {
    return promise(func);
  }
}

module.exports = function (type, index, func) {
  return wrap(type, index, func);
};
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Ajax.org B.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ***** END LICENSE BLOCK ***** */

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

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var Tokenizer = require("../tokenizer").Tokenizer;
var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var Range = require("../range").Range;
var WorkerClient = require("../worker/worker_client").WorkerClient;
var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
var CStyleFoldMode = require("./folding/cstyle").FoldMode;

var Mode = function() {
    this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules());
    this.$outdent = new MatchingBraceOutdent();
    this.$behaviour = new CstyleBehaviour();
    this.foldingRules = new CStyleFoldMode();
};
oop.inherits(Mode, TextMode);

(function() {

    this.toggleCommentLines = function(state, doc, startRow, endRow) {
        var outdent = true;
        var re = /^(\s*)\/\//;

        for (var i=startRow; i<= endRow; i++) {
            if (!re.test(doc.getLine(i))) {
                outdent = false;
                break;
            }
        }

        if (outdent) {
            var deleteRange = new Range(0, 0, 0, 0);
            for (var i=startRow; i<= endRow; i++)
            {
                var line = doc.getLine(i);
                var m = line.match(re);
                deleteRange.start.row = i;
                deleteRange.end.row = i;
                deleteRange.end.column = m[0].length;
                doc.replace(deleteRange, m[1]);
            }
        }
        else {
            doc.indentRows(startRow, endRow, "//");
        }
    };

    this.getNextLineIndent = function(state, line, tab) {
        var indent = this.$getIndent(line);

        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
        var tokens = tokenizedLine.tokens;
        var endState = tokenizedLine.state;

        if (tokens.length && tokens[tokens.length-1].type == "comment") {
            return indent;
        }

        if (state == "start" || state == "no_regex") {
            var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);
            if (match) {
                indent += tab;
            }
        } else if (state == "doc-start") {
            if (endState == "start" || endState == "no_regex") {
                return "";
            }
            var match = line.match(/^\s*(\/?)\*/);
            if (match) {
                if (match[1]) {
                    indent += " ";
                }
                indent += "* ";
            }
        }

        return indent;
    };

    this.checkOutdent = function(state, line, input) {
        return this.$outdent.checkOutdent(line, input);
    };

    this.autoOutdent = function(state, doc, row) {
        this.$outdent.autoOutdent(doc, row);
    };

    this.createWorker = function(session) {
        var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
        worker.attachToDocument(session.getDocument());

        worker.on("jslint", function(results) {
            session.setAnnotations(results.data);
        });

        worker.on("terminate", function() {
            session.clearAnnotations();
        });

        return worker;
    };

}).call(Mode.prototype);

exports.Mode = Mode;
});
<commit_msg>change toggleCommentLines behavior to match sublime text<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Ajax.org B.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ***** END LICENSE BLOCK ***** */

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

var oop = require("../lib/oop");
var lang = require("ace/lib/lang");
var TextMode = require("./text").Mode;
var Tokenizer = require("../tokenizer").Tokenizer;
var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var Range = require("../range").Range;
var WorkerClient = require("../worker/worker_client").WorkerClient;
var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
var CStyleFoldMode = require("./folding/cstyle").FoldMode;

var Mode = function() {
    this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules());
    this.$outdent = new MatchingBraceOutdent();
    this.$behaviour = new CstyleBehaviour();
    this.foldingRules = new CStyleFoldMode();
};
oop.inherits(Mode, TextMode);

(function() {

    this.lineCommentStart = "//";
    this.toggleCommentLines = function(state, session, startRow, endRow) {
        var doc = session.doc;
        var str = this.lineCommentStart;
        var regexpStart = new RegExp("^\\s*"+lang.escapeRegExp(str) + " ?");

        function isCommented(str) {
            return regexpStart.test(str);
        }

        var removeComment = true;
        var minSpace = Infinity;
        var indentations = [];

        for (var i = startRow; i <= endRow; i++) {
            var line = doc.getLine(i);
            var indent = line.search(/\S|$/);
            indentations[i] = indent;
            if (indent < minSpace)
                minSpace = indent;
            if (removeComment && !isCommented(line))
                removeComment = false;
        }

        if (removeComment) {
            for (var i = startRow; i <= endRow; i++) {
                var line = doc.getLine(i);
                var m = line.match(regexpStart);
                doc.removeInLine(i, indentations[i], m[0].length);
            }
        } else {
            str += " ";
            for (var i = startRow; i <= endRow; i++) {
                doc.insertInLine({row: i, column: minSpace}, str);
            }
        }
    };

    this.getNextLineIndent = function(state, line, tab) {
        var indent = this.$getIndent(line);

        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
        var tokens = tokenizedLine.tokens;
        var endState = tokenizedLine.state;

        if (tokens.length && tokens[tokens.length-1].type == "comment") {
            return indent;
        }

        if (state == "start" || state == "no_regex") {
            var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);
            if (match) {
                indent += tab;
            }
        } else if (state == "doc-start") {
            if (endState == "start" || endState == "no_regex") {
                return "";
            }
            var match = line.match(/^\s*(\/?)\*/);
            if (match) {
                if (match[1]) {
                    indent += " ";
                }
                indent += "* ";
            }
        }

        return indent;
    };

    this.checkOutdent = function(state, line, input) {
        return this.$outdent.checkOutdent(line, input);
    };

    this.autoOutdent = function(state, doc, row) {
        this.$outdent.autoOutdent(doc, row);
    };

    this.createWorker = function(session) {
        var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
        worker.attachToDocument(session.getDocument());

        worker.on("jslint", function(results) {
            session.setAnnotations(results.data);
        });

        worker.on("terminate", function() {
            session.clearAnnotations();
        });

        return worker;
    };

}).call(Mode.prototype);

exports.Mode = Mode;
});
<|endoftext|>


<commit_before>// Cryptocat XMPP functions and callbacks.

Cryptocat.xmpp = {}
Cryptocat.xmpp.currentStatus = 'online'
Cryptocat.xmpp.connection = null

// Default connection settings.
Cryptocat.xmpp.defaultDomain = 'crypto.cat'
Cryptocat.xmpp.defaultConferenceServer = 'conference.crypto.cat'
Cryptocat.xmpp.defaultRelay = 'https://crypto.cat/http-bind'

Cryptocat.xmpp.domain = Cryptocat.xmpp.defaultDomain
Cryptocat.xmpp.conferenceServer = Cryptocat.xmpp.defaultConferenceServer
Cryptocat.xmpp.relay = Cryptocat.xmpp.defaultRelay

$(window).ready(function() {

// connect anonymously and join conversation.
Cryptocat.xmpp.connect = function() {
	Cryptocat.conversationName = Strophe.xmlescape($('#conversationName').val())
	Cryptocat.myNickname = Strophe.xmlescape($('#nickname').val())
	Cryptocat.xmpp.connection = new Strophe.Connection(Cryptocat.xmpp.relay)
	Cryptocat.xmpp.connection.connect(Cryptocat.xmpp.domain, null, function(status) {
		if (status === Strophe.Status.CONNECTING) {
			$('#loginInfo').animate({'background-color': '#97CEEC'}, 200)
			$('#loginInfo').text(Cryptocat.locale['loginMessage']['connecting'])
		}
		else if (status === Strophe.Status.CONNECTED) {
			$('.conversationName').animate({'background-color': '#97CEEC'})
			Cryptocat.xmpp.connection.ibb.addIBBHandler(Cryptocat.otr.ibbHandler)
			/* jshint -W106 */
			Cryptocat.xmpp.connection.si_filetransfer.addFileHandler(Cryptocat.otr.fileHandler)
			/* jshint +W106 */
			Cryptocat.xmpp.connection.muc.join(
				Cryptocat.conversationName + '@' + Cryptocat.xmpp.conferenceServer,
				Cryptocat.myNickname,
				function(message) {
					if (Cryptocat.xmpp.onMessage(message)) { return true }
				},
				function (presence) {
					if (Cryptocat.xmpp.onPresence(presence)) { return true }
				}
			)
			if (Cryptocat.audioNotifications) {
				Cryptocat.sounds.keygenLoop.pause()
				Cryptocat.sounds.keygenEnd.play()
			}
			$('#fill').stop().animate({
				'width': '100%', 'opacity': '1'
			}, 250, 'linear', function() {
				window.setTimeout(function() {
					$('#dialogBoxClose').click()
				}, 200)
			})
			window.setTimeout(function() {
				Cryptocat.xmpp.onConnected()
			}, 400)
		}
		else if (status === Strophe.Status.CONNFAIL) {
			if (Cryptocat.loginError) {
				Cryptocat.xmpp.reconnect()
			}
		}
		else if (status === Strophe.Status.DISCONNECTED) {
			if (Cryptocat.loginError) {
				Cryptocat.xmpp.reconnect()
			}
		}
	})
}

// Executes on successfully completed XMPP connection.
Cryptocat.xmpp.onConnected = function() {
	clearInterval(CatFacts.interval)
	Cryptocat.storage.setItem('myNickname', Cryptocat.myNickname)
	$('#buddy-main-Conversation').attr('status', 'online')
	$('#loginInfo').text('✓')
	$('#info').fadeOut(200)
	$('#loginOptions,#languages,#customServerDialog,#version,#logoText,#loginInfo').fadeOut(200)
	$('#header').animate({'background-color': '#151520'})
	$('.logo').animate({'margin': '-11px 5px 0 0'})
	$('#loginForm').fadeOut(200, function() {
		$('#conversationInfo').fadeIn()
		$('#buddy-main-Conversation').click(function() {
			Cryptocat.onBuddyClick('main-Conversation')
		})
		$('#buddy-main-Conversation').click()
		$('#conversationWrapper').fadeIn()
		$('#optionButtons').fadeIn()
		$('#footer').delay(200).animate({'height': 60}, function() {
			$('#userInput').fadeIn(200, function() {
				$('#userInputText').focus()
			})
		})
		$('#buddyWrapper').slideDown()
	})
	Cryptocat.loginError = true
	document.title = Cryptocat.myNickname + '@' + Cryptocat.conversationName
}

// Reconnect to the same chatroom, on accidental connection loss.
Cryptocat.xmpp.reconnect = function() {
	multiParty.reset()
	if (Cryptocat.xmpp.connection) {
	    Cryptocat.xmpp.connection.reset()
	}
	Cryptocat.xmpp.connection = new Strophe.Connection(Cryptocat.xmpp.relay)
	Cryptocat.xmpp.connection.connect(Cryptocat.xmpp.domain, null, function(status) {
		if (status === Strophe.Status.CONNECTING) {
			$('.conversationName').animate({'background-color': '#F00'})
		}
		else if (status === Strophe.Status.CONNECTED) {
			$('.conversationName').animate({'background-color': '#97CEEC'})
			Cryptocat.xmpp.connection.ibb.addIBBHandler(Cryptocat.otr.ibbHandler)
			/* jshint -W106 */
			Cryptocat.xmpp.connection.si_filetransfer.addFileHandler(Cryptocat.otr.fileHandler)
			/* jshint +W106 */
			Cryptocat.xmpp.connection.muc.join(
				Cryptocat.conversationName + '@' + Cryptocat.xmpp.conferenceServer,
				Cryptocat.myNickname
			)
			if (Cryptocat.audioNotifications) {
				Cryptocat.sounds.keygenLoop.pause()
				Cryptocat.sounds.keygenEnd.play()
			}
		}
		else if ((status === Strophe.Status.CONNFAIL) || (status === Strophe.Status.DISCONNECTED)) {
			if (Cryptocat.loginError) {
				window.setTimeout(function() {
				Cryptocat.xmpp.reconnect()
				}, 5000)
			}
		}
	})
}

// Handle incoming messages from the XMPP server.
Cryptocat.xmpp.onMessage = function(message) {
	var nickname = cleanNickname($(message).attr('from'))
	var body = $(message).find('body').text()
	var type = $(message).attr('type')
	// If archived message, ignore.
	if ($(message).find('delay').length !== 0) {
		return true
	}
	//If message is from me, ignore.
	if (nickname === Cryptocat.myNickname) {
		return true
	}
	// If message is from someone not on buddy list, ignore.
	if (!$('#buddy-' + nickname).length) {
		return true
	}
	// Check if message has a 'composing' notification.
	if ($(message).find('composing').length && !body.length) {
		var conversation
		if (type === 'groupchat') {
			conversation = 'main-Conversation'
		}
		else if (type === 'chat') {
		conversation = nickname
	}
		Cryptocat.addToConversation('', nickname, conversation, 'composing')
		return true
	}
	// Check if message has an 'active' or 'paused' (stopped writing) notification.
	if ($(message).find('active').length || $(message).find('paused').length) {
		if ($('#composing-' + nickname).length) {
			$('#composing-' + nickname).parent().fadeOut(100).remove()
		}
	}
	// Check if message is a group chat message.
	if (type === 'groupchat') {
		if(!body.length) { return true }
		body = multiParty.receiveMessage(nickname, Cryptocat.myNickname, body)
		if (typeof(body) === 'string') {
			Cryptocat.addToConversation(body, nickname, 'main-Conversation', 'message')
		}
	}
	// Check ifthis is a private OTR message.
	else if (type === 'chat') {
		Cryptocat.otr.keys[nickname].receiveMsg(body)
	}
	return true
}

// Handle incoming presence updates from the XMPP server.
Cryptocat.xmpp.onPresence = function(presence) {
	var status, color, placement
	var nickname = cleanNickname($(presence).attr('from'))
	// If invalid nickname, do not process
	if ($(presence).attr('type') === 'error') {
		if ($(presence).find('error').attr('code') === '409') {
			// Delay logout in order to avoid race condition with window animation
			window.setTimeout(function() {
				Cryptocat.logout()
				Cryptocat.loginFail(Cryptocat.locale['loginMessage']['nicknameInUse'])
			}, 3000)
			return false
		}
		return true
	}
	// Ignore if presence status is coming from myself
	if (nickname === Cryptocat.myNickname) {
		return true
	}
	// Detect buddy going offline.
	if ($(presence).attr('type') === 'unavailable') {
		Cryptocat.removeBuddy(nickname)
		return true
	}
	// Detect nickname change (which may be done by non-Cryptocat XMPP clients)
	// This currently does nothing.
	if ($(presence).find('status').attr('code') === '303') {
		Cryptocat.removeBuddy(nickname)
		return true
	}
	// Add to otr keys if necessary
	if (nickname !== 'main-Conversation' && !Cryptocat.otr.keys.hasOwnProperty(nickname)) {
		Cryptocat.otr.add(nickname)
	}
	// Createbuddy element if buddy is new.
	else if (!$('#buddy-' + nickname).length) {
		Cryptocat.addBuddy(nickname)
	}
	// Handle buddy status change to 'available'.
	else if ($(presence).find('show').text() === '' || $(presence).find('show').text() === 'chat') {
		if ($('#buddy-' + nickname).attr('status') !== 'online') {
			status = 'online'
			placement = '#buddiesOnline'
		}
	}
	// Handlebuddy status change to 'away'.
	else if ($('#buddy-' + nickname).attr('status') !== 'away') {
		status = 'away'
		placement = '#buddiesAway'
	}
	// Perform status change.
	$('#buddy-' + nickname).attr('status', status)
	if (placement) {
		$('#buddy-' + nickname).animate({'color': color }, function() {
			if (Cryptocat.currentConversation !== nickname) {
				$(this).insertAfter(placement).slideDown(200)
			}
		})
	}
	return true
}

// Send your own multiparty public key to `nickname`, via XMPP-MUC.
Cryptocat.xmpp.sendPublicKey = function(nickname) {
	Cryptocat.xmpp.connection.muc.message(
		Cryptocat.conversationName + '@' + Cryptocat.xmpp.conferenceServer,
		null, multiParty.sendPublicKey(nickname), null, 'groupchat', 'active'
	)
}

// Send your current status to the XMPP server.
Cryptocat.xmpp.sendStatus = function() {
	if (Cryptocat.xmpp.currentStatus === 'away') {
		Cryptocat.xmpp.connection.muc.setStatus(Cryptocat.conversationName + '@'
		+ Cryptocat.xmpp.conferenceServer, Cryptocat.myNickname, 'away', 'away')
	}
	else {
		Cryptocat.xmpp.connection.muc.setStatus(Cryptocat.conversationName + '@'
		+ Cryptocat.xmpp.conferenceServer, Cryptocat.myNickname, '', '')
	}
}

// Clean nickname so that it's safe to use.
function cleanNickname(nickname) {
	var clean = nickname.match(/\/([\s\S]+)/)
	if (clean) { clean = Strophe.xmlescape(clean[1]) }
	else { return false }
	if (clean.match(/\W/)) { return false }
	return clean
}

})
<commit_msg>Revert "Improvements to presence stanza detection"<commit_after>// Cryptocat XMPP functions and callbacks.

Cryptocat.xmpp = {}
Cryptocat.xmpp.currentStatus = 'online'
Cryptocat.xmpp.connection = null

// Default connection settings.
Cryptocat.xmpp.defaultDomain = 'crypto.cat'
Cryptocat.xmpp.defaultConferenceServer = 'conference.crypto.cat'
Cryptocat.xmpp.defaultRelay = 'https://crypto.cat/http-bind'

Cryptocat.xmpp.domain = Cryptocat.xmpp.defaultDomain
Cryptocat.xmpp.conferenceServer = Cryptocat.xmpp.defaultConferenceServer
Cryptocat.xmpp.relay = Cryptocat.xmpp.defaultRelay

$(window).ready(function() {

// connect anonymously and join conversation.
Cryptocat.xmpp.connect = function() {
	Cryptocat.conversationName = Strophe.xmlescape($('#conversationName').val())
	Cryptocat.myNickname = Strophe.xmlescape($('#nickname').val())
	Cryptocat.xmpp.connection = new Strophe.Connection(Cryptocat.xmpp.relay)
	Cryptocat.xmpp.connection.connect(Cryptocat.xmpp.domain, null, function(status) {
		if (status === Strophe.Status.CONNECTING) {
			$('#loginInfo').animate({'background-color': '#97CEEC'}, 200)
			$('#loginInfo').text(Cryptocat.locale['loginMessage']['connecting'])
		}
		else if (status === Strophe.Status.CONNECTED) {
			$('.conversationName').animate({'background-color': '#97CEEC'})
			Cryptocat.xmpp.connection.ibb.addIBBHandler(Cryptocat.otr.ibbHandler)
			/* jshint -W106 */
			Cryptocat.xmpp.connection.si_filetransfer.addFileHandler(Cryptocat.otr.fileHandler)
			/* jshint +W106 */
			Cryptocat.xmpp.connection.muc.join(
				Cryptocat.conversationName + '@' + Cryptocat.xmpp.conferenceServer,
				Cryptocat.myNickname,
				function(message) {
					if (Cryptocat.xmpp.onMessage(message)) { return true }
				},
				function (presence) {
					if (Cryptocat.xmpp.onPresence(presence)) { return true }
				}
			)
			if (Cryptocat.audioNotifications) {
				Cryptocat.sounds.keygenLoop.pause()
				Cryptocat.sounds.keygenEnd.play()
			}
			$('#fill').stop().animate({
				'width': '100%', 'opacity': '1'
			}, 250, 'linear', function() {
				window.setTimeout(function() {
					$('#dialogBoxClose').click()
				}, 200)
			})
			window.setTimeout(function() {
				Cryptocat.xmpp.onConnected()
			}, 400)
		}
		else if (status === Strophe.Status.CONNFAIL) {
			if (Cryptocat.loginError) {
				Cryptocat.xmpp.reconnect()
			}
		}
		else if (status === Strophe.Status.DISCONNECTED) {
			if (Cryptocat.loginError) {
				Cryptocat.xmpp.reconnect()
			}
		}
	})
}

// Executes on successfully completed XMPP connection.
Cryptocat.xmpp.onConnected = function() {
	clearInterval(CatFacts.interval)
	Cryptocat.storage.setItem('myNickname', Cryptocat.myNickname)
	$('#buddy-main-Conversation').attr('status', 'online')
	$('#loginInfo').text('✓')
	$('#info').fadeOut(200)
	$('#loginOptions,#languages,#customServerDialog,#version,#logoText,#loginInfo').fadeOut(200)
	$('#header').animate({'background-color': '#151520'})
	$('.logo').animate({'margin': '-11px 5px 0 0'})
	$('#loginForm').fadeOut(200, function() {
		$('#conversationInfo').fadeIn()
		$('#buddy-main-Conversation').click(function() {
			Cryptocat.onBuddyClick('main-Conversation')
		})
		$('#buddy-main-Conversation').click()
		$('#conversationWrapper').fadeIn()
		$('#optionButtons').fadeIn()
		$('#footer').delay(200).animate({'height': 60}, function() {
			$('#userInput').fadeIn(200, function() {
				$('#userInputText').focus()
			})
		})
		$('#buddyWrapper').slideDown()
	})
	Cryptocat.loginError = true
	document.title = Cryptocat.myNickname + '@' + Cryptocat.conversationName
}

// Reconnect to the same chatroom, on accidental connection loss.
Cryptocat.xmpp.reconnect = function() {
	multiParty.reset()
	if (Cryptocat.xmpp.connection) {
	    Cryptocat.xmpp.connection.reset()
	}
	Cryptocat.xmpp.connection = new Strophe.Connection(Cryptocat.xmpp.relay)
	Cryptocat.xmpp.connection.connect(Cryptocat.xmpp.domain, null, function(status) {
		if (status === Strophe.Status.CONNECTING) {
			$('.conversationName').animate({'background-color': '#F00'})
		}
		else if (status === Strophe.Status.CONNECTED) {
			$('.conversationName').animate({'background-color': '#97CEEC'})
			Cryptocat.xmpp.connection.ibb.addIBBHandler(Cryptocat.otr.ibbHandler)
			/* jshint -W106 */
			Cryptocat.xmpp.connection.si_filetransfer.addFileHandler(Cryptocat.otr.fileHandler)
			/* jshint +W106 */
			Cryptocat.xmpp.connection.muc.join(
				Cryptocat.conversationName + '@' + Cryptocat.xmpp.conferenceServer,
				Cryptocat.myNickname
			)
			if (Cryptocat.audioNotifications) {
				Cryptocat.sounds.keygenLoop.pause()
				Cryptocat.sounds.keygenEnd.play()
			}
		}
		else if ((status === Strophe.Status.CONNFAIL) || (status === Strophe.Status.DISCONNECTED)) {
			if (Cryptocat.loginError) {
				window.setTimeout(function() {
				Cryptocat.xmpp.reconnect()
				}, 5000)
			}
		}
	})
}

// Handle incoming messages from the XMPP server.
Cryptocat.xmpp.onMessage = function(message) {
	var nickname = cleanNickname($(message).attr('from'))
	var body = $(message).find('body').text()
	var type = $(message).attr('type')
	// If archived message, ignore.
	if ($(message).find('delay').length !== 0) {
		return true
	}
	//If message is from me, ignore.
	if (nickname === Cryptocat.myNickname) {
		return true
	}
	// If message is from someone not on buddy list, ignore.
	if (!$('#buddy-' + nickname).length) {
		return true
	}
	// Check if message has a 'composing' notification.
	if ($(message).find('composing').length && !body.length) {
		var conversation
		if (type === 'groupchat') {
			conversation = 'main-Conversation'
		}
		else if (type === 'chat') {
		conversation = nickname
	}
		Cryptocat.addToConversation('', nickname, conversation, 'composing')
		return true
	}
	// Check if message has an 'active' or 'paused' (stopped writing) notification.
	if ($(message).find('active').length || $(message).find('paused').length) {
		if ($('#composing-' + nickname).length) {
			$('#composing-' + nickname).parent().fadeOut(100).remove()
		}
	}
	// Check if message is a group chat message.
	if (type === 'groupchat') {
		if(!body.length) { return true }
		body = multiParty.receiveMessage(nickname, Cryptocat.myNickname, body)
		if (typeof(body) === 'string') {
			Cryptocat.addToConversation(body, nickname, 'main-Conversation', 'message')
		}
	}
	// Check ifthis is a private OTR message.
	else if (type === 'chat') {
		Cryptocat.otr.keys[nickname].receiveMsg(body)
	}
	return true
}

// Handle incoming presence updates from the XMPP server.
Cryptocat.xmpp.onPresence = function(presence) {
	var nickname = cleanNickname($(presence).attr('from'))
	// If invalid nickname, do not process
	if ($(presence).attr('type') === 'error') {
		if ($(presence).find('error').attr('code') === '409') {
			// Delay logout in order to avoid race condition with window animation
			window.setTimeout(function() {
				Cryptocat.logout()
				Cryptocat.loginFail(Cryptocat.locale['loginMessage']['nicknameInUse'])
			}, 3000)
			return false
		}
		return true
	}
	// Ignore if presence status is coming from myself
	if (nickname === Cryptocat.myNickname) {
		return true
	}
	// Detect nickname change (which may be done by non-Cryptocat XMPP clients)
	// This currently does nothing.
	if ($(presence).find('status').attr('code') === '303') {
		return true
	}
	// Add to otr keys if necessary
	if (nickname !== 'main-Conversation' && !Cryptocat.otr.keys.hasOwnProperty(nickname)) {
		Cryptocat.otr.add(nickname)
	}
	var status, color, placement
	// Detect buddy going offline.
	if ($(presence).attr('type') === 'unavailable') {
		Cryptocat.removeBuddy(nickname)
		return true
	}
	// Createbuddy element if buddy is new.
	else if (!$('#buddy-' + nickname).length) {
		Cryptocat.addBuddy(nickname)
	}
	// Handle buddy status change to 'available'.
	else if ($(presence).find('show').text() === '' || $(presence).find('show').text() === 'chat') {
		if ($('#buddy-' + nickname).attr('status') !== 'online') {
			status = 'online'
			placement = '#buddiesOnline'
		}
	}
	// Handlebuddy status change to 'away'.
	else if ($('#buddy-' + nickname).attr('status') !== 'away') {
		status = 'away'
		placement = '#buddiesAway'
	}
	// Perform status change.
	$('#buddy-' + nickname).attr('status', status)
	if (placement) {
		$('#buddy-' + nickname).animate({'color': color }, function() {
			if (Cryptocat.currentConversation !== nickname) {
				$(this).insertAfter(placement).slideDown(200)
			}
		})
	}
	return true
}

// Send your own multiparty public key to `nickname`, via XMPP-MUC.
Cryptocat.xmpp.sendPublicKey = function(nickname) {
	Cryptocat.xmpp.connection.muc.message(
		Cryptocat.conversationName + '@' + Cryptocat.xmpp.conferenceServer,
		null, multiParty.sendPublicKey(nickname), null, 'groupchat', 'active'
	)
}

// Send your current status to the XMPP server.
Cryptocat.xmpp.sendStatus = function() {
	if (Cryptocat.xmpp.currentStatus === 'away') {
		Cryptocat.xmpp.connection.muc.setStatus(Cryptocat.conversationName + '@'
		+ Cryptocat.xmpp.conferenceServer, Cryptocat.myNickname, 'away', 'away')
	}
	else {
		Cryptocat.xmpp.connection.muc.setStatus(Cryptocat.conversationName + '@'
		+ Cryptocat.xmpp.conferenceServer, Cryptocat.myNickname, '', '')
	}
}

// Clean nickname so that it's safe to use.
function cleanNickname(nickname) {
	var clean = nickname.match(/\/([\s\S]+)/)
	if (clean) { clean = Strophe.xmlescape(clean[1]) }
	else { return false }
	if (clean.match(/\W/)) { return false }
	return clean
}

})
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
/**
 * @module ogs.geo
 */

/*jslint devel: true, forin: true, newcap: true, plusplus: true*/
/*jslint white: true, indent: 2*/

/*global geoModule, ogs, inherit, $, HTMLCanvasElement, Image*/
/*global vglModule, document*/
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * layerSource provides data to a layer
 */
//////////////////////////////////////////////////////////////////////////////
geoModule.layerSource = function(id, name, path) {
  'use strict';

   /** @private */
  var m_requestDataMTime = vglModule.timestamp(),
      m_id = id,
      m_name = name,
      m_path = path;

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return layer source modified time
   *
   * @returns {*}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.requestDataMTime = function() {
      return m_requestDataMTime;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Update the layer source MTime
   */
  ////////////////////////////////////////////////////////////////////////////
  this.requestDataMTimeModified = function() {
      // TODO Check for caller here
      m_requestDataMTime.modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return id of the layer source
   *
   * @returns {string}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.id = function() {
    return m_id;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Set id of the layer source
   */
  ////////////////////////////////////////////////////////////////////////////
  this.setId = function(id) {
    if (id !== null && m_id !== id) {
      m_id = id;
      this.modified();
      return true;
    }
    return false
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return name of the layer source
   *
   * @returns {string}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.name = function() {
    return m_name;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Set name of the layer source
   */
  ////////////////////////////////////////////////////////////////////////////
  this.setName = function(name) {
    if (name !== null && m_name !== name) {
      m_name = name;
      this.modified();
      return true;
    }

    return false
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return path of the raw data source
   *
   * @returns {string}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.path = function() {
    return m_path;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Set path of the raw data source
   */
  ////////////////////////////////////////////////////////////////////////////
  this.setPath = function(path) {
    if (path !== null && m_path !== path) {
      m_path = path;
      this.modified();
      return true;
    }
    return false
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.init = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.destroy = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.getData = function(time) {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.getMetaData = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.getTimeRange = function(varname) {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.getSpatialRange = function(varname) {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
    ////////////////////////////////////////////////////////////////////////////
  this.getScalarRange = function(varname) {
  };
};

inherit(geoModule.layerSource, vglModule.object);
<commit_msg>Fixed js syntax errors<commit_after>//////////////////////////////////////////////////////////////////////////////
/**
 * @module ogs.geo
 */

/*jslint devel: true, forin: true, newcap: true, plusplus: true*/
/*jslint white: true, indent: 2*/

/*global geoModule, ogs, inherit, $, HTMLCanvasElement, Image*/
/*global vglModule, document*/
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * layerSource provides data to a layer
 */
//////////////////////////////////////////////////////////////////////////////
geoModule.layerSource = function(id, name, path) {
  'use strict';

   /** @private */
  var m_requestDataMTime = vglModule.timestamp(),
      m_id = id,
      m_name = name,
      m_path = path;

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return layer source modified time
   *
   * @returns {*}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.requestDataMTime = function() {
      return m_requestDataMTime;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Update the layer source MTime
   */
  ////////////////////////////////////////////////////////////////////////////
  this.requestDataMTimeModified = function() {
      // TODO Check for caller here
      m_requestDataMTime.modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return id of the layer source
   *
   * @returns {string}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.id = function() {
    return m_id;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Set id of the layer source
   */
  ////////////////////////////////////////////////////////////////////////////
  this.setId = function(id) {
    if (id !== null && m_id !== id) {
      m_id = id;
      this.modified();
      return true;
    }
    return false;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return name of the layer source
   *
   * @returns {string}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.name = function() {
    return m_name;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Set name of the layer source
   */
  ////////////////////////////////////////////////////////////////////////////
  this.setName = function(name) {
    if (name !== null && m_name !== name) {
      m_name = name;
      this.modified();
      return true;
    }

    return false;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return path of the raw data source
   *
   * @returns {string}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.path = function() {
    return m_path;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Set path of the raw data source
   */
  ////////////////////////////////////////////////////////////////////////////
  this.setPath = function(path) {
    if (path !== null && m_path !== path) {
      m_path = path;
      this.modified();
      return true;
    }
    return false;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.init = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.destroy = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.getData = function(time) {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.getMetaData = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.getTimeRange = function(varname) {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
  ////////////////////////////////////////////////////////////////////////////
  this.getSpatialRange = function(varname) {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Should be implemented by a concrete class
   */
    ////////////////////////////////////////////////////////////////////////////
  this.getScalarRange = function(varname) {
  };
};

inherit(geoModule.layerSource, vglModule.object);
<|endoftext|>


<commit_before>
var Char = { Space: 0, Letter: 1, Digit: 2, Other: 3, Delimiter: 4, Operator: 5, String: 6, Reserved: 7, Comment: 8 };

function isText(text, k, subtext) {
    var l = subtext.length;

    for (var n = 0; n < l; n++)
        if (text[k + n] != subtext[n])
            return false;

    return true;
}

function classify(text, options) {
    options = options || { };

    var result = [];
    var l = text.length;
    var instring = false;

    var letterfrom = null;
    var letterto = null;

    for (var k = 0; k < l; k++) {
        var ch = text[k];

        if (options.strings) {
            if (instring && ch == options.strings.escape) {
                result[k] = Char.String;

                if (k < l - 1)
                    result[++k] = Char.String;

                continue;
            }

            if (ch == options.strings.delimiter) {
                result[k] = Char.String;
                if (instring)
                    instring = false;
                else
                    instring = true;
                checkname();
                continue;
            }
        }

        if (instring) {
            result[k] = Char.String;
            continue;
        }

        if (options.comments && options.comments.line && isText(text, k, options.comments.line)) {
            result[k] = Char.Comment;

            while (text[k + 1] && text[k + 1] != '\n')
                result[++k] = Char.Comment;

            continue;
        }

        if (isWhitespace(ch))
            result[k] = Char.Space;
        else if (isDigit(ch))
            result[k] = Char.Digit;
        else if (isLetter(ch))
            result[k] = Char.Letter;
        else if (options.delimiters && options.delimiters.indexOf(ch) >= 0)
            result[k] = Char.Delimiter;
        else if (options.operators && options.operators.indexOf(ch) >= 0)
            result[k] = Char.Operator;
        else
            result[k] = Char.Other;

        checkname();
    }

    checkname();

    return result;

    function checkname() {
        if (!options.reserved)
            return;

        if (result[k] == Char.Letter) {
            if (k == 0 || result[k - 1] != Char.Letter)
                letterfrom = k;
            letterto = k;
        }
        else if (k > 0 && result[k - 1] == Char.Letter) {
            checkreserved();
            letterfrom = null;
            letterto = null;
        }
    }

    function checkreserved() {
        if (!options.reserved)
            return;

        var name = text.slice(letterfrom, letterto + 1);

        if (options.reserved.indexOf(name) >= 0)
            for (var k = letterfrom; k <= letterto; k++)
                result[k] = Char.Reserved;
    }
}

function isWhitespace(ch) {
    return ch.charCodeAt(0) <= 32;
}

function isDigit(ch) {
    return ch >= '0' && ch <= '9';
}

function isLetter(ch) {
    return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z';
}

module.exports = {
    classify: classify,
    Char: Char
};

<commit_msg>Classifier recognize comments with start/end<commit_after>
var Char = { Space: 0, Letter: 1, Digit: 2, Other: 3, Delimiter: 4, Operator: 5, String: 6, Reserved: 7, Comment: 8 };

function isText(text, k, subtext) {
    var l = subtext.length;

    for (var n = 0; n < l; n++)
        if (text[k + n] != subtext[n])
            return false;

    return true;
}

function classify(text, options) {
    options = options || { };

    var result = [];
    var l = text.length;
    var instring = false;

    var letterfrom = null;
    var letterto = null;

    for (var k = 0; k < l; k++) {
        var ch = text[k];

        if (options.strings) {
            if (instring && ch == options.strings.escape) {
                result[k] = Char.String;

                if (k < l - 1)
                    result[++k] = Char.String;

                continue;
            }

            if (ch == options.strings.delimiter) {
                result[k] = Char.String;
                if (instring)
                    instring = false;
                else
                    instring = true;
                checkname();
                continue;
            }
        }

        if (instring) {
            result[k] = Char.String;
            continue;
        }

        if (options.comments && options.comments.line && isText(text, k, options.comments.line)) {
            result[k] = Char.Comment;

            while (text[k + 1] && text[k + 1] != '\n')
                result[++k] = Char.Comment;

            continue;
        }

        if (options.comments && options.comments.start && isText(text, k, options.comments.start)) {
            for (var n = 0; n < options.comments.start.length; n++)
                result[k++] = Char.Comment;

            while (text[k] && !isText(text, k, options.comments.end))
                result[k++] = Char.Comment;

            if (text[k])
                for (var n = 0; n < options.comments.end.length; n++)
                    result[k++] = Char.Comment;

            k--;

            continue;
        }

        if (isWhitespace(ch))
            result[k] = Char.Space;
        else if (isDigit(ch))
            result[k] = Char.Digit;
        else if (isLetter(ch))
            result[k] = Char.Letter;
        else if (options.delimiters && options.delimiters.indexOf(ch) >= 0)
            result[k] = Char.Delimiter;
        else if (options.operators && options.operators.indexOf(ch) >= 0)
            result[k] = Char.Operator;
        else
            result[k] = Char.Other;

        checkname();
    }

    checkname();

    return result;

    function checkname() {
        if (!options.reserved)
            return;

        if (result[k] == Char.Letter) {
            if (k == 0 || result[k - 1] != Char.Letter)
                letterfrom = k;
            letterto = k;
        }
        else if (k > 0 && result[k - 1] == Char.Letter) {
            checkreserved();
            letterfrom = null;
            letterto = null;
        }
    }

    function checkreserved() {
        if (!options.reserved)
            return;

        var name = text.slice(letterfrom, letterto + 1);

        if (options.reserved.indexOf(name) >= 0)
            for (var k = letterfrom; k <= letterto; k++)
                result[k] = Char.Reserved;
    }
}

function isWhitespace(ch) {
    return ch.charCodeAt(0) <= 32;
}

function isDigit(ch) {
    return ch >= '0' && ch <= '9';
}

function isLetter(ch) {
    return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z';
}

module.exports = {
    classify: classify,
    Char: Char
};

<|endoftext|>