/* ***** BEGIN LICENSE BLOCK ***** * Distributed under the BSD license: * * Copyright (c) 2010, Ajax.org B.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Ajax.org B.V. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***** END LICENSE BLOCK ***** */ ace.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) { var event = require("../lib/event"); var UA = require("../lib/useragent"); var net = require("../lib/net"); var ace = require("../ace"); require("../theme/textmate"); module.exports = exports = ace; var getCSSProperty = function(element, container, property) { var ret = element.style[property]; if (!ret) { if (window.getComputedStyle) { ret = window.getComputedStyle(element, '').getPropertyValue(property); } else { ret = element.currentStyle[property]; } } if (!ret || ret == 'auto' || ret == 'intrinsic') { ret = container.style[property]; } return ret; }; function applyStyles(elm, styles) { for (var style in styles) { elm.style[style] = styles[style]; } } function setupContainer(element, getValue) { if (element.type != 'textarea') { throw new Error("Textarea required!"); } var parentNode = element.parentNode; var container = document.createElement('div'); var resizeEvent = function() { var style = 'position:relative;'; [ 'margin-top', 'margin-left', 'margin-right', 'margin-bottom' ].forEach(function(item) { style += item + ':' + getCSSProperty(element, container, item) + ';'; }); var width = getCSSProperty(element, container, 'width') || (element.clientWidth + "px"); var height = getCSSProperty(element, container, 'height') || (element.clientHeight + "px"); style += 'height:' + height + ';width:' + width + ';'; style += 'display:inline-block;'; container.setAttribute('style', style); }; event.addListener(window, 'resize', resizeEvent); resizeEvent(); parentNode.insertBefore(container, element.nextSibling); while (parentNode !== document) { if (parentNode.tagName.toUpperCase() === 'FORM') { var oldSumit = parentNode.onsubmit; parentNode.onsubmit = function(evt) { element.value = getValue(); if (oldSumit) { oldSumit.call(this, evt); } }; break; } parentNode = parentNode.parentNode; } return container; } exports.transformTextarea = function(element, loader) { var session; var container = setupContainer(element, function() { return session.getValue(); }); element.style.display = 'none'; container.style.background = 'white'; var editorDiv = document.createElement("div"); applyStyles(editorDiv, { top: "0px", left: "0px", right: "0px", bottom: "0px", border: "1px solid gray", position: "absolute" }); container.appendChild(editorDiv); var settingOpener = document.createElement("div"); applyStyles(settingOpener, { position: "absolute", right: "0px", bottom: "0px", background: "red", cursor: "nw-resize", borderStyle: "solid", borderWidth: "9px 8px 10px 9px", width: "2px", borderColor: "lightblue gray gray lightblue", zIndex: 101 }); var settingDiv = document.createElement("div"); var settingDivStyles = { top: "0px", left: "20%", right: "0px", bottom: "0px", position: "absolute", padding: "5px", zIndex: 100, color: "white", display: "none", overflow: "auto", fontSize: "14px", boxShadow: "-5px 2px 3px gray" }; if (!UA.isOldIE) { settingDivStyles.backgroundColor = "rgba(0, 0, 0, 0.6)"; } else { settingDivStyles.backgroundColor = "#333"; } applyStyles(settingDiv, settingDivStyles); container.appendChild(settingDiv); var options = {}; var editor = ace.edit(editorDiv); session = editor.getSession(); session.setValue(element.value || element.innerHTML); editor.focus(); container.appendChild(settingOpener); setupApi(editor, editorDiv, settingDiv, ace, options, loader); setupSettingPanel(settingDiv, settingOpener, editor, options); var state = ""; event.addListener(settingOpener, "mousemove", function(e) { var rect = this.getBoundingClientRect(); var x = e.clientX - rect.left, y = e.clientY - rect.top; if (x + y < (rect.width + rect.height)/2) { this.style.cursor = "pointer"; state = "toggle"; } else { state = "resize"; this.style.cursor = "nw-resize"; } }); event.addListener(settingOpener, "mousedown", function(e) { if (state == "toggle") { editor.setDisplaySettings(); return; } container.style.zIndex = 100000; var rect = container.getBoundingClientRect(); var startX = rect.width + rect.left - e.clientX; var startY = rect.height + rect.top - e.clientY; event.capture(settingOpener, function(e) { container.style.width = e.clientX - rect.left + startX + "px"; container.style.height = e.clientY - rect.top + startY + "px"; editor.resize(); }, function() {}); }); return editor; }; function load(url, module, callback) { net.loadScript(url, function() { require([module], callback); }); } function setupApi(editor, editorDiv, settingDiv, ace, options, loader) { var session = editor.getSession(); var renderer = editor.renderer; loader = loader || load; function toBool(value) { return value === "true" || value == true; } editor.setDisplaySettings = function(display) { if (display == null) display = settingDiv.style.display == "none"; if (display) { settingDiv.style.display = "block"; settingDiv.hideButton.focus(); editor.on("focus", function onFocus() { editor.removeListener("focus", onFocus); settingDiv.style.display = "none"; }); } else { editor.focus(); } }; editor.$setOption = editor.setOption; editor.setOption = function(key, value) { if (options[key] == value) return; switch (key) { case "mode": if (value != "text") { loader("mode-" + value + ".js", "ace/mode/" + value, function() { var aceMode = require("../mode/" + value).Mode; session.setMode(new aceMode()); }); } else { session.setMode(new (require("../mode/text").Mode)); } break; case "theme": if (value != "textmate") { loader("theme-" + value + ".js", "ace/theme/" + value, function() { editor.setTheme("ace/theme/" + value); }); } else { editor.setTheme("ace/theme/textmate"); } break; case "fontSize": editorDiv.style.fontSize = value; break; case "keybindings": switch (value) { case "vim": editor.setKeyboardHandler("ace/keyboard/vim"); break; case "emacs": editor.setKeyboardHandler("ace/keyboard/emacs"); break; default: editor.setKeyboardHandler(null); } break; case "softWrap": switch (value) { case "off": session.setUseWrapMode(false); renderer.setPrintMarginColumn(80); break; case "40": session.setUseWrapMode(true); session.setWrapLimitRange(40, 40); renderer.setPrintMarginColumn(40); break; case "80": session.setUseWrapMode(true); session.setWrapLimitRange(80, 80); renderer.setPrintMarginColumn(80); break; case "free": session.setUseWrapMode(true); session.setWrapLimitRange(null, null); renderer.setPrintMarginColumn(80); break; } break; default: editor.$setOption(key, toBool(value)); } options[key] = value; }; editor.getOption = function(key) { return options[key]; }; editor.getOptions = function() { return options; }; editor.setOptions(exports.options); return editor; } function setupSettingPanel(settingDiv, settingOpener, editor, options) { var BOOL = null; var desc = { mode: "Mode:", gutter: "Display Gutter:", theme: "Theme:", fontSize: "Font Size:", softWrap: "Soft Wrap:", keybindings: "Keyboard", showPrintMargin: "Show Print Margin:", useSoftTabs: "Use Soft Tabs:", showInvisibles: "Show Invisibles" }; var optionValues = { mode: { text: "Plain", javascript: "JavaScript", xml: "XML", html: "HTML", css: "CSS", scss: "SCSS", python: "Python", php: "PHP", java: "Java", ruby: "Ruby", c_cpp: "C/C++", coffee: "CoffeeScript", json: "json", perl: "Perl", clojure: "Clojure", ocaml: "OCaml", csharp: "C#", haxe: "haXe", svg: "SVG", textile: "Textile", groovy: "Groovy", liquid: "Liquid", Scala: "Scala" }, theme: { clouds: "Clouds", clouds_midnight: "Clouds Midnight", cobalt: "Cobalt", crimson_editor: "Crimson Editor", dawn: "Dawn", eclipse: "Eclipse", idle_fingers: "Idle Fingers", kr_theme: "Kr Theme", merbivore: "Merbivore", merbivore_soft: "Merbivore Soft", mono_industrial: "Mono Industrial", monokai: "Monokai", pastel_on_dark: "Pastel On Dark", solarized_dark: "Solarized Dark", solarized_light: "Solarized Light", textmate: "Textmate", twilight: "Twilight", vibrant_ink: "Vibrant Ink" }, gutter: BOOL, fontSize: { "10px": "10px", "11px": "11px", "12px": "12px", "14px": "14px", "16px": "16px" }, softWrap: { off: "Off", 40: "40", 80: "80", free: "Free" }, keybindings: { ace: "ace", vim: "vim", emacs: "emacs" }, showPrintMargin: BOOL, useSoftTabs: BOOL, showInvisibles: BOOL }; var table = []; table.push("
Setting | Value |
---|---|
", desc[option], " | "); table.push(""); renderOption(table, option, optionValues[option], options[option]); table.push(" |