<commit_before>/**
 * @name		Album Module
 * @description	Takes care of every action an album can handle and execute.
 * @author		Tobias Reich
 * @copyright	2014 by Tobias Reich
 */

upload = {

	show: function(title, files, callback) {

		upload.close(true);
		$("body").append(build.uploadModal(title, files));

		if (callback!=null&&callback!=undefined) callback();

	},

	setIcon: function(icon) {

		$(".upload_message a").remove();
		$(".upload_message").prepend("");

	},

	setProgress: function(progress) {

		$(".progressbar div").css("width", progress + "%");

	},

	setText: function(text) {

		$(".progressbar").remove();
		$(".upload_message").append("
" + text + "
");

	},

	notify: function(title) {

		var popup;

		if (!window.webkitNotifications) return false;

		if (window.webkitNotifications.checkPermission()!==0) window.webkitNotifications.requestPermission();

		if (window.webkitNotifications.checkPermission()===0&&title) {
			popup = window.webkitNotifications.createNotification("", title, "You can now manage your new photo(s).");
			popup.show();
		}

	},

	start: {

		local: function(files) {

			var albumID = album.getID(),
				process = function(files, file) {

					var formData = new FormData(),
						xhr = new XMLHttpRequest(),
						pre_progress = 0,
						progress,
						finish = function() {

							window.onbeforeunload = null;

							$("#upload_files").val("");

							upload.close();
							upload.notify("Upload complete");

							if (album.getID()===false) lychee.goto("0");
							else album.load(albumID);

						};

					// Check if file is supported
					if (file.supported===false) {

						// Skip file
						if (file.next!==null) process(files, file.next);
						else {

							// Look for supported files
							// If zero files are supported, hide the upload after a delay

							var hasSupportedFiles = false;

							for (var i = 0; i < files.length; i++) {

								if (files[i].supported===true) {
									hasSupportedFiles = true;
									break;
								}

							}

							if (hasSupportedFiles===false) setTimeout(finish, 2000);

						}

						return false;

					}

					formData.append("function", "upload");
					formData.append("albumID", albumID);
					formData.append(0, file);

					xhr.open("POST", lychee.api_path);

					xhr.onload = function() {

						var wait = false;

						file.ready = true;

						// Set status
						if (xhr.status===200&&xhr.responseText==="1") {

							// Success
							$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") .status")
								.html("Finished")
								.addClass("success");

						} else {

							// Error
							$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") .status")
								.html("Error")
								.addClass("error");
							$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") p.notice")
								.html("Server returned the status code " + xhr.status)
								.show();

							// Throw error
							lychee.error("Upload failed. Server returned the status code " + xhr.status + "!", xhr, xhr.responseText);

						}

						// Check if there are file which are not finished
						for (var i = 0; i < files.length; i++) {

							if (files[i].ready===false) {
								wait = true;
								break;
							}

						}

						// Finish upload when all files are finished
						if (wait===false) finish();

					};

					xhr.upload.onprogress = function(e) {

						if (e.lengthComputable) {

							// Calculate progress
							progress = (e.loaded / e.total * 100 | 0);

							// Set progress when progress has changed
							if (progress>pre_progress) {
								$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") .status").html(progress + "%");
								pre_progress = progress;
							}

							if (progress>=100) {

								// Scroll to the uploading file
								var scrollPos = 0;
								if ((file.num+1)>4) scrollPos = (file.num + 1 - 4) * 40
								$(".upload_message .rows").scrollTop(scrollPos);

								// Set status to processing
								$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") .status").html("Processing");

								// Upload next file
								if (file.next!==null) process(files, file.next);

							}

						}

					};

					xhr.send(formData);

				};

			if (files.length<=0) return false;
			if (albumID===false||visible.albums()===true) albumID = 0;

			for (var i = 0; i < files.length; i++) {

				files[i].num = i;
				files[i].ready = false;
				files[i].supported = true;

				if (i < files.length-1) files[i].next = files[i+1];
				else files[i].next = null;

				// Check if file is supported
				if (files[i].type!=="image/jpeg"&&files[i].type!=="image/jpg"&&files[i].type!=="image/png"&&files[i].type!=="image/gif") {

					files[i].ready = true;
					files[i].supported = false;

				}

			}

			window.onbeforeunload = function() { return "Lychee is currently uploading!"; };

			upload.show("Uploading", files);

			// Upload first file
			process(files, files[0]);

		},

		url: function() {

			var albumID = album.getID(),
				params,
				extension,
				buttons,
				link,
				files = [];

			if (albumID===false) albumID = 0;

			buttons = [
				["Import", function() {

					link = $(".message input.text").val();

					if (link&&link.length>3) {

						extension = link.split('.').pop();
						if (extension!=="jpeg"&&extension!=="jpg"&&extension!=="png"&&extension!=="gif"&&extension!=="webp") {
							loadingBar.show("error", "The file format of this link is not supported.");
							return false;
						}

						files[0] = {
							name: link,
							supported: true
						}

						upload.show("Importing URL", files, function() {
							$(".upload_message .rows .row .status").html("Importing");
						});

						params = "importUrl&url=" + escape(encodeURI(link)) + "&albumID=" + albumID;
						lychee.api(params, function(data) {

							upload.close();
							upload.notify("Import complete");

							if (album.getID()===false) lychee.goto("0");
							else album.load(albumID);

							if (data!==true) lychee.error(null, params, data);

						});

					} else loadingBar.show("error", "Link to short or too long. Please try another one!");

				}],
				["Cancel", function() {}]
			];

			modal.show("Import from Link", "Please enter the direct link to a photo to import it: <input class='text' type='text' placeholder='http://' value='http://'>", buttons);

		},

		server: function() {

			var albumID = album.getID(),
				params,
				buttons,
				files = [],
				path;

			if (albumID===false) albumID = 0;

			buttons = [
				["Import", function() {

					path = $(".message input.text").val();

					files[0] = {
						name: path,
						supported: true
					};

					upload.show("Importing from server", files, function() {
						$(".upload_message .rows .row .status").html("Importing");
					});

					params = "importServer&albumID=" + albumID + "&path=" + escape(encodeURI(path));
					lychee.api(params, function(data) {

						upload.close();
						upload.notify("Import complete");

						if (data==="Notice: Import only contains albums!") {
							if (visible.albums()) lychee.load();
							else lychee.goto("");
						}
						else if (album.getID()===false) lychee.goto("0");
						else album.load(albumID);

						if (data==="Notice: Import only contains albums!") return true;
						else if (data==="Warning: Folder empty!") lychee.error("Folder empty. No photos imported!", params, data);
						else if (data!==true) lychee.error(null, params, data);

					});

				}],
				["Cancel", function() {}]
			];

			modal.show("Import from Server", "This action will import all photos, folders and sub-folders which are located in the following directory. The original files will be deleted after the import when possible. <input class='text' type='text' maxlength='100' placeholder='Absolute path to directory' value='" + lychee.location + "uploads/import/'>", buttons);

		},

		dropbox: function() {

			var albumID = album.getID(),
				params,
				links = "";

			if (albumID===false) albumID = 0;

			lychee.loadDropbox(function() {
				Dropbox.choose({
					linkType: "direct",
					multiselect: true,
					success: function(files) {

						for (var i = 0; i < files.length; i++) {

							links += files[i].link + ",";

							files[i] = {
								name: files[i].link,
								supported: true
							};

						}

						// Remove last comma
						links = links.substr(0, links.length-1);

						upload.show("Importing from Dropbox", files, function() {
							$(".upload_message .rows .row .status").html("Importing");
						});

						params = "importUrl&url=" + escape(links) + "&albumID=" + albumID;
						lychee.api(params, function(data) {

							upload.close();
							upload.notify("Import complete");

							if (album.getID()===false) lychee.goto("0");
							else album.load(albumID);

							if (data!==true) lychee.error(null, params, data);

						});

					}
				});
			});

		}

	},

	close: function(force) {

		if (force===true) {
			$(".upload_overlay").remove();
		} else {
			upload.setProgress(100);
			$(".upload_overlay").removeClass("fadeIn").css("opacity", 0);
			setTimeout(function() { $(".upload_overlay").remove() }, 300);
		}

	}

};<commit_msg>Don't close upload when an error occurred #203<commit_after>/**
 * @name		Album Module
 * @description	Takes care of every action an album can handle and execute.
 * @author		Tobias Reich
 * @copyright	2014 by Tobias Reich
 */

upload = {

	show: function(title, files, callback) {

		upload.close(true);
		$("body").append(build.uploadModal(title, files));

		if (callback!=null&&callback!=undefined) callback();

	},

	setIcon: function(icon) {

		$(".upload_message a").remove();
		$(".upload_message").prepend("");

	},

	setProgress: function(progress) {

		$(".progressbar div").css("width", progress + "%");

	},

	setText: function(text) {

		$(".progressbar").remove();
		$(".upload_message").append("
" + text + "
");

	},

	notify: function(title, text) {

		var popup;

		if (!text||text==="") text = "You can now manage your new photo(s).";

		if (!window.webkitNotifications) return false;

		if (window.webkitNotifications.checkPermission()!==0) window.webkitNotifications.requestPermission();

		if (window.webkitNotifications.checkPermission()===0&&title) {
			popup = window.webkitNotifications.createNotification("", title, text);
			popup.show();
		}

	},

	start: {

		local: function(files) {

			var albumID = album.getID(),
				error = false,
				process = function(files, file) {

					var formData = new FormData(),
						xhr = new XMLHttpRequest(),
						pre_progress = 0,
						progress,
						finish = function() {

							window.onbeforeunload = null;

							$("#upload_files").val("");

							if (error===false) {

								// Success
								upload.close();
								upload.notify("Upload complete");

							} else {

								// Error
								$(".upload_message a.close").show();
								upload.notify("Upload complete", "Failed to upload one or more photos.");

							}

							if (album.getID()===false) lychee.goto("0");
							else album.load(albumID);

						};

					// Check if file is supported
					if (file.supported===false) {

						// Skip file
						if (file.next!==null) process(files, file.next);
						else {

							// Look for supported files
							// If zero files are supported, hide the upload after a delay

							var hasSupportedFiles = false;

							for (var i = 0; i < files.length; i++) {

								if (files[i].supported===true) {
									hasSupportedFiles = true;
									break;
								}

							}

							if (hasSupportedFiles===false) setTimeout(finish, 2000);

						}

						return false;

					}

					formData.append("function", "upload");
					formData.append("albumID", albumID);
					formData.append(0, file);

					xhr.open("POST", lychee.api_path);

					xhr.onload = function() {

						var wait = false;

						file.ready = true;

						// Set status
						if (xhr.status===200&&xhr.responseText==="1") {

							// Success
							$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") .status")
								.html("Finished")
								.addClass("success");

						} else {

							// Error
							$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") .status")
								.html("Error")
								.addClass("error");
							$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") p.notice")
								.html("Server returned the status code " + xhr.status)
								.show();

							// Set global error
							error = true;

							// Throw error
							lychee.error("Upload failed. Server returned the status code " + xhr.status + "!", xhr, xhr.responseText);

						}

						// Check if there are file which are not finished
						for (var i = 0; i < files.length; i++) {

							if (files[i].ready===false) {
								wait = true;
								break;
							}

						}

						// Finish upload when all files are finished
						if (wait===false) finish();

					};

					xhr.upload.onprogress = function(e) {

						if (e.lengthComputable) {

							// Calculate progress
							progress = (e.loaded / e.total * 100 | 0);

							// Set progress when progress has changed
							if (progress>pre_progress) {
								$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") .status").html(progress + "%");
								pre_progress = progress;
							}

							if (progress>=100) {

								// Scroll to the uploading file
								var scrollPos = 0;
								if ((file.num+1)>4) scrollPos = (file.num + 1 - 4) * 40
								$(".upload_message .rows").scrollTop(scrollPos);

								// Set status to processing
								$(".upload_message .rows .row:nth-child(" + (file.num+1) + ") .status").html("Processing");

								// Upload next file
								if (file.next!==null) process(files, file.next);

							}

						}

					};

					xhr.send(formData);

				};

			if (files.length<=0) return false;
			if (albumID===false||visible.albums()===true) albumID = 0;

			for (var i = 0; i < files.length; i++) {

				files[i].num = i;
				files[i].ready = false;
				files[i].supported = true;

				if (i < files.length-1) files[i].next = files[i+1];
				else files[i].next = null;

				// Check if file is supported
				if (files[i].type!=="image/jpeg"&&files[i].type!=="image/jpg"&&files[i].type!=="image/png"&&files[i].type!=="image/gif") {

					files[i].ready = true;
					files[i].supported = false;

				}

			}

			window.onbeforeunload = function() { return "Lychee is currently uploading!"; };

			upload.show("Uploading", files);

			// Upload first file
			process(files, files[0]);

		},

		url: function() {

			var albumID = album.getID(),
				params,
				extension,
				buttons,
				link,
				files = [];

			if (albumID===false) albumID = 0;

			buttons = [
				["Import", function() {

					link = $(".message input.text").val();

					if (link&&link.length>3) {

						extension = link.split('.').pop();
						if (extension!=="jpeg"&&extension!=="jpg"&&extension!=="png"&&extension!=="gif"&&extension!=="webp") {
							loadingBar.show("error", "The file format of this link is not supported.");
							return false;
						}

						files[0] = {
							name: link,
							supported: true
						}

						upload.show("Importing URL", files, function() {
							$(".upload_message .rows .row .status").html("Importing");
						});

						params = "importUrl&url=" + escape(encodeURI(link)) + "&albumID=" + albumID;
						lychee.api(params, function(data) {

							upload.close();
							upload.notify("Import complete");

							if (album.getID()===false) lychee.goto("0");
							else album.load(albumID);

							if (data!==true) lychee.error(null, params, data);

						});

					} else loadingBar.show("error", "Link to short or too long. Please try another one!");

				}],
				["Cancel", function() {}]
			];

			modal.show("Import from Link", "Please enter the direct link to a photo to import it: <input class='text' type='text' placeholder='http://' value='http://'>", buttons);

		},

		server: function() {

			var albumID = album.getID(),
				params,
				buttons,
				files = [],
				path;

			if (albumID===false) albumID = 0;

			buttons = [
				["Import", function() {

					path = $(".message input.text").val();

					files[0] = {
						name: path,
						supported: true
					};

					upload.show("Importing from server", files, function() {
						$(".upload_message .rows .row .status").html("Importing");
					});

					params = "importServer&albumID=" + albumID + "&path=" + escape(encodeURI(path));
					lychee.api(params, function(data) {

						upload.close();
						upload.notify("Import complete");

						if (data==="Notice: Import only contains albums!") {
							if (visible.albums()) lychee.load();
							else lychee.goto("");
						}
						else if (album.getID()===false) lychee.goto("0");
						else album.load(albumID);

						if (data==="Notice: Import only contains albums!") return true;
						else if (data==="Warning: Folder empty!") lychee.error("Folder empty. No photos imported!", params, data);
						else if (data!==true) lychee.error(null, params, data);

					});

				}],
				["Cancel", function() {}]
			];

			modal.show("Import from Server", "This action will import all photos, folders and sub-folders which are located in the following directory. The original files will be deleted after the import when possible. <input class='text' type='text' maxlength='100' placeholder='Absolute path to directory' value='" + lychee.location + "uploads/import/'>", buttons);

		},

		dropbox: function() {

			var albumID = album.getID(),
				params,
				links = "";

			if (albumID===false) albumID = 0;

			lychee.loadDropbox(function() {
				Dropbox.choose({
					linkType: "direct",
					multiselect: true,
					success: function(files) {

						for (var i = 0; i < files.length; i++) {

							links += files[i].link + ",";

							files[i] = {
								name: files[i].link,
								supported: true
							};

						}

						// Remove last comma
						links = links.substr(0, links.length-1);

						upload.show("Importing from Dropbox", files, function() {
							$(".upload_message .rows .row .status").html("Importing");
						});

						params = "importUrl&url=" + escape(links) + "&albumID=" + albumID;
						lychee.api(params, function(data) {

							upload.close();
							upload.notify("Import complete");

							if (album.getID()===false) lychee.goto("0");
							else album.load(albumID);

							if (data!==true) lychee.error(null, params, data);

						});

					}
				});
			});

		}

	},

	close: function(force) {

		if (force===true) {
			$(".upload_overlay").remove();
		} else {
			upload.setProgress(100);
			$(".upload_overlay").removeClass("fadeIn").css("opacity", 0);
			setTimeout(function() { $(".upload_overlay").remove() }, 300);
		}

	}

};<|endoftext|>


<commit_before>
/**
 * MorphAnimation update function
 * 解决了开始播放时跳的问题
 */
THREE.MorphAnimation.prototype.update = ( function () {
	var lastFrame = 0;
	var currentFrame = 0;

	return function ( delta ) {
		if ( this.isPlaying === false ) return;
		this.currentTime += delta;
		if ( this.loop === true && this.currentTime > this.duration ) {
			this.currentTime %= this.duration;
		}
		this.currentTime = Math.min( this.currentTime, this.duration );
		var interpolation = this.duration / this.frames;
		var frame = Math.floor( this.currentTime / interpolation );

		if ( frame != currentFrame ) {
			this.mesh.morphTargetInfluences[ lastFrame ] = 0;
			this.mesh.morphTargetInfluences[ currentFrame ] = 1;
			this.mesh.morphTargetInfluences[ frame ] = 0;

			lastFrame = currentFrame;
			currentFrame = frame;
		}

		this.mesh.morphTargetInfluences[ frame ] = ( this.currentTime % interpolation ) / interpolation;
		if (lastFrame != frame) {
			this.mesh.morphTargetInfluences[ lastFrame ] = 1 - this.mesh.morphTargetInfluences[ frame ];
		}
	}
} )();

/**
 * SEAD.AnimationHandler
 */
SEA3D.AnimationHandler.prototype.updateAnimation = function(stateName) {
	var dataCount = this.animationSet.dataCount;
	var nodes = this.animationSet.animations;

	// easyfrog modify
	var currentNode = stateName == undefined ? this.currentState.node : this.getStateByName(stateName).node;

	for(var i = 0; i < dataCount; i++) {
		for(var n = 0; n < nodes.length; n++) {
			var node = nodes[n],
				state = this.states[n],
				data = node.dataList[i],
				iFunc = SEA3D.Animation.DefaultLerpFuncs[data.kind],
				frame;

			if (n == 0) {
				frame = currentNode.getInterpolationFrame(currentNode.dataList[i], iFunc);

				// make sure invoke one time
				var _fr = this.timeScale >= 0 ? Math.floor(currentNode.frame) : Math.ceil(currentNode.frame);
				if (_fr != this._lastFrame) {
					this._lastFrame =_fr;
					var _frame = _fr + '';

					// keyframe event
					if (this.keyframeEvents) {
						if (this.keyframeEvents[_frame]) {
							this.keyframeEvents[_frame]();
						}
					}

					if (!currentNode.repeat &&
						((this.timeScale > 0 && currentNode.frame == currentNode.numFrames - 1) ||
						(this.timeScale < 0 && currentNode.frame == 0))) {
						if (this.onComplete)
							this.onComplete( this );

						// !repeat pause
						this.pause();
					}
				}
			}

			if (node != currentNode) {
				if (state.weight > 0)
				{
					iFunc(
						frame.data,
						node.getInterpolationFrame(data, iFunc).data,
						state.weight
					);
				}
			}

			if (this.updateAnimationFrame)
				this.updateAnimationFrame(frame, data.kind);

		}
	}
}

<commit_msg>fix SEA3D.AnimationHandler.updte error bug in threeExtend.js.<commit_after>
/**
 * MorphAnimation update function
 * 解决了开始播放时跳的问题
 */
THREE.MorphAnimation.prototype.update = ( function () {
	var lastFrame = 0;
	var currentFrame = 0;

	return function ( delta ) {
		if ( this.isPlaying === false ) return;
		this.currentTime += delta;
		if ( this.loop === true && this.currentTime > this.duration ) {
			this.currentTime %= this.duration;
		}
		this.currentTime = Math.min( this.currentTime, this.duration );
		var interpolation = this.duration / this.frames;
		var frame = Math.floor( this.currentTime / interpolation );

		if ( frame != currentFrame ) {
			this.mesh.morphTargetInfluences[ lastFrame ] = 0;
			this.mesh.morphTargetInfluences[ currentFrame ] = 1;
			this.mesh.morphTargetInfluences[ frame ] = 0;

			lastFrame = currentFrame;
			currentFrame = frame;
		}

		this.mesh.morphTargetInfluences[ frame ] = ( this.currentTime % interpolation ) / interpolation;
		if (lastFrame != frame) {
			this.mesh.morphTargetInfluences[ lastFrame ] = 1 - this.mesh.morphTargetInfluences[ frame ];
		}
	}
} )();

/**
 * SEAD.AnimationHandler
 */
SEA3D.AnimationHandler.prototype.updateAnimation = function(stateName) {
	var dataCount = this.animationSet.dataCount;
	var nodes = this.animationSet.animations;

	// easyfrog modify
	var currentNode = stateName == undefined ? this.currentState.node : this.getStateByName(stateName).node;

	for(var i = 0; i < dataCount; i++) {
		for(var n = 0; n < nodes.length; n++) {
			var node = nodes[n],
				state = this.states[n],
				data = node.dataList[i],
				iFunc = SEA3D.Animation.DefaultLerpFuncs[data.kind],
				frame;

			if (n == 0) {
				frame = currentNode.getInterpolationFrame(currentNode.dataList[i], iFunc);

				// make sure invoke one time
				var _fr = this.timeScale >= 0 ? Math.floor(currentNode.frame) : Math.ceil(currentNode.frame);
				if (_fr != this._lastFrame) {
					this._lastFrame =_fr;
					var _frame = _fr + '';

					// keyframe event
					if (this.keyframeEvents) {
						if (this.keyframeEvents[_frame]) {
							this.keyframeEvents[_frame]();
						}
					}

					if (!currentNode.repeat &&
						((this.timeScale > 0 && currentNode.frame == currentNode.numFrames - 1) ||
						(this.timeScale < 0 && currentNode.frame == 0))) {
						if (this.onComplete)
							this.onComplete( this );

						// !repeat pause
						this.pause();
					}
				}
			}

			if (node != currentNode) {
				if (state.weight > 0)
				{
					iFunc(
						frame.data,
						node.getInterpolationFrame(data, iFunc).data,
						state.weight
					);
				}
			}

			if (this.updateAnimationFrame)
				this.updateAnimationFrame(frame, data.kind);

		}
	}
}

SEA3D.AnimationHandler.update = function( delta ) {
	for(var i = 0, len = SEA3D.AnimationHandler.animations.length; i < len; i++) {
		if (SEA3D.AnimationHandler.animations[i]) {
			SEA3D.AnimationHandler.animations[i].update( delta * 1000 );
		}
	}
}

<|endoftext|>


<commit_before>var meta = <><![CDATA[
// ==UserScript==
// @name           google music scrobbler
// @namespace      http://gmscrobber.whosemind.net
// @description    记录 google music beta 到 last.fm
// @include        http://music.google.com/music/listen*
// @include        https://music.google.com/music/listen*
// @require        https://raw.github.com/justan/gmscrobber/master/simple_scrobbler_user.js
// @version        0.1.1
// @uso:script     111546
// @initiative     false
// @changelog      love 同步
// ==/UserScript==
]]></>.toString();

meta = uso.metaParse(meta);

(function(){
var plug = <><![CDATA[
(function(){
  var XHR = XMLHttpRequest.prototype, _open = XHR.open, _send = XHR.send;
  XHR.open = function(){
    this.__type__ = arguments[0];
    this.__url__ = arguments[1];
    return _open.apply(this, arguments);
  };
  XHR.send = function(){
    this.__data__ = arguments[0];
    send(this);
    return _send.apply(this, arguments);
  };

  var list = {}, send = function(xhr){
    var path = xhr.__url__.replace(/\?.+/, '');
    if(list[path]){
      list[path].forEach(function(fn){
        fn.apply(null, [xhr.__url__, xhr.__data__]);
      });
    }
  };
  window['whosemind'] = {
    list: list,
  };
})()
]]></>.toString(), script = document.createElement('script');
script.innerHTML = plug;
document.body.appendChild(script);
})();

(function(){
var sc, gm = function(){
		var $statele, $timele, $artistele, $albumart,

    $flag,

		_clickHandler = function(){},
		likeHandler = function(){_clickHandler()},
		listener = function(){
			var info, len;

      $statele.addEventListener('click', function(){
        if(this.title == 'Play'){
          player.pause();
        }else{
          player.play();
        }
      }, false);

			setInterval(function(){
				info = getInfo();
				//log(JSON.stringify(info));
				len = player.history.length;
				if(len > 10){
					player.history.length = len;
				}

				if(len === 0 && info.title){
					log(info.title + " is the first song");
					player.newsong(info);
				}else if(len > 0 && !info.title && player.track){
					player.stop();
					player.track = null;
				}else if(len > 0 && info.title &&
					(player.history[0].title != info.title || player.history[0].artist != info.artist)){
					player.newsong(info);
				}else if(player.track){
					if($statele.title == "Play" && len && player.state != "pause"){//显示中的播放按钮
						player.pause();
					}else if($statele.title != "Play" && (player.playtime - player.lastplaytime) === 0){//不可信的定时器执行间隔
						player.buffer();
					}else if($statele.title != "Play" && player.playtime < player.lastplaytime && player.state != "seek"){//单曲循环
						player.newsong(info);
					}else if($statele.title != "Play" && player.state != "play"){
						player.play();
					}
				}
			}, 2000);
		},
		getInfo = function(){
			var fn = function(){
				return {title: fn.getTitle(),
					artist: fn.getArtist(),
					playtime: fn.getPlayTime(),
          album: fn.getAlbum(),
					duration: fn.getTotalTime()};
			};
			fn.getTitle = function(){
				return document.getElementById("playerSongTitle").firstChild.title;
			};
			fn.getArtist = function(){
				var artist = document.getElementById("playerArtist").firstChild.title;
				return artist;
			};
			fn.getTotalTime = function(){
				var ta = $timele.lastChild.innerHTML.split(":");
				return ta[0]*60 + ta[1]*1;
			};
			fn.getPlayTime = function(){
				var ta = $timele.firstChild.innerHTML.split(":");
				player.lastplaytime = player.playtime;
				player.playtime = ta[0]*60 + ta[1]*1;
				return player.playtime;
			};
      fn.getAlbum = function(){
        return $flag.parentNode.parentNode.nextSibling.nextSibling.nextSibling.firstChild.title
      };
			return fn;
		}(),
		checkFav = function(song){
      sc.getInfo(song, function(info){
        document.getElementById('playerSongInfo').title = '在 last.fm 中已记录: ' + info.len + '次';
      });
    },
    player = {
			state: "",
			history: [],
			lastplaytime: 0,
			playtime: 0,
			offset: 0,//实际播放时间与显示的播放时间差值
			track: null,
			newsong: function(song){
				sc.nowPlaying(song);
				this.history.unshift(song);
				this.track = {};
				this.state = "play";
				this.offset = 0;
				this.lastplaytime = 0;
				this.playtime = 0;
				checkFav(song);
			},
			seek: function(){
				this.state = "seek";
				log("seek");
				getInfo.getPlayTime();
				this.offset += (this.lastplaytime - this.playtime);
				log("realplaytime/offset: " + (this.playtime + this.offset) + " / " + this.offset);
			},
			pause: function(){
        log('pause...');
				sc.pause();
				this.state = "pause";
			},
			play: function(){
				var rpt;//real play time
				rpt = this.playtime + this.offset;
				log("play, now play time info, playtime: " + this.playtime + " / offset: " + this.offset);
				sc.play(rpt);
				this.state = "play";
			},
			buffer: function(){
        log('buffer..');
				sc.pause();
				this.state = "buffer";
			},
			stop: function(){
				log("stop");
				this.state = "stop";
				sc.stop();
			}
		};

		(function _init(){
      $flag = document.getElementById('song_indicator');
      $albumart = document.getElementById('playingAlbumArt');
			if($albumart && $flag){
        $timele = document.getElementById("time_container");
				document.getElementById("slider").addEventListener("click", function(){player.seek()}, false);
        $statele = document.getElementById("playPause");//播放按钮

        listener();
			}else{
        log('nothing play');
				setTimeout(function(){_init()}, 2000);
			}
		})();

    bindSend(function(url, data){
      var d = decodeURIComponent(data.replace(/json=/, '')),
        info = JSON.parse(d), entries = info.entries, rate, song = {}, _ele;
      if(entries.length == 1 && !entries[0].creationDate){//rate
        log(d);
        rate = entries[0].rating;
        id = entries[0].id;
        _ele = document.getElementById('songs-all_' + id);
        song.title = _ele.children[0].firstChild.title;
        song.artist = _ele.children[2].firstChild.title;
        setTimeout(function(){
          switch(rate){
          case 0:
          case 1:
            sc.unlove(song);
            break;
          case 5:
            sc.love(song);
            break;
          }
        }, 0);
      }
    }, 'services/modifyentries');
	},
  bindSend = function(fn, path){
    var list = unsafeWindow.whosemind.list;
    list[path] = list[path] || [];
    list[path].push(fn);
  };

	uso.check(meta.version, meta.uso.script);
  unsafeWindow.addEventListener('DOMContentLoaded', function(){
    sc = new Scrobbler({name: "google music", ready: gm})
  }, false);
})();<commit_msg>match play.google.com/music<commit_after>var meta = <><![CDATA[
// ==UserScript==
// @name           google music scrobbler
// @namespace      http://gmscrobber.whosemind.net
// @description    记录 google music beta 到 last.fm
// @include        http://play.google.com/music/listen*
// @include        https://play.google.com/music/listen*
// @require        https://raw.github.com/justan/gmscrobber/master/simple_scrobbler_user.js
// @version        0.1.1
// @uso:script     111546
// @initiative     false
// @changelog      love 同步
// ==/UserScript==
]]></>.toString();

meta = uso.metaParse(meta);

(function(){
var plug = <><![CDATA[
(function(){
  var XHR = XMLHttpRequest.prototype, _open = XHR.open, _send = XHR.send;
  XHR.open = function(){
    this.__type__ = arguments[0];
    this.__url__ = arguments[1];
    return _open.apply(this, arguments);
  };
  XHR.send = function(){
    this.__data__ = arguments[0];
    send(this);
    return _send.apply(this, arguments);
  };

  var list = {}, send = function(xhr){
    var path = xhr.__url__.replace(/\?.+/, '');
    if(list[path]){
      list[path].forEach(function(fn){
        fn.apply(null, [xhr.__url__, xhr.__data__]);
      });
    }
  };
  window['whosemind'] = {
    list: list,
  };
})()
]]></>.toString(), script = document.createElement('script');
script.innerHTML = plug;
document.body.appendChild(script);
})();

(function(){
var sc, gm = function(){
		var $statele, $timele, $artistele, $albumart,

    $flag,

		_clickHandler = function(){},
		likeHandler = function(){_clickHandler()},
		listener = function(){
			var info, len;

      $statele.addEventListener('click', function(){
        if(this.title == 'Play'){
          player.pause();
        }else{
          player.play();
        }
      }, false);

			setInterval(function(){
				info = getInfo();
				//log(JSON.stringify(info));
				len = player.history.length;
				if(len > 10){
					player.history.length = len;
				}

				if(len === 0 && info.title){
					log(info.title + " is the first song");
					player.newsong(info);
				}else if(len > 0 && !info.title && player.track){
					player.stop();
					player.track = null;
				}else if(len > 0 && info.title &&
					(player.history[0].title != info.title || player.history[0].artist != info.artist)){
					player.newsong(info);
				}else if(player.track){
					if($statele.title == "Play" && len && player.state != "pause"){//显示中的播放按钮
						player.pause();
					}else if($statele.title != "Play" && (player.playtime - player.lastplaytime) === 0){//不可信的定时器执行间隔
						player.buffer();
					}else if($statele.title != "Play" && player.playtime < player.lastplaytime && player.state != "seek"){//单曲循环
						player.newsong(info);
					}else if($statele.title != "Play" && player.state != "play"){
						player.play();
					}
				}
			}, 2000);
		},
		getInfo = function(){
			var fn = function(){
				return {title: fn.getTitle(),
					artist: fn.getArtist(),
					playtime: fn.getPlayTime(),
          album: fn.getAlbum(),
					duration: fn.getTotalTime()};
			};
			fn.getTitle = function(){
				return document.getElementById("playerSongTitle").firstChild.title;
			};
			fn.getArtist = function(){
				var artist = document.getElementById("playerArtist").firstChild.title;
				return artist;
			};
			fn.getTotalTime = function(){
				var ta = $timele.lastChild.innerHTML.split(":");
				return ta[0]*60 + ta[1]*1;
			};
			fn.getPlayTime = function(){
				var ta = $timele.firstChild.innerHTML.split(":");
				player.lastplaytime = player.playtime;
				player.playtime = ta[0]*60 + ta[1]*1;
				return player.playtime;
			};
      fn.getAlbum = function(){
        return $flag.parentNode.parentNode.nextSibling.nextSibling.nextSibling.firstChild.title
      };
			return fn;
		}(),
		checkFav = function(song){
      sc.getInfo(song, function(info){
        document.getElementById('playerSongInfo').title = '在 last.fm 中已记录: ' + info.len + '次';
      });
    },
    player = {
			state: "",
			history: [],
			lastplaytime: 0,
			playtime: 0,
			offset: 0,//实际播放时间与显示的播放时间差值
			track: null,
			newsong: function(song){
				sc.nowPlaying(song);
				this.history.unshift(song);
				this.track = {};
				this.state = "play";
				this.offset = 0;
				this.lastplaytime = 0;
				this.playtime = 0;
				checkFav(song);
			},
			seek: function(){
				this.state = "seek";
				log("seek");
				getInfo.getPlayTime();
				this.offset += (this.lastplaytime - this.playtime);
				log("realplaytime/offset: " + (this.playtime + this.offset) + " / " + this.offset);
			},
			pause: function(){
        log('pause...');
				sc.pause();
				this.state = "pause";
			},
			play: function(){
				var rpt;//real play time
				rpt = this.playtime + this.offset;
				log("play, now play time info, playtime: " + this.playtime + " / offset: " + this.offset);
				sc.play(rpt);
				this.state = "play";
			},
			buffer: function(){
        log('buffer..');
				sc.pause();
				this.state = "buffer";
			},
			stop: function(){
				log("stop");
				this.state = "stop";
				sc.stop();
			}
		};

		(function _init(){
      $flag = document.getElementById('song_indicator');
      $albumart = document.getElementById('playingAlbumArt');
			if($albumart && $flag){
        $timele = document.getElementById("time_container");
				document.getElementById("slider").addEventListener("click", function(){player.seek()}, false);
        $statele = document.getElementById("playPause");//播放按钮

        listener();
			}else{
        //log('nothing play');
				setTimeout(function(){_init()}, 2000);
			}
		})();

    bindSend(function(url, data){
      var d = decodeURIComponent(data.replace(/json=/, '')),
        info = JSON.parse(d), entries = info.entries, rate, song = {}, _ele;
      if(entries.length == 1 && !entries[0].creationDate){//rate
        log(d);
        rate = entries[0].rating;
        id = entries[0].id;
        _ele = document.getElementById('songs-all_' + id);
        song.title = _ele.children[0].firstChild.title;
        song.artist = _ele.children[2].firstChild.title;
        setTimeout(function(){
          switch(rate){
          case 0:
          case 1:
            sc.unlove(song);
            break;
          case 5:
            sc.love(song);
            break;
          }
        }, 0);
      }
    }, 'services/modifyentries');
	},
  bindSend = function(fn, path){
    var list = unsafeWindow.whosemind.list;
    list[path] = list[path] || [];
    list[path].push(fn);
  };

	uso.check(meta.version, meta.uso.script);
  unsafeWindow.addEventListener('DOMContentLoaded', function(){
    sc = new Scrobbler({name: "google music", ready: gm})
  }, false);
})();<|endoftext|>


<commit_before>document.addEventListener('contextmenu', function (e) {
  var ws = null;
  var el = e.target;

  while (ws == null && el && el.getAttribute) {
    ws = el.getAttribute("wicketsource");
    el = el.parentNode;
  }
  chrome.extension.sendRequest({
    wicketsource: ws
  });
});
<commit_msg>Use mousedown event<commit_after>document.addEventListener('mousedown', function (e) {
  var ws = null;
  var el = e.target;

  while (ws == null && el && el.getAttribute) {
    ws = el.getAttribute("wicketsource");
    el = el.parentNode;
  }
  chrome.extension.sendRequest({
    wicketsource: ws
  });
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { withLang } from 'olymp-utils';
import { FaExpand, FaCode } from 'olymp-icons';
import { createReplaceQuery } from 'olymp-router';
import { Menu, Drawer } from 'olymp-fela';
import { compose, withState, withHandlers, withPropsOnChange } from 'recompose';
import { sortBy } from 'lodash';
import { connect } from 'react-redux';
import getSchema from './get-schema';

const enhance = compose(
  withState('collapsed', 'setCollapsed', true),
  withHandlers({
    expand: ({ setCollapsed }) => () => setCollapsed(false),
    collapse: ({ setCollapsed }) => () => setCollapsed(true),
  }),
);

const dragStart = type => ev => {
  ev.dataTransfer.setData('text', `x-slate:${type}`);
};

const getIcon = key => {
  if (key === 'Bilder') {
    return 'picture';
  }
  if (key === 'Daten') {
    return 'database';
  }
  if (key === 'Kacheln') {
    return 'appstore-o';
  }
  if (key === 'Kopf') {
    return 'to-top';
  }
  if (key === 'Layout') {
    return 'file';
  }
  if (key === 'Sonstiges') {
    return 'ellipsis';
  }
  return 'plus';
};

@withLang
@connect(
  ({ location }) => ({
    pathname: location.pathname,
    query: location.query,
  }),
  dispatch => ({
    setQuery: createReplaceQuery(dispatch),
  }),
)
@enhance
@withState('collapsed', 'setCollapsed', true)
@getSchema
@withPropsOnChange(['schema'], ({ schema = {} }) => {
  const types = Object.keys(schema.nodes || {}).map(key => ({
    ...schema.nodes[key].slate,
    type: key,
  }));
  const categories = {};
  const menuItems = [];
  sortBy(types, ['category', 'label']).forEach(action => {
    const item = (
      <Menu.Item
        key={action.type}
        draggable
        onClick={() => null}
        onDragStart={dragStart(action.type)}
        // icon={<Icon type={getIcon(action.category)} />}
      >
        {action.label || action.type}
      </Menu.Item>
    );
    if (action.category) {
      if (!categories[action.category]) {
        categories[action.category] = [];
      }
      categories[action.category].push(item);
    } else {
      menuItems.push(item);
    }
  });
  return {
    items: [
      ...Object.keys(categories).map(key => (
        <Menu.List key={key} title={key}>
          {categories[key]}
        </Menu.List>
      )),
    ],
  };
})
class Navigation extends Component {
  render() {
    const {
      query,
      collapsed,
      setCollapsed,
      full,
      setFull,
      setCode,
      code,
      items,
      children,
    } = this.props;
    const keys = Object.keys(query);

    if (!keys.filter(x => x[0] === '@').length) {
      keys.push('@home');
    }

    return (
      <Drawer
        open
        collapsed={collapsed}
        dim={false}
        right
        width={collapsed ? 72 : 240}
      >
        <Menu
          collapsed={collapsed}
          inverted
          color="colorSecondary"
          onMouseEnter={() => setCollapsed(false)}
          onMouseLeave={() => setCollapsed(true)}
        >
          {children}
          <Menu.List title="Ansicht">
            <Menu.Item
              active={full}
              onClick={() => setFull(!full)}
              icon={<FaExpand />}
            >
              Vollbild
            </Menu.Item>
            <Menu.Item
              active={code}
              onClick={() => setCode(!code)}
              icon={<FaCode />}
            >
              Code anzeigen
            </Menu.Item>
          </Menu.List>
          {items}
          <Menu.Space />
        </Menu>
      </Drawer>
    );
  }
}
export default Navigation;
<commit_msg>small cleanup<commit_after>import React, { Component } from 'react';
import { withLang } from 'olymp-utils';
import { FaExpand, FaCode } from 'olymp-icons';
import { createReplaceQuery } from 'olymp-router';
import { Menu, Drawer } from 'olymp-fela';
import { compose, withState, withHandlers, withPropsOnChange } from 'recompose';
import { sortBy } from 'lodash';
import { connect } from 'react-redux';
import getSchema from './get-schema';

const enhance = compose(
  withState('collapsed', 'setCollapsed', true),
  withHandlers({
    expand: ({ setCollapsed }) => () => setCollapsed(false),
    collapse: ({ setCollapsed }) => () => setCollapsed(true),
  }),
);

const dragStart = type => ev => {
  ev.dataTransfer.setData('text', `x-slate:${type}`);
};

@withLang
@connect(
  ({ location }) => ({
    pathname: location.pathname,
    query: location.query,
  }),
  dispatch => ({
    setQuery: createReplaceQuery(dispatch),
  }),
)
@enhance
@withState('collapsed', 'setCollapsed', true)
@getSchema
@withPropsOnChange(['schema'], ({ schema = {} }) => {
  const types = Object.keys(schema.nodes || {}).map(key => ({
    ...schema.nodes[key].slate,
    type: key,
  }));
  const categories = {};
  const menuItems = [];
  sortBy(types, ['category', 'label']).forEach(action => {
    const item = (
      <Menu.Item
        key={action.type}
        draggable
        onClick={() => null}
        onDragStart={dragStart(action.type)}
        // icon={<Icon type={getIcon(action.category)} />}
      >
        {action.label || action.type}
      </Menu.Item>
    );
    if (action.category) {
      if (!categories[action.category]) {
        categories[action.category] = [];
      }
      categories[action.category].push(item);
    } else {
      menuItems.push(item);
    }
  });
  return {
    items: [
      ...Object.keys(categories).map(key => (
        <Menu.List key={key} title={key}>
          {categories[key]}
        </Menu.List>
      )),
    ],
  };
})
class Navigation extends Component {
  render() {
    const {
      query,
      collapsed,
      setCollapsed,
      full,
      setFull,
      setCode,
      code,
      items,
      children,
    } = this.props;
    const keys = Object.keys(query);

    if (!keys.filter(x => x[0] === '@').length) {
      keys.push('@home');
    }

    return (
      <Drawer
        open
        collapsed={collapsed}
        dim={false}
        right
        width={collapsed ? 72 : 240}
      >
        <Menu
          collapsed={collapsed}
          inverted
          color="colorSecondary"
          onMouseEnter={() => setCollapsed(false)}
          onMouseLeave={() => setCollapsed(true)}
        >
          {children}
          <Menu.List title="Ansicht">
            <Menu.Item
              active={full}
              onClick={() => setFull(!full)}
              icon={<FaExpand />}
            >
              Vollbild
            </Menu.Item>
            <Menu.Item
              active={code}
              onClick={() => setCode(!code)}
              icon={<FaCode />}
            >
              Code anzeigen
            </Menu.Item>
          </Menu.List>
          {items}
          <Menu.Space />
        </Menu>
      </Drawer>
    );
  }
}
export default Navigation;
<|endoftext|>


<commit_before>(function () {

    angular
        .module('larakit')
        .component('adminlteContentWrapper', {
            templateUrl: '/packages/larakit/ng-adminlte/components/adminlte-content-wrapper/component.html',
            transclude: true,
            bindings: {
                breadcrumbs: '='
            },
            controller: Controller
        });

    Controller.$inject = ['$route'];

    function Controller($route) {

        var $ctrl = this;

        $ctrl.route = $route.current;
        if($ctrl.breadcrumbs.length){
            $ctrl.current_page = $ctrl.breadcrumbs[$ctrl.breadcrumbs.length-1];
        }
    }

})();<commit_msg>fixed<commit_after>(function () {

    angular
        .module('larakit')
        .component('adminlteContentWrapper', {
            templateUrl: '/packages/larakit/ng-adminlte/components/adminlte-content-wrapper/component.html',
            transclude: true,
            bindings: {
                breadcrumbs: '='
            },
            controller: Controller
        });

    Controller.$inject = ['$route'];

    function Controller($route) {

        var $ctrl = this;

        $ctrl.route = $route.current;
        if($ctrl.breadcrumbs && $ctrl.breadcrumbs.length){
            $ctrl.current_page = $ctrl.breadcrumbs[$ctrl.breadcrumbs.length-1];
        }
    }

})();<|endoftext|>


<commit_before>/*
 * mobile event unit tests
 */

(function($){
	var libName = "jquery.mobile.event.js",
			absFn = Math.abs,
			originalEventFn = $.Event.prototype.originalEvent,
			preventDefaultFn = $.Event.prototype.preventDefault,
			events = ("touchstart touchmove touchend orientationchange tap taphold " +
								"swipe swipeleft swiperight scrollstart scrollstop").split( " " );

	module(libName, {
		setup: function(){

			// ensure bindings are removed
			$.each(events, function(i, name){
				$.each([$("#qunit-fixture"),
					$($.event.special.scrollstart),
					$($.event.special.tap),
					$($.event.special.tap),
					$($.event.special.swipe)], function(j, obj){
						obj.unbind(name);
					});
			});

			//NOTE unmock
			Math.abs = absFn;
			$.Event.prototype.originalEvent = originalEventFn;
			$.Event.prototype.preventDefault = preventDefaultFn;
		}
	});

	$.testHelper.excludeFileProtocol(function(){
		test( "new events defined on the jquery object", function(){
			$.each(events, function( i, name ) {
				delete $.fn[name];
				same($.fn[name], undefined);
			});

			$.testHelper.reloadLib(libName);

			$.each($.fn.clone(events), function( i, name ) {
				ok($.fn[name] !== undefined, name + "is not undefined");
			});
		});
	});

	asyncTest( "defined event functions bind a closure when passed", function(){
		expect( 1 );

		$('#qunit-fixture').bind(events[0], function(){
			ok(true, "event fired");
			start();
		});

		$('#qunit-fixture').trigger(events[0]);
		stop();
	});

	asyncTest( "defined event functions trigger the event with no arguments", function(){
		expect( 1 );

		$('#qunit-fixture').bind('touchstart', function(){
			ok(true, "event fired");
			start();
		});

		$('#qunit-fixture').touchstart();
		stop();
	});

	test( "defining event functions sets the attrFn to true", function(){
		$.each(events, function(i, name){
			ok($.attrFn[name], "attribute function is true");
		});
	});

	test( "scrollstart enabled defaults to true", function(){
		$.event.special.scrollstart.enabled = false;
		$.testHelper.reloadLib(libName);
		ok($.event.special.scrollstart.enabled, "scrollstart enabled");
	});

	asyncTest( "scrollstart setup binds a function that returns when its disabled", function(){
		expect( 1 );
		$.event.special.scrollstart.enabled = false;

		$($.event.special.scrollstart).bind("scrollstart", function(){
			ok(false, "scrollstart fired");
		});

		$($.event.special.scrollstart).bind("touchmove", function(){
			ok(true, "touchmove fired");
			start();
		});

		$($.event.special.scrollstart).trigger("touchmove");
	});

	asyncTest( "scrollstart setup binds a function that triggers scroll start when enabled", function(){
		$.event.special.scrollstart.enabled = true;

		$($.event.special.scrollstart).bind("scrollstart", function(){
			ok(true, "scrollstart fired");
			start();
		});

		$($.event.special.scrollstart).trigger("touchmove");
	});

	asyncTest( "scrollstart setup binds a function that triggers scroll stop after 50 ms", function(){
		var triggered = false;
		$.event.special.scrollstart.enabled = true;

		$($.event.special.scrollstart).bind("scrollstop", function(){
			triggered = true;
		});

		ok(!triggered, "not triggered");

		$($.event.special.scrollstart).trigger("touchmove");

		setTimeout(function(){
			ok(triggered, "triggered");
			start();
		}, 50);
	});

	var forceTouchSupport = function(){
		$.support.touch = true;
		$.testHelper.reloadLib(libName);

		//mock originalEvent information
		$.Event.prototype.originalEvent = {
			touches: [{ 'pageX' : 0 }, { 'pageY' : 0 }]
		};
	};

	asyncTest( "long press fires tap hold after 750 ms", function(){
		var taphold = false;

		forceTouchSupport();

		$($.event.special.tap).bind("taphold", function(){
			taphold = true;
		});

		$($.event.special.tap).trigger("touchstart");

		setTimeout(function(){
			ok(taphold);
			start();
		}, 751);
	});

	//NOTE used to simulate movement when checked
	//TODO find a better way ...
	var mockAbs = function(value){
		Math.abs = function(){
			return value;
		};
	};

	asyncTest( "touchmove prevents taphold", function(){
		expect( 1 );
		var taphold = false;

		forceTouchSupport();
		mockAbs(100);

		//NOTE record taphold event
		$($.event.special.tap).bind("taphold", function(){
			ok(false, "taphold fired");
			taphold = true;
		});

		//NOTE start the touch events
		$($.event.special.tap).trigger("touchstart");

		//NOTE fire touchmove to push back taphold
		setTimeout(function(){
			$($.event.special.tap).trigger("touchmove");
		}, 100);

		//NOTE verify that the taphold hasn't been fired
		//		 with the normal timing
		setTimeout(function(){
			ok(!taphold, "taphold not fired");
			start();
		}, 751);
	});

	asyncTest( "tap event fired without movement", function(){
		expect( 1 );
		var tap = false,
				checkTap = function(){
					ok(true, "tap fired");
				};

		forceTouchSupport();

		//NOTE record the tap event
		$($.event.special.tap).bind("tap", checkTap);

		$($.event.special.tap).trigger("touchstart");
		$($.event.special.tap).trigger("touchend");

		setTimeout(function(){
			start();
		}, 400);
	});

	asyncTest( "tap event not fired when there is movement", function(){
		expect( 1 );
		var tap = false;
		forceTouchSupport();

		//NOTE record tap event
		$($.event.special.tap).bind("tap", function(){
			ok(false, "tap fired");
			tap = true;
		});

		//NOTE make sure movement is recorded
		mockAbs(100);

		//NOTE start and move right away
		$($.event.special.tap).trigger("touchstart");
		$($.event.special.tap).trigger("touchmove");

		//NOTE end touch sequence after 20 ms
		setTimeout(function(){
			$($.event.special.tap).trigger("touchend");
		}, 20);

		setTimeout(function(){
			ok(!tap, "not tapped");
			start();
		}, 40);
	});

	var swipeTimedTest = function(opts){
		var swipe = false;

		forceTouchSupport();

		$($.event.special.swipe).bind('swipe', function(){
			swipe = true;
		});

		//NOTE bypass the trigger source check
		$.Event.prototype.originalEvent = {
			touches: false
		};

		$($.event.special.swipe).trigger("touchstart");

		//NOTE make sure the coordinates are calculated within range
		//		 to be registered as a swipe
		mockAbs(opts.coordChange);

		setTimeout(function(){
			$($.event.special.swipe).trigger("touchmove");
			$($.event.special.swipe).trigger("touchend");
		}, opts.timeout + 100);

		setTimeout(function(){
			same(swipe, opts.expected, "swipe expected");
			start();
		}, opts.timeout + 200);

		stop();
	};

	test( "swipe fired when coordinate change in less than a second", function(){
		swipeTimedTest({ timeout: 10, coordChange: 35, expected: true });
	});

	test( "swipe not fired when coordinate change takes more than a second", function(){
		swipeTimedTest({ timeout: 1000, coordChange: 35, expected: false });
	});

	test( "swipe not fired when coordinate change <= 30", function(){
		swipeTimedTest({ timeout: 1000, coordChange: 30, expected: false });
	});

	test( "swipe not fired when coordinate change >= 75", function(){
		swipeTimedTest({ timeout: 1000, coordChange: 75, expected: false });
	});

	asyncTest( "scrolling prevented when coordinate change > 10", function(){
		expect( 1 );

		forceTouchSupport();

		// ensure the swipe custome event is setup
		$($.event.special.swipe).bind('swipe', function(){});

		//NOTE bypass the trigger source check
		$.Event.prototype.originalEvent = {
			touches: false
		};

		$.Event.prototype.preventDefault = function(){
			ok(true, "prevent default called");
			start();
		};

		mockAbs(11);

		$($.event.special.swipe).trigger("touchstart");
		$($.event.special.swipe).trigger("touchmove");
	});

	asyncTest( "move handler returns when touchstart has been fired since touchstop", function(){
		expect( 1 );

		// bypass triggered event check
		$.Event.prototype.originalEvent = {
			touches: false
		};

		forceTouchSupport();

		// ensure the swipe custome event is setup
		$($.event.special.swipe).bind('swipe', function(){});

		$($.event.special.swipe).trigger("touchstart");
		$($.event.special.swipe).trigger("touchend");

		$($.event.special.swipe).bind("touchmove", function(){
			ok(true, "touchmove bound functions are fired");
			start();
		});

		Math.abs = function(){
			ok(false, "shouldn't compare coordinates");
		};

		$($.event.special.swipe).trigger("touchmove");
	});

	var nativeSupportTest = function(opts){
		$.support.orientation = opts.orientationSupport;
		same($.event.special.orientationchange[opts.method](), opts.returnValue);
	};

	test( "orientation change setup should do nothing when natively supported", function(){
		nativeSupportTest({
			method: 'setup',
			orientationSupport: true,
			returnValue: false
		});
	});

	test( "orientation change setup should bind resize when not supported natively", function(){
		nativeSupportTest({
			method: 'setup',
			orientationSupport: false,
			returnValue: undefined //NOTE result of bind function call
		});
	});

	test( "orientation change teardown should do nothing when natively supported", function(){
		nativeSupportTest({
			method: 'teardown',
			orientationSupport: true,
			returnValue: false
		});
	});

	test( "orientation change teardown should unbind resize when not supported natively", function(){
		nativeSupportTest({
			method: 'teardown',
			orientationSupport: false,
			returnValue: undefined //NOTE result of unbind function call
		});
	});
})(jQuery);<commit_msg>Fixing tap/taphold tests that broke when fastclick/vmouse changes landed.<commit_after>/*
 * mobile event unit tests
 */

(function($){
	var libName = "jquery.mobile.event.js",
			absFn = Math.abs,
			originalEventFn = $.Event.prototype.originalEvent,
			preventDefaultFn = $.Event.prototype.preventDefault,
			events = ("touchstart touchmove touchend orientationchange tap taphold " +
								"swipe swipeleft swiperight scrollstart scrollstop").split( " " );

	module(libName, {
		setup: function(){

			// ensure bindings are removed
			$.each(events, function(i, name){
				$.each([$("#qunit-fixture"),
					$($.event.special.scrollstart),
					$($.event.special.tap),
					$($.event.special.tap),
					$($.event.special.swipe)], function(j, obj){
						obj.unbind(name);
					});
			});

			//NOTE unmock
			Math.abs = absFn;
			$.Event.prototype.originalEvent = originalEventFn;
			$.Event.prototype.preventDefault = preventDefaultFn;
		}
	});

	$.testHelper.excludeFileProtocol(function(){
		test( "new events defined on the jquery object", function(){
			$.each(events, function( i, name ) {
				delete $.fn[name];
				same($.fn[name], undefined);
			});

			$.testHelper.reloadLib(libName);

			$.each($.fn.clone(events), function( i, name ) {
				ok($.fn[name] !== undefined, name + "is not undefined");
			});
		});
	});

	asyncTest( "defined event functions bind a closure when passed", function(){
		expect( 1 );

		$('#qunit-fixture').bind(events[0], function(){
			ok(true, "event fired");
			start();
		});

		$('#qunit-fixture').trigger(events[0]);
		stop();
	});

	asyncTest( "defined event functions trigger the event with no arguments", function(){
		expect( 1 );

		$('#qunit-fixture').bind('touchstart', function(){
			ok(true, "event fired");
			start();
		});

		$('#qunit-fixture').touchstart();
		stop();
	});

	test( "defining event functions sets the attrFn to true", function(){
		$.each(events, function(i, name){
			ok($.attrFn[name], "attribute function is true");
		});
	});

	test( "scrollstart enabled defaults to true", function(){
		$.event.special.scrollstart.enabled = false;
		$.testHelper.reloadLib(libName);
		ok($.event.special.scrollstart.enabled, "scrollstart enabled");
	});

	asyncTest( "scrollstart setup binds a function that returns when its disabled", function(){
		expect( 1 );
		$.event.special.scrollstart.enabled = false;

		$($.event.special.scrollstart).bind("scrollstart", function(){
			ok(false, "scrollstart fired");
		});

		$($.event.special.scrollstart).bind("touchmove", function(){
			ok(true, "touchmove fired");
			start();
		});

		$($.event.special.scrollstart).trigger("touchmove");
	});

	asyncTest( "scrollstart setup binds a function that triggers scroll start when enabled", function(){
		$.event.special.scrollstart.enabled = true;

		$($.event.special.scrollstart).bind("scrollstart", function(){
			ok(true, "scrollstart fired");
			start();
		});

		$($.event.special.scrollstart).trigger("touchmove");
	});

	asyncTest( "scrollstart setup binds a function that triggers scroll stop after 50 ms", function(){
		var triggered = false;
		$.event.special.scrollstart.enabled = true;

		$($.event.special.scrollstart).bind("scrollstop", function(){
			triggered = true;
		});

		ok(!triggered, "not triggered");

		$($.event.special.scrollstart).trigger("touchmove");

		setTimeout(function(){
			ok(triggered, "triggered");
			start();
		}, 50);
	});

	var forceTouchSupport = function(){
		$.support.touch = true;
		$.testHelper.reloadLib(libName);

		//mock originalEvent information
		$.Event.prototype.originalEvent = {
			touches: [{ 'pageX' : 0 }, { 'pageY' : 0 }]
		};
	};

	asyncTest( "long press fires tap hold after 750 ms", function(){
		var taphold = false;

		forceTouchSupport();

		$($.event.special.tap).bind("taphold", function(){
			taphold = true;
		});

		$($.event.special.tap).trigger("vmousedown");

		setTimeout(function(){
			ok(taphold);
			start();
		}, 751);
	});

	//NOTE used to simulate movement when checked
	//TODO find a better way ...
	var mockAbs = function(value){
		Math.abs = function(){
			return value;
		};
	};

	asyncTest( "move prevents taphold", function(){
		expect( 1 );
		var taphold = false;

		forceTouchSupport();
		mockAbs(100);

		//NOTE record taphold event
		$($.event.special.tap).bind("taphold", function(){
			ok(false, "taphold fired");
			taphold = true;
		});

		//NOTE start the touch events
		$($.event.special.tap).trigger("vmousedown");

		//NOTE fire touchmove to push back taphold
		setTimeout(function(){
			$($.event.special.tap).trigger("vmousecancel");
		}, 100);

		//NOTE verify that the taphold hasn't been fired
		//		 with the normal timing
		setTimeout(function(){
			ok(!taphold, "taphold not fired");
			start();
		}, 751);
	});

	asyncTest( "tap event fired without movement", function(){
		expect( 1 );
		var tap = false,
				checkTap = function(){
					ok(true, "tap fired");
				};

		forceTouchSupport();

		//NOTE record the tap event
		$($.event.special.tap).bind("tap", checkTap);

		$($.event.special.tap).trigger("vmousedown");
		$($.event.special.tap).trigger("vmouseup");
		$($.event.special.tap).trigger("vclick");

		setTimeout(function(){
			start();
		}, 400);
	});

	asyncTest( "tap event not fired when there is movement", function(){
		expect( 1 );
		var tap = false;
		forceTouchSupport();

		//NOTE record tap event
		$($.event.special.tap).bind("tap", function(){
			ok(false, "tap fired");
			tap = true;
		});

		//NOTE make sure movement is recorded
		mockAbs(100);

		//NOTE start and move right away
		$($.event.special.tap).trigger("touchstart");
		$($.event.special.tap).trigger("touchmove");

		//NOTE end touch sequence after 20 ms
		setTimeout(function(){
			$($.event.special.tap).trigger("touchend");
		}, 20);

		setTimeout(function(){
			ok(!tap, "not tapped");
			start();
		}, 40);
	});

	var swipeTimedTest = function(opts){
		var swipe = false;

		forceTouchSupport();

		$($.event.special.swipe).bind('swipe', function(){
			swipe = true;
		});

		//NOTE bypass the trigger source check
		$.Event.prototype.originalEvent = {
			touches: false
		};

		$($.event.special.swipe).trigger("touchstart");

		//NOTE make sure the coordinates are calculated within range
		//		 to be registered as a swipe
		mockAbs(opts.coordChange);

		setTimeout(function(){
			$($.event.special.swipe).trigger("touchmove");
			$($.event.special.swipe).trigger("touchend");
		}, opts.timeout + 100);

		setTimeout(function(){
			same(swipe, opts.expected, "swipe expected");
			start();
		}, opts.timeout + 200);

		stop();
	};

	test( "swipe fired when coordinate change in less than a second", function(){
		swipeTimedTest({ timeout: 10, coordChange: 35, expected: true });
	});

	test( "swipe not fired when coordinate change takes more than a second", function(){
		swipeTimedTest({ timeout: 1000, coordChange: 35, expected: false });
	});

	test( "swipe not fired when coordinate change <= 30", function(){
		swipeTimedTest({ timeout: 1000, coordChange: 30, expected: false });
	});

	test( "swipe not fired when coordinate change >= 75", function(){
		swipeTimedTest({ timeout: 1000, coordChange: 75, expected: false });
	});

	asyncTest( "scrolling prevented when coordinate change > 10", function(){
		expect( 1 );

		forceTouchSupport();

		// ensure the swipe custome event is setup
		$($.event.special.swipe).bind('swipe', function(){});

		//NOTE bypass the trigger source check
		$.Event.prototype.originalEvent = {
			touches: false
		};

		$.Event.prototype.preventDefault = function(){
			ok(true, "prevent default called");
			start();
		};

		mockAbs(11);

		$($.event.special.swipe).trigger("touchstart");
		$($.event.special.swipe).trigger("touchmove");
	});

	asyncTest( "move handler returns when touchstart has been fired since touchstop", function(){
		expect( 1 );

		// bypass triggered event check
		$.Event.prototype.originalEvent = {
			touches: false
		};

		forceTouchSupport();

		// ensure the swipe custome event is setup
		$($.event.special.swipe).bind('swipe', function(){});

		$($.event.special.swipe).trigger("touchstart");
		$($.event.special.swipe).trigger("touchend");

		$($.event.special.swipe).bind("touchmove", function(){
			ok(true, "touchmove bound functions are fired");
			start();
		});

		Math.abs = function(){
			ok(false, "shouldn't compare coordinates");
		};

		$($.event.special.swipe).trigger("touchmove");
	});

	var nativeSupportTest = function(opts){
		$.support.orientation = opts.orientationSupport;
		same($.event.special.orientationchange[opts.method](), opts.returnValue);
	};

	test( "orientation change setup should do nothing when natively supported", function(){
		nativeSupportTest({
			method: 'setup',
			orientationSupport: true,
			returnValue: false
		});
	});

	test( "orientation change setup should bind resize when not supported natively", function(){
		nativeSupportTest({
			method: 'setup',
			orientationSupport: false,
			returnValue: undefined //NOTE result of bind function call
		});
	});

	test( "orientation change teardown should do nothing when natively supported", function(){
		nativeSupportTest({
			method: 'teardown',
			orientationSupport: true,
			returnValue: false
		});
	});

	test( "orientation change teardown should unbind resize when not supported natively", function(){
		nativeSupportTest({
			method: 'teardown',
			orientationSupport: false,
			returnValue: undefined //NOTE result of unbind function call
		});
	});
})(jQuery);
<|endoftext|>


<commit_before>'use strict';

var EventEmitter = require('eventemitter3');
var Lexer = require('xml-lexer');
var Type = Lexer.Type;

var NodeType = {
    element: 'element',
    text: 'text'
};

var createNode = function createNode(options) {
    return Object.assign({
        name: '',
        type: NodeType.element,
        value: '',
        parent: null,
        attributes: {},
        children: []
    }, options);
};

var create = function create(options) {
    options = Object.assign({
        stream: false,
        doneEvent: 'done'
    }, options);

    var lexer = Lexer.create();
    var reader = new EventEmitter();

    var rootNode = createNode();
    var current = null;
    var attrName = '';

    lexer.on('data', function (data) {
        switch (data.type) {

            case Type.openTag:
                if (current === null) {
                    current = rootNode;
                    current.name = data.value;
                } else {
                    var node = createNode({
                        name: data.value,
                        parent: current
                    });
                    current.children.push(node);
                    current = node;
                }
                break;

            case Type.closeTag:
                var parent = current.parent;
                if (current.name !== data.value) {
                    // ignore unexpected closing tag
                    break;
                }
                if (options.stream && current.parent === rootNode) {
                    rootNode.children = [];
                    // do not expose parent node in top level nodes
                    current.parent = null;
                }
                reader.emit(current.name, current);
                if (current === rootNode) {
                    // end of document, stop listening
                    lexer.removeAllListeners('data');
                    reader.emit(options.doneEvent, current);
                    rootNode = null;
                }
                current = parent;
                break;

            case Type.text:
                current.children.push(createNode({
                    type: NodeType.text,
                    value: data.value,
                    parent: current
                }));
                break;

            case Type.attributeName:
                attrName = data.value;
                current.attributes[attrName] = '';
                break;

            case Type.attributeValue:
                current.attributes[attrName] = data.value;
                break;

            default:
                break;
        }
    });
    reader.parse = lexer.write;
    return reader;
};

module.exports = {
    create: create,
    NodeType: NodeType
};<commit_msg>#5 add parseSync method<commit_after>'use strict';

var EventEmitter = require('eventemitter3');
var Lexer = require('xml-lexer');
var Type = Lexer.Type;

var NodeType = {
    element: 'element',
    text: 'text'
};

var createNode = function createNode(options) {
    return Object.assign({
        name: '',
        type: NodeType.element,
        value: '',
        parent: null,
        attributes: {},
        children: []
    }, options);
};

var create = function create(options) {
    options = Object.assign({
        stream: false,
        doneEvent: 'done'
    }, options);

    var lexer = Lexer.create();
    var reader = new EventEmitter();

    var rootNode = createNode();
    var current = null;
    var attrName = '';

    lexer.on('data', function (data) {
        switch (data.type) {

            case Type.openTag:
                if (current === null) {
                    current = rootNode;
                    current.name = data.value;
                } else {
                    var node = createNode({
                        name: data.value,
                        parent: current
                    });
                    current.children.push(node);
                    current = node;
                }
                break;

            case Type.closeTag:
                var parent = current.parent;
                if (current.name !== data.value) {
                    // ignore unexpected closing tag
                    break;
                }
                if (options.stream && current.parent === rootNode) {
                    rootNode.children = [];
                    // do not expose parent node in top level nodes
                    current.parent = null;
                }
                reader.emit(current.name, current);
                if (current === rootNode) {
                    // end of document, stop listening
                    lexer.removeAllListeners('data');
                    reader.emit(options.doneEvent, current);
                    rootNode = null;
                }
                current = parent;
                break;

            case Type.text:
                current.children.push(createNode({
                    type: NodeType.text,
                    value: data.value,
                    parent: current
                }));
                break;

            case Type.attributeName:
                attrName = data.value;
                current.attributes[attrName] = '';
                break;

            case Type.attributeValue:
                current.attributes[attrName] = data.value;
                break;

            default:
                break;
        }
    });
    reader.parse = lexer.write;
    return reader;
};

var parseSync = function parseSync(xml) {
    var done = '<!done>';
    var reader = create({ doneEvent: done });
    var res = void 0;
    reader.on(done, function (ast) {
        res = ast;
    });
    reader.parse(xml);
    return res;
};

module.exports = {
    parseSync: parseSync,
    create: create,
    NodeType: NodeType
};<|endoftext|>


<commit_before>import React from 'react';
import { subscribe } from 'horizon-react';
import wedding from '../../../../../config/wedding.js';
import variables from '../../../../../config/variables.js';
import glob from 'styles/app';
import local from './_styles';
import { Row, Col, Button } from 'react-bootstrap';
import PageHeader from '../../_partials/page-header';
import prettyAddress from '../../_partials/pretty-address';
import Map from '../../_partials/map/map';
import { showGuideMapInfo } from '../../../actions/actionCreators';

/**
  *
  * The City Guide page
  *
  * @param  none
  *
  * @return {ReactComponent}
  */

const images = process.env.NODE_ENV === 'production' ? 'images' : `http://127.0.0.1:9095/static/images`;

const mapStateToProps = (state) => ({
  guideMap: state.guideMap
});

class CityGuide extends React.Component {
  handlePlaceNameClick(e){
    e.preventDefault();
    const element = document.getElementById('map')
    const alignWithTop = true;
    element.scrollIntoView(alignWithTop);
    const placeParts = e.target.id.split('-');
    const list = placeParts[0];
    const index = parseInt(placeParts[1]);
    const markers = this.props.guideMap.markers.map(
      (marker, i) => {
        let show = false;
        if (marker.pin === list && marker.idx === index) {
          show = true
        }
        return {
          ...marker,
          showInfo: show,
        };
      }
    );
    this.props.dispatch(showGuideMapInfo(markers));
  }

  render(){
    const accommodationsAddress = prettyAddress(wedding.accommodations.hotel.address);

    const makeList = (listType) => {
      let prettyListType = listType;
      if(listType === 'bar'){
        prettyListType = Drink
<i className={`material-icons ${local.icon}`}>local_bar;
      } else if(listType === 'music'){
        prettyListType = Music
<i className={`material-icons ${local.icon}`}>music_note;
      } else if(listType === 'food'){
        prettyListType = Eat
<i className={`material-icons ${local.icon}`}>restaurant;
      } else if(listType === 'fun'){
        prettyListType = Misc
<i className={`material-icons ${local.icon}`}>directions_bike;
      }
      return (
        <ul className={`${local.todoListCol}`}>
          <li
            className={`${glob.card} ${local.todoListHeader}`}
            style={{backgroundColor: variables.$map.colors[listType]}}
          >

              {prettyListType}

          {wedding.guide[listType].list.map(
            (place, idx) => {
              return (
                <li className={`${glob.card} ${local.listItem}`} key={idx}>

                      {place.name}

{place.description}

{place.address.street}

                    <a href="#" style={{border : '0px', color : variables.$map.colors[listType]}} onClick={this.handlePlaceNameClick.bind(this)} id={`${listType}-${idx}`}>
                      View on Map

              );
            }
          )}

      )
    }

    const barList = makeList('bar');
    const musicList = makeList('music');
    const foodList = makeList('food');
    const funList = makeList('fun');

    const fullList = (

{musicList}

{funList}

{foodList}

{barList}

    );

    return (

        <PageHeader page="City Guide" />

        <div className={`${glob.section}`} style={{ paddingBottom: '0px' }}>

Welcome to

{wedding.city.name}

        <div className={`${glob.section} ${glob.sectionBlue}`} style={{  }}>
          <Row>
            <Col xs={8} sm={5} md={4} className={glob.verticalCol}>
              <img src={`${images}/greetings.png`} />
            </Col>
          </Row>

        <div className={`${glob.section}`}>
          <h2 className={`${glob.headerLines} ${glob.black}`}>Accommodations

          <Row>
            <Col xs={10} sm={6} className={glob.verticalCol}>
                <div className={`${glob.card} ${local.hotel}`}>

                      {wedding.accommodations.hotel.name}

                      {wedding.accommodations.hotel.location}

{accommodationsAddress}

                      Book Hotel at {wedding.accommodations.hotel.discountAmt}% OFF

            </Col>
            <Col xs={8} sm={6} className={`${glob.verticalCol} ${local.hotelAbout}`}>

hotel

{wedding.accommodations.hotel.highlight}

{wedding.accommodations.hotel.message}

            </Col>
          </Row>

        <div className={`${glob.section} ${glob.sectionWhiteMed}`}>
          <Row>
            <Col xs={12}>
              <h2 className={`${glob.headerLines}`}>Transportation

              <ul className={`${local.transportation}`}>

                    <Button className={`${glob.button}`} href={wedding.guide.transportation.bus.how.website} target="_BLANK">
                      directions_bus

                      {wedding.guide.transportation.bus.how.name}
                    </Button>

                    <Button className={`${glob.button}`} href={wedding.guide.transportation.rideshare.how.website}  target="_BLANK">
                      directions_car

                      {wedding.guide.transportation.rideshare.how.name}
                    </Button>

                    <Button className={`${glob.button}`} href={wedding.guide.transportation.taxi.how.website} target="_BLANK">
                      local_taxi

                      {wedding.guide.transportation.taxi.how.name}
                    </Button>

            </Col>
          </Row>

        <div  className={`${glob.section}`}>
          <h2 className={`${glob.headerLines} ${glob.black}`}>Things to Do

          <Row id="map">
            <Col xs={10} xsOffset={1} lg={6} lgOffset={3}>
              <Map type="guide" />
            </Col>
          </Row>
          <Row>
            <Col xs={10} xsOffset={1} lg={6} lgOffset={3}>
              {fullList}
            </Col>
          </Row>

    );
  }
};

export default subscribe({
  mapStateToProps
})(CityGuide);
<commit_msg>Guide - import image<commit_after>import React from 'react';
import { subscribe } from 'horizon-react';
import wedding from '../../../../../config/wedding.js';
import variables from '../../../../../config/variables.js';
import glob from 'styles/app';
import local from './_styles';
import { Row, Col, Button } from 'react-bootstrap';
import PageHeader from '../../_partials/page-header';
import prettyAddress from '../../_partials/pretty-address';
import Map from '../../_partials/map/map';
import { showGuideMapInfo } from '../../../actions/actionCreators';
import greetings from '../../../../../static/images/greetings.png';

/**
  *
  * The City Guide page
  *
  * @param  none
  *
  * @return {ReactComponent}
  */

const images = process.env.NODE_ENV === 'production' ? 'images' : `http://127.0.0.1:9095/static/images`;

const mapStateToProps = (state) => ({
  guideMap: state.guideMap
});

class CityGuide extends React.Component {
  handlePlaceNameClick(e){
    e.preventDefault();
    const element = document.getElementById('map')
    const alignWithTop = true;
    element.scrollIntoView(alignWithTop);
    const placeParts = e.target.id.split('-');
    const list = placeParts[0];
    const index = parseInt(placeParts[1]);
    const markers = this.props.guideMap.markers.map(
      (marker, i) => {
        let show = false;
        if (marker.pin === list && marker.idx === index) {
          show = true
        }
        return {
          ...marker,
          showInfo: show,
        };
      }
    );
    this.props.dispatch(showGuideMapInfo(markers));
  }

  render(){
    const accommodationsAddress = prettyAddress(wedding.accommodations.hotel.address);

    const makeList = (listType) => {
      let prettyListType = listType;
      if(listType === 'bar'){
        prettyListType = Drink
<i className={`material-icons ${local.icon}`}>local_bar;
      } else if(listType === 'music'){
        prettyListType = Music
<i className={`material-icons ${local.icon}`}>music_note;
      } else if(listType === 'food'){
        prettyListType = Eat
<i className={`material-icons ${local.icon}`}>restaurant;
      } else if(listType === 'fun'){
        prettyListType = Misc
<i className={`material-icons ${local.icon}`}>directions_bike;
      }
      return (
        <ul className={`${local.todoListCol}`}>
          <li
            className={`${glob.card} ${local.todoListHeader}`}
            style={{backgroundColor: variables.$map.colors[listType]}}
          >

              {prettyListType}

          {wedding.guide[listType].list.map(
            (place, idx) => {
              return (
                <li className={`${glob.card} ${local.listItem}`} key={idx}>

                      {place.name}

{place.description}

{place.address.street}

                    <a href="#" style={{border : '0px', color : variables.$map.colors[listType]}} onClick={this.handlePlaceNameClick.bind(this)} id={`${listType}-${idx}`}>
                      View on Map

              );
            }
          )}

      )
    }

    const barList = makeList('bar');
    const musicList = makeList('music');
    const foodList = makeList('food');
    const funList = makeList('fun');

    const fullList = (

{musicList}

{funList}

{foodList}

{barList}

    );

    return (

        <PageHeader page="City Guide" />

        <div className={`${glob.section}`} style={{ paddingBottom: '0px' }}>

Welcome to

{wedding.city.name}

        <div className={`${glob.section} ${glob.sectionBlue}`} style={{  }}>
          <Row>
            <Col xs={8} sm={5} md={4} className={glob.verticalCol}>

            </Col>
          </Row>

        <div className={`${glob.section}`}>
          <h2 className={`${glob.headerLines} ${glob.black}`}>Accommodations

          <Row>
            <Col xs={10} sm={6} className={glob.verticalCol}>
                <div className={`${glob.card} ${local.hotel}`}>

                      {wedding.accommodations.hotel.name}

                      {wedding.accommodations.hotel.location}

{accommodationsAddress}

                      Book Hotel at {wedding.accommodations.hotel.discountAmt}% OFF

            </Col>
            <Col xs={8} sm={6} className={`${glob.verticalCol} ${local.hotelAbout}`}>

hotel

{wedding.accommodations.hotel.highlight}

{wedding.accommodations.hotel.message}

            </Col>
          </Row>

        <div className={`${glob.section} ${glob.sectionWhiteMed}`}>
          <Row>
            <Col xs={12}>
              <h2 className={`${glob.headerLines}`}>Transportation

              <ul className={`${local.transportation}`}>

                    <Button className={`${glob.button}`} href={wedding.guide.transportation.bus.how.website} target="_BLANK">
                      directions_bus

                      {wedding.guide.transportation.bus.how.name}
                    </Button>

                    <Button className={`${glob.button}`} href={wedding.guide.transportation.rideshare.how.website}  target="_BLANK">
                      directions_car

                      {wedding.guide.transportation.rideshare.how.name}
                    </Button>

                    <Button className={`${glob.button}`} href={wedding.guide.transportation.taxi.how.website} target="_BLANK">
                      local_taxi

                      {wedding.guide.transportation.taxi.how.name}
                    </Button>

            </Col>
          </Row>

        <div  className={`${glob.section}`}>
          <h2 className={`${glob.headerLines} ${glob.black}`}>Things to Do

          <Row id="map">
            <Col xs={10} xsOffset={1} lg={6} lgOffset={3}>
              <Map type="guide" />
            </Col>
          </Row>
          <Row>
            <Col xs={10} xsOffset={1} lg={6} lgOffset={3}>
              {fullList}
            </Col>
          </Row>

    );
  }
};

export default subscribe({
  mapStateToProps
})(CityGuide);
<|endoftext|>


<commit_before>$(function() {
  $(document).on("change", "[data-behavior~=toggle-disable-list-command]", function(e) {
    var commandButtonsSelector = $(e.target).data("commands");
    var commandButtons = $(e.target).closest(commandButtonsSelector);
    console.log(commandButtons.length);
  });
});
<commit_msg>Implement toggle behavior from checkbox change<commit_after>$(function() {
  $(document).on("change", "[data-behavior~=toggle-disable-list-command]", function(e) {
    var commandButtonsSelector = $(e.target).data("commands");
    var commandButtons = $(document).find(commandButtonsSelector);
    var list = $(document).find("[name='" + $(e.target).attr("name") + "']:checked");
    if (list.length > 0) {
      commandButtons.removeClass("disabled").attr("disabled", false);
    } else {
      commandButtons.addClass("disabled").attr("disabled", true);
    }
  });
});
<|endoftext|>


<commit_before>import React from 'react';

import ItemLink from 'common/ItemLink';

import Analyzer from 'Parser/Core/Analyzer';
import SUGGESTION_IMPORTANCE from 'Parser/Core/ISSUE_IMPORTANCE';

// Example logs with missing enchants:
// https://www.warcraftlogs.com/reports/ydxavfGq1mBrM9Vc/#fight=1&source=14

class EnchantChecker extends Analyzer {

  static ENCHANTABLE_SLOTS = {
    10: 'Ring',
    11: 'Ring',
    15: 'Weapon',
    16: 'OffHand',
  };
  static MAX_ENCHANT_IDS = [
    //BfA enchants
    5946, // Weapon Enchant - Coastal Surge
    5950, // Weapon Enchant - Gale-Force Striking
    5949, // Weapon Enchant - Torrent of Elements
    5948, // Weapon Enchant - Siphoning
    5965, // Weapon Enchant - Deadly Navigation
    5964, // Weapon Enchant - Masterful Navigation
    5963, // Weapon Enchant - Quick Navigation
    5966, // Weapon Enchant - Stalwart Navigation
    5962, // Weapon Enchant - Versatile Navigation

    5938, // Seal of Critical Strike
    5939, // Seal of Haste
    5940, // Seal of Mastery
    5941, // Seal of Versatility
    5942, // Pact of Critical Strike
    5943, // Pact of Haste
    5944, // Pact of Mastery
    5945, // Pact of Versatility
  ];

  get enchantableGear() {
    return Object.keys(this.constructor.ENCHANTABLE_SLOTS).reduce((obj, slot) => {
      const item = this.selectedCombatant._getGearItemBySlotId(slot);

      // If there is no offhand, disregard the item.
      // If the icon has `offhand` in the name, we know it's not a weapon and doesn't need an enchant.
      // This is not an ideal way to determine if an offhand is a weapon.
      if (item.id === 0 || item.icon.includes('offhand')) {
        return obj;
      }
      obj[slot] = this.selectedCombatant._getGearItemBySlotId(slot);

      return obj;
    }, {});
  }
  get numEnchantableGear() {
    return Object.keys(this.constructor.ENCHANTABLE_SLOTS).length;
  }
  get slotsMissingEnchant() {
    const gear = this.enchantableGear;
    return Object.keys(gear).filter(slot => !this.hasEnchant(gear[slot]));
  }
  get numSlotsMissingEnchant() {
    return this.slotsMissingEnchant.length;
  }
  get slotsMissingMaxEnchant() {
    const gear = this.enchantableGear;
    return Object.keys(gear).filter(slot => this.hasEnchant(gear[slot]) && !this.hasMaxEnchant(gear[slot]));
  }
  get numSlotsMissingMaxEnchant() {
    return this.slotsMissingMaxEnchant.length;
  }
  hasEnchant(item) {
    return !!item.permanentEnchant;
  }
  hasMaxEnchant(item) {
    return this.constructor.MAX_ENCHANT_IDS.includes(item.permanentEnchant);
  }

  suggestions(when) {
    const gear = this.enchantableGear;
    // iterating with keys instead of value because the values don't store what slot is being looked at
    Object.keys(gear)
      .forEach(slot => {
        const item = gear[slot];
        const slotName = this.constructor.ENCHANTABLE_SLOTS[slot];
        const hasEnchant = this.hasEnchant(item);

        when(hasEnchant).isFalse()
          .addSuggestion((suggest, actual, recommended) => {
            return suggest(
              <React.Fragment>
                Your <ItemLink id={item.id} quality={item.quality} details={item} icon={false}>{slotName}</ItemLink> is missing an enchant. Apply a strong enchant to very easily increase your throughput slightly.
              </React.Fragment>
            )
              .icon(item.icon)
              .staticImportance(SUGGESTION_IMPORTANCE.MAJOR);
          });

        const noMaxEnchant = hasEnchant && !this.hasMaxEnchant(item);
        when(noMaxEnchant).isTrue()
          .addSuggestion((suggest, actual, recommended) => {
            return suggest(
              <React.Fragment>
                Your <ItemLink id={item.id} quality={item.quality} details={item} icon={false}>{slotName}</ItemLink> has a cheap enchant. Apply a strong enchant to very easily increase your throughput slightly.
              </React.Fragment>
            )
              .icon(item.icon)
              .staticImportance(SUGGESTION_IMPORTANCE.MINOR);
          });
      });
  }
}

export default EnchantChecker;
<commit_msg>enchant fix<commit_after>import React from 'react';

import ItemLink from 'common/ItemLink';

import Analyzer from 'Parser/Core/Analyzer';
import SUGGESTION_IMPORTANCE from 'Parser/Core/ISSUE_IMPORTANCE';

// Example logs with missing enchants:
// https://www.warcraftlogs.com/reports/ydxavfGq1mBrM9Vc/#fight=1&source=14

class EnchantChecker extends Analyzer {

  static ENCHANTABLE_SLOTS = {
    10: 'Ring',
    11: 'Ring',
    15: 'Weapon',
    16: 'OffHand',
  };
  static MAX_ENCHANT_IDS = [
    //BfA enchants
    5946, // Weapon Enchant - Coastal Surge
    5950, // Weapon Enchant - Gale-Force Striking
    5949, // Weapon Enchant - Torrent of Elements
    5948, // Weapon Enchant - Siphoning
    5965, // Weapon Enchant - Deadly Navigation
    5964, // Weapon Enchant - Masterful Navigation
    5963, // Weapon Enchant - Quick Navigation
    5966, // Weapon Enchant - Stalwart Navigation
    5962, // Weapon Enchant - Versatile Navigation
    3368, // Rune of the Fallen Crusader - Death Knight Only
    3370, // Rune of Razorice - Death Knight Only
    3847, // Rune of the Stoneskin Gargoyle - Death Knight Only

    5938, // Seal of Critical Strike
    5939, // Seal of Haste
    5940, // Seal of Mastery
    5941, // Seal of Versatility
    5942, // Pact of Critical Strike
    5943, // Pact of Haste
    5944, // Pact of Mastery
    5945, // Pact of Versatility
  ];

  get enchantableGear() {
    return Object.keys(this.constructor.ENCHANTABLE_SLOTS).reduce((obj, slot) => {
      const item = this.selectedCombatant._getGearItemBySlotId(slot);

      // If there is no offhand, disregard the item.
      // If the icon has `offhand` in the name, we know it's not a weapon and doesn't need an enchant.
      // This is not an ideal way to determine if an offhand is a weapon.
      if (item.id === 0 || item.icon.includes('offhand') || item.icon.includes('shield')) {
        return obj;
      }
      obj[slot] = this.selectedCombatant._getGearItemBySlotId(slot);

      return obj;
    }, {});
  }
  get numEnchantableGear() {
    return Object.keys(this.constructor.ENCHANTABLE_SLOTS).length;
  }
  get slotsMissingEnchant() {
    const gear = this.enchantableGear;
    return Object.keys(gear).filter(slot => !this.hasEnchant(gear[slot]));
  }
  get numSlotsMissingEnchant() {
    return this.slotsMissingEnchant.length;
  }
  get slotsMissingMaxEnchant() {
    const gear = this.enchantableGear;
    return Object.keys(gear).filter(slot => this.hasEnchant(gear[slot]) && !this.hasMaxEnchant(gear[slot]));
  }
  get numSlotsMissingMaxEnchant() {
    return this.slotsMissingMaxEnchant.length;
  }
  hasEnchant(item) {
    return !!item.permanentEnchant;
  }
  hasMaxEnchant(item) {
    return this.constructor.MAX_ENCHANT_IDS.includes(item.permanentEnchant);
  }

  suggestions(when) {
    const gear = this.enchantableGear;
    // iterating with keys instead of value because the values don't store what slot is being looked at
    Object.keys(gear)
      .forEach(slot => {
        const item = gear[slot];
        const slotName = this.constructor.ENCHANTABLE_SLOTS[slot];
        const hasEnchant = this.hasEnchant(item);

        when(hasEnchant).isFalse()
          .addSuggestion((suggest, actual, recommended) => {
            return suggest(
              <React.Fragment>
                Your <ItemLink id={item.id} quality={item.quality} details={item} icon={false}>{slotName}</ItemLink> is missing an enchant. Apply a strong enchant to very easily increase your throughput slightly.
              </React.Fragment>
            )
              .icon(item.icon)
              .staticImportance(SUGGESTION_IMPORTANCE.MAJOR);
          });

        const noMaxEnchant = hasEnchant && !this.hasMaxEnchant(item);
        when(noMaxEnchant).isTrue()
          .addSuggestion((suggest, actual, recommended) => {
            return suggest(
              <React.Fragment>
                Your <ItemLink id={item.id} quality={item.quality} details={item} icon={false}>{slotName}</ItemLink> has a cheap enchant. Apply a strong enchant to very easily increase your throughput slightly.
              </React.Fragment>
            )
              .icon(item.icon)
              .staticImportance(SUGGESTION_IMPORTANCE.MINOR);
          });
      });
  }
}

export default EnchantChecker;
<|endoftext|>