ext-textarea.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
  2. "use strict";
  3. exports.isDark = false;
  4. exports.cssClass = "ace-tm";
  5. exports.cssText = ".ace-tm .ace_gutter {\
  6. background: #f0f0f0;\
  7. color: #333;\
  8. }\
  9. .ace-tm .ace_print-margin {\
  10. width: 1px;\
  11. background: #e8e8e8;\
  12. }\
  13. .ace-tm .ace_fold {\
  14. background-color: #6B72E6;\
  15. }\
  16. .ace-tm {\
  17. background-color: #FFFFFF;\
  18. color: black;\
  19. }\
  20. .ace-tm .ace_cursor {\
  21. color: black;\
  22. }\
  23. .ace-tm .ace_invisible {\
  24. color: rgb(191, 191, 191);\
  25. }\
  26. .ace-tm .ace_storage,\
  27. .ace-tm .ace_keyword {\
  28. color: blue;\
  29. }\
  30. .ace-tm .ace_constant {\
  31. color: rgb(197, 6, 11);\
  32. }\
  33. .ace-tm .ace_constant.ace_buildin {\
  34. color: rgb(88, 72, 246);\
  35. }\
  36. .ace-tm .ace_constant.ace_language {\
  37. color: rgb(88, 92, 246);\
  38. }\
  39. .ace-tm .ace_constant.ace_library {\
  40. color: rgb(6, 150, 14);\
  41. }\
  42. .ace-tm .ace_invalid {\
  43. background-color: rgba(255, 0, 0, 0.1);\
  44. color: red;\
  45. }\
  46. .ace-tm .ace_support.ace_function {\
  47. color: rgb(60, 76, 114);\
  48. }\
  49. .ace-tm .ace_support.ace_constant {\
  50. color: rgb(6, 150, 14);\
  51. }\
  52. .ace-tm .ace_support.ace_type,\
  53. .ace-tm .ace_support.ace_class {\
  54. color: rgb(109, 121, 222);\
  55. }\
  56. .ace-tm .ace_keyword.ace_operator {\
  57. color: rgb(104, 118, 135);\
  58. }\
  59. .ace-tm .ace_string {\
  60. color: rgb(3, 106, 7);\
  61. }\
  62. .ace-tm .ace_comment {\
  63. color: rgb(76, 136, 107);\
  64. }\
  65. .ace-tm .ace_comment.ace_doc {\
  66. color: rgb(0, 102, 255);\
  67. }\
  68. .ace-tm .ace_comment.ace_doc.ace_tag {\
  69. color: rgb(128, 159, 191);\
  70. }\
  71. .ace-tm .ace_constant.ace_numeric {\
  72. color: rgb(0, 0, 205);\
  73. }\
  74. .ace-tm .ace_variable {\
  75. color: rgb(49, 132, 149);\
  76. }\
  77. .ace-tm .ace_xml-pe {\
  78. color: rgb(104, 104, 91);\
  79. }\
  80. .ace-tm .ace_entity.ace_name.ace_function {\
  81. color: #0000A2;\
  82. }\
  83. .ace-tm .ace_heading {\
  84. color: rgb(12, 7, 255);\
  85. }\
  86. .ace-tm .ace_list {\
  87. color:rgb(185, 6, 144);\
  88. }\
  89. .ace-tm .ace_meta.ace_tag {\
  90. color:rgb(0, 22, 142);\
  91. }\
  92. .ace-tm .ace_string.ace_regex {\
  93. color: rgb(255, 0, 0)\
  94. }\
  95. .ace-tm .ace_marker-layer .ace_selection {\
  96. background: rgb(181, 213, 255);\
  97. }\
  98. .ace-tm.ace_multiselect .ace_selection.ace_start {\
  99. box-shadow: 0 0 3px 0px white;\
  100. }\
  101. .ace-tm .ace_marker-layer .ace_step {\
  102. background: rgb(252, 255, 0);\
  103. }\
  104. .ace-tm .ace_marker-layer .ace_stack {\
  105. background: rgb(164, 229, 101);\
  106. }\
  107. .ace-tm .ace_marker-layer .ace_bracket {\
  108. margin: -1px 0 0 -1px;\
  109. border: 1px solid rgb(192, 192, 192);\
  110. }\
  111. .ace-tm .ace_marker-layer .ace_active-line {\
  112. background: rgba(0, 0, 0, 0.07);\
  113. }\
  114. .ace-tm .ace_gutter-active-line {\
  115. background-color : #dcdcdc;\
  116. }\
  117. .ace-tm .ace_marker-layer .ace_selected-word {\
  118. background: rgb(250, 250, 255);\
  119. border: 1px solid rgb(200, 200, 250);\
  120. }\
  121. .ace-tm .ace_indent-guide {\
  122. background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\
  123. }\
  124. ";
  125. var dom = require("../lib/dom");
  126. dom.importCssString(exports.cssText, exports.cssClass);
  127. });
  128. ace.define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(require, exports, module) {
  129. "use strict";
  130. require("./lib/fixoldbrowsers");
  131. var dom = require("./lib/dom");
  132. var event = require("./lib/event");
  133. var Editor = require("./editor").Editor;
  134. var EditSession = require("./edit_session").EditSession;
  135. var UndoManager = require("./undomanager").UndoManager;
  136. var Renderer = require("./virtual_renderer").VirtualRenderer;
  137. require("./worker/worker_client");
  138. require("./keyboard/hash_handler");
  139. require("./placeholder");
  140. require("./multi_select");
  141. require("./mode/folding/fold_mode");
  142. require("./theme/textmate");
  143. require("./ext/error_marker");
  144. exports.config = require("./config");
  145. exports.require = require;
  146. exports.edit = function(el) {
  147. if (typeof(el) == "string") {
  148. var _id = el;
  149. el = document.getElementById(_id);
  150. if (!el)
  151. throw new Error("ace.edit can't find div #" + _id);
  152. }
  153. if (el && el.env && el.env.editor instanceof Editor)
  154. return el.env.editor;
  155. var value = "";
  156. if (el && /input|textarea/i.test(el.tagName)) {
  157. var oldNode = el;
  158. value = oldNode.value;
  159. el = dom.createElement("pre");
  160. oldNode.parentNode.replaceChild(el, oldNode);
  161. } else if (el) {
  162. value = dom.getInnerText(el);
  163. el.innerHTML = '';
  164. }
  165. var doc = exports.createEditSession(value);
  166. var editor = new Editor(new Renderer(el));
  167. editor.setSession(doc);
  168. var env = {
  169. document: doc,
  170. editor: editor,
  171. onResize: editor.resize.bind(editor, null)
  172. };
  173. if (oldNode) env.textarea = oldNode;
  174. event.addListener(window, "resize", env.onResize);
  175. editor.on("destroy", function() {
  176. event.removeListener(window, "resize", env.onResize);
  177. env.editor.container.env = null; // prevent memory leak on old ie
  178. });
  179. editor.container.env = editor.env = env;
  180. return editor;
  181. };
  182. exports.createEditSession = function(text, mode) {
  183. var doc = new EditSession(text, mode);
  184. doc.setUndoManager(new UndoManager());
  185. return doc;
  186. }
  187. exports.EditSession = EditSession;
  188. exports.UndoManager = UndoManager;
  189. });
  190. ace.define("ace/ext/textarea",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/net","ace/ace","ace/theme/textmate"], function(require, exports, module) {
  191. "use strict";
  192. var event = require("../lib/event");
  193. var UA = require("../lib/useragent");
  194. var net = require("../lib/net");
  195. var ace = require("../ace");
  196. require("../theme/textmate");
  197. module.exports = exports = ace;
  198. var getCSSProperty = function(element, container, property) {
  199. var ret = element.style[property];
  200. if (!ret) {
  201. if (window.getComputedStyle) {
  202. ret = window.getComputedStyle(element, '').getPropertyValue(property);
  203. } else {
  204. ret = element.currentStyle[property];
  205. }
  206. }
  207. if (!ret || ret == 'auto' || ret == 'intrinsic') {
  208. ret = container.style[property];
  209. }
  210. return ret;
  211. };
  212. function applyStyles(elm, styles) {
  213. for (var style in styles) {
  214. elm.style[style] = styles[style];
  215. }
  216. }
  217. function setupContainer(element, getValue) {
  218. if (element.type != 'textarea') {
  219. throw new Error("Textarea required!");
  220. }
  221. var parentNode = element.parentNode;
  222. var container = document.createElement('div');
  223. var resizeEvent = function() {
  224. var style = 'position:relative;';
  225. [
  226. 'margin-top', 'margin-left', 'margin-right', 'margin-bottom'
  227. ].forEach(function(item) {
  228. style += item + ':' +
  229. getCSSProperty(element, container, item) + ';';
  230. });
  231. var width = getCSSProperty(element, container, 'width') || (element.clientWidth + "px");
  232. var height = getCSSProperty(element, container, 'height') || (element.clientHeight + "px");
  233. style += 'height:' + height + ';width:' + width + ';';
  234. style += 'display:inline-block;';
  235. container.setAttribute('style', style);
  236. };
  237. event.addListener(window, 'resize', resizeEvent);
  238. resizeEvent();
  239. parentNode.insertBefore(container, element.nextSibling);
  240. while (parentNode !== document) {
  241. if (parentNode.tagName.toUpperCase() === 'FORM') {
  242. var oldSumit = parentNode.onsubmit;
  243. parentNode.onsubmit = function(evt) {
  244. element.value = getValue();
  245. if (oldSumit) {
  246. oldSumit.call(this, evt);
  247. }
  248. };
  249. break;
  250. }
  251. parentNode = parentNode.parentNode;
  252. }
  253. return container;
  254. }
  255. exports.transformTextarea = function(element, options) {
  256. var session;
  257. var container = setupContainer(element, function() {
  258. return session.getValue();
  259. });
  260. element.style.display = 'none';
  261. container.style.background = 'white';
  262. var editorDiv = document.createElement("div");
  263. applyStyles(editorDiv, {
  264. top: "0px",
  265. left: "0px",
  266. right: "0px",
  267. bottom: "0px",
  268. border: "1px solid gray",
  269. position: "absolute"
  270. });
  271. container.appendChild(editorDiv);
  272. var settingOpener = document.createElement("div");
  273. applyStyles(settingOpener, {
  274. position: "absolute",
  275. right: "0px",
  276. bottom: "0px",
  277. background: "red",
  278. cursor: "nw-resize",
  279. borderStyle: "solid",
  280. borderWidth: "9px 8px 10px 9px",
  281. width: "2px",
  282. borderColor: "lightblue gray gray lightblue",
  283. zIndex: 101
  284. });
  285. var settingDiv = document.createElement("div");
  286. var settingDivStyles = {
  287. top: "0px",
  288. left: "20%",
  289. right: "0px",
  290. bottom: "0px",
  291. position: "absolute",
  292. padding: "5px",
  293. zIndex: 100,
  294. color: "white",
  295. display: "none",
  296. overflow: "auto",
  297. fontSize: "14px",
  298. boxShadow: "-5px 2px 3px gray"
  299. };
  300. if (!UA.isOldIE) {
  301. settingDivStyles.backgroundColor = "rgba(0, 0, 0, 0.6)";
  302. } else {
  303. settingDivStyles.backgroundColor = "#333";
  304. }
  305. applyStyles(settingDiv, settingDivStyles);
  306. container.appendChild(settingDiv);
  307. options = options || exports.defaultOptions;
  308. var editor = ace.edit(editorDiv);
  309. session = editor.getSession();
  310. session.setValue(element.value || element.innerHTML);
  311. editor.focus();
  312. container.appendChild(settingOpener);
  313. setupApi(editor, editorDiv, settingDiv, ace, options, load);
  314. setupSettingPanel(settingDiv, settingOpener, editor);
  315. var state = "";
  316. event.addListener(settingOpener, "mousemove", function(e) {
  317. var rect = this.getBoundingClientRect();
  318. var x = e.clientX - rect.left, y = e.clientY - rect.top;
  319. if (x + y < (rect.width + rect.height)/2) {
  320. this.style.cursor = "pointer";
  321. state = "toggle";
  322. } else {
  323. state = "resize";
  324. this.style.cursor = "nw-resize";
  325. }
  326. });
  327. event.addListener(settingOpener, "mousedown", function(e) {
  328. if (state == "toggle") {
  329. editor.setDisplaySettings();
  330. return;
  331. }
  332. container.style.zIndex = 100000;
  333. var rect = container.getBoundingClientRect();
  334. var startX = rect.width + rect.left - e.clientX;
  335. var startY = rect.height + rect.top - e.clientY;
  336. event.capture(settingOpener, function(e) {
  337. container.style.width = e.clientX - rect.left + startX + "px";
  338. container.style.height = e.clientY - rect.top + startY + "px";
  339. editor.resize();
  340. }, function() {});
  341. });
  342. return editor;
  343. };
  344. function load(url, module, callback) {
  345. net.loadScript(url, function() {
  346. require([module], callback);
  347. });
  348. }
  349. function setupApi(editor, editorDiv, settingDiv, ace, options, loader) {
  350. var session = editor.getSession();
  351. var renderer = editor.renderer;
  352. loader = loader || load;
  353. function toBool(value) {
  354. return value === "true" || value == true;
  355. }
  356. editor.setDisplaySettings = function(display) {
  357. if (display == null)
  358. display = settingDiv.style.display == "none";
  359. if (display) {
  360. settingDiv.style.display = "block";
  361. settingDiv.hideButton.focus();
  362. editor.on("focus", function onFocus() {
  363. editor.removeListener("focus", onFocus);
  364. settingDiv.style.display = "none";
  365. });
  366. } else {
  367. editor.focus();
  368. }
  369. };
  370. editor.$setOption = editor.setOption;
  371. editor.$getOption = editor.getOption;
  372. editor.setOption = function(key, value) {
  373. switch (key) {
  374. case "mode":
  375. editor.$setOption("mode", "ace/mode/" + value)
  376. break;
  377. case "theme":
  378. editor.$setOption("theme", "ace/theme/" + value)
  379. break;
  380. case "keybindings":
  381. switch (value) {
  382. case "vim":
  383. editor.setKeyboardHandler("ace/keyboard/vim");
  384. break;
  385. case "emacs":
  386. editor.setKeyboardHandler("ace/keyboard/emacs");
  387. break;
  388. default:
  389. editor.setKeyboardHandler(null);
  390. }
  391. break;
  392. case "softWrap":
  393. case "fontSize":
  394. editor.$setOption(key, value);
  395. break;
  396. default:
  397. editor.$setOption(key, toBool(value));
  398. }
  399. };
  400. editor.getOption = function(key) {
  401. switch (key) {
  402. case "mode":
  403. return editor.$getOption("mode").substr("ace/mode/".length)
  404. break;
  405. case "theme":
  406. return editor.$getOption("theme").substr("ace/theme/".length)
  407. break;
  408. case "keybindings":
  409. var value = editor.getKeyboardHandler()
  410. switch (value && value.$id) {
  411. case "ace/keyboard/vim":
  412. return "vim";
  413. case "ace/keyboard/emacs":
  414. return "emacs";
  415. default:
  416. return "ace";
  417. }
  418. break;
  419. default:
  420. return editor.$getOption(key);
  421. }
  422. };
  423. editor.setOptions(options);
  424. return editor;
  425. }
  426. function setupSettingPanel(settingDiv, settingOpener, editor) {
  427. var BOOL = null;
  428. var desc = {
  429. mode: "Mode:",
  430. wrap: "Soft Wrap:",
  431. theme: "Theme:",
  432. fontSize: "Font Size:",
  433. showGutter: "Display Gutter:",
  434. keybindings: "Keyboard",
  435. showPrintMargin: "Show Print Margin:",
  436. useSoftTabs: "Use Soft Tabs:",
  437. showInvisibles: "Show Invisibles"
  438. };
  439. var optionValues = {
  440. mode: {
  441. text: "Plain",
  442. javascript: "JavaScript",
  443. xml: "XML",
  444. html: "HTML",
  445. css: "CSS",
  446. scss: "SCSS",
  447. python: "Python",
  448. php: "PHP",
  449. java: "Java",
  450. ruby: "Ruby",
  451. c_cpp: "C/C++",
  452. coffee: "CoffeeScript",
  453. json: "json",
  454. perl: "Perl",
  455. clojure: "Clojure",
  456. ocaml: "OCaml",
  457. csharp: "C#",
  458. haxe: "haXe",
  459. svg: "SVG",
  460. textile: "Textile",
  461. groovy: "Groovy",
  462. liquid: "Liquid",
  463. Scala: "Scala"
  464. },
  465. theme: {
  466. clouds: "Clouds",
  467. clouds_midnight: "Clouds Midnight",
  468. cobalt: "Cobalt",
  469. crimson_editor: "Crimson Editor",
  470. dawn: "Dawn",
  471. eclipse: "Eclipse",
  472. idle_fingers: "Idle Fingers",
  473. kr_theme: "Kr Theme",
  474. merbivore: "Merbivore",
  475. merbivore_soft: "Merbivore Soft",
  476. mono_industrial: "Mono Industrial",
  477. monokai: "Monokai",
  478. pastel_on_dark: "Pastel On Dark",
  479. solarized_dark: "Solarized Dark",
  480. solarized_light: "Solarized Light",
  481. textmate: "Textmate",
  482. twilight: "Twilight",
  483. vibrant_ink: "Vibrant Ink"
  484. },
  485. showGutter: BOOL,
  486. fontSize: {
  487. "10px": "10px",
  488. "11px": "11px",
  489. "12px": "12px",
  490. "14px": "14px",
  491. "16px": "16px"
  492. },
  493. wrap: {
  494. off: "Off",
  495. 40: "40",
  496. 80: "80",
  497. free: "Free"
  498. },
  499. keybindings: {
  500. ace: "ace",
  501. vim: "vim",
  502. emacs: "emacs"
  503. },
  504. showPrintMargin: BOOL,
  505. useSoftTabs: BOOL,
  506. showInvisibles: BOOL
  507. };
  508. var table = [];
  509. table.push("<table><tr><th>Setting</th><th>Value</th></tr>");
  510. function renderOption(builder, option, obj, cValue) {
  511. if (!obj) {
  512. builder.push(
  513. "<input type='checkbox' title='", option, "' ",
  514. cValue + "" == "true" ? "checked='true'" : "",
  515. "'></input>"
  516. );
  517. return;
  518. }
  519. builder.push("<select title='" + option + "'>");
  520. for (var value in obj) {
  521. builder.push("<option value='" + value + "' ");
  522. if (cValue == value) {
  523. builder.push(" selected ");
  524. }
  525. builder.push(">",
  526. obj[value],
  527. "</option>");
  528. }
  529. builder.push("</select>");
  530. }
  531. for (var option in exports.defaultOptions) {
  532. table.push("<tr><td>", desc[option], "</td>");
  533. table.push("<td>");
  534. renderOption(table, option, optionValues[option], editor.getOption(option));
  535. table.push("</td></tr>");
  536. }
  537. table.push("</table>");
  538. settingDiv.innerHTML = table.join("");
  539. var onChange = function(e) {
  540. var select = e.currentTarget;
  541. editor.setOption(select.title, select.value);
  542. };
  543. var onClick = function(e) {
  544. var cb = e.currentTarget;
  545. editor.setOption(cb.title, cb.checked);
  546. };
  547. var selects = settingDiv.getElementsByTagName("select");
  548. for (var i = 0; i < selects.length; i++)
  549. selects[i].onchange = onChange;
  550. var cbs = settingDiv.getElementsByTagName("input");
  551. for (var i = 0; i < cbs.length; i++)
  552. cbs[i].onclick = onClick;
  553. var button = document.createElement("input");
  554. button.type = "button";
  555. button.value = "Hide";
  556. event.addListener(button, "click", function() {
  557. editor.setDisplaySettings(false);
  558. });
  559. settingDiv.appendChild(button);
  560. settingDiv.hideButton = button;
  561. }
  562. exports.defaultOptions = {
  563. mode: "javascript",
  564. theme: "textmate",
  565. wrap: "off",
  566. fontSize: "12px",
  567. showGutter: "false",
  568. keybindings: "ace",
  569. showPrintMargin: "false",
  570. useSoftTabs: "true",
  571. showInvisibles: "false"
  572. };
  573. });
  574. (function() {
  575. ace.require(["ace/ext/textarea"], function() {});
  576. })();