index.htm 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>SD Editor</title>
  5. <style type="text/css" media="screen">
  6. .contextMenu {
  7. z-index: 300;
  8. position: absolute;
  9. left: 5px;
  10. border: 1px solid #444;
  11. background-color: #F5F5F5;
  12. display: none;
  13. box-shadow: 0 0 10px rgba( 0, 0, 0, .4 );
  14. font-size: 12px;
  15. font-family: sans-serif;
  16. font-weight:bold;
  17. }
  18. .contextMenu ul {
  19. list-style: none;
  20. top: 0;
  21. left: 0;
  22. margin: 0;
  23. padding: 0;
  24. }
  25. .contextMenu li {
  26. position: relative;
  27. min-width: 60px;
  28. cursor: pointer;
  29. }
  30. .contextMenu span {
  31. color: #444;
  32. display: inline-block;
  33. padding: 6px;
  34. }
  35. .contextMenu li:hover { background: #444; }
  36. .contextMenu li:hover span { color: #EEE; }
  37. .css-treeview ul, .css-treeview li {
  38. padding: 0;
  39. margin: 0;
  40. list-style: none;
  41. }
  42. .css-treeview input {
  43. position: absolute;
  44. opacity: 0;
  45. }
  46. .css-treeview {
  47. font: normal 11px Verdana, Arial, Sans-serif;
  48. -moz-user-select: none;
  49. -webkit-user-select: none;
  50. user-select: none;
  51. }
  52. .css-treeview span {
  53. color: #00f;
  54. cursor: pointer;
  55. }
  56. .css-treeview span:hover {
  57. text-decoration: underline;
  58. }
  59. .css-treeview input + label + ul {
  60. margin: 0 0 0 22px;
  61. }
  62. .css-treeview input ~ ul {
  63. display: none;
  64. }
  65. .css-treeview label, .css-treeview label::before {
  66. cursor: pointer;
  67. }
  68. .css-treeview input:disabled + label {
  69. cursor: default;
  70. opacity: .6;
  71. }
  72. .css-treeview input:checked:not(:disabled) ~ ul {
  73. display: block;
  74. }
  75. .css-treeview label, .css-treeview label::before {
  76. 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;
  77. }
  78. .css-treeview label, .css-treeview span, .css-treeview label::before {
  79. display: inline-block;
  80. height: 16px;
  81. line-height: 16px;
  82. vertical-align: middle;
  83. }
  84. .css-treeview label {
  85. background-position: 18px 0;
  86. }
  87. .css-treeview label::before {
  88. content: "";
  89. width: 16px;
  90. margin: 0 22px 0 0;
  91. vertical-align: middle;
  92. background-position: 0 -32px;
  93. }
  94. .css-treeview input:checked + label::before {
  95. background-position: 0 -16px;
  96. }
  97. /* webkit adjacent element selector bugfix */
  98. @media screen and (-webkit-min-device-pixel-ratio:0)
  99. {
  100. .css-treeview{
  101. -webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
  102. }
  103. @-webkit-keyframes webkit-adjacent-element-selector-bugfix
  104. {
  105. from {
  106. padding: 0;
  107. }
  108. to {
  109. padding: 0;
  110. }
  111. }
  112. }
  113. #uploader {
  114. position: absolute;
  115. top: 0;
  116. right: 0;
  117. left: 0;
  118. height:28px;
  119. line-height: 24px;
  120. padding-left: 10px;
  121. background-color: #444;
  122. color:#EEE;
  123. }
  124. #tree {
  125. position: absolute;
  126. top: 28px;
  127. bottom: 0;
  128. left: 0;
  129. width:200px;
  130. padding: 8px;
  131. }
  132. #editor, #preview {
  133. position: absolute;
  134. top: 28px;
  135. right: 0;
  136. bottom: 0;
  137. left: 200px;
  138. }
  139. #preview {
  140. background-color: #EEE;
  141. padding:5px;
  142. }
  143. </style>
  144. <script>
  145. function createFileUploader(element, tree, editor){
  146. var xmlHttp;
  147. var input = document.createElement("input");
  148. input.type = "file";
  149. input.multiple = false;
  150. input.name = "data";
  151. document.getElementById(element).appendChild(input);
  152. var path = document.createElement("input");
  153. path.id = "upload-path";
  154. path.type = "text";
  155. path.name = "path";
  156. path.defaultValue = "/";
  157. document.getElementById(element).appendChild(path);
  158. var button = document.createElement("button");
  159. button.innerHTML = 'Upload';
  160. document.getElementById(element).appendChild(button);
  161. var mkdir = document.createElement("button");
  162. mkdir.innerHTML = 'MkDir';
  163. document.getElementById(element).appendChild(mkdir);
  164. var mkfile = document.createElement("button");
  165. mkfile.innerHTML = 'MkFile';
  166. document.getElementById(element).appendChild(mkfile);
  167. function httpPostProcessRequest(){
  168. if (xmlHttp.readyState == 4){
  169. if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
  170. else {
  171. tree.refreshPath(path.value);
  172. }
  173. }
  174. }
  175. function createPath(p){
  176. xmlHttp = new XMLHttpRequest();
  177. xmlHttp.onreadystatechange = httpPostProcessRequest;
  178. var formData = new FormData();
  179. formData.append("path", p);
  180. xmlHttp.open("PUT", "/edit");
  181. xmlHttp.send(formData);
  182. }
  183. mkfile.onclick = function(e){
  184. if(path.value.indexOf(".") === -1) return;
  185. createPath(path.value);
  186. editor.loadUrl(path.value);
  187. };
  188. mkdir.onclick = function(e){
  189. if(path.value.length < 2) return;
  190. var dir = path.value
  191. if(dir.indexOf(".") !== -1){
  192. if(dir.lastIndexOf("/") === 0) return;
  193. dir = dir.substring(0, dir.lastIndexOf("/"));
  194. }
  195. createPath(dir);
  196. };
  197. button.onclick = function(e){
  198. if(input.files.length === 0){
  199. return;
  200. }
  201. xmlHttp = new XMLHttpRequest();
  202. xmlHttp.onreadystatechange = httpPostProcessRequest;
  203. var formData = new FormData();
  204. formData.append("data", input.files[0], path.value);
  205. xmlHttp.open("POST", "/edit");
  206. xmlHttp.send(formData);
  207. }
  208. input.onchange = function(e){
  209. if(input.files.length === 0) return;
  210. var filename = input.files[0].name;
  211. var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
  212. var name = /(.*)\.[^.]+$/.exec(filename)[1];
  213. if(typeof name !== undefined){
  214. if(name.length > 8) name = name.substring(0, 8);
  215. filename = name;
  216. }
  217. if(typeof ext !== undefined){
  218. if(ext === "html") ext = "htm";
  219. else if(ext === "jpeg") ext = "jpg";
  220. filename = filename + "." + ext;
  221. }
  222. if(path.value === "/" || path.value.lastIndexOf("/") === 0){
  223. path.value = "/"+filename;
  224. } else {
  225. path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
  226. }
  227. }
  228. }
  229. function createTree(element, editor){
  230. var preview = document.getElementById("preview");
  231. var treeRoot = document.createElement("div");
  232. treeRoot.className = "css-treeview";
  233. document.getElementById(element).appendChild(treeRoot);
  234. function loadDownload(path){
  235. document.getElementById('download-frame').src = path+"?download=true";
  236. }
  237. function loadPreview(path){
  238. document.getElementById("editor").style.display = "none";
  239. preview.style.display = "block";
  240. preview.innerHTML = '<img src="'+path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
  241. }
  242. function fillFolderMenu(el, path){
  243. var list = document.createElement("ul");
  244. el.appendChild(list);
  245. var action = document.createElement("li");
  246. list.appendChild(action);
  247. var isChecked = document.getElementById(path).checked;
  248. var expnd = document.createElement("li");
  249. list.appendChild(expnd);
  250. if(isChecked){
  251. expnd.innerHTML = "<span>Collapse</span>";
  252. expnd.onclick = function(e){
  253. document.getElementById(path).checked = false;
  254. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  255. };
  256. var refrsh = document.createElement("li");
  257. list.appendChild(refrsh);
  258. refrsh.innerHTML = "<span>Refresh</span>";
  259. refrsh.onclick = function(e){
  260. var leaf = document.getElementById(path).parentNode;
  261. if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
  262. httpGet(leaf, path);
  263. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  264. };
  265. } else {
  266. expnd.innerHTML = "<span>Expand</span>";
  267. expnd.onclick = function(e){
  268. document.getElementById(path).checked = true;
  269. var leaf = document.getElementById(path).parentNode;
  270. if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
  271. httpGet(leaf, path);
  272. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  273. };
  274. }
  275. var upload = document.createElement("li");
  276. list.appendChild(upload);
  277. upload.innerHTML = "<span>Upload</span>";
  278. upload.onclick = function(e){
  279. var pathEl = document.getElementById("upload-path");
  280. if(pathEl){
  281. var subPath = pathEl.value;
  282. if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath;
  283. else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath;
  284. }
  285. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  286. };
  287. var delFile = document.createElement("li");
  288. list.appendChild(delFile);
  289. delFile.innerHTML = "<span>Delete</span>";
  290. delFile.onclick = function(e){
  291. httpDelete(path);
  292. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  293. };
  294. }
  295. function fillFileMenu(el, path){
  296. var list = document.createElement("ul");
  297. el.appendChild(list);
  298. var action = document.createElement("li");
  299. list.appendChild(action);
  300. if(isTextFile(path)){
  301. action.innerHTML = "<span>Edit</span>";
  302. action.onclick = function(e){
  303. editor.loadUrl(path);
  304. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  305. };
  306. } else if(isImageFile(path)){
  307. action.innerHTML = "<span>Preview</span>";
  308. action.onclick = function(e){
  309. loadPreview(path);
  310. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  311. };
  312. }
  313. var download = document.createElement("li");
  314. list.appendChild(download);
  315. download.innerHTML = "<span>Download</span>";
  316. download.onclick = function(e){
  317. loadDownload(path);
  318. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  319. };
  320. var delFile = document.createElement("li");
  321. list.appendChild(delFile);
  322. delFile.innerHTML = "<span>Delete</span>";
  323. delFile.onclick = function(e){
  324. httpDelete(path);
  325. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
  326. };
  327. }
  328. function showContextMenu(e, path, isfile){
  329. var divContext = document.createElement("div");
  330. var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
  331. var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
  332. var left = e.clientX + scrollLeft;
  333. var top = e.clientY + scrollTop;
  334. divContext.className = 'contextMenu';
  335. divContext.style.display = 'block';
  336. divContext.style.left = left + 'px';
  337. divContext.style.top = top + 'px';
  338. if(isfile) fillFileMenu(divContext, path);
  339. else fillFolderMenu(divContext, path);
  340. document.body.appendChild(divContext);
  341. var width = divContext.offsetWidth;
  342. var height = divContext.offsetHeight;
  343. divContext.onmouseout = function(e){
  344. if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
  345. if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
  346. }
  347. };
  348. }
  349. function createTreeLeaf(path, name, size){
  350. var leaf = document.createElement("li");
  351. leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
  352. var label = document.createElement("span");
  353. label.textContent = name.toLowerCase();
  354. leaf.appendChild(label);
  355. leaf.onclick = function(e){
  356. if(isTextFile(leaf.id)){
  357. editor.loadUrl(leaf.id);
  358. } else if(isImageFile(leaf.id)){
  359. loadPreview(leaf.id);
  360. }
  361. };
  362. leaf.oncontextmenu = function(e){
  363. e.preventDefault();
  364. e.stopPropagation();
  365. showContextMenu(e, leaf.id, true);
  366. };
  367. return leaf;
  368. }
  369. function createTreeBranch(path, name, disabled){
  370. var leaf = document.createElement("li");
  371. var check = document.createElement("input");
  372. check.type = "checkbox";
  373. check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
  374. if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
  375. leaf.appendChild(check);
  376. var label = document.createElement("label");
  377. label.for = check.id;
  378. label.textContent = name.toLowerCase();
  379. leaf.appendChild(label);
  380. check.onchange = function(e){
  381. if(check.checked){
  382. if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
  383. httpGet(leaf, check.id);
  384. }
  385. };
  386. label.onclick = function(e){
  387. if(!check.checked){
  388. check.checked = true;
  389. if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
  390. httpGet(leaf, check.id);
  391. } else {
  392. check.checked = false;
  393. }
  394. };
  395. leaf.oncontextmenu = function(e){
  396. e.preventDefault();
  397. e.stopPropagation();
  398. showContextMenu(e, check.id, false);
  399. }
  400. return leaf;
  401. }
  402. function addList(parent, path, items){
  403. var list = document.createElement("ul");
  404. parent.appendChild(list);
  405. var ll = items.length;
  406. for(var i = 0; i < ll; i++){
  407. var item = items[i];
  408. var itemEl;
  409. if(item.type === "file"){
  410. itemEl = createTreeLeaf(path, item.name, item.size);
  411. } else {
  412. itemEl = createTreeBranch(path, item.name);
  413. }
  414. list.appendChild(itemEl);
  415. }
  416. }
  417. function isTextFile(path){
  418. var ext = /(?:\.([^.]+))?$/.exec(path)[1];
  419. if(typeof ext !== undefined){
  420. switch(ext){
  421. case "txt":
  422. case "htm":
  423. case "html":
  424. case "js":
  425. case "json":
  426. case "c":
  427. case "h":
  428. case "cpp":
  429. case "css":
  430. case "xml":
  431. return true;
  432. }
  433. }
  434. return false;
  435. }
  436. function isImageFile(path){
  437. var ext = /(?:\.([^.]+))?$/.exec(path)[1];
  438. if(typeof ext !== undefined){
  439. switch(ext){
  440. case "png":
  441. case "jpg":
  442. case "gif":
  443. case "ico":
  444. return true;
  445. }
  446. }
  447. return false;
  448. }
  449. this.refreshPath = function(path){
  450. if(path.lastIndexOf('/') < 1){
  451. path = '/';
  452. treeRoot.removeChild(treeRoot.childNodes[0]);
  453. httpGet(treeRoot, "/");
  454. } else {
  455. path = path.substring(0, path.lastIndexOf('/'));
  456. var leaf = document.getElementById(path).parentNode;
  457. if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
  458. httpGet(leaf, path);
  459. }
  460. };
  461. function delCb(path){
  462. return function(){
  463. if (xmlHttp.readyState == 4){
  464. if(xmlHttp.status != 200){
  465. alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
  466. } else {
  467. if(path.lastIndexOf('/') < 1){
  468. path = '/';
  469. treeRoot.removeChild(treeRoot.childNodes[0]);
  470. httpGet(treeRoot, "/");
  471. } else {
  472. path = path.substring(0, path.lastIndexOf('/'));
  473. var leaf = document.getElementById(path).parentNode;
  474. if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
  475. httpGet(leaf, path);
  476. }
  477. }
  478. }
  479. }
  480. }
  481. function httpDelete(filename){
  482. xmlHttp = new XMLHttpRequest();
  483. xmlHttp.onreadystatechange = delCb(filename);
  484. var formData = new FormData();
  485. formData.append("path", filename);
  486. xmlHttp.open("DELETE", "/edit");
  487. xmlHttp.send(formData);
  488. }
  489. function getCb(parent, path){
  490. return function(){
  491. if (xmlHttp.readyState == 4){
  492. //clear loading
  493. if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
  494. }
  495. }
  496. }
  497. function httpGet(parent, path){
  498. xmlHttp = new XMLHttpRequest(parent, path);
  499. xmlHttp.onreadystatechange = getCb(parent, path);
  500. xmlHttp.open("GET", "/list?dir="+path, true);
  501. xmlHttp.send(null);
  502. //start loading
  503. }
  504. httpGet(treeRoot, "/");
  505. return this;
  506. }
  507. function createEditor(element, file, lang, theme, type){
  508. function getLangFromFilename(filename){
  509. var lang = "plain";
  510. var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
  511. if(typeof ext !== undefined){
  512. switch(ext){
  513. case "txt": lang = "plain"; break;
  514. case "htm": lang = "html"; break;
  515. case "js": lang = "javascript"; break;
  516. case "c": lang = "c_cpp"; break;
  517. case "cpp": lang = "c_cpp"; break;
  518. case "css":
  519. case "scss":
  520. case "php":
  521. case "html":
  522. case "json":
  523. case "xml":
  524. lang = ext;
  525. }
  526. }
  527. return lang;
  528. }
  529. if(typeof file === "undefined") file = "/index.htm";
  530. if(typeof lang === "undefined"){
  531. lang = getLangFromFilename(file);
  532. }
  533. if(typeof theme === "undefined") theme = "textmate";
  534. if(typeof type === "undefined"){
  535. type = "text/"+lang;
  536. if(lang === "c_cpp") type = "text/plain";
  537. }
  538. var xmlHttp = null;
  539. var editor = ace.edit(element);
  540. //post
  541. function httpPostProcessRequest(){
  542. if (xmlHttp.readyState == 4){
  543. if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
  544. }
  545. }
  546. function httpPost(filename, data, type){
  547. xmlHttp = new XMLHttpRequest();
  548. xmlHttp.onreadystatechange = httpPostProcessRequest;
  549. var formData = new FormData();
  550. formData.append("data", new Blob([data], { type: type }), filename);
  551. xmlHttp.open("POST", "/edit");
  552. xmlHttp.send(formData);
  553. }
  554. //get
  555. function httpGetProcessRequest(){
  556. if (xmlHttp.readyState == 4){
  557. document.getElementById("preview").style.display = "none";
  558. document.getElementById("editor").style.display = "block";
  559. if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
  560. else editor.setValue("");
  561. editor.clearSelection();
  562. }
  563. }
  564. function httpGet(theUrl){
  565. xmlHttp = new XMLHttpRequest();
  566. xmlHttp.onreadystatechange = httpGetProcessRequest;
  567. xmlHttp.open("GET", theUrl, true);
  568. xmlHttp.send(null);
  569. }
  570. if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
  571. editor.setTheme("ace/theme/"+theme);
  572. editor.$blockScrolling = Infinity;
  573. editor.getSession().setUseSoftTabs(true);
  574. editor.getSession().setTabSize(2);
  575. editor.setHighlightActiveLine(true);
  576. editor.setShowPrintMargin(false);
  577. editor.commands.addCommand({
  578. name: 'saveCommand',
  579. bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
  580. exec: function(editor) {
  581. httpPost(file, editor.getValue()+"", type);
  582. },
  583. readOnly: false
  584. });
  585. editor.commands.addCommand({
  586. name: 'undoCommand',
  587. bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
  588. exec: function(editor) {
  589. editor.getSession().getUndoManager().undo(false);
  590. },
  591. readOnly: false
  592. });
  593. editor.commands.addCommand({
  594. name: 'redoCommand',
  595. bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
  596. exec: function(editor) {
  597. editor.getSession().getUndoManager().redo(false);
  598. },
  599. readOnly: false
  600. });
  601. httpGet(file);
  602. editor.loadUrl = function(filename){
  603. file = filename;
  604. lang = getLangFromFilename(file);
  605. type = "text/"+lang;
  606. if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
  607. httpGet(file);
  608. }
  609. return editor;
  610. }
  611. function onBodyLoad(){
  612. var vars = {};
  613. var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
  614. var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
  615. var tree = createTree("tree", editor);
  616. createFileUploader("uploader", tree, editor);
  617. };
  618. </script>
  619. <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
  620. </head>
  621. <body onload="onBodyLoad();">
  622. <div id="uploader"></div>
  623. <div id="tree"></div>
  624. <div id="editor"></div>
  625. <div id="preview" style="display:none;"></div>
  626. <iframe id=download-frame style='display:none;'></iframe>
  627. </body>
  628. </html>