ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ /** * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Only define the Joomla namespace if not defined. Joomla = window.Joomla || {}; // Only define editors if not defined Joomla.editors = Joomla.editors || {}; // An object to hold each editor instance on page, only define if not defined. Joomla.editors.instances = Joomla.editors.instances || { /** * ***************************************************************** * All Editors MUST register, per instance, the following callbacks: * ***************************************************************** * * getValue Type Function Should return the complete data from the editor * Example: function () { return this.element.value; } * setValue Type Function Should replace the complete data of the editor * Example: function (text) { return this.element.value = text; } * replaceSelection Type Function Should replace the selected text of the editor * If nothing selected, will insert the data at the cursor * Example: function (text) { return insertAtCursor(this.element, text); } * * USAGE (assuming that jform_articletext is the textarea id) * { * To get the current editor value: * Joomla.editors.instances['jform_articletext'].getValue(); * To set the current editor value: * Joomla.editors.instances['jform_articletext'].setValue('Joomla! rocks'); * To replace(selection) or insert a value at the current editor cursor: * replaceSelection: Joomla.editors.instances['jform_articletext'].replaceSelection('Joomla! rocks') * } * * ********************************************************* * ANY INTERACTION WITH THE EDITORS SHOULD USE THE ABOVE API * ********************************************************* * * jInsertEditorText() @deprecated 4.0 */ }; (function( Joomla, document ) { "use strict"; /** * Generic submit form * * @param {String} task The given task * @param {node} form The form element * @param {bool} validate The form element * * @returns {void} */ Joomla.submitform = function(task, form, validate) { if (!form) { form = document.getElementById('adminForm'); } if (task) { form.task.value = task; } // Toggle HTML5 validation form.noValidate = !validate; if (!validate) { form.setAttribute('novalidate', ''); } else if ( form.hasAttribute('novalidate') ) { form.removeAttribute('novalidate'); } // Submit the form. // Create the input type="submit" var button = document.createElement('input'); button.style.display = 'none'; button.type = 'submit'; // Append it and click it form.appendChild(button).click(); // If "submit" was prevented, make sure we don't get a build up of buttons form.removeChild(button); }; /** * Default function. Can be overriden by the component to add custom logic * * @param {bool} task The given task * * @returns {void} */ Joomla.submitbutton = function( pressbutton ) { Joomla.submitform( pressbutton ); }; /** * Custom behavior for JavaScript I18N in Joomla! 1.6 * * @type {{}} * * Allows you to call Joomla.JText._() to get a translated JavaScript string pushed in with JText::script() in Joomla. */ Joomla.JText = { strings: {}, /** * Translates a string into the current language. * * @param {String} key The string to translate * @param {String} def Default string * * @returns {String} */ '_': function( key, def ) { // Check for new strings in the optionsStorage, and load them var newStrings = Joomla.getOptions('joomla.jtext'); if ( newStrings ) { this.load(newStrings); // Clean up the optionsStorage from useless data Joomla.loadOptions({'joomla.jtext': null}); } def = def === undefined ? '' : def; key = key.toUpperCase(); return this.strings[ key ] !== undefined ? this.strings[ key ] : def; }, /** * Load new strings in to Joomla.JText * * @param {Object} object Object with new strings * @returns {Joomla.JText} */ load: function( object ) { for ( var key in object ) { if (!object.hasOwnProperty(key)) continue; this.strings[ key.toUpperCase() ] = object[ key ]; } return this; } }; /** * Joomla options storage * * @type {{}} * * @since 3.7.0 */ Joomla.optionsStorage = Joomla.optionsStorage || null; /** * Get script(s) options * * @param {String} key Name in Storage * @param {mixed} def Default value if nothing found * * @return {mixed} * * @since 3.7.0 */ Joomla.getOptions = function( key, def ) { // Load options if they not exists if (!Joomla.optionsStorage) { Joomla.loadOptions(); } return Joomla.optionsStorage[key] !== undefined ? Joomla.optionsStorage[key] : def; }; /** * Load new options from given options object or from Element * * @param {Object|undefined} options The options object to load. Eg {"com_foobar" : {"option1": 1, "option2": 2}} * * @since 3.7.0 */ Joomla.loadOptions = function( options ) { // Load form the script container if (!options) { var elements = document.querySelectorAll('.joomla-script-options.new'), str, element, option, counter = 0; for (var i = 0, l = elements.length; i < l; i++) { element = elements[i]; str = element.text || element.textContent; option = JSON.parse(str); if (option) { Joomla.loadOptions(option); counter++; } element.className = element.className.replace(' new', ' loaded'); } if (counter) { return; } } // Initial loading if (!Joomla.optionsStorage) { Joomla.optionsStorage = options || {}; } // Merge with existing else if ( options ) { for (var p in options) { if (options.hasOwnProperty(p)) { Joomla.optionsStorage[p] = options[p]; } } } }; /** * Method to replace all request tokens on the page with a new one. * * @param {String} newToken The token * * Used in Joomla Installation */ Joomla.replaceTokens = function( newToken ) { if (!/^[0-9A-F]{32}$/i.test(newToken)) { return; } var els = document.getElementsByTagName( 'input' ), i, el, n; for ( i = 0, n = els.length; i < n; i++ ) { el = els[i]; if ( el.type == 'hidden' && el.value == '1' && el.name.length == 32 ) { el.name = newToken; } } }; /** * USED IN: administrator/components/com_banners/views/client/tmpl/default.php * Actually, probably not used anywhere. Can we deprecate in favor of ? * * Verifies if the string is in a valid email format * * @param {string} text The text for validation * * @return {boolean} * * @deprecated 4.0 No replacement. Use formvalidator */ Joomla.isEmail = function( text ) { var regex = /^[\w.!#$%&‚Äô*+\/=?^`{|}~-]+@[a-z0-9-]+(?:\.[a-z0-9-]{2,})+$/i; return regex.test( text ); }; /** * USED IN: all list forms. * * Toggles the check state of a group of boxes * * Checkboxes must have an id attribute in the form cb0, cb1... * * @param {mixed} checkbox The number of box to 'check', for a checkbox element * @param {string} stub An alternative field name * * @return {boolean} */ Joomla.checkAll = function( checkbox, stub ) { if (!checkbox.form) return false; stub = stub ? stub : 'cb'; var c = 0, i, e, n; for ( i = 0, n = checkbox.form.elements.length; i < n; i++ ) { e = checkbox.form.elements[ i ]; if ( e.type == checkbox.type && e.id.indexOf( stub ) === 0 ) { e.checked = checkbox.checked; c += e.checked ? 1 : 0; } } if ( checkbox.form.boxchecked ) { checkbox.form.boxchecked.value = c; } return true; }; /** * Render messages send via JSON * Used by some javascripts such as validate.js * * @param {object} messages JavaScript object containing the messages to render. Example: * var messages = { * "message": ["Message one", "Message two"], * "error": ["Error one", "Error two"] * }; * @return {void} */ Joomla.renderMessages = function( messages ) { Joomla.removeMessages(); var messageContainer = document.getElementById( 'system-message-container' ), type, typeMessages, messagesBox, title, titleWrapper, i, messageWrapper, alertClass; for ( type in messages ) { if ( !messages.hasOwnProperty( type ) ) { continue; } // Array of messages of this type typeMessages = messages[ type ]; // Create the alert box messagesBox = document.createElement( 'div' ); // Message class alertClass = (type === 'notice') ? 'alert-info' : 'alert-' + type; alertClass = (type === 'message') ? 'alert-success' : alertClass; alertClass = (type === 'error') ? 'alert-error alert-danger' : alertClass; messagesBox.className = 'alert ' + alertClass; // Close button var buttonWrapper = document.createElement( 'button' ); buttonWrapper.setAttribute('type', 'button'); buttonWrapper.setAttribute('data-dismiss', 'alert'); buttonWrapper.className = 'close'; buttonWrapper.innerHTML = '×'; messagesBox.appendChild( buttonWrapper ); // Title title = Joomla.JText._( type ); // Skip titles with untranslated strings if ( typeof title != 'undefined' ) { titleWrapper = document.createElement( 'h4' ); titleWrapper.className = 'alert-heading'; titleWrapper.innerHTML = Joomla.JText._( type ); messagesBox.appendChild( titleWrapper ); } // Add messages to the message box for ( i = typeMessages.length - 1; i >= 0; i-- ) { messageWrapper = document.createElement( 'div' ); messageWrapper.innerHTML = typeMessages[ i ]; messagesBox.appendChild( messageWrapper ); } messageContainer.appendChild( messagesBox ); } }; /** * Remove messages * * @return {void} */ Joomla.removeMessages = function() { var messageContainer = document.getElementById( 'system-message-container' ); // Empty container with a while for Chrome performance issues while ( messageContainer.firstChild ) messageContainer.removeChild( messageContainer.firstChild ); // Fix Chrome bug not updating element height messageContainer.style.display = 'none'; messageContainer.offsetHeight; messageContainer.style.display = ''; }; /** * Treat AJAX errors. * Used by some javascripts such as sendtestmail.js and permissions.js * * @param {object} xhr XHR object. * @param {string} textStatus Type of error that occurred. * @param {string} error Textual portion of the HTTP status. * * @return {object} JavaScript object containing the system error message. * * @since 3.6.0 */ Joomla.ajaxErrorsMessages = function( xhr, textStatus, error ) { var msg = {}; // For jQuery jqXHR if (textStatus === 'parsererror') { // Html entity encode. var encodedJson = xhr.responseText.trim(); var buf = []; for (var i = encodedJson.length-1; i >= 0; i--) { buf.unshift( [ '&#', encodedJson[i].charCodeAt(), ';' ].join('') ); } encodedJson = buf.join(''); msg.error = [ Joomla.JText._('JLIB_JS_AJAX_ERROR_PARSE').replace('%s', encodedJson) ]; } else if (textStatus === 'nocontent') { msg.error = [ Joomla.JText._('JLIB_JS_AJAX_ERROR_NO_CONTENT') ]; } else if (textStatus === 'timeout') { msg.error = [ Joomla.JText._('JLIB_JS_AJAX_ERROR_TIMEOUT') ]; } else if (textStatus === 'abort') { msg.error = [ Joomla.JText._('JLIB_JS_AJAX_ERROR_CONNECTION_ABORT') ]; } // For vannila XHR else if (xhr.responseJSON && xhr.responseJSON.message) { msg.error = [ Joomla.JText._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status) + ' ' + xhr.responseJSON.message + '' ]; } else if (xhr.statusText) { msg.error = [ Joomla.JText._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status) + ' ' + xhr.statusText + '' ]; } else { msg.error = [ Joomla.JText._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status) ]; } return msg; }; /** * USED IN: administrator/components/com_cache/views/cache/tmpl/default.php * administrator/components/com_installer/views/discover/tmpl/default_item.php * administrator/components/com_installer/views/update/tmpl/default_item.php * administrator/components/com_languages/helpers/html/languages.php * libraries/joomla/html/html/grid.php * * @param {boolean} isitchecked Flag for checked * @param {node} form The form * * @return {void} */ Joomla.isChecked = function( isitchecked, form ) { if ( typeof form === 'undefined' ) { form = document.getElementById( 'adminForm' ); } form.boxchecked.value = isitchecked ? parseInt(form.boxchecked.value) + 1 : parseInt(form.boxchecked.value) - 1; // If we don't have a checkall-toggle, done. if ( !form.elements[ 'checkall-toggle' ] ) return; // Toggle main toggle checkbox depending on checkbox selection var c = true, i, e, n; for ( i = 0, n = form.elements.length; i < n; i++ ) { e = form.elements[ i ]; if ( e.type == 'checkbox' && e.name != 'checkall-toggle' && !e.checked ) { c = false; break; } } form.elements[ 'checkall-toggle' ].checked = c; }; /** * USED IN: libraries/joomla/html/toolbar/button/help.php * * Pops up a new window in the middle of the screen * @deprecated 4.0 No replacement */ Joomla.popupWindow = function( mypage, myname, w, h, scroll ) { var winl = ( screen.width - w ) / 2, wint = ( screen.height - h ) / 2, winprops = 'height=' + h + ',width=' + w + ',top=' + wint + ',left=' + winl + ',scrollbars=' + scroll + ',resizable'; window.open( mypage, myname, winprops ) .window.focus(); }; /** * USED IN: libraries/joomla/html/html/grid.php * In other words, on any reorderable table * * @param {string} order The order value * @param {string} dir The direction * @param {string} task The task * @param {node} form The form * * return {void} */ Joomla.tableOrdering = function( order, dir, task, form ) { if ( typeof form === 'undefined' ) { form = document.getElementById( 'adminForm' ); } form.filter_order.value = order; form.filter_order_Dir.value = dir; Joomla.submitform( task, form ); }; /** * USED IN: administrator/components/com_modules/views/module/tmpl/default.php * * Writes a dynamically generated list * * @param string * The parameters to insert into the ', hasSelection = key == orig_key, i, selected, item; for (i = 0 ; i < source.length; i++) { item = source[ i ]; if ( item[ 0 ] != key ) { continue; } selected = hasSelection ? orig_val == item[ 1 ] : i === 0; html += ''; } html += ''; if (element) { element.innerHTML = html; } else { document.writeln( html ); } }; /** * USED IN: administrator/components/com_content/views/article/view.html.php * actually, probably not used anywhere. * * Changes a dynamically generated list * * @param string * The name of the list to change * @param array * A javascript array of list options in the form [key,value,text] * @param string * The key to display * @param string * The original key that was selected * @param string * The original item value that was selected * * @deprecated 4.0 No replacement */ window.changeDynaList = function ( listname, source, key, orig_key, orig_val ) { var list = document.adminForm[ listname ], hasSelection = key == orig_key, i, x, item, opt; // empty the list while ( list.firstChild ) list.removeChild( list.firstChild ); i = 0; for ( x in source ) { if (!source.hasOwnProperty(x)) { continue; } item = source[x]; if ( item[ 0 ] != key ) { continue; } opt = new Option(); opt.value = item[ 1 ]; opt.text = item[ 2 ]; if ( ( hasSelection && orig_val == opt.value ) || (!hasSelection && i === 0) ) { opt.selected = true; } list.options[ i++ ] = opt; } list.length = i; }; /** * USED IN: administrator/components/com_menus/views/menus/tmpl/default.php * Probably not used at all * * @param radioObj * @return * * @deprecated 4.0 No replacement */ // return the value of the radio button that is checked // return an empty string if none are checked, or // there are no radio buttons window.radioGetCheckedValue = function ( radioObj ) { if ( !radioObj ) { return ''; } var n = radioObj.length, i; if ( n === undefined ) { return radioObj.checked ? radioObj.value : ''; } for ( i = 0; i < n; i++ ) { if ( radioObj[ i ].checked ) { return radioObj[ i ].value; } } return ''; }; /** * USED IN: administrator/components/com_users/views/mail/tmpl/default.php * Let's get rid of this and kill it * * @param frmName * @param srcListName * @return * * @deprecated 4.0 No replacement */ window.getSelectedValue = function ( frmName, srcListName ) { var srcList = document[ frmName ][ srcListName ], i = srcList.selectedIndex; if ( i !== null && i > -1 ) { return srcList.options[ i ].value; } else { return null; } }; /** * USED IN: all over :) * * @param id * @param task * @return * * @deprecated 4.0 Use Joomla.listItemTask() instead */ window.listItemTask = function ( id, task ) { return Joomla.listItemTask( id, task ); }; /** * USED IN: all over :) * * @param {string} id The id * @param {string} task The task * * @return {boolean} */ Joomla.listItemTask = function ( id, task ) { var f = document.adminForm, i = 0, cbx, cb = f[ id ]; if ( !cb ) return false; while ( true ) { cbx = f[ 'cb' + i ]; if ( !cbx ) break; cbx.checked = false; i++; } cb.checked = true; f.boxchecked.value = 1; window.submitform( task ); return false; }; /** * Default function. Usually would be overriden by the component * * @deprecated 4.0 Use Joomla.submitbutton() instead. */ window.submitbutton = function ( pressbutton ) { Joomla.submitbutton( pressbutton ); }; /** * Submit the admin form * * @deprecated 4.0 Use Joomla.submitform() instead. */ window.submitform = function ( pressbutton ) { Joomla.submitform(pressbutton); }; // needed for Table Column ordering /** * USED IN: libraries/joomla/html/html/grid.php * There's a better way to do this now, can we try to kill it? * * @deprecated 4.0 No replacement */ window.saveorder = function ( n, task ) { window.checkAll_button( n, task ); }; /** * Checks all the boxes unless one is missing then it assumes it's checked out. * Weird. Probably only used by ^saveorder * * @param integer n The total number of checkboxes expected * @param string task The task to perform * * @return void * * @deprecated 4.0 No replacement */ window.checkAll_button = function ( n, task ) { task = task ? task : 'saveorder'; var j, box; for ( j = 0; j <= n; j++ ) { box = document.adminForm[ 'cb' + j ]; if ( box ) { box.checked = true; } else { alert( "You cannot change the order of items, as an item in the list is `Checked Out`" ); return; } } Joomla.submitform( task ); }; /** * Add Joomla! loading image layer. * * Used in: /administrator/components/com_installer/views/languages/tmpl/default.php * /installation/template/js/installation.js * * @param {String} task The task to do [load, show, hide] (defaults to show). * @param {HTMLElement} parentElement The HTML element where we are appending the layer (defaults to body). * * @return {HTMLElement} The HTML loading layer element. * * @since 3.6.0 */ Joomla.loadingLayer = function(task, parentElement) { // Set default values. task = task || 'show'; parentElement = parentElement || document.body; // Create the loading layer (hidden by default). if (task === 'load') { // Gets the site base path var systemPaths = Joomla.getOptions('system.paths') || {}, basePath = systemPaths.root || ''; var loadingDiv = document.createElement('div'); loadingDiv.id = 'loading-logo'; // The loading layer CSS styles are JS hardcoded so they can be used without adding CSS. // Loading layer style and positioning. loadingDiv.style['position'] = 'fixed'; loadingDiv.style['top'] = '0'; loadingDiv.style['left'] = '0'; loadingDiv.style['width'] = '100%'; loadingDiv.style['height'] = '100%'; loadingDiv.style['opacity'] = '0.8'; loadingDiv.style['filter'] = 'alpha(opacity=80)'; loadingDiv.style['overflow'] = 'hidden'; loadingDiv.style['z-index'] = '10000'; loadingDiv.style['display'] = 'none'; loadingDiv.style['background-color'] = '#fff'; // Loading logo positioning. loadingDiv.style['background-image'] = 'url("' + basePath + '/media/jui/images/ajax-loader.gif")'; loadingDiv.style['background-position'] = 'center'; loadingDiv.style['background-repeat'] = 'no-repeat'; loadingDiv.style['background-attachment'] = 'fixed'; parentElement.appendChild(loadingDiv); } // Show or hide the layer. else { if (!document.getElementById('loading-logo')) { Joomla.loadingLayer('load', parentElement); } document.getElementById('loading-logo').style['display'] = (task == 'show') ? 'block' : 'none'; } return document.getElementById('loading-logo'); }; /** * Method to Extend Objects * * @param {Object} destination * @param {Object} source * * @return Object */ Joomla.extend = function (destination, source) { for (var p in source) { if (source.hasOwnProperty(p)) { destination[p] = source[p]; } } return destination; }; /** * Method to perform AJAX request * * @param {Object} options Request options: * { * url: 'index.php', // Request URL * method: 'GET', // Request method GET (default), POST * data: null, // Data to be sent, see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/send * perform: true, // Perform the request immediately, or return XMLHttpRequest instance and perform it later * headers: null, // Object of custom headers, eg {'X-Foo': 'Bar', 'X-Bar': 'Foo'} * * onBefore: function(xhr){} // Callback on before the request * onSuccess: function(response, xhr){}, // Callback on the request success * onError: function(xhr){}, // Callback on the request error * } * * @return XMLHttpRequest|Boolean * * @example * * Joomla.request({ * url: 'index.php?option=com_example&view=example', * onSuccess: function(response, xhr){ * console.log(response); * } * }) * * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest */ Joomla.request = function (options) { // Prepare the options options = Joomla.extend({ url: '', method: 'GET', data: null, perform: true }, options); // Use POST for send the data options.method = options.data ? 'POST' : options.method.toUpperCase(); // Set up XMLHttpRequest instance try{ var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('MSXML2.XMLHTTP.3.0'); xhr.open(options.method, options.url, true); // Set the headers xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.setRequestHeader('X-Ajax-Engine', 'Joomla!'); if (options.method === 'POST') { var token = Joomla.getOptions('csrf.token', ''); if (token) { xhr.setRequestHeader('X-CSRF-Token', token); } if (!options.headers || !options.headers['Content-Type']) { xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } } // Custom headers if (options.headers){ for (var p in options.headers) { if (options.headers.hasOwnProperty(p)) { xhr.setRequestHeader(p, options.headers[p]); } } } xhr.onreadystatechange = function () { // Request not finished if (xhr.readyState !== 4) return; // Request finished and response is ready if (xhr.status === 200) { if(options.onSuccess) { options.onSuccess.call(window, xhr.responseText, xhr); } } else if(options.onError) { options.onError.call(window, xhr); } }; // Do request if (options.perform) { if (options.onBefore && options.onBefore.call(window, xhr) === false) { // Request interrupted return xhr; } xhr.send(options.data); } } catch (error) { window.console ? console.log(error) : null; return false; } return xhr; }; }( Joomla, document ));