wysihtml5n-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +57 -0
  3. data/lib/wysihtml5n-rails.rb +6 -0
  4. data/lib/wysihtml5n/rails.rb +2 -0
  5. data/lib/wysihtml5n/rails/engine.rb +10 -0
  6. data/lib/wysihtml5n/rails/version.rb +5 -0
  7. data/test/cases/usage_css_spec.rb +57 -0
  8. data/test/cases/usage_js_spec.rb +33 -0
  9. data/test/dummy/README.rdoc +261 -0
  10. data/test/dummy/Rakefile +7 -0
  11. data/test/dummy/app/assets/javascripts/application.js +3 -0
  12. data/test/dummy/app/assets/javascripts/individual.js +3 -0
  13. data/test/dummy/app/assets/stylesheets/application.css.scss +3 -0
  14. data/test/dummy/app/assets/stylesheets/individual.css.scss +3 -0
  15. data/test/dummy/app/assets/stylesheets/sprockets.css +3 -0
  16. data/test/dummy/app/controllers/application_controller.rb +3 -0
  17. data/test/dummy/app/helpers/application_helper.rb +2 -0
  18. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  19. data/test/dummy/config.ru +4 -0
  20. data/test/dummy/config/application.rb +69 -0
  21. data/test/dummy/config/boot.rb +10 -0
  22. data/test/dummy/config/environment.rb +5 -0
  23. data/test/dummy/config/environments/development.rb +31 -0
  24. data/test/dummy/config/environments/production.rb +64 -0
  25. data/test/dummy/config/environments/test.rb +35 -0
  26. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  27. data/test/dummy/config/initializers/inflections.rb +15 -0
  28. data/test/dummy/config/initializers/mime_types.rb +5 -0
  29. data/test/dummy/config/initializers/secret_token.rb +7 -0
  30. data/test/dummy/config/initializers/session_store.rb +8 -0
  31. data/test/dummy/config/initializers/wrap_parameters.rb +10 -0
  32. data/test/dummy/config/locales/en.yml +5 -0
  33. data/test/dummy/config/routes.rb +58 -0
  34. data/test/dummy/log/test.log +224 -0
  35. data/test/dummy/public/404.html +26 -0
  36. data/test/dummy/public/422.html +26 -0
  37. data/test/dummy/public/500.html +25 -0
  38. data/test/dummy/public/favicon.ico +0 -0
  39. data/test/dummy/script/rails +6 -0
  40. data/test/dummy/tmp/cache/sass/5338c0058b360de616e31cc6c7da71b4f9557c8f/application.css.scssc +0 -0
  41. data/test/dummy/tmp/cache/sass/5338c0058b360de616e31cc6c7da71b4f9557c8f/individual.css.scssc +0 -0
  42. data/test/dummy/tmp/cache/sass/960125ced7e54163fe33c2547bbd2af7f2929975/wysihtml5n.css.scssc +0 -0
  43. data/test/dummy/tmp/cache/sass/e2cd63e71b626fbbfe6aeea51f81580fd02e0076/_bootstrap.scssc +0 -0
  44. data/test/dummy/tmp/cache/sass/e2cd63e71b626fbbfe6aeea51f81580fd02e0076/_editor.scssc +0 -0
  45. data/test/dummy/tmp/cache/sass/e2cd63e71b626fbbfe6aeea51f81580fd02e0076/_font-awesome.scssc +0 -0
  46. data/test/dummy/tmp/cache/sass/e2cd63e71b626fbbfe6aeea51f81580fd02e0076/bootstrap.scssc +0 -0
  47. data/test/dummy/tmp/cache/sass/e2cd63e71b626fbbfe6aeea51f81580fd02e0076/editor.scssc +0 -0
  48. data/test/dummy/tmp/cache/sass/e2cd63e71b626fbbfe6aeea51f81580fd02e0076/font-awesome.scssc +0 -0
  49. data/test/spec_helper.rb +12 -0
  50. data/test/support/helpers.rb +33 -0
  51. data/vendor/assets/fonts/wysihtml5n/fontawesome-webfont.eot +0 -0
  52. data/vendor/assets/fonts/wysihtml5n/fontawesome-webfont.svg +255 -0
  53. data/vendor/assets/fonts/wysihtml5n/fontawesome-webfont.ttf +0 -0
  54. data/vendor/assets/fonts/wysihtml5n/fontawesome-webfont.woff +0 -0
  55. data/vendor/assets/images/wysihtml5n/Jcrop.gif +0 -0
  56. data/vendor/assets/javascripts/wysihtml5n.js +3 -0
  57. data/vendor/assets/javascripts/wysihtml5n/jcrop.js +1695 -0
  58. data/vendor/assets/javascripts/wysihtml5n/wysihtml5-0.3.0.js +9531 -0
  59. data/vendor/assets/javascripts/wysihtml5n/wysihtml5-enhanced.js +783 -0
  60. data/vendor/assets/stylesheets/wysihtml5n.css.scss +3 -0
  61. data/vendor/assets/stylesheets/wysihtml5n/_bootstrap.scss +1692 -0
  62. data/vendor/assets/stylesheets/wysihtml5n/_editor.scss +115 -0
  63. data/vendor/assets/stylesheets/wysihtml5n/_font-awesome.scss +303 -0
  64. metadata +223 -0
@@ -0,0 +1,783 @@
1
+ (function($){
2
+ "use strict";
3
+
4
+ // parser rules for editor
5
+ var parserRules = {
6
+ "classes": {
7
+ "wysiwyg-clear-both": 1,
8
+ "wysiwyg-clear-left": 1,
9
+ "wysiwyg-clear-right": 1,
10
+ "wysiwyg-float-left": 1,
11
+ "wysiwyg-float-right": 1
12
+ },
13
+ "tags": {
14
+ "tr": {
15
+ "add_class": {
16
+ "align": "align_text"
17
+ }
18
+ },
19
+ "strike": {
20
+ "remove": 1
21
+ },
22
+ "form": {
23
+ "rename_tag": "div"
24
+ },
25
+ "rt": {
26
+ "rename_tag": "span"
27
+ },
28
+ "code": {},
29
+ "acronym": {
30
+ "rename_tag": "span"
31
+ },
32
+ "br": {
33
+ "add_class": {
34
+ "clear": "clear_br"
35
+ }
36
+ },
37
+ "details": {
38
+ "rename_tag": "div"
39
+ },
40
+ "h4": {
41
+ "add_class": {
42
+ "align": "align_text"
43
+ }
44
+ },
45
+ "em": {},
46
+ "title": {
47
+ "remove": 1
48
+ },
49
+ "multicol": {
50
+ "rename_tag": "div"
51
+ },
52
+ "figure": {
53
+ "rename_tag": "div"
54
+ },
55
+ "xmp": {
56
+ "rename_tag": "span"
57
+ },
58
+ "small": {},
59
+ "area": {
60
+ "remove": 1
61
+ },
62
+ "time": {
63
+ "rename_tag": "span"
64
+ },
65
+ "dir": {
66
+ "rename_tag": "ul"
67
+ },
68
+ "bdi": {
69
+ "rename_tag": "span"
70
+ },
71
+ "command": {
72
+ "remove": 1
73
+ },
74
+ "ul": {},
75
+ "progress": {
76
+ "rename_tag": "span"
77
+ },
78
+ "dfn": {
79
+ "rename_tag": "span"
80
+ },
81
+ "iframe": {
82
+ "check_attributes": {
83
+ "src": "src",
84
+ "width": "numbers",
85
+ "height": "numbers"
86
+ }
87
+ },
88
+ "figcaption": {
89
+ "rename_tag": "div"
90
+ },
91
+ "a": {
92
+ "check_attributes": {
93
+ "href": "href"
94
+ },
95
+ "set_attributes": {
96
+ "rel": "nofollow",
97
+ "target": "_blank"
98
+ }
99
+ },
100
+ "img": {
101
+ "check_attributes": {
102
+ "width": "numbers",
103
+ "height": "numbers",
104
+ "src": "dataURI",
105
+ "alt": "alt"
106
+ },
107
+ "add_class": {
108
+ "align": "align_img"
109
+ }
110
+ },
111
+ "rb": {
112
+ "rename_tag": "span"
113
+ },
114
+ "footer": {
115
+ "rename_tag": "div"
116
+ },
117
+ "noframes": {
118
+ "remove": 1
119
+ },
120
+ "abbr": {},
121
+ "u": {
122
+ remove:1
123
+ },
124
+ "bgsound": {
125
+ "remove": 1
126
+ },
127
+ "sup": {
128
+ "rename_tag": "span"
129
+ },
130
+ "address": {
131
+ "rename_tag": "div"
132
+ },
133
+ "basefont": {
134
+ "remove": 1
135
+ },
136
+ "nav": {
137
+ "rename_tag": "div"
138
+ },
139
+ "h1": {
140
+ "add_class": {
141
+ "align": "align_text"
142
+ }
143
+ },
144
+ "head": {
145
+ "remove": 1
146
+ },
147
+ "tbody": {
148
+ "add_class": {
149
+ "align": "align_text"
150
+ }
151
+ },
152
+ "dd": {
153
+ "rename_tag": "div"
154
+ },
155
+ "s": {
156
+ "rename_tag": "span"
157
+ },
158
+ "li": {},
159
+ "td": {
160
+ "check_attributes": {
161
+ "rowspan": "numbers",
162
+ "colspan": "numbers"
163
+ },
164
+ "add_class": {
165
+ "align": "align_text"
166
+ }
167
+ },
168
+ "object": {},
169
+ "div": {
170
+ "add_class": {
171
+ "align": "align_text"
172
+ }
173
+ },
174
+ "option": {
175
+ "rename_tag": "span"
176
+ },
177
+ "select": {
178
+ "rename_tag": "span"
179
+ },
180
+ "i": {},
181
+ "track": {
182
+ "remove": 1
183
+ },
184
+ "wbr": {
185
+ "remove": 1
186
+ },
187
+ "fieldset": {
188
+ "rename_tag": "div"
189
+ },
190
+ "big": {
191
+ "rename_tag": "span",
192
+ "set_class": "wysiwyg-font-size-larger"
193
+ },
194
+ "button": {
195
+ "rename_tag": "span"
196
+ },
197
+ "noscript": {
198
+ "remove": 1
199
+ },
200
+ "svg": {
201
+ "remove": 1
202
+ },
203
+ "input": {
204
+ "remove": 1
205
+ },
206
+ "table": {},
207
+ "keygen": {
208
+ "remove": 1
209
+ },
210
+ "h5": {
211
+ "add_class": {
212
+ "align": "align_text"
213
+ }
214
+ },
215
+ "meta": {
216
+ "remove": 1
217
+ },
218
+ "map": {
219
+ "rename_tag": "div"
220
+ },
221
+ "isindex": {
222
+ "remove": 1
223
+ },
224
+ "mark": {
225
+ "rename_tag": "span"
226
+ },
227
+ "caption": {
228
+ "add_class": {
229
+ "align": "align_text"
230
+ }
231
+ },
232
+ "tfoot": {
233
+ "add_class": {
234
+ "align": "align_text"
235
+ }
236
+ },
237
+ "base": {
238
+ "remove": 1
239
+ },
240
+ "video": {
241
+ "remove": 1
242
+ },
243
+ "strong": {},
244
+ "canvas": {
245
+ "remove": 1
246
+ },
247
+ "output": {
248
+ "rename_tag": "span"
249
+ },
250
+ "marquee": {
251
+ "rename_tag": "span"
252
+ },
253
+ "b": {
254
+ "rename_tag": "strong"
255
+ },
256
+ "q": {
257
+ "check_attributes": {
258
+ "cite": "url"
259
+ }
260
+ },
261
+ "applet": {
262
+ "remove": 1
263
+ },
264
+ "span": {},
265
+ "rp": {
266
+ "rename_tag": "span"
267
+ },
268
+ "spacer": {
269
+ "remove": 1
270
+ },
271
+ "source": {
272
+ "remove": 1
273
+ },
274
+ "aside": {
275
+ "rename_tag": "div"
276
+ },
277
+ "frame": {
278
+ "remove": 1
279
+ },
280
+ "section": {
281
+ "rename_tag": "div"
282
+ },
283
+ "body": {
284
+ "rename_tag": "div"
285
+ },
286
+ "ol": {},
287
+ "nobr": {
288
+ "rename_tag": "span"
289
+ },
290
+ "html": {
291
+ "rename_tag": "div"
292
+ },
293
+ "summary": {
294
+ "rename_tag": "span"
295
+ },
296
+ "var": {
297
+ "rename_tag": "span"
298
+ },
299
+ "del": {
300
+ "remove": 1
301
+ },
302
+ "blockquote": {
303
+ "check_attributes": {
304
+ "cite": "url"
305
+ }
306
+ },
307
+ "style": {
308
+ "remove": 1
309
+ },
310
+ "device": {
311
+ "remove": 1
312
+ },
313
+ "meter": {
314
+ "rename_tag": "span"
315
+ },
316
+ "h3": {
317
+ "add_class": {
318
+ "align": "align_text"
319
+ }
320
+ },
321
+ "textarea": {
322
+ "rename_tag": "span"
323
+ },
324
+ "embed": {
325
+ "remove": 1
326
+ },
327
+ "hgroup": {
328
+ "rename_tag": "div"
329
+ },
330
+ "font": {
331
+ "rename_tag": "span",
332
+ "add_class": {
333
+ "size": "size_font"
334
+ }
335
+ },
336
+ "tt": {
337
+ "rename_tag": "span"
338
+ },
339
+ "noembed": {
340
+ "remove": 1
341
+ },
342
+ "thead": {
343
+ "add_class": {
344
+ "align": "align_text"
345
+ }
346
+ },
347
+ "blink": {
348
+ "rename_tag": "span"
349
+ },
350
+ "plaintext": {
351
+ "rename_tag": "span"
352
+ },
353
+ "xml": {
354
+ "remove": 1
355
+ },
356
+ "h6": {
357
+ "add_class": {
358
+ "align": "align_text"
359
+ }
360
+ },
361
+ "param": {},
362
+ "th": {
363
+ "check_attributes": {
364
+ "rowspan": "numbers",
365
+ "colspan": "numbers"
366
+ },
367
+ "add_class": {
368
+ "align": "align_text"
369
+ }
370
+ },
371
+ "legend": {
372
+ "rename_tag": "span"
373
+ },
374
+ "hr": {},
375
+ "label": {
376
+ "rename_tag": "span"
377
+ },
378
+ "dl": {
379
+ "rename_tag": "div"
380
+ },
381
+ "kbd": {
382
+ "rename_tag": "span"
383
+ },
384
+ "listing": {
385
+ "rename_tag": "div"
386
+ },
387
+ "dt": {
388
+ "rename_tag": "span"
389
+ },
390
+ "nextid": {
391
+ "remove": 1
392
+ },
393
+ "pre": {},
394
+ "center": {
395
+ "rename_tag": "div",
396
+ "set_class": "wysiwyg-text-align-center"
397
+ },
398
+ "audio": {
399
+ "remove": 1
400
+ },
401
+ "datalist": {
402
+ "rename_tag": "span"
403
+ },
404
+ "samp": {
405
+ "rename_tag": "span"
406
+ },
407
+ "col": {
408
+ "remove": 1
409
+ },
410
+ "article": {
411
+ "rename_tag": "div"
412
+ },
413
+ "cite": {},
414
+ "link": {
415
+ "remove": 1
416
+ },
417
+ "script": {
418
+ "remove": 1
419
+ },
420
+ "bdo": {
421
+ "rename_tag": "span"
422
+ },
423
+ "menu": {
424
+ "rename_tag": "ul"
425
+ },
426
+ "colgroup": {
427
+ "remove": 1
428
+ },
429
+ "ruby": {
430
+ "rename_tag": "span"
431
+ },
432
+ "h2": {
433
+ "add_class": {
434
+ "align": "align_text"
435
+ }
436
+ },
437
+ "ins": {
438
+ "rename_tag": "span"
439
+ },
440
+ "p": {
441
+ "add_class": {
442
+ "align": "align_text"
443
+ }
444
+ },
445
+ "sub": {
446
+ "rename_tag": "span"
447
+ },
448
+ "comment": {
449
+ "remove": 1
450
+ },
451
+ "frameset": {
452
+ "remove": 1
453
+ },
454
+ "optgroup": {
455
+ "rename_tag": "span"
456
+ },
457
+ "header": {
458
+ "rename_tag": "div"
459
+ }
460
+ }
461
+ };
462
+
463
+ /**
464
+ * Drag And Drop Image Editor. Enables a drop-able DOM elements,
465
+ * Generates an image from dropped image file and enables image cropping via Jcrop
466
+ * @param element - target drag and drop DOM element
467
+ * @param options - options for image editor
468
+ * @return {Object}
469
+ * @constructor ImageEditor
470
+ */
471
+ var ImageEditor = function(element, options){
472
+
473
+ var dataURI = null,
474
+ options = options,
475
+ jcrop_api = null,
476
+ $dom = {
477
+ $element: $(element),
478
+ $canvas: null,
479
+ $img: null,
480
+ $ctx: null,
481
+ $input: options.input
482
+ };
483
+
484
+ $dom.$element.css({
485
+ 'width':options.width,
486
+ 'height':options.height,
487
+ 'overflow':'hidden',
488
+ 'text-align':'center'
489
+ });
490
+
491
+ /**
492
+ * Bind drag and drop events to $element
493
+ */
494
+ var bindEvents = function(){
495
+
496
+ // handle No-Op events for drag and drop
497
+ var noOpEvent = function(evt){
498
+ evt.stopPropagation();
499
+ evt.preventDefault();
500
+ }
501
+
502
+ $dom.$element.on('dragenter.dropImage', noOpEvent);
503
+ $dom.$element.on('dragexit.dropImage', noOpEvent);
504
+ $dom.$element.on('dragover.dropImage', noOpEvent);
505
+ $dom.$element.on('drop.dropImage', onDrop );
506
+ }
507
+
508
+ /**
509
+ * Handle drop event on $element
510
+ * @param evt - DOM drop event (jQuery)
511
+ */
512
+ var onDrop = function( evt ){
513
+ evt.stopPropagation();
514
+ evt.preventDefault();
515
+
516
+ var files = evt.originalEvent.dataTransfer.files;
517
+ if(files.length > 0){
518
+ var reader = new FileReader();
519
+ // init the reader event handlers
520
+ reader.onload = onFileReaderLoad;
521
+ // begin the read operation
522
+ reader.readAsDataURL(files[0])
523
+ }
524
+ }
525
+
526
+ /**
527
+ * Handle file reader load event.
528
+ * Get image data from file reader
529
+ * @param evt - FileReader load event
530
+ */
531
+ var onFileReaderLoad = function( evt ){
532
+ clear();
533
+ dataURI = evt.target.result;
534
+ startImageEditor();
535
+ }
536
+
537
+ /**
538
+ * Render image to drop zone and start jCorp editor
539
+ */
540
+ var startImageEditor = function(){
541
+ $dom.$img = $('<img />').attr('src', dataURI).appendTo($dom.$element);
542
+ $dom.$input.val(dataURI);
543
+
544
+ $dom.$img.Jcrop({
545
+ onSelect:imgFromCrop,
546
+ aspectRatio: options.aspectRatio
547
+ }, function(){
548
+ jcrop_api = this;
549
+ });
550
+ }
551
+
552
+ /**
553
+ * Generate an image from crop coordinates
554
+ * @param coords
555
+ */
556
+ var imgFromCrop = function(coords){
557
+ $dom.$ctx.clearRect(0,0,$dom.$ctx.canvas.width,$dom.$ctx.canvas.height);
558
+
559
+ $dom.$canvas.attr('width',coords.w).attr('height',coords.h);
560
+ $dom.$ctx.drawImage($dom.$img[0], coords.x, coords.y, coords.w, coords.h, 0, 0, coords.w, coords.h); //sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight
561
+ dataURI = $dom.$canvas[0].toDataURL('image/jpeg');
562
+ $dom.$input.val(dataURI);
563
+ }
564
+
565
+ /**
566
+ * Clears image and saved dataURI
567
+ */
568
+ var clear = function(){
569
+ dataURI = null;
570
+ if($dom.$img !== null){
571
+ jcrop_api.destroy();
572
+ $dom.$img.remove();
573
+ $dom.$img = null;
574
+ $dom.$input.val('');
575
+ }
576
+ }
577
+
578
+ /**
579
+ * Handle editor reopen from Wysiwyg
580
+ */
581
+ var reopen = function(){
582
+ var url = $dom.$input.val();
583
+ if(url.trim() !== ''){
584
+ clear();
585
+ dataURI = url;
586
+ startImageEditor();
587
+ }
588
+ }
589
+
590
+ /**
591
+ * Initialize the drag and drop object
592
+ */
593
+ var init = function(){
594
+ $dom.$canvas = $('<canvas></canvas>').css({
595
+ display:'none'
596
+ }).appendTo($('body'));
597
+
598
+ $dom.$ctx = $dom.$canvas[0].getContext('2d');
599
+ bindEvents();
600
+ }
601
+
602
+ init(); //initialize the image editor
603
+
604
+ // revealing module pattern
605
+ // reveal clear and init methods
606
+ return {
607
+ clear: function(){
608
+ clear();
609
+ },
610
+ reopen: function(){
611
+ reopen();
612
+ }
613
+ }
614
+ }
615
+
616
+ ImageEditor.prototype = {
617
+ constructor: ImageEditor,
618
+ $dataURI: null,
619
+ $img: null
620
+ }
621
+
622
+ /**
623
+ * Bootstrap and Drag & Drop enabled wysihtml editor
624
+ * @param textarea - textarea DOM element to turn into WYSIWYG editor
625
+ * @param options - editor and drag & drop options
626
+ * @constructor WysiHTML5
627
+ */
628
+ var WysiHTML5N = function(textarea, options){
629
+
630
+ // define editor toolbar HTML components
631
+ var toolbar = {
632
+ h1: '<li data-wysihtml5-command="formatBlock" data-wysihtml5-command-value="h1" title="Insert headline 1" class="command btn">H1</li>',
633
+ h2: '<li data-wysihtml5-command="formatBlock" data-wysihtml5-command-value="h2" title="Insert headline 2" class="command btn">H2</li>',
634
+ h3: '<li data-wysihtml5-command="formatBlock" data-wysihtml5-command-value="h3" title="Insert headline 3" class="command btn">H3</li>',
635
+ p: '<li data-wysihtml5-command="formatBlock" data-wysihtml5-command-value="p" title="Insert paragraph" class="command btn">P</li>',
636
+ bold: '<li data-wysihtml5-command="bold" title="Make text bold (CTRL + B)" class="command btn"><i class="icon-bold"></i></li>',
637
+ italic: '<li data-wysihtml5-command="italic" title="Make text italic (CTRL + I)" class="command btn"><i class="icon-italic"></i></li>',
638
+ ol: '<li data-wysihtml5-command="insertOrderedList" title="Insert an ordered list" class="command btn"><i class="icon-list-ol"></i></li>',
639
+ ul: '<li data-wysihtml5-command="insertUnorderedList" title="Insert an unordered list" class="command btn"><i class="icon-list-ul"></i></li>',
640
+ insertLink: '<li data-wysihtml5-command="createLink" title="Insert a link" class="command btn"><i class="icon-link"></i></li>',
641
+ insertImage: '<li data-wysihtml5-command="insertImage" title="Insert an image" class="command btn"><i class="icon-picture"></i></li>',
642
+ changeView: '<li data-wysihtml5-action="change_view" title="Show HTML" class="action btn">&lt;/&gt;</li>',
643
+ modals: {
644
+ insertLink:'<div class="modal" data-wysihtml5-dialog="createLink" style="display: none;">' +
645
+ '<div class="modal-header">' +
646
+ '<button type="button" class="close" data-wysihtml5-dialog-action="cancel" data-dismiss="modal">×</button>' +
647
+ '<h3>Insert Link</h3>' +
648
+ '</div>' +
649
+ '<div class="modal-body">' +
650
+ '<label>Link: <input data-wysihtml5-dialog-field="href" type="url" class="input-xlarge" placeholder="http://"></label>' +
651
+ '</div>' +
652
+ '<div class="modal-footer">' +
653
+ '<a class="btn btn-primary" data-wysihtml5-dialog-action="save">OK</a>' +
654
+ '<a class="btn" data-wysihtml5-dialog-action="cancel" data-dismiss="modal">Cancel</a>' +
655
+ '</div>' +
656
+ '</div>',
657
+ insertImage:'<div class="modal" data-wysihtml5-dialog="insertImage" style="display: none;">' +
658
+ '<div class="modal-header">' +
659
+ '<button type="button" class="close" data-wysihtml5-dialog-action="cancel" data-dismiss="modal">×</button>' +
660
+ '<h3>Insert Image</h3>' +
661
+ '</div>' +
662
+ '<div class="modal-body">' +
663
+ '<div class="drop-image"></div>' +
664
+ '<input data-wysihtml5-dialog-field="src" class="image-src-field" type="hidden" />' +
665
+ '</div>' +
666
+ '<div class="modal-footer">' +
667
+ '<a class="btn btn-primary" data-wysihtml5-dialog-action="save" class="save-image">OK</a>' +
668
+ '<a class="btn" data-wysihtml5-dialog-action="cancel" data-dismiss="modal">Cancel</a>' +
669
+ '</div>' +
670
+ '</div>'
671
+ }
672
+ };
673
+
674
+ var imageEditor,
675
+ textEditor,
676
+ $dom = {
677
+ $textarea: $(textarea),
678
+ $toolbar: null
679
+ };
680
+
681
+ /**
682
+ * Build the toolbar and append before textarea
683
+ */
684
+ var buildToolbar = function(){
685
+ var toolbarHTML = ['<ul class="btn-group">'];
686
+ var modals = [];
687
+
688
+ options.toolbar.forEach(function(key){
689
+ if(toolbar[key]){
690
+ toolbarHTML.push(toolbar[key]);
691
+ }
692
+ if(toolbar.modals[key]){
693
+ modals.push(toolbar.modals[key]);
694
+ }
695
+ });
696
+
697
+ toolbarHTML.push('</ul>');
698
+
699
+ $dom.$toolbar = $('<div class="wysiHTML5-toolbar"></div>').html(toolbarHTML.concat(modals).join('')).insertBefore($dom.$textarea);
700
+ }
701
+
702
+ /**
703
+ * Initialize the WysiHTML5 Editor
704
+ */
705
+ var initEditor = function(){
706
+ textEditor = new wysihtml5.Editor($dom.$textarea[0], {
707
+ toolbar: $dom.$toolbar[0],
708
+ stylesheets: options.stylesheets,
709
+ parserRules: options.parserRules
710
+ });
711
+
712
+ if(options.toolbar.indexOf('insertImage') > -1){
713
+ initImageEditor();
714
+ }
715
+ }
716
+
717
+ /**
718
+ * Initialize the image editor for the Wysiwyg
719
+ */
720
+ var initImageEditor = function(){
721
+ var el = $dom.$toolbar.find('.drop-image');
722
+ var opts = $.extend({input: $dom.$toolbar.find('input.image-src-field')}, options.imageEditor);
723
+ imageEditor = new ImageEditor(el, opts);
724
+
725
+ // clear image editor on insertImage event
726
+ $dom.$toolbar.find('[data-wysihtml5-command="insertImage"]').click(function(){
727
+ imageEditor.clear();
728
+ });
729
+
730
+ textEditor.on('show:dialog', function(options){
731
+ if(options.command === 'insertImage'){
732
+ imageEditor.reopen();
733
+ }
734
+ }).on('cancel:dialog', function(options){
735
+ if(options.command === 'insertImage'){
736
+ imageEditor.clear();
737
+ }
738
+ });
739
+ }
740
+
741
+ /**
742
+ * Initialize the editor plugin
743
+ */
744
+ function init(){
745
+ buildToolbar();
746
+ initEditor();
747
+ }
748
+
749
+ init(); //initialize instance
750
+ }
751
+
752
+ WysiHTML5N.prototype = {
753
+ constructor: WysiHTML5N
754
+ }
755
+
756
+ $.fn.wysiHTML5N = function(option){
757
+ return this.each(function () {
758
+ var $this = $(this),
759
+ data = $this.data('wysiHTML5N'),
760
+ options = $.extend({}, $.fn.wysiHTML5N.defaults, typeof option == 'object' && option);
761
+ if (!data){
762
+ $this.data('wysiHTML5N', (data = new WysiHTML5N(this, options)))
763
+ }
764
+ if (typeof option == 'string'){
765
+ data[option]();
766
+ }
767
+ });
768
+ }
769
+
770
+ $.fn.wysiHTML5N.defaults = {
771
+ toolbar: [
772
+ 'h1', 'h2', 'h3', 'p', 'bold', 'italic', 'unordered', 'ordered', 'insertLink', 'insertImage', 'changeView'
773
+ ],
774
+ stylesheets: [],
775
+ parserRules: parserRules,
776
+ imageEditor: {
777
+ aspectRatio:null,
778
+ width:530,
779
+ height:300
780
+ }
781
+ }
782
+
783
+ }(window.jQuery));