Commits

ryanackley  committed 9548169

initial commit

  • Participants
  • Parent commits d158f49

Comments (0)

Files changed (19)

File Archive.zip

Binary file added.

File AtlassianPluginProject.js

+AtlassianPluginProject = function(){
+	this.resourceMap = {};
+	this.matchedResourceMap = {};
+	this.matchedFileMap = {};
+	this.locationType = 'local';
+};
+AtlassianPluginProject.prototype = {
+	load : function(root, callback){
+		var resourceMap = this.resourceMap;
+		Gito.FileUtils.readFile(root, 'pom.xml', 'Text', function(pomText){
+			var p = new DOMParser();
+			var pom = p.parseFromString(pomText, "text/xml");
+			var groupId = pom.querySelector('project > groupId').textContent;
+			var artifactId = pom.querySelector('project > artifactId').textContent;
+			
+			Gito.FileUtils.readFile(root, 'src/main/resources/atlassian-plugin.xml', 'Text', function(content){
+				var doc = p.parseFromString(content, "text/xml");
+				var rootNode = doc.querySelector('atlassian-plugin');
+				
+				// '.key.value' is a little confusing. key refers to the literal "key" attribute on the xml node. value is 
+				// the string value of the attribute.
+				var key = rootNode.attributes.key.value;
+				key = key.replace('${project.groupId}', groupId).replace('${project.artifactId}', artifactId);
+				//var pattern = 'download/resources/PLUGIN_KEY:MODULE_KEY/RESOURCE_NAME';
+				
+				var resources = doc.querySelectorAll('web-resource resource');
+				for (var i = 0; i < resources.length; i++){
+					var attributes = resources[i].attributes;
+					var location = attributes.location.value;
+					if (location.indexOf('.js') != location.length - 3 && location.indexOf('.css') != location.length - 4){
+						continue;
+					}
+					var moduleKey = resources[i].parentNode.attributes.key.value;
+					var file = {root: root, path: '/src/main/resources' + (location.charAt(0) != '/' ? '/' : '') + location};
+					
+					resourceMap['download/resources/' + key + ':' + moduleKey + '/' + attributes.name.value] = file; 
+					
+				}
+				callback();
+			}); 
+		});
+	},
+	isProjectUrl: function (url){
+		var resourceMap = this.resourceMap;
+		for (var end in resourceMap){
+			var idx = url.indexOf(end);
+			if (idx != -1 && idx == url.length - end.length){
+				var file = resourceMap[end];
+				this.matchedResourceMap[url] = file;
+				this.matchedFileMap[file.root.fullPath + file.path] = url;
+				return true;
+			}
+		}
+		return false;
+	},
+	matchContents: function(url, content, callback){
+		var matchedResourceMap = this.matchedResourceMap;
+		var file = matchedResourceMap[url];
+		if (file){
+			Gito.FileUtils.readFile(file.root, file.path, 'Text', function(localContent){
+				if (content != localContent){
+					callback(false, 'Content for url ' + url + ' doesn\'t match local file ' + file.root.fullPath + file.path); 
+					delete matchedResourceMap[url];
+				}
+				else{
+					callback(true, 'Content for url ' + url + ' matches local file ' + file.root.fullPath + file.path);
+				}
+			});
+		}
+	},
+	commitResource : function(url, content, watcher, callback){
+		var localFile = this.matchedResourceMap[url];
+		if (localFile){
+			watcher.addChangedByMe(localFile.root.fullPath + localFile.path);
+			Gito.FileUtils.mkfile(localFile.root, localFile.path, content, callback);
+		}
+		else{
+			callback();
+		}
+	},
+	urlsForPath : function(path){
+		var single = this.matchedFileMap[path];
+		if (single){
+			return [single];
+		}
+		return [];
+	},
+	resetUrls : function(){
+		this.matchedResourceMap = {};
+		this.matchedFileMap = {};
+	}
+}
+ProjectTypes.push(
+    {
+		name: 'Atlassian Plugin',
+		locationType : 'local',
+		createProject : function(root, callback){
+			var project = new AtlassianPluginProject();
+			project.load(root, function(error){
+				callback(project, error);
+			});
+		} 
+    }
+);

File FauxFilesystem.js

+if (nativeFileSupport){
+	
+	Entry = function(parent, name, isFile){
+		this.parent = parent;
+		this.name = name;
+		this.isFile = isFile;
+		this.isDirectory = !isFile;
+		this.fullPath = this._fullPath();
+	}
+	
+	Entry.prototype = {
+		_fullPath : function(){
+			var path = this.name;
+			
+			var parent = this.parent;
+			while(parent != null){
+				path = parent.name + (path.charAt(0) == '/' ? '' : '/') + path;
+				parent = parent.parent;
+			}
+			return path;
+		},
+		remove : function(success, error){
+			if (nativeFileSupport.removeRecursively(this.fullPath)){
+				success()
+			}
+			else{
+				error();
+			}
+		}
+	}
+	
+	DirectoryEntry = function(parent, name){
+		window.Entry.call(this, parent, name, false);
+	}
+	DirectoryEntry.prototype = {
+		_make: function(){
+			nativeFileSupport.createDirectory(this.fullPath);
+			return this;
+		},
+		removeRecursively : function(success, error){
+			this.remove(success, error);
+		},
+		getDirectory : function(path, flags, success, error){
+			var de = new DirectoryEntry(this, path);
+			if (false === flags.create && !nativeFileSupport.fileExists(de.fullPath)){
+				error({code:FileError.NOT_FOUND_ERR});
+			}
+			else{
+				success(de._make());
+			}
+		},
+		getFile : function(path, options, success, error){
+			var fe = new FileEntry(this, path);
+			if (false === options.create && !nativeFileSupport.fileExists(fe.fullPath)){
+				error({code:FileError.NOT_FOUND_ERR});
+			}
+			else{
+				success(fe);
+			}
+		},
+		createReader: function(){
+			return new DirectoryReader(this.fullPath, this);
+		}
+		
+	}
+	
+	DirectoryEntry.prototype.__proto__ = Entry.prototype;
+	
+	DirectoryReader = function(fullPath, parent){
+		this.fullPath = fullPath;
+		this.parent = parent;
+	}
+	DirectoryReader.prototype = {
+		readEntries : function(success, error){
+			if (this.entries){
+				success([]);
+			}
+			else{
+				var names = nativeFileSupport.getDirEntries(this.fullPath);
+				this.entries = new Array(names.length);
+				for (var i = 0; i < this.entries.length; i++){
+				    var path = this.fullPath + '/' + names[i];
+				    var isDir = nativeFileSupport.isDirectory(path);
+					this.entries[i] = isDir ? new DirectoryEntry(this.parent, names[i]) : new FileEntry(this.parent, names[i]);
+				}
+				success(this.entries);
+			}	
+		}
+	}
+	
+	FileEntry = function(parent, name){
+		window.Entry.call(this, parent, name, true);
+	}
+	FileEntry.prototype ={
+		file : function(success){
+		    var blob;
+			var size = nativeFileSupport.getFileSize(this.fullPath);
+			if (size){
+				var byteArray = nativeFileSupport.contentsAtPath(this.fullPath);
+				//var jsArray = new Array(byteArray.length);
+				//for (var i = 0; i < byteArray.length; i++){
+				//	jsArray[i] = byteArray[i];
+				//}
+				
+				var bytes = new Int8Array(byteArray);
+				
+				blob = bytes.buffer;
+				//blob.size = size;
+			
+			}
+			else{
+				blob = new ArrayBuffer();
+				//blob.size= 0;
+			}
+			var bb = new BlobBuilder();
+			bb.append(blob);
+			var b = bb.getBlob();
+			b.size = size;
+			success(b);
+			
+		},
+		createWriter: function(success){
+			success(new FileWriter(this.fullPath));
+		}
+	}
+	
+	FileEntry.prototype.__proto__ = Entry.prototype;
+	
+	
+	/*BlobBuilder = function(){
+		this.stuff = [];
+	}
+	BlobBuilder.prototype = {
+		append : function(buf){
+			stuff.push(buf);
+		},
+		getBlob : function(){
+			return stuff;
+		}
+	}*/
+	
+		
+	FileWriter = function(path){
+		this.path = path;
+	}
+	FileWriter.prototype = {
+		write : function(blob){
+			var reader = new FileReader();
+			var thiz = this;
+			reader.onloadend = function(e){
+				var data = Array.prototype.slice.call(new Uint8Array(reader.result), 0);
+				//assumes one append call before writing
+				nativeFileSupport.saveBlobToFile(thiz.path, data);
+				if (thiz.onwriteend){
+					thiz.onwriteend();
+				}
+			}
+			reader.readAsArrayBuffer(blob);
+		}
+	}
+	
+	/*FileReader = function(){
+	}
+	
+	FileReader.prototype = {
+		readAsArrayBuffer : function(entry){
+			if (entry.isFile){
+				var byteArray = nativeFileSystem.contentsAtPath(entry._fullPath());
+			
+				var bytes = new Int8Array(bytesArray);
+				
+				this.result = bytes.buffer;
+				this.onloadend();
+			}
+			else{
+			
+			}
+		}
+	}*/
+	window.requestFileSystem = function(type, size, successCallback, errorCallback){
+		var root = new DirectoryEntry(null, "");//._make();
+		root.root = root;
+		successCallback(root);
+	}
+	window.BlobBuilder = WebKitBlobBuilder;
+}else{
+	window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
+}
+if (!window.BlobBuilder){
+	window.BlobBuilder = WebKitBlobBuilder;
+}

File FileWatcher.js

+var FileWatcher = function(tabId, project, path){
+	this.tabId = tabId;
+	this.project = project;
+	this.recentUpdateHandler = new RecentUpdateHandler(2000);
+	nativeFileSupport.watchDirectory(tabId.toString(), path, this.fileChanged.bind(this));
+}
+
+FileWatcher.prototype = {
+	fileChanged : function(path){
+		if (this.isMyChange(path)){
+			return;
+		}
+		var urls = this.project.urlsForPath(path)
+		if (urls){
+			var port = chrome.tabs.connect(this.tabId, {name: 'fileChange'});
+			var ran = Math.round(Math.random()*10000000);
+			urls.asyncEach(function(url, done){
+				$.ajax({type: 'GET',
+						url: url + '?r=' + ran,
+						dataType: 'text',
+						success: function(data){
+							port.postMessage({url: url, content: data});
+							done();
+						},
+						error: done});
+			}, 
+			function(){
+				port.disconnect();
+			});
+		}
+	},
+	isMyChange : function(path){
+		return this.recentUpdateHandler.isRecentUpdate(path);
+	},
+	addChangedByMe : function(path){
+		this.recentUpdateHandler.addRecentUpdate(path);
+	},
+	stopWatching : function(){
+		nativeFileSupport.stopWatching(this.tabId.toString());
+	}
+}
+var logMessage = function(){};
+var logError = function(){};

File ProjectSelectScreen.js

+WebEditor.ProjectTypes = [];
+WebEditor.ProjectSelectScreen = function(){
+    
+    WebInspector.HelpScreen.call(this, WebInspector.UIString("Setup Project"));
+    
+    var contentDiv = document.createElement('div'); 
+    
+    var p = document.createElement('p');
+    var fieldsetElement = document.createElement("fieldset");
+    fieldsetElement.createChild("label").textContent = "Project Type";
+    var projectTypes = WebEditor.ProjectTypes;
+    
+    var select = document.createElement("select");
+    for (var i = 0; i < projectTypes.length; ++i) {
+        var projectType = projectTypes[i];
+        select.add(new Option(projectType.name, i));
+    }
+    fieldsetElement.appendChild(select);
+    p.appendChild(fieldsetElement);
+    contentDiv.appendChild(p);
+    
+    p = document.createElement('p');
+    fieldsetElement = document.createElement("fieldset");
+    fieldsetElement.createChild("label").textContent = "Root Directory";
+    var button = document.createElement('button');
+    button.addEventListener('click', this.launchFileSelect.bind(this));
+    button.textContent = "Browse";
+    //contentDiv.appendChild(button);
+    fieldsetElement.appendChild(button);
+    p.appendChild(fieldsetElement);
+    contentDiv.appendChild(p);
+    this.contentElement.appendChild(contentDiv);
+}
+
+WebEditor.ProjectSelectScreen.prototype = {
+    launchFileSelect : function(callback){
+        if (window.nativeFileSupport){
+            nativeFileSupport.launchFileSelect(callback);
+        }
+    }
+}
+
+WebEditor.ProjectSelectScreen.prototype.__proto__ = WebInspector.HelpScreen.prototype;

File RecentUpdateHandler.js

+var RecentUpdateHandler = function(timeout){
+	this.timeout = timeout;
+	this.recentUpdates = [];
+};
+
+RecentUpdateHandler.prototype = {
+	addRecentUpdate : function(key){
+		this.recentUpdates.push({key:key, time:new Date().getTime()});
+	},
+	
+	isRecentUpdate : function(key){
+		var t = new Date().getTime(),
+		    replace = [],
+		    retVal = false;
+		for (var i = 0; i < this.recentUpdates.length; i++){
+			var update = this.recentUpdates[i];
+			if (key === update.key && t - update.time < this.timeout){
+				retVal = true;
+			}
+			else if (t - update.time < this.timeout){
+				replace.push(update);
+			}
+		}
+		this.recentUpdates = replace;
+		return retVal;
+	}
+}

File ResourceChecker.js

+
+var matchedUrls = {};
+var navListenerRegistered = false;
+var resourceCache = [];
+var recentUpdateHandler = new RecentUpdateHandler(500);
+
+var matchResourcesWithProject = function(resources){
+	var confirmResourceContent = function(resource){
+		resource.getContent(function(content){
+			backgroundMsgSupport.checkResourceContent(resource.url, content, function(data){
+				if (data.success){
+					logMessage(data.msg);
+					matchedUrls[resource.url] = true;
+				}
+				else{
+					logError(data.msg);
+				}
+			});
+		});
+	};
+	
+	backgroundMsgSupport.checkResources(resources, function(data){
+		for (var i = 0; i < data.length; i++){
+			if (data[i]){
+				confirmResourceContent(resources[i]);
+			}
+		}
+	});
+}
+
+var checkResources = function(callback){
+	matchedUrls = {};
+
+	chrome.devtools.inspectedWindow.getResources(function(resources){
+		resourceCache = resources;
+		matchResourcesWithProject(resources);
+	});
+}
+var registerNavListener = function(){
+	if (!navListenerRegistered){
+		chrome.devtools.network.onNavigated.addListener(function(){
+			console.log('page navigated');
+			backgroundMsgSupport.pageChanged(function(){
+				checkResources();
+			});
+		});
+	}
+	navListenerRegistered = true;
+}
+chrome.devtools.inspectedWindow.onResourceContentCommitted.addListener(function(resource, content){
+	if (matchedUrls[resource.url] && !recentUpdateHandler.isRecentUpdate(resource.url)){
+		backgroundMsgSupport.updateResource(resource.url, content);
+	}
+});
+
+var fileChangeListener = function(data){
+	var setContent = function(resource, data){
+		resource.getContent(function(content){
+			if (data.content != content){
+				recentUpdateHandler.addRecentUpdate(resource.url);
+				resource.setContent(data.content, true);
+			}
+		});
+	};
+	for (var i = 0; i < resourceCache.length; i++){
+		if (resourceCache[i].url === data.url){
+			setContent(resourceCache[i], data);
+		}
+	}
+};
+chrome.extension.onConnect.addListener(function(port) {
+	if (port.name == 'fileChange'){
+		port.onMessage.addListener(fileChangeListener);
+	}
+});

File background.html

+<!doctype html>
+<html>
+  <head>
+    <title>Background Page</title>
+    	<script>
+    		ProjectTypes = [];
+    		var projectsByTab= {};
+    		var watchersByTab={};
+    	</script>
+    	<script src="file_utils.js"></script>
+		<script src="AtlassianPluginProject.js"></script>
+		<script src="zepto1.0rc1.js"></script>
+		<script src="RecentUpdateHandler.js"></script>
+		<script src="FileWatcher.js"></script>
+    	<embed type="application/x-npapifileioforchrome" id="pluginId" style="position:absolute; top:0px;left:-10000px;width:0px;height:0px;">
+		<script>
+		  window.nativeFileSupport = document.getElementById("pluginId");
+		</script>
+		<script src="FauxFilesystem.js"></script>
+		<script>
+		  
+		  chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
+		  		var currentProject = projectsByTab[sender.tab.id];
+				if (request.key == 'ProjectTypes'){
+					//var cleanResponse = [];
+					//for (var i = 0; i < ProjectTypes.length){
+					//	cleanResponse.push({name: ProjectTypes[i].name, locationType: ProjectTypes[i].locationType});
+					//}
+					sendResponse(ProjectTypes);
+				}
+				else if (request.key == 'launchFileSelect')
+				{
+					nativeFileSupport.launchFileSelect(function(path){
+						if (path && path.length){
+							var projectType = ProjectTypes[request.index];
+							window.requestFileSystem(window.PERMANENT, 5*1024*1024*1024, function(fs){
+								fs.root.getDirectory(path, {create:false}, function(dir){
+									projectType.createProject(dir,function(project, error){
+										currentProject = project;
+										projectsByTab[sender.tab.id] = currentProject;
+										sendResponse({path:path, error:error});
+									});
+								});
+							});
+						}
+					});
+				}
+				else if (request.key == 'checkResources'){
+					var urls = request.resources;
+					var retVal = [];
+					if (currentProject){
+						for (var i = 0; i < urls.length; i++){
+							if (urls[i].type == 'script' || urls[i].type == 'stylesheet'){
+								retVal.push(currentProject.isProjectUrl(urls[i].url));
+							}
+							else{
+								retVal.push(false);
+							}
+						}
+					}
+					sendResponse(retVal);
+				}
+				else if (request.key == 'checkResourceContent'){
+					var resources = request.content;
+					if (currentProject){
+						currentProject.matchContents(request.url, request.content, function(success, msg){
+							sendResponse({success:success, msg:msg});
+						});
+					}
+				}
+				else if (request.key == 'updateResource'){
+					var currentWatcher = watchersByTab[sender.tab.id];
+					currentProject.commitResource(request.url, request.content, currentWatcher,function(){
+						sendResponse();
+					});
+				}
+				else if (request.key == 'pageChanged'){
+					currentProject.resetUrls()
+					sendResponse();
+				}
+				else if (request.key == 'watchDirectory'){
+					if (!watchersByTab[sender.tab.id]){
+						watchersByTab[sender.tab.id] = new FileWatcher(sender.tab.id, currentProject, request.path);
+					}
+				}
+				else{
+					sendResponse({});
+				}
+				
+		  });
+		  
+		  chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
+		  		if (projectsByTab[tabId])
+		  			delete projectsByTab[tabId];
+		  			
+		  		var watcher = watchersByTab[tabId];
+		  		if (watcher){
+		  			watcher.stopWatching();
+		  			delete watchersByTab[tabId];	
+		  		}
+		  });
+		</script>
+
+  </head>
+  <body>
+  </body>
+</html>

File devtools.html

+<html>
+<body>
+<script src="devtools.js"></script>
+</body>
+</html>
+chrome.devtools.panels.create('Local Project', 'icon.png', 'editorpanel.html');

File editorpanel.css

Empty file added.

File editorpanel.html

+<html>
+<head>
+	<link rel="stylesheet" type="text/css" href="editorpanel.css" />
+
+	<script src="zepto1.0rc1.js"></script>
+	<script src="NativeFileSupportShim.js"></script>
+	<script src="Logger.js"></script>
+	<script src="RecentUpdateHandler.js"></script>
+	<script src="ResourceChecker.js"></script>
+	<script>
+		$.get('http://www.atlassian.com', function(data){
+			var x = 0;
+		});
+		$(document).ready(function(){
+			
+			var typeSelect = document.getElementById('project-type');
+			
+			backgroundMsgSupport.getProjectTypes(function(projectTypes){
+				for (var i = 0; i < projectTypes.length; ++i) {
+					var projectType = projectTypes[i];
+					typeSelect.add(new Option(projectType.name, i));
+				}
+			});
+			$(typeSelect).on('change', function(e){
+				var index = typeSelect.selectedIndex;
+				var projectType = projectTypes[index];
+				if (projectType.locationType = 'local'){
+					var fileSelect = document.getElementById('file-select');
+					fileSelect.style.display = '';
+					
+					var $fileSelect = $(fileSelect);
+					$fileSelect.off('file-change');
+					$fileSelect.on('file-change', function(e, filePath){
+						requestFs(function(fs){
+							fs.root.getDirectory(filePath,{create:false}, function(dir){
+								projectType.load(dir);
+							});
+						});
+					});
+				}
+			});
+			$('#native-browse').on('click', function(e){
+				var index = typeSelect.selectedIndex;
+				backgroundMsgSupport.launchFileSelect(index, function(result){
+					if (result.path && result.path.length){
+						$('#local-file-path').text(result.path);
+						if (result.error){
+							logError(result.error);
+						}
+						else{
+							checkResources();
+							registerNavListener();
+							backgroundMsgSupport.watchDirectory(result.path, function(){});
+						}
+					}
+				});
+			});
+		});
+	</script>
+</head>
+<body>
+	<div id="project-select-form">
+		<p>
+			<fieldset>
+				<label>Project Type:</label>
+				<select id="project-type"></select>
+			</fieldset>
+		</p>
+		<p id="file-select" style="display:none">
+			<fieldset>
+				<label>Select Root Directory</label><label id="local-file-path"></label>
+				<button id="native-browse">Browse</button>
+			</fieldset>
+		</p>
+	</div>
+</body>
+</html>

File file_utils.js

+Array.prototype.asyncEach = function(func, callback){
+	if (this.length == 0){
+		callback();
+		return;
+	}
+	var list = this,
+	    counter = {x:0, end:list.length};
+	
+	var finish = function(){
+		counter.x += 1;
+		if (counter.x == counter.end){
+			callback();
+		}
+	}
+	
+	var addItem = function (item){
+		counter.end += 1;
+		func.call(list, item, done, addItem);
+	}
+	
+	for (var i = 0; i < list.length; i++){
+		func.call(list, list[i], finish, i, addItem);
+	}
+}
+
+Gito = window.Gito || {};
+
+Gito.FileUtils = (function(){
+	
+	var toArray = function(list) {
+		return Array.prototype.slice.call(list || [], 0);
+	}
+	
+	
+	var makeFile = function(root, filename, contents, callback){
+		root.getFile(filename, {create:true}, function(fileEntry){
+			fileEntry.createWriter(function(writer){
+				writer.onwriteend = function(){
+					if (callback)
+						callback();
+				}
+				var bb = new BlobBuilder();
+				bb.append(contents);
+				writer.write(bb.getBlob());
+			});
+		});
+	}
+	
+	var makeDir = function(root, dirname, callback){
+		root.getDirectory(dirname, {create:true},callback);
+	}
+	
+	return {
+		mkdirs : function(root, dirname, callback){
+			var pathParts;
+			if (dirname instanceof Array){
+				pathParts = dirname;
+			}
+			else{
+				pathParts = dirname.split('/');
+			}
+			
+			var makeDirCallback = function(dir){
+				if (pathParts.length){
+					makeDir(dir, pathParts.shift(), makeDirCallback);
+				}
+				else{
+					if (callback)
+						callback(dir);
+				}
+			}
+			makeDirCallback(root);
+		},
+		rmDir : function (root, dirname, callback){
+			root.getDirectory(dirname, {create:true}, function(dirEntry){
+				dirEntry.removeRecursively(callback, Gito.errorHandler);
+			});
+		},
+		rmFile : function(root, filename, callback){
+			root.getFile(filename, {create:true}, function(fileEntry){
+				fileEntry.remove(callback, Gito.errorHandler);
+			});
+		},
+		mkfile : function(root, filename, contents, callback){
+			if (filename.charAt(0) == '/'){
+				filename = filename.substring(1);
+			}
+			var pathParts = filename.split('/');
+			if (pathParts.length > 1){
+				Gito.FileUtils.mkdirs(root, pathParts.slice(0, pathParts.length - 1), function(dir){
+					makeFile(dir, pathParts[pathParts.length - 1], contents, callback);
+				});
+			}
+			else{
+				makeFile(root, filename, contents, callback);
+			}
+		},
+		ls: function(dir, callback){
+			var reader = dir.createReader();
+			var entries = [];
+			
+			var readEntries = function() {
+				reader.readEntries (function(results) {
+					if (!results.length) {
+						callback(entries);
+					} else {
+						entries = entries.concat(toArray(results));
+						readEntries();
+					}
+				}, function(){});
+			}
+			readEntries();
+			
+		},
+		readBlob: function(blob, dataType, callback){
+			var reader = new FileReader();
+			reader.onloadend = function(e){
+				callback(reader.result);
+			}
+			reader["readAs" + dataType](blob);
+		},
+		readFileEntry : function(fileEntry, dataType, callback){
+			fileEntry.file(function(file){
+				Gito.FileUtils.readBlob(file, dataType, callback);
+			});
+		},
+		readFile : function(root, file, dataType, callback, onerror) {
+			
+			root.getFile(file, {create:false}, function(fileEntry){
+				Gito.FileUtils.readFileEntry(fileEntry, dataType, callback);
+			}, onerror ? onerror : Gito.errorHandler);
+		}
+	
+	};
+}
+)();

File icon.png

Added
New image

File manifest.json

+{
+  "name": "Devtools-Tincr",
+  "description": "Plugin to allow editing of local files from Chrome developer tools",
+  "version": "1",
+  "devtools_page": "devtools.html",
+  "permissions" : ["http://*/"],
+  "background_page": "background.html",
+  "plugins": [
+    { "path": "NPAPIFileIOforChrome.plugin", "public": false }
+  ]
+}

File nativeFileSupportShim.js

+
+var backgroundMsgSupport = {
+	launchFileSelect : function(index, callback){
+		chrome.extension.sendRequest({key: 'launchFileSelect', index: index}, function(response){
+			callback(response);
+		});
+	},
+	getProjectTypes : function(callback){
+		chrome.extension.sendRequest({key : 'ProjectTypes'}, function(response){
+			callback(response);
+		});
+	},
+	checkResources : function(resources, callback){
+		chrome.extension.sendRequest({key : 'checkResources', resources: resources}, function(response){
+			callback(response);
+		});
+	},
+	checkResourceContent : function(url, content, callback){
+		chrome.extension.sendRequest({key : 'checkResourceContent', url: url, content:content}, function(response){
+			callback(response);
+		});
+	},
+	updateResource : function(url, content, callback){
+		chrome.extension.sendRequest({key : 'updateResource', url: url, content:content}, function(response){
+			callback(response);
+		});
+	},
+	pageChanged : function(callback){
+		chrome.extension.sendRequest({key: 'pageChanged'}, callback);
+	},
+	watchDirectory : function(fullPath, callback){
+		chrome.extension.sendRequest({key: 'watchDirectory', path : fullPath}, function(response){
+			callback(response);
+		});
+	}
+}

File untitled text 13

Empty file added.

File zepto1.0rc1.js

+/* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */
+(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e<d)e in c&&(f=b.call(a,f,c[e],e,c)),e++;return f})})();var Zepto=function(){function A(a){return v.call(a)=="[object Function]"}function B(a){return a instanceof Object}function C(b){var c,d;if(v.call(b)!=="[object Object]")return!1;d=A(b.constructor)&&b.constructor.prototype;if(!d||!hasOwnProperty.call(d,"isPrototypeOf"))return!1;for(c in b);return c===a||hasOwnProperty.call(b,c)}function D(a){return a instanceof Array}function E(a){return typeof a.length=="number"}function F(b){return b.filter(function(b){return b!==a&&b!==null})}function G(a){return a.length>0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e<a.length;e++)c=b(a[e],e),c!=null&&d.push(c);else for(f in a)c=b(a[f],f),c!=null&&d.push(c);return G(d)},c.each=function(a,b){var c,d;if(E(a)){for(c=0;c<a.length;c++)if(b.call(a[c],c,a[c])===!1)return a}else for(d in a)if(b.call(a[d],d,a[d])===!1)return a;return a},c.fn={forEach:e.forEach,reduce:e.reduce,push:e.push,indexOf:e.indexOf,concat:e.concat,map:function(a){return c.map(this,function(b,c){return a.call(b,c,b)})},slice:function(){return c(f.apply(this,arguments))},ready:function(a){return r.test(g.readyState)?a(c):g.addEventListener("DOMContentLoaded",function(){a(c)},!1),this},get:function(b){return b===a?f.call(this):this[b]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return this.forEach(function(b,c){a.call(b,c,b)}),this},filter:function(a){return c([].filter.call(this,function(b){return w.matches(b,a)}))},add:function(a,b){return c(y(this.concat(c(a,b))))},is:function(a){return this.length>0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h<a.length;h++){var i=a[f?a.length-h-1:h];O(i,function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&window.eval.call(window,a.innerHTML)}),e&&c<d-1&&(i=i.cloneNode(!0)),N(b,g,i)}})},c.fn[b%2?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),w.Z.prototype=c.fn,w.camelize=x,w.uniq=y,c.zepto=w,c}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(a){function f(a){return a._zid||(a._zid=d++)}function g(a,b,d,e){b=h(b);if(b.ns)var g=i(b.ns);return(c[f(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||g.test(a.ns))&&(!d||f(a.fn)===f(d))&&(!e||a.sel==e)})}function h(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function i(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function j(b,c,d){a.isObject(b)?a.each(b,d):b.split(/\s/).forEach(function(a){d(a,c)})}function k(b,d,e,g,i,k){k=!!k;var l=f(b),m=c[l]||(c[l]=[]);j(d,e,function(c,d){var e=i&&i(d,c),f=e||d,j=function(a){var c=f.apply(b,[a].concat(a.data));return c===!1&&a.preventDefault(),c},l=a.extend(h(c),{fn:d,proxy:j,sel:g,del:e,i:m.length});m.push(l),b.addEventListener(l.e,j,k)})}function l(a,b,d,e){var h=f(a);j(b||"",d,function(b,d){g(a,b,d,e).forEach(function(b){delete c[h][b.i],a.removeEventListener(b.e,b.proxy,!1)})})}function p(b){var c=a.extend({originalEvent:b},b);return a.each(o,function(a,d){c[a]=function(){return this[d]=m,b[a].apply(b,arguments)},c[d]=n}),c}function q(a){if(!("defaultPrevented"in a)){a.defaultPrevented=!1;var b=a.preventDefault;a.preventDefault=function(){this.defaultPrevented=!0,b.call(this)}}}var b=a.zepto.qsa,c={},d=1,e={};e.click=e.mousedown=e.mouseup=e.mousemove="MouseEvents",a.event={add:k,remove:l},a.proxy=function(b,c){if(a.isFunction(b)){var d=function(){return b.apply(c,arguments)};return d._zid=f(b),d}if(typeof c=="string")return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b){return this.each(function(){k(this,a,b)})},a.fn.unbind=function(a,b){return this.each(function(){l(this,a,b)})},a.fn.one=function(a,b){return this.each(function(c,d){k(this,a,b,null,function(a,b){return function(){var c=a.apply(d,arguments);return l(d,b,a),c}})})};var m=function(){return!0},n=function(){return!1},o={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(b,c,d){var e=!1;if(c=="blur"||c=="focus")a.iswebkit?c=c=="blur"?"focusout":c=="focus"?"focusin":c:e=!0;return this.each(function(f,g){k(g,c,d,b,function(c){return function(d){var e,f=a(d.target).closest(b,g).get(0);if(f)return e=a.extend(p(d),{currentTarget:f,liveFired:g}),c.apply(f,[e].concat([].slice.call(arguments,1)))}},e)})},a.fn.undelegate=function(a,b,c){return this.each(function(){l(this,b,c,a)})},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,d){return c==undefined||a.isFunction(c)?this.bind(b,c):this.delegate(c,b,d)},a.fn.off=function(b,c,d){return c==undefined||a.isFunction(c)?this.unbind(b,c):this.undelegate(c,b,d)},a.fn.trigger=function(b,c){return typeof b=="string"&&(b=a.Event(b)),q(b),b.data=c,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(b)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,h){d=p(typeof b=="string"?a.Event(b):b),d.data=c,d.target=h,a.each(g(h,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){if(a)this.bind(b,a);else if(this.length)try{this.get(0)[b]()}catch(c){}return this}}),a.Event=function(a,b){var c=document.createEvent(e[a]||"Events"),d=!0;if(b)for(var f in b)f=="bubbles"?d=!!b[f]:c[f]=b[f];return c.initEvent(a,d,!0,null,null,null,null,null,null,null,null,null,null,null,null),c}}(Zepto),function(a){function b(a){var b=this.os={},c=this.browser={},d=a.match(/WebKit\/([\d.]+)/),e=a.match(/(Android)\s+([\d.]+)/),f=a.match(/(iPad).*OS\s([\d_]+)/),g=!f&&a.match(/(iPhone\sOS)\s([\d_]+)/),h=a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),i=h&&a.match(/TouchPad/),j=a.match(/Kindle\/([\d.]+)/),k=a.match(/Silk\/([\d._]+)/),l=a.match(/(BlackBerry).*Version\/([\d.]+)/);if(c.webkit=!!d)c.version=d[1];e&&(b.android=!0,b.version=e[2]),g&&(b.ios=b.iphone=!0,b.version=g[2].replace(/_/g,".")),f&&(b.ios=b.ipad=!0,b.version=f[2].replace(/_/g,".")),h&&(b.webos=!0,b.version=h[2]),i&&(b.touchpad=!0),l&&(b.blackberry=!0,b.version=l[2]),j&&(b.kindle=!0,b.version=j[1]),k&&(c.silk=!0,c.version=k[1]),!k&&b.android&&a.match(/Kindle Fire/)&&(c.silk=!0)}b.call(a,navigator.userAgent),a.__detect=b}(Zepto),function(a,b){function l(a){return a.toLowerCase()}function m(a){return d?d+a:l(a)}var c="",d,e,f,g={Webkit:"webkit",Moz:"",O:"o",ms:"MS"},h=window.document,i=h.createElement("div"),j=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,k={};a.each(g,function(a,e){if(i.style[a+"TransitionProperty"]!==b)return c="-"+l(a)+"-",d=e,!1}),k[c+"transition-property"]=k[c+"transition-duration"]=k[c+"transition-timing-function"]=k[c+"animation-name"]=k[c+"animation-duration"]="",a.fx={off:d===b&&i.style.transitionProperty===b,cssPrefix:c,transitionEnd:m("TransitionEnd"),animationEnd:m("AnimationEnd")},a.fn.animate=function(b,c,d,e){return a.isObject(c)&&(d=c.easing,e=c.complete,c=c.duration),c&&(c/=1e3),this.anim(b,c,d,e)},a.fn.anim=function(d,e,f,g){var h,i={},l,m=this,n,o=a.fx.transitionEnd;e===b&&(e=.4),a.fx.off&&(e=0);if(typeof d=="string")i[c+"animation-name"]=d,i[c+"animation-duration"]=e+"s",o=a.fx.animationEnd;else{for(l in d)j.test(l)?(h||(h=[]),h.push(l+"("+d[l]+")")):i[l]=d[l];h&&(i[c+"transform"]=h.join(" ")),!a.fx.off&&typeof d=="object"&&(i[c+"transition-property"]=Object.keys(d).join(", "),i[c+"transition-duration"]=e+"s",i[c+"transition-timing-function"]=f||"linear")}return n=function(b){if(typeof b!="undefined"){if(b.target!==b.currentTarget)return;a(b.target).unbind(o,arguments.callee)}a(this).css(k),g&&g.call(this)},e>0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto);