Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

264 řádky
9.5 KiB

  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  2. // MIT License. See license.txt
  3. // Options
  4. // parent
  5. // change (event)
  6. // Properties
  7. // set_input
  8. // input
  9. wn.provide("wn.editors");
  10. wn.editors.BootstrapWYSIWYG = Class.extend({
  11. init: function(opts) {
  12. wn.require("lib/js/lib/bootstrap-wysiwyg.js");
  13. this.opts = opts;
  14. this.make_body();
  15. this.make_bindings();
  16. },
  17. make_body: function() {
  18. var me = this;
  19. this.myid = "editor-" + wn.dom.set_unique_id();
  20. $('<div class="for-rich-text">\
  21. <div class="btn-toolbar" data-role="editor-toolbar" style="margin-bottom: 7px;"\
  22. data-target="#'+ this.myid +'">\
  23. <div class="btn-group hidden-xs form-group">\
  24. <a class="btn btn-default btn-small dropdown-toggle" data-toggle="dropdown" title="Font"><i class="icon-font"></i><b class="caret"></b></a>\
  25. <ul class="dropdown-menu"></ul>\
  26. </div>\
  27. <div class="btn-group form-group">\
  28. <a class="btn btn-default btn-small dropdown-toggle" data-toggle="dropdown" title="Font Size"><i class="icon-text-height"></i> <b class="caret"></b></a>\
  29. <ul class="dropdown-menu">\
  30. <li><a data-edit="formatBlock &lt;p&gt;"><p>Paragraph</p></a></li>\
  31. <li><a data-edit="formatBlock &lt;h1&gt;"><h1>Heading 1</h1></a></li>\
  32. <li><a data-edit="formatBlock &lt;h2&gt;"><h2>Heading 2</h2></a></li>\
  33. <li><a data-edit="formatBlock &lt;h3&gt;"><h3>Heading 3</h3></a></li>\
  34. <li><a data-edit="formatBlock &lt;h4&gt;"><h4>Heading 4</h4></a></li>\
  35. <li><a data-edit="formatBlock &lt;h5&gt;"><h5>Heading 5</h5></a></li>\
  36. </ul>\
  37. </div>\
  38. <div class="btn-group form-group">\
  39. <a class="btn btn-default btn-small" data-edit="bold" title="Bold (Ctrl/Cmd+B)"><i class="icon-bold"></i></a>\
  40. <a class="btn btn-default btn-small" data-edit="insertunorderedlist" title="Bullet list"><i class="icon-list-ul"></i></a>\
  41. <a class="btn btn-default btn-small" data-edit="insertorderedlist" title="Number list"><i class="icon-list-ol"></i></a>\
  42. <a class="btn btn-default btn-small" data-edit="outdent" title="Reduce indent (Shift+Tab)"><i class="icon-indent-left"></i></a>\
  43. <a class="btn btn-default btn-small" data-edit="indent" title="Indent (Tab)"><i class="icon-indent-right"></i></a>\
  44. </div>\
  45. <div class="btn-group hidden-xs form-group">\
  46. <a class="btn btn-default btn-small" data-edit="justifyleft" title="Align Left (Ctrl/Cmd+L)"><i class="icon-align-left"></i></a>\
  47. <a class="btn btn-default btn-small" data-edit="justifycenter" title="Center (Ctrl/Cmd+E)"><i class="icon-align-center"></i></a>\
  48. <a class="btn btn-default btn-small btn-add-link" title="Insert Link">\
  49. <i class="icon-link"></i></a>\
  50. <a class="btn btn-default btn-small" title="Remove Link" data-edit="unlink">\
  51. <i class="icon-unlink"></i></a>\
  52. <a class="btn btn-default btn-small" title="Insert picture (or just drag & drop)" id="pictureBtn-'+this.myid+'"><i class="icon-picture"></i></a>\
  53. <input type="file" data-role="magic-overlay" data-target="#pictureBtn-'+this.myid+'" data-edit="insertImage" />\
  54. <a class="btn btn-default btn-small" data-edit="insertHorizontalRule" title="Horizontal Line Break">-</a>\
  55. </div>\
  56. </div>\
  57. <div id="'+this.myid+'" class="wysiwyg-editor">\
  58. </div>\
  59. </div>\
  60. <div class="for-html" style="display:none">\
  61. <textarea class="html-editor" style="width:95%; height: 440px;\
  62. font-family: Monaco, Menlo, Consolas, Courier, monospace;\
  63. font-size: 11px;"></textarea>\
  64. </div>\
  65. <div class="btn-toolbar pull-right" style="margin-top: 7px;">\
  66. <div class="btn-group">\
  67. <a class="btn btn-default btn-small btn-info btn-rich-text" title="Rich Text" disabled="disabled"><i class="icon-reorder"></i></a>\
  68. <a class="btn btn-default btn-small btn-html" title="HTML"><i class="icon-wrench"></i></a>\
  69. </div>\
  70. </div><div class="clearfix"></div>').appendTo(this.opts.parent);
  71. this.$parent = $(this.opts.parent);
  72. this.$editor = $("#" + this.myid);
  73. this.$parent.find(".btn-add-link").click(function() {
  74. me.show_link_dialog();
  75. return false;
  76. })
  77. this.$editor.on("keyup", function() { me.save_selection() });
  78. this.$editor.on("mouseup", function() { me.save_selection() });
  79. this.$textarea = this.$parent.find(".html-editor");
  80. this.input = this.$editor.get(0);
  81. },
  82. set_focus: function() {
  83. this.$editor.focus();
  84. },
  85. save_selection: function() {
  86. this.saved_selection = wn.dom.save_selection();
  87. },
  88. show_link_dialog: function() {
  89. var me = this;
  90. var d = new wn.ui.Dialog({
  91. title: "Add Link",
  92. fields: [
  93. {fieldtype: "Data", label:"Link", fieldname: "link", reqd: 1,
  94. description:"example: http://example.com"},
  95. {fieldtype: "Button", label:"Add", fieldname: "add"},
  96. ]
  97. });
  98. d.show();
  99. d.fields_dict.link.set_input("http://");
  100. $(d.fields_dict.add.input).click(function() {
  101. var values = d.get_values();
  102. if(values) {
  103. d.hide();
  104. wn.dom.restore_selection(me.saved_selection);
  105. document.execCommand("CreateLink", false, values.link);
  106. }
  107. });
  108. d.onhide = function() {
  109. wn.dom.restore_selection(me.saved_selection);
  110. }
  111. },
  112. make_bindings: function() {
  113. var me = this;
  114. var fonts = ['Serif', 'Sans', 'Arial', 'Arial Black', 'Courier',
  115. 'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande',
  116. 'Lucida Sans', 'Tahoma', 'Times', 'Times New Roman', 'Verdana'],
  117. fontTarget = this.$parent.find('[title=Font]').siblings('.dropdown-menu');
  118. $.each(fonts, function (idx, fontName) {
  119. fontTarget.append($('<li><a data-edit="fontName ' +
  120. fontName +'" style="font-family:\''+ fontName +'\'">'+
  121. fontName + '</a></li>'));
  122. });
  123. // magic-overlay
  124. this.$parent.find('[data-role=magic-overlay]').each(function () {
  125. var overlay = $(this), target = $(overlay.data('target'));
  126. overlay.css('opacity', 0).css('position', 'absolute')
  127. //.offset(target.offset())
  128. .css("left", 157) // use this because in dialogs, can't find the offset
  129. .width(38).height(33);
  130. });
  131. this.$editor
  132. .wysiwyg()
  133. .on("mouseup keyup mouseout", function() {
  134. var value = $(this).html();
  135. if(value==null) value="";
  136. me.opts.change(value);
  137. })
  138. this.$textarea
  139. .on("change", function() {
  140. var value = $(this).val();
  141. if(value==null) value="";
  142. me.opts.change(value);
  143. });
  144. this.current_editor = this.$editor;
  145. this.$parent.find(".btn-html").click(function() {
  146. if($(this).prop("disabled")==true) return;
  147. wn.require("lib/js/lib/beautify-html.js");
  148. me.$textarea.val(html_beautify(me.$editor.cleanHtml()));
  149. me.$parent.find(".for-rich-text").toggle(false);
  150. me.$parent.find(".for-html").toggle(true);
  151. me.$parent.find(".btn-html").attr("disabled", "disabled");
  152. me.$parent.find(".btn-rich-text").attr("disabled", false);
  153. me.current_editor = me.$textarea;
  154. });
  155. this.$parent.find(".btn-rich-text").click(function() {
  156. if($(this).prop("disabled")==true) return;
  157. me.$editor.html(me.$textarea.val());
  158. me.$parent.find(".for-rich-text").toggle(true);
  159. me.$parent.find(".for-html").toggle(false);
  160. me.$parent.find(".btn-rich-text").attr("disabled", "disabled");
  161. me.$parent.find(".btn-html").attr("disabled", false);
  162. me.current_editor = me.$editor;
  163. });
  164. },
  165. set_input: function(value) {
  166. if(this.opts.field.inside_change_event)
  167. return;
  168. if(this.value!=value) {
  169. this.value = value==null ? "" : value;
  170. this.$editor.html(this.value);
  171. this.$textarea.val(this.value);
  172. }
  173. },
  174. get_value: function() {
  175. if(this.current_editor==this.$editor)
  176. return this.$editor.cleanHtml();
  177. else
  178. return this.$textarea.val();
  179. }
  180. })
  181. wn.editors.ACE = Class.extend({
  182. init: function(opts) {
  183. this.opts = opts;
  184. // setup ace
  185. wn.require('lib/js/lib/ace/ace.js');
  186. this.make();
  187. this.bind_form_load();
  188. },
  189. make: function() {
  190. $(this.opts.parent).css('border','1px solid #aaa');
  191. this.pre = $("<pre style='position: relative; height: 400px; \
  192. width: 100%; padding: 0px; border-radius: 0px;\
  193. margin: 0px; background-color: #fff;'>").appendTo(this.opts.parent).get(0);
  194. this.input = {};
  195. this.myid = wn.dom.set_unique_id(this.pre);
  196. this.editor = ace.edit(this.myid);
  197. if(this.opts.field.df.options=='Markdown' || this.opts.field.df.options=='HTML') {
  198. wn.require('lib/js/lib/ace/mode-html.js');
  199. var HTMLMode = require("ace/mode/html").Mode;
  200. this.editor.getSession().setMode(new HTMLMode());
  201. }
  202. else if(this.opts.field.df.options=='Javascript') {
  203. wn.require('lib/js/lib/ace/mode-javascript.js');
  204. var JavascriptMode = require("ace/mode/javascript").Mode;
  205. this.editor.getSession().setMode(new JavascriptMode());
  206. }
  207. else if(this.opts.field.df.options=='Python') {
  208. wn.require('lib/js/lib/ace/mode-python.js');
  209. var PythonMode = require("ace/mode/python").Mode;
  210. this.editor.getSession().setMode(new PythonMode());
  211. }
  212. },
  213. set_input: function(value) {
  214. // during field refresh in run trigger, set_input is called
  215. // if called during on_change, setting doesn't make sense
  216. // and causes cursor to shift back to first position
  217. if(this.opts.field.inside_change_event) return;
  218. this.setting_value = true;
  219. this.editor.getSession().setValue(value==null ? "" : value);
  220. this.setting_value = false;
  221. },
  222. get_value: function() {
  223. return this.editor.getSession().getValue();
  224. },
  225. set_focus: function() {
  226. this.editor.focus();
  227. },
  228. bind_form_load: function() {
  229. var me = this;
  230. if(cur_frm) {
  231. $(cur_frm.wrapper).bind('render_complete', function() {
  232. me.editor.resize();
  233. me.editor.getSession().on('change', function() {
  234. if(me.setting_value) return;
  235. me.opts.change(me.get_value())
  236. })
  237. });
  238. }
  239. },
  240. set_focus: function() {
  241. this.$editor.focus();
  242. },
  243. })