<commit_before>define(function(require) {
	'use strict';

	var demoModule = require('demo/demo-module');

	describe('Title directive', function() {
		var element, scope;

		beforeEach(module(demoModule.name));

		beforeEach(inject(function($rootScope, $compile) {
			scope = $rootScope.$new();

			element = '<app-title></app-title>';

			element = $compile(element)(scope);
			scope.$digest();
		}));

		it('should create a title heading', function() {
			expect(element.text().trim()).toBe('<%= appname %>');
		});
	});
});
<commit_msg>Fixing bug in app title spec<commit_after>define(function(require) {
	'use strict';

	require('angular.mocks');

	var demoModule = require('demo/demo-module');

	describe('Title directive', function() {
		var element, scope;

		beforeEach(module(demoModule.name));

		beforeEach(inject(function($rootScope, $compile) {
			scope = $rootScope.$new();

			element = '<app-title></app-title>';

			element = $compile(element)(scope);
			scope.$digest();
		}));

		it('should create a title heading', function() {
			expect(element.text().trim()).toBe('<%= appname %>');
		});
	});
});
<|endoftext|>


<commit_before>/*
 * JavaScript tracker for SnowPlow: helpers.js
 *
 * Significant portions copyright 2010 Anthon Pang. Remainder copyright
 * 2012-2013 SnowPlow Analytics Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of Anthon Pang nor SnowPlow Analytics Ltd nor the
 *   names of their contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Is property defined?
 */
SnowPlow.isDefined = function (property) {
	return typeof property !== 'undefined';
}

/*
 * Is property a function?
 */
SnowPlow.isFunction = function (property) {
	return typeof property === 'function';
}

/*
 * Is property an object?
 *
 * @return bool Returns true if property is null, an Object, or subclass of Object (i.e., an instanceof String, Date, etc.)
 */
SnowPlow.isObject = function (property) {
	return typeof property === 'object';
}

/*
 * Is property a string?
 */
SnowPlow.isString = function (property) {
	return typeof property === 'string' || property instanceof String;
}

/*
 * UTF-8 encoding
 */
SnowPlow.encodeUtf8 = function (argString) {
	return SnowPlow.decodeUrl(SnowPlow.encodeWrapper(argString));
}

/**
 * Cleans up the page title
 */
SnowPlow.fixupTitle = function (title) {
	if (!SnowPlow.isString(title)) {
		title = title.text || '';

		var tmp = SnowPlow.documentAlias.getElementsByTagName('title');
		if (tmp && SnowPlow.isDefined(tmp[0])) {
			title = tmp[0].text;
		}
	}
	return title;
}

/*
 * Extract hostname from URL
 */
SnowPlow.getHostName = function (url) {
	// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
	var e = new RegExp('^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)'),
		matches = e.exec(url);

	return matches ? matches[1] : url;
}

/*
 * Fix-up URL when page rendered from search engine cache or translated page.
 * TODO: it would be nice to generalise this and/or move into the ETL phase.
 */
SnowPlow.fixupUrl = function (hostName, href, referrer) {
	/*
	 * Extract parameter from URL
	 */
	function getParameter(url, name) {
		// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
		var e = new RegExp('^(?:https?|ftp)(?::/*(?:[^?]+)[?])([^#]+)'),
			matches = e.exec(url),
			f = new RegExp('(?:^|&)' + name + '=([^&]*)'),
			result = matches ? f.exec(matches[1]) : 0;

		return result ? SnowPlow.decodeWrapper(result[1]) : '';
	}

	if (hostName === 'translate.googleusercontent.com') {		// Google
		if (referrer === '') {
			referrer = href;
		}
		href = getParameter(href, 'u');
		hostName = SnowPlow.getHostName(href);
	} else if (hostName === 'cc.bingj.com' ||					// Bing
			hostName === 'webcache.googleusercontent.com' ||	// Google
			hostName.slice(0, 5) === '74.6.') {					// Yahoo (via Inktomi 74.6.0.0/16)
		href = SnowPlow.documentAlias.links[0].href;
		hostName = SnowPlow.getHostName(href);
	}
	return [hostName, href, referrer];
}

/*
 * Fix-up domain
 */
SnowPlow.fixupDomain = function (domain) {
	var dl = domain.length;

	// remove trailing '.'
	if (domain.charAt(--dl) === '.') {
		domain = domain.slice(0, dl);
	}
	// remove leading '*'
	if (domain.slice(0, 2) === '*.') {
		domain = domain.slice(1);
	}
	return domain;
}

/*
 * Get page referrer
 */
SnowPlow.getReferrer = function () {
	var referrer = '';

	try {
		referrer = SnowPlow.windowAlias.top.document.referrer;
	} catch (e) {
		if (SnowPlow.windowAlias.parent) {
			try {
				referrer = SnowPlow.windowAlias.parent.document.referrer;
			} catch (e2) {
				referrer = '';
			}
		}
	}
	if (referrer === '') {
		referrer = SnowPlow.documentAlias.referrer;
	}

	return referrer;
}

/*
 * Cross-browser helper function to add event handler
 */
SnowPlow.addEventListener = function (element, eventType, eventHandler, useCapture) {
	if (element.addEventListener) {
		element.addEventListener(eventType, eventHandler, useCapture);
		return true;
	}
	if (element.attachEvent) {
		return element.attachEvent('on' + eventType, eventHandler);
	}
	element['on' + eventType] = eventHandler;
}

/*
 * Get cookie value
 */
SnowPlow.getCookie = function (cookieName) {
	var cookiePattern = new RegExp('(^|;)[ ]*' + cookieName + '=([^;]*)'),
			cookieMatch = cookiePattern.exec(SnowPlow.documentAlias.cookie);

	return cookieMatch ? SnowPlow.decodeWrapper(cookieMatch[2]) : 0;
}

/*
 * Set cookie value
 */
SnowPlow.setCookie = function (cookieName, value, msToExpire, path, domain, secure) {
	var expiryDate;

	// relative time to expire in milliseconds
	if (msToExpire) {
		expiryDate = new Date();
		expiryDate.setTime(expiryDate.getTime() + msToExpire);
	}

	SnowPlow.documentAlias.cookie = cookieName + '=' + SnowPlow.encodeWrapper(value) +
		(msToExpire ? ';expires=' + expiryDate.toGMTString() : '') +
		';path=' + (path || '/') +
		(domain ? ';domain=' + domain : '') +
		(secure ? ';secure' : '');
}

/*
 * Call plugin hook methods
 */
SnowPlow.executePluginMethod = function (methodName, callback) {
	var result = '',
			i,
			pluginMethod;

	for (i in SnowPlow.plugins) {
		if (Object.prototype.hasOwnProperty.call(SnowPlow.plugins, i)) {
			pluginMethod = SnowPlow.plugins[i][methodName];
			if (SnowPlow.isFunction(pluginMethod)) {
				result += pluginMethod(callback);
			}
		}
	}

	return result;
}

<commit_msg>Add a Base64 encoding helper with delegating to native implementation (if any)<commit_after>/*
 * JavaScript tracker for SnowPlow: helpers.js
 *
 * Significant portions copyright 2010 Anthon Pang. Remainder copyright
 * 2012-2013 SnowPlow Analytics Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of Anthon Pang nor SnowPlow Analytics Ltd nor the
 *   names of their contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Is property defined?
 */
SnowPlow.isDefined = function (property) {
	return typeof property !== 'undefined';
}

/*
 * Is property a function?
 */
SnowPlow.isFunction = function (property) {
	return typeof property === 'function';
}

/*
 * Is property an object?
 *
 * @return bool Returns true if property is null, an Object, or subclass of Object (i.e., an instanceof String, Date, etc.)
 */
SnowPlow.isObject = function (property) {
	return typeof property === 'object';
}

/*
 * Is property a string?
 */
SnowPlow.isString = function (property) {
	return typeof property === 'string' || property instanceof String;
}

/*
 * UTF-8 encoding
 */
SnowPlow.encodeUtf8 = function (argString) {
	return SnowPlow.decodeUrl(SnowPlow.encodeWrapper(argString));
}

/**
 * Cleans up the page title
 */
SnowPlow.fixupTitle = function (title) {
	if (!SnowPlow.isString(title)) {
		title = title.text || '';

		var tmp = SnowPlow.documentAlias.getElementsByTagName('title');
		if (tmp && SnowPlow.isDefined(tmp[0])) {
			title = tmp[0].text;
		}
	}
	return title;
}

/*
 * Extract hostname from URL
 */
SnowPlow.getHostName = function (url) {
	// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
	var e = new RegExp('^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)'),
		matches = e.exec(url);

	return matches ? matches[1] : url;
}

/*
 * Fix-up URL when page rendered from search engine cache or translated page.
 * TODO: it would be nice to generalise this and/or move into the ETL phase.
 */
SnowPlow.fixupUrl = function (hostName, href, referrer) {
	/*
	 * Extract parameter from URL
	 */
	function getParameter(url, name) {
		// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
		var e = new RegExp('^(?:https?|ftp)(?::/*(?:[^?]+)[?])([^#]+)'),
			matches = e.exec(url),
			f = new RegExp('(?:^|&)' + name + '=([^&]*)'),
			result = matches ? f.exec(matches[1]) : 0;

		return result ? SnowPlow.decodeWrapper(result[1]) : '';
	}

	if (hostName === 'translate.googleusercontent.com') {		// Google
		if (referrer === '') {
			referrer = href;
		}
		href = getParameter(href, 'u');
		hostName = SnowPlow.getHostName(href);
	} else if (hostName === 'cc.bingj.com' ||					// Bing
			hostName === 'webcache.googleusercontent.com' ||	// Google
			hostName.slice(0, 5) === '74.6.') {					// Yahoo (via Inktomi 74.6.0.0/16)
		href = SnowPlow.documentAlias.links[0].href;
		hostName = SnowPlow.getHostName(href);
	}
	return [hostName, href, referrer];
}

/*
 * Fix-up domain
 */
SnowPlow.fixupDomain = function (domain) {
	var dl = domain.length;

	// remove trailing '.'
	if (domain.charAt(--dl) === '.') {
		domain = domain.slice(0, dl);
	}
	// remove leading '*'
	if (domain.slice(0, 2) === '*.') {
		domain = domain.slice(1);
	}
	return domain;
}

/*
 * Get page referrer
 */
SnowPlow.getReferrer = function () {
	var referrer = '';

	try {
		referrer = SnowPlow.windowAlias.top.document.referrer;
	} catch (e) {
		if (SnowPlow.windowAlias.parent) {
			try {
				referrer = SnowPlow.windowAlias.parent.document.referrer;
			} catch (e2) {
				referrer = '';
			}
		}
	}
	if (referrer === '') {
		referrer = SnowPlow.documentAlias.referrer;
	}

	return referrer;
}

/*
 * Cross-browser helper function to add event handler
 */
SnowPlow.addEventListener = function (element, eventType, eventHandler, useCapture) {
	if (element.addEventListener) {
		element.addEventListener(eventType, eventHandler, useCapture);
		return true;
	}
	if (element.attachEvent) {
		return element.attachEvent('on' + eventType, eventHandler);
	}
	element['on' + eventType] = eventHandler;
}

/*
 * Get cookie value
 */
SnowPlow.getCookie = function (cookieName) {
	var cookiePattern = new RegExp('(^|;)[ ]*' + cookieName + '=([^;]*)'),
			cookieMatch = cookiePattern.exec(SnowPlow.documentAlias.cookie);

	return cookieMatch ? SnowPlow.decodeWrapper(cookieMatch[2]) : 0;
}

/*
 * Set cookie value
 */
SnowPlow.setCookie = function (cookieName, value, msToExpire, path, domain, secure) {
	var expiryDate;

	// relative time to expire in milliseconds
	if (msToExpire) {
		expiryDate = new Date();
		expiryDate.setTime(expiryDate.getTime() + msToExpire);
	}

	SnowPlow.documentAlias.cookie = cookieName + '=' + SnowPlow.encodeWrapper(value) +
		(msToExpire ? ';expires=' + expiryDate.toGMTString() : '') +
		';path=' + (path || '/') +
		(domain ? ';domain=' + domain : '') +
		(secure ? ';secure' : '');
}

/*
 * Call plugin hook methods
 */
SnowPlow.executePluginMethod = function (methodName, callback) {
	var result = '',
			i,
			pluginMethod;

	for (i in SnowPlow.plugins) {
		if (Object.prototype.hasOwnProperty.call(SnowPlow.plugins, i)) {
			pluginMethod = SnowPlow.plugins[i][methodName];
			if (SnowPlow.isFunction(pluginMethod)) {
				result += pluginMethod(callback);
			}
		}
	}

	return result;
}

/*
 * Encode data with Base64
 * Taken and improved from https://github.com/kvz/phpjs
 */
SnowPlow.base64encode = function(data) {

  if (!data) return data;
  if (typeof window['btoa'] == 'function') return btoa(data);

  var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  var o1, o2, o3, h1, h2, h3, h4, bits,
      i = 0,
      ac = 0,
      enc = "",
      tmp_arr = [];

  do {
    o1 = data.charCodeAt(i++);
    o2 = data.charCodeAt(i++);
    o3 = data.charCodeAt(i++);

    bits = o1 << 16 | o2 << 8 | o3;

    h1 = bits >> 18 & 0x3f;
    h2 = bits >> 12 & 0x3f;
    h3 = bits >> 6 & 0x3f;
    h4 = bits & 0x3f;

    tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
  } while (i < data.length);

  enc = tmp_arr.join('');
  var r = data.length % 3;
  return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);

}

<|endoftext|>


<commit_before>import _ from 'lodash';
import log from './logger';
import { DEFAULT_MATCH_THRESHOLD } from './commands/images';
import { IMAGE_EL_TAP_STRATEGY_W3C, DEFAULT_TEMPLATE_IMAGE_SCALE } from './image-element';

const GLOBAL_DEFAULT_SETTINGS = {
  // value between 0 and 1 representing match strength, below which an image
  // element will not be found
  imageMatchThreshold: DEFAULT_MATCH_THRESHOLD,

  // if the image returned by getScreenshot differs in size or aspect ratio
  // from the screen, attempt to fix it automatically
  fixImageFindScreenshotDims: true,

  // whether Appium should ensure that an image template sent in during image
  // element find should have its size adjusted so the match algorithm will not
  // complain
  fixImageTemplateSize: false,

  // whether Appium should ensure that an image template sent in during image
  // element find should have its scale adjusted to display size so the match
  // algorithm will not complain.
  // e.g. iOS has `width=375, height=667` window rect, but its screenshot is
  //      `width=750 × height=1334` pixels. This setting help to adjust the scale
  //      if a user use `width=750 × height=1334` pixels's base template image.
  fixImageTemplateScale: false,

  // Users might have scaled template image to reduce their storage size.
  // This setting allows users to scale a template image they send to Appium server
  // so that the Appium server compares the actual scale users originally had.
  // e.g. If a user has an image of 270 x 32 pixels which was originally 1080 x 126 pixels,
  //      the user can set {defaultImageTemplateScale: 4.0} to scale the small image
  //      to the original one so that Appium can compare it as the original one.
  defaultImageTemplateScale: DEFAULT_TEMPLATE_IMAGE_SCALE,

  // whether Appium should re-check that an image element can be matched
  // against the current screenshot before clicking it
  checkForImageElementStaleness: true,

  // whether before clicking on an image element Appium should re-determine the
  // position of the element on screen
  autoUpdateImageElementPosition: false,

  // which method to use for tapping by coordinate for image elements. the
  // options are 'w3c' or 'mjsonwp'
  imageElementTapStrategy: IMAGE_EL_TAP_STRATEGY_W3C,

  // which method to use to save the matched image area in ImageElement class.
  // It is used for debugging purpose.
  getMatchedImageResult: false,
};

// declare settings that are really handled only by basedriver, so downstream
// drivers can choose to ignore them for their own settings validation, etc...
const BASEDRIVER_HANDLED_SETTINGS = [
  'imageMatchThreshold',
  'fixImageFindScreenshotDims',
  'fixImageTemplateSize',
  'fixImageTemplateScale',
  'defaultImageTemplateScale',
  'checkForImageElementStaleness',
  'autoUpdateImageElementPosition',
  'imageElementTapStrategy',
  'getMatchedImageResult',
];

class DeviceSettings {

  constructor (defaultSettings = {}, onSettingsUpdate = null) {
    this._settings = Object.assign({}, GLOBAL_DEFAULT_SETTINGS, defaultSettings);
    this.onSettingsUpdate = onSettingsUpdate;
  }

  // calls updateSettings from implementing driver every time a setting is changed.
  async update (newSettings) {
    if (!_.isObject(newSettings)) {
      throw new Error('Settings update should be called with valid JSON');
    }
    for (let prop of _.keys(newSettings)) {
      if (_.isUndefined(this._settings[prop])) {
        log.warn(`Didn't know about setting '${prop}'. Are you sure you ` +
                 `spelled it correctly? Proceeding anyway. Valid settings: ${_.keys(this._settings)}`);
      }
      if (this._settings[prop] !== newSettings[prop]) {
        // update setting only when there is updateSettings defined.
        if (this.onSettingsUpdate) {
          await this.onSettingsUpdate(prop, newSettings[prop], this._settings[prop]);
          this._settings[prop] = newSettings[prop];
        } else {
          log.errorAndThrow('Unable to update settings; onSettingsUpdate method not found');
        }
      }
    }
  }

  getSettings () {
    return this._settings;
  }
}

export default DeviceSettings;
export { DeviceSettings, BASEDRIVER_HANDLED_SETTINGS };
<commit_msg>refactor: Change the setting update validation, so we don't print unnecessary warnings (#372)<commit_after>import _ from 'lodash';
import log from './logger';
import { DEFAULT_MATCH_THRESHOLD } from './commands/images';
import { IMAGE_EL_TAP_STRATEGY_W3C, DEFAULT_TEMPLATE_IMAGE_SCALE } from './image-element';

const GLOBAL_DEFAULT_SETTINGS = {
  // value between 0 and 1 representing match strength, below which an image
  // element will not be found
  imageMatchThreshold: DEFAULT_MATCH_THRESHOLD,

  // if the image returned by getScreenshot differs in size or aspect ratio
  // from the screen, attempt to fix it automatically
  fixImageFindScreenshotDims: true,

  // whether Appium should ensure that an image template sent in during image
  // element find should have its size adjusted so the match algorithm will not
  // complain
  fixImageTemplateSize: false,

  // whether Appium should ensure that an image template sent in during image
  // element find should have its scale adjusted to display size so the match
  // algorithm will not complain.
  // e.g. iOS has `width=375, height=667` window rect, but its screenshot is
  //      `width=750 × height=1334` pixels. This setting help to adjust the scale
  //      if a user use `width=750 × height=1334` pixels's base template image.
  fixImageTemplateScale: false,

  // Users might have scaled template image to reduce their storage size.
  // This setting allows users to scale a template image they send to Appium server
  // so that the Appium server compares the actual scale users originally had.
  // e.g. If a user has an image of 270 x 32 pixels which was originally 1080 x 126 pixels,
  //      the user can set {defaultImageTemplateScale: 4.0} to scale the small image
  //      to the original one so that Appium can compare it as the original one.
  defaultImageTemplateScale: DEFAULT_TEMPLATE_IMAGE_SCALE,

  // whether Appium should re-check that an image element can be matched
  // against the current screenshot before clicking it
  checkForImageElementStaleness: true,

  // whether before clicking on an image element Appium should re-determine the
  // position of the element on screen
  autoUpdateImageElementPosition: false,

  // which method to use for tapping by coordinate for image elements. the
  // options are 'w3c' or 'mjsonwp'
  imageElementTapStrategy: IMAGE_EL_TAP_STRATEGY_W3C,

  // which method to use to save the matched image area in ImageElement class.
  // It is used for debugging purpose.
  getMatchedImageResult: false,
};

// declare settings that are really handled only by basedriver, so downstream
// drivers can choose to ignore them for their own settings validation, etc...
const BASEDRIVER_HANDLED_SETTINGS = [
  'imageMatchThreshold',
  'fixImageFindScreenshotDims',
  'fixImageTemplateSize',
  'fixImageTemplateScale',
  'defaultImageTemplateScale',
  'checkForImageElementStaleness',
  'autoUpdateImageElementPosition',
  'imageElementTapStrategy',
  'getMatchedImageResult',
];

class DeviceSettings {

  constructor (defaultSettings = {}, onSettingsUpdate = null) {
    this._settings = Object.assign({}, GLOBAL_DEFAULT_SETTINGS, defaultSettings);
    this.onSettingsUpdate = onSettingsUpdate;
  }

  // calls updateSettings from implementing driver every time a setting is changed.
  async update (newSettings) {
    if (!_.isPlainObject(newSettings)) {
      throw new Error(`Settings update should be called with valid JSON. Got ` +
        `${JSON.stringify(newSettings)} instead`);
    }
    for (const prop of _.keys(newSettings)) {
      if (!_.isUndefined(this._settings[prop])) {
        if (this._settings[prop] === newSettings[prop]) {
          log.debug(`The value of '${prop}' setting did not change. Skipping the update for it`);
          continue;
        }
      }
      // update setting only when there is updateSettings defined.
      if (_.isFunction(this.onSettingsUpdate)) {
        await this.onSettingsUpdate(prop, newSettings[prop], this._settings[prop]);
        this._settings[prop] = newSettings[prop];
      } else {
        log.errorAndThrow(`Unable to update settings; ` +
          `onSettingsUpdate method not found on '${this.constructor.name}'`);
      }
    }
  }

  getSettings () {
    return this._settings;
  }
}

export default DeviceSettings;
export { DeviceSettings, BASEDRIVER_HANDLED_SETTINGS };
<|endoftext|>


<commit_before>'use strict';

var fs = require("fs"),
	path = require("path"),
	_ = require('../util/underscore');

module.exports = {
	_config:{},
	_defaultRoles:[],
	_roleActions:[],
	build:function(config){
		this._config = config;
		if(!fs.existsSync(this._config.options.output)){
			fs.mkdirSync(this._config.options.output);
		}
		if(this._config.options.verbose) console.log(" ");
		this._buildAppBackend()
			._buildAppFronted()
			._modifyServerMain()
			._modifyServerBootstrap()
			._processModules();
		return this;
	},
	_buildAppBackend:function(){
		if(this._config.options.verbose) console.log("Generate App Backend files");
		var backendPath = path.join(this._config.options.output,'app');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'app','modules');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'app','policies');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		require('./module/RoleBuilder').buildBackendRoles.apply(this);

		this._makePackageJSON();

		//make index.js file
		var file = path.join(this._config.options.output,"index.js");
		if(fs.existsSync(file) && this._config.options.override==false){if(this._config.options.verbose) console.log(" "); return this;		}
		fs.writeFileSync(file, fs.readFileSync(path.resolve(__dirname,"../../templates/application/index.js") ), 'utf-8');
		if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... created");

		//make app/index.js file
		var data = {
			"DEFAULT_ROLES" 	: JSON.stringify(this._defaultRoles,null,"  ")
		}
		var file = path.join(this._config.options.output,"app","index.js");
		var template = _.template(fs.readFileSync(
					path.resolve(__dirname,"../../templates/application/app/index.js")
					,{encoding:'utf-8'}));

		fs.writeFileSync(file, template(data), 'utf-8');
		if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... created");

		if(this._config.options.verbose) console.log(" ");
		return this;
	},
	_buildAppFronted:function(){
		if(this._config.options.verbose) console.log("Generate App Frontend files");
		var backendPath = path.join(this._config.options.output,'ui');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		//create folders
		var backendPath = path.join(this._config.options.output,'ui','templates');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'ui','templates','menu');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'ui','menu');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'ui','modules');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		require('./module/MenuBuilder').buildFrontendMenu.apply(this);
		require('./module/LocaleBuilder').buildFrontendLocale.apply(this);
		require('./module/MainBuilder').buildFrontendMain.apply(this);

		return this;
	},
	_modifyServerMain:function(){
		if(typeof this._config.options.appFile != 'undefined' &&
			this._config.options.appFile != null &&
			fs.existsSync(this._config.options.appFile)){
			var file = this._config.options.appFile;
			var content = fs.readFileSync(file,{encoding:'utf-8'});

			if(this._config.options.output.indexOf(path.dirname(this._config.options.appFile))!=-1){
				var appPath = this._config.options.output.replace(path.dirname(this._config.options.appFile),"");
				var deployCode = "//Auto generated app [ "+this._config.name+" ] mount point \n";
				deployCode += "require('."+ appPath +"')(openbiz)";
				if(appPath!="" &&  content.indexOf(deployCode)==-1 &&
					(typeof this._config.deploy.backend!='undefined' ||
					 typeof this._config.deploy.frontend!='undefined')){
					 content += "\n"+deployCode+"";
					if(typeof this._config.deploy.backend!='undefined'){
						content += ".loadAppToRoute('"+this._config.deploy.backend+"')";
					}
					if(typeof this._config.deploy.frontend!='undefined'){
						content += ".loadUIToRoute('"+this._config.deploy.frontend+"')";
					}
					content+=";\n";
					fs.writeFileSync(file, content, 'utf-8');
					if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... modified");
				}
			}
		}
		return this;
	},
	_modifyServerBootstrap:function(){
		if(typeof this._config.options.appFile != 'undefined' &&
			this._config.options.appFile != null &&
			fs.existsSync(this._config.options.appFile) &&
			typeof this._config.deploy.bootstrapFile != 'undefined' &&
			this._config.deploy.bootstrapFile != null &&
			fs.existsSync(path.dirname(this._config.options.appFile)+this._config.deploy.bootstrapFile)){

			var replaceTag = "/*MORE_APPS*/";
			var file = path.dirname(this._config.options.appFile)+this._config.deploy.bootstrapFile;
			var content = fs.readFileSync(file,{encoding:'utf-8'});
			var appPath = this._config.options.output.replace(path.dirname(this._config.options.appFile),"");

			if(appPath!="" && this._config.options.output.indexOf(appPath)!=-1 ){
				appPath = appPath.substring(1);
				if(content.indexOf(appPath)==-1 ){
					content = content.replace(replaceTag,",'"+appPath+"'"+replaceTag);
					fs.writeFileSync(file, content, 'utf-8');
					if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... modified");
				}
			}
		}
		return this;
	},
	_processModules:function(){
		if(this._config.options.verbose) console.log(" ");
		if(this._config.options.verbose) console.log("Process App modules \n ");
		for(var i=0; i<this._config.modules.length; i++){
			var module = this._config.modules[i];
			var config = require(path.join(path.dirname(this._config.options.config),module));
			config.options = this._config.options;
			require("./ModuleBuilder").build(config);
			if(this._config.options.verbose) console.log(" ");
		}
		return this;
	},
	_makePackageJSON:function(){
		var file = path.join(this._config.options.output,'package.json');
		if(fs.existsSync(file) && this._config.options.override==false) return this;

		var template = require("../../templates/application/package");
		template.name 		 = this._config.name;
		template.description = this._config.description;
		template.version 	 = this._config.version;
		template.homepage 	 = this._config.homepage;
		template.license 	 = this._config.license;
		template.author 	 = this._config.author;

		var data = JSON.stringify(template,null,"  ");
		fs.writeFileSync(file, data, 'utf-8');
		if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... created");
		return this;
	}
}<commit_msg>update<commit_after>'use strict';

var fs = require("fs"),
	path = require("path"),
	_ = require('../util/underscore');

module.exports = {
	_config:{},
	_defaultRoles:[],
	_roleActions:[],
	build:function(config){
		this._config = config;
		if(!fs.existsSync(this._config.options.output)){
			fs.mkdirSync(this._config.options.output);
		}
		if(this._config.options.verbose) console.log(" ");
		this._buildAppBackend()
			._buildAppFronted()
			._modifyServerMain()
			._modifyServerBootstrap()
			._processModules();
		return this;
	},
	_buildAppBackend:function(){
		if(this._config.options.verbose) console.log("Generate App Backend files");
		var backendPath = path.join(this._config.options.output,'app');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'app','modules');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'app','policies');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		require('./module/RoleBuilder').buildBackendRoles.apply(this);

		this._makePackageJSON();

		//make index.js file
		var file = path.join(this._config.options.output,"index.js");
		if(fs.existsSync(file) && this._config.options.override==false){if(this._config.options.verbose) console.log(" "); return this;		}
		fs.writeFileSync(file, fs.readFileSync(path.resolve(__dirname,"../../templates/application/index.js") ), 'utf-8');
		if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... created");

		//make app/index.js file
		var data = {
			"DEFAULT_ROLES" 	: JSON.stringify(this._defaultRoles,null,"  ")
		}
		var file = path.join(this._config.options.output,"app","index.js");
		var template = _.template(fs.readFileSync(
					path.resolve(__dirname,"../../templates/application/app/index.js")
					,{encoding:'utf-8'}));

		fs.writeFileSync(file, template(data), 'utf-8');
		if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... created");

		if(this._config.options.verbose) console.log(" ");
		return this;
	},
	_buildAppFronted:function(){
		if(this._config.options.verbose) console.log("Generate App Frontend files");
		var backendPath = path.join(this._config.options.output,'ui');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		//create folders
		var backendPath = path.join(this._config.options.output,'ui','templates');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'ui','templates','menu');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'ui','menu');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		var backendPath = path.join(this._config.options.output,'ui','modules');
		if(!fs.existsSync(backendPath)){
			fs.mkdirSync(backendPath);
		}

		require('./module/MenuBuilder').buildFrontendMenu.apply(this);
		require('./module/LocaleBuilder').buildFrontendLocale.apply(this);
		require('./module/MainBuilder').buildFrontendMain.apply(this);

		return this;
	},
	_modifyServerMain:function(){
		if(typeof this._config.options.appFile != 'undefined' &&
			this._config.options.appFile != null &&
			fs.existsSync(this._config.options.appFile)){
			var file = this._config.options.appFile;
			var content = fs.readFileSync(file,{encoding:'utf-8'});

			if(this._config.options.output.indexOf(path.dirname(this._config.options.appFile))!=-1){
				var appPath = this._config.options.output.replace(path.dirname(this._config.options.appFile),"");
				var deployCode = "//Auto generated app [ "+this._config.name+" ] mount point \n";
				deployCode += "require('."+ appPath +"')(openbiz)";
				if(appPath!="" &&  content.indexOf(deployCode)==-1 &&
					(typeof this._config.deploy.backend!='undefined' ||
					 typeof this._config.deploy.frontend!='undefined')){
					 content += "\n"+deployCode+"";
					if(typeof this._config.deploy.backend!='undefined'){
						content += ".loadAppToRoute('"+this._config.deploy.backend+"')";
					}
					if(typeof this._config.deploy.frontend!='undefined'){
						content += ".loadUIToRoute('"+this._config.deploy.frontend+"')";
					}
					content+=";\n";
					fs.writeFileSync(file, content, 'utf-8');
					if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... modified");
				}
			}
		}
		return this;
	},
	_modifyServerBootstrap:function(){
		if(typeof this._config.options.appFile != 'undefined' &&
			this._config.options.appFile != null &&
			fs.existsSync(this._config.options.appFile) &&
			typeof this._config.deploy.bootstrapFile != 'undefined' &&
			this._config.deploy.bootstrapFile != null &&
			fs.existsSync(path.dirname(this._config.options.appFile)+this._config.deploy.bootstrapFile)){

			var replaceTag = "/*MORE_APPS*/";
			var file = path.dirname(this._config.options.appFile)+this._config.deploy.bootstrapFile;
			var content = fs.readFileSync(file,{encoding:'utf-8'});
			var appPath = this._config.options.output.replace(path.dirname(this._config.options.appFile),"");

			if(appPath!="" && this._config.options.output.indexOf(appPath)!=-1 ){
				appPath = appPath.substring(1);
				if(content.indexOf("'"+appPath+"'")==-1 ){
					content = content.replace(replaceTag,",'"+appPath+"'"+replaceTag);
					fs.writeFileSync(file, content, 'utf-8');
					if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... modified");
				}
			}
		}
		return this;
	},
	_processModules:function(){
		if(this._config.options.verbose) console.log(" ");
		if(this._config.options.verbose) console.log("Process App modules \n ");
		for(var i=0; i<this._config.modules.length; i++){
			var module = this._config.modules[i];
			var config = require(path.join(path.dirname(this._config.options.config),module));
			config.options = this._config.options;
			require("./ModuleBuilder").build(config);
			if(this._config.options.verbose) console.log(" ");
		}
		return this;
	},
	_makePackageJSON:function(){
		var file = path.join(this._config.options.output,'package.json');
		if(fs.existsSync(file) && this._config.options.override==false) return this;

		var template = require("../../templates/application/package");
		template.name 		 = this._config.name;
		template.description = this._config.description;
		template.version 	 = this._config.version;
		template.homepage 	 = this._config.homepage;
		template.license 	 = this._config.license;
		template.author 	 = this._config.author;

		var data = JSON.stringify(template,null,"  ");
		fs.writeFileSync(file, data, 'utf-8');
		if(this._config.options.verbose) console.log("\tFile "+file.replace(path.dirname(this._config.options.output),"")+" ...... created");
		return this;
	}
}<|endoftext|>


<commit_before>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 5/6/13
 * Time: 9:03 PM
 */

define([], function defineDebuggerActions() {

    /**
     * Define generic Actions
     * @class DebuggerActions
     * @constructor
     */
    var DebuggerActions = function DebuggerActions() {

    };

    return DebuggerActions.extend({

        /**
         * Init Actions
         */
        init: function init() {
            this.configScope();
        },

        /**
         * Config predefined scope
         */
        configScope: function configScope() {

            /**
             * Define edit mode
             * @type {Boolean}
             */
            this.editMode = false;

            this.actions = [
                'add-item',
                'remove-items',
                'remove-all-items',
                'locate-item'
            ];

            this.extendSelectors({
                edit: 'li.edit-mode',
                actions: 'ul.actions',
                items: 'ul.items-info',
                count: 'li.items-count'
            });

        },

        /**
         * Extend debugger selectors
         * @param {*} opts
         */
        extendSelectors: function extendSelectors(opts) {
            this.selectors = {};
            $.each(opts || {}, function each(i, selector) {
                this.selectors[i] = [
                    this.debugger.info,
                    [
                        'fieldset.',
                        this.scope.model.item.name.toLowerCase(),
                        's-info'
                    ].join(''),
                    selector
                ].join(' ');
            }.bind(this));

        },

        /**
         * Render page items actions
         * @returns {string}
         */
        renderItemsActions: function renderItemsActions() {
            return [
                '

',
                this._renderActions(),
                this._renderEnableEditMode(),
                '

'
            ].join('');
        },

        /**
         * Render generic action
         * @returns {string}
         * @private
         */
        _renderActions: function _renderActions() {
            var html = [];
            $.each(this.actions, function each(i, action) {
                var fn = this['_' + action.toCamel() + 'Button'];
                if (this.debugger.base.isFunction(fn)) {
                    html.push(fn.bind(this)());
                }
            }.bind(this));
            return html.join('');
        },

        /**
         * Render add new item button
         * @returns {string}
         * @private
         */
        _addItemButton: function _addItemButton() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                style: 'disabled',
                title: 'Add item'
            });
        },

        /**
         * Render remove item button
         * @returns {string}
         * @private
         */
        _removeItemsButton: function _removeItemsButton() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                style: 'disabled select',
                title: 'Remove items'
            });
        },

        /**
         * Render remove items button
         * @returns {string}
         * @private
         */
        _removeAllItemsButton: function _removeAllItemsButton() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                style: 'disabled select',
                title: 'Remove all items'
            });
        },

        /**
         * Render locate item button
         * @returns {string}
         * @private
         */
        _locateItemButton: function _locateItemButton() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                style: 'disabled select',
                title: 'Locate item'
            });
        },

        /**
         * Render enable edit mode
         * @returns {string}
         * @private
         */
        _renderEnableEditMode: function _renderEnableEditMode() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                title: 'Edit mode'
            });
        },

        /**
         * Render items info
         * @param {*} scope
         * @returns {string}
         */
        renderItemsInfo: function renderItemsInfo(scope) {
            return [
                '
',
                this.debugger.component.renderBlock(scope.model.item.name + 's', [
                    this.renderItemsActions(),
                    this._getItemsCount(scope),
                    this.renderItemsList(scope)
                ], true),
                '
'
            ].join(' ');
        },

        /**
         * Render page items list
         * @param scope
         * @returns {string}
         */
        renderItemsList: function renderItemsList(scope) {
            var html = ['

'];
            html.push(this.getItemsList(scope));
            html.push('

');
            return html.join('');
        },

        /**
         * Get page item list
         * @param scope
         * @returns {string}
         */
        getItemsList: function getItemsList(scope) {
            var html = [];
            $.each(scope.items, function each(uuid, item) {
                var type = item.model.getConfig('type');
                html.push([
                    '
', uuid , '
'
                ].join(''));
            });

            return html.join('');
        },

        /**
         * Update page item list
         * @param page
         */
        updateItems: function updateItems(page) {
            $(this.selectors.items).html(
                this.getItemsList(page)
            );

            var $count = $(this.selectors.count);

            $count.before(
                this._getItemsCount(page)
            ).remove();

            this._bindItemsList(page);
            this.$select.addClass('select');
        },

        /**
         * Get items count
         * @param {*} page
         * @returns {string}
         * @private
         */
        _getItemsCount: function _getItemsCount(page) {
            return this.debugger.component.renderInlineOf('Count', page);
        },

        /**
         * Get page item action button
         * @param {String} action
         * @returns {*|jQuery|HTMLElement}
         * @private
         */
        _getItemAction: function _getItemAction(action) {
            return $('li.' + action, this.selectors.actions);
        },

        /**
         * Bind enable page item edit mode
         * @param {*} scope
         */
        bindEnableItemsEditMode: function bindEnableItemsEditMode(scope) {
            $(this.selectors.edit).on('click.edit', function enableItemsEditMode(e) {
                this._enableItemsEditMode(e, scope);
            }.bind(this));
        },

        /**
         * Bind item list
         * @param scope
         * @private
         */
        _bindItemsList: function _bindItemsList(scope) {
            this.$select = this.debugger.base.define(
                this.$select,
                $('.select', this.selectors.actions)
            );

            if (this.editMode) {
                $('li', this.selectors.items).on('click.select', function select(e) {
                    var $li = $(e.target),
                        item = scope.items[$li.text()];

                    if ($li.hasClass('select')) {
                        scope.logger.debug('Unselect', item);
                        $li.removeClass('select');
                        this.$select.addClass('select');
                    } else {
                        scope.logger.debug('Select', item);
                        $li.addClass('select');
                        this.$select.removeClass('select');
                    }

                    var $select = $('li.select', this.selectors.items),
                        $locate = this._getItemAction('locate-item');

                    $select.length === 1 ?
                        $locate.removeClass('disabled select') :
                        $locate.addClass('disabled select');

                }.bind(this));
            }
        },

        /**
         * Unbind item list
         * @private
         */
        _unbindItemsList: function _unbindItemsList() {
            $('li', this.selectors.items).unbind('click.select');
        },

        /**
         * Enable item edit mode
         * @param {*} e
         * @param {*} scope
         * @private
         */
        _enableItemsEditMode: function _enableItemsEditMode(e, scope) {
            var $this = $(e.target),
                $disabled = $('li[rel="disabled"]', $this.parent('ul'));
            if ($disabled.hasClass('disabled')) {
                scope.logger.debug('Activate edit mode');
                $disabled.removeClass('disabled');
                $this.addClass('active');
                this.editMode = true;
                this._bindItemsList(scope);
                this._bindAddNewItem(scope);
                this._bindRemoveItems(scope);
                this._bindRemoveAllItems(scope);
                this._bindLocateItem(scope);
            } else {
                this._disableItemsEditMode($this, scope);
            }
        },

        /**
         * Disable page item edit mode
         * @param {*} $this
         * @param {*} scope
         * @private
         */
        _disableItemsEditMode: function _disableItemsEditMode($this, scope) {
            var $disabled = $('li[rel="disabled"]', $this.parent('ul'));

            scope.logger.debug('Deactivate edit mode');
            $disabled.addClass('disabled');
            $this.removeClass('active');
            this._unbindAddNewItem(scope);
            this._unbindRemoveItems(scope);
            this._unbindRemoveAllItems(scope);
            this._unbindLocateItem(scope);
            this._unbindItemsList();
            this.editMode = false;
        },

        /**
         * Bind add new item
         * @param {*} scope
         * @private
         */
        _bindAddNewItem: function _bindAddNewItem(scope) {
            scope.logger.debug('Bind edit mode');
            this._getItemAction('add-item').on(
                'click.add',
                /**
                 * Add new item
                 */
                function addNewItem(e) {
                    scope.api.createItem([], true);
                    this._getItemAction('remove-items').removeClass('disabled');
                }.bind(this)
            );
        },

        /**
         * Unbind add new item
         * @param {*} scope
         * @private
         */
        _unbindAddNewItem: function _unbindAddNewItem(scope) {
            scope.logger.debug('Unbind Add item');
            this._getItemAction('add-item').unbind('click.add');
        },

        /**
         * Bind remove items
         * @param scope
         * @private
         */
        _bindRemoveItems: function _bindRemoveItems(scope) {
            scope.logger.debug('Bind remove items');
            this._getItemAction('remove-items').on(
                'click.remove',
                /**
                 * Remove items
                 */
                function removeItems(e) {
                    if ($('li.select', this.selectors.items).length === 0) {
                        scope.logger.warn('Select items before remove');
                        return false;
                    }
                    this._removeItems(scope);
                }.bind(this)
            );
        },

        /**
         * Unbind remove items
         * @param {*} scope
         * @private
         */
        _unbindRemoveItems: function _unbindRemoveItems(scope) {
            scope.logger.debug('Unbind remove items');
            this._getItemAction('remove-items').unbind('click.remove');
            $('li', this.selectors.items).removeClass('select');
        },

        /**
         * Bind remove all items
         * @param scope
         * @private
         */
        _bindRemoveAllItems: function _bindRemoveAllItems(scope) {
            var $lis = $('li', this.selectors.items),
                $action = this._getItemAction('remove-all-items');
            scope.logger.debug('Bind remove all items');

            if ($lis.length === 0) {
                $action.addClass('disabled');
            }

            $action.on(
                'click.remove',
                /**
                 * Remove all items
                 */
                function removeAllItems(e) {
                    if ($lis.length === 0) {
                        scope.logger.warn('Add items before remove');
                        return false;
                    }
                    this._removeAllItems(scope);
                }.bind(this)
            );
        },

        /**
         * Unbind remove all items
         * @param {*} scope
         * @private
         */
        _unbindRemoveAllItems: function _unbindRemoveAllItems(scope) {
            scope.logger.debug('Unbind remove all items');
            this._getItemAction('remove-items').unbind('click.remove');
            $('li', this.selectors.items).removeClass('select');
        },

        /**
         * Bind locate item
         * @param scope
         * @private
         */
        _bindLocateItem: function _bindLocateItem(scope) {
            scope.logger.debug('Bind locate item');

            this._getItemAction('locate-item').on('click.locate', function locate(e) {
                this._locateItem(scope);
            }.bind(this));
        },

        /**
         * Unbind remove all items
         * @param {*} scope
         * @private
         */
        _unbindLocateItem: function _unbindLocateItem(scope) {
            scope.logger.debug('Unbind locate item');
            this._getItemAction('locate-item').unbind('click.locate');
//            $('li', this.selectors.items).removeClass('select');
        },

        _locateItem: function _locateItem(scope) {
//            var $li = $('li.select', this.selectors.items);
//
//            if ($li.length !== 1) {
//                page.logger.warn('Select one item before locate');
//                return false;
//            }
//
//            var uuid = $li.text(),
//                item = page.model.getItemByUUID(uuid);
//
//            if (!this.debugger.base.isDefined(item)) {
//                page.logger.warn('Undefined item', uuid);
//                return false;
//            }
//
//            page.logger.warn('Locate', item);

        },

        /**
         * Remove items
         * @param {*} scope
         * @private
         */
        _removeItems: function _removeItems(scope) {
            var items = {};
            $.each($('li.select', this.selectors.items), function each(i, v) {
                var uuid = $(v).text();
                items[uuid] = scope.model.getItemByUUID(uuid);
            });

            scope.logger.debug('Start remove items', items);
            scope.api.destroyItems(items);

        },

        /**
         * Remove items
         * @param {*} scope
         * @private
         */
        _removeAllItems: function _removeAllItems(scope) {
            $('li', this.selectors.items).addClass('select');
            this._getItemAction('remove-all-items').addClass('disabled');
            scope.logger.debug('Start remove all items');
            this._removeItems(scope);
        }
    });
});
<commit_msg>start locate<commit_after>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 5/6/13
 * Time: 9:03 PM
 */

define([], function defineDebuggerActions() {

    /**
     * Define generic Actions
     * @class DebuggerActions
     * @constructor
     */
    var DebuggerActions = function DebuggerActions() {

    };

    return DebuggerActions.extend({

        /**
         * Init Actions
         */
        init: function init() {
            this.configScope();
        },

        /**
         * Config predefined scope
         */
        configScope: function configScope() {

            /**
             * Define edit mode
             * @type {Boolean}
             */
            this.editMode = false;

            this.actions = [
                'add-item',
                'remove-items',
                'remove-all-items',
                'locate-item'
            ];

            this.extendSelectors({
                edit: 'li.edit-mode',
                actions: 'ul.actions',
                items: 'ul.items-info',
                count: 'li.items-count'
            });

        },

        /**
         * Extend debugger selectors
         * @param {*} opts
         */
        extendSelectors: function extendSelectors(opts) {
            this.selectors = {};
            $.each(opts || {}, function each(i, selector) {
                this.selectors[i] = [
                    this.debugger.info,
                    [
                        'fieldset.',
                        this.scope.model.item.name.toLowerCase(),
                        's-info'
                    ].join(''),
                    selector
                ].join(' ');
            }.bind(this));

        },

        /**
         * Render page items actions
         * @returns {string}
         */
        renderItemsActions: function renderItemsActions() {
            return [
                '

',
                this._renderActions(),
                this._renderEnableEditMode(),
                '

'
            ].join('');
        },

        /**
         * Render generic action
         * @returns {string}
         * @private
         */
        _renderActions: function _renderActions() {
            var html = [];
            $.each(this.actions, function each(i, action) {
                var fn = this['_' + action.toCamel() + 'Button'];
                if (this.debugger.base.isFunction(fn)) {
                    html.push(fn.bind(this)());
                }
            }.bind(this));
            return html.join('');
        },

        /**
         * Render add new item button
         * @returns {string}
         * @private
         */
        _addItemButton: function _addItemButton() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                style: 'disabled',
                title: 'Add item'
            });
        },

        /**
         * Render remove item button
         * @returns {string}
         * @private
         */
        _removeItemsButton: function _removeItemsButton() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                style: 'disabled select',
                title: 'Remove items'
            });
        },

        /**
         * Render remove items button
         * @returns {string}
         * @private
         */
        _removeAllItemsButton: function _removeAllItemsButton() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                style: 'disabled select',
                title: 'Remove all items'
            });
        },

        /**
         * Render locate item button
         * @returns {string}
         * @private
         */
        _locateItemButton: function _locateItemButton() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                style: 'disabled select',
                title: 'Locate item'
            });
        },

        /**
         * Render enable edit mode
         * @returns {string}
         * @private
         */
        _renderEnableEditMode: function _renderEnableEditMode() {
            return this.debugger.component.renderInlineAction({
                rel: 'disabled',
                title: 'Edit mode'
            });
        },

        /**
         * Render items info
         * @param {*} scope
         * @returns {string}
         */
        renderItemsInfo: function renderItemsInfo(scope) {
            return [
                '
',
                this.debugger.component.renderBlock(scope.model.item.name + 's', [
                    this.renderItemsActions(),
                    this._getItemsCount(scope),
                    this.renderItemsList(scope)
                ], true),
                '
'
            ].join(' ');
        },

        /**
         * Render page items list
         * @param scope
         * @returns {string}
         */
        renderItemsList: function renderItemsList(scope) {
            var html = ['

'];
            html.push(this.getItemsList(scope));
            html.push('

');
            return html.join('');
        },

        /**
         * Get page item list
         * @param scope
         * @returns {string}
         */
        getItemsList: function getItemsList(scope) {
            var html = [];
            $.each(scope.items, function each(uuid, item) {
                var type = item.model.getConfig('type');
                html.push([
                    '
', uuid , '
'
                ].join(''));
            });

            return html.join('');
        },

        /**
         * Update page item list
         * @param page
         */
        updateItems: function updateItems(page) {
            $(this.selectors.items).html(
                this.getItemsList(page)
            );

            var $count = $(this.selectors.count);

            $count.before(
                this._getItemsCount(page)
            ).remove();

            this._bindItemsList(page);
            this.$select.addClass('select');
        },

        /**
         * Get items count
         * @param {*} page
         * @returns {string}
         * @private
         */
        _getItemsCount: function _getItemsCount(page) {
            return this.debugger.component.renderInlineOf('Count', page);
        },

        /**
         * Get page item action button
         * @param {String} action
         * @returns {*|jQuery|HTMLElement}
         * @private
         */
        _getItemAction: function _getItemAction(action) {
            return $('li.' + action, this.selectors.actions);
        },

        /**
         * Bind enable page item edit mode
         * @param {*} scope
         */
        bindEnableItemsEditMode: function bindEnableItemsEditMode(scope) {
            $(this.selectors.edit).on('click.edit', function enableItemsEditMode(e) {
                this._enableItemsEditMode(e, scope);
            }.bind(this));
        },

        /**
         * Bind item list
         * @param scope
         * @private
         */
        _bindItemsList: function _bindItemsList(scope) {
            this.$select = this.debugger.base.define(
                this.$select,
                $('.select', this.selectors.actions)
            );

            if (this.editMode) {
                $('li', this.selectors.items).on('click.select', function select(e) {
                    var $li = $(e.target),
                        item = scope.items[$li.text()];

                    if ($li.hasClass('select')) {
                        scope.logger.debug('Unselect', item);
                        $li.removeClass('select');
                        this.$select.addClass('select');
                    } else {
                        scope.logger.debug('Select', item);
                        $li.addClass('select');
                        this.$select.removeClass('select');
                    }

                    var $select = $('li.select', this.selectors.items),
                        $locate = this._getItemAction('locate-item');

                    $select.length === 1 ?
                        $locate.removeClass('disabled select') :
                        $locate.addClass('disabled select');

                }.bind(this));
            }
        },

        /**
         * Unbind item list
         * @private
         */
        _unbindItemsList: function _unbindItemsList() {
            $('li', this.selectors.items).unbind('click.select');
        },

        /**
         * Enable item edit mode
         * @param {*} e
         * @param {*} scope
         * @private
         */
        _enableItemsEditMode: function _enableItemsEditMode(e, scope) {
            var $this = $(e.target),
                $disabled = $('li[rel="disabled"]', $this.parent('ul'));
            if ($disabled.hasClass('disabled')) {
                scope.logger.debug('Activate edit mode');
                $disabled.removeClass('disabled');
                $this.addClass('active');
                this.editMode = true;
                this._bindItemsList(scope);
                this._bindAddNewItem(scope);
                this._bindRemoveItems(scope);
                this._bindRemoveAllItems(scope);
                this._bindLocateItem(scope);
            } else {
                this._disableItemsEditMode($this, scope);
            }
        },

        /**
         * Disable page item edit mode
         * @param {*} $this
         * @param {*} scope
         * @private
         */
        _disableItemsEditMode: function _disableItemsEditMode($this, scope) {
            var $disabled = $('li[rel="disabled"]', $this.parent('ul'));

            scope.logger.debug('Deactivate edit mode');
            $disabled.addClass('disabled');
            $this.removeClass('active');
            this._unbindAddNewItem(scope);
            this._unbindRemoveItems(scope);
            this._unbindRemoveAllItems(scope);
            this._unbindLocateItem(scope);
            this._unbindItemsList();
            this.editMode = false;
        },

        /**
         * Bind add new item
         * @param {*} scope
         * @private
         */
        _bindAddNewItem: function _bindAddNewItem(scope) {
            scope.logger.debug('Bind edit mode');
            this._getItemAction('add-item').on(
                'click.add',
                /**
                 * Add new item
                 */
                function addNewItem(e) {
                    scope.api.createItem([], true);
                    this._getItemAction('remove-items').removeClass('disabled');
                }.bind(this)
            );
        },

        /**
         * Unbind add new item
         * @param {*} scope
         * @private
         */
        _unbindAddNewItem: function _unbindAddNewItem(scope) {
            scope.logger.debug('Unbind Add item');
            this._getItemAction('add-item').unbind('click.add');
        },

        /**
         * Bind remove items
         * @param scope
         * @private
         */
        _bindRemoveItems: function _bindRemoveItems(scope) {
            scope.logger.debug('Bind remove items');
            this._getItemAction('remove-items').on(
                'click.remove',
                /**
                 * Remove items
                 */
                function removeItems(e) {
                    if ($('li.select', this.selectors.items).length === 0) {
                        scope.logger.warn('Select items before remove');
                        return false;
                    }
                    this._removeItems(scope);
                }.bind(this)
            );
        },

        /**
         * Unbind remove items
         * @param {*} scope
         * @private
         */
        _unbindRemoveItems: function _unbindRemoveItems(scope) {
            scope.logger.debug('Unbind remove items');
            this._getItemAction('remove-items').unbind('click.remove');
            $('li', this.selectors.items).removeClass('select');
        },

        /**
         * Bind remove all items
         * @param scope
         * @private
         */
        _bindRemoveAllItems: function _bindRemoveAllItems(scope) {
            var $lis = $('li', this.selectors.items),
                $action = this._getItemAction('remove-all-items');
            scope.logger.debug('Bind remove all items');

            if ($lis.length === 0) {
                $action.addClass('disabled');
            }

            $action.on(
                'click.remove',
                /**
                 * Remove all items
                 */
                function removeAllItems(e) {
                    if ($lis.length === 0) {
                        scope.logger.warn('Add items before remove');
                        return false;
                    }
                    this._removeAllItems(scope);
                }.bind(this)
            );
        },

        /**
         * Unbind remove all items
         * @param {*} scope
         * @private
         */
        _unbindRemoveAllItems: function _unbindRemoveAllItems(scope) {
            scope.logger.debug('Unbind remove all items');
            this._getItemAction('remove-items').unbind('click.remove');
            $('li', this.selectors.items).removeClass('select');
        },

        /**
         * Bind locate item
         * @param scope
         * @private
         */
        _bindLocateItem: function _bindLocateItem(scope) {
            scope.logger.debug('Bind locate item');

            this._getItemAction('locate-item').on('click.locate', function locate(e) {
                this._locateItem(scope);
            }.bind(this));
        },

        /**
         * Unbind remove all items
         * @param {*} scope
         * @private
         */
        _unbindLocateItem: function _unbindLocateItem(scope) {
            scope.logger.debug('Unbind locate item');
            this._getItemAction('locate-item').unbind('click.locate');
        },

        /**
         * Locate item
         * @param scope
         * @returns {boolean}
         * @private
         */
        _locateItem: function _locateItem(scope) {
            var $li = $('li.select', this.selectors.items);

            if ($li.length !== 1) {
                scope.logger.warn('Select one item before locate');
                return false;
            }

            var uuid = $li.text(),
                item = scope.model.getItemByUUID(uuid);

            if (!this.debugger.base.isDefined(item)) {
                sope.logger.warn('Undefined item', uuid);
                return false;
            }

            scope.logger.warn('Locate', item);

        },

        /**
         * Remove items
         * @param {*} scope
         * @private
         */
        _removeItems: function _removeItems(scope) {
            var items = {};
            $.each($('li.select', this.selectors.items), function each(i, v) {
                var uuid = $(v).text();
                items[uuid] = scope.model.getItemByUUID(uuid);
            });

            scope.logger.debug('Start remove items', items);
            scope.api.destroyItems(items);

        },

        /**
         * Remove items
         * @param {*} scope
         * @private
         */
        _removeAllItems: function _removeAllItems(scope) {
            $('li', this.selectors.items).addClass('select');
            this._getItemAction('remove-all-items').addClass('disabled');
            scope.logger.debug('Start remove all items');
            this._removeItems(scope);
        }
    });
});
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
//  DRY/WET KNOB
//
// 	equal power fading
//	control values:
// 	   	0 = 100% dry
//		1 = 100% wet
///////////////////////////////////////////////////////////////////////////////

define(["Tone/core/Tone", "Tone/signal/Signal", "Tone/signal/Scale"], function(Tone){

	Tone.DryWet = function(initialDry){
		Tone.call(this);

		//components
		this.dry = this.context.createGain();
		this.wet = this.context.createGain();
		//control signal
		this.control = new Tone.Signal();
		this.invert = new Tone.Scale(1, 0);
		this.normal = new Tone.Scale(0, 1);

		//connections
		this.dry.connect(this.output);
		this.wet.connect(this.output);
		//wet control
		this.chain(this.control, this.invert, this.wet.gain);
		//dry control
		this.chain(this.control, this.normal, this.dry.gain);

		//setup
		this.dry.gain.value = 0;
		this.wet.gain.value = 0;
		this.setDry(0);
	}

	Tone.extend(Tone.DryWet);

	// @param {number} val
	// @param {Tone.Time} rampTime
	Tone.DryWet.prototype.setDry = function(val, rampTime){
		rampTime = this.defaultArg(rampTime, 0);
		this.control.linearRampToValueAtTime(val*2 - 1, this.toSeconds(rampTime));
	}

	Tone.DryWet.prototype.setWet = function(val, rampTime){
		this.setDry(1-val, rampTime);
	}

	return Tone.DryWet;
});
<commit_msg>jshint and jsdoc<commit_after>define(["Tone/core/Tone", "Tone/signal/Signal", "Tone/signal/Scale"], function(Tone){

	/**
	 * DRY/WET KNOB
	 *
	 * equal power fading control values:
	 * 	0 = 100% dry
	 * 	1 = 100% wet
	 *
	 * @constructor
	 * @param {number} initialDry
	 */
	Tone.DryWet = function(initialDry){
		Tone.call(this);

		//components
		this.dry = this.context.createGain();
		this.wet = this.context.createGain();
		//control signal
		this.control = new Tone.Signal();
		this.invert = new Tone.Scale(1, 0);
		this.normal = new Tone.Scale(0, 1);

		//connections
		this.dry.connect(this.output);
		this.wet.connect(this.output);
		//wet control
		this.chain(this.control, this.invert, this.wet.gain);
		//dry control
		this.chain(this.control, this.normal, this.dry.gain);

		//setup
		this.dry.gain.value = 0;
		this.wet.gain.value = 0;
		this.setDry(0);
	};

	Tone.extend(Tone.DryWet);

	/**
	 * Set the dry value of the knob
	 *
	 * @param {number} val
	 * @param {Tone.Time} rampTime
	 */
	Tone.DryWet.prototype.setDry = function(val, rampTime){
		rampTime = this.defaultArg(rampTime, 0);
		this.control.linearRampToValueAtTime(val*2 - 1, this.toSeconds(rampTime));
	};

	/**
	 * Set the wet value of the knob
	 *
	 * @param {number} val
	 * @param {Tone.Time} rampTime
	 */
	Tone.DryWet.prototype.setWet = function(val, rampTime){
		this.setDry(1-val, rampTime);
	};

	return Tone.DryWet;
});
<|endoftext|>


<commit_before>var targtime = "2018/12/19 17:29";
//var targtime = "2016/12/29 23:50";

// var sound = new Audio("src/xxx.mp3");

function newyear2017() {
  var APP_NAME = 'New Year 2019';
  var VERSION = '1.2';

  var sprite = $("#sprite > div");
  var event = {
    down: 'mousedown',
    up: 'mouseup',
    move: 'mousemove'
  }
  var pic = {// sprite.property
    width: 300,
    height: 300,
    max: 86, // number of pics
    y0: 0, // base-y
    y: 0 // current-y
  };
  var x0 = 0; // base-mouseX
  var flag = false; // rotate flag (auto)
  var logflag = false;

  function agent_checker() {
    var agent = navigator.userAgent;
    if(agent.search(/iPhone/) != -1 || agent.search(/iPad/) != -1
       || agent.search(/iPod/) != -1 || agent.search(/Android/) != -1) {
      event.down = "touchstart";
      event.up = "touchend";
      event.move = "touchmove";
      $(window).on('touchmove', function(e) { e.preventDefault(); }, {passive: false});
      $('#title').html('＼ Swipe Me! ／');
    } else {
      $('#title').html('＼ Drag Me! ／');
    }
  }

  function draw_arrow() {
    var w = pic.height, h = ~~((1.0/3.0)*pic.width);
    $('#arrow_container').html(
      '<canvas id="arrow" width="' + h + '" height="' + w + '"></canvas>'
    );
    var canvas = $('#arrow')[0];
    if ( ! canvas || ! canvas.getContext ) {
      $('#arrow').hide();
      return false;
    }
    // arrow.width, arrow.height, bar.height, head.ratio
    var aw = 0.9, ah = 0.9, bh = 0.4, hr = 1.5;
    var ctx = canvas.getContext('2d');
    var grad = ctx.createLinearGradient(0,0, w,0);
    grad.addColorStop(0, 'rgba(80,80,255,0)');
    grad.addColorStop(1, 'rgba(120,120,255,0.7)');
    ctx.fillStyle = grad;
    ctx.translate(h/2, w/6);
    ctx.rotate(0.5*Math.PI);
    ctx.translate(-h/2, -w/6);
    ctx.beginPath();
    ctx.moveTo(~~(w-0.5*(1-aw)*w), ~~(0.5*h));
    ctx.lineTo(~~(w-0.5*(1-aw)*w - h*ah*hr), ~~(h-0.5*(1-ah)*h));
    ctx.lineTo(~~(w-0.5*(1-aw)*w - h*ah*hr), ~~(h-0.5*(1-bh)*h));
    ctx.lineTo(~~(0.5*(1-aw)*w), ~~(h-0.5*(1-bh)*h));
    ctx.lineTo(~~(0.5*(1-aw)*w), ~~(0.5*(1-bh)*h));
    ctx.lineTo(~~(w-0.5*(1-aw)*w - h*ah*hr), ~~(0.5*(1-bh)*h));
    ctx.lineTo(~~(w-0.5*(1-aw)*w - h*ah*hr), ~~(0.5*(1-ah)*h));
    ctx.closePath();
    ctx.fill();
  }

  function add_hook_event() {
    function get_mousex(e) {
      var t = e.originalEvent.touches;
      return (t ? t[0] : e).screenY;
    }
    $('html').on(event.down, function(e) {
      x0 = get_mousex(e);
      pic.y = 0;
      flag = true;
    });
    $('html').on(event.up, function(e) {
      flag = false;
      pic.y0 = (pic.y0 + pic.y) % (pic.height*pic.max);
    });
    $('html').on(event.move, function(e) {
      var x;
      if (flag) {
        x = get_mousex(e);
        pic.y = (~~(-(x-x0)/20))*pic.height;
        sprite.css('background-position', '0 ' + (pic.y0 + pic.y) + 'px');
        if (pic.y0 + pic.y <= -pic.height*pic.max) {
          $('#title').html('＼ Happy New Year ／');
        }
        if (logflag) {
          $('#log').css('color', '#fff');
          $('#log').html(pic.y0 + pic.y);
        }
      }
    });
  }

  function prep() {
    sprite.css('visibility', 'visible');
    $('#note').show();
    $('#footer').show();
    //sound.play();
  }

  agent_checker();
  draw_arrow();
  prep();
  add_hook_event();
}

function countdown() {
  var title = $('#title');
  var date_NY = (new Date(targtime)).getTime();
  var dt;
  var itv;
  title.css({'margin-top': '100px', 'font-size': '40pt'});
  function zeropad(n) { return ("0" + ~~n).slice(-2); }
  function countdown_1() {
    dt = (date_NY - (new Date().getTime()))/1000;
    if (dt > 0) {
      title.html([~~(dt/3600),
                  zeropad((dt % 3600)/60),
                  zeropad(dt % 60)].join(":"));
    } else {
      clearInterval(itv);
      location.reload();
    }
  }
  itv = setInterval(countdown_1, 1000);
}

$(function() {
  if (new Date().getTime() >= new Date(targtime).getTime()) {
    newyear2017();
  } else {
    countdown();
  }
});
<commit_msg>new year 2019<commit_after>var targtime = "2018/12/19 17:29";
//var targtime = "2016/12/29 23:50";

// var sound = new Audio("src/xxx.mp3");

function newyear2017() {
  var APP_NAME = 'New Year 2019';
  var VERSION = '1.2';

  var sprite = $("#sprite > div");
  var event = {
    down: 'mousedown',
    up: 'mouseup',
    move: 'mousemove'
  }
  var pic = {// sprite.property
    width: 300,
    height: 300,
    max: 86, // number of pics
    y0: 0, // base-y
    y: 0 // current-y
  };
  var x0 = 0; // base-mouseX
  var flag = false; // rotate flag (auto)
  var logflag = false;

  function agent_checker() {
    var agent = navigator.userAgent;
    if(agent.search(/iPhone/) != -1 || agent.search(/iPad/) != -1
       || agent.search(/iPod/) != -1 || agent.search(/Android/) != -1) {
      event.down = "touchstart";
      event.up = "touchend";
      event.move = "touchmove";
      //$(window).on('touchmove', function(e) { e.preventDefault(); }, {passive: false});
      $('#title').html('＼ Swipe Me! ／');
    } else {
      $('#title').html('＼ Drag Me! ／');
    }
  }

  function draw_arrow() {
    var w = pic.height, h = ~~((1.0/3.0)*pic.width);
    $('#arrow_container').html(
      '<canvas id="arrow" width="' + h + '" height="' + w + '"></canvas>'
    );
    var canvas = $('#arrow')[0];
    if ( ! canvas || ! canvas.getContext ) {
      $('#arrow').hide();
      return false;
    }
    // arrow.width, arrow.height, bar.height, head.ratio
    var aw = 0.9, ah = 0.9, bh = 0.4, hr = 1.5;
    var ctx = canvas.getContext('2d');
    var grad = ctx.createLinearGradient(0,0, w,0);
    grad.addColorStop(0, 'rgba(80,80,255,0)');
    grad.addColorStop(1, 'rgba(120,120,255,0.7)');
    ctx.fillStyle = grad;
    ctx.translate(h/2, w/6);
    ctx.rotate(0.5*Math.PI);
    ctx.translate(-h/2, -w/6);
    ctx.beginPath();
    ctx.moveTo(~~(w-0.5*(1-aw)*w), ~~(0.5*h));
    ctx.lineTo(~~(w-0.5*(1-aw)*w - h*ah*hr), ~~(h-0.5*(1-ah)*h));
    ctx.lineTo(~~(w-0.5*(1-aw)*w - h*ah*hr), ~~(h-0.5*(1-bh)*h));
    ctx.lineTo(~~(0.5*(1-aw)*w), ~~(h-0.5*(1-bh)*h));
    ctx.lineTo(~~(0.5*(1-aw)*w), ~~(0.5*(1-bh)*h));
    ctx.lineTo(~~(w-0.5*(1-aw)*w - h*ah*hr), ~~(0.5*(1-bh)*h));
    ctx.lineTo(~~(w-0.5*(1-aw)*w - h*ah*hr), ~~(0.5*(1-ah)*h));
    ctx.closePath();
    ctx.fill();
  }

  function add_hook_event() {
    function get_mousex(e) {
      var t = e.originalEvent.touches;
      return (t ? t[0] : e).screenY;
    }
    $('html').on(event.down, function(e) {
      x0 = get_mousex(e);
      pic.y = 0;
      flag = true;
    });
    $('html').on(event.up, function(e) {
      flag = false;
      pic.y0 = (pic.y0 + pic.y) % (pic.height*pic.max);
    });
    $('html').on(event.move, function(e) {
      var x;
      if (flag) {
        x = get_mousex(e);
        pic.y = (~~(-(x-x0)/20))*pic.height;
        sprite.css('background-position', '0 ' + (pic.y0 + pic.y) + 'px');
        if (pic.y0 + pic.y <= -pic.height*pic.max) {
          $('#title').html('＼ Happy New Year ／');
        }
        if (logflag) {
          $('#log').css('color', '#fff');
          $('#log').html(pic.y0 + pic.y);
        }
      }
      e.preventDefault();
    }, {passive: false}
    );
  }

  function prep() {
    sprite.css('visibility', 'visible');
    $('#note').show();
    $('#footer').show();
    //sound.play();
  }

  agent_checker();
  draw_arrow();
  prep();
  add_hook_event();
}

function countdown() {
  var title = $('#title');
  var date_NY = (new Date(targtime)).getTime();
  var dt;
  var itv;
  title.css({'margin-top': '100px', 'font-size': '40pt'});
  function zeropad(n) { return ("0" + ~~n).slice(-2); }
  function countdown_1() {
    dt = (date_NY - (new Date().getTime()))/1000;
    if (dt > 0) {
      title.html([~~(dt/3600),
                  zeropad((dt % 3600)/60),
                  zeropad(dt % 60)].join(":"));
    } else {
      clearInterval(itv);
      location.reload();
    }
  }
  itv = setInterval(countdown_1, 1000);
}

$(function() {
  if (new Date().getTime() >= new Date(targtime).getTime()) {
    newyear2017();
  } else {
    countdown();
  }
});
<|endoftext|>