mirror of
				https://github.com/0xFEEDC0DE64/arduino-esp32.git
				synced 2025-10-31 14:11:42 +01:00 
			
		
		
		
	
		
			
	
	
		
			675 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
		
		
			
		
	
	
			675 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
|   | <!DOCTYPE html> | ||
|  | <html lang="en"> | ||
|  |   <head> | ||
|  |     <title>SD Editor</title> | ||
|  |     <style type="text/css" media="screen"> | ||
|  |       .contextMenu { | ||
|  |         z-index: 300; | ||
|  |         position: absolute; | ||
|  |         left: 5px; | ||
|  |         border: 1px solid #444; | ||
|  |         background-color: #F5F5F5; | ||
|  |         display: none; | ||
|  |         box-shadow: 0 0 10px rgba( 0, 0, 0, .4 ); | ||
|  |         font-size: 12px; | ||
|  |         font-family: sans-serif; | ||
|  |         font-weight:bold; | ||
|  |       } | ||
|  |       .contextMenu ul { | ||
|  |         list-style: none; | ||
|  |         top: 0; | ||
|  |         left: 0; | ||
|  |         margin: 0; | ||
|  |         padding: 0; | ||
|  |       } | ||
|  |       .contextMenu li { | ||
|  |         position: relative; | ||
|  |         min-width: 60px; | ||
|  |         cursor: pointer; | ||
|  |       } | ||
|  |       .contextMenu span { | ||
|  |         color: #444; | ||
|  |         display: inline-block; | ||
|  |         padding: 6px; | ||
|  |       } | ||
|  |       .contextMenu li:hover { background: #444; } | ||
|  |       .contextMenu li:hover span { color: #EEE; } | ||
|  |      | ||
|  |       .css-treeview ul, .css-treeview li { | ||
|  |         padding: 0; | ||
|  |         margin: 0; | ||
|  |         list-style: none; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview input { | ||
|  |         position: absolute; | ||
|  |         opacity: 0; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview { | ||
|  |         font: normal 11px Verdana, Arial, Sans-serif; | ||
|  |         -moz-user-select: none; | ||
|  |         -webkit-user-select: none; | ||
|  |         user-select: none; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview span { | ||
|  |         color: #00f; | ||
|  |         cursor: pointer; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview span:hover { | ||
|  |         text-decoration: underline; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview input + label + ul { | ||
|  |         margin: 0 0 0 22px; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview input ~ ul { | ||
|  |         display: none; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview label, .css-treeview label::before { | ||
|  |         cursor: pointer; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview input:disabled + label { | ||
|  |         cursor: default; | ||
|  |         opacity: .6; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview input:checked:not(:disabled) ~ ul { | ||
|  |         display: block; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview label, .css-treeview label::before { | ||
|  |         background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAYAAAAFOewUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApxJREFUeNrslM1u00AQgGdthyalFFOK+ClIIKQKyqUVQvTEE3DmAhLwAhU8QZoH4A2Q2gMSFace4MCtJ8SPBFwAkRuiHKpA6sRN/Lu7zG5i14kctaUqRGhGXnu9O/Pt7MzsMiklvF+9t2kWTDvyIrAsA0aKRRi1T0C/hJ4LUbt5/8rNpWVlp8RSr9J40b48fxFaTQ9+ft8EZ6MJYb0Ok+dnYGpmPgXwKIAvLx8vYXc5GdMAQJgQEkpjRTh36TS2U+DWW/D17WuYgm8pwJyY1npZsZKOxImOV1I/h4+O6vEg5GCZBpgmA6hX8wHKUHDRBXQYicQ4rlc3Tf0VMs8DHBS864F2YFspjgUYjKX/Az3gsdQd2eeBHwmdGWXHcgBGSkZXOXohcEXebRoQcAgjqediNY+AVyu3Z3sAKqfKoGMsewBeEIOPgQxxPJIjcGH6qtL/0AdADzKGnuuD+2tLK7Q8DhHHbOBW+KEzcHLuYc82MkEUekLiwuvVH+guQBQzOG4XdAb8EOcRcqQvDkY2iCLuxECJ43JobMXoutqGgDa2T7UqLKwt9KRyuxKVByqVXXqIoCCUCAqhUOioTWC7G4TQEOD0APy2/7G2Xpu1J4+lxeQ4TXBbITDpoVelRN/BVFbwu5oMMJUBhoXy5tmdRcMwymP2OLQaLjx9/vnBo6V3K6izATmSnMa0Dq7ferIohJhr1p01zrlz49rZF4OMs8JkX23vVQzYp+wbYGV/KpXKjvspl8tsIKCrMNAYFxj2GKS5ZWxg4ewKsJfaGMIY5KXqPz8LBBj6+yDvVP79+yDp/9F9oIx3OisHWwe7Oal0HxCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgwD8E/BZgAP0qhKj3rXO7AAAAAElFTkSuQmCC") no-repeat; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview label, .css-treeview span, .css-treeview label::before { | ||
|  |         display: inline-block; | ||
|  |         height: 16px; | ||
|  |         line-height: 16px; | ||
|  |         vertical-align: middle; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview label { | ||
|  |         background-position: 18px 0; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview label::before { | ||
|  |         content: ""; | ||
|  |         width: 16px; | ||
|  |         margin: 0 22px 0 0; | ||
|  |         vertical-align: middle; | ||
|  |         background-position: 0 -32px; | ||
|  |       } | ||
|  | 
 | ||
|  |       .css-treeview input:checked + label::before { | ||
|  |         background-position: 0 -16px; | ||
|  |       } | ||
|  | 
 | ||
|  |       /* webkit adjacent element selector bugfix */ | ||
|  |       @media screen and (-webkit-min-device-pixel-ratio:0) | ||
|  |       { | ||
|  |         .css-treeview{ | ||
|  |           -webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s; | ||
|  |         } | ||
|  | 
 | ||
|  |         @-webkit-keyframes webkit-adjacent-element-selector-bugfix  | ||
|  |         { | ||
|  |           from  {  | ||
|  |             padding: 0; | ||
|  |           }  | ||
|  |           to  {  | ||
|  |             padding: 0; | ||
|  |           } | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       #uploader {  | ||
|  |         position: absolute; | ||
|  |         top: 0; | ||
|  |         right: 0; | ||
|  |         left: 0; | ||
|  |         height:28px; | ||
|  |         line-height: 24px; | ||
|  |         padding-left: 10px; | ||
|  |         background-color: #444; | ||
|  |         color:#EEE; | ||
|  |       } | ||
|  |       #tree {  | ||
|  |         position: absolute; | ||
|  |         top: 28px; | ||
|  |         bottom: 0; | ||
|  |         left: 0; | ||
|  |         width:200px; | ||
|  |         padding: 8px; | ||
|  |       } | ||
|  |       #editor, #preview {  | ||
|  |         position: absolute; | ||
|  |         top: 28px; | ||
|  |         right: 0; | ||
|  |         bottom: 0; | ||
|  |         left: 200px; | ||
|  |       } | ||
|  |       #preview { | ||
|  |         background-color: #EEE; | ||
|  |         padding:5px; | ||
|  |       } | ||
|  |     </style> | ||
|  |     <script> | ||
|  |       function createFileUploader(element, tree, editor){ | ||
|  |         var xmlHttp; | ||
|  |         var input = document.createElement("input"); | ||
|  |         input.type = "file"; | ||
|  |         input.multiple = false; | ||
|  |         input.name = "data"; | ||
|  |         document.getElementById(element).appendChild(input); | ||
|  |         var path = document.createElement("input"); | ||
|  |         path.id = "upload-path"; | ||
|  |         path.type = "text"; | ||
|  |         path.name = "path"; | ||
|  |         path.defaultValue = "/"; | ||
|  |         document.getElementById(element).appendChild(path); | ||
|  |         var button = document.createElement("button"); | ||
|  |         button.innerHTML = 'Upload'; | ||
|  |         document.getElementById(element).appendChild(button); | ||
|  |         var mkdir = document.createElement("button"); | ||
|  |         mkdir.innerHTML = 'MkDir'; | ||
|  |         document.getElementById(element).appendChild(mkdir); | ||
|  |         var mkfile = document.createElement("button"); | ||
|  |         mkfile.innerHTML = 'MkFile'; | ||
|  |         document.getElementById(element).appendChild(mkfile); | ||
|  |    | ||
|  |         function httpPostProcessRequest(){ | ||
|  |           if (xmlHttp.readyState == 4){ | ||
|  |             if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText); | ||
|  |             else { | ||
|  |               tree.refreshPath(path.value); | ||
|  |             } | ||
|  |           } | ||
|  |         } | ||
|  |         function createPath(p){ | ||
|  |           xmlHttp = new XMLHttpRequest(); | ||
|  |           xmlHttp.onreadystatechange = httpPostProcessRequest; | ||
|  |           var formData = new FormData(); | ||
|  |           formData.append("path", p); | ||
|  |           xmlHttp.open("PUT", "/edit"); | ||
|  |           xmlHttp.send(formData); | ||
|  |         } | ||
|  |          | ||
|  |         mkfile.onclick = function(e){ | ||
|  |           if(path.value.indexOf(".") === -1) return; | ||
|  |           createPath(path.value); | ||
|  |           editor.loadUrl(path.value); | ||
|  |         }; | ||
|  |         mkdir.onclick = function(e){ | ||
|  |           if(path.value.length < 2) return; | ||
|  |           var dir = path.value | ||
|  |           if(dir.indexOf(".") !== -1){ | ||
|  |             if(dir.lastIndexOf("/") === 0) return; | ||
|  |             dir = dir.substring(0, dir.lastIndexOf("/")); | ||
|  |           } | ||
|  |           createPath(dir); | ||
|  |         }; | ||
|  |         button.onclick = function(e){ | ||
|  |           if(input.files.length === 0){ | ||
|  |             return; | ||
|  |           } | ||
|  |           xmlHttp = new XMLHttpRequest(); | ||
|  |           xmlHttp.onreadystatechange = httpPostProcessRequest; | ||
|  |           var formData = new FormData(); | ||
|  |           formData.append("data", input.files[0], path.value); | ||
|  |           xmlHttp.open("POST", "/edit"); | ||
|  |           xmlHttp.send(formData); | ||
|  |         } | ||
|  |         input.onchange = function(e){ | ||
|  |           if(input.files.length === 0) return; | ||
|  |           var filename = input.files[0].name; | ||
|  |           var ext = /(?:\.([^.]+))?$/.exec(filename)[1]; | ||
|  |           var name = /(.*)\.[^.]+$/.exec(filename)[1]; | ||
|  |           if(typeof name !== undefined){ | ||
|  |             if(name.length > 8) name = name.substring(0, 8); | ||
|  |             filename = name; | ||
|  |           } | ||
|  |           if(typeof ext !== undefined){ | ||
|  |             if(ext === "html") ext = "htm"; | ||
|  |             else if(ext === "jpeg") ext = "jpg"; | ||
|  |             filename = filename + "." + ext; | ||
|  |           } | ||
|  |           if(path.value === "/" || path.value.lastIndexOf("/") === 0){ | ||
|  |             path.value = "/"+filename; | ||
|  |           } else { | ||
|  |             path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename; | ||
|  |           } | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       function createTree(element, editor){ | ||
|  |         var preview = document.getElementById("preview"); | ||
|  |         var treeRoot = document.createElement("div"); | ||
|  |         treeRoot.className = "css-treeview"; | ||
|  |         document.getElementById(element).appendChild(treeRoot); | ||
|  |    | ||
|  |         function loadDownload(path){ | ||
|  |           document.getElementById('download-frame').src = path+"?download=true"; | ||
|  |         } | ||
|  |    | ||
|  |         function loadPreview(path){ | ||
|  |           document.getElementById("editor").style.display = "none"; | ||
|  |           preview.style.display = "block"; | ||
|  |           preview.innerHTML = '<img src="'+path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />'; | ||
|  |         } | ||
|  |    | ||
|  |         function fillFolderMenu(el, path){ | ||
|  |           var list = document.createElement("ul"); | ||
|  |           el.appendChild(list); | ||
|  |           var action = document.createElement("li"); | ||
|  |           list.appendChild(action); | ||
|  |           var isChecked = document.getElementById(path).checked; | ||
|  |           var expnd = document.createElement("li"); | ||
|  |           list.appendChild(expnd); | ||
|  |           if(isChecked){ | ||
|  |             expnd.innerHTML = "<span>Collapse</span>"; | ||
|  |             expnd.onclick = function(e){ | ||
|  |               document.getElementById(path).checked = false; | ||
|  |               if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |             }; | ||
|  |             var refrsh = document.createElement("li"); | ||
|  |             list.appendChild(refrsh); | ||
|  |             refrsh.innerHTML = "<span>Refresh</span>"; | ||
|  |             refrsh.onclick = function(e){ | ||
|  |               var leaf = document.getElementById(path).parentNode; | ||
|  |               if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]); | ||
|  |               httpGet(leaf, path); | ||
|  |               if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |             }; | ||
|  |           } else { | ||
|  |             expnd.innerHTML = "<span>Expand</span>"; | ||
|  |             expnd.onclick = function(e){ | ||
|  |               document.getElementById(path).checked = true; | ||
|  |               var leaf = document.getElementById(path).parentNode; | ||
|  |               if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]); | ||
|  |               httpGet(leaf, path); | ||
|  |               if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |             }; | ||
|  |           } | ||
|  |           var upload = document.createElement("li"); | ||
|  |           list.appendChild(upload); | ||
|  |           upload.innerHTML = "<span>Upload</span>"; | ||
|  |           upload.onclick = function(e){ | ||
|  |             var pathEl = document.getElementById("upload-path"); | ||
|  |             if(pathEl){ | ||
|  |               var subPath = pathEl.value; | ||
|  |               if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath; | ||
|  |               else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath; | ||
|  |             } | ||
|  |             if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |           }; | ||
|  |           var delFile = document.createElement("li"); | ||
|  |           list.appendChild(delFile); | ||
|  |           delFile.innerHTML = "<span>Delete</span>"; | ||
|  |           delFile.onclick = function(e){ | ||
|  |             httpDelete(path); | ||
|  |             if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |           }; | ||
|  |         } | ||
|  |    | ||
|  |         function fillFileMenu(el, path){ | ||
|  |           var list = document.createElement("ul"); | ||
|  |           el.appendChild(list); | ||
|  |           var action = document.createElement("li"); | ||
|  |           list.appendChild(action); | ||
|  |           if(isTextFile(path)){ | ||
|  |             action.innerHTML = "<span>Edit</span>"; | ||
|  |             action.onclick = function(e){ | ||
|  |               editor.loadUrl(path); | ||
|  |               if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |             }; | ||
|  |           } else if(isImageFile(path)){ | ||
|  |             action.innerHTML = "<span>Preview</span>"; | ||
|  |             action.onclick = function(e){ | ||
|  |               loadPreview(path); | ||
|  |               if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |             }; | ||
|  |           } | ||
|  |           var download = document.createElement("li"); | ||
|  |           list.appendChild(download); | ||
|  |           download.innerHTML = "<span>Download</span>"; | ||
|  |           download.onclick = function(e){ | ||
|  |             loadDownload(path); | ||
|  |             if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |           }; | ||
|  |           var delFile = document.createElement("li"); | ||
|  |           list.appendChild(delFile); | ||
|  |           delFile.innerHTML = "<span>Delete</span>"; | ||
|  |           delFile.onclick = function(e){ | ||
|  |             httpDelete(path); | ||
|  |             if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el); | ||
|  |           }; | ||
|  |         } | ||
|  |    | ||
|  |         function showContextMenu(e, path, isfile){ | ||
|  |           var divContext = document.createElement("div"); | ||
|  |           var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop; | ||
|  |           var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft; | ||
|  |           var left = e.clientX + scrollLeft; | ||
|  |           var top = e.clientY + scrollTop; | ||
|  |           divContext.className = 'contextMenu'; | ||
|  |           divContext.style.display = 'block'; | ||
|  |           divContext.style.left = left + 'px'; | ||
|  |           divContext.style.top = top + 'px'; | ||
|  |           if(isfile) fillFileMenu(divContext, path); | ||
|  |           else fillFolderMenu(divContext, path); | ||
|  |           document.body.appendChild(divContext); | ||
|  |           var width = divContext.offsetWidth; | ||
|  |           var height = divContext.offsetHeight; | ||
|  |           divContext.onmouseout = function(e){ | ||
|  |             if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){ | ||
|  |               if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext); | ||
|  |             } | ||
|  |           }; | ||
|  |         } | ||
|  |    | ||
|  |         function createTreeLeaf(path, name, size){ | ||
|  |           var leaf = document.createElement("li"); | ||
|  |           leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase(); | ||
|  |           var label = document.createElement("span"); | ||
|  |           label.textContent = name.toLowerCase(); | ||
|  |           leaf.appendChild(label); | ||
|  |           leaf.onclick = function(e){ | ||
|  |             if(isTextFile(leaf.id)){ | ||
|  |               editor.loadUrl(leaf.id); | ||
|  |             } else if(isImageFile(leaf.id)){ | ||
|  |               loadPreview(leaf.id); | ||
|  |             } | ||
|  |           }; | ||
|  |           leaf.oncontextmenu = function(e){ | ||
|  |             e.preventDefault(); | ||
|  |             e.stopPropagation(); | ||
|  |             showContextMenu(e, leaf.id, true); | ||
|  |           }; | ||
|  |           return leaf; | ||
|  |         } | ||
|  |    | ||
|  |         function createTreeBranch(path, name, disabled){ | ||
|  |           var leaf = document.createElement("li"); | ||
|  |           var check = document.createElement("input"); | ||
|  |           check.type = "checkbox"; | ||
|  |           check.id = (((path == "/")?"":path)+"/"+name).toLowerCase(); | ||
|  |           if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled"; | ||
|  |           leaf.appendChild(check); | ||
|  |           var label = document.createElement("label"); | ||
|  |           label.for = check.id; | ||
|  |           label.textContent = name.toLowerCase(); | ||
|  |           leaf.appendChild(label); | ||
|  |           check.onchange = function(e){ | ||
|  |             if(check.checked){ | ||
|  |               if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]); | ||
|  |               httpGet(leaf, check.id); | ||
|  |             } | ||
|  |           }; | ||
|  |           label.onclick = function(e){ | ||
|  |             if(!check.checked){ | ||
|  |               check.checked = true; | ||
|  |               if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]); | ||
|  |               httpGet(leaf, check.id); | ||
|  |             } else { | ||
|  |               check.checked = false; | ||
|  |             } | ||
|  |           }; | ||
|  |           leaf.oncontextmenu = function(e){ | ||
|  |             e.preventDefault(); | ||
|  |             e.stopPropagation(); | ||
|  |             showContextMenu(e, check.id, false); | ||
|  |           } | ||
|  |           return leaf; | ||
|  |         } | ||
|  |    | ||
|  |         function addList(parent, path, items){ | ||
|  |           var list = document.createElement("ul"); | ||
|  |           parent.appendChild(list); | ||
|  |           var ll = items.length; | ||
|  |           for(var i = 0; i < ll; i++){ | ||
|  |             var item = items[i]; | ||
|  |             var itemEl; | ||
|  |             if(item.type === "file"){ | ||
|  |               itemEl = createTreeLeaf(path, item.name, item.size); | ||
|  |             } else { | ||
|  |               itemEl = createTreeBranch(path, item.name); | ||
|  |             } | ||
|  |             list.appendChild(itemEl); | ||
|  |           } | ||
|  |      | ||
|  |         } | ||
|  |    | ||
|  |         function isTextFile(path){ | ||
|  |           var ext = /(?:\.([^.]+))?$/.exec(path)[1]; | ||
|  |           if(typeof ext !== undefined){ | ||
|  |             switch(ext){ | ||
|  |               case "txt": | ||
|  |               case "htm": | ||
|  |               case "html": | ||
|  |               case "js": | ||
|  |               case "json": | ||
|  |               case "c": | ||
|  |               case "h": | ||
|  |               case "cpp": | ||
|  |               case "css": | ||
|  |               case "xml": | ||
|  |                 return true; | ||
|  |             } | ||
|  |           } | ||
|  |           return false; | ||
|  |         } | ||
|  |    | ||
|  |         function isImageFile(path){ | ||
|  |           var ext = /(?:\.([^.]+))?$/.exec(path)[1]; | ||
|  |           if(typeof ext !== undefined){ | ||
|  |             switch(ext){ | ||
|  |               case "png": | ||
|  |               case "jpg": | ||
|  |               case "gif": | ||
|  |               case "ico": | ||
|  |                 return true; | ||
|  |             } | ||
|  |           } | ||
|  |           return false; | ||
|  |         } | ||
|  |    | ||
|  |         this.refreshPath = function(path){ | ||
|  |           if(path.lastIndexOf('/') < 1){ | ||
|  |             path = '/'; | ||
|  |             treeRoot.removeChild(treeRoot.childNodes[0]); | ||
|  |             httpGet(treeRoot, "/"); | ||
|  |           } else { | ||
|  |             path = path.substring(0, path.lastIndexOf('/')); | ||
|  |             var leaf = document.getElementById(path).parentNode; | ||
|  |             if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]); | ||
|  |             httpGet(leaf, path); | ||
|  |           } | ||
|  |         }; | ||
|  |    | ||
|  |         function delCb(path){ | ||
|  |           return function(){ | ||
|  |             if (xmlHttp.readyState == 4){ | ||
|  |               if(xmlHttp.status != 200){ | ||
|  |                 alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText); | ||
|  |               } else { | ||
|  |                 if(path.lastIndexOf('/') < 1){ | ||
|  |                   path = '/'; | ||
|  |                   treeRoot.removeChild(treeRoot.childNodes[0]); | ||
|  |                   httpGet(treeRoot, "/"); | ||
|  |                 } else { | ||
|  |                   path = path.substring(0, path.lastIndexOf('/')); | ||
|  |                   var leaf = document.getElementById(path).parentNode; | ||
|  |                   if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]); | ||
|  |                   httpGet(leaf, path); | ||
|  |                 } | ||
|  |               } | ||
|  |             } | ||
|  |           } | ||
|  |         } | ||
|  |    | ||
|  |         function httpDelete(filename){ | ||
|  |           xmlHttp = new XMLHttpRequest(); | ||
|  |           xmlHttp.onreadystatechange = delCb(filename); | ||
|  |           var formData = new FormData(); | ||
|  |           formData.append("path", filename); | ||
|  |           xmlHttp.open("DELETE", "/edit"); | ||
|  |           xmlHttp.send(formData); | ||
|  |         } | ||
|  |    | ||
|  |         function getCb(parent, path){ | ||
|  |           return function(){ | ||
|  |             if (xmlHttp.readyState == 4){ | ||
|  |               //clear loading | ||
|  |               if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText)); | ||
|  |             } | ||
|  |           } | ||
|  |         } | ||
|  |    | ||
|  |         function httpGet(parent, path){ | ||
|  |           xmlHttp = new XMLHttpRequest(parent, path); | ||
|  |           xmlHttp.onreadystatechange = getCb(parent, path); | ||
|  |           xmlHttp.open("GET", "/list?dir="+path, true); | ||
|  |           xmlHttp.send(null); | ||
|  |           //start loading | ||
|  |         } | ||
|  |    | ||
|  |         httpGet(treeRoot, "/"); | ||
|  |         return this; | ||
|  |       } | ||
|  | 
 | ||
|  |       function createEditor(element, file, lang, theme, type){ | ||
|  |         function getLangFromFilename(filename){ | ||
|  |           var lang = "plain"; | ||
|  |           var ext = /(?:\.([^.]+))?$/.exec(filename)[1]; | ||
|  |           if(typeof ext !== undefined){ | ||
|  |             switch(ext){ | ||
|  |               case "txt": lang = "plain"; break; | ||
|  |               case "htm": lang = "html"; break; | ||
|  |               case "js": lang = "javascript"; break; | ||
|  |               case "c": lang = "c_cpp"; break; | ||
|  |               case "cpp": lang = "c_cpp"; break; | ||
|  |               case "css": | ||
|  |               case "scss": | ||
|  |               case "php": | ||
|  |               case "html": | ||
|  |               case "json": | ||
|  |               case "xml": | ||
|  |                 lang = ext; | ||
|  |             } | ||
|  |           } | ||
|  |           return lang; | ||
|  |         } | ||
|  |    | ||
|  |         if(typeof file === "undefined") file = "/index.htm"; | ||
|  |    | ||
|  |         if(typeof lang === "undefined"){ | ||
|  |           lang = getLangFromFilename(file); | ||
|  |         } | ||
|  |    | ||
|  |         if(typeof theme === "undefined") theme = "textmate"; | ||
|  |    | ||
|  |         if(typeof type === "undefined"){ | ||
|  |           type = "text/"+lang; | ||
|  |           if(lang === "c_cpp") type = "text/plain"; | ||
|  |         } | ||
|  |    | ||
|  |         var xmlHttp = null; | ||
|  |         var editor = ace.edit(element); | ||
|  |    | ||
|  |         //post | ||
|  |         function httpPostProcessRequest(){ | ||
|  |           if (xmlHttp.readyState == 4){ | ||
|  |             if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText); | ||
|  |           } | ||
|  |         } | ||
|  |         function httpPost(filename, data, type){ | ||
|  |           xmlHttp = new XMLHttpRequest(); | ||
|  |           xmlHttp.onreadystatechange = httpPostProcessRequest; | ||
|  |           var formData = new FormData(); | ||
|  |           formData.append("data", new Blob([data], { type: type }), filename); | ||
|  |           xmlHttp.open("POST", "/edit"); | ||
|  |           xmlHttp.send(formData); | ||
|  |         } | ||
|  |         //get | ||
|  |         function httpGetProcessRequest(){ | ||
|  |           if (xmlHttp.readyState == 4){ | ||
|  |             document.getElementById("preview").style.display = "none"; | ||
|  |             document.getElementById("editor").style.display = "block"; | ||
|  |             if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText); | ||
|  |             else editor.setValue(""); | ||
|  |             editor.clearSelection(); | ||
|  |           } | ||
|  |         } | ||
|  |         function httpGet(theUrl){ | ||
|  |             xmlHttp = new XMLHttpRequest(); | ||
|  |             xmlHttp.onreadystatechange = httpGetProcessRequest; | ||
|  |             xmlHttp.open("GET", theUrl, true); | ||
|  |             xmlHttp.send(null); | ||
|  |         } | ||
|  |    | ||
|  |         if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang); | ||
|  |         editor.setTheme("ace/theme/"+theme); | ||
|  |         editor.$blockScrolling = Infinity; | ||
|  |         editor.getSession().setUseSoftTabs(true); | ||
|  |         editor.getSession().setTabSize(2); | ||
|  |         editor.setHighlightActiveLine(true); | ||
|  |         editor.setShowPrintMargin(false); | ||
|  |         editor.commands.addCommand({ | ||
|  |             name: 'saveCommand', | ||
|  |             bindKey: {win: 'Ctrl-S',  mac: 'Command-S'}, | ||
|  |             exec: function(editor) { | ||
|  |               httpPost(file, editor.getValue()+"", type); | ||
|  |             }, | ||
|  |             readOnly: false | ||
|  |         }); | ||
|  |         editor.commands.addCommand({ | ||
|  |             name: 'undoCommand', | ||
|  |             bindKey: {win: 'Ctrl-Z',  mac: 'Command-Z'}, | ||
|  |             exec: function(editor) { | ||
|  |               editor.getSession().getUndoManager().undo(false); | ||
|  |             }, | ||
|  |             readOnly: false | ||
|  |         }); | ||
|  |         editor.commands.addCommand({ | ||
|  |             name: 'redoCommand', | ||
|  |             bindKey: {win: 'Ctrl-Shift-Z',  mac: 'Command-Shift-Z'}, | ||
|  |             exec: function(editor) { | ||
|  |               editor.getSession().getUndoManager().redo(false); | ||
|  |             }, | ||
|  |             readOnly: false | ||
|  |         }); | ||
|  |         httpGet(file); | ||
|  |         editor.loadUrl = function(filename){ | ||
|  |           file = filename; | ||
|  |           lang = getLangFromFilename(file); | ||
|  |           type = "text/"+lang; | ||
|  |           if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang); | ||
|  |           httpGet(file); | ||
|  |         } | ||
|  |         return editor; | ||
|  |       } | ||
|  |       function onBodyLoad(){ | ||
|  |         var vars = {}; | ||
|  |         var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; }); | ||
|  |         var editor = createEditor("editor", vars.file, vars.lang, vars.theme); | ||
|  |         var tree = createTree("tree", editor); | ||
|  |         createFileUploader("uploader", tree, editor); | ||
|  |       }; | ||
|  |     </script> | ||
|  |     <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script> | ||
|  |   </head> | ||
|  |   <body onload="onBodyLoad();"> | ||
|  |     <div id="uploader"></div> | ||
|  |     <div id="tree"></div> | ||
|  |     <div id="editor"></div> | ||
|  |     <div id="preview" style="display:none;"></div> | ||
|  |     <iframe id=download-frame style='display:none;'></iframe> | ||
|  |   </body> | ||
|  | </html> |