<commit_before>import Ember from 'ember'
const {
  get,
  on
} = Ember
import PerfectScroll from 'ember-perfect-scroll/components/perfect-scroll/component'

export default PerfectScroll.extend({
  _destroyPerfectScroll: on('willDestroyElement', function () {
    var el = document.getElementById(get(this, 'eId'))
    if (el) {
      window.Ps.destroy(el)
    }
  })
})
<commit_msg>fixed ps destroy issues.<commit_after>import Ember from 'ember'
const {
  get,
  on
} = Ember
import PerfectScroll from 'ember-perfect-scroll/components/perfect-scroll/component'

export default PerfectScroll.extend({
  willDestroyElement () {
    var el = document.getElementById(get(this, 'eId'))
    if (el) {
      window.Ps.destroy(el)
    }
  }
})
<|endoftext|>


<commit_before><commit_msg>Added test for adding an article<commit_after><|endoftext|>


<commit_before>import Ember from 'ember';

/**
 * @module mixins
 * @class sl-pagination-controller
 */
export default Ember.Mixin.create({

    /**
     * Controller actions hash
     *
     * @property {object} actions
     */
    actions: {

        /**
         * Change current page to the specified page
         *
         * @method actions.changePage
         */
        changePage: function( page ) {
            var currentPage = this.get( 'currentPage' ),
                nextPage,
                prevPage,
                totalPages,
                validNextPage,
                validPrevPage;

            totalPages = Math.ceil(
                this.get( 'metaData.total' ) / this.get( 'itemCountPerPage' )
            );

            switch( page ) {
                case 'first':
                    return this.set( 'currentPage', 1 );

                case 'prev':
                    validPrevPage = currentPage - 1;
                    validPrevPage = prevPage > 0;
                    return this.set( 'currentPage', validPrevPage ? validPrevPage : 1 );

                case 'next':
                    nextPage = ( currentPage + 1 );
                    validNextPage = nextPage <= totalPages;
                    return this.set( 'currentPage',  validNextPage ? nextPage : totalPages );

                case 'last':
                    return this.set( 'currentPage', totalPages );

                case 'currentPageInput':
                /* falls through */
                default:
                    page = parseInt( page );
                    page = isNaN( page ) ? 1 : page;
                    return this.set( 'currentPage', page );
            }
        },

        /**
         * Change the "per page" record limit
         *
         * @method actions.changePerPage
         */
        changePerPage: function( perPage ){
            perPage = parseInt( perPage );
            perPage = isNaN( perPage ) ? this.get( 'perPageOptions.firstObject' ) : perPage;
            this.set( 'itemCountPerPage', perPage );
        }
    },

    /**
     * An arranged copy of the content
     *
     * @property {mixed} arrangedContent
     */
    arrangedContent: function() {
        var self = this,
            content = this._super(),
            currentPage = parseInt( this.get( 'currentPage' )),
            itemCount = parseInt( this.get( 'itemCountPerPage' )),
            start = ( currentPage - 1 ) * itemCount,
            end = start + itemCount;

        if ( content.then && ( !content.isFulfilled && !content.isRejected )) {
            content.then( function() {
                self.notifyPropertyChange( 'content' );
            });
        }

        return content.slice( start, end );
    }.property(
        'content',
        'currentPage',
        'filterProperties.@each',
        'itemCountPerPage',
        'sortAscending',
        'sortProperties.@each'
    ),

    /**
     * The current page number
     *
     * @property {number} currentPage
     * @default 1
     */
    currentPage: 1,

    /**
     * Paging data for the grid to pass to its pagination controls
     *
     * @property {object} pagingData
     */
    pagingData: function() {
        var pageNumber = this.get( 'currentPage' ) - 1,
            pageCount = this.getWithDefault( 'metaData.pageCount', null ),
            total = this.getWithDefault( 'metaData.total', null ),
            perPage = this.get( 'itemCountPerPage' ),
            totalPages = this.getWithDefault( 'metaData.totalPages', 1 ),
            firstRow = pageNumber * perPage + 1;

        return {
            pageFirstRow: firstRow,
            pageLastRow: firstRow + pageCount - 1,
            totalRows: total,
            totalPages: totalPages,
            perPageOptions: this.get( 'perPageOptions' ),
            itemCountPerPage: this.get( 'itemCountPerPage' ),
            currentPage: this.get( 'currentPage' ),
            modelNames: this.get( 'metaData.modelNames' )
        };
    }.property(
        'currentPage',
        'itemCountPerPage',
        'metaData',
        'perPageOptions'
    ),

    /**
     * Options for the "per page" resource limit number
     *
     * @property {array} perPageOptions
     */
    perPageOptions: Ember.A([ 25, 50, 100 ]),

    /**
     * Accepted controller query parameters
     *
     * @property {array} queryParams
     */
    queryParams: [ 'currentPage', 'itemCountPerPage' ],

    /**
     * Reset the current page number when the itemCountPerPage is changed
     *
     * @method resetCurrentPage
     */
    resetCurrentPage: function() {
        this.set( 'currentPage', 1 );
    }.observes( 'itemCountPerPage' ),

    /**
     * Update metaData properties when relevant values is changed
     *
     * @method setupMetaData
     */
    updateMetaData: function() {
        var total = parseInt( this.get( 'metaData.total' )),
            itemCount = parseInt( this.get( 'itemCountPerPage' )),
            currentPage = parseInt( this.get( 'currentPage' )),
            start = ( currentPage - 1 ) * itemCount,
            end = start + itemCount,
            pageCount = ( start + end ) < total ? itemCount : total - start;

        this.setProperties({
            'metaData.pageCount': pageCount,
            'metaData.totalPages': Math.ceil( total / itemCount )
        });
    }.observes( 'currentPage', 'itemCountPerPage', 'metaData' )

});
<commit_msg>Refactor to follow style guides<commit_after>import Ember from 'ember';

/**
 * @module mixins
 * @class sl-pagination-controller
 */
export default Ember.Mixin.create({

    /**
     * Controller actions hash
     *
     * @property {object} actions
     */
    actions: {

        /**
         * Change current page to the specified page
         *
         * @method actions.changePage
         */
        changePage: function( page ) {
            var currentPage = this.get( 'currentPage' ),
                nextPage,
                prevPage,
                totalPages,
                validNextPage,
                validPrevPage;

            totalPages = Math.ceil(
                this.get( 'metaData.total' ) / this.get( 'itemCountPerPage' )
            );

            switch( page ) {
                case 'first':
                    return this.set( 'currentPage', 1 );

                case 'prev':
                    validPrevPage = currentPage - 1;
                    validPrevPage = prevPage > 0;
                    return this.set( 'currentPage', validPrevPage ? validPrevPage : 1 );

                case 'next':
                    nextPage = ( currentPage + 1 );
                    validNextPage = nextPage <= totalPages;
                    return this.set( 'currentPage',  validNextPage ? nextPage : totalPages );

                case 'last':
                    return this.set( 'currentPage', totalPages );

                case 'currentPageInput':
                /* falls through */
                default:
                    page = parseInt( page );
                    page = isNaN( page ) ? 1 : page;
                    return this.set( 'currentPage', page );
            }
        },

        /**
         * Change the "per page" record limit
         *
         * @method actions.changePerPage
         */
        changePerPage: function( perPage ) {
            perPage = parseInt( perPage );
            perPage = isNaN( perPage ) ? this.get( 'perPageOptions.firstObject' ) : perPage;
            this.set( 'itemCountPerPage', perPage );
        }
    },

    /**
     * An arranged copy of the content
     *
     * @property {mixed} arrangedContent
     */
    arrangedContent: function() {
        var self        = this,
            content     = this._super(),
            currentPage = parseInt( this.get( 'currentPage' ) ),
            itemCount   = parseInt( this.get( 'itemCountPerPage' ) ),
            start       = ( currentPage - 1 ) * itemCount,
            end         = start + itemCount;

        if ( content.then && ( !content.isFulfilled && !content.isRejected ) ) {
            content.then( function() {
                self.notifyPropertyChange( 'content' );
            });
        }

        return content.slice( start, end );
    }.property(
        'content',
        'currentPage',
        'filterProperties.@each',
        'itemCountPerPage',
        'sortAscending',
        'sortProperties.@each'
    ),

    /**
     * The current page number
     *
     * @property {number} currentPage
     * @default 1
     */
    currentPage: 1,

    /**
     * Paging data for the grid to pass to its pagination controls
     *
     * @property {object} pagingData
     */
    pagingData: function() {
        var pageNumber = this.get( 'currentPage' ) - 1,
            pageCount  = this.getWithDefault( 'metaData.pageCount', null ),
            total      = this.getWithDefault( 'metaData.total', null ),
            perPage    = this.get( 'itemCountPerPage' ),
            totalPages = this.getWithDefault( 'metaData.totalPages', 1 ),
            firstRow   = pageNumber * perPage + 1;

        return {
            pageFirstRow     : firstRow,
            pageLastRow      : firstRow + pageCount - 1,
            totalRows        : total,
            totalPages       : totalPages,
            perPageOptions   : this.get( 'perPageOptions' ),
            itemCountPerPage : this.get( 'itemCountPerPage' ),
            currentPage      : this.get( 'currentPage' ),
            modelNames       : this.get( 'metaData.modelNames' )
        };
    }.property(
        'currentPage',
        'itemCountPerPage',
        'metaData',
        'perPageOptions'
    ),

    /**
     * Options for the "per page" resource limit number
     *
     * @property {array} perPageOptions
     */
    perPageOptions: Ember.A([ 25, 50, 100 ]),

    /**
     * Accepted controller query parameters
     *
     * @property {array} queryParams
     */
    queryParams: [ 'currentPage', 'itemCountPerPage' ],

    /**
     * Reset the current page number when the itemCountPerPage is changed
     *
     * @method resetCurrentPage
     */
    resetCurrentPage: function() {
        this.set( 'currentPage', 1 );
    }.observes( 'itemCountPerPage' ),

    /**
     * Update metaData properties when relevant values is changed
     *
     * @method setupMetaData
     */
    updateMetaData: function() {
        var total       = parseInt( this.get( 'metaData.total' )),
            itemCount   = parseInt( this.get( 'itemCountPerPage' )),
            currentPage = parseInt( this.get( 'currentPage' )),
            start       = ( currentPage - 1 ) * itemCount,
            end         = start + itemCount,
            pageCount   = ( start + end ) < total ? itemCount : total - start;

        this.setProperties({
            'metaData.pageCount': pageCount,
            'metaData.totalPages': Math.ceil( total / itemCount )
        });
    }.observes( 'currentPage', 'itemCountPerPage', 'metaData' )

});
<|endoftext|>


<commit_before>const Util = require('../../util');
const Angle = require('./angle');
const Circle = require('./circle');
const ScaleX = require('./scale-x');
const ScaleY = require('./scale-y');
// const Scale = require('./scale');
const WaveV = require('./wave-v');

function getAdjusts(adjusts) {
  const result = [];
  Util.each(adjusts, adjust => {
    result.push(Util.upperFirst(adjust.type));
  });

  return result;
}

module.exports = {
  getDefault(config) {
    const geom = config.geom; // 获取图形实例
    const fn = config.fn; // 绘制方法
    const coord = geom.get('coord'); // 获取坐标轴

    let C; // 动画构造函数
    let geomType = geom.get('type');
    let adjusts = geom.get('adjusts') || ''; // 防止为空
    if (adjusts) {
      adjusts = getAdjusts(adjusts);
    }
    geomType = geomType + adjusts.toString();
    switch (coord.type) {
      case 'cartesian':
        switch (geomType) {
          case 'interval':
          case 'intervalStack':
          case 'intervalDodge':
            if (coord.isTransposed) {
              C = ScaleX;
            } else {
              C = ScaleY;
            }
            break;
          case 'intervalSymmetric':
            C = ScaleY;
            break;
          default:
            C = WaveV;
            break;
        }
        break;
      case 'polar':
      case 'theta':
      case 'map':
        C = Angle; // angle;
        break;
      case 'helix':
        C = Circle;
        break;
      default:
        break;
    }

    const start = coord.start;
    const end = coord.end;
    const width = coord.getWidth();
    const height = coord.getHeight();
    const cfg = {
      group: geom.get('container'),
      rect: {
        x: start.x,
        y: end.y,
        width,
        height
      },
      before: fn
    };
    if (coord.isPolar) {
      Util.mix(cfg, {
        circle: {
          center: coord.getCenter(),
          startAngle: coord.startAngle,
          endAngle: coord.endAngle,
          r: (Math.max(width, height)) / 2
        }
      });
    }
    return new C(cfg);
  }
};
<commit_msg>移除 map 坐标系<commit_after>const Util = require('../../util');
const Angle = require('./angle');
const Circle = require('./circle');
const ScaleX = require('./scale-x');
const ScaleY = require('./scale-y');
// const Scale = require('./scale');
const WaveV = require('./wave-v');

function getAdjusts(adjusts) {
  const result = [];
  Util.each(adjusts, adjust => {
    result.push(Util.upperFirst(adjust.type));
  });

  return result;
}

module.exports = {
  getDefault(config) {
    const geom = config.geom; // 获取图形实例
    const fn = config.fn; // 绘制方法
    const coord = geom.get('coord'); // 获取坐标轴

    let C; // 动画构造函数
    let geomType = geom.get('type');
    let adjusts = geom.get('adjusts') || ''; // 防止为空
    if (adjusts) {
      adjusts = getAdjusts(adjusts);
    }
    geomType = geomType + adjusts.toString();
    switch (coord.type) {
      case 'cartesian':
        switch (geomType) {
          case 'interval':
          case 'intervalStack':
          case 'intervalDodge':
            if (coord.isTransposed) {
              C = ScaleX;
            } else {
              C = ScaleY;
            }
            break;
          case 'intervalSymmetric':
            C = ScaleY;
            break;
          default:
            C = WaveV;
            break;
        }
        break;
      case 'polar':
      case 'theta':
        C = Angle; // angle;
        break;
      case 'helix':
        C = Circle;
        break;
      default:
        break;
    }

    const start = coord.start;
    const end = coord.end;
    const width = coord.getWidth();
    const height = coord.getHeight();
    const cfg = {
      group: geom.get('container'),
      rect: {
        x: start.x,
        y: end.y,
        width,
        height
      },
      before: fn
    };
    if (coord.isPolar) {
      Util.mix(cfg, {
        circle: {
          center: coord.getCenter(),
          startAngle: coord.startAngle,
          endAngle: coord.endAngle,
          r: (Math.max(width, height)) / 2
        }
      });
    }
    return new C(cfg);
  }
};
<|endoftext|>


<commit_before>var reqAnimFrameID = 0;
var projection = 0;
var manualRotation = quat.create(),
    degtorad = Math.PI / 180, // Degree-to-Radian conversion
    framesSinceIssue = 0;

(function(global) {
  'use strict';

  var controls = {
    manualControls: {
      'a' : {index: 1, sign: 1, active: 0},
      'd' : {index: 1, sign: -1, active: 0},
      'w' : {index: 0, sign: 1, active: 0},
      's' : {index: 0, sign: -1, active: 0},
      'q' : {index: 2, sign: -1, active: 0},
      'e' : {index: 2, sign: 1, active: 0},
    },

    manualRotateRate: new Float32Array([0, 0, 0]),  // Vector, camera-relative

    create: function() {
      playButton.addEventListener("click", function() {
        controls.playPause();
      });

      playL.addEventListener("click", function() {
        controls.playPause();
      });

      playR.addEventListener("click", function() {
        controls.playPause();
      });

      loopButton.addEventListener("click", function() {
        controls.toggleLooping();
      });

      muteButton.addEventListener("click", function() {
        if (video.muted === false) {
          controls.mute();
        } else {
          controls.unmute();
        }
      });

      fullScreenButton.addEventListener("click", function() {
        controls.fullscreen();
      });

      seekBar.addEventListener("change", function() {
        // Calculate the new time
        var time = video.duration * (seekBar.value / 100);
        video.currentTime = time;
      });

      video.addEventListener("timeupdate", function() {
        // don't update if paused,
        // we get last time update after seekBar mousedown pauses
        if (!video.paused) {
          // Calculate the slider value
          var value = (100 / video.duration) * video.currentTime;
          seekBar.value = value;
        }
      });

      // Pause the video when the slider handle is being dragged
      var tempPause = false;
      seekBar.addEventListener("mousedown", function() {
        if (!video.paused) {
          video.pause();
          tempPause = true;
        }
      });

      seekBar.addEventListener("mouseup", function() {
        if (tempPause) {
          video.play();
        }
      });

      videoSelect.addEventListener("change", function() {
        projection = videoSelect.value[0];
        projectionSelect.value = projection;
        controls.loadVideo(videoSelect.value.substring(1));
      });

      projectionSelect.addEventListener("change", function() {
        projection = projectionSelect.value;
      });

      document.getElementById("select-local-file").addEventListener("click", function(event) {
        event.preventDefault();
        controls.selectLocalVideo();
      });
    },

    enableKeyControls: function() {
      function key(event, sign) {
        var control = controls.manualControls[String.fromCharCode(event.keyCode).toLowerCase()];
        if (!control)
          return;
        if (sign === 1 && control.active || sign === -1 && !control.active)
          return;
        control.active = (sign === 1);
        controls.manualRotateRate[control.index] += sign * control.sign;
      }

      function onkey(event) {
        switch (String.fromCharCode(event.charCode)) {
        case 'f':
          controls.fullscreen();
          break;
        case 'z':
          vrSensor.zeroSensor();
          break;
        case 'p':
          controls.playPause();
          break;
        case ' ': //spacebar
          controls.playPause();
          break;
        case 'g':
          controls.fullscreenIgnoreHMD();
          break;
        case 'l':
          controls.toggleLooping();
          break;
        }
      }

      document.addEventListener('keydown', function(event) { key(event, 1); },
              false);
      document.addEventListener('keyup', function(event) { key(event, -1); },
              false);
      window.addEventListener("keypress", onkey, true);
    },

    /**
     * Video Commands
     */
    loaded: function() {
      leftLoad.style.display = "none";
      rightLoad.style.display = "none";
      if (video.paused) {
        leftPlay.style.display = "block";
        rightPlay.style.display = "block";
      }
    },

    play: function(event) {
      if (video.ended) {
        video.currentTime = 0.1;
      }

      video.play();
      if (!video.paused) { // In case somehow hitting play button doesnt work
        leftPlay.style.display = "none";
        rightPlay.style.display = "none";

        playButton.className = "fa fa-pause icon";
        playButton.title = "Pause";
        reqAnimFrameID = requestAnimationFrame(webGL.drawScene);
      }
    },

    pause: function() {
      video.pause();
      playButton.className = "fa fa-play icon";
      playButton.title = "Play";
      leftPlay.style.display = "block";
      rightPlay.style.display = "block";
    },

    playPause: function() {
      if (video.paused === true) {
        controls.play();
      } else {
        controls.pause();
      }
    },

    toggleLooping: function() {
      if (video.loop === true) {
        loopButton.className = "fa fa-refresh icon";
        loopButton.title="Start Looping";
        video.loop = false;
      } else {
        loopButton.className = "fa fa-chain-broken icon";
        loopButton.title="Stop Looping";
        video.loop = true;
      }
    },

    ended: function() {
      controls.pause();
      if (reqAnimFrameID) {
        cancelAnimationFrame(reqAnimFrameID);
        reqAnimFrameID = 0;
      }
    },

    mute: function() {
      video.muted = true;
      muteButton.className = "fa fa-volume-off icon";
      muteButton.title = "Unmute";
    },

    unmute: function() {
      video.muted = false;
      muteButton.className = "fa fa-volume-up icon";
      muteButton.title = "Mute";
    },

    selectLocalVideo: function() {
      var input = document.createElement("input");
      input.type = "file";
      input.accept = "video/*";

      input.addEventListener("change", function (event) {
        var files = input.files;
        if (!files.length) {
          // The user didn't select anything.  Sad.
          console.log('File selection canceled');
          return;
        }

        videoObjectURL = URL.createObjectURL(files[0]);
        console.log('Loading local file ', files[0].name, ' at URL ', videoObjectURL);
        videoSelect.value = "";
        loadVideo(videoObjectURL);
      });

      input.click();
    },

    loadVideo: function(videoFile) {
      controls.pause();
      leftPlay.style.display = "none";
      rightPlay.style.display = "none";
      leftLoad.style.display = "block";
      rightLoad.style.display = "block";

      webGL.gl.clear(webGL.gl.COLOR_BUFFER_BIT);

      if (reqAnimFrameID) {
        cancelAnimationFrame(reqAnimFrameID);
        reqAnimFrameID = 0;
      }

      // Hack to fix rotation for vidcon video for vidcon
      if (videoFile === "videos/Vidcon.webm" || videoFile === "videos/Vidcon5.mp4") {
        manualRotation = [0.38175851106643677, -0.7102527618408203, -0.2401944249868393, 0.5404701232910156];
      } else {
        manualRotation = quat.create();
      }

      var oldObjURL = videoObjectURL;
      videoObjectURL = null;

      video.src = videoFile;

      if (videoObjectURL && videoObjectURL !== videoFile) {
        URL.removeObjectURL(oldObjURL);
      }
    },

    fullscreen: function() {
      if (canvas.mozRequestFullScreen) {
        canvas.mozRequestFullScreen({ vrDisplay: vrHMD }); // Firefox
      } else if (canvas.webkitRequestFullscreen) {
        canvas.webkitRequestFullscreen({ vrDisplay: vrHMD }); // Chrome and Safari
      } else if (canvas.requestFullScreen){
        canvas.requestFullscreen();
      }
    },

    fullscreenIgnoreHMD: function() {
      if (canvas.mozRequestFullScreen) {
        canvas.mozRequestFullScreen(); // Firefox
      } else if (canvas.webkitRequestFullscreen) {
        canvas.webkitRequestFullscreen(); // Chrome and Safari
      } else if (canvas.requestFullScreen){
        canvas.requestFullscreen();
      }
    }
  };

  global.controls = controls;

})(window);
<commit_msg>fix load video issue<commit_after>var reqAnimFrameID = 0;
var projection = 0;
var manualRotation = quat.create(),
    degtorad = Math.PI / 180, // Degree-to-Radian conversion
    framesSinceIssue = 0;

(function(global) {
  'use strict';

  var controls = {
    manualControls: {
      'a' : {index: 1, sign: 1, active: 0},
      'd' : {index: 1, sign: -1, active: 0},
      'w' : {index: 0, sign: 1, active: 0},
      's' : {index: 0, sign: -1, active: 0},
      'q' : {index: 2, sign: -1, active: 0},
      'e' : {index: 2, sign: 1, active: 0},
    },

    manualRotateRate: new Float32Array([0, 0, 0]),  // Vector, camera-relative

    create: function() {
      playButton.addEventListener("click", function() {
        controls.playPause();
      });

      playL.addEventListener("click", function() {
        controls.playPause();
      });

      playR.addEventListener("click", function() {
        controls.playPause();
      });

      loopButton.addEventListener("click", function() {
        controls.toggleLooping();
      });

      muteButton.addEventListener("click", function() {
        if (video.muted === false) {
          controls.mute();
        } else {
          controls.unmute();
        }
      });

      fullScreenButton.addEventListener("click", function() {
        controls.fullscreen();
      });

      seekBar.addEventListener("change", function() {
        // Calculate the new time
        var time = video.duration * (seekBar.value / 100);
        video.currentTime = time;
      });

      video.addEventListener("timeupdate", function() {
        // don't update if paused,
        // we get last time update after seekBar mousedown pauses
        if (!video.paused) {
          // Calculate the slider value
          var value = (100 / video.duration) * video.currentTime;
          seekBar.value = value;
        }
      });

      // Pause the video when the slider handle is being dragged
      var tempPause = false;
      seekBar.addEventListener("mousedown", function() {
        if (!video.paused) {
          video.pause();
          tempPause = true;
        }
      });

      seekBar.addEventListener("mouseup", function() {
        if (tempPause) {
          video.play();
        }
      });

      videoSelect.addEventListener("change", function() {
        projection = videoSelect.value[0];
        projectionSelect.value = projection;
        controls.loadVideo(videoSelect.value.substring(1));
      });

      projectionSelect.addEventListener("change", function() {
        projection = projectionSelect.value;
      });

      document.getElementById("select-local-file").addEventListener("click", function(event) {
        event.preventDefault();
        controls.selectLocalVideo();
      });
    },

    enableKeyControls: function() {
      function key(event, sign) {
        var control = controls.manualControls[String.fromCharCode(event.keyCode).toLowerCase()];
        if (!control)
          return;
        if (sign === 1 && control.active || sign === -1 && !control.active)
          return;
        control.active = (sign === 1);
        controls.manualRotateRate[control.index] += sign * control.sign;
      }

      function onkey(event) {
        switch (String.fromCharCode(event.charCode)) {
        case 'f':
          controls.fullscreen();
          break;
        case 'z':
          vrSensor.zeroSensor();
          break;
        case 'p':
          controls.playPause();
          break;
        case ' ': //spacebar
          controls.playPause();
          break;
        case 'g':
          controls.fullscreenIgnoreHMD();
          break;
        case 'l':
          controls.toggleLooping();
          break;
        }
      }

      document.addEventListener('keydown', function(event) { key(event, 1); },
              false);
      document.addEventListener('keyup', function(event) { key(event, -1); },
              false);
      window.addEventListener("keypress", onkey, true);
    },

    /**
     * Video Commands
     */
    loaded: function() {
      leftLoad.style.display = "none";
      rightLoad.style.display = "none";
      if (video.paused) {
        leftPlay.style.display = "block";
        rightPlay.style.display = "block";
      }
    },

    play: function(event) {
      if (video.ended) {
        video.currentTime = 0.1;
      }

      video.play();
      if (!video.paused) { // In case somehow hitting play button doesnt work
        leftPlay.style.display = "none";
        rightPlay.style.display = "none";

        playButton.className = "fa fa-pause icon";
        playButton.title = "Pause";
        reqAnimFrameID = requestAnimationFrame(webGL.drawScene);
      }
    },

    pause: function() {
      video.pause();
      playButton.className = "fa fa-play icon";
      playButton.title = "Play";
      leftPlay.style.display = "block";
      rightPlay.style.display = "block";
    },

    playPause: function() {
      if (video.paused === true) {
        controls.play();
      } else {
        controls.pause();
      }
    },

    toggleLooping: function() {
      if (video.loop === true) {
        loopButton.className = "fa fa-refresh icon";
        loopButton.title="Start Looping";
        video.loop = false;
      } else {
        loopButton.className = "fa fa-chain-broken icon";
        loopButton.title="Stop Looping";
        video.loop = true;
      }
    },

    ended: function() {
      controls.pause();
      if (reqAnimFrameID) {
        cancelAnimationFrame(reqAnimFrameID);
        reqAnimFrameID = 0;
      }
    },

    mute: function() {
      video.muted = true;
      muteButton.className = "fa fa-volume-off icon";
      muteButton.title = "Unmute";
    },

    unmute: function() {
      video.muted = false;
      muteButton.className = "fa fa-volume-up icon";
      muteButton.title = "Mute";
    },

    selectLocalVideo: function() {
      var input = document.createElement("input");
      input.type = "file";
      input.accept = "video/*";

      input.addEventListener("change", function (event) {
        var files = input.files;
        if (!files.length) {
          // The user didn't select anything.  Sad.
          console.log('File selection canceled');
          return;
        }

        videoObjectURL = URL.createObjectURL(files[0]);
        console.log('Loading local file ', files[0].name, ' at URL ', videoObjectURL);
        videoSelect.value = "";
        controls.loadVideo(videoObjectURL);
      });

      input.click();
    },

    loadVideo: function(videoFile) {
      controls.pause();
      leftPlay.style.display = "none";
      rightPlay.style.display = "none";
      leftLoad.style.display = "block";
      rightLoad.style.display = "block";

      webGL.gl.clear(webGL.gl.COLOR_BUFFER_BIT);

      if (reqAnimFrameID) {
        cancelAnimationFrame(reqAnimFrameID);
        reqAnimFrameID = 0;
      }

      // Hack to fix rotation for vidcon video for vidcon
      if (videoFile === "videos/Vidcon.webm" || videoFile === "videos/Vidcon5.mp4") {
        manualRotation = [0.38175851106643677, -0.7102527618408203, -0.2401944249868393, 0.5404701232910156];
      } else {
        manualRotation = quat.create();
      }

      var oldObjURL = videoObjectURL;
      videoObjectURL = null;

      video.src = videoFile;

      if (videoObjectURL && videoObjectURL !== videoFile) {
        URL.removeObjectURL(oldObjURL);
      }
    },

    fullscreen: function() {
      if (canvas.mozRequestFullScreen) {
        canvas.mozRequestFullScreen({ vrDisplay: vrHMD }); // Firefox
      } else if (canvas.webkitRequestFullscreen) {
        canvas.webkitRequestFullscreen({ vrDisplay: vrHMD }); // Chrome and Safari
      } else if (canvas.requestFullScreen){
        canvas.requestFullscreen();
      }
    },

    fullscreenIgnoreHMD: function() {
      if (canvas.mozRequestFullScreen) {
        canvas.mozRequestFullScreen(); // Firefox
      } else if (canvas.webkitRequestFullscreen) {
        canvas.webkitRequestFullscreen(); // Chrome and Safari
      } else if (canvas.requestFullScreen){
        canvas.requestFullscreen();
      }
    }
  };

  global.controls = controls;

})(window);
<|endoftext|>


<commit_before>'use babel';

export default class CaseKeepReplaceView {
  constructor(serializedState) {
    this.state = serializedState || {}

    // Binding
    this.updatePreview = this.updatePreview.bind(this)
    this.replace = this.replace.bind(this)
    this.replaceInBuffer = this.replaceInBuffer.bind(this)
    this.replaceInSelection = this.replaceInSelection.bind(this)

    // Create root element
    this.element = document.createElement('div')
    this.element.classList.add('case-keep-replace')

    // Create children
    this.element.appendChild(this.createHeader())
    this.element.appendChild(this.createForm())
    this.element.appendChild(this.createPreview())
  }

  createHeader() {
    const header = document.createElement('h6')
    header.textContent = 'Find and replace with original case'

    return header
  }

  createForm() {
    const findInput = document.createElement('atom-text-editor')
    findInput.id = 'input-find'
    findInput.setAttribute('mini', true)
    findInput.classList.add('input-text')
    findInput.getModel().setPlaceholderText('Find ... (camelCase)')
    findInput.tabIndex = "1"
    this.findInput = findInput.getModel()
    this.findInput.onDidChange(this.updatePreview)

    const replaceInput = document.createElement('atom-text-editor')
    replaceInput.id = 'input-replace'
    replaceInput.setAttribute('mini', true)
    replaceInput.classList.add('input-text')
    replaceInput.getModel().setPlaceholderText('Replace to ... (camelCase)')
    replaceInput.tabIndex = "2"
    this.replaceInput = replaceInput.getModel()
    this.replaceInput.onDidChange(this.updatePreview)

    const form = document.createElement('div')
    form.classList.add('block', 'form')
    form.appendChild(findInput)
    form.appendChild(replaceInput)

    return form
  }

  createPreview() {
    const previewVar = document.createElement('button')
    previewVar.id = 'preview-var'
    previewVar.classList.add('btn', 'selected', 'disabled')

    const previewClass = document.createElement('button')
    previewClass.id = 'preview-class'
    previewClass.classList.add('btn', 'selected', 'disabled')

    const previewConst = document.createElement('button')
    previewConst.id = 'preview-const'
    previewConst.classList.add('btn', 'selected', 'disabled')

    const preview = document.createElement('div')
    preview.id = 'preview'
    preview.classList.add('preview', 'btn-group')
    preview.appendChild(previewVar)
    preview.appendChild(previewClass)
    preview.appendChild(previewConst)

    return preview
  }

  serialize() {}

  destroy() {
    this.element.remove();
  }

  getFindText() {
    return this.findInput.getText()
  }

  getReplaceText() {
    return this.replaceInput.getText()
  }

  getOldVarName() {
    return this.getFindText()
  }

  getNewVarName() {
    return this.getReplaceText()
  }

  getOldClassName() {
    return this.getFindText().charAt(0).toUpperCase() + this.getFindText().slice(1)
  }

  getNewClassName() {
    return this.getReplaceText().charAt(0).toUpperCase() + this.getReplaceText().slice(1)
  }

  getOldConstName() {
    return this.getFindText().toUpperCase()
  }

  getNewConstName() {
    return this.getReplaceText().toUpperCase()
  }

  getElement() {
    return this.element
  }

  getPreviewElement() {
    return document.getElementById('preview')
  }

  getPreviewVarElement() {
    return document.getElementById('preview-var')
  }

  getPreviewClassElement() {
    return document.getElementById('preview-class')
  }

  getPreviewConstElement() {
    return document.getElementById('preview-const')
  }

  updatePreview() {
    const oldVarName = this.getOldVarName() || 'oldName'
    const oldClassName = this.getOldClassName() || 'OldName'
    const oldConstName = this.getOldConstName() || 'OLDNAME'

    const newVarName = this.getNewVarName() || 'newName'
    const newClassName = this.getNewClassName() || 'NewName'
    const newConstName = this.getNewConstName() || 'NEWNAME'

    const varReplacePreview = oldVarName + ' -> ' + newVarName
    const classReplacePreview = oldClassName + ' -> ' + newClassName
    const constReplacePreview = oldConstName + ' -> ' + newConstName

    this.getPreviewVarElement().textContent = varReplacePreview
    this.getPreviewClassElement().textContent = classReplacePreview
    this.getPreviewConstElement().textContent = constReplacePreview
  }

  replaceVarsNames(text) {
    const findText = this.getOldVarName()
    const replaceText = this.getNewVarName()

    return text.replace(new RegExp(findText, 'g'), replaceText)
  }

  replaceClassesNames(text) {
    const findText = this.getOldClassName()
    const replaceText = this.getNewClassName()

    return text.replace(new RegExp(findText, 'g'), replaceText)
  }

  replaceConstantsNames(text) {
    const findText = this.getOldConstName()
    const replaceText = this.getNewConstName()

    return text.replace(new RegExp(findText, 'g'), replaceText)
  }

  replaceInSelection() {
    const editor = atom.workspace.getActiveTextEditor()
    let selection = editor.getSelectedText()

    // aaa -> bbb
    selection = this.replaceVarsNames(selection)

    // Aaa -> Bbb
    selection = this.replaceClassesNames(selection)

    // AAA -> BBB
    selection = this.replaceConstantsNames(selection)

    editor.insertText(selection)
  }

  replaceInBuffer() {
    const editor = atom.workspace.getActiveTextEditor()
    const buffer = editor.getBuffer()

    // aaa -> bbb
    this.replaceVarsNames(buffer)

    // Aaa -> Bbb
    this.replaceClassesNames(buffer)

    // AAA -> BBB
    this.replaceConstantsNames(buffer)
  }

  replace() {
    const editor = atom.workspace.getActiveTextEditor()

    if (editor.getSelectedText().length > 0) {
      editor.transact(this.replaceInSelection)
    } else {
      editor.transact(this.replaceInBuffer)
    }
  }
}
<commit_msg>Replace underscored names<commit_after>'use babel';

export default class CaseKeepReplaceView {
  constructor(serializedState) {
    this.state = serializedState || {}

    // Binding
    this.updatePreview = this.updatePreview.bind(this)
    this.replace = this.replace.bind(this)
    this.replaceInBuffer = this.replaceInBuffer.bind(this)
    this.replaceInSelection = this.replaceInSelection.bind(this)

    // Create root element
    this.element = document.createElement('div')
    this.element.classList.add('case-keep-replace')

    // Create children
    this.element.appendChild(this.createHeader())
    this.element.appendChild(this.createForm())
    this.element.appendChild(this.createPreview())
  }

  createHeader() {
    const header = document.createElement('h6')
    header.textContent = 'Find and replace with original case'

    return header
  }

  createForm() {
    const findInput = document.createElement('atom-text-editor')
    findInput.id = 'input-find'
    findInput.setAttribute('mini', true)
    findInput.classList.add('input-text')
    findInput.getModel().setPlaceholderText('Find ... (camelCase)')
    findInput.tabIndex = "1"
    this.findInput = findInput.getModel()
    this.findInput.onDidChange(this.updatePreview)

    const replaceInput = document.createElement('atom-text-editor')
    replaceInput.id = 'input-replace'
    replaceInput.setAttribute('mini', true)
    replaceInput.classList.add('input-text')
    replaceInput.getModel().setPlaceholderText('Replace to ... (camelCase)')
    replaceInput.tabIndex = "2"
    this.replaceInput = replaceInput.getModel()
    this.replaceInput.onDidChange(this.updatePreview)

    const form = document.createElement('div')
    form.classList.add('block', 'form')
    form.appendChild(findInput)
    form.appendChild(replaceInput)

    return form
  }

  createPreview() {
    const previewVar = document.createElement('button')
    previewVar.id = 'preview-var'
    previewVar.classList.add('btn', 'selected', 'disabled')

    const previewClass = document.createElement('button')
    previewClass.id = 'preview-class'
    previewClass.classList.add('btn', 'selected', 'disabled')

    const previewConst = document.createElement('button')
    previewConst.id = 'preview-const'
    previewConst.classList.add('btn', 'selected', 'disabled')

    const previewUnderscoredConst = document.createElement('button')
    previewUnderscoredConst.id = 'preview-underscored-const'
    previewUnderscoredConst.classList.add('btn', 'selected', 'disabled')

    const preview = document.createElement('div')
    preview.id = 'preview'
    preview.classList.add('preview', 'btn-group')
    preview.appendChild(previewVar)
    preview.appendChild(previewClass)
    preview.appendChild(previewConst)
    preview.appendChild(previewUnderscoredConst)

    return preview
  }

  serialize() {}

  destroy() {
    this.element.remove();
  }

  getFindText() {
    return this.findInput.getText()
  }

  getReplaceText() {
    return this.replaceInput.getText()
  }

  getOldVarName() {
    return this.getFindText()
  }

  getNewVarName() {
    return this.getReplaceText()
  }

  getOldClassName() {
    return this.getFindText().charAt(0).toUpperCase() + this.getFindText().slice(1)
  }

  getNewClassName() {
    return this.getReplaceText().charAt(0).toUpperCase() + this.getReplaceText().slice(1)
  }

  getOldConstName() {
    return this.getFindText().toUpperCase()
  }

  getNewConstName() {
    return this.getReplaceText().toUpperCase()
  }

  getOldUnderscoredConstName() {
    return this.getFindText().split(new RegExp('(?=[A-Z][a-z])', 'g')).join('_').toUpperCase()
  }

  getNewUnderscoredConstName() {
    return this.getReplaceText().split(new RegExp('(?=[A-Z][a-z])', 'g')).join('_').toUpperCase()
  }

  getElement() {
    return this.element
  }

  getPreviewElement() {
    return document.getElementById('preview')
  }

  getPreviewVarElement() {
    return document.getElementById('preview-var')
  }

  getPreviewClassElement() {
    return document.getElementById('preview-class')
  }

  getPreviewConstElement() {
    return document.getElementById('preview-const')
  }

  getPreviewUnderscoredConstElement() {
    return document.getElementById('preview-underscored-const')
  }

  updatePreview() {
    const oldVarName = this.getOldVarName() || 'oldName'
    const oldClassName = this.getOldClassName() || 'OldName'
    const oldConstName = this.getOldConstName() || 'OLDNAME'
    const oldUnderscoredConstName = this.getOldUnderscoredConstName() || 'OLD_NAME'

    const newVarName = this.getNewVarName() || 'newName'
    const newClassName = this.getNewClassName() || 'NewName'
    const newConstName = this.getNewConstName() || 'NEWNAME'
    const newUnderscoredConstName = this.getNewUnderscoredConstName() || 'NEW_NAME'

    const varReplacePreview = oldVarName + ' -> ' + newVarName
    const classReplacePreview = oldClassName + ' -> ' + newClassName
    const constReplacePreview = oldConstName + ' -> ' + newConstName
    const underscoredConstReplacePreview = oldUnderscoredConstName + ' -> ' + newUnderscoredConstName

    this.getPreviewVarElement().textContent = varReplacePreview
    this.getPreviewClassElement().textContent = classReplacePreview
    this.getPreviewConstElement().textContent = constReplacePreview
    this.getPreviewUnderscoredConstElement().textContent = underscoredConstReplacePreview
  }

  replaceVarsNames(text) {
    const findText = this.getOldVarName()
    const replaceText = this.getNewVarName()

    return text.replace(new RegExp(findText, 'g'), replaceText)
  }

  replaceClassesNames(text) {
    const findText = this.getOldClassName()
    const replaceText = this.getNewClassName()

    return text.replace(new RegExp(findText, 'g'), replaceText)
  }

  replaceConstantsNames(text) {
    const findText = this.getOldConstName()
    const replaceText = this.getNewConstName()

    return text.replace(new RegExp(findText, 'g'), replaceText)
  }

  replaceUnderscoredConstantsNames(text) {
    const findText = this.getOldUnderscoredConstName()
    const replaceText = this.getNewUnderscoredConstName()

    return text.replace(new RegExp(findText, 'g'), replaceText)
  }

  replaceInSelection() {
    const editor = atom.workspace.getActiveTextEditor()
    let selection = editor.getSelectedText()

    // aaa -> bbb
    selection = this.replaceVarsNames(selection)

    // Aaa -> Bbb
    selection = this.replaceClassesNames(selection)

    // AAA -> BBB
    selection = this.replaceConstantsNames(selection)

    // A_A -> B_B
    selection = this.replaceUnderscoredConstantsNames(selection)

    editor.insertText(selection)
  }

  replaceInBuffer() {
    const editor = atom.workspace.getActiveTextEditor()
    const buffer = editor.getBuffer()

    // aaa -> bbb
    this.replaceVarsNames(buffer)

    // Aaa -> Bbb
    this.replaceClassesNames(buffer)

    // AAA -> BBB
    this.replaceConstantsNames(buffer)

    // A_A -> B_B
    this.replaceUnderscoredConstantsNames(buffer)
  }

  replace() {
    const editor = atom.workspace.getActiveTextEditor()

    if (editor.getSelectedText().length > 0) {
      editor.transact(this.replaceInSelection)
    } else {
      editor.transact(this.replaceInBuffer)
    }
  }
}
<|endoftext|>


<commit_before>(function() {
	analyzingURL();
})();

function randomTime(time) {
	return time * (Math.ramdom() + 0.8);
}

function analyzingURL() {
	console.log('==Analyzing URL==');
	var hash = location.hash;
	console.log('Get Hash : ' + hash);
	if(/coopraid\/offer/i.test(hash))
		offer();
	else if(/coopraid\/room/i.test(hash))
		room();
	else if(/supporter/i.test(hash))
		supporter();
	else if(/raid_multi/i.test(hash))
		raid_multi();
	else if(/result_multi/i.test(hash) || /quest$/i.test(hash)) {
		setTimeout(function(){
			console.log('==Result Multi Stage==');
			location.href = "http://gbf.game.mbga.jp/#coopraid";
			setTimeout(function(){
				analyzingURL();
			}, 1000);
		}, 1000);
	}
	else if(/coopraid/i.test(hash))
		coopraid();
}

function coopraid() {
	console.log('==Coopraid Stage==');
	if($('.btn-join').length)
		$('.btn-join').trigger('tap');
	else if($('.prt-result-head head-win').length) {
		setTimeout(function(){
			location.reload();
		}, 1000);
	}
	setTimeout(function(){
		analyzingURL();
	}, 1000);
}

function offer() {
	console.log('==Offer Stage==');
	setTimeout(function(){
		if($('.prt-invite-type-1'))
			$('.prt-invite-type-1').trigger('tap');
		if($('.btn-usual-join'))
			$('.btn-usual-join').trigger('tap');
		if($('.btn-usual-ok'))
			$('.btn-usual-ok').trigger('tap');
		if($('.btn-refresh-list'))
			$('.btn-refresh-list').trigger('tap');
		if($('.btn-usual-cancel'))
			$('.btn-usual-cancel').trigger('tap');
		setTimeout(function(){
			analyzingURL();
		}, 300);
	}, 700);
}

function room() {
	console.log('==Room Stage==');
	if($('.btn-make-ready-large.not-ready').length) {
		$('.btn-make-ready-large.not-ready').trigger('tap');
	}
	else if($('.btn-execute-ready.se-ok').length) {
		$('.btn-execute-ready.se-ok').trigger('tap');
		//btn-retraction-ready
	}
	setTimeout(function(){
		analyzingURL();
	}, 1000);
}

function supporter() {
	console.log('==Supporter Stage==');
	if($('.prt-supporter-detail').length) {
		$('.prt-supporter-detail').trigger('tap');
	}
	setTimeout(function(){
		if($('.btn-usual-ok').length) {
			$('.btn-usual-ok').trigger('tap');
		}
		setTimeout(function(){
			analyzingURL();
		}, 1000);
	}, 1000);
}

function raid_multi() {
	console.log('==Raid Multi Stage==');
	if($('.btn-attack-start.display-on').length) {
		$('.btn-attack-start.display-on').trigger('tap');
	}
	else if($('.btn-result').length) {
		$('.btn-result').trigger('tap');
	}
	setTimeout(function(){
		analyzingURL();
	}, 1000);
}
<commit_msg>Update coopraid.js<commit_after>(function() {
	analyzingURL();
})();

function randomTime(time) {
	return time * (Math.ramdom() + 0.8);
}

function analyzingURL() {
	console.log('==Analyzing URL==');
	var hash = location.hash;
	console.log('Get Hash : ' + hash);
	if(/coopraid\/offer/i.test(hash))
		offer();
	else if(/coopraid\/room/i.test(hash))
		room();
	else if(/supporter/i.test(hash))
		supporter();
	else if(/raid_multi/i.test(hash))
		raid_multi();
	else if(/result_multi/i.test(hash) || /quest$/i.test(hash)) {
		setTimeout(function(){
			console.log('==Result Multi Stage==');
			location.href = "http://gbf.game.mbga.jp/#coopraid";
			setTimeout(function(){
				analyzingURL();
			}, 1000);
		}, 1000);
	}
	else if(/coopraid/i.test(hash))
		coopraid();
}

function coopraid() {
	console.log('==Coopraid Stage==');
	if($('.btn-join').length)
		$('.btn-join').trigger('tap');
	else if($('.prt-result-head head-win').length) {
		setTimeout(function(){
			location.reload();
		}, 1000);
	}
	setTimeout(function(){
		analyzingURL();
	}, 1000);
}

function offer() {
	console.log('==Offer Stage==');
	setTimeout(function(){
		if($('.prt-invite-type-1'))
			$('.prt-invite-type-1').trigger('tap');
		setTimeout(function(){
			if($('.btn-usual-join'))
				$('.btn-usual-join').trigger('tap');
			setTimeout(function(){
				if($('.btn-usual-ok'))
					$('.btn-usual-ok').trigger('tap');
				setTimeout(function(){
					if($('.btn-refresh-list'))
						$('.btn-refresh-list').trigger('tap');
					setTimeout(function(){
						if($('.btn-usual-cancel'))
							$('.btn-usual-cancel').trigger('tap');
						setTimeout(analyzingURL, 100);
					}, 100);
				}, 100);
			}, 100);
		}, 100);
	}, 600);
}

function room() {
	console.log('==Room Stage==');
	if($('.btn-make-ready-large.not-ready').length) {
		$('.btn-make-ready-large.not-ready').trigger('tap');
	}
	else if($('.btn-execute-ready.se-ok').length) {
		$('.btn-execute-ready.se-ok').trigger('tap');
		//btn-retraction-ready
	}
	setTimeout(function(){
		analyzingURL();
	}, 1000);
}

function supporter() {
	console.log('==Supporter Stage==');
	if($('.prt-supporter-detail').length) {
		$('.prt-supporter-detail').trigger('tap');
	}
	setTimeout(function(){
		if($('.btn-usual-ok').length) {
			$('.btn-usual-ok').trigger('tap');
		}
		setTimeout(function(){
			analyzingURL();
		}, 1000);
	}, 1000);
}

function raid_multi() {
	console.log('==Raid Multi Stage==');
	if($('.btn-attack-start.display-on').length) {
		$('.btn-attack-start.display-on').trigger('tap');
	}
	else if($('.btn-result').length) {
		$('.btn-result').trigger('tap');
	}
	setTimeout(function(){
		analyzingURL();
	}, 1000);
}
<|endoftext|>


<commit_before><commit_msg>Handle redirect to sub menu when click parent menu (#876)<commit_after><|endoftext|>


<commit_before>/* global Whisper: false */
/* global Backbone: false */
/* eslint-disable more/no-then */

// eslint-disable-next-line func-names
(function () {
  'use strict';

  window.Whisper = window.Whisper || {};
  window.Whisper.Database = window.Whisper.Database || {};
  window.Whisper.Database.id = window.Whisper.Database.id || 'signal';
  window.Whisper.Database.nolog = true;

  Whisper.Database.handleDOMException = (prefix, error, reject) => {
    console.log(
      `${prefix}:`,
      error && error.name,
      error && error.message,
      error && error.code
    );
    reject(error || new Error(prefix));
  };

  function clearStores(db, names) {
    return new Promise(((resolve, reject) => {
      const storeNames = names || db.objectStoreNames;
      console.log('Clearing these indexeddb stores:', storeNames);
      const transaction = db.transaction(storeNames, 'readwrite');

      let finished = false;
      const finish = (via) => {
        console.log('clearing all stores done via', via);
        if (finished) {
          resolve();
        }
        finished = true;
      };

      transaction.oncomplete = finish.bind(null, 'transaction complete');
      transaction.onerror = () => {
        Whisper.Database.handleDOMException(
          'clearStores transaction error',
          transaction.error,
          reject
        );
      };

      let count = 0;
      storeNames.forEach((storeName) => {
        const store = transaction.objectStore(storeName);
        const request = store.clear();

        request.onsuccess = () => {
          count += 1;
          console.log('Done clearing store', storeName);

          if (count >= storeNames.length) {
            console.log('Done clearing all indexeddb stores');
            finish('clears complete');
          }
        };

        request.onerror = () => {
          Whisper.Database.handleDOMException(
            'clearStores request error',
            request.error,
            reject
          );
        };
      });
    }));
  }

  Whisper.Database.open = () => {
    const { migrations } = Whisper.Database;
    const { version } = migrations[migrations.length - 1];
    const DBOpenRequest = window.indexedDB.open(Whisper.Database.id, version);

    return new Promise(((resolve, reject) => {
      // these two event handlers act on the IDBDatabase object,
      // when the database is opened successfully, or not
      DBOpenRequest.onerror = reject;
      DBOpenRequest.onsuccess = () => resolve(DBOpenRequest.result);

      // This event handles the event whereby a new version of
      // the database needs to be created Either one has not
      // been created before, or a new version number has been
      // submitted via the window.indexedDB.open line above
      DBOpenRequest.onupgradeneeded = reject;
    }));
  };

  Whisper.Database.clear = async () => {
    const db = await Whisper.Database.open();
    return clearStores(db);
  };

  Whisper.Database.clearStores = async (storeNames) => {
    const db = await Whisper.Database.open();
    return clearStores(db, storeNames);
  };

  Whisper.Database.close = () => window.wrapDeferred(Backbone.sync('closeall'));

  Whisper.Database.drop = () =>
    new Promise(((resolve, reject) => {
      const request = window.indexedDB.deleteDatabase(Whisper.Database.id);

      request.onblocked = () => {
        reject(new Error('Error deleting database: Blocked.'));
      };
      request.onupgradeneeded = () => {
        reject(new Error('Error deleting database: Upgrade needed.'));
      };
      request.onerror = () => {
        reject(new Error('Error deleting database.'));
      };

      request.onsuccess = resolve;
    }));

  Whisper.Database.migrations = [
    {
      version: '12.0',
      migrate(transaction, next) {
        console.log('migration 1.0');
        console.log('creating object stores');
        const messages = transaction.db.createObjectStore('messages');
        messages.createIndex('conversation', ['conversationId', 'received_at'], {
          unique: false,
        });
        messages.createIndex('receipt', 'sent_at', { unique: false });
        messages.createIndex('unread', ['conversationId', 'unread'], { unique: false });
        messages.createIndex('expires_at', 'expires_at', { unique: false });

        const conversations = transaction.db.createObjectStore('conversations');
        conversations.createIndex('inbox', 'active_at', { unique: false });
        conversations.createIndex('group', 'members', {
          unique: false,
          multiEntry: true,
        });
        conversations.createIndex('type', 'type', {
          unique: false,
        });
        conversations.createIndex('search', 'tokens', {
          unique: false,
          multiEntry: true,
        });

        transaction.db.createObjectStore('groups');

        transaction.db.createObjectStore('sessions');
        transaction.db.createObjectStore('identityKeys');
        transaction.db.createObjectStore('preKeys');
        transaction.db.createObjectStore('signedPreKeys');
        transaction.db.createObjectStore('items');

        console.log('creating debug log');
        transaction.db.createObjectStore('debug');

        next();
      },
    },
    {
      version: '13.0',
      migrate(transaction, next) {
        console.log('migration 13.0');
        console.log('Adding fields to identity keys');
        const identityKeys = transaction.objectStore('identityKeys');
        const request = identityKeys.openCursor();
        const promises = [];
        request.onsuccess = (event) => {
          const cursor = event.target.result;
          if (cursor) {
            const attributes = cursor.value;
            attributes.timestamp = 0;
            attributes.firstUse = false;
            attributes.nonblockingApproval = false;
            attributes.verified = 0;
            promises.push(new Promise(((resolve, reject) => {
              const putRequest = identityKeys.put(attributes, attributes.id);
              putRequest.onsuccess = resolve;
              putRequest.onerror = (e) => {
                console.log(e);
                reject(e);
              };
            })));
            cursor.continue();
          } else {
            // no more results
            Promise.all(promises).then(() => {
              next();
            });
          }
        };
        request.onerror = (event) => {
          console.log(event);
        };
      },
    },
    {
      version: '14.0',
      migrate(transaction, next) {
        console.log('migration 14.0');
        console.log('Adding unprocessed message store');
        const unprocessed = transaction.db.createObjectStore('unprocessed');
        unprocessed.createIndex('received', 'timestamp', { unique: false });
        next();
      },
    },
    {
      version: '15.0',
      migrate(transaction, next) {
        console.log('migration 15.0');
        console.log('Adding messages index for de-duplication');
        const messages = transaction.objectStore('messages');
        messages.createIndex('unique', ['source', 'sourceDevice', 'sent_at'], {
          unique: true,
        });
        next();
      },
    },
    {
      version: '16.0',
      migrate(transaction, next) {
        console.log('migration 16.0');
        console.log('Dropping log table, since we now log to disk');
        transaction.db.deleteObjectStore('debug');
        next();
      },
    },
  ];
}());
<commit_msg>Fix broken storeNames.forEach, since it's not an array<commit_after>/* global Whisper: false */
/* global Backbone: false */
/* global _: false */

/* eslint-disable more/no-then */

// eslint-disable-next-line func-names
(function () {
  'use strict';

  window.Whisper = window.Whisper || {};
  window.Whisper.Database = window.Whisper.Database || {};
  window.Whisper.Database.id = window.Whisper.Database.id || 'signal';
  window.Whisper.Database.nolog = true;

  Whisper.Database.handleDOMException = (prefix, error, reject) => {
    console.log(
      `${prefix}:`,
      error && error.name,
      error && error.message,
      error && error.code
    );
    reject(error || new Error(prefix));
  };

  function clearStores(db, names) {
    return new Promise(((resolve, reject) => {
      const storeNames = names || db.objectStoreNames;
      console.log('Clearing these indexeddb stores:', storeNames);
      const transaction = db.transaction(storeNames, 'readwrite');

      let finished = false;
      const finish = (via) => {
        console.log('clearing all stores done via', via);
        if (finished) {
          resolve();
        }
        finished = true;
      };

      transaction.oncomplete = finish.bind(null, 'transaction complete');
      transaction.onerror = () => {
        Whisper.Database.handleDOMException(
          'clearStores transaction error',
          transaction.error,
          reject
        );
      };

      let count = 0;

      // can't use built-in .forEach because db.objectStoreNames is not a plain array
      _.forEach(storeNames, (storeName) => {
        const store = transaction.objectStore(storeName);
        const request = store.clear();

        request.onsuccess = () => {
          count += 1;
          console.log('Done clearing store', storeName);

          if (count >= storeNames.length) {
            console.log('Done clearing indexeddb stores');
            finish('clears complete');
          }
        };

        request.onerror = () => {
          Whisper.Database.handleDOMException(
            'clearStores request error',
            request.error,
            reject
          );
        };
      });
    }));
  }

  Whisper.Database.open = () => {
    const { migrations } = Whisper.Database;
    const { version } = migrations[migrations.length - 1];
    const DBOpenRequest = window.indexedDB.open(Whisper.Database.id, version);

    return new Promise(((resolve, reject) => {
      // these two event handlers act on the IDBDatabase object,
      // when the database is opened successfully, or not
      DBOpenRequest.onerror = reject;
      DBOpenRequest.onsuccess = () => resolve(DBOpenRequest.result);

      // This event handles the event whereby a new version of
      // the database needs to be created Either one has not
      // been created before, or a new version number has been
      // submitted via the window.indexedDB.open line above
      DBOpenRequest.onupgradeneeded = reject;
    }));
  };

  Whisper.Database.clear = async () => {
    const db = await Whisper.Database.open();
    return clearStores(db);
  };

  Whisper.Database.clearStores = async (storeNames) => {
    const db = await Whisper.Database.open();
    return clearStores(db, storeNames);
  };

  Whisper.Database.close = () => window.wrapDeferred(Backbone.sync('closeall'));

  Whisper.Database.drop = () =>
    new Promise(((resolve, reject) => {
      const request = window.indexedDB.deleteDatabase(Whisper.Database.id);

      request.onblocked = () => {
        reject(new Error('Error deleting database: Blocked.'));
      };
      request.onupgradeneeded = () => {
        reject(new Error('Error deleting database: Upgrade needed.'));
      };
      request.onerror = () => {
        reject(new Error('Error deleting database.'));
      };

      request.onsuccess = resolve;
    }));

  Whisper.Database.migrations = [
    {
      version: '12.0',
      migrate(transaction, next) {
        console.log('migration 1.0');
        console.log('creating object stores');
        const messages = transaction.db.createObjectStore('messages');
        messages.createIndex('conversation', ['conversationId', 'received_at'], {
          unique: false,
        });
        messages.createIndex('receipt', 'sent_at', { unique: false });
        messages.createIndex('unread', ['conversationId', 'unread'], { unique: false });
        messages.createIndex('expires_at', 'expires_at', { unique: false });

        const conversations = transaction.db.createObjectStore('conversations');
        conversations.createIndex('inbox', 'active_at', { unique: false });
        conversations.createIndex('group', 'members', {
          unique: false,
          multiEntry: true,
        });
        conversations.createIndex('type', 'type', {
          unique: false,
        });
        conversations.createIndex('search', 'tokens', {
          unique: false,
          multiEntry: true,
        });

        transaction.db.createObjectStore('groups');

        transaction.db.createObjectStore('sessions');
        transaction.db.createObjectStore('identityKeys');
        transaction.db.createObjectStore('preKeys');
        transaction.db.createObjectStore('signedPreKeys');
        transaction.db.createObjectStore('items');

        console.log('creating debug log');
        transaction.db.createObjectStore('debug');

        next();
      },
    },
    {
      version: '13.0',
      migrate(transaction, next) {
        console.log('migration 13.0');
        console.log('Adding fields to identity keys');
        const identityKeys = transaction.objectStore('identityKeys');
        const request = identityKeys.openCursor();
        const promises = [];
        request.onsuccess = (event) => {
          const cursor = event.target.result;
          if (cursor) {
            const attributes = cursor.value;
            attributes.timestamp = 0;
            attributes.firstUse = false;
            attributes.nonblockingApproval = false;
            attributes.verified = 0;
            promises.push(new Promise(((resolve, reject) => {
              const putRequest = identityKeys.put(attributes, attributes.id);
              putRequest.onsuccess = resolve;
              putRequest.onerror = (e) => {
                console.log(e);
                reject(e);
              };
            })));
            cursor.continue();
          } else {
            // no more results
            Promise.all(promises).then(() => {
              next();
            });
          }
        };
        request.onerror = (event) => {
          console.log(event);
        };
      },
    },
    {
      version: '14.0',
      migrate(transaction, next) {
        console.log('migration 14.0');
        console.log('Adding unprocessed message store');
        const unprocessed = transaction.db.createObjectStore('unprocessed');
        unprocessed.createIndex('received', 'timestamp', { unique: false });
        next();
      },
    },
    {
      version: '15.0',
      migrate(transaction, next) {
        console.log('migration 15.0');
        console.log('Adding messages index for de-duplication');
        const messages = transaction.objectStore('messages');
        messages.createIndex('unique', ['source', 'sourceDevice', 'sent_at'], {
          unique: true,
        });
        next();
      },
    },
    {
      version: '16.0',
      migrate(transaction, next) {
        console.log('migration 16.0');
        console.log('Dropping log table, since we now log to disk');
        transaction.db.deleteObjectStore('debug');
        next();
      },
    },
  ];
}());
<|endoftext|>


<commit_before>"use strict";

var Defaults = {

  _autoLoad_: function() {

    var ls = localStorage;

    // Clear previous thoughts
    if (DEBUG) ls.clear();
    ls.removeItem('officeStatus');
    ls.removeItem('officeStatusMessage');

    // Set default choices if undefined, in the same order as on the options page

    if (ls.extensionName == undefined)
      ls.extensionName = 'Online Notifier';
    if (ls.extensionCreator == undefined)
      ls.extensionCreator = 'appKom'; // Max 8 letters because of styling
    if (ls.installTime == undefined)
      ls.installTime = new Date().getTime();

    // Primary affiliation
    if (ls.showAffiliation1 == undefined)
      ls.showAffiliation1 = 'true';
    if (ls.affiliationKey1 == undefined)
      ls.affiliationKey1 = (DEBUG ? 'DEBUG' : 'online');
    if (ls.affiliationUnreadCount1 == undefined)
      ls.affiliationUnreadCount1 = 0;
    if (ls.affiliationNewsList1 == undefined)
      ls.affiliationNewsList1 = JSON.stringify([]);
    if (ls.affiliationViewedList1 == undefined)
      ls.affiliationViewedList1 = JSON.stringify([]);

    if (ls.affiliationPalette == undefined)
      ls.affiliationPalette = 'online';
    if (ls.storedImages == undefined)
      ls.storedImages = JSON.stringify({});

    // Secondary affiliation
    if (ls.showAffiliation2 == undefined)
      ls.showAffiliation2 = 'true';
    if (ls.affiliationKey2 == undefined)
      ls.affiliationKey2 = 'dusken';
    if (ls.affiliationUnreadCount2 == undefined)
      ls.affiliationUnreadCount2 = 0;
    if (ls.affiliationNewsList2 == undefined)
      ls.affiliationNewsList2 = JSON.stringify([]);
    if (ls.affiliationViewedList2 == undefined)
      ls.affiliationViewedList2 = JSON.stringify([]);

    if (ls.showBus == undefined)
      ls.showBus = 'true';

    // Bus - If any of these properties are undefined we'll reset all of them
    var firstBusProps = [
      ls.firstBus,
      ls.firstBusName,
      ls.firstBusDirection,
      ls.firstBusActiveLines,
      ls.firstBusInactiveLines,
    ]
    var secondBusProps = [
      ls.secondBus,
      ls.secondBusName,
      ls.secondBusDirection,
      ls.secondBusActiveLines,
      ls.secondBusInactiveLines,
    ]
    var firstBusOk = true;
    var secondBusOk = true;
    for (var prop in firstBusProps) {
      if (typeof firstBusProps[prop] == 'undefined') {
        firstBusOk = false;
      }
    }
    for (var prop in secondBusProps) {
      if (typeof secondBusProps[prop] == 'undefined') {
        secondBusOk = false;
      }
    }
    if (!firstBusOk) {
      ls.firstBus = 16011333;
      ls.firstBusName = 'Gløshaugen Nord';
      ls.firstBusDirection = 'til byen';
      ls.firstBusActiveLines = JSON.stringify([5, 22]);
      ls.firstBusInactiveLines = JSON.stringify([169]);
    }
    if (!secondBusOk) {
      ls.secondBus = 16010333;
      ls.secondBusName = 'Gløshaugen Nord';
      ls.secondBusDirection = 'fra byen';
      ls.secondBusActiveLines = JSON.stringify([5, 22]);
      ls.secondBusInactiveLines = JSON.stringify([169]);
    }

    // Office
    if (ls.showOffice == undefined)
      ls.showOffice = 'true';
    if (ls.activelySetOffice == undefined) {
      ls.activelySetOffice = 'true';
      ls.showOffice = 'true';
    }

    // Cantina
    if (ls.showCantina == undefined)
      ls.showCantina = 'true';
    if (ls.leftCantina == undefined)
      ls.leftCantina = 'hangaren';
    if (ls.rightCantina == undefined)
      ls.rightCantina = 'realfag';

    // Notifications
    if (ls.showNotifications == undefined)
      ls.showNotifications = 'true';

    // Subscription
    if (ls.coffeeSubscription == undefined)
      ls.coffeeSubscription = 'true';
    if (ls.coffeePots == undefined)
      ls.coffeePots = 0;
    if (ls.activelySetCoffee == undefined) {
      ls.activelySetCoffee = 'true';
      ls.coffeeSubscription = 'true';
    }

    // Bigscreen
    if (ls.useBigscreen == undefined)
      ls.useBigscreen = 'false';
    if (ls.whichScreen == undefined)
      ls.whichScreen = 'notifier';

    // General
    if (ls.everOpenedOptions == undefined)
      ls.everOpenedOptions = 'false';
  }(),

  // Whenever we need to remove an existing affiliation,
  // this little heartsaver comes to our rescue. Just go
  // ahead and uncomment that affiliation in Affiliation.js !
  resetAffiliationsIfNotExist: function(key1, key2, affiliationKeys) {

    var ls = localStorage;

    var gotoOptions = function(key) {
      if (confirm('Online Notifier beklager:\n\n"'+key+'" er borte fra Notifier :(\n\nTrolig fordi foreningens nettside ikke finnes lenger.\n\nDu kan trykke OK for å åpne Notifiers innstillinger.')) {
        Browser.openTab('options.html');
      }
    }
    if (affiliationKeys.indexOf(key1) === -1) {
      ls.affiliationKey1 = 'online';
      gotoOptions(key1);
    }
    if (affiliationKeys.indexOf(key2) === -1) {
      ls.affiliationKey2 = 'dusken';
      gotoOptions(key2);
    }
  },

  // There is currently no way of knowing whether HardwareFeatures have been
  // installed recently or not, - if they exist. Therefore we will assume the
  // user starts out with the features turned on.
  // Then, the features will be turned off if:
  // a) the user has explicitly turned them off, or
  // b) hardwarefeatures are not available (this function called from background process)
  setHardwareFeatures: function(isAvailable) {

    var ls = localStorage;

    if (isAvailable) {
      // office
      if (ls.activelySetOffice == 'false')
        ls.showOffice = 'false';
      else
        ls.showOffice = 'true';
      // coffee
      if (ls.activelySetCoffee == 'false')
        ls.coffeeSubscription = 'false';
      else
        ls.coffeeSubscription = 'true';
    }
    else if (!isAvailable) {
      ls.showOffice = 'false';
      ls.coffeeSubscription = 'false';
    }
  },
}
<commit_msg>defaults: minor bugfix, thanks Jørgen<commit_after>"use strict";

var Defaults = {

  _autoLoad_: function() {

    var ls = localStorage;

    // Clear previous thoughts
    if (DEBUG) ls.clear();
    ls.removeItem('officeStatus');
    ls.removeItem('officeStatusMessage');

    // Set default choices if undefined, in the same order as on the options page

    ls.extensionName = 'Online Notifier';
    ls.extensionCreator = 'appKom'; // Max 8 letters because of styling
    if (ls.installTime == undefined)
      ls.installTime = new Date().getTime();

    // Primary affiliation
    if (ls.showAffiliation1 == undefined)
      ls.showAffiliation1 = 'true';
    if (ls.affiliationKey1 == undefined)
      ls.affiliationKey1 = (DEBUG ? 'DEBUG' : 'online');
    if (ls.affiliationUnreadCount1 == undefined)
      ls.affiliationUnreadCount1 = 0;
    if (ls.affiliationNewsList1 == undefined)
      ls.affiliationNewsList1 = JSON.stringify([]);
    if (ls.affiliationViewedList1 == undefined)
      ls.affiliationViewedList1 = JSON.stringify([]);

    if (ls.affiliationPalette == undefined)
      ls.affiliationPalette = 'online';
    if (ls.storedImages == undefined)
      ls.storedImages = JSON.stringify({});

    // Secondary affiliation
    if (ls.showAffiliation2 == undefined)
      ls.showAffiliation2 = 'true';
    if (ls.affiliationKey2 == undefined)
      ls.affiliationKey2 = 'dusken';
    if (ls.affiliationUnreadCount2 == undefined)
      ls.affiliationUnreadCount2 = 0;
    if (ls.affiliationNewsList2 == undefined)
      ls.affiliationNewsList2 = JSON.stringify([]);
    if (ls.affiliationViewedList2 == undefined)
      ls.affiliationViewedList2 = JSON.stringify([]);

    if (ls.showBus == undefined)
      ls.showBus = 'true';

    // Bus - If any of these properties are undefined we'll reset all of them
    var firstBusProps = [
      ls.firstBus,
      ls.firstBusName,
      ls.firstBusDirection,
      ls.firstBusActiveLines,
      ls.firstBusInactiveLines,
    ]
    var secondBusProps = [
      ls.secondBus,
      ls.secondBusName,
      ls.secondBusDirection,
      ls.secondBusActiveLines,
      ls.secondBusInactiveLines,
    ]
    var firstBusOk = true;
    var secondBusOk = true;
    for (var prop in firstBusProps) {
      if (typeof firstBusProps[prop] == 'undefined') {
        firstBusOk = false;
      }
    }
    for (var prop in secondBusProps) {
      if (typeof secondBusProps[prop] == 'undefined') {
        secondBusOk = false;
      }
    }
    if (!firstBusOk) {
      ls.firstBus = 16011333;
      ls.firstBusName = 'Gløshaugen Nord';
      ls.firstBusDirection = 'til byen';
      ls.firstBusActiveLines = JSON.stringify([5, 22]);
      ls.firstBusInactiveLines = JSON.stringify([169]);
    }
    if (!secondBusOk) {
      ls.secondBus = 16010333;
      ls.secondBusName = 'Gløshaugen Nord';
      ls.secondBusDirection = 'fra byen';
      ls.secondBusActiveLines = JSON.stringify([5, 22]);
      ls.secondBusInactiveLines = JSON.stringify([169]);
    }

    // Office
    if (ls.showOffice == undefined)
      ls.showOffice = 'true';
    if (ls.activelySetOffice == undefined) {
      ls.activelySetOffice = 'true';
      ls.showOffice = 'true';
    }

    // Cantina
    if (ls.showCantina == undefined)
      ls.showCantina = 'true';
    if (ls.leftCantina == undefined)
      ls.leftCantina = 'hangaren';
    if (ls.rightCantina == undefined)
      ls.rightCantina = 'realfag';

    // Notifications
    if (ls.showNotifications == undefined)
      ls.showNotifications = 'true';

    // Subscription
    if (ls.coffeeSubscription == undefined)
      ls.coffeeSubscription = 'true';
    if (ls.coffeePots == undefined)
      ls.coffeePots = 0;
    if (ls.activelySetCoffee == undefined) {
      ls.activelySetCoffee = 'true';
      ls.coffeeSubscription = 'true';
    }

    // Bigscreen
    if (ls.useBigscreen == undefined)
      ls.useBigscreen = 'false';
    if (ls.whichScreen == undefined)
      ls.whichScreen = 'notifier';

    // General
    if (ls.everOpenedOptions == undefined)
      ls.everOpenedOptions = 'false';
  }(),

  // Whenever we need to remove an existing affiliation,
  // this little heartsaver comes to our rescue. Just go
  // ahead and uncomment that affiliation in Affiliation.js !
  resetAffiliationsIfNotExist: function(key1, key2, affiliationKeys) {

    var ls = localStorage;

    var gotoOptions = function(key) {
      if (confirm('Online Notifier beklager:\n\n"'+key+'" er borte fra Notifier :(\n\nTrolig fordi foreningens nettside ikke finnes lenger.\n\nDu kan trykke OK for å åpne Notifiers innstillinger.')) {
        Browser.openTab('options.html');
      }
    }
    if (affiliationKeys.indexOf(key1) === -1) {
      ls.affiliationKey1 = 'online';
      gotoOptions(key1);
    }
    if (affiliationKeys.indexOf(key2) === -1) {
      ls.affiliationKey2 = 'dusken';
      gotoOptions(key2);
    }
  },

  // There is currently no way of knowing whether HardwareFeatures have been
  // installed recently or not, - if they exist. Therefore we will assume the
  // user starts out with the features turned on.
  // Then, the features will be turned off if:
  // a) the user has explicitly turned them off, or
  // b) hardwarefeatures are not available (this function called from background process)
  setHardwareFeatures: function(isAvailable) {

    var ls = localStorage;

    if (isAvailable) {
      // office
      if (ls.activelySetOffice == 'false')
        ls.showOffice = 'false';
      else
        ls.showOffice = 'true';
      // coffee
      if (ls.activelySetCoffee == 'false')
        ls.coffeeSubscription = 'false';
      else
        ls.coffeeSubscription = 'true';
    }
    else if (!isAvailable) {
      ls.showOffice = 'false';
      ls.coffeeSubscription = 'false';
    }
  },
}
<|endoftext|>


<commit_before>/*!
 * Chai - addProperty utility
 * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
 * MIT Licensed
 */

var chai = require('../../chai');
var config = require('../config');
var flag = require('./flag');
var transferFlags = require('./transferFlags');

/**
 * ### addProperty (ctx, name, getter)
 *
 * Adds a property to the prototype of an object.
 *
 *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {
 *       var obj = utils.flag(this, 'object');
 *       new chai.Assertion(obj).to.be.instanceof(Foo);
 *     });
 *
 * Can also be accessed directly from `chai.Assertion`.
 *
 *     chai.Assertion.addProperty('foo', fn);
 *
 * Then can be used as any other assertion.
 *
 *     expect(myFoo).to.be.foo;
 *
 * @param {Object} ctx object to which the property is added
 * @param {String} name of property to add
 * @param {Function} getter function to be used for name
 * @namespace Utils
 * @name addProperty
 * @api public
 */

module.exports = function (ctx, name, getter) {
  getter = getter === undefined ? new Function() : getter;

  Object.defineProperty(ctx, name,
    { get: function addProperty() {
        var old_ssfi = flag(this, 'ssfi');
        if (old_ssfi && config.includeStack === false)
          flag(this, 'ssfi', addProperty);

        var result = getter.call(this);
        var newAssertion = new chai.Assertion();
        transferFlags(this, newAssertion);

        return result === undefined ? newAssertion: result;
      }
    , configurable: true
  });
};
<commit_msg>addProperty: Prevent unnecessary transferFlags() calls<commit_after>/*!
 * Chai - addProperty utility
 * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
 * MIT Licensed
 */

var chai = require('../../chai');
var config = require('../config');
var flag = require('./flag');
var transferFlags = require('./transferFlags');

/**
 * ### addProperty (ctx, name, getter)
 *
 * Adds a property to the prototype of an object.
 *
 *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {
 *       var obj = utils.flag(this, 'object');
 *       new chai.Assertion(obj).to.be.instanceof(Foo);
 *     });
 *
 * Can also be accessed directly from `chai.Assertion`.
 *
 *     chai.Assertion.addProperty('foo', fn);
 *
 * Then can be used as any other assertion.
 *
 *     expect(myFoo).to.be.foo;
 *
 * @param {Object} ctx object to which the property is added
 * @param {String} name of property to add
 * @param {Function} getter function to be used for name
 * @namespace Utils
 * @name addProperty
 * @api public
 */

module.exports = function (ctx, name, getter) {
  getter = getter === undefined ? new Function() : getter;

  Object.defineProperty(ctx, name,
    { get: function addProperty() {
        var old_ssfi = flag(this, 'ssfi');
        if (old_ssfi && config.includeStack === false)
          flag(this, 'ssfi', addProperty);

        var result = getter.call(this);
        if (result !== undefined)
          return result;

        var newAssertion = new chai.Assertion();
        transferFlags(this, newAssertion);
        return newAssertion;
      }
    , configurable: true
  });
};
<|endoftext|>


<commit_before>//This is a chip-8 emulator
//Written by Jerry Schneider

//Recieves messages from the font end
self.onmessage = function(event){
    //Begin emulation
    if(event.data == "start"){
        main();
    }
    //Kill the emulator
    else if(event.data == "stop"){
        self.close();
    }
};

//The current opcode
var opcode;

//4k memory
// 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
// 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
// 0x200-0xFFF - Program ROM and work RAM
var memory = new ArrayBuffer(4096);

var memoryView = new Uint8Array(memory, 0);

//Registers
var V = [];

//Index register (upper 4 bits are unused)
var I = new ArrayBuffer(2);

//Program counter (upper 4 bits are unused)
var pc = new ArrayBuffer(2);

//Pixel Display 64 x 32
var pixels = [64 * 32];

//Timers which count down from X to 0 at 60hz
var delay_timer;
var sound_timer;

//16 frame stack
var stack = [16];
//Stack pointer
var sp;

//Key state
var key = [16];

function memoryInit(){
    //Init 16 8-bit registers
    for( i = 0; i < 16; i++ ){
        V.push( new ArrayBuffer(8) );
    }
    //Applications are expected to be loaded at 0x200
    pc = 0x200;

    //Clear memory
    opcode = 0;
    sp = 0;
    I = 0;

    //Load Fontset
}

function emulateCycle(){
    //Fetch opcode, instructions are 2 bytes long
    opcode = memory[pc] << 8 | memory[pc+1];
    //Decode opcode
    //Execute opcode

    //Update timers
}

function main(){
    memoryInit();

    //Emulation will begin once the game is loaded
}

//Load the game into the emulator memory
function loadGame(){
    for( i = 0; i < romFile.byteLength; i++ ){
        memoryView[0x200 + i] = romFile[i];
    }
}

function gameLoaded(){

    loadGame();
    for( i = 0; i < memory.byteLength; i++ ){
        console.log( memoryView[i] );
    }
    console.log('beginning emulation');
    //Emulation loop
    //while(true){
        //Emulate one cycle
        emulateCycle();

        //Draw to the screen

        //Get input
    //}
}
<commit_msg>added typeset<commit_after>//This is a chip-8 emulator
//Written by Jerry Schneider

//Load the fontset into memory at 0x50
function loadFontset(){
    for( i = 0; i < chip8_fontset.length; i++){
        memoryView[0x50 + i] = chip8_fontset[i];
    }
};

//Hardcoded fontset for the chip8
var chip8_fontset = [
  0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
  0x20, 0x60, 0x20, 0x20, 0x70, // 1
  0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
  0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
  0x90, 0x90, 0xF0, 0x10, 0x10, // 4
  0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
  0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
  0xF0, 0x10, 0x20, 0x40, 0x40, // 7
  0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
  0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
  0xF0, 0x90, 0xF0, 0x90, 0x90, // A
  0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
  0xF0, 0x80, 0x80, 0x80, 0xF0, // C
  0xE0, 0x90, 0x90, 0x90, 0xE0, // D
  0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
  0xF0, 0x80, 0xF0, 0x80, 0x80  // F
];

//Recieves messages from the font end
self.onmessage = function(event){
    //Begin emulation
    if(event.data == "start"){
        main();
    }
    //Kill the emulator
    else if(event.data == "stop"){
        self.close();
    }
};

//The current opcode
var opcode;

//4k memory
// 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
// 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
// 0x200-0xFFF - Program ROM and work RAM
var memory = new ArrayBuffer(4096);

var memoryView = new Uint8Array(memory, 0);

//Registers
var V = [];

//Index register (upper 4 bits are unused)
var I = new ArrayBuffer(2);

//Program counter (upper 4 bits are unused)
var pc = new ArrayBuffer(2);

//Pixel Display 64 x 32
var pixels = [64 * 32];

//Timers which count down from X to 0 at 60hz
var delay_timer;
var sound_timer;

//16 frame stack
var stack = [16];
//Stack pointer
var sp;

//Key state
var key = [16];

function memoryInit(){
    //Init 16 8-bit registers
    for( i = 0; i < 16; i++ ){
        V.push( new ArrayBuffer(8) );
    }
    //Applications are expected to be loaded at 0x200
    pc = 0x200;

    //Clear memory
    opcode = 0;
    sp = 0;
    I = 0;

    //Load Fontset
    loadFontset();
}

function emulateCycle(){
    //Fetch opcode, instructions are 2 bytes long
    opcode = memory[pc] << 8 | memory[pc+1];
    //Decode opcode
    //Execute opcode

    //Update timers
}

function main(){
    memoryInit();

    //Emulation will begin once the game is loaded
}

//Load the game into the emulator memory
function loadGame(){
    for( i = 0; i < romFile.byteLength; i++ ){
        memoryView[0x200 + i] = romFile[i];
    }
}

function gameLoaded(){

    loadGame();
    for( i = 0; i < memory.byteLength; i++ ){
        console.log( memoryView[i] );
    }
    console.log('beginning emulation');
    //Emulation loop
    //while(true){
        //Emulate one cycle
        emulateCycle();

        //Draw to the screen

        //Get input
    //}
}
<|endoftext|>


<commit_before>class Enemy {
  constructor() {
    this.enemies = DontPanic.game.add.group();
    var enemySpawnRate = config[config.currentLevel]['enemySpawnRate'];
    this.enemyTimer = DontPanic.game.time.events.loop(Phaser.Timer.SECOND * enemySpawnRate, this.createEnemy, this);
    this.enemyTimer.timer.start();
    // this.abduct();
  }

  createEnemy() {
    // let randomY = Math.floor(Math.random() * 200) + 50;
    const enemy = this.enemies.create(DontPanic.game.world.centerX, -10, 'enemyShip');
    enemy.scale.x = 0.2;
    enemy.scale.y = 0.2;
    enemy.fixedToCamera = true;
    DontPanic.game.physics.arcade.enable(enemy);
    enemy.body.collideWorldBounds = false;
    enemy.abductAnimate = enemy.animations.add('abduct');
    enemy.beamUpAnimate = enemy.animations.add('beamUp', [3,3,3,3,2,1,0]);
    enemy.body.setSize(275, 1140, 80, 0);
    enemy.body.immovable = true;
    enemy.abductCheck = false;
    enemy.abductSuccessful = false;
    enemy.positioned = false;
    DontPanic.game.time.events.add(Phaser.Timer.SECOND * 3.5, this.abduct, this, enemy);
    if (improbabilityDriveTriggered) {
      enemy.loadTexture(improbabilityScenarioAssets[currentScenario].enemy, 1);
      if (currentScenario == 'reset') {
        improbabilityDriveTriggered = false;
      }
    }
  }

  moveEnemy() {
    this.enemies.forEachExists((sprite) =>  {
      DontPanic.game.debug.body(sprite);
      if (!sprite.positioned && !sprite.abductCheck) {
          this.descend(sprite);
          this.moveToPlayer(sprite);
      }
      if (sprite.abductCheck) {
        this.leaveScreen(sprite);
      }
    });
  }

  moveToPlayer(sprite) {
    if (sprite.x >= player.playerSprite.x - (player.playerSprite.width / 2)) {
      sprite.cameraOffset.x -= config[config.currentLevel]['enemySpeedHorizontal'];
    } else {
      sprite.cameraOffset.x += config[config.currentLevel]['enemySpeedHorizontal'];
    }
  }

  descend(sprite) {
    if (sprite.y < (player.playerSprite.y - 255)) {
      sprite.cameraOffset.y += config[config.currentLevel]['enemySpeedVertical'];
    }
    else {
      sprite.positioned = true;
    }
  }

  leaveScreen(sprite) {
    if (sprite.x < player.playerSprite.x) {
      sprite.cameraOffset.x -= 1.5;
    } else {
      sprite.cameraOffset.x += 1.5;
    }
  }

  abduct(sprite) {
    if (!sprite.abductCheck) {
      sprite.animations.play('abduct', 20, false);
      sprite.abductAnimate.onComplete.add(() => {sprite.animations.play('beamUp', 20, false);}, this);
      sprite.abductCheck = true;
    }
  }
}

class Coins {
  constructor() {
    let coins = DontPanic.game.add.group();
    coins.enableBody = true;
    DontPanic.game.physics.arcade.enable(coins);
    this.coins = coins;
    this.initialCoins();
    // randomly generate more coins at intervals - https://developer.amazon.com/blogs/appstore/post/Tx3AT4I2ENBOI6R/intro-to-phaser-part-3-obstacles-collision-score-sound-and-publishing
    var coinSpawnRate = config[config.currentLevel]['coinSpawnRate'];
    this.coinTimer = DontPanic.game.time.events.loop(Phaser.Timer.SECOND * coinSpawnRate, this.randomCoinGenerator, this);
    this.coinTimer.timer.start();
  }

  initialCoins() {
    var initialCoinPositions = [[300, 0], [20, 40], [60, 80], [250, 200], [90, 120], [180, 350], [220, 10], [120, 290]]
    for (var i = 0; i < initialCoinPositions.length; i++) {
      this.createCoin(initialCoinPositions[i][0], initialCoinPositions[i][1]);
    }
  }

  randomCoinGenerator() {
    var randomX = Math.floor(Math.random() * 320) + 5;
    var randomY = Math.floor(Math.random() * 10) + -10;
    this.createCoin(randomX, randomY);
  }

  createCoin(x, y) {
    var coin = this.coins.create(x, y, 'coin');
    coin.scale.x = 0.3;
    coin.scale.y = 0.3;
    coin.enableBody = true;
    coin.body.velocity.y = 100;
    coin.body.collideWorldBounds = false;
    if (improbabilityDriveTriggered) {
      coin.loadTexture(improbabilityScenarioAssets[currentScenario].coins, 1);
    }
  }
}

class Obstacle {
  constructor() {
    let obstacles = DontPanic.game.add.group();
    obstacles.enableBody = true;
    DontPanic.game.physics.arcade.enable(obstacles);
    this.obstacles = obstacles;
  }

  whale() {
    var randomX = Math.floor(Math.random() * 250) + 100;
    const whale = obstacle.obstacles.create(randomX, -100, 'whale');
    whale.scale.x = 0.3;
    whale.scale.y = 0.3;
    DontPanic.game.physics.arcade.enable(whale);
    whale.body.collideWorldBounds = false;
    whale.body.gravity.y = 50;
  }

  petunias() {
    var randomX = Math.floor(Math.random() * 320) + 25;
    const petunias = obstacle.obstacles.create(randomX, -50, 'petunias');
    petunias.scale.x = 0.1;
    petunias.scale.y = 0.1;
    DontPanic.game.physics.arcade.enable(petunias);
    petunias.body.collideWorldBounds = false;
    petunias.body.gravity.y = 60;
  }
}
<commit_msg>remove comments and tidy a bit<commit_after>class Enemy {
  constructor() {
    this.enemies = DontPanic.game.add.group();
    var enemySpawnRate = config[config.currentLevel]['enemySpawnRate'];
    this.enemyTimer = DontPanic.game.time.events.loop(Phaser.Timer.SECOND * enemySpawnRate, this.createEnemy, this);
    this.enemyTimer.timer.start();
  }

  createEnemy() {
    const enemy = this.enemies.create(DontPanic.game.world.centerX, -10, 'enemyShip');
    enemy.scale.x = 0.2;
    enemy.scale.y = 0.2;
    enemy.fixedToCamera = true;
    DontPanic.game.physics.arcade.enable(enemy);
    enemy.body.collideWorldBounds = false;
    enemy.abductAnimate = enemy.animations.add('abduct');
    enemy.beamUpAnimate = enemy.animations.add('beamUp', [3,3,3,3,2,1,0]);
    enemy.body.setSize(275, 1140, 80, 0); // collision hit area
    enemy.body.immovable = true;
    enemy.abductCheck = false;
    enemy.abductSuccessful = false;
    enemy.positioned = false;
    DontPanic.game.time.events.add(Phaser.Timer.SECOND * 3.5, this.abduct, this, enemy);
    this.checkIfImprobabilityDriveSprite(enemy);
  }

  checkIfImprobabilityDriveSprite(enemy) {
    if (improbabilityDriveTriggered) {
      enemy.loadTexture(improbabilityScenarioAssets[currentScenario].enemy, 1);
      if (currentScenario == 'reset') {
        improbabilityDriveTriggered = false;
      }
    }
  }

  moveEnemy() {
    this.enemies.forEachExists((sprite) =>  {
      // DontPanic.game.debug.body(sprite);
      if (!sprite.positioned && !sprite.abductCheck) {
          this.descend(sprite);
          this.moveToPlayer(sprite);
      }
      if (sprite.abductCheck) {
        this.leaveScreen(sprite);
      }
    });
  }

  moveToPlayer(sprite) {
    if (sprite.x >= player.playerSprite.x - (player.playerSprite.width / 2)) {
      sprite.cameraOffset.x -= config[config.currentLevel]['enemySpeedHorizontal'];
    } else {
      sprite.cameraOffset.x += config[config.currentLevel]['enemySpeedHorizontal'];
    }
  }

  descend(sprite) {
    if (sprite.y < (player.playerSprite.y - 255)) {
      sprite.cameraOffset.y += config[config.currentLevel]['enemySpeedVertical'];
    }
    else {
      sprite.positioned = true;
    }
  }

  leaveScreen(sprite) {
    if (sprite.x < player.playerSprite.x) {
      sprite.cameraOffset.x -= 1.5;
    } else {
      sprite.cameraOffset.x += 1.5;
    }
  }

  abduct(sprite) {
    if (!sprite.abductCheck) {
      sprite.animations.play('abduct', 20, false);
      sprite.abductAnimate.onComplete.add(() => {sprite.animations.play('beamUp', 20, false);}, this);
      sprite.abductCheck = true;
    }
  }
}

class Coins {
  constructor() {
    let coins = DontPanic.game.add.group();
    coins.enableBody = true;
    DontPanic.game.physics.arcade.enable(coins);
    this.coins = coins;
    this.initialCoins();
    var coinSpawnRate = config[config.currentLevel]['coinSpawnRate'];
    this.coinTimer = DontPanic.game.time.events.loop(Phaser.Timer.SECOND * coinSpawnRate, this.randomCoinGenerator, this);
    this.coinTimer.timer.start();
  }

  initialCoins() {
    var initialCoinPositions = [[300, 0], [20, 40], [60, 80], [250, 200], [90, 120], [180, 350], [220, 10], [120, 290]]
    for (var i = 0; i < initialCoinPositions.length; i++) {
      this.createCoin(initialCoinPositions[i][0], initialCoinPositions[i][1]);
    }
  }

  randomCoinGenerator() {
    var randomX = Math.floor(Math.random() * 320) + 5;
    var randomY = Math.floor(Math.random() * 10) + -10;
    this.createCoin(randomX, randomY);
  }

  createCoin(x, y) {
    var coin = this.coins.create(x, y, 'coin');
    coin.scale.x = 0.3;
    coin.scale.y = 0.3;
    coin.enableBody = true;
    coin.body.velocity.y = 100;
    coin.body.collideWorldBounds = false;
    if (improbabilityDriveTriggered) {
      coin.loadTexture(improbabilityScenarioAssets[currentScenario].coins, 1);
    }
  }
}

class Obstacle {
  constructor() {
    let obstacles = DontPanic.game.add.group();
    obstacles.enableBody = true;
    DontPanic.game.physics.arcade.enable(obstacles);
    this.obstacles = obstacles;
  }

  whale() {
    var randomX = Math.floor(Math.random() * 250) + 100;
    const whale = obstacle.obstacles.create(randomX, -100, 'whale');
    whale.scale.x = 0.3;
    whale.scale.y = 0.3;
    DontPanic.game.physics.arcade.enable(whale);
    whale.body.collideWorldBounds = false;
    whale.body.gravity.y = 50;
  }

  petunias() {
    var randomX = Math.floor(Math.random() * 320) + 25;
    const petunias = obstacle.obstacles.create(randomX, -50, 'petunias');
    petunias.scale.x = 0.1;
    petunias.scale.y = 0.1;
    DontPanic.game.physics.arcade.enable(petunias);
    petunias.body.collideWorldBounds = false;
    petunias.body.gravity.y = 60;
  }
}
<|endoftext|>


<commit_before>'use strict';

function check(){
    var answer = parseInt(document.getElementById('answer').value);

    if(isNaN(answer)){
        return;
    }

    var integer = Math.floor(Math.random() * 100000) + 1;
    var result = ' was generated. You ';

    result += answer === integer
      ? 'might have ESP!'
      : 'probably don\'t have ESP.';

    document.getElementById('integer').innerHTML = integer;
    document.getElementById('result').innerHTML = result;
}

window.onkeydown = function(e){
    var key = e.keyCode || e.which;

    if(key === 13){
        check();
    }
};

window.onload = function(e){
    document.getElementById('answer').focus();
};
<commit_msg>removed unnecessary check<commit_after>'use strict';

function check(){
    var integer = Math.floor(Math.random() * 100000) + 1;
    var result = ' was generated. You ';

    result += parseInt(document.getElementById('answer').value) === integer
      ? 'might have ESP!'
      : 'probably don\'t have ESP.';

    document.getElementById('integer').innerHTML = integer;
    document.getElementById('result').innerHTML = result;
}

window.onkeydown = function(e){
    var key = e.keyCode || e.which;

    if(key === 13){
        check();
    }
};

window.onload = function(e){
    document.getElementById('answer').focus();
};
<|endoftext|>