wysibb 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3026 @@
1
+ /*! WysiBB v1.5.1 2014-03-26
2
+ Author: Vadim Dobroskok
3
+ */
4
+ if (typeof (WBBLANG)=="undefined") {WBBLANG = {};}
5
+ WBBLANG['en'] = CURLANG = {
6
+ bold: "Bold",
7
+ italic: "Italic",
8
+ underline: "Underline",
9
+ strike: "Strike",
10
+ link: "Link",
11
+ img: "Insert image",
12
+ sup: "Superscript",
13
+ sub: "Subscript",
14
+ justifyleft: "Align left",
15
+ justifycenter: "Align center",
16
+ justifyright: "Align right",
17
+ table: "Insert table",
18
+ bullist: "• Unordered list",
19
+ numlist: "1. Ordered list",
20
+ quote: "Quote",
21
+ offtop: "Offtop",
22
+ code: "Code",
23
+ spoiler: "Spoiler",
24
+ fontcolor: "Font color",
25
+ fontsize: "Font size",
26
+ fontfamily: "Font family",
27
+ fs_verysmall: "Very small",
28
+ fs_small: "Small",
29
+ fs_normal: "Normal",
30
+ fs_big: "Big",
31
+ fs_verybig: "Very big",
32
+ smilebox: "Insert emoticon",
33
+ video: "Insert YouTube",
34
+ removeFormat:"Remove Format",
35
+
36
+ modal_link_title: "Insert link",
37
+ modal_link_text: "Display text",
38
+ modal_link_url: "URL",
39
+ modal_email_text: "Display email",
40
+ modal_email_url: "Email",
41
+ modal_link_tab1: "Insert URL",
42
+
43
+ modal_img_title: "Insert image",
44
+ modal_img_tab1: "Insert URL",
45
+ modal_img_tab2: "Upload image",
46
+ modal_imgsrc_text: "Enter image URL",
47
+ modal_img_btn: "Choose file",
48
+ add_attach: "Add Attachment",
49
+
50
+ modal_video_text: "Enter the URL of the video",
51
+
52
+ close: "Close",
53
+ save: "Save",
54
+ cancel: "Cancel",
55
+ remove: "Delete",
56
+
57
+ validation_err: "The entered data is invalid",
58
+ error_onupload: "Error during file upload",
59
+
60
+ fileupload_text1: "Drop file here",
61
+ fileupload_text2: "or",
62
+
63
+ loading: "Loading",
64
+ auto: "Auto",
65
+ views: "Views",
66
+ downloads: "Downloads",
67
+
68
+ //smiles
69
+ sm1: "Smile",
70
+ sm2: "Laughter",
71
+ sm3: "Wink",
72
+ sm4: "Thank you",
73
+ sm5: "Scold",
74
+ sm6: "Shock",
75
+ sm7: "Angry",
76
+ sm8: "Pain",
77
+ sm9: "Sick"
78
+ };
79
+ wbbdebug=true;
80
+ (function($) {
81
+ 'use strict';
82
+ $.wysibb = function(txtArea,settings) {
83
+ $(txtArea).data("wbb",this);
84
+
85
+ if (settings && settings.deflang && typeof(WBBLANG[settings.deflang])!="undefined") {CURLANG = WBBLANG[settings.deflang];}
86
+ if (settings && settings.lang && typeof(WBBLANG[settings.lang])!="undefined") {CURLANG = WBBLANG[settings.lang];}
87
+ this.txtArea=txtArea;
88
+ this.$txtArea=$(txtArea);
89
+ var id = this.$txtArea.attr("id") || this.setUID(this.txtArea);
90
+ this.options = {
91
+ bbmode: false,
92
+ onlyBBmode: false,
93
+ themeName: "default",
94
+ bodyClass: "",
95
+ lang: "ru",
96
+ tabInsert: true,
97
+ // toolbar: false,
98
+ //img upload config
99
+ imgupload: false,
100
+ img_uploadurl: "/iupload.php",
101
+ img_maxwidth: 800,
102
+ img_maxheight: 800,
103
+ hotkeys: true,
104
+ showHotkeys: true,
105
+ autoresize: true,
106
+ resize_maxheight: 800,
107
+ loadPageStyles: true,
108
+ traceTextarea: true,
109
+ // direction: "ltr",
110
+ smileConversion: true,
111
+
112
+ //END img upload config
113
+ buttons: "bold,italic,underline,strike,sup,sub,|,img,video,link,|,bullist,numlist,|,fontcolor,fontsize,fontfamily,|,justifyleft,justifycenter,justifyright,|,quote,code,table,removeFormat",
114
+ allButtons: {
115
+ bold : {
116
+ title: CURLANG.bold,
117
+ buttonHTML: '<span class="fonticon ve-tlb-bold1">\uE018</span>',
118
+ excmd: 'bold',
119
+ hotkey: 'ctrl+b',
120
+ transform : {
121
+ '<b>{SELTEXT}</b>':"[b]{SELTEXT}[/b]",
122
+ '<strong>{SELTEXT}</strong>':"[b]{SELTEXT}[/b]"
123
+ }
124
+ },
125
+ italic : {
126
+ title: CURLANG.italic,
127
+ buttonHTML: '<span class="fonticon ve-tlb-italic1">\uE001</span>',
128
+ excmd: 'italic',
129
+ hotkey: 'ctrl+i',
130
+ transform : {
131
+ '<i>{SELTEXT}</i>':"[i]{SELTEXT}[/i]",
132
+ '<em>{SELTEXT}</em>':"[i]{SELTEXT}[/i]"
133
+ }
134
+ },
135
+ underline : {
136
+ title: CURLANG.underline,
137
+ buttonHTML: '<span class="fonticon ve-tlb-underline1">\uE002</span>',
138
+ excmd: 'underline',
139
+ hotkey: 'ctrl+u',
140
+ transform : {
141
+ '<u>{SELTEXT}</u>':"[u]{SELTEXT}[/u]"
142
+ }
143
+ },
144
+ strike : {
145
+ title: CURLANG.strike,
146
+ buttonHTML: '<span class="fonticon fi-stroke1 ve-tlb-strike1">\uE003</span>',
147
+ excmd: 'strikeThrough',
148
+ transform : {
149
+ '<strike>{SELTEXT}</strike>':"[s]{SELTEXT}[/s]",
150
+ '<s>{SELTEXT}</s>':"[s]{SELTEXT}[/s]"
151
+ }
152
+ },
153
+ sup : {
154
+ title: CURLANG.sup,
155
+ buttonHTML: '<span class="fonticon ve-tlb-sup1">\uE005</span>',
156
+ excmd: 'superscript',
157
+ transform : {
158
+ '<sup>{SELTEXT}</sup>':"[sup]{SELTEXT}[/sup]"
159
+ }
160
+ },
161
+ sub : {
162
+ title: CURLANG.sub,
163
+ buttonHTML: '<span class="fonticon ve-tlb-sub1">\uE004</span>',
164
+ excmd: 'subscript',
165
+ transform : {
166
+ '<sub>{SELTEXT}</sub>':"[sub]{SELTEXT}[/sub]"
167
+ }
168
+ },
169
+ link : {
170
+ title: CURLANG.link,
171
+ buttonHTML: '<span class="fonticon ve-tlb-link1">\uE007</span>',
172
+ hotkey: 'ctrl+shift+2',
173
+ modal: {
174
+ title: CURLANG.modal_link_title,
175
+ width: "500px",
176
+ tabs: [
177
+ {
178
+ input: [
179
+ {param: "SELTEXT",title:CURLANG.modal_link_text, type: "div"},
180
+ {param: "URL",title:CURLANG.modal_link_url,validation: '^http(s)?://'}
181
+ ]
182
+ }
183
+ ]
184
+ },
185
+ transform : {
186
+ '<a href="{URL}">{SELTEXT}</a>':"[url={URL}]{SELTEXT}[/url]",
187
+ '<a href="{URL}">{URL}</a>':"[url]{URL}[/url]"
188
+ }
189
+ },
190
+ img : {
191
+ title: CURLANG.img,
192
+ buttonHTML: '<span class="fonticon ve-tlb-img1">\uE006</span>',
193
+ hotkey: 'ctrl+shift+1',
194
+ addWrap: true,
195
+ modal: {
196
+ title: CURLANG.modal_img_title,
197
+ width: "600px",
198
+ tabs: [
199
+ {
200
+ title: CURLANG.modal_img_tab1,
201
+ input: [
202
+ {param: "SRC",title:CURLANG.modal_imgsrc_text,validation: '^http(s)?://.*?\.(jpg|png|gif|jpeg)$'}
203
+ ]
204
+ }
205
+ ],
206
+ onLoad: this.imgLoadModal
207
+ },
208
+ transform : {
209
+ '<img src="{SRC}" />':"[img]{SRC}[/img]",
210
+ '<img src="{SRC}" width="{WIDTH}" height="{HEIGHT}"/>':"[img width={WIDTH},height={HEIGHT}]{SRC}[/img]"
211
+ }
212
+ },
213
+ bullist : {
214
+ title: CURLANG.bullist,
215
+ buttonHTML: '<span class="fonticon ve-tlb-list1">\uE009</span>',
216
+ excmd: 'insertUnorderedList',
217
+ transform : {
218
+ '<ul>{SELTEXT}</ul>':"[list]{SELTEXT}[/list]",
219
+ '<li>{SELTEXT}</li>':"[*]{SELTEXT}[/*]"
220
+ }
221
+ },
222
+ numlist : {
223
+ title: CURLANG.numlist,
224
+ buttonHTML: '<span class="fonticon ve-tlb-numlist1">\uE00a</span>',
225
+ excmd: 'insertOrderedList',
226
+ transform : {
227
+ '<ol>{SELTEXT}</ol>':"[list=1]{SELTEXT}[/list]",
228
+ '<li>{SELTEXT}</li>':"[*]{SELTEXT}[/*]"
229
+ }
230
+ },
231
+ quote : {
232
+ title: CURLANG.quote,
233
+ buttonHTML: '<span class="fonticon ve-tlb-quote1">\uE00c</span>',
234
+ hotkey: 'ctrl+shift+3',
235
+ //subInsert: true,
236
+ transform : {
237
+ '<blockquote>{SELTEXT}</blockquote>':"[quote]{SELTEXT}[/quote]"
238
+ }
239
+ },
240
+ code : {
241
+ title: CURLANG.code,
242
+ buttonText: '[code]',
243
+ /* buttonHTML: '<span class="fonticon">\uE00d</span>', */
244
+ hotkey: 'ctrl+shift+4',
245
+ onlyClearText: true,
246
+ transform : {
247
+ '<code>{SELTEXT}</code>':"[code]{SELTEXT}[/code]"
248
+ }
249
+ },
250
+ offtop : {
251
+ title: CURLANG.offtop,
252
+ buttonText: 'offtop',
253
+ transform : {
254
+ '<span style="font-size:10px;color:#ccc">{SELTEXT}</span>':"[offtop]{SELTEXT}[/offtop]"
255
+ }
256
+ },
257
+ fontcolor: {
258
+ type: "colorpicker",
259
+ title: CURLANG.fontcolor,
260
+ excmd: "foreColor",
261
+ valueBBname: "color",
262
+ subInsert: true,
263
+ colors: "#000000,#444444,#666666,#999999,#b6b6b6,#cccccc,#d8d8d8,#efefef,#f4f4f4,#ffffff,-, \
264
+ #ff0000,#980000,#ff7700,#ffff00,#00ff00,#00ffff,#1e84cc,#0000ff,#9900ff,#ff00ff,-, \
265
+ #f4cccc,#dbb0a7,#fce5cd,#fff2cc,#d9ead3,#d0e0e3,#c9daf8,#cfe2f3,#d9d2e9,#ead1dc, \
266
+ #ea9999,#dd7e6b,#f9cb9c,#ffe599,#b6d7a8,#a2c4c9,#a4c2f4,#9fc5e8,#b4a7d6,#d5a6bd, \
267
+ #e06666,#cc4125,#f6b26b,#ffd966,#93c47d,#76a5af,#6d9eeb,#6fa8dc,#8e7cc3,#c27ba0, \
268
+ #cc0000,#a61c00,#e69138,#f1c232,#6aa84f,#45818e,#3c78d8,#3d85c6,#674ea7,#a64d79, \
269
+ #900000,#85200C,#B45F06,#BF9000,#38761D,#134F5C,#1155Cc,#0B5394,#351C75,#741B47, \
270
+ #660000,#5B0F00,#783F04,#7F6000,#274E13,#0C343D,#1C4587,#073763,#20124D,#4C1130",
271
+ transform: {
272
+ '<font color="{COLOR}">{SELTEXT}</font>':'[color={COLOR}]{SELTEXT}[/color]'
273
+ }
274
+ },
275
+ table: {
276
+ type: "table",
277
+ title: CURLANG.table,
278
+ cols: 10,
279
+ rows: 10,
280
+ cellwidth: 20,
281
+ transform: {
282
+ '<td>{SELTEXT}</td>': '[td]{SELTEXT}[/td]',
283
+ '<tr>{SELTEXT}</tr>': '[tr]{SELTEXT}[/tr]',
284
+ '<table class="wbb-table">{SELTEXT}</table>': '[table]{SELTEXT}[/table]'
285
+ },
286
+ skipRules: true
287
+ },
288
+ fontsize: {
289
+ type: 'select',
290
+ title: CURLANG.fontsize,
291
+ options: "fs_verysmall,fs_small,fs_normal,fs_big,fs_verybig"
292
+ },
293
+ fontfamily: {
294
+ type: 'select',
295
+ title: CURLANG.fontfamily,
296
+ excmd: 'fontName',
297
+ valueBBname: "font",
298
+ options: [
299
+ {title: "Arial",exvalue: "Arial"},
300
+ {title: "Comic Sans MS",exvalue: "Comic Sans MS"},
301
+ {title: "Courier New",exvalue: "Courier New"},
302
+ {title: "Georgia",exvalue: "Georgia"},
303
+ {title: "Lucida Sans Unicode",exvalue: "Lucida Sans Unicode"},
304
+ {title: "Tahoma",exvalue: "Tahoma"},
305
+ {title: "Times New Roman",exvalue: "Times New Roman"},
306
+ {title: "Trebuchet MS",exvalue: "Trebuchet MS"},
307
+ {title: "Verdana",exvalue: "Verdana"}
308
+ ],
309
+ transform: {
310
+ '<font face="{FONT}">{SELTEXT}</font>':'[font={FONT}]{SELTEXT}[/font]'
311
+ }
312
+ },
313
+ smilebox: {
314
+ type: 'smilebox',
315
+ title: CURLANG.smilebox,
316
+ buttonHTML: '<span class="fonticon ve-tlb-smilebox1">\uE00b</span>'
317
+ },
318
+ justifyleft: {
319
+ title: CURLANG.justifyleft,
320
+ buttonHTML: '<span class="fonticon ve-tlb-textleft1">\uE015</span>',
321
+ groupkey: 'align',
322
+ transform: {
323
+ '<p style="text-align:left">{SELTEXT}</p>': '[left]{SELTEXT}[/left]'
324
+ }
325
+ },
326
+ justifyright: {
327
+ title: CURLANG.justifyright,
328
+ buttonHTML: '<span class="fonticon ve-tlb-textright1">\uE016</span>',
329
+ groupkey: 'align',
330
+ transform: {
331
+ '<p style="text-align:right">{SELTEXT}</p>': '[right]{SELTEXT}[/right]'
332
+ }
333
+ },
334
+ justifycenter: {
335
+ title: CURLANG.justifycenter,
336
+ buttonHTML: '<span class="fonticon ve-tlb-textcenter1">\uE014</span>',
337
+ groupkey: 'align',
338
+ transform: {
339
+ '<p style="text-align:center">{SELTEXT}</p>': '[center]{SELTEXT}[/center]'
340
+ }
341
+ },
342
+ video: {
343
+ title: CURLANG.video,
344
+ buttonHTML: '<span class="fonticon ve-tlb-video1">\uE008</span>',
345
+ modal: {
346
+ title: CURLANG.video,
347
+ width: "600px",
348
+ tabs: [
349
+ {
350
+ title: CURLANG.video,
351
+ input: [
352
+ {param: "SRC",title:CURLANG.modal_video_text}
353
+ ]
354
+ }
355
+ ],
356
+ onSubmit: function(cmd,opt,queryState) {
357
+ var url = this.$modal.find('input[name="SRC"]').val();
358
+ if (url) {
359
+ url = url.replace(/^\s+/,"").replace(/\s+$/,"");
360
+ }
361
+ var a;
362
+ if (url.indexOf("youtu.be")!=-1) {
363
+ a = url.match(/^http[s]*:\/\/youtu\.be\/([a-z0-9_-]+)/i);
364
+ }else{
365
+ a = url.match(/^http[s]*:\/\/www\.youtube\.com\/watch\?.*?v=([a-z0-9_-]+)/i);
366
+ }
367
+ if (a && a.length==2) {
368
+ var code = a[1];
369
+ this.insertAtCursor(this.getCodeByCommand(cmd,{src:code}));
370
+ }
371
+ this.closeModal();
372
+ this.updateUI();
373
+ return false;
374
+ }
375
+ },
376
+ transform: {
377
+ '<iframe src="http://www.youtube.com/embed/{SRC}" width="640" height="480" frameborder="0"></iframe>':'[video]{SRC}[/video]'
378
+ }
379
+ },
380
+
381
+ //select options
382
+ fs_verysmall: {
383
+ title: CURLANG.fs_verysmall,
384
+ buttonText: "fs1",
385
+ excmd: 'fontSize',
386
+ exvalue: "1",
387
+ transform: {
388
+ '<font size="1">{SELTEXT}</font>':'[size=50]{SELTEXT}[/size]'
389
+ }
390
+ },
391
+ fs_small: {
392
+ title: CURLANG.fs_small,
393
+ buttonText: "fs2",
394
+ excmd: 'fontSize',
395
+ exvalue: "2",
396
+ transform: {
397
+ '<font size="2">{SELTEXT}</font>':'[size=85]{SELTEXT}[/size]'
398
+ }
399
+ },
400
+ fs_normal: {
401
+ title: CURLANG.fs_normal,
402
+ buttonText: "fs3",
403
+ excmd: 'fontSize',
404
+ exvalue: "3",
405
+ transform: {
406
+ '<font size="3">{SELTEXT}</font>':'[size=100]{SELTEXT}[/size]'
407
+ }
408
+ },
409
+ fs_big: {
410
+ title: CURLANG.fs_big,
411
+ buttonText: "fs4",
412
+ excmd: 'fontSize',
413
+ exvalue: "4",
414
+ transform: {
415
+ '<font size="4">{SELTEXT}</font>':'[size=150]{SELTEXT}[/size]'
416
+ }
417
+ },
418
+ fs_verybig: {
419
+ title: CURLANG.fs_verybig,
420
+ buttonText: "fs5",
421
+ excmd: 'fontSize',
422
+ exvalue: "6",
423
+ transform: {
424
+ '<font size="6">{SELTEXT}</font>':'[size=200]{SELTEXT}[/size]'
425
+ }
426
+ },
427
+
428
+ removeformat: {
429
+ title: CURLANG.removeFormat,
430
+ buttonHTML: '<span class="fonticon ve-tlb-removeformat1">\uE00f</span>',
431
+ excmd: "removeFormat"
432
+ }
433
+ },
434
+ systr: {
435
+ '<br/>':"\n",
436
+ '<span class="wbbtab">{SELTEXT}</span>': ' {SELTEXT}'
437
+ },
438
+ customRules: {
439
+ td: [["[td]{SELTEXT}[/td]",{seltext: {rgx:false,attr:false,sel:false}}]],
440
+ tr: [["[tr]{SELTEXT}[/tr]",{seltext: {rgx:false,attr:false,sel:false}}]],
441
+ table: [["[table]{SELTEXT}[/table]",{seltext: {rgx:false,attr:false,sel:false}}]]
442
+ //blockquote: [[" {SELTEXT}",{seltext: {rgx:false,attr:false,sel:false}}]]
443
+ },
444
+ smileList: [
445
+ //{title:CURLANG.sm1, img: '<img src="{themePrefix}{themeName}/img/smiles/sm1.png" class="sm">', bbcode:":)"},
446
+ ],
447
+ attrWrap: ['src','color','href'] //use becouse FF and IE change values for this attr, modify [attr] to _[attr]
448
+ }
449
+
450
+ //FIX for Opera. Wait while iframe loaded
451
+ this.inited=this.options.onlyBBmode;
452
+
453
+ //init css prefix, if not set
454
+ if (!this.options.themePrefix) {
455
+ $('link').each($.proxy(function(idx, el) {
456
+ var sriptMatch = $(el).get(0).href.match(/(.*\/)(.*)\/wbbtheme\.css.*$/);
457
+ if (sriptMatch !== null) {
458
+ this.options.themeName = sriptMatch[2];
459
+ this.options.themePrefix = sriptMatch[1];
460
+ }
461
+ },this));
462
+ }
463
+
464
+ //check for preset
465
+ if (typeof(WBBPRESET)!="undefined") {
466
+ if (WBBPRESET.allButtons) {
467
+ //clear transform
468
+ $.each(WBBPRESET.allButtons,$.proxy(function(k,v) {
469
+ if (v.transform && this.options.allButtons[k]) {
470
+ delete this.options.allButtons[k].transform;
471
+ }
472
+ },this));
473
+ }
474
+ $.extend(true,this.options,WBBPRESET);
475
+ }
476
+
477
+ if (settings && settings.allButtons) {
478
+ $.each(settings.allButtons,$.proxy(function(k,v) {
479
+ if (v.transform && this.options.allButtons[k]) {
480
+ delete this.options.allButtons[k].transform;
481
+ }
482
+ },this));
483
+ }
484
+ $.extend(true,this.options,settings);
485
+ this.init();
486
+ }
487
+
488
+ $.wysibb.prototype = {
489
+ lastid : 1,
490
+ init: function() {
491
+ $.log("Init",this);
492
+ //check for mobile
493
+ this.isMobile = function(a) {(/android|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|meego.+mobile|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a))}(navigator.userAgent||navigator.vendor||window.opera);
494
+
495
+ //use bbmode on mobile devices
496
+ //this.isMobile = true; //TEMP
497
+ if (this.options.onlyBBmode===true) {this.options.bbmode=true;}
498
+ //create array of controls, for queryState
499
+ this.controllers = [];
500
+
501
+ //convert button string to array
502
+ this.options.buttons = this.options.buttons.toLowerCase();
503
+ this.options.buttons = this.options.buttons.split(",");
504
+
505
+ //init system transforms
506
+ this.options.allButtons["_systr"] = {};
507
+ this.options.allButtons["_systr"]["transform"]= this.options.systr;
508
+
509
+ this.smileFind();
510
+ this.initTransforms();
511
+ this.build();
512
+ this.initModal();
513
+ if (this.options.hotkeys===true && !this.isMobile) {
514
+ this.initHotkeys();
515
+ }
516
+
517
+ //sort smiles
518
+ if (this.options.smileList && this.options.smileList.length>0) {
519
+ this.options.smileList.sort(function(a,b) {
520
+ return (b.bbcode.length-a.bbcode.length);
521
+ })
522
+ }
523
+
524
+ this.$txtArea.parents("form").bind("submit",$.proxy(function() {
525
+ this.sync();
526
+ return true;
527
+ },this));
528
+
529
+
530
+ //phpbb2
531
+ this.$txtArea.parents("form").find("input[id*='preview'],input[id*='submit'],input[class*='preview'],input[class*='submit'],input[name*='preview'],input[name*='submit']").bind("mousedown",$.proxy(function() {
532
+ this.sync();
533
+ setTimeout($.proxy(function() {
534
+ if (this.options.bbmode===false) {
535
+ this.$txtArea.removeAttr("wbbsync").val("");
536
+ }
537
+ },this),1000);
538
+ },this));
539
+ //end phpbb2
540
+
541
+ if (this.options.initCallback) {
542
+ this.options.initCallback.call(this);
543
+ }
544
+
545
+ $.log(this);
546
+
547
+ },
548
+ initTransforms: function() {
549
+ $.log("Create rules for transform HTML=>BB");
550
+ var o = this.options;
551
+ //need to check for active buttons
552
+ if (!o.rules) {o.rules={};}
553
+ if (!o.groups) {o.groups={};} //use for groupkey, For example: justifyleft,justifyright,justifycenter. It is must replace each other.
554
+ var btnlist = o.buttons.slice();
555
+
556
+ //add system transform
557
+ btnlist.push("_systr");
558
+ for (var bidx=0; bidx<btnlist.length; bidx++) {
559
+ var ob = o.allButtons[btnlist[bidx]];
560
+ if (!ob ) {continue;}
561
+ ob.en=true;
562
+
563
+ //check for simplebbcode
564
+ if (ob.simplebbcode && $.isArray(ob.simplebbcode) && ob.simplebbcode.length==2) {
565
+ ob.bbcode = ob.html = ob.simplebbcode[0]+"{SELTEXT}"+ob.simplebbcode[1];
566
+ if (ob.transform) delete ob.transform;
567
+ if (ob.modal) delete ob.modal;
568
+ }
569
+
570
+ //add transforms to option list
571
+ if (ob.type=="select" && typeof(ob.options)=="string") {
572
+ var olist = ob.options.split(",");
573
+ $.each(olist,function(i,op) {
574
+ if ($.inArray(op,btnlist)==-1) {
575
+ btnlist.push(op);
576
+ }
577
+ });
578
+ }
579
+ if (ob.transform && ob.skipRules!==true) {
580
+ var obtr = $.extend({},ob.transform);
581
+
582
+ /* if (ob.addWrap) {
583
+ //addWrap
584
+ $.log("needWrap");
585
+ for (var bhtml in obtr) {
586
+ var bbcode = ob.transform[bhtml];
587
+ var newhtml = '<span wbb="'+btnlist[bidx]+'">'+bhtml+'</span>';
588
+ obtr[newhtml] = bbcode;
589
+ }
590
+ } */
591
+
592
+ for (var bhtml in obtr) {
593
+ var orightml = bhtml;
594
+ var bbcode = obtr[bhtml];
595
+
596
+ //create root selector for isContain bbmode
597
+ if (!ob.bbSelector) {ob.bbSelector=[];}
598
+ if ($.inArray(bbcode,ob.bbSelector)==-1) {
599
+ ob.bbSelector.push(bbcode);
600
+ }
601
+ if (this.options.onlyBBmode===false) {
602
+
603
+ //wrap attributes
604
+ bhtml = this.wrapAttrs(bhtml);
605
+
606
+
607
+ var $bel = $(document.createElement('DIV')).append($(this.elFromString(bhtml,document)));
608
+ var rootSelector = this.filterByNode($bel.children());
609
+
610
+
611
+ //check if current rootSelector is exist, create unique selector for each transform (1.2.2)
612
+ if (rootSelector=="div" || typeof(o.rules[rootSelector])!="undefined") {
613
+ //create unique selector
614
+ $.log("create unique selector: "+rootSelector);
615
+ this.setUID($bel.children());
616
+ rootSelector = this.filterByNode($bel.children());
617
+ $.log("New rootSelector: "+rootSelector);
618
+ //replace transform with unique selector
619
+ var nhtml2 = $bel.html();
620
+ nhtml2 = this.unwrapAttrs(nhtml2);
621
+ var obhtml = this.unwrapAttrs(bhtml);
622
+
623
+
624
+ ob.transform[nhtml2]=bbcode;
625
+ delete ob.transform[obhtml];
626
+
627
+ bhtml=nhtml2;
628
+ orightml = nhtml2;
629
+ }
630
+
631
+ //create root selector for isContain
632
+ if (!ob.excmd) {
633
+ if (!ob.rootSelector) {ob.rootSelector=[];}
634
+ ob.rootSelector.push(rootSelector);
635
+ }
636
+
637
+ //check for rules on this rootSeletor
638
+ if (typeof(o.rules[rootSelector])=="undefined") {
639
+ o.rules[rootSelector]=[];
640
+ }
641
+ var crules={};
642
+
643
+ if (bhtml.match(/\{\S+?\}/)) {
644
+ $bel.find('*').each($.proxy(function(idx,el) {
645
+ //check attributes
646
+
647
+ var attributes = this.getAttributeList(el);
648
+ $.each(attributes,$.proxy(function(i, item) {
649
+ var attr = $(el).attr(item);
650
+ if (item.substr(0,1)=='_') {
651
+ item = item.substr(1);
652
+ }
653
+
654
+ var r = attr.match(/\{\S+?\}/g);
655
+ if (r) {
656
+ for (var a=0; a<r.length; a++) {
657
+ var rname = r[a].substr(1,r[a].length-2);
658
+ rname = rname.replace(this.getValidationRGX(rname),"");
659
+ var p = this.relFilterByNode(el,rootSelector);
660
+ var regRepl = (attr!=r[a]) ? this.getRegexpReplace(attr,r[a]):false;
661
+ crules[rname.toLowerCase()]={sel:(p) ? $.trim(p):false,attr:item,rgx:regRepl}
662
+ }
663
+ }
664
+ },this));
665
+
666
+ //check for text
667
+ var sl=[];
668
+ if (!$(el).is("iframe")) {
669
+ $(el).contents().filter(function() {return this.nodeType===3}).each($.proxy(function(i,rel) {
670
+ var txt = rel.textContent || rel.data;
671
+ if (typeof(txt)=="undefined") {return true;}
672
+ var r = txt.match(/\{\S+?\}/g)
673
+ if (r) {
674
+ for (var a=0; a<r.length; a++) {
675
+ var rname = r[a].substr(1,r[a].length-2);
676
+ rname = rname.replace(this.getValidationRGX(rname),"");
677
+ var p = this.relFilterByNode(el,rootSelector);
678
+ var regRepl = (txt!=r[a]) ? this.getRegexpReplace(txt,r[a]):false;
679
+ var sel = (p) ? $.trim(p):false;
680
+ if ($.inArray(sel,sl)>-1 || $(rel).parent().contents().size()>1) {
681
+ //has dublicate and not one children, need wrap
682
+ var nel = $("<span>").html("{"+rname+"}");
683
+ this.setUID(nel,"wbb");
684
+ var start = (txt.indexOf(rname)+rname.length)+1;
685
+ var after_txt = txt.substr(start,txt.length-start);
686
+ //create wrap element
687
+ rel.data = txt.substr(0,txt.indexOf(rname)-1);
688
+ $(rel).after(this.elFromString(after_txt,document)).after(nel);
689
+
690
+ sel=((sel) ? sel+" ":"")+this.filterByNode(nel);
691
+ regRepl=false;
692
+ }
693
+ crules[rname.toLowerCase()]={sel:sel,attr:false,rgx:regRepl}
694
+ sl[sl.length]=sel;
695
+ }
696
+ }
697
+ },this));
698
+ }
699
+ sl=null;
700
+
701
+
702
+ },this));
703
+
704
+ var nbhtml = $bel.html();
705
+ //UnWrap attributes
706
+ nbhtml = this.unwrapAttrs(nbhtml);
707
+ if (orightml!=nbhtml) {
708
+ //if we modify html, replace it
709
+ delete ob.transform[orightml];
710
+ ob.transform[nbhtml]=bbcode;
711
+ bhtml=nbhtml;
712
+ }
713
+
714
+ }
715
+ o.rules[rootSelector].push([bbcode,crules]);
716
+
717
+ //check for onlyClearText
718
+ if (ob.onlyClearText===true) {
719
+ if (!this.cleartext) {this.cleartext={};}
720
+ this.cleartext[rootSelector]=btnlist[bidx];
721
+ }
722
+
723
+ //check for groupkey
724
+ if (ob.groupkey) {
725
+ if (!o.groups[ob.groupkey]) {o.groups[ob.groupkey]=[]}
726
+ o.groups[ob.groupkey].push(rootSelector);
727
+ }
728
+ }
729
+ }
730
+
731
+ //sort rootSelector
732
+ if (ob.rootSelector) {
733
+ this.sortArray(ob.rootSelector,-1);
734
+ }
735
+
736
+ var htmll = $.map(ob.transform,function(bb,html) {return html}).sort(function(a,b) {
737
+ return ((b[0] || "").length-(a[0] || "").length)
738
+ });
739
+ ob.bbcode = ob.transform[htmll[0]];
740
+ ob.html = htmll[0];
741
+ }
742
+ };
743
+
744
+ this.options.btnlist=btnlist; //use for transforms, becouse select elements not present in buttons
745
+
746
+ //add custom rules, for table,tr,td and other
747
+ $.extend(o.rules,this.options.customRules);
748
+
749
+ //smile rules
750
+ o.srules={};
751
+ if (this.options.smileList) {
752
+ $.each(o.smileList,$.proxy(function(i,sm) {
753
+ var $sm = $(this.strf(sm.img,o));
754
+ var f = this.filterByNode($sm);
755
+ o.srules[f]=[sm.bbcode,sm.img];
756
+ },this));
757
+ }
758
+
759
+ //sort transforms by bbcode length desc
760
+ for (var rootsel in o.rules) {
761
+ this.options.rules[rootsel].sort(function(a,b) {
762
+ return (b[0].length-a[0].length)
763
+ });
764
+ }
765
+
766
+ //create rootsel list
767
+ this.rsellist = [];
768
+ for (var rootsel in this.options.rules) {
769
+ this.rsellist.push(rootsel);
770
+ }
771
+ this.sortArray(this.rsellist,-1);
772
+ },
773
+
774
+ //BUILD
775
+ build: function() {
776
+ $.log("Build editor");
777
+
778
+ //this.$editor = $('<div class="wysibb">');
779
+ this.$editor = $('<div>').addClass("wysibb");
780
+
781
+ if (this.isMobile) {
782
+ this.$editor.addClass("wysibb-mobile");
783
+ }
784
+
785
+ //set direction if defined
786
+ if (this.options.direction) {this.$editor.css("direction",this.options.direction)}
787
+
788
+ this.$editor.insertAfter(this.txtArea).append(this.txtArea);
789
+
790
+ this.startHeight = this.$txtArea.outerHeight();
791
+ this.$txtArea.addClass("wysibb-texarea");
792
+ this.buildToolbar();
793
+ //Build iframe if needed
794
+ this.$txtArea.wrap('<div class="wysibb-text">');
795
+
796
+ if (this.options.onlyBBmode===false) {
797
+ var height = this.options.minheight || this.$txtArea.outerHeight();
798
+ var maxheight = this.options.resize_maxheight;
799
+ var mheight = (this.options.autoresize===true) ? this.options.resize_maxheight:height;
800
+ this.$body = $(this.strf('<div class="wysibb-text-editor" style="max-height:{maxheight}px;min-height:{height}px"></div>',{maxheight:mheight,height:height})).insertAfter(this.$txtArea);
801
+ this.body = this.$body[0];
802
+ this.$txtArea.hide();
803
+
804
+ if (height>32) {
805
+ this.$toolbar.css("max-height",height);
806
+ }
807
+
808
+ $.log("WysiBB loaded");
809
+
810
+ this.$body.addClass("wysibb-body").addClass(this.options.bodyClass);
811
+
812
+ //set direction if defined
813
+ if (this.options.direction) {this.$body.css("direction",this.options.direction)}
814
+
815
+
816
+ if ('contentEditable' in this.body) {
817
+ this.body.contentEditable=true;
818
+ try{
819
+ //fix for mfirefox
820
+ //document.execCommand('enableObjectResizing', false, 'false'); //disable image resizing
821
+ document.execCommand('StyleWithCSS', false, false);
822
+ //document.designMode = "on";
823
+ this.$body.append("<span></span>");
824
+ }catch(e) {}
825
+ }else{
826
+ //use onlybbmode
827
+ this.options.onlyBBmode=this.options.bbmode=true;
828
+ }
829
+
830
+ //check for exist content in textarea
831
+ if (this.txtArea.value.length>0) {
832
+ this.txtAreaInitContent();
833
+ }
834
+
835
+
836
+ //clear html on paste from external editors
837
+ this.$body.bind('keydown', $.proxy(function(e) {
838
+ if ((e.which == 86 && (e.ctrlKey==true || e.metaKey==true)) || (e.which == 45 && (e.shiftKey==true || e.metaKey==true))) {
839
+ if (!this.$pasteBlock) {
840
+ this.saveRange();
841
+ this.$pasteBlock = $(this.elFromString('<div style="opacity:0;" contenteditable="true">\uFEFF</div>'));
842
+
843
+ this.$pasteBlock.appendTo(this.body);
844
+ //if (!$.support.search?type=2) {this.$pasteBlock.focus();} //IE 7,8 FIX
845
+ setTimeout($.proxy(function() {
846
+ this.clearPaste(this.$pasteBlock);
847
+ var rdata = '<span>'+this.$pasteBlock.html()+'</span>';
848
+ this.$body.attr("contentEditable","true");
849
+ this.$pasteBlock.blur().remove();
850
+ this.body.focus();
851
+
852
+ if (this.cleartext) {
853
+ $.log("Check if paste to clearText Block");
854
+ if (this.isInClearTextBlock()) {
855
+ rdata = this.toBB(rdata).replace(/\n/g,"<br/>").replace(/\s{3}/g,'<span class="wbbtab"></span>');
856
+ }
857
+ }
858
+ rdata = rdata.replace(/\t/g,'<span class="wbbtab"></span>');
859
+ this.selectRange(this.lastRange);
860
+ this.insertAtCursor(rdata,false);
861
+ this.lastRange=false;
862
+ this.$pasteBlock=false;
863
+ }
864
+ ,this), 1);
865
+ this.selectNode(this.$pasteBlock[0]);
866
+ }
867
+ return true;
868
+ }
869
+ },this));
870
+
871
+ //insert BR on press enter
872
+ this.$body.bind('keydown',$.proxy(function(e) {
873
+ if (e.which == 13) {
874
+ var isLi = this.isContain(this.getSelectNode(),'li');
875
+ if (!isLi) {
876
+ if (e.preventDefault) {e.preventDefault();}
877
+ this.checkForLastBR(this.getSelectNode());
878
+ this.insertAtCursor('<br/>',false);
879
+ }
880
+ }
881
+ },this));
882
+
883
+ //tabInsert
884
+ if (this.options.tabInsert===true) {
885
+ this.$body.bind('keydown', $.proxy(this.pressTab,this));
886
+ }
887
+
888
+ //add event listeners
889
+ this.$body.bind('mouseup keyup',$.proxy(this.updateUI,this));
890
+ this.$body.bind('mousedown',$.proxy(function(e) {this.clearLastRange();this.checkForLastBR(e.target)},this));
891
+
892
+ //trace Textarea
893
+ if (this.options.traceTextarea===true) {
894
+ $(document).bind("mousedown",$.proxy(this.traceTextareaEvent,this));
895
+ this.$txtArea.val("");
896
+ }
897
+
898
+ //attach hotkeys
899
+ if (this.options.hotkeys===true) {
900
+ this.$body.bind('keydown',$.proxy(this.presskey,this));
901
+ }
902
+
903
+ //smileConversion
904
+ if (this.options.smileConversion===true) {
905
+ this.$body.bind('keyup',$.proxy(this.smileConversion,this));
906
+ }
907
+
908
+ this.inited=true;
909
+
910
+ //create resize lines
911
+ if (this.options.autoresize===true) {
912
+ this.$bresize = $(this.elFromString('<div class="bottom-resize-line"></div>')).appendTo(this.$editor)
913
+ .wdrag({
914
+ scope:this,
915
+ axisY: true,
916
+ height: height
917
+ });
918
+ }
919
+
920
+ this.imgListeners();
921
+ }
922
+
923
+
924
+ //this.$editor.append('<span class="powered">Powered by <a href="http://www.wysibb.com" target="_blank">WysiBB<a/></span>');
925
+
926
+ //add event listeners to textarea
927
+ this.$txtArea.bind('mouseup keyup',$.proxy(function() {
928
+ clearTimeout(this.uitimer);
929
+ this.uitimer = setTimeout($.proxy(this.updateUI,this),100);
930
+ },this));
931
+
932
+ //attach hotkeys
933
+ if (this.options.hotkeys===true) {
934
+ $(document).bind('keydown',$.proxy(this.presskey,this));
935
+ }
936
+ },
937
+ buildToolbar: function() {
938
+ if (this.options.toolbar === false) {return false;}
939
+
940
+ //this.$toolbar = $('<div class="wysibb-toolbar">').prependTo(this.$editor);
941
+ this.$toolbar = $('<div>').addClass("wysibb-toolbar").prependTo(this.$editor);
942
+
943
+ var $btnContainer;
944
+ $.each(this.options.buttons,$.proxy(function(i,bn) {
945
+ var opt = this.options.allButtons[bn];
946
+ if (i==0 || bn=="|" || bn=="-") {
947
+ if (bn=="-") {
948
+ this.$toolbar.append("<div>");
949
+ }
950
+ $btnContainer = $('<div class="wysibb-toolbar-container">').appendTo(this.$toolbar);
951
+ }
952
+ if (opt) {
953
+ if (opt.type=="colorpicker") {
954
+ this.buildColorpicker($btnContainer,bn,opt);
955
+ }else if (opt.type=="table") {
956
+ this.buildTablepicker($btnContainer,bn,opt);
957
+ }else if (opt.type=="select") {
958
+ this.buildSelect($btnContainer,bn,opt);
959
+ }else if (opt.type=="smilebox") {
960
+ this.buildSmilebox($btnContainer,bn,opt);
961
+ }else{
962
+ this.buildButton($btnContainer,bn,opt);
963
+ }
964
+ }
965
+ },this));
966
+
967
+ //fix for hide tooltip on quick mouse over
968
+ this.$toolbar.find(".btn-tooltip").hover(function () {$(this).parent().css("overflow","hidden")},function() {$(this).parent().css("overflow","visible")});
969
+
970
+ //build bbcode switch button
971
+ //var $bbsw = $('<div class="wysibb-toolbar-container modeSwitch"><div class="wysibb-toolbar-btn" unselectable="on"><span class="btn-inner ve-tlb-bbcode" unselectable="on"></span></div></div>').appendTo(this.$toolbar);
972
+ var $bbsw = $(document.createElement('div')).addClass("wysibb-toolbar-container modeSwitch").html('<div class="wysibb-toolbar-btn mswitch" unselectable="on"><span class="btn-inner modesw" unselectable="on">[bbcode]</span></div>').appendTo(this.$toolbar);
973
+ if (this.options.bbmode==true) {$bbsw.children(".wysibb-toolbar-btn").addClass("on");}
974
+ if (this.options.onlyBBmode===false) {
975
+ $bbsw.children(".wysibb-toolbar-btn").click($.proxy(function(e) {
976
+ $(e.currentTarget).toggleClass("on");
977
+ this.modeSwitch();
978
+ },this));
979
+ }
980
+ },
981
+ buildButton: function(container,bn,opt) {
982
+ if (typeof(container)!="object") {
983
+ container = this.$toolbar;
984
+ }
985
+ var btnHTML = (opt.buttonHTML) ? $(this.strf(opt.buttonHTML,this.options)).addClass("btn-inner") : this.strf('<span class="btn-inner btn-text">{text}</span>',{text:opt.buttonText.replace(/</g,"&lt;")});
986
+ var hotkey = (this.options.hotkeys===true && this.options.showHotkeys===true && opt.hotkey) ? (' <span class="tthotkey">['+opt.hotkey+']</span>'):""
987
+ var $btn = $('<div class="wysibb-toolbar-btn wbb-'+bn+'">').appendTo(container).append(btnHTML).append(this.strf('<span class="btn-tooltip">{title}<ins/>{hotkey}</span>',{title:opt.title,hotkey:hotkey}));
988
+
989
+ //attach events
990
+ this.controllers.push($btn);
991
+ $btn.bind('queryState',$.proxy(function(e) {
992
+ (this.queryState(bn)) ? $(e.currentTarget).addClass("on"):$(e.currentTarget).removeClass("on");
993
+ },this));
994
+ $btn.mousedown($.proxy(function(e) {
995
+ e.preventDefault();
996
+ this.execCommand(bn,opt.exvalue || false);
997
+ $(e.currentTarget).trigger('queryState');
998
+ },this));
999
+ },
1000
+ buildColorpicker: function(container,bn,opt) {
1001
+ var $btn = $('<div class="wysibb-toolbar-btn wbb-dropdown wbb-cp">').appendTo(container).append('<div class="ve-tlb-colorpick"><span class="fonticon">\uE010</span><span class="cp-line"></span></div><ins class="fonticon ar">\uE011</ins>').append(this.strf('<span class="btn-tooltip">{title}<ins/></span>',{title:opt.title}));
1002
+ var $cpline = $btn.find(".cp-line");
1003
+
1004
+ var $dropblock = $('<div class="wbb-list">').appendTo($btn);
1005
+ $dropblock.append('<div class="nc">'+CURLANG.auto+'</div>');
1006
+ var colorlist = (opt.colors) ? opt.colors.split(","):[];
1007
+ for (var j=0; j<colorlist.length; j++) {
1008
+ colorlist[j] = $.trim(colorlist[j]);
1009
+ if (colorlist[j]=="-") {
1010
+ //insert padding
1011
+ $dropblock.append('<span class="pl"></span>');
1012
+ }else{
1013
+ $dropblock.append(this.strf('<div class="sc" style="background:{color}" title="{color}"></div>',{color:colorlist[j]}));
1014
+ }
1015
+ }
1016
+ var basecolor = $(document.body).css("color");
1017
+ //attach events
1018
+ this.controllers.push($btn);
1019
+ $btn.bind('queryState',$.proxy(function(e) {
1020
+ //queryState
1021
+ $cpline.css("background-color",basecolor);
1022
+ var r = this.queryState(bn,true);
1023
+ if (r) {
1024
+ $cpline.css("background-color",(this.options.bbmode) ? r.color:r);
1025
+ $btn.find(".ve-tlb-colorpick span.fonticon").css("color",(this.options.bbmode) ? r.color:r);
1026
+ }
1027
+ },this));
1028
+ $btn.mousedown($.proxy(function(e) {
1029
+ e.preventDefault();
1030
+ this.dropdownclick(".wbb-cp",".wbb-list",e);
1031
+ },this));
1032
+ $btn.find(".sc").mousedown($.proxy(function(e) {
1033
+ e.preventDefault();
1034
+ this.selectLastRange();
1035
+ var c = $(e.currentTarget).attr("title");
1036
+ this.execCommand(bn,c);
1037
+ $btn.trigger('queryState');
1038
+ },this));
1039
+ $btn.find(".nc").mousedown($.proxy(function(e) {
1040
+ e.preventDefault();
1041
+ this.selectLastRange();
1042
+ this.execCommand(bn,basecolor);
1043
+ $btn.trigger('queryState');
1044
+ },this));
1045
+ $btn.mousedown(function(e) {
1046
+ if (e.preventDefault) e.preventDefault();
1047
+ });
1048
+ },
1049
+ buildTablepicker: function(container,bn,opt) {
1050
+ var $btn = $('<div class="wysibb-toolbar-btn wbb-dropdown wbb-tbl">').appendTo(container).append('<span class="btn-inner fonticon ve-tlb-table1">\uE00e</span><ins class="fonticon ar">\uE011</ins>').append(this.strf('<span class="btn-tooltip">{title}<ins/></span>',{title:opt.title}));
1051
+
1052
+ var $listblock = $('<div class="wbb-list">').appendTo($btn);
1053
+ var $dropblock = $('<div>').css({"position":"relative","box-sizing":"border-box"}).appendTo($listblock);
1054
+ var rows = opt.rows || 10;
1055
+ var cols = opt.cols || 10;
1056
+ var allcount = rows*cols;
1057
+ $dropblock.css("height",(rows*opt.cellwidth+2)+"px");
1058
+ for (var j=1; j<=cols; j++) {
1059
+ for (var h=1; h<=rows; h++) {
1060
+ //var html = this.strf('<div class="tbl-sel" style="width:{width}px;height:{height}px;z-index:{zindex}" title="{row},{col}"></div>',{width: (j*opt.cellwidth),height: (h*opt.cellwidth),zindex: --allcount,row:h,col:j});
1061
+ var html = '<div class="tbl-sel" style="width:'+(j*100/cols)+'%;height:'+(h*100/rows)+'%;z-index:'+(--allcount)+'" title="'+h+','+j+'"></div>';
1062
+ $dropblock.append(html);
1063
+ }
1064
+ }
1065
+ //this.debug("Attach event on: tbl-sel");
1066
+ $btn.find(".tbl-sel").mousedown($.proxy(function(e) {
1067
+ e.preventDefault();
1068
+ var t = $(e.currentTarget).attr("title");
1069
+ var rc = t.split(",");
1070
+ var code = (this.options.bbmode) ? '[table]':'<table class="wbb-table" cellspacing="5" cellpadding="0">';
1071
+ for (var i=1; i<=rc[0]; i++) {
1072
+ code += (this.options.bbmode) ? ' [tr]\n':'<tr>';
1073
+ for (var j=1; j<=rc[1]; j++) {
1074
+ code += (this.options.bbmode) ? ' [td][/td]\n':'<td>\uFEFF</td>';
1075
+ }
1076
+ code += (this.options.bbmode) ? '[/tr]\n':'</tr>';
1077
+ }
1078
+ code += (this.options.bbmode) ? '[/table]':'</table>';
1079
+ this.insertAtCursor(code);
1080
+ },this));
1081
+ //this.debug("END Attach event on: tbl-sel");
1082
+ $btn.mousedown($.proxy(function(e) {
1083
+ e.preventDefault();
1084
+ this.dropdownclick(".wbb-tbl",".wbb-list",e);
1085
+ },this));
1086
+
1087
+ },
1088
+ buildSelect: function(container,bn,opt) {
1089
+ var $btn = $('<div class="wysibb-toolbar-btn wbb-select wbb-'+bn+'">').appendTo(container).append(this.strf('<span class="val">{title}</span><ins class="fonticon sar">\uE012</ins>',opt)).append(this.strf('<span class="btn-tooltip">{title}<ins/></span>',{title:opt.title}));
1090
+ var $sblock = $('<div class="wbb-list">').appendTo($btn);
1091
+ var $sval = $btn.find("span.val");
1092
+
1093
+ var olist = ($.isArray(opt.options)) ? opt.options:opt.options.split(",");
1094
+ var $selectbox = (this.isMobile) ? $("<select>").addClass("wbb-selectbox"):"";
1095
+ for (var i=0; i<olist.length; i++) {
1096
+ var oname = olist[i];
1097
+ if (typeof(oname)=="string") {
1098
+ var option = this.options.allButtons[oname];
1099
+ if (option) {
1100
+ //$.log("create: "+oname);
1101
+ if (option.html) {
1102
+ $('<span>').addClass("option").attr("oid",oname).attr("cmdvalue",option.exvalue).appendTo($sblock).append(this.strf(option.html,{seltext:option.title}));
1103
+ }else{
1104
+ $sblock.append(this.strf('<span class="option" oid="'+oname+'" cmdvalue="'+option.exvalue+'">{title}</span>',option));
1105
+ }
1106
+
1107
+ //SelectBox for mobile devices
1108
+ if (this.isMobile) {
1109
+ $selectbox.append($('<option>').attr("oid",oname).attr("cmdvalue",option.exvalue).append(option.title));
1110
+ }
1111
+ }
1112
+ }else{
1113
+ //build option list from array
1114
+ var params = {
1115
+ seltext: oname.title
1116
+ }
1117
+ params[opt.valueBBname]=oname.exvalue;
1118
+ $('<span>').addClass("option").attr("oid",bn).attr("cmdvalue",oname.exvalue).appendTo($sblock).append(this.strf(opt.html,params));
1119
+
1120
+ if (this.isMobile) {$selectbox.append($('<option>').attr("oid",bn).attr("cmdvalue",oname.exvalue).append(oname.exvalue))}
1121
+ }
1122
+ }
1123
+ //$sblock.append($selectbox);
1124
+ if (this.isMobile) {
1125
+ $selectbox.appendTo(container);
1126
+ this.controllers.push($selectbox);
1127
+
1128
+ $selectbox.bind('queryState',$.proxy(function(e) {
1129
+ //queryState
1130
+ $selectbox.find("option").each($.proxy(function(i,el){
1131
+ var $el = $(el);
1132
+ var r = this.queryState($el.attr("oid"),true);
1133
+ var cmdvalue = $el.attr("cmdvalue");
1134
+ if ((cmdvalue && r==$el.attr("cmdvalue")) || (!cmdvalue && r)) {
1135
+ $el.prop("selected",true);
1136
+ return false;
1137
+ }
1138
+ },this));
1139
+ },this));
1140
+
1141
+ $selectbox.change($.proxy(function(e) {
1142
+ e.preventDefault();
1143
+ var $o = $(e.currentTarget).find(":selected");
1144
+ var oid = $o.attr("oid");
1145
+ var cmdvalue = $o.attr("cmdvalue");
1146
+ var opt = this.options.allButtons[oid];
1147
+ this.execCommand(oid,opt.exvalue || cmdvalue || false);
1148
+ $(e.currentTarget).trigger('queryState');
1149
+ },this));
1150
+
1151
+ }
1152
+ this.controllers.push($btn);
1153
+ $btn.bind('queryState',$.proxy(function(e) {
1154
+ //queryState
1155
+ $sval.text(opt.title);
1156
+ $btn.find(".option.selected").removeClass("selected");
1157
+ $btn.find(".option").each($.proxy(function(i,el){
1158
+ var $el = $(el);
1159
+ var r = this.queryState($el.attr("oid"),true);
1160
+ var cmdvalue = $el.attr("cmdvalue");
1161
+ if ((cmdvalue && r==$el.attr("cmdvalue")) || (!cmdvalue && r)) {
1162
+ $sval.text($el.text());
1163
+ $el.addClass("selected");
1164
+ return false;
1165
+ }
1166
+ },this));
1167
+ },this));
1168
+ $btn.mousedown($.proxy(function(e) {
1169
+ e.preventDefault();
1170
+ this.dropdownclick(".wbb-select",".wbb-list",e);
1171
+ },this));
1172
+ $btn.find(".option").mousedown($.proxy(function(e) {
1173
+ e.preventDefault();
1174
+ var oid = $(e.currentTarget).attr("oid");
1175
+ var cmdvalue = $(e.currentTarget).attr("cmdvalue");
1176
+ var opt = this.options.allButtons[oid];
1177
+ this.execCommand(oid,opt.exvalue || cmdvalue || false);
1178
+ $(e.currentTarget).trigger('queryState');
1179
+ },this));
1180
+ },
1181
+ buildSmilebox: function(container,bn,opt) {
1182
+ if (this.options.smileList && this.options.smileList.length>0) {
1183
+ var $btnHTML = $(this.strf(opt.buttonHTML,opt)).addClass("btn-inner");
1184
+ var $btn = $('<div class="wysibb-toolbar-btn wbb-smilebox wbb-'+bn+'">').appendTo(container).append($btnHTML).append(this.strf('<span class="btn-tooltip">{title}<ins/></span>',{title:opt.title}));
1185
+ var $sblock = $('<div class="wbb-list">').appendTo($btn);
1186
+ if ($.isArray(this.options.smileList)) {
1187
+ $.each(this.options.smileList,$.proxy(function(i,sm){
1188
+ $('<span>').addClass("smile").appendTo($sblock).append($(this.strf(sm.img,this.options)).attr("title",sm.title));
1189
+ },this));
1190
+ }
1191
+ $btn.mousedown($.proxy(function(e) {
1192
+ e.preventDefault();
1193
+ this.dropdownclick(".wbb-smilebox",".wbb-list",e);
1194
+ },this));
1195
+ $btn.find('.smile').mousedown($.proxy(function(e) {
1196
+ e.preventDefault();
1197
+ //this.selectLastRange();
1198
+ this.insertAtCursor((this.options.bbmode) ? this.toBB($(e.currentTarget).html()):$($(e.currentTarget).html()));
1199
+ },this))
1200
+ }
1201
+ },
1202
+ updateUI: function(e) {
1203
+ if (!e || ((e.which>=8 && e.which<=46) || e.which>90 || e.type=="mouseup")) {
1204
+ $.each(this.controllers,$.proxy(function(i,$btn) {
1205
+ $btn.trigger('queryState');
1206
+ },this));
1207
+ }
1208
+
1209
+ //check for onlyClearText
1210
+ this.disNonActiveButtons();
1211
+
1212
+ },
1213
+ initModal: function() {
1214
+ this.$modal=$("#wbbmodal");
1215
+ if (this.$modal.size()==0) {
1216
+ $.log("Init modal");
1217
+ this.$modal = $('<div>').attr("id","wbbmodal").prependTo(document.body)
1218
+ .html('<div class="wbbm"><div class="wbbm-title"><span class="wbbm-title-text"></span><span class="wbbclose" title="'+CURLANG.close+'">×</span></div><div class="wbbm-content"></div><div class="wbbm-bottom"><button id="wbbm-submit" class="wbb-button">'+CURLANG.save+'</button><button id="wbbm-cancel" class="wbb-cancel-button">'+CURLANG.cancel+'</button><button id="wbbm-remove" class="wbb-remove-button">'+CURLANG.remove+'</button></div></div>').hide();
1219
+
1220
+ this.$modal.find('#wbbm-cancel,.wbbclose').click($.proxy(this.closeModal,this));
1221
+ this.$modal.bind('click',$.proxy(function(e) {
1222
+ if ($(e.target).parents(".wbbm").size()==0) {
1223
+ this.closeModal();
1224
+ }
1225
+ },this));
1226
+
1227
+ $(document).bind("keydown",$.proxy(this.escModal,this)); //ESC key close modal
1228
+ }
1229
+ },
1230
+ initHotkeys: function() {
1231
+ $.log("initHotkeys");
1232
+ this.hotkeys=[];
1233
+ var klist = "0123456789 abcdefghijklmnopqrstuvwxyz";
1234
+ $.each(this.options.allButtons,$.proxy(function(cmd,opt) {
1235
+ if (opt.hotkey) {
1236
+ var keys = opt.hotkey.split("+");
1237
+ if (keys && keys.length>=2) {
1238
+ var metasum=0;
1239
+ var key = keys.pop();
1240
+ $.each(keys,function(i,k) {
1241
+ switch($.trim(k.toLowerCase())) {
1242
+ case "ctrl": {metasum+=1;break;}
1243
+ case "shift": {metasum+=4;break;}
1244
+ case "alt": {metasum+=7;break;}
1245
+ }
1246
+ })
1247
+ //$.log("metasum: "+metasum+" key: "+key+" code: "+(klist.indexOf(key)+48));
1248
+ if (metasum>0) {
1249
+ if (!this.hotkeys["m"+metasum]) {this.hotkeys["m"+metasum]=[];}
1250
+ this.hotkeys["m"+metasum]["k"+(klist.indexOf(key)+48)]=cmd;
1251
+ }
1252
+ }
1253
+ }
1254
+ },this))
1255
+ },
1256
+ presskey: function(e) {
1257
+ if (e.ctrlKey==true || e.shiftKey==true || e.altKey==true) {
1258
+ var metasum = ((e.ctrlKey==true) ? 1:0)+((e.shiftKey==true) ? 4:0)+((e.altKey==true) ? 7:0);
1259
+ if (this.hotkeys["m"+metasum] && this.hotkeys["m"+metasum]["k"+e.which]) {
1260
+ this.execCommand(this.hotkeys["m"+metasum]["k"+e.which],false);
1261
+ e.preventDefault();
1262
+ return false;
1263
+ }
1264
+ }
1265
+ },
1266
+
1267
+ //COgdfMMAND FUNCTIONS
1268
+ execCommand: function(command,value) {
1269
+ $.log("execCommand: "+command);
1270
+ var opt = this.options.allButtons[command];
1271
+ if (opt.en!==true) {return false;}
1272
+ var queryState = this.queryState(command,value);
1273
+
1274
+ //check for onlyClearText
1275
+ var skipcmd = this.isInClearTextBlock();
1276
+ if (skipcmd && skipcmd!=command) {return;}
1277
+
1278
+
1279
+ if (opt.excmd) {
1280
+ //use NativeCommand
1281
+ if (this.options.bbmode) {
1282
+ $.log("Native command in bbmode: "+command);
1283
+ if (queryState && opt.subInsert!=true) {
1284
+ //remove bbcode
1285
+ this.wbbRemoveCallback(command,value);
1286
+ }else{
1287
+ //insert bbcode
1288
+ var v = {};
1289
+ if (opt.valueBBname && value) {
1290
+ v[opt.valueBBname]=value;
1291
+ }
1292
+ this.insertAtCursor(this.getBBCodeByCommand(command,v));
1293
+ }
1294
+ }else{
1295
+ this.execNativeCommand(opt.excmd,value || false);
1296
+ }
1297
+ }else if (!opt.cmd) {
1298
+ //wbbCommand
1299
+ //this.wbbExecCommand(command,value,queryState,$.proxy(this.wbbInsertCallback,this),$.proxy(this.wbbRemoveCallback,this));
1300
+ this.wbbExecCommand.call(this,command,value,queryState);
1301
+ }else{
1302
+ //user custom command
1303
+ opt.cmd.call(this,command,value,queryState);
1304
+ }
1305
+ this.updateUI();
1306
+ },
1307
+ queryState: function(command,withvalue) {
1308
+ var opt = this.options.allButtons[command];
1309
+ if (opt.en!==true) {return false;}
1310
+ //if (opt.subInsert===true && opt.type!="colorpicker") {return false;}
1311
+ if (this.options.bbmode) {
1312
+ //bbmode
1313
+ if (opt.bbSelector) {
1314
+ for (var i=0; i<opt.bbSelector.length; i++) {
1315
+ var b = this.isBBContain(opt.bbSelector[i]);
1316
+ if (b) {
1317
+ return this.getParams(b,opt.bbSelector[i],b[1]);
1318
+ }
1319
+ }
1320
+ }
1321
+ return false;
1322
+ }else{
1323
+ if (opt.excmd) {
1324
+ //native command
1325
+ if (withvalue) {
1326
+ try {
1327
+ //Firefox fix
1328
+ var v = (document.queryCommandValue(opt.excmd)+"").replace(/\'/g,"");
1329
+ if (opt.excmd=="foreColor") {
1330
+ v = this.rgbToHex(v);
1331
+ }
1332
+ //return (v==value);
1333
+ return v;
1334
+ }catch(e) {return false;}
1335
+ }else{
1336
+ try { //Firefox fix, exception while get queryState for UnorderedList
1337
+ if ((opt.excmd=="bold" || opt.excmd=="italic" || opt.excmd=="underline" || opt.excmd=="strikeThrough") && $(this.getSelectNode()).is("img")) { //Fix, when img selected
1338
+ return false;
1339
+ }else if (opt.excmd=="underline" && $(this.getSelectNode()).closest("a").size()>0) { //fix, when link select
1340
+ return false;
1341
+ }
1342
+ return document.queryCommandState(opt.excmd);
1343
+ }catch(e) {return false;}
1344
+ }
1345
+ }else{
1346
+ //custom command
1347
+ if ($.isArray(opt.rootSelector)) {
1348
+ for (var i=0; i<opt.rootSelector.length; i++) {
1349
+ var n = this.isContain(this.getSelectNode(),opt.rootSelector[i]);
1350
+ if (n) {
1351
+ return this.getParams(n,opt.rootSelector[i]);
1352
+ }
1353
+ }
1354
+ }
1355
+ return false;
1356
+ }
1357
+ }
1358
+ },
1359
+ wbbExecCommand: function(command,value,queryState) { //default command for custom bbcodes
1360
+ $.log("wbbExecCommand");
1361
+ var opt = this.options.allButtons[command];
1362
+ if (opt) {
1363
+ if (opt.modal) {
1364
+ if ($.isFunction(opt.modal)) {
1365
+ //custom modal function
1366
+ //opt.modal(command,opt.modal,queryState,new clbk(this));
1367
+ opt.modal.call(this,command,opt.modal,queryState);
1368
+ }else{
1369
+ this.showModal.call(this,command,opt.modal,queryState);
1370
+ }
1371
+ }else{
1372
+ if (queryState && opt.subInsert!=true) {
1373
+ //remove formatting
1374
+ //removeCallback(command,value);
1375
+ this.wbbRemoveCallback(command);
1376
+ }else{
1377
+ //insert format
1378
+ if (opt.groupkey) {
1379
+ var groupsel = this.options.groups[opt.groupkey];
1380
+ if (groupsel) {
1381
+ var snode = this.getSelectNode();
1382
+ $.each(groupsel,$.proxy(function(i,sel) {
1383
+ var is = this.isContain(snode,sel);
1384
+ if (is) {
1385
+ var $sp = $('<span>').html(is.innerHTML)
1386
+ var id = this.setUID($sp);
1387
+ $(is).replaceWith($sp);
1388
+ this.selectNode(this.$editor.find("#"+id)[0]);
1389
+ return false;
1390
+ }
1391
+ },this));
1392
+ }
1393
+ }
1394
+ this.wbbInsertCallback(command,value)
1395
+ }
1396
+ }
1397
+ }
1398
+ },
1399
+ wbbInsertCallback: function(command,paramobj) {
1400
+ if (typeof(paramobj)!="object") {paramobj={}};
1401
+ $.log("wbbInsertCallback: "+command);
1402
+ var data = this.getCodeByCommand(command,paramobj);
1403
+ this.insertAtCursor(data);
1404
+
1405
+ if (this.seltextID && data.indexOf(this.seltextID)!=-1) {
1406
+ var snode = this.$body.find("#"+this.seltextID)[0];
1407
+ this.selectNode(snode);
1408
+ $(snode).removeAttr("id");
1409
+ this.seltextID=false;
1410
+ }
1411
+ },
1412
+ wbbRemoveCallback: function(command,clear) {
1413
+ $.log("wbbRemoveCallback: "+command);
1414
+ var opt = this.options.allButtons[command];
1415
+ if (this.options.bbmode) {
1416
+ //bbmode
1417
+ //REMOVE BBCODE
1418
+ var pos = this.getCursorPosBB();
1419
+ var stextnum=0;
1420
+ $.each(opt.bbSelector,$.proxy(function(i,bbcode) {
1421
+ var stext = bbcode.match(/\{[\s\S]+?\}/g);
1422
+ $.each(stext,function(n,s) {
1423
+ if (s.toLowerCase()=="{seltext}") {stextnum=n;return false}
1424
+ });
1425
+ var a = this.isBBContain(bbcode);
1426
+ if (a) {
1427
+ this.txtArea.value = this.txtArea.value.substr(0,a[1])+this.txtArea.value.substr(a[1],this.txtArea.value.length-a[1]).replace(a[0][0],(clear===true) ? '':a[0][stextnum+1]);
1428
+ this.setCursorPosBB(a[1]);
1429
+ return false;
1430
+ }
1431
+ },this));
1432
+ }else{
1433
+ var node = this.getSelectNode();
1434
+ $.each(opt.rootSelector,$.proxy(function(i,s) {
1435
+ //$.log("RS: "+s);
1436
+ var root = this.isContain(node,s);
1437
+ if (!root) {return true;}
1438
+ var $root = $(root);
1439
+ var cs = this.options.rules[s][0][1];
1440
+ if ($root.is("span[wbb]") || !$root.is("span,font")) { //remove only blocks
1441
+ if (clear===true || (!cs || !cs["seltext"])) {
1442
+ this.setCursorByEl($root);
1443
+ $root.remove();
1444
+ }else{
1445
+ if (cs && cs["seltext"] && cs["seltext"]["sel"]) {
1446
+ var htmldata = $root.find(cs["seltext"]["sel"]).html();
1447
+ if (opt.onlyClearText===true) {
1448
+ htmldata = this.getHTML(htmldata,true,true);
1449
+ htmldata = htmldata.replace(/\&#123;/g,"{").replace(/\&#125;/g,"}");
1450
+ }
1451
+ $root.replaceWith(htmldata);
1452
+ }else{
1453
+ var htmldata = $root.html();
1454
+ if (opt.onlyClearText===true) {
1455
+ htmldata = this.getHTML(htmldata,true);
1456
+ htmldata = htmldata.replace(/\&lt;/g,"<").replace(/\&gt;/g,">").replace(/\&#123;/g,"{").replace(/\&#125;/g,"}");
1457
+ }
1458
+ $root.replaceWith(htmldata);
1459
+ }
1460
+ }
1461
+ return false;
1462
+ }else{
1463
+ //span,font - extract select content from this span,font
1464
+ var rng = this.getRange();
1465
+ var shtml = this.getSelectText();
1466
+ var rnode = this.getSelectNode();
1467
+ if (shtml=="") {
1468
+ shtml="\uFEFF";
1469
+ }else{
1470
+ shtml = this.clearFromSubInsert(shtml,command);
1471
+ }
1472
+ var ins = this.elFromString(shtml);
1473
+
1474
+ var before_rng = (window.getSelection) ? rng.cloneRange():this.body.createTextRange();
1475
+ var after_rng = (window.getSelection) ? rng.cloneRange():this.body.createTextRange();
1476
+
1477
+ if (window.getSelection) {
1478
+ this.insertAtCursor('<span id="wbbdivide"></span>');
1479
+ var div = $root.find('span#wbbdivide').get(0);
1480
+ before_rng.setStart(root.firstChild,0);
1481
+ before_rng.setEndBefore(div);
1482
+ after_rng.setStartAfter(div);
1483
+ after_rng.setEndAfter(root.lastChild);
1484
+ }else{
1485
+ before_rng.moveToElementText(root);
1486
+ after_rng.moveToElementText(root);
1487
+ before_rng.setEndPoint('EndToStart',rng);
1488
+ after_rng.setEndPoint('StartToEnd',rng);
1489
+ }
1490
+ var bf = this.getSelectText(false,before_rng);
1491
+ var af = this.getSelectText(false,after_rng);
1492
+ if (af!="") {
1493
+ var $af = $root.clone().html(af);
1494
+ $root.after($af);
1495
+ }
1496
+ if (clear!==true) $root.after(ins); //insert select html
1497
+ if (window.getSelection) {
1498
+ $root.html(bf);
1499
+ if (clear!==true) this.selectNode(ins);
1500
+ }else{
1501
+ $root.replaceWith(bf);
1502
+ }
1503
+ return false;
1504
+ }
1505
+ },this));
1506
+ }
1507
+ },
1508
+ execNativeCommand: function(cmd,param) {
1509
+ //$.log("execNativeCommand: '"+cmd+"' : "+param);
1510
+ this.body.focus(); //set focus to frame body
1511
+ if (cmd=="insertHTML" && !window.getSelection) { //IE does't support insertHTML
1512
+ var r = (this.lastRange) ? this.lastRange:document.selection.createRange(); //IE 7,8 range lost fix
1513
+ r.pasteHTML(param);
1514
+ var txt = $('<div>').html(param).text(); //for ie selection inside block
1515
+ var brsp = txt.indexOf("\uFEFF");
1516
+ if (brsp>-1) {
1517
+ r.moveStart('character',(-1)*(txt.length-brsp));
1518
+ r.select();
1519
+ }
1520
+ this.lastRange=false;
1521
+ }else if (cmd=="insertHTML") { //fix webkit bug with insertHTML
1522
+ var sel = this.getSelection();
1523
+ var e = this.elFromString(param);
1524
+ var rng = (this.lastRange) ? this.lastRange:this.getRange();
1525
+ rng.deleteContents();
1526
+ rng.insertNode(e);
1527
+ rng.collapse(false);
1528
+ sel.removeAllRanges();
1529
+ sel.addRange(rng);
1530
+ }else{
1531
+ if (typeof param == "undefined") {param=false;}
1532
+ if (this.lastRange) {
1533
+ $.log("Last range select");
1534
+ this.selectLastRange()
1535
+ }
1536
+ document.execCommand(cmd, false, param);
1537
+ }
1538
+
1539
+ },
1540
+ getCodeByCommand: function(command,paramobj) {
1541
+ return (this.options.bbmode) ? this.getBBCodeByCommand(command,paramobj):this.getHTMLByCommand(command,paramobj);
1542
+ },
1543
+ getBBCodeByCommand: function(command,params) {
1544
+ if (!this.options.allButtons[command]) {return "";}
1545
+ if (typeof(params)=="undefined") {params={};}
1546
+ params = this.keysToLower(params);
1547
+ if (!params["seltext"]) {
1548
+ //get selected text
1549
+ params["seltext"] = this.getSelectText(true);
1550
+ }
1551
+
1552
+ var bbcode = this.options.allButtons[command].bbcode;
1553
+ //bbcode = this.strf(bbcode,params);
1554
+ bbcode = bbcode.replace(/\{(.*?)(\[.*?\])*\}/g,function(str,p,vrgx) {
1555
+ if (vrgx) {
1556
+ var vrgxp;
1557
+ if (vrgx) {
1558
+ vrgxp = new RegExp(vrgx+"+","i");
1559
+ }
1560
+ if (typeof(params[p.toLowerCase()])!="undefined" && params[p.toLowerCase()].toString().match(vrgxp)===null) {
1561
+ //not valid value
1562
+ return "";
1563
+ }
1564
+ }
1565
+ return (typeof(params[p.toLowerCase()])=="undefined") ? "":params[p.toLowerCase()];
1566
+ });
1567
+
1568
+ //insert first with max params
1569
+ var rbbcode=null,maxpcount=0;
1570
+ if (this.options.allButtons[command].transform) {
1571
+ var tr=[];
1572
+ $.each(this.options.allButtons[command].transform,function(html,bb) {
1573
+ tr.push(bb);
1574
+ });
1575
+ tr=this.sortArray(tr,-1);
1576
+ $.each(tr,function(i,v) {
1577
+ var valid=true,pcount=0,pname={};;
1578
+ v = v.replace(/\{(.*?)(\[.*?\])*\}/g,function(str,p,vrgx) {
1579
+ var vrgxp;
1580
+ p = p.toLowerCase();
1581
+ if (vrgx) {
1582
+ vrgxp = new RegExp(vrgx+"+","i");
1583
+ }
1584
+ if (typeof(params[p.toLowerCase()])=="undefined" || (vrgx && params[p.toLowerCase()].toString().match(vrgxp)===null)) {valid=false;};
1585
+ if (typeof(params[p])!="undefined" && !pname[p]) {pname[p]=1;pcount++;}
1586
+ return (typeof(params[p.toLowerCase()])=="undefined") ? "":params[p.toLowerCase()];
1587
+ });
1588
+ if (valid && (pcount>maxpcount)) {rbbcode = v;maxpcount=pcount;}
1589
+ });
1590
+ }
1591
+ return rbbcode || bbcode;
1592
+ },
1593
+ getHTMLByCommand: function(command,params) {
1594
+ if (!this.options.allButtons[command]) {return "";}
1595
+ params = this.keysToLower(params);
1596
+ if (typeof(params)=="undefined") {params={};}
1597
+ if (!params["seltext"]) {
1598
+ //get selected text
1599
+ params["seltext"] = this.getSelectText(false);
1600
+ //$.log("seltext: '"+params["seltext"]+"'");
1601
+ if (params["seltext"]=="") {params["seltext"]="\uFEFF";}
1602
+ else{
1603
+ //clear selection from current command tags
1604
+ params["seltext"] = this.clearFromSubInsert(params["seltext"],command);
1605
+
1606
+ //toBB if params onlyClearText=true
1607
+ if (this.options.allButtons[command].onlyClearText===true) {
1608
+ params["seltext"] = this.toBB(params["seltext"]).replace(/\</g,"&lt;").replace(/\n/g,"<br/>").replace(/\s{3}/g,'<span class="wbbtab"></span>');
1609
+ }
1610
+
1611
+ }
1612
+ }
1613
+
1614
+ var postsel="";
1615
+ this.seltextID = "wbbid_"+(++this.lastid);
1616
+ if (command!="link" && command!="img") {
1617
+ params["seltext"] = '<span id="'+this.seltextID+'">'+params["seltext"]+'</span>'; //use for select seltext
1618
+ }else{
1619
+ postsel = '<span id="'+this.seltextID+'">\uFEFF</span>'
1620
+ }
1621
+ var html = this.options.allButtons[command].html;
1622
+ html = html.replace(/\{(.*?)(\[.*?\])*\}/g,function(str,p,vrgx) {
1623
+ if (vrgx) {
1624
+ var vrgxp = new RegExp(vrgx+"+","i");
1625
+ if (typeof(params[p.toLowerCase()])!="undefined" && params[p.toLowerCase()].toString().match(vrgxp)===null) {
1626
+ //not valid value
1627
+ return "";
1628
+ }
1629
+ }
1630
+ return (typeof(params[p.toLowerCase()])=="undefined") ? "":params[p.toLowerCase()];
1631
+ });
1632
+
1633
+ //insert first with max params
1634
+ var rhtml=null,maxpcount=0;
1635
+ if (this.options.allButtons[command].transform) {
1636
+ var tr=[];
1637
+ $.each(this.options.allButtons[command].transform,function(html,bb) {
1638
+ tr.push(html);
1639
+ });
1640
+ tr=this.sortArray(tr,-1);
1641
+ $.each(tr,function(i,v) {
1642
+ var valid=true, pcount=0,pname={};
1643
+ v = v.replace(/\{(.*?)(\[.*?\])*\}/g,function(str,p,vrgx) {
1644
+ var vrgxp;
1645
+ p = p.toLowerCase();
1646
+ if (vrgx) {
1647
+ vrgxp = new RegExp(vrgx+"+","i");
1648
+ }
1649
+ if (typeof(params[p])=="undefined" || (vrgx && params[p].toString().match(vrgxp)===null)) {valid=false;};
1650
+ if (typeof(params[p])!="undefined" && !pname[p]) {pname[p]=1;pcount++;}
1651
+ return (typeof(params[p])=="undefined") ? "":params[p];
1652
+ });
1653
+ if (valid && (pcount>maxpcount)) {rhtml = v;maxpcount=pcount;}
1654
+ });
1655
+ }
1656
+ return (rhtml || html)+postsel;
1657
+ },
1658
+
1659
+ //SELECTION FUNCTIONS
1660
+ getSelection: function() {
1661
+ if (window.getSelection) {
1662
+ return window.getSelection();
1663
+ }else if (document.selection) {
1664
+ return (this.options.bbmode) ? document.selection.createRange():document.selection.createRange();
1665
+ }
1666
+ },
1667
+ getSelectText: function(fromTxtArea,range) {
1668
+ if (fromTxtArea) {
1669
+ //return select text from textarea
1670
+ this.txtArea.focus();
1671
+ if('selectionStart' in this.txtArea) {
1672
+ var l = this.txtArea.selectionEnd - this.txtArea.selectionStart;
1673
+ return this.txtArea.value.substr(this.txtArea.selectionStart, l);
1674
+ }else{
1675
+ //IE
1676
+ var r = document.selection.createRange();
1677
+ return r.text;
1678
+ }
1679
+ }else{
1680
+ //return select html from body
1681
+ this.body.focus();
1682
+ if (!range) {range=this.getRange()};
1683
+ if (window.getSelection) {
1684
+ //w3c
1685
+ if (range) {
1686
+ return $('<div>').append(range.cloneContents()).html();
1687
+ }
1688
+ }else{
1689
+ //ie
1690
+ return range.htmlText;
1691
+ }
1692
+ }
1693
+ return "";
1694
+ },
1695
+ getRange: function() {
1696
+ if (window.getSelection) {
1697
+ var sel = this.getSelection();
1698
+ if (sel.getRangeAt && sel.rangeCount>0) {
1699
+ return sel.getRangeAt(0);
1700
+ }else if (sel.anchorNode) {
1701
+ var range = (this.options.bbmode) ? document.createRange() : document.createRange();
1702
+ range.setStart (sel.anchorNode, sel.anchorOffset);
1703
+ range.setEnd (sel.focusNode, sel.focusOffset);
1704
+ return range;
1705
+ }
1706
+ }else{
1707
+ return (this.options.bbmode===true) ? document.selection.createRange():document.selection.createRange();
1708
+ }
1709
+ },
1710
+ insertAtCursor: function(code,forceBBMode) {
1711
+ if (typeof(code)!="string") {code = $("<div>").append(code).html();}
1712
+ if ((this.options.bbmode && typeof(forceBBMode)=="undefined") || forceBBMode===true) {
1713
+ var clbb = code.replace(/.*(\[\/\S+?\])$/,"$1");
1714
+ var p = this.getCursorPosBB()+((code.indexOf(clbb)!=-1 && code.match(/\[.*\]/)) ? code.indexOf(clbb):code.length);
1715
+ if (document.selection) {
1716
+ //IE
1717
+ this.txtArea.focus();
1718
+ this.getSelection().text=code;
1719
+ }else if (this.txtArea.selectionStart || this.txtArea.selectionStart == '0') {
1720
+ this.txtArea.value = this.txtArea.value.substring(0, this.txtArea.selectionStart) + code + this.txtArea.value.substring(this.txtArea.selectionEnd, this.txtArea.value.length);
1721
+ }
1722
+ if (p<0) {p=0;}
1723
+ this.setCursorPosBB(p);
1724
+ }else{
1725
+ this.execNativeCommand("insertHTML",code);
1726
+ var node = this.getSelectNode();
1727
+ if (!$(node).closest("table,tr,td")) {
1728
+ this.splitPrevNext(node);
1729
+ }
1730
+ }
1731
+ },
1732
+ getSelectNode: function(rng) {
1733
+ this.body.focus();
1734
+ if (!rng) {rng=this.getRange();}
1735
+ if (!rng) {return this.$body;}
1736
+ //return (window.getSelection) ? rng.commonAncestorContainer:rng.parentElement();
1737
+ var sn = (window.getSelection) ? rng.commonAncestorContainer:rng.parentElement();
1738
+ if ($(sn).is(".imgWrap")) {sn = $(sn).children("img")[0];}
1739
+ return sn;
1740
+ },
1741
+ getCursorPosBB: function() {
1742
+ var pos=0;
1743
+ if ('selectionStart' in this.txtArea) {
1744
+ pos = this.txtArea.selectionStart;
1745
+ }else{
1746
+ this.txtArea.focus();
1747
+ var r = this.getRange();
1748
+ var rt = document.body.createTextRange();
1749
+ rt.moveToElementText(this.txtArea);
1750
+ rt.setEndPoint('EndToStart',r);
1751
+ pos = rt.text.length;
1752
+ }
1753
+ return pos;
1754
+ },
1755
+ setCursorPosBB: function(pos) {
1756
+ if (this.options.bbmode) {
1757
+ if (window.getSelection) {
1758
+ this.txtArea.selectionStart=pos;
1759
+ this.txtArea.selectionEnd=pos;
1760
+ }else{
1761
+ var range = this.txtArea.createTextRange();
1762
+ range.collapse(true);
1763
+ range.move('character', pos);
1764
+ range.select();
1765
+ }
1766
+ }
1767
+ },
1768
+ selectNode: function(node,rng) {
1769
+ if (!rng) {rng = this.getRange();}
1770
+ if (!rng) {return;}
1771
+ if (window.getSelection) {
1772
+ var sel = this.getSelection();
1773
+ rng.selectNodeContents(node)
1774
+ sel.removeAllRanges();
1775
+ sel.addRange(rng);
1776
+ }else{
1777
+ rng.moveToElementText(node);
1778
+ rng.select();
1779
+ }
1780
+ },
1781
+ selectRange: function(rng) {
1782
+ if (rng) {
1783
+ if (!window.getSelection) {
1784
+ rng.select();
1785
+ }else{
1786
+ var sel = this.getSelection();
1787
+ sel.removeAllRanges();
1788
+ sel.addRange(rng);
1789
+ }
1790
+ }
1791
+ },
1792
+ cloneRange: function(rng) {
1793
+ if (rng) {
1794
+ if (!window.getSelection) {
1795
+ return rng.duplicate();
1796
+ }else{
1797
+ return rng.cloneRange();
1798
+ }
1799
+ }
1800
+ },
1801
+ getRangeClone: function() {
1802
+ return this.cloneRange(this.getRange());
1803
+ },
1804
+ saveRange: function() {
1805
+ this.setBodyFocus();
1806
+ //this.lastRange=(this.options.bbmode) ? this.getCursorPosBB():this.getRangeClone();
1807
+ this.lastRange=this.getRangeClone();
1808
+ },
1809
+ selectLastRange: function() {
1810
+ if (this.lastRange) {
1811
+ this.body.focus();
1812
+ this.selectRange(this.lastRange);
1813
+ this.lastRange=false;
1814
+ }
1815
+ },
1816
+ setBodyFocus: function() {
1817
+ $.log("Set focus to WysiBB editor");
1818
+ if (this.options.bbmode) {
1819
+ if (!this.$txtArea.is(":focus")) {
1820
+ this.$txtArea.focus();
1821
+ }
1822
+ }else{
1823
+ if (!this.$body.is(":focus")) {
1824
+ this.$body.focus();
1825
+ }
1826
+ }
1827
+ },
1828
+ clearLastRange: function() {
1829
+ this.lastRange=false;
1830
+ },
1831
+
1832
+ //TRANSFORM FUNCTIONS
1833
+ filterByNode: function(node) {
1834
+ var $n = $(node);
1835
+ var tagName = $n.get(0).tagName.toLowerCase();
1836
+ var filter=tagName;
1837
+ var attributes = this.getAttributeList($n.get(0));
1838
+ $.each(attributes, $.proxy(function(i, item) {
1839
+ var v = $n.attr(item);
1840
+ /* $.log("v: "+v);
1841
+ if ($.inArray(item,this.options.attrWrap)!=-1) {
1842
+ item = '_'+item;
1843
+ } */
1844
+ //$.log(item);
1845
+ if (item.substr(0,1)=="_") {item=item.substr(1,item.length)}
1846
+ if (v && !v.match(/\{.*?\}/)) {
1847
+ //$.log("I1: "+item);
1848
+ if (item=="style") {
1849
+ var v = $n.attr(item);
1850
+ var va = v.split(";");
1851
+ $.each(va,function(i,f) {
1852
+ if (f && f.length>0) {
1853
+ filter+='['+item+'*="'+$.trim(f)+'"]';
1854
+ }
1855
+ });
1856
+ }else{
1857
+ filter+='['+item+'="'+v+'"]';
1858
+ }
1859
+ }else if (v && item=="style") {
1860
+ //$.log("I2: "+item);
1861
+ var vf = v.substr(0,v.indexOf("{"));
1862
+ if (vf && vf!="") {
1863
+ var v = v.substr(0,v.indexOf("{"));
1864
+ var va = v.split(";");
1865
+ $.each(va,function(i,f) {
1866
+ filter+='['+item+'*="'+f+'"]';
1867
+ });
1868
+ //filter+='['+item+'*="'+v.substr(0,v.indexOf("{"))+'"]';
1869
+ }
1870
+ }else{ //1.2.2
1871
+ //$.log("I3: "+item);
1872
+ filter+='['+item+']';
1873
+ }
1874
+ },this));
1875
+
1876
+ //index
1877
+ var idx = $n.parent().children(filter).index($n);
1878
+ if (idx>0) {
1879
+ filter+=":eq("+$n.index()+")";
1880
+ }
1881
+ return filter;
1882
+ },
1883
+ relFilterByNode: function(node,stop) {
1884
+ var p="";
1885
+ $.each(this.options.attrWrap,function(i,a) {
1886
+ stop = stop.replace('['+a,'[_'+a);
1887
+ });
1888
+ while (node && node.tagName!="BODY" && !$(node).is(stop)) {
1889
+ p=this.filterByNode(node)+" "+p;
1890
+ if (node) {node = node.parentNode;}
1891
+ }
1892
+ return p;
1893
+ },
1894
+ getRegexpReplace: function(str,validname) {
1895
+ str = str.replace(/(\(|\)|\[|\]|\.|\*|\?|\:|\\)/g,"\\$1")
1896
+ .replace(/\s+/g,"\\s+")
1897
+ .replace(validname.replace(/(\(|\)|\[|\]|\.|\*|\?|\:|\\)/g,"\\$1"),"(.+)")
1898
+ .replace(/\{\S+?\}/g,".*");
1899
+ return (str);
1900
+ },
1901
+ getBBCode: function() {
1902
+ if (!this.options.rules) {return this.$txtArea.val();}
1903
+ if (this.options.bbmode) {return this.$txtArea.val();}
1904
+ this.clearEmpty();
1905
+ this.removeLastBodyBR();
1906
+ return this.toBB(this.$body.html());
1907
+ },
1908
+ toBB: function(data) {
1909
+ if (!data) {return "";};
1910
+ var $e = (typeof(data)=="string") ? $('<span>').html(data):$(data);
1911
+ //remove last BR
1912
+ $e.find("div,blockquote,p").each(function() {
1913
+ if (this.nodeType!=3 && this.lastChild && this.lastChild.tagName=="BR") {
1914
+ $(this.lastChild).remove();
1915
+ }
1916
+ })
1917
+ if ($e.is("div,blockquote,p") && $e[0].nodeType!=3 && $e[0].lastChild && $e[0].lastChild.tagName=="BR") {
1918
+ $($e[0].lastChild).remove();
1919
+ }
1920
+ //END remove last BR
1921
+
1922
+ //Remove BR
1923
+ $e.find("ul > br, table > br, tr > br").remove();
1924
+ //IE
1925
+
1926
+ var outbb="";
1927
+
1928
+ //transform smiles
1929
+ $.each(this.options.srules,$.proxy(function(s,bb) {
1930
+ $e.find(s).replaceWith(bb[0]);
1931
+ },this));
1932
+
1933
+ $e.contents().each($.proxy(function(i,el) {
1934
+ var $el = $(el);
1935
+ if (el.nodeType===3) {
1936
+ outbb+=el.data.replace(/\n+/,"").replace(/\t/g," ");
1937
+ }else{
1938
+ //process html tag
1939
+ var rpl,processed=false;
1940
+
1941
+ //for (var rootsel in this.options.rules) {
1942
+ for (var j=0; j<this.rsellist.length; j++) {
1943
+ var rootsel = this.rsellist[j];
1944
+ if ($el && $el.is(rootsel)) {
1945
+ //it is root sel
1946
+ var rlist = this.options.rules[rootsel];
1947
+ for (var i=0; i<rlist.length; i++) {
1948
+ var bbcode = rlist[i][0];
1949
+ var crules = rlist[i][1];
1950
+ var skip=false,keepElement=false,keepAttr=false;
1951
+ if (!$el.is("br")) {
1952
+ bbcode = bbcode.replace(/\n/g,"<br>");
1953
+ }
1954
+ bbcode = bbcode.replace(/\{(.*?)(\[.*?\])*\}/g,$.proxy(function(str,s,vrgx) {
1955
+ var c = crules[s.toLowerCase()];
1956
+ //if (typeof(c)=="undefined") {$.log("Param: {"+s+"} not found in HTML representation.");skip=true;return s;}
1957
+ if (typeof(c)=="undefined") {$.log("Param: {"+s+"} not found in HTML representation.");skip=true;}
1958
+ var $cel = (c.sel) ? $(el).find(c.sel):$(el);
1959
+ if (c.attr && !$cel.attr(c.attr)) {skip=true;return s;} //skip if needed attribute not present, maybe other bbcode
1960
+ var cont = (c.attr) ? $cel.attr(c.attr):$cel.html();
1961
+ if (typeof(cont)=="undefined" || cont==null) {skip=true;return s;}
1962
+ var regexp = c.rgx;
1963
+
1964
+ //style fix
1965
+ if (regexp && c.attr=="style" && regexp.substr(regexp.length-1,1)!=";") {
1966
+ regexp+=";";
1967
+ }
1968
+ if (c.attr=="style" && cont && cont.substr(cont.length-1,1)!=";") {cont+=";"}
1969
+ //prepare regexp
1970
+ var rgx = (regexp) ? new RegExp(regexp,""):false;
1971
+ if (rgx) {
1972
+ if (cont.match(rgx)) {
1973
+ var m = cont.match(rgx);
1974
+ if (m && m.length==2) {
1975
+ cont=m[1];
1976
+ }
1977
+ }else{
1978
+ cont="";
1979
+ }
1980
+ }
1981
+
1982
+ //if it is style attr, then keep tag alive, remove this style
1983
+ if (c.attr && skip===false) {
1984
+ if (c.attr=="style") {
1985
+ keepElement=true;
1986
+ var nstyle="";
1987
+ var r = c.rgx.replace(/^\.\*\?/,"").replace(/\.\*$/,"").replace(/;$/,"");
1988
+ $($cel.attr("style").split(";")).each(function(idx,style) {
1989
+ if (style && style!="") {
1990
+ if (!style.match(r)) {
1991
+ nstyle+=style+";";
1992
+ }
1993
+ }
1994
+ });
1995
+ if (nstyle=="") {
1996
+ $cel.removeAttr("style");
1997
+ }else{
1998
+ $cel.attr("style",nstyle);
1999
+ }
2000
+ }else if (c.rgx===false){
2001
+ keepElement=true;
2002
+ keepAttr=true;
2003
+ $cel.removeAttr(c.attr);
2004
+ }
2005
+ }
2006
+ if ($el.is('table,tr,td,font')) {keepElement=true;}
2007
+
2008
+ return cont || "";
2009
+ },this));
2010
+ if (skip) {continue;}
2011
+ if ($el.is("img,br,hr")) {
2012
+ //replace element
2013
+ outbb+=bbcode;
2014
+ $el=null;
2015
+ break;
2016
+ }else{
2017
+ if (keepElement && !$el.attr("notkeep")) {
2018
+ if ($el.is("table,tr,td")) {
2019
+ bbcode = this.fixTableTransform(bbcode);
2020
+ outbb+=this.toBB($('<span>').html(bbcode));
2021
+ $el=null;
2022
+ }else{
2023
+ $el.empty().html('<span>'+bbcode+'</span>');
2024
+ }
2025
+
2026
+ }else{
2027
+ if ($el.is("iframe")) {
2028
+ outbb+=bbcode;
2029
+ }else{
2030
+ $el.empty().html(bbcode);
2031
+ outbb+=this.toBB($el);
2032
+ $el=null;
2033
+
2034
+ }
2035
+ break;
2036
+ }
2037
+ }
2038
+ }
2039
+ }
2040
+ }
2041
+ if (!$el || $el.is("iframe,img")) {return true;}
2042
+ outbb+=this.toBB($el);
2043
+ }
2044
+ },this));
2045
+
2046
+ outbb.replace(/\uFEFF/g,"");
2047
+ return outbb;
2048
+ },
2049
+ getHTML: function(bbdata,init,skiplt) {
2050
+ if (!this.options.bbmode && !init) {return this.$body.html()}
2051
+
2052
+ if (!skiplt) {bbdata = bbdata.replace(/</g,"&lt;").replace(/\{/g,"&#123;").replace(/\}/g,"&#125;");}
2053
+ bbdata = bbdata.replace(/\[code\]([\s\S]*?)\[\/code\]/g,function(s) {
2054
+ s = s.substr("[code]".length,s.length-"[code]".length-"[/code]".length).replace(/\[/g,"&#91;").replace(/\]/g,"&#93;");
2055
+ return "[code]"+s+"[/code]";
2056
+ });
2057
+
2058
+
2059
+ $.each(this.options.btnlist,$.proxy(function(i,b){
2060
+ if (b!="|" && b!="-") {
2061
+ var find=true;
2062
+ if (!this.options.allButtons[b] || !this.options.allButtons[b].transform) {
2063
+ return true;
2064
+ }
2065
+
2066
+ $.each(this.options.allButtons[b].transform,$.proxy(function(html,bb) {
2067
+ html = html.replace(/\n/g,""); //IE 7,8 FIX
2068
+ var a=[];
2069
+ bb = bb.replace(/(\(|\)|\[|\]|\.|\*|\?|\:|\\|\\)/g,"\\$1");
2070
+ //.replace(/\s/g,"\\s");
2071
+ bb = bb.replace(/\{(.*?)(\\\[.*?\\\])*\}/gi,$.proxy(function(str,s,vrgx) {
2072
+ a.push(s);
2073
+ if (vrgx) {
2074
+ //has validation regexp
2075
+ vrgx = vrgx.replace(/\\/g,"");
2076
+ return "("+vrgx+"*?)";
2077
+ }
2078
+ return "([\\s\\S]*?)";
2079
+ },this));
2080
+ var n=0,am;
2081
+ while ((am = (new RegExp(bb,"mgi")).exec(bbdata)) != null) {
2082
+ if (am) {
2083
+ var r={};
2084
+ $.each(a,$.proxy(function(i,k) {
2085
+ r[k]=am[i+1];
2086
+ },this));
2087
+ var nhtml = html;
2088
+ nhtml = nhtml.replace(/\{(.*?)(\[.*?\])\}/g,"{$1}");
2089
+ nhtml = this.strf(nhtml,r);
2090
+ bbdata = bbdata.replace(am[0],nhtml);
2091
+ }
2092
+ }
2093
+ },this));
2094
+ }
2095
+ },this));
2096
+
2097
+ //transform system codes
2098
+ $.each(this.options.systr,function(html,bb) {
2099
+ bb = bb.replace(/(\(|\)|\[|\]|\.|\*|\?|\:|\\|\\)/g,"\\$1")
2100
+ .replace(" ","\\s");
2101
+ bbdata = bbdata.replace(new RegExp(bb,"g"),html);
2102
+ });
2103
+
2104
+
2105
+ var $wrap = $(this.elFromString("<div>"+bbdata+"</div>"));
2106
+ //transform smiles
2107
+ /* $wrap.contents().filter(function() {return this.nodeType==3}).each($.proxy(smilerpl,this)).end().find("*").contents().filter(function() {return this.nodeType==3}).each($.proxy(smilerpl,this));
2108
+
2109
+ function smilerpl(i,el) {
2110
+ var ndata = el.data;
2111
+ $.each(this.options.smileList,$.proxy(function(i,row) {
2112
+ var fidx = ndata.indexOf(row.bbcode);
2113
+ if (fidx!=-1) {
2114
+ var afternode_txt = ndata.substring(fidx+row.bbcode.length,ndata.length);
2115
+ var afternode = document.createTextNode(afternode_txt);
2116
+ el.data = ndata = el.data.substr(0,fidx);
2117
+ $(el).after(afternode).after(this.strf(row.img,this.options));
2118
+ }
2119
+ },this));
2120
+ } */
2121
+ this.getHTMLSmiles($wrap);
2122
+ //$wrap.contents().filter(function() {return this.nodeType==3}).each($.proxy(this,smileRPL,this));
2123
+
2124
+ return $wrap.html();
2125
+ },
2126
+ getHTMLSmiles: function(rel) {
2127
+ $(rel).contents().filter(function() {return this.nodeType==3}).each($.proxy(this.smileRPL,this));
2128
+ },
2129
+ smileRPL: function(i,el) {
2130
+ var ndata = el.data;
2131
+ $.each(this.options.smileList,$.proxy(function(i,row) {
2132
+ var fidx = ndata.indexOf(row.bbcode);
2133
+ if (fidx!=-1) {
2134
+ var afternode_txt = ndata.substring(fidx+row.bbcode.length,ndata.length);
2135
+ var afternode = document.createTextNode(afternode_txt);
2136
+ el.data = ndata = el.data.substr(0,fidx);
2137
+ $(el).after(afternode).after(this.strf(row.img,this.options));
2138
+ this.getHTMLSmiles(el.parentNode);
2139
+ return false;
2140
+ }
2141
+ this.getHTMLSmiles(el);
2142
+ },this));
2143
+ },
2144
+ //UTILS
2145
+ setUID: function(el,attr) {
2146
+ var id = "wbbid_"+(++this.lastid);
2147
+ if (el) {
2148
+ $(el).attr(attr || "id",id);
2149
+ }
2150
+ return id;
2151
+ },
2152
+ keysToLower: function(o) {
2153
+ $.each(o,function(k,v) {
2154
+ if (k!=k.toLowerCase()) {
2155
+ delete o[k];
2156
+ o[k.toLowerCase()]=v;
2157
+ }
2158
+ });
2159
+ return o;
2160
+ },
2161
+ strf: function(str,data) {
2162
+ data = this.keysToLower($.extend({},data));
2163
+ return str.replace(/\{([\w\.]*)\}/g, function (str, key) {key = key.toLowerCase();var keys = key.split("."), value = data[keys.shift().toLowerCase()];$.each(keys, function () { value = value[this]; }); return (value === null || value === undefined) ? "" : value;});
2164
+ },
2165
+ elFromString: function(str) {
2166
+ if (str.indexOf("<")!=-1 && str.indexOf(">")!=-1) {
2167
+ //create tag
2168
+ var wr = document.createElement("SPAN");
2169
+ $(wr).html(str);
2170
+ this.setUID(wr,"wbb");
2171
+ return ($(wr).contents().size()>1) ? wr:wr.firstChild;
2172
+ }else{
2173
+ //create text node
2174
+ return document.createTextNode(str);
2175
+ }
2176
+ },
2177
+ isContain: function(node,sel) {
2178
+ while (node && !$(node).hasClass("wysibb")) {
2179
+ if ($(node).is(sel)) {return node};
2180
+ if (node) {node = node.parentNode;}
2181
+ else{return null;}
2182
+ }
2183
+ },
2184
+ isBBContain: function(bbcode) {
2185
+ var pos=this.getCursorPosBB();
2186
+ var b = this.prepareRGX(bbcode);
2187
+ var bbrgx = new RegExp(b,"g");
2188
+ var a;
2189
+ var lastindex=0;
2190
+ while ((a=bbrgx.exec(this.txtArea.value))!=null) {
2191
+ var p = this.txtArea.value.indexOf(a[0],lastindex);
2192
+ if (pos>p && pos<(p+a[0].length)) {
2193
+ return [a,p];
2194
+ }
2195
+ lastindex=p+1;
2196
+ }
2197
+ },
2198
+ prepareRGX: function(r) {
2199
+ return r.replace(/(\[|\]|\)|\(|\.|\*|\?|\:|\||\\)/g,"\\$1").replace(/\{.*?\}/g,"([\\s\\S]*?)");
2200
+ //return r.replace(/([^a-z0-9)/ig,"\\$1").replace(/\{.*?\}/g,"([\\s\\S]*?)");
2201
+ },
2202
+ checkForLastBR: function(node) {
2203
+ if (!node) {$node = this.body;}
2204
+ if (node.nodeType==3) {node=node.parentNode;}
2205
+ var $node = $(node);
2206
+ if ($node.is("span[id*='wbbid']")) {$node = $node.parent();}
2207
+ if (this.options.bbmode===false && $node.is('div,blockquote,code') && $node.contents().size()>0) {
2208
+ var l = $node[0].lastChild;
2209
+ if (!l || (l && l.tagName!="BR")) {$node.append("<br/>");}
2210
+ }
2211
+ if (this.$body.contents().size()>0 && this.body.lastChild.tagName!="BR") {
2212
+ this.$body.append('<br/>');
2213
+ }
2214
+ },
2215
+ getAttributeList: function(el) {
2216
+ var a=[];
2217
+ $.each(el.attributes,function(i,attr) {
2218
+ if (attr.specified) {
2219
+ a.push(attr.name);
2220
+ }
2221
+ });
2222
+ return a;
2223
+ },
2224
+ clearFromSubInsert: function(html,cmd) {
2225
+ if (this.options.allButtons[cmd] && this.options.allButtons[cmd].rootSelector) {
2226
+ var $wr = $('<div>').html(html);
2227
+ $.each(this.options.allButtons[cmd].rootSelector,$.proxy(function(i,s) {
2228
+ var seltext=false;
2229
+ if (typeof(this.options.rules[s][0][1]["seltext"])!="undefined") {
2230
+ seltext = this.options.rules[s][0][1]["seltext"]["sel"];
2231
+ }
2232
+ var res=true;
2233
+ $wr.find("*").each(function() { //work with find("*") and "is", becouse in ie7-8 find is case sensitive
2234
+ if ($(this).is(s)) {
2235
+ if (seltext && seltext["sel"]) {
2236
+ $(this).replaceWith($(this).find(seltext["sel"].toLowerCase()).html());
2237
+ }else{
2238
+ $(this).replaceWith($(this).html());
2239
+ }
2240
+ res=false;
2241
+ }
2242
+ });
2243
+ return res;
2244
+ },this));
2245
+ return $wr.html();
2246
+ }
2247
+ return html;
2248
+ },
2249
+ splitPrevNext: function(node) {
2250
+ if (node.nodeType==3) {node = node.parentNode};
2251
+ var f = this.filterByNode(node).replace(/\:eq.*$/g,"");
2252
+ if ($(node.nextSibling).is(f)) {
2253
+ $(node).append($(node.nextSibling).html());
2254
+ $(node.nextSibling).remove();
2255
+ }
2256
+ if ($(node.previousSibling).is(f)) {
2257
+ $(node).prepend($(node.previousSibling).html());
2258
+ $(node.previousSibling).remove();
2259
+ }
2260
+ },
2261
+ modeSwitch: function() {
2262
+ if (this.options.bbmode) {
2263
+ //to HTML
2264
+ this.$body.html(this.getHTML(this.$txtArea.val()));
2265
+ this.$txtArea.hide().removeAttr("wbbsync").val("");
2266
+ this.$body.css("min-height",this.$txtArea.height()).show().focus();
2267
+ }else{
2268
+ //to bbcode
2269
+ this.$txtArea.val(this.getBBCode()).css("min-height",this.$body.height());
2270
+ this.$body.hide();
2271
+ this.$txtArea.show().focus();
2272
+ }
2273
+ this.options.bbmode=!this.options.bbmode;
2274
+ },
2275
+ clearEmpty: function () {
2276
+ this.$body.children().filter(emptyFilter).remove();
2277
+ function emptyFilter() {
2278
+ if (!$(this).is("span,font,a,b,i,u,s")) {
2279
+ //clear empty only for span,font
2280
+ return false;
2281
+ }
2282
+ if (!$(this).hasClass("wbbtab") && $.trim($(this).html()).length==0) {
2283
+ return true;
2284
+ }else if ($(this).children().size()>0) {
2285
+ $(this).children().filter(emptyFilter).remove();
2286
+ if ($(this).html().length==0 && this.tagName!="BODY") {
2287
+ return true;
2288
+ }
2289
+ }
2290
+ }
2291
+ },
2292
+ dropdownclick: function(bsel,tsel,e) {
2293
+ //this.body.focus();
2294
+ var $btn = $(e.currentTarget).closest(bsel);
2295
+ if ($btn.hasClass("dis")) {return;}
2296
+ if ($btn.attr("wbbshow")) {
2297
+ //hide dropdown
2298
+ $btn.removeAttr("wbbshow");
2299
+ $(document).unbind("mousedown",this.dropdownhandler);
2300
+ if (document) {
2301
+ $(document).unbind("mousedown",this.dropdownhandler);
2302
+ }
2303
+ this.lastRange=false;
2304
+
2305
+ }else{
2306
+ this.saveRange();
2307
+ this.$editor.find("*[wbbshow]").each(function(i,el) {
2308
+ $(el).removeClass("on").find($(el).attr("wbbshow")).hide().end().removeAttr("wbbshow");
2309
+ })
2310
+ $btn.attr("wbbshow",tsel);
2311
+ $(document.body).bind("mousedown",$.proxy(function(evt) {this.dropdownhandler($btn,bsel,tsel,evt)},this));
2312
+ if (this.$body) {
2313
+ this.$body.bind("mousedown",$.proxy(function(evt) {this.dropdownhandler($btn,bsel,tsel,evt)},this));
2314
+ }
2315
+ }
2316
+ $btn.find(tsel).toggle();
2317
+ $btn.toggleClass("on");
2318
+ },
2319
+ dropdownhandler: function($btn,bsel,tsel,e) {
2320
+ if ($(e.target).parents(bsel).size()==0) {
2321
+ $btn.removeClass("on").find(tsel).hide();
2322
+ $(document).unbind('mousedown',this.dropdownhandler);
2323
+ if (this.$body) {
2324
+ this.$body.unbind('mousedown',this.dropdownhandler);
2325
+ }
2326
+ }
2327
+ },
2328
+ rgbToHex: function(rgb) {
2329
+ if (rgb.substr(0, 1)=='#') {return rgb;}
2330
+ //if (rgb.indexOf("rgb")==-1) {return rgb;}
2331
+ if (rgb.indexOf("rgb")==-1) {
2332
+ //IE
2333
+ var color=parseInt(rgb);
2334
+ color = ((color & 0x0000ff) << 16) | (color & 0x00ff00) | ((color & 0xff0000) >>> 16);
2335
+ return '#'+color.toString(16);
2336
+ }
2337
+ var digits = /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/.exec(rgb);
2338
+ return "#"+this.dec2hex(parseInt(digits[2]))+this.dec2hex(parseInt(digits[3]))+this.dec2hex(parseInt(digits[4]));
2339
+ },
2340
+ dec2hex: function(d) {
2341
+ if(d>15) {
2342
+ return d.toString(16);
2343
+ }else{
2344
+ return "0"+d.toString(16);
2345
+ }
2346
+ },
2347
+ sync: function() {
2348
+ if (this.options.bbmode) {
2349
+ this.$body.html(this.getHTML(this.txtArea.value,true));
2350
+ }else{
2351
+ this.$txtArea.attr("wbbsync",1).val(this.getBBCode());
2352
+ }
2353
+ },
2354
+ clearPaste: function(el) {
2355
+ var $block = $(el);
2356
+ //NEW
2357
+ $.each(this.options.rules,$.proxy(function(s,ar) {
2358
+ var $sf = $block.find(s).attr("wbbkeep",1);
2359
+ if ($sf.size()>0) {
2360
+ var s2 = ar[0][1];
2361
+ $.each(s2,function(i,v) {
2362
+ if (v.sel) {
2363
+ $sf.find(v.sel).attr("wbbkeep",1);
2364
+ }
2365
+ });
2366
+ }
2367
+ },this));
2368
+ $block.find("*[wbbkeep!='1']").each($.proxy(function(i,el) {
2369
+ var $this = $(el);
2370
+ if ($this.is('div,p') && ($this.children().size()==0 || el.lastChild.tagName!="BR")) {
2371
+ $this.after("<br/>");
2372
+ }
2373
+ },this));
2374
+ $block.find("*[wbbkeep]").removeAttr("wbbkeep").removeAttr("style");
2375
+ $.log($block.html());
2376
+ //$.log("BBCODE: "+this.toBB($block.clone(true)));
2377
+ $block.html(this.getHTML(this.toBB($block),true));
2378
+ $.log($block.html());
2379
+
2380
+ //OLD
2381
+ /* $.each(this.options.rules,$.proxy(function(s,bb) {
2382
+ $block.find(s).attr("wbbkeep",1);
2383
+ },this));
2384
+
2385
+ //replace div and p without last br to html()+br
2386
+ $block.find("*[wbbkeep!='1']").each($.proxy(function(i,el) {
2387
+ var $this = $(el);
2388
+ if ($this.is('div,p') && ($this.children().size()==0 || el.lastChild.tagName!="BR")) {
2389
+ $this.after("<br/>").after($this.contents()).remove();
2390
+ }else{
2391
+ $this.after($this.contents()).remove();
2392
+ }
2393
+ },this));
2394
+ $block.find("*[wbbkeep]").removeAttr("wbbkeep").removeAttr("style"); */
2395
+ },
2396
+ sortArray: function(ar,asc) {
2397
+ ar.sort(function(a,b) {
2398
+ return (a.length-b.length)*(asc || 1);
2399
+ });
2400
+ return ar;
2401
+ },
2402
+ smileFind: function() {
2403
+ if (this.options.smilefind) {
2404
+ var $smlist = $(this.options.smilefind).find('img[alt]');
2405
+ if ($smlist.size()>0) {
2406
+ this.options.smileList=[];
2407
+ $smlist.each($.proxy(function(i,el) {
2408
+ var $el=$(el);
2409
+ this.options.smileList.push({title:$el.attr("title"),bbcode:$el.attr("alt"),img:$el.removeAttr("alt").removeAttr("title")[0].outerHTML});
2410
+ },this));
2411
+ }
2412
+ }
2413
+ },
2414
+ destroy: function() {
2415
+ this.$editor.replaceWith(this.$txtArea);
2416
+ this.$txtArea.removeClass("wysibb-texarea").show();
2417
+ this.$modal.remove();
2418
+ this.$txtArea.data("wbb",null);
2419
+ },
2420
+ pressTab: function(e) {
2421
+ if (e && e.which == 9) {
2422
+ //insert tab
2423
+ if (e.preventDefault) {e.preventDefault();}
2424
+ if (this.options.bbmode) {
2425
+ this.insertAtCursor(' ',false);
2426
+ }else{
2427
+ this.insertAtCursor('<span class="wbbtab">\uFEFF</span>',false);
2428
+ //this.execNativeCommand("indent",false);
2429
+ }
2430
+ }
2431
+ },
2432
+ removeLastBodyBR: function() {
2433
+ if (this.body.lastChild && this.body.lastChild.nodeType!=3 && this.body.lastChild.tagName=="BR") {
2434
+ this.body.removeChild(this.body.lastChild);
2435
+ this.removeLastBodyBR();
2436
+ }
2437
+ },
2438
+ traceTextareaEvent: function(e) {
2439
+ if ($(e.target).closest("div.wysibb").size()==0) {
2440
+ if ($(document.activeElement).is("div.wysibb-body")) {
2441
+ this.saveRange();
2442
+ }
2443
+ setTimeout($.proxy(function() {
2444
+ var data = this.$txtArea.val();
2445
+ if (this.options.bbmode===false && data!="" && $(e.target).closest("div.wysibb").size()==0 && !this.$txtArea.attr("wbbsync")) {
2446
+ this.selectLastRange();
2447
+ this.insertAtCursor(this.getHTML(data,true));
2448
+ this.$txtArea.val("");
2449
+ }
2450
+ if ($(document.activeElement).is("div.wysibb-body")) {
2451
+ this.lastRange=false;
2452
+ }
2453
+ },this),100);
2454
+ }
2455
+ },
2456
+ txtAreaInitContent: function() {
2457
+ //$.log(this.txtArea.value);
2458
+ this.$body.html(this.getHTML(this.txtArea.value,true));
2459
+ },
2460
+ getValidationRGX: function(s) {
2461
+ if (s.match(/\[\S+\]/)) {
2462
+ return s.replace(/.*(\\*\[\S+\]).*/,"$1");
2463
+ }
2464
+ return "";
2465
+ },
2466
+ smileConversion: function() {
2467
+ if (this.options.smileList && this.options.smileList.length>0) {
2468
+ var snode = this.getSelectNode();
2469
+ if (snode.nodeType==3) {
2470
+ var ndata = snode.data;
2471
+ if (ndata.length>=2 && !this.isInClearTextBlock(snode) && $(snode).parents("a").size()==0) {
2472
+ $.each(this.options.srules,$.proxy(function(i,sar) {
2473
+ var smbb = sar[0];
2474
+ var fidx = ndata.indexOf(smbb);
2475
+ if (fidx!=-1) {
2476
+ var afternode_txt = ndata.substring(fidx+smbb.length,ndata.length);
2477
+ var afternode = document.createTextNode(afternode_txt);
2478
+ var afternode_cursor = document.createElement("SPAN");
2479
+ snode.data = snode.data.substr(0,fidx);
2480
+ $(snode).after(afternode).after(afternode_cursor).after(this.strf(sar[1],this.options));
2481
+ this.selectNode(afternode_cursor);
2482
+ return false;
2483
+ }
2484
+ },this));
2485
+ }
2486
+ }
2487
+ }
2488
+ },
2489
+ isInClearTextBlock: function() {
2490
+ if (this.cleartext) {
2491
+ var find=false;
2492
+ $.each(this.cleartext,$.proxy(function(sel,command) {
2493
+ if (this.queryState(command)) {
2494
+ find=command;
2495
+ return false;
2496
+ }
2497
+ },this))
2498
+ return find;
2499
+ }
2500
+ return false;
2501
+ },
2502
+ wrapAttrs: function(html) {
2503
+ $.each(this.options.attrWrap,function(i,a) {
2504
+ html = html.replace(a+'="','_'+a+'="');
2505
+ });
2506
+ return html;
2507
+ },
2508
+ unwrapAttrs: function(html) {
2509
+ $.each(this.options.attrWrap,function(i,a) {
2510
+ html = html.replace('_'+a+'="',a+'="');
2511
+ });
2512
+ return html;
2513
+ },
2514
+ disNonActiveButtons: function() {
2515
+ if (this.isInClearTextBlock()) {
2516
+ this.$toolbar.find(".wysibb-toolbar-btn:not(.on,.mswitch)").addClass("dis");
2517
+ }else{
2518
+ this.$toolbar.find(".wysibb-toolbar-btn.dis").removeClass("dis");
2519
+ }
2520
+ },
2521
+ setCursorByEl: function(el) {
2522
+ var sl = document.createTextNode("\uFEFF");
2523
+ $(el).after(sl);
2524
+ this.selectNode(sl);
2525
+ },
2526
+
2527
+ //img listeners
2528
+ imgListeners: function() {
2529
+ $(document).on("mousedown",$.proxy(this.imgEventHandler,this));
2530
+ },
2531
+ imgEventHandler: function(e) {
2532
+ var $e = $(e.target);
2533
+ if (this.hasWrapedImage && ($e.closest(".wbb-img,#wbbmodal").size()==0 || $e.hasClass("wbb-cancel-button"))) {
2534
+ this.$body.find(".imgWrap ").each(function() {
2535
+ $.log("Removed imgWrap block");
2536
+ $(this).replaceWith($(this).find("img"));
2537
+ })
2538
+ this.hasWrapedImage = false;
2539
+ this.updateUI();
2540
+ }
2541
+
2542
+ if ($e.is("img") && $e.closest(".wysibb-body").size()>0) {
2543
+ $e.wrap("<span class='imgWrap'></span>");
2544
+ this.hasWrapedImage = $e;
2545
+ this.$body.focus();
2546
+ this.selectNode($e.parent()[0]);
2547
+ }
2548
+ },
2549
+
2550
+ //MODAL WINDOW
2551
+ showModal: function(cmd,opt,queryState) {
2552
+ $.log("showModal: "+cmd);
2553
+ this.saveRange();
2554
+ var $cont = this.$modal.find(".wbbm-content").html("");
2555
+ var $wbbm = this.$modal.find(".wbbm").removeClass("hastabs");
2556
+ this.$modal.find("span.wbbm-title-text").html(opt.title);
2557
+ if (opt.tabs && opt.tabs.length>1) {
2558
+ //has tabs, create
2559
+ $wbbm.addClass("hastabs");
2560
+ var $ul = $('<div class="wbbm-tablist">').appendTo($cont).append("<ul>").children("ul");
2561
+ $.each(opt.tabs,$.proxy(function(i,row) {
2562
+ if (i==0) {row['on']="on"}
2563
+ $ul.append(this.strf('<li class="{on}" onClick="$(this).parent().find(\'.on\').removeClass(\'on\');$(this).addClass(\'on\');$(this).parents(\'.wbbm-content\').find(\'.tab-cont\').hide();$(this).parents(\'.wbbm-content\').find(\'.tab'+i+'\').show()">{title}</li>',row));
2564
+
2565
+ },this))
2566
+ }
2567
+ if (opt.width) {
2568
+ $wbbm.css("width",opt.width);
2569
+ }
2570
+ var $cnt = $('<div class="wbbm-cont">').appendTo($cont);
2571
+ if (queryState) {
2572
+ $wbbm.find('#wbbm-remove').show();
2573
+ }else{
2574
+ $wbbm.find('#wbbm-remove').hide();
2575
+ }
2576
+ $.each(opt.tabs,$.proxy(function(i,r) {
2577
+ var $c = $('<div>').addClass("tab-cont tab"+i).attr("tid",i).appendTo($cnt);
2578
+ if (i>0) {$c.hide();}
2579
+ if (r.html) {
2580
+ $c.html(this.strf(r.html,this.options));
2581
+ }else{
2582
+ $.each(r.input,$.proxy(function(j,inp) {
2583
+ inp["value"]=queryState[inp.param.toLowerCase()];
2584
+ if (inp.param.toLowerCase()=="seltext" && (!inp["value"] || inp["value"]=="")) {
2585
+ inp["value"] = this.getSelectText(this.options.bbmode);
2586
+ }
2587
+ if (inp["value"] && inp["value"].indexOf("<span id='wbbid")==0 && $(inp["value"]).is("span[id*='wbbid']")) {
2588
+ inp["value"] = $(inp["value"]).html();
2589
+ }
2590
+ if (inp.type && inp.type=="div") {
2591
+ //div input, support wysiwyg input
2592
+ $c.append(this.strf('<div class="wbbm-inp-row"><label>{title}</label><div class="inp-text div-modal-text" contenteditable="true" name="{param}">{value}</div></div>',inp));
2593
+ }else{
2594
+ //default input
2595
+ $c.append(this.strf('<div class="wbbm-inp-row"><label>{title}</label><input class="inp-text modal-text" type="text" name="{param}" value="{value}"/></div>',inp));
2596
+ }
2597
+
2598
+
2599
+ },this));
2600
+ }
2601
+ },this));
2602
+
2603
+ //this.lastRange=this.getRange();
2604
+
2605
+ if ($.isFunction(opt.onLoad)) {
2606
+ opt.onLoad.call(this,cmd,opt,queryState);
2607
+ }
2608
+
2609
+ $wbbm.find('#wbbm-submit').click($.proxy(function() {
2610
+
2611
+ if ($.isFunction(opt.onSubmit)) { //custom submit function, if return false, then don't process our function
2612
+ var r = opt.onSubmit.call(this,cmd,opt,queryState);
2613
+ if (r===false) {return;}
2614
+ }
2615
+ var params={};
2616
+ var valid=true;
2617
+ this.$modal.find(".wbbm-inperr").remove();
2618
+ this.$modal.find(".wbbm-brdred").removeClass("wbbm-brdred");
2619
+ //$.each(this.$modal.find(".tab-cont:visible input"),$.proxy(function(i,el) {
2620
+ $.each(this.$modal.find(".tab-cont:visible .inp-text"),$.proxy(function(i,el) {
2621
+ var tid = $(el).parents(".tab-cont").attr("tid");
2622
+ var pname = $(el).attr("name").toLowerCase();
2623
+ var pval="";
2624
+ if ($(el).is("input,textrea,select")) {
2625
+ pval = $(el).val();
2626
+ }else{
2627
+ pval = $(el).html();
2628
+ }
2629
+ var validation = opt.tabs[tid]["input"][i]["validation"];
2630
+ if (typeof(validation)!="undefined") {
2631
+ if (!pval.match(new RegExp(validation,"i"))) {
2632
+ valid=false;
2633
+ $(el).after('<span class="wbbm-inperr">'+CURLANG.validation_err+'</span>').addClass("wbbm-brdred");
2634
+ }
2635
+ }
2636
+ params[pname]=pval;
2637
+ },this));
2638
+ if (valid) {
2639
+ $.log("Last range: "+this.lastRange);
2640
+ this.selectLastRange();
2641
+ //insert callback
2642
+ if (queryState) {
2643
+ this.wbbRemoveCallback(cmd,true);
2644
+ }
2645
+ this.wbbInsertCallback(cmd,params);
2646
+ //END insert callback
2647
+
2648
+ this.closeModal();
2649
+ this.updateUI();
2650
+ }
2651
+ },this));
2652
+ $wbbm.find('#wbbm-remove').click($.proxy(function() {
2653
+ //clbk.remove();
2654
+ this.selectLastRange();
2655
+ this.wbbRemoveCallback(cmd); //remove callback
2656
+ this.closeModal();
2657
+ this.updateUI();
2658
+ },this));
2659
+
2660
+ $(document.body).css("overflow","hidden"); //lock the screen, remove scroll on body
2661
+ if ($("body").height() > $(window).height()) { //if body has scroll, add padding-right 18px
2662
+ $(document.body).css("padding-right","18px");
2663
+ }
2664
+ this.$modal.show();
2665
+ //if (window.getSelection)
2666
+ if (this.isMobile) {
2667
+ $wbbm.css("margin-top","10px");
2668
+ }else{
2669
+ $wbbm.css("margin-top",($(window).height()-$wbbm.outerHeight())/3+"px");
2670
+ }
2671
+ //setTimeout($.proxy(function() {this.$modal.find("input:visible")[0].focus()},this),10);
2672
+ setTimeout($.proxy(function() {this.$modal.find(".inp-text:visible")[0].focus()},this),10);
2673
+ },
2674
+ escModal: function(e) {
2675
+ if (e.which==27) {this.closeModal();}
2676
+ },
2677
+ closeModal: function() {
2678
+ $(document.body).css("overflow","auto").css("padding-right","0").unbind("keyup",this.escModal); //ESC key close modal;
2679
+ this.$modal.find('#wbbm-submit,#wbbm-remove').unbind('click');
2680
+ this.$modal.hide();
2681
+ this.lastRange=false;
2682
+ return this;
2683
+ },
2684
+ getParams: function(src,s,offset) {
2685
+ var params={};
2686
+ if (this.options.bbmode) {
2687
+ //bbmode
2688
+ var stext = s.match(/\{[\s\S]+?\}/g);
2689
+ s = this.prepareRGX(s);
2690
+ var rgx = new RegExp(s,"g");
2691
+ var val = this.txtArea.value;
2692
+ if (offset>0) {
2693
+ val = val.substr(offset,val.length-offset);
2694
+ }
2695
+ var a = rgx.exec(val);
2696
+ if (a) {
2697
+ $.each(stext,function(i,n) {
2698
+ params[n.replace(/\{|\}/g,"").replace(/"/g,"'").toLowerCase()] = a[i+1];
2699
+ });
2700
+ }
2701
+ }else{
2702
+ var rules = this.options.rules[s][0][1];
2703
+ $.each(rules,$.proxy(function(k,v) {
2704
+ var value="";
2705
+ var $v = (v.sel!==false) ? value=$(src).find(v.sel):$(src);
2706
+ if (v.attr!==false) {
2707
+ value=$v.attr(v.attr);
2708
+ }else{
2709
+ value=$v.html();
2710
+ }
2711
+ if (value) {
2712
+ if (v.rgx!==false) {
2713
+ var m = value.match(new RegExp(v.rgx));
2714
+ if (m && m.length==2) {
2715
+ value = m[1];
2716
+ }
2717
+ }
2718
+ params[k]=value.replace(/"/g,"'");
2719
+ }
2720
+ },this))
2721
+ }
2722
+ return params;
2723
+ },
2724
+
2725
+
2726
+ //imgUploader
2727
+ imgLoadModal: function() {
2728
+ $.log("imgLoadModal");
2729
+ if (this.options.imgupload===true) {
2730
+ this.$modal.find("#imguploader").dragfileupload({
2731
+ url: this.strf(this.options.img_uploadurl,this.options),
2732
+ extraParams: {
2733
+ maxwidth: this.options.img_maxwidth,
2734
+ maxheight: this.options.img_maxheight
2735
+ },
2736
+ themePrefix: this.options.themePrefix,
2737
+ themeName: this.options.themeName,
2738
+ success: $.proxy(function(data) {
2739
+ this.$txtArea.insertImage(data.image_link,data.thumb_link);
2740
+
2741
+ this.closeModal();
2742
+ this.updateUI();
2743
+ },this)
2744
+ });
2745
+
2746
+ this.$modal.find("#fileupl").bind("change",function() {
2747
+ $("#fupform").submit();
2748
+ });
2749
+ this.$modal.find("#fupform").bind("submit",$.proxy(function(e) {
2750
+ $(e.target).parents("#imguploader").hide().after('<div class="loader"><img src="'+this.options.themePrefix+'/'+this.options.themeName+'/img/loader.gif" /><br/><span>'+CURLANG.loading+'</span></div>').parent().css("text-align","center");
2751
+ },this))
2752
+
2753
+ }else{
2754
+ this.$modal.find(".hastabs").removeClass("hastabs");
2755
+ this.$modal.find("#imguploader").parents(".tab-cont").remove();
2756
+ this.$modal.find(".wbbm-tablist").remove();
2757
+ }
2758
+ },
2759
+ imgSubmitModal: function() {
2760
+ $.log("imgSubmitModal");
2761
+ },
2762
+ //DEBUG
2763
+ printObjectInIE: function(obj) {
2764
+ try{
2765
+ $.log(JSON.stringify(obj));
2766
+ }catch(e) {}
2767
+ },
2768
+ checkFilter: function(node,filter) {
2769
+ $.log("node: "+$(node).get(0).outerHTML+" filter: "+filter+" res: "+$(node).is(filter.toLowerCase()));
2770
+ },
2771
+ debug: function(msg) {
2772
+ if (this.options.debug===true) {
2773
+ var time = (new Date()).getTime();
2774
+ if (typeof(console)!="undefined") {
2775
+ console.log((time-this.startTime)+" ms: "+msg);
2776
+ }else{
2777
+ $("#exlog").append('<p>'+(time-this.startTime)+" ms: "+msg+'</p>');
2778
+ }
2779
+ this.startTime=time;
2780
+ }
2781
+ },
2782
+
2783
+ //Browser fixes
2784
+ isChrome: function() {
2785
+ return (window.chrome) ? true:false;
2786
+ },
2787
+ fixTableTransform: function(html) {
2788
+ if (!html) {return "";}
2789
+ if ($.inArray("table",this.options.buttons)==-1) {
2790
+ return html.replace(/\<(\/*?(table|tr|td|tbody))[^>]*\>/ig,"");
2791
+ }else{
2792
+ return html.replace(/\<(\/*?(table|tr|td))[^>]*\>/ig,"[$1]".toLowerCase()).replace(/\<\/*tbody[^>]*\>/ig,"");
2793
+ }
2794
+ }
2795
+ }
2796
+
2797
+ $.log = function(msg) {
2798
+ if (typeof(wbbdebug)!="undefined" && wbbdebug===true) {
2799
+ if (typeof(console)!="undefined") {
2800
+ console.log(msg);
2801
+ }else{
2802
+ $("#exlog").append('<p>'+msg+'</p>');
2803
+ }
2804
+ }
2805
+ }
2806
+ $.fn.wysibb = function(settings) {
2807
+ return this.each(function() {
2808
+ var data = $(this).data("wbb");
2809
+ if (!data) {
2810
+ new $.wysibb(this, settings);
2811
+ }
2812
+ });
2813
+ }
2814
+ $.fn.wdrag = function(opt) {
2815
+ if (!opt.scope) {opt.scope=this;}
2816
+ var start={x:0,y:0, height: 0};
2817
+ var drag;
2818
+ opt.scope.drag_mousedown = function(e) {
2819
+ e.preventDefault();
2820
+ start = {
2821
+ x: e.pageX,
2822
+ y: e.pageY,
2823
+ height: opt.height,
2824
+ sheight: opt.scope.$body.height()
2825
+ }
2826
+ drag=true;
2827
+ $(document).bind("mousemove",$.proxy(opt.scope.drag_mousemove,this));
2828
+ $(this).addClass("drag");
2829
+ };
2830
+ opt.scope.drag_mouseup = function(e) {
2831
+ if (drag===true) {
2832
+ e.preventDefault();
2833
+ $(document).unbind("mousemove",opt.scope.drag_mousemove);
2834
+ $(this).removeClass("drag");
2835
+ drag=false;
2836
+ }
2837
+ };
2838
+ opt.scope.drag_mousemove = function(e) {
2839
+ e.preventDefault();
2840
+ var axisX=0,axisY=0;
2841
+ if (opt.axisX) {
2842
+ axisX = e.pageX-start.x;
2843
+ }
2844
+ if (opt.axisY) {
2845
+ axisY = e.pageY-start.y;
2846
+ }
2847
+ if (axisY!=0) {
2848
+ var nheight = start.sheight+axisY;
2849
+ if (nheight>start.height && nheight<=opt.scope.options.resize_maxheight) {
2850
+ if (opt.scope.options.bbmode==true) {
2851
+ opt.scope.$txtArea.css((opt.scope.options.autoresize===true) ? "min-height":"height",nheight+"px");
2852
+ }else{
2853
+ opt.scope.$body.css((opt.scope.options.autoresize===true) ? "min-height":"height",nheight+"px");
2854
+ }
2855
+ }
2856
+ }
2857
+ };
2858
+
2859
+
2860
+ $(this).bind("mousedown",opt.scope.drag_mousedown);
2861
+ $(document).bind("mouseup",$.proxy(opt.scope.drag_mouseup,this));
2862
+ },
2863
+
2864
+ //API
2865
+ $.fn.getDoc = function() {
2866
+ return this.data('wbb').doc;
2867
+ }
2868
+ $.fn.getSelectText = function(fromTextArea) {
2869
+ return this.data('wbb').getSelectText(fromTextArea);
2870
+ }
2871
+ $.fn.bbcode = function(data) {
2872
+ if (typeof(data)!="undefined") {
2873
+ if (this.data('wbb').options.bbmode) {
2874
+ this.data('wbb').$txtArea.val(data);
2875
+ }else{
2876
+ this.data('wbb').$body.html(this.data("wbb").getHTML(data));
2877
+ }
2878
+ return this;
2879
+ }else{
2880
+ return this.data('wbb').getBBCode();
2881
+ }
2882
+ }
2883
+ $.fn.htmlcode = function(data) {
2884
+ if (!this.data('wbb').options.onlyBBMode && this.data('wbb').inited===true) {
2885
+ if (typeof(data)!="undefined") {
2886
+ this.data('wbb').$body.html(data);
2887
+ return this;
2888
+ }else{
2889
+ return this.data('wbb').getHTML(this.data('wbb').$txtArea.val());
2890
+ }
2891
+ }
2892
+ }
2893
+ $.fn.getBBCode = function() {
2894
+ return this.data('wbb').getBBCode();
2895
+ }
2896
+ $.fn.getHTML = function() {
2897
+ var wbb = this.data('wbb');
2898
+ return wbb.getHTML(wbb.$txtArea.val());
2899
+ }
2900
+ $.fn.getHTMLByCommand = function(command,params) {
2901
+ return this.data("wbb").getHTMLByCommand(command,params);
2902
+ }
2903
+ $.fn.getBBCodeByCommand = function(command,params) {
2904
+ return this.data("wbb").getBBCodeByCommand(command,params);
2905
+ }
2906
+ $.fn.insertAtCursor = function(data,forceBBMode) {
2907
+ this.data("wbb").insertAtCursor(data,forceBBMode);
2908
+ return this.data("wbb");
2909
+ }
2910
+ $.fn.execCommand = function(command,value) {
2911
+ this.data("wbb").execCommand(command,value);
2912
+ return this.data("wbb");
2913
+ }
2914
+ $.fn.insertImage = function(imgurl,thumburl) {
2915
+ var editor = this.data("wbb");
2916
+ var code = (thumburl) ? editor.getCodeByCommand('link',{url:imgurl,seltext: editor.getCodeByCommand('img',{src:thumburl})}): editor.getCodeByCommand('img',{src:imgurl});
2917
+ this.insertAtCursor(code);
2918
+ return editor;
2919
+ }
2920
+ $.fn.sync = function() {
2921
+ this.data("wbb").sync();
2922
+ return this.data("wbb");
2923
+ }
2924
+ $.fn.destroy = function() {
2925
+ this.data("wbb").destroy();
2926
+ }
2927
+
2928
+
2929
+ $.fn.queryState = function(command) {
2930
+ return this.data("wbb").queryState(command);
2931
+ }
2932
+ })(jQuery);
2933
+
2934
+
2935
+ //Drag&Drop file uploader
2936
+ (function($) {
2937
+ 'use strict';
2938
+
2939
+ $.fn.dragfileupload = function(options) {
2940
+ return this.each(function() {
2941
+ var upl = new FileUpload(this, options);
2942
+ upl.init();
2943
+ });
2944
+ };
2945
+
2946
+ function FileUpload(e, options) {
2947
+ this.$block=$(e);
2948
+
2949
+ this.opt = $.extend({
2950
+ url: false,
2951
+ success: false,
2952
+ extraParams: false,
2953
+ fileParam: 'img',
2954
+ validation: '\.(jpg|png|gif|jpeg)$',
2955
+
2956
+ t1: CURLANG.fileupload_text1,
2957
+ t2: CURLANG.fileupload_text2
2958
+ },options);
2959
+ }
2960
+
2961
+ FileUpload.prototype = {
2962
+ init: function() {
2963
+ if (window.FormData != null) {
2964
+ this.$block.addClass("drag");
2965
+ this.$block.prepend('<div class="p2">'+this.opt.t2+'</div>');
2966
+ this.$block.prepend('<div class="p">'+this.opt.t1+'</div>');
2967
+
2968
+ this.$block.bind('dragover', function() {$(this).addClass('dragover');return false;});
2969
+ this.$block.bind('dragleave', function() {$(this).removeClass('dragover');return false;});
2970
+
2971
+ //upload progress
2972
+ var uploadProgress = $.proxy(function(e) {
2973
+ var p = parseInt(e.loaded/e.total*100, 10);
2974
+ this.$loader.children("span").text(CURLANG.loading+': '+ p+'%');
2975
+
2976
+ }, this);
2977
+ var xhr = jQuery.ajaxSettings.xhr();
2978
+ if (xhr.upload) {
2979
+ xhr.upload.addEventListener('progress', uploadProgress, false);
2980
+ }
2981
+ this.$block[0].ondrop = $.proxy(function(e) {
2982
+ e.preventDefault();
2983
+ this.$block.removeClass('dragover');
2984
+ var ufile = e.dataTransfer.files[0];
2985
+ if (this.opt.validation && !ufile.name.match(new RegExp(this.opt.validation))) {
2986
+ this.error(CURLANG.validation_err);
2987
+ return false;
2988
+ }
2989
+ var fData = new FormData();
2990
+ fData.append(this.opt.fileParam, ufile);
2991
+
2992
+ if (this.opt.extraParams) { //check for extraParams to upload
2993
+ $.each(this.opt.extraParams,function(k,v) {
2994
+ fData.append(k, v);
2995
+ });
2996
+ }
2997
+
2998
+ this.$loader = $('<div class="loader"><img src="'+this.opt.themePrefix+'/'+this.opt.themeName+'/img/loader.gif" /><br/><span>'+CURLANG.loading+'</span></div>');
2999
+ this.$block.html(this.$loader);
3000
+
3001
+ $.ajax({
3002
+ type: 'POST',
3003
+ url: this.opt.url,
3004
+ data: fData,
3005
+ processData: false,
3006
+ contentType: false,
3007
+ xhr: function() {return xhr},
3008
+ dataType: 'json',
3009
+ success: $.proxy(function(data) {
3010
+ if (data && data.status==1) {
3011
+ this.opt.success(data);
3012
+ }else{
3013
+ this.error(data.msg || CURLANG.error_onupload);
3014
+ }
3015
+ },this),
3016
+ error: $.proxy(function (xhr, txt, thr) {this.error(CURLANG.error_onupload)},this)
3017
+ });
3018
+ },this);
3019
+
3020
+ }
3021
+ },
3022
+ error: function(msg) {
3023
+ this.$block.find(".upl-error").remove().end().append('<span class="upl-error">'+msg+'</span>').addClass("wbbm-brdred");
3024
+ }
3025
+ }
3026
+ })(jQuery);