diff --git a/public/index.html b/public/index.html
index 57b289d..3be7906 100644
--- a/public/index.html
+++ b/public/index.html
@@ -6,6 +6,7 @@
+
diff --git a/public/scripts/functions.js b/public/scripts/functions.js
index bc09b87..c2a0936 100644
--- a/public/scripts/functions.js
+++ b/public/scripts/functions.js
@@ -111,14 +111,21 @@ function populateBoard(){
var listBoard = document.getElementById("listBoard");
var results = "";
var rankings = data.data.rankings;
+ var date = new Date();
+ var seconds = date.getSeconds();
+ var minutes = date.getMinutes();
+ var hour = date.getHours();
+
for (var i = rankings.length - 1; i >= 0; i--) {
if( rankings[i].teamId == 235 ){
+ results += "Updated "+hour+"h "+minutes+"m "+seconds+"s
";
results += "Cazziammolla Placement: "+rankings[i].rank+"
";
results += "with a score of: "+rankings[i].score+"
";
if (rankings[i].rank != points && points != 0){
- score = rankings[i].rank;
ringTheBell();
}
+ points = rankings[i].rank;
+
}
};
@@ -137,6 +144,8 @@ function populateBoard(){
}
function updateLeaderBoard(){
+ loadRankingJs('https://davar.icfpcontest.org/rankings.js?cachebuster='+ new Date().getTime());
+
var intervalID = setInterval( function(){
loadRankingJs('https://davar.icfpcontest.org/rankings.js?cachebuster='+ new Date().getTime());
}, 30000);
diff --git a/public/scripts/html2canvas.js b/public/scripts/html2canvas.js
new file mode 100644
index 0000000..0bf5d25
--- /dev/null
+++ b/public/scripts/html2canvas.js
@@ -0,0 +1,4519 @@
+/*
+ html2canvas 0.5.0-alpha2
+ Copyright (c) 2015 Niklas von Hertzen
+
+ Released under MIT License
+*/
+
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.html2canvas=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) {
+ throw new Error('Second argument not supported');
+ }
+ if (typeof o !== 'object') {
+ throw new TypeError('Argument must be an object');
+ }
+ $$utils$$F.prototype = o;
+ return new $$utils$$F();
+ });
+
+ var $$asap$$len = 0;
+
+ var $$asap$$default = function asap(callback, arg) {
+ $$asap$$queue[$$asap$$len] = callback;
+ $$asap$$queue[$$asap$$len + 1] = arg;
+ $$asap$$len += 2;
+ if ($$asap$$len === 2) {
+ // If len is 1, that means that we need to schedule an async flush.
+ // If additional callbacks are queued before the queue is flushed, they
+ // will be processed by this flush that we are scheduling.
+ $$asap$$scheduleFlush();
+ }
+ };
+
+ var $$asap$$browserGlobal = (typeof window !== 'undefined') ? window : {};
+ var $$asap$$BrowserMutationObserver = $$asap$$browserGlobal.MutationObserver || $$asap$$browserGlobal.WebKitMutationObserver;
+
+ // test for web worker but not in IE10
+ var $$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&
+ typeof importScripts !== 'undefined' &&
+ typeof MessageChannel !== 'undefined';
+
+ // node
+ function $$asap$$useNextTick() {
+ return function() {
+ process.nextTick($$asap$$flush);
+ };
+ }
+
+ function $$asap$$useMutationObserver() {
+ var iterations = 0;
+ var observer = new $$asap$$BrowserMutationObserver($$asap$$flush);
+ var node = document.createTextNode('');
+ observer.observe(node, { characterData: true });
+
+ return function() {
+ node.data = (iterations = ++iterations % 2);
+ };
+ }
+
+ // web worker
+ function $$asap$$useMessageChannel() {
+ var channel = new MessageChannel();
+ channel.port1.onmessage = $$asap$$flush;
+ return function () {
+ channel.port2.postMessage(0);
+ };
+ }
+
+ function $$asap$$useSetTimeout() {
+ return function() {
+ setTimeout($$asap$$flush, 1);
+ };
+ }
+
+ var $$asap$$queue = new Array(1000);
+
+ function $$asap$$flush() {
+ for (var i = 0; i < $$asap$$len; i+=2) {
+ var callback = $$asap$$queue[i];
+ var arg = $$asap$$queue[i+1];
+
+ callback(arg);
+
+ $$asap$$queue[i] = undefined;
+ $$asap$$queue[i+1] = undefined;
+ }
+
+ $$asap$$len = 0;
+ }
+
+ var $$asap$$scheduleFlush;
+
+ // Decide what async method to use to triggering processing of queued callbacks:
+ if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
+ $$asap$$scheduleFlush = $$asap$$useNextTick();
+ } else if ($$asap$$BrowserMutationObserver) {
+ $$asap$$scheduleFlush = $$asap$$useMutationObserver();
+ } else if ($$asap$$isWorker) {
+ $$asap$$scheduleFlush = $$asap$$useMessageChannel();
+ } else {
+ $$asap$$scheduleFlush = $$asap$$useSetTimeout();
+ }
+
+ function $$$internal$$noop() {}
+ var $$$internal$$PENDING = void 0;
+ var $$$internal$$FULFILLED = 1;
+ var $$$internal$$REJECTED = 2;
+ var $$$internal$$GET_THEN_ERROR = new $$$internal$$ErrorObject();
+
+ function $$$internal$$selfFullfillment() {
+ return new TypeError("You cannot resolve a promise with itself");
+ }
+
+ function $$$internal$$cannotReturnOwn() {
+ return new TypeError('A promises callback cannot return that same promise.')
+ }
+
+ function $$$internal$$getThen(promise) {
+ try {
+ return promise.then;
+ } catch(error) {
+ $$$internal$$GET_THEN_ERROR.error = error;
+ return $$$internal$$GET_THEN_ERROR;
+ }
+ }
+
+ function $$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) {
+ try {
+ then.call(value, fulfillmentHandler, rejectionHandler);
+ } catch(e) {
+ return e;
+ }
+ }
+
+ function $$$internal$$handleForeignThenable(promise, thenable, then) {
+ $$asap$$default(function(promise) {
+ var sealed = false;
+ var error = $$$internal$$tryThen(then, thenable, function(value) {
+ if (sealed) { return; }
+ sealed = true;
+ if (thenable !== value) {
+ $$$internal$$resolve(promise, value);
+ } else {
+ $$$internal$$fulfill(promise, value);
+ }
+ }, function(reason) {
+ if (sealed) { return; }
+ sealed = true;
+
+ $$$internal$$reject(promise, reason);
+ }, 'Settle: ' + (promise._label || ' unknown promise'));
+
+ if (!sealed && error) {
+ sealed = true;
+ $$$internal$$reject(promise, error);
+ }
+ }, promise);
+ }
+
+ function $$$internal$$handleOwnThenable(promise, thenable) {
+ if (thenable._state === $$$internal$$FULFILLED) {
+ $$$internal$$fulfill(promise, thenable._result);
+ } else if (promise._state === $$$internal$$REJECTED) {
+ $$$internal$$reject(promise, thenable._result);
+ } else {
+ $$$internal$$subscribe(thenable, undefined, function(value) {
+ $$$internal$$resolve(promise, value);
+ }, function(reason) {
+ $$$internal$$reject(promise, reason);
+ });
+ }
+ }
+
+ function $$$internal$$handleMaybeThenable(promise, maybeThenable) {
+ if (maybeThenable.constructor === promise.constructor) {
+ $$$internal$$handleOwnThenable(promise, maybeThenable);
+ } else {
+ var then = $$$internal$$getThen(maybeThenable);
+
+ if (then === $$$internal$$GET_THEN_ERROR) {
+ $$$internal$$reject(promise, $$$internal$$GET_THEN_ERROR.error);
+ } else if (then === undefined) {
+ $$$internal$$fulfill(promise, maybeThenable);
+ } else if ($$utils$$isFunction(then)) {
+ $$$internal$$handleForeignThenable(promise, maybeThenable, then);
+ } else {
+ $$$internal$$fulfill(promise, maybeThenable);
+ }
+ }
+ }
+
+ function $$$internal$$resolve(promise, value) {
+ if (promise === value) {
+ $$$internal$$reject(promise, $$$internal$$selfFullfillment());
+ } else if ($$utils$$objectOrFunction(value)) {
+ $$$internal$$handleMaybeThenable(promise, value);
+ } else {
+ $$$internal$$fulfill(promise, value);
+ }
+ }
+
+ function $$$internal$$publishRejection(promise) {
+ if (promise._onerror) {
+ promise._onerror(promise._result);
+ }
+
+ $$$internal$$publish(promise);
+ }
+
+ function $$$internal$$fulfill(promise, value) {
+ if (promise._state !== $$$internal$$PENDING) { return; }
+
+ promise._result = value;
+ promise._state = $$$internal$$FULFILLED;
+
+ if (promise._subscribers.length === 0) {
+ } else {
+ $$asap$$default($$$internal$$publish, promise);
+ }
+ }
+
+ function $$$internal$$reject(promise, reason) {
+ if (promise._state !== $$$internal$$PENDING) { return; }
+ promise._state = $$$internal$$REJECTED;
+ promise._result = reason;
+
+ $$asap$$default($$$internal$$publishRejection, promise);
+ }
+
+ function $$$internal$$subscribe(parent, child, onFulfillment, onRejection) {
+ var subscribers = parent._subscribers;
+ var length = subscribers.length;
+
+ parent._onerror = null;
+
+ subscribers[length] = child;
+ subscribers[length + $$$internal$$FULFILLED] = onFulfillment;
+ subscribers[length + $$$internal$$REJECTED] = onRejection;
+
+ if (length === 0 && parent._state) {
+ $$asap$$default($$$internal$$publish, parent);
+ }
+ }
+
+ function $$$internal$$publish(promise) {
+ var subscribers = promise._subscribers;
+ var settled = promise._state;
+
+ if (subscribers.length === 0) { return; }
+
+ var child, callback, detail = promise._result;
+
+ for (var i = 0; i < subscribers.length; i += 3) {
+ child = subscribers[i];
+ callback = subscribers[i + settled];
+
+ if (child) {
+ $$$internal$$invokeCallback(settled, child, callback, detail);
+ } else {
+ callback(detail);
+ }
+ }
+
+ promise._subscribers.length = 0;
+ }
+
+ function $$$internal$$ErrorObject() {
+ this.error = null;
+ }
+
+ var $$$internal$$TRY_CATCH_ERROR = new $$$internal$$ErrorObject();
+
+ function $$$internal$$tryCatch(callback, detail) {
+ try {
+ return callback(detail);
+ } catch(e) {
+ $$$internal$$TRY_CATCH_ERROR.error = e;
+ return $$$internal$$TRY_CATCH_ERROR;
+ }
+ }
+
+ function $$$internal$$invokeCallback(settled, promise, callback, detail) {
+ var hasCallback = $$utils$$isFunction(callback),
+ value, error, succeeded, failed;
+
+ if (hasCallback) {
+ value = $$$internal$$tryCatch(callback, detail);
+
+ if (value === $$$internal$$TRY_CATCH_ERROR) {
+ failed = true;
+ error = value.error;
+ value = null;
+ } else {
+ succeeded = true;
+ }
+
+ if (promise === value) {
+ $$$internal$$reject(promise, $$$internal$$cannotReturnOwn());
+ return;
+ }
+
+ } else {
+ value = detail;
+ succeeded = true;
+ }
+
+ if (promise._state !== $$$internal$$PENDING) {
+ // noop
+ } else if (hasCallback && succeeded) {
+ $$$internal$$resolve(promise, value);
+ } else if (failed) {
+ $$$internal$$reject(promise, error);
+ } else if (settled === $$$internal$$FULFILLED) {
+ $$$internal$$fulfill(promise, value);
+ } else if (settled === $$$internal$$REJECTED) {
+ $$$internal$$reject(promise, value);
+ }
+ }
+
+ function $$$internal$$initializePromise(promise, resolver) {
+ try {
+ resolver(function resolvePromise(value){
+ $$$internal$$resolve(promise, value);
+ }, function rejectPromise(reason) {
+ $$$internal$$reject(promise, reason);
+ });
+ } catch(e) {
+ $$$internal$$reject(promise, e);
+ }
+ }
+
+ function $$$enumerator$$makeSettledResult(state, position, value) {
+ if (state === $$$internal$$FULFILLED) {
+ return {
+ state: 'fulfilled',
+ value: value
+ };
+ } else {
+ return {
+ state: 'rejected',
+ reason: value
+ };
+ }
+ }
+
+ function $$$enumerator$$Enumerator(Constructor, input, abortOnReject, label) {
+ this._instanceConstructor = Constructor;
+ this.promise = new Constructor($$$internal$$noop, label);
+ this._abortOnReject = abortOnReject;
+
+ if (this._validateInput(input)) {
+ this._input = input;
+ this.length = input.length;
+ this._remaining = input.length;
+
+ this._init();
+
+ if (this.length === 0) {
+ $$$internal$$fulfill(this.promise, this._result);
+ } else {
+ this.length = this.length || 0;
+ this._enumerate();
+ if (this._remaining === 0) {
+ $$$internal$$fulfill(this.promise, this._result);
+ }
+ }
+ } else {
+ $$$internal$$reject(this.promise, this._validationError());
+ }
+ }
+
+ $$$enumerator$$Enumerator.prototype._validateInput = function(input) {
+ return $$utils$$isArray(input);
+ };
+
+ $$$enumerator$$Enumerator.prototype._validationError = function() {
+ return new Error('Array Methods must be provided an Array');
+ };
+
+ $$$enumerator$$Enumerator.prototype._init = function() {
+ this._result = new Array(this.length);
+ };
+
+ var $$$enumerator$$default = $$$enumerator$$Enumerator;
+
+ $$$enumerator$$Enumerator.prototype._enumerate = function() {
+ var length = this.length;
+ var promise = this.promise;
+ var input = this._input;
+
+ for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) {
+ this._eachEntry(input[i], i);
+ }
+ };
+
+ $$$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) {
+ var c = this._instanceConstructor;
+ if ($$utils$$isMaybeThenable(entry)) {
+ if (entry.constructor === c && entry._state !== $$$internal$$PENDING) {
+ entry._onerror = null;
+ this._settledAt(entry._state, i, entry._result);
+ } else {
+ this._willSettleAt(c.resolve(entry), i);
+ }
+ } else {
+ this._remaining--;
+ this._result[i] = this._makeResult($$$internal$$FULFILLED, i, entry);
+ }
+ };
+
+ $$$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) {
+ var promise = this.promise;
+
+ if (promise._state === $$$internal$$PENDING) {
+ this._remaining--;
+
+ if (this._abortOnReject && state === $$$internal$$REJECTED) {
+ $$$internal$$reject(promise, value);
+ } else {
+ this._result[i] = this._makeResult(state, i, value);
+ }
+ }
+
+ if (this._remaining === 0) {
+ $$$internal$$fulfill(promise, this._result);
+ }
+ };
+
+ $$$enumerator$$Enumerator.prototype._makeResult = function(state, i, value) {
+ return value;
+ };
+
+ $$$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) {
+ var enumerator = this;
+
+ $$$internal$$subscribe(promise, undefined, function(value) {
+ enumerator._settledAt($$$internal$$FULFILLED, i, value);
+ }, function(reason) {
+ enumerator._settledAt($$$internal$$REJECTED, i, reason);
+ });
+ };
+
+ var $$promise$all$$default = function all(entries, label) {
+ return new $$$enumerator$$default(this, entries, true /* abort on reject */, label).promise;
+ };
+
+ var $$promise$race$$default = function race(entries, label) {
+ /*jshint validthis:true */
+ var Constructor = this;
+
+ var promise = new Constructor($$$internal$$noop, label);
+
+ if (!$$utils$$isArray(entries)) {
+ $$$internal$$reject(promise, new TypeError('You must pass an array to race.'));
+ return promise;
+ }
+
+ var length = entries.length;
+
+ function onFulfillment(value) {
+ $$$internal$$resolve(promise, value);
+ }
+
+ function onRejection(reason) {
+ $$$internal$$reject(promise, reason);
+ }
+
+ for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) {
+ $$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
+ }
+
+ return promise;
+ };
+
+ var $$promise$resolve$$default = function resolve(object, label) {
+ /*jshint validthis:true */
+ var Constructor = this;
+
+ if (object && typeof object === 'object' && object.constructor === Constructor) {
+ return object;
+ }
+
+ var promise = new Constructor($$$internal$$noop, label);
+ $$$internal$$resolve(promise, object);
+ return promise;
+ };
+
+ var $$promise$reject$$default = function reject(reason, label) {
+ /*jshint validthis:true */
+ var Constructor = this;
+ var promise = new Constructor($$$internal$$noop, label);
+ $$$internal$$reject(promise, reason);
+ return promise;
+ };
+
+ var $$es6$promise$promise$$counter = 0;
+
+ function $$es6$promise$promise$$needsResolver() {
+ throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
+ }
+
+ function $$es6$promise$promise$$needsNew() {
+ throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
+ }
+
+ var $$es6$promise$promise$$default = $$es6$promise$promise$$Promise;
+
+ /**
+ Promise objects represent the eventual result of an asynchronous operation. The
+ primary way of interacting with a promise is through its `then` method, which
+ registers callbacks to receive either a promise’s eventual value or the reason
+ why the promise cannot be fulfilled.
+
+ Terminology
+ -----------
+
+ - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
+ - `thenable` is an object or function that defines a `then` method.
+ - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
+ - `exception` is a value that is thrown using the throw statement.
+ - `reason` is a value that indicates why a promise was rejected.
+ - `settled` the final resting state of a promise, fulfilled or rejected.
+
+ A promise can be in one of three states: pending, fulfilled, or rejected.
+
+ Promises that are fulfilled have a fulfillment value and are in the fulfilled
+ state. Promises that are rejected have a rejection reason and are in the
+ rejected state. A fulfillment value is never a thenable.
+
+ Promises can also be said to *resolve* a value. If this value is also a
+ promise, then the original promise's settled state will match the value's
+ settled state. So a promise that *resolves* a promise that rejects will
+ itself reject, and a promise that *resolves* a promise that fulfills will
+ itself fulfill.
+
+
+ Basic Usage:
+ ------------
+
+ ```js
+ var promise = new Promise(function(resolve, reject) {
+ // on success
+ resolve(value);
+
+ // on failure
+ reject(reason);
+ });
+
+ promise.then(function(value) {
+ // on fulfillment
+ }, function(reason) {
+ // on rejection
+ });
+ ```
+
+ Advanced Usage:
+ ---------------
+
+ Promises shine when abstracting away asynchronous interactions such as
+ `XMLHttpRequest`s.
+
+ ```js
+ function getJSON(url) {
+ return new Promise(function(resolve, reject){
+ var xhr = new XMLHttpRequest();
+
+ xhr.open('GET', url);
+ xhr.onreadystatechange = handler;
+ xhr.responseType = 'json';
+ xhr.setRequestHeader('Accept', 'application/json');
+ xhr.send();
+
+ function handler() {
+ if (this.readyState === this.DONE) {
+ if (this.status === 200) {
+ resolve(this.response);
+ } else {
+ reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
+ }
+ }
+ };
+ });
+ }
+
+ getJSON('/posts.json').then(function(json) {
+ // on fulfillment
+ }, function(reason) {
+ // on rejection
+ });
+ ```
+
+ Unlike callbacks, promises are great composable primitives.
+
+ ```js
+ Promise.all([
+ getJSON('/posts'),
+ getJSON('/comments')
+ ]).then(function(values){
+ values[0] // => postsJSON
+ values[1] // => commentsJSON
+
+ return values;
+ });
+ ```
+
+ @class Promise
+ @param {function} resolver
+ Useful for tooling.
+ @constructor
+ */
+ function $$es6$promise$promise$$Promise(resolver) {
+ this._id = $$es6$promise$promise$$counter++;
+ this._state = undefined;
+ this._result = undefined;
+ this._subscribers = [];
+
+ if ($$$internal$$noop !== resolver) {
+ if (!$$utils$$isFunction(resolver)) {
+ $$es6$promise$promise$$needsResolver();
+ }
+
+ if (!(this instanceof $$es6$promise$promise$$Promise)) {
+ $$es6$promise$promise$$needsNew();
+ }
+
+ $$$internal$$initializePromise(this, resolver);
+ }
+ }
+
+ $$es6$promise$promise$$Promise.all = $$promise$all$$default;
+ $$es6$promise$promise$$Promise.race = $$promise$race$$default;
+ $$es6$promise$promise$$Promise.resolve = $$promise$resolve$$default;
+ $$es6$promise$promise$$Promise.reject = $$promise$reject$$default;
+
+ $$es6$promise$promise$$Promise.prototype = {
+ constructor: $$es6$promise$promise$$Promise,
+
+ /**
+ The primary way of interacting with a promise is through its `then` method,
+ which registers callbacks to receive either a promise's eventual value or the
+ reason why the promise cannot be fulfilled.
+
+ ```js
+ findUser().then(function(user){
+ // user is available
+ }, function(reason){
+ // user is unavailable, and you are given the reason why
+ });
+ ```
+
+ Chaining
+ --------
+
+ The return value of `then` is itself a promise. This second, 'downstream'
+ promise is resolved with the return value of the first promise's fulfillment
+ or rejection handler, or rejected if the handler throws an exception.
+
+ ```js
+ findUser().then(function (user) {
+ return user.name;
+ }, function (reason) {
+ return 'default name';
+ }).then(function (userName) {
+ // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
+ // will be `'default name'`
+ });
+
+ findUser().then(function (user) {
+ throw new Error('Found user, but still unhappy');
+ }, function (reason) {
+ throw new Error('`findUser` rejected and we're unhappy');
+ }).then(function (value) {
+ // never reached
+ }, function (reason) {
+ // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
+ // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
+ });
+ ```
+ If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
+
+ ```js
+ findUser().then(function (user) {
+ throw new PedagogicalException('Upstream error');
+ }).then(function (value) {
+ // never reached
+ }).then(function (value) {
+ // never reached
+ }, function (reason) {
+ // The `PedgagocialException` is propagated all the way down to here
+ });
+ ```
+
+ Assimilation
+ ------------
+
+ Sometimes the value you want to propagate to a downstream promise can only be
+ retrieved asynchronously. This can be achieved by returning a promise in the
+ fulfillment or rejection handler. The downstream promise will then be pending
+ until the returned promise is settled. This is called *assimilation*.
+
+ ```js
+ findUser().then(function (user) {
+ return findCommentsByAuthor(user);
+ }).then(function (comments) {
+ // The user's comments are now available
+ });
+ ```
+
+ If the assimliated promise rejects, then the downstream promise will also reject.
+
+ ```js
+ findUser().then(function (user) {
+ return findCommentsByAuthor(user);
+ }).then(function (comments) {
+ // If `findCommentsByAuthor` fulfills, we'll have the value here
+ }, function (reason) {
+ // If `findCommentsByAuthor` rejects, we'll have the reason here
+ });
+ ```
+
+ Simple Example
+ --------------
+
+ Synchronous Example
+
+ ```javascript
+ var result;
+
+ try {
+ result = findResult();
+ // success
+ } catch(reason) {
+ // failure
+ }
+ ```
+
+ Errback Example
+
+ ```js
+ findResult(function(result, err){
+ if (err) {
+ // failure
+ } else {
+ // success
+ }
+ });
+ ```
+
+ Promise Example;
+
+ ```javascript
+ findResult().then(function(result){
+ // success
+ }, function(reason){
+ // failure
+ });
+ ```
+
+ Advanced Example
+ --------------
+
+ Synchronous Example
+
+ ```javascript
+ var author, books;
+
+ try {
+ author = findAuthor();
+ books = findBooksByAuthor(author);
+ // success
+ } catch(reason) {
+ // failure
+ }
+ ```
+
+ Errback Example
+
+ ```js
+
+ function foundBooks(books) {
+
+ }
+
+ function failure(reason) {
+
+ }
+
+ findAuthor(function(author, err){
+ if (err) {
+ failure(err);
+ // failure
+ } else {
+ try {
+ findBoooksByAuthor(author, function(books, err) {
+ if (err) {
+ failure(err);
+ } else {
+ try {
+ foundBooks(books);
+ } catch(reason) {
+ failure(reason);
+ }
+ }
+ });
+ } catch(error) {
+ failure(err);
+ }
+ // success
+ }
+ });
+ ```
+
+ Promise Example;
+
+ ```javascript
+ findAuthor().
+ then(findBooksByAuthor).
+ then(function(books){
+ // found books
+ }).catch(function(reason){
+ // something went wrong
+ });
+ ```
+
+ @method then
+ @param {Function} onFulfilled
+ @param {Function} onRejected
+ Useful for tooling.
+ @return {Promise}
+ */
+ then: function(onFulfillment, onRejection) {
+ var parent = this;
+ var state = parent._state;
+
+ if (state === $$$internal$$FULFILLED && !onFulfillment || state === $$$internal$$REJECTED && !onRejection) {
+ return this;
+ }
+
+ var child = new this.constructor($$$internal$$noop);
+ var result = parent._result;
+
+ if (state) {
+ var callback = arguments[state - 1];
+ $$asap$$default(function(){
+ $$$internal$$invokeCallback(state, child, callback, result);
+ });
+ } else {
+ $$$internal$$subscribe(parent, child, onFulfillment, onRejection);
+ }
+
+ return child;
+ },
+
+ /**
+ `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
+ as the catch block of a try/catch statement.
+
+ ```js
+ function findAuthor(){
+ throw new Error('couldn't find that author');
+ }
+
+ // synchronous
+ try {
+ findAuthor();
+ } catch(reason) {
+ // something went wrong
+ }
+
+ // async with promises
+ findAuthor().catch(function(reason){
+ // something went wrong
+ });
+ ```
+
+ @method catch
+ @param {Function} onRejection
+ Useful for tooling.
+ @return {Promise}
+ */
+ 'catch': function(onRejection) {
+ return this.then(null, onRejection);
+ }
+ };
+
+ var $$es6$promise$polyfill$$default = function polyfill() {
+ var local;
+
+ if (typeof global !== 'undefined') {
+ local = global;
+ } else if (typeof window !== 'undefined' && window.document) {
+ local = window;
+ } else {
+ local = self;
+ }
+
+ var es6PromiseSupport =
+ "Promise" in local &&
+ // Some of these methods are missing from
+ // Firefox/Chrome experimental implementations
+ "resolve" in local.Promise &&
+ "reject" in local.Promise &&
+ "all" in local.Promise &&
+ "race" in local.Promise &&
+ // Older version of the spec had a resolver object
+ // as the arg rather than a function
+ (function() {
+ var resolve;
+ new local.Promise(function(r) { resolve = r; });
+ return $$utils$$isFunction(resolve);
+ }());
+
+ if (!es6PromiseSupport) {
+ local.Promise = $$es6$promise$promise$$default;
+ }
+ };
+
+ var es6$promise$umd$$ES6Promise = {
+ 'Promise': $$es6$promise$promise$$default,
+ 'polyfill': $$es6$promise$polyfill$$default
+ };
+
+ /* global define:true module:true window: true */
+ if (typeof define === 'function' && define['amd']) {
+ define(function() { return es6$promise$umd$$ES6Promise; });
+ } else if (typeof module !== 'undefined' && module['exports']) {
+ module['exports'] = es6$promise$umd$$ES6Promise;
+ } else if (typeof this !== 'undefined') {
+ this['ES6Promise'] = es6$promise$umd$$ES6Promise;
+ }
+}).call(this);
+}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"_process":2}],2:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+var queue = [];
+var draining = false;
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ draining = true;
+ var currentQueue;
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ var i = -1;
+ while (++i < len) {
+ currentQueue[i]();
+ }
+ len = queue.length;
+ }
+ draining = false;
+}
+process.nextTick = function (fun) {
+ queue.push(fun);
+ if (!draining) {
+ setTimeout(drainQueue, 0);
+ }
+};
+
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+// TODO(shtylman)
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],3:[function(require,module,exports){
+(function (global){
+/*! http://mths.be/punycode v1.2.4 by @mathias */
+;(function(root) {
+
+ /** Detect free variables */
+ var freeExports = typeof exports == 'object' && exports;
+ var freeModule = typeof module == 'object' && module &&
+ module.exports == freeExports && module;
+ var freeGlobal = typeof global == 'object' && global;
+ if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
+ root = freeGlobal;
+ }
+
+ /**
+ * The `punycode` object.
+ * @name punycode
+ * @type Object
+ */
+ var punycode,
+
+ /** Highest positive signed 32-bit float value */
+ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+ /** Bootstring parameters */
+ base = 36,
+ tMin = 1,
+ tMax = 26,
+ skew = 38,
+ damp = 700,
+ initialBias = 72,
+ initialN = 128, // 0x80
+ delimiter = '-', // '\x2D'
+
+ /** Regular expressions */
+ regexPunycode = /^xn--/,
+ regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
+ regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
+
+ /** Error messages */
+ errors = {
+ 'overflow': 'Overflow: input needs wider integers to process',
+ 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+ 'invalid-input': 'Invalid input'
+ },
+
+ /** Convenience shortcuts */
+ baseMinusTMin = base - tMin,
+ floor = Math.floor,
+ stringFromCharCode = String.fromCharCode,
+
+ /** Temporary variable */
+ key;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * A generic error utility function.
+ * @private
+ * @param {String} type The error type.
+ * @returns {Error} Throws a `RangeError` with the applicable error message.
+ */
+ function error(type) {
+ throw RangeError(errors[type]);
+ }
+
+ /**
+ * A generic `Array#map` utility function.
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function that gets called for every array
+ * item.
+ * @returns {Array} A new array of values returned by the callback function.
+ */
+ function map(array, fn) {
+ var length = array.length;
+ while (length--) {
+ array[length] = fn(array[length]);
+ }
+ return array;
+ }
+
+ /**
+ * A simple `Array#map`-like wrapper to work with domain name strings.
+ * @private
+ * @param {String} domain The domain name.
+ * @param {Function} callback The function that gets called for every
+ * character.
+ * @returns {Array} A new string of characters returned by the callback
+ * function.
+ */
+ function mapDomain(string, fn) {
+ return map(string.split(regexSeparators), fn).join('.');
+ }
+
+ /**
+ * Creates an array containing the numeric code points of each Unicode
+ * character in the string. While JavaScript uses UCS-2 internally,
+ * this function will convert a pair of surrogate halves (each of which
+ * UCS-2 exposes as separate characters) into a single code point,
+ * matching UTF-16.
+ * @see `punycode.ucs2.encode`
+ * @see
+ * @memberOf punycode.ucs2
+ * @name decode
+ * @param {String} string The Unicode input string (UCS-2).
+ * @returns {Array} The new array of code points.
+ */
+ function ucs2decode(string) {
+ var output = [],
+ counter = 0,
+ length = string.length,
+ value,
+ extra;
+ while (counter < length) {
+ value = string.charCodeAt(counter++);
+ if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+ // high surrogate, and there is a next character
+ extra = string.charCodeAt(counter++);
+ if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+ output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ // unmatched surrogate; only append this code unit, in case the next
+ // code unit is the high surrogate of a surrogate pair
+ output.push(value);
+ counter--;
+ }
+ } else {
+ output.push(value);
+ }
+ }
+ return output;
+ }
+
+ /**
+ * Creates a string based on an array of numeric code points.
+ * @see `punycode.ucs2.decode`
+ * @memberOf punycode.ucs2
+ * @name encode
+ * @param {Array} codePoints The array of numeric code points.
+ * @returns {String} The new Unicode string (UCS-2).
+ */
+ function ucs2encode(array) {
+ return map(array, function(value) {
+ var output = '';
+ if (value > 0xFFFF) {
+ value -= 0x10000;
+ output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+ value = 0xDC00 | value & 0x3FF;
+ }
+ output += stringFromCharCode(value);
+ return output;
+ }).join('');
+ }
+
+ /**
+ * Converts a basic code point into a digit/integer.
+ * @see `digitToBasic()`
+ * @private
+ * @param {Number} codePoint The basic numeric code point value.
+ * @returns {Number} The numeric value of a basic code point (for use in
+ * representing integers) in the range `0` to `base - 1`, or `base` if
+ * the code point does not represent a value.
+ */
+ function basicToDigit(codePoint) {
+ if (codePoint - 48 < 10) {
+ return codePoint - 22;
+ }
+ if (codePoint - 65 < 26) {
+ return codePoint - 65;
+ }
+ if (codePoint - 97 < 26) {
+ return codePoint - 97;
+ }
+ return base;
+ }
+
+ /**
+ * Converts a digit/integer into a basic code point.
+ * @see `basicToDigit()`
+ * @private
+ * @param {Number} digit The numeric value of a basic code point.
+ * @returns {Number} The basic code point whose value (when used for
+ * representing integers) is `digit`, which needs to be in the range
+ * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+ * used; else, the lowercase form is used. The behavior is undefined
+ * if `flag` is non-zero and `digit` has no uppercase form.
+ */
+ function digitToBasic(digit, flag) {
+ // 0..25 map to ASCII a..z or A..Z
+ // 26..35 map to ASCII 0..9
+ return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+ }
+
+ /**
+ * Bias adaptation function as per section 3.4 of RFC 3492.
+ * http://tools.ietf.org/html/rfc3492#section-3.4
+ * @private
+ */
+ function adapt(delta, numPoints, firstTime) {
+ var k = 0;
+ delta = firstTime ? floor(delta / damp) : delta >> 1;
+ delta += floor(delta / numPoints);
+ for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+ delta = floor(delta / baseMinusTMin);
+ }
+ return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+ }
+
+ /**
+ * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+ * symbols.
+ * @memberOf punycode
+ * @param {String} input The Punycode string of ASCII-only symbols.
+ * @returns {String} The resulting string of Unicode symbols.
+ */
+ function decode(input) {
+ // Don't use UCS-2
+ var output = [],
+ inputLength = input.length,
+ out,
+ i = 0,
+ n = initialN,
+ bias = initialBias,
+ basic,
+ j,
+ index,
+ oldi,
+ w,
+ k,
+ digit,
+ t,
+ /** Cached calculation results */
+ baseMinusT;
+
+ // Handle the basic code points: let `basic` be the number of input code
+ // points before the last delimiter, or `0` if there is none, then copy
+ // the first basic code points to the output.
+
+ basic = input.lastIndexOf(delimiter);
+ if (basic < 0) {
+ basic = 0;
+ }
+
+ for (j = 0; j < basic; ++j) {
+ // if it's not a basic code point
+ if (input.charCodeAt(j) >= 0x80) {
+ error('not-basic');
+ }
+ output.push(input.charCodeAt(j));
+ }
+
+ // Main decoding loop: start just after the last delimiter if any basic code
+ // points were copied; start at the beginning otherwise.
+
+ for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+ // `index` is the index of the next character to be consumed.
+ // Decode a generalized variable-length integer into `delta`,
+ // which gets added to `i`. The overflow checking is easier
+ // if we increase `i` as we go, then subtract off its starting
+ // value at the end to obtain `delta`.
+ for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+ if (index >= inputLength) {
+ error('invalid-input');
+ }
+
+ digit = basicToDigit(input.charCodeAt(index++));
+
+ if (digit >= base || digit > floor((maxInt - i) / w)) {
+ error('overflow');
+ }
+
+ i += digit * w;
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+ if (digit < t) {
+ break;
+ }
+
+ baseMinusT = base - t;
+ if (w > floor(maxInt / baseMinusT)) {
+ error('overflow');
+ }
+
+ w *= baseMinusT;
+
+ }
+
+ out = output.length + 1;
+ bias = adapt(i - oldi, out, oldi == 0);
+
+ // `i` was supposed to wrap around from `out` to `0`,
+ // incrementing `n` each time, so we'll fix that now:
+ if (floor(i / out) > maxInt - n) {
+ error('overflow');
+ }
+
+ n += floor(i / out);
+ i %= out;
+
+ // Insert `n` at position `i` of the output
+ output.splice(i++, 0, n);
+
+ }
+
+ return ucs2encode(output);
+ }
+
+ /**
+ * Converts a string of Unicode symbols to a Punycode string of ASCII-only
+ * symbols.
+ * @memberOf punycode
+ * @param {String} input The string of Unicode symbols.
+ * @returns {String} The resulting Punycode string of ASCII-only symbols.
+ */
+ function encode(input) {
+ var n,
+ delta,
+ handledCPCount,
+ basicLength,
+ bias,
+ j,
+ m,
+ q,
+ k,
+ t,
+ currentValue,
+ output = [],
+ /** `inputLength` will hold the number of code points in `input`. */
+ inputLength,
+ /** Cached calculation results */
+ handledCPCountPlusOne,
+ baseMinusT,
+ qMinusT;
+
+ // Convert the input in UCS-2 to Unicode
+ input = ucs2decode(input);
+
+ // Cache the length
+ inputLength = input.length;
+
+ // Initialize the state
+ n = initialN;
+ delta = 0;
+ bias = initialBias;
+
+ // Handle the basic code points
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue < 0x80) {
+ output.push(stringFromCharCode(currentValue));
+ }
+ }
+
+ handledCPCount = basicLength = output.length;
+
+ // `handledCPCount` is the number of code points that have been handled;
+ // `basicLength` is the number of basic code points.
+
+ // Finish the basic string - if it is not empty - with a delimiter
+ if (basicLength) {
+ output.push(delimiter);
+ }
+
+ // Main encoding loop:
+ while (handledCPCount < inputLength) {
+
+ // All non-basic code points < n have been handled already. Find the next
+ // larger one:
+ for (m = maxInt, j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue >= n && currentValue < m) {
+ m = currentValue;
+ }
+ }
+
+ // Increase `delta` enough to advance the decoder's state to ,
+ // but guard against overflow
+ handledCPCountPlusOne = handledCPCount + 1;
+ if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+ error('overflow');
+ }
+
+ delta += (m - n) * handledCPCountPlusOne;
+ n = m;
+
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+
+ if (currentValue < n && ++delta > maxInt) {
+ error('overflow');
+ }
+
+ if (currentValue == n) {
+ // Represent delta as a generalized variable-length integer
+ for (q = delta, k = base; /* no condition */; k += base) {
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+ if (q < t) {
+ break;
+ }
+ qMinusT = q - t;
+ baseMinusT = base - t;
+ output.push(
+ stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+ );
+ q = floor(qMinusT / baseMinusT);
+ }
+
+ output.push(stringFromCharCode(digitToBasic(q, 0)));
+ bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+ delta = 0;
+ ++handledCPCount;
+ }
+ }
+
+ ++delta;
+ ++n;
+
+ }
+ return output.join('');
+ }
+
+ /**
+ * Converts a Punycode string representing a domain name to Unicode. Only the
+ * Punycoded parts of the domain name will be converted, i.e. it doesn't
+ * matter if you call it on a string that has already been converted to
+ * Unicode.
+ * @memberOf punycode
+ * @param {String} domain The Punycode domain name to convert to Unicode.
+ * @returns {String} The Unicode representation of the given Punycode
+ * string.
+ */
+ function toUnicode(domain) {
+ return mapDomain(domain, function(string) {
+ return regexPunycode.test(string)
+ ? decode(string.slice(4).toLowerCase())
+ : string;
+ });
+ }
+
+ /**
+ * Converts a Unicode string representing a domain name to Punycode. Only the
+ * non-ASCII parts of the domain name will be converted, i.e. it doesn't
+ * matter if you call it with a domain that's already in ASCII.
+ * @memberOf punycode
+ * @param {String} domain The domain name to convert, as a Unicode string.
+ * @returns {String} The Punycode representation of the given domain name.
+ */
+ function toASCII(domain) {
+ return mapDomain(domain, function(string) {
+ return regexNonASCII.test(string)
+ ? 'xn--' + encode(string)
+ : string;
+ });
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /** Define the public API */
+ punycode = {
+ /**
+ * A string representing the current Punycode.js version number.
+ * @memberOf punycode
+ * @type String
+ */
+ 'version': '1.2.4',
+ /**
+ * An object of methods to convert from JavaScript's internal character
+ * representation (UCS-2) to Unicode code points, and back.
+ * @see
+ * @memberOf punycode
+ * @type Object
+ */
+ 'ucs2': {
+ 'decode': ucs2decode,
+ 'encode': ucs2encode
+ },
+ 'decode': decode,
+ 'encode': encode,
+ 'toASCII': toASCII,
+ 'toUnicode': toUnicode
+ };
+
+ /** Expose `punycode` */
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ typeof define == 'function' &&
+ typeof define.amd == 'object' &&
+ define.amd
+ ) {
+ define('punycode', function() {
+ return punycode;
+ });
+ } else if (freeExports && !freeExports.nodeType) {
+ if (freeModule) { // in Node.js or RingoJS v0.8.0+
+ freeModule.exports = punycode;
+ } else { // in Narwhal or RingoJS v0.7.0-
+ for (key in punycode) {
+ punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+ }
+ }
+ } else { // in Rhino or a web browser
+ root.punycode = punycode;
+ }
+
+}(this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],4:[function(require,module,exports){
+var log = require('./log');
+var Promise = require('./promise');
+
+function restoreOwnerScroll(ownerDocument, x, y) {
+ if (ownerDocument.defaultView && (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)) {
+ ownerDocument.defaultView.scrollTo(x, y);
+ }
+}
+
+function cloneCanvasContents(canvas, clonedCanvas) {
+ try {
+ if (clonedCanvas) {
+ clonedCanvas.width = canvas.width;
+ clonedCanvas.height = canvas.height;
+ clonedCanvas.getContext("2d").putImageData(canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height), 0, 0);
+ }
+ } catch(e) {
+ log("Unable to copy canvas content from", canvas, e);
+ }
+}
+
+function cloneNode(node, javascriptEnabled) {
+ var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
+
+ var child = node.firstChild;
+ while(child) {
+ if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
+ clone.appendChild(cloneNode(child, javascriptEnabled));
+ }
+ child = child.nextSibling;
+ }
+
+ if (node.nodeType === 1) {
+ clone._scrollTop = node.scrollTop;
+ clone._scrollLeft = node.scrollLeft;
+ if (node.nodeName === "CANVAS") {
+ cloneCanvasContents(node, clone);
+ } else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") {
+ clone.value = node.value;
+ }
+ }
+
+ return clone;
+}
+
+function initNode(node) {
+ if (node.nodeType === 1) {
+ node.scrollTop = node._scrollTop;
+ node.scrollLeft = node._scrollLeft;
+
+ var child = node.firstChild;
+ while(child) {
+ initNode(child);
+ child = child.nextSibling;
+ }
+ }
+}
+
+module.exports = function(ownerDocument, containerDocument, width, height, options, x ,y) {
+ var documentElement = cloneNode(ownerDocument.documentElement, options.javascriptEnabled);
+ var container = containerDocument.createElement("iframe");
+
+ container.className = "html2canvas-container";
+ container.style.visibility = "hidden";
+ container.style.position = "fixed";
+ container.style.left = "-10000px";
+ container.style.top = "0px";
+ container.style.border = "0";
+ container.width = width;
+ container.height = height;
+ container.scrolling = "no"; // ios won't scroll without it
+ containerDocument.body.appendChild(container);
+
+ return new Promise(function(resolve) {
+ var documentClone = container.contentWindow.document;
+
+ /* Chrome doesn't detect relative background-images assigned in inline