<commit_before>export default class {
    constructor(fileURL){
        this._fileURL = fileURL;
        this._loaded = false;
        this._buffer = null;
    }

    setup(){
        return new Promise((resolve, reject) => {
            try {
                this._context = new AudioContext();
                console.debug("audio context created");
                resolve();
            } catch (e) {
                reject(new Error("can't create AudioContext"));
                return;
            }
        }).then(() => {
            return this._loadBuffer(this._fileURL)
        }).then(() => {
            this._loaded = true;
        })
    }

    play(){
        console.debug("playing sound");
        const source = this._context.createBufferSource();
        source.buffer = this._buffer;
        source.connect(this._context.destination);
        source.start(0);
    }

    _loadBuffer(){
        const request = new XMLHttpRequest();
        request.open('GET', this._fileURL , true);
        request.responseType = 'arraybuffer';

        return new Promise((resolve, reject) => {
            request.onload = () => {
                this._context.decodeAudioData(request.response, (buffer) => {
                    this._buffer = buffer;
                    resolve();
                }, (e) => {
                    reject(e);
                });
            };
            request.send();
        })
    }
}
<commit_msg>Support Safari<commit_after>export default class {
    constructor(fileURL){
        this._fileURL = fileURL;
        this._loaded = false;
        this._buffer = null;
    }

    setup(){
        return new Promise((resolve, reject) => {
            try {
                const AudioContext = window.AudioContext || window.webkitAudioContext;
                this._context = new AudioContext();
                console.debug("audio context created");
                resolve();
            } catch (e) {
                reject(new Error("can't create AudioContext"));
                return;
            }
        }).then(() => {
            return this._loadBuffer(this._fileURL)
        }).then(() => {
            this._loaded = true;
        })
    }

    play(){
        console.debug("playing sound");
        const source = this._context.createBufferSource();
        source.buffer = this._buffer;
        source.connect(this._context.destination);
        source.start(0);
    }

    _loadBuffer(){
        const request = new XMLHttpRequest();
        request.open('GET', this._fileURL , true);
        request.responseType = 'arraybuffer';

        return new Promise((resolve, reject) => {
            request.onload = () => {
                this._context.decodeAudioData(request.response, (buffer) => {
                    this._buffer = buffer;
                    resolve();
                }, (e) => {
                    reject(e);
                });
            };
            request.send();
        })
    }
}
<|endoftext|>


<commit_before>import $ from 'jquery';
import * as Backbone from 'backbone';
import Events from '../helpers/backbone-events';

class SearchBoxView extends Backbone.View {

  get el() { return '#search-box'; }

  get events() {
    return {
      'submit form': 'sendQuery'
    }
  }

  get query() {
    return $('#search-box input').val();
  }

  initialize() {
    this.listenTo(Events, 'search:noQuery', this.handleEmptyQuery);
  }

  sendQuery() {
    if( this.query !== '' ) {
      dispatcher.trigger('router:go', ('search/?q=' + this.query));
    }
  handleEmptyQuery() {
    window.console.log('query was empty');
  }

}

export default SearchBoxView;
<commit_msg>Remove unneeded event for search box<commit_after>import $ from 'jquery';
import * as Backbone from 'backbone';
import Events from '../helpers/backbone-events';

class SearchBoxView extends Backbone.View {

  get el() { return '#search-box'; }

  get events() {
    return {
      'submit form': 'sendQuery'
    }
  }

  get query() {
    return $('#search-box input').val();
  }

  initialize() {
    this.listenTo(Events, 'search:noQuery', this.handleEmptyQuery);
  }

  handleEmptyQuery() {
    window.console.log('query was empty');
  }

}

export default SearchBoxView;
<|endoftext|>


<commit_before>(function () {

    "use strict";

    describe("Styled ModelTable", function () {

        var dom = null;

        beforeEach(function () {
            dom = document.createElement('div');
            document.body.appendChild(dom);
        });

        afterEach(function () {
            if (dom != null) {
                dom.remove();
                dom = null;
            }
        });

        it("Test 0 number gets added", function () {
            var columns = [
                {field: "test", "label": "TestName", sortable: false, type: "number"},
            ];
            //Default options
            var options = {};
            //Create the table
            var table = new StyledElements.ModelTable(columns, options);

            //Create and push the data
            var data = [
                {test: 0}
            ];
            var keys = Object.keys(data[0]);
            table.source.changeElements(data);

            expect(table.columnsCells[0][0].innerHTML).toBe("0");
        });
    });
})();<commit_msg>More tests<commit_after>(function () {

    "use strict";

    describe("Styled ModelTable", function () {

        var dom = null;

        beforeEach(function () {
            dom = document.createElement('div');
            document.body.appendChild(dom);
        });

        afterEach(function () {
            if (dom != null) {
                dom.remove();
                dom = null;
            }
        });

        it("ModelTable should be created", function () {
            var columns = [
                {field: "test", "label": "TestName", type: "string"}
            ];
            //Default options
            var options = {};
            //Create the table
            var table = new StyledElements.ModelTable(columns, options);

            expect(table).not.toBe(null);
        });

        it("data should be added to the model tables", function () {
            var columns = [
                {field: "test", "label": "TestName", sortable: false, type: "string"},
                {field: "test2", "label": "TestName", sortable: false, type: "string"}
            ];
            //Default options
            var options = {};
            //Create the table
            var table = new StyledElements.ModelTable(columns, options);

            //Create and push the data
            var data = [
                {test: "Hello", test2: "world"},
                {test: "Bye", test2: "5"}
            ];
            var keys = Object.keys(data[0]);
            table.source.changeElements(data);

            var cols = table.columnsCells;

            //Check data was added
            for (var i = 0; i< cols.length; i++) {
                for (var j = 0; j < cols[i].length; j++) {
                    expect(table.columnsCells[i][j].innerHTML).toBe(data[j][keys[i]]);
                }
            }
        });

        it("Test 0 number gets added", function () {
            var columns = [
                {field: "test", "label": "TestName", sortable: false, type: "number"}
            ];
            //Default options
            var options = {};
            //Create the table
            var table = new StyledElements.ModelTable(columns, options);

            //Create and push the data
            var data = [
                {test: 0}
            ];
            table.source.changeElements(data);

            expect(table.columnsCells[0][0].innerHTML).toBe("0");
        });

        it("Data should be able to be sorted", function () {
            var columns = [
                {field: "test", "label": "TestName", sortable: true, type: "number"},
                {field: "test2", "label": "TestName", sortable: true, type: "number"}
            ];
            //Default options
            var options = {
                initialSortColumn: 0
            };
            //Create the table
            var table = new StyledElements.ModelTable(columns, options);

            //Create and push the data
            var data = [
                {test: 2, test2: 1},
                {test: 1, test2: 2}
            ];
            table.source.changeElements(data);

            //Check if data was sorted by default
            expect(table.columnsCells[0][0].innerHTML).toBe("1");
            expect(table.columnsCells[1][0].innerHTML).toBe("2");
            expect(table.columnsCells[0][1].innerHTML).toBe("2");
            expect(table.columnsCells[1][1].innerHTML).toBe("1");

            //Change the sort order
            table.pSortByColumn(0, true);

            expect(table.columnsCells[0][0].innerHTML).toBe("2");
            expect(table.columnsCells[1][0].innerHTML).toBe("1");
            expect(table.columnsCells[0][1].innerHTML).toBe("1");
            expect(table.columnsCells[1][1].innerHTML).toBe("2");

        });

        it("Test selecting", function () {
            var columns = [
                {field: "test", "label": "TestName", sortable: false, type: "number"}
            ];
            //Default options
            var options = {};
            //Create the table
            var table = new StyledElements.ModelTable(columns, options);

            //Create and push the data
            var data = [
                {test: "hello world"},
                {test: "bye world"},

            ];
            table.source.changeElements(data);

            //Select first row
            table.select(0);

            expect(table.selection.length).toBe(1);
            expect(table.selection[0]).toBe(0);

            //Select second row
            table.select(1);

            expect(table.selection.length).toBe(1);
            expect(table.selection[0]).toBe(1);

            //Select both rows
            table.select([0,1]);

            expect(table.selection.length).toBe(2);
            expect(table.selection[0]).toBe(0);
            expect(table.selection[1]).toBe(1);

            //Deselect all
            table.select(null);
            expect(table.selection.length).toBe(0);

        });

        it("Model table should be able to get resetted", function () {
            var columns = [
                {field: "test", "label": "TestName", sortable: false, type: "number"}
            ];
            //Default options
            var options = {};
            //Create the table
            var table = new StyledElements.ModelTable(columns, options);

            //Create and push the data
            var data = [
                {test: "hello world"}
            ];
            table.source.changeElements(data);

            expect(table.columnsCells[0][0].innerHTML).toBe("hello world");

            //Wipe the data
            table.pClearTable();

            expect(table.columnsCells[0].length).toBe(0);
        });

        it("Destroy model table", function () {
                        var columns = [
                {field: "test", "label": "TestName", sortable: false, type: "number"}
            ];
            //Default options
            var options = {};
            //Create the table
            var table = new StyledElements.ModelTable(columns, options);

            //Create and push the data
            var data = [
                {test: "hello world"}
            ];
            table.source.changeElements(data);

            expect(table.columnsCells[0][0].innerHTML).toBe("hello world");

            //Wipe the data
            table.destroy();

            expect(table.columnsCells[0].length).toBe(0);
            expect(table.layout).toBe(null);
            expect(table.source).toBe(null);
        });
    });
})();<|endoftext|>


<commit_before>/*
 * ko.boostrap-validation.js
 * @version: 0.1
 * @description: A simple knockout extender that will provide validation messages for user input.
 * 				 This extender is specifically tailored for Twitter Bootstrap validation states, but
 *				 it can be modified work with your own framework/implementation quite easily.
 * @author: David East - http://www.davidea.st/
 * @license: MIT
 */

// @Extender: bootstrapValidation
// @params:
//   - target (observable): The observable being extended
// 	 - options (obj): The user defined settings for validating the observable
// 		- successMessage (string): The message to display if the input is valid
// 		- errorMessage (string): The message to display if the input is invalid
// 		- successClass (string): The css class to apply in the event of a valid input
// 		- errorClass (string): The css class to apply in the event of an invalid input
// 		- regex (regex): The regular expression to validate against
// 		- required (bool): If false an invalid message will display in the case
// 						   of invalid input, but when no text is entered no success
// 						   message will be displayed. This will not affect the isValid
// 						   method on the ko.bootstrapValidatedViewModel.
ko.extenders.boostrapValidation = function(target, options) {

	// set the defaults
	var defaults = {
		successMessage: 'Good!',
		errorMessage: 'Invalid!',
		successClass: 'success',
		errorClass: 'error',
		regex: /^\s*\S.*$/,
		required: true
	}

	// overwrite the defaults with the user defined settings
	var settings = ko.utils.extend(defaults, options);

	// create the sub-observables that are responsible for the UI
	target.validationMessage = ko.observable('');
	target.validationClass = ko.observable('');
	// the hasError sub-observable is initally set to the required option because if it's
	// required we want an error off the bat, if not we don't want to count it as an error
	target.hasError = ko.observable(settings.required);
	// the required property is used to check whether the target observable needs to be
	// validated against the isValid check on the boostrapValidatedViewModel
	target.required = settings.required;

	// create a subscription on the observable to evaluate the value of the observable
	target.subscribe(function() {

		// the observable's value
		var value = target(),
			// does the value of the observable  match the regex?
			matchesPattern = settings.regex.test(value),
			// convenience variable, there is an error if the value does not match the pattern
			hasError = (!matchesPattern),
			// ternary, if there is an error use the errorMessage
			message = hasError ? settings.errorMessage : settings.successMessage,
			// ternary, if there is an error use the errorClass
			cssClass = hasError ? settings.errorClass : settings.successClass;

		// set sub-observable values depending on the required setting
		if (!settings.required && value.length === 0) {
			// if the observable is not required then don't display anything when there is no input
			target.validationMessage('');
			target.validationClass('');
		}
		else{
			// if the required setting is true the simply just set the sub-observables
			target.validationMessage(message);
			target.validationClass(cssClass);
		}

		// the observable will not have an error if the required setting is false
		target.hasError(settings.required ? hasError : false);

	});

	return target;
};

// @ViewModel: bootstrapValidatedViewModel
// @description: This view model takes in another view model as a parameter and
//				 attaches an isValid computed on to the paramter view model, which
//				 will return true if any observables with the hasError sub-observable
//				 return false.
// @params:
//	- viewModel: The view model to attach the isValid computed on to
ko.bootstrapValidatedViewModel = function(viewModel) {

	// Loop through the view model and find any properties that have the hasError
	// sub-observable.
	viewModel.isValid = ko.computed(function() {
		var errorCount = 0;

		for (var key in viewModel) {
			// Incremement a counter if any hasError sub-observables return true.
		   if (viewModel[key].hasOwnProperty('hasError')) {
		   		errorCount = viewModel[key].hasError() ? errorCount +=1 : errorCount;
		   };
		}

		// if the errorCount is zero then the view model is valid
		return errorCount === 0;
	}, viewModel);

	return viewModel;
};<commit_msg>Removed the required property from the target observable; it was unnecessary to the rest of the implementation.<commit_after>/*
 * ko.boostrap-validation.js
 * @version: 0.1
 * @description: A simple knockout extender that will provide validation messages for user input.
 * 				 This extender is specifically tailored for Twitter Bootstrap validation states, but
 *				 it can be modified work with your own framework/implementation quite easily.
 * @author: David East - http://www.davidea.st/
 * @license: MIT
 */

// @Extender: bootstrapValidation
// @params:
//   - target (observable): The observable being extended
// 	 - options (obj): The user defined settings for validating the observable
// 		- successMessage (string): The message to display if the input is valid
// 		- errorMessage (string): The message to display if the input is invalid
// 		- successClass (string): The css class to apply in the event of a valid input
// 		- errorClass (string): The css class to apply in the event of an invalid input
// 		- regex (regex): The regular expression to validate against
// 		- required (bool): If false an invalid message will display in the case
// 						   of invalid input, but when no text is entered no success
// 						   message will be displayed. This will not affect the isValid
// 						   method on the ko.bootstrapValidatedViewModel.
ko.extenders.boostrapValidation = function(target, options) {

	// set the defaults
	var defaults = {
		successMessage: 'Good!',
		errorMessage: 'Invalid!',
		successClass: 'success',
		errorClass: 'error',
		regex: /^\s*\S.*$/,
		required: true
	}

	// overwrite the defaults with the user defined settings
	var settings = ko.utils.extend(defaults, options);

	// create the sub-observables that are responsible for the UI
	target.validationMessage = ko.observable('');
	target.validationClass = ko.observable('');
	// the hasError sub-observable is initally set to the required option because if it's
	// required we want an error off the bat, if not we don't want to count it as an error
	target.hasError = ko.observable(settings.required);

	// create a subscription on the observable to evaluate the value of the observable
	target.subscribe(function() {

		// the observable's value
		var value = target(),
			// does the value of the observable  match the regex?
			matchesPattern = settings.regex.test(value),
			// convenience variable, there is an error if the value does not match the pattern
			hasError = (!matchesPattern),
			// ternary, if there is an error use the errorMessage
			message = hasError ? settings.errorMessage : settings.successMessage,
			// ternary, if there is an error use the errorClass
			cssClass = hasError ? settings.errorClass : settings.successClass;

		// set sub-observable values depending on the required setting
		if (!settings.required && value.length === 0) {
			// if the observable is not required then don't display anything when there is no input
			target.validationMessage('');
			target.validationClass('');
		}
		else{
			// if the required setting is true the simply just set the sub-observables
			target.validationMessage(message);
			target.validationClass(cssClass);
		}

		// the observable will not have an error if the required setting is false
		target.hasError(settings.required ? hasError : false);

	});

	return target;
};

// @ViewModel: bootstrapValidatedViewModel
// @description: This view model takes in another view model as a parameter and
//				 attaches an isValid computed on to the paramter view model, which
//				 will return true if any observables with the hasError sub-observable
//				 return false.
// @params:
//	- viewModel: The view model to attach the isValid computed on to
ko.bootstrapValidatedViewModel = function(viewModel) {

	// Loop through the view model and find any properties that have the hasError
	// sub-observable.
	viewModel.isValid = ko.computed(function() {
		var errorCount = 0;

		for (var key in viewModel) {
			// Incremement a counter if any hasError sub-observables return true.
		   if (viewModel[key].hasOwnProperty('hasError')) {
		   		errorCount = viewModel[key].hasError() ? errorCount +=1 : errorCount;
		   };
		}

		// if the errorCount is zero then the view model is valid
		return errorCount === 0;
	}, viewModel);

	return viewModel;
};<|endoftext|>


<commit_before>import Color from './color/color';
import RGB from './color/rgb';
import HSL from './color/hsl';

export default class Kolour {
  constructor(color) {
    if (!color) {
      throw new TypeError('color must not be null');
    }
    this.assign(color);
  }

  assign(color) {
    color.keys().forEach(key => {
      let name = Symbol.keyFor(key);
      if (this.hasOwnProperty(name)) {
        return;
      }

      Object.defineProperty(this, name, {
        get: () => {
          return function(value = null) {
            let color = this.color;
            if (!color.has(key)) {
              throw new Error(`${color.space()} does not have a key for ${name}`);
            }

            if (value === null) {
              return color.get(key);
            }
            color.set(key, value);
            return this;
          }.bind(this);
        }
      });
    });
    this.color = color;
  }
}
<commit_msg>Modified implementation of assign to fit implementaion of color class<commit_after>import Color from './color/color';
import RGB from './color/rgb';
import HSL from './color/hsl';

export default class Kolour {
  constructor(color) {
    if (!color) {
      throw new TypeError('color must not be null');
    }
    this.assign(color);
  }

  assign(color) {
    color.keys().forEach(key => {
      if (this.hasOwnProperty(key)) {
        return;
      }

      Object.defineProperty(this, key, {
        get: () => {
          return function(value = null) {
            let color = this.color;
            if (!color.has(key)) {
              throw new Error(`${color.space()} does not have a key for ${key}`);
            }

            if (value === null) {
              return color.get(key);
            }
            color.set(key, value);
            return this;
          }.bind(this);
        }
      });
    });
    this.color = color;
  }
}
<|endoftext|>


<commit_before>export function setCookie(name, value, mode="cookie") {
  if(mode == "cookie") {
    var Days = 30;
    var exp = new Date();
    exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
    document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
    return true;
  } else if(mode == "storage") {
    var _localStorage = window.localStorage;
    if (_localStorage) {
      _localStorage.setItem(name, value);
      return true;
    }
    return false;
  }

}

export function getCookie(name, mode="cookie") {
  if(mode == "cookie") {
    var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
    if (arr = document.cookie.match(reg)) {
      return unescape(arr[2]);
    }
    else {
      return null;
    }
  } else if(mode == "storage") {
    var _localStorage = window.localStorage;
    if (_localStorage) {
      return _localStorage.getItem(name);
    }
    else
      return null;
  }
}

export function delCookie(name, mode="cookie") {
  if(mode == "cookie") {
    var exp = new Date();
    exp.setTime(exp.getTime() - 1);
    var cval = getCookie(name);
    if (cval != null) {
      document.cookie = name + '=' + cval + ";expires=" + exp.toGMTString();
    }
  } else if(mode == "storage") {
    var _localStorage = window.localStorage;
    if (_localStorage) {
      _localStorage.removeItem(name);
    }
  }
}

export function priceFormat(price, n) {
  n = n >= 0 && n <= 20 ? n : 2;
  price = parseFloat((price + "").replace(/[^\d\.-]/g, "")).toFixed(n) + "";
  var l = price.split(".")[0].split("").reverse(), r = price.split(".")[1];
  var t = "";
  for (var i = 0; i < l.length; i++) {
    t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : "");
  }
  if(n==0){
    return t.split("").reverse().join("");
  } else {
    return t.split("").reverse().join("") + "." + r;
  }
}

export function baoquanFormat(price, n) {
  price = price/100;
  n = n >= 0 && n <= 20 ? n : 2;
  price = parseFloat((price + "").replace(/[^\d\.-]/g, "")).toFixed(n) + "";
  var l = price.split(".")[0].split("").reverse(), r = price.split(".")[1];
  var t = "";
  for (var i = 0; i < l.length; i++) {
    t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : "");
  }
  if(n==0){
    return t.split("").reverse().join("");
  } else {
    return t.split("").reverse().join("") + "." + r;
  }
}

export function tagStrFormat(str, num) {
  return /(\d+)(\D+)/ig.exec(str)[num]
}

export function createCORSRequest(method, url){
  let cors_api_host = 'finiyang.com:8080'
  let cors_api_url = 'http://' + cors_api_host + '/'
  let slice = [].slice
  let origin = window.location.protocol + '//' + window.location.host
  let open = XMLHttpRequest.prototype.open
  XMLHttpRequest.prototype.open = function() {
    let args = slice.call(arguments)
    let targetOrigin = /^https?:\/\/([^\/]+)/i.exec(args[1])
    if (targetOrigin && targetOrigin[0].toLowerCase() !== origin &&
        targetOrigin[1] !== cors_api_host) {
        args[1] = cors_api_url + args[1]
    }
    return open.apply(this, args)
  }
  let xhr = new XMLHttpRequest()
  if ("withCredentials" in xhr){
      xhr.open(method, url, true)
  } else {
      xhr = null
  }
  return xhr
}

export function deepCopy(o) {
    if (o instanceof Array) {
        var n = [];
        for (var i = 0; i < o.length; ++i) {
            n[i] = deepCopy(o[i]);
        }
        return n;

    } else if (o instanceof Object) {
        var n = {}
        for (var i in o) {
            n[i] = deepCopy(o[i]);
        }
        return n;
    } else {
        return o;
    }
}

export function eventFun(pageName,model, id) {
  return {
    'data-event-pageName': pageName,
    'data-event-model': model,
    'data-event-id': id,
    'data-event': 'point'
  }
}

export const icons = {
  'tmall': require('static/imgs/thirdSource/tmall.png'),
  'dangdang': require('static/imgs/thirdSource/dangdang.png'),
  'gome': require('static/imgs/thirdSource/gome.png'),
  'jd': require('static/imgs/thirdSource/jd.png'),
  'jumei': require('static/imgs/thirdSource/jumei.png'),
  'kaola': require('static/imgs/thirdSource/kaola.png'),
  'mi': require('static/imgs/thirdSource/mi.png'),
  'taobao': require('static/imgs/thirdSource/taobao.png'),
  'yhd': require('static/imgs/thirdSource/yhd.png'),
  'yougou': require('static/imgs/thirdSource/yougou.png'),
  'qbao': require('static/imgs/thirdSource/qbao.png'),
}

export function showSourceTip(url,source,PopUp,e){
  console.log(this,PopUp.show);

  e.preventDefault();
}
<commit_msg>Util update<commit_after>export function setCookie(name, value, mode="cookie") {
  if(mode == "cookie") {
    var Days = 30;
    var exp = new Date();
    exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
    document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
    return true;
  } else if(mode == "storage") {
    var _localStorage = window.localStorage;
    if (_localStorage) {
      _localStorage.setItem(name, value);
      return true;
    }
    return false;
  }

}

export function getCookie(name, mode="cookie") {
  if(mode == "cookie") {
    var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
    if (arr = document.cookie.match(reg)) {
      return unescape(arr[2]);
    }
    else {
      return null;
    }
  } else if(mode == "storage") {
    var _localStorage = window.localStorage;
    if (_localStorage) {
      return _localStorage.getItem(name);
    }
    else
      return null;
  }
}

export function delCookie(name, mode="cookie") {
  if(mode == "cookie") {
    var exp = new Date();
    exp.setTime(exp.getTime() - 1);
    var cval = getCookie(name);
    if (cval != null) {
      document.cookie = name + '=' + cval + ";expires=" + exp.toGMTString();
    }
  } else if(mode == "storage") {
    var _localStorage = window.localStorage;
    if (_localStorage) {
      _localStorage.removeItem(name);
    }
  }
}

export function priceFormat(price, n) {
  n = n >= 0 && n <= 20 ? n : 2;
  price = parseFloat((price + "").replace(/[^\d\.-]/g, "")).toFixed(n) + "";
  var l = price.split(".")[0].split("").reverse(), r = price.split(".")[1];
  var t = "";
  for (var i = 0; i < l.length; i++) {
    t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : "");
  }
  if(n==0){
    return t.split("").reverse().join("");
  } else {
    return t.split("").reverse().join("") + "." + r;
  }
}

export function baoquanFormat(price, n) {
  price = price/100;
  n = n >= 0 && n <= 20 ? n : 2;
  price = parseFloat((price + "").replace(/[^\d\.-]/g, "")).toFixed(n) + "";
  var l = price.split(".")[0].split("").reverse(), r = price.split(".")[1];
  var t = "";
  for (var i = 0; i < l.length; i++) {
    t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : "");
  }
  if(n==0){
    return t.split("").reverse().join("");
  } else {
    return t.split("").reverse().join("") + "." + r;
  }
}

export function tagStrFormat(str, num) {
  return /(\d+)(\D+)/ig.exec(str)[num]
}

export function createCORSRequest(method, url){
  let cors_api_host = 'finiyang.com:8080'
  let cors_api_url = 'http://' + cors_api_host + '/'
  let slice = [].slice
  let origin = window.location.protocol + '//' + window.location.host
  let open = XMLHttpRequest.prototype.open
  XMLHttpRequest.prototype.open = function() {
    let args = slice.call(arguments)
    let targetOrigin = /^https?:\/\/([^\/]+)/i.exec(args[1])
    if (targetOrigin && targetOrigin[0].toLowerCase() !== origin &&
        targetOrigin[1] !== cors_api_host) {
        args[1] = cors_api_url + args[1]
    }
    return open.apply(this, args)
  }
  let xhr = new XMLHttpRequest()
  if ("withCredentials" in xhr){
      xhr.open(method, url, true)
  } else {
      xhr = null
  }
  return xhr
}

export function deepCopy(o) {
    if (o instanceof Array) {
        var n = [];
        for (var i = 0; i < o.length; ++i) {
            n[i] = deepCopy(o[i]);
        }
        return n;

    } else if (o instanceof Object) {
        var n = {}
        for (var i in o) {
            n[i] = deepCopy(o[i]);
        }
        return n;
    } else {
        return o;
    }
}

export function eventFun(pageName,model, id) {
  return {
    'data-event-pageName': pageName,
    'data-event-model': model,
    'data-event-id': id,
    'data-event': 'point'
  }
}

export const icons = {
  'tmall': require('static/imgs/thirdSource/tmall.png'),
  'dangdang': require('static/imgs/thirdSource/dangdang.png'),
  'gome': require('static/imgs/thirdSource/gome.png'),
  'jd': require('static/imgs/thirdSource/jd.png'),
  'jumei': require('static/imgs/thirdSource/jumei.png'),
  'kaola': require('static/imgs/thirdSource/kaola.png'),
  'mi': require('static/imgs/thirdSource/mi.png'),
  'taobao': require('static/imgs/thirdSource/taobao.png'),
  'yhd': require('static/imgs/thirdSource/yhd.png'),
  'yougou': require('static/imgs/thirdSource/yougou.png'),
  'qbao': require('static/imgs/thirdSource/qbao.png'),
}

export function showSourceTip(url,source,PopUp,e){
  console.log(this,PopUp.show);

  e.preventDefault();
}

export function getParamByName(name, url) {
  if (!url) url = window.location.href;
  name = name.replace(/[\[\]]/g, "\\$&");
  var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
      results = regex.exec(url);
  if (!results) return null;
  if (!results[2]) return '';
  return decodeURIComponent(results[2].replace(/\+/g, " "));
}
<|endoftext|>


<commit_before>"use strict";

var DocumentNode = require('../node/node');
var _ = require('underscore');

var License = function(node, document) {
  DocumentNode.call(this, node, document);
};

// Type definition
// --------

License.type = {
  "id": "license",
  "properties": {
    "name": "string",
    "code": "string",
    "version": "string",
    "description": "string",
    "url": "string"
  }
};

// This is used for the auto-generated docs
// -----------------
//

License.description = {
  "name": "License",
  "remarks": [
    "Describes the content license used by the document"
  ],
  "properties": {
    "name": "License name",
    "code": "Coded license name, e.g. cc-by",
    "version": "License version",
    "description": "Text describing the license",
    "url": "URL for more information about the license"
  }
};

License.Prototype = function() {

};

License.available_licenses = {
  "none": {
    "id": "license",
    "type": "license",
    "name": "None",
    "code": "none",
    "description": "No license",
    "version": "1.0",
    "url": ""
  },
  "cc-by": {
    "id": "license",
    "type": "license",
    "name": "Creative Commons Attribution License",
    "code": "cc-by",
    "version": "3.0",
    "description": "This article is distributed under the terms of the Creative Commons Attribution License, which permits unrestricted use and redistribution provided that the original author and source are credited.",
    "url": "http://creativecommons.org/licenses/by/3.0/us/"
  }
};

License.Prototype.prototype = DocumentNode.prototype;
License.prototype = new License.Prototype();
License.prototype.constructor = License;

License.prototype.defineProperties();

module.exports = License;
<commit_msg>New licenses.<commit_after>"use strict";

var DocumentNode = require('../node/node');
var _ = require('underscore');

var License = function(node, document) {
  DocumentNode.call(this, node, document);
};

// Type definition
// --------

License.type = {
  "id": "license",
  "properties": {
    "name": "string",
    "code": "string",
    "version": "string",
    "description": "string",
    "url": "string"
  }
};

// This is used for the auto-generated docs
// -----------------
//

License.description = {
  "name": "License",
  "remarks": [
    "Describes the content license used by the document"
  ],
  "properties": {
    "name": "License name",
    "code": "Coded license name, e.g. cc-by",
    "version": "License version",
    "description": "Text describing the license",
    "url": "URL for more information about the license"
  }
};

License.Prototype = function() {

};

License.available_licenses = {
  "none": {
    "id": "license",
    "type": "license",
    "name": "None",
    "code": "none",
    "description": "No license is attached to this article.",
    "version": "1.0",
    "url": ""
  },
  "public-domain": {
    "id": "license",
    "type": "license",
    "name": "Public Domain",
    "code": "public-domain",
    "description": "This work has been identified as being free of known restrictions under copyright law, including all related and neighboring rights. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.",
    "version": "1.0",
    "url": "http://creativecommons.org/publicdomain/mark/1.0/"
  },
  "cc-by": {
    "id": "license",
    "type": "license",
    "name": "Creative Commons Attribution",
    "code": "cc-by",
    "version": "3.0",
    "description": "This article is distributed under the terms of the Creative Commons Attribution License, which permits unrestricted use and redistribution provided that the original author and source are credited.",
    "url": "http://creativecommons.org/licenses/by/3.0/us/"
  },
  "gutenberg": {
    "id": "license",
    "type": "license",
    "name": "Project Gutenberg",
    "code": "gutenberg",
    "version": "1.0",
    "description": "This article is distributed under the terms of the Project Gutenberg License.",
    "url": "http://www.gutenberg.org/wiki/Gutenberg:The_Project_Gutenberg_License"
  }
};

License.Prototype.prototype = DocumentNode.prototype;
License.prototype = new License.Prototype();
License.prototype.constructor = License;

License.prototype.defineProperties();

module.exports = License;
<|endoftext|>


<commit_before>//
// ES6 module loader
//
// Minimal System loader implementation based on
// https://github.com/caridy/es6-micro-loader
//
// Add class and babel transpile support. Transpile targets modern
// chrome browsers and omits much ES5 compatible transformations.
//
import * as path from 'path'
import * as babel from 'babel-core'

export class Loader {
  constructor(options = {}) {
    this._registry = Object.create(null)

    if (options.base) {
      this._base = new URL(options.base)
    }
  }

  get(name) {
    let mod = this._registry[name]

    if (mod && !mod.executed) {
      mod.execute()
    }

    return mod && mod.proxy
  }

  register(name, dependencies, wrapper) {
    if (Array.isArray(name)) {
      this._anonymousEntry = []
      this._anonymousEntry.push.apply(this._anonymousEntry, arguments)
      return // breaking to let the _load function to name the module
    }

    let proxy = Object.create(null)
    let values = Object.create(null)
    let mod, meta

    // creating a new entry in the internal registry
    this._registry[name] = mod = {

      // live bindings
      proxy: proxy,

      // exported values
      values: values,

      // if module is already initialized
      executed: false,

      // normalized dependencies
      dependencies: dependencies.map(dep => do {
        // Handle special cases for import names like "kernel"
        // They must not be path and must not have an extension
        if (dep.indexOf('/') < 0 && dep.indexOf('.') < 0) {
          dep
        } else {
          path.normalize(path.resolve(name, '..', dep))
        }
      }),

      // other modules that depends on this so we can push updates into those modules
      dependants: [],

      // method used to push updates of dependencies into the module body
      update: (moduleName, moduleObj) => {
        meta.setters[mod.dependencies.indexOf(moduleName)](moduleObj)
      },

      execute: () => {
        // Flag as executed
        mod.executed = true

        mod.dependencies.map(dep => {
          let imports = this.get(dep) && this._registry[dep].values // optimization to pass plain values instead of bindings

          if (imports) {
            this._registry[dep].dependants.push(name)

            mod.update(dep, imports)
          }
        })

        meta.execute()
      }
    }

    let _export = (identifier, value) => {
      if (typeof identifier === 'object') {
        for (let prop in Object.getOwnPropertyNames(identifier)) {
          _export(prop, identifier[prop])
        }

        return identifier
      }

      values[identifier] = value

      // locking down the updates on the module to avoid infinite loop
      mod.lock = true

      mod.dependants.forEach(function(moduleName) {
        if (this._registry[moduleName] && !this._registry[moduleName].lock) {
          this._registry[moduleName].update(name, values)
        }
      })

      mod.lock = false

      if (!Object.getOwnPropertyDescriptor(proxy, identifier)) {
          Object.defineProperty(proxy, identifier, {
              enumerable: true,
              get: () => {
                  return values[identifier]
              }
          })
      }

      return value
    }

    // collecting execute() and setters[]
    meta = wrapper(_export)
  }

  async import(modName, options = {}) {
    let name = path.normalize(modName)
    let mod = this.get(name)

    if (mod) {
      return mod
    }

    await this.load(name, options)

    return this.get(name)
  }

  async transpile(blob, {filename}) {
    let source = babel.transform(blob, {
      plugins: [
        require("babel-plugin-syntax-async-functions"),
        require("babel-plugin-syntax-async-generators"),
        require("babel-plugin-syntax-do-expressions"),
        require("babel-plugin-syntax-exponentiation-operator"),
        require("babel-plugin-syntax-export-extensions"),
        require("babel-plugin-syntax-function-bind"),
        require("babel-plugin-syntax-object-rest-spread"),
        require("babel-plugin-syntax-trailing-function-commas"),
        require("babel-plugin-transform-async-to-generator"),
        require("babel-plugin-transform-async-to-module-method"),
        require("babel-plugin-transform-do-expressions"),
        require("babel-plugin-transform-es2015-destructuring"),
        require("babel-plugin-transform-es2015-modules-systemjs"),
        require("babel-plugin-transform-exponentiation-operator"),
        require("babel-plugin-transform-export-extensions"),
        require("babel-plugin-transform-function-bind"),
        require("babel-plugin-transform-object-rest-spread"),
      ],
      sourceMaps: 'inline',
      filename: filename,
      sourceFileName: filename,
      compact: true,
    })

    return source
  }

  async resolve(name) {
    return do {
      if (this._base) {
        new URL(path.normalize('./' + name), this._base)
      } else {
        name
      }
    }
  }

  async fetch(uri) {
    let response = await self.fetch(uri)

    if (response.status != 200) {
      throw new Error('Could not fetch: ' + name)
    }

    let blob = await response.text()

    return blob
  }

  async load(name, options = {}) {
    let uri = await this.resolve(name, options)
    let blob = await this.fetch(uri, options)

    let source = await this.transpile(blob, {
      moduleId: name,
      filename: name
    })

    let code = source.code + '\n//# sourceURL=' + uri + '!transpiled'

    new Function('System', code)(this)

    if (this._anonymousEntry) {
      this.register(name, this._anonymousEntry[0], this._anonymousEntry[1]);
      this._anonymousEntry = undefined;
    }

    let mod = this._registry[name]

    if (!mod) {
      throw new Error('Error loading module ' + name)
    }

    return Promise.all(mod.dependencies.map(dependency => {
      if (this._registry[dependency]) {
        return Promise.resolve()
      } else {
        return this.load(dependency)
      }
    }))
  }
}
<commit_msg>Use Map for registry<commit_after>//
// ES6 module loader
//
// Minimal System loader implementation based on
// https://github.com/caridy/es6-micro-loader
//
// Add class and babel transpile support. Transpile targets modern
// chrome browsers and omits much ES5 compatible transformations.
//
import * as path from 'path'
import * as babel from 'babel-core'

export class Loader {
  constructor(options = {}) {
    this._registry = new Map()

    if (options.base) {
      this._base = new URL(options.base)
    }
  }

  get(name) {
    let mod = this._registry.get(name)

    if (mod && !mod.executed) {
      mod.execute()
    }

    return mod && mod.proxy
  }

  register(name, dependencies, wrapper) {
    if (Array.isArray(name)) {
      this._anonymousEntry = []
      this._anonymousEntry.push.apply(this._anonymousEntry, arguments)
      return // breaking to let the _load function to name the module
    }

    let proxy = Object.create(null)
    let values = Object.create(null)
    let mod, meta

    // creating a new entry in the internal registry
    this._registry.set(name, mod = {

      // live bindings
      proxy: proxy,

      // exported values
      values: values,

      // if module is already initialized
      executed: false,

      // normalized dependencies
      dependencies: dependencies.map(dep => do {
        // Handle special cases for import names like "kernel"
        // They must not be path and must not have an extension
        if (dep.indexOf('/') < 0 && dep.indexOf('.') < 0) {
          dep
        } else {
          path.normalize(path.resolve(name, '..', dep))
        }
      }),

      // other modules that depends on this so we can push updates into those modules
      dependants: [],

      // method used to push updates of dependencies into the module body
      update: (moduleName, moduleObj) => {
        meta.setters[mod.dependencies.indexOf(moduleName)](moduleObj)
      },

      execute: () => {
        // Flag as executed
        mod.executed = true

        mod.dependencies.map(dep => {
          let imports = this.get(dep) && this._registry.get(dep).values // optimization to pass plain values instead of bindings

          if (imports) {
            this._registry.get(dep).dependants.push(name)

            mod.update(dep, imports)
          }
        })

        meta.execute()
      }
    })

    let _export = (identifier, value) => {
      if (typeof identifier === 'object') {
        for (let prop in Object.getOwnPropertyNames(identifier)) {
          _export(prop, identifier[prop])
        }

        return identifier
      }

      values[identifier] = value

      // locking down the updates on the module to avoid infinite loop
      mod.lock = true

      mod.dependants.forEach(function(moduleName) {
        let module = this._registry.get(moduleName)

        if (module && !module.lock) {
          module.update(name, values)
        }
      })

      mod.lock = false

      if (!Object.getOwnPropertyDescriptor(proxy, identifier)) {
          Object.defineProperty(proxy, identifier, {
              enumerable: true,
              get: () => {
                  return values[identifier]
              }
          })
      }

      return value
    }

    // collecting execute() and setters[]
    meta = wrapper(_export)
  }

  async import(modName, options = {}) {
    let name = path.normalize(modName)
    let mod = this.get(name)

    if (mod) {
      return mod
    }

    await this.load(name, options)

    return this.get(name)
  }

  async transpile(blob, {filename}) {
    let source = babel.transform(blob, {
      plugins: [
        require("babel-plugin-syntax-async-functions"),
        require("babel-plugin-syntax-async-generators"),
        require("babel-plugin-syntax-do-expressions"),
        require("babel-plugin-syntax-exponentiation-operator"),
        require("babel-plugin-syntax-export-extensions"),
        require("babel-plugin-syntax-function-bind"),
        require("babel-plugin-syntax-object-rest-spread"),
        require("babel-plugin-syntax-trailing-function-commas"),
        require("babel-plugin-transform-async-to-generator"),
        require("babel-plugin-transform-async-to-module-method"),
        require("babel-plugin-transform-do-expressions"),
        require("babel-plugin-transform-es2015-destructuring"),
        require("babel-plugin-transform-es2015-modules-systemjs"),
        require("babel-plugin-transform-exponentiation-operator"),
        require("babel-plugin-transform-export-extensions"),
        require("babel-plugin-transform-function-bind"),
        require("babel-plugin-transform-object-rest-spread"),
      ],
      sourceMaps: 'inline',
      filename: filename,
      sourceFileName: filename,
      compact: true,
    })

    return source
  }

  async resolve(name) {
    return do {
      if (this._base) {
        new URL(path.normalize('./' + name), this._base)
      } else {
        name
      }
    }
  }

  async fetch(uri) {
    let response = await self.fetch(uri)

    if (response.status != 200) {
      throw new Error('Could not fetch: ' + name)
    }

    let blob = await response.text()

    return blob
  }

  async load(name, options = {}) {
    let uri = await this.resolve(name, options)
    let blob = await this.fetch(uri, options)

    let source = await this.transpile(blob, {
      moduleId: name,
      filename: name
    })

    let code = source.code + '\n//# sourceURL=' + uri + '!transpiled'

    new Function('System', code)(this)

    if (this._anonymousEntry) {
      this.register(name, this._anonymousEntry[0], this._anonymousEntry[1]);
      this._anonymousEntry = undefined;
    }

    let mod = this._registry.get(name)

    if (!mod) {
      throw new Error('Error loading module ' + name)
    }

    return Promise.all(mod.dependencies.map(dependency => {
      if (this._registry.has(dependency)) {
        return Promise.resolve()
      } else {
        return this.load(dependency)
      }
    }))
  }
}
<|endoftext|>


<commit_before>(function() {
"use strict";

if (!window.Echo) window.Echo = {};

if (Echo.Loader) return;

/**
 * @class Echo.Loader
 * Static class which implements common mechanics for resources loading,
 * Echo environment establishing and Canvases initialization mechanics.
 */
Echo.Loader = {
	"version": "",
	"debug": false,
	"config": {
		"cdnBaseURL": "http://cdn.echoenabled.com/",
		"storageURL": "https://s3.amazonaws.com/echo-canvases/",
		"errorTimeout": 5000 // 5 sec
	},
	"canvases": [],  // Canvases list initialized on the page
	"overrides": {},  // Canvas Apps overrides object
	"vars": {
		"state": {"resources": {}, "queue": []},
		"processing": false,
		"syncQueue": []
	}
};

/**
 * @static
 * Function to get normalized URL.
 *
 * @param {String} url
 * JavaScript or CSS stylesheet file URL.
 *
 * @param {Boolean} [devVersion=true]
 * Specifies whether function should return dev version of the file or not,
 * false value is useful when we want to get URL to image because
 * images don't have dev versions
 */
Echo.Loader.getURL = function(url, devVersion) {
	if (typeof devVersion === "undefined") devVersion = true;
	return /^https?:\/\/|^\/\//.test(url)
		? url
		: Echo.Loader.config.cdnBaseURL + "sdk/v" + Echo.Loader.version +
			(devVersion && Echo.Loader.isDebug() ? "/dev" : "") +
			(!url || url.charAt(0) === "/" ? "" : "/") + url;
};

/**
 * @static
 * Function to load the JavaScript or CSS stylesheet files in async mode.
 *
 * @param {Array} resources
 * Array of objects with the properties described below:
 *
 * @param {String} resources.url
 * JavaScript or CSS stylesheet file URL.
 *
 * @param {Function} resources.loaded
 * Function used to check whether the script was loaded. This function must return
 * the boolean value which indicates whether the resource was already loaded on the
 * page or not. If the resource has already been loaded - no download is performed
 * and the callback is called immediately.
 *
 * @param {Function} [callback]
 * Callback function which should be called as soon as all requested files
 * were downloaded.
 *
 * @param {Object} [config]
 * Object with configuration parameters
 *
 * @param {Number} config.errorTimeout
 * Timeout loading of resources in milliseconds, use as yepnope.errorTimeout
 *
 */
Echo.Loader.download = function(resources, callback, config) {
	config = config || {};
	callback = callback || function() {};

	if (!resources || !resources.length) {
		callback();
		return;
	}

	var state = Echo.Loader.vars.state;
	var syncQueue = Echo.Loader.vars.syncQueue;
	var invokeCallbacks = function() {
		var callbacks = [];
		// Important note: we should *not* execute callbacks
		// while iterating through the queue. We need to update
		// the queue first and only after that execute the callbacks,
		// because there might be calls to "Echo.Loader.download" function
		// which can interfere with the current queue state.
		state.queue = Echo.Loader._map(state.queue, function(item) {
			if (Echo.Loader._areResourcesReady(item.resources)) {
				callbacks.push(item.callback);
				return; // do *not* put this resource back into the queue
			}
			return item;
		});
		Echo.Loader._map(callbacks, function(_callback) { _callback(); });
	};

	// Important note: we should *not* execute another
	// Echo.yepnope until last one is completed.
	// See more information about the issue on Github:
	// https://github.com/SlexAxton/yepnope.js/issues/113
	var checkSyncQueue = function() {
		if (!Echo.Loader.vars.processing && syncQueue.length) {
			Echo.Loader.vars.processing = true;
			Echo.yepnope(syncQueue.shift());
		}
	};

	state.queue.push({"resources": resources, "callback": callback});

	var urls = Echo.Loader._map(resources, function(resource) {
		var url = Echo.Loader.getURL(resource.url);
		if (!Echo.Loader._areResourcesReady([resource]) &&
			state.resources[url] !== "loading") {
				state.resources[url] = "loading";
				return url;
		}
	});

	// invoke queued handler in case all requested resources
	// are ready by the time the "download" function is called
	if (!urls.length) {
		invokeCallbacks();
		return;
	}

	var prefix = "timeout=" + (config.errorTimeout || Echo.Loader.config.errorTimeout) + "!";
	syncQueue.push({
		"load": Echo.Loader._map(urls, function(url) { return prefix + url; }),
		"complete": function() {
			// mark all loaded scripts as "ready"
			Echo.Loader._map(urls, function(url) {
				state.resources[url] = "ready";
			});
			invokeCallbacks();
			Echo.Loader.vars.processing = false;
			checkSyncQueue();
		}
	});
	checkSyncQueue();
};

/**
 * @static
 * Allows to identify if the debug mode is enabled for Echo environment
 * on the page (i.e whether the logs should be printed in console,
 * non-minified versions of scripts should be used)
 *
 * @return {Boolean}
 */
Echo.Loader.isDebug = function() {
	return Echo.Loader.debug;
};

(function() {
	if (Echo.Loader.debug) return;

	var debug;
	var _debugCookieName = "echo-debug";
	var options = {"path": "/"};
	var hashParts = window.location.hash.match(/echo.debug:(true|false)/);
	if (hashParts && hashParts.length) {
		debug = hashParts[1];
	}
	if (typeof debug !== "undefined") {
		if (debug === "true") {
			Echo.Loader.debug = true;
			Echo.Cookie.set(_debugCookieName, true, options);
		} else {
			Echo.Loader.debug = false;
			Echo.Cookie.remove(_debugCookieName, options);
		}
		return;
	}
	Echo.Loader.debug = !!Echo.Cookie.get(_debugCookieName);
})();

/**
 * @static
 * Function to initialize Echo environment on the page by downloading Backplane lib,
 * jQuery library with the necessary dependencies and the base Echo classes.
 *
 * @param {Function} [callback]
 * Callback function which should be called as soon as Echo environment is ready.
 */
Echo.Loader.initEnvironment = function(callback) {
	var resources = [{
		"url": "backplane.js",
		"loaded": function() { return !!window.Backplane; }
	}, {
		"url": "third-party/jquery.pack.js",
		"loaded": function() { return !!Echo.jQuery; }
	}, {
		"url": "environment.pack.js",
		"loaded": function() { return !!Echo.Utils; }
	}];
	if (Echo.Loader._areResourcesReady(resources)) {
		callback && callback();
		return;
	}
	Echo.Loader.download(resources, callback);
};

/**
 * @static
 * Function which provides an ability to override config parameters of the
 * specific application within the canvas.
 *
 * @param {String} canvasID
 * Canvas ID.
 *
 * @param {String} appID
 * Application ID inside the canvas.
 *
 * @param {Object} config
 * Object with the application config overrides.
 */
Echo.Loader.override = function(canvasID, appID, config) {
	var overrides = Echo.Loader.overrides;
	overrides[canvasID] = overrides[canvasID] || {};
	overrides[canvasID][appID] = config;
};

/**
 * @static
 * Function to initialize canvases on the page.
 *
 * @param {Object} [config]
 * Object which defines the initialization of config parameters
 *
 * @param {Mixed} [config.canvases]
 * Array of jQuery elements or a single jQuery element, which represents a
 * canvas target. If this param is omitted, Echo Loader will look for the
 * canvases in the DOM structure.
 *
 * @param {Object} [config.target]
 * Target element where Echo Loader should look for the canvases if no
 * canvases were passed in the "config.canvases" field.
 */
Echo.Loader.init = function(config) {
	config = config || {};
	Echo.Loader.initEnvironment(function() {
		var $ = Echo.jQuery;
		var canvases = config.canvases;

		// convert a single canvas to the 1-element array
		// to keep the same contract below in the code
		if (canvases && !$.isArray(canvases) && !(canvases instanceof $)) {
			canvases = [canvases];
		}

		// if no canvases defined during initialization,
		// we look for all canvases in the target ('document' by default)
		canvases = canvases || $(".echo-canvas", config.target);

		if (!canvases.length) {
			Echo.Loader._error({
				"code": "no_canvases_found",
				"message": "No canvases found on the page..."
			});
			return;
		}

		$.map(canvases, function(canvas) {
			var target = $(canvas);
			var instance = new Echo.Canvas({
				"target": target,
				"overrides": Echo.Loader.overrides[target.data("canvas-id")]
			});
			Echo.Loader.canvases.push(instance);
		});
	});
};

/**
 * @static
 * Function to initialize application on the page. The function performs the following actions:
 *
 * + initializes Echo JavaScript environment (if it was not initialized yet)
 * + establishes the Backplane connection (if app.backplane is defined)
 * + establishes Echo User session on the page (if app.config.appkey is defined)
 * + downloads the application script
 * + calls the app JavaScript class constructor which handles further application initialization
 *
 * @param {Object} app
 * Object which defines the base app configuration.
 *
 * @param {String} app.component
 * The name of the JavaScript app class which should be initialized.
 *
 * @param {String} app.script
 * Appliction JavaScript class script URL.
 *
 * @param {Object} [app.scripts]
 * Object which specifies the location (URL) of the production (minified) and development
 * (non-minified) versions of the app JavaScript class code. The "prod" and "dev" keys
 * should be used in order to specify the production and development URLs respectively.
 *
 * @param {Object} [app.backplane]
 * Object which contains the data to be passed into the Backplane.init call.
 *
 * @param {Object} [app.config]
 * Parameters to be passed into the application constructor during its initialization.
 */
Echo.Loader.initApplication = function(app) {
	Echo.Loader.initEnvironment(function() {
		if (!app || !app.config || !app.config.target) {
			Echo.Loader._error({
				"args": {"app": app},
				"code": "invalid_app_config",
				"message": "Invalid config passed into the initApplication function"
			});
			return;
		}
		var instance = new Echo.Canvas({
			"target": app.config.target,
			"data": { // as we receive if from the Canvas Storage
				"apps": [app],
				"backplane": app.backplane
			}
		});
		Echo.Loader.canvases.push(instance);
	});
};

Echo.Loader._error = function(data) {
	if (!Echo.Events || !Echo.Utils || !Echo.jQuery) return;
	Echo.Events.publish({
		"topic": "Echo.Loader.onError",
		"data": data
	});
	Echo.Utils.log(Echo.jQuery.extend(data, {"type": "error", "component": "Echo.Loader"}));
};

// implementation of the "map" function for the cases when jQuery is not loaded yet
Echo.Loader._map = function(list, iterator) {
	var result = [];
	if (list && list.length && iterator) {
		for (var i = 0; i < list.length; i++) {
			var value = iterator(list[i], i);
			if (value === false) break; // jQuery-like convention
			if (typeof value !== "undefined") result.push(value);
		}
	}
	return result;
};

Echo.Loader._areResourcesReady = function(resources) {
	var state = Echo.Loader.vars.state;
	var resourceReadyFlags = Echo.Loader._map(resources, function(resource) {
		var url = Echo.Loader.getURL(resource.url);
		// the 'true' flag will be added into the
		// result array only when resource is ready
		return (resource.loaded && resource.loaded()) ||
			(state.resources[url] && state.resources[url] === "ready");
	});
	return resources.length === resourceReadyFlags.length;
};

})();
<commit_msg>[Echo.Loader] S3 canvases requests must be targeted to the same scheme as the hosting page, this is the restriction of the XDomainRequest object<commit_after>(function() {
"use strict";

if (!window.Echo) window.Echo = {};

if (Echo.Loader) return;

/**
 * @class Echo.Loader
 * Static class which implements common mechanics for resources loading,
 * Echo environment establishing and Canvases initialization mechanics.
 */
Echo.Loader = {
	"version": "",
	"debug": false,
	"config": {
		"cdnBaseURL": "http://cdn.echoenabled.com/",
		"storageURL": "http://s3.amazonaws.com/echo-canvases/",
		"errorTimeout": 5000 // 5 sec
	},
	"canvases": [],  // Canvases list initialized on the page
	"overrides": {},  // Canvas Apps overrides object
	"vars": {
		"state": {"resources": {}, "queue": []},
		"processing": false,
		"syncQueue": []
	}
};

/**
 * @static
 * Function to get normalized URL.
 *
 * @param {String} url
 * JavaScript or CSS stylesheet file URL.
 *
 * @param {Boolean} [devVersion=true]
 * Specifies whether function should return dev version of the file or not,
 * false value is useful when we want to get URL to image because
 * images don't have dev versions
 */
Echo.Loader.getURL = function(url, devVersion) {
	if (typeof devVersion === "undefined") devVersion = true;
	return /^https?:\/\/|^\/\//.test(url)
		? url
		: Echo.Loader.config.cdnBaseURL + "sdk/v" + Echo.Loader.version +
			(devVersion && Echo.Loader.isDebug() ? "/dev" : "") +
			(!url || url.charAt(0) === "/" ? "" : "/") + url;
};

/**
 * @static
 * Function to load the JavaScript or CSS stylesheet files in async mode.
 *
 * @param {Array} resources
 * Array of objects with the properties described below:
 *
 * @param {String} resources.url
 * JavaScript or CSS stylesheet file URL.
 *
 * @param {Function} resources.loaded
 * Function used to check whether the script was loaded. This function must return
 * the boolean value which indicates whether the resource was already loaded on the
 * page or not. If the resource has already been loaded - no download is performed
 * and the callback is called immediately.
 *
 * @param {Function} [callback]
 * Callback function which should be called as soon as all requested files
 * were downloaded.
 *
 * @param {Object} [config]
 * Object with configuration parameters
 *
 * @param {Number} config.errorTimeout
 * Timeout loading of resources in milliseconds, use as yepnope.errorTimeout
 *
 */
Echo.Loader.download = function(resources, callback, config) {
	config = config || {};
	callback = callback || function() {};

	if (!resources || !resources.length) {
		callback();
		return;
	}

	var state = Echo.Loader.vars.state;
	var syncQueue = Echo.Loader.vars.syncQueue;
	var invokeCallbacks = function() {
		var callbacks = [];
		// Important note: we should *not* execute callbacks
		// while iterating through the queue. We need to update
		// the queue first and only after that execute the callbacks,
		// because there might be calls to "Echo.Loader.download" function
		// which can interfere with the current queue state.
		state.queue = Echo.Loader._map(state.queue, function(item) {
			if (Echo.Loader._areResourcesReady(item.resources)) {
				callbacks.push(item.callback);
				return; // do *not* put this resource back into the queue
			}
			return item;
		});
		Echo.Loader._map(callbacks, function(_callback) { _callback(); });
	};

	// Important note: we should *not* execute another
	// Echo.yepnope until last one is completed.
	// See more information about the issue on Github:
	// https://github.com/SlexAxton/yepnope.js/issues/113
	var checkSyncQueue = function() {
		if (!Echo.Loader.vars.processing && syncQueue.length) {
			Echo.Loader.vars.processing = true;
			Echo.yepnope(syncQueue.shift());
		}
	};

	state.queue.push({"resources": resources, "callback": callback});

	var urls = Echo.Loader._map(resources, function(resource) {
		var url = Echo.Loader.getURL(resource.url);
		if (!Echo.Loader._areResourcesReady([resource]) &&
			state.resources[url] !== "loading") {
				state.resources[url] = "loading";
				return url;
		}
	});

	// invoke queued handler in case all requested resources
	// are ready by the time the "download" function is called
	if (!urls.length) {
		invokeCallbacks();
		return;
	}

	var prefix = "timeout=" + (config.errorTimeout || Echo.Loader.config.errorTimeout) + "!";
	syncQueue.push({
		"load": Echo.Loader._map(urls, function(url) { return prefix + url; }),
		"complete": function() {
			// mark all loaded scripts as "ready"
			Echo.Loader._map(urls, function(url) {
				state.resources[url] = "ready";
			});
			invokeCallbacks();
			Echo.Loader.vars.processing = false;
			checkSyncQueue();
		}
	});
	checkSyncQueue();
};

/**
 * @static
 * Allows to identify if the debug mode is enabled for Echo environment
 * on the page (i.e whether the logs should be printed in console,
 * non-minified versions of scripts should be used)
 *
 * @return {Boolean}
 */
Echo.Loader.isDebug = function() {
	return Echo.Loader.debug;
};

(function() {
	if (Echo.Loader.debug) return;

	var debug;
	var _debugCookieName = "echo-debug";
	var options = {"path": "/"};
	var hashParts = window.location.hash.match(/echo.debug:(true|false)/);
	if (hashParts && hashParts.length) {
		debug = hashParts[1];
	}
	if (typeof debug !== "undefined") {
		if (debug === "true") {
			Echo.Loader.debug = true;
			Echo.Cookie.set(_debugCookieName, true, options);
		} else {
			Echo.Loader.debug = false;
			Echo.Cookie.remove(_debugCookieName, options);
		}
		return;
	}
	Echo.Loader.debug = !!Echo.Cookie.get(_debugCookieName);
})();

/**
 * @static
 * Function to initialize Echo environment on the page by downloading Backplane lib,
 * jQuery library with the necessary dependencies and the base Echo classes.
 *
 * @param {Function} [callback]
 * Callback function which should be called as soon as Echo environment is ready.
 */
Echo.Loader.initEnvironment = function(callback) {
	var resources = [{
		"url": "backplane.js",
		"loaded": function() { return !!window.Backplane; }
	}, {
		"url": "third-party/jquery.pack.js",
		"loaded": function() { return !!Echo.jQuery; }
	}, {
		"url": "environment.pack.js",
		"loaded": function() { return !!Echo.Utils; }
	}];
	if (Echo.Loader._areResourcesReady(resources)) {
		callback && callback();
		return;
	}
	Echo.Loader.download(resources, callback);
};

/**
 * @static
 * Function which provides an ability to override config parameters of the
 * specific application within the canvas.
 *
 * @param {String} canvasID
 * Canvas ID.
 *
 * @param {String} appID
 * Application ID inside the canvas.
 *
 * @param {Object} config
 * Object with the application config overrides.
 */
Echo.Loader.override = function(canvasID, appID, config) {
	var overrides = Echo.Loader.overrides;
	overrides[canvasID] = overrides[canvasID] || {};
	overrides[canvasID][appID] = config;
};

/**
 * @static
 * Function to initialize canvases on the page.
 *
 * @param {Object} [config]
 * Object which defines the initialization of config parameters
 *
 * @param {Mixed} [config.canvases]
 * Array of jQuery elements or a single jQuery element, which represents a
 * canvas target. If this param is omitted, Echo Loader will look for the
 * canvases in the DOM structure.
 *
 * @param {Object} [config.target]
 * Target element where Echo Loader should look for the canvases if no
 * canvases were passed in the "config.canvases" field.
 */
Echo.Loader.init = function(config) {
	config = config || {};
	Echo.Loader.initEnvironment(function() {
		var $ = Echo.jQuery;
		var canvases = config.canvases;

		// convert a single canvas to the 1-element array
		// to keep the same contract below in the code
		if (canvases && !$.isArray(canvases) && !(canvases instanceof $)) {
			canvases = [canvases];
		}

		// if no canvases defined during initialization,
		// we look for all canvases in the target ('document' by default)
		canvases = canvases || $(".echo-canvas", config.target);

		if (!canvases.length) {
			Echo.Loader._error({
				"code": "no_canvases_found",
				"message": "No canvases found on the page..."
			});
			return;
		}

		$.map(canvases, function(canvas) {
			var target = $(canvas);
			var instance = new Echo.Canvas({
				"target": target,
				"overrides": Echo.Loader.overrides[target.data("canvas-id")]
			});
			Echo.Loader.canvases.push(instance);
		});
	});
};

/**
 * @static
 * Function to initialize application on the page. The function performs the following actions:
 *
 * + initializes Echo JavaScript environment (if it was not initialized yet)
 * + establishes the Backplane connection (if app.backplane is defined)
 * + establishes Echo User session on the page (if app.config.appkey is defined)
 * + downloads the application script
 * + calls the app JavaScript class constructor which handles further application initialization
 *
 * @param {Object} app
 * Object which defines the base app configuration.
 *
 * @param {String} app.component
 * The name of the JavaScript app class which should be initialized.
 *
 * @param {String} app.script
 * Appliction JavaScript class script URL.
 *
 * @param {Object} [app.scripts]
 * Object which specifies the location (URL) of the production (minified) and development
 * (non-minified) versions of the app JavaScript class code. The "prod" and "dev" keys
 * should be used in order to specify the production and development URLs respectively.
 *
 * @param {Object} [app.backplane]
 * Object which contains the data to be passed into the Backplane.init call.
 *
 * @param {Object} [app.config]
 * Parameters to be passed into the application constructor during its initialization.
 */
Echo.Loader.initApplication = function(app) {
	Echo.Loader.initEnvironment(function() {
		if (!app || !app.config || !app.config.target) {
			Echo.Loader._error({
				"args": {"app": app},
				"code": "invalid_app_config",
				"message": "Invalid config passed into the initApplication function"
			});
			return;
		}
		var instance = new Echo.Canvas({
			"target": app.config.target,
			"data": { // as we receive if from the Canvas Storage
				"apps": [app],
				"backplane": app.backplane
			}
		});
		Echo.Loader.canvases.push(instance);
	});
};

Echo.Loader._error = function(data) {
	if (!Echo.Events || !Echo.Utils || !Echo.jQuery) return;
	Echo.Events.publish({
		"topic": "Echo.Loader.onError",
		"data": data
	});
	Echo.Utils.log(Echo.jQuery.extend(data, {"type": "error", "component": "Echo.Loader"}));
};

// implementation of the "map" function for the cases when jQuery is not loaded yet
Echo.Loader._map = function(list, iterator) {
	var result = [];
	if (list && list.length && iterator) {
		for (var i = 0; i < list.length; i++) {
			var value = iterator(list[i], i);
			if (value === false) break; // jQuery-like convention
			if (typeof value !== "undefined") result.push(value);
		}
	}
	return result;
};

Echo.Loader._areResourcesReady = function(resources) {
	var state = Echo.Loader.vars.state;
	var resourceReadyFlags = Echo.Loader._map(resources, function(resource) {
		var url = Echo.Loader.getURL(resource.url);
		// the 'true' flag will be added into the
		// result array only when resource is ready
		return (resource.loaded && resource.loaded()) ||
			(state.resources[url] && state.resources[url] === "ready");
	});
	return resources.length === resourceReadyFlags.length;
};

})();
<|endoftext|>


<commit_before>require('enyo');

var
	json = require('./json'),
	utils = require('./utils'),
	platform = require('./platform');

/**
* These platforms only allow one argument for [console.log()]{@glossary console.log}:
*
* * android
* * ios
* * webos
*
* @private
*/
var dumbConsole = Boolean(platform.android || platform.ios || platform.webos);

/**
* Internally used methods and properties associated with logging.
*
* @module enyo/logging
* @public
*/
exports = module.exports = {

	/**
	* The log level to use. Can be a value from -1 to 99, where -1 disables all
	* logging, 0 is 'error', 10 is 'warn', and 20 is 'log'. It is preferred that
	* this value be set using the [setLogLevel()]{@link module:enyo/logging#setLogLevel}
	* method.
	*
	* @type {Number}
	* @default 99
	* @public
	*/
	level: 99,

	/**
	* The known levels.
	*
	* @private
	*/
	levels: {log: 20, warn: 10, error: 0},

	/**
	* @private
	*/
	shouldLog: function (fn) {
		var ll = parseInt(this.levels[fn], 0);
		return (ll <= this.level);
	},

	/**
	* @private
	*/
	validateArgs: function (args) {
		// gracefully handle and prevent circular reference errors in objects
		for (var i=0, l=args.length, item; (item=args[i]) || i<l; i++) {
			try {
				if (typeof item === 'object') {
					args[i] = json.stringify(item);
				}
			} catch (e) {
				args[i] = 'Error: ' + e.message;
			}
		}
	},

	/**
	* @private
	*/
	_log: function (fn, args) {
		// avoid trying to use console on IE instances where the object hasn't been
		// created due to the developer tools being unopened
		var console = global.console;
		if (typeof console === 'undefined') {
            return;
        }
		//var a$ = utils.logging.formatArgs(fn, args);
		var a$ = utils.isArray(args) ? args : utils.cloneArray(args);
		if (platform.androidFirefox) {
			// Firefox for Android's console does not handle objects with circular references
			this.validateArgs(a$);
		}
		if (dumbConsole) {
			// at least in early versions of webos, console.* only accept a single argument
			a$ = [a$.join(' ')];
		}
		var fn$ = console[fn];
		if (fn$ && fn$.apply) {
			// some consoles support 'warn', 'info', and so on
			fn$.apply(console, a$);
		} else if (console.log.apply) {
			// some consoles support console.log.apply
			console.log.apply(console, a$);
		} else {
			// otherwise, do our own formatting
			console.log(a$.join(' '));
		}
	},

	/**
	* This is exposed elsewhere.
	*
	* @private
	*/
	log: function (fn, args) {

		if (fn != 'log' && fn != 'warn' && fn != 'error') {
			args = Array.prototype.slice.call(arguments);
			fn = 'log';
		}

		var console = global.console;
		if (typeof console !== 'undefined') {
			if (this.shouldLog(fn)) {
				this._log(fn, args);
			}
		}
	}
};

/**
* Sets the log level to the given value. This will restrict the amount of output depending on
* the settings. The higher the value, the more output that will be allowed. The default is
* 99. The value, -1, would silence all logging, even 'error' (0).
* Without the 'see': {@link module:enyo/logging#log}.
*
* @see module:enyo/logging#level
* @see module:enyo/logging#log
* @see module:enyo/logging#warn
* @see module:enyo/logging#error
* @param {Number} level - The level to set logging to.
*/
exports.setLogLevel = function (level) {
	var ll = parseInt(level, 0);
	if (isFinite(ll)) {
		this.level = ll;
	}
};

/**
* A wrapper for [console.log()]{@glossary console.log}, compatible
* across supported platforms. Will output only if the current
* [log level]{@link module:enyo/logging#level} allows it. [Object]{@glossary Object}
* parameters will be serialized via [JSON.stringify()]{@glossary JSON.stringify}
* automatically.
*
* @utility
* @see {@glossary console.log}
* @param {...*} - The arguments to be logged.
* @public
*/

/**
* A wrapper for [console.warn()]{@glossary console.warn}, compatible
* across supported platforms. Will output only if the current
* [log level]{@link module:enyo/logging#level} allows it. [Object]{@glossary Object}
* parameters will be serialized via [JSON.stringify()]{@glossary JSON.stringify}
* automatically.
*
* @utility
* @see {@glossary console.warn}
* @param {...*} - The arguments to be logged.
* @public
*/
exports.warn = function () {
	this.log('warn', arguments);
};

/**
* A wrapper for [console.error()]{@glossary console.error}, compatible
* across supported platforms. Will output only if the current
* [log level]{@link module:enyo/logging#level} allows it. [Object]{@glossary Object}
* parameters will be serialized via [JSON.stringify()]{@glossary JSON.stringify}
* automatically.
*
* @utility
* @see {@glossary console.error}
* @param {...*} - The arguments to be logged.
* @public
*/
exports.error = function () {
	this.log('error', arguments);
};
<commit_msg>ENYO-2993: Use correct module name.<commit_after>require('enyo');

var
	json = require('./json'),
	utils = require('./utils'),
	platform = require('./platform');

/**
* These platforms only allow one argument for [console.log()]{@glossary console.log}:
*
* * android
* * ios
* * webos
*
* @private
*/
var dumbConsole = Boolean(platform.android || platform.ios || platform.webos);

/**
* Internally used methods and properties associated with logging.
*
* @module enyo/logger
* @public
*/
exports = module.exports = {

	/**
	* The log level to use. Can be a value from -1 to 99, where -1 disables all
	* logging, 0 is 'error', 10 is 'warn', and 20 is 'log'. It is preferred that
	* this value be set using the [setLogLevel()]{@link module:enyo/logger#setLogLevel}
	* method.
	*
	* @type {Number}
	* @default 99
	* @public
	*/
	level: 99,

	/**
	* The known levels.
	*
	* @private
	*/
	levels: {log: 20, warn: 10, error: 0},

	/**
	* @private
	*/
	shouldLog: function (fn) {
		var ll = parseInt(this.levels[fn], 0);
		return (ll <= this.level);
	},

	/**
	* @private
	*/
	validateArgs: function (args) {
		// gracefully handle and prevent circular reference errors in objects
		for (var i=0, l=args.length, item; (item=args[i]) || i<l; i++) {
			try {
				if (typeof item === 'object') {
					args[i] = json.stringify(item);
				}
			} catch (e) {
				args[i] = 'Error: ' + e.message;
			}
		}
	},

	/**
	* @private
	*/
	_log: function (fn, args) {
		// avoid trying to use console on IE instances where the object hasn't been
		// created due to the developer tools being unopened
		var console = global.console;
		if (typeof console === 'undefined') {
            return;
        }
		//var a$ = utils.logging.formatArgs(fn, args);
		var a$ = utils.isArray(args) ? args : utils.cloneArray(args);
		if (platform.androidFirefox) {
			// Firefox for Android's console does not handle objects with circular references
			this.validateArgs(a$);
		}
		if (dumbConsole) {
			// at least in early versions of webos, console.* only accept a single argument
			a$ = [a$.join(' ')];
		}
		var fn$ = console[fn];
		if (fn$ && fn$.apply) {
			// some consoles support 'warn', 'info', and so on
			fn$.apply(console, a$);
		} else if (console.log.apply) {
			// some consoles support console.log.apply
			console.log.apply(console, a$);
		} else {
			// otherwise, do our own formatting
			console.log(a$.join(' '));
		}
	},

	/**
	* This is exposed elsewhere.
	*
	* @private
	*/
	log: function (fn, args) {

		if (fn != 'log' && fn != 'warn' && fn != 'error') {
			args = Array.prototype.slice.call(arguments);
			fn = 'log';
		}

		var console = global.console;
		if (typeof console !== 'undefined') {
			if (this.shouldLog(fn)) {
				this._log(fn, args);
			}
		}
	}
};

/**
* Sets the log level to the given value. This will restrict the amount of output depending on
* the settings. The higher the value, the more output that will be allowed. The default is
* 99. The value, -1, would silence all logging, even 'error' (0).
* Without the 'see': {@link module:enyo/logger#log}.
*
* @see module:enyo/logger#level
* @see module:enyo/logger#log
* @see module:enyo/logger#warn
* @see module:enyo/logger#error
* @param {Number} level - The level to set logging to.
*/
exports.setLogLevel = function (level) {
	var ll = parseInt(level, 0);
	if (isFinite(ll)) {
		this.level = ll;
	}
};

/**
* A wrapper for [console.log()]{@glossary console.log}, compatible
* across supported platforms. Will output only if the current
* [log level]{@link module:enyo/logger#level} allows it. [Object]{@glossary Object}
* parameters will be serialized via [JSON.stringify()]{@glossary JSON.stringify}
* automatically.
*
* @utility
* @see {@glossary console.log}
* @param {...*} - The arguments to be logged.
* @public
*/

/**
* A wrapper for [console.warn()]{@glossary console.warn}, compatible
* across supported platforms. Will output only if the current
* [log level]{@link module:enyo/logger#level} allows it. [Object]{@glossary Object}
* parameters will be serialized via [JSON.stringify()]{@glossary JSON.stringify}
* automatically.
*
* @utility
* @see {@glossary console.warn}
* @param {...*} - The arguments to be logged.
* @public
*/
exports.warn = function () {
	this.log('warn', arguments);
};

/**
* A wrapper for [console.error()]{@glossary console.error}, compatible
* across supported platforms. Will output only if the current
* [log level]{@link module:enyo/logger#level} allows it. [Object]{@glossary Object}
* parameters will be serialized via [JSON.stringify()]{@glossary JSON.stringify}
* automatically.
*
* @utility
* @see {@glossary console.error}
* @param {...*} - The arguments to be logged.
* @public
*/
exports.error = function () {
	this.log('error', arguments);
};
<|endoftext|>


<commit_before>export class Logger {

  /**
   * Logging interface for the riot-view-router mixin.
   * @param {Router} router - Router for utilities to reference
   */
  constructor (router) {
    this.$router = router
    this.logs = []

    Object.defineProperty(this, 'time', {
      get: function() {
        return new Date().getTime()
      }
    })
  }

  /**
   * Format log for logstore
   * @param {string} message - message to log.
   * @param {int} timestamp - timestamp for log.
   */
  _format(message, timestamp) {
    return `[${new Date(timestamp).toString()}]: (riot-view-router) "${message}"`
  }

  /**
   * Fetch logs, allows for filtering by type.
   * @param {string} type - Log type to filter by.
   * @returns {Array}
   */
  $get (type) {
    return this.logs.filter((log) => type ? log.type == type : true)
  }

  /**
   * Pushes provided message to log store.
   * @param {string} message - Message to log.
   */
  log (message) {
    const timestamp = this.time
    if (this.$router.debugging)
      console.log(this._format(message, timestamp))
    this.logs.push({ type: 'general', message, timestamp })
  }

  /**
   * Pushes provided message to log store.
   * @param {string} message - Message to log.
   */
  warn (message) {
    const timestamp = this.time
    if (this.$router.debugging)
      console.warn(this._format(message, timestamp))
    this.logs.push({ type: 'warning', message, timestamp })
  }

  /**
   * Pushes provided message to log store.
   * @param {string} message - Message to log.
   */
  error (message) {
    const timestamp = this.time
    if (this.$router.debugging)
      console.error(this._format(message, timestamp))
    this.logs.push({ type: 'critical', message, timestamp })
  }

}
<commit_msg>Fixed debugging references in logger<commit_after>export class Logger {

  /**
   * Logging interface for the riot-view-router mixin.
   * @param {Router} router - Router for utilities to reference
   */
  constructor (router) {
    this.$router = router
    this.logs = []

    Object.defineProperty(this, 'time', {
      get: function() {
        return new Date().getTime()
      }
    })
  }

  /**
   * Format log for logstore
   * @param {string} message - message to log.
   * @param {int} timestamp - timestamp for log.
   */
  _format(message, timestamp) {
    return `[${new Date(timestamp).toString()}]: (riot-view-router) "${message}"`
  }

  /**
   * Fetch logs, allows for filtering by type.
   * @param {string} type - Log type to filter by.
   * @returns {Array}
   */
  $get (type) {
    return this.logs.filter((log) => type ? log.type == type : true)
  }

  /**
   * Pushes provided message to log store.
   * @param {string} message - Message to log.
   */
  log (message) {
    const timestamp = this.time
    if (this.$router.settings.debugging)
      console.log(this._format(message, timestamp))
    this.logs.push({ type: 'general', message, timestamp })
  }

  /**
   * Pushes provided message to log store.
   * @param {string} message - Message to log.
   */
  warn (message) {
    const timestamp = this.time
    if (this.$router.settings.debugging)
      console.warn(this._format(message, timestamp))
    this.logs.push({ type: 'warning', message, timestamp })
  }

  /**
   * Pushes provided message to log store.
   * @param {string} message - Message to log.
   */
  error (message) {
    const timestamp = this.time
    if (this.$router.settings.debugging)
      console.error(this._format(message, timestamp))
    this.logs.push({ type: 'critical', message, timestamp })
  }

}
<|endoftext|>


<commit_before>/* @flow strict-local */
import React from 'react';
import { Platform } from 'react-native';
import { TabNavigator, TabBarBottom } from 'react-navigation';

import type { TabNavigationOptionsPropsType } from '../types';
import tabsOptions from '../styles/tabs';
import HomeTab from './HomeTab';
import StreamTabs from './StreamTabs';
import PmConversationsCard from '../pm-conversations/PmConversationsCard';
import SettingsCard from '../settings/SettingsCard';
import { IconHome, IconStream, IconSettings } from '../common/Icons';
import IconUnreadConversations from '../nav/IconUnreadConversations';

export default TabNavigator(
  {
    home: {
      screen: HomeTab,
      navigationOptions: {
        tabBarLabel: 'Home',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => (
          <IconHome size={24} color={props.tintColor} />
        ),
      },
    },
    streams: {
      screen: StreamTabs,
      navigationOptions: {
        tabBarLabel: 'Streams',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => (
          <IconStream size={24} color={props.tintColor} />
        ),
      },
    },
    conversations: {
      screen: PmConversationsCard,
      navigationOptions: {
        tabBarLabel: 'Conversations',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => (
          <IconUnreadConversations color={props.tintColor} />
        ),
      },
    },
    settings: {
      screen: SettingsCard,
      navigationOptions: {
        tabBarLabel: 'Settings',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => (
          <IconSettings size={24} color={props.tintColor} />
        ),
      },
    },
  },
  {
    backBehavior: 'none',
    tabBarComponent: TabBarBottom,
    tabBarPosition: 'bottom',
    ...tabsOptions({
      showLabel: !!Platform.isPad,
      showIcon: true,
    }),
  },
);
<commit_msg>ProfileCard: Add to MainTabs.<commit_after>/* @flow strict-local */
import React from 'react';
import { Platform } from 'react-native';
import { TabNavigator, TabBarBottom } from 'react-navigation';

import type { TabNavigationOptionsPropsType } from '../types';
import tabsOptions from '../styles/tabs';
import HomeTab from './HomeTab';
import StreamTabs from './StreamTabs';
import PmConversationsCard from '../pm-conversations/PmConversationsCard';
import SettingsCard from '../settings/SettingsCard';
import { IconHome, IconSettings, IconStream } from '../common/Icons';
import { OwnAvatar } from '../common';
import IconUnreadConversations from '../nav/IconUnreadConversations';
import ProfileCard from '../account-info/ProfileCard';

export default TabNavigator(
  {
    home: {
      screen: HomeTab,
      navigationOptions: {
        tabBarLabel: 'Home',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => (
          <IconHome size={24} color={props.tintColor} />
        ),
      },
    },
    streams: {
      screen: StreamTabs,
      navigationOptions: {
        tabBarLabel: 'Streams',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => (
          <IconStream size={24} color={props.tintColor} />
        ),
      },
    },
    conversations: {
      screen: PmConversationsCard,
      navigationOptions: {
        tabBarLabel: 'Conversations',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => (
          <IconUnreadConversations color={props.tintColor} />
        ),
      },
    },
    settings: {
      screen: SettingsCard,
      navigationOptions: {
        tabBarLabel: 'Settings',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => (
          <IconSettings size={24} color={props.tintColor} />
        ),
      },
    },
    profile: {
      screen: ProfileCard,
      navigationOptions: {
        tabBarLabel: 'Profile',
        tabBarIcon: (props: TabNavigationOptionsPropsType) => <OwnAvatar size={24} />,
      },
    },
  },
  {
    backBehavior: 'none',
    tabBarComponent: TabBarBottom,
    tabBarPosition: 'bottom',
    ...tabsOptions({
      showLabel: !!Platform.isPad,
      showIcon: true,
    }),
  },
);
<|endoftext|>


<commit_before>/**
 * [Miscellaneous description]
 */

function Miscellaneous($, _content) {

    /**
     * [createFixedToolbar description]
     * @return {[type]}
     */
    this.createFixedToolbar = function() {
        $("div#header").css({
            "position": "fixed",
            "zIndex": 10,
            "top": 0
        });
        $("div#monkey").css("margin-top", "88px");
    };

    /**
     * Vergrößert den Content-Bereich um 200px.
     * Sorgt leider für ein "Flackern" wenn man die Seite lädt, da das CSS relativ spät geladen wird.
     * Lässt sich glaube ich nicht ändern im Userscript.
     */
    this.makeContentWider = function() {
        var maxWidth = 1200,
            leftSidebarWidth = $("#c_left").outerWidth(),
            rightSidebarWidth = $("#c_right").outerWidth(),
            sidebarsWidth = !leftSidebarWidth ? rightSidebarWidth + 1 : !rightSidebarWidth ? leftSidebarWidth + 1 : (leftSidebarWidth && rightSidebarWidth) ? leftSidebarWidth + rightSidebarWidth : 1200,
            padding = 4,
            siteLocation = new SiteLocation($);

        $("#header > div > div").css({
            "width": maxWidth + "px"
        });

        $("#monkey").css({
            "maxWidth": maxWidth + "px",
            "width": maxWidth + "px"
        });

        $("#container").css({
            "width": maxWidth + "px"
        });

        $("#c_content").css({
            "width": (maxWidth - sidebarsWidth - padding) + "px"
        });

        // fixt den Livestream Bereich
        if(siteLocation.getLocation("livestreams")) {
            // vergroessert die Livestream Thumbnails im Highlight Bereich um 30%
            $("#c_content > .livestream_highlights").find(".livestream_cap > img").each(function() {
                $(this).css("height", $(this).height() * 1.3 + "px");
                $(this).css("width", $(this).width() * 1.3 + "px");
            });
        }

        // fixt den VOD Bereich
        if(siteLocation.getLocation("vods")) {
            //vergroessert die VOD Thumbnails im Highlight Bereich um 30%
            $("#c_content > .vod_highlights").find(".vod_thumb > img").each(function() {
                $(this).css("height", $(this).height() * 1.3 + "px");
                $(this).css("width", $(this).width() * 1.3 + "px");
            });

            // veraendert die Margins der VOD Thumbnails, damit sie sauber in einer Reihe angezeigt werden
            $("#c_content > .vod_videos_list > li").each(function() {
                $(this).css("margin", "0px 10px 10px 10px");
            });
        }

        // fixt den Gallery Bereich
        if(siteLocation.getLocation("gallery")) {
            // verandert die Margins der Thumbnails, damit sie saber in einer Reihe angezeigt werden
            $("#c_content > .gallery_albums > li").each(function() {
                $(this).css("margin", "0px 5px 5px 10px");
            });
        }

        // fixt den verzerrten YouTube Player im Forum
        if(siteLocation.getLocation("forums")) {
            $(".forum_ed_youtube embed").each(function() {
                $(this).css("height", $(this).width() * (9 / 16) + "px");
            });
        }

        // fixt den verzerrten YouTube Player in den News
        if (siteLocation.getLocation("news")) {
            $("iframe").each(function () {
                if ($(this).attr("src").match(/^http:\/\/(?:www\.)?youtube.com\/embed\/\w+(&\S*)?$/)) {
                    $(this).css("height", $(this).width() * (9 / 16) + "px");
                }
            })
        }

        // fixt den verzerrten YouTube Player in den Schlagzeilen
        if (siteLocation.getLocation("headlines")) {
            $("iframe").each(function () {
                if ($(this).attr("src").match(/^http:\/\/(?:www\.)?youtube.com\/embed\/\w+(&\S*)?$/)) {
                    $(this).css("height", $(this).width() * (9 / 16) + "px");
                }
            })
        }
    };

    /**
     * Ändert den Pfeil im Forum so, dass er zum letzten Post springt, nicht zum letzten gelesenen.
     */
    this.changeForumArrowBehavior = function() {
        $("img[src$='arrow_last_item.gif']").each(function() {
            var e = $(this).parent("a"),
                url = e.attr("href"),
                newLink = url.substring(0, url.lastIndexOf("/")) + "&page=last#plast";

            e.attr("href", newLink);
        });
    };

    /**
     * Sortiert den Thread-Titel um, sodass dieser an erster Stelle steht.
     */
    this.resortTitle = function () {
        var title = $('head').find('title').text();
        var pieces = title.split(' \u00BB Thread: ');

        document.title = pieces.reverse().join(' \u00BB ').replace(/^Thread:\W+/, '');
    };

    this.buttonScrollUp = function(){
        $('#c_content h2:last').append('')
            .find('#icon_miscellaneous_buttonScrollUp')
            .on('click', function(){
                window.scrollTo(0, 0);
            });
    };

    this.buttonScrollDown = function(){
        $('#c_content h1:first').append('')
            .find('#icon_miscellaneous_buttonScrollDown')
            .on('click', function(){
                window.scrollTo(0, document.body.offsetHeight);
            });
    }
}
<commit_msg>BUGFIX: changeForumArrowBehavior<commit_after>/**
 * [Miscellaneous description]
 */

function Miscellaneous($, _content) {

    /**
     * [createFixedToolbar description]
     * @return {[type]}
     */
    this.createFixedToolbar = function() {
        $("div#header").css({
            "position": "fixed",
            "zIndex": 10,
            "top": 0
        });
        $("div#monkey").css("margin-top", "88px");
    };

    /**
     * Vergrößert den Content-Bereich um 200px.
     * Sorgt leider für ein "Flackern" wenn man die Seite lädt, da das CSS relativ spät geladen wird.
     * Lässt sich glaube ich nicht ändern im Userscript.
     */
    this.makeContentWider = function() {
        var maxWidth = 1200,
            leftSidebarWidth = $("#c_left").outerWidth(),
            rightSidebarWidth = $("#c_right").outerWidth(),
            sidebarsWidth = !leftSidebarWidth ? rightSidebarWidth + 1 : !rightSidebarWidth ? leftSidebarWidth + 1 : (leftSidebarWidth && rightSidebarWidth) ? leftSidebarWidth + rightSidebarWidth : 1200,
            padding = 4,
            siteLocation = new SiteLocation($);

        $("#header > div > div").css({
            "width": maxWidth + "px"
        });

        $("#monkey").css({
            "maxWidth": maxWidth + "px",
            "width": maxWidth + "px"
        });

        $("#container").css({
            "width": maxWidth + "px"
        });

        $("#c_content").css({
            "width": (maxWidth - sidebarsWidth - padding) + "px"
        });

        // fixt den Livestream Bereich
        if(siteLocation.getLocation("livestreams")) {
            // vergroessert die Livestream Thumbnails im Highlight Bereich um 30%
            $("#c_content > .livestream_highlights").find(".livestream_cap > img").each(function() {
                $(this).css("height", $(this).height() * 1.3 + "px");
                $(this).css("width", $(this).width() * 1.3 + "px");
            });
        }

        // fixt den VOD Bereich
        if(siteLocation.getLocation("vods")) {
            //vergroessert die VOD Thumbnails im Highlight Bereich um 30%
            $("#c_content > .vod_highlights").find(".vod_thumb > img").each(function() {
                $(this).css("height", $(this).height() * 1.3 + "px");
                $(this).css("width", $(this).width() * 1.3 + "px");
            });

            // veraendert die Margins der VOD Thumbnails, damit sie sauber in einer Reihe angezeigt werden
            $("#c_content > .vod_videos_list > li").each(function() {
                $(this).css("margin", "0px 10px 10px 10px");
            });
        }

        // fixt den Gallery Bereich
        if(siteLocation.getLocation("gallery")) {
            // verandert die Margins der Thumbnails, damit sie saber in einer Reihe angezeigt werden
            $("#c_content > .gallery_albums > li").each(function() {
                $(this).css("margin", "0px 5px 5px 10px");
            });
        }

        // fixt den verzerrten YouTube Player im Forum
        if(siteLocation.getLocation("forums")) {
            $(".forum_ed_youtube embed").each(function() {
                $(this).css("height", $(this).width() * (9 / 16) + "px");
            });
        }

        // fixt den verzerrten YouTube Player in den News
        if (siteLocation.getLocation("news")) {
            $("iframe").each(function () {
                if ($(this).attr("src").match(/^http:\/\/(?:www\.)?youtube.com\/embed\/\w+(&\S*)?$/)) {
                    $(this).css("height", $(this).width() * (9 / 16) + "px");
                }
            })
        }

        // fixt den verzerrten YouTube Player in den Schlagzeilen
        if (siteLocation.getLocation("headlines")) {
            $("iframe").each(function () {
                if ($(this).attr("src").match(/^http:\/\/(?:www\.)?youtube.com\/embed\/\w+(&\S*)?$/)) {
                    $(this).css("height", $(this).width() * (9 / 16) + "px");
                }
            })
        }
    };

    /**
     * Ändert den Pfeil im Forum so, dass er zum letzten Post springt, nicht zum letzten gelesenen.
     */
    this.changeForumArrowBehavior = function() {
        _content.get('forumNavigation')
            .find('img[src$=\'arrow_last_item2.gif\']')
            .each(function() {

                var parentA = this.parentElement;
                parentA.href = parentA.href + '#plast';
        });
    };

    /**
     * Sortiert den Thread-Titel um, sodass dieser an erster Stelle steht.
     */
    this.resortTitle = function () {
        var title = $('head').find('title').text();
        var pieces = title.split(' \u00BB Thread: ');

        document.title = pieces.reverse().join(' \u00BB ').replace(/^Thread:\W+/, '');
    };

    this.buttonScrollUp = function(){
        $('#c_content h2:last').append('')
            .find('#icon_miscellaneous_buttonScrollUp')
            .on('click', function(){
                window.scrollTo(0, 0);
            });
    };

    this.buttonScrollDown = function(){
        $('#c_content h1:first').append('')
            .find('#icon_miscellaneous_buttonScrollDown')
            .on('click', function(){
                window.scrollTo(0, document.body.offsetHeight);
            });
    }
}
<|endoftext|>