/*! WysiBB - WYSIWYG BBCode editor - v1.3.0 - 2012-11-28
* http://www.wysibb.com
* Copyright (c) 2012 Vadim Dobroskok; Licensed MIT, GPL */
if (typeof (WBBLANG) == "undefined") {
WBBLANG = {};
}
WBBLANG['ru'] = CURLANG = {
bold:"Полужирный",
italic:"Курсив",
underline:"Подчеркнутый",
strike:"Зачеркнутый",
link:"Ссылка",
img:"Изображение",
sup:"Надстрочный текст",
sub:"Подстрочный текст",
justifyleft:"Текст по левому краю",
justifycenter:"Текст по центру",
justifyright:"Текст по правому краю",
table:"Вставить таблицу",
bullist:"Обычный список",
numlist:"Нумерованный список",
quote:"Цитата",
offtop:"Оффтоп",
code:"Код",
spoiler:"Сворачиваемый текст",
fontcolor:"Цвет текста",
fontsize:"Размер текста",
fontfamily:"Шрифт текста",
fs_verysmall:"Очень маленький",
fs_small:"Маленький",
fs_normal:"Нормальный",
fs_big:"Большой",
fs_verybig:"Очень большой",
smilebox:"Вставить смайл",
video:"Вставить видео",
removeFormat:"Удалить форматирование",
modal_link_title:"Вставить ссылку",
modal_link_text:"Отображаемый текст",
modal_link_url:"URL ссылки",
modal_link_target:"Открывать в новом окне",
modal_email_text:"Отображаемый эл.адрес",
modal_email_url:"Email",
modal_link_tab1:"Вставить URL",
modal_img_title:"Вставить изображение",
modal_img_tab1:"Ввести URL",
modal_img_tab2:"Загрузить файл",
modal_imgsrc_text:"Введите адрес изображения",
modal_img_btn:"Выберите файл для загрузки",
add_attach:"Добавить вложение",
modal_video_text:"Введите URL видео",
close:"Закрыть",
save:"Сохранить",
cancel:"Отмена",
remove:"Удалить",
validation_err:"Введенные данные некорректны",
error_onupload:"Ошибка во время загрузки файла или такое расширение файла не поддерживается",
fileupload_text1:"Перетащите файл сюда",
fileupload_text2:"или",
loading:"Загрузка",
auto:"Авто",
views:"Просмотров",
downloads:"Скачиваний",
//smiles
sm1:"Улыбка",
sm2:"Смех",
sm3:"Подмигивание",
sm4:"Спасибо, класс",
sm5:"Ругаю",
sm6:"Шок",
sm7:"Злой",
sm8:"Огорчение",
sm9:"Тошнит"
};
var wbbdebug = true;
(function ($) {
'use strict';
$.wysibb = function (txtArea, settings) {
$(txtArea).data("wbb", this);
if (settings && settings.deflang && typeof(WBBLANG[settings.deflang]) != "undefined") {
CURLANG = WBBLANG[settings.deflang];
}
if (settings && settings.lang && typeof(WBBLANG[settings.lang]) != "undefined") {
CURLANG = WBBLANG[settings.lang];
}
this.txtArea = txtArea;
this.$txtArea = $(txtArea);
var id = this.$txtArea.attr("id") || this.setUID(this.txtArea);
this.options = {
bbmode:false,
onlyBBmode:false,
themeName:"default",
bodyClass:"",
lang:"ru",
tabInsert:true,
// toolbar: false,
//img upload config
imgupload:true,
img_uploadurl:"/iupload.php",
img_maxwidth:800,
img_maxheight:800,
hotkeys:true,
showHotkeys:true,
autoresize:true,
resize_maxheight:800,
loadPageStyles:true,
traceTextarea:true,
// direction: "ltr",
smileConversion:true,
//END img upload config
buttons:"bold,italic,underline,strike,sup,sub,|,img,video,link,|,bullist,numlist,smilebox,|,fontcolor,fontsize,fontfamily,|,justifyleft,justifycenter,justifyright,|,quote,code,offtop,table,removeFormat",
allButtons:{
bold:{
title:CURLANG.bold,
buttonHTML:'\uE000',
excmd:'bold',
hotkey:'ctrl+b',
transform:{
'{SELTEXT}':"[b]{SELTEXT}[/b]",
'{SELTEXT}':"[b]{SELTEXT}[/b]"
}
},
italic:{
title:CURLANG.italic,
buttonHTML:'\uE001',
excmd:'italic',
hotkey:'ctrl+i',
transform:{
'{SELTEXT}':"[i]{SELTEXT}[/i]",
'{SELTEXT}':"[i]{SELTEXT}[/i]"
}
},
underline:{
title:CURLANG.underline,
buttonHTML:'\uE002',
excmd:'underline',
hotkey:'ctrl+u',
transform:{
'{SELTEXT}':"[u]{SELTEXT}[/u]"
}
},
strike:{
title:CURLANG.strike,
buttonHTML:'\uE003',
excmd:'strikeThrough',
transform:{
'{SELTEXT}':"[s]{SELTEXT}[/s]",
'{SELTEXT}':"[s]{SELTEXT}[/s]"
}
},
sup:{
title:CURLANG.sup,
buttonHTML:'\uE005',
excmd:'superscript',
transform:{
'{SELTEXT}':"[sup]{SELTEXT}[/sup]"
}
},
sub:{
title:CURLANG.sub,
buttonHTML:'\uE004',
excmd:'subscript',
transform:{
'{SELTEXT}':"[sub]{SELTEXT}[/sub]"
}
},
link:{
title:CURLANG.link,
buttonHTML:'\uE007',
hotkey:'ctrl+shift+2',
modal:{
title:CURLANG.modal_link_title,
width:"500px",
tabs:[
{
input:[
{param:"SELTEXT", title:CURLANG.modal_link_text, type:"div"},
{param:"URL", title:CURLANG.modal_link_url, validation:'^http(s)?://'},
]
}
]
},
transform:{
'{SELTEXT}':"[url={URL}]{SELTEXT}[/url]"
}
},
img:{
title:CURLANG.img,
buttonHTML:'\uE006',
hotkey:'ctrl+shift+1',
modal:{
title:CURLANG.modal_img_title,
width:"600px",
tabs:[
{
title:CURLANG.modal_img_tab1,
input:[
{param:"SRC", title:CURLANG.modal_imgsrc_text, validation:'^http(s)?://.*?\.(jpg|png|gif|jpeg)$'}
]
}/*,
{
title:CURLANG.modal_img_tab2,
html:'
{SELTEXT}
':'[left]{SELTEXT}[/left]' } }, justifyright:{ title:CURLANG.justifyright, buttonHTML:'\uE016', groupkey:'align', transform:{ '{SELTEXT}
':'[right]{SELTEXT}[/right]' } }, justifycenter:{ title:CURLANG.justifycenter, buttonHTML:'\uE014', groupkey:'align', transform:{ '{SELTEXT}
':'[center]{SELTEXT}[/center]' } }, video:{ title:CURLANG.video, buttonHTML:'\uE008', modal:{ title:CURLANG.video, width:"600px", tabs:[ { title:CURLANG.video, input:[ {param:"SRC", title:CURLANG.modal_video_text} ] } ], onSubmit:function (cmd, opt, queryState) { var url = this.$modal.find('input[name="SRC"]').val(); var a; if (url.indexOf("youtu.be") != -1) { a = url.match(/^http:\/\/youtu\.be\/([a-z0-9_]+)/i); } else { a = url.match(/^http:\/\/www\.youtube\.com\/watch\?.*?v=([a-z0-9_]+)/i); } if (a && a.length == 2) { var code = a[1]; this.insertAtCursor(this.getCodeByCommand(cmd, {src:code})); } this.closeModal(); this.updateUI(); return false; } }, transform:{ '':'[video]{SRC}[/video]' } }, //select options fs_verysmall:{ title:CURLANG.fs_verysmall, buttonText:"fs1", excmd:'fontSize', exvalue:"1", transform:{ '{SELTEXT}':'[size=50]{SELTEXT}[/size]' } }, fs_small:{ title:CURLANG.fs_small, buttonText:"fs2", excmd:'fontSize', exvalue:"2", transform:{ '{SELTEXT}':'[size=85]{SELTEXT}[/size]' } }, fs_normal:{ title:CURLANG.fs_normal, buttonText:"fs3", excmd:'fontSize', exvalue:"3", transform:{ '{SELTEXT}':'[size=100]{SELTEXT}[/size]' } }, fs_big:{ title:CURLANG.fs_big, buttonText:"fs4", excmd:'fontSize', exvalue:"4", transform:{ '{SELTEXT}':'[size=150]{SELTEXT}[/size]' } }, fs_verybig:{ title:CURLANG.fs_verybig, buttonText:"fs5", excmd:'fontSize', exvalue:"6", transform:{ '{SELTEXT}':'[size=200]{SELTEXT}[/size]' } }, removeformat:{ title:CURLANG.removeFormat, buttonHTML:'\uE00f', excmd:"removeFormat" } }, systr:{ '
', bbcode:":)"},
{title:CURLANG.sm8, img:'
', bbcode:":("},
{title:CURLANG.sm1, img:'
', bbcode:":D"},
{title:CURLANG.sm3, img:'
', bbcode:";)"},
{title:CURLANG.sm4, img:'
', bbcode:":up:"},
{title:CURLANG.sm5, img:'
', bbcode:":down:"},
{title:CURLANG.sm6, img:'
', bbcode:":shock:"},
{title:CURLANG.sm7, img:'
', bbcode:":angry:"},
{title:CURLANG.sm9, img:'
', bbcode:":sick:"}
],
attrWrap:['src', 'color', 'href'] //use becouse FF and IE change values for this attr, modify [attr] to _[attr]
}
//FIX for Opera. Wait while iframe loaded
this.inited = this.options.onlyBBmode;
//init css prefix, if not set
if (!this.options.themePrefix) {
$('link').each($.proxy(function (idx, el) {
var sriptMatch = $(el).get(0).href.match(/(.*\/)(.*)\/wbbtheme\.css.*$/);
if (sriptMatch !== null) {
this.options.themeName = sriptMatch[2];
this.options.themePrefix = sriptMatch[1];
}
}, this));
}
//check for preset
if (typeof(WBBPRESET) != "undefined") {
if (WBBPRESET.allButtons) {
//clear transform
$.each(WBBPRESET.allButtons, $.proxy(function (k, v) {
if (v.transform && this.options.allButtons[k]) {
delete this.options.allButtons[k].transform;
}
}, this));
}
$.extend(true, this.options, WBBPRESET);
}
if (settings && settings.allButtons) {
$.each(settings.allButtons, $.proxy(function (k, v) {
if (v.transform && this.options.allButtons[k]) {
delete this.options.allButtons[k].transform;
}
}, this));
}
$.extend(true, this.options, settings);
this.init();
}
$.wysibb.prototype = {
lastid:1,
init:function () {
$.log("Init", this);
//check for mobile
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);
//use bbmode on mobile devices
if (this.isMobile) {
this.onlyBBmode = this.bbmode = true
}
//create array of controls, for queryState
this.controllers = [];
//convert button string to array
this.options.buttons = this.options.buttons.toLowerCase();
this.options.buttons = this.options.buttons.split(",");
//init system transforms
this.options.allButtons["_systr"] = {};
this.options.allButtons["_systr"]["transform"] = this.options.systr;
this.smileFind();
this.initTransforms();
this.build();
this.initModal();
if (this.options.hotkeys === true && !this.isMobile) {
this.initHotkeys();
}
//sort smiles
if (this.options.smileList && this.options.smileList.length > 0) {
this.options.smileList.sort(function (a, b) {
return (b.bbcode.length - a.bbcode.length);
})
}
this.$txtArea.parents("form").bind("submit", $.proxy(function () {
this.sync();
return true;
}, this));
//phpbb2
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 () {
this.sync();
setTimeout($.proxy(function () {
if (this.options.bbmode === false) {
this.$txtArea.removeAttr("wbbsync").val("");
}
}, this), 1000);
}, this));
//end phpbb2
if (this.options.initCallback) {
this.options.initCallback.call(this);
}
$.log(this);
},
initTransforms:function () {
$.log("Create rules for transform HTML=>BB");
var o = this.options;
//need to check for active buttons
if (!o.rules) {
o.rules = {};
}
if (!o.groups) {
o.groups = {};
} //use for groupkey, For example: justifyleft,justifyright,justifycenter. It is must replace each other.
var btnlist = o.buttons.slice();
//add system transform
btnlist.push("_systr");
for (var bidx = 0; bidx < btnlist.length; bidx++) {
var ob = o.allButtons[btnlist[bidx]];
if (!ob) {
continue;
}
ob.en = true;
//add transforms to option list
if (ob.type == "select" && typeof(ob.options) == "string") {
var olist = ob.options.split(",");
$.each(olist, function (i, op) {
if ($.inArray(op, btnlist) == -1) {
btnlist.push(op);
}
});
}
if (ob.transform && ob.skipRules !== true) {
var obtr = $.extend({}, ob.transform);
for (var bhtml in obtr) {
var orightml = bhtml;
var bbcode = ob.transform[bhtml];
//wrap attributes
$.each(o.attrWrap, function (i, a) {
bhtml = bhtml.replace(a + '="', '_' + a + '="');
});
var $bel = $(document.createElement('DIV')).append($(this.elFromString(bhtml, document)));
var rootSelector = this.filterByNode($bel.children());
//check if current rootSelector is exist, create unique selector for each transform (1.2.2)
if (rootSelector == "div" || typeof(o.rules[rootSelector]) != "undefined") {
//create unique selector
$.log("create unique selector: " + rootSelector);
this.setUID($bel.children());
rootSelector = this.filterByNode($bel.children());
//replace transform with unique selector
var nhtml2 = $bel.html();
ob.transform[nhtml2] = bbcode;
delete ob.transform[bhtml];
bhtml = nhtml2;
}
//create root selector for isContain
if (!ob.excmd) {
if (!ob.rootSelector) {
ob.rootSelector = [];
}
ob.rootSelector.push(rootSelector);
}
if (!ob.bbSelector) {
ob.bbSelector = [];
}
if ($.inArray(bbcode, ob.bbSelector) == -1) {
ob.bbSelector.push(bbcode);
}
//check for rules on this rootSeletor
if (typeof(o.rules[rootSelector]) == "undefined") {
o.rules[rootSelector] = [];
}
var crules = {};
if (bhtml.match(/\{\S+?\}/)) {
$bel.find('*').each($.proxy(function (idx, el) {
//check attributes
var attributes = this.getAttributeList(el);
$.each(attributes, $.proxy(function (i, item) {
var attr = $(el).attr(item);
if (item.substr(0, 1) == '_') {
item = item.substr(1);
}
var r = attr.match(/\{\S+?\}/g);
if (r) {
for (var a = 0; a < r.length; a++) {
var rname = r[a].substr(1, r[a].length - 2);
rname = rname.replace(this.getValidationRGX(rname), "");
var p = this.relFilterByNode(el, rootSelector);
var regRepl = (attr != r[a]) ? this.getRegexpReplace(attr, r[a]) : false;
crules[rname.toLowerCase()] = {sel:(p) ? $.trim(p) : false, attr:item, rgx:regRepl}
}
}
}, this));
//check for text
var sl = [];
if (!$(el).is("iframe")) {
$(el).contents().filter(function () {
return this.nodeType === 3
}).each($.proxy(function (i, rel) {
var txt = rel.textContent || rel.data;
if (typeof(txt) == "undefined") {
return true;
}
var r = txt.match(/\{\S+?\}/g)
if (r) {
for (var a = 0; a < r.length; a++) {
var rname = r[a].substr(1, r[a].length - 2);
rname = rname.replace(this.getValidationRGX(rname), "");
var p = this.relFilterByNode(el, rootSelector);
var regRepl = (txt != r[a]) ? this.getRegexpReplace(txt, r[a]) : false;
var sel = (p) ? $.trim(p) : false;
if ($.inArray(sel, sl) > -1 || $(rel).parent().contents().size() > 1) {
//has dublicate and not one children, need wrap
var nel = $("").html("{" + rname + "}");
this.setUID(nel, "wbb");
var start = (txt.indexOf(rname) + rname.length) + 1;
var after_txt = txt.substr(start, txt.length - start);
//create wrap element
rel.data = txt.substr(0, txt.indexOf(rname) - 1);
$(rel).after(this.elFromString(after_txt, document)).after(nel);
sel = ((sel) ? sel + " " : "") + this.filterByNode(nel);
regRepl = false;
}
crules[rname.toLowerCase()] = {sel:sel, attr:false, rgx:regRepl}
sl[sl.length] = sel;
}
}
}, this));
}
sl = null;
}, this));
var nbhtml = $bel.html();
//UnWrap attributes
$.each(o.attrWrap, function (i, a) {
nbhtml = nbhtml.replace('_' + a + '="', a + '="');
});
if (orightml != nbhtml) {
//if we modify html, replace it
delete ob.transform[orightml];
ob.transform[nbhtml] = bbcode;
bhtml = nbhtml;
}
}
o.rules[rootSelector].push([bbcode, crules]);
//check for onlyClearText
if (ob.onlyClearText === true) {
if (!this.cleartext) {
this.cleartext = {};
}
this.cleartext[rootSelector] = btnlist[bidx];
}
//check for groupkey
if (ob.groupkey) {
if (!o.groups[ob.groupkey]) {
o.groups[ob.groupkey] = []
}
o.groups[ob.groupkey].push(rootSelector);
}
}
var htmll = $.map(ob.transform,function (bb, html) {
return html
}).sort(function (a, b) {
return ((b[0] || "").length - (a[0] || "").length)
});
ob.bbcode = ob.transform[htmll[0]];
ob.html = htmll[0];
}
}
;
this.options.btnlist = btnlist; //use for transforms, becouse select elements not present in buttons
//add custom rules, for table,tr,td and other
$.extend(o.rules, this.options.customRules);
//smile rules
o.srules = {};
if (this.options.smileList) {
$.each(o.smileList, $.proxy(function (i, sm) {
var $sm = $(this.strf(sm.img, o));
var f = this.filterByNode($sm);
o.srules[f] = [sm.bbcode, sm.img];
}, this));
}
//sort transforms by bbcode length desc
for (var rootsel in o.rules) {
this.options.rules[rootsel].sort(function (a, b) {
return (b[0].length - a[0].length)
});
}
//create rootsel list
this.rsellist = [];
for (var rootsel in this.options.rules) {
this.rsellist.push(rootsel);
}
this.sortArray(this.rsellist, -1);
},
//BUILD
build:function () {
$.log("Build editor");
//this.$editor = $('