tjadmin 0.0.3 → 0.0.4

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