zen 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
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
+ };