<commit_before>window.Modernizr = {
  indexeddb: true
};

require.config({
  paths: {
    jquery: '/bower_components/jquery/jquery',
    underscore: '/bower_components/underscore/underscore',
    backbone: '/bower_components/backbone/backbone',
    feature: '/bower_components/amd-feature/feature',
    domReady: '/bower_components/requirejs-domready/domReady',
    text: '/bower_components/requirejs-text/text',
    'BMP.Blobs': '//d1c6dfkb81l78v.cloudfront.net/blink/blobs/1377493706402/bmp-blobs.min',
    BlinkForms: '//d1c6dfkb81l78v.cloudfront.net/blink/forms/3/3.1.1/forms3jqm.min',
    signaturepad: '//d1c6dfkb81l78v.cloudfront.net/signaturepad/2.3.0/jq.sig.min',
    jquerymobile: '/bower_components/jquery-mobile-bower/js/jquery.mobile-1.3.2',
    moment: '/bower_components/momentjs/min/moment.min',
    picker: '/bower_components/pickadate/lib/picker',
    'picker.date': '/bower_components/pickadate/lib/picker.date',
    'picker.time': '/bower_components/pickadate/lib/picker.time',
    mustache: '/bower_components/mustache/mustache',
    bluebird: '/bower_components/bluebird/js/browser/bluebird',
    pouchdb: '/bower_components/pouchdb/dist/pouchdb-nightly',
    implementations: '/tests/implementations'
  },
  shim: {
    'underscore': {
      exports: '_'
    },
    'backbone': {
      deps: ['jquery', 'underscore'],
      exports: 'Backbone'
    },
    'BMP.Blobs': {
      deps: ['underscore', 'jquery'],
      exports: 'BMP'
    }
  },
  baseUrl: '/scripts'
});

require([
    'feature!promises',
    'jquery',
    'underscore',
    'backbone',
    'BMP.Blobs',
    'mustache',
    'BlinkForms',
    'pouchdb',
    'jquerymobile',
  ], function (Promise, $, _, Backbone, BMP, Mustache, BlinkForms, Pouch) {
  window.BlinkForms = BlinkForms;
  window.Mustache = Mustache;
  window.Promise = Promise;
  window.Pouch = Pouch;

  require(['main'], function () {
    console.log('BIC started!');
  });
});
<commit_msg>Updates to integration server for compatability with IE8<commit_after>window.Modernizr = {
  indexeddb: true
};

require.config({
  paths: {
    jquery: '/bower_components/jquery/jquery',
    underscore: '/bower_components/underscore/underscore',
    backbone: '/bower_components/backbone/backbone',
    feature: '/bower_components/amd-feature/feature',
    domReady: '/bower_components/requirejs-domready/domReady',
    text: '/bower_components/requirejs-text/text',
    'BMP.Blobs': '//d1c6dfkb81l78v.cloudfront.net/blink/blobs/1377493706402/bmp-blobs.min',
    BlinkForms: '//d1c6dfkb81l78v.cloudfront.net/blink/forms/3/3.1.1/forms3jqm.min',
    signaturepad: '//d1c6dfkb81l78v.cloudfront.net/signaturepad/2.3.0/jq.sig.min',
    jquerymobile: '/bower_components/jquery-mobile-bower/js/jquery.mobile-1.3.2',
    moment: '/bower_components/momentjs/min/moment.min',
    picker: '/bower_components/pickadate/lib/picker',
    'picker.date': '/bower_components/pickadate/lib/picker.date',
    'picker.time': '/bower_components/pickadate/lib/picker.time',
    mustache: '/bower_components/mustache/mustache',
    bluebird: '/bower_components/bluebird/js/browser/bluebird',
    pouchdb: '/bower_components/pouchdb/dist/pouchdb-nightly',
    implementations: '/tests/implementations',
    'es5-shim': '//d1c6dfkb81l78v.cloudfront.net/es5-shim/2.3.0/es5-shim.min'
  },
  shim: {
    'underscore': {
      exports: '_'
    },
    'backbone': {
      deps: ['jquery', 'underscore'],
      exports: 'Backbone'
    },
    'BMP.Blobs': {
      deps: ['underscore', 'jquery'],
      exports: 'BMP'
    },
    'signaturepad': {
      deps: ['jquery'],
      exports: '$'
    }
  },
  baseUrl: '/scripts'
});

require([
    'feature!promises',
    'jquery',
    'underscore',
    'backbone',
    'BMP.Blobs',
    'mustache',
    'BlinkForms',
    'jquerymobile',
    'feature!es5'
  ], function (Promise, $, _, Backbone, BMP, Mustache, BlinkForms) {
  window.BlinkForms = BlinkForms;
  window.Mustache = Mustache;
  window.Promise = Promise;

  require(['main'], function () {
    console.log('BIC started!');
  });
});
<|endoftext|>


<commit_before>//******************************
// Tooltip v:0.1.a, 2013, jQuery plugin
// Creater: Egor Podgaiski, http://gorik.name/
// Dual licensed under the MIT and GPL licenses:
// http://www.opensource.org/licenses/mit-license.php
// http://www.gnu.org/licenses/gpl.html
// I Am ...
//******************************
(function($){
    $.fn.toolTip = function(options){

        var settings = $.extend({
            interval : 500, // интервал перед затуханием
            duration : 400, // длительность затухания
            left : 0, //смещение по горизонтали относительно центра элемента
            top : 0, // смещение по вертикали относительно верха элемента
            content : null, // jq объект содержащий контент для тултипа
            action : '' // альтернативный вызов тултипа ("","click")
        }, options);

        return this.each(function(){

            var el = $(this),
                tooltip = null;
                action = settings.action;

            document.toolTipTimeout = 0;

            if (!$('#toolTipBox').length){
                tooltip = $('<div/>',{
                    'class':'tooltip',
                    id:'toolTipBox',
                    style:'position:absolute; display:none;'
                })
                $('body').append(tooltip);
            }
            else{
                tooltip = $('#toolTipBox');
                tooltip.off(); /*TODO придумать способ добавлять одиножды event*/
            }

            if (!el.hasClass('this_tooltip')){
                el.addClass('this_tooltip')
            }

            if (action != ''){
                el.on({
                    click: function(event){
                        var el = $(this),
                            elOffset = el.offset(),
                            tooltipTop = 0,
                            tooltipLeft = 0,
                            defText = '';

                        window.clearTimeout(document.toolTipTimeout);

                        defText = el.find(".tooltip_text");

                        if (settings.content && settings.content != ''){
                            tooltip.html($(settings.content).html());
                        }
                        else if (defText.length && defText.html() != ''){
                            tooltip.html(defText.html());
                        }
                        else{
                            if(tooltip.is(':visible')){
                                tooltip.hide();
                                tooltip.html('');
                            }
                            return;
                        }

                        tooltipTop = elOffset.top - tooltip.outerHeight() + settings.top;
                        tooltipLeft = elOffset.left + (el.outerWidth())/2 - (tooltip.outerWidth()/2) + settings.left;

                        tooltip.css({
                            "top": tooltipTop + "px",
                            "left": tooltipLeft + "px"
                        })
                        .fadeIn(settings.duration);

                        document.toolTipTimeout = window.setTimeout(function(){
                            tooltip.fadeOut('fast');
                        },settings.interval);

                    }
                });
            }
            else{
                el.on({
                    mouseenter: function(event){
                        var el = $(this),
                            elOffset = el.offset(),
                            tooltipTop = '',
                            tooltipLeft = '',
                            defText = '';

                        window.clearTimeout(document.toolTipTimeout);

                        if (tooltip.fadeInStarted) return;

                        defText = el.find(".tooltip_text");

                        if (settings.content && settings.content.html() != ''){
                            tooltip.html(settings.content.html());
                        }
                        else if (defText.length && defText.html() != ''){
                            tooltip.html(defText.html());
                        }

                        tooltipTop = elOffset.top - tooltip.outerHeight() + settings.top;
                        tooltipLeft = elOffset.left + (el.outerWidth())/2 - (tooltip.outerWidth()/2) + settings.left;

                        tooltip.fadeInStarted = true;
                        tooltip.css({
                            "top": tooltipTop,
                            "left": tooltipLeft
                        }).fadeIn(settings.duration, function(){
                            tooltip.fadeInStarted = false;
                        });

                    },
                    mouseleave: function(){
                        document.toolTipTimeout = window.setTimeout(function(){
                            tooltip.fadeOut('fast');
                        },settings.interval);
                    }
                });
            }

            tooltip.on("mouseenter", function(event){
                window.clearTimeout(document.toolTipTimeout);
            });

            tooltip.on("mouseleave", function(event){
                document.toolTipTimeout = window.setTimeout(function(){
                    $('#toolTipBox').fadeOut('fast');
                },settings.interval);
            });
        });
    }
})(jQuery);<commit_msg>Fixed bug ws settings Temporary added property styleClass<commit_after>//******************************
// Tooltip v:0.1.a, 2013, jQuery plugin
// Creater: Egor Podgaiski, http://gorik.name/
// Dual licensed under the MIT and GPL licenses:
// http://www.opensource.org/licenses/mit-license.php
// http://www.gnu.org/licenses/gpl.html
// I Am ...
//******************************
(function($){
    $.fn.toolTip = function(options){

        var settings = $.extend({
            interval : 500, // интервал перед затуханием
            ttLeaveInterval : 500, // интервал перед затуханием после увода мыши с подсказки
            duration : 400, // длительность затухания
            left : 0, //смещение по горизонтали относительно центра элемента
            top : 0, // смещение по вертикали относительно верха элемента
            content : null, // jq объект содержащий контент для тултипа
            action : '', // альтернативный вызов тултипа ("","click")
            styleClass : '' // свой класс для изменения вида тултипа
        }, options);

        return this.each(function(){

            var el = $(this),
                tooltip = null,
                interval = settings.interval,
                ttLeaveInterval = settings.ttLeaveInterval,
                duration = settings.duration,
                top = settings.top,
                left = settings.left,
                content = settings.content,
                action = settings.action,
                styleClass = settings.styleClass;

            document.toolTipTimeout = 0;

            if (!$('#toolTipBox').length){
                tooltip = $('<div/>',{
                    'class':'tooltip',
                    id:'toolTipBox',
                    style:'position:absolute; display:none;'
                })
                $('body').append(tooltip);
            }
            else{
                tooltip = $('#toolTipBox');
                tooltip.off(); //TODO: придумать способ добавлять одиножды event
            }

            if (!el.hasClass('this_tooltip')){
                el.addClass('this_tooltip')
            }

            if (action != ''){
                el.on({
                    click: function(event){
                        var el = $(this),
                            elOffset = el.offset(),
                            tooltipTop = 0,
                            tooltipLeft = 0,
                            defText = '';

                        window.clearTimeout(document.toolTipTimeout);

                        defText = el.find(".tooltip_text");

                        if (content &&  content != ''){
                            tooltip.html($(content).html());
                        }
                        else if (defText.length && defText.html() != ''){
                            tooltip.html(defText.html());
                        }
                        else{
                            if(tooltip.is(':visible')){
                                tooltip.hide();
                                tooltip.html('');
                            }
                            return;
                        }

                        tooltipTop = elOffset.top - tooltip.outerHeight() + top;
                        tooltipLeft = elOffset.left + (el.outerWidth())/2 - (tooltip.outerWidth()/2) + left;

                        tooltip.addClass(styleClass).css({
                            "top": tooltipTop + "px",
                            "left": tooltipLeft + "px"
                        })
                        .fadeIn(duration);

                        document.toolTipTimeout = window.setTimeout(function(){
                            tooltip.fadeOut('fast', function(){
                                tooltip.removeClass(styleClass);
                            });
                        },interval);

                    }
                });
            }
            else{
                el.on({
                    mouseenter: function(event){
                        var el = $(this),
                            elOffset = el.offset(),
                            tooltipTop = '',
                            tooltipLeft = '',
                            defText = '';

                        window.clearTimeout(document.toolTipTimeout);

                        if (tooltip.fadeInStarted) return;

                        defText = el.find(".tooltip_text");

                        if (content && content.html() != ''){
                            tooltip.html(content.html());
                        }
                        else if (defText.length && defText.html() != ''){
                            tooltip.html(defText.html());
                        }

                        tooltipTop = elOffset.top - tooltip.outerHeight() + top;
                        tooltipLeft = elOffset.left + (el.outerWidth())/2 - (tooltip.outerWidth()/2) + left;

                        tooltip.fadeInStarted = true;
                        tooltip.addClass(styleClass).css({
                            "top": tooltipTop,
                            "left": tooltipLeft
                        }).fadeIn(duration, function(){
                            tooltip.fadeInStarted = false;
                        });

                    },
                    mouseleave: function(){
                        document.toolTipTimeout = window.setTimeout(function(){
                            tooltip.fadeOut('fast');
                            tooltip.removeClass(styleClass);
                        },interval);
                    }
                });
            }

            tooltip.on("mouseenter", function(event){
                window.clearTimeout(document.toolTipTimeout);
            });

            tooltip.on("mouseleave", function(event){
                document.toolTipTimeout = window.setTimeout(function(){
                    $('#toolTipBox').fadeOut('fast', function(){
                        $('#toolTipBox').attr('class', 'tooltip');/*TODO*/
                    });
                },ttLeaveInterval);
            });
        });
    }
})(jQuery);<|endoftext|>


<commit_before><commit_msg>Added watsonc api<commit_after><|endoftext|>


<commit_before>if (!XMLHttpRequest.prototype.sendAsBinary) {
  XMLHttpRequest.prototype.sendAsBinary = function (sData) {
    var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);
    for (var nIdx = 0; nIdx < nBytes; nIdx++) {
      ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;
    }
    /* send as ArrayBufferView...: */
    this.send(ui8Data);
    /* ...or as ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */
  };
}

   $('#toggleFormat').on('click', function(){$('#fileNamesTip').toggle();});

 /* var uploadURL = location.search.substr(1);
	if (uploadURL) {
	  uploadURL = decodeURIComponent(uploadURL);
	  if (uploadURL.indexOf('http://') == -1) { uploadURL = decodeURIComponent(uploadURL); }
	  $set('uploadURL', uploadURL);
	  $('otherSettings').appendChild( $('uploadUrlWr') );
	}

  RestoreLastSettingsFor( $get('uploadURL') );

  if (!GetCookie('fileNamesTipShown')) {
	$show('fileNamesTip');
	SetCookie('fileNamesTipShown', true, 48);
  }

  setInterval(function () {
	$('submit').disabled = $('files').files.length == 0 || upOptions.running;
	$style( 'tagsWr', 'display', $('tagsFromNames').checked ? 'none' : 'block' );
  }, 200);/*

var upOptions = {running: false};

function FilesSelected(selFiles) {
    if (upOptions.running) { return; }

  upOptions = UploadOptions();
    if (upOptions.auth.use && !IsNum(upOptions.auth.userID)) {
      alert('Wrong user ID - it must be a number.');
      return;
    }
    if (upOptions.auth.use && upOptions.auth.ticket.length != 40) {
      alert('Wrong ticket - it must be 40 characters long.');
      return;
    }

  upOptions.running = true;

  try {
    var files = [];

      $each(selFiles, function (file) {
        if (IsUploadable(file)) { files.push(file); }
      });

    SendFiles(files);
  } catch (e) {
    if (typeof e == 'string') {
      alert('Couldn\'t upload - ' + e);
    } else {
      alert("Exception has occured during files submission. Like it\'s said, this script works only with Firefox 3.6+.\n" + e.message);
    }
  }
}

  function IsUploadable(file) {
    return (typeof file.type == 'string' ? file.type.substr(0, 6) == 'image/' : true)
           && /(jpe?g|gif|png|bmp)$/i.test(file.name);
  }

  function OnFirstUpload(files) {
    SaveLastSettings();

    Log('info', 'Started uploading ' + upOptions.stats.total + ' files.');
    UpdateUpProgress(0);
  }

  function OnAllUploaded() {
    upOptions.running = false;

      var msg = 'Finished uploading; ' + upOptions.stats.success + ' uploaded ok + ' +
                upOptions.stats.failed + ' failed = ' +
                upOptions.stats.total + ' images total.';
    Log('info end', msg);

    $set('status', '');
    UpdateUpProgress(0);

    var ourBooru = upOptions.uploadURL.match(/^http:\/\/([\w\d-]+)\.booru\.org\//i);
      if (ourBooru) {
          var baseCtrUpdURL = 'http://booru.org/?action=updateimagecount&updateimagecount[booru]=';

        var image = new Image();
            image.src = baseCtrUpdURL + ourBooru[1] + '&rand=' + Math.random();
      }
  }

  function UploadOptions() {
      var rating = {when: $('forceRating').checked ? 'always' : 'default',
                    set:  $('setSafe').checked  ? 's' :
                            $('setQuest').checked ? 'q' : 'e'};

      var tagging = {when: $('tagsFromNames').checked ? 'name' :
                           $('forceTags').checked ? 'always' : 'add',
                     set: $get('tags').toLowerCase().split(/\s+/)};

      var auth = {userID: $get('userID'), ticket: $get('ticket')};
          auth.use = auth.userID != '' || auth.ticket != '';

      var tagmeStart = $get('tagmeStart');
          tagmeStart = IsNum(tagmeStart) ? tagmeStart : 4;

    return {delay: 1000, uploadURL: $get('uploadURL'), title: $get('title'),
            tagmeStart: tagmeStart, rating: rating, tagging: tagging,
            stats: {total: 0, success: 0, failed: 0}, auth: auth};
  }

  function Log(className, msg) {
      var now = new Date;
      msg = '[' + now.getHours() + ':' + now.getMinutes() + '] ' + msg;

    $show('log');

      if ($('log').childNodes.length > 200) {
        var log = $('log');
        while (child = log.firstChild) { log.removeChild(child); }
      }

    var line = document.createElement('div');
        line.className = className;
        line.innerHTML = EscapeHTML(msg);

    $('log').appendChild(line);
  }

    function EscapeHTML(str) {
        var entity = {'&': '&', '<': '<', '>': '>'};
      return str.replace(/&|<|>/g, function (ch) {
        return entity[ ch[0] ];
      });
    }

    function LogSuccess(file) {
      Log('success', 'Image ' + file.name + ' was successfully uploaded.');
      upOptions.stats.success++;
    }

    function LogFailure(file, reason) {
      Log('error', 'Couldn\'t upload ' + file.name + ': ' + reason + '.');
      upOptions.stats.failed++;
    }

  function SendFiles(files, index) {
      index = index || 0;

    if (index < files.length) {
      if (index == 0) {
        upOptions.stats.total = files.length;
        OnFirstUpload(files);
      }

      SendFile( files[index], function () { SendFiles(files, index + 1); } );
      $set('status', 'Uploading #' + (index + 1) + ' image out of ' + files.length + '...');
    } else {
      OnAllUploaded();
    }
  }

    function SendFile(file, callback) {
      var reqVars = {title: upOptions.title, tags: TagsFor(file),
                     rating: RatingFor(file), submit: 'Upload'};
      if (upOptions.auth.use) {
        reqVars.cookies = 'user_id=' +   upOptions.auth.userID + '; ' +
                          'pass_hash=' + upOptions.auth.ticket;
      }

      var xhr = CreateXHRequest();

      xhr.onreadystatechange = function () {
        if (this.readyState == 4 && (this.status == 200 || this.status == 304 /*not modified*/)) {
          // "mage" instead of "image" because first "I" might be capitalized.
          if (this.responseText.indexOf('mage added') != -1) {
            LogSuccess(file);
          } else if (this.responseText.indexOf('already exists') != -1) {
            LogFailure(file, 'this image already exists');
          } else if (this.responseText.indexOf('permission') != -1) {
            LogFailure(file, 'no permissions');

              var msg = 'Could not upload this image - the board says we\'ve got no permissions.\nMaybe wrong ticket? Stopped.';
            alert(msg);
            OnAllUploaded();

            throw msg;
          } else {
            LogFailure(file, 'wrong response, check your posting form URL');
          }

          UpdateUpProgress( (upOptions.stats.success + upOptions.stats.failed) / upOptions.stats.total );
          setTimeout(callback, upOptions.delay);
        }
      }

      var boundary = '--bOh3aYae';
      var EOLN = "\r\n";

      var postVars = '';

        for (var name in reqVars) {
          postVars += boundary + EOLN +
                      'Content-Disposition: form-data; name="' + name + '"' + EOLN +
                      EOLN + reqVars[name] + EOLN;
        }

      var reader = new FileReader;

          reader.onloadend = function () {
            var data = boundary + EOLN +
                       'Content-Disposition: form-data; name="upload";' +
                          ' filename="' + file.name + '"' + EOLN +
                       'Content-Type: application/octet-stream' + EOLN +
                       'Content-Transfer-Encoding: binary' + EOLN +
                       EOLN +
                         reader.result + EOLN +
                         postVars +
                       boundary + '--';

            xhr.open('POST', ProxyUrlFor(upOptions.uploadURL));
              xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary.substr(2));
              xhr.setRequestHeader('Content-Length', data.length);
            xhr.sendAsBinary(data);
          }

      reader.readAsBinaryString(file);
    }

    function UpdateUpProgress(percent) {
      WidthOf('progress', WidthOf('progressWr') * percent);
    }

      function RatingFor(file) { return InfoAbout(file)[0]; }
      function TagsFor(file) { return NormTags( InfoAbout(file)[1] ); }

        function InfoAbout(file) {
            var fileName = file.name.toLowerCase();

          var ext = fileName.match(/ *\.(\w{2,4})$/i);
          if (ext) { fileName = fileName.replace(ext[0], ''); }

            if (!ext) {
              throw 'File ' + file.name + ' have no extension.';
            } else {
              ext = ext[1];
            }

          var rating = fileName.match(/^([sqe])( +|$)/i);
          if (rating) { fileName = fileName.replace(rating[0], ''); }

            if (upOptions.rating.when == 'always' || !rating) {
              rating = upOptions.rating.set;
            } else {
              rating = rating[1];
            }

          var tags = fileName;

          return [rating, tags, ext];
        }

        function NormTags(tags) {
          tags = tags.toLowerCase().split(/\s+/);

            tags = ArrayUnique( tags.sort() );
            if (tags[0] == '') { tags.shift(); }

          if (tags.length < upOptions.tagmeStart) {
            tags.push('tagme');
            tags = tags.sort();
          }

            switch (upOptions.tagging.when) {
            case 'name':
              break;
            case 'always':
              tags = [];
            case 'add':
              tags = tags.concat(upOptions.tagging.set);
              tags = ArrayUnique( tags.sort() );
            }

          return tags.join(' ');
        }

          function ArrayUnique(src) {
            var unique = [];

              $each(src, function (item, index) {
                var dup = false;

                  $each(unique, function (item2, index2) {
                    if (index != index2 && item == item2) {
                      dup = true;
                      return true;
                    }
                  });

                if (!dup) { unique.push(item); }
              });

            return unique;
          }

      // XHR doesn't allow cross-domains requests.
      function ProxyUrlFor(url) {
        return url;
      }

  var settingsToSave = ['userID', 'ticket', 'tags', 'tagmeStart'];

  var checkboxesToSave = ['forceRating', 'ratingAsDefault',
                            'setSafe', 'setQuest', 'setExplicit',
                          'tagsFromNames', 'forceTags', 'addTags'];

function RestoreLastSettingsFor(uploadURL) {
  var cookieBaseName = CookieSettingsBaseNameFor(uploadURL);

  $each(settingsToSave, function (setting) {
    var lastValue = GetCookie(cookieBaseName + setting);
    if (lastValue) {
      if (!$get(setting) || (setting == 'tagmeStart' && $get(setting) == 4)) {
        $set(setting, lastValue);
      }
    }
  });

  $each(checkboxesToSave, function (setting) {
    var lastValue = GetCookie(cookieBaseName + setting);
    if (IsNum(lastValue)) { $(setting).checked = lastValue == '1'; }
  });
}

  function CookieSettingsBaseNameFor(uploadURL) {
    var domain = '';
      var matches = uploadURL.match(/^(http:\/\/)?(www\.)?([^\/]+)/i);
      if (matches) { domain = matches[3].replace(/\W/g, '-'); }

    return 'last@' + domain + ':';
  }

  function SaveLastSettings() {
    var cookieBaseName = CookieSettingsBaseNameFor(upOptions.uploadURL);

    $each(settingsToSave, function (setting) {
      SetCookie( cookieBaseName + setting, $get(setting), 7 * 24 * 3600 );
    });

    $each(checkboxesToSave, function (setting) {
      SetCookie( cookieBaseName + setting, $(setting).checked ? '1' : '0', 7 * 24 * 3600 );
    });
  }
<commit_msg>le fu~<commit_after>if (!XMLHttpRequest.prototype.sendAsBinary) {
  XMLHttpRequest.prototype.sendAsBinary = function (sData) {
    var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);
    for (var nIdx = 0; nIdx < nBytes; nIdx++) {
      ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;
    }
    /* send as ArrayBufferView...: */
    this.send(ui8Data);
    /* ...or as ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */
  };
}

   $('#toggleFormat').on('click', function(){$('#fileNamesTip').toggle();});

 /* var uploadURL = location.search.substr(1);
	if (uploadURL) {
	  uploadURL = decodeURIComponent(uploadURL);
	  if (uploadURL.indexOf('http://') == -1) { uploadURL = decodeURIComponent(uploadURL); }
	  $set('uploadURL', uploadURL);
	  $('otherSettings').appendChild( $('uploadUrlWr') );
	}

  RestoreLastSettingsFor( $get('uploadURL') );

  if (!GetCookie('fileNamesTipShown')) {
	$show('fileNamesTip');
	SetCookie('fileNamesTipShown', true, 48);
  }

  setInterval(function () {
	$('submit').disabled = $('files').files.length == 0 || upOptions.running;
	$style( 'tagsWr', 'display', $('tagsFromNames').checked ? 'none' : 'block' );
  }, 200);*/

var upOptions = {running: false};

function FilesSelected(selFiles) {
    if (upOptions.running) { return; }

  upOptions = UploadOptions();
    if (upOptions.auth.use && !IsNum(upOptions.auth.userID)) {
      alert('Wrong user ID - it must be a number.');
      return;
    }
    if (upOptions.auth.use && upOptions.auth.ticket.length != 40) {
      alert('Wrong ticket - it must be 40 characters long.');
      return;
    }

  upOptions.running = true;

  try {
    var files = [];

      $each(selFiles, function (file) {
        if (IsUploadable(file)) { files.push(file); }
      });

    SendFiles(files);
  } catch (e) {
    if (typeof e == 'string') {
      alert('Couldn\'t upload - ' + e);
    } else {
      alert("Exception has occured during files submission. Like it\'s said, this script works only with Firefox 3.6+.\n" + e.message);
    }
  }
}

  function IsUploadable(file) {
    return (typeof file.type == 'string' ? file.type.substr(0, 6) == 'image/' : true)
           && /(jpe?g|gif|png|bmp)$/i.test(file.name);
  }

  function OnFirstUpload(files) {
    SaveLastSettings();

    Log('info', 'Started uploading ' + upOptions.stats.total + ' files.');
    UpdateUpProgress(0);
  }

  function OnAllUploaded() {
    upOptions.running = false;

      var msg = 'Finished uploading; ' + upOptions.stats.success + ' uploaded ok + ' +
                upOptions.stats.failed + ' failed = ' +
                upOptions.stats.total + ' images total.';
    Log('info end', msg);

    $set('status', '');
    UpdateUpProgress(0);

    var ourBooru = upOptions.uploadURL.match(/^http:\/\/([\w\d-]+)\.booru\.org\//i);
      if (ourBooru) {
          var baseCtrUpdURL = 'http://booru.org/?action=updateimagecount&updateimagecount[booru]=';

        var image = new Image();
            image.src = baseCtrUpdURL + ourBooru[1] + '&rand=' + Math.random();
      }
  }

  function UploadOptions() {
      var rating = {when: $('forceRating').checked ? 'always' : 'default',
                    set:  $('setSafe').checked  ? 's' :
                            $('setQuest').checked ? 'q' : 'e'};

      var tagging = {when: $('tagsFromNames').checked ? 'name' :
                           $('forceTags').checked ? 'always' : 'add',
                     set: $get('tags').toLowerCase().split(/\s+/)};

      var auth = {userID: $get('userID'), ticket: $get('ticket')};
          auth.use = auth.userID != '' || auth.ticket != '';

      var tagmeStart = $get('tagmeStart');
          tagmeStart = IsNum(tagmeStart) ? tagmeStart : 4;

    return {delay: 1000, uploadURL: $get('uploadURL'), title: $get('title'),
            tagmeStart: tagmeStart, rating: rating, tagging: tagging,
            stats: {total: 0, success: 0, failed: 0}, auth: auth};
  }

  function Log(className, msg) {
      var now = new Date;
      msg = '[' + now.getHours() + ':' + now.getMinutes() + '] ' + msg;

    $show('log');

      if ($('log').childNodes.length > 200) {
        var log = $('log');
        while (child = log.firstChild) { log.removeChild(child); }
      }

    var line = document.createElement('div');
        line.className = className;
        line.innerHTML = EscapeHTML(msg);

    $('log').appendChild(line);
  }

    function EscapeHTML(str) {
        var entity = {'&': '&', '<': '<', '>': '>'};
      return str.replace(/&|<|>/g, function (ch) {
        return entity[ ch[0] ];
      });
    }

    function LogSuccess(file) {
      Log('success', 'Image ' + file.name + ' was successfully uploaded.');
      upOptions.stats.success++;
    }

    function LogFailure(file, reason) {
      Log('error', 'Couldn\'t upload ' + file.name + ': ' + reason + '.');
      upOptions.stats.failed++;
    }

  function SendFiles(files, index) {
      index = index || 0;

    if (index < files.length) {
      if (index == 0) {
        upOptions.stats.total = files.length;
        OnFirstUpload(files);
      }

      SendFile( files[index], function () { SendFiles(files, index + 1); } );
      $set('status', 'Uploading #' + (index + 1) + ' image out of ' + files.length + '...');
    } else {
      OnAllUploaded();
    }
  }

    function SendFile(file, callback) {
      var reqVars = {title: upOptions.title, tags: TagsFor(file),
                     rating: RatingFor(file), submit: 'Upload'};
      if (upOptions.auth.use) {
        reqVars.cookies = 'user_id=' +   upOptions.auth.userID + '; ' +
                          'pass_hash=' + upOptions.auth.ticket;
      }

      var xhr = CreateXHRequest();

      xhr.onreadystatechange = function () {
        if (this.readyState == 4 && (this.status == 200 || this.status == 304 /*not modified*/)) {
          // "mage" instead of "image" because first "I" might be capitalized.
          if (this.responseText.indexOf('mage added') != -1) {
            LogSuccess(file);
          } else if (this.responseText.indexOf('already exists') != -1) {
            LogFailure(file, 'this image already exists');
          } else if (this.responseText.indexOf('permission') != -1) {
            LogFailure(file, 'no permissions');

              var msg = 'Could not upload this image - the board says we\'ve got no permissions.\nMaybe wrong ticket? Stopped.';
            alert(msg);
            OnAllUploaded();

            throw msg;
          } else {
            LogFailure(file, 'wrong response, check your posting form URL');
          }

          UpdateUpProgress( (upOptions.stats.success + upOptions.stats.failed) / upOptions.stats.total );
          setTimeout(callback, upOptions.delay);
        }
      }

      var boundary = '--bOh3aYae';
      var EOLN = "\r\n";

      var postVars = '';

        for (var name in reqVars) {
          postVars += boundary + EOLN +
                      'Content-Disposition: form-data; name="' + name + '"' + EOLN +
                      EOLN + reqVars[name] + EOLN;
        }

      var reader = new FileReader;

          reader.onloadend = function () {
            var data = boundary + EOLN +
                       'Content-Disposition: form-data; name="upload";' +
                          ' filename="' + file.name + '"' + EOLN +
                       'Content-Type: application/octet-stream' + EOLN +
                       'Content-Transfer-Encoding: binary' + EOLN +
                       EOLN +
                         reader.result + EOLN +
                         postVars +
                       boundary + '--';

            xhr.open('POST', ProxyUrlFor(upOptions.uploadURL));
              xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary.substr(2));
              xhr.setRequestHeader('Content-Length', data.length);
            xhr.sendAsBinary(data);
          }

      reader.readAsBinaryString(file);
    }

    function UpdateUpProgress(percent) {
      WidthOf('progress', WidthOf('progressWr') * percent);
    }

      function RatingFor(file) { return InfoAbout(file)[0]; }
      function TagsFor(file) { return NormTags( InfoAbout(file)[1] ); }

        function InfoAbout(file) {
            var fileName = file.name.toLowerCase();

          var ext = fileName.match(/ *\.(\w{2,4})$/i);
          if (ext) { fileName = fileName.replace(ext[0], ''); }

            if (!ext) {
              throw 'File ' + file.name + ' have no extension.';
            } else {
              ext = ext[1];
            }

          var rating = fileName.match(/^([sqe])( +|$)/i);
          if (rating) { fileName = fileName.replace(rating[0], ''); }

            if (upOptions.rating.when == 'always' || !rating) {
              rating = upOptions.rating.set;
            } else {
              rating = rating[1];
            }

          var tags = fileName;

          return [rating, tags, ext];
        }

        function NormTags(tags) {
          tags = tags.toLowerCase().split(/\s+/);

            tags = ArrayUnique( tags.sort() );
            if (tags[0] == '') { tags.shift(); }

          if (tags.length < upOptions.tagmeStart) {
            tags.push('tagme');
            tags = tags.sort();
          }

            switch (upOptions.tagging.when) {
            case 'name':
              break;
            case 'always':
              tags = [];
            case 'add':
              tags = tags.concat(upOptions.tagging.set);
              tags = ArrayUnique( tags.sort() );
            }

          return tags.join(' ');
        }

          function ArrayUnique(src) {
            var unique = [];

              $each(src, function (item, index) {
                var dup = false;

                  $each(unique, function (item2, index2) {
                    if (index != index2 && item == item2) {
                      dup = true;
                      return true;
                    }
                  });

                if (!dup) { unique.push(item); }
              });

            return unique;
          }

      // XHR doesn't allow cross-domains requests.
      function ProxyUrlFor(url) {
        return url;
      }

  var settingsToSave = ['userID', 'ticket', 'tags', 'tagmeStart'];

  var checkboxesToSave = ['forceRating', 'ratingAsDefault',
                            'setSafe', 'setQuest', 'setExplicit',
                          'tagsFromNames', 'forceTags', 'addTags'];

function RestoreLastSettingsFor(uploadURL) {
  var cookieBaseName = CookieSettingsBaseNameFor(uploadURL);

  $each(settingsToSave, function (setting) {
    var lastValue = GetCookie(cookieBaseName + setting);
    if (lastValue) {
      if (!$get(setting) || (setting == 'tagmeStart' && $get(setting) == 4)) {
        $set(setting, lastValue);
      }
    }
  });

  $each(checkboxesToSave, function (setting) {
    var lastValue = GetCookie(cookieBaseName + setting);
    if (IsNum(lastValue)) { $(setting).checked = lastValue == '1'; }
  });
}

  function CookieSettingsBaseNameFor(uploadURL) {
    var domain = '';
      var matches = uploadURL.match(/^(http:\/\/)?(www\.)?([^\/]+)/i);
      if (matches) { domain = matches[3].replace(/\W/g, '-'); }

    return 'last@' + domain + ':';
  }

  function SaveLastSettings() {
    var cookieBaseName = CookieSettingsBaseNameFor(upOptions.uploadURL);

    $each(settingsToSave, function (setting) {
      SetCookie( cookieBaseName + setting, $get(setting), 7 * 24 * 3600 );
    });

    $each(checkboxesToSave, function (setting) {
      SetCookie( cookieBaseName + setting, $(setting).checked ? '1' : '0', 7 * 24 * 3600 );
    });
  }
<|endoftext|>


<commit_before>Spell = function(game, startPosition, endPosition, type) {
    //Phaser.Sprite.call(this, game, initX, initY, 'hero');
    Phaser.Graphics.call(this, game, 0, 0);

    this.game = game;
    this.startPosition = startPosition;
    this.endPosition = endPosition;
    this.spellType = type;
    this.game.add.existing(this);

    if (this.startPosition['x'] === this.endPosition['x']) {
        this.direction = 'vertical';
    } else {
        this.direction = 'horizontal'
    }
    this.clear();
    if (this.spellType == 'TANK_AOE') {
        this.drawTankAOE();
    } else if (this.spellType == 'MAGE_DIRECT_DAMAGE') {
        this.drawFireball();
    } else if (this.spellType == 'MAGE_AOE') {
        this.drawFireAOE();
    } else if (this.spellType == 'HEALER_HEAL') {
        this.drawHeal();
    } else if (this.spellType == 'HEALER_DIRECT_DAMAGE') {
        this.drawHealerDamage();
    } else if (this.spellType == 'TANK_ATTACK') {
        this.drawTankAttack();
    } else {
        this.drawLine();
    }

    this.frame = 15;
    this.frameMax = 15;

    this.maxWidth = this.width;
    this.maxHeight = this.height;
    //setTimeout(this.destroy.bind(this), 1000);
};

Spell.prototype = Object.create(Phaser.Graphics.prototype);
Spell.prototype.constructor = Spell;

Spell.prototype.drawLine = function() {
    this.lineStyle(5, Math.floor(Math.random() * 16777215), 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawFireball = function() {
    this.lineStyle(5, 16729088, 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawFireAOE = function() {
    this.lineStyle(5, 16729088, 0.8);
    this.beginFill(16769024, 0.5);
    this.drawCircle(this.startPosition['x'], this.startPosition['y'], 80);
}

Spell.prototype.drawHeal = function() {
    this.lineStyle(5, 57876, 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawHealerDamage = function() {
    this.lineStyle(5, 16364288, 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawTankAttack = function() {
    this.lineStyle(5, 11184810, 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawTankAOE = function() {
    this.lineStyle(5, 11184810, 0.8);
    this.beginFill(13421772, 0.5);
    this.drawCircle(this.startPosition['x'], this.startPosition['y'], 80);
}

<commit_msg>put ze animation bakz<commit_after>Spell = function(game, startPosition, endPosition, type) {
    //Phaser.Sprite.call(this, game, initX, initY, 'hero');
    Phaser.Graphics.call(this, game, 0, 0);

    this.game = game;
    this.startPosition = startPosition;
    this.endPosition = endPosition;
    this.spellType = type;
    this.game.add.existing(this);

    if (this.startPosition['x'] === this.endPosition['x']) {
        this.direction = 'vertical';
    } else {
        this.direction = 'horizontal'
    }

    if (this.spellType == 'TANK_AOE') {
        this.drawTankAOE();
    } else if (this.spellType == 'MAGE_DIRECT_DAMAGE') {
        this.drawFireball();
    } else if (this.spellType == 'MAGE_AOE') {
        this.drawFireAOE();
    } else if (this.spellType == 'HEALER_HEAL') {
        this.drawHeal();
    } else if (this.spellType == 'HEALER_DIRECT_DAMAGE') {
        this.drawHealerDamage();
    } else if (this.spellType == 'TANK_ATTACK') {
        this.drawTankAttack();
    } else {
        this.drawLine();
    }

    this.frame = 15;
    this.frameMax = 15;

    this.maxWidth = this.width;
    this.maxHeight = this.height;
    //setTimeout(this.destroy.bind(this), 100);
};

Spell.prototype = Object.create(Phaser.Graphics.prototype);
Spell.prototype.constructor = Spell;

Spell.prototype.drawLine = function() {
    this.clear();
    this.lineStyle(5, Math.floor(Math.random() * 16777215), 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawFireball = function() {
    this.clear();
    this.lineStyle(5, 16729088, 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawFireAOE = function() {
    this.lineStyle(5, 16729088, 0.8);
    this.beginFill(16769024, 0.5);
    this.drawCircle(this.startPosition['x'], this.startPosition['y'], 80);
}

Spell.prototype.drawHeal = function() {
    this.clear();
    this.lineStyle(5, 57876, 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawHealerDamage = function() {
    this.clear();
    this.lineStyle(5, 16364288, 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawTankAttack = function() {
    this.clear();
    this.lineStyle(5, 11184810, 1);
    this.moveTo(this.startPosition['x'], this.startPosition['y']);
    this.lineTo(this.endPosition['x'], this.endPosition['y']);
}

Spell.prototype.drawTankAOE = function() {
    this.lineStyle(5, 11184810, 0.8);
    this.beginFill(13421772, 0.5);
    this.drawCircle(this.startPosition['x'], this.startPosition['y'], 80);
}

Spell.prototype.update = function() {
    if (this.spellType == 'TANK_AOE') {

    } else {
        if (this.direction === 'vertical') {
            this.startPosition.y = this.startPosition.y + (this.endPosition.y - this.startPosition.y) * ((this.frameMax - this.frame) / this.frameMax);
        } else {
            this.startPosition.x = this.startPosition.x + (this.endPosition.x - this.startPosition.x) * ((this.frameMax - this.frame) / this.frameMax);
        }
        if (this.spellType == 'MAGE_DIRECT_DAMAGE') {
            this.drawFireball();
        } else if (this.spellType == 'MAGE_AOE') {
            this.drawFireAOE();
        } else if (this.spellType == 'HEALER_HEAL') {
            this.drawHeal();
        } else if (this.spellType == 'HEALER_DIRECT_DAMAGE') {
            this.drawHealerDamage();
        } else if (this.spellType == 'TANK_ATTACK') {
            this.drawTankAttack();
        } else {
            this.drawLine();
        }
    }
    this.frame--;
};
<|endoftext|>


<commit_before>/* implements selecting webviews, switching between them, and creating new ones. */

var createView = remote.getGlobal('createView')
var destroyView = remote.getGlobal('destroyView')
var getView = remote.getGlobal('getView')
var getContents = remote.getGlobal('getContents')

var placeholderImg = document.getElementById('webview-placeholder')

var windowIsFullscreen = false // TODO track this for each individual webContents

if (window.platformType === 'windows') {
  var navbarHeight = 46 // used to set the bounds of the view
} else {
  var navbarHeight = 36
}

function lazyRemoteObject (getObject) {
  var cachedItem = null
  return new Proxy({}, {
    get: function (obj, prop) {
      if (!cachedItem) {
        cachedItem = getObject()
      }
      return cachedItem[prop]
    }
  })
}

// the permissionRequestHandler used for webviews
function pagePermissionRequestHandler (webContents, permission, callback) {
  if (permission === 'notifications' || permission === 'fullscreen') {
    callback(true)
  } else {
    callback(false)
  }
}

function getViewBounds () {
  if (windowIsFullscreen) {
    return {
      x: 0,
      y: 0,
      width: window.innerWidth,
      height: window.innerHeight
    }
  }
  return {
    x: 0,
    y: navbarHeight,
    width: window.innerWidth,
    height: window.innerHeight - 36
  }
}

function captureCurrentTab () {
  ipc.send('getCapture', {
    id: tabs.getSelected(),
    width: Math.round(window.innerWidth / 10),
    height: Math.round(window.innerHeight / 10)
  })
}

// set the permissionRequestHandler for non-private tabs

remote.session.defaultSession.setPermissionRequestHandler(pagePermissionRequestHandler)

// called whenever the page url changes

function onPageLoad (e) {
  var _this = this
  setTimeout(function () { // TODO convert to arrow function
    /* add a small delay before getting these attributes, because they don't seem to update until a short time after the did-finish-load event is fired. Fixes #320 */

    // var tab = _this.getAttribute('data-tab')
    // var url = _this.getAttribute('src') // src attribute changes whenever a page is loaded
    var tab = webviews.getTabFromContents(_this)
    var url = _this.getURL()

    // if the page is an error page, the URL is really the value of the "url" query parameter
    if (url.startsWith(webviews.internalPages.error) || url.startsWith(webviews.internalPages.crash)) {
      url = new URLSearchParams(new URL(url).search).get('url')
    }

    if (url.indexOf('https://') === 0 || url.indexOf('about:') === 0 || url.indexOf('chrome:') === 0 || url.indexOf('file://') === 0) {
      tabs.update(tab, {
        secure: true,
        url: url
      })
    } else {
      tabs.update(tab, {
        secure: false,
        url: url
      })
    }

    tabBar.rerenderTab(tab)

    // capture a preview image if necessary

    if (tab === tabs.getSelected() && tabs.get(tab).url && tabs.get(tab).url !== 'about:blank' && !tabs.get(tab).previewImage) {
      captureCurrentTab()
    }
  }, 0)
}

window.webviews = {
  container: document.getElementById('webviews'),
  elementMap: {}, // tabId: webview
  tabViewMap: {}, // tabId: browserView
  tabContentsMap: {}, // tabId: webContents
  selectedId: null,
  placeholderRequests: [],
  internalPages: {
    crash: 'file://' + __dirname + '/pages/crash/index.html',
    error: 'file://' + __dirname + '/pages/error/index.html'
  },
  events: [],
  IPCEvents: [],
  bindEvent: function (event, fn, options) {
    webviews.events.push({
      event: event,
      fn: fn,
      options: options
    })
  },
  bindIPC: function (name, fn) {
    webviews.IPCEvents.push({
      name: name,
      fn: fn
    })
  },
  add: function (tabId) {
    var tabData = tabs.get(tabId)

    // if the tab is private, we want to partition it. See http://electron.atom.io/docs/v0.34.0/api/web-view-tag/#partition
    // since tab IDs are unique, we can use them as partition names
    if (tabs.get(tabId).private === true) {
      var partition = tabId.toString() // options.tabId is a number, which remote.session.fromPartition won't accept. It must be converted to a string first

      // register permissionRequestHandler for this tab
      // private tabs use a different session, so the default permissionRequestHandler won't apply

      remote.session.fromPartition(partition).setPermissionRequestHandler(pagePermissionRequestHandler)

      // enable ad/tracker/contentType blocking in this tab if needed

      registerFiltering(partition)
    }

    ipc.send('createView', {
      id: tabId,
      webPreferencesString: JSON.stringify({
        webPreferences: {
          nodeIntegration: false,
          scrollBounce: true,
          preload: __dirname + '/dist/preload.js', // TODO fix on windows
          allowPopups: false,
          partition: partition
        }
      }),
      boundsString: JSON.stringify(getViewBounds()),
      events: webviews.events
    })
    /*
        let view = createView(
          tabId,
          JSON.stringify({
            webPreferences: {
              nodeIntegration: false,
              scrollBounce: true,
              preload: __dirname + '/dist/preload.js', // TODO fix on windows
              allowPopups: false,
              partition: partition
            }
          }),
          JSON.stringify(getViewBounds()),
          webviews.events
        )
        */

    let view = lazyRemoteObject(function () {
      return getView(tabId)
    })

    let contents = lazyRemoteObject(function () {
      return getView(tabId).webContents
    })

    /*    contents.on('ipc-message', function (e, args) {
          var w = this
          var tab = webviews.getTabFromContents(this)

          webviews.IPCEvents.forEach(function (item) {
            if (item.name === args[0]) {
              item.fn(w, tab, args[1])
            }
          })
        })*/

    // contents.loadURL(tabData.url)
    webviews.callAsync(tabData.id, 'loadURL', tabData.url)

    webviews.tabViewMap[tabId] = view
    webviews.tabContentsMap[tabId] = contents
    return view
  },
  setSelected: function (id) {
    webviews.selectedId = id

    // create the view if it doesn't already exist
    if (!webviews.getView(id)) {
      webviews.add(id)
    }

    if (webviews.placeholderRequestCount > 0) {
      return
    }

    ipc.send('setView', {
      id: id,
      bounds: getViewBounds()
    })

  // mainWindow.setBrowserView(view)
  // view.setBounds(getViewBounds())
  },
  update: function (id, url) {
    webviews.get(id).loadURL(urlParser.parse(url))
  },
  destroy: function (id) {
    var w = webviews.tabViewMap[id]
    if (w) {
      ipc.send('destroyView', id)
    /*if (id === webviews.selectedId) {
      mainWindow.setBrowserView(null)
      webviews.selectedId = null
    }
    w.destroy()
    */
    }
    delete webviews.tabViewMap[id]
    delete webviews.tabContentsMap[id]
  },
  getView: function (id) {
    return webviews.tabViewMap[id]
  },
  get: function (id) {
    return webviews.tabContentsMap[id]
  },
  requestPlaceholder: function (reason) {
    if (!webviews.placeholderRequests.includes(reason)) {
      webviews.placeholderRequests.push(reason)
    }
    if (webviews.placeholderRequests.length === 1) {
      // create a new placeholder

      var img = tabs.get(tabs.getSelected()).previewImage
      var url = tabs.get(tabs.getSelected()).url
      if (img) {
        placeholderImg.src = img
        placeholderImg.hidden = false
      } else if (url && url !== 'about:blank') {
        captureCurrentTab()
      }
    }
    setTimeout(function () {
      ipc.send('hideView', webviews.selectedId)
    }, 0)
  },
  hidePlaceholder: function (reason) {
    webviews.placeholderRequests.splice(webviews.placeholderRequests.indexOf(reason), 1)

    if (webviews.placeholderRequests.length === 0) {
      // multiple things can request a placeholder at the same time, but we should only show the view again if nothing requires a placeholder anymore
      if (webviews.tabViewMap[webviews.selectedId]) {
        ipc.send('showView', webviews.selectedId)
      }
      placeholderImg.hidden = true
    }
  },
  getTabFromContents: function (contents) {
    for (let tabId in webviews.tabContentsMap) {
      if (webviews.tabContentsMap[tabId] === contents) {
        return tabId
      }
    }
    return null
  },
  releaseFocus: function () {
    mainWindow.webContents.focus()
  },
  focus: function (id) {
    ipc.send('focusView', id)
  },
  callAsync: function (id, method, arg) {
    ipc.send('callViewMethod', {id: id, method: method, arg: arg})
  }
}

// called when js/preload/textExtractor.js returns the page's text content
webviews.bindIPC('pageData', function (webview, tabId, args) {
  var tab = tabs.get(tabId),
    data = args[0]

  var isInternalPage = tab.url.indexOf(__dirname) !== -1 && tab.url.indexOf(readerView.readerURL) === -1

  // don't save to history if in private mode, or the page is a browser page
  if (tab.private === false && !isInternalPage) {
    bookmarks.updateHistory(tabId, data.extractedText, data.metadata)
  }
})

// called when a swipe event is triggered in js/preload/swipeEvents.js

webviews.bindIPC('goBack', function () {
  settings.get('swipeNavigationEnabled', function (value) {
    if (value === true || value === undefined) {
      webviews.get(tabs.getSelected()).goBack()
    }
  })
})

webviews.bindIPC('goForward', function () {
  settings.get('swipeNavigationEnabled', function (value) {
    if (value === true || value === undefined) {
      webviews.get(tabs.getSelected()).goForward()
    }
  })
})

/* workaround for https://github.com/electron/electron/issues/3471 */

webviews.bindEvent('new-window', function (e, url, frameName, disposition) {
  var tab = webviews.getTabFromContents(this)
  var currentIndex = tabs.getIndex(tabs.getSelected())

  var newTab = tabs.add({
    url: url,
    private: tabs.get(tab).private // inherit private status from the current tab
  }, currentIndex + 1)
  addTab(newTab, {
    enterEditMode: false,
    openInBackground: disposition === 'background-tab' // possibly open in background based on disposition
  })
}, {preventDefault: true})

window.addEventListener('resize', throttle(function () {
  ipc.send('setBounds', {id: tabs.getSelected(), bounds: getViewBounds()})
}, 100))

mainWindow.on('enter-html-full-screen', function () {
  windowIsFullscreen = true
  ipc.send('setBounds', {id: tabs.getSelected(), bounds: getViewBounds()})
})

mainWindow.on('leave-html-full-screen', function () {
  windowIsFullscreen = false
  ipc.send('setBounds', {id: tabs.getSelected(), bounds: getViewBounds()})
})

webviews.bindEvent('did-finish-load', onPageLoad)
webviews.bindEvent('did-navigate-in-page', onPageLoad)

webviews.bindEvent('page-favicon-updated', function (e, favicons) {
  var id = webviews.getTabFromContents(this)
  updateTabColor(favicons, id)
})

webviews.bindEvent('page-title-updated', function (e, title, explicitSet) {
  var tab = webviews.getTabFromContents(this)
  tabs.update(tab, {
    title: title
  })
  tabBar.rerenderTab(tab)
})

webviews.bindEvent('did-start-loading', function () {
  tabBar.handleProgressBar(webviews.getTabFromContents(this), 'start')
})

webviews.bindEvent('did-stop-loading', function () {
  tabBar.handleProgressBar(webviews.getTabFromContents(this), 'finish')
})

webviews.bindEvent('did-fail-load', function (e, errorCode, errorDesc, validatedURL, isMainFrame) {
  if (errorCode !== -3 && isMainFrame && validatedURL) {
    navigate(webviews.getTabFromContents(this), webviews.internalPages.error + '?ec=' + encodeURIComponent(errorCode) + '&url=' + encodeURIComponent(validatedURL))
  }
})

webviews.bindEvent('crashed', function (e, isKilled) {
  var tabId = webviews.getTabFromContents(this)
  var url = tabs.get(tabId).url

  tabs.update(tabId, {
    url: webviews.internalPages.crash + '?url=' + encodeURIComponent(url)
  })

  // the existing process has crashed, so we can't reuse it
  webviews.destroy(tabId)
  webviews.add(tabId)

  if (tabId === tabs.getSelected()) {
    webviews.setSelected(tabId)
  }
})

ipc.on('view-event', function (e, args) {
  webviews.events.forEach(function (ev) {
    if (ev.event === args.name) {
      ev.fn.apply(webviews.tabContentsMap[args.id], [e].concat(args.args))
    }
  })
})

ipc.on('view-ipc', function (e, data) {
  webviews.IPCEvents.forEach(function (item) {
    if (item.name === data.name) {
      item.fn(webviews.tabContentsMap[data.id], data.id, [data.data])
    }
  })
})

setInterval(function () {
  if (webviews.placeholderRequests.length > 0) {
    // capturePage doesn't work while the view is hidden
    return
  }
  captureCurrentTab()
}, 30000)

ipc.on('captureData', function (e, data) {
  tabs.update(data.id, {
    previewImage: data.url
  })
  if (data.id === tabs.getSelected() && webviews.placeholderRequests.length > 0) {
    placeholderImg.src = data.url
    placeholderImg.hidden = false
  }
})
<commit_msg>delay creating preview image until page is actually visible<commit_after>/* implements selecting webviews, switching between them, and creating new ones. */

var createView = remote.getGlobal('createView')
var destroyView = remote.getGlobal('destroyView')
var getView = remote.getGlobal('getView')
var getContents = remote.getGlobal('getContents')

var placeholderImg = document.getElementById('webview-placeholder')

var windowIsFullscreen = false // TODO track this for each individual webContents

if (window.platformType === 'windows') {
  var navbarHeight = 46 // used to set the bounds of the view
} else {
  var navbarHeight = 36
}

function lazyRemoteObject (getObject) {
  var cachedItem = null
  return new Proxy({}, {
    get: function (obj, prop) {
      if (!cachedItem) {
        cachedItem = getObject()
      }
      return cachedItem[prop]
    }
  })
}

// the permissionRequestHandler used for webviews
function pagePermissionRequestHandler (webContents, permission, callback) {
  if (permission === 'notifications' || permission === 'fullscreen') {
    callback(true)
  } else {
    callback(false)
  }
}

function getViewBounds () {
  if (windowIsFullscreen) {
    return {
      x: 0,
      y: 0,
      width: window.innerWidth,
      height: window.innerHeight
    }
  }
  return {
    x: 0,
    y: navbarHeight,
    width: window.innerWidth,
    height: window.innerHeight - 36
  }
}

function captureCurrentTab () {
  ipc.send('getCapture', {
    id: tabs.getSelected(),
    width: Math.round(window.innerWidth / 10),
    height: Math.round(window.innerHeight / 10)
  })
}

// set the permissionRequestHandler for non-private tabs

remote.session.defaultSession.setPermissionRequestHandler(pagePermissionRequestHandler)

// called whenever the page url changes

function onPageLoad (e) {
  var _this = this
  setTimeout(function () { // TODO convert to arrow function
    /* add a small delay before getting these attributes, because they don't seem to update until a short time after the did-finish-load event is fired. Fixes #320 */

    // var tab = _this.getAttribute('data-tab')
    // var url = _this.getAttribute('src') // src attribute changes whenever a page is loaded
    var tab = webviews.getTabFromContents(_this)
    var url = _this.getURL()

    // if the page is an error page, the URL is really the value of the "url" query parameter
    if (url.startsWith(webviews.internalPages.error) || url.startsWith(webviews.internalPages.crash)) {
      url = new URLSearchParams(new URL(url).search).get('url')
    }

    if (url.indexOf('https://') === 0 || url.indexOf('about:') === 0 || url.indexOf('chrome:') === 0 || url.indexOf('file://') === 0) {
      tabs.update(tab, {
        secure: true,
        url: url
      })
    } else {
      tabs.update(tab, {
        secure: false,
        url: url
      })
    }

    tabBar.rerenderTab(tab)

    // capture a preview image if necessary

    if (tab === tabs.getSelected() && tabs.get(tab).url && tabs.get(tab).url !== 'about:blank' && !tabs.get(tab).previewImage) {
      setTimeout(function () {
        //sometimes the page isn't visible until a short time after the did-finish-load event occurs
        captureCurrentTab()
      }, 100)
    }
  }, 0)
}

window.webviews = {
  container: document.getElementById('webviews'),
  elementMap: {}, // tabId: webview
  tabViewMap: {}, // tabId: browserView
  tabContentsMap: {}, // tabId: webContents
  selectedId: null,
  placeholderRequests: [],
  internalPages: {
    crash: 'file://' + __dirname + '/pages/crash/index.html',
    error: 'file://' + __dirname + '/pages/error/index.html'
  },
  events: [],
  IPCEvents: [],
  bindEvent: function (event, fn, options) {
    webviews.events.push({
      event: event,
      fn: fn,
      options: options
    })
  },
  bindIPC: function (name, fn) {
    webviews.IPCEvents.push({
      name: name,
      fn: fn
    })
  },
  add: function (tabId) {
    var tabData = tabs.get(tabId)

    // if the tab is private, we want to partition it. See http://electron.atom.io/docs/v0.34.0/api/web-view-tag/#partition
    // since tab IDs are unique, we can use them as partition names
    if (tabs.get(tabId).private === true) {
      var partition = tabId.toString() // options.tabId is a number, which remote.session.fromPartition won't accept. It must be converted to a string first

      // register permissionRequestHandler for this tab
      // private tabs use a different session, so the default permissionRequestHandler won't apply

      remote.session.fromPartition(partition).setPermissionRequestHandler(pagePermissionRequestHandler)

      // enable ad/tracker/contentType blocking in this tab if needed

      registerFiltering(partition)
    }

    ipc.send('createView', {
      id: tabId,
      webPreferencesString: JSON.stringify({
        webPreferences: {
          nodeIntegration: false,
          scrollBounce: true,
          preload: __dirname + '/dist/preload.js', // TODO fix on windows
          allowPopups: false,
          partition: partition
        }
      }),
      boundsString: JSON.stringify(getViewBounds()),
      events: webviews.events
    })
    /*
        let view = createView(
          tabId,
          JSON.stringify({
            webPreferences: {
              nodeIntegration: false,
              scrollBounce: true,
              preload: __dirname + '/dist/preload.js', // TODO fix on windows
              allowPopups: false,
              partition: partition
            }
          }),
          JSON.stringify(getViewBounds()),
          webviews.events
        )
        */

    let view = lazyRemoteObject(function () {
      return getView(tabId)
    })

    let contents = lazyRemoteObject(function () {
      return getView(tabId).webContents
    })

    /*    contents.on('ipc-message', function (e, args) {
          var w = this
          var tab = webviews.getTabFromContents(this)

          webviews.IPCEvents.forEach(function (item) {
            if (item.name === args[0]) {
              item.fn(w, tab, args[1])
            }
          })
        })*/

    // contents.loadURL(tabData.url)
    webviews.callAsync(tabData.id, 'loadURL', tabData.url)

    webviews.tabViewMap[tabId] = view
    webviews.tabContentsMap[tabId] = contents
    return view
  },
  setSelected: function (id) {
    webviews.selectedId = id

    // create the view if it doesn't already exist
    if (!webviews.getView(id)) {
      webviews.add(id)
    }

    if (webviews.placeholderRequestCount > 0) {
      return
    }

    ipc.send('setView', {
      id: id,
      bounds: getViewBounds()
    })

  // mainWindow.setBrowserView(view)
  // view.setBounds(getViewBounds())
  },
  update: function (id, url) {
    webviews.get(id).loadURL(urlParser.parse(url))
  },
  destroy: function (id) {
    var w = webviews.tabViewMap[id]
    if (w) {
      ipc.send('destroyView', id)
    /*if (id === webviews.selectedId) {
      mainWindow.setBrowserView(null)
      webviews.selectedId = null
    }
    w.destroy()
    */
    }
    delete webviews.tabViewMap[id]
    delete webviews.tabContentsMap[id]
  },
  getView: function (id) {
    return webviews.tabViewMap[id]
  },
  get: function (id) {
    return webviews.tabContentsMap[id]
  },
  requestPlaceholder: function (reason) {
    if (!webviews.placeholderRequests.includes(reason)) {
      webviews.placeholderRequests.push(reason)
    }
    if (webviews.placeholderRequests.length === 1) {
      // create a new placeholder

      var img = tabs.get(tabs.getSelected()).previewImage
      var url = tabs.get(tabs.getSelected()).url
      if (img) {
        placeholderImg.src = img
        placeholderImg.hidden = false
      } else if (url && url !== 'about:blank') {
        captureCurrentTab()
      }
    }
    setTimeout(function () {
      ipc.send('hideView', webviews.selectedId)
    }, 0)
  },
  hidePlaceholder: function (reason) {
    webviews.placeholderRequests.splice(webviews.placeholderRequests.indexOf(reason), 1)

    if (webviews.placeholderRequests.length === 0) {
      // multiple things can request a placeholder at the same time, but we should only show the view again if nothing requires a placeholder anymore
      if (webviews.tabViewMap[webviews.selectedId]) {
        ipc.send('showView', webviews.selectedId)
      }
      placeholderImg.hidden = true
    }
  },
  getTabFromContents: function (contents) {
    for (let tabId in webviews.tabContentsMap) {
      if (webviews.tabContentsMap[tabId] === contents) {
        return tabId
      }
    }
    return null
  },
  releaseFocus: function () {
    mainWindow.webContents.focus()
  },
  focus: function (id) {
    ipc.send('focusView', id)
  },
  callAsync: function (id, method, arg) {
    ipc.send('callViewMethod', {id: id, method: method, arg: arg})
  }
}

// called when js/preload/textExtractor.js returns the page's text content
webviews.bindIPC('pageData', function (webview, tabId, args) {
  var tab = tabs.get(tabId),
    data = args[0]

  var isInternalPage = tab.url.indexOf(__dirname) !== -1 && tab.url.indexOf(readerView.readerURL) === -1

  // don't save to history if in private mode, or the page is a browser page
  if (tab.private === false && !isInternalPage) {
    bookmarks.updateHistory(tabId, data.extractedText, data.metadata)
  }
})

// called when a swipe event is triggered in js/preload/swipeEvents.js

webviews.bindIPC('goBack', function () {
  settings.get('swipeNavigationEnabled', function (value) {
    if (value === true || value === undefined) {
      webviews.get(tabs.getSelected()).goBack()
    }
  })
})

webviews.bindIPC('goForward', function () {
  settings.get('swipeNavigationEnabled', function (value) {
    if (value === true || value === undefined) {
      webviews.get(tabs.getSelected()).goForward()
    }
  })
})

/* workaround for https://github.com/electron/electron/issues/3471 */

webviews.bindEvent('new-window', function (e, url, frameName, disposition) {
  var tab = webviews.getTabFromContents(this)
  var currentIndex = tabs.getIndex(tabs.getSelected())

  var newTab = tabs.add({
    url: url,
    private: tabs.get(tab).private // inherit private status from the current tab
  }, currentIndex + 1)
  addTab(newTab, {
    enterEditMode: false,
    openInBackground: disposition === 'background-tab' // possibly open in background based on disposition
  })
}, {preventDefault: true})

window.addEventListener('resize', throttle(function () {
  ipc.send('setBounds', {id: tabs.getSelected(), bounds: getViewBounds()})
}, 100))

mainWindow.on('enter-html-full-screen', function () {
  windowIsFullscreen = true
  ipc.send('setBounds', {id: tabs.getSelected(), bounds: getViewBounds()})
})

mainWindow.on('leave-html-full-screen', function () {
  windowIsFullscreen = false
  ipc.send('setBounds', {id: tabs.getSelected(), bounds: getViewBounds()})
})

webviews.bindEvent('did-finish-load', onPageLoad)
webviews.bindEvent('did-navigate-in-page', onPageLoad)

webviews.bindEvent('page-favicon-updated', function (e, favicons) {
  var id = webviews.getTabFromContents(this)
  updateTabColor(favicons, id)
})

webviews.bindEvent('page-title-updated', function (e, title, explicitSet) {
  var tab = webviews.getTabFromContents(this)
  tabs.update(tab, {
    title: title
  })
  tabBar.rerenderTab(tab)
})

webviews.bindEvent('did-start-loading', function () {
  tabBar.handleProgressBar(webviews.getTabFromContents(this), 'start')
})

webviews.bindEvent('did-stop-loading', function () {
  tabBar.handleProgressBar(webviews.getTabFromContents(this), 'finish')
})

webviews.bindEvent('did-fail-load', function (e, errorCode, errorDesc, validatedURL, isMainFrame) {
  if (errorCode !== -3 && isMainFrame && validatedURL) {
    navigate(webviews.getTabFromContents(this), webviews.internalPages.error + '?ec=' + encodeURIComponent(errorCode) + '&url=' + encodeURIComponent(validatedURL))
  }
})

webviews.bindEvent('crashed', function (e, isKilled) {
  var tabId = webviews.getTabFromContents(this)
  var url = tabs.get(tabId).url

  tabs.update(tabId, {
    url: webviews.internalPages.crash + '?url=' + encodeURIComponent(url)
  })

  // the existing process has crashed, so we can't reuse it
  webviews.destroy(tabId)
  webviews.add(tabId)

  if (tabId === tabs.getSelected()) {
    webviews.setSelected(tabId)
  }
})

ipc.on('view-event', function (e, args) {
  webviews.events.forEach(function (ev) {
    if (ev.event === args.name) {
      ev.fn.apply(webviews.tabContentsMap[args.id], [e].concat(args.args))
    }
  })
})

ipc.on('view-ipc', function (e, data) {
  webviews.IPCEvents.forEach(function (item) {
    if (item.name === data.name) {
      item.fn(webviews.tabContentsMap[data.id], data.id, [data.data])
    }
  })
})

setInterval(function () {
  if (webviews.placeholderRequests.length > 0) {
    // capturePage doesn't work while the view is hidden
    return
  }
  captureCurrentTab()
}, 30000)

ipc.on('captureData', function (e, data) {
  tabs.update(data.id, {
    previewImage: data.url
  })
  if (data.id === tabs.getSelected() && webviews.placeholderRequests.length > 0) {
    placeholderImg.src = data.url
    placeholderImg.hidden = false
  }
})
<|endoftext|>


<commit_before>// ==UserScript==
// @name		Auto SFA Login
// @namespace	http://allenbsmith.com/
// @version		0.1
// @description	Automatically logs you into SFA without interaction. :)
//				Many thanks to Tin Isles. My code was inspired from his.
//				http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/
// @author		A. B. Smith
// @require		https://raw.githubusercontent.com/Caligatio/jsSHA/master/src/sha.js
// ==/UserScript==

// Main Operations
document.getElementById('username').value = 'yourusername';
document.getElementById('password').value = 'yourpassword';
document.getElementById('OneTimePassword').value = updateOtp('yoursecret');
document.querySelectorAll('button')[0].click();

// Auxiliary Functions
function dec2hex(s) {
	return (s < 15.5 ? '0' : '') + Math.round(s).toString(16);
}
function hex2dec(s) {
	return parseInt(s, 16);
}

function base32tohex(base32) {
	var base32chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
	var bits = "";
	var hex = "";
	for (var i = 0; i < base32.length; i++) {
		var val = base32chars.indexOf(base32.charAt(i).toUpperCase());
		bits += leftpad(val.toString(2), 5, '0');
	}
	for (var i = 0; i + 4 <= bits.length; i += 4) {
		var chunk = bits.substr(i, 4);
		hex = hex + parseInt(chunk, 2).toString(16);
	}
	return hex;
}

function leftpad(str, len, pad) {
	if (len + 1 >= str.length) {
		str = Array(len + 1 - str.length).join(pad) + str;
	}
	return str;
}

function updateOtp(secret) {
	var key = base32tohex(secret);
	var epoch = Math.round(new Date().getTime() / 1000.0);
	var time = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0');
	// Many thanks to Caligatio for his SHA code.
	// Licenses can be found at his GitHub page.
	// https://github.com/Caligatio/jsSHA
	var sha = new jsSHA("SHA-1", "HEX");
	sha.setHMACKey(key, "HEX");
	sha.update(time);
	var hmac = sha.getHMAC("HEX");
	var offset = hex2dec(hmac.substring(hmac.length - 1));
	var otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
	otp = (otp).substr(otp.length - 6, 6);
	return otp;
}
<commit_msg>Update auto-sfa-login.user.js<commit_after>// ==UserScript==
// @name        Auto SFA Login
// @namespace   http://allenbsmith.com/
// @version     0.1
// @description Automatically logs you into SFA without interaction. :)
//              Many thanks to Tin Isles. My code was inspired from his.
//              http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/
// @author      A. B. Smith
// @require     https://raw.githubusercontent.com/Caligatio/jsSHA/master/src/sha.js
// ==/UserScript==

// Main Operations
document.getElementById('username').value = 'yourusername';
document.getElementById('password').value = 'yourpassword';
document.getElementById('OneTimePassword').value = updateOtp('yoursecret');
document.querySelectorAll('button')[0].click();

// Auxiliary Functions
function dec2hex(s) {
    return (s < 15.5 ? '0' : '') + Math.round(s).toString(16);
}
function hex2dec(s) {
    return parseInt(s, 16);
}

function base32tohex(base32) {
    var base32chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
    var bits = "";
    var hex = "";
    for (var i = 0; i < base32.length; i++) {
        var val = base32chars.indexOf(base32.charAt(i).toUpperCase());
        bits += leftpad(val.toString(2), 5, '0');
    }
    for (var i = 0; i + 4 <= bits.length; i += 4) {
        var chunk = bits.substr(i, 4);
        hex = hex + parseInt(chunk, 2).toString(16);
    }
    return hex;
}

function leftpad(str, len, pad) {
    if (len + 1 >= str.length) {
        str = Array(len + 1 - str.length).join(pad) + str;
    }
    return str;
}

function updateOtp(secret) {
    var key = base32tohex(secret);
    var epoch = Math.round(new Date().getTime() / 1000.0);
    var time = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0');
    // Many thanks to Caligatio for his SHA code.
    // Licenses can be found at his GitHub page.
    // https://github.com/Caligatio/jsSHA
    var sha = new jsSHA("SHA-1", "HEX");
    sha.setHMACKey(key, "HEX");
    sha.update(time);
    var hmac = sha.getHMAC("HEX");
    var offset = hex2dec(hmac.substring(hmac.length - 1));
    var otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
    otp = (otp).substr(otp.length - 6, 6);
    return otp;
}
<|endoftext|>


<commit_before>//|
//| {{ project_name }}
//|
//| This file is the main application file
//|
//| .--------------------------------------------------------------.
//| | NAMING CONVENTIONS:                                          |
//| |--------------------------------------------------------------|
//| | Singleton-literals and prototype objects | PascalCase        |
//| |--------------------------------------------------------------|
//| | Functions and public variables           | camelCase         |
//| |--------------------------------------------------------------|
//| | Global variables and constants           | UPPERCASE         |
//| |--------------------------------------------------------------|
//| | Private variables                        | _underscorePrefix |
//| '--------------------------------------------------------------'
//|
//| Comment syntax for the entire project follows JSDoc:
//| - http://code.google.com/p/jsdoc-toolkit/wiki/TagReference
//'
console.log('\'Allo \'Allo!');
<commit_msg>Adição de arquivos estáticos e também do shell para startup do projeto<commit_after>//|**
//| {{ project_name }}
//|
//| This file is the main application file
//|
//| .--------------------------------------------------------------.
//| | NAMING CONVENTIONS:                                          |
//| |--------------------------------------------------------------|
//| | Singleton-literals and prototype objects | PascalCase        |
//| |--------------------------------------------------------------|
//| | Functions and public variables           | camelCase         |
//| |--------------------------------------------------------------|
//| | Global variables and constants           | UPPERCASE         |
//| |--------------------------------------------------------------|
//| | Private variables                        | _underscorePrefix |
//| '--------------------------------------------------------------'
//|
//| Comment syntax for the entire project follows JSDoc:
//| - http://code.google.com/p/jsdoc-toolkit/wiki/TagReference
//'*/
console.log('\'Allo \'Allo!');
<|endoftext|>


<commit_before>/* implements selecting webviews, switching between them, and creating new ones. */

// the permissionRequestHandler used for webviews
function pagePermissionRequestHandler(webContents, permission, callback) {
    if (permission === 'notifications' || permission === 'fullscreen') {
        callback(true)
    } else {
        callback(false)
    }
}

// set the permissionRequestHandler for non-private tabs

remote.session.defaultSession.setPermissionRequestHandler(pagePermissionRequestHandler)

// called whenever the page url changes

function onPageLoad(e) {
    var _this = this
    setTimeout(function () { // TODO convert to arrow function
        /* add a small delay before getting these attributes, because they don't seem to update until a short time after the did-finish-load event is fired. Fixes #320 */

        var tab = _this.getAttribute('data-tab')
        var url = _this.getAttribute('src') // src attribute changes whenever a page is loaded

        if (url.indexOf('https://') === 0 || url.indexOf('about:') === 0 || url.indexOf('chrome:') === 0 || url.indexOf('file://') === 0) {
            tabs.update(tab, {
                secure: true,
                url: url
            })
        } else {
            tabs.update(tab, {
                secure: false,
                url: url
            })
        }

        tabBar.rerenderTab(tab)
    }, 0)
}

var webviews = {
    container: document.getElementById('webviews'),
    elementMap: {}, //tabId: webview
    internalPages: {
        crash: 'file:///' + __dirname + '/pages/crash/index.html',
        error: 'file:///' + __dirname + '/pages/error/index.html',
    },
    events: [],
    IPCEvents: [],
    bindEvent: function (event, fn, useWebContents) {
        webviews.events.push({
            event: event,
            fn: fn,
            useWebContents: useWebContents
        })
    },
    bindIPC: function (name, fn) {
        webviews.IPCEvents.push({
            name: name,
            fn: fn
        })
    },
    getDOM: function (options) {
        var w = document.createElement('webview')
        w.setAttribute('preload', 'dist/webview.min.js')

        if (options.url) {
            w.setAttribute('src', urlParser.parse(options.url))
        }

        w.setAttribute('data-tab', options.tabId)

        // if the tab is private, we want to partition it. See http://electron.atom.io/docs/v0.34.0/api/web-view-tag/#partition
        // since tab IDs are unique, we can use them as partition names
        if (tabs.get(options.tabId).private === true) {
            var partition = options.tabId.toString() // options.tabId is a number, which remote.session.fromPartition won't accept. It must be converted to a string first

            w.setAttribute('partition', partition)

            // register permissionRequestHandler for this tab
            // private tabs use a different session, so the default permissionRequestHandler won't apply

            remote.session.fromPartition(partition).setPermissionRequestHandler(pagePermissionRequestHandler)

            // enable ad/tracker/contentType blocking in this tab if needed

            registerFiltering(partition)
        }

        // webview events

        webviews.events.forEach(function (ev) {
            if (ev.useWebContents) { // some events (such as context-menu) are only available on the webContents rather than the webview element
                w.addEventListener('did-attach', function () {
                    this.getWebContents().on(ev.event, function () {
                        ev.fn.apply(w, arguments)
                    })
                })
            } else {
                w.addEventListener(ev.event, ev.fn)
            }
        })

        w.addEventListener('page-favicon-updated', function (e) {
            var id = this.getAttribute('data-tab')
            updateTabColor(e.favicons, id)
        })

        w.addEventListener('page-title-set', function (e) {
            var tab = this.getAttribute('data-tab')
            tabs.update(tab, {
                title: e.title
            })
            tabBar.rerenderTab(tab)
        })

        w.addEventListener('did-finish-load', onPageLoad)
        w.addEventListener('did-navigate-in-page', onPageLoad)

        /* workaround for https://github.com/electron/electron/issues/8505 and similar issues */
        w.addEventListener('load-commit', function (e) {
            if (e.isMainFrame) {
                tabBar.handleProgressBar(this.getAttribute('data-tab'), 'start')
            }
            this.classList.add('loading')
        })

        w.addEventListener('did-stop-loading', function () {
            tabBar.handleProgressBar(this.getAttribute('data-tab'), 'finish')
            setTimeout(function () {
                w.classList.remove('loading')
            }, 100)
        })

        // open links in new tabs

        w.addEventListener('new-window', function (e) {
            var tab = this.getAttribute('data-tab')
            var currentIndex = tabs.getIndex(tabs.getSelected())

            var newTab = tabs.add({
                url: e.url,
                private: tabs.get(tab).private // inherit private status from the current tab
            }, currentIndex + 1)
            addTab(newTab, {
                enterEditMode: false,
                openInBackground: e.disposition === 'background-tab' // possibly open in background based on disposition
            })
        })

        w.addEventListener('close', function (e) {
            closeTab(this.getAttribute('data-tab'))
        })

        w.addEventListener('ipc-message', function (e) {
            var w = this
            var tab = this.getAttribute('data-tab')

            webviews.IPCEvents.forEach(function (item) {
                if (item.name === e.channel) {
                    item.fn(w, tab, e.args)
                }
            })
        })

        w.addEventListener('crashed', function (e) {
            var tabId = this.getAttribute('data-tab')

            tabs.update(tabId, {
                url: webviews.internalPages.crash
            })

            //the existing process has crashed, so we can't reuse it
            webviews.destroy(tabId)
            webviews.add(tabId)

            if (tabId === tabs.getSelected()) {
                webviews.setSelected(tabId)
            }
        })

        w.addEventListener('did-fail-load', function (e) {
            if (e.errorCode !== -3 && e.validatedURL === e.target.getURL()) {
                navigate(this.getAttribute('data-tab'), webviews.internalPages.error + '?ec=' + encodeURIComponent(e.errorCode) + '&url=' + encodeURIComponent(e.target.getURL()))
            }
        })

        w.addEventListener('enter-html-full-screen', function (e) {
            this.classList.add('fullscreen')
        })

        w.addEventListener('leave-html-full-screen', function (e) {
            this.classList.remove('fullscreen')
        })

        return w;
    },
    add: function (tabId) {
        var tabData = tabs.get(tabId)

        var webview = webviews.getDOM({
            tabId: tabId,
            url: tabData.url
        })

        webviews.elementMap[tabId] = webview;

        // this is used to hide the webview while still letting it load in the background
        // webviews are hidden when added - call webviews.setSelected to show it
        webview.classList.add('hidden')
        webview.classList.add('loading')

        webviews.container.appendChild(webview)

        return webview
    },
    setSelected: function (id) {
        var webviewEls = document.getElementsByTagName('webview')
        for (var i = 0; i < webviewEls.length; i++) {
            webviewEls[i].classList.add('hidden')
        }

        var wv = webviews.get(id)

        if (!wv) {
            wv = webviews.add(id)
        }

        wv.classList.remove('hidden')
    },
    update: function (id, url) {
        webviews.get(id).setAttribute('src', urlParser.parse(url))
    },
    destroy: function (id) {
        var w = webviews.elementMap[id]
        if (w) {
            w.parentNode.removeChild(w)
        }
        delete webviews.elementMap[id]
    },
    get: function (id) {
        return webviews.elementMap[id]
    }
}

// called when js/webview/textExtractor.js returns the page's text content
webviews.bindIPC('pageData', function (webview, tabId, args) {
    var tab = tabs.get(tabId),
        data = args[0]

    var isInternalPage = tab.url.indexOf(__dirname) !== -1 && tab.url.indexOf(readerView.readerURL) === -1

    // don't save to history if in private mode, or the page is a browser page
    if (tab.private === false && !isInternalPage) {
        bookmarks.updateHistory(tabId, data.extractedText, data.metadata)
    }
})

// called when a swipe event is triggered in js/webview/swipeEvents.js

webviews.bindIPC('goBack', function () {
    settings.get('swipeNavigationEnabled', function (value) {
        if (value === true || value === undefined) {
            webviews.get(tabs.getSelected()).goBack()
        }
    })
})

webviews.bindIPC('goForward', function () {
    settings.get('swipeNavigationEnabled', function (value) {
        if (value === true || value === undefined) {
            webviews.get(tabs.getSelected()).goForward()
        }
    })
})

webviews.bindIPC('showBackArrow', function() {
    var backArrow = document.getElementById('leftArrowContainer')
    backArrow.classList.toggle('shown')
    setTimeout(function() {
      backArrow.classList.toggle('shown')
    }, 600)
})

webviews.bindIPC('showForwardArrow', function() {
    var forwardArrow = document.getElementById('rightArrowContainer')
    forwardArrow.classList.toggle('shown')
    setTimeout(function() {
      forwardArrow.classList.toggle('shown')
    }, 600)
})

/* workaround for https://github.com/electron/electron/issues/3471 */

webviews.bindEvent('did-get-redirect-request', function (e, oldURL, newURL, isMainFrame, httpResponseCode, requestMethod, referrer, header) {
    if (isMainFrame && httpResponseCode === 302 && requestMethod === 'POST') {
        this.stop()
        var _this = this
        setTimeout(function () {
            _this.loadURL(newURL)
        }, 0)
    }
}, true)
<commit_msg>better workaround for electron/electron#8505<commit_after>/* implements selecting webviews, switching between them, and creating new ones. */

// the permissionRequestHandler used for webviews
function pagePermissionRequestHandler(webContents, permission, callback) {
    if (permission === 'notifications' || permission === 'fullscreen') {
        callback(true)
    } else {
        callback(false)
    }
}

// set the permissionRequestHandler for non-private tabs

remote.session.defaultSession.setPermissionRequestHandler(pagePermissionRequestHandler)

// called whenever the page url changes

function onPageLoad(e) {
    var _this = this
    setTimeout(function () { // TODO convert to arrow function
        /* add a small delay before getting these attributes, because they don't seem to update until a short time after the did-finish-load event is fired. Fixes #320 */

        var tab = _this.getAttribute('data-tab')
        var url = _this.getAttribute('src') // src attribute changes whenever a page is loaded

        if (url.indexOf('https://') === 0 || url.indexOf('about:') === 0 || url.indexOf('chrome:') === 0 || url.indexOf('file://') === 0) {
            tabs.update(tab, {
                secure: true,
                url: url
            })
        } else {
            tabs.update(tab, {
                secure: false,
                url: url
            })
        }

        tabBar.rerenderTab(tab)
    }, 0)
}

var webviews = {
    container: document.getElementById('webviews'),
    elementMap: {}, //tabId: webview
    internalPages: {
        crash: 'file:///' + __dirname + '/pages/crash/index.html',
        error: 'file:///' + __dirname + '/pages/error/index.html',
    },
    events: [],
    IPCEvents: [],
    bindEvent: function (event, fn, useWebContents) {
        webviews.events.push({
            event: event,
            fn: fn,
            useWebContents: useWebContents
        })
    },
    bindIPC: function (name, fn) {
        webviews.IPCEvents.push({
            name: name,
            fn: fn
        })
    },
    getDOM: function (options) {
        var w = document.createElement('webview')
        w.setAttribute('preload', 'dist/webview.min.js')

        if (options.url) {
            w.setAttribute('src', urlParser.parse(options.url))
        }

        w.setAttribute('data-tab', options.tabId)

        // if the tab is private, we want to partition it. See http://electron.atom.io/docs/v0.34.0/api/web-view-tag/#partition
        // since tab IDs are unique, we can use them as partition names
        if (tabs.get(options.tabId).private === true) {
            var partition = options.tabId.toString() // options.tabId is a number, which remote.session.fromPartition won't accept. It must be converted to a string first

            w.setAttribute('partition', partition)

            // register permissionRequestHandler for this tab
            // private tabs use a different session, so the default permissionRequestHandler won't apply

            remote.session.fromPartition(partition).setPermissionRequestHandler(pagePermissionRequestHandler)

            // enable ad/tracker/contentType blocking in this tab if needed

            registerFiltering(partition)
        }

        // webview events

        webviews.events.forEach(function (ev) {
            if (ev.useWebContents) { // some events (such as context-menu) are only available on the webContents rather than the webview element
                w.addEventListener('did-attach', function () {
                    this.getWebContents().on(ev.event, function () {
                        ev.fn.apply(w, arguments)
                    })
                })
            } else {
                w.addEventListener(ev.event, ev.fn)
            }
        })

        w.addEventListener('page-favicon-updated', function (e) {
            var id = this.getAttribute('data-tab')
            updateTabColor(e.favicons, id)
        })

        w.addEventListener('page-title-set', function (e) {
            var tab = this.getAttribute('data-tab')
            tabs.update(tab, {
                title: e.title
            })
            tabBar.rerenderTab(tab)
        })

        w.addEventListener('did-finish-load', onPageLoad)
        w.addEventListener('did-navigate-in-page', onPageLoad)

        w.addEventListener('load-commit', function (e) {
            if (e.isMainFrame) {
                tabBar.handleProgressBar(this.getAttribute('data-tab'), 'start')
            }
            /* workaround for https://github.com/electron/electron/issues/8505 and similar issues */
            this.classList.add('loading')
            this.setAttribute("last-load-event", Date.now().toString())
        })

        w.addEventListener('did-stop-loading', function () {
            tabBar.handleProgressBar(this.getAttribute('data-tab'), 'finish')

            this.setAttribute("last-load-event", Date.now().toString())
            //only set webviews to hidden if no load events have occurred for 15 seconds because of https://github.com/electron/electron/issues/8505
            setTimeout(function () {
                if (Date.now() - parseInt(w.getAttribute("last-load-event")) > 14000) {
                    w.classList.remove('loading')
                }
            }, 15000)
        })

        // open links in new tabs

        w.addEventListener('new-window', function (e) {
            var tab = this.getAttribute('data-tab')
            var currentIndex = tabs.getIndex(tabs.getSelected())

            var newTab = tabs.add({
                url: e.url,
                private: tabs.get(tab).private // inherit private status from the current tab
            }, currentIndex + 1)
            addTab(newTab, {
                enterEditMode: false,
                openInBackground: e.disposition === 'background-tab' // possibly open in background based on disposition
            })
        })

        w.addEventListener('close', function (e) {
            closeTab(this.getAttribute('data-tab'))
        })

        w.addEventListener('ipc-message', function (e) {
            var w = this
            var tab = this.getAttribute('data-tab')

            webviews.IPCEvents.forEach(function (item) {
                if (item.name === e.channel) {
                    item.fn(w, tab, e.args)
                }
            })
        })

        w.addEventListener('crashed', function (e) {
            var tabId = this.getAttribute('data-tab')

            tabs.update(tabId, {
                url: webviews.internalPages.crash
            })

            //the existing process has crashed, so we can't reuse it
            webviews.destroy(tabId)
            webviews.add(tabId)

            if (tabId === tabs.getSelected()) {
                webviews.setSelected(tabId)
            }
        })

        w.addEventListener('did-fail-load', function (e) {
            if (e.errorCode !== -3 && e.validatedURL === e.target.getURL()) {
                navigate(this.getAttribute('data-tab'), webviews.internalPages.error + '?ec=' + encodeURIComponent(e.errorCode) + '&url=' + encodeURIComponent(e.target.getURL()))
            }
        })

        w.addEventListener('enter-html-full-screen', function (e) {
            this.classList.add('fullscreen')
        })

        w.addEventListener('leave-html-full-screen', function (e) {
            this.classList.remove('fullscreen')
        })

        return w;
    },
    add: function (tabId) {
        var tabData = tabs.get(tabId)

        var webview = webviews.getDOM({
            tabId: tabId,
            url: tabData.url
        })

        webviews.elementMap[tabId] = webview;

        // this is used to hide the webview while still letting it load in the background
        // webviews are hidden when added - call webviews.setSelected to show it
        webview.classList.add('hidden')
        webview.classList.add('loading')

        webviews.container.appendChild(webview)

        return webview
    },
    setSelected: function (id) {
        var webviewEls = document.getElementsByTagName('webview')
        for (var i = 0; i < webviewEls.length; i++) {
            webviewEls[i].classList.add('hidden')
        }

        var wv = webviews.get(id)

        if (!wv) {
            wv = webviews.add(id)
        }

        wv.classList.remove('hidden')
    },
    update: function (id, url) {
        webviews.get(id).setAttribute('src', urlParser.parse(url))
    },
    destroy: function (id) {
        var w = webviews.elementMap[id]
        if (w) {
            w.parentNode.removeChild(w)
        }
        delete webviews.elementMap[id]
    },
    get: function (id) {
        return webviews.elementMap[id]
    }
}

// called when js/webview/textExtractor.js returns the page's text content
webviews.bindIPC('pageData', function (webview, tabId, args) {
    var tab = tabs.get(tabId),
        data = args[0]

    var isInternalPage = tab.url.indexOf(__dirname) !== -1 && tab.url.indexOf(readerView.readerURL) === -1

    // don't save to history if in private mode, or the page is a browser page
    if (tab.private === false && !isInternalPage) {
        bookmarks.updateHistory(tabId, data.extractedText, data.metadata)
    }
})

// called when a swipe event is triggered in js/webview/swipeEvents.js

webviews.bindIPC('goBack', function () {
    settings.get('swipeNavigationEnabled', function (value) {
        if (value === true || value === undefined) {
            webviews.get(tabs.getSelected()).goBack()
        }
    })
})

webviews.bindIPC('goForward', function () {
    settings.get('swipeNavigationEnabled', function (value) {
        if (value === true || value === undefined) {
            webviews.get(tabs.getSelected()).goForward()
        }
    })
})

webviews.bindIPC('showBackArrow', function() {
    var backArrow = document.getElementById('leftArrowContainer')
    backArrow.classList.toggle('shown')
    setTimeout(function() {
      backArrow.classList.toggle('shown')
    }, 600)
})

webviews.bindIPC('showForwardArrow', function() {
    var forwardArrow = document.getElementById('rightArrowContainer')
    forwardArrow.classList.toggle('shown')
    setTimeout(function() {
      forwardArrow.classList.toggle('shown')
    }, 600)
})

/* workaround for https://github.com/electron/electron/issues/3471 */

webviews.bindEvent('did-get-redirect-request', function (e, oldURL, newURL, isMainFrame, httpResponseCode, requestMethod, referrer, header) {
    if (isMainFrame && httpResponseCode === 302 && requestMethod === 'POST') {
        this.stop()
        var _this = this
        setTimeout(function () {
            _this.loadURL(newURL)
        }, 0)
    }
}, true)
<|endoftext|>