<commit_before>/*
 * Copyright (c) 2011-2013 by Animatron.
 * All rights are reserved.
 *
 * Animatron Player is licensed under the MIT License, see LICENSE.
 *
 * @VERSION
 */

(function() { // anonymous wrapper to exclude global context clash
  var C = anm.C;
  var _ResMan = __anm.resource_manager;

  C.MOD_AUDIO = 'audio';
  if (anm.M[C.MOD_AUDIO]) throw new Error('AUDIO module already enabled');

  anm.M[C.MOD_AUDIO] = {};

  var E = anm.Element;

  // Element functions
  // ----------------------------------------------------------------------------------------------------------------

  var _audio_customRender = function(gtime, ltime, ctx) {
    // TODO: remove
    return false;
  };

  var _onAudioStart = function(ltime, duration) {
    if (!this._audio_is_loaded || this._audio_is_playing) {
      return false;
    }

    this._audio_is_playing = true;
    this._audio.currentTime = this._audio_band_offset + ltime;
    this._audio.volume = 1;
    this._audio.play();
  };

  var _onAudioStop = function(ltime, duration) {
    if (this._audio_is_playing) {
      this._audio.pause();
      this._audio_is_playing = false;
      this._audio.volume = 0;
    }
  };

  E.prototype.importCustomData = function(object, type, importer) {
    if ((14 == type)/*ANM*/ ||
        ("0e" == type)/*ANM_INTACT*/) {
      if (importer == "ANM") {
        /** audio **/
        /*
         * array {
         *     14;                         // 0
         *     string;                     // 1, url
         *     number;                     // 2, band offset
         * } *audio_element*;
         */
        this._audio_url = this._audio_format_url(object[1]);
        this._audio_band_offset = object[2];
      } else if (importer == "ANM_INTACT") {
        this._audio_band_offset = object.bandOffset;
        this._audio_url = this._audio_format_url(object.url);
      }

      this.isAudio = true;
      this._audio = null;
      this._audio_is_loaded = false;
      this._audio_is_playing = false;
      this._audio_canPlay = false;

      this.on(C.X_START, _onAudioStart);
      this.on(C.X_STOP, _onAudioStop);
      this.on(C.S_STOP, _onAudioStop);
      this.on(C.S_PAUSE, _onAudioStop);

      // assign custom render function
      this.__frameProcessors.push(_audio_customRender);

      this._audio_load();
    }
  };

  E.prototype._audio_format_url = function(url) {
    return url + (this._mpeg_supported() ? ".mp3" : ".ogg");
  };

  E.__test_elm = null;
  E.prototype._mpeg_supported = function() {
    var a = E.__test_elm ? E.__test_elm : (E.__test_elm = document.createElement('audio'), E.__test_elm);
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
  }

  var prev__hasRemoteResources = E.prototype._hasRemoteResources;
  E.prototype._hasRemoteResources = function() {
    return prev__hasRemoteResources.call(this, arguments) || this.isAudio;
  }

  var prev__getRemoteResources = E.prototype._getRemoteResources;
  E.prototype._getRemoteResources = function() {
    var prev = prev__getRemoteResources.call(this, arguments);
    if (!this.isAudio && !prev) return null;
    if (!this.isAudio) return prev;
        // return [ this._audio_url ].concat(prev || [])
    return prev ? [ this._audio_url ].concat(prev) : [ this._audio_url ];
  }

  function audioErrProxy(src, pass_to) {
    return function(err) {
      // e_.MEDIA_ERR_ABORTED=1
      // e_.MEDIA_ERR_NETWORK=2
      // e_.MEDIA_ERR_DECODE=3
      // e_.MEDIA_ERR_SRC_NOT_SUPPORTED=4
      // e_.MEDIA_ERR_ENCRYPTED=5
      pass_to(new Error('Failed to load audio file from ' + src + ' with error code: ' +
                        err.currentTarget.error.code));
    }
  };
  E.prototype._audio_load = function() {
    var me = this;

    _ResMan.loadOrGet(me._audio_url,
      function(notify_success, notify_error) { // loader
          var el = document.createElement("audio");
          el.setAttribute("preload", "auto");

          var onSuccess = function(element) {
            element.removeEventListener("progress", progressListener, false);
            element.removeEventListener("canplay", canPlayListener, false);
            notify_success(element);
          };

          var pingChromeToLoad = function(element) {
            if (me._audio_canPlay && element.buffered.length == 1 && window.chrome) {
              var end = element.buffered.end(0);
              if (element.duration - end > 0.05) {
                element.volume = 0;
                element.currentTime = end;
                element.play();
                element.pause();
              } else {
                onSuccess(element);
              }
            }
          };

          var progressListener = function(e) {
            var buffered = el.buffered;
            if (buffered.length == 1) {
                var end = buffered.end(0);
                if (el.duration - end < 0.05) {
                  onSuccess(el);
                }

                pingChromeToLoad(el);
            }
          };

          var canPlayListener = function(e) {
            me._audio_canPlay = true;
            pingChromeToLoad(el);
          };

          el.addEventListener("progress", progressListener, false);
          el.addEventListener("canplay", canPlayListener, false);
          el.addEventListener("error", audioErrProxy(me._audio_url, notify_error), false);

          try {
            document.getElementsByTagName("body")[0].appendChild(el);
            el.src = me._audio_url;
          } catch(e) { notify_error(e); }
      },
      function(audio) { // oncomplete
          me._audio = audio;
          me._audio_is_loaded = true;
      },
      function(err) { __anm.console.error(err.message || err); }); // onerror
  };

})();<commit_msg>simplify preload<commit_after>/*
 * Copyright (c) 2011-2013 by Animatron.
 * All rights are reserved.
 *
 * Animatron Player is licensed under the MIT License, see LICENSE.
 *
 * @VERSION
 */

(function() { // anonymous wrapper to exclude global context clash
  var C = anm.C;
  var _ResMan = __anm.resource_manager;

  C.MOD_AUDIO = 'audio';
  if (anm.M[C.MOD_AUDIO]) throw new Error('AUDIO module already enabled');

  anm.M[C.MOD_AUDIO] = {};

  var E = anm.Element;

  // Element functions
  // ----------------------------------------------------------------------------------------------------------------

  var _audio_customRender = function(gtime, ltime, ctx) {
    // TODO: remove
    return false;
  };

  var _onAudioStart = function(ltime, duration) {
    if (!this._audio_is_loaded || this._audio_is_playing) {
      return false;
    }

    this._audio_is_playing = true;
    this._audio.currentTime = this._audio_band_offset + ltime;
    this._audio.volume = 1;
    this._audio.play();
  };

  var _onAudioStop = function(ltime, duration) {
    if (this._audio_is_playing) {
      this._audio.pause();
      this._audio_is_playing = false;
      this._audio.volume = 0;
    }
  };

  E.prototype.importCustomData = function(object, type, importer) {
    if ((14 == type)/*ANM*/ ||
        ("0e" == type)/*ANM_INTACT*/) {
      if (importer == "ANM") {
        /** audio **/
        /*
         * array {
         *     14;                         // 0
         *     string;                     // 1, url
         *     number;                     // 2, band offset
         * } *audio_element*;
         */
        this._audio_url = this._audio_format_url(object[1]);
        this._audio_band_offset = object[2];
      } else if (importer == "ANM_INTACT") {
        this._audio_band_offset = object.bandOffset;
        this._audio_url = this._audio_format_url(object.url);
      }

      this.isAudio = true;
      this._audio = null;
      this._audio_is_loaded = false;
      this._audio_is_playing = false;
      this._audio_canPlay = false;

      this.on(C.X_START, _onAudioStart);
      this.on(C.X_STOP, _onAudioStop);
      this.on(C.S_STOP, _onAudioStop);
      this.on(C.S_PAUSE, _onAudioStop);

      // assign custom render function
      this.__frameProcessors.push(_audio_customRender);

      this._audio_load();
    }
  };

  E.prototype._audio_format_url = function(url) {
    return url + (this._mpeg_supported() ? ".mp3" : ".ogg");
  };

  E.__test_elm = null;
  E.prototype._mpeg_supported = function() {
    var a = E.__test_elm ? E.__test_elm : (E.__test_elm = document.createElement('audio'), E.__test_elm);
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
  }

  var prev__hasRemoteResources = E.prototype._hasRemoteResources;
  E.prototype._hasRemoteResources = function() {
    return prev__hasRemoteResources.call(this, arguments) || this.isAudio;
  }

  var prev__getRemoteResources = E.prototype._getRemoteResources;
  E.prototype._getRemoteResources = function() {
    var prev = prev__getRemoteResources.call(this, arguments);
    if (!this.isAudio && !prev) return null;
    if (!this.isAudio) return prev;
        // return [ this._audio_url ].concat(prev || [])
    return prev ? [ this._audio_url ].concat(prev) : [ this._audio_url ];
  }

  function audioErrProxy(src, pass_to) {
    return function(err) {
      // e_.MEDIA_ERR_ABORTED=1
      // e_.MEDIA_ERR_NETWORK=2
      // e_.MEDIA_ERR_DECODE=3
      // e_.MEDIA_ERR_SRC_NOT_SUPPORTED=4
      // e_.MEDIA_ERR_ENCRYPTED=5
      pass_to(new Error('Failed to load audio file from ' + src + ' with error code: ' +
                        err.currentTarget.error.code));
    }
  };
  E.prototype._audio_load = function() {
    var me = this;

    _ResMan.loadOrGet(me._audio_url,
      function(notify_success, notify_error) { // loader
          var el = document.createElement("audio");
          el.setAttribute("preload", "auto");

          var progressListener = function(e) {
            var buffered = el.buffered;
            if (buffered.length == 1) {
                var end = buffered.end(0);
                if (el.duration - end < 0.05) {
                  el.removeEventListener("progress", progressListener, false);
                  el.removeEventListener("canplay", canPlayListener, false);
                  notify_success(el);
                  return;
                }

                if (me._audio_canPlay && window.chrome) {
                  el.volume = 0;
                  el.currentTime = end;
                  el.play();
                  el.pause();
                }
            }
          };

          var canPlayListener = function(e) {
            me._audio_canPlay = true;
            progressListener(e);
          };

          el.addEventListener("progress", progressListener, false);
          el.addEventListener("canplay", canPlayListener, false);
          el.addEventListener("error", audioErrProxy(me._audio_url, notify_error), false);

          try {
            document.getElementsByTagName("body")[0].appendChild(el);
            el.src = me._audio_url;
          } catch(e) { notify_error(e); }
      },
      function(audio) { // oncomplete
          me._audio = audio;
          me._audio_is_loaded = true;
      },
      function(err) { __anm.console.error(err.message || err); }); // onerror
  };

})();<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013 by Animatron.
 * All rights are reserved.
 *
 * Animatron Player is licensed under the MIT License, see LICENSE.
 *
 * @VERSION
 */

(function() { // anonymous wrapper to exclude global context clash
  var C = anm.C,
      Tween = anm.Tween,
      Tweens = anm.Tweens;
  var _ResMan = __anm.resource_manager;

  C.MOD_AUDIO = 'audio';
  if (anm.M[C.MOD_AUDIO]) throw new Error('AUDIO module already enabled');

  anm.M[C.MOD_AUDIO] = {};

  var E = anm.Element;

  // Initialization
  // ----------------------------------------------------------------------------------------------------------------

  C.T_VOLUME = 'VOLUME';
  Tween.TWEENS_PRIORITY[C.T_VOLUME] = Tween.TWEENS_COUNT++;
  Tweens[C.T_VOLUME] = function() {
    return function(t, duration, data) {
      if (!this.$._audio_is_loaded) return;
      this.$._audio.volume = data[0] * (1.0 - t) + data[1] * t;
    };
  };

  if (anm.I['ANM']) {
    var Import = anm.I['ANM'];
    var prev_tweentype = Import.tweentype;
    Import.tweentype = function(src) {
      if (src === 7) return C.T_VOLUME;
      return prev_tweentype.apply(this, arguments);
    }
    var prev_tweendata = Import.tweendata;
    Import.tweendata = function(type, src) {
      if ((type === C.T_VOLUME) && src) {
        if (src.length == 2) return src;
        if (src.length == 1) return [ src[0], src[0] ];
      }
      return prev_tweendata.apply(this, arguments);
    }
  }

  // Element functions
  // ----------------------------------------------------------------------------------------------------------------

  var _audio_customRender = function(gtime, ltime, ctx) {
    // TODO: remove
    //return false;
  };

  var _onAudioStart = function(ltime, duration) {
    if (!this._audio_is_loaded || this._audio_is_playing) {
      return false;
    }

    this._audio_is_playing = true;
    this._audio.currentTime = this._audio_band_offset + ltime;
    this._audio.volume = 1;
    this._audio.play();
  };

  var _onAudioStop = function(ltime, duration) {
    if (this._audio_is_playing) {
      this._audio.pause();
      this._audio_is_playing = false;
      this._audio.volume = 0;
    }
  };

  E._customImporters.push(function(source, type, importer) {
    if ((14 == type)/*ANM*/ ||
        ("0e" == type)/*ANM_INTACT*/) {
      if (importer == "ANM") {
        /** audio **/
        /*
         * array {
         *     14;                         // 0
         *     string;                     // 1, url
         *     number;                     // 2, band offset
         * } *audio_element*;
         */
        this._audio_url = source[1];
        this._audio_band_offset = source[2];
      } else if (importer == "ANM_INTACT") {
        this._audio_band_offset = source.bandOffset;
        this._audio_url = this._audio_format_url(source.url);
      }

      this.isAudio = true;
      this._audio = null;
      this._audio_is_loaded = false;
      this._audio_is_playing = false;
      this._audio_canPlay = false;

      this.on(C.X_START, _onAudioStart);
      this.on(C.X_STOP, _onAudioStop);
      this.on(C.S_STOP, _onAudioStop);
      this.on(C.S_PAUSE, _onAudioStop);

      // assign custom render function
      this.__frameProcessors.push(_audio_customRender);

      this._audio_load();
    }
  });

  E.prototype._audio_format_url = function(url) {
    return url + (this._mpeg_supported() ? ".mp3" : ".ogg");
  };

  E.__test_elm = null;
  E.prototype._mpeg_supported = function() {
    var a = E.__test_elm ? E.__test_elm : (E.__test_elm = document.createElement('audio'), E.__test_elm);
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
  }

  var prev__hasRemoteResources = E.prototype._hasRemoteResources;
  E.prototype._hasRemoteResources = function() {
    return prev__hasRemoteResources.call(this, arguments) || this.isAudio;
  }

  var prev__getRemoteResources = E.prototype._getRemoteResources;
  E.prototype._getRemoteResources = function() {
    var prev = prev__getRemoteResources.call(this, arguments);
    if (!this.isAudio && !prev) return null;
    if (!this.isAudio) return prev;
        // return [ this._audio_url ].concat(prev || [])
    return prev ? [ this._audio_url ].concat(prev) : [ this._audio_url ];
  }

  function audioErrProxy(src, pass_to) {
    return function(err) {
      // e_.MEDIA_ERR_ABORTED=1
      // e_.MEDIA_ERR_NETWORK=2
      // e_.MEDIA_ERR_DECODE=3
      // e_.MEDIA_ERR_SRC_NOT_SUPPORTED=4
      // e_.MEDIA_ERR_ENCRYPTED=5
      pass_to(new Error('Failed to load audio file from ' + src + ' with error code: ' +
                        err.currentTarget.error.code));
    }
  };

  E.prototype._audio_load = function() {
    var me = this;

    _ResMan.loadOrGet(me._audio_url,
      function(notify_success, notify_error) { // loader
          if (__anm.conf.doNotLoadAudio) { notify_error('Loading audio is turned off');
                                           return; }

          var el = document.createElement("audio");
          el.setAttribute("preload", "auto");

          var progressListener = function(e) {
            var buffered = el.buffered;
            if (buffered.length == 1) {
                var end = buffered.end(0);
                if (el.duration - end < 0.05) {
                  el.removeEventListener("progress", progressListener, false);
                  el.removeEventListener("canplay", canPlayListener, false);
                  notify_success(el);
                  return;
                }

                if (me._audio_canPlay && window.chrome) {
                  el.volume = 0;
                  el.currentTime = end;
                  el.play();
                  el.pause();
                }
            }
          };

          var canPlayListener = function(e) {
            me._audio_canPlay = true;
            progressListener(e);
          };

          el.addEventListener("progress", progressListener, false);
          el.addEventListener("canplay", canPlayListener, false);
          el.addEventListener("error", audioErrProxy(me._audio_url, notify_error), false);

          var addSource = function(audio, url, type) {
              var src = document.createElement("source");
              src.type = type;
              src.src = url;
              src.addEventListener("error", notify_error, false);
              audio.appendChild(src);
          };

          try {
            document.getElementsByTagName("body")[0].appendChild(el);
            addSource(el, me._audio_url + ".mp3", "audio/mpeg");
            addSource(el, me._audio_url + ".ogg", "audio/ogg");
          } catch(e) { notify_error(e); }
      },
      function(audio) { // oncomplete
          me._audio = audio;
          me._audio_is_loaded = true;
      },
      function(err) { __anm.console.error(err ? (err.message || err) : 'Unknown error');
                      /* throw err; */ }); // onerror
  };

})();<commit_msg>fix ios/android audio<commit_after>/*
 * Copyright (c) 2011-2013 by Animatron.
 * All rights are reserved.
 *
 * Animatron Player is licensed under the MIT License, see LICENSE.
 *
 * @VERSION
 */

(function() { // anonymous wrapper to exclude global context clash
  var C = anm.C,
      Tween = anm.Tween,
      Tweens = anm.Tweens;
  var _ResMan = __anm.resource_manager;

  C.MOD_AUDIO = 'audio';
  if (anm.M[C.MOD_AUDIO]) throw new Error('AUDIO module already enabled');

  anm.M[C.MOD_AUDIO] = {};

  var E = anm.Element;

  // Initialization
  // ----------------------------------------------------------------------------------------------------------------

  C.T_VOLUME = 'VOLUME';
  Tween.TWEENS_PRIORITY[C.T_VOLUME] = Tween.TWEENS_COUNT++;
  Tweens[C.T_VOLUME] = function() {
    return function(t, duration, data) {
      if (!this.$._audio_is_loaded) return;
      this.$._audio.volume = data[0] * (1.0 - t) + data[1] * t;
    };
  };

  if (anm.I['ANM']) {
    var Import = anm.I['ANM'];
    var prev_tweentype = Import.tweentype;
    Import.tweentype = function(src) {
      if (src === 7) return C.T_VOLUME;
      return prev_tweentype.apply(this, arguments);
    }
    var prev_tweendata = Import.tweendata;
    Import.tweendata = function(type, src) {
      if ((type === C.T_VOLUME) && src) {
        if (src.length == 2) return src;
        if (src.length == 1) return [ src[0], src[0] ];
      }
      return prev_tweendata.apply(this, arguments);
    }
  }

  // Element functions
  // ----------------------------------------------------------------------------------------------------------------

  var _audio_customRender = function(gtime, ltime, ctx) {
    // TODO: remove
    //return false;
  };

  var _onAudioStart = function(ltime, duration) {
    if (!this._audio_is_loaded || this._audio_is_playing) {
      return false;
    }

    this._audio_is_playing = true;
    var current_time = this._audio_band_offset + ltime;

    if (this._web_audio_api) {
      this._source = window._audio_ctx.createBufferSource();
      this._source.buffer = this._audio_buffer;
      this._source.connect(window._audio_ctx.destination);
      if (this._source.play) {
        this._source.play(0, current_time);
      } else {
        this._source.noteGrainOn(0, current_time, this._source.buffer.duration - current_time);
      }
    } else {
      this._audio.currentTime = current_time;
      this._audio.volume = 1;
      this._audio.play();
    }
  };

  var _onAudioStop = function(ltime, duration) {
    if (this._audio_is_playing) {
      if (this._web_audio_api) {
        if (this._source.stop) {
          this._source.stop(0);
        } else {
          this._source.noteOff(0);
        }

        this._source = null;
      } else {
        this._audio.pause();
        this._audio.volume = 0;
      }

      this._audio_is_playing = false;
    }
  };

  E._customImporters.push(function(source, type, importer) {
    if ((14 == type)/*ANM*/ ||
        ("0e" == type)/*ANM_INTACT*/) {
      if (importer == "ANM") {
        /** audio **/
        /*
         * array {
         *     14;                         // 0
         *     string;                     // 1, url
         *     number;                     // 2, band offset
         * } *audio_element*;
         */
        this._audio_url = source[1];
        this._audio_band_offset = source[2];
      } else if (importer == "ANM_INTACT") {
        this._audio_band_offset = source.bandOffset;
        this._audio_url = this._audio_format_url(source.url);
      }

      this.isAudio = true;
      this._audio = null;
      this._audio_is_loaded = false;
      this._audio_is_playing = false;
      this._audio_canPlay = false;

      this.on(C.X_START, _onAudioStart);
      this.on(C.X_STOP, _onAudioStop);
      this.on(C.S_STOP, _onAudioStop);
      this.on(C.S_PAUSE, _onAudioStop);

      // assign custom render function
      this.__frameProcessors.push(_audio_customRender);

      this._audio_load();
    }
  });

  E.prototype._audio_format_url = function(url) {
    return url + (this._mpeg_supported() ? ".mp3" : ".ogg");
  };

  E.__test_elm = null;

  E.prototype._mpeg_supported = function() {
    var a = E.__test_elm ? E.__test_elm : (E.__test_elm = document.createElement('audio'), E.__test_elm);
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
  }

  E.prototype._web_audio_api_supported = function() {
    return window.webkitAudioContext || window.audioContext;
  }

  E.prototype._init_web_audio_if_needed = function() {
    if (window._audio_ctx) return;
    var ctx = window.webkitAudioContext || window.audioContext;
    window._audio_ctx = new ctx();
  }

  var prev__hasRemoteResources = E.prototype._hasRemoteResources;
  E.prototype._hasRemoteResources = function() {
    return prev__hasRemoteResources.call(this, arguments) || this.isAudio;
  }

  var prev__getRemoteResources = E.prototype._getRemoteResources;
  E.prototype._getRemoteResources = function() {
    var prev = prev__getRemoteResources.call(this, arguments);
    if (!this.isAudio && !prev) return null;
    if (!this.isAudio) return prev;
        // return [ this._audio_url ].concat(prev || [])
    return prev ? [ this._audio_url ].concat(prev) : [ this._audio_url ];
  }

  function audioErrProxy(src, pass_to) {
    return function(err) {
      // e_.MEDIA_ERR_ABORTED=1
      // e_.MEDIA_ERR_NETWORK=2
      // e_.MEDIA_ERR_DECODE=3
      // e_.MEDIA_ERR_SRC_NOT_SUPPORTED=4
      // e_.MEDIA_ERR_ENCRYPTED=5
      pass_to(new Error('Failed to load audio file from ' + src + ' with error code: ' +
                        err.currentTarget.error.code));
    }
  };

  E.prototype._audio_load = function() {
    var me = this;

    _ResMan.loadOrGet(me._audio_url,
      function(notify_success, notify_error) { // loader
          if (__anm.conf.doNotLoadAudio) {
            notify_error('Loading audio is turned off');
            return;
          }

          me._web_audio_api = me._web_audio_api_supported();
          if (me._web_audio_api) {
            // use Web Audio API if possible
            me._init_web_audio_if_needed();

            var loadingDone = function(e) {
              var req = e.target;
              me._audio_buffer = window._audio_ctx.createBuffer(req.response, false);
              me._audio_is_loaded = true;
              notify_success(me);
            };

            var req = new XMLHttpRequest();
            req.open('GET', me._audio_format_url(me._audio_url), true);
            req.responseType = 'arraybuffer';
            req.addEventListener('load', loadingDone, false);
            req.send();
          } else {
            var el = document.createElement("audio");
            el.setAttribute("preload", "auto");

            var progressListener = function(e) {
              var buffered = el.buffered;
              if (buffered.length == 1) {
                  var end = buffered.end(0);
                  if (el.duration - end < 0.05) {
                    el.removeEventListener("progress", progressListener, false);
                    el.removeEventListener("canplay", canPlayListener, false);
                    notify_success(el);
                    return;
                  }

                  if (me._audio_canPlay && window.chrome) {
                    el.volume = 0;
                    el.currentTime = end;
                    el.play();
                    el.pause();
                  }
              } else if (me._audio_canPlay && buffered.length != 1) {
                // will skip preloading since it seems like it will not work properly anyway:
                // it's a workaround for Android-based browsers which
                // will not allow prebuffering until user will explicitly allow it (by touching something)
                notify_success(el);
              }
            };

            var canPlayListener = function(e) {
              me._audio_canPlay = true;
              progressListener(e);
            };

            el.addEventListener("progress", progressListener, false);
            el.addEventListener("canplay", canPlayListener, false);
            el.addEventListener("error", audioErrProxy(me._audio_url, notify_error), false);

            var addSource = function(audio, url, type) {
                var src = document.createElement("source");
                src.type = type;
                src.src = url;
                src.addEventListener("error", notify_error, false);
                audio.appendChild(src);
            };

            try {
              document.getElementsByTagName("body")[0].appendChild(el);
              addSource(el, me._audio_url + ".mp3", "audio/mpeg");
              addSource(el, me._audio_url + ".ogg", "audio/ogg");
            } catch(e) { notify_error(e); }
          }
      },
      function(audio) { // oncomplete
          me._audio = audio;
          me._audio_is_loaded = true;
      },
      function(err) { __anm.console.error(err ? (err.message || err) : 'Unknown error');
                      /* throw err; */ }); // onerror
  };

})();<|endoftext|>


<commit_before>// Note: requires coordinates to be counterclockwise and convex!
d3.geom.polygon = function(coordinates) {

  coordinates.area = function() {
    var i = 0,
        n = coordinates.length,
        a = coordinates[n - 1][0] * coordinates[0][1],
        b = coordinates[n - 1][1] * coordinates[0][0];
    while (++i < n) {
      a += coordinates[i - 1][0] * coordinates[i][1];
      b += coordinates[i - 1][1] * coordinates[i][0];
    }
    return (b - a) * .5;
  };

  coordinates.centroid = function(k) {
    var i = -1,
        n = coordinates.length,
        x = 0,
        y = 0,
        a,
        b = coordinates[n - 1],
        c;
    if (!arguments.length) k = -1 / (6 * coordinates.area());
    while (++i < n) {
      a = b;
      b = coordinates[i];
      c = a[0] * b[1] - b[0] * a[1];
      x += (a[0] + b[0]) * c;
      y += (a[1] + b[1]) * c;
    }
    return [x * k, y * k];
  };

  // The Sutherland-Hodgman clipping algorithm.
  coordinates.clip = function(subject) {
    var input,
        i = -1,
        n = coordinates.length,
        j,
        m,
        a = coordinates[n - 1],
        b,
        c,
        d;
    while (++i < n) {
      input = subject.slice();
      subject.length = 0;
      b = coordinates[i];
      c = input[(m = input.length) - 1];
      j = -1;
      while (++j < m) {
        d = input[j];
        if (d3_geom_polygonInside(d, a, b)) {
          if (!d3_geom_polygonInside(c, a, b)) {
            subject.push(d3_geom_polygonIntersect(c, d, a, b));
          }
          subject.push(d);
        } else if (d3_geom_polygonInside(c, a, b)) {
          subject.push(d3_geom_polygonIntersect(c, d, a, b));
        }
        c = d;
      }
      a = b;
    }
    return subject;
  };

  return coordinates;
};

function d3_geom_polygonInside(p, a, b) {
  return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
}

// Intersect two infinite lines cd and ab.
function d3_geom_polygonIntersect(c, d, a, b) {
  var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3,
      y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3,
      ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
  return [x1 + ua * x21, y1 + ua * y21];
}
<commit_msg>Clarify convex polygon comment.<commit_after>d3.geom.polygon = function(coordinates) {

  coordinates.area = function() {
    var i = 0,
        n = coordinates.length,
        a = coordinates[n - 1][0] * coordinates[0][1],
        b = coordinates[n - 1][1] * coordinates[0][0];
    while (++i < n) {
      a += coordinates[i - 1][0] * coordinates[i][1];
      b += coordinates[i - 1][1] * coordinates[i][0];
    }
    return (b - a) * .5;
  };

  coordinates.centroid = function(k) {
    var i = -1,
        n = coordinates.length,
        x = 0,
        y = 0,
        a,
        b = coordinates[n - 1],
        c;
    if (!arguments.length) k = -1 / (6 * coordinates.area());
    while (++i < n) {
      a = b;
      b = coordinates[i];
      c = a[0] * b[1] - b[0] * a[1];
      x += (a[0] + b[0]) * c;
      y += (a[1] + b[1]) * c;
    }
    return [x * k, y * k];
  };

  // The Sutherland-Hodgman clipping algorithm.
  // Note: requires the clip polygon to be counterclockwise and convex.
  coordinates.clip = function(subject) {
    var input,
        i = -1,
        n = coordinates.length,
        j,
        m,
        a = coordinates[n - 1],
        b,
        c,
        d;
    while (++i < n) {
      input = subject.slice();
      subject.length = 0;
      b = coordinates[i];
      c = input[(m = input.length) - 1];
      j = -1;
      while (++j < m) {
        d = input[j];
        if (d3_geom_polygonInside(d, a, b)) {
          if (!d3_geom_polygonInside(c, a, b)) {
            subject.push(d3_geom_polygonIntersect(c, d, a, b));
          }
          subject.push(d);
        } else if (d3_geom_polygonInside(c, a, b)) {
          subject.push(d3_geom_polygonIntersect(c, d, a, b));
        }
        c = d;
      }
      a = b;
    }
    return subject;
  };

  return coordinates;
};

function d3_geom_polygonInside(p, a, b) {
  return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
}

// Intersect two infinite lines cd and ab.
function d3_geom_polygonIntersect(c, d, a, b) {
  var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3,
      y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3,
      ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
  return [x1 + ua * x21, y1 + ua * y21];
}
<|endoftext|>


<commit_before>/**************************************************************
 *	Ellipse curve
 **************************************************************/

THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise ) {

	this.aX = aX;
	this.aY = aY;

	this.xRadius = xRadius;
	this.yRadius = yRadius;

	this.aStartAngle = aStartAngle;
	this.aEndAngle = aEndAngle;

	this.aClockwise = aClockwise;

};

THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
THREE.EllipseCurve.prototype.constructor = THREE.EllipseCurve;

THREE.EllipseCurve.prototype.getPoint = function ( t ) {

	var deltaAngle = this.aEndAngle - this.aStartAngle;

	if ( deltaAngle < 0 ) deltaAngle += Math.PI * 2;
	if ( deltaAngle > Math.PI * 2 ) deltaAngle -= Math.PI * 2;

	var angle;

	if ( this.aClockwise === true ) {

		angle = this.aEndAngle + ( 1 - t ) * ( Math.PI * 2 - deltaAngle );

	} else {

		angle = this.aStartAngle + t * deltaAngle;

	}

	var vector = new THREE.Vector2();

	vector.x = this.aX + this.xRadius * Math.cos( angle );
	vector.y = this.aY + this.yRadius * Math.sin( angle );

	return vector;

};
<commit_msg>Add rotation (optional) to THREE.EllipseCurve.<commit_after>/**************************************************************
 *	Ellipse curve
 **************************************************************/

THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {

	this.aX = aX;
	this.aY = aY;

	this.xRadius = xRadius;
	this.yRadius = yRadius;

	this.aStartAngle = aStartAngle;
	this.aEndAngle = aEndAngle;

	this.aClockwise = aClockwise;

	this.aRotation = aRotation || 0;

};

THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
THREE.EllipseCurve.prototype.constructor = THREE.EllipseCurve;

THREE.EllipseCurve.prototype.getPoint = function ( t ) {

	var deltaAngle = this.aEndAngle - this.aStartAngle;

	if ( deltaAngle < 0 ) deltaAngle += Math.PI * 2;
	if ( deltaAngle > Math.PI * 2 ) deltaAngle -= Math.PI * 2;

	var angle;

	if ( this.aClockwise === true ) {

		angle = this.aEndAngle + ( 1 - t ) * ( Math.PI * 2 - deltaAngle );

	} else {

		angle = this.aStartAngle + t * deltaAngle;

	}

	var x = this.aX + this.xRadius * Math.cos( angle );
	var y = this.aY + this.yRadius * Math.sin( angle );

	if ( this.aRotation ) {

		var cos = Math.cos( this.aRotation );
		var sin = Math.sin( this.aRotation );

		// Rotate the point about the center of the ellipse.
		x = ( x - this.aX ) * cos - ( y - this.aY ) * sin + this.aX;
		y = ( x - this.aX ) * sin + ( y - this.aY ) * cos + this.aY;

	}

	return new THREE.Vector2( x, y );

};
<|endoftext|>


<commit_before>import React from "react";
import ReactDOM from "react-dom";
import $ from "jquery";
import {WeaveLayoutManager} from "../lib/WeaveUI.js";

//weavejs.WeaveAPI.Locale.reverseLayout = true; // for testing

window.weave1 = new Weave();
window.weave2 = new Weave();
weavejs.core.WeaveArchive.loadUrl(weave1, "/tncp/TN_EDU.weave").then(function(){
    weavejs.core.WeaveArchive.loadUrl(weave2, "/tncp/TN_FluVaccinations.weave").then(render)
});

var weaveInsts = [weave1,weave2]
function render()
{
	$(() => {
		ReactDOM.render(<MultipleView weaveInstances={weaveInsts} style={{width: "50%", height: "50%"}}/>, document.getElementById("weaveElt"));
	});
}

class MultipleView extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            toggleIndex:0,
            addView: false,
            scale:1
        }
        this.toggleView = this.toggleView.bind(this);
        this.addView = this.addView.bind(this);
        this.scaleView = this.scaleView.bind(this);
    }

    toggleView(){
        this.setState({
            toggleIndex: this.state.toggleIndex == 0 ?1:0,
            addView:false
        });
    }

    addView(){
        this.setState({
            addView:!this.state.addView
        });
    }

    scaleView(){
        this.setState({
            scale: this.state.scale == 1 ?0.8:1
        });
    }

    render(){
        var styleObject = {
            border:"2px solid black",
            display: "flex",
            transform: "scale(" + String(this.state.scale) + ")"
        }

        var weaveInst = this.props.weaveInstances[this.state.toggleIndex];
        var layout = weaveInst.root.requestObject("Layout", Weave.getDefinition("FlexibleLayout"));

        var weaveUI = [

        		<WeaveLayoutManager  layout={layout} style={{flex: "1"}}/>

        ];

       /* var weaveUI = this.props.weaveInstances.map(function(weaveInst,index){
            var layout = weaveInst.root.requestObject("Layout", Weave.getDefinition("FlexibleLayout"));
            var styleObject = {
                border:"2px solid black",
                display:"none"
            }

            if(this.state.toggleIndex == index){
                border:"2px solid black",
                styleObject.display = "flex",
                styleObject.transform =  "scale(" + String(this.state.scale) + ")";
            }

            return
<WeaveLayoutManager  layout={layout} style={{flex: "1"}}/>

        },this)*/

        var singleViewLabel = "Add Single Tool View For Active Weave";
        if(this.state.addView){
            var weaveInst = this.props.weaveInstances[this.state.toggleIndex];
            var layout = weaveInst.root.requestObject("SingleToolLayout", Weave.getDefinition("FlexibleLayout"));
            layout.state = {
                  "direction": "horizontal",
                  "flex": 1,
                  "id": [
                    "MapTool"
                  ]
                }
            var keyIndex = weaveUI.length;
            singleViewLabel = "Remove Single Tool View"

            var singleToolView =
<WeaveLayoutManager  layout={layout} style={{flex: 1 }}/>

            weaveUI.push(singleToolView);
        }

        return

                         Toggle Weave  |
                         {singleViewLabel} |
                         Scale

                    {weaveUI}

    }

}

<commit_msg>cleaning up test code<commit_after>import React from "react";
import ReactDOM from "react-dom";
import $ from "jquery";
import {WeaveLayoutManager} from "../lib/WeaveUI.js";

//weavejs.WeaveAPI.Locale.reverseLayout = true; // for testing

window.weave1 = new Weave();
window.weave2 = new Weave();
weavejs.core.WeaveArchive.loadUrl(weave1, "/tncp/TN_EDU.weave").then(function(){
	weavejs.core.WeaveArchive.loadUrl(weave2, "/tncp/TN_FluVaccinations.weave").then(render)
});

var weaveInsts = [weave1, weave2];
function render()
{
	$(() => {
		ReactDOM.render(<MultipleView weaveInstances={weaveInsts} style={{width: "50%", height: "50%"}}/>, document.getElementById("weaveElt"));
	});
}

class MultipleView extends React.Component {

	constructor(props) {
		super(props);
		this.state = {
			toggleIndex: 0,
			addView: false,
			scale: 1
		}
        this.toggleView = this.toggleView.bind(this);
        this.addView = this.addView.bind(this);
        this.scaleView = this.scaleView.bind(this);
	}

	toggleView()
	{
		this.setState({
			toggleIndex: this.state.toggleIndex == 0 ? 1 : 0,
			addView: false
		});
	}

	addView()
	{
		this.setState({
			addView: !this.state.addView
		});
	}

	scaleView()
	{
		this.setState({
			scale: this.state.scale == 1 ? 0.8 : 1
		});
	}

	render()
	{
		var styleObject = {
			border: "2px solid black",
			display: "flex",
			transform: "scale(" + String(this.state.scale) + ")"
		}

		var weaveInst = this.props.weaveInstances[this.state.toggleIndex];
		var layout = weaveInst.root.requestObject("Layout", Weave.getDefinition("FlexibleLayout"));

		var weaveUI = [

				<WeaveLayoutManager layout={layout} style={{width: "100%", height: "100%"}}/>

		];

		/*
		var weaveUI = this.props.weaveInstances.map((weaveInst, index) => {
			var layout = weaveInst.root.requestObject("Layout", Weave.getDefinition("FlexibleLayout"));
			var styleObject = {
				border:"2px solid black",
				display:"none"
			}

			if(this.state.toggleIndex == index){
				border:"2px solid black",
				styleObject.display = "flex",
				styleObject.transform =  "scale(" + String(this.state.scale) + ")";
			}

			return (

					<WeaveLayoutManager layout={layout} style={{width: "100%", height: "100%"}}/>

			);
		});
		*/

		var singleViewLabel = "Add Single Tool View For Active Weave";
		if (this.state.addView)
		{
			var weaveInst = this.props.weaveInstances[this.state.toggleIndex];
			var layout = weaveInst.root.requestObject("SingleToolLayout", Weave.getDefinition("FlexibleLayout"));
			layout.state = {
				  "direction": "horizontal",
				  "flex": 1,
				  "id": ["MapTool"]
				}
			var keyIndex = weaveUI.length;
			singleViewLabel = "Remove Single Tool View"

			weaveUI.push(

					<WeaveLayoutManager layout={layout} style={{width: "100%", height: "100%"}}/>

			);
		}

		return (

					 Toggle Weave  |
					 {singleViewLabel} |
					 Scale

				{weaveUI}

		);
	}
}
<|endoftext|>


<commit_before>// vim:set sw=4 ts=4 sts=4 ft=javascript expandtab:
/*
 * Return the deciphering key stored in anchor part of the URL
 * Stolen from https://github.com/sebsauvage/ZeroBin/blob/master/js/zerobin.js
 */
function pageKey() {
    var key = window.location.hash.substring(1);  // Get key

    // Some stupid web 2.0 services and redirectors add data AFTER the anchor
    // (such as &utm_source=...).
    // We will strip any additional data.

    // First, strip everything after the equal sign (=) which signals end of base64 string.
    i = key.indexOf('='); if (i>-1) { key = key.substring(0,i+1); }

    // If the equal sign was not present, some parameters may remain:
    i = key.indexOf('&'); if (i>-1) { key = key.substring(0,i); }

    // Then add trailing equal sign if it's missing
    if (key.charAt(key.length-1)!=='=') key+='=';

    return key;
}
function base64ToArrayBuffer(base64) {
    var binary_string =  window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array( len );
    for (var i = 0; i < len; i++)        {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}

// Something's wring
function addAlert(msg) {
    $('#please-wait').remove();

    var pbd = $('#pbd');
    pbd.attr('role', 'alert');
    pbd.html(['
',
                  '
',
                      '', msg, '',
                  '
',
              '
'].join(''));
}

// Spawn WebSocket
function spawnWebsocket(pa) {
    var ws       = new WebSocket(ws_url);
    ws.onopen    = function() {
        console.log('Connection is established!');

        var l    = $('#loading');
        l.html(i18n.loading.replace(/XX1/, pa));
        window.ws.send('{"part":'+pa+'}');
    };
    ws.onclose   = function() {
        console.log('Connection is closed');
        if (!window.completed) {
            console.log('Connection closed. Retrying to get slice '+pa);
            window.ws = spawnWebsocket(pa);
        }
    }
    ws.onmessage = function(e) {
        var res  = e.data.split('XXMOJOXX');
        var json = res.shift();
        var data = JSON.parse(json);

        if (data.msg !== undefined) {
            addAlert(data.msg);
            console.log(data.msg);
            window.onbeforeunload = null;
        } else {
            console.log('Getting slice '+(data.part + 1)+' of '+data.total);
            var slice   = JSON.parse(res.shift());
            var percent = Math.round(100 * (data.part + 1)/data.total);
            var pb      = $('#pb');
            pb.css('width', percent+'%');
            pb.attr('aria-valuenow', percent);
            $('#pbt').html(percent+'%');
            try {
                var b64 = sjcl.decrypt(window.key, slice);
                window.a[data.part] = base64ToArrayBuffer(b64);
                if (data.part + 1 === data.total) {
                    var blob = new Blob(a, {type: data.type});

                    $('#please-wait').remove();
                    $('#loading').remove();

                    var pbd  = $('#pbd');
                    pbd.attr('class', 'center-align');
                    var blobURL   = URL.createObjectURL(blob);
                    var innerHTML = [ '
', i18n.download, '
'];

                    if (data.type.match(/^image\//) !== null) {
                        innerHTML.push('');
                    } else if (data.type.match(/^video\//) !== null) {
                        innerHTML.push('<video class="responsive-video" controls>',
                                           '<source src="', blobURL, '" type="', data.type, '">',
                                       '</video>');
                    }
                    pbd.html(innerHTML.join(''));

                    window.ws.send('{"ended":true}');
                    window.onbeforeunload = null;
                    window.completed = true;
                } else {
                    var l = $('#loading');
                    l.html(i18n.loading.replace(/XX1/, (data.part + 1)));
                    if (ws.readyState === 3) {
                        window.ws = spawnWebsocket(data.part + 1);
                    } else {
                        window.ws.onclose = function() {
                            console.log('Connection is closed');
                            if (!window.completed) {
                                console.log('Connection closed. Retrying to get slice '+(data.part + 1));
                                window.ws = spawnWebsocket(data.part + 1);
                            }
                        }
                        window.ws.onerror = function() {
                            console.log('Error. Retrying to get slice '+(data.part + 1));
                            window.ws = spawnWebsocket(data.part + 1);
                        };
                        window.ws.send('{"part":'+(data.part + 1)+'}');
                    }
                }
            } catch(err) {
                if (err.message === 'ccm: tag doesn\'t match') {
                    addAlert(i18n.badkey);
                } else {
                    addAlert(err.message);
                }
                window.onbeforeunload = null;
            }
        }
    }
    ws.onerror = function() {
        console.log('Error. Retrying to get slice '+pa);
        window.ws = spawnWebsocket(pa);
    }
    return ws;
}
// When it's ready
$(document).ready(function(){
    $('#filesize').html(filesize($('#filesize').attr('data-filesize'), {base: 10}));
    window.a         = new Array();
    window.key       = pageKey();
    window.completed = false;

    if (key !== '=') {
        // Set websocket
        window.ws = spawnWebsocket(0);

        // Prevent exiting page before full download
        window.onbeforeunload = confirmExit;
    } else {
        addAlert(i18n.nokey);
    }
});
<commit_msg>Fix #47 (message block not displayed on download page)<commit_after>// vim:set sw=4 ts=4 sts=4 ft=javascript expandtab:
/*
 * Return the deciphering key stored in anchor part of the URL
 * Stolen from https://github.com/sebsauvage/ZeroBin/blob/master/js/zerobin.js
 */
function pageKey() {
    var key = window.location.hash.substring(1);  // Get key

    // Some stupid web 2.0 services and redirectors add data AFTER the anchor
    // (such as &utm_source=...).
    // We will strip any additional data.

    // First, strip everything after the equal sign (=) which signals end of base64 string.
    i = key.indexOf('='); if (i>-1) { key = key.substring(0,i+1); }

    // If the equal sign was not present, some parameters may remain:
    i = key.indexOf('&'); if (i>-1) { key = key.substring(0,i); }

    // Then add trailing equal sign if it's missing
    if (key.charAt(key.length-1)!=='=') key+='=';

    return key;
}
function base64ToArrayBuffer(base64) {
    var binary_string =  window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array( len );
    for (var i = 0; i < len; i++)        {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}

// Something's wring
function addAlert(msg) {
    $('#please-wait').remove();

    var pbd = $('#pbd');
    pbd.attr('role', 'alert');
    pbd.removeClass('progress');
    pbd.html(['
',
                  '
',
                      '', msg, '',
                  '
',
              '
'].join(''));
}

// Spawn WebSocket
function spawnWebsocket(pa) {
    var ws       = new WebSocket(ws_url);
    ws.onopen    = function() {
        console.log('Connection is established!');

        var l    = $('#loading');
        l.html(i18n.loading.replace(/XX1/, pa));
        window.ws.send('{"part":'+pa+'}');
    };
    ws.onclose   = function() {
        console.log('Connection is closed');
        if (!window.completed) {
            console.log('Connection closed. Retrying to get slice '+pa);
            window.ws = spawnWebsocket(pa);
        }
    }
    ws.onmessage = function(e) {
        var res  = e.data.split('XXMOJOXX');
        var json = res.shift();
        var data = JSON.parse(json);

        if (data.msg !== undefined) {
            addAlert(data.msg);
            console.log(data.msg);
            window.onbeforeunload = null;
        } else {
            console.log('Getting slice '+(data.part + 1)+' of '+data.total);
            var slice   = JSON.parse(res.shift());
            var percent = Math.round(100 * (data.part + 1)/data.total);
            var pb      = $('#pb');
            pb.css('width', percent+'%');
            pb.attr('aria-valuenow', percent);
            $('#pbt').html(percent+'%');
            try {
                var b64 = sjcl.decrypt(window.key, slice);
                window.a[data.part] = base64ToArrayBuffer(b64);
                if (data.part + 1 === data.total) {
                    var blob = new Blob(a, {type: data.type});

                    $('#please-wait').remove();
                    $('#loading').remove();

                    var pbd  = $('#pbd');
                    pbd.attr('class', 'center-align');
                    var blobURL   = URL.createObjectURL(blob);
                    var innerHTML = [ '
', i18n.download, '
'];

                    if (data.type.match(/^image\//) !== null) {
                        innerHTML.push('');
                    } else if (data.type.match(/^video\//) !== null) {
                        innerHTML.push('<video class="responsive-video" controls>',
                                           '<source src="', blobURL, '" type="', data.type, '">',
                                       '</video>');
                    }
                    pbd.html(innerHTML.join(''));

                    window.ws.send('{"ended":true}');
                    window.onbeforeunload = null;
                    window.completed = true;
                } else {
                    var l = $('#loading');
                    l.html(i18n.loading.replace(/XX1/, (data.part + 1)));
                    if (ws.readyState === 3) {
                        window.ws = spawnWebsocket(data.part + 1);
                    } else {
                        window.ws.onclose = function() {
                            console.log('Connection is closed');
                            if (!window.completed) {
                                console.log('Connection closed. Retrying to get slice '+(data.part + 1));
                                window.ws = spawnWebsocket(data.part + 1);
                            }
                        }
                        window.ws.onerror = function() {
                            console.log('Error. Retrying to get slice '+(data.part + 1));
                            window.ws = spawnWebsocket(data.part + 1);
                        };
                        window.ws.send('{"part":'+(data.part + 1)+'}');
                    }
                }
            } catch(err) {
                if (err.message === 'ccm: tag doesn\'t match') {
                    addAlert(i18n.badkey);
                } else {
                    addAlert(err.message);
                }
                window.onbeforeunload = null;
            }
        }
    }
    ws.onerror = function() {
        console.log('Error. Retrying to get slice '+pa);
        window.ws = spawnWebsocket(pa);
    }
    return ws;
}
// When it's ready
$(document).ready(function(){
    $('#filesize').html(filesize($('#filesize').attr('data-filesize'), {base: 10}));
    window.a         = new Array();
    window.key       = pageKey();
    window.completed = false;

    if (key !== '=') {
        // Set websocket
        window.ws = spawnWebsocket(0);

        // Prevent exiting page before full download
        window.onbeforeunload = confirmExit;
    } else {
        addAlert(i18n.nokey);
    }
});
<|endoftext|>


<commit_before>/*@pjs preload="data/images/logo1.png";*/

var sketchProc=function(processingInstance){ with (processingInstance){

//Setup
var wi = window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth;
var he = window.innerHeight ||
         document.documentElement.clientHeight ||
         document.body.clientHeight;
size(wi*0.9,he*0.9);
frameRate(60);

setup = function() {
	mainfont = createFont("Times New Roman");
	logo = loadImage("data/images/logo1.png");
	ismobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

	keys = [];
	pages = [];
	page = 0;

	chapter1 = [];
	chapter1pages = [];
	chapter1length = 6;

	chapter2 = [];
	chapter2pages = [];

	m = false;
	md = false;
	flevel = 255;
	bw = width/6;
	bh = width/12;
	prim = color(15,15,15);
	sec = color(100,30,30);
	tert = color(150,150,150);
	backg = color(55,55,55);

	// Standard fade in.
	fade = function() {
		flevel -= 10;
		fill(55,55,55,flevel);
		noStroke();
		rectMode(CORNER);
		rect(-1,-1,width+1,height+1);
	};

	// Loads all panels in the named folder into the target array.
	loadpanels = function(name,number,target) {
		for (i = 0; i < number;) {
			target[i] = loadImage("data/images/panels/"+name+i+".png");
			i ++;
		}
	};
	loadpanels("chap1/",chapter1length,chapter1);

	// The array of data for buttons used.
	buttons = {
		start:{x:width*(3/4),y:height/2,w:bw,h:bh,text:"Enter"},
		next:{x:width*(8/9),y:height*(1/2),w:bw,h:bh,text:"Next"},
		prev:{x:width*(1/9),y:height*(1/2),w:bw,h:bh,text:"Previous"},
	};

	// The hefty button function.  Works on all platforms tested.  Needs an exterior click call.
	button = function(con) {
		bux = con.x
		buy = con.y
		buw = con.w
		buh = con.h
		butext = con.text
		con.pressed = false;
		mouseover = false;

		rectMode(CENTER);

		if (mouseX>bux-buw/2&&mouseX<bux+buw/2 && mouseY>buy-buh/2&&mouseY<buy+buh/2) {
			mouseover = true;
		}

		if (mouseover) {
			fill(prim);
		} else {
			fill(sec);
		}
		stroke(prim);
		strokeWeight(buh/10);
		rect(bux,buy,buw,buh,buh/2.5);

		if (mouseover) {
			fill(sec);
		} else {
			fill(prim);
		}
		textFont(mainfont,buh/2);
		if (ismobile) {
			textSize(buh/3);
		}
		textAlign(CENTER,CENTER);
		text(butext,bux,buy);

		if (ismobile && mouseover) {
			con.pressed = true;
			return con.pressed;
		}

		if (mouseover && m) {
			con.pressed = true;
			return con.pressed;
		}
		return con.pressed;
	};

	// Standard button layout
	standardbuttons = function() {
		button(buttons.next);
		if (buttons.next.pressed) {
			if (ismobile) {
				if (flevel < 0) {
					page += 1;
					flevel = 255;
				}
			} else if (flevel < 80) {
				page += 1;
				flevel = 255;
			}
		};

		button(buttons.prev);
		if (buttons.prev.pressed) {
			if (ismobile) {
				if (flevel < 0) {
					page -= 1;
					flevel = 255;
				}
			} else if (flevel < 80) {
				page -= 1;
				flevel = 255;
			}

		};
	};

	// Displays an image properly.
	displaypanel = function(img,x,y) {
		imageMode(CENTER);
		pushMatrix();
		translate(x,y);
		scale(0.001*height,0.001*height);
			image(img,0,0);
		popMatrix();
	};

	// Creates a full page
	displaypage = function(chap,number) {
		background(backg);
		displaypanel(chap[number],width/2,height/2);
		standardbuttons();
		fade();
	};
	// Loads an array with full pages
	loadpages = function(cha,targ) {
		for (i = 0; i < cha.length; i ++) {
			targ.push(function() {displaypage("chap1/",page-1)});
		};
		targ[cha.length] = function() {
			background(backg);
			textSize(height/5);
			fill(sec);
			text("Under Construction",width/2,height/2);
		};
	};

	pages = [
		function() {
			background(backg)

			displaypanel(logo,width/4,height/2)

			button(buttons.start)
			if (buttons.start.pressed==true) {
				page += 1
			}
		},

	];
	loadpages(chapter1,pages);
};

draw = function() {
	pages[page]();
	textSize(17);
	text(page,width/2,height/2);
};

keyPressed = function() {
	keys[keyCode] = true;
};
keyReleased = function() {
	keys[keyCode] = false;
};
mousePressed = function() {
	m = true;
};
mouseReleased = function() {
	m = false;
};
}};
<commit_msg>Update main.js<commit_after>/*@pjs preload="data/images/logo1.png";*/

var sketchProc=function(processingInstance){ with (processingInstance){

//Setup
var wi = window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth;
var he = window.innerHeight ||
         document.documentElement.clientHeight ||
         document.body.clientHeight;
size(wi*0.9,he*0.9);
frameRate(60);

setup = function() {
	mainfont = createFont("Times New Roman");
	logo = loadImage("data/images/logo1.png");
	ismobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

	keys = [];
	pages = [];
	page = 0;

	chapter1 = [];
	chapter1pages = [];
	chapter1length = 6;

	chapter2 = [];
	chapter2pages = [];

	m = false;
	md = false;
	flevel = 255;
	bw = width/6;
	bh = width/12;
	prim = color(15,15,15);
	sec = color(100,30,30);
	tert = color(150,150,150);
	backg = color(55,55,55);

	// Standard fade in.
	fade = function() {
		flevel -= 10;
		fill(55,55,55,flevel);
		noStroke();
		rectMode(CORNER);
		rect(-1,-1,width+1,height+1);
	};

	// Loads all panels in the named folder into the target array.
	loadpanels = function(name,number,target) {
		for (i = 0; i < number;) {
			target[i] = loadImage("data/images/panels/"+name+i+".png");
			i ++;
		}
	};
	loadpanels("chap1/",chapter1length,chapter1);

	// The array of data for buttons used.
	buttons = {
		start:{x:width*(3/4),y:height/2,w:bw,h:bh,text:"Enter"},
		next:{x:width*(8/9),y:height*(1/2),w:bw,h:bh,text:"Next"},
		prev:{x:width*(1/9),y:height*(1/2),w:bw,h:bh,text:"Previous"},
	};

	// The hefty button function.  Works on all platforms tested.  Needs an exterior click call.
	button = function(con) {
		bux = con.x
		buy = con.y
		buw = con.w
		buh = con.h
		butext = con.text
		con.pressed = false;
		mouseover = false;

		rectMode(CENTER);

		if (mouseX>bux-buw/2&&mouseX<bux+buw/2 && mouseY>buy-buh/2&&mouseY<buy+buh/2) {
			mouseover = true;
		}

		if (mouseover) {
			fill(prim);
		} else {
			fill(sec);
		}
		stroke(prim);
		strokeWeight(buh/10);
		rect(bux,buy,buw,buh,buh/2.5);

		if (mouseover) {
			fill(sec);
		} else {
			fill(prim);
		}
		textFont(mainfont,buh/2);
		if (ismobile) {
			textSize(buh/3);
		}
		textAlign(CENTER,CENTER);
		text(butext,bux,buy);

		if (ismobile && mouseover) {
			con.pressed = true;
			return con.pressed;
		}

		if (mouseover && m) {
			con.pressed = true;
			return con.pressed;
		}
		return con.pressed;
	};

	// Standard button layout
	standardbuttons = function() {
		button(buttons.next);
		if (buttons.next.pressed) {
			if (ismobile) {
				if (flevel < 0) {
					page += 1;
					flevel = 255;
				}
			} else if (flevel < 80) {
				page += 1;
				flevel = 255;
			}
		};

		button(buttons.prev);
		if (buttons.prev.pressed) {
			if (ismobile) {
				if (flevel < 0) {
					page -= 1;
					flevel = 255;
				}
			} else if (flevel < 80) {
				page -= 1;
				flevel = 255;
			}

		};
	};

	// Displays an image properly.
	displaypanel = function(img,x,y) {
		imageMode(CENTER);
		pushMatrix();
		translate(x,y);
		scale(0.001*height,0.001*height);
			image(img,0,0);
		popMatrix();
	};

	// Creates a full page
	displaypage = function(chap,number) {
		background(backg);
		displaypanel(chap[number],width/2,height/2);
		standardbuttons();
		fade();
	};
	// Loads an array with full pages
	loadpages = function(cha,targ) {
		for (i = 0; i < cha.length; i ++) {
			targ.push(function() {displaypage("chap1/",page-1)});
		};
		targ[cha.length] = function() {
			background(backg);
			textSize(height/5);
			fill(sec);
			text("Under Construction",width/2,height/2);
		};
	};

	pages = [
		function() {
			background(backg)

			displaypanel(logo,width/4,height/2)

			button(buttons.start)
			if (buttons.start.pressed==true) {
				page += 1
			}
		},

	];
	loadpages(chapter1,pages);
};

draw = function() {
	pages[page]();
};

keyPressed = function() {
	keys[keyCode] = true;
};
keyReleased = function() {
	keys[keyCode] = false;
};
mousePressed = function() {
	m = true;
};
mouseReleased = function() {
	m = false;
};
}};
<|endoftext|>


<commit_before>/*global document, location, io, XMLHttpRequest, setTimeout, setInterval, StyleFix, ActiveXObject*/
(function () {
    'use strict';

    var pollTimeout = 2000,
        findCssIncludes = function () {
            var cssIncludes = [],
                links = document.getElementsByTagName('link'),
                styleSheet,
                cssRule,
                i,
                j,
                href,
                isLocal = function (href) {
                    var local = new RegExp("^" + document.location.protocol + "//" + document.location.host.replace(/[\.]/g, '\\$0')),
                        remote = /:\/\/|^\/\//;

                    return local.test(href) || !remote.test(href);
                };

            for (i = 0; i < links.length; i += 1) {
                if (/\bstylesheet\b/i.test(links[i].getAttribute('rel'))) {
                    href = links[i].getAttribute('href');
                    if (isLocal(href)) {
                        cssIncludes.push({type: 'link', href: href, node: links[i]});
                    }
                }
            }

            for (i = 0; i < document.styleSheets.length; i += 1) {
                styleSheet = document.styleSheets[i];
                for (j = 0; j < styleSheet.cssRules.length; j += 1) {
                    cssRule = styleSheet.cssRules[j];
                    if (cssRule.type === 3 && isLocal(cssRule.href)) { // CSSImportRule
                        cssIncludes.push({type: 'import', href: cssRule.href, node: cssRule, styleElement: styleSheet.ownerNode});
                    }
                }
            }

            return cssIncludes;
        },
        removeCacheBuster = function (href) {
            return href.replace(/[?&]livestyle=\d+/, '');
        },
        addCacheBuster = function (href) {
            return href + (href.indexOf('?') === -1 ? '?' : '&') + 'livestyle=' + new Date().getTime();
        },
        refresh = function (href) {
            var cssIncludes = findCssIncludes(),
                i,
                cssInclude,
                cssIncludeHref,
                newHref,
                replacerRegExp,
                freed;

            for (i = 0; i < cssIncludes.length; i += 1) {
                cssInclude = cssIncludes[i];
                cssIncludeHref = removeCacheBuster(cssInclude.href);

                if (cssIncludeHref === href) {
                    newHref = addCacheBuster(href);
                    if (cssInclude.type === 'import') {
                        replacerRegExp = new RegExp("@import\\s+url\\(" + cssInclude.href.replace(/[\?\[\]\(\)\{\}]/g, "\\$&") + "\\)");
                        cssInclude.styleElement.innerHTML = cssInclude.styleElement.innerHTML.replace(replacerRegExp, '@import url(' + newHref + ')');
                    } else {
                        cssInclude.node.setAttribute('href', newHref);
                        if (typeof StyleFix !== 'undefined' && StyleFix.link) { // PrefixFree support http://leaverou.github.com/prefixfree/
                            freed = cssInclude.node.prefixfreed;
                            StyleFix.link(cssInclude.node, true);
                            freed.parentNode.removeChild(freed);
                        }
                    }
                    // Replacing the first occurrence should be good enough. Besides, the @import replacement code invalidates
                    // the rest of the cssIncludes in the same stylesheet.
                    break;
                }
            }
        },
        startListening = function () {
            var socket = io.connect();

            socket.on('connect', function () {
                var hrefs = [],
                    watchNewStylesheets = function () {
                        var cssIncludes = findCssIncludes(),
                            toWatch = [],
                            i;

                        for (i = 0; i < cssIncludes.length; i += 1) {
                            if (hrefs.indexOf(cssIncludes[i].href) === -1) {
                                hrefs.push(cssIncludes[i].href);
                                toWatch.push(cssIncludes[i].href);
                            }
                        }

                        socket.emit('watch', toWatch, location.href);
                    };

                watchNewStylesheets();
                setInterval(watchNewStylesheets, pollTimeout);
            }).on('change', refresh);
        },
        state = {},
        startPolling = function () {
            var getXHR = function () {
                    try {
                        return new XMLHttpRequest();
                    } catch (e1) {
                        try {
                            return new ActiveXObject("Msxml2.XMLHTTP.6.0");
                        } catch (e2) {
                            try {
                                return new ActiveXObject("Msxml2.XMLHTTP.3.0");
                            } catch (e3) {
                                try {
                                    return new ActiveXObject("Msxml2.XMLHTTP");
                                } catch (e4) {
                                    try {
                                        return new ActiveXObject("Microsoft.XMLHTTP");
                                    } catch (e5) {}
                                }
                            }
                        }
                    }

                    return null; // no XHR support
                },
                cssIncludes = findCssIncludes(),
                proceed = function () {
                    var cssInclude,
                        url,
                        xhr;

                    if (cssIncludes.length > 0) {
                        cssInclude = cssIncludes.shift();
                        url = removeCacheBuster(cssInclude.href);
                        xhr = getXHR();

                        xhr.onreadystatechange = function () {
                            var lastModified,
                                etag;

                            if (xhr.readyState === 4) {
                                if (xhr.status === 200) {
                                    lastModified = Date.parse(xhr.getResponseHeader("Last-Modified"));
                                    etag = xhr.getResponseHeader("ETag");

                                    if (!state[url] || state[url].lastModified < lastModified || state[url].etag !== etag) {
                                        state[url] = {
                                            lastModified: lastModified,
                                            etag: etag
                                        };
                                        refresh(url);
                                    }
                                }

                                proceed();
                            }
                        };
                        xhr.open('HEAD', addCacheBuster(url), true);
                        xhr.send(null);
                    } else {
                        setTimeout(startPolling, pollTimeout);
                    }
                };

            proceed();
        };

    if (typeof io !== 'undefined') {
        startListening();
    } else {
        startPolling();
    }
}());
<commit_msg>livestyle-client.js: IE fixes. Now seems to work except @import statements (document.styleSheet.cssRules is undefined). Tested in IE7.<commit_after>/*global document, location, io, XMLHttpRequest, setTimeout, setInterval, StyleFix, ActiveXObject*/
(function () {
    'use strict';

    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (o, from) {
            var i = from || 0;
            for (; i < this.length; i += 1) {
                if (this[i] === o) {
                    return i;
                }
            }
            return -1;
        };
    }

    var pollTimeout = 2000,
        findCssIncludes = function () {
            var cssIncludes = [],
                links = document.getElementsByTagName('link'),
                styleSheet,
                cssRule,
                i,
                j,
                href,
                isLocal = function (href) {
                    var local = new RegExp("^" + document.location.protocol + "//" + document.location.host.replace(/[\.]/g, '\\$0')),
                        remote = /:\/\/|^\/\//;

                    return local.test(href) || !remote.test(href);
                };

            for (i = 0; i < links.length; i += 1) {
                if (/\bstylesheet\b/i.test(links[i].getAttribute('rel'))) {
                    href = links[i].getAttribute('href');
                    if (isLocal(href)) {
                        cssIncludes.push({type: 'link', href: href, node: links[i]});
                    }
                }
            }
            for (i = 0; i < document.styleSheets.length; i += 1) {
                styleSheet = document.styleSheets[i];
                if (styleSheet.cssRules) { // Not present in IE?
                    for (j = 0; j < styleSheet.cssRules.length; j += 1) {
                        cssRule = styleSheet.cssRules[j];
                        if (cssRule.type === 3 && isLocal(cssRule.href)) { // CSSImportRule
                            cssIncludes.push({type: 'import', href: cssRule.href, node: cssRule, styleElement: styleSheet.ownerNode});
                        }
                    }
                }
            }

            return cssIncludes;
        },
        removeCacheBuster = function (href) {
            return href.replace(/[?&]livestyle=\d+/, '');
        },
        addCacheBuster = function (href) {
            return href + (href.indexOf('?') === -1 ? '?' : '&') + 'livestyle=' + new Date().getTime();
        },
        refresh = function (href) {
            var cssIncludes = findCssIncludes(),
                i,
                cssInclude,
                cssIncludeHref,
                newHref,
                replacerRegExp,
                freed;

            for (i = 0; i < cssIncludes.length; i += 1) {
                cssInclude = cssIncludes[i];
                cssIncludeHref = removeCacheBuster(cssInclude.href);

                if (cssIncludeHref === href) {
                    newHref = addCacheBuster(href);
                    if (cssInclude.type === 'import') {
                        replacerRegExp = new RegExp("@import\\s+url\\(" + cssInclude.href.replace(/[\?\[\]\(\)\{\}]/g, "\\$&") + "\\)");
                        cssInclude.styleElement.innerHTML = cssInclude.styleElement.innerHTML.replace(replacerRegExp, '@import url(' + newHref + ')');
                    } else {
                        cssInclude.node.setAttribute('href', newHref);
                        if (typeof StyleFix !== 'undefined' && StyleFix.link) { // PrefixFree support http://leaverou.github.com/prefixfree/
                            freed = cssInclude.node.prefixfreed;
                            StyleFix.link(cssInclude.node, true);
                            freed.parentNode.removeChild(freed);
                        }
                    }
                    // Replacing the first occurrence should be good enough. Besides, the @import replacement code invalidates
                    // the rest of the cssIncludes in the same stylesheet.
                    break;
                }
            }
        },
        startListening = function () {
            var socket = io.connect();

            socket.on('connect', function () {
                var hrefs = [],
                    watchNewStylesheets = function () {
                        var cssIncludes = findCssIncludes(),
                            toWatch = [],
                            i;

                        for (i = 0; i < cssIncludes.length; i += 1) {
                            if (hrefs.indexOf(cssIncludes[i].href) === -1) {
                                hrefs.push(cssIncludes[i].href);
                                toWatch.push(cssIncludes[i].href);
                            }
                        }

                        socket.emit('watch', toWatch, location.href);
                    };

                watchNewStylesheets();
                setInterval(watchNewStylesheets, pollTimeout);
            }).on('change', refresh);
        },
        state = {},
        startPolling = function () {
            var getXHR = function () {
                    try {
                        return new XMLHttpRequest();
                    } catch (e1) {
                        try {
                            return new ActiveXObject("Msxml2.XMLHTTP.6.0");
                        } catch (e2) {
                            try {
                                return new ActiveXObject("Msxml2.XMLHTTP.3.0");
                            } catch (e3) {
                                try {
                                    return new ActiveXObject("Msxml2.XMLHTTP");
                                } catch (e4) {
                                    try {
                                        return new ActiveXObject("Microsoft.XMLHTTP");
                                    } catch (e5) {}
                                }
                            }
                        }
                    }

                    return null; // no XHR support
                },
                cssIncludes = findCssIncludes(),
                proceed = function () {
                    var cssInclude,
                        url,
                        xhr;

                    if (cssIncludes.length > 0) {
                        cssInclude = cssIncludes.shift();
                        url = removeCacheBuster(cssInclude.href);
                        xhr = getXHR();

                        xhr.onreadystatechange = function () {
                            var lastModified,
                                etag;

                            if (xhr.readyState === 4) {
                                if (xhr.status === 200) {
                                    lastModified = Date.parse(xhr.getResponseHeader("Last-Modified"));
                                    etag = xhr.getResponseHeader("ETag");

                                    if (!state[url] || state[url].lastModified < lastModified || state[url].etag !== etag) {
                                        state[url] = {
                                            lastModified: lastModified,
                                            etag: etag
                                        };
                                        refresh(url);
                                    }
                                }

                                proceed();
                            }
                        };
                        xhr.open('HEAD', addCacheBuster(url), true);
                        xhr.send(null);
                    } else {
                        setTimeout(startPolling, pollTimeout);
                    }
                };

            proceed();
        };

    if (typeof io !== 'undefined') {
        startListening();
    } else {
        startPolling();
    }
}());
<|endoftext|>