User:PerfektesChaos/js/editToolStrIns/debug.js

/// editToolStrIns /// Edit tool to insert characters and strings -- especially for WMF /// 2018-02-15 PerfektesChaos@de.wikipedia // ResourceLoader: compatible; //   dependencies: user, mediawiki.util, jquery.textSelection /// Fingerprint: #0#0# /* jshint bitwise:false, forin:false                                  */ /* global window:false                                                */ /* jshint curly:true, eqeqeq:true, futurehostile:true, latedef:true, laxbreak:true, nocomma:true, strict:true, undef:true, unused:true          */

( function ( mw, $ ) {  "use strict";   var Version   = -1.25,       Sign      = "editToolStrIns",       Signature = "ext.gadget." + Sign,       ETSI;   if ( typeof mw.libs[ Sign ]  !==  "object" ||  ! mw.libs[ Sign ] ) {      mw.libs[ Sign ]  =  { };   }   ETSI            = mw.libs[ Sign ];   ETSI.type       = Sign;   ETSI.vsn        = Version;   ETSI.signature  = Signature;   ETSI.doc        = "mw:User:PerfektesChaos/js/" + ETSI.type + "";   if ( ETSI.vsn < 0  &&  typeof ETSI.debugging !== "object" ) {      ETSI.debugging = { loud: true,                         say:  "ETSI" };   }

// Uses: //   MediaWiki  1.18 (mw.libs, jQuery.textSelection) //   jQuery     core; $.focus, .isArray //   JavaScript 1.3 //   DOM        Level 3

/* Based upon previous work of: mw:User:Alex Smotrov             2008 w:de:User:Revolus                2008/2009 w:de:User:WIKImaniac             2009 w:de:MediaWiki:Onlyifediting.js  2011-08-11 /// @license GPL [//www.mediawiki.org/w/COPYING] (+GFDL, LGPL, CC-BY-SA) /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html */ /// About: mw:User:PerfektesChaos/js/editToolStrIns

if ( typeof ETSI.debugging !== "object" ) { ETSI.debugging = false; }  if ( typeof ETSI.l10n !== "object" ) { ETSI.l10n = { }; }  ETSI.attr   = { names: { "class":       false, "lang":       false, "dir":        false, "font-family": true, "font-size":  true } };  ETSI.defs   = { global:     null, looser:    false }; ETSI.gui   = { builder:    false, container: ".mw-editTools", self:      "edit-tool-SI", $container: false, $wrapper:  false }; ETSI.listen = false; ETSI.loaded = false; ETSI.menu  = { }; ETSI.nowiki = "nowiki"; ETSI.util  = { };

// No customization recommended above this point. // Start adption and localization here:

ETSI.gui.old =  "#editpage-specialchars," + "#mw-edittools-charinsert," + "#specialchars";  // 2014-01-05 ETSI.menu.separator = " •"; ETSI.menu.divide   = { "display":      "inline-block", "font-weight": "bold", "margin-left": "0.8em", "margin-right": "0.45em", "white-space": "nowrap" }; ETSI.menu.stick    = "…"; ETSI.l10n.dewiki = {  // example for introduction period "list": [ "0",     "Standard", "",  "WikiSyntax", ":6",    "Datei:", ":10",   "Vorlage:", "IPA",   "IPA-Lautschrift", "Latin", "Lateinisch", "AHD",   "AHD-Lautschrift", "grc",   "Altgriechisch", "ar",    "Arabisch", "DMG",   "DMG-Umschrift", "eo",    "Esperanto", "et",    "Estnisch", "fr",    "Französisch", "gl",    "Galicisch", "el",    "Griechisch", "haw",   "Hawaiisch", "iw",    "Hebräisch", "is",    "Isländisch", "it",    "Italienisch", "hbs",   "Kroatisch/Serbisch/Bosnisch", "Cyril", "Kyrillisch", "Latin", "Lateinisch", "lv",    "Lettisch", "lt",    "Litauisch", "mt",    "Maltesisch", "pl",    "Polnisch", "pt",    "Portugiesisch", "Pinyin", "Pinyin", "roa",   "Romanisch", "ro",    "Rumänisch", "Scand", "Skandinavisch", "wen",   "Sorbisch", "es",    "Spanisch", "cz",    "Tschechisch", "tr",    "Türkisch", "hu",    "Ungarisch", "vi",    "Vietnamesisch" ], "defs": { "AHD": { "class": "Unicode" }, "ar": { "class": "spanAr", "font-size": "1.25em" }, "grc": { "class": "polytonic" }, "haw": { "font-family": "Arial Unicode MS, Lucida Sans Unicode, MS Mincho, " + "Arial, sans-serif;" } } };  // .l10n.dewiki.list 2011-11-01 ETSI.l10n.enwiki = { "defs": {  // example (introduction period) "0":        [ [ "–",                       "—",                       [ "‘", "’" ],                       [ "“", "”" ] ],                     false, [ 1, "°″′≈≠≤≥±−×÷√←→·§" ],                    [ 0, "Sign your posts on talk pages:" ], [ "~" ],                    [ 0, "Cite your sources:" ], [ [ " " ] ] ],     "":      [ [ 0, "Insert:" ], [ "–",                      "—",                       [ "‘", "’" ],                       [ "“", "”" ] ],                     false, [ 1, "°″′≈≠≤≥±−×÷√←→·§" ],                    false, [ "~",                      [ " " ] ],                     [ 0, "Wiki markup:" ], [ [ "" ],                      [ "" ],                       "|",                       [ "[", "]" ],                       [ "", "" ],                       [ "" ],                       [ "#REDIRECT ", "" ], " ",                      [ " ", " " ],                       [ "", "" ],                       [ "", "" ],                       [ " " ],                       [ " ", " " ],                       [ ""', '"" ],                       [ " " ],                       [ "" ],                       "",                       " " ],                  [ " " ],                  [ " ", " " ],                  [ " ", " " ],                  [ "", "" ],                  [ "", "" ],                  [ "" ] ],                [ "<" + ETSI.nowiki + " />", [ "<" + ETSI.nowiki + ">", "" ] ], [ [ "$$", "$$" ],                 [ " " ]                  ],                [ [ " " ],                  [ " " ],                  [ " " ],                  " " ],                [ [ " ", " " ],                  [ " ", " " ],                  [ " ", " " ] ] ],      ":10":  [ { "font-family": "monospace"  }, [ [ "" ],                 [ "" ],                  "|",                  [ "",             "", "", "if" ], [ "",         "", "", "ifeq" ], [ "",       "", "", "ifexist" ], [ "",            "", "", "expr" ], [ "",        "", "", "ifexpr" ], [ "",       "", "", "iferror" ], [ "","","", "switch" ], [ "",            "", "", "tag" ], [ "NaN",        "", "", "formatnum" ], [ "",       "", "", "formatdate" ], [ "", "",               "", "", "lc" ], [ "", "",               "", "", "uc" ], [ "",            "", "", "subst" ] ] ], // ISO 639 "ang": [ { "lang": "ang" }, [ 1, "ĀāÆæǢǣǼǽĊċÐðĒēĠġĪīŌōŪūǷƿȲȳÞþȜȝ" ] ], "ar": [ { "lang": "ar", "dir": "rtl" }, [ 1, "؛؟ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىي،", "پچژگڭ"] ], "bn": [ { "lang": "bn" }, [ 2, 0x0981, 0x0983, 0x0985, 0x098C, 0x098F, 0x0990, 0x0993, 0x09A8, 0x09AA, 0x09B0, 0x09B2, 0x09B2, 0x09B6, 0x09B9, 0x09BC, 0x09C4, 0x09C7, 0x09C8, 0x09CB, 0x09CE, 0x09D7, 0x09D7, 0x09DC, 0x09DD, 0x09DF, 0x09E3, 0x09E6, 0x09FB ] ], "cz": [ { "lang": "cz" }, [ 1, "ÁáČčĎďÉéĚěÍíŇňÓóŘřŠšŤťÚúŮůÝýŽž" ] ], "de": [ { "lang": "de" }, [ 1, "ÄäÖößÜü" ], [ [ "„", "“" ],                [ "‚", "‘" ],                 [ "»", "«" ],                 [ "›", "‹" ] ] ],      "el":  [ { "lang": "el" }, [ 1, "ΑΆΒΓΔΕΈΖΗΉΘΙΊΚΛΜΝΞΟΌΠΡΣΤΥΎΦΧΨΩΏ", "αάβγδεέζηήθιίκλμνξοόπρσςτυύφχψωώ" ] ], "eo": [ { "lang": "eo" }, [ 1, "ĈĉĜĝĤĥĴĵŜŝŬŭ" ] ], "es": [ { "lang": "es" }, [ 1, "ÁáÉéÍíÑñÓóÚúÜü¡¿" ] ], "et": [ { "lang": "et" }, [ 1, "ČčŠšŽžÕõÄäÖöÜü" ] ], "fr": [ { "lang": "fr" }, [ 1, "ÀàÂâÇçÉéÈèÊêËëÎîÏïÔôŒœÙùÛûÜüŸÿ" ], [ [ "«", "»" ],                [ "‹", "›" ] ] ],      "gl":  [ { "lang": "gl" }, [ 1, "ÁáÀàÂâÄäÉéÈèÊêËëÌìÎîÏïÓóÒòÔôÖöÙùÛû" + "ẀẁŴŵẄẅÝýỲỳŶŷŸÿ" ] ], "grc": [ { "lang": "grc" }, [ 1, "ΑαΆάΒβΓγΔδΕεΈέΖζΗηΉήΘθΙιΊίΪϊΐΚκΛλΜμΝνΞξΟοΌόΠπΡρΣσς" + "ΤτΥυΫϋΎύΰΦφΧχΨψΩωΏώ;·ἀἁὰᾶἂἃἄἅἆἇᾳᾀᾁᾴᾲᾷᾄᾅᾂᾃᾆᾇἐἑὲἔἕἒ" + "ἓἠἡὴῆἤἢἣἥἦἧῃῄῂῇᾐᾑᾔᾒᾕᾓᾖᾗἰἱὶῖἴἲἵἳἶἷὸὀὁὄὅὂὃῤῥὐὑὺῦὔὕὒ" + "ὓὖὗὠὡὼῶὤὢὥὣὦὧῳῴῲῷᾠᾡᾤᾢᾥᾣᾦᾧ`᾿῾῍῎῏῟῞῝῍῎ϜϝϘϙϠϡ" ] ], "gu": [ { "lang": "gu" }, [ 2, 0x0A81, 0x0A83, 0x0A85, 0x0A8D, 0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, 0x0AB5, 0x0AB9, 0x0ABC, 0x0AC5, 0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0AD0, 0x0AD0, 0x0AE0, 0x0AE3 ], [ 2, 0x0AE6, 0x0AEF, 0x0AF1, 0x0AF1 ] ], "haw": [ { "lang": "haw" }, [ 1, "ĀāĒēĪīŌōŪūʻ" ] ], "hbs": [ { "lang": "hbs" }, [ -32, "Č č Ć ć Dž dž Đ đ Š š Ž ž" ] ], "hu": [ { "lang": "hu" }, [ 1, "áéíŐöóőŰúüű" ] ], "is": [ { "lang": "is" }, [ 1, "ÁáÐðÉéÍíÓóÚúÝýÞþÆæÖöǫ" ] ], "it": [ { "lang": "it" }, [ 1, "ÁáÀàÉéÈèÍíÌìÓóÒòÚúÙù" ] ], "iw": [ { "lang": "yi", "dir": "rtl" }, [ 3, 0x05D0, false, 0x05D0, 0x05B7, false, 0x05D0, 0x05B8, false, 0x05D1, false, 0x05D1, 0x05BF, false, 0x05D2, false, 0x05D3, false, 0x05D4, false, 0x05D5, false, 0x05D5, 0x05BC, 0x05F0, false, 0x05F1, false, 0x05D6, false, 0x05D6, 0x05E9, false, 0x05D7, false, 0x05D8, false, 0x05D9, false, 0x05D9, 0x05B4, false, 0x05F2, false, 0x05F2, 0x05B7, false, 0x05DB, false, 0x05DA, false, 0x05DB, 0x05BC, 0x05DC, false, 0x05DE, false, 0x05DD, false, 0x05E0, false, 0x05DF, false, 0x05E1, false, 0x05E2, false, 0x05E4, false, 0x05E4, 0x05BC, false, 0x05E4, 0x05BF, false, 0x05E3, false, 0x05E6, false, 0x05E5, false, 0x05E7, false, 0x05E8, false, 0x05E9, false, 0x05E9, 0x05C2, false, 0x05EA, 0x05BC, false, 0x05EA, false, 0x05F3, false, 0x05F4, false, 0x05BE ] ], "lo": [ { "lang": "lo" }, [ 2, 0x0E81, 0x0E82, 0x0E84, 0x0E84, 0x0E87, 0x0E88, 0x0E8A, 0x0E8A, 0x0E8D, 0x0E8D, 0x0E94, 0x0E97, 0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EA5, 0x0EA5, 0x0EA7, 0x0EA7, 0x0EAA, 0x0EAB, 0x0EAD, 0x0EB9, 0x0EC0, 0x0EC4, 0x0EC6, 0x0EC6, 0x0EC8, 0x0ECD, 0x0ED0, 0x0ED9, 0x0EDC, 0x0EDD ] ], "lv": [ { "lang": "lv" }, [ 1, "ĀČĒĢĪĶĻŅŠŪŽ", "āčēģīķļņšūž" ] ], "lt": [ { "lang": "lt" }, [ 1, "ĄČĘĖĮŠŲŪŽ", "ąčęėįšųūž" ] ], "mt": [ { "lang": "mt" }, [ 1, "ĊċĠġĦħŻż" ] ], "pl": [ { "lang": "pl" }, [ 1, "ąĄćĆęĘłŁńŃóÓśŚźŹżŻ" ] ], "pt": [ { "lang": "pt" }, [ 1, "ÁáÀàÂâÃãÇçÉéÊêÍíÓóÔôÕõÚúÜü" ] ], "ro": [ { "lang": "ro" }, [ 1, "ĂăÂâÎîȘșȚț" ] ], "roa": [ { "lang": "roa" }, [ 1, "ĀāĒēĪīŌōŪū" ] ], "si": [ { "lang": "si" }, [ 2, 0x0D82, 0x0D83, 0x0D85, 0x0D96, 0x0D9A, 0x0DB1, 0x0DB3, 0x0DBB, 0x0DBD, 0x0DBD, 0x0DC0, 0x0DC6, 0x0DCA, 0x0DCA, 0x0DCF, 0x0DD4, 0x0DD6, 0x0DD6, 0x0DD8, 0x0DDF, 0x0DF2, 0x0DF4 ] ], "sk": [ { "lang": "sk" }, [ 1, "ÁáČčĎďÉéÍíĽľŇňÓóÔôŔŕŠšŤťÚúÝýŽž" ] ], "te": [ { "lang": "te" }, [ 2, 0x0C01, 0x0C03, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10, 0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C3D, 0x0C44, 0x0C46, 0x0C48, 0x0C4A, 0x0C4D, 0x0C55, 0x0C56, 0x0C58, 0x0C59, 0x0C60, 0x0C63, 0x0C66, 0x0C6F, 0x0C78, 0x0C7F ] ], "th": [ { "lang": "th" }, [ 2, 0x0E01, 0x0E3A ], [ 2, 0x0E3F, 0x0E5B ] ], "tr": [ { "lang": "tr" }, [ -32, "Â Ə Ç Ğ Gʻ Î İ Ñ Ň Oʻ Ş Û Ý Ž", "â ə ç ğ gʻ î ı ñ ň oʻ ş û ý ž" ] ], "vi": [ { "lang": "vi" }, [ 1, "ÀàẢảÁáẠạÃãĂăẰằẲẳẴẵẮắẶặÂâẦầẨẩẪẫẤấẬậ", "Đđ", "ÈèẺẻẼẽÉéẸẹÊêỀềỂểỄễẾếỆệ", "ỈỉĨĩÍíỊịÌì", "ỎỏÓóỌọÒòÕõÔôỒồỔổỖỗỐốỘộƠơỜờỞởỠỡỚớỢợ", "ÙùỦủŨũÚúỤụƯưỪừỬửỮữỨứỰự", "ỲỳỶỷỸỹỴỵÝý" ] ], "wen": [ { "lang": "wen" }, [ 1, "ČčĆćěŁłńóřŕŠšŚśŽžŹź" ] ], // ISO 15924 "Khmr": [ null,  // Khmer [ 2, 0x1780, 0x17DD ], [ 2, 0x17E0, 0x17E9 ], [ 2, 0x17F0, 0x17F9 ] ], "Phli": [ { "dir": "rtl",  // Pahlavi "font-family": "ZH Mono" }, [ 2, 0x10B60, 0x10B72 ], [ 2, 0x10B78, 0x10B7F ] ], "Prti": [ { "dir": "rtl",  // Parthian "font-family": "ZH Mono" }, [ 2, 0x10B40, 0x10B55 ], [ 2, 0x10B58, 0x10B5F ] ], "Xsux": [ { "font-family":  // Cuneiform "Akkadian, CuneiformComposite, Free Idg Serif" }, [ 2, 0x12000, 0x1236F ], [ 2, 0x12400, 0x12462 ], [ 2, 0x12470, 0x12473 ] ], // Others "AHD":   [ null, [ 1, "āăäâēĕīĭîōŏôŭ" ], false, [ [ "o͞o", "", "", "food" ], [ "o͝o", "", "", "foot" ] ] ], "Cyril": [ null, [ 1,                   "АӘБВГҐЃҒДЂЕЄЁЖЗЅИІЇİЙӢЈКЌҚЛЉМНЊҢОӨПРСТЋУЎӮ" + "ҰҮФХҲҺЦЧҶЏШЩЪЫЬЭЮЯ", "аәбвгґѓғдђеєёжзѕиіїйӣјкќқлљмнњңоөпрстћуўӯ" + "ұүфхҳһцчҷџшщъыьэюя" ] ], "DMG":   [ null, [ 1, "ʾʿĀāČčḌḍḎḏǦǧĠġḤḥḪḫĪīḷŋṢṣS̱s̱ŠšṬṭṮṯŪūẒẓẔẕŽžŻż" ] ], "Finance":[ null, [ 1, "‰", "₳฿₵¢₡₢$₫₯€₠₣ƒ₴₭₤ℳ₥₦№₧₰£៛₨₪৳₮₩¥" ], [ [ "¤", "", "", "unspecified currency" ] ], [ 1, "©®™", "§" ] ],     "IPA":    [ { "class": "IPA" }, [ -32, "p t̪ t ʈ c k q ʡ ʔ", "b d̪ d ɖ ɟ ɡ ɢ", "ɓ ɗ ʄ ɠ ʛ", "t͡s t͡ʃ t͡ɕ d͡z d͡ʒ d͡ʑ", "ɸ f θ s ʃ ʅ ʆ ʂ ɕ ç ɧ x χ ħ ʜ h", "β v ʍ ð z ʒ ʓ ʐ ʑ ʝ ɣ ʁ ʕ ʖ ʢ ɦ", "ɬ ɮ", "m m̩ ɱ ɱ̩ ɱ̍ n̪ n̪̍ n n̩ ɳ ɳ̩ ɲ ɲ̩ ŋ ŋ̍ ŋ̩ ɴ ", "ɴ̩ ʙ ʙ̩ r r̩ ʀ ʀ̩", "ɾ ɽ ɿ ɺ", "l̪ l̪̩ l l̩ ɫ ɫ̩ ɭ ɭ̩ ʎ ʎ̩ ʟ ʟ̩", "w ɥ ʋ ɹ ɻ j ɰ", "ʘ ǂ ǀ ǃ ǁ", "ʰ ʱ ʷ ʸ ʲ ʳ ⁿ ˡ ʴ ʵ ˢ ˣ ˠ ʶ ˤ ˁ ˀ ʼ", "i i̯ ĩ y y̯ ỹ ɪ ɪ̯ ɪ̃ ʏ ʏ̯ ʏ̃ ɨ ɨ̯ ɨ̃ ʉ ʉ̯ ʉ̃ " + "ɯ ɯ̯ ɯ̃ u u̯ ũ ʊ ʊ̯ ʊ̃", "e e̯ ẽ ø ø̯ ø̃ ɘ ɘ̯ ɘ̃ ɵ ɵ̯ ɵ̃ ɤ ɤ̯ ɤ̃ o o̯ õ", "ɛ ɛ̯ ɛ̃ œ œ̯ œ̃ ɜ ɜ̯ ɜ̃ ə ə̯ ə̃ ɞ ɞ̯ ɞ̃ ʌ ʌ̯ " + "ʌ̃ ɔ ɔ̯ ɔ̃", "æ æ̯ æ̃ ɶ ɶ̯ ɶ̃ a a̯ ã " + "ɐ ɐ̯ ɐ̃ ɑ ɑ̯ ɑ̃ ɒ ɒ̯ ɒ̃", "ˈ ˌ ː ˑ ˘ . ‿ | ‖" ] ], "KhmrSy": [ null,  // Khmer lunatics [ 2, 0x19E0, 0x19FF ] ], "Latin": [ null, [ -32, "Á á Ć ć É é Í í Ó ó Ś ś Ú ú Ý ý Ǿ ǿ", "À à È è Ì ì Ò ò Ù ù", "Â â Ĉ ĉ Ê ê Ĝ ĝ Ĥ ĥ Î î Ĵ ĵ Ô ô ŝ Ŝ Û û", "Ä ä Ë ë Ï ï Ö ö Ü ü ÿ", "Ã ã Ñ ñ Õ õ", "Å å", "Ç ç", "Č č Š š ŭ", "Ł ł", "Ő ő Ű ű", "Ø ø", "Ā ā Ē ē Ī ī Ō ō Ū ū Ȳ ȳ", "Ă ă Ĕ ĕ Ğ ğ Ĭ ĭ Ŏ ŏ Ŭ ŭ Y̆ y̆" , "ß", "Æ æ Œ œ", "Ð ð Þ þ |" ] ], "Pinyin": [ null, [ 1, "ÁáÀàǍǎĀāÉéÈèĚěĒēÍíÌìǏǐĪī" + "ÓóÒòǑǒŌōÚúÙùÜüǓǔŪūǗǘǛǜǙǚǕǖ" ] ], "Scand": [ null, [ 1, "ÀàÉéÅåÆæÄäØøÖö", "ÐðÍíÓóÚúÝýÞþǫ" ] ], "TeX":   [ null, [ [ "$$", "$$" ],                   [ "{,}",        "",      "", "comma {,}","," ], "\\",                   [ "{", "}" ],                    "^",                    [ "\\cdot",     "",      "", "cdot",     "·" ], [ "\\times",   "",      "", "times",    "×" ], [ "\\pm",      "",      "", "pm",       "±" ], [ "\\mp",      "",      "", "mp",       "∓" ], [ "\\sum{",    "}",     "", "sum{}",    "Σ" ], [ "\\frac{",   "}{}",   "", "frac{}{}", "—" ], [ "\\sqrt{",   "}",     "", "sqrt{}",   "√" ], [ "\\sqrt[n]{", "}",    "", "sqrt[n]{}","ⁿ√" ], [ "\\leq",     "",      "", "leq",      "≤" ], [ "\\geq",     "",      "", "geq",      "≥" ], [ "\\approx",  "",      "", "approx",   "≈" ], [ "\\ne",      "",      "", "ne",       "≠" ], [ "\\circ",    "",      "", "circ",     "°" ], [ "\\pi",      "",      "", "",         "π" ], [ "\\infty",   "",      "", "infty",    "∞" ], [ "\\cup",     "",      "", "cup",      "∪" ], [ "\\cap",     "",      "", "cap",      "∩" ], [ "\\angle",   "",      "", "angle",    "∠" ], [ "\\underline","",     "", "underline","_" ], [ "\\overline", "",     "", "overline", "¯" ], [ "\\begin",   "\\end", "", "",       "begin…end" ], [ "\\!\\,",    "",      "", "space\\!\\,","SPC" ], [ "\\{",       "",      "", "",         "{" ],                    [ "\\}",        "",      "", "",         "}" ] ] ],      "TeX_ar": [ null, [ [ "\\leftarrow",       "","","leftarrow",     "←" ], [ "\\leftrightarrow",  "","","leftrightarrow","↔" ], [ "\\rightarrow",      "","","rightarrow",    "→" ], [ "\\Leftarrow",       "","","Leftarrow",     "⇐" ], [ "\\Leftrightarrow",  "","","Leftrightarrow","⇔" ], [ "\\Rightarrow",      "","","Rightarrow",    "⇒" ], [ "\\uparrow",         "","","uparrow",       "↑" ], [ "\\updownarrow",     "","","updownarrow",   "↕" ], [ "\\downarrow",       "","","downarrow",     "↓" ], [ "\\Uparrow",         "","","Downarrow",     "⇑" ], [ "\\Updownarrow",     "","","Updownarrow",   "⇕" ], [ "\\Downarrow",       "","","Downarrow",     "⇓" ], [ "\\nearrow",         "","","nearrow",       "↗" ], [ "\\searrow",         "","","searrow",       "↘" ], [ "\\swarrow",         "","","swarrow",       "↙" ], [ "\\nwarrow",         "","","nwarrow",       "↖" ], ["\\leftrightarrows", "","","leftrightarrows","⇆" ], ["\\updownarrow ",    "","","updownarrow ",   "⇅" ], ["\\rightleftarrows", "","","rightleftarrows","⇄"]], "\\leftrightharpoons","","","leftrightharpoons","⇋"],                  ["\\rightleftharpoons","","","rightleftharpoons","⇌"],                    ["\\leftharpoondown", "","","leftharpoondown", "↽"],                    ["\\rightharpoondown","","","rightharpoondown","⇁"],                    ["\\leftharpoonup",   "","","leftharpoonup",   "↼"],                    ["\\rightharpoonup",  "","","rightharpoonup",  "⇀"],                    ["\\upharpoonleft",   "","","upharpoonleft",   "↿"],                    ["\\upharpoonright",  "","","upharpoonright",  "↾"],                    ["\\downharpoonleft", "","","downharpoonleft", "⇃"],                    ["\\downharpoonright","","","downharpoonright","⇂", [ ["\\circlearrowleft", "","","circlearrowleft", "↺"], ["\\circlearrowright","","","circlearrowright","↻"], ["\\curvearrowleft", "","","curvearrowleft",  "↶"], ["\\curvearrowright", "","","curvearrowright", "↷"], ["\\hookleftarrow",  "","","hookleftarrow",   "↩"], ["\\hookrightarrow", "","","hookrightarrow",  "↪"], ["\\looparrowleft",  "","","looparrowleft",   "↫"], ["\\looparrowright", "","","looparrowright",  "↬"], ["\\leftrightsquigarrow","","","leftrightsquigarrow","↭"]], [ [ "\\rightmapsto",   "", "","rightmapsto",  "↦" ], [ "\\upmapsto",      "", "","upmapsto",     "↥" ], [ "\\leftmapsto",    "", "","leftmapsto",   "↤" ], [ "\\downmapsto",    "", "","downmapsto",   "↧" ] ], [ [ "\\Lsh",           "", "", "Lsh",         "↰" ], [ "\\Rsh",           "", "", "Rsh",         "↱" ], [ "\\dlsh",          "", "", "dlsh",        "↲" ], [ "\\drsh",          "", "", "drsh",        "↳" ] ], [ [ "\\nleftrightarrow","","","nleftrightarrow","↮" ], [ "\\nleftarrow",    "","","nleftarrow",     "↚" ], [ "\\nrightarrow",   "","","nrightarrow",    "↛" ], [ "\\nLeftrightarrow","","","nLeftrightarrow","⇎" ], [ "\\nLeftarrow",    "","","nLeftarrow",     "⇍" ], [ "\\nRightarrow",   "","","nRightarrow",    "⇏"]]], "TeX_bi": [ null, [ [ "\\leq",        "", "", "leq",          "≤" ], [ "\\geq",        "", "", "geq",          "≥" ], [ "\\propto",     "", "", "propto",       "∝" ], [ "\\neq",        "", "", "neq",          "≠" ], [ "\\equiv",      "", "", "equiv",        "≡" ], [ "\\ll",         "", "", "ll",           "≪" ], [ "\\gg",         "", "", "gg",           "≫" ], [ "\\simeq ",     "", "", "simeq ",       "≃" ], [ "\\cong",       "", "", "cong",         "≅" ], [ "\\approx",     "", "", "approx",       "≈" ], [ "\\triangleq",  "", "", "triangleq",    "≜" ], [ "\\doteq",      "", "", "doteq",        "≐" ], [ "\\stackrel{\\mathrm{def}}","=def","","","≝" ] ], [ [ "\\neg",        "", "", "neg",          "↦" ], [ "\\wedge",      "", "", "wedge",        "∧" ], [ "\\vee",        "", "", "vee",          "∨" ], [ "\\veebar",     "", "", "veebar",       "⊻" ], [ "\\therefore",  "", "", "therefore",    "∴" ], [ "\\because",    "", "", "because",      "∵" ], [ "\\forall",     "", "", "forall",       "∀" ], [ "\\exists",     "", "", "exists",       "∃" ] ], [ [ "\\in",         "", "", "in",           "∈" ], [ "\\nowns",      "", "", "nowns",        "∉" ], [ "\\ni",         "", "", "ni",           "∋" ], [ "\\emptyset",   "", "", "emptyset",     "∅" ], [ "\\cup",        "", "", "cup",          "∪" ], [ "\\cap",        "", "", "cap",          "∩" ], [ "\\subset",     "", "", "subset",       "⊂" ], [ "\\nsubset",    "", "", "nsubset",      "⊄" ], [ "\\subseteq",   "", "", "subseteq",     "⊆" ], [ "\\nsubseteq",  "", "", "nsubseteq",    "⊈" ], [ "\\subsetneq",  "", "", "subsetneq",    "⊊" ], [ "\\supset",     "", "", "supset",       "⊃" ], [ "\\nsupset",    "", "", "nsupset",      "⊅" ], [ "\\subseteq",   "", "", "subseteq",     "⊇" ], [ "\\nsupseteq",  "", "", "nsupseteq",    "⊉" ], [ "\\supsetneq",  "", "", "supsetneq",    "⊋" ] ], [ [ "\\centerdot",  "", "", "centerdot",    "⋅" ], [ "\\ast",        "", "", "ast",          "∗" ], [ "\\circ",       "", "", "circ",         "∘" ], [ "\\oplus",      "", "", "oplus",        "⊕" ], [ "\\otimes",     "", "", "otimes",       "⊗" ], [ "\\square",     "", "", "square",       "□" ], [ "\\nmid",       "", "", "nmid",         "∤" ], [ "\\rightmapsto", "", "", "rightmapsto", "↦" ], [ "\\wr",         "", "", "wr",           "≀" ], [ "\\triangleleft","", "", "triangleleft", "◅" ], [ "\\triangleright","","", "triangleright","▻" ], [ "\\ltimes",     "", "", "ltimes",       "⋉" ], [ "\\rtimes",     "", "", "rtimes",       "⋊" ], [ "\\bowtie",     "", "", "bowtie",       "⋈" ] ], [ [ "\\vdash",      "", "", "vdash",        "⊢" ], [ "\\dashv",      "", "", "dashv",        "⊣" ], [ "\\intercal",   "", "", "intercal",     "⊤" ], [ "\\perp",       "", "", "perp",         "⊥" ], [ "\\models",     "", "", "models",       "⊧" ] ] ], "TeX_di": [ null, [ [ "\\sum_{i=0}^N", "", "", "sum_{i=0}^N", "∑" ], [ "\\prod_{i=0}^N", "", "", "prod_{i=0}^N","∏" ], [ "\\coprod",      "", "", "coprod",      "∐" ] ], [ [ "\\lfloor",      "", "", "lfloor",      "⌊" ], [ "\\rfloor",      "", "", "rfloor",      "⌋" ], [ "\\lceil",       "", "", "lceil",       "⌈" ], [ "\\rceil",       "", "", "rceil",       "⌉" ] ], [ [ "\\prime",       "", "", "prime",       "′" ], [ "\\int_{-N}^N",  "", "", "int",         "∫" ], [ "\\iint",        "", "", "iint",        "∬" ], [ "\\iiint",       "", "", "iiint",       "∭" ], [ "\\oint_c",      "", "", "oint_c",      "∮" ], [ "\\partial",     "", "", "partial",     "∂" ], [ "\\Delta",       "", "", "Delta",       "∆" ], [ "\\nabla",       "", "", "nabla",       "∇" ] ], [ [ "\\Complex",     "", "", "Complex",     "ℂ" ], [ "\\mathbb{H}",   "", "", "mathbb{H}",   "ℍ" ], [ "\\Natural",     "", "", "Natural",     "ℕ" ], [ "\\mathbb{P}",   "", "", "mathbb{P}",   "ℙ" ], [ "\\Rational",    "", "", "Rational",    "ℚ" ], [ "\\Real",        "", "", "Real",        "ℝ" ], [ "\\Integer",     "", "", "Integer",     "ℤ" ], [ "\\aleph",       "", "", "aleph",       "ℵ" ] ] ], "TeX_gr": [ null, [ [ "\\alpha",  "", "", "", "α" ], [ "\\beta",   "", "", "", "β" ], [ "\\gamma",  "", "", "", "γ" ], [ "\\delta",  "", "", "", "δ" ], [ "\\epsilon", "", "", "", "ε" ], [ "\\zeta",   "", "", "", "ζ" ], [ "\\eta",    "", "", "", "η" ], [ "\\theta",  "", "", "", "θ" ], [ "\\iota",   "", "", "", "ι" ], [ "\\kappa",  "", "", "", "κ" ], [ "\\lambda", "", "", "", "λ" ], [ "\\mu",     "", "", "", "μ" ], [ "\\nu",     "", "", "", "ν" ], [ "\\xi",     "", "", "", "ξ" ], [ "\\omicron", "", "", "", "ο" ], [ "\\pi",     "", "", "", "π" ], [ "\\rho",    "", "", "", "ρ" ], [ "\\sigma",  "", "", "", "σ" ], [ "\\tau",    "", "", "", "ς" ], [ "\\upsilon", "", "", "", "τ" ], [ "\\phi",    "", "", "", "υ" ], [ "\\chi",    "", "", "", "φ" ], [ "\\psi",    "", "", "", "χ" ], [ "\\omega",  "", "", "", "ψ" ] ], [ [ "\\Alpha",  "", "", "", "Α" ], [ "\\Beta",   "", "", "", "Β" ], [ "\\Gamma",  "", "", "", "Γ" ], [ "\\Delta",  "", "", "", "Δ" ], [ "\\Epsilon", "", "", "", "Ε" ], [ "\\Zeta",   "", "", "", "Ζ" ], [ "\\Eta",    "", "", "", "Η" ], [ "\\Theta",  "", "", "", "Θ" ], [ "\\Iota",   "", "", "", "Ι" ], [ "\\Kappa",  "", "", "", "Κ" ], [ "\\Lambda", "", "", "", "Λ" ], [ "\\Mu",     "", "", "", "Μ" ], [ "\\Nu",     "", "", "", "Ν" ], [ "\\Xi",     "", "", "", "Ξ" ], [ "\\Omicron", "", "", "", "Ο" ], [ "\\Pi",     "", "", "", "Π" ], [ "\\Rho",    "", "", "", "Ρ" ], [ "\\Sigma",  "", "", "", "Σ" ], [ "\\Tau",    "", "", "", "Τ" ], [ "\\Upsilon", "", "", "", "Υ" ], [ "\\Phi",    "", "", "", "Φ" ], [ "\\Chi",    "", "", "", "Χ" ], [ "\\Psi",    "", "", "", "Ψ" ], [ "\\Omega",  "", "", "", "Ω" ] ], [ 0, " var: " ], [ [ "\\varepsilon", "", "", "", "ε" ], [ "\\vartheta",  "", "", "", "θ" ], [ "\\varkappa",  "", "", "", "κ" ], [ "\\varpi",     "", "", "", "π" ], [ "\\varrho",    "", "", "", "ρ" ], [ "\\varsigma",  "", "", "", "σ" ], [ "\\varphi",    "", "", "", "υ" ] ] ], "TeX_tx": [ null, [ [ "\\mbox",        "",  "", "", "mbox" ], [ "\\text",        "",  "", "", "text" ], [ "\\displaystyle", "", "", "", "displaystyle" ], [ "\\textstyle",   "",  "", "", "textstyle" ], [ "\\boldsymbol{", "}", "", "","boldsymbol" ], [ "\\mathit{",     "}", "", "italic", "mathit" ], [ "\\mathrm{",     "}", "", "roman", "mathrm" ], [ "\\mathsf{",     "}", "", "sans serif","mathsf" ], [ "\\color{",      "}", "", "", "color" ] ] ] };  // .defs.global ETSI.defs.global.IPA_T = ETSI.defs.global.IPA.concat( [ [ [ "" ] ] ] );

// No customization recommended beyond this point.

function fiat { // Perform update; furnish entire list and model once again // Precondition: //   GUI environment available //   document ready // Postcondition: //   Gadget equipped // Uses: //   >  .gui.builder //   >  .defs.opts //   >  .vsn //   >  .gui.self //   >  .gui.hintList //   >  .gui.hintMenu //   >< .gui.$container //    < .gui.$wrapper //    < .gui.$gadget //    < .gui.$menu //   .gui.fiat //   .factory //   .gui.favour //   .gui.focus //   .gui.facet // 2017-06-01 PerfektesChaos@de.wikipedia var later = ( ETSI.gui.$container ? true : false ), i,         multi, n,         $opt, $sep; if ( ETSI.gui.builder ) { ETSI.gui.fiat; }     ETSI.gui.$container = $( ETSI.gui.container ); multi              = ETSI.gui.$container.length; if ( multi ) { ETSI.gui.$container.remove( "." + ETSI.gui.self );// each ETSI.factory; ETSI.gui.favour; if ( ETSI.defs.opts ) { n   = ETSI.defs.opts.length; $sep = $( " " ); if ( ! later ) { ETSI.gui.focus; }           ETSI.gui.$wrapper = $( " " ); ETSI.gui.$wrapper.attr( "class", ETSI.gui.self ); ETSI.gui.$gadget = $( " " ); ETSI.gui.$gadget.attr( "class", ETSI.gui.self + "-gadget" ); if ( ETSI.gui.hintList ) { ETSI.gui.$gadget.attr( "title",                                     ETSI.gui.hintList /** + x **/ ); }           ETSI.gui.$gadget.change( ETSI.gui.facet ) .keyup( ETSI.gui.facet ); for ( i = 0; i < n;  i++ ) { $opt = $( " " ); $opt.attr( "value", i ) .text( ETSI.defs.opts[ i ][ 3 ] ); ETSI.gui.$gadget.append( $opt ); }  // for i            ETSI.gui.$wrapper.append( ETSI.gui.$gadget ) .append( $sep ); ETSI.gui.$menu = $( " " ); ETSI.gui.$menu.attr( "class", ETSI.gui.self + "-menu" ) .css( "display", "inline" ); if ( ETSI.gui.hintMenu ) { ETSI.gui.$menu.attr( "title", ETSI.gui.hintMenu ); }           ETSI.gui.$wrapper.append( ETSI.gui.$menu ); ETSI.gui.facet( false ); for ( i = 1; i < multi;  i++ ) { ETSI.gui.$container.eq( i ) .prepend( ETSI.gui.$wrapper.clone ); }  // for i            ETSI.gui.$container.first.prepend( ETSI.gui.$wrapper ); ETSI.gui.$container.show; }     }   }   // fiat

function fire { // Initialize on load of document, or update // Precondition: //   document ready // Uses: //    < .listen //   fiat // 2017-06-06 PerfektesChaos@de.wikipedia ETSI.listen = true; fiat; }  // fire

function fired { // Initialize on load of codes, or update // Uses: //   >  .listen //    < .loaded //   fiat //   (fire) // 2017-06-06 PerfektesChaos@de.wikipedia if ( ETSI.listen ) { fiat; } else { $( fire ); }     ETSI.loaded = true; }  // fired

ETSI.attr.fetch = function ( access ) { // Retrieve attribute value from definition and user customization // Precondition: //   access  -- definition item // Uses: //   >< .attr.current // 2011-10-27 PerfektesChaos@de.wikipedia var d = access[ 0 ], s,         v;      if ( d ) { for ( v in this.current ) { if ( ! this.current[ v ] ) { s = d[ v ]; if ( typeof s === "string" ) { this.current[ v ] = s;              } }        }   // for v in .current }  };   // .attr.fetch

ETSI.attr.fit = function ( attempt ) { // Does definition element match requirements for a valid attr? // Precondition: //   attempt  -- item // Postcondition: //   Returns true if is valid attr // Uses: //   >  .attr.names // 2011-10-27 PerfektesChaos@de.wikipedia var r = false, v;     if ( attempt ) { for ( v in this.names ) { if ( typeof attempt[ v ] === "string" ) { r = true; break;  // for v in .names }        }   // for v in .names } else { r = true; }     return r;   };   // .attr.fit

ETSI.attr.furnish = function ( assign, acquire, applied ) { // Equip menu with attributes // Precondition: //   assign   -- jQuery menu to be extended //   acquire  -- ID of requested content definition //   applied  -- definition element which provided menu content // Postcondition: //   Menu attributed by cascading properties, if any. // Uses: //   >  .attr.names //   >  .defs.current //    < .attr.current //   .attr.fetch // 2011-11-26 PerfektesChaos@de.wikipedia var n = ETSI.defs.current.length, d,         i,          q,          v;      this.current = { }; for ( v in this.names ) { this.current[ v ] = false; }  // for v in attr.names this.current.dir = "ltr"; for ( i = 0; i < n;  i++ ) { q = ETSI.defs.current[ i ]; d = q[ 1 ].defs; if ( typeof d === "object" ) { d = d[ acquire ]; if ( typeof d === "object" ) { this.fetch( d ); }        }         if ( q[ 0 ]  ===  applied ) { break;  // for i         } }  // for i      for ( v in this.current ) { d = this.current[ v ]; if ( d ) { if ( this.names[ v ] ) { assign.css( v, d ); } else { assign.attr( v, d ); }        }      }   // for v in attr.current };  // .attr.furnish

ETSI.defs.factory = function { // Build data model from project and user spec // Postcondition: //   .defs.current has been built in current environment // Uses: //   >  .user //   >  .user.lang //   >  .project //   >  .l10n //   >  .lang //    < .defs.current //    < .defs.lead //   .defs.found //   mw.config.get //   .defs.fluent //   .defs.features // 2011-11-26 PerfektesChaos@de.wikipedia var scope = false, shift = false, slang = false, o,         p;      this.current = [ ]; if ( typeof ETSI.user === "object" ) { o = this.found( "user", ETSI.user ); if ( o ) { p = o.lang; if ( typeof p === "string" ) { if ( p.length ) { shift = p;              } }           if ( typeof o.custom === "object" ) { this.lead = true; }        }      }      if ( typeof ETSI.project === "string" ) { if ( ETSI.project.length ) { scope = ETSI.project; }     }      if ( ! scope ) { scope = mw.config.get( "wgDBname" ); }     this.found( "db", scope ); p = scope.search( /wik[it].+$/ ); if ( p > 0 ) { this.found( "project", scope.substr( p ) ); }     if ( typeof ETSI.lang === "string" ) { if ( ETSI.lang.length ) { slang = ETSI.lang; }     }      if ( typeof slang !== "string" ) { slang = mw.config.get( "wgContentLanguage" ); }     p = this.fluent( slang, "projlang", "projsub", false ); if ( typeof shift !== "string" ) { shift = mw.config.get( "wgUserLanguage" ).toLowerCase; }     p = this.fluent( shift, "language", "dialect", p ); this.features; this.current.push( [ "global", { "defs": this.global } ] ); this.fluent( "en", "fallback", false, p ); };  // .defs.factory

ETSI.defs.fade = function ( access ) { // Remove an an option definition from standard options // Precondition: //   access  -- ID of definition // Postcondition: //   .defs.opts is updated // Uses: //   >< .defs.opts // 2011-11-23 PerfektesChaos@de.wikipedia var d,         i,          n;      if ( access ) { n = this.opts.length; for ( i = 0; i < n;  i++ ) { d = this.opts[ i ]; if ( d[ 0 ] ===  access ) { this.opts.splice( i, 1 ); break;  // for i            } }  // for i      } };  // .defs.fade

ETSI.defs.fair = function { // Check standard list, reduce to valid items and build options // Uses: //   >< .defs.tmp //   >< .defs.opts //   .defs.finder // 2011-11-23 PerfektesChaos@de.wikipedia var n   = this.tmp.length / 2, d,         i,          j,          say, seek; for ( i = 0; i < n;  i++ ) { j   = i + i;         seek = this.tmp[ j ]; say = this.tmp[ j + 1 ]; if ( typeof say === "string" &&              typeof seek === "string" ) { if ( say.length ) { d = this.finder( seek ); if ( d ) { d = d.concat( [ say, false ] ); if ( this.opts ) { this.opts.push( d ); } else { this.opts = [ d ]; }              }            }         }      }   // for i      delete this.tmp; };  // .defs.fair

ETSI.defs.features = function { // Assign project and user settings // Precondition: //   defs.current is filled with user and l10n objects // Postcondition: //   Cascading settings performed // Uses: //   >  .defs.current //   .set // 2011-11-26 PerfektesChaos@de.wikipedia var n = this.current.length - 1, c,         i,          p;      for ( i = n;  i >= 0;  i-- ) { c = this.current[ i ][ 1 ].config; if ( typeof c === "object" ) { for ( p in c ) { ETSI.set( p, c[ p ] ); }  // for p in c         } }  // for i-- };  // .defs.features

ETSI.defs.filter = function { // Remove situation dependent list items // Postcondition: //   Standard list has been reduced if appropriate // Uses: //   >< .defs.opts //   >< .defs.reNS // 2011-11-23 PerfektesChaos@de.wikipedia var n = this.opts.length, i,         s;      for ( i = n - 1;  i >= 0;  i-- ) { s = this.opts[ i ][ 0 ]; if ( typeof s === "string" ) { switch ( s.charCodeAt( 0 ) ) { case 47 :  // '/' project type // TODO break; case 58 :  // ':' namespace if ( ! this.reNS ) { this.reNS = "^:" + mw.config.get( "wgNamespaceNumber" ) + "(_.*)?$";                    this.reNS = new RegExp( this.reNS, "" ); }                 if ( ! this.reNS.test( s ) ) { this.opts.splice( i, 1 ); n--; }                 break; }  // switch charCodeAt }     }   // for i-- if ( ! n ) { this.opts = false; }  };   // .defs.filter

ETSI.defs.find = function ( access, alike ) { // Find property within objects in current environment // Precondition: //   access  -- name of property //   alike   -- type of property // Postcondition: //   Returns not-empty value,  or false if not found // Uses: //   >  .defs.current // 2011-11-23 PerfektesChaos@de.wikipedia var n = this.current.length, r = false, i,         p;      for ( i = 0;  i < n;  i++ ) { p = this.current[ i ][ 1 ][ access ]; if ( typeof p ===  alike ) { if ( p ) { r = p;              break;   // for i            } }     }   // for i      return r;   };   // .defs.find

ETSI.defs.finder = function ( acquire ) { // Find content definition within current environment // Precondition: //   acquire  -- ID of requested content definition // Postcondition: //   Returns false if not found, or      //            Array(3):  [0] ID,  [1] definition,  [2] origin // Uses: //   >  .defs.current // 2011-11-23 PerfektesChaos@de.wikipedia var n = this.current.length, d,         i,          g,          p,          r = false; for ( i = 0; i < n;  i++ ) { g = this.current[ i ]; p = g[ 1 ].defs; if ( typeof p === "object" ) { d = p[ acquire ]; if ( typeof d === "object" ) { if ( d.length > 1 ) { r = [ acquire, d,  g[ 0 ] ]; break;  // for i               } }        }      }   // for i      return r;   };   // .defs.finder

ETSI.defs.fluent = function ( assign, appoint, another, already ) { // Build data model with respect to language // Precondition: //   assign   -- string: code of language (ISO 639) //   appoint  -- string: id of language in current data model //   another  -- string: id of dialect in data model //   already  -- Array(2) of known items, or false if not yet set // Postcondition: //   Returns Array(2) of items, or false if not set // Uses: //   .defs.found // 2011-10-27 PerfektesChaos@de.wikipedia var k    = assign.indexOf( "-" ), r    = ( already  ?  already  :  [ false, false ] ), slang = assign.toLowerCase, s,         sub; if ( k > 1 ) { s  = slang.substr( 0,  k - 1 ); sub = s + "_"  +   slang.substr( 0,  k + 1 ); if ( already ) { if ( already[0] === s ) { s = false; }           if ( already[1] === sub ) { sub = false; }        }         if ( s ) { this.found( appoint, s ); }        if ( sub ) { this.found( another, sub ); }        r = [ s, sub ]; } else { if ( already ) { if ( already[ 0 ] ===  slang ) { slang = false; }        }         if ( slang ) { this.found( appoint, slang ); r = [ slang, false ]; }     }      return r;   };   // .defs.fluent

ETSI.defs.format = function { // Adjust all definitions in focus as canonical form definition // Postcondition: //   All definitions available in canonical form // Uses: //   this //   >  .defs.current //   .attr.fit // 2011-11-23 PerfektesChaos@de.wikipedia var n = this.current.length, c,         d,          e,          g,          i,          o,          p;      for ( i = 0;  i < n;  i++ ) { o = this.current[ i ][ 1 ]; c = o.defs; if ( typeof c === "object" ) { if ( c ) { for ( e in c ) { d = c[ e ]; if ( typeof d === "object" ) { if ( ETSI.attr.fit( d ) ) { c[ e ] = [ d ]; } else { if ( $.isArray( d ) ) { if ( ! ETSI.attr.fit( d[0] ) ) { d.unshift( [ null ] ); }                       } else { p = d.atributes; g = d.groups; if ( p || g ) { if ( ! p ) { p = null; }                             if ( g ) { c[ e ] = [ p, { "groups": g } ]; } else { c[ e ] = [ p ]; }                          } else { d = false; }                       }                     }                  } else { d = false; }                 if ( ! d ) { delete c[ e ]; }              }   // for e in c            } } else { c = false; }        if ( ! c ) { delete o.defs; }     }   // for i   };   // .defs.format

ETSI.defs.found = function ( appoint, assign ) { // Append data model item to current model, if valid // Precondition: //   appoint  -- string: id in current data model //   assign   -- string: id in .l10n. object (direct access) // Postcondition: //   Returns object reference in data model // Uses: //   >  .l10n //    < .defs.current // 2011-11-23 PerfektesChaos@de.wikipedia var o = false, r = false; switch ( typeof assign ) { case "object" : o = assign; break; case "string" : o = ETSI.l10n[ assign ]; break; }  // switch typeof assign if ( typeof o === "object" ) { if ( o ) { this.current.push( [ appoint, o ] ); r = o;        } }     return r;   };   // .defs.found

ETSI.defs.friend = function ( access ) { // Find option title within standard list // Precondition: //   access  -- ID of option // Postcondition: //   Returns false if not found, or title string // Uses: //   >  .defs.opts // 2011-11-23 PerfektesChaos@de.wikipedia var n = this.opts.length, i,         o,          r = false; for ( i = 0; i < n;  i++ ) { o = this.opts[ i ]; if ( o[ 0 ] ===  access ) { r = o[ 3 ]; break; }     }   // for i      return r;   };   // .defs.friend

ETSI.defs.furnish = function { // Customize standard list by heading elements and removing items // Precondition: //   Customization entry available //   Standard list in preprocessed form // Postcondition: //   Standard list has been updated // Uses: //   >  .user.custom //   >< .defs.opts //   .defs.finder //   .defs.friend //   .defs.fade //   jQuery.isArray //   .util.trimRight // 2015-06-25 PerfektesChaos@de.wikipedia var i,         j,          n,          opt, say, seek, temp; if ( typeof ETSI.user.custom === "object" ) { if ( $.isArray( ETSI.user.custom ) ) { n = ETSI.user.custom.length / 2; if ( n ) { temp = [ ]; for ( i = 0; i < n;  i++ ) { j   = i + i;                  seek = ETSI.user.custom[ j ]; if ( typeof seek === "string" ) { if ( seek.length ) { j++; say = ETSI.user.custom[ j ]; if ( say ) { opt = false; if ( typeof say === "string" ) { say = ETSI.util.trimRight( say ); if ( ! say.length ) { say = false; }                          } else { say = this.friend( seek ); if ( typeof say !== "string" ) { say = "<" + seek + ">"; }                          }                           if ( say ) { opt = this.finder( seek ); if ( opt ) { opt = opt.concat( [ say, false ] ); temp.push( opt ); }                          }                        }                        if ( seek !== "" ) { this.fade( seek ); }                    }                  }               }   // for i               if ( temp.length ) { this.opts = temp.concat( this.opts ); }           }   // user.custom not empty }  // user.custom isArray }  // user.custom };  // .defs.furnish

ETSI.gui.facet = function ( action ) { // Display menu: initial selection or handle GUI event // Precondition: //   action  -- false:  initialization after setup //              object: GUI event // Uses: //   >  .gui.$gadget //   >  .gui.selection //   >  .gui.cookie //   >  .gui.$menu //   >  .defs.opts //   .gui.find //   .menu.factory // Remark: May be used as event handler -- 'this' is not accessed // 2017-05-31 PerfektesChaos@de.wikipedia var learn = ( typeof ETSI.gui.cookie === "string" ), k,         s;      if ( action ) { k = ETSI.gui.$gadget.prop( "value" ); // .attr -> prop } else { if ( typeof ETSI.gui.selection ===  "string" ) { k = ETSI.gui.find( ETSI.gui.selection ); } else { k = -1; }        if ( k < 0 ) { if ( learn ) { if ( typeof window.sessionStorage ===  "object" ) { s = window.sessionStorage.getItem( ETSI.gui.cookie ); k = ETSI.gui.find( s ); }           }         }         ETSI.gui.$gadget.prop( "value", k );  // .attr -> prop }     k = ( k < 0  ?  0  :  k ); if ( ! ETSI.defs.opts[ k ][ 4 ] ) { ETSI.defs.opts[ k ][ 4 ] = ETSI.menu.factory( ETSI.defs.opts[ k ] ); }     ETSI.gui.$menu.children.detach; ETSI.gui.$menu.append( ETSI.defs.opts[ k ][ 4 ] ); if ( learn ) { if ( typeof window.sessionStorage ===  "object" ) { try { window.sessionStorage.setItem( ETSI.gui.cookie,                                             ETSI.defs.opts[ k ][ 0 ] );

} catch ( e ) { }        }      }   };   // .gui.facet

ETSI.gui.fasten = function ( around, arglist ) { // Trim selection // Precondition: //   around   -- selected text //   arglist  -- parameters for jQuery.textSelection // Postcondition: //   Returns trimmed selected text and extends arglist //   >< .gui.reWSbeg //    < .gui.reWSend // 2018-02-15 PerfektesChaos@de.wikipedia var r = around, got; if ( r ) { if ( typeof this.reWSbeg !==  "object" ) { this.reWSbeg = new RegExp( "^\\s+" ); this.reWSend = new RegExp( "\\S(\\s+)$" ); }        got = this.reWSbeg.exec( r ); if ( got ) { if ( typeof arglist.pre ===  "string" ) { arglist.pre = got[ 0 ] + arglist.pre; } else { arglist.pre = got[ 0 ]; }           r = r.substr( got[ 0 ].length ); }        got = this.reWSend.exec( r ); if ( got ) { if ( typeof arglist.post ===  "string" ) { arglist.post = arglist.post + got[ 1 ]; } else { arglist.post = got[ 1 ]; }           r = r.substr( 0,  r.length - got[ 1 ].length ); }     }      return r;   };   // .gui.fasten

ETSI.gui.favour = function { // Kick out competitors // Uses: //   this //   >  .gui.old //   mw.util.addCSS // 2014-11-28 PerfektesChaos@de.wikipedia if ( typeof this.old === "string" ) { ETSI.gui.$container.empty; mw.util.addCSS( this.old + "{display:none}" );  // if later }  };   // .gui.favour

ETSI.gui.fiat = function { // Assign or create target container // Uses: //   >< .gui.builder //    < .gui.container // 2017-06-01 PerfektesChaos@de.wikipedia var f,         i,          lone, n,         rule, s,         sel, selectors, $container, $div, $related; for ( sel in this.builder ) { if ( /^[.#][^,.#= ]+$/.test( sel ) ) { $container = $( sel ); if ( ! $container.length ) { rule = this.builder[ sel ]; if ( typeof rule ===  "object"                    &&     rule   &&                    typeof rule.fiat  ===  "string"                    &&     rule.fiat   &&                    typeof rule.start  ===  "string"                    &&     rule.start ) { $related = $( rule.start ); f       = rule.fiat; n       = $related.length; if ( n  &&                       typeof $related[ f ]  ===  "function" ) { lone = ( sel.substr( 0, 1 ) ===  "#" ); if ( lone &&  n !== 1 ) { n = 0; }                    if ( n ) { s = sel.substr( 1 ); for ( i = 0; i < n;  i++ ) { $div = $( " " ); if ( lone ) { $div.attr( "id", s ); } else { $div.addClass( s ); }                          $related.eq( i )[ f ]( $div ); }  // for i                        $container = $( sel ); }                 }               }            }            if ( $container.length ) { if ( selectors ) { selectors = selectors + "," + sel; } else { selectors = sel; }           }         }      }   // for sel in this.builder if ( selectors ) { this.container = selectors; } else { this.container = "#"; }     this.builder = false; };  // .gui.fiat

ETSI.gui.fill = function ( arglist, additional ) { // Perform insertion // Precondition: //   arglist     -- parameters for jQuery.textSelection //   additional  -- event.ctrlKey code // Uses: //   >  .gui.$textarea //   >  .defs.looser //   >< .gui.wikEd:: //       >  .wikEd.focus //       >< .wikEd.active //   >< .gui.$current //   .gui.flip //   >  wikEd:: //         >  .useWikEd //   .gui.fossil //   jQuery.textSelection // 2018-02-15 PerfektesChaos@de.wikipedia var launch, pars; if ( this.$current.length ) { launch = true; if ( this.wikEd ) { if ( window.wikEd.useWikEd !== true ) { this.wikEd.active = false; }           if ( this.wikEd.active ) { if ( this.wikEd.focus ) { if ( arglist.post ||                       arglist.peri  ||                       arglist.replace ) { // jQuery.textSelection (2011-11) does not support // DOM composition within iframe launch = this.flip( arglist ); }                 if ( window.wikEd.frameBody ) { window.wikEd.UpdateTextarea( null ); }                 this.$current = this.$textarea; }           } else { this.wikEd.focus = false; }        }         if ( launch ) { pars = arglist; if ( ETSI.defs.looser ) { if ( arglist.post   === undefined  &&                    arglist.replace === undefined ) { pars.replace = true; if ( arglist.peri === undefined ) { pars.peri = ""; }              }            }            if ( additional  &&  ! pars.replace ) { pars = { peri:   arglist.peri, pre:    arglist.pre, post:   arglist.post, replace: true }; }           if ( typeof ETSI.user  ===  "object"                 &&     ETSI.user   &&                 typeof ETSI.user.client  ===  "string"                 &&     ETSI.user.client  ===  "LFdoubled" ) { this.fossil( "encapsulateSelection", pars ); } else { this.$current.textSelection( "encapsulateSelection",                                           pars ); }        }      }   };   // .gui.fill

ETSI.gui.find = function ( adjust ) { // Retrieve number of item in gadget for a certain identifier // Precondition: //   adjust  -- identifier // Postcondition: //   Returns number,  < 0 if not found // Uses: //   >  .defs.opts // 2011-11-23 PerfektesChaos@de.wikipedia var r = -1, i,         n;      n = ETSI.defs.opts.length; for ( i = 0; i < n;  i++ ) { if ( ETSI.defs.opts[ i ][ 0 ] ===  adjust ) { r = i;           break;   // for i         } }  // for i      return r;   };   // .gui.find

ETSI.gui.fit = function ( arglist, additional ) { // Perform RegExp replacement // Precondition: //   arglist  -- Array(6) //               [0] to be inserted before caret / selection //                   string or empty //               [1] to be inserted after caret / selection //                   string or empty //               [2] string with replacement expression //               [5] string with RegExp to process selection //   additional  -- event.ctrlKey code // Uses: //   >  .gui.$current //   jQuery.textSelection //   .gui.fill // 2017-05-01 PerfektesChaos@de.wikipedia var pars, range, re, sel; if ( this.$current.length ) { pars = { }; range = this.$current.textSelection( "getCaretPosition",                                             { "startAndEnd":                                                true } ); if ( arglist[0] ) { pars.pre = arglist[0]; }        if ( arglist[1] ) { pars.post = arglist[1]; }        if ( range[0] < range[1] ) { if ( typeof arglist[ 2 ] ===  "string"  &&                 typeof arglist[ 5 ]  ===  "string" ) { re = new RegExp( arglist[ 5 ], "" ); sel = this.$current.textSelection( "getSelection" ); pars.peri   = sel.replace( re, arglist[2] ); pars.replace = true; }        }         this.fill( pars, additional ); }  };   // .gui.fit

ETSI.gui.flip = function ( arglist ) { // Strip whitespace from current selection, insert in special cases //   (mainly for wikEd) // Precondition: //   arglist  -- encapsulateSelection object //               >  .pre //               >  .peri //               >  .post //               >  .replace //   Browser supports wikEd, wikEd is active // Postcondition: //   Returns false, if insertion has been performed // Uses: //   >  .gui.self //   >< .gui.wikEd //          < .encapsulateSelection //   .gui.flipper //   >  wikEd:: //         .GetSelection //         .EditButton //   .util.trimLeft //   .util.trimRight // 2015-06-25 PerfektesChaos@de.wikipedia var r    = true, range = window.wikEd.GetSelection, sel  = range.toString, n    = sel.length; if ( n ) { if ( n !==  ETSI.util.trimLeft( sel ).length   ||              n  !==  ETSI.util.trimRight( sel ).length ) { this.wikEd.encapsulateSelection = arglist; window.wikEd.EditButton( null,                                    this.self,                                     null,                                     this.flipper ); r = false; }  // heading or trailing whitespace }  // not empty return r;  };   // .gui.flip

ETSI.gui.flipper = function ( about ) { // Handler for change per wikEd with whitespace around selection // Precondition: //   about  -- wikEd action object // Uses: //   >  .gui.wikEd //         < .encapsulateSelection //              >  .pre //              >  .peri //              >  .post //              >  .replace //   >  wikEd:: //         .GetText //         .EditButton //   >< .gui.reWSbeg //    < .gui.reWSend // Remark: Used as event handler -- 'this' is not ETSI // 2018-02-15 PerfektesChaos@de.wikipedia var encapsulate = ETSI.gui.wikEd.encapsulateSelection, got, select, start, sample, suffix; // select the appropriate text change target // (whole, selection, cursor,     //  focusWord, focusLine, selectionWord, or selectionLine) // focus... is the text under the cursor; // ...Word and ...Line extend the target //                    to the start/end of the word or line window.wikEd.GetText( about, "selection" ); about.changed = about.selection; select       = about.changed.plain; start        = encapsulate.pre; suffix       = encapsulate.post; if ( typeof start === "string" ) { start = start.replace( /&/g, "&amp;" ) .replace( //g, "&gt;" ); } else { start = ""; }     if ( typeof suffix === "string" ) { suffix = suffix.replace( /&/g, "&amp;" ) .replace( //g, "&gt;" ); } else { suffix = ""; }     if ( typeof ETSI.gui.reWSbeg  !==  "object" ) { ETSI.gui.reWSbeg = new RegExp( "^\\s+" ); ETSI.gui.reWSend = new RegExp( "\\S(\\s+)$" ); }     got = ETSI.gui.reWSbeg.exec( select ); if ( got ) { start = got[0] + start; select = select.substr( got[0].length ); }     got = ETSI.gui.reWSend.exec( select ); if ( got ) { suffix = suffix + got[1]; select = select.substr( 0, select.length - got[1].length ); }     if ( encapsulate.replace ) { select = ""; }     sample = encapsulate.peri; if ( typeof sample === "string" ) { if ( ! select.length ) { sample = sample.replace( /&/g, "&amp;" ) .replace( //g, "&gt;" ); }     } else { sample = select; }     about.changed.plain = start + sample + suffix; // keep the changed text selected about.changed.keepSel = true; return; };  // .gui.flipper

ETSI.gui.focus = function { // Initialize focussing // Precondition: //   document ready // Postcondition: //   Binding is established // Uses: //   this //    < .gui.$textarea //    < .gui.$current //    < .gui.wikEd //   >  wikEd:: //         >  .disabled //         >  .useWikEd //         >  .frameDocument //         .Setup //   jQuery.focus //   (.gui.frames) // 2015-03-09 PerfektesChaos@de.wikipedia var $ins =  $( "textarea, input:text" ); this.$textarea =  $( "#wpTextbox1" ); this.wikEd     =  false; $ins.focus( function { ETSI.gui.$current = $( this );                              if ( ETSI.gui.wikEd ) {                                  ETSI.gui.wikEd.focus = false;                               }                             } ); if ( this.$textarea.length ) { this.$current = this.$textarea; } else { this.$current = $( "textarea, input:text" ).first; }     if ( typeof window.wikEd === "object" ) { if ( window.wikEd &&  this.$textarea.length ) { if ( typeof window.wikEd.Setup === "function" ) { // not just wikEdDiff? if ( typeof window.wikEd.disabled !== "boolean"                   // asynchronous overrun                    ||  ! window.wikEd.disabled ) { window.wikEd.Setup; }              if ( typeof window.wikEd.disabled === "boolean" ) { this.wikEd = ! window.wikEd.disabled; }           }            if ( this.wikEd ) { this.wikEd = { active: window.wikEd.useWikEd, focus: true }; window.wikEd.frameDocument.addEventListener( "click",                                                           this.frames,                                                            false ); window.wikEd.frameDocument.addEventListener( "dblclick",                                                           this.frames,                                                            false ); window.wikEd.frameDocument.addEventListener( "keypress",                                                           this.frames,                                                            false ); /* wikEd uses an iframe which cannot receive focus under < .gui.reCRLF //   .gui.fasten // 2018-02-15 PerfektesChaos@de.wikipedia var textarea = this.$current.get( 0 ), iBeg    = textarea.selectionStart  ||  0, iEnd    = textarea.selectionEnd    ||  iBeg, story   = this.$current.val, sub     = story.slice( 0, iEnd ), r, sel, suffix; if ( typeof this.reCRLF !==  "object" ) { this.reCRLF = new RegExp( "\r?\n", "g" ); }     sub  = sub.replace( this.reCRLF, "\r\n" ) .slice( 0, iEnd ); iEnd = sub.replace( this.reCRLF, "\n" ).length; if ( action === "encapsulateSelection" ) { suffix = story.slice( iEnd ); story = sub.slice( 0, iBeg ) .replace( this.reCRLF, "\n" ); //alert(iBeg+", "+iEnd+" >>>"+story+"<<<  >>>"+suffix) if ( ! arglist.replace ) { sel = sub.slice( iBeg ).replace( this.reCRLF, "\n" ); sel = ETSI.gui.fasten( sel, arglist ); }        if ( typeof arglist.pre  ===  "string" ) { story = story + arglist.pre; }        if ( arglist.replace ) { if ( typeof arglist.peri ===  "string" ) { story = story + arglist.peri; }        } else { story = story + sel; }        if ( typeof arglist.post  ===  "string" ) { story = story + arglist.post; }        iEnd  = story.replace( this.reCRLF, "\r\n" ).length; story = story + suffix; this.$current.val( story ); textarea.selectionEnd  = iEnd; textarea.selectionStart = iBeg; this.$current.focus; textarea.selectionEnd  = iEnd; textarea.selectionStart = iEnd; /*              var e, i, s;               e = [ "pre", "peri", "post" ]; for ( i = 0; i < e.length;  i++ ) { s = e[ i ]; if ( typeof pars[ s ] ===  "string"                       &&     pars[ s ] ) { pars[ s ] = pars[ s ].replace( this.reCRLF,                                                   "\r\n" ); }              }   // for i               */ }     return r;   };   // .gui.fossil

ETSI.gui.frames = function ( active ) { // Handle iframe focussing, e.g. wikEd // Precondition: //   active  -- object: event // Uses: //   >< .gui.wikEd:: //        < .wikEd.focus // 2011-11-21 PerfektesChaos@de.wikipedia if ( this.wikEd ) { this.wikEd.focus = true; }  };   // .gui.frames

ETSI.menu.factory = function ( apply ) { // Build menu area // Precondition: //   apply  -- Array(5) //             [0] identifier //             [1] definition //             [2] origin //             [3] option title //             [4] $menu (false) // Postcondition: //   Returns jQuery object for $menu (apply[4]) // Uses: //   >  .menu.separator //   >  .gui.self //   >  .menu.divide //   >< .menu.$sep //   .attr.furnish //   .menu.field // 2017-05-11 PerfektesChaos@de.wikipedia var d   = apply[ 1 ], lead = false, n   = d.length, $r  = $( " " ), i,         sel, $sep; $r.css( "display", "inline" ); if ( typeof this.$sep !== "object" ) { this.$sep = false; if ( typeof this.separator === "string" ) { if ( this.separator.length ) { $sep = $( " " ); $sep.addClass( ETSI.gui.self + "-sep" ) .text( this.separator ); if ( typeof this.divide === "object" ) { $sep.css( this.divide ); }              this.$sep = $( " " ); this.$sep.text( " " ) .prepend( $sep ); }        }      }      ETSI.attr.furnish( $r,  apply[ 0 ],  apply[ 2 ] ); sel = $r.attr( "class" ); if ( typeof sel === "string" ) { sel = sel + ","; } else { sel = ""; }     sel = sel + ETSI.gui.self + "-menu-"  + apply[ 0 ]; $r.attr( "class", sel ); for ( i = 1; i < n;  i++ ) { lead = this.field( $r, d[ i ],  lead ); }  // for i      return $r; };  // .menu.factory

ETSI.menu.family = function ( assign, apply, align ) { // Process definition element of type "numeric range of single UCS" // Precondition: //   assign  -- jQuery element to be extended //   apply   -- definition item; Array with at least 3 elements //              [0] code for "numeric range" //              [1] UCS, first character in first pair //              [2] UCS, last character in first pair //              [4] optional: UCS, first character in second pair //              [5] optional: UCS, last character in second pair //              ... etc.      //    align   -- true: insert group separator ahead // Ranges are supposed to cover less than 1024 codepoints // Postcondition: //   assign is extended // Uses: //   .menu.fence //   .menu.fill //   .menu.fixed // 2011-11-23 PerfektesChaos@de.wikipedia var n = apply.length, i,         j,          k,          m;      this.fence( assign, align ); for ( k = 1; k < n;  k += 2 ) { i = apply[ k ]; j = apply[ k + 1 ]; m = j - i;        if ( i < j ) { if ( m < 1024 ) { for( true;  i <= j;  i++ ) { this.fill( assign, i ); }  // for i               m = false; }        } else {   // rtl if ( m > -1024 ) { for ( true; i >= j;  i-- ) { this.fill( assign, i ); }  // for i-- m = false; }        }         if ( m ) { this.fixed( assign,                       "ERROR: too many UCS chars: " + i + "..." + j,                        true ); }     }   // for k   };   // .menu.family

ETSI.menu.feed = function ( assign, apply, align ) { // Process a definition element of type "separated compressed" // Precondition: //   assign  -- jQuery element to be extended //   apply   -- definition item; Array with at least 2 elements //              [0] number < 0, -[0]: code of separator //              [1] and further: string, separated by -[0] //   align   -- true: insert group separator ahead // Postcondition: //   assign is extended // Uses: //   .menu.fence //   .menu.fill // 2011-10-27 PerfektesChaos@de.wikipedia var lead  = align, more  = apply.length, sep   = String.fromCharCode( -apply[ 0 ] ), i,         m,          n,          subs, stream; for ( i = 1; i < more;  i++ ) { stream = apply[ i ]; if ( typeof stream === "string" ) { subs = stream.split( sep ); n   = subs.length; this.fence( assign, n && lead ); for ( m = 0; m < n;  m++ ) { this.fill( assign, subs[ m ] ); }  // for m         } lead = true; }  // for i   };   // .menu.feed

ETSI.menu.fence = function ( assign, align ) { // Insert group separator conditionally // Precondition: //   assign  -- jQuery element to be extended //   align   -- true: insert group separator ahead, else nothing // Postcondition: //   group separator has been appended to assign, if align // Uses: //   >  .menu.$sep // 2011-11-23 PerfektesChaos@de.wikipedia if ( align ) { if ( this.$sep ) { assign.append( this.$sep.clone ); }     }   };   // .menu.fence

ETSI.menu.field = function ( assign, apply, align ) { // Process a group (one item in definition array) // Precondition: //   assign  -- jQuery element to be extended //   apply   -- definition element //              Array:   with specifications //              boolean: false  -- no group separator //              number:  0      -- no group separator //   align   -- true: insert group separator ahead // Postcondition: //   Returns necessity for separator before next group // Uses: //   .menu.flush //   .menu.family //   .menu.figures //   .menu.feed //   .menu.fixed //   .menu.fence //   .menu.fill // 2011-11-28 PerfektesChaos@de.wikipedia var light = true, r    = true, begin, i,         n;      if ( apply ) { begin = apply[0]; light = ( typeof begin === "number" ); if ( light ) { if ( begin === 1 ) { this.flush( assign, apply, align ); } else if ( begin === 2 ) { this.family( assign, apply, align ); } else if ( begin === 3 ) { this.figures( assign, apply, align ); } else if ( begin < -31 ) { this.feed( assign, apply, align ); } else if ( ! begin ) { if ( apply[1] ) { this.fixed( assign, apply[1], align ); }              r = false; } else if ( begin > 126 ) { light = false; }        }      } else { r = false; }  // apply if ( ! light ) { n = apply.length; this.fence( assign, align ); for ( i = 0; i < n;  i++ ) { this.fill( assign, apply[i] ); }  // for i      } return r;  };   // .menu.field

ETSI.menu.figures = function ( assign, apply, align ) { // Process a definition element of type "numeric UCS sequences" // Precondition: //   assign  -- jQuery element to be extended //   apply   -- definition item; Array with at least 3 elements //              [0] code for "numeric sequences" //              [1] UCS of first character in first token //              [2] UCS of next character in first token, //                  or false / 0 to separate from next token //              [...] UCS of first character in second token //              ... etc.      //    align   -- true: insert group separator ahead // Ranges are supposed to cover less than 1024 codepoints // Postcondition: //   assign is extended // Uses: //   .menu.fence //   .menu.fromCharCode //   .menu.fill // 2011-11-28 PerfektesChaos@de.wikipedia var n = apply.length, s = "", i,         k;      this.fence( assign, align ); for ( k = 1; k < n;  k++ ) { i = apply[ k ]; if ( i ) { s = s + this.fromCharCode( i ); } else { this.fill( assign, s ); s = ""; }     }   // for k   };   // .menu.figures

ETSI.menu.fill = function ( assign, apply ) { // Create a single token // Precondition: //   assign  -- jQuery element to be extended //   apply   -- specification //              string: insert ahead //              number: insert UCS ahead //              Array(1...)    [0]...[4]: string or empty //              [0] to be inserted before cursor pos / selection //              [1] to be inserted after cursor pos / selection //              [2] to be inserted if there is no selection range //              [3] tooltip //              [4] explicit label for token //              [5] advanced //                  true:     Replace current selection, if any. //                  function: to be executed with apply //                  string:   RegExp for selection, apply to [2] //              [6] double advanced //                  true:     Replace current selection, if any. //                  function: to be executed with apply //              [...] any other value that is currently ignored // Uses: //   >  .menu.stick //   >  .gui.self //   .menu.fromCharCode //   (.gui.fill) //   (.menu.fun) //   (.gui.fit) // 2017-05-22 PerfektesChaos@de.wikipedia var exec  = false, label = false, light = false, loose = false, pars  = false, say   = "", story = false, n,         sample, start, suffix, $space, $span, $token; switch ( typeof apply ) { case "number" : if ( apply > 0 ) { say  = this.fromCharCode( apply ); light = true; }           break; case "string" : say  = apply; light = true; break; case "object" : if ( apply ) { loose = false; n     = apply.length;  // undefined  en.WP               sample = ""; start = ( apply[0] ? apply[0] : "" ); suffix = ""; if ( typeof start === "number" ) { start = this.fromCharCode( start ); }              say = start; } else { n = 0; }           if ( n > 1 ) { if ( apply[1] ) { suffix = apply[1]; if ( typeof suffix ===  "number" ) { suffix = this.fromCharCode( suffix ); }                 say   = start + suffix; story = start + ( this.stick ? this.stick : "" ) + suffix; }              if ( n > 2 ) { if ( apply[2] ) { sample = apply[2]; story = say + sample + suffix; }                 if ( n > 3 ) { if ( apply[3] ) { story = apply[3]; }                    if ( n > 4 ) { label = ( typeof apply[4] ===  "string"                                  &&     apply[4] ); if ( label ) { say = apply[4]; }                       if ( n > 5 ) { switch ( typeof apply[5] ) { case "boolean" : loose = apply[5]; break; case "function" : exec = function( event ) { this.fun( apply,                                                    event.ctrlKey ); return false; };                                break; case "string" : exec = function( event ) { ETSI.gui.fit( apply,                                                        event.ctrlKey ); return false; };                                break; }  // switch typeof apply[5] if ( n > 6 ) { switch ( typeof apply[6] ) { case "boolean" : loose = apply[6]; break; }  // switch typeof apply[6] }                       }                     }                  }               }            }            if ( ! exec   &&                 ( start || suffix || sample || loose ) ) { pars = { peri:   sample, pre:    start, post:   suffix, replace: loose }; }           break; }  // switch typeof apply n = say.length; if ( n ) { if ( light ) { pars = { pre: say }; }        if ( pars ) { if ( ! exec ) { exec = function( event ) { ETSI.gui.fill( pars, event.ctrlKey ); return false; };           }         }         if ( exec ) { $space = $( " " ); $space.text( " " ); $span = $( " " ); $span.css( { "display":    "inline-block",                         "white-space": "nowrap" } ); if ( label  &&                 say.charCodeAt( 0 ) === 60   &&       // <                 say.charCodeAt( n - 1 ) === 62 ) {    // > $span.html( say ); } else { $span.text( say ); }           $token = $( "" ); $token.attr( { "class": ETSI.gui.self + "-token",                           "href":   "#" } ); if ( story ) { $token.attr( "title", story ); }           $token.append( $span ) .click( exec ); assign.append( $space ) .append( $token ); }     }   };   // .menu.fill

ETSI.menu.fixed = function ( assign, apply, align ) { // Process a definition element of type "fixed text" // Precondition: //   assign  -- jQuery element to be extended //   apply   -- (HTML) string to be inserted //   align   -- true: insert separating spaces ahead // Postcondition: //   apply has been appended to assign // 2011-10-27 PerfektesChaos@de.wikipedia var s = " " + ( align ? " " : "" ) + apply + " "; assign.append( s ); };  // .menu.fixed

ETSI.menu.flush = function ( assign, apply, align ) { // Process a definition element of type "packed characters" // Precondition: //   assign  -- jQuery element to be extended //   apply   -- definition item; Array with at least 2 elements //              [0] === 1      //               [1] and further: string, character sequence group //   align   -- true: insert group separator ahead // Postcondition: //   assign is extended // Uses: //   .menu.fence //   .menu.fill // 2011-10-27 PerfektesChaos@de.wikipedia var lead  = align, more  = apply.length, i,         m,          n,          stream; for ( i = 1; i < more;  i++ ) { stream = apply[i]; if ( typeof stream === "string" ) { n = stream.length; this.fence( assign, n && lead ); for ( m = 0; m < n;  m++ ) { this.fill( assign, stream.substr( m, 1 ) ); }  // for m         } lead = true; }  // for i   };   // .menu.flush

ETSI.menu.fromCharCode = function ( address ) { // Extended fromCharCode for UCS > 0xFFFF (4 bytes/char) // Precondition: //   address  -- number, UCS // Postcondition: //   Returns a single character, //      which might have a string length of 2 instead of 1 // Requires: JavaScript 1.3 String.fromCharCode 2 byte chars only // 2011-10-27 PerfektesChaos@de.wikipedia var c,         r;      if ( address > 0xFFFF ) { c = address - 0x10000; r = String.fromCharCode( 0xD800 +  ( c >> 10 ),                                  0xDC00  +  ( c & 0x3FF ) ); } else { r = String.fromCharCode( address ); }     return r;   };   // .menu.fromCharCode

ETSI.menu.fun = function ( apply, additional ) { // Evaluate user defined function // Precondition: //   apply       -- specification array; apply[5] is the UDF //                  If apply[5] returns //                  an encapsulateSelection object, //                  insertion will be performed. //   additional  -- event.ctrlKey code // Uses: //   >  .gui.$current //   .gui.fill // 2017-05-22 PerfektesChaos@de.wikipedia var got = apply[5]( apply,                         ETSI.gui.$current.textSelection( "getSelection" ) ); if ( typeof got === "object" ) { ETSI.gui.fill( got, additional ); }  };   // .menu.fun

ETSI.util.trimLeft = function ( adjust ) { // Trim string left // Precondition: //   adjust  -- string // Postcondition: //   Returns trimmed string // 2015-06-25 PerfektesChaos@de.wikipedia return adjust.replace( /^\s+/, "" ); };  // .util.trimLeft

ETSI.util.trimRight = function ( adjust ) { // Trim string right // Precondition: //   adjust  -- string // Postcondition: //   Returns trimmed string // 2015-06-25 PerfektesChaos@de.wikipedia return adjust.replace( /\s+$/, "" ); };  // .util.trimRight

ETSI.factory = function { // (Re-)build entire data model from project and user spec // Postcondition: //   .current defs are defined // Uses: //   >< .defs.lead //   >< .defs.opts //    < .defs.tmp //    < .defs.reNS //    < .gui.hintList //    < .gui.hintMenu //   .defs.factory //   .defs.format //   .defs.fair //   .defs.furnish //   .defs.filter // 2012-10-29 PerfektesChaos@de.wikipedia this.defs.lead = false; this.defs.opts = false; this.defs.reNS = false; this.defs.factory; this.defs.tmp    = this.defs.find( "list", "object" ); this.gui.hintList = this.defs.find( "hintList", "string" ); this.gui.hintMenu = this.defs.find( "hintMenu", "string" ); this.defs.format; this.defs.fair; if ( this.defs.lead ) { this.defs.furnish; }     if ( this.defs.opts ) { this.defs.filter; }  };   // .factory

ETSI.about_defs = function ( alerting ) { // Show message box with all available definition identifiers (API) // Precondition: //   alerting  -- false: don't try to pop up message box // Postcondition: //   Message box is presented, if possible. //   Returns void(0) if message box shown, //           else string with definition identifiers. // Uses: //   > .defs.current // 2011-11-23 PerfektesChaos@de.wikipedia var collect = [ ], r      = false, d,         i,          n,          p,          q,          v;      n = this.defs.current.length; for ( i = 0; i < n;  i++ ) { d = this.defs.current[ i ][ 1 ].defs; for ( q in d ) { v = d[ q ]; if ( typeof v === "object" ) { if ( v.length > 1 ) { collect = collect.concat( [ q ] ); }           }         }   // for q in d      }   // for i      n = collect.length; if ( n ) { collect.sort; r = ""; p = ""; for ( q = 0; q < n;  q++ ) { v = collect[ q ]; if ( v !== p ) { r += " " + v;              p  = v;            } }  // for q         r = r.substr( 1 ); } else { r = "*-*-*-*"; }     if ( alerting !== false ) { if ( typeof window === "object" ) { window.alert( r ); r = void( 0 ); }  // online }     return r;   };   // .about_defs

ETSI.about_version = function { // Retrieve version information // Postcondition: //   Returns string with information // Uses: //   > .gui.self //   > .type //   > .vsn // 2015-03-10 PerfektesChaos@de.wikipedia var r;     r  = "MediaWiki User:PerfektesChaos " + this.type + " self='" + this.gui.self + "' vsn=" + this.vsn; return r;  };   // .about_version

ETSI.set = function ( action, apply ) { // Set project or user property (API) // Precondition: //   action  -- string: which property to be set //              "container":         additional selectors //              "cookieName":        memorize recent selection ID      //                                    or false //              "ellipsis":          tooltip generation //                                   put between start and end tag //              "groupSeparator":    non-empty string //                                   or false //              "groupSeparatorCSS": object with CSS assignments //              "hintList":          string: tooltip for gadget //              "hintMenu":          string: tooltip for menus //              "old":               selector for other edittools //                                   or false //              "replace":           always replace instead insert //              "selection":         gadget shift, ID string //   apply   -- string or boolean // Uses: //   >  .defs.opts //    < .gui.builder //    < .gui.cookie //    < .menu.divide //    < .gui.hintList //    < .gui.hintMenu //    < .menu.separator //    < .menu.stick //    < .gui.old //    < .defs.looser //    < .gui.selection //   .gui.favour //   .gui.facet //   .util.trimLeft //   .util.trimRight // 2017-06-01 PerfektesChaos@de.wikipedia switch ( action ) { case "container" : if ( typeof apply === "object" ) { this.gui.builder = apply; }           break; case "cookieName" : if ( typeof apply === "string" ) { this.gui.cookie = ETSI.util.trimLeft( apply ); this.gui.cookie = ETSI.util.trimRight( this.gui.cookie ); if ( ! this.gui.cookie.length ) { this.gui.cookie = false; }           } else { this.gui.cookie = false; }           break; case "ellipsis" : if ( typeof apply === "string" ) { this.menu.stick = apply; }           break; case "groupSeparator" : this.menu.separator = apply; break; case "groupSeparatorCSS" : if ( typeof apply === "object" ) { this.menu.divide = apply; }           break; case "hintList" : if ( typeof apply === "string" ) { this.gui.hintList = apply; }           break; case "hintMenu" : if ( typeof apply === "string" ) { this.gui.hintMenu = apply; }           break; case "old" : this.gui.old = apply; this.gui.favour; break; case "replace" : this.defs.looser = apply; break; case "selection" : this.gui.selection = apply; if ( typeof this.opts === "object" ) { this.gui.facet; }           break; }  // switch action };  // .set

ETSI.update = function { // Furnish entire list and model once again (may be used as API) // Uses: //   >  .loaded //   fired // Remark: Used as event handler -- 'this' is not ETSI // 2017-06-01 PerfektesChaos@de.wikipedia if ( ETSI.loaded ) { fired; }  };   // .update

function first { // Autorun on load (once) // Uses: //   >  .user.config.container //   >  .hookAfterLoad //    < .gui.builder //   mw.config.get //   mw.hook //   mw.loader.using //   (fired) //   (ETSI.hookAfterLoad) // 2017-06-07 PerfektesChaos@de.wikipedia var launch, s;     switch ( mw.config.get( "wgNamespaceNumber" ) ) { case -1 : s     = mw.config.get( "wgCanonicalSpecialPageName" ); launch = ( s === "Upload" ); break; default: s     = mw.config.get( "wgAction" ); launch = ( s === "edit" ||  s === "submit" ); }  // switch action if ( launch ) { if ( typeof ETSI.user ===  "object"              &&     ETSI.user     &&              typeof ETSI.user.config  ===  "object"              &&     ETSI.user.config              &&     ETSI.user     &&              typeof ETSI.user.config.container  ===  "object"              &&     ETSI.user.config.container ) { ETSI.gui.builder = ETSI.user.config.container; }        mw.hook( ETSI.type + ".ready" ).fire( ETSI ); mw.loader.using( [ "user",                           "mediawiki.util",                            "jquery.textSelection" ],                          fired ); if ( typeof ETSI.hookAfterLoad ===  "function" ) { ETSI.hookAfterLoad; }     }   }   // first

if ( mw.loader.getState( Signature ) !==  "ready" ) { mw.loader.state( Signature, "ready" ); first; } }( window.mediaWiki, window.jQuery ) );

/// end of editToolStrIns.js