--=REKLAMA=--
Uwaga: aby zobaczyć zmiany po zapisaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.
/* ------------------------------------------------------------------------ *\ copyright: ©2010-2013 Maciej Jaros (pl:User:Nux, en:User:EcceNux) license: GNU General Public License v2, http://opensource.org/licenses/gpl-license.php OR CC-BY-SA http://creativecommons.org/licenses/by-sa/3.0/deed.pl Libraries used: * jQuery (keypress, preventDefault) * sel_t * wikibits Best <del>viewed</del> edited in Netbeans 7.3+. ;-) Jest be sure to add: -J-Dfile.encoding=UTF-8 in [netbeans installation dir]\etc\netbeans.conf in netbeans_default_options \* ------------------------------------------------------------------------ */ /** * Text box keys listener class that allows to add actions for certain key combinations. * * @param {String} textBoxId Id of the text box. * @returns {nuxTBKeys} */ function nuxTBKeys(textBoxId) { /** @type nuxTBKeys */ var _this = this; /** * Version - just for show ;-) * @type String */ this.ver = this.version = '1.0.2'; // Colectors and helpers var $input, input; // jQuery and DOM input var pressedCharsBuffer = ''; // pressed chars buffer var interestingChars = ''; // chars of interest within the script var maxChars = 0; // max chars that might be interesting for the script var isDisabled = false; /** * Replacements array (filled by addReplacements). * * @type Array */ var arrReplacements = []; /** * Escape string before creating a RegExp. * * @param {String} str String to be used in new RegExp. * @returns {String} */ var escapeStr4RegExp = function(str) { return str.replace(/([\[\]\{\}\|\.\*\?\(\)\$\^\\])/g,'\\$1'); }; /** * Adds a single replacement rule, should be called before init() * * Note: rules added at the begining will be checked first. * Also: rule match will prevent any following from matching. * * from - string to be replaced * to - string to insert instead * beforeForbidden - string that must not be appear just before or text before nust not match: `{re:/.../,maxCheck:123}` * beforeMustHave - string that must appear just before or text before must match `{re:/.../,maxCheck:123}` * use `$` in `re` to match just before string to be replaced * * @param {type} atr * @returns {undefined} */ this.addReplacements = function(atr/*{from, to}*/) { // add the replacement rule with some precalculated attributes var atrRewritten = jQuery.extend({}, atr); atrRewritten.from = atr.from.substr(0, atr.from.length-1); arrReplacements[arrReplacements.length] = { chLastChar : atr.from.charAt(atr.from.length-1), reMatch : new RegExp(escapeStr4RegExp(atr.from)+'$'), objReplaceAtrs : atrRewritten }; // re-calculte some main attributes if (maxChars<atr.from.length) { maxChars=atr.from.length; } for (var i=0; i<atr.from.length; i++) { var ch = atr.from.charAt(i); if (interestingChars.indexOf(ch)===-1) { interestingChars += ch; } } }; /** * Init must be run after the text box is available * @returns {unresolved} */ this.init = function() { if (!jQuery) return; var _this = this; $input = jQuery('#'+textBoxId); input = document.getElementById(textBoxId); // main collector $input.keypress(function(evt) {onKeyPress(evt);}); // remove anything collected on the way (so that moving a cursor with a mouse wouldn't cause anything weird to happen) $input.click(function(evt) {pressedCharsBuffer = '';}); }; /** * Enable/disable listener. */ this.toggleDisablance = function() { isDisabled = !isDisabled; }; /** * Set disablance of the listener. * * @param {Boolean} is2BeDisabled */ this.setDisablance = function(is2BeDisabled) { isDisabled = is2BeDisabled; }; /** * Get disablance state of the listener. * * @return {Boolean} Current state. */ this.getDisablance = function() { return isDisabled; }; /** * Collecting and checking characters. * * @param {Event} evt KeyPress event data */ var onKeyPress = function(evt) { // no rules added or disabled? if (arrReplacements.length<=0 || isDisabled) { return; } // // collect chars // var ch; // normal key? (for a PgDown issue in FF) if (typeof(evt.which)=='undefined' || evt.which) { ch = evt.charCode || evt.keyCode; } else { return; } ch = String.fromCharCode(ch); pressedCharsBuffer += ch; // // check for matches // for (var i=0; i<arrReplacements.length; i++) { // single replacement rule check var repRule = arrReplacements[i]; if (ch==repRule.chLastChar && pressedCharsBuffer.search(repRule.reMatch)!=-1) { if (replaceLatestStr(repRule.objReplaceAtrs, ch)) // note ch is not out yet! { evt.preventDefault(); // prevent output of ch break; // prevent other replacements } } } // // Check for finish // // overflow? if (pressedCharsBuffer.length>maxChars) { pressedCharsBuffer = pressedCharsBuffer.substr(1); // cut out least important character } // unneeded char if (interestingChars.indexOf(ch)==-1) { pressedCharsBuffer = ''; } }; /** * Replace text that was just put in the input from `atr.from` to `atr.to`. * * @param {type} atr * @param {type} chLastChar * @returns {Boolean} true if replaced */ var replaceLatestStr = function(atr/*{from, to}*/, chLastChar) { // get current position var startScroll = input.scrollY; var bounds = sel_t.getSelBound(input); /** * Get string just before match. */ var getStringBeforeMatch = function(numOfChars) { var start = bounds.end - atr.from.length - numOfChars; var length = numOfChars; if (start < 0) { start = 0; length = bounds.end - atr.from.length; } return input.value.substr(start, length); }; // check if the selected text would be correct var strBeforeCursor = input.value.substr(bounds.end - atr.from.length, atr.from.length); if (strBeforeCursor != atr.from) // something went wrong (probably cursor jumped somehow) { return false; } // bail out when matched (mostly for quotes) if ('beforeForbidden' in atr) { var o = atr.beforeForbidden; if (typeof(o) === 'string') { if (o == getStringBeforeMatch(o.length)) { return false; } } // `{re:/.../,maxCheck:123}` else { if (o.re.test(getStringBeforeMatch(o.maxCheck))) { return false; } } } // bail out when NOT matched (mostly for quotes) if ('beforeMustHave' in atr) { var o = atr.beforeMustHave; if (typeof(o) === 'string') { if (o != getStringBeforeMatch(o.length)) { return false; } } // `{re:/.../,maxCheck:123}` else { if (!o.re.test(getStringBeforeMatch(o.maxCheck))) { return false; } } } // add last character to enable undo (note: it might replace selected text) sel_t.setSelStr(input, chLastChar, false); //bounds = sel_t.getSelBound(input); // re-read bounds // don't work as expected on Opera (Opera seems to reset bounds to the end of the whole text of the input) bounds.start += chLastChar.length; bounds.end = bounds.start; // prepare new bounds bounds.start = bounds.end - atr.from.length - chLastChar.length; if (bounds.start<0) // probably interpretation error { return false; } // select chars to be replaced sel_t.setSelBound(input, bounds, false); // replace sel_t.setSelStr(input, atr.to, false); // reset cursor to the end of inserted text //bounds = sel_t.getSelBound(inp); // don't work as expected on IE (IE seems to reset bounds to a start of the selection) bounds.start += atr.to.length; bounds.end = bounds.start; sel_t.setSelBound(input, bounds, false); // reset position input.scrollY = startScroll; return true; }; } // ---------------------------------------------------------------- // // Autokorekta (pl) // // // init object // window.oAutokorekta = new nuxTBKeys('wpTextbox1'); // minus/dywiz na myślnik oAutokorekta.addReplacements ({from:' - ', to:' – '}); // arrows oAutokorekta.addReplacements ({from:' -> ', to:' → '}); oAutokorekta.addReplacements ({from:' <- ', to:' ← '}); // quotes oAutokorekta.addReplacements ({from:' "', to:' „'}); oAutokorekta.addReplacements ({from:'"', to:'”', beforeForbidden:'=', beforeMustHave:{re:/„[^"”]*$/, maxCheck:5000} }); /** * Button settings */ oAutokorekta.oImgbtn = { on : { src : '//upload.wikimedia.org/wikipedia/commons/thumb/7/77/Vista-clean.png/22px-Vista-clean.png', alt : 'włączona', title : 'Autokorekta jest włączona' }, off : { src : '//upload.wikimedia.org/wikipedia/commons/thumb/6/65/Gnome-window-close.svg/22px-Gnome-window-close.svg.png', alt : 'wyłączona', title : 'Autokorekta jest wyłączona' } }; /** * Button adder * @returns {Boolean} */ oAutokorekta.addDisableButon = function() { // add a group in a standard way jQuery('#wpTextbox1').wikiEditor('addToToolbar', { 'section': 'advanced', 'groups': { 'autorepcontrol': { 'label': 'Autokorekta' } } }); // get added group var elGroup = $("#wikiEditor-ui-toolbar div.section-advanced div.group-autorepcontrol")[0]; if (!elGroup) { return false; } // add button var nel = document.createElement('img'); if (!oAutokorekta.getDisablance()) { nel.src = oAutokorekta.oImgbtn.on.src; nel.alt = oAutokorekta.oImgbtn.on.alt; nel.title = oAutokorekta.oImgbtn.on.title; } else { nel.src = oAutokorekta.oImgbtn.off.src; nel.alt = oAutokorekta.oImgbtn.off.alt; nel.title = oAutokorekta.oImgbtn.off.title; } nel.className = "tool tool-button"; nel.style.cssText = "width: 22px; height: 22px; padding-top:2px"; nel.onclick = oAutokorekta.onClickDisableBtn; elGroup.appendChild(nel); // show group elGroup.style.display = ''; // border elGroup.style.cssText = "border-left: 1px solid #DDDDDD"; // seems OK return true; }; /** * Button click. */ oAutokorekta.onClickDisableBtn = function() { oAutokorekta.toggleDisablance(); if (this.alt == oAutokorekta.oImgbtn.on.alt) { this.src = oAutokorekta.oImgbtn.off.src; this.alt = oAutokorekta.oImgbtn.off.alt; this.title = oAutokorekta.oImgbtn.off.title; jQuery.cookie("js_oAutokorekta_setup", "off", { expires: 7 }); } else { this.src = oAutokorekta.oImgbtn.on.src; this.alt = oAutokorekta.oImgbtn.on.alt; this.title = oAutokorekta.oImgbtn.on.title; jQuery.cookie("js_oAutokorekta_setup", "on", { expires: 7 }); } // re-set focus try { input.focus(); } catch (e) {} }; /** * Sets up the gadget. */ oAutokorekta.setup = function() { // Cookie setup stuff var js_oAutokorekta_setup = ''; if (document.cookie.search(/(^|[ ;])js_oAutokorekta_setup=/) != -1) { document.cookie.replace(/(^|[ ;])js_oAutokorekta_setup=(.*?)(;|$)/, function( a, s, val, e ) { js_oAutokorekta_setup = val; }); // re-set cookie jQuery.cookie("js_oAutokorekta_setup", js_oAutokorekta_setup, {expires: 7}); } // setup default state if (js_oAutokorekta_setup != 'on') // defaults to off { oAutokorekta.setDisablance(true); } if (mw.config.get('wgNamespaceNumber' ) < 0) { return; } // Check if the new toolbar is available if (mw.user.options.get( 'usebetatoolbar' ) !== 1) { return; } mw.loader.using("ext.wikiEditor.toolbar", function() { $(function() { // wyłączone przez użytkownika if (window.isAutokorektaWylaczona) { return; } if (oAutokorekta.addDisableButon() || window.isAutokorektaAlwaysOn) { oAutokorekta.init(); } }); }); }; if (mw.config.get( 'wgAction' ) == 'edit' || mw.config.get( 'wgAction' ) == 'submit') { oAutokorekta.setup(); }