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