tjadmin 0.0.3 → 0.0.4

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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/lib/tjadmin/version.rb +1 -1
  3. data/vendor/assets/font/DXI1ORHCpsQm3Vp6mXoaTXhCUOGz7vYGh680lGh-uXM.woff +0 -0
  4. data/vendor/assets/font/FontAwesome.otf +0 -0
  5. data/vendor/assets/font/cJZKeOuBrn4kERxqtaUH3T8E0i7KZn-EPnyo3HZu7kw.woff +0 -0
  6. data/vendor/assets/font/fontawesome-webfont.eot +0 -0
  7. data/vendor/assets/font/fontawesome-webfont.svg +399 -0
  8. data/vendor/assets/font/fontawesome-webfont.ttf +0 -0
  9. data/vendor/assets/font/fontawesome-webfont.woff +0 -0
  10. data/vendor/assets/javascripts/tjadmin/ace-elements.js +866 -0
  11. data/vendor/assets/javascripts/tjadmin/ace-extra.js +374 -0
  12. data/vendor/assets/javascripts/tjadmin/ace.js +310 -0
  13. data/vendor/assets/javascripts/tjadmin/additional-methods.js +617 -0
  14. data/vendor/assets/javascripts/tjadmin/bootbox.js +660 -0
  15. data/vendor/assets/javascripts/tjadmin/bootstrap-colorpicker.js +540 -0
  16. data/vendor/assets/javascripts/tjadmin/bootstrap-tag.js +206 -0
  17. data/vendor/assets/javascripts/tjadmin/bootstrap-wysiwyg.js +206 -0
  18. data/vendor/assets/javascripts/tjadmin/bootstrap.js +2280 -0
  19. data/vendor/assets/javascripts/tjadmin/chosen.jquery.js +1166 -0
  20. data/vendor/assets/javascripts/tjadmin/date-time/bootstrap-datepicker.js +1016 -0
  21. data/vendor/assets/javascripts/tjadmin/date-time/bootstrap-timepicker.js +888 -0
  22. data/vendor/assets/javascripts/tjadmin/date-time/daterangepicker.js +854 -0
  23. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.bg.js +14 -0
  24. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.ca.js +14 -0
  25. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.cs.js +15 -0
  26. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.da.js +14 -0
  27. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.de.js +16 -0
  28. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.el.js +13 -0
  29. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.es.js +14 -0
  30. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.fi.js +14 -0
  31. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.fr.js +16 -0
  32. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.he.js +15 -0
  33. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.hr.js +13 -0
  34. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.hu.js +16 -0
  35. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.id.js +13 -0
  36. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.is.js +14 -0
  37. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.it.js +16 -0
  38. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.ja.js +15 -0
  39. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.kr.js +13 -0
  40. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.lt.js +16 -0
  41. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.lv.js +16 -0
  42. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.ms.js +14 -0
  43. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.nb.js +14 -0
  44. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.nl.js +14 -0
  45. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.pl.js +15 -0
  46. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.pt-BR.js +14 -0
  47. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.pt.js +14 -0
  48. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.ro.js +15 -0
  49. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.rs-latin.js +14 -0
  50. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.rs.js +14 -0
  51. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.ru.js +14 -0
  52. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.sk.js +15 -0
  53. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.sl.js +14 -0
  54. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.sv.js +14 -0
  55. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.sw.js +15 -0
  56. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.th.js +14 -0
  57. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.tr.js +15 -0
  58. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.uk.js +14 -0
  59. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.zh-CN.js +14 -0
  60. data/vendor/assets/javascripts/tjadmin/date-time/locales/bootstrap-datepicker.zh-TW.js +13 -0
  61. data/vendor/assets/javascripts/tjadmin/date-time/moment.js +1400 -0
  62. data/vendor/assets/javascripts/tjadmin/excanvas.js +1428 -0
  63. data/vendor/assets/javascripts/tjadmin/flot/jquery.flot.js +3061 -0
  64. data/vendor/assets/javascripts/tjadmin/flot/jquery.flot.pie.js +817 -0
  65. data/vendor/assets/javascripts/tjadmin/flot/jquery.flot.resize.js +60 -0
  66. data/vendor/assets/javascripts/tjadmin/fuelux/data/fuelux.tree-sampledata.js +174 -0
  67. data/vendor/assets/javascripts/tjadmin/fuelux/fuelux.spinner.js +201 -0
  68. data/vendor/assets/javascripts/tjadmin/fuelux/fuelux.tree.js +173 -0
  69. data/vendor/assets/javascripts/tjadmin/fuelux/fuelux.wizard.js +172 -0
  70. data/vendor/assets/javascripts/tjadmin/fullcalendar.js +5973 -0
  71. data/vendor/assets/javascripts/tjadmin/jquery-1.10.2.js +9789 -0
  72. data/vendor/assets/javascripts/tjadmin/jquery-2.0.3.js +8829 -0
  73. data/vendor/assets/javascripts/tjadmin/jquery-ui-1.10.3.custom.js +5423 -0
  74. data/vendor/assets/javascripts/tjadmin/jquery.autosize.js +242 -0
  75. data/vendor/assets/javascripts/tjadmin/jquery.colorbox.js +1063 -0
  76. data/vendor/assets/javascripts/tjadmin/jquery.dataTables.js +12099 -0
  77. data/vendor/assets/javascripts/tjadmin/jquery.easy-pie-chart.js +200 -0
  78. data/vendor/assets/javascripts/tjadmin/jquery.gritter.js +418 -0
  79. data/vendor/assets/javascripts/tjadmin/jquery.hotkeys.js +113 -0
  80. data/vendor/assets/javascripts/tjadmin/jquery.inputlimiter.1.3.1.js +172 -0
  81. data/vendor/assets/javascripts/tjadmin/jquery.knob.js +656 -0
  82. data/vendor/assets/javascripts/tjadmin/jquery.maskedinput.js +338 -0
  83. data/vendor/assets/javascripts/tjadmin/jquery.mobile.custom.js +1081 -0
  84. data/vendor/assets/javascripts/tjadmin/jquery.slimscroll.js +448 -0
  85. data/vendor/assets/javascripts/tjadmin/jquery.sparkline.js +3054 -0
  86. data/vendor/assets/javascripts/tjadmin/jquery.ui.touch-punch.js +160 -0
  87. data/vendor/assets/javascripts/tjadmin/jquery.validate.js +1231 -0
  88. data/vendor/assets/javascripts/tjadmin/markdown/bootstrap-markdown.js +993 -0
  89. data/vendor/assets/javascripts/tjadmin/markdown/markdown.js +1616 -0
  90. data/vendor/assets/javascripts/tjadmin/markdown/to-markdown.js +184 -0
  91. data/vendor/assets/javascripts/tjadmin/select2.js +3168 -0
  92. data/vendor/assets/javascripts/tjadmin/spin.js +349 -0
  93. data/vendor/assets/javascripts/tjadmin/x-editable/ace-editable.js +368 -0
  94. data/vendor/assets/javascripts/tjadmin/x-editable/bootstrap-editable.js +6827 -0
  95. data/vendor/assets/javascripts/tjadmin.js +5 -0
  96. data/vendor/assets/stylesheets/tjadmin/ace-fonts.css.scss +13 -0
  97. data/vendor/assets/stylesheets/tjadmin/ace-ie.css +293 -0
  98. data/vendor/assets/stylesheets/tjadmin/ace-responsive.css +1113 -0
  99. data/vendor/assets/stylesheets/tjadmin/ace-skins.css +1301 -0
  100. data/vendor/assets/stylesheets/tjadmin/ace.css +14701 -0
  101. data/vendor/assets/stylesheets/tjadmin/bootstrap-responsive.css +1109 -0
  102. data/vendor/assets/stylesheets/tjadmin/bootstrap.css +6167 -0
  103. data/vendor/assets/stylesheets/tjadmin/chosen.css +430 -0
  104. data/vendor/assets/stylesheets/tjadmin/font-awesome-ie7.css +1203 -0
  105. data/vendor/assets/stylesheets/tjadmin/font-awesome.css +1479 -0
  106. data/vendor/assets/stylesheets/tjadmin/jquery-ui-1.10.3.custom.css +223 -0
  107. data/vendor/assets/stylesheets/tjadmin.css +9 -0
  108. metadata +106 -1
@@ -0,0 +1,993 @@
1
+ /* ===================================================
2
+ * bootstrap-markdown.js v1.1.4
3
+ * http://github.com/toopay/bootstrap-markdown
4
+ * ===================================================
5
+ * Copyright 2013 Taufan Aditya
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ * ========================================================== */
19
+
20
+ !function ($) {
21
+
22
+ "use strict"; // jshint ;_;
23
+
24
+
25
+ /* MARKDOWN CLASS DEFINITION
26
+ * ========================== */
27
+
28
+ var Markdown = function (element, options) {
29
+ // Class Properties
30
+ this.$ns = 'bootstrap-markdown'
31
+ this.$element = $(element)
32
+ this.$editable = {el:null, type:null,attrKeys:[], attrValues:[], content:null}
33
+ this.$options = $.extend(true, {}, $.fn.markdown.defaults, options)
34
+ this.$oldContent = null
35
+ this.$isPreview = false
36
+ this.$editor = null
37
+ this.$textarea = null
38
+ this.$handler = []
39
+ this.$callback = []
40
+ this.$nextTab = []
41
+
42
+ this.showEditor()
43
+ }
44
+
45
+ Markdown.prototype = {
46
+
47
+ constructor: Markdown
48
+
49
+ , __alterButtons: function(name,alter) {
50
+ var handler = this.$handler, isAll = (name == 'all'),that = this
51
+
52
+ $.each(handler,function(k,v) {
53
+ var halt = true
54
+ if (isAll) {
55
+ halt = false
56
+ } else {
57
+ halt = v.indexOf(name) < 0
58
+ }
59
+
60
+ if (halt == false) {
61
+ alter(that.$editor.find('button[data-handler="'+v+'"]'))
62
+ }
63
+ })
64
+ }
65
+
66
+ , __buildButtons: function(buttonsArray, container) {
67
+ var i,
68
+ ns = this.$ns,
69
+ handler = this.$handler,
70
+ callback = this.$callback
71
+
72
+ for (i=0;i<buttonsArray.length;i++) {
73
+ // Build each group container
74
+ var y, btnGroups = buttonsArray[i]
75
+ for (y=0;y<btnGroups.length;y++) {
76
+ // Build each button group
77
+ var z,
78
+ buttons = btnGroups[y].data,
79
+ btnGroupContainer = $('<div/>', {
80
+ 'class': 'btn-group'
81
+ })
82
+
83
+ for (z=0;z<buttons.length;z++) {
84
+ var button = buttons[z],
85
+ buttonToggle = '',
86
+ buttonHandler = ns+'-'+button.name,
87
+ btnText = button.btnText ? button.btnText : '',
88
+ btnClass = button.btnClass ? button.btnClass : 'btn',
89
+ tabIndex = button.tabIndex ? button.tabIndex : '-1'
90
+
91
+ if (button.toggle == true) {
92
+ buttonToggle = ' data-toggle="button"'
93
+ }
94
+
95
+ // Attach the button object
96
+ btnGroupContainer.append('<button class="'
97
+ +btnClass
98
+ +' btn-small" title="'
99
+ +button.title
100
+ +'" tabindex="'
101
+ +tabIndex
102
+ +'" data-provider="'
103
+ +ns
104
+ +'" data-handler="'
105
+ +buttonHandler
106
+ +'"'
107
+ +buttonToggle
108
+ +'><i class="'
109
+ +button.icon
110
+ +'"></i> '
111
+ +btnText
112
+ +'</button>')
113
+
114
+ // Register handler and callback
115
+ handler.push(buttonHandler)
116
+ callback.push(button.callback)
117
+ }
118
+
119
+ // Attach the button group into container dom
120
+ container.append(btnGroupContainer)
121
+ }
122
+ }
123
+
124
+ return container
125
+ }
126
+ , __setListener: function() {
127
+ // Set size and resizable Properties
128
+ var hasRows = typeof this.$textarea.attr('rows') != 'undefined',
129
+ maxRows = this.$textarea.val().split("\n").length > 5 ? this.$textarea.val().split("\n").length : '5',
130
+ rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows
131
+
132
+ this.$textarea.attr('rows',rowsVal)
133
+ this.$textarea.css('resize','none')
134
+
135
+ this.$textarea
136
+ .on('focus', $.proxy(this.focus, this))
137
+ .on('keypress', $.proxy(this.keypress, this))
138
+ .on('keyup', $.proxy(this.keyup, this))
139
+
140
+ if (this.eventSupported('keydown')) {
141
+ this.$textarea.on('keydown', $.proxy(this.keydown, this))
142
+ }
143
+
144
+ // Re-attach markdown data
145
+ this.$textarea.data('markdown',this)
146
+ }
147
+
148
+ , __handle: function(e) {
149
+ var target = $(e.currentTarget),
150
+ handler = this.$handler,
151
+ callback = this.$callback,
152
+ handlerName = target.attr('data-handler'),
153
+ callbackIndex = handler.indexOf(handlerName),
154
+ callbackHandler = callback[callbackIndex]
155
+
156
+ // Trigger the focusin
157
+ $(e.currentTarget).focus()
158
+
159
+ callbackHandler(this)
160
+
161
+ // Unless it was the save handler,
162
+ // focusin the textarea
163
+ if (handlerName.indexOf('cmdSave') < 0) {
164
+ this.$textarea.focus()
165
+ }
166
+
167
+ e.preventDefault()
168
+ }
169
+
170
+ , showEditor: function() {
171
+ var instance = this,
172
+ textarea,
173
+ ns = this.$ns,
174
+ container = this.$element,
175
+ originalHeigth = container.css('height'),
176
+ originalWidth = container.css('width'),
177
+ editable = this.$editable,
178
+ handler = this.$handler,
179
+ callback = this.$callback,
180
+ options = this.$options,
181
+ editor = $( '<div/>', {
182
+ 'class': 'md-editor',
183
+ click: function() {
184
+ instance.focus()
185
+ }
186
+ })
187
+
188
+ // Prepare the editor
189
+ if (this.$editor == null) {
190
+ // Create the panel
191
+ var editorHeader = $('<div/>', {
192
+ 'class': 'md-header'
193
+ })
194
+
195
+ // Build the main buttons
196
+ if (options.buttons.length > 0) {
197
+ editorHeader = this.__buildButtons(options.buttons, editorHeader)
198
+ }
199
+
200
+ // Build the additional buttons
201
+ if (options.additionalButtons.length > 0) {
202
+ editorHeader = this.__buildButtons(options.additionalButtons, editorHeader)
203
+ }
204
+
205
+ editor.append(editorHeader)
206
+
207
+ // Wrap the textarea
208
+ if (container.is('textarea')) {
209
+ container.before(editor)
210
+ textarea = container
211
+ textarea.addClass('md-input')
212
+ editor.append(textarea)
213
+ } else {
214
+ var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(),
215
+ currentContent = $.trim(rawContent)
216
+
217
+ // This is some arbitrary content that could be edited
218
+ textarea = $('<textarea/>', {
219
+ 'class': 'md-input',
220
+ 'val' : currentContent
221
+ })
222
+
223
+ editor.append(textarea)
224
+
225
+ // Save the editable
226
+ editable.el = container
227
+ editable.type = container.prop('tagName').toLowerCase()
228
+ editable.content = container.html()
229
+
230
+ $(container[0].attributes).each(function(){
231
+ editable.attrKeys.push(this.nodeName)
232
+ editable.attrValues.push(this.nodeValue)
233
+ })
234
+
235
+ // Set editor to blocked the original container
236
+ container.replaceWith(editor)
237
+ }
238
+
239
+ // Create the footer if savable
240
+ if (options.savable) {
241
+ var editorFooter = $('<div/>', {
242
+ 'class': 'md-footer'
243
+ }),
244
+ saveHandler = 'cmdSave'
245
+
246
+ // Register handler and callback
247
+ handler.push(saveHandler)
248
+ callback.push(options.onSave)
249
+
250
+ editorFooter.append('<button class="btn btn-success" data-provider="'
251
+ +ns
252
+ +'" data-handler="'
253
+ +saveHandler
254
+ +'"><i class="icon icon-white icon-ok"></i> Save</button>')
255
+
256
+ editor.append(editorFooter)
257
+ }
258
+
259
+ // Set width/height
260
+ $.each(['height','width'],function(k,attr){
261
+ if (options[attr] != 'inherit') {
262
+ if (jQuery.isNumeric(options[attr])) {
263
+ editor.css(attr,options[attr]+'px')
264
+ } else {
265
+ editor.addClass(options[attr])
266
+ }
267
+ }
268
+ })
269
+
270
+ // Reference
271
+ this.$editor = editor
272
+ this.$textarea = textarea
273
+ this.$editable = editable
274
+ this.$oldContent = this.getContent()
275
+
276
+ this.__setListener()
277
+
278
+ // Set editor attributes, data short-hand API and listener
279
+ this.$editor.attr('id',(new Date).getTime())
280
+ this.$editor.on('click', '[data-provider="bootstrap-markdown"]', $.proxy(this.__handle, this))
281
+
282
+ } else {
283
+ this.$editor.show()
284
+ }
285
+
286
+ if (options.autofocus) {
287
+ this.$textarea.focus()
288
+ this.$editor.addClass('active')
289
+ }
290
+
291
+ // Trigger the onShow hook
292
+ options.onShow(this)
293
+
294
+ return this
295
+ }
296
+
297
+ , showPreview: function() {
298
+ var options = this.$options,
299
+ callbackContent = options.onPreview(this), // Try to get the content from callback
300
+ container = this.$textarea,
301
+ afterContainer = container.next(),
302
+ replacementContainer = $('<div/>',{'class':'md-preview','data-provider':'markdown-preview'}),
303
+ content
304
+
305
+ // Give flag that tell the editor enter preview mode
306
+ this.$isPreview = true
307
+ // Disable all buttons
308
+ this.disableButtons('all').enableButtons('cmdPreview')
309
+
310
+ if (typeof callbackContent == 'string') {
311
+ // Set the content based by callback content
312
+ content = callbackContent
313
+ } else {
314
+ // Set the content
315
+ content = (typeof markdown == 'object') ? markdown.toHTML(container.val()) : container.val()
316
+ }
317
+
318
+ // Build preview element
319
+ replacementContainer.html(content)
320
+
321
+ if (afterContainer && afterContainer.attr('class') == 'md-footer') {
322
+ // If there is footer element, insert the preview container before it
323
+ replacementContainer.insertBefore(afterContainer)
324
+ } else {
325
+ // Otherwise, just append it after textarea
326
+ container.parent().append(replacementContainer)
327
+ }
328
+
329
+ // Hide the last-active textarea
330
+ container.hide()
331
+
332
+ // Attach the editor instances
333
+ replacementContainer.data('markdown',this)
334
+
335
+ return this
336
+ }
337
+
338
+ , hidePreview: function() {
339
+ // Give flag that tell the editor quit preview mode
340
+ this.$isPreview = false
341
+
342
+ // Obtain the preview container
343
+ var container = this.$editor.find('div[data-provider="markdown-preview"]')
344
+
345
+ // Remove the preview container
346
+ container.remove()
347
+
348
+ // Enable all buttons
349
+ this.enableButtons('all')
350
+
351
+ // Back to the editor
352
+ this.$textarea.show()
353
+ this.__setListener()
354
+
355
+ return this
356
+ }
357
+
358
+ , isDirty: function() {
359
+ return this.$oldContent != this.getContent()
360
+ }
361
+
362
+ , getContent: function() {
363
+ return this.$textarea.val()
364
+ }
365
+
366
+ , setContent: function(content) {
367
+ this.$textarea.val(content)
368
+
369
+ return this
370
+ }
371
+
372
+ , findSelection: function(chunk) {
373
+ var content = this.getContent(), startChunkPosition
374
+
375
+ if (startChunkPosition = content.indexOf(chunk), startChunkPosition >= 0 && chunk.length > 0) {
376
+ var oldSelection = this.getSelection(), selection
377
+
378
+ this.setSelection(startChunkPosition,startChunkPosition+chunk.length)
379
+ selection = this.getSelection()
380
+
381
+ this.setSelection(oldSelection.start,oldSelection.end)
382
+
383
+ return selection
384
+ } else {
385
+ return null
386
+ }
387
+ }
388
+
389
+ , getSelection: function() {
390
+
391
+ var e = this.$textarea[0]
392
+
393
+ return (
394
+
395
+ ('selectionStart' in e && function() {
396
+ var l = e.selectionEnd - e.selectionStart
397
+ return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) }
398
+ }) ||
399
+
400
+ /* browser not supported */
401
+ function() {
402
+ return null
403
+ }
404
+
405
+ )()
406
+
407
+ }
408
+
409
+ , setSelection: function(start,end) {
410
+
411
+ var e = this.$textarea[0]
412
+
413
+ return (
414
+
415
+ ('selectionStart' in e && function() {
416
+ e.selectionStart = start
417
+ e.selectionEnd = end
418
+ return
419
+ }) ||
420
+
421
+ /* browser not supported */
422
+ function() {
423
+ return null
424
+ }
425
+
426
+ )()
427
+
428
+ }
429
+
430
+ , replaceSelection: function(text) {
431
+
432
+ var e = this.$textarea[0]
433
+
434
+ return (
435
+
436
+ ('selectionStart' in e && function() {
437
+ e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length)
438
+ // Set cursor to the last replacement end
439
+ e.selectionStart = e.value.length
440
+ return this
441
+ }) ||
442
+
443
+ /* browser not supported */
444
+ function() {
445
+ e.value += text
446
+ return jQuery(e)
447
+ }
448
+
449
+ )()
450
+
451
+ }
452
+
453
+ , getNextTab: function() {
454
+ // Shift the nextTab
455
+ if (this.$nextTab.length == 0) {
456
+ return null
457
+ } else {
458
+ var nextTab, tab = this.$nextTab.shift()
459
+
460
+ if (typeof tab == 'function') {
461
+ nextTab = tab()
462
+ } else if (typeof tab == 'object' && tab.length > 0) {
463
+ nextTab = tab
464
+ }
465
+
466
+ return nextTab
467
+ }
468
+ }
469
+
470
+ , setNextTab: function(start,end) {
471
+ // Push new selection into nextTab collections
472
+ if (typeof start == 'string') {
473
+ var that = this
474
+ this.$nextTab.push(function(){
475
+ return that.findSelection(start)
476
+ })
477
+ } else if (typeof start == 'numeric' && typeof end == 'numeric') {
478
+ var oldSelection = this.getSelection()
479
+
480
+ this.setSelection(start,end)
481
+ this.$nextTab.push(this.getSelection())
482
+
483
+ this.setSelection(oldSelection.start,oldSelection.end)
484
+ }
485
+
486
+ return
487
+ }
488
+
489
+ , enableButtons: function(name) {
490
+ var alter = function (el) {
491
+ el.removeAttr('disabled')
492
+ }
493
+
494
+ this.__alterButtons(name,alter)
495
+
496
+ return this
497
+ }
498
+
499
+ , disableButtons: function(name) {
500
+ var alter = function (el) {
501
+ el.attr('disabled','disabled')
502
+ }
503
+
504
+ this.__alterButtons(name,alter)
505
+
506
+ return this
507
+ }
508
+
509
+ , eventSupported: function(eventName) {
510
+ var isSupported = eventName in this.$element
511
+ if (!isSupported) {
512
+ this.$element.setAttribute(eventName, 'return;')
513
+ isSupported = typeof this.$element[eventName] === 'function'
514
+ }
515
+ return isSupported
516
+ }
517
+
518
+ , keydown: function (e) {
519
+ this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
520
+ this.keyup(e)
521
+ }
522
+
523
+ , keypress: function (e) {
524
+ if (this.suppressKeyPressRepeat) return
525
+ this.keyup(e)
526
+ }
527
+
528
+ , keyup: function (e) {
529
+ var blocked = false
530
+ switch(e.keyCode) {
531
+ case 40: // down arrow
532
+ case 38: // up arrow
533
+ case 16: // shift
534
+ case 17: // ctrl
535
+ case 18: // alt
536
+ break
537
+
538
+ case 9: // tab
539
+ var nextTab
540
+ if (nextTab = this.getNextTab(),nextTab != null) {
541
+ // Get the nextTab if exists
542
+ var that = this
543
+ setTimeout(function(){
544
+ that.setSelection(nextTab.start,nextTab.end)
545
+ },500)
546
+
547
+ blocked = true
548
+ } else {
549
+ // The next tab memory contains nothing...
550
+ // check the cursor position to determine tab action
551
+ var cursor = this.getSelection()
552
+
553
+ if (cursor.start == cursor.end && cursor.end == this.getContent().length) {
554
+ // The cursor already reach the end of the content
555
+ blocked = false
556
+
557
+ } else {
558
+ // Put the cursor to the end
559
+ this.setSelection(this.getContent().length,this.getContent().length)
560
+
561
+ blocked = true
562
+ }
563
+ }
564
+
565
+ break
566
+
567
+ case 13: // enter
568
+ case 27: // escape
569
+ blocked = false
570
+ break
571
+
572
+ default:
573
+ blocked = false
574
+ }
575
+
576
+ if (blocked) {
577
+ e.stopPropagation()
578
+ e.preventDefault()
579
+ }
580
+ }
581
+
582
+ , focus: function (e) {
583
+ var options = this.$options,
584
+ isHideable = options.hideable,
585
+ editor = this.$editor
586
+
587
+ editor.addClass('active')
588
+
589
+ // Blur other markdown(s)
590
+ $(document).find('.md-editor').each(function(){
591
+ if ($(this).attr('id') != editor.attr('id')) {
592
+ var attachedMarkdown
593
+
594
+ if (attachedMarkdown = $(this).find('textarea').data('markdown'),
595
+ attachedMarkdown == null) {
596
+ attachedMarkdown = $(this).find('div[data-provider="markdown-preview"]').data('markdown')
597
+ }
598
+
599
+ if (attachedMarkdown) {
600
+ attachedMarkdown.blur()
601
+ }
602
+ }
603
+ })
604
+
605
+ return this
606
+ }
607
+
608
+ , blur: function (e) {
609
+ var options = this.$options,
610
+ isHideable = options.hideable,
611
+ editor = this.$editor,
612
+ editable = this.$editable
613
+
614
+ if (editor.hasClass('active') || this.$element.parent().length == 0) {
615
+ editor.removeClass('active')
616
+
617
+ if (isHideable) {
618
+
619
+ // Check for editable elements
620
+ if (editable.el != null) {
621
+ // Build the original element
622
+ var oldElement = $('<'+editable.type+'/>'),
623
+ content = this.getContent(),
624
+ currentContent = (typeof markdown == 'object') ? markdown.toHTML(content) : content
625
+
626
+ $(editable.attrKeys).each(function(k,v) {
627
+ oldElement.attr(editable.attrKeys[k],editable.attrValues[k])
628
+ })
629
+
630
+ // Get the editor content
631
+ oldElement.html(currentContent)
632
+
633
+ editor.replaceWith(oldElement)
634
+ } else {
635
+ editor.hide()
636
+
637
+ }
638
+ }
639
+
640
+ // Trigger the onBlur hook
641
+ options.onBlur(this)
642
+ }
643
+
644
+ return this
645
+ }
646
+
647
+ }
648
+
649
+ /* MARKDOWN PLUGIN DEFINITION
650
+ * ========================== */
651
+
652
+ var old = $.fn.markdown
653
+
654
+ $.fn.markdown = function (option) {
655
+ return this.each(function () {
656
+ var $this = $(this)
657
+ , data = $this.data('markdown')
658
+ , options = typeof option == 'object' && option
659
+ if (!data) $this.data('markdown', (data = new Markdown(this, options)))
660
+ })
661
+ }
662
+
663
+ $.fn.markdown.defaults = {
664
+ /* Editor Properties */
665
+ autofocus: false,
666
+ hideable: false,
667
+ savable:false,
668
+ width: 'inherit',
669
+ height: 'inherit',
670
+
671
+ /* Buttons Properties */
672
+ buttons: [
673
+ [{
674
+ name: 'groupFont',
675
+ data: [{
676
+ name: 'cmdBold',
677
+ title: 'Bold',
678
+ icon: 'icon icon-bold',
679
+ callback: function(e){
680
+ // Give/remove ** surround the selection
681
+ var chunk, cursor, selected = e.getSelection(), content = e.getContent()
682
+
683
+ if (selected.length == 0) {
684
+ // Give extra word
685
+ chunk = 'strong text'
686
+ } else {
687
+ chunk = selected.text
688
+ }
689
+
690
+ // transform selection and set the cursor into chunked text
691
+ if (content.substr(selected.start-2,2) == '**'
692
+ && content.substr(selected.end,2) == '**' ) {
693
+ e.setSelection(selected.start-2,selected.end+2)
694
+ e.replaceSelection(chunk)
695
+ cursor = selected.start-2
696
+ } else {
697
+ e.replaceSelection('**'+chunk+'**')
698
+ cursor = selected.start+2
699
+ }
700
+
701
+ // Set the cursor
702
+ e.setSelection(cursor,cursor+chunk.length)
703
+ }
704
+ },{
705
+ name: 'cmdItalic',
706
+ title: 'Italic',
707
+ icon: 'icon icon-italic',
708
+ callback: function(e){
709
+ // Give/remove * surround the selection
710
+ var chunk, cursor, selected = e.getSelection(), content = e.getContent()
711
+
712
+ if (selected.length == 0) {
713
+ // Give extra word
714
+ chunk = 'emphasized text'
715
+ } else {
716
+ chunk = selected.text
717
+ }
718
+
719
+ // transform selection and set the cursor into chunked text
720
+ if (content.substr(selected.start-1,1) == '*'
721
+ && content.substr(selected.end,1) == '*' ) {
722
+ e.setSelection(selected.start-1,selected.end+1)
723
+ e.replaceSelection(chunk)
724
+ cursor = selected.start-1
725
+ } else {
726
+ e.replaceSelection('*'+chunk+'*')
727
+ cursor = selected.start+1
728
+ }
729
+
730
+ // Set the cursor
731
+ e.setSelection(cursor,cursor+chunk.length)
732
+ }
733
+ },{
734
+ name: 'cmdHeading',
735
+ title: 'Heading',
736
+ icon: 'icon icon-font',
737
+ callback: function(e){
738
+ // Append/remove ### surround the selection
739
+ var chunk, cursor, selected = e.getSelection(), content = e.getContent(), pointer, prevChar
740
+
741
+ if (selected.length == 0) {
742
+ // Give extra word
743
+ chunk = 'heading text'
744
+ } else {
745
+ chunk = selected.text
746
+ }
747
+
748
+ // transform selection and set the cursor into chunked text
749
+ if ((pointer = 4, content.substr(selected.start-pointer,pointer) == '### ')
750
+ || (pointer = 3, content.substr(selected.start-pointer,pointer) == '###')) {
751
+ e.setSelection(selected.start-pointer,selected.end)
752
+ e.replaceSelection(chunk)
753
+ cursor = selected.start-pointer
754
+ } else if (prevChar = content.substr(selected.start-1,1), !!prevChar && prevChar != '\n') {
755
+ e.replaceSelection('\n\n### '+chunk+'\n')
756
+ cursor = selected.start+6
757
+ } else {
758
+ // Empty string before element
759
+ e.replaceSelection('### '+chunk+'\n')
760
+ cursor = selected.start+4
761
+ }
762
+
763
+ // Set the cursor
764
+ e.setSelection(cursor,cursor+chunk.length)
765
+ }
766
+ }]
767
+ },{
768
+ name: 'groupLink',
769
+ data: [{
770
+ name: 'cmdUrl',
771
+ title: 'URL/Link',
772
+ icon: 'icon icon-globe',
773
+ callback: function(e){
774
+ // Give [] surround the selection and prepend the link
775
+ var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link
776
+
777
+ if (selected.length == 0) {
778
+ // Give extra word
779
+ chunk = 'enter link description here'
780
+ } else {
781
+ chunk = selected.text
782
+ }
783
+
784
+ bootbox.prompt("Insert Hyperlink", function(link) {
785
+ if (link != null) {
786
+ // transform selection and set the cursor into chunked text
787
+ e.replaceSelection('['+chunk+']('+link+')')
788
+ cursor = selected.start+1
789
+
790
+ // Set the cursor
791
+ e.setSelection(cursor,cursor+chunk.length)
792
+ }
793
+ });
794
+ }
795
+ },{
796
+ name: 'cmdImage',
797
+ title: 'Image',
798
+ icon: 'icon icon-picture',
799
+ callback: function(e){
800
+ // Give ![] surround the selection and prepend the image link
801
+ var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link
802
+
803
+ if (selected.length == 0) {
804
+ // Give extra word
805
+ chunk = 'enter image description here'
806
+ } else {
807
+ chunk = selected.text
808
+ }
809
+
810
+ bootbox.prompt("Insert Image Hyperlink", function(link) {
811
+ if (link != null) {
812
+ // transform selection and set the cursor into chunked text
813
+ e.replaceSelection('!['+chunk+']('+link+' "enter image title here")')
814
+ cursor = selected.start+2
815
+
816
+ // Set the next tab
817
+ e.setNextTab('enter image title here')
818
+
819
+ // Set the cursor
820
+ e.setSelection(cursor,cursor+chunk.length)
821
+ }
822
+ });
823
+ }
824
+ }]
825
+ },{
826
+ name: 'groupMisc',
827
+ data: [{
828
+ name: 'cmdList',
829
+ title: 'List',
830
+ icon: 'icon icon-list',
831
+ callback: function(e){
832
+ // Prepend/Give - surround the selection
833
+ var chunk, cursor, selected = e.getSelection(), content = e.getContent()
834
+
835
+ // transform selection and set the cursor into chunked text
836
+ if (selected.length == 0) {
837
+ // Give extra word
838
+ chunk = 'list text here'
839
+
840
+ e.replaceSelection('- '+chunk)
841
+
842
+ // Set the cursor
843
+ cursor = selected.start+2
844
+ } else {
845
+ if (selected.text.indexOf('\n') < 0) {
846
+ chunk = selected.text
847
+
848
+ e.replaceSelection('- '+chunk)
849
+
850
+ // Set the cursor
851
+ cursor = selected.start+2
852
+ } else {
853
+ var list = []
854
+
855
+ list = selected.text.split('\n')
856
+ chunk = list[0]
857
+
858
+ $.each(list,function(k,v) {
859
+ list[k] = '- '+v
860
+ })
861
+
862
+ e.replaceSelection('\n\n'+list.join('\n'))
863
+
864
+ // Set the cursor
865
+ cursor = selected.start+4
866
+ }
867
+ }
868
+
869
+
870
+
871
+ // Set the cursor
872
+ e.setSelection(cursor,cursor+chunk.length)
873
+ }
874
+ }]
875
+ },{
876
+ name: 'groupUtil',
877
+ data: [{
878
+ name: 'cmdPreview',
879
+ toggle: true,
880
+ title: 'Preview',
881
+ btnText: 'Preview',
882
+ btnClass: 'btn btn-inverse',
883
+ icon: 'icon icon-white icon-search',
884
+ callback: function(e){
885
+ // Check the preview mode and toggle based on this flag
886
+ var isPreview = e.$isPreview,content
887
+
888
+ if (isPreview == false) {
889
+ // Give flag that tell the editor enter preview mode
890
+ e.showPreview()
891
+ } else {
892
+ e.hidePreview()
893
+ }
894
+ }
895
+ }]
896
+ }]
897
+ ],
898
+ additionalButtons:[], // Place to hook more buttons by code
899
+
900
+ /* Events hook */
901
+ onShow: function (e) {},
902
+ onPreview: function (e) {},
903
+ onSave: function (e) {},
904
+ onBlur: function (e) {}
905
+ }
906
+
907
+ $.fn.markdown.Constructor = Markdown
908
+
909
+
910
+ /* MARKDOWN NO CONFLICT
911
+ * ==================== */
912
+
913
+ $.fn.markdown.noConflict = function () {
914
+ $.fn.markdown = old
915
+ return this
916
+ }
917
+
918
+ /* MARKDOWN GLOBAL FUNCTION & DATA-API
919
+ * ==================================== */
920
+ var initMarkdown = function(el) {
921
+ var $this = el
922
+
923
+ if ($this.data('markdown')) {
924
+ $this.data('markdown').showEditor()
925
+ return
926
+ }
927
+ $this.markdown($this.data())
928
+ }
929
+
930
+ var analyzeMarkdown = function(e) {
931
+ var blurred = false,
932
+ el,
933
+ $docEditor = $(e.currentTarget)
934
+
935
+ // Check whether it was editor childs or not
936
+ if ((e.type == 'focusin' || e.type == 'click') && $docEditor.length == 1 && typeof $docEditor[0] == 'object'){
937
+ el = $docEditor[0].activeElement
938
+ if ( ! $(el).data('markdown')) {
939
+ if (typeof $(el).parent().parent().parent().attr('class') == "undefined"
940
+ || $(el).parent().parent().parent().attr('class').indexOf('md-editor') < 0) {
941
+ if ( typeof $(el).parent().parent().attr('class') == "undefined"
942
+ || $(el).parent().parent().attr('class').indexOf('md-editor') < 0) {
943
+
944
+ blurred = true
945
+ }
946
+ } else {
947
+ blurred = false
948
+ }
949
+ }
950
+
951
+
952
+ if (blurred) {
953
+ // Blur event
954
+ $(document).find('.md-editor').each(function(){
955
+ var parentMd = $(el).parent()
956
+
957
+ if ($(this).attr('id') != parentMd.attr('id')) {
958
+ var attachedMarkdown
959
+
960
+ if (attachedMarkdown = $(this).find('textarea').data('markdown'),
961
+ attachedMarkdown == null) {
962
+ attachedMarkdown = $(this).find('div[data-provider="markdown-preview"]').data('markdown')
963
+ }
964
+
965
+ if (attachedMarkdown) {
966
+ attachedMarkdown.blur()
967
+ }
968
+ }
969
+ })
970
+ }
971
+
972
+ e.stopPropagation()
973
+ }
974
+ }
975
+
976
+ $(document)
977
+ .on('click.markdown.data-api', '[data-provide="markdown-editable"]', function (e) {
978
+ initMarkdown($(this))
979
+ e.preventDefault()
980
+ })
981
+ .on('click', function (e) {
982
+ analyzeMarkdown(e)
983
+ })
984
+ .on('focusin', function (e) {
985
+ analyzeMarkdown(e)
986
+ })
987
+ .ready(function(){
988
+ $('textarea[data-provide="markdown"]').each(function(){
989
+ initMarkdown($(this))
990
+ })
991
+ })
992
+
993
+ }(window.jQuery);