<commit_before>
var fs = require('fs');

var selectorNotFoundPath = 'capture/resources/selectorNotFound_noun_164558_cc.png'
var hiddenSelectorPath = 'capture/resources/hiddenSelector_noun_63405.png'
var genConfigPath = 'capture/config.json'

var configJSON = fs.read(genConfigPath);
var config = JSON.parse(configJSON);
if (!config.paths) {
  config.paths = {};
}

var bitmaps_reference = config.paths.bitmaps_reference || 'bitmaps_reference';
var bitmaps_test = config.paths.bitmaps_test || 'bitmaps_test';
var casper_scripts = config.paths.casper_scripts || null;
var compareConfigFileName = config.paths.compare_data || 'compare/config.json';
var viewports = config.viewports;
var scenarios = config.scenarios||config.grabConfigs;

var compareConfig = {testPairs:[]};

var casper = require("casper").create({
  // clientScripts: ["jquery.js"] // uncomment to add jQuery if you need that.
  // TODO: if (config.debug) { add prop debug true }
});

if (config.debug) {
  console.log('Debug is enabled!');

  casper.on("page.error", function(msg, trace) {
      this.echo("Remote Error >    " + msg, "error");
      this.echo("file:     " + trace[0].file, "WARNING");
      this.echo("line:     " + trace[0].line, "WARNING");
      this.echo("function: " + trace[0]["function"], "WARNING");
  });
}

casper.on('remote.message', function(message) {
  this.echo('remote console > ' + message);
});

casper.on('resource.received', function(resource) {
  var status = resource.status;
  if(status >= 400) {
    casper.log('remote error > ' + resource.url + ' failed to load (' + status + ')', 'error');
  }
});

function capturePageSelectors(url,scenarios,viewports,bitmaps_reference,bitmaps_test,isReference){

  var
    screenshotNow = new Date(),
    screenshotDateTime = screenshotNow.getFullYear() + pad(screenshotNow.getMonth() + 1) + pad(screenshotNow.getDate()) + '-' + pad(screenshotNow.getHours()) + pad(screenshotNow.getMinutes()) + pad(screenshotNow.getSeconds());

  var consoleBuffer = '';
  var scriptTimeout = 20000;

  casper.on('remote.message', function(message) {
      this.echo(message);
      consoleBuffer = consoleBuffer + '\n' + message;
  });

  casper.start();

  casper.each(scenarios,function(casper, scenario, scenario_index){

    casper.each(viewports, function(casper, vp, viewport_index) {
      this.then(function() {
        this.viewport(vp.width||vp.viewport.width, vp.height||vp.viewport.height);
      });

      var url = scenario.url;
      if (isReference && scenario.referenceUrl) {
        url = scenario.referenceUrl;
      }

      var onBeforeScript = scenario.onBeforeScript || config.onBeforeScript;
      if (onBeforeScript) {
        require(getScriptPath(onBeforeScript))(casper, scenario, vp);
      }

      this.thenOpen(url, function() {
        casper.waitFor(
          function(){ //test
            var readyEvent = scenario.readyEvent || config.readyEvent;
            if(!readyEvent) {
              return true;
            }
            var regExReadyFlag = new RegExp(readyEvent,'i');
            return consoleBuffer.search(regExReadyFlag) >= 0;
          }
          ,function(){//on done
            consoleBuffer = '';
            casper.echo('Ready event received.');
          }
          ,function(){casper.echo('ERROR: casper timeout.')} //on timeout
          ,scriptTimeout
        );
        casper.wait(scenario.delay||1);
      });

      casper.then(function() {
        this.echo('Current location is ' + url, 'info');

        if (config.debug) {
          var src = this.evaluate(function() {return document.body.outerHTML; });
          this.echo(src);
        }
      });

      // Custom casperjs scripting after ready event and delay
      casper.then(function() {
        // onReadyScript files should export a module like so:
        //
        // module.exports = function(casper, scenario, vp) {
        //   // run custom casperjs code
        // };
        //
        var onReadyScript = scenario.onReadyScript || config.onReadyScript;
        if (onReadyScript) {
          require(getScriptPath(onReadyScript))(casper, scenario, vp);
        }
      });

      this.then(function(){

        this.echo('Screenshots for ' + vp.name + ' (' + (vp.width||vp.viewport.width) + 'x' + (vp.height||vp.viewport.height) + ')', 'info');

        //HIDE SELECTORS WE WANT TO AVOID
            if ( scenario.hasOwnProperty('hideSelectors') ) {
              scenario.hideSelectors.forEach(function(o,i,a){
                casper.evaluate(function(o){
                  Array.prototype.forEach.call(document.querySelectorAll(o), function(s, j){
                    s.style.visibility='hidden';
                  });
                },o);
              });
            }

        //REMOVE UNWANTED SELECTORS FROM RENDER TREE
            if ( scenario.hasOwnProperty('removeSelectors') ) {
              scenario.removeSelectors.forEach(function(o,i,a){
                casper.evaluate(function(o){
                  Array.prototype.forEach.call(document.querySelectorAll(o), function(s, j){
                    s.style.display='none';
                  });
                },o);
              });
            }

        //CREATE SCREEN SHOTS AND TEST COMPARE CONFIGURATION (CONFIG FILE WILL BE SAVED WHEN THIS PROCESS RETURNS)
            // If no selectors are provided then set the default 'body'
            if ( !scenario.hasOwnProperty('selectors') ) {
              scenario.selectors = [ 'body' ];
            }
        scenario.selectors.forEach(function(o,i,a){
          var cleanedSelectorName = o.replace(/[^a-z0-9_\-]/gi,'');//remove anything that's not a letter or a number
          //var cleanedUrl = scenario.url.replace(/[^a-zA-Z\d]/,'');//remove anything that's not a letter or a number
          var fileName = scenario_index + '_' + i + '_' + cleanedSelectorName + '_' + viewport_index + '_' + vp.name + '.png';;

          var reference_FP  = bitmaps_reference + '/' + fileName;
          var test_FP       = bitmaps_test + '/' + screenshotDateTime + '/' + fileName;

          var filePath      = (isReference)?reference_FP:test_FP;

          if(o === "body:noclip" || o === "viewport") {
            casper.capture(filePath);
          } else if (casper.exists(o)) {
            if (casper.visible(o)) {
              casper.captureSelector(filePath, o);
            } else {
              var assetData = fs.read(hiddenSelectorPath, 'b');
              fs.write(filePath, assetData, 'b');
            }
          } else {
            var assetData = fs.read(selectorNotFoundPath, 'b');
            fs.write(filePath, assetData, 'b');
          }

          if (!isReference) {
            compareConfig.testPairs.push({
              reference:reference_FP,
              test:test_FP,
              selector:o,
              fileName:fileName,
              label:scenario.label,
              misMatchThreshold: scenario.misMatchThreshold || config.misMatchThreshold
            });
          }
          //casper.echo('remote capture to > '+filePath,'info');

        });//end topLevelModules.forEach

      });

    });//end casper.each viewports

  });//end casper.each scenario

}

//========================
//this query should be moved to the prior process
//`isReference` could be better passed as env parameter
var exists = fs.exists(bitmaps_reference);
var isReference = false;
if(!exists){isReference=true; console.log('CREATING NEW REFERENCE FILES')}
//========================

capturePageSelectors(
  'index.html'
  ,scenarios
  ,viewports
  ,bitmaps_reference
  ,bitmaps_test
  ,isReference
);

casper.run(function(){
  complete();
  this.exit();
});

function complete(){
  fs.touch(compareConfigFileName);
  var compareConfigFile = fs.read(compareConfigFileName);
  var compareConfigJSON = JSON.parse(compareConfigFile || '{}');
  compareConfigJSON.compareConfig = compareConfig;
  fs.write(compareConfigFileName, JSON.stringify(compareConfigJSON,null,2), 'w');
  console.log(
    'Comparison config file updated.'
    //,configData
  );
}

function pad(number) {
  var r = String(number);
  if ( r.length === 1 ) {
    r = '0' + r;
  }
  return r;
}

function getScriptPath(scriptFilePath) {
  var script_path = ensureFileSuffix(scriptFilePath, 'js');

  if (casper_scripts) {
    script_path = glueStringsWithSlash(casper_scripts, script_path);
  }

  // make sure it's there...
  if (!fs.isFile(script_path)) {
    casper.echo(script_path + ' was not found.', 'ERROR');
    return;
  }

  return shimRelativePath(script_path);
}

function ensureFileSuffix(filename, suffix) {
  var re = new RegExp('\.' + suffix + '$', '');

  return filename.replace(re, '') + '.' + suffix;
}

// merge both strings while soft-enforcing a single slash between them
function glueStringsWithSlash(stringA, stringB) {
  return stringA.replace(/\/$/, '') + '/' + stringB.replace(/^\//, '');
}

// require() calls are relative to this file `genBitmaps.js` (not CWD) -- therefore relative paths need shimmimg
function shimRelativePath(path) {
  return path.replace(/^\.\.\//, '../../../').replace(/^\.\//, '../../');
}
<commit_msg>added better magic selector name<commit_after>
var fs = require('fs');

var selectorNotFoundPath = 'capture/resources/selectorNotFound_noun_164558_cc.png'
var hiddenSelectorPath = 'capture/resources/hiddenSelector_noun_63405.png'
var genConfigPath = 'capture/config.json'

var configJSON = fs.read(genConfigPath);
var config = JSON.parse(configJSON);
if (!config.paths) {
  config.paths = {};
}

var bitmaps_reference = config.paths.bitmaps_reference || 'bitmaps_reference';
var bitmaps_test = config.paths.bitmaps_test || 'bitmaps_test';
var casper_scripts = config.paths.casper_scripts || null;
var compareConfigFileName = config.paths.compare_data || 'compare/config.json';
var viewports = config.viewports;
var scenarios = config.scenarios||config.grabConfigs;

var compareConfig = {testPairs:[]};

var casper = require("casper").create({
  // clientScripts: ["jquery.js"] // uncomment to add jQuery if you need that.
  // TODO: if (config.debug) { add prop debug true }
});

if (config.debug) {
  console.log('Debug is enabled!');

  casper.on("page.error", function(msg, trace) {
      this.echo("Remote Error >    " + msg, "error");
      this.echo("file:     " + trace[0].file, "WARNING");
      this.echo("line:     " + trace[0].line, "WARNING");
      this.echo("function: " + trace[0]["function"], "WARNING");
  });
}

casper.on('remote.message', function(message) {
  this.echo('remote console > ' + message);
});

casper.on('resource.received', function(resource) {
  var status = resource.status;
  if(status >= 400) {
    casper.log('remote error > ' + resource.url + ' failed to load (' + status + ')', 'error');
  }
});

function capturePageSelectors(url,scenarios,viewports,bitmaps_reference,bitmaps_test,isReference){

  var
    screenshotNow = new Date(),
    screenshotDateTime = screenshotNow.getFullYear() + pad(screenshotNow.getMonth() + 1) + pad(screenshotNow.getDate()) + '-' + pad(screenshotNow.getHours()) + pad(screenshotNow.getMinutes()) + pad(screenshotNow.getSeconds());

  var consoleBuffer = '';
  var scriptTimeout = 20000;

  casper.on('remote.message', function(message) {
      this.echo(message);
      consoleBuffer = consoleBuffer + '\n' + message;
  });

  casper.start();

  casper.each(scenarios,function(casper, scenario, scenario_index){

    casper.each(viewports, function(casper, vp, viewport_index) {
      this.then(function() {
        this.viewport(vp.width||vp.viewport.width, vp.height||vp.viewport.height);
      });

      var url = scenario.url;
      if (isReference && scenario.referenceUrl) {
        url = scenario.referenceUrl;
      }

      var onBeforeScript = scenario.onBeforeScript || config.onBeforeScript;
      if (onBeforeScript) {
        require(getScriptPath(onBeforeScript))(casper, scenario, vp);
      }

      this.thenOpen(url, function() {
        casper.waitFor(
          function(){ //test
            var readyEvent = scenario.readyEvent || config.readyEvent;
            if(!readyEvent) {
              return true;
            }
            var regExReadyFlag = new RegExp(readyEvent,'i');
            return consoleBuffer.search(regExReadyFlag) >= 0;
          }
          ,function(){//on done
            consoleBuffer = '';
            casper.echo('Ready event received.');
          }
          ,function(){casper.echo('ERROR: casper timeout.')} //on timeout
          ,scriptTimeout
        );
        casper.wait(scenario.delay||1);
      });

      casper.then(function() {
        this.echo('Current location is ' + url, 'info');

        if (config.debug) {
          var src = this.evaluate(function() {return document.body.outerHTML; });
          this.echo(src);
        }
      });

      // Custom casperjs scripting after ready event and delay
      casper.then(function() {
        // onReadyScript files should export a module like so:
        //
        // module.exports = function(casper, scenario, vp) {
        //   // run custom casperjs code
        // };
        //
        var onReadyScript = scenario.onReadyScript || config.onReadyScript;
        if (onReadyScript) {
          require(getScriptPath(onReadyScript))(casper, scenario, vp);
        }
      });

      this.then(function(){

        this.echo('Screenshots for ' + vp.name + ' (' + (vp.width||vp.viewport.width) + 'x' + (vp.height||vp.viewport.height) + ')', 'info');

        //HIDE SELECTORS WE WANT TO AVOID
            if ( scenario.hasOwnProperty('hideSelectors') ) {
              scenario.hideSelectors.forEach(function(o,i,a){
                casper.evaluate(function(o){
                  Array.prototype.forEach.call(document.querySelectorAll(o), function(s, j){
                    s.style.visibility='hidden';
                  });
                },o);
              });
            }

        //REMOVE UNWANTED SELECTORS FROM RENDER TREE
            if ( scenario.hasOwnProperty('removeSelectors') ) {
              scenario.removeSelectors.forEach(function(o,i,a){
                casper.evaluate(function(o){
                  Array.prototype.forEach.call(document.querySelectorAll(o), function(s, j){
                    s.style.display='none';
                  });
                },o);
              });
            }

        //CREATE SCREEN SHOTS AND TEST COMPARE CONFIGURATION (CONFIG FILE WILL BE SAVED WHEN THIS PROCESS RETURNS)
            // If no selectors are provided then set the default 'body'
            if ( !scenario.hasOwnProperty('selectors') ) {
              scenario.selectors = [ 'body' ];
            }
        scenario.selectors.forEach(function(o,i,a){
          var cleanedSelectorName = o.replace(/[^a-z0-9_\-]/gi,'');//remove anything that's not a letter or a number
          //var cleanedUrl = scenario.url.replace(/[^a-zA-Z\d]/,'');//remove anything that's not a letter or a number
          var fileName = scenario_index + '_' + i + '_' + cleanedSelectorName + '_' + viewport_index + '_' + vp.name + '.png';;

          var reference_FP  = bitmaps_reference + '/' + fileName;
          var test_FP       = bitmaps_test + '/' + screenshotDateTime + '/' + fileName;

          var filePath      = (isReference)?reference_FP:test_FP;

          if(o === "body:noclip" || o === "document") {
            casper.capture(filePath);
          } else if (casper.exists(o)) {
            if (casper.visible(o)) {
              casper.captureSelector(filePath, o);
            } else {
              var assetData = fs.read(hiddenSelectorPath, 'b');
              fs.write(filePath, assetData, 'b');
            }
          } else {
            var assetData = fs.read(selectorNotFoundPath, 'b');
            fs.write(filePath, assetData, 'b');
          }

          if (!isReference) {
            compareConfig.testPairs.push({
              reference:reference_FP,
              test:test_FP,
              selector:o,
              fileName:fileName,
              label:scenario.label,
              misMatchThreshold: scenario.misMatchThreshold || config.misMatchThreshold
            });
          }
          //casper.echo('remote capture to > '+filePath,'info');

        });//end topLevelModules.forEach

      });

    });//end casper.each viewports

  });//end casper.each scenario

}

//========================
//this query should be moved to the prior process
//`isReference` could be better passed as env parameter
var exists = fs.exists(bitmaps_reference);
var isReference = false;
if(!exists){isReference=true; console.log('CREATING NEW REFERENCE FILES')}
//========================

capturePageSelectors(
  'index.html'
  ,scenarios
  ,viewports
  ,bitmaps_reference
  ,bitmaps_test
  ,isReference
);

casper.run(function(){
  complete();
  this.exit();
});

function complete(){
  fs.touch(compareConfigFileName);
  var compareConfigFile = fs.read(compareConfigFileName);
  var compareConfigJSON = JSON.parse(compareConfigFile || '{}');
  compareConfigJSON.compareConfig = compareConfig;
  fs.write(compareConfigFileName, JSON.stringify(compareConfigJSON,null,2), 'w');
  console.log(
    'Comparison config file updated.'
    //,configData
  );
}

function pad(number) {
  var r = String(number);
  if ( r.length === 1 ) {
    r = '0' + r;
  }
  return r;
}

function getScriptPath(scriptFilePath) {
  var script_path = ensureFileSuffix(scriptFilePath, 'js');

  if (casper_scripts) {
    script_path = glueStringsWithSlash(casper_scripts, script_path);
  }

  // make sure it's there...
  if (!fs.isFile(script_path)) {
    casper.echo(script_path + ' was not found.', 'ERROR');
    return;
  }

  return shimRelativePath(script_path);
}

function ensureFileSuffix(filename, suffix) {
  var re = new RegExp('\.' + suffix + '$', '');

  return filename.replace(re, '') + '.' + suffix;
}

// merge both strings while soft-enforcing a single slash between them
function glueStringsWithSlash(stringA, stringB) {
  return stringA.replace(/\/$/, '') + '/' + stringB.replace(/^\//, '');
}

// require() calls are relative to this file `genBitmaps.js` (not CWD) -- therefore relative paths need shimmimg
function shimRelativePath(path) {
  return path.replace(/^\.\.\//, '../../../').replace(/^\.\//, '../../');
}
<|endoftext|>


<commit_before>var SearchManager = function(manager) {
    var self = this;
    this.offset = 0;
    this.audioManager = manager;
    this.topTracksVk = [];
    this.searchTracks = [];
    this.searching = false;
    this.$infoLoadingSpinner = $('#info-header-spinner');
    this.$vkMusicLoadingSpinner = $('#vkMusic-header-spinner');

    this._uploadNewSongs = function () {
        if ($('.btn-primary.searchBtn').text() == 'Vkontakte' && this.mcs.topPct >= 75 && !self.searching) {
            self.searching = true;
            var searchParam = $('#search').val().toLocaleLowerCase();
            self.offset += 20;
            $.ajax({
                url: 'api/search/vkontakte?searchText=' + searchParam + "&offset=" + self.offset,
                type: 'GET',
                dataType: 'json',
                success: function (tracks) {
                    self.searchTracks = $.merge(self.searchTracks, tracks);
                    self._showTracks(self.searchTracks, $('#searchTrackTemplate'));
                    self.audioManager.updateProgressbar('.vkMusicList');
                    self.searching = false;
                }
            });
        }
    };

    this._updatePlaylists = function() {
        $.ajax({
            url: 'api/playlists/',
            type: 'GET',
            dataType: 'json',
            success: function (playlists) {
                $('#playlistsTable').empty();
                $(playlists).each(function () {
                    $('#playlistsTable').append('

' + this.Name + '

' + this.Id + '

');
                });
            }
        });
    };

    this._search = function() {
        var searchParam = $('#search').val().toLocaleLowerCase();
        $('.vkMusicList').find('.track').remove();
        $('#users').find('.user').remove();
        if (searchParam != '') {
            self.$vkMusicLoadingSpinner.show();
            if ($('.searchBtn.btn-primary').text() == 'User') {
                $.ajax({
                    url: 'api/search/users?searchText=' + searchParam,
                    type: 'GET',
                    dataType: 'json',
                    success: function (users) {
                        self._showUsers(users, $('#searchUserTemplate'));
                    }
                });
            } else {
                $.ajax({
                    url: 'api/usertracks/globalsearch?searchText=' + searchParam + "&criteria=" + $('.btn-primary').data('search').toLocaleLowerCase(),
                    type: 'GET',
                    dataType: 'json',
                    success: function(tracks) {
                        self.searchTracks = tracks;
                        self._showTracks(self.searchTracks, $('#searchTrackTemplate'));
                    }
                });
            }
        }
    };

    this._showUsers = function(users, template) {
        var correctedUsers = $.extend(true, [], users);

        for (var i = 0; i < correctedUsers.length; i++) {
            if (typeof(correctedUsers[i].Name) != 'undefined') {
                var tmpl = template.tmpl(correctedUsers[i]);
                tmpl.appendTo('#users');
            }
        }

        self.$vkMusicLoadingSpinner.hide();
    }

    this._showTracks = function (tracks, template) {
        var correctedTracks = $.extend(true, [], tracks);
        for (var i = 0; i < tracks.length; i++) {
            correctedTracks[i].Duration = self._toFormattedTime(correctedTracks[i].Duration, true);
        }
        $('.vkMusicList').find('.track').detach();
        for (var i = 0; i < correctedTracks.length; i++) {
            var tmpl = template.tmpl(correctedTracks[i]);
            tmpl.appendTo('.vkMusicList');
            if (self.audioManager.$currentTrack !== null
                && self.audioManager.$currentTrack.children('.trackId').html() == correctedTracks[i].id) {
                tmpl.toggleClass('.draggable-item-selected');
                //self.audioManager.$currentTrack = tmpl; !!!!!
                //tmpl.append(self.audioManager.progressSlider.getSlider());
                if (self.audioManager.audio.paused) {
                    self.audioManager._setPlayImgButton(tmpl);
                    self.audioManager.$currentTrack.find('.track-duration').show();
                    self.audioManager.$currentTrack.find('.track-remaining').hide();
                } else {
                    self.audioManager._setPauseImgButton(tmpl);
                    self.audioManager.$currentTrack.find('.track-duration').hide();
                    self.audioManager.$currentTrack.find('.track-remaining').show();
                }
            }
        }

        self.audioManager.refreshTracks();
        self.audioManager.bindPlayBtnListeners();
        $('.vkMusicList > .tableRow > .track-info-btn').click(self._getTrackInfo);
        $('.vkMusicTable').mCustomScrollbar({
            theme: 'dark-3',
            scrollButtons: { enable: true },
            updateOnContentResize: true,
            scrollInertia: 0,
            autoHideScrollbar: true,
            advanced: { updateOnSelectorChange: "true" },
            callbacks: { whileScrolling: self._uploadNewSongs }
        });
        self._createContextMenu();
        self.$vkMusicLoadingSpinner.hide();
    };

    this._getTrackInfo = function () {
        var $self = $(this);
        var author = $self.parent().children('.track-description').children('.track-info');
        var trackName = $self.parent().children('.track-description').children('.track-title');
        self.$infoLoadingSpinner.show();
        $.ajax({
            url: '/api/usertracks/trackinfo?artist=' + author.html() + '&trackName=' + trackName.html(),
            async: true,
            success: function(trackInfo) {
                self.$infoLoadingSpinner.hide();
                var $trackInfoTemplate = $('#trackInfoTemplate');
                var object = $trackInfoTemplate.tmpl(trackInfo);
                var $trackInfoContainer = $('#infoModal .modal-body');
                $trackInfoContainer.text('');
                object.appendTo($trackInfoContainer);
                if (trackInfo.Lyric != null) {
                    for (var i = 0; i < trackInfo.Lyric.length; i++) {
                        var $p = $('
');
                        $p.text(trackInfo.Lyric[i]);
                        $trackInfoContainer.find('.trackLyric').append($p);
                    }
                }
                if (trackInfo.Summary != null) {
                    $trackInfoContainer.find('.trackSummary').append(trackInfo.Summary);
                }
                self.topTracks = trackInfo.ArtistTopTrackList;
                $('#listenTopBtn').attr('disabled', false);
            }
        });
    };

    this._toFormattedTime = function (input, roundSeconds) {
        if (roundSeconds) {
            input = Math.ceil(input);
        }

        var withHours = false;

        if (input >= 60 * 60) {
            withHours = true;
        }

        var hoursString = '00';
        var minutesString = '00';
        var secondsString = '00';
        var hours = 0;
        var minutes = 0;
        var seconds = 0;

        hours = Math.floor(input / (60 * 60));
        input = input % (60 * 60);

        minutes = Math.floor(input / 60);
        input = input % 60;

        seconds = input;

        hoursString = (hours >= 10) ? hours.toString() : '0' + hours.toString();
        minutesString = (minutes >= 10) ? minutes.toString() : '0' + minutes.toString();
        secondsString = (seconds >= 10) ? seconds.toString() : '0' + seconds.toString();

        return ((withHours) ? hoursString + ':' : '') + minutesString + ':' + secondsString;
    };

    this._delay = (function () {
        var timer = 0;
        return function (callback, ms) {
            clearTimeout(timer);
            timer = setTimeout(callback, ms);
        }
    })();

    this._createContextMenu = function() {
        var ctxMenu = new ContextMenu();
        var contextMenuActions = [
            { id: 'savevktrack', name: 'Move to', isNewSection: true, hasSubMenu: true, needSelectedItems: false },
            { id: 'createplaylist', name: 'Create new playlist', isNewSection: false, hasSubMenu: false, needSelectedItems: false },
        ];

        ctxMenu.initializeContextMenu(-1, contextMenuActions, this, self);

        //$('.track').off('mousedown').mousedown(function (event) {
        //    if (event.which == 3) {
        //        $('.track.draggable-item-selected').toggleClass('draggable-item-selected', false);
        //        var $target = $(event.target).parents('.track');
        //        $target.toggleClass('draggable-item-selected', true);
        //        ctxMenu.drawContextMenu(event);
        //    }
        //});

        $(document).off('mousedown', '.track').on('mousedown', '.track', function (event) {
            var $target = $(event.target).parents('.track');
            if (event.which == 3) {
                //$('.track.draggable-item-selected').toggleClass('draggable-item-selected', false);
                $target.toggleClass('draggable-item-selected', true);
                ctxMenu.drawContextMenu(event);
            } else if (event.which == 1) {
                var $currentItem = $target;
                if (event.ctrlKey) {
                    if ($currentItem.hasClass('draggable-item-selected')) {
                        $currentItem.toggleClass('draggable-item-selected', false);
                    } else {
                        $currentItem.toggleClass('draggable-item-selected', true);
                    }
                } else if (event.shiftKey) {
                    var indexFirst = -1;
                    var indexLast = -1;
                    if ($('.draggable-item-selected').last().index() < $currentItem.index()) {
                        indexFirst = $('.draggable-item-selected').last().index();
                        indexLast = $currentItem.index();
                    } else {
                        indexFirst = $currentItem.index();
                        indexLast = $('.draggable-item-selected').last().index();
                    }

                    var currentChildren = $currentItem.parent().children();

                    for (var i = indexFirst; i <= indexLast; i++) {
                        var $currentChild = $(currentChildren[i]);
                        if (!$currentChild.hasClass('draggable-item-selected')) {
                            $currentChild.toggleClass('draggable-item-selected', true);
                        }
                    }
                } else {
                    $('.draggable-item-selected').toggleClass('draggable-item-selected', false);
                    $currentItem.toggleClass('draggable-item-selected', true);
                }
            }
        });

        ctxMenu.$contextMenuContainer.mousedown(function (event) {
            ctxMenu.$contextMenuContainer.hide();
            ctxMenu.selectAction($('.track.selected'));
        });
    };

    this._saveTrackFromVkToPlaylist = function ($currentItem, index, playlistId) {
        var tracks = [];

        var currentPlaylist = $('.playlist .playlistId:contains(' + playlistId + ')').parent('.playlist');
        if (currentPlaylist.find('.readonly').text() == 'true')
            return;
        $currentItem.children().toggleClass('vk-item', false);
        $currentItem.children('.tableRow').each(function () {
            tracks.push({
                ThirdPartId: $(this).closest('.tableRow').find('.thirdPartId').text(),
                OwnerId: $(this).closest('.tableRow').find('.ownerId').text()
            });
        }).get();
        $currentItem.empty();
        $.ajax({
            url: '/api/usertracks?provider=Vkontakte&index=' + index,
            type: 'POST',
            data: JSON.stringify({
                "PlaylistId": playlistId,
                "TrackInfos": tracks
            }),
            contentType: 'application/json'
        });
    };

    this._updatePlaylists();
    this._search();
};

SearchManager.prototype.bindListeners = function () {
    var self = this;

    //$(document).click(function(e) {
    //    var contextMenu = $('.contextMenu');
    //    if (contextMenu.length > 0) {
    //        contextMenu.detach();
    //    }
    //});

    $('#search').keyup(function () {
        self._delay(function () {
            self._search();
            self.audioManager.stop();
        }, 1000);
    });

    $('.searchBtn').click(function () {
        $('.searchBtn:not(.btn-default)').removeClass('btn-primary').addClass('btn-default');
        $(this).removeClass('btn-default').addClass('btn-primary');
        self._search();
        self.audioManager.stop();
    });

    $('#infoModal').on('hidden.bs.modal', function () {
        $('#infoModal .modal-body').text('');
        $('#listenTopBtn').attr('disabled', true);
    });

    $('#listenTopBtn').click(function () {
        $('.modal-body').text('');
        if (self.topTracks != null) {
            $('#vkMusic-header-title').text('');
            self.$vkMusicLoadingSpinner.show();
            $('.vkMusicList').find('.track').remove();

            if (self.topTracks != null) {
                var tracks = JSON.stringify({ trackdata: self.topTracks });
                $.ajax({
                    url: '/api/usertracks/tracksearch?provider=Vkontakte&infoForSearch=' + tracks,
                    type: 'POST',
                    dataType: 'json',
                    contentType: 'application/json;',
                    success: function (data) {
                        self.topTracksVk = [];
                        $(data).each(function () {
                            this.duration = self._toFormattedTime(this.duration, true);
                            if ((typeof (this.artist) != 'undefined') && (typeof (this.title) != 'undefined')) {
                                self.topTracksVk.push(this);
                            }
                        });
                        self._showTracks(self.topTracksVk, $('#trackTemplate'));
                        self.audioManager.bindPlayBtnListeners();
                        $('.vkMusicList > .tableRow > .track-info-btn').click(self._getTrackInfo);
                        self.$vkMusicLoadingSpinner.hide();
                    }
                });
            }
        }
    });

    $('#okPlaylistCreateModalBtn').click(function () {

        $('#createPlaylistModal').modal('hide');
        $('#createPlaylistModal').on('hidden.bs.modal', function () {
            $('#createPlaylistModal .modal-body #playlistNameToCreate').val("");
            $('#createPlaylistModal .modal-body select :first').attr("selected", "selected");
        });

        var playlistName = $('#playlistNameToCreate').val();
        var playlistAccessibility = $('#newPlaylistAccessibility option:selected').val();
        $.ajax({
            url: '/api/playlists?name=' + playlistName + '&accessibilty=' + playlistAccessibility,
            type: 'POST',
            contentType: 'application/json',
            async: false,
            success: function (playlistId) {
                self._saveTrackFromVkToPlaylist($('#itemsContainer'), -1, playlistId);
            }
        });
        self._updatePlaylists();
    });
};<commit_msg>Corrected getting trackinfo<commit_after>var SearchManager = function(manager) {
    var self = this;
    this.offset = 0;
    this.audioManager = manager;
    this.topTracksVk = [];
    this.searchTracks = [];
    this.searching = false;
    this.$infoLoadingSpinner = $('#info-header-spinner');
    this.$vkMusicLoadingSpinner = $('#vkMusic-header-spinner');

    this._uploadNewSongs = function () {
        if ($('.btn-primary.searchBtn').text() == 'Vkontakte' && this.mcs.topPct >= 75 && !self.searching) {
            self.searching = true;
            var searchParam = $('#search').val().toLocaleLowerCase();
            self.offset += 20;
            $.ajax({
                url: 'api/search/vkontakte?searchText=' + searchParam + "&offset=" + self.offset,
                type: 'GET',
                dataType: 'json',
                success: function (tracks) {
                    self.searchTracks = $.merge(self.searchTracks, tracks);
                    self._showTracks(self.searchTracks, $('#searchTrackTemplate'));
                    self.audioManager.updateProgressbar('.vkMusicList');
                    self.searching = false;
                }
            });
        }
    };

    this._updatePlaylists = function() {
        $.ajax({
            url: 'api/playlists/',
            type: 'GET',
            dataType: 'json',
            success: function (playlists) {
                $('#playlistsTable').empty();
                $(playlists).each(function () {
                    $('#playlistsTable').append('

' + this.Name + '

' + this.Id + '

');
                });
            }
        });
    };

    this._search = function() {
        var searchParam = $('#search').val().toLocaleLowerCase();
        $('.vkMusicList').find('.track').remove();
        $('#users').find('.user').remove();
        if (searchParam != '') {
            self.$vkMusicLoadingSpinner.show();
            if ($('.searchBtn.btn-primary').text() == 'User') {
                $.ajax({
                    url: 'api/search/users?searchText=' + searchParam,
                    type: 'GET',
                    dataType: 'json',
                    success: function (users) {
                        self._showUsers(users, $('#searchUserTemplate'));
                    }
                });
            } else {
                $.ajax({
                    url: 'api/usertracks/globalsearch?searchText=' + searchParam + "&criteria=" + $('.btn-primary').data('search').toLocaleLowerCase(),
                    type: 'GET',
                    dataType: 'json',
                    success: function(tracks) {
                        self.searchTracks = tracks;
                        self._showTracks(self.searchTracks, $('#searchTrackTemplate'));
                    }
                });
            }
        }
    };

    this._showUsers = function(users, template) {
        var correctedUsers = $.extend(true, [], users);

        for (var i = 0; i < correctedUsers.length; i++) {
            if (typeof(correctedUsers[i].Name) != 'undefined') {
                var tmpl = template.tmpl(correctedUsers[i]);
                tmpl.appendTo('#users');
            }
        }

        self.$vkMusicLoadingSpinner.hide();
    }

    this._showTracks = function (tracks, template) {
        var correctedTracks = $.extend(true, [], tracks);
        for (var i = 0; i < tracks.length; i++) {
            correctedTracks[i].Duration = self._toFormattedTime(correctedTracks[i].Duration, true);
        }
        $('.vkMusicList').find('.track').detach();
        for (var i = 0; i < correctedTracks.length; i++) {
            var tmpl = template.tmpl(correctedTracks[i]);
            tmpl.appendTo('.vkMusicList');
            if (self.audioManager.$currentTrack !== null
                && self.audioManager.$currentTrack.children('.trackId').html() == correctedTracks[i].id) {
                tmpl.toggleClass('.draggable-item-selected');
                //self.audioManager.$currentTrack = tmpl; !!!!!
                //tmpl.append(self.audioManager.progressSlider.getSlider());
                if (self.audioManager.audio.paused) {
                    self.audioManager._setPlayImgButton(tmpl);
                    self.audioManager.$currentTrack.find('.track-duration').show();
                    self.audioManager.$currentTrack.find('.track-remaining').hide();
                } else {
                    self.audioManager._setPauseImgButton(tmpl);
                    self.audioManager.$currentTrack.find('.track-duration').hide();
                    self.audioManager.$currentTrack.find('.track-remaining').show();
                }
            }
        }

        self.audioManager.refreshTracks();
        self.audioManager.bindPlayBtnListeners();
        $('.track-info > a').click(self._getTrackInfo);
        $('.vkMusicTable').mCustomScrollbar({
            theme: 'dark-3',
            scrollButtons: { enable: true },
            updateOnContentResize: true,
            scrollInertia: 0,
            autoHideScrollbar: true,
            advanced: { updateOnSelectorChange: "true" },
            callbacks: { whileScrolling: self._uploadNewSongs }
        });
        self._createContextMenu();
        self.$vkMusicLoadingSpinner.hide();
    };

    this._getTrackInfo = function () {
        var $self = $(this);
        var author = $self.children('.track-artist').html();
        var trackName = $self.children('.track-title').html();
        self.$infoLoadingSpinner.show();
        $.ajax({
            url: '/api/usertracks/trackinfo?artist=' + author + '&trackName=' + trackName,
            async: true,
            success: function(trackInfo) {
                self.$infoLoadingSpinner.hide();
                var $trackInfoTemplate = $('#trackInfoTemplate');
                var object = $trackInfoTemplate.tmpl(trackInfo);
                var $trackInfoContainer = $('#infoModal .modal-body');
                $trackInfoContainer.text('');
                object.appendTo($trackInfoContainer);
                if (trackInfo.Lyric != null) {
                    for (var i = 0; i < trackInfo.Lyric.length; i++) {
                        var $p = $('
');
                        $p.text(trackInfo.Lyric[i]);
                        $trackInfoContainer.find('.trackLyric').append($p);
                    }
                }
                if (trackInfo.Summary != null) {
                    $trackInfoContainer.find('.trackSummary').append(trackInfo.Summary);
                }
                self.topTracks = trackInfo.ArtistTopTrackList;
                $('#listenTopBtn').attr('disabled', false);
            }
        });
    };

    this._toFormattedTime = function (input, roundSeconds) {
        if (roundSeconds) {
            input = Math.ceil(input);
        }

        var withHours = false;

        if (input >= 60 * 60) {
            withHours = true;
        }

        var hoursString = '00';
        var minutesString = '00';
        var secondsString = '00';
        var hours = 0;
        var minutes = 0;
        var seconds = 0;

        hours = Math.floor(input / (60 * 60));
        input = input % (60 * 60);

        minutes = Math.floor(input / 60);
        input = input % 60;

        seconds = input;

        hoursString = (hours >= 10) ? hours.toString() : '0' + hours.toString();
        minutesString = (minutes >= 10) ? minutes.toString() : '0' + minutes.toString();
        secondsString = (seconds >= 10) ? seconds.toString() : '0' + seconds.toString();

        return ((withHours) ? hoursString + ':' : '') + minutesString + ':' + secondsString;
    };

    this._delay = (function () {
        var timer = 0;
        return function (callback, ms) {
            clearTimeout(timer);
            timer = setTimeout(callback, ms);
        }
    })();

    this._createContextMenu = function() {
        var ctxMenu = new ContextMenu();
        var contextMenuActions = [
            { id: 'savevktrack', name: 'Move to', isNewSection: true, hasSubMenu: true, needSelectedItems: false },
            { id: 'createplaylist', name: 'Create new playlist', isNewSection: false, hasSubMenu: false, needSelectedItems: false },
        ];

        ctxMenu.initializeContextMenu(-1, contextMenuActions, this, self);

        //$('.track').off('mousedown').mousedown(function (event) {
        //    if (event.which == 3) {
        //        $('.track.draggable-item-selected').toggleClass('draggable-item-selected', false);
        //        var $target = $(event.target).parents('.track');
        //        $target.toggleClass('draggable-item-selected', true);
        //        ctxMenu.drawContextMenu(event);
        //    }
        //});

        $(document).off('mousedown', '.track').on('mousedown', '.track', function (event) {
            var $target = $(event.target).parents('.track');
            if (event.which == 3) {
                //$('.track.draggable-item-selected').toggleClass('draggable-item-selected', false);
                $target.toggleClass('draggable-item-selected', true);
                ctxMenu.drawContextMenu(event);
            } else if (event.which == 1) {
                var $currentItem = $target;
                if (event.ctrlKey) {
                    if ($currentItem.hasClass('draggable-item-selected')) {
                        $currentItem.toggleClass('draggable-item-selected', false);
                    } else {
                        $currentItem.toggleClass('draggable-item-selected', true);
                    }
                } else if (event.shiftKey) {
                    var indexFirst = -1;
                    var indexLast = -1;
                    if ($('.draggable-item-selected').last().index() < $currentItem.index()) {
                        indexFirst = $('.draggable-item-selected').last().index();
                        indexLast = $currentItem.index();
                    } else {
                        indexFirst = $currentItem.index();
                        indexLast = $('.draggable-item-selected').last().index();
                    }

                    var currentChildren = $currentItem.parent().children();

                    for (var i = indexFirst; i <= indexLast; i++) {
                        var $currentChild = $(currentChildren[i]);
                        if (!$currentChild.hasClass('draggable-item-selected')) {
                            $currentChild.toggleClass('draggable-item-selected', true);
                        }
                    }
                } else {
                    $('.draggable-item-selected').toggleClass('draggable-item-selected', false);
                    $currentItem.toggleClass('draggable-item-selected', true);
                }
            }
        });

        ctxMenu.$contextMenuContainer.mousedown(function (event) {
            ctxMenu.$contextMenuContainer.hide();
            ctxMenu.selectAction($('.track.selected'));
        });
    };

    this._saveTrackFromVkToPlaylist = function ($currentItem, index, playlistId) {
        var tracks = [];

        var currentPlaylist = $('.playlist .playlistId:contains(' + playlistId + ')').parent('.playlist');
        if (currentPlaylist.find('.readonly').text() == 'true')
            return;
        $currentItem.children().toggleClass('vk-item', false);
        $currentItem.children('.tableRow').each(function () {
            tracks.push({
                ThirdPartId: $(this).closest('.tableRow').find('.thirdPartId').text(),
                OwnerId: $(this).closest('.tableRow').find('.ownerId').text()
            });
        }).get();
        $currentItem.empty();
        $.ajax({
            url: '/api/usertracks?provider=Vkontakte&index=' + index,
            type: 'POST',
            data: JSON.stringify({
                "PlaylistId": playlistId,
                "TrackInfos": tracks
            }),
            contentType: 'application/json'
        });
    };

    this._updatePlaylists();
    this._search();
};

SearchManager.prototype.bindListeners = function () {
    var self = this;

    $(document).click(function(e) {
        var contextMenu = $('.contextMenu');
        if (contextMenu.length > 0) {
            contextMenu.detach();
        }
    });

    $('#search').keyup(function () {
        self._delay(function () {
            self._search();
            self.audioManager.stop();
        }, 1000);
    });

    $('.searchBtn').click(function () {
        $('.searchBtn:not(.btn-default)').removeClass('btn-primary').addClass('btn-default');
        $(this).removeClass('btn-default').addClass('btn-primary');
        self._search();
        self.audioManager.stop();
    });

    $('#infoModal').on('hidden.bs.modal', function () {
        $('#infoModal .modal-body').text('');
        $('#listenTopBtn').attr('disabled', true);
    });

    $('#listenTopBtn').click(function () {
        $('.modal-body').text('');
        if (self.topTracks != null) {
            $('#vkMusic-header-title').text('');
            self.$vkMusicLoadingSpinner.show();
            $('.vkMusicList').find('.track').remove();

            if (self.topTracks != null) {
                var tracks = JSON.stringify({ trackdata: self.topTracks });
                $.ajax({
                    url: '/api/usertracks/tracksearch?provider=Vkontakte&infoForSearch=' + tracks,
                    type: 'POST',
                    dataType: 'json',
                    contentType: 'application/json;',
                    success: function (data) {
                        self.topTracksVk = [];
                        $(data).each(function () {
                            this.duration = self._toFormattedTime(this.duration, true);
                            if ((typeof (this.artist) != 'undefined') && (typeof (this.title) != 'undefined')) {
                                self.topTracksVk.push(this);
                            }
                        });
                        self._showTracks(self.topTracksVk, $('#trackTemplate'));
                        self.audioManager.bindPlayBtnListeners();
                        $('.track-info > a').click(self._getTrackInfo);
                        self.$vkMusicLoadingSpinner.hide();
                    }
                });
            }
        }
    });

    $('#okPlaylistCreateModalBtn').click(function () {

        $('#createPlaylistModal').modal('hide');
        $('#createPlaylistModal').on('hidden.bs.modal', function () {
            $('#createPlaylistModal .modal-body #playlistNameToCreate').val("");
            $('#createPlaylistModal .modal-body select :first').attr("selected", "selected");
        });

        var playlistName = $('#playlistNameToCreate').val();
        var playlistAccessibility = $('#newPlaylistAccessibility option:selected').val();
        $.ajax({
            url: '/api/playlists?name=' + playlistName + '&accessibilty=' + playlistAccessibility,
            type: 'POST',
            contentType: 'application/json',
            async: false,
            success: function (playlistId) {
                self._saveTrackFromVkToPlaylist($('#itemsContainer'), -1, playlistId);
            }
        });
        self._updatePlaylists();
    });
};<|endoftext|>


<commit_before>'use strict';

var url = require('url')
  , async = require('async')
  , request = require('request')
  , schedule = require('node-schedule');

//
// Time interval for the probe and interval cutoffs in milliseconds.
//
var day = 864E5
  , interval = 6E5
  , intervals = {
      none: 0,
      minute: interval / 10,
      hour: day / 24,
      "day⁺": day
    };

//
// Probe constructor.
//
var Probe = require('./probe')('delta', {
  minute: new schedule.Range(0, 60, intervals.minute * 10)
});

//
// Set of functions to check the equality of a and b for set of keys.
//
Probe.readable('equal', {
  'name': function name(a, b) {
    return a && b && a === b;
  },

  'time': function time(a, b) {
    if (!a || !b) return false;
    var mod = a.modified === b.modified;

    a = Array.isArray(a) ? a : Object.keys(a);
    b = Array.isArray(a) ? a : Object.keys(a);

    return mod && a.length === b.length && a.reduce(function has(memo, item) {
      return memo && ~b.indexOf(item);
    }, true);
  },

  //
  // Unpublished modules will have no versions, modified time should be equal.
  //
  'versions': function versions(a, b) {
    if (!a || !b) return false;

    a = Array.isArray(a) ? a : Object.keys(a);
    b = Array.isArray(a) ? a : Object.keys(a);

    return a.length === b.length && a.reduce(function has(memo, item) {
      return memo && ~b.indexOf(item);
    }, true);
  }
});

/**
 * Combine the results to a meaningful object.
 *
 * @param {Boolean} different Are origin and variation equal or not.
 * @param {Object} origin Module document from original feed.
 * @param {Object} variation Module document from target registry.
 * @return {Object} Module name and its absolute lag in msec
 * @api private
 */
Probe.readable('lag', function lag(different, origin, variation) {
  var now = 0
    , main = 0;

  //
  // If the document for the target npm mirror is missing, registry has lag equal
  // to module creation. Otherwise calculate the difference between modified.
  //
  if (different) {
    now = Date.now();
    main = new Date('unpublished' in origin.time
      ? origin.time.unpublished.time
      : origin.time.modified
    ).getTime();
  }

  //
  // Return absolute lag in msec.
  //
  return {
    missing: !variation,
    module: origin.name,
    lag: Math.abs(now - main)
  };
});

/**
 * Get the difference between both objects for listed `this.equal` functions.
 * If the variation is missing or null then return immediatly.
 *
 * @param {Object} origin Module document from original feed.
 * @param {Object} variation Module document from target registry.
 * @api private
 */
Probe.readable('diff', function diff(origin, variation) {
  var keys = [];

  try {
    if (!variation) throw new Error('No variation doc found');
    variation = JSON.parse(variation);
  } catch (e) {
    return this.lag(true, origin);
  }

  for (var check in this.equal) {
    if (!this.equal[check](origin[check], variation[check])) keys.push(check);
  }

  return this.lag(keys.length, origin, variation);
});

/**
 * Check for error responses in the body. This is required since not all 404's or
 * errors can be blindly treated as a missing document.
 *
 * @param {String} body Content to be checked.
 * @return {Boolean} body has error
 */
Probe.readable('error', function error(body) {
  return ~body.indexOf('"error":"not_found"')
      || ~body.indexOf('"error":"illegal_database_name"');
});

/**
 * Check the last changes feed against each mirror registry.
 *
 * @param {Object} endpoint url parsed endpoint
 * @param {Function} done completion callback.
 * @api public
 */
Probe.readable('execute', function execute(endpoint, done) {
  var probe = this;

  async.map(probe.collector.feed, function get(module, next) {
    var target = url.format({
      protocol: endpoint.protocol,
      pathname: endpoint.pathname + module.id,
      host: endpoint.host
    });

    //
    // Fetch documents, ignore errors by setting the body to an empty JSON
    // object representation, mapping should continue for other modules.
    // Deleted modules will respond with statusCode = 404, so ignore that as well.
    //
    request(target, function get(error, response, body) {
      if (error || (response.statusCode !== 200 && probe.error(body))) body = null;
      next(null, probe.diff(module.doc, body));
    });
  }, function calc(error, result) {
    if (error) return done(error);
    var filtered = []
      , lag = [];

    //
    // Store the names of the modules the are lagging.
    //
    result.forEach(function each(test) {
      if (test.lag > 0) filtered.push(test.module);
      lag.push(test.lag);
    });

    result = {
      lag: probe.collector.calculate(lag),
      n: probe.collector.feed.length,
      modules: filtered
    };

    probe.emit('delta::executed', result);
    done(null, result);
  });
});

/**
 * Seperate time units into intervals.
 *
 * @param {Array} memo Container to store results in.
 * @param {Object} probe Results from probe.
 * @return {Object} altered memo.
 * @api private
 */
Probe.transform = function transform(memo, probe, i, stack) {
  var position = Object.keys(intervals)
    , interval;

  //
  // Return duration as string for results.
  //
  position.forEach(function each(key, i) {
    if (!probe.results || !probe.results.lag) return;

    //
    // Provide all intervals on the same day with latest minute count.
    //
    memo[i].lag = Math.round(probe.results.lag.mean / intervals.hour);

    //
    // Current found interval is correct, stop processing before updating again.
    // Check if the interval is undefined as it can also be 0, e.g. no lag.
    //
    if ('undefined' !== typeof interval) return;
    if (probe.results.lag.mean <= intervals[key]) interval = i;
  });

  //
  // Update the occurence of the interval and add the modules for reference.
  //
  if ('undefined' === typeof interval) interval = position.length - 1;

  memo[interval].n++;
  return memo;
};

/**
 * Return custom content to be displayed as latest measurement.
 *
 * @param {Array} transformed Data transformed with transform
 * @param {Array} plain Orginal data.
 * @returns {Object}
 * @api private
 */
Probe.latest = function latest(transformed, plain) {
  return transformed[transformed.length - 1].values.lag;
};

/**
 * Group functionality by time, this will group per day.
 *
 * @param {Number} time Unix timestamp.
 * @returns {Date}
 * @api public
 */
Probe.group = function group(time) {
  return new Date(time).setHours(0, 0, 0, 0);
};

//
// Default stack to map and process results.
//
Probe.map = Object.keys(intervals).map(function map(key) {
  return {
    type: key,
    lag: 0,
    n: 0
  };
});

//
// Expose the intervals that are used by default.
//
Probe.intervals = intervals;

//
// Which registries should the probe run against.
//
Probe.list = Object.keys(require('../registries'));

//
// Export the probe.
//
module.exports = Probe;<commit_msg>[fix] use minutes for lag, bikeshedding<commit_after>'use strict';

var url = require('url')
  , async = require('async')
  , request = require('request')
  , schedule = require('node-schedule');

//
// Time interval for the probe and interval cutoffs in milliseconds.
//
var day = 864E5
  , interval = 6E5
  , intervals = {
      none: 0,
      minute: interval / 10,
      hour: day / 24,
      "day⁺": day
    };

//
// Probe constructor.
//
var Probe = require('./probe')('delta', {
  minute: new schedule.Range(0, 60, intervals.minute * 10)
});

//
// Set of functions to check the equality of a and b for set of keys.
//
Probe.readable('equal', {
  'name': function name(a, b) {
    return a && b && a === b;
  },

  'time': function time(a, b) {
    if (!a || !b) return false;
    var mod = a.modified === b.modified;

    a = Array.isArray(a) ? a : Object.keys(a);
    b = Array.isArray(a) ? a : Object.keys(a);

    return mod && a.length === b.length && a.reduce(function has(memo, item) {
      return memo && ~b.indexOf(item);
    }, true);
  },

  //
  // Unpublished modules will have no versions, modified time should be equal.
  //
  'versions': function versions(a, b) {
    if (!a || !b) return false;

    a = Array.isArray(a) ? a : Object.keys(a);
    b = Array.isArray(a) ? a : Object.keys(a);

    return a.length === b.length && a.reduce(function has(memo, item) {
      return memo && ~b.indexOf(item);
    }, true);
  }
});

/**
 * Combine the results to a meaningful object.
 *
 * @param {Boolean} different Are origin and variation equal or not.
 * @param {Object} origin Module document from original feed.
 * @param {Object} variation Module document from target registry.
 * @return {Object} Module name and its absolute lag in msec
 * @api private
 */
Probe.readable('lag', function lag(different, origin, variation) {
  var now = 0
    , main = 0;

  //
  // If the document for the target npm mirror is missing, registry has lag equal
  // to module creation. Otherwise calculate the difference between modified.
  //
  if (different) {
    now = Date.now();
    main = new Date('unpublished' in origin.time
      ? origin.time.unpublished.time
      : origin.time.modified
    ).getTime();
  }

  //
  // Return absolute lag in msec.
  //
  return {
    missing: !variation,
    module: origin.name,
    lag: Math.abs(now - main)
  };
});

/**
 * Get the difference between both objects for listed `this.equal` functions.
 * If the variation is missing or null then return immediatly.
 *
 * @param {Object} origin Module document from original feed.
 * @param {Object} variation Module document from target registry.
 * @api private
 */
Probe.readable('diff', function diff(origin, variation) {
  var keys = [];

  try {
    if (!variation) throw new Error('No variation doc found');
    variation = JSON.parse(variation);
  } catch (e) {
    return this.lag(true, origin);
  }

  for (var check in this.equal) {
    if (!this.equal[check](origin[check], variation[check])) keys.push(check);
  }

  return this.lag(keys.length, origin, variation);
});

/**
 * Check for error responses in the body. This is required since not all 404's or
 * errors can be blindly treated as a missing document.
 *
 * @param {String} body Content to be checked.
 * @return {Boolean} body has error
 */
Probe.readable('error', function error(body) {
  return ~body.indexOf('"error":"not_found"')
      || ~body.indexOf('"error":"illegal_database_name"');
});

/**
 * Check the last changes feed against each mirror registry.
 *
 * @param {Object} endpoint url parsed endpoint
 * @param {Function} done completion callback.
 * @api public
 */
Probe.readable('execute', function execute(endpoint, done) {
  var probe = this;

  async.map(probe.collector.feed, function get(module, next) {
    var target = url.format({
      protocol: endpoint.protocol,
      pathname: endpoint.pathname + module.id,
      host: endpoint.host
    });

    //
    // Fetch documents, ignore errors by setting the body to an empty JSON
    // object representation, mapping should continue for other modules.
    // Deleted modules will respond with statusCode = 404, so ignore that as well.
    //
    request(target, function get(error, response, body) {
      if (error || (response.statusCode !== 200 && probe.error(body))) body = null;
      next(null, probe.diff(module.doc, body));
    });
  }, function calc(error, result) {
    if (error) return done(error);
    var filtered = []
      , lag = [];

    //
    // Store the names of the modules the are lagging.
    //
    result.forEach(function each(test) {
      if (test.lag > 0) filtered.push(test.module);
      lag.push(test.lag);
    });

    result = {
      lag: probe.collector.calculate(lag),
      n: probe.collector.feed.length,
      modules: filtered
    };

    probe.emit('delta::executed', result);
    done(null, result);
  });
});

/**
 * Seperate time units into intervals.
 *
 * @param {Array} memo Container to store results in.
 * @param {Object} probe Results from probe.
 * @return {Object} altered memo.
 * @api private
 */
Probe.transform = function transform(memo, probe, i, stack) {
  var position = Object.keys(intervals)
    , interval;

  //
  // Return duration as string for results.
  //
  position.forEach(function each(key, i) {
    if (!probe.results || !probe.results.lag) return;

    //
    // Provide all intervals on the same day with latest minute count.
    //
    memo[i].lag = Math.round(probe.results.lag.mean / intervals.minute);

    //
    // Current found interval is correct, stop processing before updating again.
    // Check if the interval is undefined as it can also be 0, e.g. no lag.
    //
    if ('undefined' !== typeof interval) return;
    if (probe.results.lag.mean <= intervals[key]) interval = i;
  });

  //
  // Update the occurence of the interval and add the modules for reference.
  //
  if ('undefined' === typeof interval) interval = position.length - 1;

  memo[interval].n++;
  return memo;
};

/**
 * Return custom content to be displayed as latest measurement.
 *
 * @param {Array} transformed Data transformed with transform
 * @param {Array} plain Orginal data.
 * @returns {Object}
 * @api private
 */
Probe.latest = function latest(transformed, plain) {
  return transformed[transformed.length - 1].values.lag;
};

/**
 * Group functionality by time, this will group per day.
 *
 * @param {Number} time Unix timestamp.
 * @returns {Date}
 * @api public
 */
Probe.group = function group(time) {
  return new Date(time).setHours(0, 0, 0, 0);
};

//
// Default stack to map and process results.
//
Probe.map = Object.keys(intervals).map(function map(key) {
  return {
    type: key,
    lag: 0,
    n: 0
  };
});

//
// Expose the intervals that are used by default.
//
Probe.intervals = intervals;

//
// Which registries should the probe run against.
//
Probe.list = Object.keys(require('../registries'));

//
// Export the probe.
//
module.exports = Probe;<|endoftext|>


<commit_before><commit_msg>dammit.<commit_after><|endoftext|>


<commit_before>if(!settings) {
	var settings = new Store("settings", {
	"timestamp": "absolute",
	"name_display": "username",
	"url_redirection": "true",
	"circled_avatars": "true",
	"img_preview": "small",
	"reduced_padding": "true",
	"no_columns_icons": "true",
	"full_after_24h": "true",
	"typeahead_display_username_only": "true"
	});
}

chrome.extension.onRequest.addListener(
	function(request, sender, sendResponse) {
		sendResponse(settings.toObject());
	}
);<commit_msg>Some options are not enabled by default anymore<commit_after>if(!settings) {
	var settings = new Store("settings", {
	"timestamp": "relative",
	"name_display": "both",
	"url_redirection": "true",
	"circled_avatars": "false",
	"img_preview": "small",
	"reduced_padding": "true",
	"no_columns_icons": "false",
	"full_after_24h": "false",
	"typeahead_display_username_only": "true"
	});
}

chrome.extension.onRequest.addListener(
	function(request, sender, sendResponse) {
		sendResponse(settings.toObject());
	}
);<|endoftext|>


<commit_before>var http = require('http');
var requestImport = require('request');
var url = require('url');

var xpath = require('xpath')
var dom = require('xmldom').DOMParser

const PORT=8080;

//We need a function which handles requests and send response
function handleRequest(request, response){

	if( request.url.indexOf('favicon.ico') > -1)
	{
		console.log('facicon request cancelled');
		response.end();
		return;
	}

	var queryData = url.parse(request.url, true).query;
	var road = queryData.road;

	requestImport('http://hatrafficinfo.dft.gov.uk/feeds/datex/England/UnplannedEvent/content.xml', function (error, innerResponse, body)
	{
		//console.log('Inside request body');
		//
		//console.log('' + innerResponse ==null);
		//console.log('error:' + error);
		//console.log('statusCode' + innerResponse.statusCode);

		if (!error && innerResponse.statusCode === 200)
		{
			console.log('200 OK');

			var xml = body.replace(' ','').replace('©','').replace(' xmlns="http://datex2.eu/schema/1_0/1_0" modelBaseVersion="1.0"', '');
			//console.log(xml);
			console.log("contains " + road + ": " + (xml.indexOf(road) > -1));

			var doc = new dom().parseFromString(xml);
			//console.log(doc);

			var nodes = xpath.select('//situation[.//groupOfLocations//descriptor/value="' + road + '"]//nonGeneralPublicComment/comment/value', doc);
			console.log('length: ' + nodes.length);

			if(nodes.length===0)
			{
				console.log("No notifications found for " + road);
				response.end("No notifications found for " + road);
				return;
			}

			console.log('nodes[0].data: ' + nodes[0].firstChild.data);
			// console.log("node: " + nodes[0].toString())

			response.end(nodes[0].firstChild.data);
		}
	});

}

//Create a server
var server = http.createServer(handleRequest);

//Lets start our server
server.listen(PORT, function(){
   console.log("Server listening on: http://localhost:%s", PORT);
});

<commit_msg>Case insensitve handling of road param<commit_after>var http = require('http');
var requestImport = require('request');
var url = require('url');

var xpath = require('xpath')
var dom = require('xmldom').DOMParser

const PORT=8080;

//We need a function which handles requests and send response
function handleRequest(request, response){

	if( request.url.indexOf('favicon.ico') > -1)
	{
		console.log('facicon request cancelled');
		response.end();
		return;
	}

	var queryData = url.parse(request.url, true).query;
	var road = queryData.road.toUpperCase();

	requestImport('http://hatrafficinfo.dft.gov.uk/feeds/datex/England/UnplannedEvent/content.xml', function (error, innerResponse, body)
	{
		//console.log('Inside request body');
		//
		//console.log('' + innerResponse ==null);
		//console.log('error:' + error);
		//console.log('statusCode' + innerResponse.statusCode);

		if (!error && innerResponse.statusCode === 200)
		{
			console.log('200 OK');

			var xml = body.replace(' ','').replace('©','').replace(' xmlns="http://datex2.eu/schema/1_0/1_0" modelBaseVersion="1.0"', '');
			//console.log(xml);
			console.log("contains " + road + ": " + (xml.indexOf(road) > -1));

			var doc = new dom().parseFromString(xml);
			//console.log(doc);

			var nodes = xpath.select('//situation[.//groupOfLocations//descriptor/value="' + road + '"]//nonGeneralPublicComment/comment/value', doc);
			console.log('length: ' + nodes.length);

			if(nodes.length===0)
			{
				console.log("No notifications found for " + road);
				response.end("No notifications found for " + road);
				return;
			}

			console.log('nodes[0].data: ' + nodes[0].firstChild.data);
			// console.log("node: " + nodes[0].toString())

			response.end(nodes[0].firstChild.data);
		}
	});

}

//Create a server
var server = http.createServer(handleRequest);

//Lets start our server
server.listen(PORT, function(){
   console.log("Server listening on: http://localhost:%s", PORT);
});

<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Disposable, CompositeDisposable, SerialDisposable } from 'disposables';
import shallowEqual from './utils/shallowEqual';
import shallowEqualScalar from './utils/shallowEqualScalar';
import isPlainObject from 'lodash/lang/isPlainObject';
import invariant from 'invariant';
import bindConnector from './bindConnector';

export default function decorateHandler({
  DecoratedComponent,
  createHandler,
  createMonitor,
  createConnector,
  registerHandler,
  containerDisplayName,
  getType,
  collect,
  options
}) {
  const { arePropsEqual = shallowEqualScalar } = options;
  const displayName =
    DecoratedComponent.displayName ||
    DecoratedComponent.name ||
    'Component';

  return class DragDropContainer extends Component {
    static DecoratedComponent = DecoratedComponent;

    static displayName = `${containerDisplayName}(${displayName})`;

    static contextTypes = {
      dragDropManager: PropTypes.object.isRequired
    }

    getHandlerId() {
      return this.handlerId;
    }

    getDecoratedComponentInstance() {
      return this.decoratedComponentInstance;
    }

    shouldComponentUpdate(nextProps, nextState) {
      return !arePropsEqual(nextProps, this.props) ||
             !shallowEqual(nextState, this.state);
    }

    constructor(props, context) {
      super(props, context);
      this.handleChange = this.handleChange.bind(this);
      this.handleChildRef = this.handleChildRef.bind(this);

      invariant(
        typeof this.context.dragDropManager === 'object',
        'Could not find the drag and drop manager in the context of %s. ' +
        'Make sure to wrap the top-level component of your app with DragDropContext. ' +
        'Read more: http://gaearon.github.io/react-dnd/docs-troubleshooting.html#could-not-find-the-drag-and-drop-manager-in-the-context',
        displayName,
        displayName
      );

      this.manager = this.context.dragDropManager;
      this.handlerMonitor = createMonitor(this.manager);
      this.handler = createHandler(this.handlerMonitor);
      this.disposable = new SerialDisposable();

      this.receiveProps(props);
      this.state = this.getCurrentState();
    }

    componentWillReceiveProps(nextProps) {
      if (!arePropsEqual(nextProps, this.props)) {
        this.receiveProps(nextProps);
        this.handleChange();
      }
    }

    componentWillUnmount() {
      this.disposable.dispose();
    }

    receiveProps(props) {
      this.handler.receiveProps(props);
      this.receiveType(getType(props));
    }

    receiveType(type) {
      if (type === this.currentType) {
        return;
      }

      this.currentType = type;

      const {
        handlerId,
        unregister
      } = registerHandler(
        type,
        this.handler,
        this.manager
      );

      const connector = createConnector(this.manager.getBackend());
      const {
        handlerConnector,
        disposable: connectorDisposable
      } = bindConnector(connector, handlerId);

      const globalMonitor = this.manager.getMonitor();
      const unsubscribe = globalMonitor.subscribeToStateChange(
        this.handleChange,
        { handlerIds: [handlerId] }
      );

      this.disposable.setDisposable(
        new CompositeDisposable(
          new Disposable(unregister),
          new Disposable(unsubscribe),
          connectorDisposable
        )
      );

      this.handlerMonitor.receiveHandlerId(handlerId);
      this.handlerConnector = handlerConnector;
      this.handlerId = handlerId;
    }

    handleChange() {
      const nextState = this.getCurrentState();
      if (!shallowEqual(nextState, this.state)) {
        this.setState(nextState);
      }
    }

    handleChildRef(component) {
      this.decoratedComponentInstance = component;
      this.handler.receiveComponent(component);
    }

    getCurrentState() {
      const nextState = collect(this.handlerConnector, this.handlerMonitor);
      if (process.env.NODE_ENV !== 'production') {
        invariant(
          isPlainObject(nextState),
          'Expected `collect` specified as the second argument to ' +
          '%s for %s to return a plain object of props to inject. ' +
          'Instead, received %s.',
          containerDisplayName,
          displayName,
          nextState
        );
      }
      return nextState;
    }

    render() {
      return (
        <DecoratedComponent {...this.props}
                            {...this.state}
                            ref={this.handleChildRef} />
      );
    }
  };
}<commit_msg>Perform receiving new type in correct order. Fixes #277<commit_after>import React, { Component, PropTypes } from 'react';
import { Disposable, CompositeDisposable, SerialDisposable } from 'disposables';
import shallowEqual from './utils/shallowEqual';
import shallowEqualScalar from './utils/shallowEqualScalar';
import isPlainObject from 'lodash/lang/isPlainObject';
import invariant from 'invariant';
import bindConnector from './bindConnector';

export default function decorateHandler({
  DecoratedComponent,
  createHandler,
  createMonitor,
  createConnector,
  registerHandler,
  containerDisplayName,
  getType,
  collect,
  options
}) {
  const { arePropsEqual = shallowEqualScalar } = options;
  const displayName =
    DecoratedComponent.displayName ||
    DecoratedComponent.name ||
    'Component';

  return class DragDropContainer extends Component {
    static DecoratedComponent = DecoratedComponent;

    static displayName = `${containerDisplayName}(${displayName})`;

    static contextTypes = {
      dragDropManager: PropTypes.object.isRequired
    }

    getHandlerId() {
      return this.handlerId;
    }

    getDecoratedComponentInstance() {
      return this.decoratedComponentInstance;
    }

    shouldComponentUpdate(nextProps, nextState) {
      return !arePropsEqual(nextProps, this.props) ||
             !shallowEqual(nextState, this.state);
    }

    constructor(props, context) {
      super(props, context);
      this.handleChange = this.handleChange.bind(this);
      this.handleChildRef = this.handleChildRef.bind(this);

      invariant(
        typeof this.context.dragDropManager === 'object',
        'Could not find the drag and drop manager in the context of %s. ' +
        'Make sure to wrap the top-level component of your app with DragDropContext. ' +
        'Read more: http://gaearon.github.io/react-dnd/docs-troubleshooting.html#could-not-find-the-drag-and-drop-manager-in-the-context',
        displayName,
        displayName
      );

      this.manager = this.context.dragDropManager;
      this.handlerMonitor = createMonitor(this.manager);
      this.handler = createHandler(this.handlerMonitor);
      this.disposable = new SerialDisposable();

      this.receiveProps(props);
      this.state = this.getCurrentState();
    }

    componentWillReceiveProps(nextProps) {
      if (!arePropsEqual(nextProps, this.props)) {
        this.receiveProps(nextProps);
        this.handleChange();
      }
    }

    componentWillUnmount() {
      this.disposable.dispose();
    }

    receiveProps(props) {
      this.handler.receiveProps(props);
      this.receiveType(getType(props));
    }

    receiveType(type) {
      if (type === this.currentType) {
        return;
      }

      this.currentType = type;

      const {
        handlerId,
        unregister
      } = registerHandler(
        type,
        this.handler,
        this.manager
      );

      const connector = createConnector(this.manager.getBackend());
      const {
        handlerConnector,
        disposable: connectorDisposable
      } = bindConnector(connector, handlerId);

      this.handlerId = handlerId;
      this.handlerConnector = handlerConnector;
      this.handlerMonitor.receiveHandlerId(handlerId);

      const globalMonitor = this.manager.getMonitor();
      const unsubscribe = globalMonitor.subscribeToStateChange(
        this.handleChange,
        { handlerIds: [handlerId] }
      );

      this.disposable.setDisposable(
        new CompositeDisposable(
          new Disposable(unsubscribe),
          new Disposable(unregister),
          connectorDisposable
        )
      );
    }

    handleChange() {
      const nextState = this.getCurrentState();
      if (!shallowEqual(nextState, this.state)) {
        this.setState(nextState);
      }
    }

    handleChildRef(component) {
      this.decoratedComponentInstance = component;
      this.handler.receiveComponent(component);
    }

    getCurrentState() {
      const nextState = collect(this.handlerConnector, this.handlerMonitor);
      if (process.env.NODE_ENV !== 'production') {
        invariant(
          isPlainObject(nextState),
          'Expected `collect` specified as the second argument to ' +
          '%s for %s to return a plain object of props to inject. ' +
          'Instead, received %s.',
          containerDisplayName,
          displayName,
          nextState
        );
      }
      return nextState;
    }

    render() {
      return (
        <DecoratedComponent {...this.props}
                            {...this.state}
                            ref={this.handleChildRef} />
      );
    }
  };
}<|endoftext|>


<commit_before>require('basis.data');
require('basis.data.dataset');

var inspectBasis = require('devpanel').inspectBasis;
var inspectBasisUI = inspectBasis.require('basis.ui');

var instances = {};
var updateInfoQueue = {};
var updateInfoTimer_ = null;

var config = { data: null };
var updateObj = { parent: null, satelliteName: null, groupNode: null, grouping: null };

var allInstances = new basis.data.Dataset();

function updateInfo(){
  var queue = updateInfoQueue;
  var models = [];

  updateInfoQueue = {};
  updateInfoTimer_ = null;

  //console.log('updateInfo');

  for (var id in queue)
  {
    var instance = instances[id].data.instance;
    if (instance.firstChild)
      instance.childNodes.forEach(function(child){
        queue[child.basisObjectId] = true;
      });
  }

  for (var id in queue)
  {
    var model = instances[id];
    var instance = model.data.instance;
    var parent = instance.parentNode || instance.owner;

    updateObj.parent = parent && parent.basisObjectId;  // reuse updateObj to less GC
    updateObj.groupNode = instance.groupNode && instance.groupNode.basisObjectId;  // reuse updateObj to less GC
    updateObj.grouping = instance.grouping && instance.grouping.basisObjectId;
    updateObj.satelliteName = instance.ownerSatelliteName;

    instances[id].update(updateObj);
    models.push(model);
  }

  allInstances.add(models);
}

function processEvent(event){
  var instance = event.instance;
  var id = instance.basisObjectId;
  switch (event.action)
  {
    case 'create':
      //console.log('create', id);

      // reuse config for less garbage
      config.data = {
        id: id,
        instance: instance,
        parent: null
      };

      instances[id] = new basis.data.Object(config);

      updateInfoQueue[id] = true;
      if (!updateInfoTimer_)
        updateInfoTimer_ = basis.setImmediate(updateInfo);

      break;

    case 'destroy':
      //console.log('destroy', id);

      var model = instances[id];
      delete instances[id];
      delete updateInfoQueue[id];
      model.destroy();

      break;
  }
}

inspectBasisUI.GroupingNode.prototype.debug_emit =
inspectBasisUI.Node.prototype.debug_emit = function(event){
  var id = event.sender.basisObjectId;

  if (id in instances)
    updateInfoQueue[id] = true;

  if (!updateInfoTimer_)
    updateInfoTimer_ = basis.setImmediate(updateInfo);
};

inspectBasisUI.debug_notifier.attach(processEvent);
inspectBasisUI.debug_getInstances().map(function(instance){
  processEvent({
    action: 'create',
    instance: instance
  });
});

module.exports = {
  instanceMap: instances,
  instances: allInstances
};
<commit_msg>devpanel: fix rollout update queue for nodes contains non-basis.ui.Node child nodes (i.e. charts)<commit_after>require('basis.data');
require('basis.data.dataset');

var inspectBasis = require('devpanel').inspectBasis;
var inspectBasisUI = inspectBasis.require('basis.ui');

var instances = {};
var updateInfoQueue = {};
var updateInfoTimer_ = null;

var config = { data: null };
var updateObj = { parent: null, satelliteName: null, groupNode: null, grouping: null };

var allInstances = new basis.data.Dataset();

function updateInfo(){
  var queue = updateInfoQueue;
  var models = [];

  updateInfoQueue = {};
  updateInfoTimer_ = null;

  //console.log('updateInfo');

  for (var id in queue)
  {
    var instance = instances[id].data.instance;
    if (instance.firstChild)
      instance.childNodes.forEach(function(child){
        var id = child.basisObjectId;
        if (id in instances)
          queue[id] = true;
      });
  }

  for (var id in queue)
  {
    var model = instances[id];
    var instance = model.data.instance;
    var parent = instance.parentNode || instance.owner;

    updateObj.parent = parent && parent.basisObjectId;  // reuse updateObj to less GC
    updateObj.groupNode = instance.groupNode && instance.groupNode.basisObjectId;  // reuse updateObj to less GC
    updateObj.grouping = instance.grouping && instance.grouping.basisObjectId;
    updateObj.satelliteName = instance.ownerSatelliteName;

    instances[id].update(updateObj);
    models.push(model);
  }

  allInstances.add(models);
}

function processEvent(event){
  var instance = event.instance;
  var id = instance.basisObjectId;
  switch (event.action)
  {
    case 'create':
      //console.log('create', id);

      // reuse config for less garbage
      config.data = {
        id: id,
        instance: instance,
        parent: null
      };

      instances[id] = new basis.data.Object(config);

      updateInfoQueue[id] = true;
      if (!updateInfoTimer_)
        updateInfoTimer_ = basis.setImmediate(updateInfo);

      break;

    case 'destroy':
      //console.log('destroy', id);

      var model = instances[id];
      delete instances[id];
      delete updateInfoQueue[id];
      model.destroy();

      break;
  }
}

inspectBasisUI.GroupingNode.prototype.debug_emit =
inspectBasisUI.Node.prototype.debug_emit = function(event){
  var id = event.sender.basisObjectId;

  if (id in instances)
    updateInfoQueue[id] = true;

  if (!updateInfoTimer_)
    updateInfoTimer_ = basis.setImmediate(updateInfo);
};

inspectBasisUI.debug_notifier.attach(processEvent);
inspectBasisUI.debug_getInstances().map(function(instance){
  processEvent({
    action: 'create',
    instance: instance
  });
});

module.exports = {
  instanceMap: instances,
  instances: allInstances
};
<|endoftext|>


<commit_before>/*
 kitchen.js
 Copyright (C) 2015 toshi0383 All Rights Reserved.
*/

var parser;
var currentTab;

function defaultPresenter(xml) {
    if(this.loadingIndicatorVisible) {
        navigationDocument.replaceDocument(xml, this.loadingIndicator);
        this.loadingIndicatorVisible = false;
    } else {
        navigationDocument.pushDocument(xml);
    }
}

function searchPresenter(xml) {

    this.defaultPresenter.call(this, xml);
    var doc = xml;

    var searchField = doc.getElementsByTagName("searchField").item(0);
    var keyboard = searchField.getFeature("Keyboard");

    keyboard.onTextChange = function() {
        var searchText = keyboard.text;
        buildResults(doc, searchText);
    }
}

/**
 *  Displays an XML string as a "document" within a tab.
 *  A new document will be created for the tab if it doesn't exist.
 *
 *  @param xml The XML string to be presented
 *
 *  @return void
 */
function menuBarItemPresenter(xml) {
    var feature = currentTab.parentNode.getFeature("MenuBarDocument");
    if (feature) {
        var currentDoc = feature.getDocument(currentTab);
        if (!currentDoc) {
            feature.setDocument(xml, currentTab);
        }
    }
}

/// Documents presented in the modal view are presented in fullscreen
/// with a semi-transparent background that blurs the document below it.
function modalDialogPresenter(xml) {
    navigationDocument.presentModal(xml);
}

/// Dismisses the current modal window
function dismissModal() {
    navigationDocument.dismissModal();
}

function play(event) {
    var ele = event.target,
        actionID = ele.getAttribute('playActionID');
    if(actionID && typeof playActionIDHandler !== 'undefined'){
        playActionIDHandler(actionID);
        return;
    }
}

function holdselect(event) {
}

function highlight(event) {
}

function load(event) {
    var self = this,
        ele = event.target,
        templateURL = ele.getAttribute("template"),
        presentation = ele.getAttribute("presentation"),
        actionID = ele.getAttribute("actionID"),
        menuIndex = ele.getAttribute("menuIndex"),
        tagName = ele.tagName;

    // If this is a menu item then trigger the relevent handler
    if(menuIndex){
        currentTab = ele;
        tabBarHandler(menuIndex);
    }

    if(actionID && typeof actionIDHandler !== 'undefined'){
        actionIDHandler(actionID);
        return;
    }

    if (!templateURL) {
        return;
    }
    self.showLoadingIndicator(presentation);
    loadTemplateFromURL(templateURL, function(resource) {
        present(resource, presentation, ele);
    });
}

function present(resource, presentation, ele) {
    if (!resource) {
        return;
    }
    var self = this;
    var doc = makeDocument(resource);
    doc.addEventListener("select", self.load.bind(self));
    doc.addEventListener("highlight", self.highlight.bind(self));
    doc.addEventListener("holdselect", self.holdselect.bind(self));
    doc.addEventListener("play", self.play.bind(self));

    if (self[presentation] instanceof Function) {
        self[presentation].call(self, doc, ele);
    } else {
        self.defaultPresenter.call(self, doc);
    }
}

function makeDocument(resource) {
    var doc = parser.parseFromString(resource, "application/xml");
    return doc;
}

function showLoadingIndicator(presentation) {
    if (!this.loadingIndicator) {
        this.loadingIndicator = this.makeDocument(loadingTemplate());
    }

    if (!this.loadingIndicatorVisible &&
        presentation != "modalDialogPresenter" &&
        presentation != "menuBarItemPresenter")
    {
        navigationDocument.pushDocument(this.loadingIndicator);
        this.loadingIndicatorVisible = true;
    }
}

/**
 Show the loading indicator for the presentation type passed from UIKit
 */
function showLoadingIndicatorForType(presentationType) {
    if (presentationType == 1 ||
        presentationType == 2 ||
        this.loadingIndicatorVisible) {
        return;
    }

    if (!this.loadingIndicator) {
        this.loadingIndicator = this.makeDocument(loadingTemplate());
    }

    navigationDocument.pushDocument(this.loadingIndicator);
    this.loadingIndicatorVisible = true;
}

function removeLoadingIndicator() {
    if (this.loadingIndicatorVisible) {
        navigationDocument.removeDocument(this.loadingIndicator);
        this.loadingIndicatorVisible = false;
    }
}

function loadingTemplate() {
    return `<?xml version="1.0" encoding="UTF-8" ?>
        <document>
          <loadingTemplate>
            <activityIndicator>
              <text>Loading...</text>
            </activityIndicator>
          </loadingTemplate>
        </document>`
}

/// load template from absolute URL
function loadTemplateFromURL(templateURL, callback, presentationType) {
    var self = this;

    evaluateScripts([templateURL], function(success) {
        if (success) {
            var resource = Template.call(self);
            callback.call(self, resource, presentationType);
        } else {
            var message = `There was an error attempting to load the resource '${resource}' with URL: '${templateURL}'. \n\n Please try again later.`

            removeLoadingIndicator();
            if (kitchenErrorHandler !== undefined) {
                kitchenErrorHandler(message);
            }
        }
    });
}

function presenterForType(type) {
    switch(type) {
        case 1:
            return modalDialogPresenter;
        case 2:
            return menuBarItemPresenter;
        default:
            return defaultPresenter;
    }
}

/// load template from Main Bundle URL
function openTemplateFromJSFile(jsFileName, presentationType) {
    mainBundleUrl = App.options.MAIN_BUNDLE_URL
    loadTemplateFromURL(`${mainBundleUrl}${jsFileName}`, openTemplateFromXMLString, presentationType);
}

function openTemplateFromURL(url, presentationType) {
    loadTemplateFromURL(`${url}`, openTemplateFromXMLString, presentationType);
}

function openTemplateFromXMLString(xmlString, presentationType) {
    showLoadingIndicatorForType(presentationType);
    var doc = makeDocument(xmlString);
    doc.addEventListener("select", load.bind(this));
    doc.addEventListener("highlight", highlight.bind(this));
    doc.addEventListener("holdselect", holdselect.bind(this));
    doc.addEventListener("play", play.bind(this));

    presenterForType(presentationType).call(this, doc);
}

App.onLaunch = function(options) {
    App.options = options
    parser = new DOMParser();
}
<commit_msg>Dismiss modal before new presentation<commit_after>/*
 kitchen.js
 Copyright (C) 2015 toshi0383 All Rights Reserved.
*/

var parser;
var currentTab;

function defaultPresenter(xml) {
    dismissModal();
    if(this.loadingIndicatorVisible) {
        navigationDocument.replaceDocument(xml, this.loadingIndicator);
        this.loadingIndicatorVisible = false;
    } else {
        navigationDocument.pushDocument(xml);
    }
}

function searchPresenter(xml) {

    this.defaultPresenter.call(this, xml);
    var doc = xml;

    var searchField = doc.getElementsByTagName("searchField").item(0);
    var keyboard = searchField.getFeature("Keyboard");

    keyboard.onTextChange = function() {
        var searchText = keyboard.text;
        buildResults(doc, searchText);
    }
}

/**
 *  Displays an XML string as a "document" within a tab.
 *  A new document will be created for the tab if it doesn't exist.
 *
 *  @param xml The XML string to be presented
 *
 *  @return void
 */
function menuBarItemPresenter(xml) {
    var feature = currentTab.parentNode.getFeature("MenuBarDocument");
    if (feature) {
        var currentDoc = feature.getDocument(currentTab);
        if (!currentDoc) {
            feature.setDocument(xml, currentTab);
        }
    }
}

/// Documents presented in the modal view are presented in fullscreen
/// with a semi-transparent background that blurs the document below it.
function modalDialogPresenter(xml) {
    navigationDocument.presentModal(xml);
}

/// Dismisses the current modal window
function dismissModal() {
    navigationDocument.dismissModal();
}

function play(event) {
    var ele = event.target,
        actionID = ele.getAttribute('playActionID');
    if(actionID && typeof playActionIDHandler !== 'undefined'){
        playActionIDHandler(actionID);
        return;
    }
}

function holdselect(event) {
}

function highlight(event) {
}

function load(event) {
    var self = this,
        ele = event.target,
        templateURL = ele.getAttribute("template"),
        presentation = ele.getAttribute("presentation"),
        actionID = ele.getAttribute("actionID"),
        menuIndex = ele.getAttribute("menuIndex"),
        tagName = ele.tagName;

    // If this is a menu item then trigger the relevent handler
    if(menuIndex){
        currentTab = ele;
        tabBarHandler(menuIndex);
    }

    if(actionID && typeof actionIDHandler !== 'undefined'){
        actionIDHandler(actionID);
        return;
    }

    if (!templateURL) {
        return;
    }
    self.showLoadingIndicator(presentation);
    loadTemplateFromURL(templateURL, function(resource) {
        present(resource, presentation, ele);
    });
}

function present(resource, presentation, ele) {
    if (!resource) {
        return;
    }
    var self = this;
    var doc = makeDocument(resource);
    doc.addEventListener("select", self.load.bind(self));
    doc.addEventListener("highlight", self.highlight.bind(self));
    doc.addEventListener("holdselect", self.holdselect.bind(self));
    doc.addEventListener("play", self.play.bind(self));

    if (self[presentation] instanceof Function) {
        self[presentation].call(self, doc, ele);
    } else {
        self.defaultPresenter.call(self, doc);
    }
}

function makeDocument(resource) {
    var doc = parser.parseFromString(resource, "application/xml");
    return doc;
}

function showLoadingIndicator(presentation) {
    if (!this.loadingIndicator) {
        this.loadingIndicator = this.makeDocument(loadingTemplate());
    }

    if (!this.loadingIndicatorVisible &&
        presentation != "modalDialogPresenter" &&
        presentation != "menuBarItemPresenter")
    {
        navigationDocument.pushDocument(this.loadingIndicator);
        this.loadingIndicatorVisible = true;
    }
}

/**
 Show the loading indicator for the presentation type passed from UIKit
 */
function showLoadingIndicatorForType(presentationType) {
    if (presentationType == 1 ||
        presentationType == 2 ||
        this.loadingIndicatorVisible) {
        return;
    }

    if (!this.loadingIndicator) {
        this.loadingIndicator = this.makeDocument(loadingTemplate());
    }

    navigationDocument.pushDocument(this.loadingIndicator);
    this.loadingIndicatorVisible = true;
}

function removeLoadingIndicator() {
    if (this.loadingIndicatorVisible) {
        navigationDocument.removeDocument(this.loadingIndicator);
        this.loadingIndicatorVisible = false;
    }
}

function loadingTemplate() {
    return `<?xml version="1.0" encoding="UTF-8" ?>
        <document>
          <loadingTemplate>
            <activityIndicator>
              <text>Loading...</text>
            </activityIndicator>
          </loadingTemplate>
        </document>`
}

/// load template from absolute URL
function loadTemplateFromURL(templateURL, callback, presentationType) {
    var self = this;

    evaluateScripts([templateURL], function(success) {
        if (success) {
            var resource = Template.call(self);
            callback.call(self, resource, presentationType);
        } else {
            var message = `There was an error attempting to load the resource '${resource}' with URL: '${templateURL}'. \n\n Please try again later.`

            removeLoadingIndicator();
            if (kitchenErrorHandler !== undefined) {
                kitchenErrorHandler(message);
            }
        }
    });
}

function presenterForType(type) {
    switch(type) {
        case 1:
            return modalDialogPresenter;
        case 2:
            return menuBarItemPresenter;
        default:
            return defaultPresenter;
    }
}

/// load template from Main Bundle URL
function openTemplateFromJSFile(jsFileName, presentationType) {
    mainBundleUrl = App.options.MAIN_BUNDLE_URL
    loadTemplateFromURL(`${mainBundleUrl}${jsFileName}`, openTemplateFromXMLString, presentationType);
}

function openTemplateFromURL(url, presentationType) {
    loadTemplateFromURL(`${url}`, openTemplateFromXMLString, presentationType);
}

function openTemplateFromXMLString(xmlString, presentationType) {
    showLoadingIndicatorForType(presentationType);
    var doc = makeDocument(xmlString);
    doc.addEventListener("select", load.bind(this));
    doc.addEventListener("highlight", highlight.bind(this));
    doc.addEventListener("holdselect", holdselect.bind(this));
    doc.addEventListener("play", play.bind(this));

    presenterForType(presentationType).call(this, doc);
}

App.onLaunch = function(options) {
    App.options = options
    parser = new DOMParser();
}
<|endoftext|>


<commit_before>'use strict';
var createHash = require('create-hash/browser');
var Transform = require('stream').Transform;
var inherits = require('inherits')
var zeroBuffer = new Buffer(128)
zeroBuffer.fill(0)

function Hmac(alg, key) {
  Transform.call(this)

  if (typeof key === 'string') {
    key = new Buffer(key)
  }

  var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64

  this._alg = alg
  this._key = key

  if (key.length > blocksize) {
    key = createHash(alg).update(key).digest()

  } else if (key.length < blocksize) {
    key = Buffer.concat([key, zeroBuffer], blocksize)
  }

  var ipad = this._ipad = new Buffer(blocksize)
  var opad = this._opad = new Buffer(blocksize)

  for (var i = 0; i < blocksize; i++) {
    ipad[i] = key[i] ^ 0x36
    opad[i] = key[i] ^ 0x5C
  }

  this._hash = createHash(alg).update(ipad)
}

inherits(Hmac, Transform)

Hmac.prototype.update = function (data, enc) {
  if (typeof data === 'string') {
    data = new Buffer(data, enc)
  }

  this._hash.update(data)
  return this
}

Hmac.prototype._transform = function (data, enc, next) {
  this._hash.update(data)

  next()
}

Hmac.prototype._flush = function (next) {
  this.push(this.digest())

  next()
}

Hmac.prototype.digest = function (enc) {
  var h = this._hash.digest()
  var outData = createHash(this._alg).update(this._opad).update(h).digest()

  return enc ? outData.toString() : outData
}

module.exports = function createHmac(alg, key) {
  return new Hmac(alg, key)
}
<commit_msg>browser: use correct casing for variable usage<commit_after>'use strict';
var createHash = require('create-hash/browser');
var inherits = require('inherits')

var Transform = require('stream').Transform

var ZEROS = new Buffer(128)
ZEROS.fill(0)

function Hmac(alg, key) {
  Transform.call(this)

  if (typeof key === 'string') {
    key = new Buffer(key)
  }

  var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64

  this._alg = alg
  this._key = key

  if (key.length > blocksize) {
    key = createHash(alg).update(key).digest()

  } else if (key.length < blocksize) {
    key = Buffer.concat([key, ZEROS], blocksize)
  }

  var ipad = this._ipad = new Buffer(blocksize)
  var opad = this._opad = new Buffer(blocksize)

  for (var i = 0; i < blocksize; i++) {
    ipad[i] = key[i] ^ 0x36
    opad[i] = key[i] ^ 0x5C
  }

  this._hash = createHash(alg).update(ipad)
}

inherits(Hmac, Transform)

Hmac.prototype.update = function (data, enc) {
  if (typeof data === 'string') {
    data = new Buffer(data, enc)
  }

  this._hash.update(data)
  return this
}

Hmac.prototype._transform = function (data, enc, next) {
  this._hash.update(data)

  next()
}

Hmac.prototype._flush = function (next) {
  this.push(this.digest())

  next()
}

Hmac.prototype.digest = function (enc) {
  var h = this._hash.digest()
  var outData = createHash(this._alg).update(this._opad).update(h).digest()

  return enc ? outData.toString() : outData
}

module.exports = function createHmac(alg, key) {
  return new Hmac(alg, key)
}
<|endoftext|>