<commit_before>/* jshint indent: false */ // TODO: ENYO-3311

/* global ares */
/**
 * UI: Phonegap pane in the ProjectProperties popup
 * @name Phonegap.BuildStatusUI
 */
enyo.kind({
	name: "Phonegap.ProjectProperties.PlatformBuildStatus",
	kind: "onyx.IconButton",
	classes: "ares-project-properties-build-status-icon",
	ontap: "showStatusMessage",
	published: {
		platform: undefined,
		buildStatusData: undefined,
	},
	buildStatusDataChanged: function() {
		if (this.buildStatusData && this.buildStatusData.status[this.platform] === "complete") {
			//Build status: complete
			this.setSrc("$services/assets/images/platforms/" + this.platform + "-logo-complete-32x32.png");

		} else {
			if (this.buildStatusData && this.buildStatusData.status[this.platform] === "error" ||
			    this.buildStatusData && this.buildStatusData.status[this.platform] === null){

				//Build status: error
				this.setSrc("$services/assets/images/platforms/" + this.platform + "-logo-error-32x32.png");

			} else {
				if(this.buildStatusData === null) {

					//Build status: application not built
					this.setSrc("$services/assets/images/platforms/" + this.platform + "-logo-not-available-32x32.png");

				} else {
					//Build status: pending
					this.setSrc("$services/assets/images/platforms/" + this.platform + "-logo-not-available-32x32.png");
					this.bubble("appIdChanged");
				}
			}
		}
	}
});

enyo.kind({
	name: "Phonegap.ProjectProperties.BuildStatus",
	kind: "FittableRows",
	published: {
		appId: "",
		buildStatusData: undefined,
		phongapUrl: "https://build.phonegap.com",
		provider: undefined,
		selectedPlatform: undefined
	},
	handlers: {
		onUpdateStatusMessage: "updateDownloadMessageContent"
	},
	components: [
		{
			name: "buildStatusContainer", kind: "FittableRows", classes: "ares-project-properties-build-status-container",
			components: [
				{
					name: "platformIconContainer",
					classes:"ares-project-properties-platform-icon-container",
					kind: "FittableColumns",
				},

				{ name: "downloadStatus", kind: "Phonegap.ProjectProperties.DownloadStatus" },
				{
					name: "messageContainer",
					classes: "ares-project-properties-status-message-container",
					showing: false,
					components: [
						{
							name: "hideStatusContainer",
							kind: "onyx.IconButton",
							src: "$project-view/assets/images/close-button-16x16.png",
							classes: "ares-project-properties-hide-status-button",
							ontap:"hideMessageContainer"
						},
						{
							name: "statusMessage",
							classes: "ares-project-properties-status-message"
						}
					]
				},
				{
					kind: "FittableColumns",
					style: "height: 32px; position: relative; top:-6em;",
					components: [
						{
							name:"separatorForDownloadButton"
						},
						{
							name: "downloadButton",
							kind: "onyx.IconButton",
							src: "$services/assets/images/download-icon.png",
							shown: false,
							ontap: "downloadPackage"
						}
					]
				}

			]
		}
	],
	/**@private*/
	create: function() {
		this.inherited(arguments);
		this.createIconButtons();
		this.appIdChanged();
		this.setProvider(Phonegap.ProjectProperties.getProvider());
	},

	/**
	 * Create the IconButtons displaying the build state of the application
	 * for all platforms defined in the object {Phonegap.ProjectProperties.downloadStatus}
	 *
	 * @private
	 */
	createIconButtons: function() {
		for (var key in Phonegap.ProjectProperties.downloadStatus) {
			this.$.platformIconContainer.createComponent(
				{
					name: key + "Decorator",
					classes: "ares-project-properties-build-status-icon",
					components: [
						{
							name: key + "Button",
							kind: "Phonegap.ProjectProperties.PlatformBuildStatus",
							platform: key
						}
					]
				},
				{owner: this}
			);

		}
	},

	/**
	 * Charge the icon showing the build status of the application of a a given platform depending on
	 * its status. the status is checked from the "buildStatusData" object.
	 * By clicking on the icon, the status message is displayed.
	 *
	 * @private
	 */
	buildStatusDataChanged: function(){
		var pendingApplication = false;

		//Check if there is a pending build.
		for(var key1 in this.buildStatusData && this.buildStatusData.status) {
			if (this.buildStatusData.status[key1] === "pending") {
				pendingApplication = true;
			}
		}

		//If there is a pending build, another buildStatus Request is sent after 600 ms timeout.
		if (pendingApplication) {
			setTimeout(this.sendBuildStatusRequest(), 2000);
		}

		// Get only the Enyo control that have the "platform" attribute
		// => {Phonegap.ProjectProperties.PlatformBuildStatus} instance
		for(var key2 in this.$){
			if(this.$[key2].platform !== undefined) {
				this.$[key2].setBuildStatusData(this.buildStatusData);
			}
		}

		//Update to Status container if a platform is selected.
		if(this.selectedPlatform !== undefined) {
			this.showStatusMessage({platform: this.selectedPlatform});
		}

	},

	/**
	 * Use the phonegap service to request a {buildStatus} object from Phonegap build
	 * @private
	 */
	sendBuildStatusRequest: function() {
		this.provider.getAppData(this.appId, enyo.bind(this, this.getBuildStatusData));
	},

	/**
	 * Update the content of the statusMessage row.
	 * @protected
	 */
	updateDownloadMessageContent: function() {

		this.$.statusMessage.setContent(this.$.downloadStatus.getDownloadStatus(this.selectedPlatform));
		this.$.statusMessage.show();
		this.updateDownloadMessageDisplay(this.selectedPlatform);

		//stop the propagation of the bubble event
		return true;
	},

	/**
	 * Highlight the selected platform button by appling a css style on its decorator.
	 * @param {enyo.component} inIconButtonDecorator decorator of the button
	 * @private
	 */
	addHightlightIconButton: function(inIconButtonDecorator) {
		this.removeHightlightIconButton();
		inIconButtonDecorator.addClass("ares-project-properties-buildStatus-icon-highlight");

	},

	/**
	 * Remove the highlignt effect from all platform buttons.
	 * @private
	 */
	removeHightlightIconButton: function() {
		for(var key in Phonegap.ProjectProperties.downloadStatus) {
			this.$[key + "Decorator"].removeClass("ares-project-properties-buildStatus-icon-highlight");
		}
	},

	/**
	 *
	 * @param  {String} inPlatform Mobile platform supported by Phonegap.
	 * @private
	 */
	updateDownloadMessageDisplay: function(inPlatform) {
		var classAttribute = "ares-project-properties-buildStatus-download-button-" + inPlatform;
		this.$.separatorForDownloadButton.setClassAttribute(classAttribute);

		this.$.downloadButton.show();
	},

	/**@private*/
	showStatusMessage: function(inSender, inEvent){

		this.$.messageContainer.show();
		this.addHightlightIconButton(this.$[inSender.platform+ "Decorator"]);

		if (this.buildStatusData && this.buildStatusData.status[inSender.platform] === "complete") {
			this.$.statusMessage.setContent("");
			this.setSelectedPlatform(inSender.platform);

			if (this.buildStatusData.download[inSender.platform] !== undefined &&
				this.buildStatusData.title !== undefined) {

				this.updateStatusMessage();

				this.updateDownloadMessage(inSender.platform);

			} else {
				this.$.downloadButton.hide();
			}
				this.updateDownloadMessageDisplay(inSender.platform);
		} else {
			if (this.buildStatusData && this.buildStatusData.status[inSender.platform] === "error" ||
				this.buildStatusData && this.buildStatusData.status[inSender.platform] === null){

				//Build status: error
				this.$.downloadButton.hide();
				this.$.statusMessage.setContent("Error: " + this.buildStatusData.error[inSender.platform]);
			} else {

				if(this.buildStatusData === null) {

					//Build status: application not built
					this.$.downloadButton.hide();
					this.$.statusMessage.setContent("Build the application first");

				} else {

					//Build status: pending
					this.$.downloadButton.hide();
					this.$.statusMessage.setContent("Build in progress");
				}
			}
		}
	return true; //stop the propagation of the event

	},

	/**
	 * Listener to launch the download request form the Phonegap Build service manager.
	 * @param  {Object} inSender
	 * @param  {Object} inEvent
	 * @private
	 */
	downloadPackage: function(inSender, inEvent) {

		var projectConfig = this.owner.getProject();
		this.provider.downloadPackage(projectConfig, this.selectedPlatform, this.buildStatusData, enyo.bind(this, this.getPackage));

		//set the download status to "Download on progress"
		this.$.downloadStatus.setDownloadStatus(this.selectedPlatform, 2);
	},
	/**
	 * Callback used in the function "downloadPackage()"" in "Build.js"
	 * Update the status message to show the current status of the download request.
	 *
	 * @param  {Object} err       error object
	 * @private
	 */
	getPackage: function(err) {
		if(err) {
			//set the download status to "Download failed"
			this.$.downloadStatus.setDownloadStatus(this.selectedPlatform, 0);
		} else {
			//set the download status to "Download complete"
			this.$.downloadStatus.setDownloadStatus(this.selectedPlatform, 1);
		}
	},

	/**@private*/
	hideMessageContainer: function() {
		//Unselect the focused platform
		this.setSelectedPlatform(undefined);
		this.removeHightlightIconButton();

		this.$.messageContainer.hide();
		this.$.downloadButton.hide();
	},

	/**@private*/
	hideMessageContent: function() {
		this.$.downloadButton.hide();
	},

	/**@private*/
	appIdChanged: function(){

		if(this.appId === "" || this.appId === undefined){
			this.setBuildStatusData(null);
		} else {
			this.sendBuildStatusRequest();
		}
		this.$.buildStatusContainer.render();
	},

	/**
	 * Callback function to initialize the "buildStatusData" object.
	 *
	 * @param  {Object} err               error object
	 * @param  {Object} inBuildStatusData Object returned by Phonegap build, it contains several informations
	 *                                    about the built application.
	 * @private
	 */
	getBuildStatusData: function (err, inBuildStatusData) {
		if (err) {
			this.warn("err:", err);
		} else {
			this.setBuildStatusData(inBuildStatusData.user);
		}
	}
});

/**
 * Model kind to keep track on the download status for each
 * mobile platform supported by Phonegap Build.
 *
 * Used only by the widget {Phonegap.ProjectProperties.BuildStatus}
 */
enyo.kind({
	name: "Phonegap.ProjectProperties.DownloadStatus",
	published: {
		downloadStatus: {"android": "", "ios": "", "winphone": "",
						"blackberry": "", "webos": ""}
	},

	/**
	 * Set the download status for a platform defined in {this.downloadStatus}.
	 *
	 * @param {String} inPlatform       platform defined in {this.downloadStatus}
	 * @param {integer} inDownloadStatus code status: 0 => failed, 1 => complete, other => on progress
	 * @public
	 */
	setDownloadStatus: function(inPlatform, inDownloadStatus) {
		if(inDownloadStatus === 1){
			Phonegap.ProjectProperties.downloadStatus[inPlatform] = "Download complete";
		} else {
			if (inDownloadStatus === 0) {
				Phonegap.ProjectProperties.downloadStatus[inPlatform] = "Download failed";
			} else {
				Phonegap.ProjectProperties.downloadStatus[inPlatform] = "Download on progress";
			}
		}

		this.bubble("onUpdateStatusMessage");
	},

	/**
	 * Get the download status value by platform.
	 *
	 * @param  {String} inPlatform [description]
	 * @return {String} status message
	 * @public
	 */
	getDownloadStatus: function(inPlatform) {
		return Phonegap.ProjectProperties.downloadStatus[inPlatform];
	}

});<commit_msg>ENYO-2788: delete dead code.<commit_after>/* jshint indent: false */ // TODO: ENYO-3311

/* global ares */
/**
 * UI: Phonegap pane in the ProjectProperties popup
 * @name Phonegap.BuildStatusUI
 */
enyo.kind({
	name: "Phonegap.ProjectProperties.PlatformBuildStatus",
	kind: "onyx.IconButton",
	classes: "ares-project-properties-build-status-icon",
	ontap: "showStatusMessage",
	published: {
		platform: undefined,
		buildStatusData: undefined,
	},
	buildStatusDataChanged: function() {
		if (this.buildStatusData && this.buildStatusData.status[this.platform] === "complete") {
			//Build status: complete
			this.setSrc("$services/assets/images/platforms/" + this.platform + "-logo-complete-32x32.png");

		} else {
			if (this.buildStatusData && this.buildStatusData.status[this.platform] === "error" ||
			    this.buildStatusData && this.buildStatusData.status[this.platform] === null){

				//Build status: error
				this.setSrc("$services/assets/images/platforms/" + this.platform + "-logo-error-32x32.png");

			} else {
				if(this.buildStatusData === null) {

					//Build status: application not built
					this.setSrc("$services/assets/images/platforms/" + this.platform + "-logo-not-available-32x32.png");

				} else {
					//Build status: pending
					this.setSrc("$services/assets/images/platforms/" + this.platform + "-logo-not-available-32x32.png");
					this.bubble("appIdChanged");
				}
			}
		}
	}
});

enyo.kind({
	name: "Phonegap.ProjectProperties.BuildStatus",
	kind: "FittableRows",
	published: {
		appId: "",
		buildStatusData: undefined,
		phongapUrl: "https://build.phonegap.com",
		provider: undefined,
		selectedPlatform: undefined
	},
	handlers: {
		onUpdateStatusMessage: "updateDownloadMessageContent"
	},
	components: [
		{
			name: "buildStatusContainer", kind: "FittableRows", classes: "ares-project-properties-build-status-container",
			components: [
				{
					name: "platformIconContainer",
					classes:"ares-project-properties-platform-icon-container",
					kind: "FittableColumns",
				},

				{ name: "downloadStatus", kind: "Phonegap.ProjectProperties.DownloadStatus" },
				{
					name: "messageContainer",
					classes: "ares-project-properties-status-message-container",
					showing: false,
					components: [
						{
							name: "hideStatusContainer",
							kind: "onyx.IconButton",
							src: "$project-view/assets/images/close-button-16x16.png",
							classes: "ares-project-properties-hide-status-button",
							ontap:"hideMessageContainer"
						},
						{
							name: "statusMessage",
							classes: "ares-project-properties-status-message"
						}
					]
				},
				{
					kind: "FittableColumns",
					style: "height: 32px; position: relative; top:-6em;",
					components: [
						{
							name:"separatorForDownloadButton"
						},
						{
							name: "downloadButton",
							kind: "onyx.IconButton",
							src: "$services/assets/images/download-icon.png",
							shown: false,
							ontap: "downloadPackage"
						}
					]
				}

			]
		}
	],
	/**@private*/
	create: function() {
		this.inherited(arguments);
		this.createIconButtons();
		this.appIdChanged();
		this.setProvider(Phonegap.ProjectProperties.getProvider());
	},

	/**
	 * Create the IconButtons displaying the build state of the application
	 * for all platforms defined in the object {Phonegap.ProjectProperties.downloadStatus}
	 *
	 * @private
	 */
	createIconButtons: function() {
		for (var key in Phonegap.ProjectProperties.downloadStatus) {
			this.$.platformIconContainer.createComponent(
				{
					name: key + "Decorator",
					classes: "ares-project-properties-build-status-icon",
					components: [
						{
							name: key + "Button",
							kind: "Phonegap.ProjectProperties.PlatformBuildStatus",
							platform: key
						}
					]
				},
				{owner: this}
			);

		}
	},

	/**
	 * Charge the icon showing the build status of the application of a a given platform depending on
	 * its status. the status is checked from the "buildStatusData" object.
	 * By clicking on the icon, the status message is displayed.
	 *
	 * @private
	 */
	buildStatusDataChanged: function(){
		var pendingApplication = false;

		//Check if there is a pending build.
		for(var key1 in this.buildStatusData && this.buildStatusData.status) {
			if (this.buildStatusData.status[key1] === "pending") {
				pendingApplication = true;
			}
		}

		//If there is a pending build, another buildStatus Request is sent after 600 ms timeout.
		if (pendingApplication) {
			setTimeout(this.sendBuildStatusRequest(), 2000);
		}

		// Get only the Enyo control that have the "platform" attribute
		// => {Phonegap.ProjectProperties.PlatformBuildStatus} instance
		for(var key2 in this.$){
			if(this.$[key2].platform !== undefined) {
				this.$[key2].setBuildStatusData(this.buildStatusData);
			}
		}

		//Update to Status container if a platform is selected.
		if(this.selectedPlatform !== undefined) {
			this.showStatusMessage({platform: this.selectedPlatform});
		}

	},

	/**
	 * Use the phonegap service to request a {buildStatus} object from Phonegap build
	 * @private
	 */
	sendBuildStatusRequest: function() {
		this.provider.getAppData(this.appId, enyo.bind(this, this.getBuildStatusData));
	},

	/**
	 * Update the content of the statusMessage row.
	 * @protected
	 */
	updateDownloadMessageContent: function() {

		this.$.statusMessage.setContent(this.$.downloadStatus.getDownloadStatus(this.selectedPlatform));
		this.$.statusMessage.show();
		this.updateDownloadMessageDisplay(this.selectedPlatform);

		//stop the propagation of the bubble event
		return true;
	},

	/**
	 * Highlight the selected platform button by appling a css style on its decorator.
	 * @param {enyo.component} inIconButtonDecorator decorator of the button
	 * @private
	 */
	addHightlightIconButton: function(inIconButtonDecorator) {
		this.removeHightlightIconButton();
		inIconButtonDecorator.addClass("ares-project-properties-buildStatus-icon-highlight");

	},

	/**
	 * Remove the highlignt effect from all platform buttons.
	 * @private
	 */
	removeHightlightIconButton: function() {
		for(var key in Phonegap.ProjectProperties.downloadStatus) {
			this.$[key + "Decorator"].removeClass("ares-project-properties-buildStatus-icon-highlight");
		}
	},

	/**
	 *
	 * @param  {String} inPlatform Mobile platform supported by Phonegap.
	 * @private
	 */
	updateDownloadMessageDisplay: function(inPlatform) {
		var classAttribute = "ares-project-properties-buildStatus-download-button-" + inPlatform;
		this.$.separatorForDownloadButton.setClassAttribute(classAttribute);

		this.$.downloadButton.show();
	},

	/**@private*/
	showStatusMessage: function(inSender, inEvent){

		this.$.messageContainer.show();
		this.addHightlightIconButton(this.$[inSender.platform+ "Decorator"]);

		if (this.buildStatusData && this.buildStatusData.status[inSender.platform] === "complete") {

				this.updateDownloadMessageContent();
				this.updateDownloadMessageDisplay(inSender.platform);
		} else {
			if (this.buildStatusData && this.buildStatusData.status[inSender.platform] === "error" ||
				this.buildStatusData && this.buildStatusData.status[inSender.platform] === null){

				//Build status: error
				this.$.downloadButton.hide();
				this.$.statusMessage.setContent("Error: " + this.buildStatusData.error[inSender.platform]);
			} else {

				if(this.buildStatusData === null) {

					//Build status: application not built
					this.$.downloadButton.hide();
					this.$.statusMessage.setContent("Build the application first");

				} else {

					//Build status: pending
					this.$.downloadButton.hide();
					this.$.statusMessage.setContent("Build in progress");
				}
			}
		}
	return true; //stop the propagation of the event

	},

	/**
	 * Listener to launch the download request form the Phonegap Build service manager.
	 * @param  {Object} inSender
	 * @param  {Object} inEvent
	 * @private
	 */
	downloadPackage: function(inSender, inEvent) {

		var projectConfig = this.owner.getProject();
		this.provider.downloadPackage(projectConfig, this.selectedPlatform, this.buildStatusData, enyo.bind(this, this.getPackage));

		//set the download status to "Download on progress"
		this.$.downloadStatus.setDownloadStatus(this.selectedPlatform, 2);
	},
	/**
	 * Callback used in the function "downloadPackage()"" in "Build.js"
	 * Update the status message to show the current status of the download request.
	 *
	 * @param  {Object} err       error object
	 * @private
	 */
	getPackage: function(err) {
		if(err) {
			//set the download status to "Download failed"
			this.$.downloadStatus.setDownloadStatus(this.selectedPlatform, 0);
		} else {
			//set the download status to "Download complete"
			this.$.downloadStatus.setDownloadStatus(this.selectedPlatform, 1);
		}
	},

	/**@private*/
	hideMessageContainer: function() {
		//Unselect the focused platform
		this.setSelectedPlatform(undefined);
		this.removeHightlightIconButton();

		this.$.messageContainer.hide();
		this.$.downloadButton.hide();
	},

	/**@private*/
	hideMessageContent: function() {
		this.$.downloadButton.hide();
	},

	/**@private*/
	appIdChanged: function(){

		if(this.appId === "" || this.appId === undefined){
			this.setBuildStatusData(null);
		} else {
			this.sendBuildStatusRequest();
		}
		this.$.buildStatusContainer.render();
	},

	/**
	 * Callback function to initialize the "buildStatusData" object.
	 *
	 * @param  {Object} err               error object
	 * @param  {Object} inBuildStatusData Object returned by Phonegap build, it contains several informations
	 *                                    about the built application.
	 * @private
	 */
	getBuildStatusData: function (err, inBuildStatusData) {
		if (err) {
			this.warn("err:", err);
		} else {
			this.setBuildStatusData(inBuildStatusData.user);
		}
	}
});

/**
 * Model kind to keep track on the download status for each
 * mobile platform supported by Phonegap Build.
 *
 * Used only by the widget {Phonegap.ProjectProperties.BuildStatus}
 */
enyo.kind({
	name: "Phonegap.ProjectProperties.DownloadStatus",
	published: {
		downloadStatus: {"android": "", "ios": "", "winphone": "",
						"blackberry": "", "webos": ""}
	},

	/**
	 * Set the download status for a platform defined in {this.downloadStatus}.
	 *
	 * @param {String} inPlatform       platform defined in {this.downloadStatus}
	 * @param {integer} inDownloadStatus code status: 0 => failed, 1 => complete, other => on progress
	 * @public
	 */
	setDownloadStatus: function(inPlatform, inDownloadStatus) {
		if(inDownloadStatus === 1){
			Phonegap.ProjectProperties.downloadStatus[inPlatform] = "Download complete";
		} else {
			if (inDownloadStatus === 0) {
				Phonegap.ProjectProperties.downloadStatus[inPlatform] = "Download failed";
			} else {
				Phonegap.ProjectProperties.downloadStatus[inPlatform] = "Download on progress";
			}
		}

		this.bubble("onUpdateStatusMessage");
	},

	/**
	 * Get the download status value by platform.
	 *
	 * @param  {String} inPlatform [description]
	 * @return {String} status message
	 * @public
	 */
	getDownloadStatus: function(inPlatform) {
		return Phonegap.ProjectProperties.downloadStatus[inPlatform];
	}

});<|endoftext|>


<commit_before>

var totalDownloads = 145928; // pre-GitHub download total

var handleApiResponse = function() {
  if (xmlHttp.readyState === 4) {
    var releasesData = JSON.parse(xmlHttp.responseText);
    totalDownloads += releasesData.reduce(
      function (total, current) {
        return total + current.assets[0].download_count;
      },
      0
    );

    var linkHeader = xmlHttp.getResponseHeader("Link");
    var nextUrlMatch = linkHeader.match(/<(.+)>; rel="next"/);
    if (nextUrlMatch) {
      xmlHttp = new XMLHttpRequest();
      xmlHttp.onreadystatechange = handleApiResponse;
      xmlHttp.open("GET", nextUrlMatch[1]);
      xmlHttp.send();
    } else {
      document.getElementById("download-count").innerText = totalDownloads + " downloads";
    }
  }
};

var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = handleApiResponse;
xmlHttp.open("GET", "https://api.github.com/repos/LiveSplit/LiveSplit/releases");
xmlHttp.send();
<commit_msg>Remove empty lines<commit_after>var totalDownloads = 145928; // pre-GitHub download total

var handleApiResponse = function() {
  if (xmlHttp.readyState === 4) {
    var releasesData = JSON.parse(xmlHttp.responseText);
    totalDownloads += releasesData.reduce(
      function (total, current) {
        return total + current.assets[0].download_count;
      },
      0
    );

    var linkHeader = xmlHttp.getResponseHeader("Link");
    var nextUrlMatch = linkHeader.match(/<(.+)>; rel="next"/);
    if (nextUrlMatch) {
      xmlHttp = new XMLHttpRequest();
      xmlHttp.onreadystatechange = handleApiResponse;
      xmlHttp.open("GET", nextUrlMatch[1]);
      xmlHttp.send();
    } else {
      document.getElementById("download-count").innerText = totalDownloads + " downloads";
    }
  }
};

var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = handleApiResponse;
xmlHttp.open("GET", "https://api.github.com/repos/LiveSplit/LiveSplit/releases");
xmlHttp.send();
<|endoftext|>


<commit_before>// @flow
import React, {Component} from 'react'
import {Box, Icon, Input, Text} from '../../common-adapters'
import {globalColors, globalMargins, globalStyles} from '../../styles'
import {Picker} from 'emoji-mart'
import {backgroundImageFn} from '../../common-adapters/emoji'

import type {Props} from './input'

type State = {
  emojiPickerOpen: boolean,
  text: string,
}

const _cachedInput: {[key: ?string]: ?string} = { }

class Conversation extends Component<void, Props, State> {
  _input: any;
  _fileInput: any;
  state: State;

  _setRef = r => {
    this._input = r
  }

  constructor (props: Props) {
    super(props)
    const {emojiPickerOpen} = props
    this.state = {emojiPickerOpen, text: _cachedInput[props.selectedConversation] || ''}
  }

  componentDidMount () {
    document.body.addEventListener('keydown', this._globalKeyDownHandler)
  }

  componentWillUnmount () {
    document.body.removeEventListener('keydown', this._globalKeyDownHandler)
  }

  componentWillReceiveProps (nextProps: Props) {
    if (nextProps.selectedConversation !== this.props.selectedConversation) {
      this.focusInput()
      _cachedInput[this.props.selectedConversation] = this.state.text
      this.setState({text: _cachedInput[nextProps.selectedConversation] || ''})
    }
  }

  componentDidUpdate (prevProps: Props) {
    if (!this.props.isLoading && prevProps.isLoading) {
      this.focusInput()
    }
  }

  _handleGlobalKeyPress (ev: Event) {
    if (!this._input) {
      return
    }

    const target = ev.target
    if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
      return
    }

    this._input.focus()
  }
  _globalKeyDownHandler = (ev: Event) => this._handleGlobalKeyPress(ev)

  _insertEmoji (emojiColons: string) {
    const text: string = this.state.text || ''
    if (this._input) {
      const {selectionStart = 0, selectionEnd = 0} = this._input.selections() || {}
      const nextText = [text.substring(0, selectionStart), emojiColons, text.substring(selectionEnd)].join('')
      this.setState({text: nextText})
      this.focusInput()
    }
  }

  _onClickEmoji = () => {
    this.setState({emojiPickerOpen: !this.state.emojiPickerOpen})
  }

  _openFilePicker = () => {
    if (this._fileInput) {
      this._fileInput.click()
    }
  }

  _pickFile () {
    if (this._fileInput && this._fileInput.files && this._fileInput.files[0]) {
      const {path, name, type} = this._fileInput.files[0]
      this.props.onAttach(path, name, type.indexOf('image') >= 0 ? 'Image' : 'Other')
      this._fileInput.value = null
    }
  }

  focusInput = () => {
    this._input && this._input.focus()
  }

  _pickerOnClick = (emoji) => {
    this._insertEmoji(emoji.colons)
    this._onClickEmoji()
  }

  render () {
    return (
      <Box style={{...globalStyles.flexBoxColumn, borderTop: `solid 1px ${globalColors.black_05}`}}>
        <Box style={{...globalStyles.flexBoxRow, alignItems: 'flex-start'}}>
          <input type='file' style={{display: 'none'}} ref={r => { this._fileInput = r }} onChange={() => this._pickFile()} />
          <Input
            autoFocus={true}
            small={true}
            style={styleInput}
            ref={this._setRef}
            hintText='Write a message'
            hideUnderline={true}
            onChangeText={text => this.setState({text})}
            value={this.state.text}
            multiline={true}
            rowsMin={1}
            rowsMax={5}
            onEnterKeyDown={(e) => {
              e.preventDefault()
              if (this.state.text) {
                this.props.onPostMessage(this.state.text)
                this.setState({text: ''})
              }
            }}
          />
          {this.state.emojiPickerOpen && (
            <Box>
              <Box style={{position: 'absolute', right: 0, bottom: 0, top: 0, left: 0}} onClick={() => this.setState({emojiPickerOpen: false})} />
              <Box style={{position: 'relative'}}>
                <Box style={{position: 'absolute', right: 0, bottom: 0}}>
                  <Picker onClick={this._pickerOnClick} emoji={'ghost'} title={'emojibase'} backgroundImageFn={backgroundImageFn} />
                </Box>
              </Box>
            </Box>
          )}
          <Icon onClick={this._onClickEmoji} style={styleIcon} type='iconfont-emoji' />
          <Icon onClick={this._openFilePicker} style={styleIcon} type='iconfont-attachment' />
        </Box>
        <Text type='BodySmall' style={styleFooter} onClick={this.focusInput}>*bold*, _italics_, `code`</Text>
      </Box>
    )
  }
}

const styleInput = {
  flex: 1,
  marginTop: globalMargins.tiny,
  marginLeft: globalMargins.tiny,
  marginRight: globalMargins.tiny,
  textAlign: 'left',
}

const styleIcon = {
  paddingTop: globalMargins.tiny,
  paddingRight: globalMargins.tiny,
}

const styleFooter = {
  flex: 1,
  color: globalColors.black_20,
  cursor: 'text',
  textAlign: 'right',
  marginTop: 0,
  marginBottom: globalMargins.xtiny,
  marginRight: globalMargins.tiny,
}

export default Conversation
<commit_msg>Use eslint browser env so that instance checks lint<commit_after>// @flow
/* eslint-env browser */
import React, {Component} from 'react'
import {Box, Icon, Input, Text} from '../../common-adapters'
import {globalColors, globalMargins, globalStyles} from '../../styles'
import {Picker} from 'emoji-mart'
import {backgroundImageFn} from '../../common-adapters/emoji'

import type {Props} from './input'

type State = {
  emojiPickerOpen: boolean,
  text: string,
}

const _cachedInput: {[key: ?string]: ?string} = { }

class Conversation extends Component<void, Props, State> {
  _input: any;
  _fileInput: any;
  state: State;

  _setRef = r => {
    this._input = r
  }

  constructor (props: Props) {
    super(props)
    const {emojiPickerOpen} = props
    this.state = {emojiPickerOpen, text: _cachedInput[props.selectedConversation] || ''}
  }

  componentDidMount () {
    document.body.addEventListener('keydown', this._globalKeyDownHandler)
  }

  componentWillUnmount () {
    document.body.removeEventListener('keydown', this._globalKeyDownHandler)
  }

  componentWillReceiveProps (nextProps: Props) {
    if (nextProps.selectedConversation !== this.props.selectedConversation) {
      this.focusInput()
      _cachedInput[this.props.selectedConversation] = this.state.text
      this.setState({text: _cachedInput[nextProps.selectedConversation] || ''})
    }
  }

  componentDidUpdate (prevProps: Props) {
    if (!this.props.isLoading && prevProps.isLoading) {
      this.focusInput()
    }
  }

  _handleGlobalKeyPress (ev: Event) {
    if (!this._input) {
      return
    }

    const target = ev.target
    if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
      return
    }

    this._input.focus()
  }
  _globalKeyDownHandler = (ev: Event) => this._handleGlobalKeyPress(ev)

  _insertEmoji (emojiColons: string) {
    const text: string = this.state.text || ''
    if (this._input) {
      const {selectionStart = 0, selectionEnd = 0} = this._input.selections() || {}
      const nextText = [text.substring(0, selectionStart), emojiColons, text.substring(selectionEnd)].join('')
      this.setState({text: nextText})
      this.focusInput()
    }
  }

  _onClickEmoji = () => {
    this.setState({emojiPickerOpen: !this.state.emojiPickerOpen})
  }

  _openFilePicker = () => {
    if (this._fileInput) {
      this._fileInput.click()
    }
  }

  _pickFile () {
    if (this._fileInput && this._fileInput.files && this._fileInput.files[0]) {
      const {path, name, type} = this._fileInput.files[0]
      this.props.onAttach(path, name, type.indexOf('image') >= 0 ? 'Image' : 'Other')
      this._fileInput.value = null
    }
  }

  focusInput = () => {
    this._input && this._input.focus()
  }

  _pickerOnClick = (emoji) => {
    this._insertEmoji(emoji.colons)
    this._onClickEmoji()
  }

  render () {
    return (
      <Box style={{...globalStyles.flexBoxColumn, borderTop: `solid 1px ${globalColors.black_05}`}}>
        <Box style={{...globalStyles.flexBoxRow, alignItems: 'flex-start'}}>
          <input type='file' style={{display: 'none'}} ref={r => { this._fileInput = r }} onChange={() => this._pickFile()} />
          <Input
            autoFocus={true}
            small={true}
            style={styleInput}
            ref={this._setRef}
            hintText='Write a message'
            hideUnderline={true}
            onChangeText={text => this.setState({text})}
            value={this.state.text}
            multiline={true}
            rowsMin={1}
            rowsMax={5}
            onEnterKeyDown={(e) => {
              e.preventDefault()
              if (this.state.text) {
                this.props.onPostMessage(this.state.text)
                this.setState({text: ''})
              }
            }}
          />
          {this.state.emojiPickerOpen && (
            <Box>
              <Box style={{position: 'absolute', right: 0, bottom: 0, top: 0, left: 0}} onClick={() => this.setState({emojiPickerOpen: false})} />
              <Box style={{position: 'relative'}}>
                <Box style={{position: 'absolute', right: 0, bottom: 0}}>
                  <Picker onClick={this._pickerOnClick} emoji={'ghost'} title={'emojibase'} backgroundImageFn={backgroundImageFn} />
                </Box>
              </Box>
            </Box>
          )}
          <Icon onClick={this._onClickEmoji} style={styleIcon} type='iconfont-emoji' />
          <Icon onClick={this._openFilePicker} style={styleIcon} type='iconfont-attachment' />
        </Box>
        <Text type='BodySmall' style={styleFooter} onClick={this.focusInput}>*bold*, _italics_, `code`</Text>
      </Box>
    )
  }
}

const styleInput = {
  flex: 1,
  marginTop: globalMargins.tiny,
  marginLeft: globalMargins.tiny,
  marginRight: globalMargins.tiny,
  textAlign: 'left',
}

const styleIcon = {
  paddingTop: globalMargins.tiny,
  paddingRight: globalMargins.tiny,
}

const styleFooter = {
  flex: 1,
  color: globalColors.black_20,
  cursor: 'text',
  textAlign: 'right',
  marginTop: 0,
  marginBottom: globalMargins.xtiny,
  marginRight: globalMargins.tiny,
}

export default Conversation
<|endoftext|>


<commit_before>// This file exists as an entry point for bundling our umd builds.
// Both in rollup and in webpack, umd builds built from es6 modules are not compatible with mixed imports. (which exist in index.js)
// This file does away with named imports in favor of a single export default.
import Select from './Select';
import Async from './Async';
import AsyncCreatable from './AsyncCreatable';
import Creatable from './Creatable';

Select.Async = Async;
Select.AsyncCreatable = AsyncCreatable;
Select.Creatable = Creatable;

export default Select;
<commit_msg>Updating index.umd to export Value, ref #1962<commit_after>// This file exists as an entry point for bundling our umd builds.
// Both in rollup and in webpack, umd builds built from es6 modules are not
// compatible with mixed imports (which exist in index.js)
// This file does away with named imports in favor of a single export default.

import Select from './Select';
import Async from './Async';
import AsyncCreatable from './AsyncCreatable';
import Creatable from './Creatable';
import Value from './Value';

Select.Async = Async;
Select.AsyncCreatable = AsyncCreatable;
Select.Creatable = Creatable;
Select.Value = Value;

export default Select;
<|endoftext|>


<commit_before>    /**
     * OAuth Consumer
     *
     * @constructor
     * @param {String} key
     * @param {String} secret
     */
    jsOAuth = function (key, secret, callback_url) {
        var args = arguments, args_callee = args.callee, args_length = args.length,
            token = EMPTY_STRING, jsoauth = this;

        if (!(this instanceof args_callee)) {
            return new args_callee(key, secret, callback_url);
        }

        jsoauth.key = key; /** @type {String|undefined} */
        jsoauth.secret = secret; /** @type {String|undefined} */
        jsoauth.callback_url = callback_url;  /** @type {String|undefined} */
        jsoauth.signature = '';
        jsoauth.signature_method = jsOAuth.SIGNATURE_METHOD['PLAINTEXT'];
        jsoauth.OAUTH_REALM = '';
        jsoauth.OAUTH_REQUEST_TOKEN_URL = '';
        jsoauth.OAUTH_REQUEST_AUTH_URL = '';
        jsoauth.OAUTH_GET_TOKEN_URL = '';

        jsoauth.oauth_parameters = new Collection({
            'oauth_consumer_key': key,
            'oauth_token': token,
            'oauth_signature_method': jsoauth.signature_method.toString(),
            'oauth_signature': jsoauth.signature,
            'oauth_timestamp': '',
            'oauth_nonce': '',
            'oauth_version': jsoauth.OAUTH_VERSION,
            'oauth_verifier': ''
        });

        /**
         * Create a new http request
         *
         * @param {String} url
         * @param {String} method
         * @param {Object} parameters
         */
        jsoauth.Request = function(url, method, parameters){
            var args = arguments, args_callee = args.callee, args_length = args.length,
                request = this;

            if (!(this instanceof args_callee)) {
                return new args_callee(url, method, parameters);
            }

            request = jsoauth.Request.prototype.constructor.call(
                request, url, method, parameters);

            /** @property */
            request.timestamp = ''; // current timestamp

            /** @property */
            request.nonce = generateKey(64); // 64-bit rendom key

            return request;
        };

        jsoauth.Request.prototype = new HttpRequest();

        /**
         * Sign a request using the signature_method
         *
         * @param {Object} consumer
         * @param {String} token
         */
        jsoauth.Request.prototype.sign = function (consumer, token) {
            return consumer.signature_method.sign(consumer, token);
        };

        jsoauth.Request.prototype.getTimestamp = function () {
            return parseInt((new Date).getTime() / 1000) + '';
        };

        /**
         *
         * @constructor
         * @param {String} key
         * @param {String} secret
         */
        jsoauth.Token = function(key, secret){

        };

        /**
         * @memberOf jsOAuth
         */
        jsoauth.getRequestToken = function () {
            var request = new this.Request(this.OAUTH_REQUEST_TOKEN_URL,
                HttpRequest.METHOD_GET, {}), params = this.oauth_parameters,
                auth = [];

            authorization_header = 'OAuth realm="' + this.OAUTH_REALM + '",';

            params.ksort();
            params.oauth_signature = request.sign(this);
            console.log(params.oauth_signature);
            params.oauth_timestamp = request.getTimestamp();
            params.oauth_nonce = request.nonce;
            for (i in params) {
                if (params.hasOwnProperty(i)) {
                    auth.push(i + '="' + params[i] + '"');
                }
            }
            authorization_header += auth.join(',');

            request.setRequestHeader('Authorization', authorization_header);
            request.parameters.setQueryParams(params);

            // done.
            request.send();
        },

        /**
         * @memberOf jsOAuth
         */
        jsoauth.requestAuthorization = function () {},

        /**
         * @memberOf jsOAuth
         */
        jsoauth.getAccessToken = function () {}

        return jsoauth;
    };

    function generateKey(key_len) {
        key_len = key_len || 64;

        var key_bytes = key_len / 8, value = '', key_iter = key_bytes / 4,
            key_remainder = key_bytes % 4,
            chars = ['20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
                     '2A', '2B', '2C', '2D', '2E', '2F', '30', '31', '32', '33',
                     '34', '35', '36', '37', '38', '39', '3A', '3B', '3C', '3D',
                     '3E', '3F', '40', '41', '42', '43', '44', '45', '46', '47',
                     '48', '49', '4A', '4B', '4C', '4D', '4E', '4F', '50', '51',
                     '52', '53', '54', '55', '56', '57', '58', '59', '5A', '5B',
                     '5C', '5D', '5E', '5F', '60', '61', '62', '63', '64', '65',
                     '66', '67', '68', '69', '6A', '6B', '6C', '6D', '6E', '6F',
                     '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
                     '7A', '7B', '7C', '7D', '7E'],
            i;

        for (i = 0; i < key_iter; i++) {
            value += chars[rand()] + chars[rand()] + chars[rand()]+ chars[rand()];
        }

        // handle remaing bytes
        for (i = 0; i < key_remainder; i++) {
            value += chars[rand()];
        }

        return value;

        function rand() {
            var math = Math;
            return math.floor(math.random() * chars.length);
        }
    }

    jsOAuth.prototype.OAUTH_VERSION            = '1.0';    /** @const */

    jsOAuth.SIGNATURE_METHOD = {
        'HMAC-SHA1': {
            /**
             * Override default toString method to use as a constant key
             */
            toString: function () {
                return 'HMAC-SHA1';
            }
        },
        'PLAINTEXT': {
            toString: function () {
                return 'PLAINTEXT';
            },
            sign: function(consumer, token){
                var signature = [];
                signature.push(QueryString.urlEncode(consumer.secret));

                if (token) {
                    signature.push(QueryString.urlEncode(token.secret));
                } else {
                    signature.push('');
                }

                return QueryString.urlEncode(signature.join('&'));
            }
        }
    };

    /** closure compiler "export" method, use quoted syntax */
    window['jsOAuth'] = jsOAuth;

<commit_msg>fixed PLAINTEXT signing method<commit_after>    /**
     * OAuth Consumer
     *
     * @constructor
     * @param {String} key
     * @param {String} secret
     */
    jsOAuth = function (key, secret, callback_url) {
        var args = arguments, args_callee = args.callee, args_length = args.length,
            token = EMPTY_STRING, jsoauth = this;

        if (!(this instanceof args_callee)) {
            return new args_callee(key, secret, callback_url);
        }

        jsoauth.key = key; /** @type {String|undefined} */
        jsoauth.secret = secret; /** @type {String|undefined} */
        jsoauth.callback_url = callback_url;  /** @type {String|undefined} */
        jsoauth.signature = '';
        jsoauth.signature_method = jsOAuth.SIGNATURE_METHOD['PLAINTEXT'];
        jsoauth.OAUTH_REALM = '';
        jsoauth.OAUTH_REQUEST_TOKEN_URL = '';
        jsoauth.OAUTH_REQUEST_AUTH_URL = '';
        jsoauth.OAUTH_GET_TOKEN_URL = '';

        jsoauth.oauth_parameters = new Collection({
            'oauth_consumer_key': key,
            'oauth_token': token,
            'oauth_signature_method': jsoauth.signature_method.toString(),
            'oauth_signature': jsoauth.signature,
            'oauth_timestamp': '',
            'oauth_nonce': '',
            'oauth_version': jsoauth.OAUTH_VERSION,
            'oauth_verifier': ''
        });

        /**
         * Create a new http request
         *
         * @param {String} url
         * @param {String} method
         * @param {Object} parameters
         */
        jsoauth.Request = function(url, method, parameters){
            var args = arguments, args_callee = args.callee, args_length = args.length,
                request = this;

            if (!(this instanceof args_callee)) {
                return new args_callee(url, method, parameters);
            }

            request = jsoauth.Request.prototype.constructor.call(
                request, url, method, parameters);

            /** @property */
            request.timestamp = ''; // current timestamp

            /** @property */
            request.nonce = generateKey(64); // 64-bit rendom key

            return request;
        };

        jsoauth.Request.prototype = new HttpRequest();

        /**
         * Sign a request using the signature_method
         *
         * @param {Object} consumer
         * @param {String} token
         */
        jsoauth.Request.prototype.sign = function (consumer, token) {
            return consumer.signature_method.sign(consumer, token);
        };

        jsoauth.Request.prototype.getTimestamp = function () {
            return parseInt((new Date).getTime() / 1000) + '';
        };

        /**
         *
         * @constructor
         * @param {String} key
         * @param {String} secret
         */
        jsoauth.Token = function(key, secret){

        };

        /**
         * @memberOf jsOAuth
         */
        jsoauth.getRequestToken = function () {
            var request = new this.Request(this.OAUTH_REQUEST_TOKEN_URL,
                HttpRequest.METHOD_GET, {}), params = this.oauth_parameters,
                auth = [], signature;

            authorization_header = 'OAuth realm="' + this.OAUTH_REALM + '",';

            params.ksort();

            params.oauth_signature = request.sign(this);
            params.oauth_timestamp = request.getTimestamp();
            params.oauth_nonce = request.nonce;
            for (i in params) {
                if (params.hasOwnProperty(i)) {
                    auth.push(i + '="' + params[i] + '"');
                }
            }
            authorization_header += auth.join(',');

            request.setRequestHeader('Authorization', authorization_header);
            request.parameters.setQueryParams(params);

            // done.
            request.send();
        },

        /**
         * @memberOf jsOAuth
         */
        jsoauth.requestAuthorization = function () {},

        /**
         * @memberOf jsOAuth
         */
        jsoauth.getAccessToken = function () {}

        return jsoauth;
    };

    function generateKey(key_len) {
        key_len = key_len || 64;

        var key_bytes = key_len / 8, value = '', key_iter = key_bytes / 4,
            key_remainder = key_bytes % 4,
            chars = ['20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
                     '2A', '2B', '2C', '2D', '2E', '2F', '30', '31', '32', '33',
                     '34', '35', '36', '37', '38', '39', '3A', '3B', '3C', '3D',
                     '3E', '3F', '40', '41', '42', '43', '44', '45', '46', '47',
                     '48', '49', '4A', '4B', '4C', '4D', '4E', '4F', '50', '51',
                     '52', '53', '54', '55', '56', '57', '58', '59', '5A', '5B',
                     '5C', '5D', '5E', '5F', '60', '61', '62', '63', '64', '65',
                     '66', '67', '68', '69', '6A', '6B', '6C', '6D', '6E', '6F',
                     '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
                     '7A', '7B', '7C', '7D', '7E'],
            i;

        for (i = 0; i < key_iter; i++) {
            value += chars[rand()] + chars[rand()] + chars[rand()]+ chars[rand()];
        }

        // handle remaing bytes
        for (i = 0; i < key_remainder; i++) {
            value += chars[rand()];
        }

        return value;

        function rand() {
            var math = Math;
            return math.floor(math.random() * chars.length);
        }
    }

    jsOAuth.prototype.OAUTH_VERSION            = '1.0';    /** @const */

    jsOAuth.SIGNATURE_METHOD = {
        'HMAC-SHA1': {
            /**
             * Override default toString method to use as a constant key
             */
            toString: function () {
                return 'HMAC-SHA1';
            }
        },
        'PLAINTEXT': {
            toString: function () {
                return 'PLAINTEXT';
            },
            sign: function(consumer, token){
                var signature = [];
                signature.push(QueryString.urlEncode(consumer.secret));

                if (token) {
                    signature.push(QueryString.urlEncode(token.secret));
                } else {
                    signature.push('');
                }

                return signature.join('&');
            }
        }
    };

    /** closure compiler "export" method, use quoted syntax */
    window['jsOAuth'] = jsOAuth;

<|endoftext|>


<commit_before>/*
 * Export: 数据导出
 * */
import $ from './jTool';
import Core from './Core';
import Cache from './Cache';
const Export = {
	html: function () {
		var html = '';
		return html;
	}
	/*
	 [对外公开方法]
	 @导出表格 .xls
	 $.table:当前操作的grid,由插件自动传入
	 $.fileName: 导出后的文件名
	 $.onlyChecked: 是否只导出已选中的表格
	 */
	,exportGridToXls: function(table, fileName, onlyChecked){
		let Settings = Cache.getSettings(table);
		var _this = this;
		var gmExportAction = $('#gm-export-action'); //createDOM内添加
		if(gmExportAction.length === 0){
			Core.outLog('导出失败，请查看配置项:supportExport是否配置正确', 'error');
			return;
		}

		var uri = 'data:application/vnd.ms-excel;base64,',
			theadHTML= '',	//存储导出的thead数据
			tbodyHTML ='', //存储导出的tbody下的数据
			tableDOM = $(table);	//当前要导出的table
		var thDOM = $('thead[grid-manager-thead] th[th-visible="visible"][gm-create="false"]', tableDOM),
			trDOM,
			tdDOM;
		//验证：是否只导出已选中的表格
		if(onlyChecked){
			trDOM = $('tbody tr[checked="true"]', tableDOM);
		}else{
			trDOM = $('tbody tr', tableDOM);
		}
		$.each(thDOM, function(i, v){
			theadHTML += ''
				+ v.getElementsByClassName('th-text')[0].textContent
				+ '	';
		});
		$.each(trDOM, function(i, v){
			tdDOM = $('td[gm-create="false"]', v);
			tbodyHTML += '
';
			$.each(tdDOM, function(i2, v2){
				tbodyHTML += v2.outerHTML
			});
			tbodyHTML += '
';
		});
		// 拼接要导出html格式数据
		var exportHTML  = ''
			+ '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
			+ '
'
			+ '
'
			+ theadHTML
			+ '
'
			+ '
'
			+ tbodyHTML
			+ '
'
			+ '
'
			+ '';
		gmExportAction.prop('href', uri + base64(exportHTML));
		gmExportAction.prop('download', (fileName || Settings.gridManagerName) +'.xls');
		gmExportAction.get(0).click();

		function base64(s) {
			return window.btoa(unescape(encodeURIComponent(s)))
		}
	}
};
export default Export;
<commit_msg>Export.js transform to es6<commit_after>/*
 * Export: 数据导出
 * */
import $ from './jTool';
import Core from './Core';
import Cache from './Cache';
const Export = {
	html: function () {
		const html = '';
		return html;
	}
	/*
	 [对外公开方法]
	 @导出表格 .xls
	 $.table:当前操作的grid,由插件自动传入
	 $.fileName: 导出后的文件名
	 $.onlyChecked: 是否只导出已选中的表格
	 */
	,exportGridToXls: function(table, fileName, onlyChecked){
		let Settings = Cache.getSettings(table);
		const gmExportAction = $('#gm-export-action'); //createDOM内添加
		if(gmExportAction.length === 0){
			Core.outLog('导出失败，请查看配置项:supportExport是否配置正确', 'error');
			return;
		}
		// type base64
		const uri = 'data:application/vnd.ms-excel;base64,';

		//存储导出的thead数据
		let	theadHTML = '';
		//存储导出的tbody下的数据
		let	tbodyHTML = '';

		//当前要导出的table
		const tableDOM = $(table);
		const thDOM = $('thead[grid-manager-thead] th[th-visible="visible"][gm-create="false"]', tableDOM);

		let	trDOM,
			tdDOM;
		//验证：是否只导出已选中的表格
		if(onlyChecked){
			trDOM = $('tbody tr[checked="true"]', tableDOM);
		}else{
			trDOM = $('tbody tr', tableDOM);
		}
		$.each(thDOM, function(i, v){
			theadHTML += `<th>${v.getElementsByClassName('th-text')[0].textContent}</th>`;
		});
		$.each(trDOM, function(i, v){
			tdDOM = $('td[gm-create="false"]', v);
			tbodyHTML += '
';
			$.each(tdDOM, function(i2, v2){

				tbodyHTML += v2.outerHTML;
			});
			tbodyHTML += '
';
		});
		// 拼接要导出html格式数据
		const exportHTML =`

				<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

'
							${theadHTML}

							${tbodyHTML}

			`;
		gmExportAction.prop('href', uri + base64(exportHTML));
		gmExportAction.prop('download', (fileName || Settings.gridManagerName) +'.xls');
		gmExportAction.get(0).click();

		function base64(s) {
			return window.btoa(unescape(encodeURIComponent(s)))
		}
	}
};
export default Export;
<|endoftext|>


<commit_before>/*
 * Jingle v0.4 Copyright (c) 2013 shixy, http://shixy.github.io/Jingle/
 * Released under MIT license
 * walker.shixy@gmail.com
 */
var Jingle = J = {
    version : '0.4',
    $ : window.Zepto,
    //参数设置
    settings : {
        //single  单页面工程  muti  多页面工程
        appType : 'single',
        //page默认动画效果
        transitionType : 'slide',
        //自定义动画时的默认动画时间(非page转场动画时间)
        transitionTime : 250,
        //自定义动画时的默认动画函数(非page转场动画函数)
        transitionTimingFunc : 'ease-in',
        //是否显示欢迎界面
        showWelcome : false,
        //欢迎界面卡片切换时的执行函数，可以制作酷帅吊炸天的欢迎界面
        welcomeSlideChange : null,
        //加载page模板时，是否显示遮罩
        showPageLoading : false,
        //page模板默认的相对位置，主要用于开发hybrid应用，实现page的自动装载
        basePagePath : 'html/',
        //page模板的远程路径{#id: href,#id: href}
        remotePage:{}
    },
    //手机或者平板
    mode : window.innerWidth < 800 ? "phone" : "tablet",
    hasTouch : 'ontouchstart' in window,
    //是否启动完成
    launchCompleted : false,
    //是否有打开的侧边菜单
    hasMenuOpen : false,
    //是否有打开的弹出框
    hasPopupOpen : false,
    isWebApp : location.protocol == 'http:',
    /**
     * 启动Jingle
     * @param opts {object}
     */
    launch : function(opts){
        $.extend(this.settings,opts);
        var hasShowWelcome = window.localStorage.getItem('hasShowWelcome');
        if(!hasShowWelcome && this.settings.showWelcome){
            this.Welcome.show();
        }
        this.Element.init();
        this.Element.initControlGroup();
        this.Router.init();
        this.Menu.init();
        this.Selected.init();
    }
};
<commit_msg>模板文件后缀名改为可配置<commit_after>/*
 * Jingle v0.4 Copyright (c) 2013 shixy, http://shixy.github.io/Jingle/
 * Released under MIT license
 * walker.shixy@gmail.com
 */
var Jingle = J = {
    version : '0.4',
    $ : window.Zepto,
    //参数设置
    settings : {
        //single  单页面工程  muti  多页面工程
        appType : 'single',
        //page默认动画效果
        transitionType : 'slide',
        //自定义动画时的默认动画时间(非page转场动画时间)
        transitionTime : 250,
        //自定义动画时的默认动画函数(非page转场动画函数)
        transitionTimingFunc : 'ease-in',
        //是否显示欢迎界面
        showWelcome : false,
        //欢迎界面卡片切换时的执行函数，可以制作酷帅吊炸天的欢迎界面
        welcomeSlideChange : null,
        //加载page模板时，是否显示遮罩
        showPageLoading : false,
        //page模板默认的相对位置，主要用于开发hybrid应用，实现page的自动装载
        basePagePath : 'html/',
        basePageSuffix : '.html',
        //page模板的远程路径{#id: href,#id: href}
        remotePage:{}
    },
    //手机或者平板
    mode : window.innerWidth < 800 ? "phone" : "tablet",
    hasTouch : 'ontouchstart' in window,
    //是否启动完成
    launchCompleted : false,
    //是否有打开的侧边菜单
    hasMenuOpen : false,
    //是否有打开的弹出框
    hasPopupOpen : false,
    isWebApp : location.protocol == 'http:',
    /**
     * 启动Jingle
     * @param opts {object}
     */
    launch : function(opts){
        $.extend(this.settings,opts);
        var hasShowWelcome = window.localStorage.getItem('hasShowWelcome');
        if(!hasShowWelcome && this.settings.showWelcome){
            this.Welcome.show();
        }
        this.Element.init();
        this.Element.initControlGroup();
        this.Router.init();
        this.Menu.init();
        this.Selected.init();
    }
};
<|endoftext|>


<commit_before>var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var Ui = function () { };
Ui.prototype = {
    initLanguageBar: function (storage) {
        var directoryHeaderAppender = (function () {
            var anchorSelector = '#directory-list > div.streams-grid.items-grid > div.directory_header > ul';
            var wrapperClass = 'tlf-languageBarContainer-directoryHeader';

            function isAdded() {
                return $(anchorSelector).find('.' + wrapperClass).length !== 0;
            }

            function add() {
                if (isAdded())
                    return;

                var $langBar = (new LanguageBar(storage)).create();
                $(anchorSelector).append($langBar);

                $($langBar).wrap(function () {
                    return '

';
                });
            }

            return {
                add: add
            };
        })();

        var routes = [
            { urlPattern: '^https?://([a-zA-Z]+\.)?twitch.tv/directory/?$', domModifySelector: '.section_header.first > .title', appender: directoryHeaderAppender }
        ];

        var observer = new MutationObserver(function (mutations) {
            var route = routes[0];

            // TODO: Check URL pattern

            if (!isNodeAdded(mutations, route.domModifySelector))
                return;

            // TODO: Check if isAddedTo

            stop();
            route.appender.add();
            start();
        });

        function isNodeAdded(mutations, selector) {
            return mutations.some(function (item) {
                return $(item.addedNodes).find(selector).length !== 0;
            });
        }

        function start() {
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        function stop() {
            observer.disconnect();
        }

        start();
    }
};<commit_msg>WIP: implementing language bar initialization.<commit_after>var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var Ui = function () { };
Ui.prototype = {
    initLanguageBar: function (storage) {
        var allowedUrls = [
            '^https?://([a-zA-Z]+\.)?twitch.tv/directory/all(/?|/.+)$'
        ];

        var languageBarAppender = (function () {
            var anchorSelector = '#directory-list .directory_header > ul.nav';
            var wrapperClass = 'tlf-languageBarContainer-directoryHeader';

            function isAdded() {
                return $(anchorSelector).find('.' + wrapperClass).length !== 0;
            }

            function add() {
                var $langBar = (new LanguageBar(storage)).create();
                $(anchorSelector).append($langBar);

                $($langBar).wrap(function () {
                    return '

';
                });
            }

            return {
                add: add,
                isAdded: isAdded
            };
        })();

        var observer = new MutationObserver(function (mutations) {
            if (!isUrlAllowed(document.URL))
                return;

            if (languageBarAppender.isAdded())
                return;

            stopMutationObserver();
            languageBarAppender.add();
            startMutationObserver();
        });

        function isUrlAllowed(url) {
            return allowedUrls.some(function (x) {
                return (new RegExp(x)).test(decodeURIComponent(url));
            });
        }

        function startMutationObserver() {
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        function stopMutationObserver() {
            observer.disconnect();
        }

        startMutationObserver();
    }
};<|endoftext|>


<commit_before>// Basic variables
var stage, canvas, context, ticker; // Setup variables

function init() { // Main function that runs when the HTML body loads; Runs once
  // Makes canvas fit to screen
  canvas = document.getElementById('gameCanvas');
  canvas.height = window.innerHeight - 50;
  canvas.width = window.innerWidth;

  // Makes canvas smooth (not blurry)
  context = canvas.getContext('2d');
  context.webkitImageSmoothingEnabled = false;
  context.mozImageSmoothingEnabled = false;
  context.imageSmoothingEnabled = false;

  // Creates a CreateJS stage
  stage = new createjs.Stage("gameCanvas");

  //Creates ticker
  createjs.Ticker.setFPS(60);
  createjs.Ticker.addEventListener("tick", handleTick);
} // init()

function handleTick(event) { // Game loop
  // Updates stage
  stage.update(event);

  // PUT GAME STUFF HERE
} // handleTick(event)
<commit_msg>Set gravity<commit_after>// Basic variables
var stage, canvas, context, ticker; // Setup variables
var gravity = 0.981; // Sets gravity to realistic

function init() { // Main function that runs when the HTML body loads; Runs once
  // Makes canvas fit to screen
  canvas = document.getElementById('gameCanvas');
  canvas.height = window.innerHeight - 50;
  canvas.width = window.innerWidth;

  // Makes canvas smooth (not blurry)
  context = canvas.getContext('2d');
  context.webkitImageSmoothingEnabled = false;
  context.mozImageSmoothingEnabled = false;
  context.imageSmoothingEnabled = false;

  // Creates a CreateJS stage
  stage = new createjs.Stage("gameCanvas");

  //Creates ticker
  createjs.Ticker.setFPS(60);
  createjs.Ticker.addEventListener("tick", handleTick);
} // init()

function handleTick(event) { // Game loop
  // Updates stage
  stage.update(event);

  // PUT GAME STUFF HERE
} // handleTick(event)
<|endoftext|>


<commit_before>/*===============================================================================
************   Handle clicks and make them fast (on tap);   ************
===============================================================================*/
app.initClickEvents = function () {
    function handleClicks(e) {
        /*jshint validthis:true */
        var clicked = $(this);
        var url = clicked.attr('href');
        var isLink = clicked[0].nodeName.toLowerCase() === 'a';

        // Str to boolean for data attributes
        function toBoolean(str) {
            if (str === 'false') return false;
            if (str === 'true') return true;
            return undefined;
        }
        // Check if link is external
        if (isLink) {
            /*jshint shadow:true */
            for (var i = 0; i < app.params.externalLinks.length; i++) {
                if (clicked.hasClass(app.params.externalLinks[i])) {
                    return;
                }

                if (clicked[0].rel === app.params.externalLinks[i]) {
                    return;
                }
            }
        }

        // Smart Select
        if (clicked.hasClass('smart-select')) {
            if (app.smartSelectOpen) app.smartSelectOpen(clicked);
        }

        // Open Panel
        if (clicked.hasClass('open-panel')) {
            if ($('.panel').length === 1) {
                if ($('.panel').hasClass('panel-left')) app.openPanel('left');
                else app.openPanel('right');
            }
            else {
                if (clicked.attr('data-panel') === 'right') app.openPanel('right');
                else app.openPanel('left');
            }
        }
        // Close Panel
        if (clicked.hasClass('close-panel')) {
            app.closePanel();
        }

        if (clicked.hasClass('panel-overlay') && app.params.panelsCloseByOutside) {
            app.closePanel();
        }
        // Popover
        if (clicked.hasClass('open-popover')) {
            var popover;
            if (clicked.attr('data-popover')) {
                popover = clicked.attr('data-popover');
            }
            else popover = '.popover';
            app.popover(popover, clicked);
        }
        if (clicked.hasClass('close-popover')) {
            app.closeModal('.popover.modal-in');
        }
        // Popup
        var popup;
        if (clicked.hasClass('open-popup')) {
            if (clicked.attr('data-popup')) {
                popup = clicked.attr('data-popup');
            }
            else popup = '.popup';
            app.popup(popup);
        }
        if (clicked.hasClass('close-popup')) {
            if (clicked.attr('data-popup')) {
                popup = clicked.attr('data-popup');
            }
            else popup = '.popup.modal-in';
            app.closeModal(popup);
        }
        // Login Screen
        var loginScreen;
        if (clicked.hasClass('open-login-screen')) {
            if (clicked.attr('data-login-screen')) {
                loginScreen = clicked.attr('data-login-screen');
            }
            else loginScreen = '.login-screen';
            app.loginScreen(loginScreen);
        }
        if (clicked.hasClass('close-login-screen')) {
            app.closeModal('.login-screen.modal-in');
        }
        // Close Modal
        if (clicked.hasClass('modal-overlay')) {
            if ($('.modal.modal-in').length > 0 && app.params.modalCloseByOutside)
                app.closeModal('.modal.modal-in');
            if ($('.actions-modal.modal-in').length > 0 && app.params.actionsCloseByOutside)
                app.closeModal('.actions-modal.modal-in');

            if ($('.popover.modal-in').length > 0) app.closeModal('.popover.modal-in');
        }
        if (clicked.hasClass('popup-overlay')) {
            if ($('.popup.modal-in').length > 0 && app.params.popupCloseByOutside)
                app.closeModal('.popup.modal-in');
        }

        // Tabs
        if (clicked.hasClass('tab-link')) {
            app.showTab(clicked.attr('data-tab') || clicked.attr('href'), clicked);
        }
        // Swipeout Delete
        if (clicked.hasClass('swipeout-delete')) {
            if (clicked.attr('data-confirm')) {
                var text = clicked.attr('data-confirm');
                var title = clicked.attr('data-confirm-title');
                if (title) {
                    app.confirm(text, title, function () {
                        app.swipeoutDelete(clicked.parents('.swipeout'));
                    });
                }
                else {
                    app.confirm(text, function () {
                        app.swipeoutDelete(clicked.parents('.swipeout'));
                    });
                }
            }
            else {
                app.swipeoutDelete(clicked.parents('.swipeout'));
            }

        }
        // Sortable
        if (clicked.hasClass('toggle-sortable')) {
            app.sortableToggle(clicked.data('sortable'));
        }
        if (clicked.hasClass('open-sortable')) {
            app.sortableOpen(clicked.data('sortable'));
        }
        if (clicked.hasClass('close-sortable')) {
            app.sortableClose(clicked.data('sortable'));
        }
        // Accordion
        if (clicked.hasClass('accordion-item-toggle') || (clicked.hasClass('item-link') && clicked.parent().hasClass('accordion-item'))) {
            var accordionItem = clicked.parents('.accordion-item');
            if (accordionItem.length === 0) accordionItem = clicked.parents('li');
            app.accordionToggle(accordionItem);
        }
        // Load Page
        if (app.params.ajaxLinks && !clicked.is(app.params.ajaxLinks) || !isLink) {
            return;
        }
        if (isLink) {
            e.preventDefault();
        }
        var validUrl = url && url.length > 0 && url.indexOf('#') !== 0;
        if (validUrl || clicked.hasClass('back')) {
            var view;
            if (clicked.attr('data-view')) {
                view = $(clicked.attr('data-view'))[0].f7View;
            }
            else {
                view = clicked.parents('.' + app.params.viewClass)[0] && clicked.parents('.' + app.params.viewClass)[0].f7View;
                if (view && view.params.linksView) {
                    view = $(view.params.linksView)[0].f7View;
                }
            }
            if (!view) {
                for (var i = 0; i < app.views.length; i++) {
                    if (app.views[i].main) view = app.views[i];
                }
            }
            if (!view) return;

            var animatePages;
            if (clicked.attr('data-animatePages')) {
                animatePages = toBoolean(clicked.attr('data-animatePages'));
            }
            else {
                if (clicked.hasClass('with-animation')) animatePages = true;
                if (clicked.hasClass('no-animation')) animatePages = false;
            }
            var options = {
                animatePages: animatePages,
                ignoreCache: toBoolean(clicked.attr('data-ignoreCache')),
                forceUrl: toBoolean(clicked.attr('data-forceUrl')),
                reload: toBoolean(clicked.attr('data-reload')),
                reloadPrevious: toBoolean(clicked.attr('data-reloadPrevious')),
                url: clicked.attr('href')
            };

            if (clicked.hasClass('back')) view.goBack(options);
            else view.loadPage(options);
        }
    }
    $(document).on('click', 'a, .open-panel, .close-panel, .panel-overlay, .modal-overlay, .popup-overlay, .swipeout-delete, .close-popup, .open-popup, .open-popover, .open-login-screen, .close-login-screen .smart-select, .toggle-sortable, .open-sortable, .close-sortable, .accordion-item-toggle', handleClicks);
};
<commit_msg>Load dom cached pages by links<commit_after>/*===============================================================================
************   Handle clicks and make them fast (on tap);   ************
===============================================================================*/
app.initClickEvents = function () {
    function handleClicks(e) {
        /*jshint validthis:true */
        var clicked = $(this);
        var url = clicked.attr('href');
        var isLink = clicked[0].nodeName.toLowerCase() === 'a';

        // Str to boolean for data attributes
        function toBoolean(str) {
            if (str === 'false') return false;
            if (str === 'true') return true;
            return undefined;
        }
        // Check if link is external
        if (isLink) {
            /*jshint shadow:true */
            for (var i = 0; i < app.params.externalLinks.length; i++) {
                if (clicked.hasClass(app.params.externalLinks[i])) {
                    return;
                }

                if (clicked[0].rel === app.params.externalLinks[i]) {
                    return;
                }
            }
        }

        // Smart Select
        if (clicked.hasClass('smart-select')) {
            if (app.smartSelectOpen) app.smartSelectOpen(clicked);
        }

        // Open Panel
        if (clicked.hasClass('open-panel')) {
            if ($('.panel').length === 1) {
                if ($('.panel').hasClass('panel-left')) app.openPanel('left');
                else app.openPanel('right');
            }
            else {
                if (clicked.attr('data-panel') === 'right') app.openPanel('right');
                else app.openPanel('left');
            }
        }
        // Close Panel
        if (clicked.hasClass('close-panel')) {
            app.closePanel();
        }

        if (clicked.hasClass('panel-overlay') && app.params.panelsCloseByOutside) {
            app.closePanel();
        }
        // Popover
        if (clicked.hasClass('open-popover')) {
            var popover;
            if (clicked.attr('data-popover')) {
                popover = clicked.attr('data-popover');
            }
            else popover = '.popover';
            app.popover(popover, clicked);
        }
        if (clicked.hasClass('close-popover')) {
            app.closeModal('.popover.modal-in');
        }
        // Popup
        var popup;
        if (clicked.hasClass('open-popup')) {
            if (clicked.attr('data-popup')) {
                popup = clicked.attr('data-popup');
            }
            else popup = '.popup';
            app.popup(popup);
        }
        if (clicked.hasClass('close-popup')) {
            if (clicked.attr('data-popup')) {
                popup = clicked.attr('data-popup');
            }
            else popup = '.popup.modal-in';
            app.closeModal(popup);
        }
        // Login Screen
        var loginScreen;
        if (clicked.hasClass('open-login-screen')) {
            if (clicked.attr('data-login-screen')) {
                loginScreen = clicked.attr('data-login-screen');
            }
            else loginScreen = '.login-screen';
            app.loginScreen(loginScreen);
        }
        if (clicked.hasClass('close-login-screen')) {
            app.closeModal('.login-screen.modal-in');
        }
        // Close Modal
        if (clicked.hasClass('modal-overlay')) {
            if ($('.modal.modal-in').length > 0 && app.params.modalCloseByOutside)
                app.closeModal('.modal.modal-in');
            if ($('.actions-modal.modal-in').length > 0 && app.params.actionsCloseByOutside)
                app.closeModal('.actions-modal.modal-in');

            if ($('.popover.modal-in').length > 0) app.closeModal('.popover.modal-in');
        }
        if (clicked.hasClass('popup-overlay')) {
            if ($('.popup.modal-in').length > 0 && app.params.popupCloseByOutside)
                app.closeModal('.popup.modal-in');
        }

        // Tabs
        if (clicked.hasClass('tab-link')) {
            app.showTab(clicked.attr('data-tab') || clicked.attr('href'), clicked);
        }
        // Swipeout Delete
        if (clicked.hasClass('swipeout-delete')) {
            if (clicked.attr('data-confirm')) {
                var text = clicked.attr('data-confirm');
                var title = clicked.attr('data-confirm-title');
                if (title) {
                    app.confirm(text, title, function () {
                        app.swipeoutDelete(clicked.parents('.swipeout'));
                    });
                }
                else {
                    app.confirm(text, function () {
                        app.swipeoutDelete(clicked.parents('.swipeout'));
                    });
                }
            }
            else {
                app.swipeoutDelete(clicked.parents('.swipeout'));
            }

        }
        // Sortable
        if (clicked.hasClass('toggle-sortable')) {
            app.sortableToggle(clicked.data('sortable'));
        }
        if (clicked.hasClass('open-sortable')) {
            app.sortableOpen(clicked.data('sortable'));
        }
        if (clicked.hasClass('close-sortable')) {
            app.sortableClose(clicked.data('sortable'));
        }
        // Accordion
        if (clicked.hasClass('accordion-item-toggle') || (clicked.hasClass('item-link') && clicked.parent().hasClass('accordion-item'))) {
            var accordionItem = clicked.parents('.accordion-item');
            if (accordionItem.length === 0) accordionItem = clicked.parents('li');
            app.accordionToggle(accordionItem);
        }
        // Load Page
        if (app.params.ajaxLinks && !clicked.is(app.params.ajaxLinks) || !isLink) {
            return;
        }
        if (isLink) {
            e.preventDefault();
        }
        var validUrl = url && url.length > 0 && url !== '#';

        if (validUrl || clicked.hasClass('back')) {

            var view;
            if (clicked.attr('data-view')) {
                view = $(clicked.attr('data-view'))[0].f7View;
            }
            else {
                view = clicked.parents('.' + app.params.viewClass)[0] && clicked.parents('.' + app.params.viewClass)[0].f7View;
                if (view && view.params.linksView) {
                    view = $(view.params.linksView)[0].f7View;
                }
            }
            if (!view) {
                for (var i = 0; i < app.views.length; i++) {
                    if (app.views[i].main) view = app.views[i];
                }
            }
            if (!view) return;

            var pageName;
            if (url.indexOf('#') === 0)  {
                if (view.params.domCache) {
                    pageName = url.split('#')[1];
                    url = undefined;
                }
                else return;
            }

            var animatePages;
            if (clicked.attr('data-animatePages')) {
                animatePages = toBoolean(clicked.attr('data-animatePages'));
            }
            else {
                if (clicked.hasClass('with-animation')) animatePages = true;
                if (clicked.hasClass('no-animation')) animatePages = false;
            }
            var options = {
                animatePages: animatePages,
                ignoreCache: toBoolean(clicked.attr('data-ignoreCache')),
                forceUrl: toBoolean(clicked.attr('data-forceUrl')),
                reload: toBoolean(clicked.attr('data-reload')),
                reloadPrevious: toBoolean(clicked.attr('data-reloadPrevious')),
                pageName: pageName,
                url: url
            };

            if (clicked.hasClass('back')) view.goBack(options);
            else view.loadPage(options);
        }
    }
    $(document).on('click', 'a, .open-panel, .close-panel, .panel-overlay, .modal-overlay, .popup-overlay, .swipeout-delete, .close-popup, .open-popup, .open-popover, .open-login-screen, .close-login-screen .smart-select, .toggle-sortable, .open-sortable, .close-sortable, .accordion-item-toggle', handleClicks);
};
<|endoftext|>


<commit_before>'use strict';

var Board = require('./game/board')
  , Grid = require('./client/grid');

var Socket = require('simple-websocket')
  , rainbow = require('color-rainbow')
  , thus = require('thus')
  , colorNamer = require('color-namer')
  , declared = require('declared')
  , humane = require('humane-js').create({ timeout: 500 })
  , uniq = require('uniq');

var EventEmitter = require('events').EventEmitter;

var server = new Socket('ws://localhost:2020');
var game = new EventEmitter;
var grid;

var showMyColor = function (color) {
  document.getElementById('mycolor').style.display = 'block';

  thus(document.getElementById('mycolor-icon'), function () {
    var hex = color.hexString();
    this.textContent = color.keyword() || colorNamer(hex, 'html')[0].name;
    this.style.color = hex;
  });
};

server.on('message', function (message) {
  game.emit(message.code, message);
});

game
  .on('wait', function () {
    humane.log('Waiting for the opponent…', { timeout: 0 });
  })
  .on('start', function (message) {
    humane.remove();
    humane.log('Let the carnage begin!', { timeout: 1500 });

    var board = Board(message.numColors, message.board);
    var player = message.player;
    game.opponent = message.opponent;

    var canvas = document.getElementById('grid');
    var palette = rainbow.create(board.numColors);

    game.grid = Grid(board, canvas, palette);

    var validateMove = function (region) {
      var instantWin = region == board.regionAt(game.opponent);

      var unreachable = !board.border(player).some(function (pos) {
        return board.regionAt(pos) == region;
      });

      var invalidMove = instantWin || unreachable;

      if (invalidMove) {
        humane.log('Invalid move!');
      }

      return !invalidMove;
    };

    game.grid.on('click', function (i, j, owner) {
      owner = declared(owner, player);
      var ownerColor = board.colorAt(owner);
      var targetRegion = board.regions[i][j];
      var targetColor = board.colors[i][j];

      if (owner == player) {
        if (!validateMove(targetRegion)) {
          return;
        }

        server.send(JSON.stringify({
          code: 'move',
          i: i,
          j: j
        }));
      }

      // Select regions adjacent to the owner's region.
      var regions = uniq(board.border(owner).filter(function (cell) {
        return board.colorAt(cell) == targetColor;
      }).map(board.regionAt.bind(board)));

      regions.forEach(function (region) {
        region.forEach(function (pos) {
          this.fill(pos.i, pos.j, ownerColor);
        }, this);
      }, this);

      board.recomputeRegions();
    });

    showMyColor(palette[board.colorAt(player)]);
  })
  .on('move', function (message) {
    // Opponent clicked some cell.
    game.grid.emit('click', message.i, message.j, game.opponent);
  });
<commit_msg>Refactor client.js<commit_after>'use strict';

var Board = require('./game/board')
  , Grid = require('./client/grid');

var Socket = require('simple-websocket')
  , rainbow = require('color-rainbow')
  , thus = require('thus')
  , colorNamer = require('color-namer')
  , declared = require('declared')
  , humane = require('humane-js').create({ timeout: 500 })
  , uniq = require('uniq');

var EventEmitter = require('events').EventEmitter;

var showMyColor = function (color) {
  document.getElementById('mycolor').style.display = 'block';

  thus(document.getElementById('mycolor-icon'), function () {
    var hex = color.hexString();
    this.textContent = color.keyword() || colorNamer(hex, 'html')[0].name;
    this.style.color = hex;
  });
};

var Game = function () {
  return new EventEmitter().
    on('wait', function () {
      humane.log('Waiting for the opponent…', { timeout: 0 });
    }).

    on('start', function (message) {
      var game = this;
      game.player = message.player;
      game.opponent = message.opponent;

      game.board = Board(message.numColors, message.board);

      var canvas = document.getElementById('grid');
      var palette = rainbow.create(board.numColors);
      game.grid = Grid(board, canvas, palette);

      var validateMove = function (region) {
        var instantWin = region == game.board.regionAt(game.opponent);

        var unreachable = !game.board.border(game.player).some(function (pos) {
          return game.board.regionAt(pos) == region;
        });

        var invalidMove = instantWin || unreachable;

        if (invalidMove) {
          humane.log('Invalid move!');
        }

        return !invalidMove;
      };

      this.grid.on('click', function (i, j, owner) {
        owner = declared(owner, game.player);
        var ownerColor = game.board.colorAt(owner);
        var targetRegion = game.board.regions[i][j];
        var targetColor = game.board.colors[i][j];

        if (owner == game.player) {
          if (!validateMove(targetRegion)) {
            return;
          }

          server.send(JSON.stringify({
            code: 'move',
            i: i,
            j: j
          }));
        }

        // Select regions adjacent to the owner's region.
        var regions = uniq(game.board.border(owner).filter(function (cell) {
          return game.board.colorAt(cell) == targetColor;
        }).map(game.board.regionAt.bind(game.board)));

        regions.forEach(function (region) {
          region.forEach(function (pos) {
            this.fill(pos.i, pos.j, ownerColor);
          }, this);
        }, this);

        game.board.recomputeRegions();
      });

      showMyColor(palette[board.colorAt(player)]);

      humane.remove();
      humane.log('Let the carnage begin!', { timeout: 1500 });
    }).

    on('move', function (message) {
      // Opponent clicked some cell.
      this.grid.emit('click', message.i, message.j, this.opponent);
    });
};

/**
 * Start the game client.
 *
 * @arg {number} wsport - Back-end WebSocket server port.
 */
var start = function (wsport) {
  var game = Game();

  new Socket('ws://localhost:' + wsport)
    .on('message', function (message) {
      game.emit(message.code, message);
    });
};

start(2020);
<|endoftext|>


<commit_before>
var config =  {'baseurl': 'http://cobwebsvc.edina.ac.uk/', 'versions': '1.3,1.4'};<commit_msg>IssueID #4: remove file that is not needed<commit_after><|endoftext|>