1
/* ***** BEGIN LICENSE BLOCK *****
2
* Distributed under the BSD license:
4
* Copyright (c) 2010, Ajax.org B.V.
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are met:
9
* * Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* * Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
* * Neither the name of Ajax.org B.V. nor the
15
* names of its contributors may be used to endorse or promote products
16
* derived from this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
22
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
* ***** END LICENSE BLOCK ***** */
31
define('ace/ext/textarea', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent', 'ace/lib/net', 'ace/ace', 'ace/theme/textmate', 'ace/mode/text'], function(require, exports, module) {
34
var event = require("../lib/event");
35
var UA = require("../lib/useragent");
36
var net = require("../lib/net");
37
var ace = require("../ace");
39
require("../theme/textmate");
41
module.exports = exports = ace;
42
var getCSSProperty = function(element, container, property) {
43
var ret = element.style[property];
46
if (window.getComputedStyle) {
47
ret = window.getComputedStyle(element, '').getPropertyValue(property);
49
ret = element.currentStyle[property];
53
if (!ret || ret == 'auto' || ret == 'intrinsic') {
54
ret = container.style[property];
59
function applyStyles(elm, styles) {
60
for (var style in styles) {
61
elm.style[style] = styles[style];
65
function setupContainer(element, getValue) {
66
if (element.type != 'textarea') {
67
throw "Textarea required!";
70
var parentNode = element.parentNode;
71
var container = document.createElement('div');
72
var resizeEvent = function() {
73
var style = 'position:relative;';
75
'margin-top', 'margin-left', 'margin-right', 'margin-bottom'
76
].forEach(function(item) {
78
getCSSProperty(element, container, item) + ';';
80
var width = getCSSProperty(element, container, 'width') || (element.clientWidth + "px");
81
var height = getCSSProperty(element, container, 'height') || (element.clientHeight + "px");
82
style += 'height:' + height + ';width:' + width + ';';
83
style += 'display:inline-block;';
84
container.setAttribute('style', style);
86
event.addListener(window, 'resize', resizeEvent);
88
parentNode.insertBefore(container, element.nextSibling);
89
while (parentNode !== document) {
90
if (parentNode.tagName.toUpperCase() === 'FORM') {
91
var oldSumit = parentNode.onsubmit;
92
parentNode.onsubmit = function(evt) {
93
element.value = getValue();
95
oldSumit.call(this, evt);
100
parentNode = parentNode.parentNode;
105
exports.transformTextarea = function(element, loader) {
107
var container = setupContainer(element, function() {
108
return session.getValue();
110
element.style.display = 'none';
111
container.style.background = 'white';
112
var editorDiv = document.createElement("div");
113
applyStyles(editorDiv, {
118
border: "1px solid gray",
121
container.appendChild(editorDiv);
123
var settingOpener = document.createElement("div");
124
applyStyles(settingOpener, {
125
position: "absolute",
130
borderStyle: "solid",
131
borderWidth: "9px 8px 10px 9px",
133
borderColor: "lightblue gray gray lightblue",
137
var settingDiv = document.createElement("div");
138
var settingDivStyles = {
143
position: "absolute",
150
boxShadow: "-5px 2px 3px gray"
153
settingDivStyles.backgroundColor = "rgba(0, 0, 0, 0.6)";
155
settingDivStyles.backgroundColor = "#333";
158
applyStyles(settingDiv, settingDivStyles);
159
container.appendChild(settingDiv);
162
var editor = ace.edit(editorDiv);
163
session = editor.getSession();
165
session.setValue(element.value || element.innerHTML);
167
container.appendChild(settingOpener);
168
setupApi(editor, editorDiv, settingDiv, ace, options, loader);
169
setupSettingPanel(settingDiv, settingOpener, editor, options);
172
event.addListener(settingOpener, "mousemove", function(e) {
173
var rect = this.getBoundingClientRect();
174
var x = e.clientX - rect.left, y = e.clientY - rect.top;
175
if (x + y < (rect.width + rect.height)/2) {
176
this.style.cursor = "pointer";
180
this.style.cursor = "nw-resize";
184
event.addListener(settingOpener, "mousedown", function(e) {
185
if (state == "toggle") {
186
editor.setDisplaySettings();
189
container.style.zIndex = 100000;
190
var rect = container.getBoundingClientRect();
191
var startX = rect.width + rect.left - e.clientX;
192
var startY = rect.height + rect.top - e.clientY;
193
event.capture(settingOpener, function(e) {
194
container.style.width = e.clientX - rect.left + startX + "px";
195
container.style.height = e.clientY - rect.top + startY + "px";
203
function load(url, module, callback) {
204
net.loadScript(url, function() {
205
require([module], callback);
209
function setupApi(editor, editorDiv, settingDiv, ace, options, loader) {
210
var session = editor.getSession();
211
var renderer = editor.renderer;
212
loader = loader || load;
214
function toBool(value) {
215
return value === "true" || value == true;
218
editor.setDisplaySettings = function(display) {
220
display = settingDiv.style.display == "none";
222
settingDiv.style.display = "block";
223
settingDiv.hideButton.focus();
224
editor.on("focus", function onFocus() {
225
editor.removeListener("focus", onFocus);
226
settingDiv.style.display = "none"
233
editor.setOption = function(key, value) {
234
if (options[key] == value) return;
238
renderer.setShowGutter(toBool(value));
242
if (value != "text") {
243
loader("mode-" + value + ".js", "ace/mode/" + value, function() {
244
var aceMode = require("../mode/" + value).Mode;
245
session.setMode(new aceMode());
248
session.setMode(new (require("../mode/text").Mode));
253
if (value != "textmate") {
254
loader("theme-" + value + ".js", "ace/theme/" + value, function() {
255
editor.setTheme("ace/theme/" + value);
258
editor.setTheme("ace/theme/textmate");
263
editorDiv.style.fontSize = value;
269
editor.setKeyboardHandler("ace/keyboard/vim");
272
editor.setKeyboardHandler("ace/keyboard/emacs");
275
editor.setKeyboardHandler(null);
282
session.setUseWrapMode(false);
283
renderer.setPrintMarginColumn(80);
286
session.setUseWrapMode(true);
287
session.setWrapLimitRange(40, 40);
288
renderer.setPrintMarginColumn(40);
291
session.setUseWrapMode(true);
292
session.setWrapLimitRange(80, 80);
293
renderer.setPrintMarginColumn(80);
296
session.setUseWrapMode(true);
297
session.setWrapLimitRange(null, null);
298
renderer.setPrintMarginColumn(80);
304
session.setUseSoftTabs(toBool(value));
307
case "showPrintMargin":
308
renderer.setShowPrintMargin(toBool(value));
311
case "showInvisibles":
312
editor.setShowInvisibles(toBool(value));
316
options[key] = value;
319
editor.getOption = function(key) {
323
editor.getOptions = function() {
327
for (var option in exports.options) {
328
editor.setOption(option, exports.options[option]);
334
function setupSettingPanel(settingDiv, settingOpener, editor, options) {
339
gutter: "Display Gutter:",
341
fontSize: "Font Size:",
342
softWrap: "Soft Wrap:",
343
keybindings: "Keyboard",
344
showPrintMargin: "Show Print Margin:",
345
useSoftTabs: "Use Soft Tabs:",
346
showInvisibles: "Show Invisibles"
352
javascript: "JavaScript",
362
coffee: "CoffeeScript",
377
clouds_midnight: "Clouds Midnight",
379
crimson_editor: "Crimson Editor",
382
idle_fingers: "Idle Fingers",
383
kr_theme: "Kr Theme",
384
merbivore: "Merbivore",
385
merbivore_soft: "Merbivore Soft",
386
mono_industrial: "Mono Industrial",
388
pastel_on_dark: "Pastel On Dark",
389
solarized_dark: "Solarized Dark",
390
solarized_light: "Solarized Light",
391
textmate: "Textmate",
392
twilight: "Twilight",
393
vibrant_ink: "Vibrant Ink"
414
showPrintMargin: BOOL,
420
table.push("<table><tr><th>Setting</th><th>Value</th></tr>");
422
function renderOption(builder, option, obj, cValue) {
425
"<input type='checkbox' title='", option, "' ",
426
cValue == "true" ? "checked='true'" : "",
431
builder.push("<select title='" + option + "'>");
432
for (var value in obj) {
433
builder.push("<option value='" + value + "' ");
435
if (cValue == value) {
436
builder.push(" selected ");
443
builder.push("</select>");
446
for (var option in options) {
447
table.push("<tr><td>", desc[option], "</td>");
449
renderOption(table, option, optionValues[option], options[option]);
450
table.push("</td></tr>");
452
table.push("</table>");
453
settingDiv.innerHTML = table.join("");
455
var onChange = function(e) {
456
var select = e.currentTarget;
457
editor.setOption(select.title, select.value);
459
var onClick = function(e) {
460
var cb = e.currentTarget;
461
editor.setOption(cb.title, cb.checked);
463
var selects = settingDiv.getElementsByTagName("select");
464
for (var i = 0; i < selects.length; i++)
465
selects[i].onchange = onChange;
466
var cbs = settingDiv.getElementsByTagName("input");
467
for (var i = 0; i < cbs.length; i++)
468
cbs[i].onclick = onClick;
471
var button = document.createElement("input");
472
button.type = "button";
473
button.value = "Hide";
474
event.addListener(button, "click", function() {
475
editor.setDisplaySettings(false);
477
settingDiv.appendChild(button);
478
settingDiv.hideButton = button;
487
showPrintMargin: "false",
489
showInvisibles: "false"