<commit_before>(function($) {
     window['Devtools'] = { //window represents the browser window
        //by putting it in window, it's essentially greating a global variable

        // development settings.
        //VERSION: 0.1,

        defaults: {
            logging: false,  // false to turn off logging
            production: false
        },

	get_rid : function(name) {

        var rids = {
            "rulesets": {"prod": "b506607x14",
                          "dev": "b506607x14"
            }
        };

	    return this.defaults.production ? rids[name].prod : rids[name].dev;
	},

    rid_eci: null, //fleet_eci
    rid_summary: {}, //vehicle_summary
    rid_list: [], //vehicles

    log: function() {
        if (this.defaults.logging && console && console.log) {
            [].unshift.call(arguments, "Devtools:"); // arguments is Array-like, it's not an Array
            console.log.apply(console, arguments);
        }
    },

    getProfile: function(channel, cb, options)
    {
        cb = cb || function(){};
        options = options || {};
            Devtools.log("Retrieving profile for user");

        return CloudOS.skyCloud("a169x676", "get_all_me", {}, function(res) { //fix this up. what rule is this calling?
            CloudOS.clean(res);
            if(typeof cb !== "undefined"){
                cb(res);
            }
        },
        {"eci": channel});
    },

    getRulesets: function(cb, options) //almost like getProfile in fuse-api.js
    {

        cb = cb || function(){};
        options = options || {};
        //var rid = "rulesets";
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Showing the rulesets");
        return CloudOS.skyCloud(Devtools.get_rid("rulesets"), "showRulesets", {}, function(json) {
            Devtools.log("Displaying rulesets", json);
            cb(json);
        }, {"eci":eci});
    },

// ---------- account ----------
    // this is called in _layouts/code.html when the account is created
    initAccount: function(attrs, cb, options)
        {
        cb = cb || function(){};
        options = options || {};
        attrs = attrs || {};
            Devtools.log("Initializing account for user with attributes ", attrs);

            return CloudOS.raiseEvent("Devtools", "bootstrap", attrs, {}, function(response)
            {
        // note that because the channel is create asynchronously, processing callback does
        // NOT mean the channel exists.
                Devtools.log("account initialized");
        if(response.length < 1) {
            throw "Account initialization failed";
        }
        cb(response);
            });
        },

//---------the functions for updating rulesets

    updateUrl: function(rid, url, cb, options) //basing this off of updateCarvoyantVehicle
    {
        cb = cb || function(){};
        options = options || {};
        var json = {rids: rid}; //not sure what this does
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Updating the URL");
        return CloudOS.raiseEvent("devtools", "update_url", json, {}, function(json) {
            Devtools.log("Directive from updating URL", json);
            cb(json);
        }, {"eci":eci});
    },

    showInstalledRulesets: function(cb, options) // PJW
    {
        cb = cb || function(){};
        options = options || {};
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Showing the rulesets");
        return CloudOS.skyCloud(Devtools.get_rid("rulesets"), "showInstalledRulesets", {}, function(json) {
            Devtools.log("Displaying installed rulesets", json);
            cb(json);
        }, {"eci":eci});
    },

    installRulesets: function(ridlist, cb, options) // PJW
    {
        cb = cb || function(){};
        options = options || {};
	var json = {rids: ridlist};
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Installing rulesets");
        return CloudOS.raiseEvent("devtools", "install_rulesets", json, {}, function(json) {
            Devtools.log("Directive from installing rulesets", json);
            cb(json);
        }, {"eci":eci});
    },

    uninstallRulesets: function(ridlist, cb, options) // PJW
    {
        cb = cb || function(){};
        options = options || {};
	var json = {rids: ridlist};
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Uninstalling rulesets");
        return CloudOS.raiseEvent("devtools", "uninstall_rulesets", json, {}, function(json) {
            Devtools.log("Directive from uninstalling rulesets", json);
            cb(json);
        }, {"eci":eci});
    },
    RegisterRuleset: function(url,cb,options)
    {
        cb = cb || function(){};
        options = options || {};
    var json = {rulesetURL: url}; // json for attribute thats passed to the ruleset as eventattribute
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Registering rulesets");
        return CloudOS.raiseEvent("devtools", "register_ruleset", json, {}, function(json) {
            Devtools.log("Directive from register ruleset", json);
            cb(json);
        }, {"eci":eci});
    }

//
}; //closes the "window" inside the function DON'T DELETE

//----------------------------------

    function isEmpty(obj) {

        // null and undefined are "empty"
        if (obj === null) return true;

        // Assume if it has a length property with a non-zero value
        // that that property is correct.
        if (obj.length > 0)    return false;
        if (obj.length === 0)  return true;

        // Otherwise, does it have any properties of its own?
        // Note that this doesn't handle
        // toString and valueOf enumeration bugs in IE < 9
        for (var key in obj) {
                if (hasOwnProperty.call(obj, key)) return false;
        }

        return true;

        }

})(jQuery);
<commit_msg>event att.<commit_after>(function($) {
     window['Devtools'] = { //window represents the browser window
        //by putting it in window, it's essentially greating a global variable

        // development settings.
        //VERSION: 0.1,

        defaults: {
            logging: false,  // false to turn off logging
            production: false
        },

	get_rid : function(name) {

        var rids = {
            "rulesets": {"prod": "b506607x14",
                          "dev": "b506607x14"
            }
        };

	    return this.defaults.production ? rids[name].prod : rids[name].dev;
	},

    rid_eci: null, //fleet_eci
    rid_summary: {}, //vehicle_summary
    rid_list: [], //vehicles

    log: function() {
        if (this.defaults.logging && console && console.log) {
            [].unshift.call(arguments, "Devtools:"); // arguments is Array-like, it's not an Array
            console.log.apply(console, arguments);
        }
    },

    getProfile: function(channel, cb, options)
    {
        cb = cb || function(){};
        options = options || {};
            Devtools.log("Retrieving profile for user");

        return CloudOS.skyCloud("a169x676", "get_all_me", {}, function(res) { //fix this up. what rule is this calling?
            CloudOS.clean(res);
            if(typeof cb !== "undefined"){
                cb(res);
            }
        },
        {"eci": channel});
    },

    getRulesets: function(cb, options) //almost like getProfile in fuse-api.js
    {

        cb = cb || function(){};
        options = options || {};
        //var rid = "rulesets";
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Showing the rulesets");
        return CloudOS.skyCloud(Devtools.get_rid("rulesets"), "showRulesets", {}, function(json) {
            Devtools.log("Displaying rulesets", json);
            cb(json);
        }, {"eci":eci});
    },

// ---------- account ----------
    // this is called in _layouts/code.html when the account is created
    initAccount: function(attrs, cb, options)
        {
        cb = cb || function(){};
        options = options || {};
        attrs = attrs || {};
            Devtools.log("Initializing account for user with attributes ", attrs);

            return CloudOS.raiseEvent("Devtools", "bootstrap", attrs, {}, function(response)
            {
        // note that because the channel is create asynchronously, processing callback does
        // NOT mean the channel exists.
                Devtools.log("account initialized");
        if(response.length < 1) {
            throw "Account initialization failed";
        }
        cb(response);
            });
        },

//---------the functions for updating rulesets

    updateUrl: function(rid, url, cb, options) //basing this off of updateCarvoyantVehicle
    {
        cb = cb || function(){};
        options = options || {};
        var json = {rids: rid,url: url}; //not sure what this does
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Updating the URL");
        return CloudOS.raiseEvent("devtools", "update_url", json, {}, function(json) {
            Devtools.log("Directive from updating URL", json);
            cb(json);
        }, {"eci":eci});
    },

    showInstalledRulesets: function(cb, options) // PJW
    {
        cb = cb || function(){};
        options = options || {};
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Showing the rulesets");
        return CloudOS.skyCloud(Devtools.get_rid("rulesets"), "showInstalledRulesets", {}, function(json) {
            Devtools.log("Displaying installed rulesets", json);
            cb(json);
        }, {"eci":eci});
    },

    installRulesets: function(ridlist, cb, options) // PJW
    {
        cb = cb || function(){};
        options = options || {};
	var json = {rids: ridlist};
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Installing rulesets");
        return CloudOS.raiseEvent("devtools", "install_rulesets", json, {}, function(json) {
            Devtools.log("Directive from installing rulesets", json);
            cb(json);
        }, {"eci":eci});
    },

    uninstallRulesets: function(ridlist, cb, options) // PJW
    {
        cb = cb || function(){};
        options = options || {};
	var json = {rids: ridlist};
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Uninstalling rulesets");
        return CloudOS.raiseEvent("devtools", "uninstall_rulesets", json, {}, function(json) {
            Devtools.log("Directive from uninstalling rulesets", json);
            cb(json);
        }, {"eci":eci});
    },
    RegisterRuleset: function(url,cb,options)
    {
        cb = cb || function(){};
        options = options || {};
    var json = {rulesetURL: url}; // json for attribute thats passed to the ruleset as eventattribute
        var eci = options.eci || CloudOS.defaultECI;
        Devtools.log("Registering rulesets");
        return CloudOS.raiseEvent("devtools", "register_ruleset", json, {}, function(json) {
            Devtools.log("Directive from register ruleset", json);
            cb(json);
        }, {"eci":eci});
    }

//
}; //closes the "window" inside the function DON'T DELETE

//----------------------------------

    function isEmpty(obj) {

        // null and undefined are "empty"
        if (obj === null) return true;

        // Assume if it has a length property with a non-zero value
        // that that property is correct.
        if (obj.length > 0)    return false;
        if (obj.length === 0)  return true;

        // Otherwise, does it have any properties of its own?
        // Note that this doesn't handle
        // toString and valueOf enumeration bugs in IE < 9
        for (var key in obj) {
                if (hasOwnProperty.call(obj, key)) return false;
        }

        return true;

        }

})(jQuery);
<|endoftext|>


<commit_before>const _ = require('lodash');
const assert = require('assert');
const BN = require('bn.js');
const Decimal = require('decimal.js');
const makeClass = require('../utils/make-class');
const {SerializedType} = require('./serialized-type');
const {bytesToHex} = require('../utils/bytes-utils');
const {Currency} = require('./currency');
const {AccountID} = require('./account-id');
const {UInt64} = require('./uint-64');

const MIN_IOU_EXPONENT = -96;
const MAX_IOU_EXPONENT = 80;
const MAX_IOU_PRECISION = 16;
const MIN_IOU_MANTISSA = '1000' + '0000' + '0000' + '0000'; // 16 digits
const MAX_IOU_MANTISSA = '9999' + '9999' + '9999' + '9999'; // ..
const MAX_IOU = new Decimal(`${MAX_IOU_MANTISSA}e${MAX_IOU_EXPONENT}`);
const MIN_IOU = new Decimal(`${MIN_IOU_MANTISSA}e${MIN_IOU_EXPONENT}`);
const DROPS_PER_XRP = new Decimal('1e6');
const MAX_NETWORK_DROPS = new Decimal('1e17');
const MIN_XRP = new Decimal('1e-6')
const MAX_XRP = MAX_NETWORK_DROPS.dividedBy(DROPS_PER_XRP);

// Never use exponential form
Decimal.config({
  toExpPos: MAX_IOU_EXPONENT + MAX_IOU_PRECISION,
  toExpNeg: MIN_IOU_EXPONENT - MAX_IOU_PRECISION
});

const AMOUNT_PARAMETERS_DESCRIPTION = `
Native values must be described in drops, a million of which equal one XRP.
This must be an integer number, with the absolute value not exceeding \
${MAX_NETWORK_DROPS}

IOU values must have a maximum precision of ${MAX_IOU_PRECISION} significant \
digits. They are serialized as\na canonicalised mantissa and exponent.

The valid range for a mantissa is between ${MIN_IOU_MANTISSA} and \
${MAX_IOU_MANTISSA}
The exponent must be >= ${MIN_IOU_EXPONENT} and <= ${MAX_IOU_EXPONENT}

Thus the largest serializable IOU value is:
${MAX_IOU.toString()}

And the smallest:
${MIN_IOU.toString()}
`

function isDefined(val) {
  return !_.isUndefined(val);
}

function raiseIllegalAmountError(value) {
  throw new Error(`${value.toString()} is an illegal amount\n` +
                   AMOUNT_PARAMETERS_DESCRIPTION);
}

const parsers = {
  string(str) {
    if (!str.match(/\d+/)) {
      raiseIllegalAmountError(str);
    }
    return [new Decimal(str).dividedBy(DROPS_PER_XRP), Currency.XRP];
  },
  object(object) {
    assert(isDefined(object.currency), 'currency must be defined');
    assert(isDefined(object.issuer), 'issuer must be defined');
    return [new Decimal(object.value),
            Currency.from(object.currency),
            AccountID.from(object.issuer)];
  }
};

const Amount = makeClass({
  Amount(value, currency, issuer) {
    this.value = value || new Decimal('0');
    this.currency = currency || Currency.XRP;
    this.issuer = issuer || null;
    this.assertValueIsValid();
  },
  mixins: SerializedType,
  statics: {
    from(value) {
      if (value instanceof this) {
        return value;
      }
      const parser = parsers[typeof value];
      if (parser) {
        return new this(...parser(value));
      }
      throw new Error(`unsupported value: ${value}`);
    },
    fromParser(parser) {
      const mantissa = parser.read(8);
      const b1 = mantissa[0];
      const b2 = mantissa[1];

      const isIOU = b1 & 0x80;
      const isPositive = b1 & 0x40;
      const sign = isPositive ? '' : '-';

      if (isIOU) {
        mantissa[0] = 0;
        const currency = parser.readType(Currency);
        const issuer = parser.readType(AccountID);
        const exponent = ((b1 & 0x3F) << 2) + ((b2 & 0xff) >> 6) - 97;
        mantissa[1] &= 0x3F;
        // decimal.js won't accept e notation with hex
        const value = new Decimal(`${sign}0x${bytesToHex(mantissa)}`)
                                 .times('1e' + exponent);
        return new this(value, currency, issuer);
      }

      mantissa[0] &= 0x3F;
      const drops = new Decimal(`${sign}0x${bytesToHex(mantissa)}`);
      const xrpValue = drops.dividedBy(DROPS_PER_XRP);
      return new this(xrpValue, Currency.XRP);
    }
  },
  assertValueIsValid() {
    // zero is always a valid amount value
    if (!this.isZero()) {
      if (this.isNative()) {
        const abs = this.value.abs();
        if (abs.lt(MIN_XRP) || abs.gt(MAX_XRP)) {
          // value is in XRP scale, but show the value in canonical json form
          raiseIllegalAmountError(this.value.times(DROPS_PER_XRP))
        }
      } else {
        const p = this.value.precision();
        const e = this.exponent();
        if (p > MAX_IOU_PRECISION ||
            e > MAX_IOU_EXPONENT ||
            e < MIN_IOU_EXPONENT) {
          raiseIllegalAmountError(this.value)
        }
      }
    }
  },
  isNative() {
    return this.currency.isNative();
  },
  mantissa() {
    return new UInt64(
      new BN(this.value.times('1e' + -this.exponent()).abs().toString()));
  },
  isZero() {
    return this.value.isZero();
  },
  exponent() {
    return this.isNative() ? -6 : this.value.e - 15;
  },
  valueString() {
    return (this.isNative() ? this.value.times(DROPS_PER_XRP) : this.value)
            .toString();
  },
  toBytesSink(sink) {
    const isNative = this.isNative();
    const notNegative = !this.value.isNegative();
    const mantissa = this.mantissa().toBytes();

    if (isNative) {
      mantissa[0] |= notNegative ? 0x40 : 0;
      sink.put(mantissa);
    } else {
      mantissa[0] |= 0x80;
      if (!this.isZero()) {
        if (notNegative) {
          mantissa[0] |= 0x40;
        }
        const exponent = this.value.e - 15;
        const exponentByte = 97 + exponent;
        mantissa[0] |= (exponentByte >>> 2);
        mantissa[1] |= (exponentByte & 0x03) << 6;
      }
      sink.put(mantissa);
      this.currency.toBytesSink(sink);
      this.issuer.toBytesSink(sink);
    }
  },
  toJSON() {
    const valueString = this.valueString();
    if (this.isNative()) {
      return valueString;
    }
    return {
      value: valueString,
      currency: this.currency.toJSON(),
      issuer: this.issuer.toJSON()
    };
  }
});

module.exports = {
  Amount
};
<commit_msg>dont validate amounts coming from binary parser<commit_after>const _ = require('lodash');
const assert = require('assert');
const BN = require('bn.js');
const Decimal = require('decimal.js');
const makeClass = require('../utils/make-class');
const {SerializedType} = require('./serialized-type');
const {bytesToHex} = require('../utils/bytes-utils');
const {Currency} = require('./currency');
const {AccountID} = require('./account-id');
const {UInt64} = require('./uint-64');

const MIN_IOU_EXPONENT = -96;
const MAX_IOU_EXPONENT = 80;
const MAX_IOU_PRECISION = 16;
const MIN_IOU_MANTISSA = '1000' + '0000' + '0000' + '0000'; // 16 digits
const MAX_IOU_MANTISSA = '9999' + '9999' + '9999' + '9999'; // ..
const MAX_IOU = new Decimal(`${MAX_IOU_MANTISSA}e${MAX_IOU_EXPONENT}`);
const MIN_IOU = new Decimal(`${MIN_IOU_MANTISSA}e${MIN_IOU_EXPONENT}`);
const DROPS_PER_XRP = new Decimal('1e6');
const MAX_NETWORK_DROPS = new Decimal('1e17');
const MIN_XRP = new Decimal('1e-6')
const MAX_XRP = MAX_NETWORK_DROPS.dividedBy(DROPS_PER_XRP);

// Never use exponential form
Decimal.config({
  toExpPos: MAX_IOU_EXPONENT + MAX_IOU_PRECISION,
  toExpNeg: MIN_IOU_EXPONENT - MAX_IOU_PRECISION
});

const AMOUNT_PARAMETERS_DESCRIPTION = `
Native values must be described in drops, a million of which equal one XRP.
This must be an integer number, with the absolute value not exceeding \
${MAX_NETWORK_DROPS}

IOU values must have a maximum precision of ${MAX_IOU_PRECISION} significant \
digits. They are serialized as\na canonicalised mantissa and exponent.

The valid range for a mantissa is between ${MIN_IOU_MANTISSA} and \
${MAX_IOU_MANTISSA}
The exponent must be >= ${MIN_IOU_EXPONENT} and <= ${MAX_IOU_EXPONENT}

Thus the largest serializable IOU value is:
${MAX_IOU.toString()}

And the smallest:
${MIN_IOU.toString()}
`

function isDefined(val) {
  return !_.isUndefined(val);
}

function raiseIllegalAmountError(value) {
  throw new Error(`${value.toString()} is an illegal amount\n` +
                   AMOUNT_PARAMETERS_DESCRIPTION);
}

const parsers = {
  string(str) {
    if (!str.match(/\d+/)) {
      raiseIllegalAmountError(str);
    }
    return [new Decimal(str).dividedBy(DROPS_PER_XRP), Currency.XRP];
  },
  object(object) {
    assert(isDefined(object.currency), 'currency must be defined');
    assert(isDefined(object.issuer), 'issuer must be defined');
    return [new Decimal(object.value),
            Currency.from(object.currency),
            AccountID.from(object.issuer)];
  }
};

const Amount = makeClass({
  Amount(value, currency, issuer, validate = true) {
    this.value = value || new Decimal('0');
    this.currency = currency || Currency.XRP;
    this.issuer = issuer || null;
    validate && this.assertValueIsValid();
  },
  mixins: SerializedType,
  statics: {
    from(value) {
      if (value instanceof this) {
        return value;
      }
      const parser = parsers[typeof value];
      if (parser) {
        return new this(...parser(value));
      }
      throw new Error(`unsupported value: ${value}`);
    },
    fromParser(parser) {
      const mantissa = parser.read(8);
      const b1 = mantissa[0];
      const b2 = mantissa[1];

      const isIOU = b1 & 0x80;
      const isPositive = b1 & 0x40;
      const sign = isPositive ? '' : '-';

      if (isIOU) {
        mantissa[0] = 0;
        const currency = parser.readType(Currency);
        const issuer = parser.readType(AccountID);
        const exponent = ((b1 & 0x3F) << 2) + ((b2 & 0xff) >> 6) - 97;
        mantissa[1] &= 0x3F;
        // decimal.js won't accept e notation with hex
        const value = new Decimal(`${sign}0x${bytesToHex(mantissa)}`)
                                 .times('1e' + exponent);
        return new this(value, currency, issuer, false);
      }

      mantissa[0] &= 0x3F;
      const drops = new Decimal(`${sign}0x${bytesToHex(mantissa)}`);
      const xrpValue = drops.dividedBy(DROPS_PER_XRP);
      return new this(xrpValue, Currency.XRP, null, false);
    }
  },
  assertValueIsValid() {
    // zero is always a valid amount value
    if (!this.isZero()) {
      if (this.isNative()) {
        const abs = this.value.abs();
        if (abs.lt(MIN_XRP) || abs.gt(MAX_XRP)) {
          // value is in XRP scale, but show the value in canonical json form
          raiseIllegalAmountError(this.value.times(DROPS_PER_XRP))
        }
      } else {
        const p = this.value.precision();
        const e = this.exponent();
        if (p > MAX_IOU_PRECISION ||
            e > MAX_IOU_EXPONENT ||
            e < MIN_IOU_EXPONENT) {
          raiseIllegalAmountError(this.value)
        }
      }
    }
  },
  isNative() {
    return this.currency.isNative();
  },
  mantissa() {
    return new UInt64(
      new BN(this.value.times('1e' + -this.exponent()).abs().toString()));
  },
  isZero() {
    return this.value.isZero();
  },
  exponent() {
    return this.isNative() ? -6 : this.value.e - 15;
  },
  valueString() {
    return (this.isNative() ? this.value.times(DROPS_PER_XRP) : this.value)
            .toString();
  },
  toBytesSink(sink) {
    const isNative = this.isNative();
    const notNegative = !this.value.isNegative();
    const mantissa = this.mantissa().toBytes();

    if (isNative) {
      mantissa[0] |= notNegative ? 0x40 : 0;
      sink.put(mantissa);
    } else {
      mantissa[0] |= 0x80;
      if (!this.isZero()) {
        if (notNegative) {
          mantissa[0] |= 0x40;
        }
        const exponent = this.value.e - 15;
        const exponentByte = 97 + exponent;
        mantissa[0] |= (exponentByte >>> 2);
        mantissa[1] |= (exponentByte & 0x03) << 6;
      }
      sink.put(mantissa);
      this.currency.toBytesSink(sink);
      this.issuer.toBytesSink(sink);
    }
  },
  toJSON() {
    const valueString = this.valueString();
    if (this.isNative()) {
      return valueString;
    }
    return {
      value: valueString,
      currency: this.currency.toJSON(),
      issuer: this.issuer.toJSON()
    };
  }
});

module.exports = {
  Amount
};
<|endoftext|>


<commit_before>jsio('import lib.Enum as Enum');

/**
 * @package math.util;
 */

/**
 * Interpolate between values a and b at the point x in the interval.
 */

exports.interpolate = function(a, b, x) { return a * (1 - x) + b * x; }

/**
 * Return a random integer between a and b. Optionally, a random seed can be
 * given.
 */

exports.random = function(a, b, rand) { return a + ((rand || Math.random)() * (b - a) | 0); }

/**
 * Return a random integer between a and b, inclusive. Optionally, a random seed
 * can be given.
 */

exports.randomInclusive = function(a, b, rand) { return exports.random(a, b+1, rand); }

/**
 * Return a value where min <= num <= max.
 */

exports.clip = function(num, min, max) { return Math.max(Math.min(num, max), min); }

/**
 * Return the sign of a number.
 */

exports.sign = function (num) {
	return num && num / Math.abs(num);
};

/**
 * Rounding a value with the given precision, given the provided rounding method.
 * NOTE: Number.toFixed returns a string, I'm not sure this is desired.

 ### util.round (n [, precision, method])
 1. `n {number} value`
 2. `precision {number} = null` ---Optional.
 3. `method {number}` ---Optional enum from `util.round`.
 4. Return `{number}`

 Round a number to a given precision, or by a given method.

 The precision method can be one of the following:

   * `util.round.ROUND_HALF_UP` ---Round 0.5 to 1.
   * `util.round.ROUND_HALF_AWAY_FROM_ZERO`
   * `util.round.ROUND_HALF_TO_EVEN` ---Round to the nearest even number.
   * `util.round.ROUND_HALF_TO_ODD` ---Round to the nearest odd number.
   * `util.round.ROUND_HALF_STOCHASTIC` ---Round at random.
   * `util.round.ROUND_HALF_ALTERNATE` ---Alternate rounding up/down with sequential uses of this function.
 *
 */

var round = exports.round = function(a, precision, method) {
	if (!method || method == round.ROUND_HALF_AWAY_FROM_ZERO) {
		return a.toFixed(precision);
	}

	if(!precision) {
		if (method == round.ROUND_HALF_UP) { Math.round(a); }

		var i = a | 0,
				frac = a - i,
				half = frac == 0.5 || frac == -0.5;
		if (!half) { return Math.round(a); }

		var sign = a < 0 ? -1 : 1;
		switch(method) {
			case round.ROUND_HALF_TO_EVEN:
				return i % 2 ? i + sign : i;
			case round.ROUND_HALF_TO_ODD:
				return i % 2 ? i : i + sign;
			case round.ROUND_HALF_STOCHASTIC:
				return Math.random() < 0.5 ? i + sign : i;
			case round.ROUND_HALF_ALTERNATE:
				return (round.alt = !round.alt) ? i + sign : i;
		}
	}

	var i = a | 0,
			frac = a - i,
			p = Math.pow(10, precision);
	return (i + round(frac * p, 0, method) / p).toFixed(precision);
}

/**
 * Available rounding possibilities.
 */

Enum.call(round, 'ROUND_HALF_UP', 'ROUND_HALF_AWAY_FROM_ZERO', 'ROUND_HALF_TO_EVEN', 'ROUND_HALF_TO_ODD', 'ROUND_HALF_STOCHASTIC', 'ROUND_HALF_ALTERNATE');

/**
 * Alternating flag for rounding strategy ROUND_HALF_ALTERNATE.
 */

round.alt = true;
<commit_msg>adds modulo operator to math util lib<commit_after>jsio('import lib.Enum as Enum');

/**
 * @package math.util;
 */

/**
 * Interpolate between values a and b at the point x in the interval.
 */

exports.interpolate = function(a, b, x) { return a * (1 - x) + b * x; }

/**
 * Return a random integer between a and b. Optionally, a random seed can be
 * given.
 */

exports.random = function(a, b, rand) { return a + ((rand || Math.random)() * (b - a) | 0); }

/**
 * Return a random integer between a and b, inclusive. Optionally, a random seed
 * can be given.
 */

exports.randomInclusive = function(a, b, rand) { return exports.random(a, b+1, rand); }

/**
 * Return a value where min <= num <= max.
 */

exports.clip = function(num, min, max) { return Math.max(Math.min(num, max), min); }

/**
 * Return the sign of a number.
 */

exports.sign = function (num) {
	return num && num / Math.abs(num);
};

/**
 * An actual modulo operator.
 */
exports.mod = function(m, n) {
    return ((m % n) + n) % n;
};

/**
 * Rounding a value with the given precision, given the provided rounding method.
 * NOTE: Number.toFixed returns a string, I'm not sure this is desired.

 ### util.round (n [, precision, method])
 1. `n {number} value`
 2. `precision {number} = null` ---Optional.
 3. `method {number}` ---Optional enum from `util.round`.
 4. Return `{number}`

 Round a number to a given precision, or by a given method.

 The precision method can be one of the following:

   * `util.round.ROUND_HALF_UP` ---Round 0.5 to 1.
   * `util.round.ROUND_HALF_AWAY_FROM_ZERO`
   * `util.round.ROUND_HALF_TO_EVEN` ---Round to the nearest even number.
   * `util.round.ROUND_HALF_TO_ODD` ---Round to the nearest odd number.
   * `util.round.ROUND_HALF_STOCHASTIC` ---Round at random.
   * `util.round.ROUND_HALF_ALTERNATE` ---Alternate rounding up/down with sequential uses of this function.
 *
 */

var round = exports.round = function(a, precision, method) {
	if (!method || method == round.ROUND_HALF_AWAY_FROM_ZERO) {
		return a.toFixed(precision);
	}

	if(!precision) {
		if (method == round.ROUND_HALF_UP) { Math.round(a); }

		var i = a | 0,
				frac = a - i,
				half = frac == 0.5 || frac == -0.5;
		if (!half) { return Math.round(a); }

		var sign = a < 0 ? -1 : 1;
		switch(method) {
			case round.ROUND_HALF_TO_EVEN:
				return i % 2 ? i + sign : i;
			case round.ROUND_HALF_TO_ODD:
				return i % 2 ? i : i + sign;
			case round.ROUND_HALF_STOCHASTIC:
				return Math.random() < 0.5 ? i + sign : i;
			case round.ROUND_HALF_ALTERNATE:
				return (round.alt = !round.alt) ? i + sign : i;
		}
	}

	var i = a | 0,
			frac = a - i,
			p = Math.pow(10, precision);
	return (i + round(frac * p, 0, method) / p).toFixed(precision);
}

/**
 * Available rounding possibilities.
 */

Enum.call(round, 'ROUND_HALF_UP', 'ROUND_HALF_AWAY_FROM_ZERO', 'ROUND_HALF_TO_EVEN', 'ROUND_HALF_TO_ODD', 'ROUND_HALF_STOCHASTIC', 'ROUND_HALF_ALTERNATE');

/**
 * Alternating flag for rounding strategy ROUND_HALF_ALTERNATE.
 */

round.alt = true;
<|endoftext|>


<commit_before>var exec = require('cordova/exec');
/**
 * Constructor
 */
function tts() {}

tts.prototype.init = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsInitSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsInitFailed', result));
    },
    "TtsPlugin",
    "initTTS",
    []
    );
};

tts.prototype.setLanguage = function(lang) {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsSetLanguageSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsSetLanguageFailed', result));
    },
    "TtsPlugin",
    "setLanguage",
    [lang]
    );
};

tts.prototype.setRate = function(rate) {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsSetRateSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsSetRateFailed', result));
    },
    "TtsPlugin",
    "setRate",
    [rate]
    );
};

tts.prototype.speak = function(text) {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsSpeakSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsSpeakFailed', result));
    },
    "TtsPlugin",
    "speak",
    [text]
    );
};

tts.prototype.stop = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsStopSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsStopFailed', result));
    },
    "TtsPlugin",
    "stop",
    []
    );
};

tts.prototype.pause = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsPauseSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsPauseFailed', result));
    },
    "TtsPlugin",
    "pause",
    []
    );
};

tts.prototype.resume = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsResumeSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsResumeFailed', result));
    },
    "TtsPlugin",
    "resume",
    []
    );
};

tts.prototype.restart = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsRestartSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsRestartFailed', result));
    },
    "TtsPlugin",
    "restart",
    []
    );
};

var tts = new tts();
module.exports = tts;<commit_msg>is speaking attempt<commit_after>var exec = require('cordova/exec');
/**
 * Constructor
 */
function tts() {}

tts.prototype.init = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsInitSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsInitFailed', result));
    },
    "TtsPlugin",
    "initTTS",
    []
    );
};

tts.prototype.setLanguage = function(lang) {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsSetLanguageSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsSetLanguageFailed', result));
    },
    "TtsPlugin",
    "setLanguage",
    [lang]
    );
};

tts.prototype.setRate = function(rate) {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsSetRateSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsSetRateFailed', result));
    },
    "TtsPlugin",
    "setRate",
    [rate]
    );
};

tts.prototype.speak = function(text) {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsSpeakSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsSpeakFailed', result));
    },
    "TtsPlugin",
    "speak",
    [text]
    );
};

tts.prototype.isSpeaking = function(text) {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsIsSpeakinSpeakSuccess', result));
        return result;
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsSpeakFailed', result));
    },
    "TtsPlugin",
    "isSpeaking",
    []
    );
};

tts.prototype.stop = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsStopSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsStopFailed', result));
    },
    "TtsPlugin",
    "stop",
    []
    );
};

tts.prototype.pause = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsPauseSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsPauseFailed', result));
    },
    "TtsPlugin",
    "pause",
    []
    );
};

tts.prototype.resume = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsResumeSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsResumeFailed', result));
    },
    "TtsPlugin",
    "resume",
    []
    );
};

tts.prototype.restart = function() {
    exec(function(result){
        document.dispatchEvent(new CustomEvent('ttsRestartSuccess', result));
    },
    function(error){
        document.dispatchEvent(new CustomEvent('ttsRestartFailed', result));
    },
    "TtsPlugin",
    "restart",
    []
    );
};

var tts = new tts();
module.exports = tts;<|endoftext|>


<commit_before>ButtonAdapter = {
	name: 'ButtonAdapter',

	handles : [
		'button'
	],

	toHTML: function(data) {
		var $div = $('<div>');
		var $a = $('<a>').appendTo($div);
		/*var $clear = */$('<div>', { style: 'clear: both' }).appendTo($div);
		$a.html(data.text);
		$a.attr('href', data.href);
		$a.attr('data-st-user-href', data['user-href']);
		// we dont use $a.css('style') because css method use computed style and could change all the style attr of the elem.
		$a.attr('style', 'overflow: hidden; display: block; line-height: normal; box-sizing: border-box; border-style: solid; text-align: center; margin: 0 auto;');
		$a.find('> *').css('margin', '0');

		Object.keys(data).forEach(function(e) {
			if (!/^css\-/.test(e))
				return;
			var cssKey = e.replace(/^css-/, '');
			var cssVal = data[e];
			$a.attr('style', $a.attr('style') + cssKey + ':' + cssVal + ';');
		});

		return $div.html();
	},

	toJSON: function(html) {
		var $a = $(html);

		var data = {};
		data.format = 'html';
		data.text = $a.html();
		data.href = $a.attr('href');
		data['user-href'] = $a.attr('data-st-user-href');
		$a.attr('style').split(';')
			.filter(function(elem) {
				return elem.indexOf(':') != -1
			})
			.forEach(function (e) {
				var v = e.split(':');
				var cssAttr = v[0].replace(/\s/g, '');
				var cssVal = v[1].trim();
				data['css-' + cssAttr] = cssVal;
			});

		return data;
	}
}

module.exports = ButtonAdapter;<commit_msg>ButtonAdapter: If href is empty, don't set the attribute.<commit_after>ButtonAdapter = {
	name: 'ButtonAdapter',

	handles : [
		'button'
	],

	toHTML: function(data) {
		var $div = $('<div>');
		var $a = $('<a>').appendTo($div);
		/*var $clear = */$('<div>', { style: 'clear: both' }).appendTo($div);
		$a.html(data.text);
		if (data.href && data.href.length > 0)
			$a.attr('href', data.href);
		$a.attr('data-st-user-href', data['user-href']);
		// we dont use $a.css('style') because css method use computed style and could change all the style attr of the elem.
		$a.attr('style', 'overflow: hidden; display: block; line-height: normal; box-sizing: border-box; border-style: solid; text-align: center; margin: 0 auto;');
		$a.find('> *').css('margin', '0');

		Object.keys(data).forEach(function(e) {
			if (!/^css\-/.test(e))
				return;
			var cssKey = e.replace(/^css-/, '');
			var cssVal = data[e];
			$a.attr('style', $a.attr('style') + cssKey + ':' + cssVal + ';');
		});

		return $div.html();
	},

	toJSON: function(html) {
		var $a = $(html);

		var data = {};
		data.format = 'html';
		data.text = $a.html();
		data.href = $a.attr('href');
		data['user-href'] = $a.attr('data-st-user-href');
		$a.attr('style').split(';')
			.filter(function(elem) {
				return elem.indexOf(':') != -1
			})
			.forEach(function (e) {
				var v = e.split(':');
				var cssAttr = v[0].replace(/\s/g, '');
				var cssVal = v[1].trim();
				data['css-' + cssAttr] = cssVal;
			});

		return data;
	}
}

module.exports = ButtonAdapter;<|endoftext|>


<commit_before>/*
Class: AjaxPager
Load content via link click, slide it in to replace previously loaded content if it exists, or into place if none exists.

-! not generalized enough

Styles:
	``` scss
	.ajaxLoaderContent{
		margin-bottom: 2em;
		*overflow: hidden;
		position: relative;
	}
	.ajaxLoaderWrap{
		overflow: hidden;
	}
	.ajaxPage{
		left: 0;
		top: 0;
		.ajaxLoaderWrap-initialized &{
			position: absolute;
			width: 100%;
		}
	}
	```

*/
/* global define */
define([
	'jquery'
	,'tmclasses/tmclasses'
	,'tmlib/fx/AnimationTransition'
],function(
	jQuery
	,tmclasses
	,_AnimationTransition
){
	var __getElmDimensions = function(_elm){
		var _data = {};
		if(_elm){
			var _originalCSS = {
				position: _elm.css('position'),
				visibility: _elm.css('visibility')
			};

			_elm.css({position: 'absolute', visibility: 'hidden'});
			_data.width = _elm.outerWidth();
			_data.height = _elm.outerHeight();
			_elm.css(_originalCSS);
		}

		return _data;
	};

	var AjaxPager = tmclasses.create({
		init: function(){
			var _self = this;
			_self.__parent(arguments);

			if(!_self.transition){
				_self.transition = new _AnimationTransition({
					stylesBefore: [
						null
						,null
						,function(){
							_self.contentWidth = _self.content.outerWidth();
							return {
								display: 'block'
								,left: _self.contentWidth + 'px'
							};
						}
					]
					,stylesTransition: [
						function($elm, _opts){
							var _height = _self.getHiddenElementHeight(_opts.elements[2]);
							return {
								height: _height
							};
						}
						,function(){
							return {
								left: '-' + _self.contentWidth + 'px'
							};
						}
						,{left: 0}
					]
				});
			}
			_self.transition.sub('after', function(_opts){
				_self.currentPage = _opts.elements[2];
			});

			_self.activate();
		}
		,properties: {
			activate: function(){
				var _self = this;
				if(_self.elm){
					if(!_self.currentPage){
						_self.currentPage = _self.elm.find('.ajaxPage');
					}
					if(!_self.currentPage.length){
						_self.currentPage = undefined;
					}
					if(!_self._loadedPages){
						_self._loadedPages = {};
					}
					//$ajaxLoaderHeading = $ajaxLoaderWrap.find('.ajaxLoaderHeading');
					if(!_self.content){
						_self.content = _self.elm.find('.ajaxLoaderContent');
					}
					if(!_self.content.length){
						_self.content = jQuery('
');
						_self.content.hide();
						_self.elm.prepend(_self.content);
						//$ajaxLoaderHeading.after(_self.content);
					}
					if(_self.currentPage){
						_self.content.css('height', _self.currentPage.outerHeight());
					}

					_self.elm.on('click', '.ajaxLoaderAction', function(_event){
						_event.preventDefault();
						var _action = jQuery(this);
						var _url = _action.attr('href');
						if(_url !== _self.currentURL){
							_self.showPage(_url);
							_self.currentURL = _url;
						}
					});

					//--listen to browser width change, reset height of container if needed
					if(_self.responsiveHandler){
						_self.responsiveHandler.sub('resize', function(){
							if(_self.currentPage){
								var _height = _self.getHiddenElementHeight(_self.currentPage);
								_self.content.height(_height);
							}
						});
					}

					//--add initialized state class
					_self.elm.addClass('ajaxLoaderWrap-initialized');
				}
			}
			,content: undefined
			,_contentWidth: undefined
			,currentPage: undefined
			,currentURL: undefined
			,elm: undefined
			,getHiddenElementHeight: function($elm){
				var _height = __getElmDimensions($elm).height;
				return _height;
			}
			,_loadedPages: undefined
			,responsiveHandler: undefined
			,getPage: function(_url){
				var _self = this;
				var _page;
				var _promise = new jQuery.Deferred();
				if(typeof _self._loadedPages[_url] !== 'undefined'){
					_page = _self._loadedPages[_url];
					_promise.resolve(_page);
				}else if(_url.charAt(0) === '#'){
					_page = jQuery(_url);
					_promise.resolve(_page);
				}else{
					jQuery.ajax({
						url: _url
						,success: function(_data){
							if(typeof _data !== 'object'){
								_data = jQuery.parseJSON(_data);
							}
							if(_data.content){
								var $item = jQuery('
' + _data.content + '
');

								//--'preload' images
								//$item.find('img').each(function(){
								//	var $img = jQuery('');
								//	$img[0].src = this.src;
								//	$body.append($img);
								//	$img.remove();
								//});

								$item.hide();
								_self.content.append($item);
								_self._loadedPages[_url] = $item;
								_promise.resolve($item);
							}
						}
					});
				}
				return _promise;
			}
			,_renderPage: function(_page, _url){
				var _self = this;
				if(_self.currentPage){
					_self.transition.transitionForElements({
						elements: [
							_self.content
							,_self.currentPage
							,_page
						]
					});
					//_self.currentPage.fadeOut(function(){
					//	_page.fadeIn(function(){
					//		_self.currentPage = _page;
					//	});
					//});
				}else{
					_page.show();
					_self.content.show();
					var _height = _self.getHiddenElementHeight(_page);
					_self.content.animate({height: _height}, function(){
						_self.currentPage = _page;
					});
				}
			}
			,showPage: function(_url){
				var _self = this;
				this.getPage(_url).done(function(_page){
					if(_page){
						var _img = _page.find('img');
						if(_img.length && (_img.height() === 0 || (parseInt(_img.attr('height'),10) !== parseInt(_img.height(),10)))){
							_img.load(function(){
								_self._renderPage(_page, _url);
							});
						}else{
							_self._renderPage(_page, _url);
						}
						if(_url){
							_self.currentURL = _url;
						}
					}
				});
			}
			,transition: undefined
		}
	});
	return AjaxPager;
});
<commit_msg>ui/AjaxPager: fix 1px overlap of pages issue in IE !BUGFIX<commit_after>/*
Class: AjaxPager
Load content via link click, slide it in to replace previously loaded content if it exists, or into place if none exists.

-! not generalized enough

Styles:
	``` scss
	.ajaxLoaderContent{
		margin-bottom: 2em;
		*overflow: hidden;
		position: relative;
	}
	.ajaxLoaderWrap{
		overflow: hidden;
	}
	.ajaxPage{
		left: 0;
		top: 0;
		.ajaxLoaderWrap-initialized &{
			position: absolute;
			width: 100%;
		}
	}
	```

*/
/* global define */
define([
	'jquery'
	,'tmclasses/tmclasses'
	,'tmlib/fx/AnimationTransition'
],function(
	jQuery
	,tmclasses
	,_AnimationTransition
){
	var __getElmDimensions = function(_elm){
		var _data = {};
		if(_elm){
			var _originalCSS = {
				position: _elm.css('position'),
				visibility: _elm.css('visibility')
			};

			_elm.css({position: 'absolute', visibility: 'hidden'});
			_data.width = _elm.outerWidth();
			_data.height = _elm.outerHeight();
			_elm.css(_originalCSS);
		}

		return _data;
	};

	var AjaxPager = tmclasses.create({
		init: function(){
			var _self = this;
			_self.__parent(arguments);

			if(!_self.transition){
				_self.transition = new _AnimationTransition({
					stylesBefore: [
						null
						,null
						,function(){
							_self.contentWidth = _self.content.outerWidth() + 1; //-# add 1 to prevent overlap in IE
							return {
								display: 'block'
								,left: _self.contentWidth + 'px'
							};
						}
					]
					,stylesTransition: [
						function($elm, _opts){
							var _height = _self.getHiddenElementHeight(_opts.elements[2]);
							return {
								height: _height
							};
						}
						,function(){
							return {
								left: '-' + _self.contentWidth + 'px'
							};
						}
						,{left: 0}
					]
				});
			}
			_self.transition.sub('after', function(_opts){
				_self.currentPage = _opts.elements[2];
			});

			_self.activate();
		}
		,properties: {
			activate: function(){
				var _self = this;
				if(_self.elm){
					if(!_self.currentPage){
						_self.currentPage = _self.elm.find('.ajaxPage');
					}
					if(!_self.currentPage.length){
						_self.currentPage = undefined;
					}
					if(!_self._loadedPages){
						_self._loadedPages = {};
					}
					//$ajaxLoaderHeading = $ajaxLoaderWrap.find('.ajaxLoaderHeading');
					if(!_self.content){
						_self.content = _self.elm.find('.ajaxLoaderContent');
					}
					if(!_self.content.length){
						_self.content = jQuery('
');
						_self.content.hide();
						_self.elm.prepend(_self.content);
						//$ajaxLoaderHeading.after(_self.content);
					}
					if(_self.currentPage){
						_self.content.css('height', _self.currentPage.outerHeight());
					}

					_self.elm.on('click', '.ajaxLoaderAction', function(_event){
						_event.preventDefault();
						var _action = jQuery(this);
						var _url = _action.attr('href');
						if(_url !== _self.currentURL){
							_self.showPage(_url);
							_self.currentURL = _url;
						}
					});

					//--listen to browser width change, reset height of container if needed
					if(_self.responsiveHandler){
						_self.responsiveHandler.sub('resize', function(){
							if(_self.currentPage){
								var _height = _self.getHiddenElementHeight(_self.currentPage);
								_self.content.height(_height);
							}
						});
					}

					//--add initialized state class
					_self.elm.addClass('ajaxLoaderWrap-initialized');
				}
			}
			,content: undefined
			,_contentWidth: undefined
			,currentPage: undefined
			,currentURL: undefined
			,elm: undefined
			,getHiddenElementHeight: function($elm){
				var _height = __getElmDimensions($elm).height;
				return _height;
			}
			,_loadedPages: undefined
			,responsiveHandler: undefined
			,getPage: function(_url){
				var _self = this;
				var _page;
				var _promise = new jQuery.Deferred();
				if(typeof _self._loadedPages[_url] !== 'undefined'){
					_page = _self._loadedPages[_url];
					_promise.resolve(_page);
				}else if(_url.charAt(0) === '#'){
					_page = jQuery(_url);
					_promise.resolve(_page);
				}else{
					jQuery.ajax({
						url: _url
						,success: function(_data){
							if(typeof _data !== 'object'){
								_data = jQuery.parseJSON(_data);
							}
							if(_data.content){
								var $item = jQuery('
' + _data.content + '
');

								//--'preload' images
								//$item.find('img').each(function(){
								//	var $img = jQuery('');
								//	$img[0].src = this.src;
								//	$body.append($img);
								//	$img.remove();
								//});

								$item.hide();
								_self.content.append($item);
								_self._loadedPages[_url] = $item;
								_promise.resolve($item);
							}
						}
					});
				}
				return _promise;
			}
			,_renderPage: function(_page, _url){
				var _self = this;
				if(_self.currentPage){
					_self.transition.transitionForElements({
						elements: [
							_self.content
							,_self.currentPage
							,_page
						]
					});
					//_self.currentPage.fadeOut(function(){
					//	_page.fadeIn(function(){
					//		_self.currentPage = _page;
					//	});
					//});
				}else{
					_page.show();
					_self.content.show();
					var _height = _self.getHiddenElementHeight(_page);
					_self.content.animate({height: _height}, function(){
						_self.currentPage = _page;
					});
				}
			}
			,showPage: function(_url){
				var _self = this;
				this.getPage(_url).done(function(_page){
					if(_page){
						var _img = _page.find('img');
						if(_img.length && (_img.height() === 0 || (parseInt(_img.attr('height'),10) !== parseInt(_img.height(),10)))){
							_img.load(function(){
								_self._renderPage(_page, _url);
							});
						}else{
							_self._renderPage(_page, _url);
						}
						if(_url){
							_self.currentURL = _url;
						}
					}
				});
			}
			,transition: undefined
		}
	});
	return AjaxPager;
});
<|endoftext|>


<commit_before>function GameManager(size, InputManager, Actuator, StorageManager) {
  this.size           = size; // Size of the grid
  this.inputManager   = new InputManager;
  this.storageManager = new StorageManager;
  this.actuator       = new Actuator;

  this.startTiles     = 2;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.storageManager.clearGameState();
  this.actuator.continueGame(); // Clear the game won/lost message
  this.setup();
};

// Keep playing after winning (allows going over 2048)
GameManager.prototype.keepPlaying = function () {
  this.keepPlaying = true;
  this.actuator.continueGame(); // Clear the game won/lost message
};

// Return true if the game is lost, or has won and the user hasn't kept playing
GameManager.prototype.isGameTerminated = function () {
  return this.over || (this.won && !this.keepPlaying);
};

// Set up the game
GameManager.prototype.setup = function () {
  var previousState = this.storageManager.getGameState();

  // Reload the game from a previous game if present
  if (previousState) {
    this.grid        = new Grid(previousState.grid.size,
                                previousState.grid.cells); // Reload grid
    this.score       = previousState.score;
    this.over        = previousState.over;
    this.won         = previousState.won;
    this.keepPlaying = previousState.keepPlaying;
  } else {
    this.grid        = new Grid(this.size);
    this.score       = 0;
    this.over        = false;
    this.won         = false;
    this.keepPlaying = false;

    // Add the initial tiles
    this.addStartTiles();
  }

  // Update the actuator
  this.actuate();
};

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = Math.random() < 0.9 ? 4096 : 8192;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
  }
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
  if (this.storageManager.getBestScore() < this.score) {
    this.storageManager.setBestScore(this.score);
  }

  // Clear the state when the game is over (game over only, not win)
  if (this.over) {
    this.storageManager.clearGameState();
  } else {
    this.storageManager.setGameState(this.serialize());
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.storageManager.getBestScore(),
    terminated: this.isGameTerminated()
  });

};

// Represent the current game as an object
GameManager.prototype.serialize = function () {
  return {
    grid:        this.grid.serialize(),
    score:       this.score,
    over:        this.over,
    won:         this.won,
    keepPlaying: this.keepPlaying
  };
};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
  this.grid.cells[tile.x][tile.y] = null;
  this.grid.cells[cell.x][cell.y] = tile;
  tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
  // 0: up, 1: right, 2: down, 3: left
  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && next.value === tile.value && !next.mergedFrom) {
          var merged = new Tile(positions.next, tile.value * 2);
          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);

          // Converge the two tiles' positions
          tile.updatePosition(positions.next);

          // Update the score
          self.score += merged.value;

          // The mighty 2048 tile
          if (merged.value === 2048) self.won = true;
        } else {
          self.moveTile(tile, positions.farthest);
        }

        if (!self.positionsEqual(cell, tile)) {
          moved = true; // The tile moved from its original cell!
        }
      }
    });
  });

  if (moved) {
    this.addRandomTile();

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1 }, // Up
    1: { x: 1,  y: 0 },  // Right
    2: { x: 0,  y: 1 },  // Down
    3: { x: -1, y: 0 }   // Left
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();

  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;

  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      tile = this.grid.cellContent({ x: x, y: y });

      if (tile) {
        for (var direction = 0; direction < 4; direction++) {
          var vector = self.getVector(direction);
          var cell   = { x: x + vector.x, y: y + vector.y };

          var other  = self.grid.cellContent(cell);

          if (other && other.value === tile.value) {
            return true; // These two tiles can be merged
          }
        }
      }
    }
  }

  return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y;
};
<commit_msg>The game should work now.<commit_after>function GameManager(size, InputManager, Actuator, StorageManager) {
  this.size           = size; // Size of the grid
  this.inputManager   = new InputManager;
  this.storageManager = new StorageManager;
  this.actuator       = new Actuator;

  this.startTiles     = 2;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.storageManager.clearGameState();
  this.actuator.continueGame(); // Clear the game won/lost message
  this.setup();
};

// Keep playing after winning (allows going over 2048)
GameManager.prototype.keepPlaying = function () {
  this.keepPlaying = true;
  this.actuator.continueGame(); // Clear the game won/lost message
};

// Return true if the game is lost, or has won and the user hasn't kept playing
GameManager.prototype.isGameTerminated = function () {
  return this.over || (this.won && !this.keepPlaying);
};

// Set up the game
GameManager.prototype.setup = function () {
  var previousState = this.storageManager.getGameState();

  // Reload the game from a previous game if present
  if (previousState) {
    this.grid        = new Grid(previousState.grid.size,
                                previousState.grid.cells); // Reload grid
    this.score       = previousState.score;
    this.over        = previousState.over;
    this.won         = previousState.won;
    this.keepPlaying = previousState.keepPlaying;
  } else {
    this.grid        = new Grid(this.size);
    this.score       = 0;
    this.over        = false;
    this.won         = false;
    this.keepPlaying = false;

    // Add the initial tiles
    this.addStartTiles();
  }

  // Update the actuator
  this.actuate();
};

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = 4096;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
  }
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
  if (this.storageManager.getBestScore() < this.score) {
    this.storageManager.setBestScore(this.score);
  }

  // Clear the state when the game is over (game over only, not win)
  if (this.over) {
    this.storageManager.clearGameState();
  } else {
    this.storageManager.setGameState(this.serialize());
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.storageManager.getBestScore(),
    terminated: this.isGameTerminated()
  });

};

// Represent the current game as an object
GameManager.prototype.serialize = function () {
  return {
    grid:        this.grid.serialize(),
    score:       this.score,
    over:        this.over,
    won:         this.won,
    keepPlaying: this.keepPlaying
  };
};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
  this.grid.cells[tile.x][tile.y] = null;
  this.grid.cells[cell.x][cell.y] = tile;
  tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
  // 0: up, 1: right, 2: down, 3: left
  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && next.value === tile.value && !next.mergedFrom) {
          var merged = new Tile(positions.next, tile.value * 2);
          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);

          // Converge the two tiles' positions
          tile.updatePosition(positions.next);

          // Update the score
          self.score += merged.value;

          // The mighty 2048 tile
          if (merged.value === 2048) self.won = true;
        } else {
          self.moveTile(tile, positions.farthest);
        }

        if (!self.positionsEqual(cell, tile)) {
          moved = true; // The tile moved from its original cell!
        }
      }
    });
  });

  if (moved) {
    this.addRandomTile();

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1 }, // Up
    1: { x: 1,  y: 0 },  // Right
    2: { x: 0,  y: 1 },  // Down
    3: { x: -1, y: 0 }   // Left
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();

  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;

  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      tile = this.grid.cellContent({ x: x, y: y });

      if (tile) {
        for (var direction = 0; direction < 4; direction++) {
          var vector = self.getVector(direction);
          var cell   = { x: x + vector.x, y: y + vector.y };

          var other  = self.grid.cellContent(cell);

          if (other && other.value === tile.value) {
            return true; // These two tiles can be merged
          }
        }
      }
    }
  }

  return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y;
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';

class TextLine extends Component {
    static defaultProps = {
        insertedText: {},
        selectedText: []
    };

    render() {
        const { text, insertedText, selectedText, active } = this.props;

        const spanStyle = {
            fontSize: 26,
            fontFamily: 'helvetica-light',
        };

        const textRanges = [];

        let start = 0;
        for (let end of Object.keys(insertedText)) {
            textRanges.push({
                text: text.substring(start, end),
            });
            textRanges.push({
                text: insertedText[end],
                type: 'insertion'
            });
            start = end;
        }

        textRanges.push({
            text: text.substring(start, text.length),
        });

        if (textRanges.length === 1 && selectedText.length > 0) {
            textRanges.length = 0;

            let start = 0;
            for (const selection of selectedText) {
                textRanges.push({
                    text: text.substring(start, selection.start),
                });
                textRanges.push({
                    text: text.substring(selection.start, selection.end),
                    type: 'selection'
                });
                start = selection.end;
            }
            textRanges.push({
                text: text.substring(start, text.length),
            });
        }

        const lineStyle = {
            marginTop: 30,
            marginBottom: 30,
            opacity: active ? 1.0 : 0.3,
        };

        return

            {textRanges.map(
                (range, i) => {
                    let style = {...spanStyle};
                    if (range.type === 'insertion') {
                        style.textDecoration = 'underline';
                        style.color = 'orange';
                    } else if (range.type === 'selection') {
                        style.borderRadius = 4;
                        style.border = 'solid 2px';
                        style.paddingLeft = 2;
                        style.paddingRight = 2;
                        style.color = 'blue';
                    }
                    return {range.text};
                }
            )}

;
    }
}

export { TextLine as default };
<commit_msg>replace *, -, / with actual operator glyphs<commit_after>import React, { Component } from 'react';

class TextLine extends Component {
    static defaultProps = {
        insertedText: {},
        selectedText: []
    };

    render() {
        const { text, insertedText, selectedText, active } = this.props;

        const spanStyle = {
            fontSize: 26,
            fontFamily: 'helvetica-light',
        };

        const textRanges = [];

        let start = 0;
        for (let end of Object.keys(insertedText)) {
            textRanges.push({
                text: text.substring(start, end),
            });
            textRanges.push({
                text: insertedText[end],
                type: 'insertion'
            });
            start = end;
        }

        textRanges.push({
            text: text.substring(start, text.length),
        });

        if (textRanges.length === 1 && selectedText.length > 0) {
            textRanges.length = 0;

            let start = 0;
            for (const selection of selectedText) {
                textRanges.push({
                    text: text.substring(start, selection.start),
                });
                textRanges.push({
                    text: text.substring(selection.start, selection.end),
                    type: 'selection'
                });
                start = selection.end;
            }
            textRanges.push({
                text: text.substring(start, text.length),
            });
        }

        const lineStyle = {
            marginTop: 30,
            marginBottom: 30,
            opacity: active ? 1.0 : 0.3,
        };

        return

            {textRanges.map(
                (range, i) => {
                    let style = {...spanStyle};
                    if (range.type === 'insertion') {
                        style.textDecoration = 'underline';
                        style.color = 'orange';
                    } else if (range.type === 'selection') {
                        style.borderRadius = 4;
                        style.border = 'solid 2px';
                        style.paddingLeft = 2;
                        style.paddingRight = 2;
                        style.color = 'blue';
                    }
                    const text = range.text
                        .replace('/', '÷')
                        .replace('-', '–')
                        .replace('*', '·');
                    return {text};
                }
            )}

;
    }
}

export { TextLine as default };
<|endoftext|>


<commit_before>var ImageLoader = new Class({
	Implements: [Events, Options],

	options: {
		// Number of concurrent downloads
		concurrentDownloads: 4,

		// Name of the "img" elements' data attribute that stores the image URL
		dataAttribute: "data-src",

		// Delay between loading two images (in milliseconds)
		delay: 0,

		// Array of "img" elements whose content we lazy load
		elements: []
	},

	initialize: function(options) {
		// Merge provided options with default options
		this.setOptions(options);

		// Index of the image that is loaded next
		this.index = 0;

		// Number of loaded images
		this.loadedImagesCount = 0;
	},

	/**
	 * Starts the image loader.
	 */
	run: function() {
		// Load images concurrently and in order
		for (var i = 0; i < this.options.concurrentDownloads; i++) {
			this.loadNextImage();
		}
	},

	/**
	 * Loads the next image that is not loaded or loading yet.
	 */
	loadNextImage: function() {
		this.loadImage(this.index++);
	},

	/**
	 * Loads a particular image.
	 *
	 * Fires a class-wide "load" event if the image loaded, otherwise an "error"
	 * event. Also fires a class-wide "complete" event if it was the last image
	 * to load.
	 * @param integer index Position in the array "this.options.elements"
	 */
	loadImage: function(index) {
		if (index >= this.options.elements.length) {
			return;
		}

		var image = new Image();

		image.addEvent("error", function() {
			// Relay the image "error" event
			this.fireEvent("error", this.options.elements[index]);

			// If this was the last image to load, fire the "complete" event
			if (++this.loadedImagesCount === this.options.elements.length) {
				this.fireEvent("complete");
				return;
			}

			this.loadNextImage.bind(this).delay(this.options.delay);
		}.bind(this));

		image.addEvent("load", function(event) {
			// Relay the image "load" event
			this.fireEvent("load", [this.options.elements[index], event]);

			// If this was the last image to load, fire the "complete" event
			if (++this.loadedImagesCount === this.options.elements.length) {
				this.fireEvent("complete");
				return;
			}

			this.loadNextImage.bind(this).delay(this.options.delay);
		}.bind(this));

		// Start loading the image
		image.src = this.options.elements[index].getProperty(this.options.dataAttribute);
	}
});

// Example usage
window.addEvent("domready", function() {
	var imageLoader = new ImageLoader({
		elements: $$(".image")
	});

	imageLoader.addEvent("complete", function() {
		console.log("Loading images completed.");
	});

	imageLoader.addEvent("error", function(element) {
		console.log("Image failed to load: " + element.getProperty(this.options.dataAttribute));
		element.getParent().destroy();
	});

	imageLoader.addEvent("load", function(element) {
		console.log("Image loaded: " + element.getProperty(this.options.dataAttribute));

		element.setProperty("src", element.getProperty(this.options.dataAttribute));
		element.removeProperty(this.options.dataAttribute);
	});

	imageLoader.run();
});<commit_msg>Images below the fold are not loaded until they become visible (e.g. through scrolling).<commit_after>var ImageLoader = new Class({
	Implements: [Events, Options],

	Binds: ["loadConcurrently"],

	options: {
		// Name of the "img" elements' data attribute that stores the image URL
		dataAttribute: "data-src",

		// Delay between loading two images (in milliseconds)
		delay: 0,

		// Array of "img" elements whose content we lazy load
		elements: [],

		// Maximum number of concurrent downloads
		maxConcurrentDownloads: 4,

		// Only load images that are not further below the fold than this (in px)
		maxDistance: 250
	},

	initialize: function(options) {
		// Merge provided options with default options
		this.setOptions(options);

		// Index of the image that is loaded next
		this.index = 0;

		// Number of loaded images
		this.loadedImagesCount = 0;

		// Number of running downloads
		this.concurrentDownloads = 0;

		// Timeout IDs of delayed functions (queued downloads)
		this.timeoutIds = [];
	},

	/**
	 * Starts the image loader.
	 */
	run: function() {
		this.loadConcurrently();

		window.addEvent("resize", this.loadConcurrently);
		window.addEvent("scroll", this.loadConcurrently);
	},

	/**
	 * Loads images concurrently and in order.
	 */
	loadConcurrently: function() {
		// Cancel any queued downloads
		for (var i = 0; i < this.timeoutIds.length; i++) {
			clearTimeout(this.timeoutIds[i]);
			this.timeoutIds.splice(i, 1);
		}

		// Start downloads
		for (var i = this.concurrentDownloads; i < this.options.maxConcurrentDownloads; i++) {
			this.loadNextImage();
		}
	},

	/**
	 * Loads the next image that is not loaded or loading yet.
	 */
	loadNextImage: function() {
		if (this.index >= this.options.elements.length) {
			return;
		}

		var fold = window.getSize().y + window.getScroll().y;

		if (this.options.elements[this.index].getPosition().y > fold + this.options.maxDistance) {
			return;
		}

		this.loadImage(this.index++);
	},

	/**
	 * Loads a particular image.
	 *
	 * Fires a class-wide "load" event if the image loaded, otherwise an "error"
	 * event. Also fires a class-wide "complete" event if it was the last image
	 * to load.
	 * @param integer index Position in the array "this.options.elements"
	 */
	loadImage: function(index) {
		var image = new Image();

		image.addEvent("error", this.imageEventHandler.bind(this, "error", this.options.elements[index]));
		image.addEvent("load", this.imageEventHandler.bind(this, "load", this.options.elements[index]));

		this.concurrentDownloads++;

		// Start loading the image
		image.src = this.options.elements[index].getProperty(this.options.dataAttribute);
	},

	imageEventHandler: function(eventName, imageElement) {
		this.concurrentDownloads--;

		// Relay the image event
		this.fireEvent(eventName, imageElement);

		// If this was the last image to load, fire the "complete" event
		if (++this.loadedImagesCount === this.options.elements.length) {
			window.removeEvent("resize", this.loadConcurrently);
			window.removeEvent("scroll", this.loadConcurrently);

			this.fireEvent("complete");
			return;
		}

		var timeoutId = this.loadNextImage.bind(this).delay(this.options.delay);
		this.timeoutIds.push(timeoutId);
	}
});

// Example usage
window.addEvent("domready", function() {
	var imageLoader = new ImageLoader({
		elements: $$(".image")
	});

	imageLoader.addEvent("complete", function() {
		console.log("Loading images completed.");
	});

	imageLoader.addEvent("error", function(element) {
		console.log("Image failed to load: " + element.getProperty(this.options.dataAttribute));
		element.getParent().destroy();
	});

	imageLoader.addEvent("load", function(element) {
		console.log("Image loaded: " + element.getProperty(this.options.dataAttribute));

		element.setProperty("src", element.getProperty(this.options.dataAttribute));
		element.removeProperty(this.options.dataAttribute);
	});

	imageLoader.run();
});<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Application desktop for a sprint.ly product.
 *
 * @author kyawtun@yathit.com (Kyaw Tun)
 */

/**
 * Sprint.ly product workspace.
 * @constructor
 */
app.Workspace = function(product) {
  /**
   * Current product.
   * @type {sprintly.Product}
   * @protected
   */
  this.product = product;

  /**
   * @protected
   * @type {HTMLElement}
   */
  this.root = document.createElement('div');

  this.toolbar = new app.ui.Toolbar();

  var item = new app.model.Entity(product.Item);
  var people = new app.model.Entity(product.People);
  var itemList = new sprintly.EntityList(product, sprintly.Entity.ITEM);
  var peopleList = new sprintly.EntityList(product, sprintly.Entity.PEOPLE);

  this.pages = [
    new app.ui.page.Doc(),
    new app.ui.page.Search(),
    new app.ui.page.Entity(item, new app.ui.page.ItemRenderer()),
    new app.ui.page.Entity(people, new app.ui.page.PeopleRenderer()),
    new app.ui.page.EntityList(itemList, new app.ui.page.ItemListRenderer()),
    new app.ui.page.EntityList(peopleList, new app.ui.page.PeopleListRenderer())
  ];

};

/**
 * Render desktop.
 * @param {Element} el
 */
app.Workspace.prototype.render = function(el) {
  el.appendChild(this.root);
  this.toolbar.render(this.root);
  for (var i = 0; i < this.pages.length; i++) {
    this.pages[i].render(this.root);
  }

  var me = this;
  window.addEventListener('hashchange', function(e) {
    me.route(location.hash);
  });

  this.route(location.hash);
};

/**
 * Switch to a page.
 * @param {string} name page name.
 * @param {string} id query parameter.
 * @param {Object} filter query parameter.
 * @return {boolean}
 */
app.Workspace.prototype.switchPage = function(name, id, filter) {
  var ok = false;
  var pageName = id ? name : name + '-list';
  for (var i = 0; i < this.pages.length; i++) {
    var page = this.pages[i];
    var show = page.name == pageName;
    if (show) {
      ok = true;
      googleAnalytics('send', 'pageView', {'pageName': pageName});
    }
    page.setShown(show, id, filter);
  }
  return ok;
};

app.Workspace.prototype.goHome = function() {
  location.hash = 'items';
};

/**
 * @param {string} hash
 */
app.Workspace.prototype.route = function(hash) {
  var m = hash.match(/^#([^\/]+)\/?([^@]*)@?(.*)/);
  if (m) {
    var filter = {};
    if (m[3]) {
      var fs = m[3].split(',');
      for (var i = 0; i < fs.length; i++) {
        var p = fs[i].split('=');
        filter[p[0]] = p[1];
      }
    }
    var ok = this.switchPage(m[1], m[2], filter);
    if (!ok) {
      this.goHome();
    }
  } else {
    console.log('unknwon hash ' + hash);
    this.goHome();
  }
};

<commit_msg>adding filter<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Application desktop for a sprint.ly product.
 *
 * @author kyawtun@yathit.com (Kyaw Tun)
 */

/**
 * Sprint.ly product workspace.
 * @constructor
 */
app.Workspace = function(product) {
  /**
   * Current product.
   * @type {sprintly.Product}
   * @protected
   */
  this.product = product;

  /**
   * @protected
   * @type {HTMLElement}
   */
  this.root = document.createElement('div');

  this.toolbar = new app.ui.Toolbar();

  var item = new app.model.Entity(product.Item);
  var people = new app.model.Entity(product.People);
  var itemList = new sprintly.EntityList(product, sprintly.Entity.ITEM);
  var peopleList = new sprintly.EntityList(product, sprintly.Entity.PEOPLE);

  this.pages = [
    new app.ui.page.Doc(),
    new app.ui.page.Search(),
    new app.ui.page.Entity(item, new app.ui.page.ItemRenderer()),
    new app.ui.page.Entity(people, new app.ui.page.PeopleRenderer()),
    new app.ui.page.EntityList(itemList, new app.ui.page.ItemListRenderer()),
    new app.ui.page.EntityList(peopleList, new app.ui.page.PeopleListRenderer())
  ];

};

/**
 * Render desktop.
 * @param {Element} el
 */
app.Workspace.prototype.render = function(el) {
  el.appendChild(this.root);
  this.toolbar.render(this.root);
  for (var i = 0; i < this.pages.length; i++) {
    this.pages[i].render(this.root);
  }

  var me = this;
  window.addEventListener('hashchange', function(e) {
    me.route(location.hash);
  });

  this.route(location.hash);
};

/**
 * Switch to a page.
 * @param {string} name page name.
 * @param {string} id query parameter.
 * @param {Object} filter query parameter.
 * @return {boolean}
 */
app.Workspace.prototype.switchPage = function(name, id, filter) {
  var ok = false;
  var pageName = id ? name : name + '-list';
  for (var i = 0; i < this.pages.length; i++) {
    var page = this.pages[i];
    var show = page.name == pageName;
    if (show) {
      ok = true;
      googleAnalytics('send', 'pageView', {'pageName': pageName});
    }
    page.setShown(show, id, filter);
  }
  return ok;
};

app.Workspace.prototype.goHome = function() {
  location.hash = 'items';
};

/**
 * @param {string} hash
 */
app.Workspace.prototype.route = function(hash) {
  var m = hash.match(/^#([^\/]+)\/?([^@]*)@?(.*)/);
  if (m) {
    var filter = {};
    if (m[3]) {
      try {
        filter = JSON.parse(m[3]);
      } catch (e) {
        filter = {};
      }
    }
    var ok = this.switchPage(m[1], m[2], filter);
    if (!ok) {
      this.goHome();
    }
  } else {
    console.log('unknwon hash ' + hash);
    this.goHome();
  }
};

<|endoftext|>


<commit_before>import { tidyUpSequenceData } from "ve-sequence-utils";
// import cleanSequenceData from "./utils/cleanSequenceData";

export default function updateEditor(
  store,
  editorName,
  initialValues = {},
  extraMeta = {}
) {
  const { sequenceData = {}, ...rest } = initialValues;
  const initialValuesToUse = {
    ...rest,
    ...(sequenceData && {
      sequenceData: tidyUpSequenceData(sequenceData, {
        //if we have sequence data coming in make sure to tidy it up for the user :)
        annotationsAsObjects: true
      })
    })
  };

  store.dispatch({
    type: "VECTOR_EDITOR_UPDATE",
    payload: initialValuesToUse,
    meta: {
      editorName,
      ...extraMeta
    }
  });
}
<commit_msg>fixing issue with update editor<commit_after>import { tidyUpSequenceData } from "ve-sequence-utils";
// import cleanSequenceData from "./utils/cleanSequenceData";

export default function updateEditor(
  store,
  editorName,
  initialValues = {},
  extraMeta = {}
) {
  const { sequenceData, ...rest } = initialValues;
  const initialValuesToUse = {
    ...rest,
    ...(sequenceData && {
      sequenceData: tidyUpSequenceData(sequenceData, {
        //if we have sequence data coming in make sure to tidy it up for the user :)
        annotationsAsObjects: true
      })
    })
  };

  store.dispatch({
    type: "VECTOR_EDITOR_UPDATE",
    payload: initialValuesToUse,
    meta: {
      editorName,
      ...extraMeta
    }
  });
}
<|endoftext|>