ext-textarea.js 18 KB

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