<commit_before>

L.TileLayer.addInitHook(function(url,opts) {

	if (!opts.useCache) {
		this._db     = null;
		this._canvas = null;
		return;
	}

	this._db = new PouchDB('offline-tiles');
	this._canvas = document.createElement('canvas');

	if (!(this._canvas.getContext && this._canvas.getContext('2d'))) {
		// HTML5 canvas is needed to pack the tiles as base64 data. If
		//   the browser doesn't support canvas, the code will forcefully
		//   skip caching the tiles.
		this._canvas = null;
	}
});

L.TileLayer.prototype.options.useCache     = false;
L.TileLayer.prototype.options.saveToCache  = true;
L.TileLayer.prototype.options.useOnlyCache = false;
L.TileLayer.prototype.options.cacheMaxAge  = 24*3600*1000;

L.TileLayer.include({

	// Overwrites L.TileLayer.prototype._loadTile
	_loadTile: function(tile, tilePoint) {
		tile._layer  = this;
		tile.onerror = this._tileOnError;

		this._adjustTilePoint(tilePoint);

		var tileUrl = this.getTileUrl(tilePoint);
		this.fire('tileloadstart', {
			tile: tile,
			url: tileUrl
		});

		if (this.options.useCache && this._canvas) {
			this._db.get(tileUrl, {revs_info: true}, this._onCacheLookup(tile,tileUrl));
		} else {
			// Fall back to standard behaviour
			tile.onload  = this._tileOnLoad;
			tile.src = tileUrl;
		}
	},

	// Returns a callback (closure over tile/key/originalSrc) to be run when the DB
	//   backend is finished with a fetch operation.
	_onCacheLookup: function(tile,tileUrl) {
		return function(err,data) {
			if (data) {
				this.fire('tilecachehit', {
					tile: tile,
					url: tileUrl
				});
				if (Date.now() > data.timestamp + this.options.cacheMaxAge && !this.options.useOnlyCache) {
					// Tile is too old, try to refresh it
// 					console.log('Tile is too old: ', tileUrl);

					if (this.options.saveToCache) {
						tile.onload = this._saveTile(tileUrl, data._revs_info[0].rev);
					}
					tile.crossOrigin = 'Anonymous';
					tile.src = tileUrl;
					tile.onerror = function(ev) {
						// If the tile is too old but couldn't be fetched from the network,
						//   serve the one still in cache.
						this.src = data.dataUrl;
					}
				} else {
					// Serve tile from cached data
// 					console.log('Tile is cached: ', tileUrl);
					tile.onload  = this._tileOnLoad;
					tile.src = data.dataUrl;    // data.dataUrl is already a base64-encoded PNG image.
				}
			} else {
				this.fire('tilecachemiss', {
					tile: tile,
					url: tileUrl
				});
				if (this.options.useOnlyCache) {
					// Offline, not cached
// 					console.log('Tile not in cache', tileUrl);
					tile.onload  = this._tileOnLoad;
					tile.src = L.Util.emptyImageUrl;
				} else {
					// Online, not cached, request the tile normally
// 					console.log('Requesting tile normally', tileUrl);
					if (this.options.saveToCache) {
						tile.onload = this._saveTile(tileUrl);
					} else {
						tile.onload  = this._tileOnLoad;
					}
					tile.crossOrigin = 'Anonymous';
					tile.src = tileUrl;
				}
			}
		}.bind(this);
	},

	// Returns an event handler (closure over DB key), which runs
	//   when the tile (which is an <img>) is ready.
	// The handler will delete the document from pouchDB if an existing revision is passed.
	//   This will keep just the latest valid copy of the image in the cache.
	_saveTile: function(tileUrl, existingRevision) {
		return function(ev) {
			if (this._canvas === null) return;
			var img = ev.target;
			L.TileLayer.prototype._tileOnLoad.call(img,ev);
			this._canvas.width  = img.naturalWidth  || img.width;
			this._canvas.height = img.naturalHeight || img.height;

			var context = this._canvas.getContext('2d');
			context.drawImage(img, 0, 0);

			var dataUrl = this._canvas.toDataURL('image/png');
			var doc = {dataUrl: dataUrl, timestamp: Date.now()};

			if (existingRevision) {
				this._db.remove(tileUrl, existingRevision);
			}
			this._db.put(doc, tileUrl, doc.timestamp);
		}.bind(this);
	},

	// Seeds the cache given a bounding box (latLngBounds), and
	//   the minimum and maximum zoom levels
	// Use with care! This can spawn thousands of requests and
	//   flood tileservers!
	seed: function(bbox, minZoom, maxZoom) {
		if (minZoom > maxZoom) return;
		if (!this._map) return;

		var queue = [];

		for (var z = minZoom; z<maxZoom; z++) {

			var northEastPoint = this._map.project(bbox.getNorthEast(),z);
			var southWestPoint = this._map.project(bbox.getSouthWest(),z);

			// Calculate tile indexes as per L.TileLayer._update and
			//   L.TileLayer._addTilesFromCenterOut
			var tileSize   = this._getTileSize();
			var tileBounds = L.bounds(
				northEastPoint.divideBy(tileSize)._floor(),
				southWestPoint.divideBy(tileSize)._floor());

			for (var j = tileBounds.min.y; j <= tileBounds.max.y; j++) {
				for (var i = tileBounds.min.x; i <= tileBounds.max.x; i++) {
					point = new L.Point(i, j);
					point.z = z;
					queue.push(this.getTileUrl(point));
				}
			}
		}

		var seedData = {
			bbox: bbox,
			minZoom: minZoom,
			maxZoom: maxZoom,
			queueLength: queue.length
		}
		this.fire('seedstart', seedData);
		var tile = this._createTile();
		tile._layer = this;
		this._seedOneTile(tile, queue, seedData);
	},

	// Uses a defined tile to eat through one item in the queue and
	//   asynchronously recursively call itself when the tile has
	//   finished loading.
	_seedOneTile: function(tile, remaining, seedData) {
		if (!remaining.length) {
			this.fire('seedend', seedData);
			return;
		}
		this.fire('seedprogress', {
			bbox:    seedData.bbox,
			minZoom: seedData.minZoom,
			maxZoom: seedData.maxZoom,
			queueLength: seedData.queueLength,
			remainingLength: remaining.length
		});

		var url = remaining.pop();

		this._db.get(url, function(err,data){
			if (!data) {
				/// FIXME: Do something on tile error!!
				tile.onload = function(ev){
					this._saveTile(url)(ev);
					this._seedOneTile(tile, remaining, seedData);
				}.bind(this);
				tile.crossOrigin = 'Anonymous';
				tile.src = url;
			} else {
				this._seedOneTile(tile, remaining, seedData);
			}
		}.bind(this));

	}

});

<commit_msg>fix mixin init hook scope<commit_after>

L.TileLayer.addInitHook(function() {

	if (!this.options.useCache) {
		this._db     = null;
		this._canvas = null;
		return;
	}

	this._db = new PouchDB('offline-tiles');
	this._canvas = document.createElement('canvas');

	if (!(this._canvas.getContext && this._canvas.getContext('2d'))) {
		// HTML5 canvas is needed to pack the tiles as base64 data. If
		//   the browser doesn't support canvas, the code will forcefully
		//   skip caching the tiles.
		this._canvas = null;
	}
});

L.TileLayer.prototype.options.useCache     = false;
L.TileLayer.prototype.options.saveToCache  = true;
L.TileLayer.prototype.options.useOnlyCache = false;
L.TileLayer.prototype.options.cacheMaxAge  = 24*3600*1000;

L.TileLayer.include({

	// Overwrites L.TileLayer.prototype._loadTile
	_loadTile: function(tile, tilePoint) {
		tile._layer  = this;
		tile.onerror = this._tileOnError;

		this._adjustTilePoint(tilePoint);

		var tileUrl = this.getTileUrl(tilePoint);
		this.fire('tileloadstart', {
			tile: tile,
			url: tileUrl
		});

		if (this.options.useCache && this._canvas) {
			this._db.get(tileUrl, {revs_info: true}, this._onCacheLookup(tile,tileUrl));
		} else {
			// Fall back to standard behaviour
			tile.onload  = this._tileOnLoad;
			tile.src = tileUrl;
		}
	},

	// Returns a callback (closure over tile/key/originalSrc) to be run when the DB
	//   backend is finished with a fetch operation.
	_onCacheLookup: function(tile,tileUrl) {
		return function(err,data) {
			if (data) {
				this.fire('tilecachehit', {
					tile: tile,
					url: tileUrl
				});
				if (Date.now() > data.timestamp + this.options.cacheMaxAge && !this.options.useOnlyCache) {
					// Tile is too old, try to refresh it
// 					console.log('Tile is too old: ', tileUrl);

					if (this.options.saveToCache) {
						tile.onload = this._saveTile(tileUrl, data._revs_info[0].rev);
					}
					tile.crossOrigin = 'Anonymous';
					tile.src = tileUrl;
					tile.onerror = function(ev) {
						// If the tile is too old but couldn't be fetched from the network,
						//   serve the one still in cache.
						this.src = data.dataUrl;
					}
				} else {
					// Serve tile from cached data
// 					console.log('Tile is cached: ', tileUrl);
					tile.onload  = this._tileOnLoad;
					tile.src = data.dataUrl;    // data.dataUrl is already a base64-encoded PNG image.
				}
			} else {
				this.fire('tilecachemiss', {
					tile: tile,
					url: tileUrl
				});
				if (this.options.useOnlyCache) {
					// Offline, not cached
// 					console.log('Tile not in cache', tileUrl);
					tile.onload  = this._tileOnLoad;
					tile.src = L.Util.emptyImageUrl;
				} else {
					// Online, not cached, request the tile normally
// 					console.log('Requesting tile normally', tileUrl);
					if (this.options.saveToCache) {
						tile.onload = this._saveTile(tileUrl);
					} else {
						tile.onload  = this._tileOnLoad;
					}
					tile.crossOrigin = 'Anonymous';
					tile.src = tileUrl;
				}
			}
		}.bind(this);
	},

	// Returns an event handler (closure over DB key), which runs
	//   when the tile (which is an <img>) is ready.
	// The handler will delete the document from pouchDB if an existing revision is passed.
	//   This will keep just the latest valid copy of the image in the cache.
	_saveTile: function(tileUrl, existingRevision) {
		return function(ev) {
			if (this._canvas === null) return;
			var img = ev.target;
			L.TileLayer.prototype._tileOnLoad.call(img,ev);
			this._canvas.width  = img.naturalWidth  || img.width;
			this._canvas.height = img.naturalHeight || img.height;

			var context = this._canvas.getContext('2d');
			context.drawImage(img, 0, 0);

			var dataUrl = this._canvas.toDataURL('image/png');
			var doc = {dataUrl: dataUrl, timestamp: Date.now()};

			if (existingRevision) {
				this._db.remove(tileUrl, existingRevision);
			}
			this._db.put(doc, tileUrl, doc.timestamp);
		}.bind(this);
	},

	// Seeds the cache given a bounding box (latLngBounds), and
	//   the minimum and maximum zoom levels
	// Use with care! This can spawn thousands of requests and
	//   flood tileservers!
	seed: function(bbox, minZoom, maxZoom) {
		if (minZoom > maxZoom) return;
		if (!this._map) return;

		var queue = [];

		for (var z = minZoom; z<maxZoom; z++) {

			var northEastPoint = this._map.project(bbox.getNorthEast(),z);
			var southWestPoint = this._map.project(bbox.getSouthWest(),z);

			// Calculate tile indexes as per L.TileLayer._update and
			//   L.TileLayer._addTilesFromCenterOut
			var tileSize   = this._getTileSize();
			var tileBounds = L.bounds(
				northEastPoint.divideBy(tileSize)._floor(),
				southWestPoint.divideBy(tileSize)._floor());

			for (var j = tileBounds.min.y; j <= tileBounds.max.y; j++) {
				for (var i = tileBounds.min.x; i <= tileBounds.max.x; i++) {
					point = new L.Point(i, j);
					point.z = z;
					queue.push(this.getTileUrl(point));
				}
			}
		}

		var seedData = {
			bbox: bbox,
			minZoom: minZoom,
			maxZoom: maxZoom,
			queueLength: queue.length
		}
		this.fire('seedstart', seedData);
		var tile = this._createTile();
		tile._layer = this;
		this._seedOneTile(tile, queue, seedData);
	},

	// Uses a defined tile to eat through one item in the queue and
	//   asynchronously recursively call itself when the tile has
	//   finished loading.
	_seedOneTile: function(tile, remaining, seedData) {
		if (!remaining.length) {
			this.fire('seedend', seedData);
			return;
		}
		this.fire('seedprogress', {
			bbox:    seedData.bbox,
			minZoom: seedData.minZoom,
			maxZoom: seedData.maxZoom,
			queueLength: seedData.queueLength,
			remainingLength: remaining.length
		});

		var url = remaining.pop();

		this._db.get(url, function(err,data){
			if (!data) {
				/// FIXME: Do something on tile error!!
				tile.onload = function(ev){
					this._saveTile(url)(ev);
					this._seedOneTile(tile, remaining, seedData);
				}.bind(this);
				tile.crossOrigin = 'Anonymous';
				tile.src = url;
			} else {
				this._seedOneTile(tile, remaining, seedData);
			}
		}.bind(this));

	}

});

<|endoftext|>


<commit_before>/*******************************************************************************
 *
 * module Bridge
 *
 ******************************************************************************/

var Bridge = function() {

  /* Due to OSX' async callback nature the messages needs to be queued up and
   * carefully sent in sequence. The next message cannot be sent until a message
   * from Ruby confirms the last message was received.
   */
  var messages = [];
  var busy = false;

  return {

    /* Prepares the communication bridge.
     */
    init : function() {
      bridge = $('<input id="SKUI_RUBY_BRIDGE" type="hidden" />');
      $('body').append( bridge );
    },

    /* Escapes backslashes and single quotes.
     * (private ?)
     */
    escape_string : function( value ) {
      return value.replace('\\', '\\\\').replace("'", "\\'");
    },

    /* Executes a Javascript command and returns the return value to the
     * Ruby bridge.
     */
    execute : function( code_string ) {
      // Clean up <SCRIPT></SCRIPT> elements which Ruby
      // UI::WebDialog.execute_script leaves behind.
      $('body script').detach();
      // Execute the JavaScript code and put the return value back into the
      // bridge.
      Bridge.return_ruby( eval(code_string) );
    },

    /* Returns the checked state for the Checkbox control given by UI ID.
     */
    get_checkbox_state : function( ui_id ) {
      return $('#'+ui_id+' input').prop('checked');
    },

    /* Returns the checked state for the given jQuery selector.
     */
    get_checked_state : function( selector ) {
      return $(selector).prop('checked');
    },

    /* Returns the HTML for the given jQuery selector.
     */
    get_html : function( selector ) {
      return $(selector).html();
    },

    /* Returns the Rect for the Checkbox control given by UI ID.
     */
    get_control_rect : function( ui_id ) {
      $control = $('#'+ui_id);
      position = $control.position();
      width  = $control.outerWidth();
      height = $control.outerHeight();
      rect = {
        'left'   : position.left,
        'top'    : position.top,
        'right'  : position.left + width,
        'bottom' : position.top + height,
        'width'  : width,
        'height' : height
      }
      return rect;
    },

    /* Returns the text for the given jQuery selector.
     */
    get_text : function( selector ) {
      return $(selector).text();
    },

    /* Returns the value for the given jQuery selector.
     */
    get_value : function( selector ) {
      return $(selector).val();
    },

    /* Process the next message in the queue to Ruby.
     */
    push_message : function() {
      if ( busy ) {
        return false;
      } else {
        message = messages.shift();
        if ( message ) {
          busy = true;
          uri_message = encodeURIComponent( message );
          window.location = 'skp:SKUI_Event_Callback@' + uri_message;
          return true;
        } else {
          return false;
        }
      }
    },

    /* Ruby calls this when a message has been received which means the next
     * message can be sent.
     */
    pump_message : function() {
      busy = false;
      Bridge.push_message();
      return busy;
    },

    /* Send the next message in the queue to Ruby.
     */
    queue_message : function( message ) {
      messages.push( message );
      return Bridge.push_message();
    },

    /* Resets the Ruby bridge.
     */
    reset : function() {
      $('#SKUI_RUBY_BRIDGE').val( '' );
    },

    /* Returns a Javascript object to the Ruby bridge element so that SketchUp
     * Ruby script can fetch the value.
     */
    return_ruby : function( value ) {
      $('#SKUI_RUBY_BRIDGE').val( Bridge.value_to_ruby(value) );
    },

    /* Sets the ID for the <BODY> element so that the Window class' properties
     * can control the appearance of the window background.
     */
    set_window_id : function( ui_id ) {
      $('body').attr( 'id', ui_id );
    },

    /* Converts Javascript objects into Ruby objects.
     *
     * TODO:
     * * JSON
     * * ...
     *
     * (private ?)
     */
    value_to_ruby : function( value ) {
      var ruby_string = '';
      switch ( $.type( value ) ) {
        case 'boolean':
          ruby_string = value.toString();
          break;
        case 'number':
          if ( isNaN( value ) ) {
            ruby_string = '0.0/0.0';
          } else if ( isFinite( value ) ) {
            ruby_string = value.toString();
          } else {
            // Infinite
            ruby_string = ( value > 0 ) ? '1.0/0.0' : '-1.0/0.0';
          }
          break;
        case 'string':
          ruby_string = "'" + Bridge.escape_string( value ) + "'";
          break;
        case 'null':
        case 'undefined':
          ruby_string = 'nil';
          break;
        case 'array':
          ruby_values = $.map(value, function(value, index) {
            return Bridge.value_to_ruby( value );
          });
          ruby_string = '[' + ruby_values.join(',') + ']';
          break;
        case 'date':
          ruby_string = 'Time.at(' + value.getTime() + ')';
          break;
        case 'regexp':
          // http://www.w3schools.com/jsref/jsref_obj_regexp.asp
          i = value.ignoreCase ? 'i' : '';
          g = value.global     ? 'g' : ''; // Not supported in Ruby.
          m = value.multiline  ? 'm' : '';
          regex = '/'+value.source+'/'+i+m;
          ruby_string = Bridge.value_to_ruby( regex );
          break;
        case 'function':
          ruby_string = "'<FUNCTION>'";
          break;
        case 'object':
          // Assume JSON.
          ruby_hash = new Array();
          $.each(value, function(k, v) {
            ruby_key   = Bridge.value_to_ruby( k );
            ruby_value = Bridge.value_to_ruby( v );
            ruby_hash.push( ruby_key + " => " + ruby_value );
          });
          ruby_string = '{' + ruby_hash.join(',') + '}';
          break;
      }
      return ruby_string;
    }

  };

}(); // Bridge<commit_msg>Fixed Bridge.escape_string to replace all occurances.<commit_after>/*******************************************************************************
 *
 * module Bridge
 *
 ******************************************************************************/

var Bridge = function() {

  /* Due to OSX' async callback nature the messages needs to be queued up and
   * carefully sent in sequence. The next message cannot be sent until a message
   * from Ruby confirms the last message was received.
   */
  var messages = [];
  var busy = false;

  return {

    /* Prepares the communication bridge.
     */
    init : function() {
      bridge = $('<input id="SKUI_RUBY_BRIDGE" type="hidden" />');
      $('body').append( bridge );
    },

    /* Escapes backslashes and single quotes.
     * (private ?)
     */
    escape_string : function( value ) {
      return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
    },

    /* Executes a Javascript command and returns the return value to the
     * Ruby bridge.
     */
    execute : function( code_string ) {
      // Clean up <SCRIPT></SCRIPT> elements which Ruby
      // UI::WebDialog.execute_script leaves behind.
      $('body script').detach();
      // Execute the JavaScript code and put the return value back into the
      // bridge.
      Bridge.return_ruby( eval(code_string) );
    },

    /* Returns the checked state for the Checkbox control given by UI ID.
     */
    get_checkbox_state : function( ui_id ) {
      return $('#'+ui_id+' input').prop('checked');
    },

    /* Returns the checked state for the given jQuery selector.
     */
    get_checked_state : function( selector ) {
      return $(selector).prop('checked');
    },

    /* Returns the HTML for the given jQuery selector.
     */
    get_html : function( selector ) {
      return $(selector).html();
    },

    /* Returns the Rect for the Checkbox control given by UI ID.
     */
    get_control_rect : function( ui_id ) {
      $control = $('#'+ui_id);
      position = $control.position();
      width  = $control.outerWidth();
      height = $control.outerHeight();
      rect = {
        'left'   : position.left,
        'top'    : position.top,
        'right'  : position.left + width,
        'bottom' : position.top + height,
        'width'  : width,
        'height' : height
      }
      return rect;
    },

    /* Returns the text for the given jQuery selector.
     */
    get_text : function( selector ) {
      return $(selector).text();
    },

    /* Returns the value for the given jQuery selector.
     */
    get_value : function( selector ) {
      return $(selector).val();
    },

    /* Process the next message in the queue to Ruby.
     */
    push_message : function() {
      if ( busy ) {
        return false;
      } else {
        message = messages.shift();
        if ( message ) {
          busy = true;
          uri_message = encodeURIComponent( message );
          window.location = 'skp:SKUI_Event_Callback@' + uri_message;
          return true;
        } else {
          return false;
        }
      }
    },

    /* Ruby calls this when a message has been received which means the next
     * message can be sent.
     */
    pump_message : function() {
      busy = false;
      Bridge.push_message();
      return busy;
    },

    /* Send the next message in the queue to Ruby.
     */
    queue_message : function( message ) {
      messages.push( message );
      return Bridge.push_message();
    },

    /* Resets the Ruby bridge.
     */
    reset : function() {
      $('#SKUI_RUBY_BRIDGE').val( '' );
    },

    /* Returns a Javascript object to the Ruby bridge element so that SketchUp
     * Ruby script can fetch the value.
     */
    return_ruby : function( value ) {
      $('#SKUI_RUBY_BRIDGE').val( Bridge.value_to_ruby(value) );
    },

    /* Sets the ID for the <BODY> element so that the Window class' properties
     * can control the appearance of the window background.
     */
    set_window_id : function( ui_id ) {
      $('body').attr( 'id', ui_id );
    },

    /* Converts Javascript objects into Ruby objects.
     *
     * TODO:
     * * JSON
     * * ...
     *
     * (private ?)
     */
    value_to_ruby : function( value ) {
      var ruby_string = '';
      switch ( $.type( value ) ) {
        case 'boolean':
          ruby_string = value.toString();
          break;
        case 'number':
          if ( isNaN( value ) ) {
            ruby_string = '0.0/0.0';
          } else if ( isFinite( value ) ) {
            ruby_string = value.toString();
          } else {
            // Infinite
            ruby_string = ( value > 0 ) ? '1.0/0.0' : '-1.0/0.0';
          }
          break;
        case 'string':
          ruby_string = "'" + Bridge.escape_string( value ) + "'";
          break;
        case 'null':
        case 'undefined':
          ruby_string = 'nil';
          break;
        case 'array':
          ruby_values = $.map(value, function(value, index) {
            return Bridge.value_to_ruby( value );
          });
          ruby_string = '[' + ruby_values.join(',') + ']';
          break;
        case 'date':
          ruby_string = 'Time.at(' + value.getTime() + ')';
          break;
        case 'regexp':
          // http://www.w3schools.com/jsref/jsref_obj_regexp.asp
          i = value.ignoreCase ? 'i' : '';
          g = value.global     ? 'g' : ''; // Not supported in Ruby.
          m = value.multiline  ? 'm' : '';
          regex = '/'+value.source+'/'+i+m;
          ruby_string = Bridge.value_to_ruby( regex );
          break;
        case 'function':
          ruby_string = "'<FUNCTION>'";
          break;
        case 'object':
          // Assume JSON.
          ruby_hash = new Array();
          $.each(value, function(k, v) {
            ruby_key   = Bridge.value_to_ruby( k );
            ruby_value = Bridge.value_to_ruby( v );
            ruby_hash.push( ruby_key + " => " + ruby_value );
          });
          ruby_string = '{' + ruby_hash.join(',') + '}';
          break;
      }
      return ruby_string;
    }

  };

}(); // Bridge<|endoftext|>


<commit_before>//utilidades variadas que podem ser reutilizadas em todo o projeto
FlashBuy.util = {
  isDevice: function () {
    return document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1;
  },
  onDeviceReady: function(callback) {
    if(FlashBuy.util.isDevice()) {
      $(document).on('deviceready', callback);
    } else {
      $(document).ready(callback);
    }
  },
  QRCode: {
    scan: function (callback) {
      var success = function(success) {
        callback(true, success);
      };
      var error = function(error) {
        callback(false, error);
      };

      cordova.plugins.barcodeScanner.scan(
        success,
        error
      );
    },
    generate: function (information, callback) {
      var success = function(success) {
        callback(true, success);
      };
      var error = function(error) {
        callback(false, error);
      };

      cordova.plugins.barcodeScanner.encode(
        cordova.plugins.barcodeScanner.Encode.TEXT_TYPE,
        information,
        success,
        error
      );
    }
  },
  getDeviceId: function () {
    return device.uuid;
  },
  getDeviceInfo: function() {
    return device;
  }
};

$(document).trigger('FlashBuy.util.ready');
<commit_msg>retirado implementação antiga de QRCode, gen e scan<commit_after>//utilidades variadas que podem ser reutilizadas em todo o projeto
FlashBuy.util = {
  isDevice: function () {
    return document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1;
  },
  onDeviceReady: function(callback) {
    if(FlashBuy.util.isDevice()) {
      $(document).on('deviceready', callback);
    } else {
      $(document).ready(callback);
    }
  },
  gerarQRCode: function () {
      //implementar...
  },
  getDeviceId: function () {
    return device.uuid;
  },
  getDeviceInfo: function() {
    return device;
  }
};

$(document).trigger('FlashBuy.util.ready');
<|endoftext|>


<commit_before>$(document).ready(function(){
  var max = 70;
  var characters_remaining = max - $('#event_name').val().length;

  $('.text-counter').text(characters_remaining);

  $('#event_name').keyup(function () {

    characters_remaining = max - $(this).val().length;

    $('.text-counter').text(characters_remaining);

    if (parseInt(characters_remaining) < 0) {
      $('.char-limit').addClass('invalid-char-limit');
    }
    else {
      $('.char-limit').removeClass('invalid-char-limit');
    }
  });
});
<commit_msg>Add case for when `#event_name` is undefined<commit_after>$(document).ready(function(){
  var max = 70;

  if ($('#event_name').val() !== undefined) {
    var characters_remaining = max - $('#event_name').val().length;
  }

  $('.text-counter').text(characters_remaining);

  $('#event_name').keyup(function () {

    characters_remaining = max - $(this).val().length;

    $('.text-counter').text(characters_remaining);

    if (parseInt(characters_remaining) < 0) {
      $('.char-limit').addClass('invalid-char-limit');
    }
    else {
      $('.char-limit').removeClass('invalid-char-limit');
    }
  });
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'react-emotion';
import raf from 'raf-schd';
import { Button, LoadingButton } from '@keystonejs/ui/src/primitives/buttons';
import { colors } from '@keystonejs/ui/src/theme';

const Wrapper = styled.div({
  marginTop: 60,
  minHeight: 120,
  position: 'relative',
});
const Toolbar = styled.div({
  backgroundColor: colors.page,
  boxShadow: 'rgba(0, 0, 0, 0.1) 0px -2px 0px',
  display: 'flex',
  justifyContent: 'space-between',
  margin: '24px 0',
  padding: '24px 0',
});

function getWindowSize() {
  return {
    x: window.innerWidth,
    y: window.innerHeight,
  };
}

export default class Footer extends Component {
  state = {
    position: 'relative',
    width: 'auto',
    height: 'auto',
    top: 0,
  };
  static propTypes = {
    onDelete: PropTypes.func,
    onReset: PropTypes.func,
    onSave: PropTypes.func,
  };
  componentDidMount() {
    // Bail in IE8 because React doesn't support the onScroll event in that browser
    // Conveniently (!) IE8 doesn't have window.getComputedStyle which we also use here
    if (!window.getComputedStyle) return;

    this.windowSize = getWindowSize();
    const footerStyle = window.getComputedStyle(this.footer);
    const bar = this.footer.bar;
    console.log(bar);
    this.footerSize = {
      x: this.footer.offsetWidth,
      y: this.footer.offsetHeight + parseInt(footerStyle.marginTop || '0'),
    };
    window.addEventListener('scroll', this.recalcPosition, false);
    window.addEventListener('resize', this.recalcPosition, false);
    this.recalcPosition();
  }
  componentWillUnmount() {
    window.removeEventListener('scroll', this.recalcPosition, false);
    window.removeEventListener('resize', this.recalcPosition, false);
  }
  recalcPosition = raf(() => {
    const foo = this.wrapper.foo;
    console.log(foo);
    this.footerSize.x = this.wrapper.offsetWidth;

    var offsetTop = 0;
    var offsetEl = this.wrapper;

    while (offsetEl) {
      offsetTop += offsetEl.offsetTop;
      offsetEl = offsetEl.offsetParent;
    }

    const maxY = offsetTop + this.footerSize.y;
    const viewY = window.scrollY + window.innerHeight;

    const newSize = getWindowSize();
    const sizeChanged =
      newSize.x !== this.windowSize.x || newSize.y !== this.windowSize.y;
    this.windowSize = newSize;

    const newState = {
      height: this.footerSize.y,
      width: this.footerSize.x,
    };

    if (viewY > maxY && (sizeChanged || this.mode !== 'inline')) {
      this.mode = 'inline';
      newState.top = 0;
      newState.position = 'absolute';
      this.setState(newState);
    } else if (viewY <= maxY && (sizeChanged || this.mode !== 'fixed')) {
      this.mode = 'fixed';
      newState.top = window.innerHeight - this.footerSize.y;
      newState.position = 'fixed';
      this.setState(newState);
    }
  });
  getWrapper = ref => {
    this.wrapper = ref;
  };
  getToolbar = ref => {
    this.footer = ref;
  };

  render() {
    const { onSave, onReset, onDelete, updateInProgress } = this.props;
    const { height, position, top, width } = this.state;

    const wrapperStyle = { height };
    const footerStyle = { height, position, top, width };

    return (
      <Wrapper innerRef={this.getWrapper} style={wrapperStyle} key="wrapper">
        <Toolbar innerRef={this.getToolbar} style={footerStyle} key="footer">

            <LoadingButton
              appearance="primary"
              isDisabled={updateInProgress}
              isLoading={updateInProgress}
              onClick={onSave}
              style={{ marginRight: 8 }}
              type="submit"
            >
              Save Changes
            </LoadingButton>
            <Button
              appearance="warning"
              isDisabled={!onReset || updateInProgress}
              variant="subtle"
              onClick={onReset}
            >
              Reset Changes
            </Button>

            <Button
              appearance="danger"
              isDisabled={updateInProgress}
              variant="subtle"
              onClick={onDelete}
            >
              Delete
            </Button>

        </Toolbar>
      </Wrapper>
    );
  }
}
<commit_msg>Handle race condition<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'react-emotion';
import raf from 'raf-schd';
import { Button, LoadingButton } from '@keystonejs/ui/src/primitives/buttons';
import { colors } from '@keystonejs/ui/src/theme';

const Wrapper = styled.div({
  marginTop: 60,
  minHeight: 120,
  position: 'relative',
});
const Toolbar = styled.div({
  backgroundColor: colors.page,
  boxShadow: 'rgba(0, 0, 0, 0.1) 0px -2px 0px',
  display: 'flex',
  justifyContent: 'space-between',
  margin: '24px 0',
  padding: '24px 0',
});

function getWindowSize() {
  return {
    x: window.innerWidth,
    y: window.innerHeight,
  };
}

export default class Footer extends Component {
  state = {
    position: 'relative',
    width: 'auto',
    height: 'auto',
    top: 0,
  };
  static propTypes = {
    onDelete: PropTypes.func,
    onReset: PropTypes.func,
    onSave: PropTypes.func,
  };
  componentDidMount() {
    // Bail in IE8 because React doesn't support the onScroll event in that browser
    // Conveniently (!) IE8 doesn't have window.getComputedStyle which we also use here
    if (!window.getComputedStyle) return;

    this.windowSize = getWindowSize();
    const footerStyle = window.getComputedStyle(this.footer);
    this.footerSize = {
      x: this.footer.offsetWidth,
      y: this.footer.offsetHeight + parseInt(footerStyle.marginTop || '0'),
    };
    window.addEventListener('scroll', this.recalcPosition, false);
    window.addEventListener('resize', this.recalcPosition, false);
    this.recalcPosition();
  }
  componentWillUnmount() {
    window.removeEventListener('scroll', this.recalcPosition, false);
    window.removeEventListener('resize', this.recalcPosition, false);
  }
  recalcPosition = raf(() => {
    if (this.wrapper === null) {
      // Due to the use of raf, this function may end up being called *after*
      // the component is unmounted. If this happens, we can safely return early.
      return;
    }
    this.footerSize.x = this.wrapper.offsetWidth;

    var offsetTop = 0;
    var offsetEl = this.wrapper;

    while (offsetEl) {
      offsetTop += offsetEl.offsetTop;
      offsetEl = offsetEl.offsetParent;
    }

    const maxY = offsetTop + this.footerSize.y;
    const viewY = window.scrollY + window.innerHeight;

    const newSize = getWindowSize();
    const sizeChanged =
      newSize.x !== this.windowSize.x || newSize.y !== this.windowSize.y;
    this.windowSize = newSize;

    const newState = {
      height: this.footerSize.y,
      width: this.footerSize.x,
    };

    if (viewY > maxY && (sizeChanged || this.mode !== 'inline')) {
      this.mode = 'inline';
      newState.top = 0;
      newState.position = 'absolute';
      this.setState(newState);
    } else if (viewY <= maxY && (sizeChanged || this.mode !== 'fixed')) {
      this.mode = 'fixed';
      newState.top = window.innerHeight - this.footerSize.y;
      newState.position = 'fixed';
      this.setState(newState);
    }
  });
  getWrapper = ref => {
    this.wrapper = ref;
  };
  getToolbar = ref => {
    this.footer = ref;
  };

  render() {
    const { onSave, onReset, onDelete, updateInProgress } = this.props;
    const { height, position, top, width } = this.state;

    const wrapperStyle = { height };
    const footerStyle = { height, position, top, width };

    return (
      <Wrapper innerRef={this.getWrapper} style={wrapperStyle} key="wrapper">
        <Toolbar innerRef={this.getToolbar} style={footerStyle} key="footer">

            <LoadingButton
              appearance="primary"
              isDisabled={updateInProgress}
              isLoading={updateInProgress}
              onClick={onSave}
              style={{ marginRight: 8 }}
              type="submit"
            >
              Save Changes
            </LoadingButton>
            <Button
              appearance="warning"
              isDisabled={!onReset || updateInProgress}
              variant="subtle"
              onClick={onReset}
            >
              Reset Changes
            </Button>

            <Button
              appearance="danger"
              isDisabled={updateInProgress}
              variant="subtle"
              onClick={onDelete}
            >
              Delete
            </Button>

        </Toolbar>
      </Wrapper>
    );
  }
}
<|endoftext|>


<commit_before>import AWS from 'aws-sdk'

const dynamoDb = new AWS.DynamoDB.DocumentClient();

export const create = (event, context, callback) => {
  const timestamp = new Date().getTime();
  const body = JSON.parse(event.body);
  body.createdAt = timestamp;
  body.updatedAt = timestamp;

  const params = {
    TableName: 'books',
    Item: body
  };

  dynamoDb.put(params, (error, result) => {
    if (error) {
      console.error(error);
      callback(new Error('Couldn\'t create item.'));
      return;
    }

    const response = {
      statusCode: 200,
      body: JSON.stringify({message: 'Success.'}),
    };
    callback(null, response);
  });
};

export const list = (event, context, callback) => {
  const params = {
    TableName: 'books'
  };

  dynamoDb.scan(params, (error, result) => {
    if (error) {
      console.error(error);
      callback(new Error('Couldn\'t get items.'));
      return;
    }

    // create a response
    const response = {
      statusCode: 200,
      body: JSON.stringify(result.Items),
    };
    callback(null, response);
  });
};

export const select = (event, context, callback) => {
  const params = {
    TableName: 'books',
    FilterExpression : "begins_with(volumeInfo.title, :val) or begins_with(volumeInfo.authors[0], :val)",
    ExpressionAttributeValues : {":val" :event.queryStringParameters.q}
  };

  dynamoDb.scan(params, (error, result) => {
    if (error) {
      console.error(error);
      callback(new Error('Couldn\'t get items.'));
      return;
    }

    const response = {
      statusCode: 200,
      body: JSON.stringify(result.Items),
    };
    callback(null, response);
  });
};
<commit_msg>Remove: unnecessary comment<commit_after>import AWS from 'aws-sdk'

const dynamoDb = new AWS.DynamoDB.DocumentClient();

export const create = (event, context, callback) => {
  const timestamp = new Date().getTime();
  const body = JSON.parse(event.body);
  body.createdAt = timestamp;
  body.updatedAt = timestamp;

  const params = {
    TableName: 'books',
    Item: body
  };

  dynamoDb.put(params, (error, result) => {
    if (error) {
      console.error(error);
      callback(new Error('Couldn\'t create item.'));
      return;
    }

    const response = {
      statusCode: 200,
      body: JSON.stringify({message: 'Success.'}),
    };
    callback(null, response);
  });
};

export const list = (event, context, callback) => {
  const params = {
    TableName: 'books'
  };

  dynamoDb.scan(params, (error, result) => {
    if (error) {
      console.error(error);
      callback(new Error('Couldn\'t get items.'));
      return;
    }

    const response = {
      statusCode: 200,
      body: JSON.stringify(result.Items),
    };
    callback(null, response);
  });
};

export const select = (event, context, callback) => {
  const params = {
    TableName: 'books',
    FilterExpression : "begins_with(volumeInfo.title, :val) or begins_with(volumeInfo.authors[0], :val)",
    ExpressionAttributeValues : {":val" :event.queryStringParameters.q}
  };

  dynamoDb.scan(params, (error, result) => {
    if (error) {
      console.error(error);
      callback(new Error('Couldn\'t get items.'));
      return;
    }

    const response = {
      statusCode: 200,
      body: JSON.stringify(result.Items),
    };
    callback(null, response);
  });
};
<|endoftext|>


<commit_before>const prettyBytes = require('prettier-bytes')
const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB

const isSupported = !!indexedDB

const DB_NAME = 'uppy-blobs'
const STORE_NAME = 'files' // maybe have a thumbnail store in the future
const DEFAULT_EXPIRY = 24 * 60 * 60 * 1000 // 24 hours
const DB_VERSION = 3

// Set default `expires` dates on existing stored blobs.
function migrateExpiration (store) {
  const request = store.openCursor()
  request.onsuccess = (event) => {
    const cursor = event.target.result
    const entry = cursor.value
    entry.expires = Date.now() + DEFAULT_EXPIRY
    cursor.update(entry)
  }
}

function connect (dbName) {
  const request = indexedDB.open(dbName, DB_VERSION)
  return new Promise((resolve, reject) => {
    request.onupgradeneeded = (event) => {
      const db = event.target.result
      const transaction = event.currentTarget.transaction

      if (event.oldVersion < 2) {
        // Added in v2: DB structure changed to a single shared object store
        const store = db.createObjectStore(STORE_NAME, { keyPath: 'id' })
        store.createIndex('store', 'store', { unique: false })
      }

      if (event.oldVersion < 3) {
        // Added in v3
        const store = transaction.objectStore(STORE_NAME)
        store.createIndex('expires', 'expires', { unique: false })

        migrateExpiration(store)
      }

      transaction.oncomplete = () => {
        resolve(db)
      }
    }
    request.onsuccess = (event) => {
      resolve(event.target.result)
    }
    request.onerror = reject
  })
}

function waitForRequest (request) {
  return new Promise((resolve, reject) => {
    request.onsuccess = (event) => {
      resolve(event.target.result)
    }
    request.onerror = reject
  })
}

let cleanedUp = false
class IndexedDBStore {
  constructor (opts) {
    this.opts = Object.assign({
      dbName: DB_NAME,
      storeName: 'default',
      expires: DEFAULT_EXPIRY, // 24 hours
      maxFileSize: 10 * 1024 * 1024, // 10 MB
      maxTotalSize: 300 * 1024 * 1024 // 300 MB
    }, opts)

    this.name = this.opts.storeName

    const createConnection = () => {
      return connect(this.opts.dbName)
    }

    if (!cleanedUp) {
      cleanedUp = true
      this.ready = IndexedDBStore.cleanup()
        .then(createConnection, createConnection)
    } else {
      this.ready = createConnection
    }
  }

  key (fileID) {
    return `${this.name}!${fileID}`
  }

  /**
   * List all file blobs currently in the store.
   */
  list () {
    return this.ready.then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readonly')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.index('store')
        .getAll(IDBKeyRange.only(this.name))
      return waitForRequest(request)
    }).then((files) => {
      const result = {}
      files.forEach((file) => {
        result[file.fileID] = file.data
      })
      return result
    })
  }

  /**
   * Get one file blob from the store.
   */
  get (fileID) {
    return this.ready.then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readonly')
      const request = transaction.objectStore(STORE_NAME)
        .get(this.key(fileID))
      return waitForRequest(request)
    }).then((result) => ({
      id: result.data.fileID,
      data: result.data.data
    }))
  }

  /**
   * Get the total size of all stored files.
   *
   * @private
   */
  getSize () {
    return this.ready.then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readonly')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.index('store')
        .openCursor(IDBKeyRange.only(this.name))
      return new Promise((resolve, reject) => {
        let size = 0
        request.onsuccess = (event) => {
          const cursor = event.target.result
          if (cursor) {
            size += cursor.value.data.size
            cursor.continue()
          } else {
            resolve(size)
          }
        }
        request.onerror = () => {
          reject(new Error('Could not retrieve stored blobs size'))
        }
      })
    })
  }

  /**
   * Save a file in the store.
   */
  put (file) {
    if (file.data.size > this.opts.maxFileSize) {
      return Promise.reject(new Error('File is too big to store.'))
    }
    return this.getSize().then((size) => {
      if (size > this.opts.maxTotalSize) {
        return Promise.reject(new Error('No space left'))
      }
      return this.ready
    }).then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readwrite')
      const request = transaction.objectStore(STORE_NAME).add({
        id: this.key(file.id),
        fileID: file.id,
        store: this.name,
        expires: Date.now() + this.opts.expires,
        data: file.data
      })
      return waitForRequest(request)
    })
  }

  /**
   * Delete a file blob from the store.
   */
  delete (fileID) {
    return this.ready.then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readwrite')
      const request = transaction.objectStore(STORE_NAME)
        .delete(this.key(fileID))
      return waitForRequest(request)
    })
  }

  /**
   * Delete all stored blobs that have an expiry date that is before Date.now().
   * This is a static method because it deletes expired blobs from _all_ Uppy instances.
   */
  static cleanup () {
    return connect(DB_NAME).then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readwrite')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.index('expires')
        .openCursor(IDBKeyRange.upperBound(Date.now()))
      return new Promise((resolve, reject) => {
        request.onsuccess = (event) => {
          const cursor = event.target.result
          if (cursor) {
            const entry = cursor.value
            console.log(
              '[IndexedDBStore] Deleting record', entry.fileID,
              'of size', prettyBytes(entry.data.size),
              '- expired on', new Date(entry.expires))
            cursor.delete() // Ignoring return value … it's not terrible if this goes wrong.
            cursor.continue()
          } else {
            resolve()
          }
        }
        request.onerror = reject
      })
    }).then((db) => {
      db.close()
    })
  }
}

IndexedDBStore.isSupported = isSupported

module.exports = IndexedDBStore
<commit_msg>restore: Fix undefined `db.close()` after cleanup.<commit_after>const prettyBytes = require('prettier-bytes')
const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB

const isSupported = !!indexedDB

const DB_NAME = 'uppy-blobs'
const STORE_NAME = 'files' // maybe have a thumbnail store in the future
const DEFAULT_EXPIRY = 24 * 60 * 60 * 1000 // 24 hours
const DB_VERSION = 3

// Set default `expires` dates on existing stored blobs.
function migrateExpiration (store) {
  const request = store.openCursor()
  request.onsuccess = (event) => {
    const cursor = event.target.result
    const entry = cursor.value
    entry.expires = Date.now() + DEFAULT_EXPIRY
    cursor.update(entry)
  }
}

function connect (dbName) {
  const request = indexedDB.open(dbName, DB_VERSION)
  return new Promise((resolve, reject) => {
    request.onupgradeneeded = (event) => {
      const db = event.target.result
      const transaction = event.currentTarget.transaction

      if (event.oldVersion < 2) {
        // Added in v2: DB structure changed to a single shared object store
        const store = db.createObjectStore(STORE_NAME, { keyPath: 'id' })
        store.createIndex('store', 'store', { unique: false })
      }

      if (event.oldVersion < 3) {
        // Added in v3
        const store = transaction.objectStore(STORE_NAME)
        store.createIndex('expires', 'expires', { unique: false })

        migrateExpiration(store)
      }

      transaction.oncomplete = () => {
        resolve(db)
      }
    }
    request.onsuccess = (event) => {
      resolve(event.target.result)
    }
    request.onerror = reject
  })
}

function waitForRequest (request) {
  return new Promise((resolve, reject) => {
    request.onsuccess = (event) => {
      resolve(event.target.result)
    }
    request.onerror = reject
  })
}

let cleanedUp = false
class IndexedDBStore {
  constructor (opts) {
    this.opts = Object.assign({
      dbName: DB_NAME,
      storeName: 'default',
      expires: DEFAULT_EXPIRY, // 24 hours
      maxFileSize: 10 * 1024 * 1024, // 10 MB
      maxTotalSize: 300 * 1024 * 1024 // 300 MB
    }, opts)

    this.name = this.opts.storeName

    const createConnection = () => {
      return connect(this.opts.dbName)
    }

    if (!cleanedUp) {
      cleanedUp = true
      this.ready = IndexedDBStore.cleanup()
        .then(createConnection, createConnection)
    } else {
      this.ready = createConnection
    }
  }

  key (fileID) {
    return `${this.name}!${fileID}`
  }

  /**
   * List all file blobs currently in the store.
   */
  list () {
    return this.ready.then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readonly')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.index('store')
        .getAll(IDBKeyRange.only(this.name))
      return waitForRequest(request)
    }).then((files) => {
      const result = {}
      files.forEach((file) => {
        result[file.fileID] = file.data
      })
      return result
    })
  }

  /**
   * Get one file blob from the store.
   */
  get (fileID) {
    return this.ready.then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readonly')
      const request = transaction.objectStore(STORE_NAME)
        .get(this.key(fileID))
      return waitForRequest(request)
    }).then((result) => ({
      id: result.data.fileID,
      data: result.data.data
    }))
  }

  /**
   * Get the total size of all stored files.
   *
   * @private
   */
  getSize () {
    return this.ready.then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readonly')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.index('store')
        .openCursor(IDBKeyRange.only(this.name))
      return new Promise((resolve, reject) => {
        let size = 0
        request.onsuccess = (event) => {
          const cursor = event.target.result
          if (cursor) {
            size += cursor.value.data.size
            cursor.continue()
          } else {
            resolve(size)
          }
        }
        request.onerror = () => {
          reject(new Error('Could not retrieve stored blobs size'))
        }
      })
    })
  }

  /**
   * Save a file in the store.
   */
  put (file) {
    if (file.data.size > this.opts.maxFileSize) {
      return Promise.reject(new Error('File is too big to store.'))
    }
    return this.getSize().then((size) => {
      if (size > this.opts.maxTotalSize) {
        return Promise.reject(new Error('No space left'))
      }
      return this.ready
    }).then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readwrite')
      const request = transaction.objectStore(STORE_NAME).add({
        id: this.key(file.id),
        fileID: file.id,
        store: this.name,
        expires: Date.now() + this.opts.expires,
        data: file.data
      })
      return waitForRequest(request)
    })
  }

  /**
   * Delete a file blob from the store.
   */
  delete (fileID) {
    return this.ready.then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readwrite')
      const request = transaction.objectStore(STORE_NAME)
        .delete(this.key(fileID))
      return waitForRequest(request)
    })
  }

  /**
   * Delete all stored blobs that have an expiry date that is before Date.now().
   * This is a static method because it deletes expired blobs from _all_ Uppy instances.
   */
  static cleanup () {
    return connect(DB_NAME).then((db) => {
      const transaction = db.transaction([STORE_NAME], 'readwrite')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.index('expires')
        .openCursor(IDBKeyRange.upperBound(Date.now()))
      return new Promise((resolve, reject) => {
        request.onsuccess = (event) => {
          const cursor = event.target.result
          if (cursor) {
            const entry = cursor.value
            console.log(
              '[IndexedDBStore] Deleting record', entry.fileID,
              'of size', prettyBytes(entry.data.size),
              '- expired on', new Date(entry.expires))
            cursor.delete() // Ignoring return value … it's not terrible if this goes wrong.
            cursor.continue()
          } else {
            resolve(db)
          }
        }
        request.onerror = reject
      })
    }).then((db) => {
      db.close()
    })
  }
}

IndexedDBStore.isSupported = isSupported

module.exports = IndexedDBStore
<|endoftext|>


<commit_before>/* This is `mask`, a tiny MIT-licensed library providing collision masks
 * and thus pixel-perfect collision detection in JavaScript. Collision
 * masks are read from [PBM][] files. Check the [github][] page for more
 * information.
 * [github]: https://github.com/startling/mask
 * [PBM]: http://netpbm.sourceforge.net/doc/pbm.html
 */
/*!*/
var Mask = (function () {
  /* Construct a `Mask`.
   *
   * Examples:
   *
   *     new Mask()
   *
   * @constructor
   * @api public
   */
  function Mask () {
    this.x = this.y = this.w = this.h = 0;
  }
  /* Make a clone of a `Mask`.
   *
   * @this {Mask}
   * @api public
   */
  Mask.prototype.clone = function () {
    var other = new Mask();
    other.x = this.x;
    other.y = this.y;
    other.w = this.w;
    other.h = this.h;
    return other;
  };
  /* Translate this `Mask` in two dimensions.
   *
   * @this {Mask}
   * @param {Number} x x-distance
   * @param {Number} y y-distancex
   * @api public
   */
  Mask.prototype.translate = function (x, y) {
    this.x += x;
    this.y += y;
  };
  /* Make a copy of this `Mask` translated to the coordinates given.
   *
   * @this {Mask}
   * @param {Number} x x-coordinate
   * @param {Number} y y-coordinate
   * @return {Mask}
   * @api public
   */
  Mask.prototype.at = function (x, y) {
    var other = this.clone();
    other.x = x;
    other.y = y;
    return other;
  };
  /* Mask a copy of this `Mask` translated in two dimensions.
   * @this {Mask}
   * @param {Number} x x-distance
   * @param {Number} y y-distance
   * @return {Mask}
   * @api public
   */
  Mask.prototype.translated = function (x, y) {
    var other = this.clone();
    other.translate(x, y);
    return other;
  };
  /* Test whether a Mask is completely contained within another.
   *
   * @this {Mask}
   * @param {Mask} b The containing Mask.
   * @api public
   */
  Mask.prototype.within = function (b) {
    var intersect = intersection(this, b);
    for (var x = intersect.x; x < intersect.w; x++) {
      for (var y = intersect.y; y < intersect.h; y++) {
        if (this.collidesAt(x, y) &&
            !b.collidesAt(x, y)) {
          return false;
        }
      }
    }
    return true;
  };
  /* Test whether this mask collides at the given location.
   *
   * @this {Mask}
   * @param {Number} x x-coordinate
   * @param {Number} y y-coordinate
   * @return {Mask}
   * @api public
   */
  Mask.prototype.collidesAt = function (x, y) {
    return false;
  };
  /** Some callbacks expect a `Mask`.
   * @callback MaskCallback
   * @param {Mask} the collision map
   * @api private
   */
  /* Create a `Mask` object from an `ArrayBuffer` taken as a PBM image.
   *
   * N.B. do not use the newly-constructed `Mask` directly until
   * the callback is called.
   *
   * @constructor
   * @param {ArrayBuffer} array image data
   * @param {MaskCallback} callback
   * @api public
   */
  Mask.PBM = function (array, callback) {
    Mask.bind(this)();
    this.data = null;
    var bytes = new Uint8Array(array);
    if (bytes.byteLength > 2) {
      if (bytes[0] === 'P'.charCodeAt(0)) {
        if (bytes[1] === '4'.charCodeAt(0)) {
          // This is a PBM binary file...
          return fromBinaryPBM(this, bytes, callback);
        } else if (bytes[1] == "1".charCodeAt(0)) {
          // This is a PBM ASCII file...
          return fromASCIIPBM(this, bytes, callback);
        } else {
          // Unknown signature.
          return callback(null, new Error("Unknown PBM signature."));
        }
      } else {
        // Unknown signature.
        return callback(null, new Error("Unknown PBM signature."));
      }
    } else {
      // File too short.
      return callback(null, Error("Invalid PBM image."));
    }
  };
  Mask.PBM.prototype = new Mask();
  Mask.PBM.prototype.clone = function () {
    var other = this.__proto__.clone();
    other.data = this.data;
    return other;
  };
  Mask.PBM.prototype.collidesAt = function (x, y) {
    return !!this.data[x - this.x] &&
      !!this.data[x - this.x][y - this.y];
  };
  /* Skip every byte matching a regular expression.
   *
   * @api private
   * @param {RegExp} regex regular expression
   * @param {Uint8Buffer} bytes character data
   * @param {object} state parser state
   */
  function skipRegex (regex, bytes, state) {
    for (; state.index < bytes.byteLength; state.index++) {
      var here = String.fromCharCode(bytes[state.index]);
      if (!here.match(regex)) {
        break;
      }
    }
  }
  /* Find all the leading characters matching a regular expression and
   * stick them in an array.
   *
   * @api private
   * @param {RegExp} regex regular expression
   * @param {Uint8Buffer} bytes character data
   * @param {object} state parser state
   * @return {Array}
   */
  function accumulateRegex (regex, bytes, state) {
    var accumulator = [];
    for (; state.index < bytes.byteLength; state.index++) {
      var here = String.fromCharCode(bytes[state.index]);
      if (here.match(regex)) {
        accumulator.push(here);
      } else {
        break;
      }
    }
    return accumulator;
  }
  /* Skip the parts that come after a PBM signature -- whitespace and any
   * number of comments.
   *
   * @api private
   * @param {Uint8Buffer} bytes character data
   * @param {object} state parser state
   */
  function skipPostSignature (bytes, state) {
    skipRegex(/\s/, bytes, state);
    var here = String.fromCharCode(bytes[state.index]);
    while (here === '#') {
      state.index++;
      skipRegex(/[^\n]/, bytes, state);
      skipRegex(/\s/, bytes, state);
      here = String.fromCharCode(bytes[state.index]);
    }
  }
  /* Create a `Mask` from an Uint8Array taken semantically as an ASCII PBM image.
   *
   * @param {Uint8Buffer} bytes PBM image data.
   * @param {MaskCallback} callback
   * @api private
   */
  fromASCIIPBM = function (m, bytes, callback) {
    var bits = [];
    var state = {index: 2};
    // Skip the spaces and comments post-signature.
    skipPostSignature(bytes, state);
    var width = accumulateRegex(/\d/, bytes, state).join("");
    skipRegex(/\s/, bytes, state);
    // Read numbers and stick them into 'height' until whitespace.
    var height = accumulateRegex(/\d/, bytes, state).join("");
    skipRegex(/\s/, bytes, state);
    // Initialize the mask.
    m.w = parseInt(width, 10);
    m.h = parseInt(height, 10);
    // Read 0 and 1 until the end of the file, skipping everything else.
    for (; state.index < bytes.byteLength; state.index++) {
      function add (x) {
        if (!bits.length || bits[bits.length - 1].length === m.w) {
          bits.push([]);
        }
        bits[bits.length - 1].push(x);
      }
      switch (bytes[state.index]) {
      case '0'.charCodeAt(0):
        add(false);
        break;
      case '1'.charCodeAt(0):
        add(true);
        break;
      default:
        break;
      }
    }
    m.data = bits;
    return callback(m);
  };
  /* Create a `Mask` from an Uint8Array taken semantically as an binary
   * PBM image.
   *
   * @param {Uint8Buffer} bytes PBM image data.
   * @param {MaskCallback} callback
   * @api private
   */
  fromBinaryPBM = function (m, bytes, callback) {
    var bits = [];
    var state = {index: 2};
    // Skip the spaces and comments post-signature.
    skipPostSignature(bytes, state);
    // Read numbers and stick them into 'width' until whitespace.
    var width = accumulateRegex(/\d/, bytes, state).join("");
    skipRegex(/\s/, bytes, state);
    // Read numbers and stick them into 'height' until whitespace.
    var height = accumulateRegex(/\d/, bytes, state).join("");
    skipRegex(/\s/, bytes, state);
    // Initialize the mask.
    m.w = parseInt(width, 10);
    m.h = parseInt(height, 10);
    // Read each byte, in sequence.
    for (; state.index < bytes.byteLength; state.index++) {
      if (bits.length === m.h - 1 &&
          bits[bits.length - 1].length === m.w - 1) {
        break;
      }
      else if (!bits.length || bits[bits.length - 1].length >= m.w) {
        bits.push([]);
      }
      for (var b = 0; b < 8; b++) {
        if (bits[bits.length - 1].length < m.w) {
          var bit = Boolean((bytes[state.index] >> (7 - b)) & 0x01);
          bits[bits.length - 1].push(bit);
        }
      }
    }
    m.data = bits;
    callback(m);
  };
  /* Create a `Mask` from a PBM image at some URL.
   *
   * @param {String} url A URL pointing to a PBM image.
   * @param {MaskCallback} callback
   * @api public
   */
  Mask.PBM.url = function (url, callback) {
    var req = new XMLHttpRequest();
    req.responseType = "arraybuffer";
    req.onload = function (ev) {
      if (req.response) {
        return Mask.fromPBM(req.response, callback);
      } else {
        // No response.
        return callback(null, new Error("No response."));
      }
    };
    req.onerror = function (e) {
      return callback(null, e);
    };
    req.open("GET", url, true);
    req.send();
  };
  /* Create an object representing the intersection of the bounding
   * boxes of two objects.
   *
   * @api private
   */
  function intersection (a, b) {
    var a_2 = {x: a.x + a.w, y: a.y + a.h};
    var b_2 = {x: b.x + b.w, y: b.y + b.h};
    var overlap = {x: a.x > b.x ? a.x : b.x,
                   y: a.y > b.y ? a.y : b.y};
    overlap.w = (a_2.x < b_2.x ? a_2.x : b_2.x) - overlap.x;
    overlap.h = (a_2.y < b_2.y ? a_2.y : b_2.y) - overlap.y;
    return overlap;
  }
  /* Test whether two Masks collide.
   *
   * @param {Mask} a
   * @param {Mask} b
   * @api public
   */
  Mask.collision = function (a, b) {
    var intersect = intersection(a, b);
    for (var x = intersect.x; x < intersect.x + intersect.w; x++) {
      for (var y = intersect.y; y < intersect.y + intersect.h; y++) {
        if (a.collidesAt(x, y) &&
            b.collidesAt(x, y)) {
          return true;
        }
      }
    }
    return false;
  };
  /* Create a mask as an inversion of another.
   *
   * @constructor
   * @param {Mask} other
   * @api public
   */
  Mask.Invert = function (other) {
    this.x = other.x;
    this.y = other.y;
    this.w = other.w;
    this.h = other.h;
    this.inversion = other;
  };
  Mask.Invert.prototype = new Mask();
  Mask.Invert.prototype.collidesAt = function (x, y) {
    return !this.inversion.collidesAt(x, y);
  };
  /* Create a vector box mask.
   *
   * @constructor
   * @param {Number} w width
   * @param {Number} h height
   * @api public
   */
  Mask.Box = function (w, h) {
    this.x = 0;
    this.y = 0;
    this.w = w;
    this.h = h;
  };
  Mask.Box.prototype = new Mask();
  Mask.Box.prototype.clone = function () {
    var other = new Mask.Box(this.w, this.h);
    other.translate(this.x, this.y);
    return other;
  };
  Mask.Box.prototype.collidesAt = function (x, y) {
    return x >= this.x && y >= this.y &&
      x <= (this.x + this.w) && y <= (this.y + this.h);
  };
  /*!*/
  if (typeof module !== "undefined") {
    module.exports = { Mask: Mask };
  }
  return Mask;
})();
<commit_msg>Two asterisks for every doc comment<commit_after>/** This is `mask`, a tiny MIT-licensed library providing collision masks
 * and thus pixel-perfect collision detection in JavaScript. Collision
 * masks are read from [PBM][] files. Check the [github][] page for more
 * information.
 * [github]: https://github.com/startling/mask
 * [PBM]: http://netpbm.sourceforge.net/doc/pbm.html
 */
/*!*/
var Mask = (function () {
  /** Construct a `Mask`.
   *
   * Examples:
   *
   *     new Mask()
   *
   * @constructor
   * @api public
   */
  function Mask () {
    this.x = this.y = this.w = this.h = 0;
  }
  /** Make a clone of a `Mask`.
   *
   * @this {Mask}
   * @api public
   */
  Mask.prototype.clone = function () {
    var other = new Mask();
    other.x = this.x;
    other.y = this.y;
    other.w = this.w;
    other.h = this.h;
    return other;
  };
  /** Translate this `Mask` in two dimensions.
   *
   * @this {Mask}
   * @param {Number} x x-distance
   * @param {Number} y y-distancex
   * @api public
   */
  Mask.prototype.translate = function (x, y) {
    this.x += x;
    this.y += y;
  };
  /** Make a copy of this `Mask` translated to the coordinates given.
   *
   * @this {Mask}
   * @param {Number} x x-coordinate
   * @param {Number} y y-coordinate
   * @return {Mask}
   * @api public
   */
  Mask.prototype.at = function (x, y) {
    var other = this.clone();
    other.x = x;
    other.y = y;
    return other;
  };
  /** Mask a copy of this `Mask` translated in two dimensions.
   * @this {Mask}
   * @param {Number} x x-distance
   * @param {Number} y y-distance
   * @return {Mask}
   * @api public
   */
  Mask.prototype.translated = function (x, y) {
    var other = this.clone();
    other.translate(x, y);
    return other;
  };
  /** Test whether a Mask is completely contained within another.
   *
   * @this {Mask}
   * @param {Mask} b The containing Mask.
   * @api public
   */
  Mask.prototype.within = function (b) {
    var intersect = intersection(this, b);
    for (var x = intersect.x; x < intersect.w; x++) {
      for (var y = intersect.y; y < intersect.h; y++) {
        if (this.collidesAt(x, y) &&
            !b.collidesAt(x, y)) {
          return false;
        }
      }
    }
    return true;
  };
  /** Test whether this mask collides at the given location.
   *
   * @this {Mask}
   * @param {Number} x x-coordinate
   * @param {Number} y y-coordinate
   * @return {Mask}
   * @api public
   */
  Mask.prototype.collidesAt = function (x, y) {
    return false;
  };
  /** Some callbacks expect a `Mask`.
   * @callback MaskCallback
   * @param {Mask} the collision map
   * @api private
   */
  /** Create a `Mask` object from an `ArrayBuffer` taken as a PBM image.
   *
   * N.B. do not use the newly-constructed `Mask` directly until
   * the callback is called.
   *
   * @constructor
   * @param {ArrayBuffer} array image data
   * @param {MaskCallback} callback
   * @api public
   */
  Mask.PBM = function (array, callback) {
    Mask.bind(this)();
    this.data = null;
    var bytes = new Uint8Array(array);
    if (bytes.byteLength > 2) {
      if (bytes[0] === 'P'.charCodeAt(0)) {
        if (bytes[1] === '4'.charCodeAt(0)) {
          // This is a PBM binary file...
          return fromBinaryPBM(this, bytes, callback);
        } else if (bytes[1] == "1".charCodeAt(0)) {
          // This is a PBM ASCII file...
          return fromASCIIPBM(this, bytes, callback);
        } else {
          // Unknown signature.
          return callback(null, new Error("Unknown PBM signature."));
        }
      } else {
        // Unknown signature.
        return callback(null, new Error("Unknown PBM signature."));
      }
    } else {
      // File too short.
      return callback(null, Error("Invalid PBM image."));
    }
  };
  Mask.PBM.prototype = new Mask();
  Mask.PBM.prototype.clone = function () {
    var other = this.__proto__.clone();
    other.data = this.data;
    return other;
  };
  Mask.PBM.prototype.collidesAt = function (x, y) {
    return !!this.data[x - this.x] &&
      !!this.data[x - this.x][y - this.y];
  };
  /** Skip every byte matching a regular expression.
   *
   * @api private
   * @param {RegExp} regex regular expression
   * @param {Uint8Buffer} bytes character data
   * @param {object} state parser state
   */
  function skipRegex (regex, bytes, state) {
    for (; state.index < bytes.byteLength; state.index++) {
      var here = String.fromCharCode(bytes[state.index]);
      if (!here.match(regex)) {
        break;
      }
    }
  }
  /** Find all the leading characters matching a regular expression and
   * stick them in an array.
   *
   * @api private
   * @param {RegExp} regex regular expression
   * @param {Uint8Buffer} bytes character data
   * @param {object} state parser state
   * @return {Array}
   */
  function accumulateRegex (regex, bytes, state) {
    var accumulator = [];
    for (; state.index < bytes.byteLength; state.index++) {
      var here = String.fromCharCode(bytes[state.index]);
      if (here.match(regex)) {
        accumulator.push(here);
      } else {
        break;
      }
    }
    return accumulator;
  }
  /** Skip the parts that come after a PBM signature -- whitespace and any
   * number of comments.
   *
   * @api private
   * @param {Uint8Buffer} bytes character data
   * @param {object} state parser state
   */
  function skipPostSignature (bytes, state) {
    skipRegex(/\s/, bytes, state);
    var here = String.fromCharCode(bytes[state.index]);
    while (here === '#') {
      state.index++;
      skipRegex(/[^\n]/, bytes, state);
      skipRegex(/\s/, bytes, state);
      here = String.fromCharCode(bytes[state.index]);
    }
  }
  /** Create a `Mask` from an Uint8Array taken semantically as an ASCII PBM image.
   *
   * @param {Uint8Buffer} bytes PBM image data.
   * @param {MaskCallback} callback
   * @api private
   */
  fromASCIIPBM = function (m, bytes, callback) {
    var bits = [];
    var state = {index: 2};
    // Skip the spaces and comments post-signature.
    skipPostSignature(bytes, state);
    var width = accumulateRegex(/\d/, bytes, state).join("");
    skipRegex(/\s/, bytes, state);
    // Read numbers and stick them into 'height' until whitespace.
    var height = accumulateRegex(/\d/, bytes, state).join("");
    skipRegex(/\s/, bytes, state);
    // Initialize the mask.
    m.w = parseInt(width, 10);
    m.h = parseInt(height, 10);
    // Read 0 and 1 until the end of the file, skipping everything else.
    for (; state.index < bytes.byteLength; state.index++) {
      function add (x) {
        if (!bits.length || bits[bits.length - 1].length === m.w) {
          bits.push([]);
        }
        bits[bits.length - 1].push(x);
      }
      switch (bytes[state.index]) {
      case '0'.charCodeAt(0):
        add(false);
        break;
      case '1'.charCodeAt(0):
        add(true);
        break;
      default:
        break;
      }
    }
    m.data = bits;
    return callback(m);
  };
  /** Create a `Mask` from an Uint8Array taken semantically as an binary
   * PBM image.
   *
   * @param {Uint8Buffer} bytes PBM image data.
   * @param {MaskCallback} callback
   * @api private
   */
  fromBinaryPBM = function (m, bytes, callback) {
    var bits = [];
    var state = {index: 2};
    // Skip the spaces and comments post-signature.
    skipPostSignature(bytes, state);
    // Read numbers and stick them into 'width' until whitespace.
    var width = accumulateRegex(/\d/, bytes, state).join("");
    skipRegex(/\s/, bytes, state);
    // Read numbers and stick them into 'height' until whitespace.
    var height = accumulateRegex(/\d/, bytes, state).join("");
    skipRegex(/\s/, bytes, state);
    // Initialize the mask.
    m.w = parseInt(width, 10);
    m.h = parseInt(height, 10);
    // Read each byte, in sequence.
    for (; state.index < bytes.byteLength; state.index++) {
      if (bits.length === m.h - 1 &&
          bits[bits.length - 1].length === m.w - 1) {
        break;
      }
      else if (!bits.length || bits[bits.length - 1].length >= m.w) {
        bits.push([]);
      }
      for (var b = 0; b < 8; b++) {
        if (bits[bits.length - 1].length < m.w) {
          var bit = Boolean((bytes[state.index] >> (7 - b)) & 0x01);
          bits[bits.length - 1].push(bit);
        }
      }
    }
    m.data = bits;
    callback(m);
  };
  /** Create a `Mask` from a PBM image at some URL.
   *
   * @param {String} url A URL pointing to a PBM image.
   * @param {MaskCallback} callback
   * @api public
   */
  Mask.PBM.url = function (url, callback) {
    var req = new XMLHttpRequest();
    req.responseType = "arraybuffer";
    req.onload = function (ev) {
      if (req.response) {
        return Mask.fromPBM(req.response, callback);
      } else {
        // No response.
        return callback(null, new Error("No response."));
      }
    };
    req.onerror = function (e) {
      return callback(null, e);
    };
    req.open("GET", url, true);
    req.send();
  };
  /** Create an object representing the intersection of the bounding
   * boxes of two objects.
   *
   * @api private
   */
  function intersection (a, b) {
    var a_2 = {x: a.x + a.w, y: a.y + a.h};
    var b_2 = {x: b.x + b.w, y: b.y + b.h};
    var overlap = {x: a.x > b.x ? a.x : b.x,
                   y: a.y > b.y ? a.y : b.y};
    overlap.w = (a_2.x < b_2.x ? a_2.x : b_2.x) - overlap.x;
    overlap.h = (a_2.y < b_2.y ? a_2.y : b_2.y) - overlap.y;
    return overlap;
  }
  /** Test whether two Masks collide.
   *
   * @param {Mask} a
   * @param {Mask} b
   * @api public
   */
  Mask.collision = function (a, b) {
    var intersect = intersection(a, b);
    for (var x = intersect.x; x < intersect.x + intersect.w; x++) {
      for (var y = intersect.y; y < intersect.y + intersect.h; y++) {
        if (a.collidesAt(x, y) &&
            b.collidesAt(x, y)) {
          return true;
        }
      }
    }
    return false;
  };
  /** Create a mask as an inversion of another.
   *
   * @constructor
   * @param {Mask} other
   * @api public
   */
  Mask.Invert = function (other) {
    this.x = other.x;
    this.y = other.y;
    this.w = other.w;
    this.h = other.h;
    this.inversion = other;
  };
  Mask.Invert.prototype = new Mask();
  Mask.Invert.prototype.collidesAt = function (x, y) {
    return !this.inversion.collidesAt(x, y);
  };
  /** Create a vector box mask.
   *
   * @constructor
   * @param {Number} w width
   * @param {Number} h height
   * @api public
   */
  Mask.Box = function (w, h) {
    this.x = 0;
    this.y = 0;
    this.w = w;
    this.h = h;
  };
  Mask.Box.prototype = new Mask();
  Mask.Box.prototype.clone = function () {
    var other = new Mask.Box(this.w, this.h);
    other.translate(this.x, this.y);
    return other;
  };
  Mask.Box.prototype.collidesAt = function (x, y) {
    return x >= this.x && y >= this.y &&
      x <= (this.x + this.w) && y <= (this.y + this.h);
  };
  /*!*/
  if (typeof module !== "undefined") {
    module.exports = { Mask: Mask };
  }
  return Mask;
})();
<|endoftext|>


<commit_before>var otazky = ["How old are you?",
	"Where do you live?",
	"What is your name?"
];

var odpovedi = Array();
odpovedi[1] = ["0--50", "50--100"];
odpovedi[2] = ["Europe", "USA", "Mars"];

$(function() {
	//Hlavicka (otazky)
	var row = $("<tr/>");
	$.each(otazky, function(index, value) {
		var cell = $("<th/>");
		cell.text(value);
		cell.appendTo(row);
	});
	$("table").append(row);

	// Odpovedi
	$.get("data.xml", function(xml) {
		//console.log(xml);
		//console.log($("VERZE", xml).text());

		var otazek = [];
		$("ODP", xml).each(function() {
			otazek.push(parseInt($(this).attr("POR")));
		});
		//console.log(otazek);	//Jeste pole
		otazek = otazek.sort(function(a, b) {return b - a})[0];
		//console.log(otazek);	//Pocet otazek

		//console.log($("PROCHAZEJICI", xml).length);	//Pocet pruchodu (vcetne prazdnych!)
		$("PROCHAZEJICI", xml).each(function() {
			var row = $("<tr/>");
			for (var i = 1; i <= otazek; i++) {
				//console.log(i, $("AKCE:last ODP[POR='" + i + "']", this));
				var odpovedi_arr = Array();
				$("AKCE:last ODP[POR='" + i + "']", this).each(function() {
					var odpoved = $(this).attr("HOD");
					if (odpovedi[i] && !isNaN(odpoved)) {
						odpovedi_arr.push(odpovedi[i][parseInt(odpoved) - 1]);
					} else {
						odpovedi_arr.push(odpoved);
					}
				});
				var cell = $("<td/>");
				cell.text(odpovedi_arr.join(", "))
				cell.appendTo(row);
			}
			if (row.text()) {	//Vyhodime prazdne odpovedi
				$("table").append(row);
			}
		});
	}, "xml");	//Format
});
<commit_msg>Prvni pokus o plugin<commit_after>(function($) {
	$.fn.munis = function() {
		//Hlavicka (otazky)
		var row = $("<tr/>");
		$.each(otazky, function(index, value) {
			var cell = $("<th/>");
			cell.text(value);
			cell.appendTo(row);
		});
		$("table").append(row);

		// Odpovedi
		$.get("data.xml", function(xml) {
			//console.log(xml);
			//console.log($("VERZE", xml).text());

			var otazek = [];
			$("ODP", xml).each(function() {
				otazek.push(parseInt($(this).attr("POR")));
			});
			//console.log(otazek);	//Jeste pole
			otazek = otazek.sort(function(a, b) {return b - a})[0];
			//console.log(otazek);	//Pocet otazek

			//console.log($("PROCHAZEJICI", xml).length);	//Pocet pruchodu (vcetne prazdnych!)
			$("PROCHAZEJICI", xml).each(function() {
				var row = $("<tr/>");
				for (var i = 1; i <= otazek; i++) {
					//console.log(i, $("AKCE:last ODP[POR='" + i + "']", this));
					var odpovedi_arr = Array();
					$("AKCE:last ODP[POR='" + i + "']", this).each(function() {
						var odpoved = $(this).attr("HOD");
						if (odpovedi[i] && !isNaN(odpoved)) {
							odpovedi_arr.push(odpovedi[i][parseInt(odpoved) - 1]);
						} else {
							odpovedi_arr.push(odpoved);
						}
					});
					var cell = $("<td/>");
					cell.text(odpovedi_arr.join(", "))
					cell.appendTo(row);
				}
				if (row.text()) {	//Vyhodime prazdne odpovedi
					$("table").append(row);
				}
			});
		}, "xml");	//Format
	};
})(jQuery);
<|endoftext|>


<commit_before>'use strict'
const Bluebird = require('bluebird')
const url = require('url')
const Site = use('site')
const cache = use('cache')
const moment = require('moment')

class ArchiveOfOurOwn extends Site {
  static matches (siteUrlStr) {
    const siteUrl = url.parse(siteUrlStr)
    const hostname = siteUrl.hostname
    if (!/(^|www[.])archiveofourown.org$/.test(hostname)) return false
    const path = siteUrl.pathname || siteUrl.path || ''
    if (!/^[/]works[/]\d+/.test(path)) return false
    return true
  }

  constructor (siteUrlStr) {
    super(siteUrlStr)
    this.link = this.link.replace(/[/]works[/](\d+).*?$/, '/works/$1')
    this.publisher = 'archiveofourown.org'
    this.publisherName = 'Archive of Our Own'
    const siteUrl = url.parse(siteUrlStr)
    const path = siteUrl.pathname || siteUrl.path || ''
    const ficMatch = path.match(/^[/]works[/](\d+)/)
    this.workId = ficMatch[1]
  }

  chapterIndex () {
    return 'https://archiveofourown.org/works/' + this.workId + '/navigate'
  }
  tagGroup ($, prefix, $dd) {
    const tags = []
    $dd.find('li').each((ii, vv) => {
      tags.push(prefix + ':' + $(vv).text().trim())
    })
    return tags
  }
  getFicMetadata (fetch, fic) {
    fic.link = this.link
    fic.publisher = this.publisherName
    fic.chapterHeadings = true
    return fetch(this.chapterIndex()).spread((meta, html) => {
      const cheerio = require('cheerio')
      const $ = cheerio.load(html)
      if ($('.error-503-maintenance').length) {
        const err = new Error($('#main').text().trim().split(/\n/).map(l => l.trim()).join('\n'))
        err.link = this.chapterIndex()
        err.code = 503
        err.site = this.publisherName
        return cache.clearUrl(err.link).then(() => {
          throw err
        })
      }
      const base = $('base').attr('href') || this.chapterIndex()
      const heading = $('h2.heading')
      fic.title = heading.find('a[rel!="author"]').text()
      const $author = heading.find('a[rel="author"]')
      fic.authorUrl = this.normalizeLink($author.attr('href'), base)
      fic.author = $author.text()
      const chapterList = $('ol.index').find('li')
      chapterList.each((ii, vv) => {
        const $vv = $(vv)
        const name = $vv.find('a').text().replace(/^\d+[.] /, '')
        const link = this.normalizeLink($vv.find('a').attr('href'), base)
        const created = moment.utc($vv.find('span.datetime').text(), '(YYYY-MM-DD)')
        fic.addChapter({name, link, created})
      })
      return fic.chapters[0].getContent(fetch)
    }).then(chapter => {
      if (chapter.$('.error-503-maintenance').length) {
        const err = new Error(chapter.$('#main').text().trim().split(/\n/).map(l => l.trim()).join('\n'))
        err.link = chapter.fetchWith()
        err.code = 503
        err.site = this.publisherName
        return cache.clearUrl(err.link).then(() => {
          throw err
        })
      }
      const $meta = chapter.$('dl.meta')
      const ratings = this.tagGroup(chapter.$, 'rating', $meta.find('dd.rating'))
      const warnings = this.tagGroup(chapter.$, 'warning', $meta.find('dd.warnings'))
        .filter(warn => !/No Archive Warnings Apply/.test(warn))
      const category = this.tagGroup(chapter.$, 'category', $meta.find('dd.category'))
      const fandom = this.tagGroup(chapter.$, 'fandom', $meta.find('dd.fandom'))
      const relationship = this.tagGroup(chapter.$, '', $meta.find('dd.relationship'))
        .filter(r => r !== ':Friendship - Relationship')
        .map(r => r.replace(/^:/, /[/]/.test(r) ? 'ship:' : 'friendship:'))
      const characters = this.tagGroup(chapter.$, 'character', $meta.find('dd.character'))
      const freeform = this.tagGroup(chapter.$, 'freeform', $meta.find('dd.freeform'))
      const language = 'language:' + $meta.find('dd.language').text().trim()
      fic.tags = [].concat(ratings, warnings, category, fandom, relationship, characters, freeform, language)
      const $stats = $meta.find('dl.stats')
      const chapterCounts = $stats.find('dd.chapters').text().trim().split('/')
      const written = chapterCounts[0]
      const planned = chapterCounts[1]
      if (written === planned) {
        if (written === '1') {
          fic.tags.push('status:one-shot')
        } else {
          fic.tags.push('status:complete')
        }
      }
      fic.created = moment.utc($stats.find('dd.published').text().trim())
      const modified = $stats.find('dd.status').text().trim()
      fic.modified = modified && moment.utc(modified)
      fic.words = Number($stats.find('dd.words').text().trim())
      fic.comments = Number($stats.find('dd.comments').text().trim())
      fic.kudos = Number($stats.find('dd.kudos').text().trim())
      fic.bookmarks = Number($stats.find('dd.bookmarks').text().trim())
      fic.hits = Number($stats.find('dd.hits').text().trim())
      fic.title = chapter.$('h2.title').text().trim()
      fic.description = (chapter.$('.summary').find('.userstuff').html() || '').replace(/<p>/g, '\n<p>').replace(/^\s+|\s+$/g, '')
    })
  }

  getChapter (fetch, chapterInfo) {
    return fetch(chapterInfo.fetchWith()).spread((meta, html) => {
      const ChapterContent = use('chapter-content')
      const chapter = new ChapterContent(chapterInfo, {html, site: this})
      if (chapter.$('.error-503-maintenance').length) {
        const err = new Error(chapter.$('#main').text().trim().split(/\n/).map(l => l.trim()).join('\n'))
        err.link = chapter.fetchWith()
        err.code = 503
        err.site = this.publisherName
        return cache.clearUrl(err.link).then(() => {
          throw err
        })
      }
      if (chapter.$('p.caution').length) {
        chapterInfo.fetchFrom = chapterInfo.fetchWith() + '?view_adult=true'
        return this.getChapter(fetch, chapterInfo)
      }
      chapter.base = chapter.$('base').attr('href') || meta.finalUrl
      if (meta.finalUrl !== chapter.link) {
        chapter.fetchFrom = chapter.link
        chapter.link = meta.finalUrl
      }
      const $content = chapter.$('div[role="article"]')
      $content.find('h3.landmark').remove()

      const notes = chapter.$('#notes').find('.userstuff').html()
      const endNotes = chapter.$('div.end').find('.userstuff').html()
      let content = ''
      if (notes && !/\(See the end of the chapter for.*notes.*.\)/.test(notes)) {
        content += `<aside style="border: solid black 1px; padding: 1em">${notes}</aside>`
      }
      content += $content.html()
      if (endNotes) content += `<aside epub:type="endnote" style="border: solid black 1px; padding: 1em">${endNotes}</aside>`
      chapter.content = content
      return chapter
    })
  }
}

module.exports = ArchiveOfOurOwn
<commit_msg>ao3: Strip anchors from normalized links<commit_after>'use strict'
const Bluebird = require('bluebird')
const url = require('url')
const Site = use('site')
const cache = use('cache')
const moment = require('moment')

class ArchiveOfOurOwn extends Site {
  static matches (siteUrlStr) {
    const siteUrl = url.parse(siteUrlStr)
    const hostname = siteUrl.hostname
    if (!/(^|www[.])archiveofourown.org$/.test(hostname)) return false
    const path = siteUrl.pathname || siteUrl.path || ''
    if (!/^[/]works[/]\d+/.test(path)) return false
    return true
  }

  constructor (siteUrlStr) {
    super(siteUrlStr)
    this.link = this.link.replace(/[/]works[/](\d+).*?$/, '/works/$1')
    this.publisher = 'archiveofourown.org'
    this.publisherName = 'Archive of Our Own'
    const siteUrl = url.parse(siteUrlStr)
    const path = siteUrl.pathname || siteUrl.path || ''
    const ficMatch = path.match(/^[/]works[/](\d+)/)
    this.workId = ficMatch[1]
  }

  normalizeLink (href, base) {
    return super.normalizeLink(href, base).replace(/#.*$/, '')
  }
  chapterIndex () {
    return 'https://archiveofourown.org/works/' + this.workId + '/navigate'
  }
  tagGroup ($, prefix, $dd) {
    const tags = []
    $dd.find('li').each((ii, vv) => {
      tags.push(prefix + ':' + $(vv).text().trim())
    })
    return tags
  }
  getFicMetadata (fetch, fic) {
    fic.link = this.link
    fic.publisher = this.publisherName
    fic.chapterHeadings = true
    return fetch(this.chapterIndex()).spread((meta, html) => {
      const cheerio = require('cheerio')
      const $ = cheerio.load(html)
      if ($('.error-503-maintenance').length) {
        const err = new Error($('#main').text().trim().split(/\n/).map(l => l.trim()).join('\n'))
        err.link = this.chapterIndex()
        err.code = 503
        err.site = this.publisherName
        return cache.clearUrl(err.link).then(() => {
          throw err
        })
      }
      const base = $('base').attr('href') || this.chapterIndex()
      const heading = $('h2.heading')
      fic.title = heading.find('a[rel!="author"]').text()
      const $author = heading.find('a[rel="author"]')
      fic.authorUrl = this.normalizeLink($author.attr('href'), base)
      fic.author = $author.text()
      const chapterList = $('ol.index').find('li')
      chapterList.each((ii, vv) => {
        const $vv = $(vv)
        const name = $vv.find('a').text().replace(/^\d+[.] /, '')
        const link = this.normalizeLink($vv.find('a').attr('href'), base)
        const created = moment.utc($vv.find('span.datetime').text(), '(YYYY-MM-DD)')
        fic.addChapter({name, link, created})
      })
      return fic.chapters[0].getContent(fetch)
    }).then(chapter => {
      if (chapter.$('.error-503-maintenance').length) {
        const err = new Error(chapter.$('#main').text().trim().split(/\n/).map(l => l.trim()).join('\n'))
        err.link = chapter.fetchWith()
        err.code = 503
        err.site = this.publisherName
        return cache.clearUrl(err.link).then(() => {
          throw err
        })
      }
      const $meta = chapter.$('dl.meta')
      const ratings = this.tagGroup(chapter.$, 'rating', $meta.find('dd.rating'))
      const warnings = this.tagGroup(chapter.$, 'warning', $meta.find('dd.warnings'))
        .filter(warn => !/No Archive Warnings Apply/.test(warn))
      const category = this.tagGroup(chapter.$, 'category', $meta.find('dd.category'))
      const fandom = this.tagGroup(chapter.$, 'fandom', $meta.find('dd.fandom'))
      const relationship = this.tagGroup(chapter.$, '', $meta.find('dd.relationship'))
        .filter(r => r !== ':Friendship - Relationship')
        .map(r => r.replace(/^:/, /[/]/.test(r) ? 'ship:' : 'friendship:'))
      const characters = this.tagGroup(chapter.$, 'character', $meta.find('dd.character'))
      const freeform = this.tagGroup(chapter.$, 'freeform', $meta.find('dd.freeform'))
      const language = 'language:' + $meta.find('dd.language').text().trim()
      fic.tags = [].concat(ratings, warnings, category, fandom, relationship, characters, freeform, language)
      const $stats = $meta.find('dl.stats')
      const chapterCounts = $stats.find('dd.chapters').text().trim().split('/')
      const written = chapterCounts[0]
      const planned = chapterCounts[1]
      if (written === planned) {
        if (written === '1') {
          fic.tags.push('status:one-shot')
        } else {
          fic.tags.push('status:complete')
        }
      }
      fic.created = moment.utc($stats.find('dd.published').text().trim())
      const modified = $stats.find('dd.status').text().trim()
      fic.modified = modified && moment.utc(modified)
      fic.words = Number($stats.find('dd.words').text().trim())
      fic.comments = Number($stats.find('dd.comments').text().trim())
      fic.kudos = Number($stats.find('dd.kudos').text().trim())
      fic.bookmarks = Number($stats.find('dd.bookmarks').text().trim())
      fic.hits = Number($stats.find('dd.hits').text().trim())
      fic.title = chapter.$('h2.title').text().trim()
      fic.description = (chapter.$('.summary').find('.userstuff').html() || '').replace(/<p>/g, '\n<p>').replace(/^\s+|\s+$/g, '')
    })
  }

  getChapter (fetch, chapterInfo) {
    return fetch(chapterInfo.fetchWith()).spread((meta, html) => {
      const ChapterContent = use('chapter-content')
      const chapter = new ChapterContent(chapterInfo, {html, site: this})
      if (chapter.$('.error-503-maintenance').length) {
        const err = new Error(chapter.$('#main').text().trim().split(/\n/).map(l => l.trim()).join('\n'))
        err.link = chapter.fetchWith()
        err.code = 503
        err.site = this.publisherName
        return cache.clearUrl(err.link).then(() => {
          throw err
        })
      }
      if (chapter.$('p.caution').length) {
        chapterInfo.fetchFrom = chapterInfo.fetchWith() + '?view_adult=true'
        return this.getChapter(fetch, chapterInfo)
      }
      chapter.base = chapter.$('base').attr('href') || meta.finalUrl
      if (meta.finalUrl !== chapter.link) {
        chapter.fetchFrom = chapter.link
        chapter.link = meta.finalUrl
      }
      const $content = chapter.$('div[role="article"]')
      $content.find('h3.landmark').remove()

      const notes = chapter.$('#notes').find('.userstuff').html()
      const endNotes = chapter.$('div.end').find('.userstuff').html()
      let content = ''
      if (notes && !/\(See the end of the chapter for.*notes.*.\)/.test(notes)) {
        content += `<aside style="border: solid black 1px; padding: 1em">${notes}</aside>`
      }
      content += $content.html()
      if (endNotes) content += `<aside epub:type="endnote" style="border: solid black 1px; padding: 1em">${endNotes}</aside>`
      chapter.content = content
      return chapter
    })
  }
}

module.exports = ArchiveOfOurOwn
<|endoftext|>


<commit_before>import Bacon from 'baconjs'
import R from 'ramda'
import colors from 'colors'

let debug = require('debug')('tutum-tagger')

let isSuccessOrFailed = R.contains(R.__, ['Running', 'Stopped'])
let isSuccess = R.equals('Running')
let isStarting = R.equals('Starting')

export default function startServiceOrTakeRunning(service, tutum, tutumStream) {
  return Bacon.once(service)
    .flatMap((service) => {
      if (isStarting(service.state)) {
        debug(`Service ${service.resource_uri.cyan} is starting already.`)

        return service
      }

      debug(`Starting service ${service.resource_uri.cyan}.`)

      return startService(service, tutum)
    })
    .flatMap((service) => getServiceStartFinished(service, tutumStream))
}

function startService(service, tutum) {
  return Bacon.fromPromise(tutum.startService({
    uri: service.resource_uri
  }))
}

function getServiceStartFinished(service, tutumStream) {
  return tutumStream
    .filter((event) => event.resource_uri == service.resource_uri)
    .doAction((event) => debug(`Got an event for ${event.resource_uri.cyan} and state ${event.state.cyan}.`))
    .filter((event) => isSuccessOrFailed(event.state))
    .flatMap((event) => Bacon.once(isSuccess(event.state)))
    .doAction((isSuccessful) => debug(`Service start ${isSuccessful ? 'is'.green : 'is not'.red} successful.`))
    .first()
}
<commit_msg>Add the missing "Redeploying" state to handle autoredeploy<commit_after>import Bacon from 'baconjs'
import R from 'ramda'
import colors from 'colors'

let debug = require('debug')('tutum-tagger')

let isSuccessOrFailed = R.contains(R.__, ['Running', 'Stopped'])
let isSuccess = R.equals('Running')
let isStarting = R.contains(R.__, ['Starting', 'Redeploying'])

export default function startServiceOrTakeRunning(service, tutum, tutumStream) {
  return Bacon.once(service)
    .flatMap((service) => {
      if (isStarting(service.state)) {
        debug(`Service ${service.resource_uri.cyan} is starting already.`)

        return service
      }

      debug(`Starting service ${service.resource_uri.cyan}.`)

      return startService(service, tutum)
    })
    .flatMap((service) => getServiceStartFinished(service, tutumStream))
}

function startService(service, tutum) {
  return Bacon.fromPromise(tutum.startService({
    uri: service.resource_uri
  }))
}

function getServiceStartFinished(service, tutumStream) {
  return tutumStream
    .filter((event) => event.resource_uri == service.resource_uri)
    .doAction((event) => debug(`Got an event for ${event.resource_uri.cyan} and state ${event.state.cyan}.`))
    .filter((event) => isSuccessOrFailed(event.state))
    .flatMap((event) => Bacon.once(isSuccess(event.state)))
    .doAction((isSuccessful) => debug(`Service start ${isSuccessful ? 'is'.green : 'is not'.red} successful.`))
    .first()
}
<|endoftext|>