aura 0.0.1.pre10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (249) hide show
  1. data/.gitignore +6 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +2 -0
  4. data/HISTORY.md +95 -0
  5. data/README.md +53 -0
  6. data/Rakefile +27 -0
  7. data/Scribefile +8 -0
  8. data/app/css/_utilities.scss +88 -0
  9. data/app/css/admin.scss +21 -0
  10. data/app/css/admin/_settings.scss +136 -0
  11. data/app/css/admin/chrome.scss +208 -0
  12. data/app/css/admin/common.scss +78 -0
  13. data/app/css/admin/forms.scss +342 -0
  14. data/app/css/admin/jquery_wysiwyg.scss +96 -0
  15. data/app/css/admin/loading.scss +18 -0
  16. data/app/css/admin/meta.scss +42 -0
  17. data/app/css/admin/reset.scss +46 -0
  18. data/app/css/admin/sections.scss +79 -0
  19. data/app/css/admin/setup.scss +22 -0
  20. data/app/css/admin/sidebar.scss +136 -0
  21. data/app/css/admin/slug.scss +78 -0
  22. data/app/css/admin/uiscreen.scss +22 -0
  23. data/app/css/admin/wysiwyg_field.scss +11 -0
  24. data/app/css/admin_watermark.scss +23 -0
  25. data/app/css/default_home_page.scss +13 -0
  26. data/app/css/login.scss +47 -0
  27. data/app/helpers/admin_helpers.rb +59 -0
  28. data/app/helpers/flash_helpers.rb +86 -0
  29. data/app/helpers/form_builder_helpers.rb +9 -0
  30. data/app/helpers/html_helpers.rb +27 -0
  31. data/app/helpers/jquery_helpers.rb +26 -0
  32. data/app/helpers/main_helpers.rb +67 -0
  33. data/app/helpers/page_helpers.rb +92 -0
  34. data/app/helpers/template_helpers.rb +94 -0
  35. data/app/helpers/user_helpers.rb +45 -0
  36. data/app/init/admin.rb +34 -0
  37. data/app/init/extensions.rb +18 -0
  38. data/app/init/pistol.rb +11 -0
  39. data/app/init/sequel.rb +11 -0
  40. data/app/main.rb +106 -0
  41. data/app/migrations/page.rb +29 -0
  42. data/app/migrations/settings.rb +11 -0
  43. data/app/migrations/user.rb +13 -0
  44. data/app/models/page.rb +116 -0
  45. data/app/models/page_seed.rb +47 -0
  46. data/app/models/settings.rb +59 -0
  47. data/app/models/user.rb +60 -0
  48. data/app/routes/admin.rb +44 -0
  49. data/app/routes/css_js.rb +53 -0
  50. data/app/routes/design_tests.rb +15 -0
  51. data/app/routes/editor.rb +152 -0
  52. data/app/routes/site.rb +33 -0
  53. data/app/routes/user.rb +48 -0
  54. data/app/views/admin/_back_to_dashboard.haml +3 -0
  55. data/app/views/admin/dashboard.haml +46 -0
  56. data/app/views/admin/layout.haml +73 -0
  57. data/app/views/admin/settings.haml +40 -0
  58. data/app/views/admin/settings/database.haml +42 -0
  59. data/app/views/base/crumbs.haml +50 -0
  60. data/app/views/base/delete.haml +19 -0
  61. data/app/views/base/edit.haml +61 -0
  62. data/app/views/base/errors.haml +10 -0
  63. data/app/views/base/form.haml +11 -0
  64. data/app/views/base/list.haml +14 -0
  65. data/app/views/base/list_actions.haml +4 -0
  66. data/app/views/base/list_item.haml +7 -0
  67. data/app/views/base/nav.haml +36 -0
  68. data/app/views/base/new.haml +36 -0
  69. data/app/views/base/preview.haml +28 -0
  70. data/app/views/base/tabs.haml +12 -0
  71. data/app/views/default_home_page.haml +15 -0
  72. data/app/views/design_tests/admin_styles.haml +58 -0
  73. data/app/views/form_builder/builder.haml +29 -0
  74. data/app/views/page/edit.haml +29 -0
  75. data/app/views/page/form.haml +22 -0
  76. data/app/views/page/meta_form.haml +22 -0
  77. data/app/views/page/new.haml +26 -0
  78. data/app/views/user/edit.haml +52 -0
  79. data/app/views/user/form.haml +43 -0
  80. data/app/views/user/list.haml +11 -0
  81. data/app/views/user/login.haml +33 -0
  82. data/app/views/user/new.haml +25 -0
  83. data/app/views/user/welcome.haml +29 -0
  84. data/app/views/watermark/watermark.haml +16 -0
  85. data/aura.gemspec +36 -0
  86. data/bin/aura +8 -0
  87. data/config/database.rb +12 -0
  88. data/config/extensions.rb +5 -0
  89. data/config/scss.rb +14 -0
  90. data/config/user.rb +10 -0
  91. data/default/.gitignore +6 -0
  92. data/default/Gemfile +11 -0
  93. data/default/README.md +24 -0
  94. data/default/Rakefile +8 -0
  95. data/default/app/README +3 -0
  96. data/default/app/css/.gitignore +0 -0
  97. data/default/app/helpers/helpers.rb.example +9 -0
  98. data/default/app/js/.gitignore +0 -0
  99. data/default/app/migrations/model.rb.example +20 -0
  100. data/default/app/models/model.rb.example +11 -0
  101. data/default/app/models/page-ext.rb.example +17 -0
  102. data/default/app/routes/site.rb.example +5 -0
  103. data/default/app/views/hello.haml.example +1 -0
  104. data/default/config.ru +3 -0
  105. data/default/config/.gitignore +0 -0
  106. data/default/config/database.rb.example +30 -0
  107. data/default/config/extensions.rb +5 -0
  108. data/default/config/user.rb.example +10 -0
  109. data/default/db/.gitignore +0 -0
  110. data/default/init.rb +15 -0
  111. data/default/public/.gitignore +0 -0
  112. data/extensions/contact_form/migrations/contact_form.rb +13 -0
  113. data/extensions/contact_form/models/contact_form.rb +13 -0
  114. data/extensions/contact_form/routes/contact_form.rb +11 -0
  115. data/extensions/contact_form/views/contact_form/edit.haml +8 -0
  116. data/extensions/contact_form/views/contact_form/form.haml +3 -0
  117. data/extensions/contact_form/views/contact_form/nav.haml +42 -0
  118. data/extensions/contact_form/views/contact_form/responses.haml +20 -0
  119. data/extensions/contact_form/views/contact_form/tabs.haml +8 -0
  120. data/extensions/default_theme/css/theme/_settings.scss +3 -0
  121. data/extensions/default_theme/css/theme/chrome.scss +66 -0
  122. data/extensions/default_theme/css/theme/reset.scss +34 -0
  123. data/extensions/default_theme/css/theme/style.scss +3 -0
  124. data/extensions/default_theme/info.yml +2 -0
  125. data/extensions/default_theme/public/browse.png +0 -0
  126. data/extensions/default_theme/views/base/id_portfolio.haml +32 -0
  127. data/extensions/default_theme/views/base/show.haml +31 -0
  128. data/extensions/default_theme/views/errors/error.haml +9 -0
  129. data/extensions/default_theme/views/errors/not_found.haml +11 -0
  130. data/extensions/default_theme/views/layout.haml +33 -0
  131. data/lib/aura.rb +315 -0
  132. data/lib/aura/admin.rb +41 -0
  133. data/lib/aura/app.rb +4 -0
  134. data/lib/aura/cli.rb +19 -0
  135. data/lib/aura/cli/base.rb +89 -0
  136. data/lib/aura/cli/helpers.rb +32 -0
  137. data/lib/aura/editor.rb +30 -0
  138. data/lib/aura/extension.rb +189 -0
  139. data/lib/aura/files.rb +38 -0
  140. data/lib/aura/menu.rb +142 -0
  141. data/lib/aura/models.rb +80 -0
  142. data/lib/aura/public.rb +68 -0
  143. data/lib/aura/rendering.rb +134 -0
  144. data/lib/aura/seeder.rb +38 -0
  145. data/lib/aura/slugs.rb +87 -0
  146. data/lib/aura/subtype.rb +48 -0
  147. data/lib/aura/tasks.rb +24 -0
  148. data/lib/aura/tasks/common.rb +17 -0
  149. data/lib/aura/tasks/db.rake +54 -0
  150. data/lib/aura/utils.rb +81 -0
  151. data/lib/aura/version.rb +25 -0
  152. data/lib/core/hasharray.rb +65 -0
  153. data/lib/core/object_ext.rb +9 -0
  154. data/lib/sequel/plugins/aura_custom.rb +16 -0
  155. data/lib/sequel/plugins/aura_editable.rb +39 -0
  156. data/lib/sequel/plugins/aura_hierarchy.rb +82 -0
  157. data/lib/sequel/plugins/aura_model.rb +271 -0
  158. data/lib/sequel/plugins/aura_renderable.rb +42 -0
  159. data/lib/sequel/plugins/aura_sluggable.rb +103 -0
  160. data/lib/sequel/plugins/aura_subtyped.rb +83 -0
  161. data/lib/terra.rb +185 -0
  162. data/lib/terra/ext.rb +16 -0
  163. data/lib/terra/field.rb +98 -0
  164. data/lib/terra/fields.rb +122 -0
  165. data/lib/terra/fieldset.rb +93 -0
  166. data/lib/terra/form.rb +111 -0
  167. data/manual/configuration.md +42 -0
  168. data/manual/extensions.md +45 -0
  169. data/manual/files.md +70 -0
  170. data/manual/helpers.md +39 -0
  171. data/manual/index.md +65 -0
  172. data/manual/models.md +58 -0
  173. data/manual/recipes.md +38 -0
  174. data/manual/recipes/bundling_sample_data.md +30 -0
  175. data/manual/recipes/creating_themes.md +10 -0
  176. data/manual/recipes/using_markdown_or_textile.md +24 -0
  177. data/manual/routes.md +39 -0
  178. data/manual/theming.md +55 -0
  179. data/manual/views.md +128 -0
  180. data/public/hi.html +0 -0
  181. data/public/images/admin/back.png +0 -0
  182. data/public/images/admin/browse.png +0 -0
  183. data/public/images/admin/mock-bg.png +0 -0
  184. data/public/images/admin/top-loader.gif +0 -0
  185. data/public/images/admin/uiscreen-loader.gif +0 -0
  186. data/public/images/admin_icons/add.png +0 -0
  187. data/public/images/admin_icons/contact.png +0 -0
  188. data/public/images/admin_icons/dashboard.png +0 -0
  189. data/public/images/admin_icons/generic.png +0 -0
  190. data/public/images/admin_icons/home-12.png +0 -0
  191. data/public/images/admin_icons/page.png +0 -0
  192. data/public/images/admin_icons/settings.png +0 -0
  193. data/public/images/jquery.wysiwyg.gif +0 -0
  194. data/public/js/admin.form_builder.js +15 -0
  195. data/public/js/admin.js +62 -0
  196. data/public/js/admin.layout.js +53 -0
  197. data/public/js/admin.nav.js +241 -0
  198. data/public/js/admin.slug.js +46 -0
  199. data/public/js/admin.subpage.js +15 -0
  200. data/public/js/jquery.hashlisten.js +85 -0
  201. data/public/js/jquery.js +166 -0
  202. data/public/js/jquery.livenavigate.js +58 -0
  203. data/public/js/jquery.livequery.js +226 -0
  204. data/public/js/jquery.quickvalidate.js +164 -0
  205. data/public/js/jquery.tmpl.js +486 -0
  206. data/public/js/jquery.uiscreen.js +150 -0
  207. data/public/js/jquery.wysiwyg.js +2339 -0
  208. data/public/js/jqueryui.js +766 -0
  209. data/public/js/lib.dirty.js +11 -0
  210. data/public/js/lib.loading.js +23 -0
  211. data/public/js/lib.wysiwyg.js +155 -0
  212. data/public/js/underscore-1.1.7.js +27 -0
  213. data/test/app/app/css/test_raw.css +1 -0
  214. data/test/app/app/css/test_sass.sass +3 -0
  215. data/test/app/app/damogram.txt +1 -0
  216. data/test/app/app/js/test_coffee.coffee +4 -0
  217. data/test/app/app/js/test_javascript.js +4 -0
  218. data/test/app/init.rb +5 -0
  219. data/test/stories/admin_css_story.rb +18 -0
  220. data/test/stories/css_js_story.rb +29 -0
  221. data/test/stories/first_login_story.rb +29 -0
  222. data/test/stories/visit_story.rb +39 -0
  223. data/test/stories_helper.rb +58 -0
  224. data/test/test_cli_helper.rb +31 -0
  225. data/test/test_helper.rb +111 -0
  226. data/test/test_temp_helper.rb +9 -0
  227. data/test/unit/cli_test.rb +38 -0
  228. data/test/unit/dump_test.rb +14 -0
  229. data/test/unit/extensions_test.rb +18 -0
  230. data/test/unit/files_test.rb +14 -0
  231. data/test/unit/flash_helper_test.rb +36 -0
  232. data/test/unit/html_helper_test.rb +29 -0
  233. data/test/unit/jquery_helper_test.rb +18 -0
  234. data/test/unit/model_test.rb +34 -0
  235. data/test/unit/page_helpers_test.rb +36 -0
  236. data/test/unit/seeder_test.rb +15 -0
  237. data/test/unit/settings_test.rb +29 -0
  238. data/test/unit/slug_test.rb +39 -0
  239. data/test/unit/ss_migration_test.rb +14 -0
  240. data/test/unit/terra_test.rb +125 -0
  241. data/test/unit/utils_test.rb +11 -0
  242. data/vendor/sinatra-sequel/.gitignore +3 -0
  243. data/vendor/sinatra-sequel/COPYING +18 -0
  244. data/vendor/sinatra-sequel/README.md +84 -0
  245. data/vendor/sinatra-sequel/Rakefile +67 -0
  246. data/vendor/sinatra-sequel/lib/sinatra/sequel.rb +73 -0
  247. data/vendor/sinatra-sequel/sinatra-sequel.gemspec +39 -0
  248. data/vendor/sinatra-sequel/spec/spec_sinatra_sequel.rb +70 -0
  249. metadata +536 -0
@@ -0,0 +1,150 @@
1
+ // Usage:
2
+ //
3
+ // $("#element").screen();
4
+ // $("#element").unscreen();
5
+ // $.unscreen(); // remove all screens
6
+ //
7
+ ;(function($) {
8
+ function resetPosition($screen, $el) {
9
+ $screen
10
+ .css({
11
+ 'top': $el.position().top + parseInt($el.css('margin-top')),
12
+ 'left': $el.position().left + parseInt($el.css('margin-left')),
13
+ 'position': 'absolute',
14
+ 'width': $el.outerWidth(),
15
+ 'height': $el.outerHeight()
16
+ });
17
+ };
18
+
19
+ $.uiscreen = $.extend(function(el) {
20
+ $.uiscreen.activate(el);
21
+ }, {
22
+ // State
23
+ $screens: [],
24
+
25
+ // Options
26
+ background: '#555555',
27
+ opacity: 0.5,
28
+ screen_template: "<div class='uiscreen'><div class='uiscreen-spinner'></div></div>",
29
+ z_index: 10010,
30
+ fadein_time: 250,
31
+ fadeout_time: 0,
32
+
33
+ // Methods
34
+ activate: function(el, options) {
35
+ var $el = $(el);
36
+ if ($(el).length === 0) { return false; }
37
+
38
+ if (!options) { options = {}; }
39
+
40
+ var id = "uiscreen-for-" + ($el.attr('id') ? $el.attr('id') : 'noid');
41
+
42
+ var $screen = this.$screen($el);
43
+ if (options['class']) { $screen.addClass(options['class']); }
44
+
45
+ $screen.css({ 'opacity': this.opacity });
46
+ resetPosition($screen, $el);
47
+
48
+ $el.offsetParent().append($screen);
49
+ $screen
50
+ .data('parent', $el)
51
+ .attr('id', id)
52
+ .addClass('fadein')
53
+ .show()
54
+ .animate(
55
+ { 'opacity': this.opacity },
56
+ this.fadein_time,
57
+ function() {
58
+ $(this).removeClass('fadein');
59
+ });
60
+ },
61
+
62
+ kill: function(el, options) {
63
+ var $el = $(el);
64
+
65
+ if (!$el.data('$screen')) {
66
+ return;
67
+ }
68
+
69
+ var speed = (options && (options.speed != undefined)) ? options.speed : this.fadeout_time;
70
+
71
+ $el.data('$screen')
72
+ .addClass('fadeout')
73
+ .animate(
74
+ { 'opacity': 0 },
75
+ speed,
76
+ function() {
77
+ $(this).remove();
78
+ });
79
+
80
+ $el.data('$screen', null);
81
+ },
82
+
83
+ // Return the screen for a certain element
84
+ $screen: function($el) {
85
+ if ($el.data('$screen')) { return $el.data('$screen'); }
86
+
87
+ // Construct the screen.
88
+ var $screen =
89
+ $(this.screen_template).
90
+ css({
91
+ 'position': 'absolute',
92
+ 'margin': 0,
93
+ 'padding':0,
94
+ 'border': 0,
95
+ 'top': 0,
96
+ 'left': 0,
97
+ 'width': 1,
98
+ 'height': 1,
99
+ 'z-index': this.z_index
100
+ })
101
+ .hide();
102
+
103
+ if (this.background)
104
+ { $screen.css({ 'background': this.background }); }
105
+
106
+ $(document.body).append($screen);
107
+ this.$screens.push($screen);
108
+
109
+ $el.data('$screen', $screen);
110
+ return $screen;
111
+ }
112
+ });
113
+
114
+ $.unscreen = function(options) {
115
+ var $parents = $('');
116
+ for (i in $.uiscreen.$screens) {
117
+ var screen = $.uiscreen.$screens[i];
118
+ var $parent = screen.data('parent');
119
+ if (($parent) && ($parent.unscreen)) { $parent.unscreen(options); }
120
+ }
121
+ };
122
+
123
+ $.fn.screen = function(options) {
124
+ this.each(function() {
125
+ $.uiscreen.activate($(this), options);
126
+ });
127
+ return this;
128
+ };
129
+
130
+ $.fn.unscreen = function(options) {
131
+ this.each(function() {
132
+ $.uiscreen.kill($(this), options);
133
+ });
134
+ return this;
135
+ };
136
+
137
+ // Make sure that all uiscreens hug their parents, literally
138
+ $.uiscreen.autoresize = function() {
139
+ var $parents = $('');
140
+ for (i in $.uiscreen.$screens) {
141
+ var screen = $.uiscreen.$screens[i];
142
+ var $parent = screen.data('parent');
143
+ if ($parent) { resetPosition($(screen), $parent); }
144
+ }
145
+ };
146
+
147
+ $(window).resize(function () {
148
+ $.uiscreen.autoresize();
149
+ });
150
+ })(jQuery);
@@ -0,0 +1,2339 @@
1
+ /**
2
+ * wn
3
+ * WYSIWYG - jQuery plugin 0.97
4
+ * (0.97.2 - From infinity)
5
+ *
6
+ * Copyright (c) 2008-2009 Juan M Martinez, 2010-2011 Akzhan Abdulin and all contributors
7
+ * https://github.com/akzhan/jwysiwyg
8
+ *
9
+ * Dual licensed under the MIT and GPL licenses:
10
+ * http://www.opensource.org/licenses/mit-license.php
11
+ * http://www.gnu.org/licenses/gpl.html
12
+ *
13
+ */
14
+
15
+ /*jslint browser: true, forin: true */
16
+
17
+ (function ($) {
18
+ "use strict";
19
+ /* Wysiwyg namespace: private properties and methods */
20
+
21
+ var console = window.console ? window.console : {
22
+ log: $.noop,
23
+ error: function (msg) {
24
+ $.error(msg);
25
+ }
26
+ };
27
+ var supportsProp = (('prop' in $.fn) && ('removeProp' in $.fn));
28
+
29
+ function Wysiwyg() {
30
+ this.controls = {
31
+ bold: {
32
+ groupIndex: 0,
33
+ visible: true,
34
+ tags: ["b", "strong"],
35
+ css: {
36
+ fontWeight: "bold"
37
+ },
38
+ tooltip: "Bold",
39
+ hotkey: {"ctrl": 1, "key": 66}
40
+ },
41
+
42
+ copy: {
43
+ groupIndex: 8,
44
+ visible: false,
45
+ tooltip: "Copy"
46
+ },
47
+
48
+ createLink: {
49
+ groupIndex: 6,
50
+ visible: true,
51
+ exec: function () {
52
+ var self = this;
53
+ if ($.wysiwyg.controls && $.wysiwyg.controls.link) {
54
+ $.wysiwyg.controls.link.init(this);
55
+ } else if ($.wysiwyg.autoload) {
56
+ $.wysiwyg.autoload.control("wysiwyg.link.js", function () {
57
+ self.controls.createLink.exec.apply(self);
58
+ });
59
+ } else {
60
+ console.error("$.wysiwyg.controls.link not defined. You need to include wysiwyg.link.js file");
61
+ }
62
+ },
63
+ tags: ["a"],
64
+ tooltip: "Create link"
65
+ },
66
+
67
+ cut: {
68
+ groupIndex: 8,
69
+ visible: false,
70
+ tooltip: "Cut"
71
+ },
72
+
73
+ decreaseFontSize: {
74
+ groupIndex: 9,
75
+ visible: false,
76
+ tags: ["small"],
77
+ tooltip: "Decrease font size",
78
+ exec: function () {
79
+ this.decreaseFontSize();
80
+ }
81
+ },
82
+
83
+ h1: {
84
+ groupIndex: 7,
85
+ visible: true,
86
+ className: "h1",
87
+ command: ($.browser.msie || $.browser.safari) ? "FormatBlock" : "heading",
88
+ "arguments": ($.browser.msie || $.browser.safari) ? "<h1>" : "h1",
89
+ tags: ["h1"],
90
+ tooltip: "Header 1"
91
+ },
92
+
93
+ h2: {
94
+ groupIndex: 7,
95
+ visible: true,
96
+ className: "h2",
97
+ command: ($.browser.msie || $.browser.safari) ? "FormatBlock" : "heading",
98
+ "arguments": ($.browser.msie || $.browser.safari) ? "<h2>" : "h2",
99
+ tags: ["h2"],
100
+ tooltip: "Header 2"
101
+ },
102
+
103
+ h3: {
104
+ groupIndex: 7,
105
+ visible: true,
106
+ className: "h3",
107
+ command: ($.browser.msie || $.browser.safari) ? "FormatBlock" : "heading",
108
+ "arguments": ($.browser.msie || $.browser.safari) ? "<h3>" : "h3",
109
+ tags: ["h3"],
110
+ tooltip: "Header 3"
111
+ },
112
+
113
+ highlight: {
114
+ tooltip: "Highlight",
115
+ className: "highlight",
116
+ groupIndex: 1,
117
+ visible: false,
118
+ css: {
119
+ backgroundColor: "rgb(255, 255, 102)"
120
+ },
121
+ exec: function () {
122
+ var command, node, selection, args;
123
+
124
+ if ($.browser.msie || $.browser.safari) {
125
+ command = "backcolor";
126
+ } else {
127
+ command = "hilitecolor";
128
+ }
129
+
130
+ if ($.browser.msie) {
131
+ node = this.getInternalRange().parentElement();
132
+ } else {
133
+ selection = this.getInternalSelection();
134
+ node = selection.extentNode || selection.focusNode;
135
+
136
+ while (node.style === undefined) {
137
+ node = node.parentNode;
138
+ if (node.tagName && node.tagName.toLowerCase() === "body") {
139
+ return;
140
+ }
141
+ }
142
+ }
143
+
144
+ if (node.style.backgroundColor === "rgb(255, 255, 102)" ||
145
+ node.style.backgroundColor === "#ffff66") {
146
+ args = "#ffffff";
147
+ } else {
148
+ args = "#ffff66";
149
+ }
150
+
151
+ this.editorDoc.execCommand(command, false, args);
152
+ }
153
+ },
154
+
155
+ html: {
156
+ groupIndex: 10,
157
+ visible: false,
158
+ exec: function () {
159
+ var elementHeight;
160
+
161
+ if (this.options.resizeOptions && $.fn.resizable) {
162
+ elementHeight = this.element.height();
163
+ }
164
+
165
+ if (this.viewHTML) {
166
+ this.setContent(this.original.value);
167
+
168
+ $(this.original).hide();
169
+ this.editor.show();
170
+
171
+ if (this.options.resizeOptions && $.fn.resizable) {
172
+ // if element.height still the same after frame was shown
173
+ if (elementHeight === this.element.height()) {
174
+ this.element.height(elementHeight + this.editor.height());
175
+ }
176
+
177
+ this.element.resizable($.extend(true, {
178
+ alsoResize: this.editor
179
+ }, this.options.resizeOptions));
180
+ }
181
+
182
+ this.ui.toolbar.find("li").each(function () {
183
+ var li = $(this);
184
+
185
+ if (li.hasClass("html")) {
186
+ li.removeClass("active");
187
+ } else {
188
+ li.removeClass('disabled');
189
+ }
190
+ });
191
+ } else {
192
+ this.saveContent();
193
+
194
+ $(this.original).css({
195
+ width: this.element.outerWidth(),
196
+ height: this.element.height() - this.ui.toolbar.height(),
197
+ resize: "none"
198
+ }).show();
199
+ this.editor.hide();
200
+
201
+ if (this.options.resizeOptions && $.fn.resizable) {
202
+ // if element.height still the same after frame was hidden
203
+ if (elementHeight === this.element.height()) {
204
+ this.element.height(this.ui.toolbar.height());
205
+ }
206
+
207
+ this.element.resizable("destroy");
208
+ }
209
+
210
+ this.ui.toolbar.find("li").each(function () {
211
+ var li = $(this);
212
+
213
+ if (li.hasClass("html")) {
214
+ li.addClass("active");
215
+ } else {
216
+ if (false === li.hasClass("fullscreen")) {
217
+ li.removeClass("active").addClass('disabled');
218
+ }
219
+ }
220
+ });
221
+ }
222
+
223
+ this.viewHTML = !(this.viewHTML);
224
+ },
225
+ tooltip: "View source code"
226
+ },
227
+
228
+ increaseFontSize: {
229
+ groupIndex: 9,
230
+ visible: false,
231
+ tags: ["big"],
232
+ tooltip: "Increase font size",
233
+ exec: function () {
234
+ this.increaseFontSize();
235
+ }
236
+ },
237
+
238
+ indent: {
239
+ groupIndex: 2,
240
+ visible: true,
241
+ tooltip: "Indent"
242
+ },
243
+
244
+ insertHorizontalRule: {
245
+ groupIndex: 6,
246
+ visible: true,
247
+ tags: ["hr"],
248
+ tooltip: "Insert Horizontal Rule"
249
+ },
250
+
251
+ insertImage: {
252
+ groupIndex: 6,
253
+ visible: true,
254
+ exec: function () {
255
+ var self = this;
256
+
257
+ if ($.wysiwyg.controls && $.wysiwyg.controls.image) {
258
+ $.wysiwyg.controls.image.init(this);
259
+ } else if ($.wysiwyg.autoload) {
260
+ $.wysiwyg.autoload.control("wysiwyg.image.js", function () {
261
+ self.controls.insertImage.exec.apply(self);
262
+ });
263
+ } else {
264
+ console.error("$.wysiwyg.controls.image not defined. You need to include wysiwyg.image.js file");
265
+ }
266
+ },
267
+ tags: ["img"],
268
+ tooltip: "Insert image"
269
+ },
270
+
271
+ insertOrderedList: {
272
+ groupIndex: 5,
273
+ visible: true,
274
+ tags: ["ol"],
275
+ tooltip: "Insert Ordered List"
276
+ },
277
+
278
+ insertTable: {
279
+ groupIndex: 6,
280
+ visible: true,
281
+ exec: function () {
282
+ var self = this;
283
+
284
+ if ($.wysiwyg.controls && $.wysiwyg.controls.table) {
285
+ $.wysiwyg.controls.table(this);
286
+ } else if ($.wysiwyg.autoload) {
287
+ $.wysiwyg.autoload.control("wysiwyg.table.js", function () {
288
+ self.controls.insertTable.exec.apply(self);
289
+ });
290
+ } else {
291
+ console.error("$.wysiwyg.controls.table not defined. You need to include wysiwyg.table.js file");
292
+ }
293
+ },
294
+ tags: ["table"],
295
+ tooltip: "Insert table"
296
+ },
297
+
298
+ insertUnorderedList: {
299
+ groupIndex: 5,
300
+ visible: true,
301
+ tags: ["ul"],
302
+ tooltip: "Insert Unordered List"
303
+ },
304
+
305
+ italic: {
306
+ groupIndex: 0,
307
+ visible: true,
308
+ tags: ["i", "em"],
309
+ css: {
310
+ fontStyle: "italic"
311
+ },
312
+ tooltip: "Italic",
313
+ hotkey: {"ctrl": 1, "key": 73}
314
+ },
315
+
316
+ justifyCenter: {
317
+ groupIndex: 1,
318
+ visible: true,
319
+ tags: ["center"],
320
+ css: {
321
+ textAlign: "center"
322
+ },
323
+ tooltip: "Justify Center"
324
+ },
325
+
326
+ justifyFull: {
327
+ groupIndex: 1,
328
+ visible: true,
329
+ css: {
330
+ textAlign: "justify"
331
+ },
332
+ tooltip: "Justify Full"
333
+ },
334
+
335
+ justifyLeft: {
336
+ visible: true,
337
+ groupIndex: 1,
338
+ css: {
339
+ textAlign: "left"
340
+ },
341
+ tooltip: "Justify Left"
342
+ },
343
+
344
+ justifyRight: {
345
+ groupIndex: 1,
346
+ visible: true,
347
+ css: {
348
+ textAlign: "right"
349
+ },
350
+ tooltip: "Justify Right"
351
+ },
352
+
353
+ ltr: {
354
+ groupIndex: 10,
355
+ visible: false,
356
+ exec: function () {
357
+ var p = this.dom.getElement("p");
358
+
359
+ if (!p) {
360
+ return false;
361
+ }
362
+
363
+ $(p).attr("dir", "ltr");
364
+ return true;
365
+ },
366
+ tooltip : "Left to Right"
367
+ },
368
+
369
+ outdent: {
370
+ groupIndex: 2,
371
+ visible: true,
372
+ tooltip: "Outdent"
373
+ },
374
+
375
+ paragraph: {
376
+ groupIndex: 7,
377
+ visible: false,
378
+ className: "paragraph",
379
+ command: "FormatBlock",
380
+ "arguments": ($.browser.msie || $.browser.safari) ? "<p>" : "p",
381
+ tags: ["p"],
382
+ tooltip: "Paragraph"
383
+ },
384
+
385
+ paste: {
386
+ groupIndex: 8,
387
+ visible: false,
388
+ tooltip: "Paste"
389
+ },
390
+
391
+ redo: {
392
+ groupIndex: 4,
393
+ visible: true,
394
+ tooltip: "Redo"
395
+ },
396
+
397
+ removeFormat: {
398
+ groupIndex: 10,
399
+ visible: true,
400
+ exec: function () {
401
+ this.removeFormat();
402
+ },
403
+ tooltip: "Remove formatting"
404
+ },
405
+
406
+ rtl: {
407
+ groupIndex: 10,
408
+ visible: false,
409
+ exec: function () {
410
+ var p = this.dom.getElement("p");
411
+
412
+ if (!p) {
413
+ return false;
414
+ }
415
+
416
+ $(p).attr("dir", "rtl");
417
+ return true;
418
+ },
419
+ tooltip : "Right to Left"
420
+ },
421
+
422
+ strikeThrough: {
423
+ groupIndex: 0,
424
+ visible: true,
425
+ tags: ["s", "strike"],
426
+ css: {
427
+ textDecoration: "line-through"
428
+ },
429
+ tooltip: "Strike-through"
430
+ },
431
+
432
+ subscript: {
433
+ groupIndex: 3,
434
+ visible: true,
435
+ tags: ["sub"],
436
+ tooltip: "Subscript"
437
+ },
438
+
439
+ superscript: {
440
+ groupIndex: 3,
441
+ visible: true,
442
+ tags: ["sup"],
443
+ tooltip: "Superscript"
444
+ },
445
+
446
+ underline: {
447
+ groupIndex: 0,
448
+ visible: true,
449
+ tags: ["u"],
450
+ css: {
451
+ textDecoration: "underline"
452
+ },
453
+ tooltip: "Underline",
454
+ hotkey: {"ctrl": 1, "key": 85}
455
+ },
456
+
457
+ undo: {
458
+ groupIndex: 4,
459
+ visible: true,
460
+ tooltip: "Undo"
461
+ },
462
+
463
+ code: {
464
+ visible : true,
465
+ groupIndex: 6,
466
+ tooltip: "Code snippet",
467
+ exec: function () {
468
+ var range = this.getInternalRange(),
469
+ common = $(range.commonAncestorContainer),
470
+ $nodeName = range.commonAncestorContainer.nodeName.toLowerCase();
471
+ if (common.parent("code").length) {
472
+ common.unwrap();
473
+ } else {
474
+ if ($nodeName !== "body") {
475
+ common.wrap("<code/>");
476
+ }
477
+ }
478
+ }
479
+ },
480
+
481
+ cssWrap: {
482
+ visible : false,
483
+ groupIndex: 6,
484
+ tooltip: "CSS Wrapper",
485
+ exec: function () {
486
+ $.wysiwyg.controls.cssWrap.init(this);
487
+ }
488
+ }
489
+
490
+ };
491
+
492
+ this.defaults = {
493
+ html: '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body style="margin: 3px;">INITIAL_CONTENT</body></html>',
494
+ debug: false,
495
+ controls: {},
496
+ css: {},
497
+ events: {},
498
+ autoGrow: false,
499
+ autoSave: true,
500
+ brIE: true, // http://code.google.com/p/jwysiwyg/issues/detail?id=15
501
+ formHeight: 270,
502
+ formWidth: 440,
503
+ iFrameClass: null,
504
+ initialContent: "<p>Initial content</p>",
505
+ maxHeight: 10000, // see autoGrow
506
+ maxLength: 0,
507
+ messages: {
508
+ nonSelection: "Select the text you wish to link"
509
+ },
510
+ toolbarHtml: '<ul role="menu" class="toolbar"></ul>',
511
+ removeHeadings: false,
512
+ replaceDivWithP: false,
513
+ resizeOptions: false,
514
+ rmUnusedControls: false, // https://github.com/akzhan/jwysiwyg/issues/52
515
+ rmUnwantedBr: true, // http://code.google.com/p/jwysiwyg/issues/detail?id=11
516
+ tableFiller: "Lorem ipsum",
517
+ initialMinHeight: null,
518
+
519
+ controlImage: {
520
+ forceRelativeUrls: false
521
+ },
522
+
523
+ controlLink: {
524
+ forceRelativeUrls: false
525
+ },
526
+
527
+ plugins: { // placeholder for plugins settings
528
+ autoload: false,
529
+ i18n: false,
530
+ rmFormat: {
531
+ rmMsWordMarkup: false
532
+ }
533
+ },
534
+
535
+ dialog : "default"
536
+ };
537
+
538
+ this.availableControlProperties = [
539
+ "arguments",
540
+ "callback",
541
+ "className",
542
+ "command",
543
+ "css",
544
+ "custom",
545
+ "exec",
546
+ "groupIndex",
547
+ "hotkey",
548
+ "icon",
549
+ "tags",
550
+ "tooltip",
551
+ "visible"
552
+ ];
553
+
554
+ this.editor = null;
555
+ this.editorDoc = null;
556
+ this.element = null;
557
+ this.options = {};
558
+ this.original = null;
559
+ this.savedRange = null;
560
+ this.timers = [];
561
+ this.validKeyCodes = [8, 9, 13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46];
562
+
563
+ this.isDestroyed = false;
564
+
565
+ this.dom = { // DOM related properties and methods
566
+ ie: {
567
+ parent: null // link to dom
568
+ },
569
+ w3c: {
570
+ parent: null // link to dom
571
+ }
572
+ };
573
+ this.dom.parent = this;
574
+ this.dom.ie.parent = this.dom;
575
+ this.dom.w3c.parent = this.dom;
576
+
577
+ this.ui = {}; // UI related properties and methods
578
+ this.ui.self = this;
579
+ this.ui.toolbar = null;
580
+ this.ui.initialHeight = null; // ui.grow
581
+
582
+ this.dom.getAncestor = function (element, filterTagName) {
583
+ filterTagName = filterTagName.toLowerCase();
584
+
585
+ while (element && typeof element.tagName != "undefined" && "body" !== element.tagName.toLowerCase()) {
586
+ if (filterTagName === element.tagName.toLowerCase()) {
587
+ return element;
588
+ }
589
+
590
+ element = element.parentNode;
591
+ }
592
+ if(!element.tagName && (element.previousSibling || element.nextSibling)) {
593
+ if(element.previousSibling) {
594
+ if(element.previousSibling.tagName.toLowerCase() == filterTagName) {
595
+ return element.previousSibling;
596
+ }
597
+ }
598
+ if(element.nextSibling) {
599
+ if(element.nextSibling.tagName.toLowerCase() == filterTagName) {
600
+ return element.nextSibling;
601
+ }
602
+ }
603
+ }
604
+
605
+ return null;
606
+ };
607
+
608
+ this.dom.getElement = function (filterTagName) {
609
+ var dom = this;
610
+
611
+ filterTagName = filterTagName.toLowerCase();
612
+
613
+ if (window.getSelection) {
614
+ return dom.w3c.getElement(filterTagName);
615
+ } else {
616
+ return dom.ie.getElement(filterTagName);
617
+ }
618
+ };
619
+
620
+ this.dom.ie.getElement = function (filterTagName) {
621
+ var dom = this.parent,
622
+ selection = dom.parent.getInternalSelection(),
623
+ range = selection.createRange(),
624
+ element;
625
+
626
+ if ("Control" === selection.type) {
627
+ // control selection
628
+ if (1 === range.length) {
629
+ element = range.item(0);
630
+ } else {
631
+ // multiple control selection
632
+ return null;
633
+ }
634
+ } else {
635
+ element = range.parentElement();
636
+ }
637
+
638
+ return dom.getAncestor(element, filterTagName);
639
+ };
640
+
641
+ this.dom.w3c.getElement = function (filterTagName) {
642
+ var dom = this.parent,
643
+ range = dom.parent.getInternalRange(),
644
+ element;
645
+
646
+ if (!range) {
647
+ return null;
648
+ }
649
+
650
+ element = range.commonAncestorContainer;
651
+
652
+ if (3 === element.nodeType) {
653
+ element = element.parentNode;
654
+ }
655
+
656
+ // if startContainer not Text, Comment, or CDATASection element then
657
+ // startOffset is the number of child nodes between the start of the
658
+ // startContainer and the boundary point of the Range
659
+ if (element === range.startContainer) {
660
+ element = element.childNodes[range.startOffset];
661
+ }
662
+
663
+ if(!element.tagName && (element.previousSibiling || element.nextSibling)) {
664
+ if(element.previousSibiling) {
665
+ if(element.previousSibiling.tagName.toLowerCase() == filterTagName) {
666
+ return element.previousSibiling;
667
+ }
668
+ }
669
+ if(element.nextSibling) {
670
+ if(element.nextSibling.tagName.toLowerCase() == filterTagName) {
671
+ return element.nextSibling;
672
+ }
673
+ }
674
+ }
675
+
676
+ return dom.getAncestor(element, filterTagName);
677
+ };
678
+
679
+ this.ui.addHoverClass = function () {
680
+ $(this).addClass("wysiwyg-button-hover");
681
+ };
682
+
683
+ this.ui.appendControls = function () {
684
+ var ui = this,
685
+ self = this.self,
686
+ controls = self.parseControls(),
687
+ hasVisibleControls = true, // to prevent separator before first item
688
+ groups = [],
689
+ controlsByGroup = {},
690
+ i,
691
+ currentGroupIndex, // jslint wants all vars at top of function
692
+ iterateGroup = function (controlName, control) {
693
+ if (control.groupIndex && currentGroupIndex !== control.groupIndex) {
694
+ currentGroupIndex = control.groupIndex;
695
+ hasVisibleControls = false;
696
+ }
697
+
698
+ if (!control.visible) {
699
+ return;
700
+ }
701
+
702
+ if (!hasVisibleControls) {
703
+ ui.appendItemSeparator();
704
+ hasVisibleControls = true;
705
+ }
706
+
707
+ if (control.custom) {
708
+ ui.appendItemCustom(controlName, control);
709
+ } else {
710
+ ui.appendItem(controlName, control);
711
+ }
712
+ };
713
+
714
+ $.each(controls, function (name, c) {
715
+ var index = "empty";
716
+
717
+ if (undefined !== c.groupIndex) {
718
+ if ("" === c.groupIndex) {
719
+ index = "empty";
720
+ } else {
721
+ index = c.groupIndex;
722
+ }
723
+ }
724
+
725
+ if (undefined === controlsByGroup[index]) {
726
+ groups.push(index);
727
+ controlsByGroup[index] = {};
728
+ }
729
+ controlsByGroup[index][name] = c;
730
+ });
731
+
732
+ groups.sort(function (a, b) {
733
+ if ("number" === typeof (a) && typeof (a) === typeof (b)) {
734
+ return (a - b);
735
+ } else {
736
+ a = a.toString();
737
+ b = b.toString();
738
+
739
+ if (a > b) {
740
+ return 1;
741
+ }
742
+
743
+ if (a === b) {
744
+ return 0;
745
+ }
746
+
747
+ return -1;
748
+ }
749
+ });
750
+
751
+ if (0 < groups.length) {
752
+ // set to first index in groups to proper placement of separator
753
+ currentGroupIndex = groups[0];
754
+ }
755
+
756
+ for (i = 0; i < groups.length; i += 1) {
757
+ $.each(controlsByGroup[groups[i]], iterateGroup);
758
+ }
759
+ };
760
+
761
+ this.ui.appendItem = function (name, control) {
762
+ var self = this.self,
763
+ className = control.className || control.command || name || "empty",
764
+ tooltip = control.tooltip || control.command || name || "";
765
+
766
+ return $('<li role="menuitem" unselectable="on">' + (className) + "</li>")
767
+ .addClass(className)
768
+ .attr("title", tooltip)
769
+ .hover(this.addHoverClass, this.removeHoverClass)
770
+ .click(function () {
771
+ if ($(this).hasClass("disabled")) {
772
+ return false;
773
+ }
774
+
775
+ self.triggerControl.apply(self, [name, control]);
776
+
777
+ this.blur();
778
+ self.ui.returnRange();
779
+ self.ui.focus();
780
+ return true;
781
+ })
782
+ .appendTo(self.ui.toolbar);
783
+ };
784
+
785
+ this.ui.appendItemCustom = function (name, control) {
786
+ var self = this.self,
787
+ tooltip = control.tooltip || control.command || name || "";
788
+
789
+ if (control.callback) {
790
+ $(window).bind("trigger-" + name + ".wysiwyg", control.callback);
791
+ }
792
+
793
+ return $('<li role="menuitem" unselectable="on" style="background: url(\'' + control.icon + '\') no-repeat;"></li>')
794
+ .addClass("custom-command-" + name)
795
+ .addClass("wysiwyg-custom-command")
796
+ .addClass(name)
797
+ .attr("title", tooltip)
798
+ .hover(this.addHoverClass, this.removeHoverClass)
799
+ .click(function () {
800
+ if ($(this).hasClass("disabled")) {
801
+ return false;
802
+ }
803
+
804
+ self.triggerControl.apply(self, [name, control]);
805
+
806
+ this.blur();
807
+ self.ui.returnRange();
808
+ self.ui.focus();
809
+
810
+ self.triggerControlCallback(name);
811
+ return true;
812
+ })
813
+ .appendTo(self.ui.toolbar);
814
+ };
815
+
816
+ this.ui.appendItemSeparator = function () {
817
+ var self = this.self;
818
+ return $('<li role="separator" class="separator"></li>').appendTo(self.ui.toolbar);
819
+ };
820
+
821
+ this.autoSaveFunction = function () {
822
+ this.saveContent();
823
+ };
824
+
825
+ this.ui.checkTargets = function (element) {
826
+ var self = this.self;
827
+
828
+ $.each(self.options.controls, function (name, control) {
829
+ var className = control.className || control.command || name || "empty",
830
+ tags,
831
+ elm,
832
+ css,
833
+ el,
834
+ checkActiveStatus = function (cssProperty, cssValue) {
835
+ var handler;
836
+
837
+ if ("function" === typeof (cssValue)) {
838
+ handler = cssValue;
839
+ if (handler(el.css(cssProperty).toString().toLowerCase(), self)) {
840
+ self.ui.toolbar.find("." + className).addClass("active");
841
+ }
842
+ } else {
843
+ if (el.css(cssProperty).toString().toLowerCase() === cssValue) {
844
+ self.ui.toolbar.find("." + className).addClass("active");
845
+ }
846
+ }
847
+ };
848
+
849
+ if ("fullscreen" !== className) {
850
+ self.ui.toolbar.find("." + className).removeClass("active");
851
+ }
852
+
853
+ if (control.tags || (control.options && control.options.tags)) {
854
+ tags = control.tags || (control.options && control.options.tags);
855
+
856
+ elm = element;
857
+ while (elm) {
858
+ if (elm.nodeType !== 1) {
859
+ break;
860
+ }
861
+
862
+ if ($.inArray(elm.tagName.toLowerCase(), tags) !== -1) {
863
+ self.ui.toolbar.find("." + className).addClass("active");
864
+ }
865
+
866
+ elm = elm.parentNode;
867
+ }
868
+ }
869
+
870
+ if (control.css || (control.options && control.options.css)) {
871
+ css = control.css || (control.options && control.options.css);
872
+ el = $(element);
873
+
874
+ while (el) {
875
+ if (el[0].nodeType !== 1) {
876
+ break;
877
+ }
878
+ $.each(css, checkActiveStatus);
879
+
880
+ el = el.parent();
881
+ }
882
+ }
883
+ });
884
+ };
885
+
886
+ this.ui.designMode = function () {
887
+ var attempts = 3,
888
+ self = this.self,
889
+ runner;
890
+ runner = function (attempts) {
891
+ if ("on" === self.editorDoc.designMode) {
892
+ if (self.timers.designMode) {
893
+ window.clearTimeout(self.timers.designMode);
894
+ }
895
+
896
+ // IE needs to reget the document element (this.editorDoc) after designMode was set
897
+ if (self.innerDocument() !== self.editorDoc) {
898
+ self.ui.initFrame();
899
+ }
900
+
901
+ return;
902
+ }
903
+
904
+ try {
905
+ self.editorDoc.designMode = "on";
906
+ } catch (e) {
907
+ }
908
+
909
+ attempts -= 1;
910
+ if (attempts > 0) {
911
+ self.timers.designMode = window.setTimeout(function () { runner(attempts); }, 100);
912
+ }
913
+ };
914
+
915
+ runner(attempts);
916
+ };
917
+
918
+ this.destroy = function () {
919
+ this.isDestroyed = true;
920
+
921
+ var i, $form = this.element.closest("form");
922
+
923
+ for (i = 0; i < this.timers.length; i += 1) {
924
+ window.clearTimeout(this.timers[i]);
925
+ }
926
+
927
+ // Remove bindings
928
+ $form.unbind(".wysiwyg");
929
+ this.element.remove();
930
+ $.removeData(this.original, "wysiwyg");
931
+ $(this.original).show();
932
+ return this;
933
+ };
934
+
935
+ this.getRangeText = function () {
936
+ var r = this.getInternalRange();
937
+
938
+ if (r.toString) {
939
+ r = r.toString();
940
+ } else if (r.text) { // IE
941
+ r = r.text;
942
+ }
943
+
944
+ return r;
945
+ };
946
+ //not used?
947
+ this.execute = function (command, arg) {
948
+ if (typeof (arg) === "undefined") {
949
+ arg = null;
950
+ }
951
+ this.editorDoc.execCommand(command, false, arg);
952
+ };
953
+
954
+ this.extendOptions = function (options) {
955
+ var controls = {};
956
+
957
+ /**
958
+ * If the user set custom controls, we catch it, and merge with the
959
+ * defaults controls later.
960
+ */
961
+ if ("object" === typeof options.controls) {
962
+ controls = options.controls;
963
+ delete options.controls;
964
+ }
965
+
966
+ options = $.extend(true, {}, this.defaults, options);
967
+ options.controls = $.extend(true, {}, controls, this.controls, controls);
968
+
969
+ if (options.rmUnusedControls) {
970
+ $.each(options.controls, function (controlName) {
971
+ if (!controls[controlName]) {
972
+ delete options.controls[controlName];
973
+ }
974
+ });
975
+ }
976
+
977
+ return options;
978
+ };
979
+
980
+ this.ui.focus = function () {
981
+ var self = this.self;
982
+
983
+ self.editor.get(0).contentWindow.focus();
984
+ return self;
985
+ };
986
+
987
+ this.ui.returnRange = function () {
988
+ var self = this.self, sel;
989
+
990
+ if (self.savedRange !== null) {
991
+ if (window.getSelection) { //non IE and there is already a selection
992
+ sel = window.getSelection();
993
+ if (sel.rangeCount > 0) {
994
+ sel.removeAllRanges();
995
+ }
996
+ try {
997
+ sel.addRange(self.savedRange);
998
+ } catch (e) {
999
+ console.error(e);
1000
+ }
1001
+ } else if (window.document.createRange) { // non IE and no selection
1002
+ window.getSelection().addRange(self.savedRange);
1003
+ } else if (window.document.selection) { //IE
1004
+ self.savedRange.select();
1005
+ }
1006
+
1007
+ self.savedRange = null;
1008
+ }
1009
+ };
1010
+
1011
+ this.increaseFontSize = function () {
1012
+ if ($.browser.mozilla || $.browser.opera) {
1013
+ this.editorDoc.execCommand('increaseFontSize', false, null);
1014
+ } else if ($.browser.safari) {
1015
+ var newNode = this.editorDoc.createElement('big');
1016
+ this.getInternalRange().surroundContents(newNode);
1017
+ } else {
1018
+ console.error("Internet Explorer?");
1019
+ }
1020
+ };
1021
+
1022
+ this.decreaseFontSize = function () {
1023
+ if ($.browser.mozilla || $.browser.opera) {
1024
+ this.editorDoc.execCommand('decreaseFontSize', false, null);
1025
+ } else if ($.browser.safari) {
1026
+ var newNode = this.editorDoc.createElement('small');
1027
+ this.getInternalRange().surroundContents(newNode);
1028
+ } else {
1029
+ console.error("Internet Explorer?");
1030
+ }
1031
+ };
1032
+
1033
+ this.getContent = function () {
1034
+ if (this.viewHTML) {
1035
+ this.setContent(this.original.value);
1036
+ }
1037
+ return this.events.filter('getContent', this.editorDoc.body.innerHTML);
1038
+ };
1039
+
1040
+ /**
1041
+ * A jWysiwyg specific event system.
1042
+ *
1043
+ * Example:
1044
+ *
1045
+ * $("#editor").getWysiwyg().events.bind("getContent", function (orig) {
1046
+ * return "<div id='content'>"+orgi+"</div>";
1047
+ * });
1048
+ *
1049
+ * This makes it so that when ever getContent is called, it is wrapped in a div#content.
1050
+ */
1051
+ this.events = {
1052
+ _events : {},
1053
+
1054
+ /**
1055
+ * Similar to jQuery's bind, but for jWysiwyg only.
1056
+ */
1057
+ bind : function (eventName, callback) {
1058
+ if (typeof (this._events.eventName) !== "object") {
1059
+ this._events[eventName] = [];
1060
+ }
1061
+ this._events[eventName].push(callback);
1062
+ },
1063
+
1064
+ /**
1065
+ * Similar to jQuery's trigger, but for jWysiwyg only.
1066
+ */
1067
+ trigger : function (eventName, args) {
1068
+ if (typeof (this._events.eventName) === "object") {
1069
+ var editor = this.editor;
1070
+ $.each(this._events[eventName], function (k, v) {
1071
+ if (typeof (v) === "function") {
1072
+ v.apply(editor, args);
1073
+ }
1074
+ });
1075
+ }
1076
+ },
1077
+
1078
+ /**
1079
+ * This "filters" `originalText` by passing it as the first argument to every callback
1080
+ * with the name `eventName` and taking the return value and passing it to the next function.
1081
+ *
1082
+ * This function returns the result after all the callbacks have been applied to `originalText`.
1083
+ */
1084
+ filter : function (eventName, originalText) {
1085
+ if (typeof (this._events[eventName]) === "object") {
1086
+ var editor = this.editor,
1087
+ args = Array.prototype.slice.call(arguments, 1);
1088
+
1089
+ $.each(this._events[eventName], function (k, v) {
1090
+ if (typeof (v) === "function") {
1091
+ originalText = v.apply(editor, args);
1092
+ }
1093
+ });
1094
+ }
1095
+ return originalText;
1096
+ }
1097
+ };
1098
+
1099
+ this.getElementByAttributeValue = function (tagName, attributeName, attributeValue) {
1100
+ var i, value, elements = this.editorDoc.getElementsByTagName(tagName);
1101
+
1102
+ for (i = 0; i < elements.length; i += 1) {
1103
+ value = elements[i].getAttribute(attributeName);
1104
+
1105
+ if ($.browser.msie) {
1106
+ /** IE add full path, so I check by the last chars. */
1107
+ value = value.substr(value.length - attributeValue.length);
1108
+ }
1109
+
1110
+ if (value === attributeValue) {
1111
+ return elements[i];
1112
+ }
1113
+ }
1114
+
1115
+ return false;
1116
+ };
1117
+
1118
+ this.getInternalRange = function () {
1119
+ var selection = this.getInternalSelection();
1120
+
1121
+ if (!selection) {
1122
+ return null;
1123
+ }
1124
+
1125
+ if (selection.rangeCount && selection.rangeCount > 0) { // w3c
1126
+ return selection.getRangeAt(0);
1127
+ } else if (selection.createRange) { // ie
1128
+ return selection.createRange();
1129
+ }
1130
+
1131
+ return null;
1132
+ };
1133
+
1134
+ this.getInternalSelection = function () {
1135
+ // firefox: document.getSelection is deprecated
1136
+ if (this.editor.get(0).contentWindow) {
1137
+ if (this.editor.get(0).contentWindow.getSelection) {
1138
+ return this.editor.get(0).contentWindow.getSelection();
1139
+ }
1140
+ if (this.editor.get(0).contentWindow.selection) {
1141
+ return this.editor.get(0).contentWindow.selection;
1142
+ }
1143
+ }
1144
+ if (this.editorDoc.getSelection) {
1145
+ return this.editorDoc.getSelection();
1146
+ }
1147
+ if (this.editorDoc.selection) {
1148
+ return this.editorDoc.selection;
1149
+ }
1150
+
1151
+ return null;
1152
+ };
1153
+
1154
+ this.getRange = function () {
1155
+ var selection = this.getSelection();
1156
+
1157
+ if (!selection) {
1158
+ return null;
1159
+ }
1160
+
1161
+ if (selection.rangeCount && selection.rangeCount > 0) { // w3c
1162
+ selection.getRangeAt(0);
1163
+ } else if (selection.createRange) { // ie
1164
+ return selection.createRange();
1165
+ }
1166
+
1167
+ return null;
1168
+ };
1169
+
1170
+ this.getSelection = function () {
1171
+ return (window.getSelection) ? window.getSelection() : window.document.selection;
1172
+ };
1173
+
1174
+ // :TODO: you can type long string and letters will be hidden because of overflow
1175
+ this.ui.grow = function () {
1176
+ var self = this.self,
1177
+ innerBody = $(self.editorDoc.body),
1178
+ innerHeight = $.browser.msie ? innerBody[0].scrollHeight : innerBody.height() + 2 + 20, // 2 - borders, 20 - to prevent content jumping on grow
1179
+ minHeight = self.ui.initialHeight,
1180
+ height = Math.max(innerHeight, minHeight);
1181
+
1182
+ height = Math.min(height, self.options.maxHeight);
1183
+
1184
+ self.editor.attr("scrolling", height < self.options.maxHeight ? "no" : "auto"); // hide scrollbar firefox
1185
+ innerBody.css("overflow", height < self.options.maxHeight ? "hidden" : ""); // hide scrollbar chrome
1186
+
1187
+ self.editor.get(0).height = height;
1188
+
1189
+ return self;
1190
+ };
1191
+
1192
+ this.init = function (element, options) {
1193
+ var self = this,
1194
+ $form = $(element).closest("form"),
1195
+ newX = element.width || element.clientWidth || 0,
1196
+ newY = element.height || element.clientHeight || 0
1197
+ ;
1198
+
1199
+ this.options = this.extendOptions(options);
1200
+ this.original = element;
1201
+ this.ui.toolbar = $(this.options.toolbarHtml);
1202
+
1203
+ if ($.browser.msie && parseInt($.browser.version, 10) < 8) {
1204
+ this.options.autoGrow = false;
1205
+ }
1206
+
1207
+ if (newX === 0 && element.cols) {
1208
+ newX = (element.cols * 8) + 21;
1209
+ }
1210
+ if (newY === 0 && element.rows) {
1211
+ newY = (element.rows * 16) + 16;
1212
+ }
1213
+
1214
+ this.editor = $(window.location.protocol === "https:" ? '<iframe src="javascript:false;"></iframe>' : "<iframe></iframe>").attr("frameborder", "0");
1215
+
1216
+ if (this.options.iFrameClass) {
1217
+ this.editor.addClass(this.options.iFrameClass);
1218
+ } else {
1219
+ this.editor.css({
1220
+ minHeight: (newY - 6).toString() + "px",
1221
+ // fix for issue 12 ( http://github.com/akzhan/jwysiwyg/issues/issue/12 )
1222
+ width: (newX > 50) ? (newX - 8).toString() + "px" : ""
1223
+ });
1224
+ if ($.browser.msie && parseInt($.browser.version, 10) < 7) {
1225
+ this.editor.css("height", newY.toString() + "px");
1226
+ }
1227
+ }
1228
+ /**
1229
+ * http://code.google.com/p/jwysiwyg/issues/detail?id=96
1230
+ */
1231
+ this.editor.attr("tabindex", $(element).attr("tabindex"));
1232
+
1233
+ this.element = $("<div/>").addClass("wysiwyg");
1234
+
1235
+ if (!this.options.iFrameClass) {
1236
+ this.element.css({
1237
+ width: (newX > 0) ? newX.toString() + "px" : "100%"
1238
+ });
1239
+ }
1240
+
1241
+ $(element).hide().before(this.element);
1242
+
1243
+ this.viewHTML = false;
1244
+
1245
+ /**
1246
+ * @link http://code.google.com/p/jwysiwyg/issues/detail?id=52
1247
+ */
1248
+ this.initialContent = $(element).val();
1249
+ this.ui.initFrame();
1250
+
1251
+ if (this.options.resizeOptions && $.fn.resizable) {
1252
+ this.element.resizable($.extend(true, {
1253
+ alsoResize: this.editor
1254
+ }, this.options.resizeOptions));
1255
+ }
1256
+
1257
+ if (this.options.autoSave) {
1258
+ $form.bind("submit.wysiwyg", function () { self.autoSaveFunction(); });
1259
+ }
1260
+
1261
+ $form.bind("reset.wysiwyg", function () { self.resetFunction(); });
1262
+ };
1263
+
1264
+ this.ui.initFrame = function () {
1265
+ var self = this.self,
1266
+ stylesheet,
1267
+ growHandler,
1268
+ saveHandler;
1269
+
1270
+ self.ui.appendControls();
1271
+ self.element.append(self.ui.toolbar)
1272
+ .append($("<div><!-- --></div>")
1273
+ .css({
1274
+ clear: "both"
1275
+ }))
1276
+ .append(self.editor);
1277
+
1278
+ self.editorDoc = self.innerDocument();
1279
+
1280
+ if (self.isDestroyed) {
1281
+ return null;
1282
+ }
1283
+
1284
+ self.ui.designMode();
1285
+ self.editorDoc.open();
1286
+ self.editorDoc.write(
1287
+ self.options.html
1288
+ /**
1289
+ * @link http://code.google.com/p/jwysiwyg/issues/detail?id=144
1290
+ */
1291
+ .replace(/INITIAL_CONTENT/, function () { return self.wrapInitialContent(); })
1292
+ );
1293
+ self.editorDoc.close();
1294
+
1295
+ $.wysiwyg.plugin.bind(self);
1296
+
1297
+ $(self.editorDoc).trigger("initFrame.wysiwyg");
1298
+
1299
+ $(self.editorDoc).bind("click.wysiwyg", function (event) {
1300
+ self.ui.checkTargets(event.target ? event.target : event.srcElement);
1301
+ });
1302
+
1303
+ /**
1304
+ * @link http://code.google.com/p/jwysiwyg/issues/detail?id=20
1305
+ */
1306
+ $(self.original).focus(function () {
1307
+ if ($(this).filter(":visible")) {
1308
+ return;
1309
+ }
1310
+ self.ui.focus();
1311
+ });
1312
+
1313
+ $(self.editorDoc).keydown(function (event) {
1314
+ var emptyContentRegex;
1315
+ if (event.keyCode === 8) { // backspace
1316
+ emptyContentRegex = /^<([\w]+)[^>]*>(<br\/?>)?<\/\1>$/;
1317
+ if (emptyContentRegex.test(self.getContent())) { // if content is empty
1318
+ event.stopPropagation(); // prevent remove single empty tag
1319
+ return false;
1320
+ }
1321
+ }
1322
+ return true;
1323
+ });
1324
+
1325
+ if (!$.browser.msie) {
1326
+ $(self.editorDoc).keydown(function (event) {
1327
+ var controlName;
1328
+
1329
+ /* Meta for Macs. tom@punkave.com */
1330
+ if (event.ctrlKey || event.metaKey) {
1331
+ for (controlName in self.controls) {
1332
+ if (self.controls[controlName].hotkey && self.controls[controlName].hotkey.ctrl) {
1333
+ if (event.keyCode === self.controls[controlName].hotkey.key) {
1334
+ self.triggerControl.apply(self, [controlName, self.controls[controlName]]);
1335
+
1336
+ return false;
1337
+ }
1338
+ }
1339
+ }
1340
+ }
1341
+
1342
+ return true;
1343
+ });
1344
+ } else if (self.options.brIE) {
1345
+ $(self.editorDoc).keydown(function (event) {
1346
+ if (event.keyCode === 13) {
1347
+ var rng = self.getRange();
1348
+ rng.pasteHTML("<br/>");
1349
+ rng.collapse(false);
1350
+ rng.select();
1351
+
1352
+ return false;
1353
+ }
1354
+
1355
+ return true;
1356
+ });
1357
+ }
1358
+
1359
+ if (self.options.plugins.rmFormat.rmMsWordMarkup) {
1360
+ $(self.editorDoc).bind("keyup.wysiwyg", function (event) {
1361
+ if (event.ctrlKey || event.metaKey) {
1362
+ // CTRL + V (paste)
1363
+ if (86 === event.keyCode) {
1364
+ if ($.wysiwyg.rmFormat) {
1365
+ if ("object" === typeof (self.options.plugins.rmFormat.rmMsWordMarkup)) {
1366
+ $.wysiwyg.rmFormat.run(self, {rules: { msWordMarkup: self.options.plugins.rmFormat.rmMsWordMarkup }});
1367
+ } else {
1368
+ $.wysiwyg.rmFormat.run(self, {rules: { msWordMarkup: { enabled: true }}});
1369
+ }
1370
+ }
1371
+ }
1372
+ }
1373
+ });
1374
+ }
1375
+
1376
+ if (self.options.autoSave) {
1377
+ $(self.editorDoc).keydown(function () { self.autoSaveFunction(); })
1378
+ .keyup(function () { self.autoSaveFunction(); })
1379
+ .mousedown(function () { self.autoSaveFunction(); })
1380
+ .bind($.support.noCloneEvent ? "input.wysiwyg" : "paste.wysiwyg", function () { self.autoSaveFunction(); });
1381
+ }
1382
+
1383
+ if (self.options.autoGrow) {
1384
+ if (self.options.initialMinHeight !== null) {
1385
+ self.ui.initialHeight = self.options.initialMinHeight;
1386
+ } else {
1387
+ self.ui.initialHeight = $(self.editorDoc).height();
1388
+ }
1389
+ $(self.editorDoc.body).css("border", "1px solid white"); // cancel margin collapsing
1390
+
1391
+ growHandler = function () {
1392
+ self.ui.grow();
1393
+ };
1394
+
1395
+ $(self.editorDoc).keyup(growHandler);
1396
+ $(self.editorDoc).bind("editorRefresh.wysiwyg", growHandler);
1397
+
1398
+ // fix when content height > textarea height
1399
+ self.ui.grow();
1400
+ }
1401
+
1402
+ if (self.options.css) {
1403
+ if (String === self.options.css.constructor) {
1404
+ if ($.browser.msie) {
1405
+ stylesheet = self.editorDoc.createStyleSheet(self.options.css);
1406
+ $(stylesheet).attr({
1407
+ "media": "all"
1408
+ });
1409
+ } else {
1410
+ stylesheet = $("<link/>").attr({
1411
+ "href": self.options.css,
1412
+ "media": "all",
1413
+ "rel": "stylesheet",
1414
+ "type": "text/css"
1415
+ });
1416
+
1417
+ $(self.editorDoc).find("head").append(stylesheet);
1418
+ }
1419
+ } else {
1420
+ self.timers.initFrame_Css = window.setTimeout(function () {
1421
+ $(self.editorDoc.body).css(self.options.css);
1422
+ }, 0);
1423
+ }
1424
+ }
1425
+
1426
+ if (self.initialContent.length === 0) {
1427
+ if ("function" === typeof (self.options.initialContent)) {
1428
+ self.setContent(self.options.initialContent());
1429
+ } else {
1430
+ self.setContent(self.options.initialContent);
1431
+ }
1432
+ }
1433
+
1434
+ if (self.options.maxLength > 0) {
1435
+ $(self.editorDoc).keydown(function (event) {
1436
+ if ($(self.editorDoc).text().length >= self.options.maxLength && $.inArray(event.which, self.validKeyCodes) === -1) {
1437
+ event.preventDefault();
1438
+ }
1439
+ });
1440
+ }
1441
+
1442
+ // Support event callbacks
1443
+ $.each(self.options.events, function (key, handler) {
1444
+ $(self.editorDoc).bind(key + ".wysiwyg", function (event) {
1445
+ // Trigger event handler, providing the event and api to
1446
+ // support additional functionality.
1447
+ handler.apply(self.editorDoc, [event, self]);
1448
+ });
1449
+ });
1450
+
1451
+ // restores selection properly on focus
1452
+ if ($.browser.msie) {
1453
+ // Event chain: beforedeactivate => focusout => blur.
1454
+ // Focusout & blur fired too late to handle internalRange() in dialogs.
1455
+ // When clicked on input boxes both got range = null
1456
+ $(self.editorDoc).bind("beforedeactivate.wysiwyg", function () {
1457
+ self.savedRange = self.getInternalRange();
1458
+ });
1459
+ } else {
1460
+ $(self.editorDoc).bind("blur.wysiwyg", function () {
1461
+ self.savedRange = self.getInternalRange();
1462
+ });
1463
+ }
1464
+
1465
+ $(self.editorDoc.body).addClass("wysiwyg");
1466
+ if (self.options.events && self.options.events.save) {
1467
+ saveHandler = self.options.events.save;
1468
+
1469
+ $(self.editorDoc).bind("keyup.wysiwyg", saveHandler);
1470
+ $(self.editorDoc).bind("change.wysiwyg", saveHandler);
1471
+
1472
+ if ($.support.noCloneEvent) {
1473
+ $(self.editorDoc).bind("input.wysiwyg", saveHandler);
1474
+ } else {
1475
+ $(self.editorDoc).bind("paste.wysiwyg", saveHandler);
1476
+ $(self.editorDoc).bind("cut.wysiwyg", saveHandler);
1477
+ }
1478
+ }
1479
+
1480
+ /**
1481
+ * XHTML5 {@link https://github.com/akzhan/jwysiwyg/issues/152}
1482
+ */
1483
+ if (self.options.xhtml5 && self.options.unicode) {
1484
+ var replacements = {ne:8800,le:8804,para:182,xi:958,darr:8595,nu:957,oacute:243,Uacute:218,omega:969,prime:8242,pound:163,igrave:236,thorn:254,forall:8704,emsp:8195,lowast:8727,brvbar:166,alefsym:8501,nbsp:160,delta:948,clubs:9827,lArr:8656,Omega:937,Auml:196,cedil:184,and:8743,plusmn:177,ge:8805,raquo:187,uml:168,equiv:8801,laquo:171,rdquo:8221,Epsilon:917,divide:247,fnof:402,chi:967,Dagger:8225,iacute:237,rceil:8969,sigma:963,Oslash:216,acute:180,frac34:190,lrm:8206,upsih:978,Scaron:352,part:8706,exist:8707,nabla:8711,image:8465,prop:8733,zwj:8205,omicron:959,aacute:225,Yuml:376,Yacute:221,weierp:8472,rsquo:8217,otimes:8855,kappa:954,thetasym:977,harr:8596,Ouml:214,Iota:921,ograve:242,sdot:8901,copy:169,oplus:8853,acirc:226,sup:8835,zeta:950,Iacute:205,Oacute:211,crarr:8629,Nu:925,bdquo:8222,lsquo:8216,apos:39,Beta:914,eacute:233,egrave:232,lceil:8968,Kappa:922,piv:982,Ccedil:199,ldquo:8220,Xi:926,cent:162,uarr:8593,hellip:8230,Aacute:193,ensp:8194,sect:167,Ugrave:217,aelig:230,ordf:170,curren:164,sbquo:8218,macr:175,Phi:934,Eta:919,rho:961,Omicron:927,sup2:178,euro:8364,aring:229,Theta:920,mdash:8212,uuml:252,otilde:245,eta:951,uacute:250,rArr:8658,nsub:8836,agrave:224,notin:8713,ndash:8211,Psi:936,Ocirc:212,sube:8838,szlig:223,micro:181,not:172,sup1:185,middot:183,iota:953,ecirc:234,lsaquo:8249,thinsp:8201,sum:8721,ntilde:241,scaron:353,cap:8745,atilde:227,lang:10216,__replacement:65533,isin:8712,gamma:947,Euml:203,ang:8736,upsilon:965,Ntilde:209,hearts:9829,Alpha:913,Tau:932,spades:9824,dagger:8224,THORN:222,"int":8747,lambda:955,Eacute:201,Uuml:220,infin:8734,rlm:8207,Aring:197,ugrave:249,Egrave:200,Acirc:194,rsaquo:8250,ETH:208,oslash:248,alpha:945,Ograve:210,Prime:8243,mu:956,ni:8715,real:8476,bull:8226,beta:946,icirc:238,eth:240,prod:8719,larr:8592,ordm:186,perp:8869,Gamma:915,reg:174,ucirc:251,Pi:928,psi:968,tilde:732,asymp:8776,zwnj:8204,Agrave:192,deg:176,AElig:198,times:215,Delta:916,sim:8764,Otilde:213,Mu:924,uArr:8657,circ:710,theta:952,Rho:929,sup3:179,diams:9830,tau:964,Chi:935,frac14:188,oelig:339,shy:173,or:8744,dArr:8659,phi:966,iuml:239,Lambda:923,rfloor:8971,iexcl:161,cong:8773,ccedil:231,Icirc:206,frac12:189,loz:9674,rarr:8594,cup:8746,radic:8730,frasl:8260,euml:235,OElig:338,hArr:8660,Atilde:195,Upsilon:933,there4:8756,ouml:246,oline:8254,Ecirc:202,yacute:253,auml:228,permil:8240,sigmaf:962,iquest:191,empty:8709,pi:960,Ucirc:219,supe:8839,Igrave:204,yen:165,rang:10217,trade:8482,lfloor:8970,minus:8722,Zeta:918,sub:8834,epsilon:949,yuml:255,Sigma:931,Iuml:207,ocirc:244};
1485
+ self.events.bind("getContent", function (text) {
1486
+ return text.replace(/&(?:amp;)?(?!amp|lt|gt|quot)([a-z][a-z0-9]*);/gi, function (str, p1) {
1487
+ if (!replacements[p1]) {
1488
+ p1 = p1.toLowerCase();
1489
+ if (!replacements[p1]) {
1490
+ p1 = "__replacement";
1491
+ }
1492
+ }
1493
+
1494
+ var num = replacements[p1];
1495
+ /* Numeric return if ever wanted: return replacements[p1] ? "&#"+num+";" : ""; */
1496
+ return String.fromCharCode(num);
1497
+ });
1498
+ });
1499
+ }
1500
+ };
1501
+
1502
+ this.innerDocument = function () {
1503
+ var element = this.editor.get(0);
1504
+
1505
+ if (element.nodeName.toLowerCase() === "iframe") {
1506
+ if (element.contentDocument) { // Gecko
1507
+ return element.contentDocument;
1508
+ } else if (element.contentWindow) { // IE
1509
+ return element.contentWindow.document;
1510
+ }
1511
+
1512
+ if (this.isDestroyed) {
1513
+ return null;
1514
+ }
1515
+
1516
+ console.error("Unexpected error in innerDocument");
1517
+
1518
+ /*
1519
+ return ( $.browser.msie )
1520
+ ? document.frames[element.id].document
1521
+ : element.contentWindow.document // contentDocument;
1522
+ */
1523
+ }
1524
+
1525
+ return element;
1526
+ };
1527
+
1528
+ this.insertHtml = function (szHTML) {
1529
+ var img, range;
1530
+
1531
+ if (!szHTML || szHTML.length === 0) {
1532
+ return this;
1533
+ }
1534
+
1535
+ if ($.browser.msie) {
1536
+ this.ui.focus();
1537
+ this.editorDoc.execCommand("insertImage", false, "#jwysiwyg#");
1538
+ img = this.getElementByAttributeValue("img", "src", "#jwysiwyg#");
1539
+ if (img) {
1540
+ $(img).replaceWith(szHTML);
1541
+ }
1542
+ } else {
1543
+ if ($.browser.mozilla) { // @link https://github.com/akzhan/jwysiwyg/issues/50
1544
+ if (1 === $(szHTML).length) {
1545
+ range = this.getInternalRange();
1546
+ range.deleteContents();
1547
+ range.insertNode($(szHTML).get(0));
1548
+ } else {
1549
+ this.editorDoc.execCommand("insertHTML", false, szHTML);
1550
+ }
1551
+ } else {
1552
+ if (!this.editorDoc.execCommand("insertHTML", false, szHTML)) {
1553
+ this.editor.focus();
1554
+ /* :TODO: place caret at the end
1555
+ if (window.getSelection) {
1556
+ } else {
1557
+ }
1558
+ this.editor.focus();
1559
+ */
1560
+ this.editorDoc.execCommand("insertHTML", false, szHTML);
1561
+ }
1562
+ }
1563
+ }
1564
+
1565
+ this.saveContent();
1566
+
1567
+ return this;
1568
+ };
1569
+
1570
+ this.parseControls = function () {
1571
+ var self = this;
1572
+
1573
+ $.each(this.options.controls, function (controlName, control) {
1574
+ $.each(control, function (propertyName) {
1575
+ if (-1 === $.inArray(propertyName, self.availableControlProperties)) {
1576
+ throw controlName + '["' + propertyName + '"]: property "' + propertyName + '" not exists in Wysiwyg.availableControlProperties';
1577
+ }
1578
+ });
1579
+ });
1580
+
1581
+ if (this.options.parseControls) {
1582
+ return this.options.parseControls.call(this);
1583
+ }
1584
+
1585
+ return this.options.controls;
1586
+ };
1587
+
1588
+ this.removeFormat = function () {
1589
+ if ($.browser.msie) {
1590
+ this.ui.focus();
1591
+ }
1592
+
1593
+ if (this.options.removeHeadings) {
1594
+ this.editorDoc.execCommand("formatBlock", false, "<p>"); // remove headings
1595
+ }
1596
+
1597
+ this.editorDoc.execCommand("removeFormat", false, null);
1598
+ this.editorDoc.execCommand("unlink", false, null);
1599
+
1600
+ if ($.wysiwyg.rmFormat && $.wysiwyg.rmFormat.enabled) {
1601
+ if ("object" === typeof (this.options.plugins.rmFormat.rmMsWordMarkup)) {
1602
+ $.wysiwyg.rmFormat.run(this, {rules: { msWordMarkup: this.options.plugins.rmFormat.rmMsWordMarkup }});
1603
+ } else {
1604
+ $.wysiwyg.rmFormat.run(this, {rules: { msWordMarkup: { enabled: true }}});
1605
+ }
1606
+ }
1607
+
1608
+ return this;
1609
+ };
1610
+
1611
+ this.ui.removeHoverClass = function () {
1612
+ $(this).removeClass("wysiwyg-button-hover");
1613
+ };
1614
+
1615
+ this.resetFunction = function () {
1616
+ this.setContent(this.initialContent);
1617
+ };
1618
+
1619
+ this.saveContent = function () {
1620
+ if (this.viewHTML)
1621
+ {
1622
+ return; // no need
1623
+ }
1624
+ if (this.original) {
1625
+ var content, newContent;
1626
+
1627
+ content = this.getContent();
1628
+
1629
+ if (this.options.rmUnwantedBr) {
1630
+ content = content.replace(/<br\/?>$/, "");
1631
+ }
1632
+
1633
+ if (this.options.replaceDivWithP) {
1634
+ newContent = $("<div/>").addClass("temp").append(content);
1635
+
1636
+ newContent.children("div").each(function () {
1637
+ var element = $(this), p = element.find("p"), i;
1638
+
1639
+ if (0 === p.length) {
1640
+ p = $("<p></p>");
1641
+
1642
+ if (this.attributes.length > 0) {
1643
+ for (i = 0; i < this.attributes.length; i += 1) {
1644
+ p.attr(this.attributes[i].name, element.attr(this.attributes[i].name));
1645
+ }
1646
+ }
1647
+
1648
+ p.append(element.html());
1649
+
1650
+ element.replaceWith(p);
1651
+ }
1652
+ });
1653
+
1654
+ content = newContent.html();
1655
+ }
1656
+
1657
+ $(this.original).val(content);
1658
+
1659
+ if (this.options.events && this.options.events.save) {
1660
+ this.options.events.save.call(this);
1661
+ }
1662
+ }
1663
+
1664
+ return this;
1665
+ };
1666
+
1667
+ this.setContent = function (newContent) {
1668
+ this.editorDoc.body.innerHTML = newContent;
1669
+ this.saveContent();
1670
+
1671
+ return this;
1672
+ };
1673
+
1674
+ this.triggerControl = function (name, control) {
1675
+ var cmd = control.command || name,
1676
+ args = control["arguments"] || [];
1677
+
1678
+ if (control.exec) {
1679
+ control.exec.apply(this);
1680
+ } else {
1681
+ this.ui.focus();
1682
+ this.ui.withoutCss();
1683
+ // when click <Cut>, <Copy> or <Paste> got "Access to XPConnect service denied" code: "1011"
1684
+ // in Firefox untrusted JavaScript is not allowed to access the clipboard
1685
+ try {
1686
+ this.editorDoc.execCommand(cmd, false, args);
1687
+ } catch (e) {
1688
+ console.error(e);
1689
+ }
1690
+ }
1691
+
1692
+ if (this.options.autoSave) {
1693
+ this.autoSaveFunction();
1694
+ }
1695
+ };
1696
+
1697
+ this.triggerControlCallback = function (name) {
1698
+ $(window).trigger("trigger-" + name + ".wysiwyg", [this]);
1699
+ };
1700
+
1701
+ this.ui.withoutCss = function () {
1702
+ var self = this.self;
1703
+
1704
+ if ($.browser.mozilla) {
1705
+ try {
1706
+ self.editorDoc.execCommand("styleWithCSS", false, false);
1707
+ } catch (e) {
1708
+ try {
1709
+ self.editorDoc.execCommand("useCSS", false, true);
1710
+ } catch (e2) {
1711
+ }
1712
+ }
1713
+ }
1714
+
1715
+ return self;
1716
+ };
1717
+
1718
+ this.wrapInitialContent = function () {
1719
+ var content = this.initialContent,
1720
+ found = content.match(/<\/?p>/gi);
1721
+
1722
+ if (!found) {
1723
+ return "<p>" + content + "</p>";
1724
+ } else {
1725
+ // :TODO: checking/replacing
1726
+ }
1727
+
1728
+ return content;
1729
+ };
1730
+ }
1731
+
1732
+ /*
1733
+ * Wysiwyg namespace: public properties and methods
1734
+ */
1735
+ $.wysiwyg = {
1736
+ messages: {
1737
+ noObject: "Something goes wrong, check object"
1738
+ },
1739
+
1740
+ /**
1741
+ * Custom control support by Alec Gorge ( http://github.com/alecgorge )
1742
+ */
1743
+ addControl: function (object, name, settings) {
1744
+ return object.each(function () {
1745
+ var oWysiwyg = $(this).data("wysiwyg"),
1746
+ customControl = {},
1747
+ toolbar;
1748
+
1749
+ if (!oWysiwyg) {
1750
+ return this;
1751
+ }
1752
+
1753
+ customControl[name] = $.extend(true, {visible: true, custom: true}, settings);
1754
+ $.extend(true, oWysiwyg.options.controls, customControl);
1755
+
1756
+ // render new toolbar
1757
+ toolbar = $(oWysiwyg.options.toolbarHtml);
1758
+ oWysiwyg.ui.toolbar.replaceWith(toolbar);
1759
+ oWysiwyg.ui.toolbar = toolbar;
1760
+ oWysiwyg.ui.appendControls();
1761
+ });
1762
+ },
1763
+
1764
+ clear: function (object) {
1765
+ return object.each(function () {
1766
+ var oWysiwyg = $(this).data("wysiwyg");
1767
+
1768
+ if (!oWysiwyg) {
1769
+ return this;
1770
+ }
1771
+
1772
+ oWysiwyg.setContent("");
1773
+ });
1774
+ },
1775
+
1776
+ console: console, // let our console be available for extensions
1777
+
1778
+ destroy: function (object) {
1779
+ return object.each(function () {
1780
+ var oWysiwyg = $(this).data("wysiwyg");
1781
+
1782
+ if (!oWysiwyg) {
1783
+ return this;
1784
+ }
1785
+
1786
+ oWysiwyg.destroy();
1787
+ });
1788
+ },
1789
+
1790
+ "document": function (object) {
1791
+ // no chains because of return
1792
+ var oWysiwyg = object.data("wysiwyg");
1793
+
1794
+ if (!oWysiwyg) {
1795
+ return undefined;
1796
+ }
1797
+
1798
+ return $(oWysiwyg.editorDoc);
1799
+ },
1800
+
1801
+ getContent: function (object) {
1802
+ // no chains because of return
1803
+ var oWysiwyg = object.data("wysiwyg");
1804
+
1805
+ if (!oWysiwyg) {
1806
+ return undefined;
1807
+ }
1808
+
1809
+ return oWysiwyg.getContent();
1810
+ },
1811
+
1812
+ init: function (object, options) {
1813
+ return object.each(function () {
1814
+ var opts = $.extend(true, {}, options),
1815
+ obj;
1816
+
1817
+ // :4fun:
1818
+ // remove this textarea validation and change line in this.saveContent function
1819
+ // $(this.original).val(content); to $(this.original).html(content);
1820
+ // now you can make WYSIWYG editor on h1, p, and many more tags
1821
+ if (("textarea" !== this.nodeName.toLowerCase()) || $(this).data("wysiwyg")) {
1822
+ return;
1823
+ }
1824
+
1825
+ obj = new Wysiwyg();
1826
+ obj.init(this, opts);
1827
+ $.data(this, "wysiwyg", obj);
1828
+
1829
+ $(obj.editorDoc).trigger("afterInit.wysiwyg");
1830
+ });
1831
+ },
1832
+
1833
+ insertHtml: function (object, szHTML) {
1834
+ return object.each(function () {
1835
+ var oWysiwyg = $(this).data("wysiwyg");
1836
+
1837
+ if (!oWysiwyg) {
1838
+ return this;
1839
+ }
1840
+
1841
+ oWysiwyg.insertHtml(szHTML);
1842
+ });
1843
+ },
1844
+
1845
+ plugin: {
1846
+ listeners: {},
1847
+
1848
+ bind: function (Wysiwyg) {
1849
+ var self = this;
1850
+
1851
+ $.each(this.listeners, function (action, handlers) {
1852
+ var i, plugin;
1853
+
1854
+ for (i = 0; i < handlers.length; i += 1) {
1855
+ plugin = self.parseName(handlers[i]);
1856
+
1857
+ $(Wysiwyg.editorDoc).bind(action + ".wysiwyg", {plugin: plugin}, function (event) {
1858
+ $.wysiwyg[event.data.plugin.name][event.data.plugin.method].apply($.wysiwyg[event.data.plugin.name], [Wysiwyg]);
1859
+ });
1860
+ }
1861
+ });
1862
+ },
1863
+
1864
+ exists: function (name) {
1865
+ var plugin;
1866
+
1867
+ if ("string" !== typeof (name)) {
1868
+ return false;
1869
+ }
1870
+
1871
+ plugin = this.parseName(name);
1872
+
1873
+ if (!$.wysiwyg[plugin.name] || !$.wysiwyg[plugin.name][plugin.method]) {
1874
+ return false;
1875
+ }
1876
+
1877
+ return true;
1878
+ },
1879
+
1880
+ listen: function (action, handler) {
1881
+ var plugin;
1882
+
1883
+ plugin = this.parseName(handler);
1884
+
1885
+ if (!$.wysiwyg[plugin.name] || !$.wysiwyg[plugin.name][plugin.method]) {
1886
+ return false;
1887
+ }
1888
+
1889
+ if (!this.listeners[action]) {
1890
+ this.listeners[action] = [];
1891
+ }
1892
+
1893
+ this.listeners[action].push(handler);
1894
+
1895
+ return true;
1896
+ },
1897
+
1898
+ parseName: function (name) {
1899
+ var elements;
1900
+
1901
+ if ("string" !== typeof (name)) {
1902
+ return false;
1903
+ }
1904
+
1905
+ elements = name.split(".");
1906
+
1907
+ if (2 > elements.length) {
1908
+ return false;
1909
+ }
1910
+
1911
+ return {name: elements[0], method: elements[1]};
1912
+ },
1913
+
1914
+ register: function (data) {
1915
+ if (!data.name) {
1916
+ console.error("Plugin name missing");
1917
+ }
1918
+
1919
+ $.each($.wysiwyg, function (pluginName) {
1920
+ if (pluginName === data.name) {
1921
+ console.error("Plugin with name '" + data.name + "' was already registered");
1922
+ }
1923
+ });
1924
+
1925
+ $.wysiwyg[data.name] = data;
1926
+
1927
+ return true;
1928
+ }
1929
+ },
1930
+
1931
+ removeFormat: function (object) {
1932
+ return object.each(function () {
1933
+ var oWysiwyg = $(this).data("wysiwyg");
1934
+
1935
+ if (!oWysiwyg) {
1936
+ return this;
1937
+ }
1938
+
1939
+ oWysiwyg.removeFormat();
1940
+ });
1941
+ },
1942
+
1943
+ save: function (object) {
1944
+ return object.each(function () {
1945
+ var oWysiwyg = $(this).data("wysiwyg");
1946
+
1947
+ if (!oWysiwyg) {
1948
+ return this;
1949
+ }
1950
+
1951
+ oWysiwyg.saveContent();
1952
+ });
1953
+ },
1954
+
1955
+ selectAll: function (object) {
1956
+ var oWysiwyg = object.data("wysiwyg"), oBody, oRange, selection;
1957
+
1958
+ if (!oWysiwyg) {
1959
+ return this;
1960
+ }
1961
+
1962
+ oBody = oWysiwyg.editorDoc.body;
1963
+ if (window.getSelection) {
1964
+ selection = oWysiwyg.getInternalSelection();
1965
+ selection.selectAllChildren(oBody);
1966
+ } else {
1967
+ oRange = oBody.createTextRange();
1968
+ oRange.moveToElementText(oBody);
1969
+ oRange.select();
1970
+ }
1971
+ },
1972
+
1973
+ setContent: function (object, newContent) {
1974
+ return object.each(function () {
1975
+ var oWysiwyg = $(this).data("wysiwyg");
1976
+
1977
+ if (!oWysiwyg) {
1978
+ return this;
1979
+ }
1980
+
1981
+ oWysiwyg.setContent(newContent);
1982
+ });
1983
+ },
1984
+
1985
+ triggerControl: function (object, controlName) {
1986
+ return object.each(function () {
1987
+ var oWysiwyg = $(this).data("wysiwyg");
1988
+
1989
+ if (!oWysiwyg) {
1990
+ return this;
1991
+ }
1992
+
1993
+ if (!oWysiwyg.controls[controlName]) {
1994
+ console.error("Control '" + controlName + "' not exists");
1995
+ }
1996
+
1997
+ oWysiwyg.triggerControl.apply(oWysiwyg, [controlName, oWysiwyg.controls[controlName]]);
1998
+ });
1999
+ },
2000
+
2001
+ support: {
2002
+ prop: supportsProp
2003
+ },
2004
+
2005
+ utils: {
2006
+ extraSafeEntities: [["<", ">", "'", '"', " "], [32]],
2007
+
2008
+ encodeEntities: function (str) {
2009
+ var self = this, aStr, aRet = [];
2010
+
2011
+ if (this.extraSafeEntities[1].length === 0) {
2012
+ $.each(this.extraSafeEntities[0], function (i, ch) {
2013
+ self.extraSafeEntities[1].push(ch.charCodeAt(0));
2014
+ });
2015
+ }
2016
+ aStr = str.split("");
2017
+ $.each(aStr, function (i) {
2018
+ var iC = aStr[i].charCodeAt(0);
2019
+ if ($.inArray(iC, self.extraSafeEntities[1]) && (iC < 65 || iC > 127 || (iC > 90 && iC < 97))) {
2020
+ aRet.push('&#' + iC + ';');
2021
+ } else {
2022
+ aRet.push(aStr[i]);
2023
+ }
2024
+ });
2025
+
2026
+ return aRet.join('');
2027
+ }
2028
+ }
2029
+ };
2030
+
2031
+ /**
2032
+ * Unifies dialog methods to allow custom implementations
2033
+ *
2034
+ * Events:
2035
+ * * afterOpen
2036
+ * * beforeShow
2037
+ * * afterShow
2038
+ * * beforeHide
2039
+ * * afterHide
2040
+ * * beforeClose
2041
+ * * afterClose
2042
+ *
2043
+ * Example:
2044
+ * var dialog = new ($.wysiwyg.dialog)($('#idToTextArea').data('wysiwyg'), {"title": "Test", "content": "form data, etc."});
2045
+ *
2046
+ * dialog.bind("afterOpen", function () { alert('you should see a dialog behind this one!'); });
2047
+ *
2048
+ * dialog.open();
2049
+ *
2050
+ *
2051
+ */
2052
+ $.wysiwyg.dialog = function (jWysiwyg, opts) {
2053
+ var theme = (jWysiwyg && jWysiwyg.options && jWysiwyg.options.dialog) ? jWysiwyg.options.dialog : "default",
2054
+ obj = $.wysiwyg.dialog.createDialog(theme),
2055
+ that = this,
2056
+ $that = $(that);
2057
+
2058
+ this.options = {
2059
+ "modal": true,
2060
+ "draggable": true,
2061
+ "title": "Title",
2062
+ "content": "Content",
2063
+ "width":"auto",
2064
+ "height":"auto",
2065
+ "open": false,
2066
+ "close": false
2067
+ };
2068
+
2069
+ this.isOpen = false;
2070
+
2071
+ $.extend(this.options, opts);
2072
+
2073
+ // Opens a dialog with the specified content
2074
+ this.open = function () {
2075
+ this.isOpen = true;
2076
+
2077
+ obj.init.apply(that, []);
2078
+ var $dialog = obj.show.apply(that, []);
2079
+
2080
+ $that.trigger("afterOpen", [$dialog]);
2081
+
2082
+ };
2083
+
2084
+ this.show = function () {
2085
+ this.isOpen = true;
2086
+
2087
+ $that.trigger("beforeShow");
2088
+
2089
+ var $dialog = obj.show.apply(that, []);
2090
+
2091
+ $that.trigger("afterShow");
2092
+ };
2093
+
2094
+ this.hide = function () {
2095
+ this.isOpen = false;
2096
+
2097
+ $that.trigger("beforeHide");
2098
+
2099
+ var $dialog = obj.hide.apply(that, []);
2100
+
2101
+ $that.trigger("afterHide", [$dialog]);
2102
+ };
2103
+
2104
+ // Closes the dialog window.
2105
+ this.close = function () {
2106
+ this.isOpen = false;
2107
+
2108
+ var $dialog = obj.hide.apply(that, []);
2109
+
2110
+ $that.trigger("beforeClose", [$dialog]);
2111
+
2112
+ obj.destroy.apply(that, []);
2113
+
2114
+ $that.trigger("afterClose", [$dialog]);
2115
+
2116
+ };
2117
+
2118
+ if (this.options.open) {
2119
+ $that.bind("afterOpen", this.options.open);
2120
+ }
2121
+ if (this.options.close) {
2122
+ $that.bind("afterClose", this.options.close);
2123
+ }
2124
+
2125
+ return this;
2126
+ };
2127
+
2128
+ // "Static" Dialog methods.
2129
+ $.extend(true, $.wysiwyg.dialog, {
2130
+ _themes : {}, // sample {"Theme Name": object}
2131
+ _theme : "", // the current theme
2132
+
2133
+ register : function(name, obj) {
2134
+ $.wysiwyg.dialog._themes[name] = obj;
2135
+ },
2136
+
2137
+ deregister : function (name) {
2138
+ delete $.wysiwyg.dialog._themes[name];
2139
+ },
2140
+
2141
+ createDialog : function (name) {
2142
+ return new ($.wysiwyg.dialog._themes[name]);
2143
+ }
2144
+ });
2145
+
2146
+ $(function () { // need access to jQuery UI stuff.
2147
+ if (jQuery.ui) {
2148
+ $.wysiwyg.dialog.register("jqueryui", function () {
2149
+ var that = this;
2150
+
2151
+ this._$dialog = null;
2152
+
2153
+ this.init = function() {
2154
+ var abstractDialog = this,
2155
+ content = this.options.content;
2156
+
2157
+ if (typeof content === 'object') {
2158
+ if (typeof content.html === 'function') {
2159
+ content = content.html();
2160
+ } else if(typeof content.toString === 'function') {
2161
+ content = content.toString();
2162
+ }
2163
+ }
2164
+
2165
+ that._$dialog = $('<div></div>').attr('title', this.options.title).html(content);
2166
+
2167
+ var dialogHeight = this.options.height == 'auto' ? 300 : this.options.height,
2168
+ dialogWidth = this.options.width == 'auto' ? 450 : this.options.width;
2169
+
2170
+ // console.log(that._$dialog);
2171
+
2172
+ that._$dialog.dialog({
2173
+ modal: this.options.modal,
2174
+ draggable: this.options.draggable,
2175
+ height: dialogHeight,
2176
+ width: dialogWidth
2177
+ });
2178
+
2179
+ return that._$dialog;
2180
+ };
2181
+
2182
+ this.show = function () {
2183
+ that._$dialog.dialog("open");
2184
+ return that._$dialog;
2185
+ };
2186
+
2187
+ this.hide = function () {
2188
+ that._$dialog.dialog("close");
2189
+ return that._$dialog;
2190
+ };
2191
+
2192
+ this.destroy = function() {
2193
+ that._$dialog.dialog("destroy");
2194
+ return that._$dialog;
2195
+ };
2196
+ });
2197
+ }
2198
+
2199
+ $.wysiwyg.dialog.register("default", function () {
2200
+ var that = this;
2201
+
2202
+ this._$dialog = null;
2203
+
2204
+ this.init = function() {
2205
+ var abstractDialog = this,
2206
+ content = this.options.content;
2207
+
2208
+ if (typeof content === 'object') {
2209
+ if(typeof content.html === 'function') {
2210
+ content = content.html();
2211
+ }
2212
+ else if(typeof content.toString === 'function') {
2213
+ content = content.toString();
2214
+ }
2215
+ }
2216
+
2217
+ that._$dialog = $('<div class="wysiwyg-dialog"></div>');
2218
+
2219
+ var $topbar = $('<div class="wysiwyg-dialog-topbar"><div class="wysiwyg-dialog-close-wrapper"></div><div class="wysiwyg-dialog-title">'+this.options.title+'</div></div>');
2220
+ var $link = $('<a href="#" class="wysiwyg-dialog-close-button">X</a>');
2221
+
2222
+ $link.click(function () {
2223
+ abstractDialog.close(); // this is important it makes sure that is close from the abstract $.wysiwyg.dialog instace, not just locally
2224
+ });
2225
+
2226
+ $topbar.find('.wysiwyg-dialog-close-wrapper').prepend($link);
2227
+
2228
+ var $dcontent = $('<div class="wysiwyg-dialog-content">'+content+'</div>');
2229
+
2230
+ that._$dialog.append($topbar).append($dcontent);
2231
+
2232
+ // Set dialog's height & width, and position it correctly:
2233
+ var dialogHeight = this.options.height == 'auto' ? 300 : this.options.height,
2234
+ dialogWidth = this.options.width == 'auto' ? 450 : this.options.width;
2235
+ that._$dialog.hide().css({
2236
+ "width": dialogWidth,
2237
+ "height": dialogHeight,
2238
+ "left": (($(window).width() - dialogWidth) / 2),
2239
+ "top": (($(window).height() - dialogHeight) / 3)
2240
+ });
2241
+
2242
+ $("body").append(that._$dialog);
2243
+
2244
+ return that._$dialog;
2245
+ };
2246
+
2247
+ this.show = function () {
2248
+
2249
+ // Modal feature:
2250
+ if (this.options.modal) {
2251
+ that._$dialog.wrap('<div class="wysiwyg-dialog-modal-div"></div>');
2252
+ }
2253
+
2254
+ // Draggable feature:
2255
+ if (this.options.draggable) {
2256
+
2257
+ var mouseDown = false;
2258
+
2259
+ that._$dialog.find("div.wysiwyg-dialog-topbar").bind("mousedown", function (e) {
2260
+ e.preventDefault();
2261
+ $(this).css({ "cursor": "move" });
2262
+ var $topbar = $(this),
2263
+ _dialog = $(this).parents(".wysiwyg-dialog"),
2264
+ offsetX = (e.pageX - parseInt(_dialog.css("left"))),
2265
+ offsetY = (e.pageY - parseInt(_dialog.css("top")));
2266
+ mouseDown = true;
2267
+ $(this).css({ "cursor": "move" });
2268
+
2269
+ $(document).bind("mousemove", function (e) {
2270
+ e.preventDefault();
2271
+ if (mouseDown) {
2272
+ _dialog.css({
2273
+ "top": (e.pageY - offsetY),
2274
+ "left": (e.pageX - offsetX)
2275
+ });
2276
+ }
2277
+ }).bind("mouseup", function (e) {
2278
+ e.preventDefault();
2279
+ mouseDown = false;
2280
+ $topbar.css({ "cursor": "auto" });
2281
+ $(document).unbind("mousemove").unbind("mouseup");
2282
+ });
2283
+
2284
+ });
2285
+ }
2286
+
2287
+ that._$dialog.show();
2288
+ return that._$dialog;
2289
+
2290
+ };
2291
+
2292
+ this.hide = function () {
2293
+ that._$dialog.hide();
2294
+ return that._$dialog;
2295
+ };
2296
+
2297
+ this.destroy = function() {
2298
+
2299
+ // Modal feature:
2300
+ if (this.options.modal) {
2301
+ that._$dialog.unwrap();
2302
+ }
2303
+
2304
+ // Draggable feature:
2305
+ if (this.options.draggable) {
2306
+ that._$dialog.find("div.wysiwyg-dialog-topbar").unbind("mousedown");
2307
+ }
2308
+
2309
+ that._$dialog.remove();
2310
+ return that._$dialog;
2311
+ };
2312
+ });
2313
+ });
2314
+ // end Dialog
2315
+
2316
+ $.fn.wysiwyg = function (method) {
2317
+ var args = arguments, plugin;
2318
+
2319
+ if ("undefined" !== typeof $.wysiwyg[method]) {
2320
+ // set argument object to undefined
2321
+ args = Array.prototype.concat.call([args[0]], [this], Array.prototype.slice.call(args, 1));
2322
+ return $.wysiwyg[method].apply($.wysiwyg, Array.prototype.slice.call(args, 1));
2323
+ } else if ("object" === typeof method || !method) {
2324
+ Array.prototype.unshift.call(args, this);
2325
+ return $.wysiwyg.init.apply($.wysiwyg, args);
2326
+ } else if ($.wysiwyg.plugin.exists(method)) {
2327
+ plugin = $.wysiwyg.plugin.parseName(method);
2328
+ args = Array.prototype.concat.call([args[0]], [this], Array.prototype.slice.call(args, 1));
2329
+ return $.wysiwyg[plugin.name][plugin.method].apply($.wysiwyg[plugin.name], Array.prototype.slice.call(args, 1));
2330
+ } else {
2331
+ console.error("Method '" + method + "' does not exist on jQuery.wysiwyg.\nTry to include some extra controls or plugins");
2332
+ }
2333
+ };
2334
+
2335
+ $.fn.getWysiwyg = function () {
2336
+ return $.data(this, "wysiwyg");
2337
+ };
2338
+ })(jQuery);
2339
+