/** * Wrapper for CKEditor based goodness * Written by Matt Mecham for his sins. * (c) 2011 IPS, Inc. */ /** * From: http://phpjs.org * By: Kevin van Zonneveld (http://kevin.vanzonneveld.net), Martijn Wieringa */ phpjs = { substr_count: function(haystack, needle, offset, length) { var pos = 0, cnt = 0; haystack += ''; needle += ''; if (isNaN(offset)) { offset = 0; } if (isNaN(length)) { length = 0; } offset--; while ((offset = haystack.indexOf(needle, offset + 1)) != -1) { if (length > 0 && (offset + needle.length) > length) { return false; } else { cnt++; } } return cnt; }, stristr: function(haystack, needle, bool) { var pos = 0; haystack += ''; pos = haystack.toLowerCase().indexOf((needle + '').toLowerCase()); if (pos == -1) { return false; } else { if (bool) { return haystack.substr(0, pos); } else { return haystack.slice(pos); } } }, stripos: function (f_haystack, f_needle, f_offset) { var haystack = (f_haystack + '').toLowerCase(); var needle = (f_needle + '').toLowerCase(); var index = 0; if ((index = haystack.indexOf(needle, f_offset)) !== -1) { return index; } return false; }, substr: function(str, start, len) { str += ''; var end = str.length; if (start < 0) { start += end; } end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start); return start >= str.length || start < 0 || start > end ? !1 : str.slice(start, end); }, substr_replace: function(str, replace, start, length) { if (start < 0) { // start position in str start = start + str.length; } length = length !== undefined ? length : str.length; if (length < 0) { length = length + str.length - start; } return str.slice(0, start) + replace.substr(0, length) + replace.slice(length) + str.slice(start + length); }, strlen: function( str ) { return str.length; }, strrpos: function(haystack, needle, offset) { var i = -1; if (offset) { i = (haystack + '').slice(offset).lastIndexOf(needle); // strrpos' offset indicates starting point of range till end, // while lastIndexOf's optional 2nd argument indicates ending point of range from the beginning if (i !== -1) { i += offset; } } else { i = (haystack + '').lastIndexOf(needle); } return i >= 0 ? i : false; }, str_ireplace: function(search, replace, subject) { var i, k = ''; var searchl = 0; var reg; var escapeRegex = function (s) { return s.replace(/([\\\^\$*+\[\]?{}.=!:(|)])/g, '\\$1'); }; search += ''; searchl = search.length; if (Object.prototype.toString.call(replace) !== '[object Array]') { replace = [replace]; if (Object.prototype.toString.call(search) === '[object Array]') { // If search is an array and replace is a string, // then this replacement string is used for every value of search while (searchl > replace.length) { replace[replace.length] = replace[0]; } } } if (Object.prototype.toString.call(search) !== '[object Array]') { search = [search]; } while (search.length > replace.length) { // If replace has fewer values than search, // then an empty string is used for the rest of replacement values replace[replace.length] = ''; } if (Object.prototype.toString.call(subject) === '[object Array]') { // If subject is an array, then the search and replace is performed // with every entry of subject , and the return value is an array as well. for (k in subject) { if (subject.hasOwnProperty(k)) { subject[k] = str_ireplace(search, replace, subject[k]); } } return subject; } searchl = search.length; for (i = 0; i < searchl; i++) { reg = new RegExp(escapeRegex(search[i]), 'gi'); subject = subject.replace(reg, replace[i]); } return subject; }, /* Based on @link http://coding.pressbin.com/16/Javascript-equivalent-of-PHPs-pregmatchall */ preg_match_all: function(regex, haystack) { var globalRegex = new RegExp(regex, 'gi'); var globalMatch = haystack.match(globalRegex); matchArray = new Array(); try { $(globalMatch).each( function( i ) { nonGlobalRegex = new RegExp(regex, 'i'); nonGlobalMatch = i.match(nonGlobalRegex); matchArray.push(nonGlobalMatch); } ); } catch(err){} return matchArray; } }; ipsTextArea = { /** * Insert text at the cursor position * Some code from * @link http://bytes.com/topic/javascript/answers/149268-moving-cursor-end-textboxes-text * @param editorId * @param text */ insertAtCursor: function( editorId, text ) { var te = $('cke_' + editorId).down('textarea'); var scrollPos = te.scrollTop; if ( CKEDITOR.env.ie ) { te.focus(); sel = document.selection.createRange(); sel.text = text; sel.select(); } else if ( te.selectionStart || te.selectionStart == '0' ) { var startPos = te.selectionStart; var endPos = te.selectionEnd; te.value = te.value.substring(0, startPos) + text + te.value.substring(endPos, te.value.length); if ( startPos == endPos ) { this.setSelectionRange( te, startPos + text.length, endPos + text.length ); } else { this.setCaretToPos( te, startPos + text.length ); } } else { te.value += text; } te.scrollTop = scrollPos; }, /** * Set selection range * Some code from * @link http://bytes.com/topic/javascript/answers/149268-moving-cursor-end-textboxes-text */ setSelectionRange: function(input, selectionStart, selectionEnd) { if ( input.setSelectionRange ) { input.focus(); input.setSelectionRange(selectionStart, selectionEnd); } else if ( input.createTextRange ) { var range = input.createTextRange(); range.collapse(true); range.moveEnd('character', selectionEnd); range.moveStart('character', selectionStart); range.select(); } }, /** * Set caret position * Some code from * @link http://bytes.com/topic/javascript/answers/149268-moving-cursor-end-textboxes-text */ setCaretToPos: function( input, pos ) { this.setSelectionRange( input, pos, pos ); } }; IPSCKTools = { getEmbeddedTagPositions: function( txt, tag, brackets ) { if ( ! ( brackets instanceof Array ) ) { brackets = [ '[', ']' ]; } var close_tag = brackets[0] + '/' + tag + brackets[1]; var open_tag = brackets[0] + tag; var map = { open: {}, close: {} }; var iteration = 0; var curPos = 0; /* Pick through bit of code */ while( ( curPos = phpjs.stripos( txt, open_tag, curPos ) ) !== false ) { if ( iteration > 1000 ) { break; } /* Make sure the next character is either ] = or a space */ var nextChar = phpjs.substr( txt, curPos + phpjs.strlen( tag ) + 1, 1 ); if ( nextChar != brackets[1] && nextChar != '=' && nextChar != ' ' ) { if( curPos > phpjs.strlen(txt) ) { curPos = 0; break; } curPos++; } else { map['open'][ iteration ] = curPos + phpjs.strlen( open_tag ); var new_pos = phpjs.stripos( txt, brackets[0], curPos ) ? phpjs.stripos( txt, brackets[0], curPos ) : curPos + 1; /* Got an option, grab that */ var _option = phpjs.substr( txt, curPos + phpjs.strlen(open_tag), (phpjs.stripos( txt, brackets[1], curPos ) - (curPos + phpjs.strlen(open_tag) )) ); map['open'][ iteration ] += parseInt( phpjs.strlen( _option ) ) + 1; /* Got a closing tag? */ var closingTagPos = phpjs.stripos( txt, close_tag, new_pos ); if ( closingTagPos !== false ) { map['close'][ iteration ] = closingTagPos; var _content = phpjs.substr( txt, (curPos + phpjs.strlen( open_tag ) + phpjs.strlen(_option) + 1), (closingTagPos - (curPos + phpjs.strlen(open_tag) + phpjs.strlen(_option) + 1)) ); /* Did we have an opening tag in that mess? */ if ( _content && phpjs.stristr( _content, open_tag ) ) { var count = phpjs.substr_count( _content.toLowerCase(), open_tag.toLowerCase() ); /* Found N opening tags in portion of text */ if ( count > 0 ) { /* So now find Nth closing tag */ var _nPos = closingTagPos + phpjs.strlen( close_tag ); while( count > 0 ) { _closePos = phpjs.stripos( txt, close_tag, _nPos ); if ( _closePos !== false ) { map['close'][ iteration ] = _closePos; _content = phpjs.substr( txt, (curPos + phpjs.strlen( open_tag ) + phpjs.strlen(_option) + 1), (_closePos - (curPos + phpjs.strlen(open_tag) + phpjs.strlen(_option) + 1)) ); count = phpjs.substr_count( _content.toLowerCase(), open_tag.toLowerCase() ); _nPos = _closePos + phpjs.strlen( close_tag ); if ( ! isNaN( _nPos ) && _nPos > phpjs.strlen( txt ) ) { count = 0; } } else { count = 0; } } } } } iteration++; curPos = closingTagPos ? closingTagPos : curPos + 1; if ( curPos > phpjs.strlen(txt) ) { curPos = 0; break; } } } return map; }, /** * Get the selected HTML from the editor * @param object */ getSelectionHtml: function( editor ) { var selection = editor.getSelection(); if ( CKEDITOR.env.ie ) { try { if ( ! Prototype.Browser.IE8 ) { selection.unlock(true); } } catch(e){} try { var text = selection.getNative().createRange().htmlText; if ( text.toLowerCase().strip() == '
' ) { return ''; } return text; } catch( e ){ return false; } } else if ( CKEDITOR.env.opera ) { var selection = selection.getNative(); var range = selection ? selection.getRangeAt(0) : selection.createRange(); var div = document.createElement('div'); div.appendChild( range.cloneContents() ); return div.innerHTML.replace( /
<\/p>/g, '
" + ipb.lang['ck_bbcode_desc'] + "
))<\/pre>)/ ) )
{
var find = _matches[0].regExpEscape();
var replace = '';
/* Dollar signs in the code confuse javascript into thinking it's a replacement placeholder. */
_matches[0] = _matches[0].replace( /\$/g, '$' );
codeBlocks[ _c ] = _matches[0];
text = text.replace( new RegExp( find, 'g' ), replace );
_c++;
}
while( _matches = text.match( /(\[code((\n|.)+?(?=\[\/code\]))\[\/code\])/ ) )
{
var find = _matches[0].regExpEscape();
var replace = '';
/* Dollar signs in the code confuse javascript into thinking it's a replacement placeholder. */
_matches[0] = _matches[0].replace( /\$/g, '$' );
codeBlocks[ _c ] = _matches[0];
text = text.replace( new RegExp( find, 'g' ), replace );
_c++;
}
if ( $(IPS_smiles.emoticons) )
{
$(IPS_smiles.emoticons).each( function( grin )
{
if ( grin.text !== null )
{
emoPosition = 0;
var testEmo = grin.text;
testEmo = testEmo.replace( //g, '>' );
testEmo = testEmo.replace( /\[/g, '[' );
testEmo = testEmo.replace( /\]/g, ']' );
while ( ( position = phpjs.stripos( text, testEmo, emoPosition ) ) !== false )
{
lastOpenTagPosition = phpjs.strrpos( phpjs.substr( text, 0, position ), '[' );
lastCloseTagPosition = phpjs.strrpos( phpjs.substr( text, 0, position ), ']' );
if ( ( position === 0 || phpjs.stripos( invalidWrappers, phpjs.substr( text, position - 1, 1 ) ) === false )
&& ( ( lastOpenTagPosition === false || lastCloseTagPosition === false ) || ( lastCloseTagPosition !== false && lastCloseTagPosition > lastOpenTagPosition ) )
&& ( phpjs.strlen( text ) == ( position + phpjs.strlen( testEmo ) ) || phpjs.stripos( invalidWrappers, phpjs.substr( text, ( position + phpjs.strlen( testEmo ) ), 1 ) ) === false ) )
{
var replace = '
';
text = phpjs.substr_replace( text, replace, position, phpjs.strlen( testEmo ) );
position += phpjs.strlen( replace );
}
emoPosition = position + 1;
if ( emoPosition > phpjs.strlen( text ) )
{
break;
}
}
}
} );
}
/* Change back... */
var _c = 0;
$(codeBlocks).each( function( code )
{
text = text.replace( new RegExp( '', 'g' ), codeBlocks[ _c ] );
_c++;
} );
return text;
},
/**
* Make safe for CKEditor
*/
ckPre: function( text )
{
text = text.replace( '