<commit_before>'use strict';

var __ = require('underscore'),
    Backbone = require('backbone'),
    $ = require('jquery'),
    loadTemplate = require('../utils/loadTemplate'),
    Polyglot = require('node-polyglot'),
    languagesModel = require('../models/languagesMd'),
    adminPanelView = require('../views/adminPanelVw'),
    notificationsPanelView = require('../views/notificationsPanelVw'),
    remote = require('remote'),
    messageModal = require('../utils/messageModal.js');

var ipcRenderer = require('ipc-renderer');  // Allows to talk Electon main process

module.exports = Backbone.View.extend({

  el: '#pageNav',

  events: {
    'click .js-navClose': 'navCloseClick',
    'click .js-navMin': 'navMinClick',
    'click .js-navMax': 'navMaxClick',
    'click .js-navBack': 'navBackClick',
    'click .js-navFwd': 'navFwdClick',
    'click .js-showAboutModal': 'showAboutModal',
    'click .js-hideAboutModal': 'hideAboutModal',
    'click .js-showSupportModal': 'showSupportModal',
    'click .js-hideSupportModal': 'hideSupportModal',
    'click .js-aboutModal .js-tab': 'aboutModalTabClick',
    'click .js-navNotifications': 'navNotificationsClick',
    'click .js-navProfile': 'navProfileClick',
    'click .js-navRefresh': 'navRefreshClick',
    'click .js-navAdminPanel': 'navAdminPanel',
    //'click .js-navProfileMenu a': 'closeNav',
    'focus .js-navAddressBar': 'addressBarFocus',
    'keyup .js-navAddressBar': 'addressBarKeyup',
    'click .js-closeStatus': 'closeStatusBar',
    'click .js-homeModal-themeSelected': 'setSelectedTheme',
    'blur input': 'validateInput',
    'blur textarea': 'validateInput',
    'click .js-navInstallUpdate': 'sendInstallUpdate',
    'click .js-navDismisslUpdate': 'dismissUpdate'
  },

  initialize: function(options){
    var self = this;
    this.options = options || {};
    /* recieves socketView and userProfile from main.js */
    this.socketView = options.socketView;
    this.userProfile = options.userProfile;
    this.model.set('vendor', this.userProfile.get('profile').vendor);
    this.model.set('moderator', this.userProfile.get('profile').moderator);
    this.subViews = [];
    this.languages = new languagesModel();

    this.currentWindow = remote.getCurrentWindow();

    this.socketNotificationID = Math.random().toString(36).slice(2);
    this.socketView.getNotifications(this.socketNotificationID);

    this.listenTo(window.obEventBus, "updateProfile", function(response){
      this.refreshProfile();
    });
    this.listenTo(window.obEventBus, "updateUserModel", function(response){
      this.model.fetch();
    });

    // pre-select lauguage.
    var localLanguage = window.navigator.language;
    var localLanguageFound = false;
    var languageList = this.languages.get('languages');
    for(var i in languageList) {
      if(languageList[i].langCode == localLanguage) {
        localLanguageFound = true;
        break;
      }
    }

    this.render();
  },

  sendInstallUpdate: function() {
    ipcRenderer.send('installUpdate');
    $('.js-softwareUpdate').addClass('softwareUpdateHidden');
  },

  dismissUpdate: function() {
    $('.js-softwareUpdate').addClass('softwareUpdateHidden');
  },

  handleSocketMessage: function(response) {
    var data = JSON.parse(response.data);
    if(data.id == this.socketNotificationID){
      console.log(data);
    }
  },

  /*
  closeNav: function(){
    var targ = this.$el.find('.js-navProfileMenu');
    targ.addClass('hide');
    $('#overlay').addClass('hide');
  },
  */

  refreshProfile: function() {
    var self = this;

    this.userProfile.fetch({
      success: function(model){
        self.model.set('vendor', model.get('profile').vendor);
        self.model.set('moderator', model.get('profile').moderator);
        self.render();
      }
    });
  },

  render: function(){
    var self = this;
    //reset tests for applying lists or List.js will fail on a re-render
    this.countryReady = false;
    this.currencyReady = false;
    this.languageReady = false;
    //load userProfile data into model
    this.model.set('guid', this.userProfile.get('profile').guid);
    this.model.set('avatar_hash', this.userProfile.get('profile').avatar_hash);
    loadTemplate('./js/templates/pageNav.html', function(loadedTemplate) {
      self.$el.html(loadedTemplate(self.model.toJSON()));
      self.notificationsPanel = new notificationsPanelView({
        parentEl: '#notificationsPanel',
        socketView: self.socketView,
        serverUrl: self.options.model.get('serverUrl')
      });
      self.listenTo(self.notificationsPanel, 'notificationsCounted', self.setNotificationCount);
      self.subViews.push(self.notificationsPanel);

      //add the admin panel
      self.adminPanel = new adminPanelView({model: self.model});
      self.subViews.push(self.adminPanel);
      self.addressInput = self.$el.find('.js-navAddressBar');
      self.statusBar = self.$el.find('.js-navStatusBar');
      //listen for address bar set events
      self.listenTo(window.obEventBus, "setAddressBar", function(options){
        var text = options.handle || options.addressText;
        self.addressInput.val(text);
        self.closeStatusBar();
      });

      self.listenTo(self.userProfile, 'change:avatar_hash', function(){
        self.model.set('vendor', self.userProfile.get('profile').vendor);
        self.render();
      });

      self.listenTo(window.obEventBus, "socketMessageReceived", function(response){
        self.handleSocketMessage(response);
      });

      if(self.showDiscoverCallout) {
        // display discover callout
        self.$el.find('.js-OnboardingIntroDiscoverHolder').removeClass('hide');
      }

      //when language is changed, re-render
      self.listenTo(self.model, 'change:language', function(){
        self.render();
      });
    });
    return this;
  },

  showAboutModal: function(e){

    // display the modal
    $('.js-aboutModalHolder').fadeIn(300, function(){
      // set the active tab
      $('.js-aboutModal .navBar .btn.btn-bar').removeClass('active');
      $('.js-about-mainTab').addClass('active');

      // set the active section
      $('.js-aboutModal .modal-section').addClass('hide');
      $('.js-aboutModal .js-modalAboutMain').removeClass('hide');
    });

    // blur the container for extra focus
    $('#obContainer').addClass('blur');
  },

  hideAboutModal: function(e){
    $('.js-aboutModalHolder').fadeOut(300);
    $('#obContainer').removeClass('blur');
  },

  showSupportModal: function(e){
    $('.js-aboutModalHolder').fadeIn(300, function() {
      $('.js-aboutModal .navBar .btn.btn-bar').removeClass('active');
      $('.js-about-donationsTab').addClass('active');
      $('.js-aboutModal .modal-section').addClass('hide');
      $('.js-aboutModal .js-modalAboutSupport').removeClass('hide');
    });
    $('#obContainer').addClass('blur');
  },

  hideSupportModal: function(e){
    $('.js-aboutModalHolder').fadeOut(300);
    $('#obContainer').removeClass('blur');
  },

  aboutModalTabClick: function(e){
    var tab = $(e.currentTarget).data('tab');
    $('.js-aboutModal .btn-tab').removeClass('active');
    $(e.currentTarget).addClass('active');

    switch(tab) {
      case "about":
        $('.modal-about-section').addClass('hide');
        $('.js-modalAboutMain').removeClass('hide');
        break;
      case "support":
        $('.modal-about-section').addClass('hide');
        $('.js-modalAboutSupport').removeClass('hide');
        break;
      case "contributors":
        $('.modal-about-section').addClass('hide');
        $('.js-modalAboutContributors').removeClass('hide');
        break;
      case "licensing":
        $('.modal-about-section').addClass('hide');
        $('.js-modalAboutLicensing').removeClass('hide');
        break;
    }
  },

  navNotificationsClick: function(e){
    e.stopPropagation();
    this.setNotificationCount("");
    var targ = this.$el.find('.js-navNotificationsMenu');
    targ.siblings('.popMenu').addClass('hide');
    if(targ.hasClass('hide')){
      targ.removeClass('hide').addClass('popMenu-notifications-opened');
      $('#overlay').removeClass('hide');
      $('html').on('click.closeNav', function(e){
        if($(e.target).closest(targ).length === 0){
          targ.addClass('hide').removeClass('popMenu-notifications-opened');
          $('#overlay').addClass('hide');
          $(this).off('.closeNav');
        }
      });
    }else{
      targ.addClass('hide');
      $('#overlay').addClass('hide');
    }
  },

  setNotificationCount: function(count){
    if(count > 99) {
      count = "..";
    }
    this.$el.find('.js-navNotifications .badge').attr('data-count', count);
  },

  navProfileClick: function(e){
    e.stopPropagation();
    var targ = this.$el.find('.js-navProfileMenu');
    targ.siblings('.popMenu').addClass('hide');
    if(targ.hasClass('hide')){
      targ.removeClass('hide').addClass('popMenu-navBar-opened');
      $('#overlay').removeClass('hide');
      $('html').on('click.closeNav', function(e){
        if($(e.target).closest(targ).length === 0){
          targ.addClass('hide').removeClass('popMenu-navBar-opened');
          $('#overlay').addClass('hide');
          $(this).off('.closeNav');
        }
      });
    }else{
      targ.addClass('hide');
      $('#overlay').addClass('hide');
    }
  },

  navCloseClick: function(){
    var process = remote.process;
    if (process.platform != 'darwin') {
      this.currentWindow.close();
    } else {
      this.currentWindow.hide();
    }
  },

  navMinClick: function(){
    this.currentWindow.minimize();
  },

  navMaxClick: function(){
    if(this.currentWindow.isMaximized()){
      this.currentWindow.unmaximize();
    } else {
      this.currentWindow.maximize();
    }
  },

  navBackClick: function(){
    window.history.back();
  },

  navFwdClick: function(){
    window.history.forward();
  },

  navRefreshClick: function(){
    this.currentWindow.reload();
  },

  addressBarFocus: function(e){
    // on inital focus of input, select all text (this makes it easier to copy or delete the text)
    $(e.target).one('mouseup', function () {
      $('#addressBar').select();
    });
  },

  addressBarKeyup: function(e){
    var barText = this.addressInput.val();
    //detect enter key
    if (e.keyCode == 13){
      this.addressBarProcess(barText);
    } else {
      this.closeStatusBar();
    }
  },

  addressBarProcess: function(addressBarText){
    var guid = "",
        handle = "",
        state = "",
        itemHash = "",
        addressTextArray = addressBarText.replace(/ /g, "").split("/");

    state = addressTextArray[1] ? "/" + addressTextArray[1] : "";
    itemHash = addressTextArray[2] ? "/" + addressTextArray[2] : "";

    if(addressTextArray[0].charAt(0) == "@"){
      // user entered a handle
      handle = addressTextArray[0].replace('@', '');
      this.processHandle(handle, state, itemHash);
    } else if(!addressTextArray[0].length){
      // user trying to go back to discover
      Backbone.history.navigate('#home', {trigger:true});
    } else if(addressTextArray[0].length === 40){
      // user entered a guid
      guid = addressTextArray[0];
      Backbone.history.navigate('#userPage/' + guid + state + itemHash, {trigger:true});
    } else if(addressTextArray[0].charAt(0) == "#"){
      // user entered a search term
      Backbone.history.navigate('#home/products/' + addressTextArray[0].replace('#', ''), {trigger:true});
    } else {
      //user entered text that doesn't match a known pattern, assume it's a product search
      Backbone.history.navigate('#home/products/' + addressTextArray[0], {trigger:true});
    }
  },

  processHandle: function(handle, state, itemHash){
    if(handle){
      $.ajax({
        url: this.model.get('resolver') + "/v2/users/" + handle,
        dataType: "json"
      }).done(function(resolverData){
        if(resolverData[handle].profile && resolverData[handle].profile.account){
          var account = resolverData[handle].profile.account.filter(function (accountObject) {
            return accountObject.service == "openbazaar";
          });
          Backbone.history.navigate('#userPage/' + account[0].identifier + state + itemHash, {trigger: true});
        } else {
          messageModal.show(window.polyglot.t('errorMessages.serverError'), window.polyglot.t('errorMessages.badHandle'));
        }
      }).fail(function(jqXHR, status, errorThrown){
        messageModal.show(window.polyglot.t('errorMessages.serverError'), window.polyglot.t('errorMessages.badHandle'));
      });
    }
  },

  showStatusBar: function(msgText){
    this.statusBar.find('.js-statusBarMessage').text(msgText);
    this.statusBar.removeClass('fadeOut');
  },

  closeStatusBar: function(){
    this.statusBar.addClass('fadeOut');
  },

  navAdminPanel: function(){
    this.$el.find('.js-adminModal').fadeIn(300);
    this.adminPanel.updatePage();
  },

  close: function(){
    __.each(this.subViews, function(subView) {
      if(subView.close){
        subView.close();
      }else{
        subView.remove();
      }
    });
    this.remove();
  },

  setSelectedTheme: function(e){
    // Needs to save to the object and update the dom
  },

  shadeColor2: function shadeColor2(color, percent) {
    var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
    return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
  },

  validateInput: function(e) {
    e.target.checkValidity();
    $(e.target).closest('.flexRow').addClass('formChecked');
  },

});
<commit_msg>put back close nav<commit_after>'use strict';

var __ = require('underscore'),
    Backbone = require('backbone'),
    $ = require('jquery'),
    loadTemplate = require('../utils/loadTemplate'),
    Polyglot = require('node-polyglot'),
    languagesModel = require('../models/languagesMd'),
    adminPanelView = require('../views/adminPanelVw'),
    notificationsPanelView = require('../views/notificationsPanelVw'),
    remote = require('remote'),
    messageModal = require('../utils/messageModal.js');

var ipcRenderer = require('ipc-renderer');  // Allows to talk Electon main process

module.exports = Backbone.View.extend({

  el: '#pageNav',

  events: {
    'click .js-navClose': 'navCloseClick',
    'click .js-navMin': 'navMinClick',
    'click .js-navMax': 'navMaxClick',
    'click .js-navBack': 'navBackClick',
    'click .js-navFwd': 'navFwdClick',
    'click .js-showAboutModal': 'showAboutModal',
    'click .js-hideAboutModal': 'hideAboutModal',
    'click .js-showSupportModal': 'showSupportModal',
    'click .js-hideSupportModal': 'hideSupportModal',
    'click .js-aboutModal .js-tab': 'aboutModalTabClick',
    'click .js-navNotifications': 'navNotificationsClick',
    'click .js-navProfile': 'navProfileClick',
    'click .js-navRefresh': 'navRefreshClick',
    'click .js-navAdminPanel': 'navAdminPanel',
    'click .js-navProfileMenu a': 'closeNav',
    'focus .js-navAddressBar': 'addressBarFocus',
    'keyup .js-navAddressBar': 'addressBarKeyup',
    'click .js-closeStatus': 'closeStatusBar',
    'click .js-homeModal-themeSelected': 'setSelectedTheme',
    'blur input': 'validateInput',
    'blur textarea': 'validateInput',
    'click .js-navInstallUpdate': 'sendInstallUpdate',
    'click .js-navDismisslUpdate': 'dismissUpdate'
  },

  initialize: function(options){
    var self = this;
    this.options = options || {};
    /* recieves socketView and userProfile from main.js */
    this.socketView = options.socketView;
    this.userProfile = options.userProfile;
    this.model.set('vendor', this.userProfile.get('profile').vendor);
    this.model.set('moderator', this.userProfile.get('profile').moderator);
    this.subViews = [];
    this.languages = new languagesModel();

    this.currentWindow = remote.getCurrentWindow();

    this.socketNotificationID = Math.random().toString(36).slice(2);
    this.socketView.getNotifications(this.socketNotificationID);

    this.listenTo(window.obEventBus, "updateProfile", function(response){
      this.refreshProfile();
    });
    this.listenTo(window.obEventBus, "updateUserModel", function(response){
      this.model.fetch();
    });

    // pre-select lauguage.
    var localLanguage = window.navigator.language;
    var localLanguageFound = false;
    var languageList = this.languages.get('languages');
    for(var i in languageList) {
      if(languageList[i].langCode == localLanguage) {
        localLanguageFound = true;
        break;
      }
    }

    this.render();
  },

  sendInstallUpdate: function() {
    ipcRenderer.send('installUpdate');
    $('.js-softwareUpdate').addClass('softwareUpdateHidden');
  },

  dismissUpdate: function() {
    $('.js-softwareUpdate').addClass('softwareUpdateHidden');
  },

  handleSocketMessage: function(response) {
    var data = JSON.parse(response.data);
    if(data.id == this.socketNotificationID){
      console.log(data);
    }
  },

  closeNav: function(){
    var targ = this.$el.find('.js-navProfileMenu');
    targ.addClass('hide');
    $('#overlay').addClass('hide');
  },

  refreshProfile: function() {
    var self = this;

    this.userProfile.fetch({
      success: function(model){
        self.model.set('vendor', model.get('profile').vendor);
        self.model.set('moderator', model.get('profile').moderator);
        self.render();
      }
    });
  },

  render: function(){
    var self = this;
    //reset tests for applying lists or List.js will fail on a re-render
    this.countryReady = false;
    this.currencyReady = false;
    this.languageReady = false;
    //load userProfile data into model
    this.model.set('guid', this.userProfile.get('profile').guid);
    this.model.set('avatar_hash', this.userProfile.get('profile').avatar_hash);
    loadTemplate('./js/templates/pageNav.html', function(loadedTemplate) {
      self.$el.html(loadedTemplate(self.model.toJSON()));
      self.notificationsPanel = new notificationsPanelView({
        parentEl: '#notificationsPanel',
        socketView: self.socketView,
        serverUrl: self.options.model.get('serverUrl')
      });
      self.listenTo(self.notificationsPanel, 'notificationsCounted', self.setNotificationCount);
      self.subViews.push(self.notificationsPanel);

      //add the admin panel
      self.adminPanel = new adminPanelView({model: self.model});
      self.subViews.push(self.adminPanel);
      self.addressInput = self.$el.find('.js-navAddressBar');
      self.statusBar = self.$el.find('.js-navStatusBar');
      //listen for address bar set events
      self.listenTo(window.obEventBus, "setAddressBar", function(options){
        var text = options.handle || options.addressText;
        self.addressInput.val(text);
        self.closeStatusBar();
      });

      self.listenTo(self.userProfile, 'change:avatar_hash', function(){
        self.model.set('vendor', self.userProfile.get('profile').vendor);
        self.render();
      });

      self.listenTo(window.obEventBus, "socketMessageReceived", function(response){
        self.handleSocketMessage(response);
      });

      if(self.showDiscoverCallout) {
        // display discover callout
        self.$el.find('.js-OnboardingIntroDiscoverHolder').removeClass('hide');
      }

      //when language is changed, re-render
      self.listenTo(self.model, 'change:language', function(){
        self.render();
      });
    });
    return this;
  },

  showAboutModal: function(e){

    // display the modal
    $('.js-aboutModalHolder').fadeIn(300, function(){
      // set the active tab
      $('.js-aboutModal .navBar .btn.btn-bar').removeClass('active');
      $('.js-about-mainTab').addClass('active');

      // set the active section
      $('.js-aboutModal .modal-section').addClass('hide');
      $('.js-aboutModal .js-modalAboutMain').removeClass('hide');
    });

    // blur the container for extra focus
    $('#obContainer').addClass('blur');
  },

  hideAboutModal: function(e){
    $('.js-aboutModalHolder').fadeOut(300);
    $('#obContainer').removeClass('blur');
  },

  showSupportModal: function(e){
    $('.js-aboutModalHolder').fadeIn(300, function() {
      $('.js-aboutModal .navBar .btn.btn-bar').removeClass('active');
      $('.js-about-donationsTab').addClass('active');
      $('.js-aboutModal .modal-section').addClass('hide');
      $('.js-aboutModal .js-modalAboutSupport').removeClass('hide');
    });
    $('#obContainer').addClass('blur');
  },

  hideSupportModal: function(e){
    $('.js-aboutModalHolder').fadeOut(300);
    $('#obContainer').removeClass('blur');
  },

  aboutModalTabClick: function(e){
    var tab = $(e.currentTarget).data('tab');
    $('.js-aboutModal .btn-tab').removeClass('active');
    $(e.currentTarget).addClass('active');

    switch(tab) {
      case "about":
        $('.modal-about-section').addClass('hide');
        $('.js-modalAboutMain').removeClass('hide');
        break;
      case "support":
        $('.modal-about-section').addClass('hide');
        $('.js-modalAboutSupport').removeClass('hide');
        break;
      case "contributors":
        $('.modal-about-section').addClass('hide');
        $('.js-modalAboutContributors').removeClass('hide');
        break;
      case "licensing":
        $('.modal-about-section').addClass('hide');
        $('.js-modalAboutLicensing').removeClass('hide');
        break;
    }
  },

  navNotificationsClick: function(e){
    e.stopPropagation();
    this.setNotificationCount("");
    var targ = this.$el.find('.js-navNotificationsMenu');
    targ.siblings('.popMenu').addClass('hide');
    if(targ.hasClass('hide')){
      targ.removeClass('hide').addClass('popMenu-notifications-opened');
      $('#overlay').removeClass('hide');
      $('html').on('click.closeNav', function(e){
        if($(e.target).closest(targ).length === 0){
          targ.addClass('hide').removeClass('popMenu-notifications-opened');
          $('#overlay').addClass('hide');
          $(this).off('.closeNav');
        }
      });
    }else{
      targ.addClass('hide');
      $('#overlay').addClass('hide');
    }
  },

  setNotificationCount: function(count){
    if(count > 99) {
      count = "..";
    }
    this.$el.find('.js-navNotifications .badge').attr('data-count', count);
  },

  navProfileClick: function(e){
    e.stopPropagation();
    var targ = this.$el.find('.js-navProfileMenu');
    targ.siblings('.popMenu').addClass('hide');
    if(targ.hasClass('hide')){
      targ.removeClass('hide').addClass('popMenu-navBar-opened');
      $('#overlay').removeClass('hide');
      $('html').on('click.closeNav', function(e){
        if($(e.target).closest(targ).length === 0){
          targ.addClass('hide').removeClass('popMenu-navBar-opened');
          $('#overlay').addClass('hide');
          $(this).off('.closeNav');
        }
      });
    }else{
      targ.addClass('hide');
      $('#overlay').addClass('hide');
    }
  },

  navCloseClick: function(){
    var process = remote.process;
    if (process.platform != 'darwin') {
      this.currentWindow.close();
    } else {
      this.currentWindow.hide();
    }
  },

  navMinClick: function(){
    this.currentWindow.minimize();
  },

  navMaxClick: function(){
    if(this.currentWindow.isMaximized()){
      this.currentWindow.unmaximize();
    } else {
      this.currentWindow.maximize();
    }
  },

  navBackClick: function(){
    window.history.back();
  },

  navFwdClick: function(){
    window.history.forward();
  },

  navRefreshClick: function(){
    this.currentWindow.reload();
  },

  addressBarFocus: function(e){
    // on inital focus of input, select all text (this makes it easier to copy or delete the text)
    $(e.target).one('mouseup', function () {
      $('#addressBar').select();
    });
  },

  addressBarKeyup: function(e){
    var barText = this.addressInput.val();
    //detect enter key
    if (e.keyCode == 13){
      this.addressBarProcess(barText);
    } else {
      this.closeStatusBar();
    }
  },

  addressBarProcess: function(addressBarText){
    var guid = "",
        handle = "",
        state = "",
        itemHash = "",
        addressTextArray = addressBarText.replace(/ /g, "").split("/");

    state = addressTextArray[1] ? "/" + addressTextArray[1] : "";
    itemHash = addressTextArray[2] ? "/" + addressTextArray[2] : "";

    if(addressTextArray[0].charAt(0) == "@"){
      // user entered a handle
      handle = addressTextArray[0].replace('@', '');
      this.processHandle(handle, state, itemHash);
    } else if(!addressTextArray[0].length){
      // user trying to go back to discover
      Backbone.history.navigate('#home', {trigger:true});
    } else if(addressTextArray[0].length === 40){
      // user entered a guid
      guid = addressTextArray[0];
      Backbone.history.navigate('#userPage/' + guid + state + itemHash, {trigger:true});
    } else if(addressTextArray[0].charAt(0) == "#"){
      // user entered a search term
      Backbone.history.navigate('#home/products/' + addressTextArray[0].replace('#', ''), {trigger:true});
    } else {
      //user entered text that doesn't match a known pattern, assume it's a product search
      Backbone.history.navigate('#home/products/' + addressTextArray[0], {trigger:true});
    }
  },

  processHandle: function(handle, state, itemHash){
    if(handle){
      $.ajax({
        url: this.model.get('resolver') + "/v2/users/" + handle,
        dataType: "json"
      }).done(function(resolverData){
        if(resolverData[handle].profile && resolverData[handle].profile.account){
          var account = resolverData[handle].profile.account.filter(function (accountObject) {
            return accountObject.service == "openbazaar";
          });
          Backbone.history.navigate('#userPage/' + account[0].identifier + state + itemHash, {trigger: true});
        } else {
          messageModal.show(window.polyglot.t('errorMessages.serverError'), window.polyglot.t('errorMessages.badHandle'));
        }
      }).fail(function(jqXHR, status, errorThrown){
        messageModal.show(window.polyglot.t('errorMessages.serverError'), window.polyglot.t('errorMessages.badHandle'));
      });
    }
  },

  showStatusBar: function(msgText){
    this.statusBar.find('.js-statusBarMessage').text(msgText);
    this.statusBar.removeClass('fadeOut');
  },

  closeStatusBar: function(){
    this.statusBar.addClass('fadeOut');
  },

  navAdminPanel: function(){
    this.$el.find('.js-adminModal').fadeIn(300);
    this.adminPanel.updatePage();
  },

  close: function(){
    __.each(this.subViews, function(subView) {
      if(subView.close){
        subView.close();
      }else{
        subView.remove();
      }
    });
    this.remove();
  },

  setSelectedTheme: function(e){
    // Needs to save to the object and update the dom
  },

  shadeColor2: function shadeColor2(color, percent) {
    var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
    return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
  },

  validateInput: function(e) {
    e.target.checkValidity();
    $(e.target).closest('.flexRow').addClass('formChecked');
  },

});
<|endoftext|>


<commit_before>var utils = require("../utils_mod.js");
var cheerio = require("cheerio");
var request = require("request");

BChile = function(user, pass) {
	this.user = user;
	this.pass = pass;
	this.jar = request.jar();
	this.req = require("request").defaults({ jar:this.jar, followAllRedirects:true, headers:{"user-agent": utils._ua} });

	this.keepAliveInt = null;

	this.username = "";
	this.logged = false;
};

BChile.bname = "Banco de Chile/Edwards/CrediChile";
BChile.userIsRUT = true;

BChile.prefixDomain = "https://www.bancochile.cl";
BChile.prefix = BChile.prefixDomain + "/bchile-perfilamiento/";
BChile.formURL = BChile.prefix + "Process?AID=LOGIN-0004"
BChile.formURL2 = "https://www.bancochile.cl/bchile-perfilamiento/Process?AID=LOGIN-0004"
// a = new banks.chile.module("", ""); a.login();

BChile.prototype.login = function(callback) {
	console.log("[BC] Retrieving login page... " + BChile.formURL);
	var that = this;
	_callback = callback || function(){};
	this.req(BChile.formURL2, function(err, res, body) {
		if(err != null) {
			console.log(err);
			return;
		}

		if(body.indexOf("Ingreso a Banco") == -1) {
			console.log("[BC] Wrong page received");
			console.log(body);
			_callback(false, new Error("Wrong page received"));
			return;
		}

		console.log("[BC] Login page loaded");
		var formSubmitURL = BChile.prefixDomain + utils.textFinder(body, 'myformLogin1" action="', '"').replace(/&/g, "&");

		console.log("[BC] Form Action URL: " + formSubmitURL);

		var opts = {
			form: {
				CustLoginID: utils.formatRUT(that.user, !1),
				SignonPswd: that.pass,
				relogin: "0",
				marca: "",
				segmento: ",",
				pagina: "login"
			}
		};

		console.log("[BC] Log-in...");
		that.req.post(formSubmitURL, opts, function(err, res, body) {
			if(err != null) {
				console.log(err);
				return;
			}

			if(body.indexOf("?AID=CARTOLACONTODO-0000") == -1) {
				console.log("[BC] Login unsuccessful");
				console.log(body);
				_callback(false, null); return;
			}

			console.log("[BC] Logged in successful");
			_callback(true, null);
		}).on('error', function(e){ _callback(false, e); });
	}).on('error', function(e){ _callback(false, e); });
};

BChile.prototype.getAccounts = function(callback) {
	if(!this.logged) {
		console.error("[BE][GA] Not logged!");
		callback(false, new Error("Not logged"));
		return;
	}

	this.req(BChile.resumenURL, function(err, res, body) {
		if(body.indexOf("<title>Resumen de Productos") == -1) {
			console.log("[BE][GA] Wrong page received");
			callback(false, new Error("Wrong page received"));
			return;
		}

		var accounts = [];
		var $1 = cheerio.load(body);
		var els = $1("#table_1 tbody tr");
		for(var i = 0; i < els.length; i++) {
			var tds = $1("td", els[i]),
				accType = tds.eq(0).text().trim(),
				accNum = tds.eq(1).text().trim(),
				accBal = tds.eq(3).text().replace(/[^0-9]/g, "");

			accounts.push({accNumber:accNum, accType: accType, accBal: accBal})
		}

		callback(accounts, null);
	});
}

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

BChile.prototype.checkStatus = function(callback) {
	this.req(BChile.homeURL, function(err, res, body) {
		this.logged = body.indexOf("<title>Home -") != -1;
		callback(this.logged);
	});
}

BChile.prototype.keepAliveCallback = function(callback) {
	//console.log("[BE][KA] Checking status...");
	var that = this;
	var _call = callback;
	that.checkStatus(function(logged){
		if(!logged) {
			that.keepAliveInt = null;
			console.log("[BE][KA] Session got closed!");
			_call(that);
			return;
		}

		//console.log("[BE][KA] Session OK");
		that.keepAliveInt = setTimeout(function(){ that.keepAliveCallback(); }, 30000);
	});
}

BChile.prototype.startKeepAlive = function() {
	if(this.keepAliveInt != null) return;

	this.keepAliveCallback();
}

module.exports = BChile;<commit_msg>Soporte para BChile, corregido<commit_after>var request = require("request");
var utils = require("../utils_mod.js");

BancoCL = function(user, pass) {
	this.user = user;
	this.pass = pass;
	this.jar = request.jar();
	this.req = request.defaults({ jar:this.jar, followAllRedirects:true, headers:{"user-agent": _ua} });

	this.keepAliveInt = null;

	this.username = "";
	this.logged = false;
};

BancoCL.bname = "B. Chile/Edwards/CrediChile";
BancoCL.userIsRUT = true;

BancoCL.prefixDomain = "https://www.bancochile.cl";
BancoCL.prefix = BancoCL.prefixDomain + "/bchile-perfilamiento/Process?";
BancoCL.prefixAjax = BancoCL.prefixDomain + "/bchile-perfilamiento/Ajax?";
BancoCL.loginURL = BancoCL.prefix + "MID=&AID=LOGIN-0005";
BancoCL.validaClave = BancoCL.prefix + "AID=VALIDA_CLAVE-0000";
BancoCL.uInfoURL = BancoCL.prefix + "MID=&AID=CARTOLA_CON_SALDOS-0200";
BancoCL.ajaxSaldo = BancoCL.prefix + "AID=AJAX_OBTENER_SALDOS1&indice=";
BancoCL.checkSession = BancoCL.prefix + "AID=ESTADO_SESION-010";

BancoCL.prototype.login = function(callback) {
	var that = this;
	var _callback = callback || function(){};

	console.log("[BCL] Checking login data... ");
	that.validatePass(function(loginCheck, err){
		if(!loginCheck) {
			_callback(err);
			return;
		}

		var opts = {
			url: BancoCL.loginURL,
			form: {
				rutFull: utils.formatRUT(that.user),
				SignonPswd: that.pass
			}
		};

		console.log("[BCL] Log-in... ");
		that.req.post(opts, function(err, res, body){
			if(err != null) {
				_callback(err)
				return;
			}

			if(res.request.href.indexOf("CARTOLACONTODO") == -1) {
				_callback(new Error('No se pudo iniciar sesión.'));
				return;
			}

			console.log("[BCL] Retrieving user name... ");
			that.req(BancoCL.uInfoURL, function(err, res, body) {
				if(err != null) {
					_callback(err);
					return;
				}

				that.logged = true;
				that.username = utils.textFinder(body, "Sr(a). ", "<");
				_callback(null, true);
			});
		});
	});
};

BancoCL.prototype.getAccounts = function(callback) {
	var _call = callback || function(){};
	var that = this;
	if(!this.logged) {
		console.error("[BCL][GA] Not logged!");
		_call(new Error("Not logged"));
		return;
	}

	this.req(BancoCL.uInfoURL, function(err, res, body) {
		if(res.request.href.indexOf("CARTOLA_CON_SALDOS") == -1) {
			console.log("[BCL][GA] Wrong page received");
			_call(new Error("Wrong page received"));
			return;
		}

		var accs = [];
		var r = (new RegExp('mtoDisp[0-9]*', 'g')).exec(body);
		for(var i = 0, c = 0; i < r.length; i++) {
			that.req(BancoCL.ajaxSaldo + i, function(err, res, data){
				if(data.indexOf('<') != -1) {
					_call(new Error('Contenido incorrecto recibido'));
					return;
				}

				try {
					var d = data.replace(/'/g, '"')
						.replace("nroProducto", "accNumber")
						.replace("montoContable", "accBal")
						.replace("codProducto", "accType");
					d = JSON.parse(d);
					delete d[0].montoDisponible;
					accs.push(d[0]);
				} catch(e) {
					console.log('[BCL][GA] Error al decodificar JSON');
					showData(data);
					_call(e);
				}

				if(++c == r.length) {
					_call(null, accs);
				}
			});
		}
	});
}

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

BancoCL.prototype.validatePass = function(callback) {
	callback = callback || function(){};
	if(this.pass == "") {
		callback(false, null);
	}

	var that = this;
	var opts = {
		form: {
			CustLoginID: utils.formatRUT(that.user),
			SignonPswd: that.pass
		}
	};

	this.req.post(BancoCL.validaClave, opts, function(err, res, body) {
		if(err != null) {
			log("check error");
			console.log(err);
			return;
		}

		var code = false;
		try {
			var x = JSON.parse(body.replace(/'/g, '"'));
			var code = x[0].compara_sesion;
		} catch(e) {
			console.log(body);
			callback(false, e);
			return;
		}

		switch(code) {
			case "00":
				callback(true, null);
			break;
			case "01":
			case "02":
			case "04":
				callback(false, new Error("Contraseña incorrecta"));
			break;
			case "05":
				callback(false, new Error("Contraseña bloqueada"));
			break;
			default:
				callback(false, new Error("Error desconocido"));
		}
	})
}

BancoCL.prototype.checkStatus = function(callback) {
	var _call = callback || function(){};
	var that = this;
	this.req(BancoCL.checkSession, function(err, res, body) {
		if(err != null) {
			_call(err);
			return;
		}

		that.logged = body.trim() == "00";
		_call(null, that.logged);
	});
}

BancoCL.prototype.keepAliveCallback = function() {
	//console.log("[BE][KA] Checking status...");
	var that = this;
	that.checkStatus(function(err, logged){
		if(err != null) {
			console.log("[BCL][KA] Error received! " + err.message);
			return;
		}

		if(!logged) {
			that.keepAliveInt = null;
			console.log("[BCL][KA] Session got closed!");
			return;
		}

		//console.log("[BE][KA] Session OK");
		that.keepAliveInt = setTimeout(function(){ that.keepAliveCallback(); }, 20000);
	});
}

BancoCL.prototype.startKeepAlive = function() {
	if(this.keepAliveInt != null) return;

	this.keepAliveCallback();
}

module.exports = BancoCL;<|endoftext|>


<commit_before>// -------------------------------------------------
// ---------------------- PLIC ---------------------
// -------------------------------------------------
// PLIC (Platform-Level Interrupt Controller) device for RISC-V

"use strict";
var message = require('../messagehandler');
var utils = require('../utils');

/*
 * 0x0000   Priority Device 0
 * 0x0004   Priority Device 1
 * ....
 * 0x2000   enable bitmask 32-bit * 32 entries for handler 0
 * 0x2080   enable for handler 1
 * 0x200000 hart threshold
 * 0x200004 hart claim
 * 0x201000 hart threshold
 * ...
 */

function PLICDev() {
    this.Reset();
}

PLICDev.prototype.Reset = function() {
    // 32-Bit registers
    this.regs = new Uint32Array(0x3000);
}

PLICDev.prototype.ReadReg32 = function (addr) {
    message.Debug("PLIC: unknown ReadReg32: " + utils.ToHex(addr));
    return 0x0;
}

PLICDev.prototype.WriteReg32 = function (addr, value) {
    message.Debug("PLIC: unknown WriteReg32: " + utils.ToHex(addr) + ": " + utils.ToHex(value));
}

module.exports = PLICDev;
<commit_msg>Update Plic<commit_after>// -------------------------------------------------
// ---------------------- PLIC ---------------------
// -------------------------------------------------
// PLIC (Platform-Level Interrupt Controller) device for RISC-V

"use strict";
var message = require('../messagehandler');
var utils = require('../utils');

/*
 * 0x0000   Priority Device 0
 * 0x0004   Priority Device 1
 * ....
 * 0x2000   enable bitmask 32-bit * 32 entries for handler 0
 * 0x2080   enable for handler 1
 * 0x200000 hart threshold
 * 0x200004 hart claim
 * 0x201000 hart threshold
 * ...
 */

var IRQ_S_EXT = 9;

function PLICDev(cpuirqhandler) {
    this.cpuirqhandler = cpuirqhandler
    this.Reset();
}

PLICDev.prototype.Reset = function() {
    // 32-Bit registers
    this.regs = new Uint32Array(0x3000);
    this.mask = 0x0;
}

PLICDev.prototype.ReadReg32 = function (addr) {
    //message.Debug("PLIC: unknown ReadReg32: " + utils.ToHex(addr));
    var i = 0;
    if (addr == 0x00200004) {
        for(i=0; i<32; i++)
            if (this.mask & (1<<i)) return i;
    }
    return 0x0;
}

PLICDev.prototype.WriteReg32 = function (addr, value) {
    //message.Debug("PLIC: unknown WriteReg32: " + utils.ToHex(addr) + ": " + utils.ToHex(value));
}

PLICDev.prototype.RaiseInterrupt = function (line) {
    line = line | 0;
    if (line == 0x1) return; // HTIF
    //message.Debug("PLIC: Raise line " + line);
    this.mask |= 1 << line;
    this.cpuirqhandler.RaiseInterrupt(IRQ_S_EXT, -1);
}

PLICDev.prototype.ClearInterrupt = function (line) {
    line = line | 0;
    //message.Debug("PLIC: Clear line " + line);
    this.mask &= ~(1 << line);
    if (this.mask == 0x0) {
        this.cpuirqhandler.ClearInterrupt(IRQ_S_EXT, -1);
    }
}

module.exports = PLICDev;
<|endoftext|>


<commit_before>$(document).ready( function() {

  var blacklist1 = '';
  var blacklist2 = '';
  var blacklist3 = '';

  var requestURL = 'http://dev-site.vbox.local/symfony/web/app_dev.php/svdm/tweet?1=' + blacklist1 + "&2=" + blacklist2 + "&3=" + blacklist3;

  console.log(requestURL);

  get_tweet(requestURL);

  //setInterval(function() { get_tweet(requestURL)}, 1000);

});

function get_tweet(url) {
  $.ajax({
    type: 'GET',
    url: url,
    success: function(data) { insertTweet(data); },
    contentType: "application/json",
    dataType: 'json'
  });
}

function insertTweet(tweet) {

  $('.tweet-media').html('');

  $('.tweet-message').text(tweet.message);

  if (tweet.media_url != "") {
    $('.tweet-media').html("");
  }
}
<commit_msg>Seperated initURL from the reqeuestURL<commit_after>$(document).ready( function() {

  var blacklist = ['','','']
  var requestURL;

  var initURL = 'http://dev-site.vbox.local/symfony/web/app_dev.php/svdm/tweet'

  get_tweet(initURL);

  //setInterval(function() { get_tweet(requestURL)}, 1000);

  function get_tweet(url) {
    $.ajax({
      type: 'GET',
      url: url,
      success: function(data) { insertTweet(data); },
      contentType: "application/json",
      dataType: 'json'
    });

    console.log(url);
  }

  function insertTweet(tweet) {

    $('.tweet-media').html('');

    $('.tweet-message').text(tweet.message);

    if (tweet.media_url != "") {
      $('.tweet-media').html("");
    }

    blacklist[0] = tweet.tid;

    requestURL = 'http://dev-site.vbox.local/symfony/web/app_dev.php/svdm/tweet?1=' + blacklist[0] + "&2=" + blacklist[1] + "&3=" + blacklist[2];
  }
});

<|endoftext|>


<commit_before>// Copyright 2014-2017, University of Colorado Boulder

/**
 * Base class for button models, which describe the behavior of buttons when users interact with them.  Property values
 * are set by an associated listener, see ButtonListener for details.
 */
define( function( require ) {
  'use strict';

  // modules
  var BooleanProperty = require( 'AXON/BooleanProperty' );
  var inherit = require( 'PHET_CORE/inherit' );
  var PressListener = require( 'SCENERY/listeners/PressListener' );
  var Property = require( 'AXON/Property' );
  var sun = require( 'SUN/sun' );
  var Tandem = require( 'TANDEM/Tandem' );

  /**
   * @param {Object} [options]
   * @constructor
   */
  function ButtonModel( options ) {

    options = _.extend( {
      // {function} called on pointer down
      startCallback: function() {},
      // {function} called on pointer up, @param {boolean} over - indicates whether the pointer was released over the button
      endCallback: function( over ) {},
      // {boolean} is the button enabled?
      enabled: true,

      tandem: Tandem.required,

      // a11y
      fireOnHoldInterval: 100 // fire continuously at this interval in ms when holding down button with keyboard
    }, options );

    var self = this;

    // model properties
    this.overProperty = new Property( false ); // @public - Is the pointer over the button?
    this.downProperty = new Property( false ); // @public - Is the pointer down?

    // @public - Is the button enabled?
    this.enabledProperty = new BooleanProperty( options.enabled, {
      tandem: options.tandem.createTandem( 'enabledProperty' )
    } );

    // @private - keep track of and store all listeners this model creates
    this.listeners = [];

    // @private {number}
    this._fireOnHoldInterval = options.fireOnHoldInterval;

    // startCallback on pointer down, endCallback on pointer up. lazyLink so they aren't called immediately.
    this.downProperty.lazyLink( function( down ) {
      if ( down ) {
        options.startCallback();
      }
      else {
        options.endCallback( self.overProperty.get() );
      }
    } );

    // interrupt listeners when enabled is set to false
    this.enabledProperty.link( function( enabled ) {
      if ( !enabled ) {
        for ( var i = 0; i < self.listeners.length; i++ ) {
          var listener = self.listeners[ i ];
          listener.interrupt && listener.interrupt();
        }
      }
    } );
    this.disposeButtonModel = function() {
      this.overProperty.dispose();
      this.downProperty.dispose();
      this.enabledProperty.dispose();
      this.listeners = [];
    };
  }

  sun.register( 'ButtonModel', ButtonModel );

  return inherit( Object, ButtonModel, {

    /**
     * @public
     */
    dispose: function() {
      this.disposeButtonModel();
    },

    /**
     * Click the button by pressing the button down and then releasing after a timeout. When assistive technology is
     * used, the browser does not receive 'down' or 'up' events on buttons - only a single 'click' event. For a11y we
     * need to toggle the pressed state every 'click' event.
     * @param {function} [endListener] - optional function to be called once the button has been released after
     *                                   accessibility related interaction.
     * @public
     */
    a11yClick: function( endListener ) {
      if ( !this.downProperty.get() && this.enabledProperty.get() ) {

        // ensure that button is 'over' so listener can be called while button is down
        this.overProperty.set( true );
        this.downProperty.set( true );

        var self = this;
        // Timer.setTimeout( function() {

        // no longer down, don't reset 'over' so button can be styled as long as it has focus
        self.downProperty.set( false );

        endListener && endListener();
        // }, self._fireOnHoldInterval );
      }
    },

    /**
     * Button is no longer considered over on blur, unless blur was initiated by a 'down' event.
     *
     * @public
     */
    a11yBlur: function() {
      if ( !this.downProperty.get() ) {
        this.overProperty.value = false;
      }
    },

    /**
     * Creates a standard button listener that can be added to a node and that will trigger the changes to this model.
     * @param {Tandem} tandem
     * @returns {PressListener}
     * @public
     */
    createListener: function( tandem ) {
      var self = this;

      var pressListener = new PressListener( {
        tandem: tandem,
        isPressedProperty: this.downProperty,
        isOverProperty: this.overProperty,
        canStartPress: function() {
          return self.enabledProperty.value;
        }
      } );
      this.listeners.push( pressListener );
      return pressListener;
    }
  } );
} );<commit_msg>documentation, https://github.com/phetsims/sun/issues/372<commit_after>// Copyright 2014-2017, University of Colorado Boulder

/**
 * Base class for button models, which describe the behavior of buttons when users interact with them.  Property values
 * are set by an associated listener, see ButtonListener for details.
 */
define( function( require ) {
  'use strict';

  // modules
  var BooleanProperty = require( 'AXON/BooleanProperty' );
  var inherit = require( 'PHET_CORE/inherit' );
  var PressListener = require( 'SCENERY/listeners/PressListener' );
  var Property = require( 'AXON/Property' );
  var sun = require( 'SUN/sun' );
  var Tandem = require( 'TANDEM/Tandem' );

  /**
   * @param {Object} [options]
   * @constructor
   */
  function ButtonModel( options ) {

    options = _.extend( {
      // {function} called on pointer down
      startCallback: function() {},
      // {function} called on pointer up, @param {boolean} over - indicates whether the pointer was released over the button
      endCallback: function( over ) {},
      // {boolean} is the button enabled?
      enabled: true,

      tandem: Tandem.required,

      // a11y
      fireOnHoldInterval: 100 // fire continuously at this interval in ms when holding down button with keyboard
    }, options );

    var self = this;

    // model properties
    this.overProperty = new Property( false ); // @public - Is the pointer over the button?
    this.downProperty = new Property( false ); // @public - Is the pointer down?

    // @public - Is the button enabled?
    this.enabledProperty = new BooleanProperty( options.enabled, {
      tandem: options.tandem.createTandem( 'enabledProperty' )
    } );

    // @private - keep track of and store all listeners this model creates
    this.listeners = [];

    // @private {number}
    this._fireOnHoldInterval = options.fireOnHoldInterval;

    // startCallback on pointer down, endCallback on pointer up. lazyLink so they aren't called immediately.
    this.downProperty.lazyLink( function( down ) {
      if ( down ) {
        options.startCallback();
      }
      else {
        options.endCallback( self.overProperty.get() );
      }
    } );

    // interrupt listeners when enabled is set to false
    this.enabledProperty.link( function( enabled ) {
      if ( !enabled ) {
        for ( var i = 0; i < self.listeners.length; i++ ) {
          var listener = self.listeners[ i ];
          listener.interrupt && listener.interrupt();
        }
      }
    } );

    // @private
    this.disposeButtonModel = function() {

      // This will unlink all listeners, causing potential issues if listeners try to unlink properties afterwards
      this.overProperty.dispose();
      this.downProperty.dispose();
      this.enabledProperty.dispose();
      this.listeners = [];
    };
  }

  sun.register( 'ButtonModel', ButtonModel );

  return inherit( Object, ButtonModel, {

    /**
     * @public
     */
    dispose: function() {
      this.disposeButtonModel();
    },

    /**
     * Click the button by pressing the button down and then releasing after a timeout. When assistive technology is
     * used, the browser does not receive 'down' or 'up' events on buttons - only a single 'click' event. For a11y we
     * need to toggle the pressed state every 'click' event.
     * @param {function} [endListener] - optional function to be called once the button has been released after
     *                                   accessibility related interaction.
     * @public
     */
    a11yClick: function( endListener ) {
      if ( !this.downProperty.get() && this.enabledProperty.get() ) {

        // ensure that button is 'over' so listener can be called while button is down
        this.overProperty.set( true );
        this.downProperty.set( true );

        var self = this;
        // Timer.setTimeout( function() {

        // no longer down, don't reset 'over' so button can be styled as long as it has focus
        self.downProperty.set( false );

        endListener && endListener();
        // }, self._fireOnHoldInterval );
      }
    },

    /**
     * Button is no longer considered over on blur, unless blur was initiated by a 'down' event.
     *
     * @public
     */
    a11yBlur: function() {
      if ( !this.downProperty.get() ) {
        this.overProperty.value = false;
      }
    },

    /**
     * Creates a standard button listener that can be added to a node and that will trigger the changes to this model.
     * @param {Tandem} tandem
     * @returns {PressListener}
     * @public
     */
    createListener: function( tandem ) {
      var self = this;

      var pressListener = new PressListener( {
        tandem: tandem,
        isPressedProperty: this.downProperty,
        isOverProperty: this.overProperty,
        canStartPress: function() {
          return self.enabledProperty.value;
        }
      } );
      this.listeners.push( pressListener );
      return pressListener;
    }
  } );
} );<|endoftext|>


<commit_before>
(function($){

  window.enableBlame = function(url, original_path) {
    var message = null;
    var message_rev = null;

    /* for each blame cell containing a changeset link... */
    var rev_paths = {};
    $("table.code th.blame a").each(function() {
      href = $(this).attr("href");
      rev_href = href.substr(href.indexOf("changeset/") + 10);
      elts = rev_href.split("/");
      var path = elts.slice(1).join("/");
      if (path != original_path)
        rev_paths["r"+elts[0]] = path;
    });

    /* for each blame cell... */
    $("table.code th.blame").each(function() {
      var rev = $(this).attr("class").split(" ")[1]; // "blame r123"
      var path = rev_paths[rev] || original_path; // only found if != orig

      if (!rev)
        return;

      $(this).click(function() {
        var row = this.parentNode;
        var message_is_visible = message && message.css("display") == "block";
        var highlight_rev = null;

        function show() {
          /* Display commit message for the selected revision */

          var message_w = message.get(0).offsetWidth;

          // limit message panel width to 3/5 of the row width
          var row_w = row.offsetWidth;
          var max_w = (3.0 * row_w / 5.0);
          if (!message_w || message_w > max_w) {
            message_w = max_w;
            var borderw = (2+8)*2; // borderwidth + padding on both sides
            message.css({width: message_w - borderw + "px"});
          }

                var row_offset = $(row).offset();
          var left = row_offset.left + row.offsetWidth - message_w;
          message.css({display: "block", top: row_offset.top+"px", left: left-2+"px"});
        }

        function hide() {
          /* Hide commit message */
          message.css({display: "none"});

          /* Remove highlighting for lines of the current revision */
          $("table.code th."+message_rev).each(function() {
            $(this.parentNode).removeClass("hilite")
          });
        }

        if (message_rev != rev) {              // fetch a new revision
          if (message_is_visible) {
            hide();
          }
          message_rev = rev;
          highlight_rev = message_rev;

          $.get(url + rev.substr(1), {annotate: path}, function(data) {
            // remove former message panel if any
            if (message)
              message.remove();
            // create new message panel
            message = $("
").addClass("message").css({
              position: "absolute", zIndex: 2
            }).appendTo("body"); /* add a close button somehow... */
            // fill in changeset data
            message.html(data || "(no changeset information)");

            show();
          });
        } else if (message_is_visible) {
          hide();
        } else {
          show();
          highlight_rev = message_rev;
        }

        /* Highlight all lines of the current revision */
        $("table.code th."+highlight_rev).each(function() {
          $(this.parentNode).addClass("hilite")
        });

      });
    });
  }

})(jQuery);
<commit_msg>Improvement to the blame view: when clicking on the changeset number, no longer go to that changeset but show the changeset in a popup window, like clicking on the background of the cell would have done.<commit_after>
(function($){

  window.enableBlame = function(url, original_path) {
    var message = null;
    var message_rev = null;

    /* for each blame cell containing a changeset link... */
    var rev_paths = {};
    $("table.code th.blame a").each(function() {
      href = $(this).attr("href");
      $(this).removeAttr("href");
      rev_href = href.substr(href.indexOf("changeset/") + 10);
      elts = rev_href.split("/");
      var path = elts.slice(1).join("/");
      if (path != original_path)
        rev_paths["r"+elts[0]] = path;
    });

    /* for each blame cell... */
    $("table.code th.blame").each(function() {
      var rev = $(this).attr("class").split(" ")[1]; // "blame r123"
      var path = rev_paths[rev] || original_path; // only found if != orig

      if (!rev)
        return;

      $(this).css("cursor", "pointer").click(function() {
        var row = this.parentNode;
        var message_is_visible = message && message.css("display") == "block";
        var highlight_rev = null;

        function show() {
          /* Display commit message for the selected revision */

          var message_w = message.get(0).offsetWidth;

          // limit message panel width to 3/5 of the row width
          var row_w = row.offsetWidth;
          var max_w = (3.0 * row_w / 5.0);
          if (!message_w || message_w > max_w) {
            message_w = max_w;
            var borderw = (2+8)*2; // borderwidth + padding on both sides
            message.css({width: message_w - borderw + "px"});
          }

          var row_offset = $(row).offset();
          var left = row_offset.left + row.offsetWidth - message_w;
          message.css({display: "block", top: row_offset.top+"px", left: left-2+"px"});
        }

        function hide() {
          /* Hide commit message */
          message.css({display: "none"});

          /* Remove highlighting for lines of the current revision */
          $("table.code th."+message_rev).each(function() {
            $(this.parentNode).removeClass("hilite")
          });
        }

        if (message_rev != rev) {              // fetch a new revision
          if (message_is_visible) {
            hide();
          }
          message_rev = rev;
          highlight_rev = message_rev;

          $.get(url + rev.substr(1), {annotate: path}, function(data) {
            // remove former message panel if any
            if (message)
              message.remove();
            // create new message panel
            message = $("
").addClass("message").css({
              position: "absolute", zIndex: 2
            }).appendTo("body"); /* add a close button somehow... */
            // fill in changeset data
            message.html(data || "(no changeset information)");

            show();
          });
        } else if (message_is_visible) {
          hide();
        } else {
          show();
          highlight_rev = message_rev;
        }

        /* Highlight all lines of the current revision */
        $("table.code th."+highlight_rev).each(function() {
          $(this.parentNode).addClass("hilite")
        });

      });
    });
  }

})(jQuery);
<|endoftext|>


<commit_before>/*
Copyright (C) 2016 Tony Mobily

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

const firstBy = require('thenby')

const Mixin = (superclass) => class extends superclass {
  // op can be 'fetch', 'update', 'insert', 'query', 'delete'.
  // If 'query, then data is an array. Otherwise, it's a record
  async transformResult (request, data, op) { }

  static get data () { return [] } // Data. This can get re-set to something else in children

  constructor () {
    super()
    this.data = this.constructor.data
  }

  reposition (currentPos) {
    //
    // No positioning managed: exit right away
    if (!this.positioning) return

    const record = this.data[currentPos]

    const beforeId = record[this.beforeIdField]

    // No beforeId defined: will leave it where it is
    if (typeof beforeId === 'undefined') return

    // The current position is last and beforeId is null: it's already where it
    // should be (last)
    if (currentPos === this.data.length - 1 && beforeId === null) return

    const newPos = this.data.findIndex(el => el[this.idProperty] === beforeId)
    if (newPos === -1) return
    this.data.splice(newPos, 0, this.data.splice(currentPos, 1)[0])
    return newPos
  }

  // Input:
  // - request.body
  // Output: an object (saved record)

  async implementInsert (request) {
    await super.implementInsert(request)

    request.record = request.body
    if (typeof request.record[this.idProperty] === 'undefined') {
      request.record[this.idProperty] = Math.max(this.data.map(el => el[this.idProperty])) + 1
    } else {
      if (this.data.findIndex(el => el[this.idProperty] === request.record[this.idProperty]) !== -1) {
        throw new Error('ID already present, cannot insert duplicate IDs')
      }
    }

    this.data.push(request.record)
    // if (this.positioning) request.record[this.positionField] = this.reposition(this.data.length - 1)
    if (this.positioning) this.reposition(this.data.length - 1)

    return this.transformResult(request, request.record, 'insert')
  }

  // Input:
  // - request.params (query)
  // - request.body (data)
  // Output: an object (updated record, refetched)
  //
  async implementUpdate (request) {
    await super.implementUpdate(request)

    const currentPos = this.data.findIndex(el => el[this.idProperty] === request.record[this.idProperty])
    this.data[currentPos] = request.record
    // if (this.positioning) request.record[this.positionField] = this.reposition(currentPos)
    if (this.positioning) this.reposition(currentPos)

    return this.transformResult(request, request.record, 'update')
  }

  // Input: request.params (with key this.idProperty set)
  // Output: nothing
  async implementDelete (request) {
    await super.implementDelete(request)

    const currentPos = this.data.findIndex(el => el[this.idProperty] === request.record[this.idProperty])
    this.data.splice(currentPos, 1)

    return this.transformResult(request, request.record, 'delete')

  }

  // Input: request.params, request.options.[conditionsHash,skip,limit,sort]
  // Output: { data: [], grandTotal: ? }
  async implementQuery (request) {
    await super.implementQuery(request)

    let retData = this.data

    if (Object.keys(request.options.conditionsHash).length) retData = await this.filterByConditions(request, retData)
    if (Object.keys(request.options.sort).length) retData = await this.sortBy(request, retData)

    if (request.options.skip) retData = retData.splice(request.options.skip, 0)
    if (request.options.limit) retData = retData.slice(0, request.options.limit)

    const transformedData = [ ...retData ]
    await this.transformResult(request, transformedData, 'query')

    return { data: transformedData, grandTotal: retData.length }
  }

  async filterByConditions (request, d) {
    const ch = request.options.conditionsHash

    return d.filter(item => {
      for (const key in ch) {
        if (typeof item[key] === 'undefined' || item[key] !== ch[key]) return false
      }
      return true
    })
  }

  async sortBy (request, d) {
    const sortFields = request.options.sort
    const sortKeys = Object.keys(sortFields)
    const sortConditions = firstBy()
    for (let i = 1, l = sortKeys.length; i < l; i++) {
      sortConditions.thenBy(sortFields[i], { ignoreCase: true, direction: sortFields[i] === 1 })
    }
    return d.sort(sortConditions)
  }

  // Input: request.params (with key this.idProperty set)
  // Output: an object
  async implementFetch (request) {
    await super.implementFetch(request)

    const currentPos = this.data.findIndex(el => el[this.idProperty] === request.params[this.idProperty])

    request.record = this.data[currentPos]

    // Requested by the API: when implementing implementFetch(), this function
    // must be called when request.record is set
    if (request.record) this.implementFetchPermissions(request)

    this.transformResult(request, request.record, 'fetch')
    return request.record
  }
}

exports = module.exports = Mixin
<commit_msg>Last fixes t othe memory store, which now actually works<commit_after>/*
Copyright (C) 2016 Tony Mobily

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

const firstBy = require('thenby')

const Mixin = (superclass) => class extends superclass {
  // op can be 'fetch', 'update', 'insert', 'query', 'delete'.
  // If 'query, then data is an array. Otherwise, it's a record
  async transformResult (request, data, op) { }

  static get data () { return [] } // Data. This can get re-set to something else in children

  constructor () {
    super()
    this.data = this.constructor.data
  }

  reposition (currentPos) {
    //
    // No positioning managed: exit right away
    if (!this.positioning) return

    const record = this.data[currentPos]

    const beforeId = record[this.beforeIdField]

    // No beforeId defined: will leave it where it is
    if (typeof beforeId === 'undefined') return

    // The current position is last and beforeId is null: it's already where it
    // should be (last)
    if (currentPos === this.data.length - 1 && beforeId === null) return

    const newPos = this.data.findIndex(el => el[this.idProperty] === beforeId)
    if (newPos === -1) return
    this.data.splice(newPos, 0, this.data.splice(currentPos, 1)[0])
    return newPos
  }

  // Input:
  // - request.body
  // Output: an object (saved record)

  async implementInsert (request) {
    await super.implementInsert(request)

    request.record = request.body
    if (typeof request.record[this.idProperty] === 'undefined') {
      request.record[this.idProperty] = Math.max(this.data.map(el => el[this.idProperty])) + 1
    } else {
      if (this.data.findIndex(el => el[this.idProperty] === request.record[this.idProperty]) !== -1) {
        throw new Error('ID already present, cannot insert duplicate IDs')
      }
    }

    this.data.push(request.record)
    // if (this.positioning) request.record[this.positionField] = this.reposition(this.data.length - 1)
    if (this.positioning) this.reposition(this.data.length - 1)

    await this.transformResult(request, request.record, 'insert')
    return request.record
  }

  // Input:
  // - request.params (query)
  // - request.body (data)
  // Output: an object (updated record, refetched)
  //
  async implementUpdate (request) {
    await super.implementUpdate(request)

    const currentPos = this.data.findIndex(el => el[this.idProperty] === request.record[this.idProperty])
    this.data[currentPos] = request.record
    // if (this.positioning) request.record[this.positionField] = this.reposition(currentPos)
    if (this.positioning) this.reposition(currentPos)

    await this.transformResult(request, request.record, 'update')
    return request.record
  }

  // Input: request.params (with key this.idProperty set)
  // Output: nothing
  async implementDelete (request) {
    await super.implementDelete(request)

    const currentPos = this.data.findIndex(el => el[this.idProperty] === request.record[this.idProperty])
    this.data.splice(currentPos, 1)

    await this.transformResult(request, request.record, 'delete')
    return request.record
  }

  // Input: request.params, request.options.[conditionsHash,skip,limit,sort]
  // Output: { data: [], grandTotal: ? }
  async implementQuery (request) {
    await super.implementQuery(request)

    let retData = this.data

    if (Object.keys(request.options.conditionsHash).length) retData = await this.filterByConditions(request, retData)
    if (Object.keys(request.options.sort).length) retData = await this.sortBy(request, retData)

    if (request.options.skip) retData = retData.splice(request.options.skip, 0)
    if (request.options.limit) retData = retData.slice(0, request.options.limit)

    const transformedData = [ ...retData ]
    await this.transformResult(request, transformedData, 'query')

    return { data: transformedData, grandTotal: retData.length }
  }

  async filterByConditions (request, d) {
    const ch = request.options.conditionsHash

    return d.filter(item => {
      for (const key in ch) {
        if (typeof item[key] === 'undefined' || item[key] !== ch[key]) return false
      }
      return true
    })
  }

  async sortBy (request, d) {
    const sortFields = request.options.sort
    const sortKeys = Object.keys(sortFields)
    const sortConditions = firstBy()
    for (let i = 1, l = sortKeys.length; i < l; i++) {
      sortConditions.thenBy(sortFields[i], { ignoreCase: true, direction: sortFields[i] === 1 })
    }
    return d.sort(sortConditions)
  }

  // Input: request.params (with key this.idProperty set)
  // Output: an object
  async implementFetch (request) {
    await super.implementFetch(request)

    const currentPos = this.data.findIndex(el => el[this.idProperty] === request.params[this.idProperty])

    request.record = this.data[currentPos]

    // Requested by the API: when implementing implementFetch(), this function
    // must be called when request.record is set
    if (request.record) this.implementFetchPermissions(request)

    await this.transformResult(request, request.record, 'fetch')
    return request.record
  }
}

exports = module.exports = Mixin
<|endoftext|>


<commit_before>/**
 *
 */
App.ProductSerializer = App.Serializer.extend({});
/**
 *
 */
App.ProductController = Ember.ObjectController.extend(
{
  needs: ['products', 'products.show', 'application'],
  actions:
  {
    cashBack: function(product, redirect)
    {
      var glome_id = this.get('controllers.application').get('glomeid');

      if (glome_id && product.id)
      {
        var url = App.apiHost + '/api/products/' + product.id + '/click/' + glome_id + '.json'

        if (typeof redirect == 'undefined')
        {
          url += '?redirect=' + product.page
        }
        else
        {
          url += '?redirect=' + redirect
        }

        return Ember.$.getJSON(url).then(function(data)
        {
          window.open(data.url, '_blank');
        });
      }
    }
  }
});
<commit_msg>hackish url building for search<commit_after>/**
 *
 */
App.ProductSerializer = App.Serializer.extend({});
/**
 *
 */
App.ProductAdapter = App.Adapter.extend(
{
  buildURL: function(type, id)
  {
    var url = App.apiHost + '/api/products';

    if (id == 'search')
    {
      url += '/' + id;
    }
    url += '.json';
    return url;
  }
});
/**
 *
 */
App.ProductController = Ember.ObjectController.extend(
{
  needs: ['products', 'products.show', 'application'],
  actions:
  {
    cashBack: function(product, redirect)
    {
      var glome_id = this.get('controllers.application').get('glomeid');

      if (glome_id && product.id)
      {
        var url = App.apiHost + '/api/products/' + product.id + '/click/' + glome_id + '.json'

        if (typeof redirect == 'undefined')
        {
          url += '?redirect=' + product.page
        }
        else
        {
          url += '?redirect=' + redirect
        }

        return Ember.$.getJSON(url).then(function(data)
        {
          window.open(data.url, '_blank');
        });
      }
    }
  }
});
<|endoftext|>


<commit_before>test("Popcorn Subtitle Plugin", function () {

  var popped = Popcorn( "#video" ),
      popped2 = Popcorn( "#video2" ),
      expects = 16,
      count = 0,
      subTop = 9001,
      subLeft = 9001,
      subtitlediv,
      subtitle2div;

  expect(expects);

  function plus() {
    if ( ++count === expects ) {
      start();
    }
  }

  stop( 12000 );

  ok ( 'subtitle' in popped, "subtitle is a method of the popped instance" );
  plus();

  popped.subtitle({
      start: 0,
      end: 2,
      text: 'this is the first subtitle of 2011',
      language: "en",
      languagesrc: "language",
      accessibilitysrc: "accessibility"
    } )
  .subtitle({
      start: 2,
      end: 4,
      text: 'this is the second subtitle of 2011',
      language: "en",
      languagesrc: "language",
      accessibilitysrc: "accessibility"
    } )
  .subtitle({
      start: 5,
      end: 7,
      text: 'this is the third subtitle of 2011',
      language: "en",
      languagesrc: "language",
      accessibilitysrc: "accessibility"
    } )
    .volume(0)
    .play();

  subtitlediv = popped.getTrackEvent( popped.getLastTrackEventId() ).container;

  popped.subtitle({
    start: 7,
    end: 9,
    text: 'instance one test'
  });

  popped2.subtitle({
      start: 7,
      end: 9,
      text: 'instance two test'
    })
    .volume(0)
    .play().pause();

  subtitle2div = popped2.getTrackEvent( popped2.getLastTrackEventId() ).container;

  popped.exec( 1, function() {

    popped.media.pause();
    equals( subtitlediv.children[ 0 ].innerHTML, "this is the first subtitle of 2011", "subtitle displaying correct information" );
    plus();

    // capturing location now, to check against later,
    // a subtitle must be displayed to get valid data
    // which is why we do this in exec
    subLeft = subtitlediv.style.left;
    subTop  = subtitlediv.style.top;

    // changing position
    popped.media.style.position = "absolute";
    popped.media.style.left = "400px";
    popped.media.style.top = "600px";
    popped.media.play()

  });

  popped.exec( 3, function() {

    popped.media.pause();

    // check position of subttile that should of moved with video,
    // a subtitle must be displayed to get valid data
    ok( subtitlediv.style.left !== subLeft, "subtitle's left position has changed" );
    plus();
    ok( subtitlediv.style.top !== subTop, "subtitle's top position has changed" );
    plus();

    // we know values have changed, but how accurate are they?
    // check values against the video's values
    // we need four checks because if we just check against video's position,
    // and video's position hasn't updated either, we'll pass when we should fail
    equals( subtitlediv.style.left, popped.position().left + "px", "subtitle left position moved" );
    plus();
    ok( Popcorn.position( subtitlediv ).top > popped.position().top, "subtitle top position moved" );
    plus();

    equals (subtitlediv.children[ 1 ].innerHTML, "this is the second subtitle of 2011", "subtitle displaying correct information" );
    plus();

    popped.media.play();

  });

  popped.exec( 4, function() {

    popped.media.pause();
    equals (subtitlediv.children[ 1 ].innerHTML, "", "subtitle is clear" );
    plus();

    popped.media.play();

  });

  popped.exec( 6, function() {

    popped.media.play();

    equals (subtitlediv.style.display, "inline", "subtitles being displayed with accessiblity on" );
    plus();

    // turn accessibility off
    document.getElementById( "accessibility" ).click();

    equals (subtitlediv.style.display, "none", "subtitles not being displayed with accessiblity off" );
    plus();

    // turn accessibility back on
    document.getElementById( "accessibility" ).click();

    equals (subtitlediv.style.display, "inline", "subtitles being displayed with accessiblity back on" );
    plus();

    equals (subtitlediv.children[ 2 ].innerHTML, "this is the third subtitle of 2011", "subtitle displaying correct information" );
    plus();
    popped.media.play();

  });

  popped.exec( 8, function() {
    popped.pause();
    popped2.currentTime( 8 );
  });

  popped2.exec( 8, function() {
    popped2.media.pause();

    equals (subtitlediv.children[ 3 ].innerHTML, "instance one test", "subtitle displaying correct information" );
    plus();
    equals (subtitle2div.children[ 0 ].innerHTML, "instance two test", "subtitle displaying correct information" );
    plus();

    popped.media.play();
  });

  popped.exec( 10, function() {
    ok ( document.getElementById( 'subtitle-0' ).style.display === "none" &&
        document.getElementById( 'subtitle-1' ).style.display === "none" &&
        document.getElementById( 'subtitle-2' ).style.display === "none", "All subtitles are no longer visible" );
    plus();

    popped.pause().removeTrackEvent( popped.data.trackEvents.byStart[ 6 ]._id );

    ok( !document.getElementById( 'subtitle-2' ), "removed subtitle div was properly destroyed"  );
    plus();
  });
});

<commit_msg>[#644] 'review' 'fixes'<commit_after>test("Popcorn Subtitle Plugin", function () {

  var popped = Popcorn( "#video" ),
      popped2 = Popcorn( "#video2" ),
      expects = 16,
      count = 0,
      subTop = 9001,
      subLeft = 9001,
      subtitlediv,
      subtitle2div;

  expect(expects);

  function plus() {
    if ( ++count === expects ) {
      start();
    }
  }

  stop( 12000 );

  ok ( 'subtitle' in popped, "subtitle is a method of the popped instance" );
  plus();

  popped.subtitle({
      start: 0,
      end: 2,
      text: 'this is the first subtitle of 2011',
      language: "en",
      languagesrc: "language",
      accessibilitysrc: "accessibility"
    } )
  .subtitle({
      start: 2,
      end: 4,
      text: 'this is the second subtitle of 2011',
      language: "en",
      languagesrc: "language",
      accessibilitysrc: "accessibility"
    } )
  .subtitle({
      start: 5,
      end: 7,
      text: 'this is the third subtitle of 2011',
      language: "en",
      languagesrc: "language",
      accessibilitysrc: "accessibility"
    } )
    .volume(0)
    .play();

  subtitlediv = popped.getTrackEvent( popped.getLastTrackEventId() ).container;

  popped.subtitle({
    start: 7,
    end: 9,
    text: 'instance one test'
  });

  popped2.subtitle({
      start: 7,
      end: 9,
      text: 'instance two test'
    })
    .volume(0)
    .play().pause();

  subtitle2div = popped2.getTrackEvent( popped2.getLastTrackEventId() ).container;

  popped.exec( 1, function() {

    popped.media.pause();
    equals( subtitlediv.children[ 0 ].innerHTML, "this is the first subtitle of 2011", "subtitle displaying correct information" );
    plus();

    // capturing location now, to check against later,
    // a subtitle must be displayed to get valid data
    // which is why we do this in exec
    subLeft = subtitlediv.style.left;
    subTop  = subtitlediv.style.top;

    // changing position
    popped.media.style.position = "absolute";
    popped.media.style.left = "400px";
    popped.media.style.top = "600px";
    popped.media.play();

  });

  popped.exec( 3, function() {

    popped.media.pause();

    // check position of subttile that should of moved with video,
    // a subtitle must be displayed to get valid data
    ok( subtitlediv.style.left !== subLeft, "subtitle's left position has changed" );
    plus();
    ok( subtitlediv.style.top !== subTop, "subtitle's top position has changed" );
    plus();

    // we know values have changed, but how accurate are they?
    // check values against the video's values
    // we need four checks because if we just check against video's position,
    // and video's position hasn't updated either, we'll pass when we should fail
    equals( subtitlediv.style.left, popped.position().left + "px", "subtitle left position moved" );
    plus();
    ok( Popcorn.position( subtitlediv ).top > popped.position().top, "subtitle top position moved" );
    plus();

    equals (subtitlediv.children[ 1 ].innerHTML, "this is the second subtitle of 2011", "subtitle displaying correct information" );
    plus();

    popped.media.play();

  });

  popped.exec( 4, function() {

    popped.media.pause();
    equals (subtitlediv.children[ 1 ].innerHTML, "", "subtitle is clear" );
    plus();

    popped.media.play();

  });

  popped.exec( 6, function() {

    popped.media.play();

    equals (subtitlediv.style.display, "inline", "subtitles being displayed with accessiblity on" );
    plus();

    // turn accessibility off
    document.getElementById( "accessibility" ).click();

    equals (subtitlediv.style.display, "none", "subtitles not being displayed with accessiblity off" );
    plus();

    // turn accessibility back on
    document.getElementById( "accessibility" ).click();

    equals (subtitlediv.style.display, "inline", "subtitles being displayed with accessiblity back on" );
    plus();

    equals (subtitlediv.children[ 2 ].innerHTML, "this is the third subtitle of 2011", "subtitle displaying correct information" );
    plus();
    popped.media.play();

  });

  popped.exec( 8, function() {
    popped.pause();
    popped2.currentTime( 8 );
  });

  popped2.exec( 8, function() {
    popped2.media.pause();

    equals (subtitlediv.children[ 3 ].innerHTML, "instance one test", "subtitle displaying correct information" );
    plus();
    equals (subtitle2div.children[ 0 ].innerHTML, "instance two test", "subtitle displaying correct information" );
    plus();

    popped.media.play();
  });

  popped.exec( 10, function() {
    ok ( document.getElementById( 'subtitle-0' ).style.display === "none" &&
        document.getElementById( 'subtitle-1' ).style.display === "none" &&
        document.getElementById( 'subtitle-2' ).style.display === "none", "All subtitles are no longer visible" );
    plus();

    popped.pause().removeTrackEvent( popped.data.trackEvents.byStart[ 6 ]._id );

    ok( !document.getElementById( 'subtitle-2' ), "removed subtitle div was properly destroyed"  );
    plus();
  });
});

<|endoftext|>


<commit_before>/** @jsx React.DOM */
define([
    'underscore', 'jquery', 'react', 'kendo',
    '../util/debug',
    '../ControlCommon'
], function (_, $, React, kendo, debug, controlCommon) {
    'use strict';

    void controlCommon;

    var UserPicker = React.createClass({

        fieldClass: 'formFieldAutocomplete',

        getDefaultProps: function () {
            return {
                value: undefined,
                onChange: function () {},
                id: undefined,
                placeholder: 'Select User...', // l10n requires thought, no strings down here
                template: '

#: fullName #

#: emailAddress #

',
                dataTextField: 'nameOrEmail',
                listClass: 'userPicker',
                disabled: false,
                isValid: [true, ''],
                readonly: false,
                noControl: false
            };
        },

        componentWillMount: function () {
            debug.verify(this.props.dataSource);
        },

        componentDidMount: function (rootNode) {
            var $el = $(rootNode);
            debug.verify($el);

            var onChange = this.props.onChange,
                header = $('

'),
                autoComplete;

            $el.kendoAutoComplete({
                dataSource: this.props.dataSource,
                dataTextField: this.props.dataTextField,
                placeholder: this.props.placeholder,
                highlightFirst: true,
                suggest: false,
                template: this.props.template,
                close: function (e) {
                    var widget = e.sender;
                    // Don't close the picker on an empty search result because we want to tell the user about it.
                    if (widget._typing && widget.dataSource.total() === 0) {
                        e.preventDefault();
                    }
                },
                dataBound: function (e) {
                    var widget = e.sender,
                        dataSource = widget.dataSource;

                    if (dataSource.total() === 0) {
                        header.text('No matches');
                        widget.popup.open();
                    }
                    else if (dataSource.total() < 0) {
                        header.text('All Users (100+ matches)');
                    }
                    else {
                        header.text(kendo.format('All Users ({0:n0} matches)', dataSource.total()));
                    }
                },
                change: function (e) {
                    var widget = e.sender;

                    if (widget.dataSource.total() === 1) {
                        // Exact match - so raise the change event
                        onChange(widget.dataItem(0));
                    }
                },
                select: function (e) {
                    onChange(this.dataItem(e.item.index()));
                }
            }).on('blur', this.onBlur);

            autoComplete = $el.data('kendoAutoComplete');

            if (this.props.listClass) {
                // Add a special class to the popup element so we can style the list items
                autoComplete.list.addClass(this.props.listClass);
            }

            if (this.props.value) {
                autoComplete.value(this.props.value.fullName);
            }
            if (this.props.disabled) {
                autoComplete.enable(false);
            }
            else if (this.props.readonly) {
                autoComplete.readonly(true);
            }
            // Add an element to contain some text above the list of users
            header.prependTo(autoComplete.list);
        },

        componentWillUnmount: function () {
            var $el = $(this.getDOMNode());

            $el.data('kendoAutoComplete').destroy();
        },

        componentDidUpdate: function (prevProps, prevState, rootNode) {
            var $el = $(rootNode),
                autoComplete = $el.data('kendoAutoComplete');

            if (prevProps.dataSource !== this.props.dataSource) {
                autoComplete.setDataSource(this.props.dataSource);
            }

            autoComplete.value(this.props.value ? this.props.value.fullName : null);

            if (this.props.disabled) {
                autoComplete.enable(false);
            }
            else {
                autoComplete.readonly(this.props.readonly);
            }
        },

        onBlur: function (e) {
            var autoComplete = $(e.target).data('kendoAutoComplete');

            if (autoComplete) {
                // Always reset the text back to the current value, in case they typed stuff that didn't match anything
                autoComplete.value(this.props.value ? this.props.value.fullName : null);
            }
        },

        /*jshint ignore:start */
        render: function () {
            debug.verify(!this.props.noControl);
            return (<input type="text" id={this.props.id} className="k-textbox"/>);
        }
        /*jshint ignore:end */
    });

    return UserPicker;

});
<commit_msg>Removed hard-coded status messages. They should come from the server response payload.<commit_after>/** @jsx React.DOM */
define([
    'underscore', 'jquery', 'react', 'kendo',
    '../util/debug',
    '../ControlCommon'
], function (_, $, React, kendo, debug, controlCommon) {
    'use strict';

    void controlCommon;

    var UserPicker = React.createClass({

        fieldClass: 'formFieldAutocomplete',

        getDefaultProps: function () {
            return {
                value: undefined,
                onChange: function () {},
                id: undefined,
                placeholder: 'Select User...', // l10n requires thought, no strings down here
                template: '

#: fullName #

#: emailAddress #

',
                dataTextField: 'nameOrEmail',
                listClass: 'userPicker',
                disabled: false,
                isValid: [true, ''],
                readonly: false,
                noControl: false
            };
        },

        componentWillMount: function () {
            debug.verify(this.props.dataSource);
        },

        componentDidMount: function (rootNode) {
            var $el = $(rootNode);
            debug.verify($el);

            var onChange = this.props.onChange,
                header = $('

'),
                autoComplete;

            $el.kendoAutoComplete({
                dataSource: this.props.dataSource,
                dataTextField: this.props.dataTextField,
                placeholder: this.props.placeholder,
                highlightFirst: true,
                suggest: false,
                template: this.props.template,
                close: function (e) {
                    var widget = e.sender;
                    // Don't close the picker on an empty search result because we want to tell the user about it.
                    if (widget._typing && widget.dataSource.total() === 0) {
                        e.preventDefault();
                    }
                },
                dataBound: function (e) {
                    var widget = e.sender,
                        dataSource = widget.dataSource;

                    header.text(dataSource.message);

                    if (dataSource.total() === 0) {
                        widget.popup.open();
                    }
                },
                change: function (e) {
                    var widget = e.sender;

                    if (widget.dataSource.total() === 1) {
                        // Exact match - so raise the change event
                        onChange(widget.dataItem(0));
                    }
                },
                select: function (e) {
                    onChange(this.dataItem(e.item.index()));
                }
            }).on('blur', this.onBlur);

            autoComplete = $el.data('kendoAutoComplete');

            if (this.props.listClass) {
                // Add a special class to the popup element so we can style the list items
                autoComplete.list.addClass(this.props.listClass);
            }

            if (this.props.value) {
                autoComplete.value(this.props.value.fullName);
            }
            if (this.props.disabled) {
                autoComplete.enable(false);
            }
            else if (this.props.readonly) {
                autoComplete.readonly(true);
            }
            // Add an element to contain some text above the list of users
            header.prependTo(autoComplete.list);
        },

        componentWillUnmount: function () {
            var $el = $(this.getDOMNode());

            $el.data('kendoAutoComplete').destroy();
        },

        componentDidUpdate: function (prevProps, prevState, rootNode) {
            var $el = $(rootNode),
                autoComplete = $el.data('kendoAutoComplete');

            if (prevProps.dataSource !== this.props.dataSource) {
                autoComplete.setDataSource(this.props.dataSource);
            }

            autoComplete.value(this.props.value ? this.props.value.fullName : null);

            if (this.props.disabled) {
                autoComplete.enable(false);
            }
            else {
                autoComplete.readonly(this.props.readonly);
            }
        },

        onBlur: function (e) {
            var autoComplete = $(e.target).data('kendoAutoComplete');

            if (autoComplete) {
                // Always reset the text back to the current value, in case they typed stuff that didn't match anything
                autoComplete.value(this.props.value ? this.props.value.fullName : null);
            }
        },

        /*jshint ignore:start */
        render: function () {
            debug.verify(!this.props.noControl);
            return (<input type="text" id={this.props.id} className="k-textbox"/>);
        }
        /*jshint ignore:end */
    });

    return UserPicker;

});
<|endoftext|>


<commit_before>'use strict';

var banner = '(function (root, factory) {\n' +
             '    if (typeof require === \'function\' && typeof exports === \'object\') {\n' +
             '        // CommonJS\n' +
             '        var ol = require(\'openlayers\');\n' +
             '        exports.angularOpenlayersDirective = factory(ol);\n' +
             '    } else if (typeof define === \'function\' && define.amd) {\n' +
             '        // AMD.\n' +
             '        define([\'ol\'], function (ol) {\n' +
             '            return root.angularOpenlayersDirective = factory(ol);\n' +
             '        });\n' +
             '    } else {\n' +
             '        // Browser globals\n' +
             '        root.angularOpenlayersDirective = factory(root.ol);\n' +
             '    }\n' +
             '}(this, function (ol) {\n';

module.exports = function (grunt, options) {
    return {
        dist: {
            options: {
                banner: banner,
                footer: '\n}));'
            },
            src: [
                'src/directives/openlayers.js',
                'src/directives/center.js',
                'src/directives/layer.js',
                'src/directives/events.js',
                'src/directives/path.js',
                'src/directives/view.js',
                'src/directives/control.js',
                'src/directives/marker.js',
                'src/services/olData.js',
                'src/services/olHelpers.js',
                'src/services/olMapDefaults.js'
            ],
            dest: 'dist/angular-openlayers-directive.pre.js',
        },
        css: {
            src: [
                'css/markers.css',
                'css/openlayers.css'
            ],
            dest: 'dist/angular-openlayers-directive.css'
        },
        license: {
            src: [
                'src/header-MIT-license.txt',
                'dist/angular-openlayers-directive.min.no-header.js'
            ],
            dest: 'dist/angular-openlayers-directive.min.js',
        },
    };
};
<commit_msg>enhanced commonjs compatibility<commit_after>'use strict';

var banner = '(function (root, factory) {\n' +
             '    if (typeof require === \'function\' && typeof exports === \'object\') {\n' +
             '        // CommonJS\n' +
             '        var ol = require(\'openlayers\');\n' +
             '        var ngSanitize = require(\'angular-sanitize\');\n' +
             '        exports.angularOpenlayersDirective = factory(ol).name;\n' +
             '    } else if (typeof define === \'function\' && define.amd) {\n' +
             '        // AMD.\n' +
             '        define([\'ol\'], function (ol) {\n' +
             '            return root.angularOpenlayersDirective = factory(ol);\n' +
             '        });\n' +
             '    } else {\n' +
             '        // Browser globals\n' +
             '        root.angularOpenlayersDirective = factory(root.ol);\n' +
             '    }\n' +
             '}(this, function (ol) {\n';
var footer = 'return angular.module(\'openlayers-directive\')' +
			 '\n}));

module.exports = function (grunt, options) {
    return {
        dist: {
            options: {
                banner: banner,
                footer: footer
            },
            src: [
                'src/directives/openlayers.js',
                'src/directives/center.js',
                'src/directives/layer.js',
                'src/directives/events.js',
                'src/directives/path.js',
                'src/directives/view.js',
                'src/directives/control.js',
                'src/directives/marker.js',
                'src/services/olData.js',
                'src/services/olHelpers.js',
                'src/services/olMapDefaults.js'
            ],
            dest: 'dist/angular-openlayers-directive.pre.js',
        },
        css: {
            src: [
                'css/markers.css',
                'css/openlayers.css'
            ],
            dest: 'dist/angular-openlayers-directive.css'
        },
        license: {
            src: [
                'src/header-MIT-license.txt',
                'dist/angular-openlayers-directive.min.no-header.js'
            ],
            dest: 'dist/angular-openlayers-directive.min.js',
        },
    };
};
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'tr',

  user: null,
  cabin: null,
  attributeBindings: ['user', 'cabin'],

  utUrl: Ember.computed('cabin.id', {
    get: function () {
      return ['//www.ut.no', 'hytte', this.get('cabin.id')].join('/');
    }
  }),

  userHasAccess: Ember.computed('user', 'cabin', {
    get: function () {
      let userHasAccess = false;
      let user = this.get('user');
      let object = this.get('cabin');

      if (!user) {
        return false;
      }

      if (user.get('er_admin') === true) {
        return true;
      }

      var userGroups = user.get('grupper') || [];
      var objectGroups = object.get('grupper') || [];

      if (user.get('gruppe.id')) {
        userGroups.addObject(user.get('gruppe.id'));
      }

      if (userGroups.get('length') === 0) {
        return false;
      }

      if (object.get('privat.juridisk_eier')) {
        objectGroups.addObject(object.get('privat.juridisk_eier'));
      }

      if (object.get('privat.vedlikeholdes_av')) {
        objectGroups.addObject(object.get('privat.vedlikeholdes_av'));
      }

      userHasAccess = userGroups.find(function (item, index, enumerable) {
        if (objectGroups.indexOf(item.get('id')) !== -1) {
          return true;
        }
      });

      return userHasAccess;
    }
  })
});
<commit_msg>Add computed property returning true if user is admin<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'tr',

  user: null,
  cabin: null,
  attributeBindings: ['user', 'cabin'],

  utUrl: Ember.computed('cabin.id', {
    get: function () {
      return ['//www.ut.no', 'hytte', this.get('cabin.id')].join('/');
    }
  }),

  userIsAdmin: Ember.computed('user.er_admin', {
    get: function () {
      return this.get('user.er_admin');
    }
  }),

  userHasAccess: Ember.computed('user', 'cabin', {
    get: function () {
      let userHasAccess = false;
      let user = this.get('user');
      let object = this.get('cabin');

      if (!user) {
        return false;
      }

      if (user.get('er_admin') === true) {
        return true;
      }

      var userGroups = user.get('grupper') || [];
      var objectGroups = object.get('grupper') || [];

      if (user.get('gruppe.id')) {
        userGroups.addObject(user.get('gruppe.id'));
      }

      if (userGroups.get('length') === 0) {
        return false;
      }

      if (object.get('privat.juridisk_eier')) {
        objectGroups.addObject(object.get('privat.juridisk_eier'));
      }

      if (object.get('privat.vedlikeholdes_av')) {
        objectGroups.addObject(object.get('privat.vedlikeholdes_av'));
      }

      userHasAccess = userGroups.find(function (item, index, enumerable) {
        if (objectGroups.indexOf(item.get('id')) !== -1) {
          return true;
        }
      });

      return userHasAccess;
    }
  })
});
<|endoftext|>