zen 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. data/.gems +34 -0
  2. data/.travis.yml +7 -0
  3. data/AUTHORS +5 -0
  4. data/CHANGELOG +14 -0
  5. data/{license.txt → LICENSE} +0 -0
  6. data/MANIFEST +67 -51
  7. data/README.md +18 -25
  8. data/Rakefile +2 -3
  9. data/bin/zen +2 -2
  10. data/lib/zen.rb +93 -57
  11. data/lib/zen/asset.rb +7 -8
  12. data/lib/zen/bin/app.rb +0 -2
  13. data/lib/zen/controller/admin_controller.rb +4 -9
  14. data/lib/zen/controller/base_controller.rb +0 -25
  15. data/lib/zen/controller/main_controller.rb +5 -5
  16. data/lib/zen/controller/preview.rb +50 -0
  17. data/lib/zen/helper/common.rb +4 -68
  18. data/lib/zen/helper/message.rb +82 -0
  19. data/lib/zen/helper/theme.rb +2 -2
  20. data/lib/zen/language.rb +68 -38
  21. data/lib/zen/language/en/zen_general.yml +1 -4
  22. data/lib/zen/language/nl/zen_general.yml +28 -0
  23. data/lib/zen/language/nl/zen_models.yml +13 -0
  24. data/lib/zen/layout/admin.xhtml +1 -1
  25. data/lib/zen/layout/login.xhtml +1 -1
  26. data/lib/zen/model/settings.rb +2 -0
  27. data/lib/zen/package.rb +29 -25
  28. data/lib/zen/package/all.rb +1 -1
  29. data/lib/zen/package/categories/lib/categories/controller/categories.rb +51 -63
  30. data/lib/zen/package/categories/lib/categories/controller/category_groups.rb +45 -52
  31. data/lib/zen/package/categories/lib/categories/language/en/categories.yml +2 -2
  32. data/lib/zen/package/categories/lib/categories/language/nl/categories.yml +39 -0
  33. data/lib/zen/package/categories/lib/categories/language/nl/category_groups.yml +33 -0
  34. data/lib/zen/package/categories/lib/categories/plugin/categories.rb +2 -2
  35. data/lib/zen/package/comments/lib/comments.rb +31 -2
  36. data/lib/zen/package/comments/lib/comments/controller/comments.rb +42 -57
  37. data/lib/zen/package/comments/lib/comments/controller/comments_form.rb +36 -51
  38. data/lib/zen/package/comments/lib/comments/language/en/comments.yml +7 -3
  39. data/lib/zen/package/comments/lib/comments/language/nl/comments.yml +48 -0
  40. data/lib/zen/package/comments/lib/comments/model/comment.rb +45 -4
  41. data/lib/zen/package/comments/lib/comments/plugin/anti_spam.rb +152 -0
  42. data/lib/zen/package/comments/lib/comments/plugin/comments.rb +5 -6
  43. data/lib/zen/package/comments/lib/comments/view/admin/comments/index.xhtml +2 -2
  44. data/lib/zen/package/custom_fields/lib/custom_fields/controller/custom_field_groups.rb +43 -52
  45. data/lib/zen/package/custom_fields/lib/custom_fields/controller/custom_fields.rb +68 -67
  46. data/lib/zen/package/custom_fields/lib/custom_fields/language/en/custom_fields.yml +1 -1
  47. data/lib/zen/package/custom_fields/lib/custom_fields/language/nl/custom_field_groups.yml +32 -0
  48. data/lib/zen/package/custom_fields/lib/custom_fields/language/nl/custom_fields.yml +52 -0
  49. data/lib/zen/package/custom_fields/lib/custom_fields/model/custom_field.rb +3 -3
  50. data/lib/zen/package/custom_fields/lib/custom_fields/model/custom_field_group.rb +4 -7
  51. data/lib/zen/package/custom_fields/lib/custom_fields/model/custom_field_value.rb +3 -3
  52. data/lib/zen/package/menus/lib/menus/controller/menu_items.rb +37 -44
  53. data/lib/zen/package/menus/lib/menus/controller/menus.rb +33 -43
  54. data/lib/zen/package/menus/lib/menus/helper/menu_item.rb +5 -10
  55. data/lib/zen/package/menus/lib/menus/language/nl/menu_items.yml +41 -0
  56. data/lib/zen/package/menus/lib/menus/language/nl/menus.yml +39 -0
  57. data/lib/zen/package/menus/lib/menus/model/menu.rb +3 -3
  58. data/lib/zen/package/menus/lib/menus/model/menu_item.rb +3 -3
  59. data/lib/zen/package/menus/lib/menus/plugin/menus.rb +5 -6
  60. data/lib/zen/package/menus/migrations/1297184342_create_schema.rb +1 -1
  61. data/lib/zen/package/sections/lib/sections.rb +20 -0
  62. data/lib/zen/package/sections/lib/sections/controller/section_entries.rb +85 -79
  63. data/lib/zen/package/sections/lib/sections/controller/sections.rb +58 -66
  64. data/lib/zen/package/sections/lib/sections/language/en/sections.yml +0 -1
  65. data/lib/zen/package/sections/lib/sections/language/nl/section_entries.yml +43 -0
  66. data/lib/zen/package/sections/lib/sections/language/nl/sections.yml +47 -0
  67. data/lib/zen/package/sections/lib/sections/model/section.rb +11 -15
  68. data/lib/zen/package/sections/lib/sections/model/section_entry.rb +9 -5
  69. data/lib/zen/package/sections/lib/sections/plugin/section_entries.rb +7 -8
  70. data/lib/zen/package/sections/lib/sections/plugin/sections.rb +3 -4
  71. data/lib/zen/package/sections/lib/sections/view/admin/section-entries/form.xhtml +0 -4
  72. data/lib/zen/package/sections/lib/sections/view/admin/section-entries/index.xhtml +8 -2
  73. data/lib/zen/package/sections/migrations/1306772479_remove_unique_slug.rb +28 -0
  74. data/lib/zen/package/settings/lib/settings.rb +21 -34
  75. data/lib/zen/package/settings/lib/settings/controller/settings.rb +29 -22
  76. data/lib/zen/package/settings/lib/settings/language/en/settings.yml +7 -5
  77. data/lib/zen/package/settings/lib/settings/language/nl/settings.yml +39 -0
  78. data/lib/zen/package/settings/lib/settings/model/setting.rb +3 -5
  79. data/lib/zen/package/settings/lib/settings/plugin/group_base.rb +3 -4
  80. data/lib/zen/package/settings/lib/settings/plugin/setting_base.rb +3 -5
  81. data/lib/zen/package/settings/lib/settings/plugin/settings.rb +11 -4
  82. data/lib/zen/package/settings/lib/settings/view/admin/settings/index.xhtml +5 -5
  83. data/lib/zen/package/settings/migrations/1299538742_add_language_key.rb +8 -8
  84. data/lib/zen/package/settings/migrations/1303196915_settings_plugin.rb +2 -5
  85. data/lib/zen/package/users/lib/users/controller/access_rules.rb +54 -61
  86. data/lib/zen/package/users/lib/users/controller/user_groups.rb +49 -57
  87. data/lib/zen/package/users/lib/users/controller/users.rb +58 -73
  88. data/lib/zen/package/users/lib/users/language/en/users.yml +6 -0
  89. data/lib/zen/package/users/lib/users/language/nl/access_rules.yml +37 -0
  90. data/lib/zen/package/users/lib/users/language/nl/user_groups.yml +31 -0
  91. data/lib/zen/package/users/lib/users/language/nl/users.yml +56 -0
  92. data/lib/zen/package/users/lib/users/model/user.rb +16 -1
  93. data/lib/zen/package/users/lib/users/view/admin/users/form.xhtml +27 -2
  94. data/lib/zen/package/users/lib/users/view/admin/users/index.xhtml +15 -3
  95. data/lib/zen/package/users/migrations/1304939855_user_settings.rb +15 -0
  96. data/lib/zen/plugin.rb +7 -9
  97. data/lib/zen/public/admin/css/{buttons.css → zen/buttons.css} +11 -7
  98. data/lib/zen/public/admin/css/{datepicker.css → zen/datepicker.css} +0 -0
  99. data/lib/zen/public/admin/css/{editor.css → zen/editor.css} +10 -5
  100. data/lib/zen/public/admin/css/{forms.css → zen/forms.css} +1 -1
  101. data/lib/zen/public/admin/css/{general.css → zen/general.css} +7 -7
  102. data/lib/zen/public/admin/css/{grid.css → zen/grid.css} +0 -0
  103. data/lib/zen/public/admin/css/{layout.css → zen/layout.css} +4 -5
  104. data/lib/zen/public/admin/css/zen/messages.css +61 -0
  105. data/lib/zen/public/admin/css/{notifications.css → zen/notifications.css} +4 -4
  106. data/lib/zen/public/admin/css/{reset.css → zen/reset.css} +0 -0
  107. data/lib/zen/public/admin/css/{tables.css → zen/tables.css} +3 -3
  108. data/lib/zen/public/admin/css/{tabs.css → zen/tabs.css} +5 -5
  109. data/lib/zen/public/admin/css/zen/window.css +79 -0
  110. data/lib/zen/public/admin/images/{icons → zen/icons}/accept.png +0 -0
  111. data/lib/zen/public/admin/images/{icons → zen/icons}/add.png +0 -0
  112. data/lib/zen/public/admin/images/{icons → zen/icons}/back.png +0 -0
  113. data/lib/zen/public/admin/images/{icons → zen/icons}/bold.png +0 -0
  114. data/lib/zen/public/admin/images/zen/icons/close.png +0 -0
  115. data/lib/zen/public/admin/images/{icons → zen/icons}/delete.png +0 -0
  116. data/lib/zen/public/admin/images/{icons → zen/icons}/edit.png +0 -0
  117. data/lib/zen/public/admin/images/{icons → zen/icons}/error.png +0 -0
  118. data/lib/zen/public/admin/images/{icons → zen/icons}/help.png +0 -0
  119. data/lib/zen/public/admin/images/{icons → zen/icons}/info.png +0 -0
  120. data/lib/zen/public/admin/images/{icons → zen/icons}/italic.png +0 -0
  121. data/lib/zen/public/admin/images/{icons → zen/icons}/large/error.png +0 -0
  122. data/lib/zen/public/admin/images/{icons → zen/icons}/large/notice.png +0 -0
  123. data/lib/zen/public/admin/images/{icons → zen/icons}/large/success.png +0 -0
  124. data/lib/zen/public/admin/images/{icons → zen/icons}/link.png +0 -0
  125. data/lib/zen/public/admin/images/{icons → zen/icons}/logout.png +0 -0
  126. data/lib/zen/public/admin/images/{icons → zen/icons}/ol.png +0 -0
  127. data/lib/zen/public/admin/images/{icons → zen/icons}/pdf.png +0 -0
  128. data/lib/zen/public/admin/images/zen/icons/preview.png +0 -0
  129. data/lib/zen/public/admin/images/{icons → zen/icons}/ul.png +0 -0
  130. data/lib/zen/public/admin/images/{icons → zen/icons}/user.png +0 -0
  131. data/lib/zen/public/admin/images/{icons → zen/icons}/view.png +0 -0
  132. data/lib/zen/public/admin/js/zen/core.js +73 -0
  133. data/lib/zen/public/admin/js/zen/editor.js +527 -0
  134. data/lib/zen/public/admin/js/zen/editor/markdown.js +84 -0
  135. data/lib/zen/public/admin/js/zen/editor/textile.js +84 -0
  136. data/lib/zen/public/admin/js/zen/init.js +12 -66
  137. data/lib/zen/public/admin/js/zen/tabs.js +5 -0
  138. data/lib/zen/public/admin/js/zen/window.js +206 -0
  139. data/lib/zen/task/build.rake +23 -6
  140. data/lib/zen/task/clean.rake +6 -7
  141. data/lib/zen/task/db.rake +7 -9
  142. data/lib/zen/task/package.rake +6 -6
  143. data/lib/zen/task/test.rake +6 -0
  144. data/lib/zen/task/theme.rake +3 -3
  145. data/lib/zen/theme.rb +3 -4
  146. data/lib/zen/validation.rb +7 -9
  147. data/lib/zen/version.rb +3 -4
  148. data/lib/zen/view/bottom.xhtml +0 -5
  149. data/lib/zen/view/main.xhtml +2 -0
  150. data/proto/app/app.rb +6 -4
  151. data/proto/app/config/config.rb +1 -7
  152. data/proto/app/config/database.rb +47 -43
  153. data/proto/app/config/middlewares.rb +0 -40
  154. data/proto/app/start.rb +1 -6
  155. data/proto/app/{vendor → theme}/.gitkeep +0 -0
  156. data/proto/migration.rb +3 -3
  157. data/proto/package/lib/package.rb +0 -1
  158. data/proto/package/lib/package/controller/controllers.rb +7 -40
  159. data/proto/package/lib/package/model/model.rb +3 -3
  160. metadata +106 -79
  161. data/CHANGELOG.md +0 -27
  162. data/ROADMAP.md +0 -53
  163. data/lib/zen/database.rb +0 -112
  164. data/lib/zen/logger.rb +0 -56
  165. data/lib/zen/public/admin/css/modals.css +0 -63
  166. data/lib/zen/public/admin/images/icons/close.png +0 -0
  167. data/lib/zen/public/admin/js/vendor/yepnope.js +0 -1
  168. data/lib/zen/public/admin/js/zen/editor/base.js +0 -262
  169. data/lib/zen/public/admin/js/zen/editor/drivers/html.js +0 -89
  170. data/lib/zen/public/admin/js/zen/editor/drivers/markdown.js +0 -87
  171. data/lib/zen/public/admin/js/zen/editor/drivers/textile.js +0 -87
  172. data/lib/zen/public/admin/js/zen/modal.js +0 -146
  173. data/lib/zen/public/admin/js/zen/notification.js +0 -211
  174. data/proto/app/config/requires.rb +0 -10
  175. data/proto/app/vendor/theme/.gitkeep +0 -0
  176. data/proto/package/lib/package/view/admin/package/edit.xhtml +0 -0
  177. data/proto/package/lib/package/view/admin/package/form.xhtml +0 -0
  178. data/proto/package/lib/package/view/admin/package/new.xhtml +0 -0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * This file contains various extensions and core functions that are used by the
3
+ * Javascript API provided by Zen.
4
+ *
5
+ * @author Yorick Peterse
6
+ * @since 0.2.6
7
+ */
8
+ Zen = {};
9
+
10
+ /**
11
+ * Object containing all the assets that were loaded from a class using the Depends
12
+ * mutator.
13
+ *
14
+ * @author Yorick Peterse
15
+ * @since 0.2.6
16
+ */
17
+ Zen.assets = {
18
+ javascript: [],
19
+ stylesheet: []
20
+ }
21
+
22
+ /**
23
+ * Extends the Class class so that dependencies on Javascript and CSS files can be
24
+ * inserted into a class using the assets system that comes with Mootools.
25
+ *
26
+ * Note that you shouldn't specify the file extension, this will be added automatically.
27
+ *
28
+ * @example
29
+ * var my_class = new Class(
30
+ * {
31
+ * Depends:
32
+ * {
33
+ * stylesheet: ['zen/editor']
34
+ * }
35
+ * });
36
+ *
37
+ * @author Yorick Peterse
38
+ * @since 0.2.6
39
+ * @param [Object] deps Object containing the stylesheets and Javascript files required
40
+ * by a class.
41
+ */
42
+ Class.Mutators.Depends = function(deps)
43
+ {
44
+ // Load all Javascript files
45
+ if ( deps.javascript )
46
+ {
47
+ deps.javascript.each(function(file)
48
+ {
49
+ file = '/admin/js/' + file + '.js';
50
+
51
+ if ( !Zen.assets.javascript.contains(file) )
52
+ {
53
+ Asset.javascript(file);
54
+ Zen.assets.javascript.push(file);
55
+ }
56
+ });
57
+ }
58
+
59
+ // Load all stylesheets
60
+ if ( deps.stylesheet )
61
+ {
62
+ deps.stylesheet.each(function(file)
63
+ {
64
+ file = '/admin/css/' + file + '.css';
65
+
66
+ if ( !Zen.assets.stylesheet.contains(file) )
67
+ {
68
+ Asset.css(file);
69
+ Zen.assets.stylesheet.push(file);
70
+ }
71
+ });
72
+ }
73
+ }
@@ -0,0 +1,527 @@
1
+ /**
2
+ * Base class for all drivers that provides several common methods and allows developers
3
+ * to use the same syntax for all editor drivers.
4
+ *
5
+ * ## Usage
6
+ *
7
+ * In order to create a new instance of Zen.Editor your textareas will need an attribute
8
+ * called "data-format". Without this attribute this class will assume you're using HTML
9
+ * as your markup. An example of the most basic textarea looks like the following:
10
+ *
11
+ * <textarea data-format="markdown"></textarea>
12
+ *
13
+ * To make it easier to retrieve an editor instance once it's created you should add an ID
14
+ * to the element. Instances of a textarea with an ID set can be retrieved from
15
+ * Zen.Editor.instances, this doesn't work for classes or other attributes.
16
+ *
17
+ * <textarea data-format="markdown" id="markdown_editor"></textarea>
18
+ *
19
+ * Once you have your element in place you can create a new instance by doing the
20
+ * following:
21
+ *
22
+ * var editor = new Zen.Editor($('markdown_editor'));
23
+ *
24
+ * This will create a new editor instance using HTML as the markup. Because we've set an
25
+ * ID we can retrieve this instance as following:
26
+ *
27
+ * Zen.Editor.instances.markdown_editor
28
+ *
29
+ * This means that it's not required to actually store the instance in a variable unless
30
+ * you're not using an ID.
31
+ *
32
+ * The first parameter of the Zen.Editor class can either be a string or an element. If
33
+ * it's a string it's assumed that it's a valid CSS selector and the first element found
34
+ * will be used. If it's an element it will be used directly without any further
35
+ * processing. A few examples can be seen below.
36
+ *
37
+ * new Zen.Editor('#markdown_editor'); // => markdown_editor will be used
38
+ * new Zen.Editor($$('textarea.some_editor')); // => First item will be used
39
+ *
40
+ * The second parameter is an object with custom options. Currently there are only two
41
+ * options available:
42
+ *
43
+ * * height: sets a fixed height for the textarea.
44
+ * * width: does the same as "height" but for the width.
45
+ *
46
+ * The third (and last) parameter is an array of custom buttons to add to the editor on
47
+ * top of the default buttons. This parameter should be an array of objects where each
48
+ * object has the following three keys:
49
+ *
50
+ * * name: a unique name for the button, also set as the class of the <li> element.
51
+ * * label: a label to display in the button, also used for the value of the title
52
+ * attribute.
53
+ * * onClick: function that's executed whenever the button is clicked. This function can
54
+ * take a single parameter which is set to the instance of the editor to which the button
55
+ * belongs.
56
+ *
57
+ * A full example looks like the following:
58
+ *
59
+ * new Zen.Editor(
60
+ * $('markdown_editor'),
61
+ * {
62
+ * height: 600
63
+ * },
64
+ * [
65
+ * {
66
+ * name: 'example',
67
+ * label: 'example',
68
+ * onClick: function(editor)
69
+ * {
70
+ * console.log(editor.get('value'));
71
+ * }
72
+ * }
73
+ * ]
74
+ * );
75
+ *
76
+ * ## Available Drivers
77
+ *
78
+ * Currently the following drivers are available:
79
+ *
80
+ * * HTML (default)
81
+ * * Markdown
82
+ * * Textile
83
+ *
84
+ * ## Creating Drivers
85
+ *
86
+ * Creating a new driver for your own favorite markup engine (e.g. restructuredText) is
87
+ * pretty simple. Each driver should be declared under the Zen.Editor namespace and should
88
+ * extend the base class, Zen.Editor. The latter makes it possible for the driver to use
89
+ * features of the parent class if it doesn't override or provides them itself.
90
+ *
91
+ * A basic skeleton for a driver looks like the following:
92
+ *
93
+ * Zen.Editor.RestructuredText = new Class(
94
+ * {
95
+ * Extends: Zen.Editor
96
+ * });
97
+ *
98
+ * Usually you don't want to redeclare the initialize() method as it's used to create most
99
+ * of the required data for an editor. Typically you'll only want to override the methods
100
+ * for the default buttons or add your own ones.
101
+ *
102
+ * Once a driver has been written it's class has to be registered, this can be done as
103
+ * following:
104
+ *
105
+ * Zen.Editor.drivers.restructured_text = 'RestructuredText';
106
+ *
107
+ * The key of Zen.Editor.drivers should match the value set in the data-format attribute,
108
+ * it's value should be the name of the driver's class.
109
+ *
110
+ * @author Yorick Peterse
111
+ * @since 0.2.6
112
+ * @implements Options
113
+ * @namespace Zen
114
+ */
115
+ Zen.Editor = new Class(
116
+ {
117
+ Implements: Options,
118
+
119
+ Depends:
120
+ {
121
+ stylesheet: ['zen/editor'],
122
+ javascript: ['zen/editor/markdown', 'zen/editor/textile', 'zen/window']
123
+ },
124
+
125
+ /**
126
+ * Object containing all the default options merged with the custom ones.
127
+ *
128
+ * @author Yorick Peterse
129
+ * @since 0.2.6
130
+ * @var [Object]
131
+ */
132
+ options:
133
+ {
134
+ // The default height in pixels
135
+ height: 400,
136
+
137
+ // The default width in pixels, set it to null to leave it unchanged (default)
138
+ width: null
139
+ },
140
+
141
+ /**
142
+ * Array containing all the buttons to display in the toolbar and their onClick
143
+ * events. Note that if the onClick values are strings the class assumes they're
144
+ * methods available in the current instance.
145
+ *
146
+ * Each callback gets two parameters sent to it: the editor instance and the object of
147
+ * the button that was clicked.
148
+ *
149
+ * @author Yorick Peterse
150
+ * @since 0.2.6
151
+ * @var [Array]
152
+ */
153
+ buttons:
154
+ [
155
+ {name: 'bold' , label: 'Bold' , onClick: 'bold'},
156
+ {name: 'italic' , label: 'Italic' , onClick: 'italic'},
157
+ {name: 'link' , label: 'Link' , onClick: 'link'},
158
+ {name: 'ul' , label: 'Unordered list', onClick: 'ul'},
159
+ {name: 'ol' , label: 'Ordered list' , onClick: 'ol'},
160
+ {name: 'preview', label: 'Preview' , onClick: 'preview'}
161
+ ],
162
+
163
+ /**
164
+ * The DOM element to use for the editor.
165
+ *
166
+ * @author Yorick Peterse
167
+ * @since 0.2.6
168
+ * @var [Element]
169
+ */
170
+ element: null,
171
+
172
+ /**
173
+ * Creates a new instance of the class and saves and validates all the given data.
174
+ *
175
+ * @example
176
+ * var editor = new Zen.Editor($('editor'), {markup: 'markdown'});
177
+ *
178
+ * @author Yorick Peterse
179
+ * @since 0.2.6
180
+ * @param [Object|String] element Either a DOM element or a CSS selector. If a
181
+ * selector is specified only the first element will be used.
182
+ * @param [Object] options Object containing a custom set of options that will be
183
+ * merged with this.options.
184
+ * @param [Array] buttons An array with a custom set of buttons to add on top of the
185
+ * default ones.
186
+ */
187
+ initialize: function(element, options, buttons)
188
+ {
189
+ // Merge the options
190
+ this.setOptions(options);
191
+
192
+ // The element variable is always required
193
+ if ( typeOf(element) === 'undefined' )
194
+ {
195
+ throw new SyntaxError("You need to specify an element for the editor.");
196
+ }
197
+
198
+ this.element = Zen.Editor.getElement(element);
199
+
200
+ // Create the HTML for the editor
201
+ var toolbar = new Element('div', {'class': 'editor_toolbar'});
202
+ var container = new Element('div', {'class': 'editor_container'});
203
+ var ul = new Element('ul');
204
+ var current_class = this;
205
+
206
+ // Push the custom buttons
207
+ if ( typeof buttons !== 'undefined' && buttons.length > 0 )
208
+ {
209
+ this.buttons.combine(buttons);
210
+ }
211
+
212
+ // Create the HTML for all the buttons
213
+ this.buttons.each(function(button)
214
+ {
215
+ var li = new Element(
216
+ 'li',
217
+ {
218
+ 'class': button.name,
219
+ html: button.label,
220
+ title: button.label
221
+ }
222
+ );
223
+
224
+ // Add the onClick event, when clicked the current editor's instance is passed
225
+ // to the event allowing developers to work with it's content.
226
+ li.addEvent('click', function()
227
+ {
228
+ var current_editor = this.getParent('.editor_container')
229
+ .getElement('textarea');
230
+
231
+ if ( typeOf(button.onClick) === 'string' )
232
+ {
233
+ current_class[button.onClick](current_editor, this);
234
+ }
235
+ else
236
+ {
237
+ button.onClick(current_editor, this);
238
+ }
239
+ });
240
+
241
+ li.inject(ul);
242
+ });
243
+
244
+ // Inject the HTML into the DOM
245
+ ul.inject(toolbar);
246
+ toolbar.inject(container);
247
+ container.inject(this.element, 'before');
248
+
249
+ // Set the options
250
+ ['height', 'width'].each(function(attr)
251
+ {
252
+ if ( current_class.options[attr] !== null )
253
+ {
254
+ element.setStyle(attr, current_class.options[attr]);
255
+ }
256
+ });
257
+
258
+ // Inject the textarea back into the container
259
+ element.inject(container);
260
+ element.set('data-state', 'initialized');
261
+ },
262
+
263
+ /**
264
+ * Destroys the editor instance. This will remove all HTML and removes the textarea
265
+ * from Zen.Editor.instances if it has an ID.
266
+ *
267
+ * @author Yorick Peterse
268
+ * @since 0.2.6
269
+ */
270
+ destroy: function()
271
+ {
272
+ // First we'll have to remove all HTML
273
+ var parent_container = this.element.getParent('.editor_container');
274
+ var id = this.element.id;
275
+
276
+ this.element.inject(parent_container, 'before');
277
+ this.element.removeAttribute('data-state');
278
+
279
+ parent_container.destroy();
280
+
281
+ if ( typeOf(id) !== 'undefined' )
282
+ {
283
+ Zen.Editor.instances[id] = null;
284
+ }
285
+
286
+ // Reset the dimensions
287
+ this.element.setStyle('height', null);
288
+ this.element.setStyle('width' , null);
289
+ },
290
+
291
+ /**
292
+ * Inserts a set of <strong> tags around the cursor.
293
+ *
294
+ * @author Yorick Peterse
295
+ * @since 0.2.6
296
+ * @param [Element] editor The editor to insert the tags into.
297
+ */
298
+ bold: function(editor)
299
+ {
300
+ editor.insertAroundCursor({before: '<strong>', after: '</strong>'});
301
+ },
302
+
303
+ /**
304
+ * Inserts a set of <em> tags around the cursor.
305
+ *
306
+ * @author Yorick Peterse
307
+ * @since 0.2.6
308
+ * @param [Element] editor The editor to insert the tags into.
309
+ */
310
+ italic: function(editor)
311
+ {
312
+ editor.insertAroundCursor({before: '<em>', after: '</em>'});
313
+ },
314
+
315
+ /**
316
+ * Asks for a URL and inserts it into the textarea using an <a> tag.
317
+ *
318
+ * @author Yorick Peterse
319
+ * @since 0.2.6
320
+ * @param [Element] editor The editor to insert the tags into.
321
+ */
322
+ link: function(editor)
323
+ {
324
+ var link = prompt('URL', 'http://');
325
+
326
+ editor.insertAroundCursor(
327
+ {
328
+ before: '<a href="' + link + '">',
329
+ after: '</a>'
330
+ });
331
+ },
332
+
333
+ /**
334
+ * Inserts a set of <ul> and <li> tags around the cursor.
335
+ *
336
+ * @author Yorick Peterse
337
+ * @since 0.2.6
338
+ * @param [Element] editor The editor to insert the tags into.
339
+ */
340
+ ul: function(editor)
341
+ {
342
+ editor.insertAroundCursor(
343
+ {
344
+ before: "\n<ul>\n <li>",
345
+ after: "</li>\n</ul>\n"
346
+ });
347
+ },
348
+
349
+ /**
350
+ * Inserts a set of <ol> and <li> tags around the cursor.
351
+ *
352
+ * @author Yorick Peterse
353
+ * @since 0.2.6
354
+ * @param [Element] editor The editor to insert the tags into.
355
+ */
356
+ ol: function(editor)
357
+ {
358
+ editor.insertAroundCursor(
359
+ {
360
+ before: "\n<ol>\n <li>",
361
+ after: "</li>\n</ol>\n"
362
+ });
363
+ },
364
+
365
+ /**
366
+ * Shows a preview of the content entered in the text area.
367
+ *
368
+ * @author Yorick Peterse
369
+ * @since 0.2.6
370
+ * @param [Element] editor The editor to render the preview for.
371
+ */
372
+ preview: function(editor)
373
+ {
374
+ var markup = editor.get('value');
375
+ var engine = editor.get('data-format');
376
+
377
+ new Request(
378
+ {
379
+ method: 'POST',
380
+ url: '/admin/preview',
381
+ data: {engine: engine, markup: markup},
382
+ onSuccess: function(response)
383
+ {
384
+ new Zen.Window(
385
+ response,
386
+ {
387
+ title: 'Preview',
388
+ width: 600,
389
+ move: true,
390
+ buttons:
391
+ [
392
+ {
393
+ name: 'close',
394
+ label: 'Close',
395
+ onClick: function(instance)
396
+ {
397
+ instance.destroy();
398
+ }
399
+ }
400
+ ]
401
+ }
402
+ );
403
+ }
404
+ }).send();
405
+ }
406
+ });
407
+
408
+ /**
409
+ * Object containing the names of all available drivers and their classes.
410
+ * Note that these drivers should be declared under the Zen.Editor namespace.
411
+ *
412
+ * @author Yorick Peterse
413
+ * @since 0.2.6
414
+ * @var [Object]
415
+ */
416
+ Zen.Editor.drivers = {
417
+ markdown: 'Markdown',
418
+ textile: 'Textile'
419
+ };
420
+
421
+ /**
422
+ * Object that will contain a list of all instances of the Zen.Editor class. Note that the
423
+ * textareas will need an ID in order for them to be added to this list.
424
+ *
425
+ * @author Yorick Peterse
426
+ * @since 0.2.6
427
+ * @var [Object]
428
+ */
429
+ Zen.Editor.instances = {};
430
+
431
+ /**
432
+ * Class method that can be used to create editor instances using different drivers while
433
+ * still using the same syntax.
434
+ *
435
+ * @example
436
+ * var editor = Zen.Editor.init('markdown', $('editor'), {height: 200});
437
+ *
438
+ * @author Yorick Peterse
439
+ * @since 0.2.6
440
+ * @param [String] driver The name of the driver to use.
441
+ * @param [Object|String] A DOM element or a CSS selector.
442
+ * @param [Object] options An object containing custom options to use.
443
+ * @param [Object[ buttons An array of buttons to add to the editor.
444
+ * @see Zen.Editor.initialize
445
+ * @return [Object] An instance of the correct driver or an error class in case something
446
+ * went wrong.
447
+ */
448
+ Zen.Editor.init = function(driver, element, options, buttons)
449
+ {
450
+ if ( !driver )
451
+ {
452
+ throw new SyntaxError("You need to specify a driver.");
453
+ }
454
+
455
+ if ( !element )
456
+ {
457
+ throw new SyntaxError("You need to specify a DOM element or a CSS selector.");
458
+ }
459
+
460
+ // Get the element so we can determine if the textarea has already been processed
461
+ element = Zen.Editor.getElement(element);
462
+
463
+ if ( element.get('data-state') === 'initialized' )
464
+ {
465
+ return;
466
+ }
467
+
468
+ var driver_class = Zen.Editor.drivers[driver];
469
+ var instance = null;
470
+
471
+ // Try to see if a driver exists for the given name. If there isn't we'll use the
472
+ // HTML driver as a fallback.
473
+ if ( typeOf(driver_class) === 'undefined' || !Zen.Editor[driver_class] )
474
+ {
475
+ instance = new Zen.Editor(element, options, buttons);
476
+ }
477
+ else
478
+ {
479
+ instance = new Zen.Editor[driver_class](element, options, buttons);
480
+ }
481
+
482
+ // Store the instance if it has an ID
483
+ if ( typeOf(instance.element.id) !== 'undefined' )
484
+ {
485
+ Zen.Editor.instances[instance.element.id] = instance;
486
+ }
487
+
488
+ return instance;
489
+ };
490
+
491
+ /**
492
+ * Retrieves the correct element for the given CSS selector or element(s). If the
493
+ * parameter is a single DOM element it will be returned immediately, if it's an array of
494
+ * objects only the first one will be returned. If the parameter is a string this method
495
+ * will return the first element for the given selector.
496
+ *
497
+ * @example
498
+ * Zen.Editor.getElement($$('.some_class')); # => Element
499
+ *
500
+ * @author Yorick Peterse
501
+ * @since 0.2.6
502
+ * @param [String|Array|Element] The source data from which to extract the (first)
503
+ * element.
504
+ * @return [Element]
505
+ */
506
+ Zen.Editor.getElement = function(element)
507
+ {
508
+ if ( typeOf(element) === 'element' )
509
+ {
510
+ return element;
511
+ }
512
+
513
+ if ( typeOf(element) === 'string' )
514
+ {
515
+ element = $$(element);
516
+
517
+ if ( element.length === 0 )
518
+ {
519
+ throw new Error("The CSS selector did not result in any elements.");
520
+ }
521
+ }
522
+
523
+ if ( element.length > 0 )
524
+ {
525
+ return element[0];
526
+ }
527
+ };