read-only-gollum 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. data/Gemfile +4 -0
  2. data/HISTORY.md +102 -0
  3. data/Home.md +3 -0
  4. data/LICENSE +21 -0
  5. data/README.md +477 -0
  6. data/Rakefile +142 -0
  7. data/bin/read-only-gollum +126 -0
  8. data/docs/sanitization.md +32 -0
  9. data/lib/gollum.rb +41 -0
  10. data/lib/gollum/blob_entry.rb +78 -0
  11. data/lib/gollum/committer.rb +218 -0
  12. data/lib/gollum/file.rb +64 -0
  13. data/lib/gollum/frontend/app.rb +225 -0
  14. data/lib/gollum/frontend/public/css/dialog.css +141 -0
  15. data/lib/gollum/frontend/public/css/editor.css +537 -0
  16. data/lib/gollum/frontend/public/css/gollum.css +660 -0
  17. data/lib/gollum/frontend/public/css/ie7.css +69 -0
  18. data/lib/gollum/frontend/public/css/template.css +381 -0
  19. data/lib/gollum/frontend/public/images/icon-sprite.png +0 -0
  20. data/lib/gollum/frontend/public/javascript/editor/gollum.editor.js +1096 -0
  21. data/lib/gollum/frontend/public/javascript/editor/langs/asciidoc.js +167 -0
  22. data/lib/gollum/frontend/public/javascript/editor/langs/creole.js +104 -0
  23. data/lib/gollum/frontend/public/javascript/editor/langs/markdown.js +211 -0
  24. data/lib/gollum/frontend/public/javascript/editor/langs/org.js +173 -0
  25. data/lib/gollum/frontend/public/javascript/editor/langs/pod.js +111 -0
  26. data/lib/gollum/frontend/public/javascript/editor/langs/rdoc.js +74 -0
  27. data/lib/gollum/frontend/public/javascript/editor/langs/textile.js +175 -0
  28. data/lib/gollum/frontend/public/javascript/gollum.dialog.js +263 -0
  29. data/lib/gollum/frontend/public/javascript/gollum.js +161 -0
  30. data/lib/gollum/frontend/public/javascript/gollum.placeholder.js +54 -0
  31. data/lib/gollum/frontend/public/javascript/jquery.color.js +123 -0
  32. data/lib/gollum/frontend/public/javascript/jquery.js +7179 -0
  33. data/lib/gollum/frontend/templates/compare.mustache +38 -0
  34. data/lib/gollum/frontend/templates/create.mustache +17 -0
  35. data/lib/gollum/frontend/templates/edit.mustache +17 -0
  36. data/lib/gollum/frontend/templates/editor.mustache +116 -0
  37. data/lib/gollum/frontend/templates/error.mustache +8 -0
  38. data/lib/gollum/frontend/templates/history.mustache +58 -0
  39. data/lib/gollum/frontend/templates/layout.mustache +28 -0
  40. data/lib/gollum/frontend/templates/page.mustache +37 -0
  41. data/lib/gollum/frontend/templates/pages.mustache +35 -0
  42. data/lib/gollum/frontend/templates/search.mustache +36 -0
  43. data/lib/gollum/frontend/templates/searchbar.mustache +10 -0
  44. data/lib/gollum/frontend/views/compare.rb +94 -0
  45. data/lib/gollum/frontend/views/create.rb +48 -0
  46. data/lib/gollum/frontend/views/edit.rb +52 -0
  47. data/lib/gollum/frontend/views/editable.rb +13 -0
  48. data/lib/gollum/frontend/views/error.rb +7 -0
  49. data/lib/gollum/frontend/views/history.rb +44 -0
  50. data/lib/gollum/frontend/views/layout.rb +20 -0
  51. data/lib/gollum/frontend/views/page.rb +57 -0
  52. data/lib/gollum/frontend/views/pages.rb +19 -0
  53. data/lib/gollum/frontend/views/search.rb +20 -0
  54. data/lib/gollum/git_access.rb +248 -0
  55. data/lib/gollum/markup.rb +489 -0
  56. data/lib/gollum/page.rb +430 -0
  57. data/lib/gollum/pagination.rb +61 -0
  58. data/lib/gollum/sanitization.rb +174 -0
  59. data/lib/gollum/tex.rb +89 -0
  60. data/lib/gollum/web_sequence_diagram.rb +43 -0
  61. data/lib/gollum/wiki.rb +636 -0
  62. data/read-only-gollum.gemspec +224 -0
  63. data/templates/formatting.html +92 -0
  64. data/test/examples/empty.git/HEAD +1 -0
  65. data/test/examples/empty.git/config +5 -0
  66. data/test/examples/empty.git/description +1 -0
  67. data/test/examples/empty.git/hooks/applypatch-msg.sample +15 -0
  68. data/test/examples/empty.git/hooks/commit-msg.sample +24 -0
  69. data/test/examples/empty.git/hooks/post-commit.sample +8 -0
  70. data/test/examples/empty.git/hooks/post-receive.sample +15 -0
  71. data/test/examples/empty.git/hooks/post-update.sample +8 -0
  72. data/test/examples/empty.git/hooks/pre-applypatch.sample +14 -0
  73. data/test/examples/empty.git/hooks/pre-commit.sample +46 -0
  74. data/test/examples/empty.git/hooks/pre-rebase.sample +169 -0
  75. data/test/examples/empty.git/hooks/prepare-commit-msg.sample +36 -0
  76. data/test/examples/empty.git/hooks/update.sample +128 -0
  77. data/test/examples/empty.git/info/exclude +6 -0
  78. data/test/examples/empty.git/objects/info/.gitkeep +0 -0
  79. data/test/examples/empty.git/objects/pack/.gitkeep +0 -0
  80. data/test/examples/empty.git/refs/heads/.gitkeep +0 -0
  81. data/test/examples/lotr.git/COMMIT_EDITMSG +1 -0
  82. data/test/examples/lotr.git/HEAD +1 -0
  83. data/test/examples/lotr.git/ORIG_HEAD +1 -0
  84. data/test/examples/lotr.git/config +12 -0
  85. data/test/examples/lotr.git/description +1 -0
  86. data/test/examples/lotr.git/index +0 -0
  87. data/test/examples/lotr.git/info/exclude +6 -0
  88. data/test/examples/lotr.git/logs/HEAD +3 -0
  89. data/test/examples/lotr.git/logs/refs/heads/master +3 -0
  90. data/test/examples/lotr.git/objects/06/131480411710c92a82fe2d1e76932c70feb2e5 +0 -0
  91. data/test/examples/lotr.git/objects/0a/de1e2916346d4c1f2fb63b863fd3c16808fe44 +0 -0
  92. data/test/examples/lotr.git/objects/0e/d8cbe0a25235bd867e65193c7d837c66b328ef +3 -0
  93. data/test/examples/lotr.git/objects/12/629d666c5e3178f82f533f543d61b53dc78c0b +0 -0
  94. data/test/examples/lotr.git/objects/1d/b89ebba7e2c14d93b94ff98cfa3708a4f0d4e3 +2 -0
  95. data/test/examples/lotr.git/objects/24/49c2681badfd3c189e8ed658dacffe8ba48fe5 +0 -0
  96. data/test/examples/lotr.git/objects/25/4bdc1ba27d8b8a794538a8522d9a2b56ec2dd9 +0 -0
  97. data/test/examples/lotr.git/objects/2c/b9156ad383914561a8502fc70f5a1d887e48ad +4 -0
  98. data/test/examples/lotr.git/objects/5d/cac289a8603188d2c5caf481dcba2985126aaa +0 -0
  99. data/test/examples/lotr.git/objects/60/f12f4254f58801b9ee7db7bca5fa8aeefaa56b +0 -0
  100. data/test/examples/lotr.git/objects/71/4323c104239440a5c66ab12a67ed07a83c404f +0 -0
  101. data/test/examples/lotr.git/objects/84/0ec5b1ba1320e8ec443f28f99566f615d5af10 +0 -0
  102. data/test/examples/lotr.git/objects/93/6b83ee0dd8837adb82511e40d5e4ebe59bb675 +0 -0
  103. data/test/examples/lotr.git/objects/94/523d7ae48aeba575099dd12926420d8fd0425d +2 -0
  104. data/test/examples/lotr.git/objects/96/97dc65e095658bbd1b8e8678e08881e86d32f1 +0 -0
  105. data/test/examples/lotr.git/objects/a3/1ca2a7c352c92531a8b99815d15843b259e814 +0 -0
  106. data/test/examples/lotr.git/objects/a6/59b3763b822dd97544621fd0beef162ea37b14 +4 -0
  107. data/test/examples/lotr.git/objects/a8/ad3c09dd842a3517085bfadd37718856dee813 +0 -0
  108. data/test/examples/lotr.git/objects/aa/b61fe89d56f8614c0a8151da34f939dcedfa68 +0 -0
  109. data/test/examples/lotr.git/objects/bc/4b5fc0ce2c2ba3acef6647e4f67256ee45ab60 +0 -0
  110. data/test/examples/lotr.git/objects/c3/b43e9f08966b088e7a0192e436b7a884542e05 +0 -0
  111. data/test/examples/lotr.git/objects/dc/596d6b2dd89ab05c66f4abd7d5eb706bc17f19 +0 -0
  112. data/test/examples/lotr.git/objects/ec/da3205bee14520aab5a7bb307392064b938e83 +0 -0
  113. data/test/examples/lotr.git/objects/f4/84ebb1f40f8eb20d1bcd8d1d71934d2b8ae961 +0 -0
  114. data/test/examples/lotr.git/objects/fa/e7ef5344202bba4129abdc13060d9297d99465 +3 -0
  115. data/test/examples/lotr.git/objects/info/packs +2 -0
  116. data/test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.idx +0 -0
  117. data/test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.pack +0 -0
  118. data/test/examples/lotr.git/packed-refs +2 -0
  119. data/test/examples/lotr.git/refs/heads/master +1 -0
  120. data/test/examples/lotr.git/refs/remotes/origin/HEAD +1 -0
  121. data/test/examples/page_file_dir.git/COMMIT_EDITMSG +1 -0
  122. data/test/examples/page_file_dir.git/HEAD +1 -0
  123. data/test/examples/page_file_dir.git/config +6 -0
  124. data/test/examples/page_file_dir.git/description +1 -0
  125. data/test/examples/page_file_dir.git/index +0 -0
  126. data/test/examples/page_file_dir.git/info/exclude +6 -0
  127. data/test/examples/page_file_dir.git/logs/HEAD +1 -0
  128. data/test/examples/page_file_dir.git/logs/refs/heads/master +1 -0
  129. data/test/examples/page_file_dir.git/objects/0c/7d27db1f575263efdcab3dc650f4502a2dbcbf +0 -0
  130. data/test/examples/page_file_dir.git/objects/22/b404803c966dd92865614d86ff22ca12e50c1e +0 -0
  131. data/test/examples/page_file_dir.git/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 +0 -0
  132. data/test/examples/page_file_dir.git/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6 +0 -0
  133. data/test/examples/page_file_dir.git/objects/5b/43e14e0a15fb6f08feab1773d1c0991e9f71e2 +0 -0
  134. data/test/examples/page_file_dir.git/refs/heads/master +1 -0
  135. data/test/examples/revert.git/COMMIT_EDITMSG +1 -0
  136. data/test/examples/revert.git/HEAD +1 -0
  137. data/test/examples/revert.git/config +12 -0
  138. data/test/examples/revert.git/description +1 -0
  139. data/test/examples/revert.git/index +0 -0
  140. data/test/examples/revert.git/info/exclude +6 -0
  141. data/test/examples/revert.git/logs/HEAD +2 -0
  142. data/test/examples/revert.git/logs/refs/heads/master +2 -0
  143. data/test/examples/revert.git/objects/20/2ced67cea93c7b6bd2928aa1daef8d1d55a20d +0 -0
  144. data/test/examples/revert.git/objects/41/76394bfa11222363c66ce7e84b5f154095b6d9 +0 -0
  145. data/test/examples/revert.git/objects/6a/69f92020f5df77af6e8813ff1232493383b708 +0 -0
  146. data/test/examples/revert.git/objects/b4/785957bc986dc39c629de9fac9df46972c00fc +0 -0
  147. data/test/examples/revert.git/objects/f4/03b791119f8232b7cb0ba455c624ac6435f433 +0 -0
  148. data/test/examples/revert.git/objects/info/packs +2 -0
  149. data/test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.idx +0 -0
  150. data/test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.pack +0 -0
  151. data/test/examples/revert.git/packed-refs +2 -0
  152. data/test/examples/revert.git/refs/heads/master +1 -0
  153. data/test/examples/revert.git/refs/remotes/origin/HEAD +1 -0
  154. data/test/examples/yubiwa.git/HEAD +1 -0
  155. data/test/examples/yubiwa.git/config +5 -0
  156. data/test/examples/yubiwa.git/description +1 -0
  157. data/test/examples/yubiwa.git/info/exclude +6 -0
  158. data/test/examples/yubiwa.git/objects/10/fa2ddc4e3b4009d8a453aace10bd6148c1ad00 +0 -0
  159. data/test/examples/yubiwa.git/objects/52/4b82874327ea7cbf730389964ba7cb3de966de +0 -0
  160. data/test/examples/yubiwa.git/objects/58/3fc201cb457fb3f1480f3e1e5999b119633835 +0 -0
  161. data/test/examples/yubiwa.git/objects/87/bc1dd46ab3d3874d4e898d45dd512cc20a7cc8 +1 -0
  162. data/test/examples/yubiwa.git/objects/89/64ed1b4e21aa90e831763bbce9034bfda81b70 +0 -0
  163. data/test/examples/yubiwa.git/objects/9f/f6dd0660da5fba2d3374adb2b84fa653bb538b +0 -0
  164. data/test/examples/yubiwa.git/objects/ac/e97abf2b177815a1972d7db22f229f58c83309 +0 -0
  165. data/test/examples/yubiwa.git/objects/b1/f443863a4816628807fbf86141ebef055dda34 +0 -0
  166. data/test/examples/yubiwa.git/refs/heads/master +1 -0
  167. data/test/helper.rb +66 -0
  168. data/test/test_app.rb +169 -0
  169. data/test/test_committer.rb +64 -0
  170. data/test/test_file.rb +27 -0
  171. data/test/test_git_access.rb +52 -0
  172. data/test/test_markup.rb +628 -0
  173. data/test/test_page.rb +166 -0
  174. data/test/test_page_revert.rb +45 -0
  175. data/test/test_wiki.rb +462 -0
  176. metadata +470 -0
@@ -0,0 +1,1096 @@
1
+ /**
2
+ * gollum.editor.js
3
+ * A jQuery plugin that creates the Gollum Editor.
4
+ *
5
+ * Usage:
6
+ * $.GollumEditor(); on DOM ready.
7
+ */
8
+ (function($) {
9
+
10
+ // Editor options
11
+ var DefaultOptions = {
12
+ MarkupType: 'markdown',
13
+ EditorMode: 'code',
14
+ NewFile: false,
15
+ HasFunctionBar: true,
16
+ Debug: false,
17
+ NoDefinitionsFor: []
18
+ };
19
+ var ActiveOptions = {};
20
+
21
+ /**
22
+ * $.GollumEditor
23
+ *
24
+ * You don't need to do anything. Just run this on DOM ready.
25
+ */
26
+ $.GollumEditor = function( IncomingOptions ) {
27
+
28
+ ActiveOptions = $.extend( DefaultOptions, IncomingOptions );
29
+
30
+ debug('GollumEditor loading');
31
+
32
+ if ( EditorHas.baseEditorMarkup() ) {
33
+
34
+ if ( EditorHas.titleDisplayed() ) {
35
+ $('#gollum-editor-title-field').addClass('active');
36
+ }
37
+
38
+ if ( EditorHas.editSummaryMarkup() ) {
39
+ $.GollumEditor.Placeholder.add($('#gollum-editor-edit-summary input'));
40
+ $('#gollum-editor form[name="gollum-editor"]').submit(function( e ) {
41
+ e.preventDefault();
42
+ $.GollumEditor.Placeholder.clearAll();
43
+ debug('submitting');
44
+ $(this).unbind('submit');
45
+ $(this).submit();
46
+ });
47
+ }
48
+
49
+ if ( EditorHas.collapsibleInputs() ) {
50
+ $('#gollum-editor .collapsed a.button, ' +
51
+ '#gollum-editor .expanded a.button').click(function( e ) {
52
+ e.preventDefault();
53
+ $(this).parent().toggleClass('expanded');
54
+ $(this).parent().toggleClass('collapsed');
55
+ });
56
+ }
57
+
58
+ if ( EditorHas.previewButton() ) {
59
+ var formAction =
60
+ $('#gollum-editor #gollum-editor-preview').click(function() {
61
+ // make a dummy form, submit to new target window
62
+ // get form fields
63
+ var oldAction = $('#gollum-editor form').attr('action');
64
+ var $form = $($('#gollum-editor form').get(0));
65
+ $form.attr('action', this.href || '/preview');
66
+ $form.attr('target', '_blank');
67
+ $form.submit();
68
+
69
+
70
+ $form.attr('action', oldAction);
71
+ $form.removeAttr('target');
72
+ return false;
73
+ });
74
+ }
75
+
76
+ // Initialize the function bar by loading proper definitions
77
+ if ( EditorHas.functionBar() ) {
78
+
79
+ var htmlSetMarkupLang =
80
+ $('#gollum-editor-body').attr('data-markup-lang');
81
+
82
+ if ( htmlSetMarkupLang ) {
83
+ ActiveOptions.MarkupType = htmlSetMarkupLang;
84
+ }
85
+
86
+ // load language definition
87
+ LanguageDefinition.setActiveLanguage( ActiveOptions.MarkupType );
88
+ if ( EditorHas.formatSelector() ) {
89
+ FormatSelector.init(
90
+ $('#gollum-editor-format-selector select') );
91
+ }
92
+
93
+ if ( EditorHas.help() ) {
94
+ $('#gollum-editor-help').hide();
95
+ $('#gollum-editor-help').removeClass('jaws');
96
+ }
97
+
98
+ }
99
+ // EditorHas.functionBar
100
+ }
101
+ // EditorHas.baseEditorMarkup
102
+ };
103
+
104
+
105
+
106
+ /**
107
+ * $.GollumEditor.defineLanguage
108
+ * Defines a set of language actions that Gollum can use.
109
+ * Used by the definitions in langs/ to register language definitions.
110
+ */
111
+ $.GollumEditor.defineLanguage = function( language_name, languageObject ) {
112
+ if ( typeof languageObject == 'object' ) {
113
+ LanguageDefinition.define( language_name, languageObject );
114
+ } else {
115
+ debug('GollumEditor.defineLanguage: definition for ' + language_name +
116
+ ' is not an object');
117
+ }
118
+ };
119
+
120
+
121
+ /**
122
+ * debug
123
+ * Prints debug information to console.log if debug output is enabled.
124
+ *
125
+ * @param mixed Whatever you want to dump to console.log
126
+ * @return void
127
+ */
128
+ var debug = function(m) {
129
+ if ( ActiveOptions.Debug &&
130
+ typeof console != 'undefined' ) {
131
+ console.log( m );
132
+ }
133
+ };
134
+
135
+
136
+
137
+ /**
138
+ * LanguageDefinition
139
+ * Language definition file handler
140
+ * Loads language definition files as necessary.
141
+ */
142
+ var LanguageDefinition = {
143
+
144
+ _ACTIVE_LANG: '',
145
+ _LOADED_LANGS: [],
146
+ _LANG: {},
147
+
148
+ /**
149
+ * Defines a language
150
+ *
151
+ * @param name string The name of the language
152
+ * @param name object The definition object
153
+ */
154
+ define: function( name, definitionObject ) {
155
+ LanguageDefinition._ACTIVE_LANG = name;
156
+ LanguageDefinition._LOADED_LANGS.push( name );
157
+ if ( typeof $.GollumEditor.WikiLanguage == 'object' ) {
158
+ var definition = {};
159
+ $.extend(definition, $.GollumEditor.WikiLanguage, definitionObject);
160
+ LanguageDefinition._LANG[name] = definition;
161
+ } else {
162
+ LanguageDefinition._LANG[name] = definitionObject;
163
+ }
164
+ },
165
+
166
+ getActiveLanguage: function() {
167
+ return LanguageDefinition._ACTIVE_LANG;
168
+ },
169
+
170
+ setActiveLanguage: function( name ) {
171
+ if(LanguageDefinition.getHookFunctionFor("deactivate")) {
172
+ LanguageDefinition.getHookFunctionFor("deactivate")();
173
+ }
174
+ if ( !LanguageDefinition.isLoadedFor(name) ) {
175
+ LanguageDefinition._ACTIVE_LANG = null;
176
+ LanguageDefinition.loadFor( name, function(x, t) {
177
+ if ( t != 'success' ) {
178
+ debug('Failed to load language definition for ' + name);
179
+ // well, fake it and turn everything off for this one
180
+ LanguageDefinition.define( name, {} );
181
+ }
182
+
183
+ // update features that rely on the language definition
184
+ if ( EditorHas.functionBar() ) {
185
+ FunctionBar.refresh();
186
+ }
187
+
188
+ if ( LanguageDefinition.isValid() && EditorHas.formatSelector() ) {
189
+ FormatSelector.updateSelected();
190
+ }
191
+
192
+ if(LanguageDefinition.getHookFunctionFor("activate")) {
193
+ LanguageDefinition.getHookFunctionFor("activate")();
194
+ }
195
+ } );
196
+ } else {
197
+ LanguageDefinition._ACTIVE_LANG = name;
198
+ FunctionBar.refresh();
199
+
200
+ if(LanguageDefinition.getHookFunctionFor("activate")) {
201
+ LanguageDefinition.getHookFunctionFor("activate")();
202
+ }
203
+ }
204
+ },
205
+
206
+ getHookFunctionFor: function(attr, specified_lang) {
207
+ if ( !specified_lang ) {
208
+ specified_lang = LanguageDefinition._ACTIVE_LANG;
209
+ }
210
+
211
+ if ( LanguageDefinition.isLoadedFor(specified_lang) &&
212
+ LanguageDefinition._LANG[specified_lang][attr] &&
213
+ typeof LanguageDefinition._LANG[specified_lang][attr] == 'function' ) {
214
+ return LanguageDefinition._LANG[specified_lang][attr];
215
+ }
216
+
217
+ return null;
218
+ },
219
+
220
+ /**
221
+ * gets a definition object for a specified attribute
222
+ *
223
+ * @param string attr The specified attribute.
224
+ * @param string specified_lang The language to pull a definition for.
225
+ * @return object if exists, null otherwise
226
+ */
227
+ getDefinitionFor: function( attr, specified_lang ) {
228
+ if ( !specified_lang ) {
229
+ specified_lang = LanguageDefinition._ACTIVE_LANG;
230
+ }
231
+
232
+ if ( LanguageDefinition.isLoadedFor(specified_lang) &&
233
+ LanguageDefinition._LANG[specified_lang][attr] &&
234
+ typeof LanguageDefinition._LANG[specified_lang][attr] == 'object' ) {
235
+ return LanguageDefinition._LANG[specified_lang][attr];
236
+ }
237
+
238
+ return null;
239
+ },
240
+
241
+
242
+ /**
243
+ * loadFor
244
+ * Asynchronously loads a definition file for the current markup.
245
+ * Definition files are necessary to use the code editor.
246
+ *
247
+ * @param string markup_name The markup name you want to load
248
+ * @return void
249
+ */
250
+ loadFor: function( markup_name, on_complete ) {
251
+ // Keep us from hitting 404s on our site, check the definition blacklist
252
+ if ( ActiveOptions.NoDefinitionsFor.length ) {
253
+ for ( var i=0; i < ActiveOptions.NoDefinitionsFor.length; i++ ) {
254
+ if ( markup_name == ActiveOptions.NoDefinitionsFor[i] ) {
255
+ // we don't have this. get out.
256
+ if ( typeof on_complete == 'function' ) {
257
+ on_complete( null, 'error' );
258
+ return;
259
+ }
260
+ }
261
+ }
262
+ }
263
+
264
+ // attempt to load the definition for this language
265
+ var script_uri = '/javascript/editor/langs/' + markup_name + '.js';
266
+ $.ajax({
267
+ url: script_uri,
268
+ dataType: 'script',
269
+ complete: function( xhr, textStatus ) {
270
+ if ( typeof on_complete == 'function' ) {
271
+ on_complete( xhr, textStatus );
272
+ }
273
+ }
274
+ });
275
+ },
276
+
277
+
278
+ /**
279
+ * isLoadedFor
280
+ * Checks to see if a definition file has been loaded for the
281
+ * specified markup language.
282
+ *
283
+ * @param string markup_name The name of the markup.
284
+ * @return boolean
285
+ */
286
+ isLoadedFor: function( markup_name ) {
287
+ if ( LanguageDefinition._LOADED_LANGS.length === 0 ) {
288
+ return false;
289
+ }
290
+
291
+ for ( var i=0; i < LanguageDefinition._LOADED_LANGS.length; i++ ) {
292
+ if ( LanguageDefinition._LOADED_LANGS[i] == markup_name ) {
293
+ return true;
294
+ }
295
+ }
296
+ return false;
297
+ },
298
+
299
+ isValid: function() {
300
+ return ( LanguageDefinition._ACTIVE_LANG &&
301
+ typeof LanguageDefinition._LANG[LanguageDefinition._ACTIVE_LANG] ==
302
+ 'object' );
303
+ }
304
+
305
+ };
306
+
307
+
308
+ /**
309
+ * EditorHas
310
+ * Various conditionals to check what features of the Gollum Editor are
311
+ * active/operational.
312
+ */
313
+ var EditorHas = {
314
+
315
+
316
+ /**
317
+ * EditorHas.baseEditorMarkup
318
+ * True if the basic editor form is in place.
319
+ *
320
+ * @return boolean
321
+ */
322
+ baseEditorMarkup: function() {
323
+ return ( $('#gollum-editor').length &&
324
+ $('#gollum-editor-body').length );
325
+ },
326
+
327
+
328
+ /**
329
+ * EditorHas.collapsibleInputs
330
+ * True if the editor contains collapsible inputs for things like the
331
+ * sidebar or footer, false otherwise.
332
+ *
333
+ * @return boolean
334
+ */
335
+ collapsibleInputs: function() {
336
+ return $('#gollum-editor .collapsed, #gollum-editor .expanded').length;
337
+ },
338
+
339
+
340
+ /**
341
+ * EditorHas.formatSelector
342
+ * True if the editor has a format selector (for switching between
343
+ * language types), false otherwise.
344
+ *
345
+ * @return boolean
346
+ */
347
+ formatSelector: function() {
348
+ return $('#gollum-editor-format-selector select').length;
349
+ },
350
+
351
+
352
+ /**
353
+ * EditorHas.functionBar
354
+ * True if the Function Bar markup exists.
355
+ *
356
+ * @return boolean
357
+ */
358
+ functionBar: function() {
359
+ return ( ActiveOptions.HasFunctionBar &&
360
+ $('#gollum-editor-function-bar').length );
361
+ },
362
+
363
+
364
+ /**
365
+ * EditorHas.ff4Environment
366
+ * True if in a Firefox 4.0 Beta environment.
367
+ *
368
+ * @return boolean
369
+ */
370
+ ff4Environment: function() {
371
+ var ua = new RegExp(/Firefox\/4.0b/);
372
+ return ( ua.test( navigator.userAgent ) );
373
+ },
374
+
375
+
376
+ /**
377
+ * EditorHas.editSummaryMarkup
378
+ * True if the editor has a summary field (Gollum's commit message),
379
+ * false otherwise.
380
+ *
381
+ * @return boolean
382
+ */
383
+ editSummaryMarkup: function() {
384
+ return ( $('input#gollum-editor-message-field').length > 0 );
385
+ },
386
+
387
+
388
+ /**
389
+ * EditorHas.help
390
+ * True if the editor contains the inline help sector, false otherwise.
391
+ *
392
+ * @return boolean
393
+ */
394
+ help: function() {
395
+ return ( $('#gollum-editor #gollum-editor-help').length &&
396
+ $('#gollum-editor #function-help').length );
397
+ },
398
+
399
+
400
+ /**
401
+ * EditorHas.previewButton
402
+ * True if the editor has a preview button, false otherwise.
403
+ *
404
+ * @return boolean
405
+ */
406
+ previewButton: function() {
407
+ return ( $('#gollum-editor #gollum-editor-preview').length );
408
+ },
409
+
410
+
411
+ /**
412
+ * EditorHas.titleDisplayed
413
+ * True if the editor is displaying a title field, false otherwise.
414
+ *
415
+ * @return boolean
416
+ */
417
+ titleDisplayed: function() {
418
+ return ( ActiveOptions.NewFile );
419
+ }
420
+
421
+ };
422
+
423
+
424
+ /**
425
+ * FunctionBar
426
+ *
427
+ * Things the function bar does.
428
+ */
429
+ var FunctionBar = {
430
+
431
+ isActive: false,
432
+
433
+
434
+ /**
435
+ * FunctionBar.activate
436
+ * Activates the function bar, attaching all click events
437
+ * and displaying the bar.
438
+ *
439
+ */
440
+ activate: function() {
441
+ debug('Activating function bar');
442
+
443
+ // check these out
444
+ $('#gollum-editor-function-bar a.function-button').each(function() {
445
+ if ( LanguageDefinition.getDefinitionFor( $(this).attr('id') ) ) {
446
+ $(this).click( FunctionBar.evtFunctionButtonClick );
447
+ $(this).removeClass('disabled');
448
+ }
449
+ else if ( $(this).attr('id') != 'function-help' ) {
450
+ $(this).addClass('disabled');
451
+ }
452
+ });
453
+
454
+ // show bar as active
455
+ $('#gollum-editor-function-bar').addClass( 'active' );
456
+ FunctionBar.isActive = true;
457
+ },
458
+
459
+
460
+ deactivate: function() {
461
+ $('#gollum-editor-function-bar a.function-button').unbind('click');
462
+ $('#gollum-editor-function-bar').removeClass( 'active' );
463
+ FunctionBar.isActive = false;
464
+ },
465
+
466
+
467
+ /**
468
+ * FunctionBar.evtFunctionButtonClick
469
+ * Event handler for the function buttons. Traps the click and
470
+ * executes the proper language action.
471
+ *
472
+ * @param jQuery.Event jQuery event object.
473
+ */
474
+ evtFunctionButtonClick: function(e) {
475
+ e.preventDefault();
476
+ var def = LanguageDefinition.getDefinitionFor( $(this).attr('id') );
477
+ if ( typeof def == 'object' ) {
478
+ FunctionBar.executeAction( def );
479
+ }
480
+ },
481
+
482
+
483
+ /**
484
+ * FunctionBar.executeAction
485
+ * Executes a language-specific defined action for a function button.
486
+ *
487
+ */
488
+ executeAction: function( definitionObject ) {
489
+ // get the selected text from the textarea
490
+ var txt = $('#gollum-editor-body').val();
491
+ // hmm, I'm not sure this will work in a textarea
492
+ var selPos = FunctionBar
493
+ .getFieldSelectionPosition( $('#gollum-editor-body') );
494
+ var selText = FunctionBar.getFieldSelection( $('#gollum-editor-body') );
495
+ var repText = selText;
496
+ var reselect = true;
497
+ var cursor = null;
498
+
499
+ // execute a replacement function if one exists
500
+ if ( definitionObject.exec &&
501
+ typeof definitionObject.exec == 'function' ) {
502
+ definitionObject.exec( txt, selText, $('#gollum-editor-body') );
503
+ return;
504
+ }
505
+
506
+ // execute a search/replace if they exist
507
+ var searchExp = /([^\n]+)/gi;
508
+ if ( definitionObject.search &&
509
+ typeof definitionObject.search == 'object' ) {
510
+ debug('Replacing search Regex');
511
+ searchExp = null;
512
+ searchExp = new RegExp ( definitionObject.search );
513
+ debug( searchExp );
514
+ }
515
+ debug('repText is ' + '"' + repText + '"');
516
+ // replace text
517
+ if ( definitionObject.replace &&
518
+ typeof definitionObject.replace == 'string' ) {
519
+ debug('Running replacement - using ' + definitionObject.replace);
520
+ var rt = definitionObject.replace;
521
+ repText = repText.replace( searchExp, rt );
522
+ // remove backreferences
523
+ repText = repText.replace( /\$[\d]/g, '' );
524
+
525
+ if ( repText === '' ) {
526
+ debug('Search string is empty');
527
+
528
+ // find position of $1 - this is where we will place the cursor
529
+ cursor = rt.indexOf('$1');
530
+
531
+ // we have an empty string, so just remove backreferences
532
+ repText = rt.replace( /\$[\d]/g, '' );
533
+
534
+ // if the position of $1 doesn't exist, stick the cursor in
535
+ // the middle
536
+ if ( cursor == -1 ) {
537
+ cursor = Math.floor( rt.length / 2 );
538
+ }
539
+ }
540
+ }
541
+
542
+ // append if necessary
543
+ if ( definitionObject.append &&
544
+ typeof definitionObject.append == 'string' ) {
545
+ if ( repText == selText ) {
546
+ reselect = false;
547
+ }
548
+ repText += definitionObject.append;
549
+ }
550
+
551
+ if ( repText ) {
552
+ FunctionBar.replaceFieldSelection( $('#gollum-editor-body'),
553
+ repText, reselect, cursor );
554
+ }
555
+
556
+ },
557
+
558
+
559
+ /**
560
+ * getFieldSelectionPosition
561
+ * Retrieves the selection range for the textarea.
562
+ *
563
+ * @return object the .start and .end offsets in the string
564
+ */
565
+ getFieldSelectionPosition: function( $field ) {
566
+ if ($field.length) {
567
+ var start = 0, end = 0;
568
+ var el = $field.get(0);
569
+
570
+ if (typeof el.selectionStart == "number" &&
571
+ typeof el.selectionEnd == "number") {
572
+ start = el.selectionStart;
573
+ end = el.selectionEnd;
574
+ } else {
575
+ var range = document.selection.createRange();
576
+ var stored_range = range.duplicate();
577
+ stored_range.moveToElementText( el );
578
+ stored_range.setEndPoint( 'EndToEnd', range );
579
+ start = stored_range.text.length - range.text.length;
580
+ end = start + range.text.length;
581
+
582
+ // so, uh, we're close, but we need to search for line breaks and
583
+ // adjust the start/end points accordingly since IE counts them as
584
+ // 2 characters in TextRange.
585
+ var s = start;
586
+ var lb = 0;
587
+ var i;
588
+ debug('IE: start position is currently ' + s);
589
+ for ( i=0; i < s; i++ ) {
590
+ if ( el.value.charAt(i).match(/\r/) ) {
591
+ ++lb;
592
+ }
593
+ }
594
+
595
+ if ( lb ) {
596
+ debug('IE start: compensating for ' + lb + ' line breaks');
597
+ start = start - lb;
598
+ lb = 0;
599
+ }
600
+
601
+ var e = end;
602
+ for ( i=0; i < e; i++ ) {
603
+ if ( el.value.charAt(i).match(/\r/) ) {
604
+ ++lb;
605
+ }
606
+ }
607
+
608
+ if ( lb ) {
609
+ debug('IE end: compensating for ' + lb + ' line breaks');
610
+ end = end - lb;
611
+ }
612
+ }
613
+
614
+ return {
615
+ start: start,
616
+ end: end
617
+ };
618
+ } // end if ($field.length)
619
+ },
620
+
621
+
622
+ /**
623
+ * getFieldSelection
624
+ * Returns the currently selected substring of the textarea.
625
+ *
626
+ * @param jQuery A jQuery object for the textarea.
627
+ * @return string Selected string.
628
+ */
629
+ getFieldSelection: function( $field ) {
630
+ var selStr = '';
631
+ var selPos;
632
+
633
+ if ( $field.length ) {
634
+ selPos = FunctionBar.getFieldSelectionPosition( $field );
635
+ selStr = $field.val().substring( selPos.start, selPos.end );
636
+ debug('Selected: ' + selStr + ' (' + selPos.start + ', ' +
637
+ selPos.end + ')');
638
+ return selStr;
639
+ }
640
+ return false;
641
+ },
642
+
643
+
644
+ isShown: function() {
645
+ return ($('#gollum-editor-function-bar').is(':visible'));
646
+ },
647
+
648
+ refresh: function() {
649
+ if ( EditorHas.functionBar() ) {
650
+ debug('Refreshing function bar');
651
+ if ( LanguageDefinition.isValid() ) {
652
+ $('#gollum-editor-function-bar a.function-button').unbind('click');
653
+ FunctionBar.activate();
654
+ if ( Help ) {
655
+ Help.setActiveHelp( LanguageDefinition.getActiveLanguage() );
656
+ }
657
+ } else {
658
+ debug('Language definition is invalid.');
659
+ if ( FunctionBar.isShown() ) {
660
+ // deactivate the function bar; it's not gonna work now
661
+ FunctionBar.deactivate();
662
+ }
663
+ if ( Help.isShown() ) {
664
+ Help.hide();
665
+ }
666
+ }
667
+ }
668
+ },
669
+
670
+
671
+ /**
672
+ * replaceFieldSelection
673
+ * Replaces the currently selected substring of the textarea with
674
+ * a new string.
675
+ *
676
+ * @param jQuery A jQuery object for the textarea.
677
+ * @param string The string to replace the current selection with.
678
+ * @param boolean Reselect the new text range.
679
+ */
680
+ replaceFieldSelection: function( $field, replaceText, reselect, cursorOffset ) {
681
+ var selPos = FunctionBar.getFieldSelectionPosition( $field );
682
+ var fullStr = $field.val();
683
+ var selectNew = true;
684
+ if ( reselect === false) {
685
+ selectNew = false;
686
+ }
687
+
688
+ var scrollTop = null;
689
+ if ( $field[0].scrollTop ) {
690
+ scrollTop = $field[0].scrollTop;
691
+ }
692
+
693
+ $field.val( fullStr.substring(0, selPos.start) + replaceText +
694
+ fullStr.substring(selPos.end) );
695
+ $field[0].focus();
696
+
697
+ if ( selectNew ) {
698
+ if ( $field[0].setSelectionRange ) {
699
+ if ( cursorOffset ) {
700
+ $field[0].setSelectionRange(
701
+ selPos.start + cursorOffset,
702
+ selPos.start + cursorOffset
703
+ );
704
+ } else {
705
+ $field[0].setSelectionRange( selPos.start,
706
+ selPos.start + replaceText.length );
707
+ }
708
+ } else if ( $field[0].createTextRange ) {
709
+ var range = $field[0].createTextRange();
710
+ range.collapse( true );
711
+ if ( cursorOffset ) {
712
+ range.moveEnd( selPos.start + cursorOffset );
713
+ range.moveStart( selPos.start + cursorOffset );
714
+ } else {
715
+ range.moveEnd( 'character', selPos.start + replaceText.length );
716
+ range.moveStart( 'character', selPos.start );
717
+ }
718
+ range.select();
719
+ }
720
+ }
721
+
722
+ if ( scrollTop ) {
723
+ // this jumps sometimes in FF
724
+ $field[0].scrollTop = scrollTop;
725
+ }
726
+ }
727
+ };
728
+
729
+
730
+
731
+ /**
732
+ * FormatSelector
733
+ *
734
+ * Functions relating to the format selector (if it exists)
735
+ */
736
+ var FormatSelector = {
737
+
738
+ $_SELECTOR: null,
739
+
740
+ /**
741
+ * FormatSelector.evtChangeFormat
742
+ * Event handler for when a format has been changed by the format
743
+ * selector. Will automatically load a new language definition
744
+ * via JS if necessary.
745
+ *
746
+ * @return void
747
+ */
748
+ evtChangeFormat: function( e ) {
749
+ var newMarkup = $(this).val();
750
+ LanguageDefinition.setActiveLanguage( newMarkup );
751
+ },
752
+
753
+
754
+ /**
755
+ * FormatSelector.init
756
+ * Initializes the format selector.
757
+ *
758
+ * @return void
759
+ */
760
+ init: function( $sel ) {
761
+ debug('Initializing format selector');
762
+
763
+ // unbind events if init is being called twice for some reason
764
+ if ( FormatSelector.$_SELECTOR &&
765
+ typeof FormatSelector.$_SELECTOR == 'object' ) {
766
+ FormatSelector.$_SELECTOR.unbind( 'change' );
767
+ }
768
+
769
+ FormatSelector.$_SELECTOR = $sel;
770
+
771
+ // set format selector to the current language
772
+ FormatSelector.updateSelected();
773
+ FormatSelector.$_SELECTOR.change( FormatSelector.evtChangeFormat );
774
+ },
775
+
776
+
777
+ /**
778
+ * FormatSelector.update
779
+ */
780
+ updateSelected: function() {
781
+ var currentLang = LanguageDefinition.getActiveLanguage();
782
+ FormatSelector.$_SELECTOR.val( currentLang );
783
+ }
784
+
785
+ };
786
+
787
+
788
+
789
+ /**
790
+ * Help
791
+ *
792
+ * Functions that manage the display and loading of inline help files.
793
+ */
794
+ var Help = {
795
+
796
+ _ACTIVE_HELP: '',
797
+ _LOADED_HELP_LANGS: [],
798
+ _HELP: {},
799
+
800
+ /**
801
+ * Help.define
802
+ *
803
+ * Defines a new help context and enables the help function if it
804
+ * exists in the Gollum Function Bar.
805
+ *
806
+ * @param string name The name you're giving to this help context.
807
+ * Generally, this should match the language name.
808
+ * @param object definitionObject The definition object being loaded from a
809
+ * language / help definition file.
810
+ * @return void
811
+ */
812
+ define: function( name, definitionObject ) {
813
+ if ( Help.isValidHelpFormat( definitionObject ) ) {
814
+ debug('help is a valid format');
815
+
816
+ Help._ACTIVE_HELP_LANG = name;
817
+ Help._LOADED_HELP_LANGS.push( name );
818
+ Help._HELP[name] = definitionObject;
819
+
820
+ if ( $("#function-help").length ) {
821
+ if ( $('#function-help').hasClass('disabled') ) {
822
+ $('#function-help').removeClass('disabled');
823
+ }
824
+ $('#function-help').unbind('click');
825
+ $('#function-help').click( Help.evtHelpButtonClick );
826
+
827
+ // generate help menus
828
+ Help.generateHelpMenuFor( name );
829
+
830
+ if ( $('#gollum-editor-help').length &&
831
+ typeof $('#gollum-editor-help').attr('data-autodisplay') !== 'undefined' &&
832
+ $('#gollum-editor-help').attr('data-autodisplay') === 'true' ) {
833
+ Help.show();
834
+ }
835
+ }
836
+ } else {
837
+ if ( $('#function-help').length ) {
838
+ $('#function-help').addClass('disabled');
839
+ }
840
+ }
841
+ },
842
+
843
+ /**
844
+ * Help.generateHelpMenuFor
845
+ * Generates the markup for the main help menu given a context name.
846
+ *
847
+ * @param string name The context name.
848
+ * @return void
849
+ */
850
+ generateHelpMenuFor: function( name ) {
851
+ if ( !Help._HELP[name] ) {
852
+ debug('Help is not defined for ' + name.toString());
853
+ return false;
854
+ }
855
+ var helpData = Help._HELP[name];
856
+
857
+ // clear this shiz out
858
+ $('#gollum-editor-help-parent').html('');
859
+ $('#gollum-editor-help-list').html('');
860
+ $('#gollum-editor-help-content').html('');
861
+
862
+ // go go inefficient algorithm
863
+ for ( var i=0; i < helpData.length; i++ ) {
864
+ if ( typeof helpData[i] != 'object' ) {
865
+ break;
866
+ }
867
+
868
+ var $newLi = $('<li><a href="#" rel="' + i + '">' +
869
+ helpData[i].menuName + '</a></li>');
870
+ $('#gollum-editor-help-parent').append( $newLi );
871
+ if ( i === 0 ) {
872
+ // select on first run
873
+ $newLi.children('a').addClass('selected');
874
+ }
875
+ $newLi.children('a').click( Help.evtParentMenuClick );
876
+ }
877
+
878
+ // generate parent submenu on first run
879
+ Help.generateSubMenu( helpData[0], 0 );
880
+ $($('#gollum-editor-help-list li a').get(0)).click();
881
+
882
+ },
883
+
884
+ /**
885
+ * Help.generateSubMenu
886
+ * Generates the markup for the inline help sub-menu given the data
887
+ * object for the submenu and the array index to start at.
888
+ *
889
+ * @param object subData The data for the sub-menu.
890
+ * @param integer index The index clicked on (parent menu index).
891
+ * @return void
892
+ */
893
+ generateSubMenu: function( subData, index ) {
894
+ $('#gollum-editor-help-list').html('');
895
+ $('#gollum-editor-help-content').html('');
896
+ for ( var i=0; i < subData.content.length; i++ ) {
897
+ if ( typeof subData.content[i] != 'object' ) {
898
+ break;
899
+ }
900
+
901
+ var $subLi = $('<li><a href="#" rel="' + index + ':' + i + '">' +
902
+ subData.content[i].menuName + '</a></li>');
903
+
904
+
905
+ $('#gollum-editor-help-list').append( $subLi );
906
+ $subLi.children('a').click( Help.evtSubMenuClick );
907
+ }
908
+ },
909
+
910
+ hide: function() {
911
+ if ( $.browser.msie ) {
912
+ $('#gollum-editor-help').css('display', 'none');
913
+ } else {
914
+ $('#gollum-editor-help').animate({
915
+ opacity: 0
916
+ }, 200, function() {
917
+ $('#gollum-editor-help')
918
+ .animate({ height: 'hide' }, 200);
919
+ });
920
+ }
921
+ },
922
+
923
+ show: function() {
924
+ if ( $.browser.msie ) {
925
+ // bypass effects for internet explorer, since it does weird crap
926
+ // to text antialiasing with opacity animations
927
+ $('#gollum-editor-help').css('display', 'block');
928
+ } else {
929
+ $('#gollum-editor-help').animate({
930
+ height: 'show'
931
+ }, 200, function() {
932
+ $('#gollum-editor-help')
933
+ .animate({ opacity: 1 }, 300);
934
+ });
935
+ }
936
+ },
937
+
938
+ /**
939
+ * Help.showHelpFor
940
+ * Displays the actual help content given the two menu indexes, which are
941
+ * rendered in the rel="" attributes of the help menus
942
+ *
943
+ * @param integer index1 parent index
944
+ * @param integer index2 submenu index
945
+ * @return void
946
+ */
947
+ showHelpFor: function( index1, index2 ) {
948
+ var html =
949
+ Help._HELP[Help._ACTIVE_HELP_LANG][index1].content[index2].data;
950
+ $('#gollum-editor-help-content').html(html);
951
+ },
952
+
953
+ /**
954
+ * Help.isLoadedFor
955
+ * Returns true if help is loaded for a specific markup language,
956
+ * false otherwise.
957
+ *
958
+ * @param string name The name of the markup language.
959
+ * @return boolean
960
+ */
961
+ isLoadedFor: function( name ) {
962
+ for ( var i=0; i < Help._LOADED_HELP_LANGS.length; i++ ) {
963
+ if ( name == Help._LOADED_HELP_LANGS[i] ) {
964
+ return true;
965
+ }
966
+ }
967
+ return false;
968
+ },
969
+
970
+ isShown: function() {
971
+ return ($('#gollum-editor-help').is(':visible'));
972
+ },
973
+
974
+ /**
975
+ * Help.isValidHelpFormat
976
+ * Does a quick check to make sure that the help definition isn't in a
977
+ * completely messed-up format.
978
+ *
979
+ * @param object (Array) helpArr The help definition array.
980
+ * @return boolean
981
+ */
982
+ isValidHelpFormat: function( helpArr ) {
983
+ return ( typeof helpArr == 'object' &&
984
+ helpArr.length &&
985
+ typeof helpArr[0].menuName == 'string' &&
986
+ typeof helpArr[0].content == 'object' &&
987
+ helpArr[0].content.length );
988
+ },
989
+
990
+ /**
991
+ * Help.setActiveHelp
992
+ * Sets the active help definition to the one defined in the argument,
993
+ * re-rendering the help menu to match the new definition.
994
+ *
995
+ * @param string name The name of the help definition.
996
+ * @return void
997
+ */
998
+ setActiveHelp: function( name ) {
999
+ if ( !Help.isLoadedFor( name ) ) {
1000
+ if ( $('#function-help').length ) {
1001
+ $('#function-help').addClass('disabled');
1002
+ }
1003
+ if ( Help.isShown() ) {
1004
+ Help.hide();
1005
+ }
1006
+ } else {
1007
+ Help._ACTIVE_HELP_LANG = name;
1008
+ if ( $("#function-help").length ) {
1009
+ if ( $('#function-help').hasClass('disabled') ) {
1010
+ $('#function-help').removeClass('disabled');
1011
+ }
1012
+ $('#function-help').unbind('click');
1013
+ $('#function-help').click( Help.evtHelpButtonClick );
1014
+ Help.generateHelpMenuFor( name );
1015
+ }
1016
+ }
1017
+ },
1018
+
1019
+ /**
1020
+ * Help.evtHelpButtonClick
1021
+ * Event handler for clicking the help button in the function bar.
1022
+ *
1023
+ * @param jQuery.Event e The jQuery event object.
1024
+ * @return void
1025
+ */
1026
+ evtHelpButtonClick: function( e ) {
1027
+ e.preventDefault();
1028
+ if ( Help.isShown() ) {
1029
+ // turn off autodisplay if it's on
1030
+ if ( $('#gollum-editor-help').length &&
1031
+ $('#gollum-editor-help').attr('data-autodisplay') !== 'undefined' &&
1032
+ $('#gollum-editor-help').attr('data-autodisplay') === 'true' ) {
1033
+ $.post('/wiki/help?_method=delete');
1034
+ $('#gollum-editor-help').attr('data-autodisplay', '');
1035
+ }
1036
+ Help.hide(); }
1037
+ else { Help.show(); }
1038
+ },
1039
+
1040
+ /**
1041
+ * Help.evtParentMenuClick
1042
+ * Event handler for clicking on an item in the parent menu. Automatically
1043
+ * renders the submenu for the parent menu as well as the first result for
1044
+ * the actual plain text.
1045
+ *
1046
+ * @param jQuery.Event e The jQuery event object.
1047
+ * @return void
1048
+ */
1049
+ evtParentMenuClick: function( e ) {
1050
+ e.preventDefault();
1051
+ // short circuit if we've selected this already
1052
+ if ( $(this).hasClass('selected') ) { return; }
1053
+
1054
+ // populate from help data for this
1055
+ var helpIndex = $(this).attr('rel');
1056
+ var subData = Help._HELP[Help._ACTIVE_HELP_LANG][helpIndex];
1057
+
1058
+ $('#gollum-editor-help-parent li a').removeClass('selected');
1059
+ $(this).addClass('selected');
1060
+ Help.generateSubMenu( subData, helpIndex );
1061
+ $($('#gollum-editor-help-list li a').get(0)).click();
1062
+ },
1063
+
1064
+ /**
1065
+ * Help.evtSubMenuClick
1066
+ * Event handler for clicking an item in a help submenu. Renders the
1067
+ * appropriate text for the submenu link.
1068
+ *
1069
+ * @param jQuery.Event e The jQuery event object.
1070
+ * @return void
1071
+ */
1072
+ evtSubMenuClick: function( e ) {
1073
+ e.preventDefault();
1074
+ if ( $(this).hasClass('selected') ) { return; }
1075
+
1076
+ // split index rel data
1077
+ var rawIndex = $(this).attr('rel').split(':');
1078
+ $('#gollum-editor-help-list li a').removeClass('selected');
1079
+ $(this).addClass('selected');
1080
+ Help.showHelpFor( rawIndex[0], rawIndex[1] );
1081
+ }
1082
+ };
1083
+
1084
+ // Publicly-accessible function to Help.define
1085
+ $.GollumEditor.defineHelp = Help.define;
1086
+
1087
+ // Dialog exists as its own thing now
1088
+ $.GollumEditor.Dialog = $.GollumDialog;
1089
+ $.GollumEditor.replaceSelection = function( repText ) {
1090
+ FunctionBar.replaceFieldSelection( $('#gollum-editor-body'), repText );
1091
+ };
1092
+
1093
+ // Placeholder exists as its own thing now
1094
+ $.GollumEditor.Placeholder = $.GollumPlaceholder;
1095
+
1096
+ })(jQuery);