"text": "Content-Type: multipart/form-data; boundary=---------------------------324082132622671\r\nContent-Length: 97652\r\n\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpAntispam\"\r\n\r\n\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"baseRevId\"\r\n\r\n16045053\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"altBaseRevId\"\r\n\r\n0\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"undidRev\"\r\n\r\n0\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"editingStatsId\"\r\n\r\n8022031d58749d0b31d1eaaedae232d6\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpSection\"\r\n\r\n\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpStarttime\"\r\n\r\n20161230183136\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpEdittime\"\r\n\r\n20161104171956\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"editRevId\"\r\n\r\n\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpScrolltop\"\r\n\r\n0\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpAutoSummary\"\r\n\r\nd41d8cd98f00b204e9800998ecf8427e\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"oldid\"\r\n\r\n0\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"parentRevId\"\r\n\r\n16045053\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"format\"\r\n\r\ntext/x-wiki\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nwikitext\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpTextbox1\"\r\n\r\n{{suositeltu}}\r\n{{Tennispelaaja\r\n | nimi = Jarkko Nieminen\r\n | kuva = [[Kuva:Jarkko Nieminen Olympics 2012.jpg|260px|Jarkko Nieminen Lontoon kesäolympialaisissa 2012.]]\r\n | maa = {{Suomi}}\r\n | asuinpaikka = [[Helsinki]], Suomi\r\n | syntymäaika = {{Syntymäaika ja ikä|23|07|1981}}\r\n | pituus = 185 cm\r\n | paino = 78 kg\r\n | kätisyys = vasen\r\n | ammattilaisena = 2000–2015\r\n<!-- Kaksinpelisaavutukset -->\r\n | sijoitus = 13. (10.7.2006)\r\n | turnausvoitot = 2\r\n | aus = puolivälierät ([[Australian avoin tennisturnaus 2008|2008]])\r\n | fra = 4. kierros ([[Ranskan avoin tennisturnaus 2003|2003]])\r\n | wim = puolivälierät ([[Wimbledonin tennisturnaus 2006|2006]])\r\n | us = puolivälierät ([[Yhdysvaltain avoin tennisturnaus 2005|2005]])\r\n<!-- Nelinpelisaavutukset -->\r\n | sijoitus-np = 42. (28.1.2008)\r\n | turnausvoitot-np = 5\r\n | aus-np = välierät ([[Australian avoin tennisturnaus 2010|2010]])\r\n | fra-np = 2. kierros ([[Ranskan avoin tennisturnaus 2003|2003]], [[Ranskan avoin tennisturnaus 2008|2008]])\r\n | wim-np = 2. kierros ([[Wimbledonin tennisturnaus 2007|2007]])\r\n | us-np = puolivälierät ([[Yhdysvaltain avoin tennisturnaus 2008|2008]])\r\n}}\r\n{{Salibandyn pelaaja\r\n| nimi = Jarkko Nieminen\r\n| kuva = \r\n| kuvakoko = \r\n| pelipaikka =\r\n| kätisyys = oikea\r\n| lempinimi = \r\n| nykyinen_seura = {{Suomen lippu}} [[Classic]]\r\n| numero = 13<ref name=\"säbä\" />\r\n| pituus = 185 cm\r\n| paino = 78 kg \r\n| aikaisemmat_seurat = \r\n| pelasi = \r\n| kansallisuus = {{Suomi}}\r\n| kansallisuus_2 = \r\n| syntymäaika = {{Syntymäaika ja ikä|23|07|1981}}\r\n| syntymäpaikka = {{Suomi}}\r\n| kuolinaika = \r\n| kuolinpaikka = \r\n| uran_alku = 2016\r\n| uran_loppu =\r\n| ottelut(pisteet) = \r\n| mjvuodet = \r\n| maajoukkue = \r\n| maaottelut(pisteet) =\r\n}}\r\n\r\n'''Jarkko Kalervo Nieminen''' (s. [[23. heinäkuuta]] [[1981]] [[Masku]])<ref>{{Kirjaviite | Tekijä = Siukonen, Markku | Nimeke = Itsenäisen Suomen urheilusankareita | Vuosi = 2007 | Sivu = 308 | Julkaisija = Minerva | Tunniste = ISBN 978-952-492-055-1}}</ref> on ammattilaisuransa lopettanut [[Suomalaiset|suomalainen]] [[tennis]]pelaaja. Nieminen sijoittui parhaimmillaan [[Association of Tennis Professionals|ATP-maailmanlistalla]] kaksinpelissä sijalle 13 heinäkuussa 2006 ja nelinpelissä sijalle 42 tammikuussa 2008. Hän voitti uransa aikana kaksi ATP-turnausta kaksinpelissä ja viisi nelinpelissä. [[Grand Slam]] -turnauksissa hän selviytyi kaksinpelissä kolme kertaa puolivälieriin ja nelinpelissä kerran välieriin.<ref name=\"ATP Profile\">{{ATP}}</ref>\r\n\r\nNieminen on korkeimmalle koskaan maailmanlistalla sijoittunut suomalainen tennispelaaja ja ainoa ATP-kaksinpeliturnauksen voittanut suomalainen.<ref name=\"MTV3\">{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/erik.shtml?700885 | Nimeke = Jarkko Nieminen | Julkaisu = MTV3.fi | Julkaisija = MTV Oy | Viitattu = 2.12.2009}}{{dead link|date=December 2016}}</ref> [[Davis Cup]]issa Nieminen edusti [[Suomen Davis Cup -joukkue|Suomea]] vuosina 1999−2016.<ref name=\"DC\">{{Verkkoviite | Osoite = http://www.daviscup.com/en/players/player/profile.aspx?playerid=10018551 | Nimeke = Jarkko Nieminen | Julkaisu = daviscup.com | Julkaisija = Davis Cup | Viitattu = 2.8.2010 | Kieli = {{en}}}}</ref> Hän on voittanut joukkueessa eniten otteluita ja eniten kaksinpelejä.<ref>{{Verkkoviite | Osoite = http://www.daviscup.com/en/teams/team/profile.aspx?id=FIN | Nimeke = Finland | Julkaisu = daviscup.com | Julkaisija = Davis Cup | Viitattu = 2.8.2010 | Kieli = {{en}}}}</ref> Palkintorahaa Nieminen voitti ammattilaisurallaan yli 7,7 miljoonaa Yhdysvaltain dollaria.<ref name=\"ATP Profile\"/> Nieminen toimi ATP:n pelaajaneuvostossa vuosina 2010–2014.<ref>{{Verkkoviite|nimeke = Emotional Nieminen Calls It A Career In Stockholm|osoite = http://www.atpworldtour.com/en/news/nieminen-calls-it-a-career-at-stockholm-2015|julkaisu = ATP World Tour|viitattu = 21.10.2015|kieli = {{en}}}}</ref>\r\n\r\nTennisuransa jälkeen Nieminen on aloittanut ammattilaisuran [[salibandy]]ssä, ja hän tulee edustamaan [[Salibandyliiga]]ssa pelaavaa [[Classic]]ia kaudella 2016–2017.<ref name=\"säbä\">{{Verkkoviite | Osoite = http://floorball.fi/uutiset/liigan-uutiset/jarkko-nieminen-pelaamaan-salibandya-tampereen-classiciin/ | Nimeke = Jarkko Nieminen pelaamaan salibandya Tampereen Classiciin ! | Julkaisu = floorball.fi | Julkaisija = [[SSBL Salibandy|SSBL Salibandy Oy]] | Viitattu = 11.4.2016}}</ref>\r\n\r\n== Ura ==\r\n=== Lapsuus ja junioriura (−1999) ===\r\nNieminen aloitti tenniksen 3-vuotiaana lyömällä pehmopalloa olohuoneen seinään.<ref>{{Verkkoviite | Osoite = http://www.vantaanlauri.fi/arkisto/2009-10-29/tenniksen-pelaamisen-ilo | Nimeke = Tenniksen pelaamisen ilo | Tekijä = Saxell, Susanna | Julkaisu = vantaanlauri.fi | Ajankohta = 29.10.2009 | Julkaisija = Vantaan seurakunnat | Viitattu = 4.8.2014}}{{dead link|date=December 2016}}</ref> Hän urheili nuorena muutenkin monipuolisesti noin kymmentä eri lajia, joista hän lopetti myöhemmin yksitellen yhdeksän.<ref>{{Verkkoviite | Osoite = http://www.iltasanomat.fi/salibandy/art-2000001156371.html | Nimeke = Jättiyllätys: Jarkko Nieminen pelaa ensi kaudella Salibandyliigassa | Tekijä = Auremaa, Tomi | Julkaisu = iltasanomat.fi | Ajankohta = 11.4.2016 | Julkaisija = Sanoma Media Finland Oy | Viitattu = 11.4.2016}}</ref> Salibandystä muodostui lopulta hänelle toiseksi rakkain laji tenniksen jälkeen.<ref name=\"classic\">{{Verkkoviite|Osoite=http://www.scclassic.com/fi/uutiset/:source/frontpage/newsid/4348/actionarea/4/category/1/mode/nolist/contentareaid/176?PHPSESSID=b0147c1cfbc6b65228b5dd0eba569f3e|Nimeke=JARKKO NIEMINEN PELAAMAAN SALIBANDYA TAMPEREEN CLASSICIIN|Julkaisu=scclassic.com|Julkaisija=[[Classic|Salibandy Club Classic Ry]]|Viitattu=11.4.2016}}</ref> Kouluaikoinaan Nieminen harjoitteli Impivaaran tenniskeskuksessa Matti Hangasluoman tenniskoulussa sekä pelasi vanhempiensa vetämissä tenniskerhoissa.<ref>Nieminen, s. 46–47</ref><ref>Nieminen, s. 23–24</ref> Ensimmäisen Suomen mestaruutensa hän voitti omassa ikäluokassaan 11-vuotiaana.<ref>Nieminen, s. 84</ref> Nieminen aloitti 15-vuotiaana yhteistyön [[Henrik Johansén]]in kanssa.<ref name=\"City\">{{Lehtiviite | Tekijä = Suhonen, Pete | Otsikko = Jarkko Nieminen | Julkaisu = City | Ajankohta = 2002 | Numero = 9 | Julkaisija = Janton Oy | www = http://www.city.fi/artikkeli/Jarkko+Nieminen/491/ | Viitattu = 2.12.2009}}</ref> Sisäkenttien Suomen mestaruuskilpailuissa Nieminen pelasi miesten kaksinpelin loppuottelussa vuosina 1997–1999 ja voitti nelinpelin 1998 [[Ville Liukko|Ville Liukon]] kanssa ja 1999 [[Lauri Kiiski|Lauri Kiisken]] kanssa.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:24660,0 | Nimeke = \"Väärä\" Nieminen voitti tennisfinaalin | Tekijä = Welling, Jari | Julkaisu = TS.fi | Ajankohta = 14.3.1999 | Julkaisija = TS-Yhtymä | Viitattu = 18.8.2010}}{{Dead link}}</ref><ref>{{Verkkoviite | Osoite = http://www.tennis.fi/kilpailut/suomen+mestarit/miehet+4-p+sisa/ | Nimeke = Miehet 4-p sisäkentillä | Julkaisu = Tennisverkko | Julkaisija = Suomen Tennisliitto | Viitattu = 18.8.2010}}</ref>\r\n\r\nKeväällä 1999 Nieminen valittiin Jacques Hervet'n ja [[Iván Molina]]n vetämään ITF:n junioritiimiin.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:28296,0 | Nimeke = Jarkko Nieminen kiertää kahdeksan viikkoa ITF:n huippuryhmässä | Tekijä = Welling, Jari | Julkaisu = TS.fi | Ajankohta = 29.5.1999 | Julkaisija = TS-Yhtymä | Viitattu = 9.8.2010}}{{Dead link}}</ref> Hän selviytyi [[Wimbledonin tennisturnaus 1999|Wimbledonin]] poikien nelinpelin loppuotteluun parinsa [[Todor Enev]]in kanssa.<ref name=\"ITF Activity\">{{Verkkoviite | Osoite = http://www.itftennis.com/Juniors/players/player/profile.aspx?PlayerID=10018551 | Nimeke = Nieminen, Jarkko (FIN) – Activity | Julkaisu = ITF Juniors | Julkaisija = ITF | Viitattu = 16.11.2009 | Kieli = {{en}}}}</ref> [[Tampere Open]]issa hän selviytyi ATP-haastajaturnauksen välieriin.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:30951,0 | Nimeke = Nieminen menestyksekkäin suomalaispelaaja Tampereella | Tekijä = Kuntsi, Eeva | Julkaisu = TS.fi | Ajankohta = 25.7.1999 | Julkaisija = TS-Yhtymä | Viitattu = 18.8.2010}}</ref> Syyskuussa 1999 hän voitti [[Yhdysvaltain avoin tennisturnaus 1999|Yhdysvaltain avoimissa]] poikien kaksinpelin lyömällä loppuottelussa [[Kristian Pless]]in lukemin 6–7, 6–3, 6–4.<ref name=\"ITF Activity\"/> Syyskuun lopulla hän teki [[Davis Cup]] -debyyttinsä maailmanlohkon karsinnoissa [[Suomen Davis Cup -joukkue|Suomen]] ja [[Italian Davis Cup -joukkue|Italian]] välisessä maaottelussa. Ensimmäisen kaksinpelinsä hän hävisi [[Andrea Gaudenzi]]a vastaan ja reväytti ottelun kolmannessa erässä vatsalihaksensa, eikä näin ollen pystynyt pelaamaan toista ja ratkaisevaa kaksinpeliään. Suomi hävisi karsinnan [[Tuomas Ketola]]n tuuratessa Niemistä.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:34006,0 | Nimeke = Suomi ulos Davis cupista | Julkaisu = TS.fi | Ajankohta = 27.9.1999 | Julkaisija = TS-Yhtymä | Viitattu = 9.8.2010}}</ref> Junioreiden maailmanlistalla Nieminen oli korkeimmillaan kuudentena.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:39117,0 | Nimeke = Jarkko Nieminen lähtee miesten mittelöihin | Julkaisu = TS.fi | Ajankohta = 30.12.1999 | Julkaisija = TS-Yhtymä | Viitattu = 9.8.2010}}</ref>\r\n\r\n=== ATP-haastajaturnauksista ATP-kiertueelle (2000–2002) ===\r\nTammikuussa 2000 Nieminen sopi vuoden mittaisen yhteistyösopimuksen ITF:n junioritiimiä valmentavan Jacques Hervet'n kanssa.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:39837,0 | Nimeke = Jarkko Nieminen Hervet'n talliin | Tekijä = Welling, Jari | Julkaisu = TS.fi | Ajankohta = 13.1.2000 | Julkaisija = TS-Yhtymä | Viitattu = 9.8.2010}}</ref> Vuoden aikana hän kierteli ITF Futures- ja ATP Challenger -turnauksia. Heinäkuussa Tampere Openissa hän voitti nelinpelin Ville Liukon kanssa ja selviytyi kaksinpelissä välieriin.<ref name=\"ATP Profile\"/> Marraskuussa 2000 Nieminen pääsi lucky loserina uransa ensimmäiseen ATP-kaksinpeliturnaukseen [[Stockholm Open|Tukholman avoimiin]], mutta hävisi avauskierroksella [[Jonas Björkman]]ille.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:60051,0 | Nimeke = Nieminen oli yllättää Björkmanin Tukholmassa | Tekijä = Welling, Jari | Julkaisu = TS.fi | Ajankohta = 24.11.2000 | Julkaisija = TS-Yhtymä | Viitattu = 9.8.2010}}</ref>\r\n\r\nHelmikuussa 2001 hän voitti ensimmäisen ATP-haastajaturnauksensa [[Wolfsburg]]issa. Hän voitti vielä saman vuoden aikana Tampereen, [[Córdoba (Espanja)|Cordoban]] ja [[Maia (Portugali)|Maian]] ATP-haastajaturnaukset.<ref name=\"ATP Profile\"/> Uransa toiseen ATP-turnaukseen, Tukholman avoimiin Nieminen pääsi karsintojen kautta. Turnauksen puolivälierissä hän voitti silloisen maailmanlistan 18:nneksi sijoitetun ja Ruotsin ykköspelaajan [[Thomas Johansson]]in.<ref>{{Lehtiviite | Tekijä = Jarkko Nieminen iski suomalaista tennishistoriaa | Otsikko = Jarkko Nieminen iski suomalaista tennishistoriaa | Julkaisu = Helsingin Sanomat | Ajankohta = 27.10.2001 | Sivut = | Julkaisija = Sanoma News Oy}}</ref> Välierissä hän päihitti silloisen maailmanlistan 20:nneksi sijoitetun, moniin helppoihin virheisiin sortuneen [[Thomas Enqvist]]in.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:85256,0 | Nimeke = Jarkko Nieminen vyöryi finaaliin | Tekijä = Welling, Jari | Julkaisu = TS.fi | Ajankohta = 28.10.2001 | Julkaisija = TS-Yhtymä | Viitattu = 13.8.2010}}</ref> Loppuottelussa pitkän peliviikon väsyttämä ja ottelun aikana pakaransa reväyttänyt Nieminen hävisi viisieräisen kamppailun jälkeen [[Sjeng Schalken]]ille lukemin 6–3, 3–6, 3–6, 6–4, 3–6.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:85336,0 | Nimeke = Sjeng Schalken rimpuili irti Niemisen silmukasta | Tekijä = Welling, Jari | Julkaisu = TS.fi | Ajankohta = 29.10.2001 | Julkaisija = TS-Yhtymä | Viitattu = 13.8.2010}}</ref> Loppuottelupaikkansa ansiosta hän nousi ATP-maailmanlistalla sijalta 103 sijalle 69.<ref name=\"ATP Profile\"/>\r\n\r\n[[Australian avoin tennisturnaus 2002|Australian avoimissa 2002]] Nieminen osallistui uransa ensimmäiseen Grand Slam -turnaukseen. Hän hävisi ensimmäisen kierroksen ottelunsa idolilleen [[Pete Sampras]]ille.<ref name=\"Nieminen 89\">Nieminen, s. 89–95</ref> Huhtikuussa [[Portugal Open|Estoril Openissa]] hän selviytyi loppuotteluun voittamalla puolivälierissä entisen maailmanlistan ykkösen [[Marat Safin]]in ja välierissä [[Fernando Meligeni]]n, mutta hävisi loppuottelun [[David Nalbandian]]ille.<ref name=\"ATP Profile\"/> Kolme viikkoa myöhemmin [[Valencia Open 500|Mallorcan ATP-turnauksessa]] hän voitti puolivälierissä [[Dominik Hrbatý]]n ja välierissä [[Mariano Zabaleta]]n, mutta hävisi loppuottelun [[Gastón Gaudio]]lle kuumeviruksen kangistamana.<ref name=\"ATP Profile\"/><ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:105665,0 | Nimeke = Virus vei Niemisen voimat Mallorcan loppuottelussa | Tekijä = Welling, Jari | Julkaisu = TS.fi | Ajankohta = 6.5.2002 | Julkaisija = TS-Yhtymä | Viitattu = 9.8.2010}}</ref> Turnauksen jälkeen Nieminen nousi ATP-maailmanlistalla sijalle 43, jolloin hänestä tuli kaikkien aikojen korkeimmalle sijoitettu suomalaispelaaja.<ref name=\"MTV3\"/><ref name=\"ATP Profile\"/> [[Ranskan avoin tennisturnaus 2002|Ranskan avoimissa 2002]] hän voitti avauskierroksella [[Nicolás Lapentti|Nicolás Lapentin]] ja toisella [[Amir Hadad]]in, mutta hävisi kolmannella kierroksella [[Tommy Haas]]ille.<ref name=\"ATP Profile\"/> [[Wimbledonin tennisturnaus 2002|Wimbledonissa]] Nieminen pääsi viimeiseksi sijoitetuksi pelaajaksi, mutta hävisi toisella kierroksella [[Julian Knowle]]lle.<ref name=\"Nieminen 98\">Nieminen, s. 98–102</ref> Heinäkuussa hän voitti Tampere Openin.<ref name=\"ATP Profile\"/> Syyskuussa Suomi karsi pääsystä maailmanlohkoon maaottelussa [[Alankomaiden Davis Cup -joukkue|Alankomaita]] vastaan. Nieminen hävisi ensimmäisen kaksinpelinsä [[Raemon Sluiter]]ille ja nelinpelinsä Tuomas Ketolan kanssa [[Paul Haarhuis]]ille ja Sjeng Schalkenille, eikä Niemisen kaksinpelivoitto [[Martin Verkerk]]istä riittänyt Suomelle voittoon.<ref name=\"DC\"/> Marraskuussa hän voitti [[IPP Open]]in Helsingissä.<ref>{{Verkkoviite | Osoite = http://www.ts.fi/arkisto/haku.aspx?ts=1,0,0,0:0:130510,0 | Nimeke = Nieminen nosti kuudennen kerran Challenger-turnauksen voittopyttyä | Julkaisu = TS.fi | Ajankohta = 18.11.2002 | Julkaisija = TS-Yhtymä | Viitattu = 19.8.2010}}</ref>\r\n\r\n=== Valmentajanvaihdos ja rannemurtuma (2003–2004) ===\r\n[[Australian avoin tennisturnaus 2003|Australian avoimissa 2003]] Nieminen voitti ensimmäisellä kierroksella [[Nikolai Davydenko]]n ja toisella [[Jevgeni Kafelnikov]]in, mutta hävisi kolmannella kierroksella [[Guillermo Coria]]lle. Australian avointen jälkeen hän pelasi [[Milan Indoor|Milanon ATP-turnauksen]] välierissä. [[München]]in [[BMW Open]]issa hän selviytyi loppuotteluun, mutta hävisi sen [[Roger Federer]]ille. [[Ranskan avoin tennisturnaus 2003|Ranskan avoimissa]] hän voitti kolmannella kierroksella [[Victor Hănescu]]n, mutta hävisi neljännellä kierroksella [[Fernando González]]ille. [[Wimbledonin tennisturnaus 2003|Wimbledonissa]] hän hävisi kolmannella kierroksella [[Olivier Rochus]]ille.<ref name=\"ATP Profile\"/> Heinäkuun lopulla Nieminen lopetti seitsemän vuotta kestäneen yhteistyön Henrik Johansénin kanssa, ja hänen uudeksi valmentajakseen tuli [[Fredrik Rosengren]].<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/muutlajit/uutiset.shtml/2003/07/176886 | Nimeke = Jarkko Nieminen hakee uutta kipinää valmennuspuolelta | Julkaisu = MTV3.fi | Ajankohta = 15.7.2003 | Julkaisija = MTV Oy | Viitattu = 16.11.2009}}</ref> [[Yhdysvaltain avoin tennisturnaus 2003|Yhdysvaltain avoimissa]] Nieminen hävisi toisella kierroksella David Nalbandianille. [[Bangkok]]in ATP-turnauksen puolivälierissä hän voitti entisen maailmanlistan ykkösen [[Carlos Moyà]]n, mutta hävisi välierissä [[Taylor Dent]]ille.<ref name=\"ATP Profile\"/>\r\n\r\nTammikuussa 2004 Nieminen selviytyi välieriin [[Brisbane International|Adelaiden ATP-turnauksessa]], mutta [[Australian avoin tennisturnaus 2004|Australian avoimissa]] hän putosi jo toisella kierroksella. Maaliskuussa hän pelasi [[Dubai Tennis Championships|Dubain ATP-turnauksen]] välierissä.<ref name=\"ATP Profile\"/> [[Monte Carlo Masters]] -turnauksen avauskierroksella Nieminen kaatui oikean ranteensa päälle saaden luunmurtuman.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/muutlajit/uutiset.shtml/2004/04/213869 | Nimeke = Niemisellä rannemurtuma, paluu ehkä kesäkuussa | Julkaisu = MTV3.fi | Ajankohta = 20.4.2004 | Julkaisija = MTV Oy | Viitattu = 21.2.2010}}</ref> Nieminen palasi takaisin kentille heinäkuun alussa [[Swedish Open]]issa, [[Båstad]]issa.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/muutlajit/uutiset.shtml/2004/07/304912 | Nimeke = Jarkko Niemisellä voitokas paluu | Julkaisu = MTV3.fi | Ajankohta = 5.7.2004 | Julkaisija = MTV Oy | Viitattu = 21.2.2010}}</ref> Osallistuessaan [[Tennis kesäolympialaisissa 2004|Ateenan olympialaisiin]] Nieminen ei ollut täysin palautunut rannevammastaan ja putosi jo toisella kierroksella.<ref name=\"NOC\">{{Verkkoviite | Osoite = http://www.noc.fi/olympiahistoria/kisasivut/peking-kisasivut/suomen_joukkue/tennis/ | Nimeke = Jarkko Nieminen | Julkaisu = Pekingin kisasivut | Julkaisija = Suomen Olympiakomitea | Viitattu = 16.11.2009}}</ref> [[Yhdysvaltain avoin tennisturnaus 2004|Yhdysvaltain avoimista]] Nieminen tippui avauskierroksella. [[Peking]]in [[China Open (tennis)|China Openissa]] hän hävisi välierissä.<ref name=\"ATP Profile\"/> Lokakuun lopulla Niemisen ja hänen valmentajansa Fredrik Rosengrenin yhteistyö päättyi. Valmennussuhteen aikana Rosengren pyrki kehittämään Niemisen aggressiivisuutta ja itseluottamusta tiukoissa peleissä.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/muutlajit/uutiset.shtml/2004/10/324753 | Nimeke = Niemisen ja valmentajan yhteistyö päättyi tappioon | Julkaisu = MTV3.fi | Ajankohta = 25.10.2004 | Julkaisija = MTV Oy | Viitattu = 16.11.2009}}</ref>\r\n[[Kuva:JarkkoNieminen.JPG|230px|thumb|Jarkko Nieminen Tanskan joukkuemestaruuskilpailuissa syyskuussa 2008.]]\r\n\r\n=== Nousu uran huipulle (2005–2006) ===\r\nTammikuussa 2005 Nieminen joutui luovuttamaan [[Australian avoin tennisturnaus 2005|Australian avointen]] kolmannella kierroksella ottelunsa Roger Federerille vatsalihasten kipeydyttyä.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/muutlajit/uutiset.shtml/2005/10/395775 | Nimeke = Jarkko Nieminen: Federer osoitti miksi on ykkönen | Julkaisu = MTV3.fi | Ajankohta = 1.10.2005 | Julkaisija = MTV Oy | Viitattu = 16.11.2009}}</ref> Huhtikuussa Nieminen pääsi Münchenin ATP-turnauksen välieriin. [[Ranskan avoin tennisturnaus 2005|Ranskan avoimissa]] Nieminen kukisti yhden maineikkaimmista pelaajista, kun hän voitti maailmanlistan seitsemänneksi sijoitetun ja entisen maailmanlistan ykkösen [[Andre Agassi]]n 7–5, 4–6, 6–7, 6–1, 6–0. Toisella kierroksella Nieminen hävisi [[Igor Andrejev]]ille. Touko–kesäkuun vaihteessa hän voitti [[Prostějov]]in ATP-haastajaturnauksen. [[Wimbledonin tennisturnaus 2005|Wimbledonissa]] Nieminen hävisi ensimmäisellä kierroksella [[Tim Henman]]ille viidessä erässä. Hän pääsi välieriin [[Stuttgartin avoin tennisturnaus|Mercedes Cupissa]] [[Stuttgart]]issa. [[Yhdysvaltain avoin tennisturnaus 2005|Yhdysvaltain avoimissa]] hän selviytyi puolivälieriin saakka voitettuaan kolmannella kierroksella [[Maks Mirny]]n ja neljännellä kierroksella [[Fernando Verdasco]]n. Puolivälierissä hän hävisi [[Lleyton Hewitt]]ille viidessä erässä lukemin 6–2, 1–6, 6–3, 3–6, 1–6. Syksyllä hän pelasi vielä [[Thailand Open|Bangkokin]] ja [[Japanin avoin tennisturnaus|Tokion ATP-turnausten]] välierissä.<ref name=\"ATP Profile\"/>\r\n\r\nUransa ensimmäisen ATP-turnausvoittonsa Nieminen saavutti 14. tammikuuta 2006 [[Auckland]]in [[Heineken Open]]issa. Loppuottelussa hän voitti kroatialaisen [[Mario Ančić]]in lukemin 6–2, 6–2.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_turnausvoittoon_aucklandissa/5986152 | Nimeke = Nieminen turnausvoittoon Aucklandissa | Julkaisu = Yle Urheilu | Ajankohta = 14.1.2010 | Julkaisija = Yleisradio Oy | Viitattu = 4.8.2014}}</ref> Voitto oli kaikkien aikojen ensimmäinen suomalaisen tennispelaajan saavuttama ATP-turnausvoitto kaksinpelissä.<ref name=\"MTV3\"/> Kevään aikana Nieminen selviytyi [[Rotterdamin avoin tennisturnaus|Rotterdamin]] ja Münchenin ATP-turnausten välieriin ja [[Indian Wells Masters]] -turnauksen puolivälieriin.<ref name=\"ATP Profile\"/> [[Ranskan avoin tennisturnaus 2006|Ranskan avoimissa]] Nieminen oli sijoitettu 16. sijalle. Avauskierroksella hän joutui kuitenkin luovuttamaan kolmannessa erässä vatsavaivojen takia kesken ottelun [[Raemon Sluiter]]ia vastaan.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/muutlajit/uutiset.shtml/2006/05/448455 | Nimeke = Nieminen luovutti avausottelunsa Ranskassa | Julkaisu = MTV3.fi | Ajankohta = 29.5.2006 | Julkaisija = MTV Oy | Viitattu = 18.2.2010}}</ref> Nieminen pääsi puolivälieriin [[Wimbledonin tennisturnaus 2006|Wimbledonin turnauksessa]] niukalla voitolla [[Dmitri Tursunov]]ista lukemin 7–5, 6–4, 6–7(2), 6–7(6), 9–7.<ref name=\"ATP Profile\"/> Ottelun aikana tapahtuneesta mailan maahan heitosta hän sai 1000 dollarin sakot.<ref name=\"Nieminen 98\"/> Puolivälierissä Nieminen hävisi [[Rafael Nadal]]ille suoraan kolmessa erässä 6–3, 6–4, 6–4.<ref name=\"ATP Profile\"/> Hän saavutti uransa korkeimman ATP-maailmanlistan sijoituksensa 10. heinäkuuta noustuaan ATP-maailmanlistalla 13:nneksi.<ref name=\"ATP Profile\"/> Wimbledonin jälkeisellä viikolla hän pääsi Båstadin ATP-turnauksen välieriin. Elokuussa hän pelasi [[Kanadan avoin tennisturnaus|Canada Masters]] -turnauksen puolivälierissä. Tukholman avoimissa Nieminen pääsi loppuotteluun, mutta hävisi [[James Blake]]lle suoraan kahdessa erässä. Loka–marraskuun vaihteessa hän selviytyi vielä [[Paris Masters]] -turnauksen puolivälieriin.<ref name=\"ATP Profile\"/>\r\n\r\n=== Tasaista peliä ATP-kiertueella (2007–2008) ===\r\nVuoden 2007 vaihteessa Nieminen sai vatsatautiviruksen ja Niemisen kauden aloitus myöhästyi viikolla. Vatsataudin takia huonosti valmistautunut Nieminen hävisi toisella kierroksella [[Australian avoin tennisturnaus 2007|Australian avoimissa]].<ref name=\"Nieminen 89\"/> [[Marseille]]n [[Open 13]] -turnauksessa hän pelasi välierissä. [[Ranskan avoin tennisturnaus 2007|Ranskan avoimissa 2007]] Nieminen hävisi [[Lleyton Hewitt]]ille kolmannella kierroksella. Kesäkuussa hän selviytyi [[Halle (Westfalen)|Hallen]] [[Gerry Weber Open]]in välieriin. Hän putosi [[Wimbledonin tennisturnaus 2007|Wimbledonista]] kolmannella kierroksella hävittyään [[Mihail Južnyi]]lle.<ref name=\"ATP Profile\"/> Syyskuussa 2007 [[Kingfisher Airlines Tennis Open|Mumbain ATP-turnauksessa]] Nieminen voitti parinsa [[Robert Lindstedt]]in kanssa ensimmäisen nelinpelin ATP-turnauksensa. Turnauksen kaksi ensimmäistä kierrosta luovutusvoitoilla edenneet Nieminen ja Lindstedt voittivat loppuottelussa kovasyöttöiset [[Rohan Bopanna]]n ja [[Aisam-ul-Haq Qureshi]]n.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2007/09/566308 | Nimeke = Niemiselle turnausvoitto nelinpelissä | Julkaisu = MTV3.fi | Ajankohta = 30.9.2007 | Julkaisija = MTV Oy | Viitattu = 19.8.2010}}</ref> Lokakuussa [[Swiss Indoors|Davidoff Swiss Indoors]] -turnauksessa [[Basel]]issa Nieminen voitti puolivälierissä Fernando Gonzálezin. Loppuottelussa hän hävisi Roger Federerille.<ref name=\"ATP Profile\"/>\r\n\r\nValmistautuessaan Australiassa vuoden ensimmäiseen [[Brisbane International|Adelaiden ATP-turnaukseen]] 2008 Nieminen sai lämpöhalvauksen, mutta selviytyi silti turnauksen loppuotteluun.<ref name=\"Nieminen 115\">Nieminen, s. 115–118</ref> Hän hävisi loppuottelun [[Michaël Llodra]]lle.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2008/01/597179 | Nimeke = Niemisen finaalituska jatkui Adelaidessa | Julkaisu = MTV3.fi | Ajankohta = 6.1.2008 | Julkaisija = MTV Oy | Viitattu = 18.8.2010}}</ref> [[Australian avoin tennisturnaus 2008|Australian avoimissa]] hän selviytyi kolmannen kerran Grand Slam -turnauksen puolivälieriin voitettuaan neljännellä kierroksella [[Philipp Kohlschreiber]]in. Puolivälierissä hän hävisi Rafael Nadalille lukemin 5–7, 3–6, 1–6.<ref name=\"ATP Profile\"/> Kevättalvella Nieminen sairastui sitkeään virustautiin. Yli kolmen vuoden ajan ilman valmentajaa pelannut Nieminen palkkasi huhtikuussa 2008 valmentajakseen [[Joakim Nyström]]in.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_niemiselle_ruotsalaisvalmentaja/6034097 | Nimeke = Jarkko Niemiselle ruotsalaisvalmentaja | Julkaisu = Yle Urheilu | Ajankohta = 8.4.2008 | Viitattu = 4.8.2014}}</ref> [[Ranskan avoin tennisturnaus 2008|Ranskan avoimissa 2008]] Nieminen hävisi kolmannella kierroksella Rafael Nadalille ja [[Wimbledonin tennisturnaus 2008|Wimbledonissa 2008]] toisella kierroksella [[Marin Čilić]]ille.<ref name=\"ATP Profile\"/> [[Tennis kesäolympialaisissa 2008|Pekingin olympialaisissa]] hän putosi jo ensimmäisellä kierroksella hävittyään Thomas Johanssonille.<ref name=\"olympialaiset\">{{Verkkoviite | Osoite = http://www.hs.fi/urheilu/artikkeli/Jarkko+Niemisen+pelit+p%C3%A4%C3%A4ttyiv%C3%A4t/1135238514100 | Nimeke = Jarkko Niemisen pelit päättyivät | Julkaisu = HS.fi | Ajankohta = 11.8.2008 | Julkaisija = Sanoma News Oy | Viitattu = 16.11.2009}}{{dead link|date=December 2016}}</ref> Niemisen valmentaja Joakim Nyström piti Davis Cupiin osallistumista yhtenä syynä häviöön.<ref>{{Verkkoviite | Osoite = http://www.iltasanomat.fi/urheilu/Valmentaja%20J%C3%A4t%C3%A4%20Davis%20cup%20v%C3%A4liin%20Jarkko!/art-1288335842809.html | Nimeke = Valmentaja: Jätä Davis cup väliin, Jarkko! | Tekijä = Knuuttila, Mikko | Julkaisu = iltasanomat.fi | Ajankohta = 12.8.2008 | Julkaisija = Sanoma News Oy | Viitattu = 9.3.2010}}{{dead link|date=December 2016}}</ref> [[Yhdysvaltain avoin tennisturnaus 2008|Yhdysvaltain avoimissa]] Nieminen hävisi Fernando Gonzálezille kolmannella kierroksella.<ref name=\"ATP Profile\"/> Tukholman avoimissa hän selviytyi välieriin.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2008/10/729654 | Nimeke = Nalbandian selätti vaisun Niemisen | Julkaisu = MTV3.fi | Ajankohta = 11.10.2008 | Julkaisija = MTV Oy | Viitattu = 19.8.2010}}</ref>\r\n\r\n=== Ranneleikkaus ja paluu tenniskentille (2009–2011) ===\r\n[[Tiedosto:Nieminen 2009 US Open 01.jpg|230px|thumb|left|Jarkko Nieminen [[Yhdysvaltain avoin tennisturnaus 2009|Yhdysvaltain avoimissa 2009]].]]\r\nTammikuussa 2009 Nieminen selviytyi [[Sydney]]n [[Sydney International|Medibank Internationalissa]] loppuotteluun.<ref name=\"MTV 781349\">{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2009/01/781349 | Nimeke = Nieminen taipui taistelun jälkeen | Julkaisu = MTV3.fi | Ajankohta = 17.1.2009 | Julkaisija = MTV Oy | Viitattu = 19.8.2010}}</ref> [[Jo-Wilfried Tsonga]] luovutti puolivälieräottelun selkävaivojen takia.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2009/01/780039 | Nimeke = Nieminen välieriin Sydneyssä – Djokovic vastaan | Julkaisu = MTV3.fi | Ajankohta = 15.1.2009 | Julkaisija = MTV Oy | Viitattu = 18.2.2010}}</ref> Välierissä Nieminen voitti maailmanlistan kolmosen [[Novak Đoković]]in 6–4, 7–6 tuulisissa olosuhteissa, mutta hävisi loppuottelun David Nalbandianille.<ref name=\"MTV 781349\"/><ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2009/01/780854 | Nimeke = Nieminen: Aivan mahtavaa! | Julkaisu = MTV3.fi | Ajankohta = 16.1.2009 | Julkaisija = MTV Oy | Viitattu = 18.2.2010}}</ref> Huhtikuussa 2009 hän lopetti yhteistyön valmentajansa Joakim Nyströmin kanssa.<ref>{{Verkkoviite | Osoite = http://www.hs.fi/urheilu/artikkeli/Jarkko+Niemiselle+voitto+ilman+valmentajaa/1135245545876 | Nimeke = Jarkko Niemiselle voitto ilman valmentajaa | Julkaisu = HS.fi | Ajankohta = 28.4.2009 | Julkaisija = Sanoma News Oy | Viitattu = 16.11.2009}}{{dead link|date=December 2016}}</ref> [[Tunis]]in ATP-haastajaturnauksen välierissä hän loukkasi oikean ranteensa, jossa diagnosoitiin myöhemmin jänteen tukikalvon repeämä.<ref name=\"ATP Profile\"/><ref>{{Verkkoviite | Osoite = http://ohjelmat.yle.fi/akuutti/arkisto/2009/jarkko_niemisen_erilainen_kesa | Nimeke = Jarkko Niemisen erilainen kesä | Tekijä = Kyllönen, Tero | Julkaisu = YLE Ohjelmat | Ajankohta = 1.9.2009 | Julkaisija = Yleisradio Oy | Viitattu = 21.2.2010}}{{dead link|date=December 2016}}</ref> Toukokuussa hän oli ranneleikkauksessa, josta toivuttuaan hän palasi tenniskentille elokuussa 2009.<ref>{{Verkkoviite | Osoite = http://yle.fi/uutiset/niemisen_kesassa_kuntoutusta_ja_konsertteja/5251310 | Nimeke = Niemisen kesässä kuntoutusta ja konsertteja | Tekijä = Rikman, Johanna | Julkaisu = Yle Urheilu | Ajankohta = 14.5.2009 | Viitattu = 4.8.2014}}</ref><ref>{{Verkkoviite | Osoite = http://www.ts.fi/urheilu/85130/Nieminen+haastaa+Benneteaun+Baselissa | Nimeke = Nieminen haastaa Benneteaun Baselissa | Julkaisu = ts.fi | Ajankohta = 1.11.2009 | Viitattu = 4.8.2014}}</ref> Marraskuussa hän voitti ATP-haastajaturnauksen [[Jersey]]ssä.<ref>{{Verkkoviite | Osoite = http://www.hs.fi/urheilu/artikkeli/Jarkko+Nieminen+voitti+Jerseyn+ATP-haastajaturnauksen/1135250779951 | Nimeke = Jarkko Nieminen voitti Jerseyn ATP-haastajaturnauksen | Julkaisu = HS.fi | Ajankohta = 15.11.2009 | Julkaisija = Sanoma News Oy | Viitattu = 19.8.2010}}{{dead link|date=December 2016}}</ref> Kuun lopulla hän hävisi [[Henri Kontinen|Henri Kontiselle]] IPP Openin puolivälierissä. Edellisen kerran hän hävisi suomalaispelaajalle maaliskuussa 2000 hävittyään sisäkenttien Suomen mestaruuskilpailuiden loppuottelun [[Timo Nieminen (tennispelaaja)|Timo Niemiselle]].<ref>{{Verkkoviite | Osoite = http://yle.fi/uutiset/3-5945637 | Nimeke = Vallanvaihto? Kontinen löi Niemisen Talissa | Julkaisu = YLE Urheilu | Ajankohta = 27.11.2009 | Julkaisija = Yleisradio Oy | Viitattu = 18.8.2010}}</ref>\r\n\r\n[[Australian avoin tennisturnaus 2010|Australian avoimissa 2010]] Nieminen voitti avauskierroksella [[Nick Lindahl]]in suoraan kolmessa erässä.<ref>{{Verkkoviite | Osoite = http://yle.fi/uutiset/3-5492824 | Nimeke = Jarkko Niemiselle riitti yksi peli tiistaina | Julkaisu = YLE Urheilu | Ajankohta = 19.1.2010 | Julkaisija = Yleisradio Oy | Viitattu = 19.1.2010}}</ref> Toisella kierroksella Nieminen kohtasi [[Florent Serra]]n, mutta hävisi hänelle viiden erän kamppailun.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2010/01/1037527 | Nimeke = Jarkko Nieminen hukkasi voiton avaimet ja putosi | Julkaisu = MTV3.fi | Ajankohta = 20.1.2010 | Julkaisija = MTV Oy | Viitattu = 20.1.2010}}</ref> Australian avointen nelinpelissä Nieminen pääsi välieriin parinsa [[Michael Kohlmann]]in kanssa. Hänestä tuli ensimmäinen Grand Slam -turnauksen välierissä pelannut suomalainen.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/3-5497256 | Nimeke = Jarkko Nieminen iski suomalaishistoriaa | Julkaisu = YLE Urheilu | Ajankohta = 26.1.2010 | Julkaisija = Yleisradio Oy | Viitattu = 26.1.2010}}</ref> Helmikuun lopulla Nieminen selviytyi välieriin [[Delray Beach International Tennis Championships|Delray Beachin ATP-turnauksessa]].<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/3-6150054 | Nimeke = Nieminen Delray Beachin välieriin | Julkaisu = YLE Urheilu | Ajankohta = 27.2.2010 | Julkaisija = Yleisradio Oy | Viitattu = 27.2.2010}}</ref> Maaliskuussa hän voitti [[Marrakech]]in ATP-haastajaturnauksen.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2010/03/1083468 | Nimeke = Jarkko Nieminen turnausvoittoon | Julkaisu = MTV3.fi | Ajankohta = 21.3.2010 | Julkaisija = MTV Oy | Viitattu = 21.3.2010}}</ref> Touko-kesäkuussa pelattavissa [[Ranskan avoin tennisturnaus 2010|Ranskan avoimissa]] Nieminen hävisi avauskierroksella tiukan taistelun jälkeen kuudenneksi sijoitetulle [[Andy Roddick]]ille luvuin 2–6, 6–4, 6–4, 6–7(4), 3–6.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/3-5568653 | Nimeke = Niemiselle jälleen karvas Grand Slam -tappio | Julkaisu = YLE Urheilu | Ajankohta = 25.5.2010 | Julkaisija = Yleisradio Oy | Viitattu = 24.6.2010}}</ref> Kesän alussa Nieminen palkkasi valmentajakseen Jan de Wittin.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2010/06/1146304 | Nimeke = Jarkko Nieminen palkkasi valmentajan | Julkaisu = MTV3.fi | Ajankohta = 20.6.2010 | Julkaisija = MTV Oy | Viitattu = 3.12.2010}}</ref> [[Wimbledonin tennisturnaus 2010|Wimbledonissa]] hän voitti avauskierroksella [[Stefan Koubek]]in, mutta hävisi toisella kierroksella neljänneksi sijoitetulle [[Andy Murray]]lle.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2010/06/nieminen_palasi_wimbledoniin_voittajana_1781639.html | Nimeke = Nieminen palasi Wimbledoniin voittajana | Julkaisu = YLE Urheilu | Ajankohta = 22.6.2010 | Julkaisija = Yleisradio Oy | Viitattu = 24.6.2010}}{{dead link|date=December 2016}}</ref><ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2010/06/murray_ei_antanut_niemiselle_mahdollisuuksia_1787268.html | Nimeke = Murray ei antanut Niemiselle mahdollisuuksia | Julkaisu = YLE Urheilu | Ajankohta = 24.6.2010 | Julkaisija = Yleisradio Oy | Viitattu = 24.6.2010}}{{dead link|date=December 2016}}</ref> Heinä–elokuun vaihteessa hän voitti [[Sveitsin avoin tennisturnaus|Gstaadin ATP-turnauksen]] nelinpelin parinsa [[Johan Brunström]]in kanssa.<ref>{{Verkkoviite | Osoite = http://www.hs.fi/urheilu/tennis/artikkeli/Jarkko+Nieminen+pelasi+yst%C3%A4v%C3%A4ns%C3%A4+kanssa+paremmin+kuin+ikin%C3%A4/1135259000617 | Nimeke = Jarkko Nieminen pelasi ystävänsä kanssa \"paremmin kuin ikinä\" | Julkaisu = HS.fi | Ajankohta = 1.8.2010 | Julkaisija = Sanoma News Oy | Viitattu = 2.8.2010 | Kieli = {{en}}}}</ref> Syys–lokakuun vaihteessa hän löysi hyvän pelivireen ja selviytyi Bangkokin Thailand Openin loppuotteluun.<ref>{{Verkkoviite | Osoite = http://www.urheilulehti.fi/lisaa-lajeja/tennis/eerikainen-nieminen-pelaa-vanhaa-hyvaa-peliaan | Nimeke = Eerikäinen: Nieminen pelaa vanhaa hyvää peliään | Tekijä = Eerikäinen, Janne | Julkaisu = urheilulehti.fi | Ajankohta = 1.10.2010 | Julkaisija = A-lehdet Oy | Viitattu = 3.10.2010}}</ref><ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2010/10/nieminen_itsevarmana_syotto_on_loytynyt_2025505.html | Nimeke = Nieminen itsevarmana: Syöttö on löytynyt | Julkaisu = YLE Urheilu | Ajankohta = 1.10.2010 | Julkaisija = Yleisradio Oy | Viitattu = 3.10.2010}}{{dead link|date=December 2016}}</ref><ref name=\"YLE 2028845\">{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2010/10/nieminen_taipui_huikeassa_taistelussa_2028845.html | Nimeke = Nieminen taipui huikeassa taistelussa | Julkaisu = YLE Urheilu | Ajankohta = 3.10.2010 | Julkaisija = Yleisradio Oy | Viitattu = 3.10.2010}}{{dead link|date=December 2016}}</ref> Loppuottelun hän kuitenkin hävisi välierissä Rafael Nadalin voittaneelle [[Guillermo García-López]]ille kolmessa erässä.<ref name=\"YLE 2028845\"/> Tukholman avoimissa Nieminen voitti silloisen maailmanlistan kuutosen [[Tomáš Berdych]]in, mutta hävisi välierissä [[Florian Mayer]]ille.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2010/10/jarkko_nieminen_murjoi_maailmanlistan_kuutosen_2075178.html | Nimeke = Jarkko Nieminen murjoi maailmanlistan kuutosen | Julkaisu = YLE Urheilu | Ajankohta = 20.10.2010 | Julkaisija = Yleisradio Oy | Viitattu = 23.10.2010}}{{dead link|date=December 2016}}</ref><ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2010/10/mayer_paatti_niemisen_lennon_valieratrillerissa_2083472.html | Nimeke = Mayer päätti Niemisen lennon välierätrillerissä | Julkaisu = YLE Urheilu | Ajankohta = 23.10.2010 | Julkaisija = Yleisradio Oy | Viitattu = 23.10.2010}}{{dead link|date=December 2016}}</ref> Marraskuussa Nieminen kommentoi uskovansa hänen pelinsä menneen eteenpäin vuodesta 2006. Syötön kehittymisestä hän oli erityisen tyytyväinen.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2010/11/jarkko_niemisen_upea_syksy_2119474.html | Nimeke = ILMIÖITÄ: Jarkko Niemisen upea syksy | Julkaisu = YLE Urheilu | Ajankohta = 5.11.2010 | Julkaisija = Yleisradio Oy | Viitattu = 5.12.2010}}{{dead link|date=December 2016}}</ref> Lisäksi Nieminen kommentoi pelanneensa vuoden aikana liikaa ja kehui valmentajaansa de Wittiä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2010/11/jarkko_nieminen_pelasi_tana_vuonna_liikaa_2164725.html | Nimeke = Jarkko Nieminen pelasi tänä vuonna liikaa | Julkaisu = YLE Urheilu | Ajankohta = 23.11.2010 | Julkaisija = Yleisradio Oy | Viitattu = 4.12.2010}}{{dead link|date=December 2016}}</ref>\r\n\r\nVuonna 2011 Nieminen joutui luovuttamaan Sydneyn turnauksen ensimmäisellä kierroksella [[Frederico Gil]]iä vastaan polvivamman vuoksi.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/01/jarkko_nieminen_luovutti_sydneyssa_2274805.html | Nimeke = Jarkko Nieminen luovutti Sydneyssä | Julkaisu = YLE Urheilu | Ajankohta = 5.2.2011 | Julkaisija = Yleisradio Oy | Viitattu = 8.2.2011}}{{dead link|date=December 2016}}</ref> Seuraavalla viikolla alkaneissa [[Australian avoin tennisturnaus 2011|Australian avoimissa]] hän hävisi ensimmäisellä kierroksella seitsemänneksi sijoitetulle [[David Ferrer]]ille, joka pääsi turnauksessa aina välieriin asti.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/02/onnetar_oikuttelee_niemiselle_-_ferrer_taas_vastaan_2342501.html | Nimeke = Onnetar oikuttelee Niemiselle - Ferrer taas vastaan! | Julkaisu = YLE Urheilu | Ajankohta = 5.2.2011 | Julkaisija = Yleisradio Oy | Viitattu = 8.2.2011}}{{dead link|date=December 2016}}</ref> Rotterdamin turnauksen avauskierroksella Nieminen kohtasi jälleen Ferrerin, ja voitti hänet tällä kertaa suoraan kahdessa erässä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/02/nieminen_kaatoi_maailmanlistan_kuutosen_2348629.html | Nimeke = Nieminen kaatoi maailmanlistan kuutosen | Julkaisu = YLE Urheilu | Ajankohta = 5.2.2011 | Julkaisija = Yleisradio Oy | Viitattu = 8.2.2011}}{{dead link|date=December 2016}}</ref> [[Ranskan avoin tennisturnaus 2011|Ranskan avoimissa]] Nieminen hävisi ensimmäisen kierroksen ottelunsa David Ferrerille suoraan kolmessa erässä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/05/nieminen_vain_suupala_ferrerille_2612608.html | Nimeke = Nieminen vain suupala Ferrerille | Julkaisu = YLE Urheilu | Ajankohta = 22.5.2011 | Julkaisija = Yleisradio Oy | Viitattu = 22.5.2011}}{{dead link|date=December 2016}}</ref> Myös [[Wimbledonin tennisturnaus 2011|Wimbledonissa]] Nieminen kärsi tappion avauskierroksella, kun hän hävisi [[Nicolas Almagro]]lle lukemin 7–6(5), 3–6, 4–6, 4–6.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/06/niemiselle_jalleen_karvas_tappio_avauskierroksella_2679233.html | Nimeke = Niemiselle jälleen karvas tappio avauskierroksella | Julkaisu = YLE Urheilu | Ajankohta = 21.6.2011 | Julkaisija = Yleisradio Oy | Viitattu = 21.6.2011}}{{dead link|date=December 2016}}</ref> Huono Grand Slam -menestys jatkui [[Yhdysvaltain avoin tennisturnaus 2011|Yhdysvaltain avoimissa]], missä Nieminen hävisi avauskierroksella Fernando Verdascolle. Nieminen ei ollut aiemmin pudonnut jokaisesta kauden Grand Slam -turnauksesta ensimmäisellä kierroksella.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/08/nieminen_syvassa_grand_slam_-suossa_2831860.html | Nimeke = Nieminen syvässä Grand Slam -suossa | Julkaisu = YLE Urheilu | Ajankohta = 31.8.2011 | Julkaisija = Yleisradio Oy | Viitattu = 31.8.2011}}{{dead link|date=December 2016}}</ref> Lokakuussa Nieminen selviytyi kolmannen kerran Tukholman avointen loppuotteluun. Turnauksen toisella kierroksella hän voitti maailmanlistan sijalla 19 olleen [[Stanislas Wawrinka]]n 6–3, 6–4 ja välierässä James Blaken luvuin 7–6(5), 5–7, 6–2.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/10/niemiselle_komea_voitto_tukholmassa_2964572.html | Nimeke = Niemiselle komea voitto Tukholmassa | Julkaisu = YLE Urheilu | Ajankohta = 20.10.2011 | Julkaisija = Yleisradio Oy | Viitattu = 23.10.2011}}{{dead link|date=December 2016}}</ref><ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/10/nieminen_kolmatta_kertaa_tukholman_finaaliin_2968637.html | Nimeke = Nieminen kolmatta kertaa Tukholman finaaliin | Julkaisu = YLE Urheilu | Ajankohta = 22.10.2011 | Julkaisija = Yleisradio Oy | Viitattu = 23.10.2011}}{{dead link|date=December 2016}}</ref> Loppuottelussa Nieminen hävisi kolmieräisen ottelun maailmanlistan sijalla kymmenen olleelle [[Gaël Monfils]]ille lukemin 5–7, 6–3, 2–6.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/10/monfils_nujersi_niemisen_tukholmassa_2969953.html | Nimeke = Monfils nujersi Niemisen Tukholmassa | Julkaisu = YLE Urheilu | Ajankohta = 23.10.2011 | Julkaisija = Yleisradio Oy | Viitattu = 23.10.2011}}{{dead link|date=December 2016}}</ref> Marraskuussa Nieminen pelasi Baselin turnauksessa, jossa hän voitti ensimmäistä kertaa urallaan erän Roger Federeriä vastaan. Toisen kierroksen ottelu heidän 12:nnessa kohtaamisessaan päättyi kuitenkin Federerin voittoon lukemin 6–1, 4–6, 6–3.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2011/11/jarkko_nieminen_vei_eran_roger_federerilta_2998324.html | Nimeke = Jarkko Nieminen vei erän Roger Federeriltä | Julkaisu = YLE Urheilu | Ajankohta = 2.11.2011 | Julkaisija = Yleisradio Oy | Viitattu = 2.11.2011}}{{dead link|date=December 2016}}</ref>\r\n\r\n=== Uran toinen turnausvoitto (2012) ===\r\nNieminen saavutti uransa toisen turnausvoittonsa kaksinpelissä voitettuaan tammikuussa 2012 pelatun Sydneyn turnauksen. Loppuottelussa hän päihitti [[Julien Benneteau]]n luvuin 6–2, 7–5.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2012/01/niemisen_pitka_piina_paattyi_sydneyssa_3175299.html | Nimeke = Niemisen pitkä piina päättyi Sydneyss | Julkaisu = Yle Urheilu | Ajankohta = 15.1.2012 | Julkaisija = Yleisradio Oy | Viitattu = 28.1.2012}}{{dead link|date=December 2016}}</ref> Samassa turnauksessa Nieminen selviytyi myös nelinpelin loppuotteluun yhdessä [[Matthew Ebden]]in kanssa. He hävisivät kuitenkin maailmanlistan ykkösparille, [[Bob Bryan]] ja [[Mike Bryan]].<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2012/01/quotolen_aika_hyva_uskomaan_itseeniquot_3175402.html | Nimeke = \"Olen aika hyvä uskomaan itseeni\" | Julkaisu = Yle Urheilu | Ajankohta = 15.1.2012 | Julkaisija = Yleisradio Oy | Viitattu = 28.1.2012}}{{dead link|date=December 2016}}</ref> [[Australian avoin tennisturnaus 2012|Australian avoimissa]] Nieminen joutui luovuttamaan ensimmäisen kierroksen ottelussaan David Nalbandiania vastaan vatsalihasvamman vuoksi. Nieminen oli tappiolla ottelua luvuin 4–6, 2–4.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/lajit/tennis/2012/01/nieminen_luovutti_australian_avoimissa_3177360.html | Nimeke = Nieminen luovutti Australian avoimissa | Julkaisu = Yle Urheilu | Ajankohta = 16.1.2012 | Julkaisija = Yleisradio Oy | Viitattu = 28.1.2012}}{{dead link|date=December 2016}}</ref> [[Ranskan avoin tennisturnaus 2012|Ranskan avointen]] ensimmäisellä kierroksella Nieminen voitti Igor Andrejevin, joka luovutti kolmannessa erässä. Andrejev voitti ensimmäisen erän 6–3 ja Nieminen toisen erän 6–2. Ottelun jälkeen Nieminen sanoi pelanneensa harjoituksissa elämänsä tennistä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_pelaan_elamani_tennista/6141072 | Nimeke = Nieminen: Pelaan elämäni tennistä | Ajankohta = 29.5.2012 | Julkaisu = Yle Urheilu | Julkaisija = Yleisradio Oy | Viitattu = 1.6.2012}}</ref> Toisella kierroksella Nieminen hävisi neljänneksi sijoitetulle Andy Murraylle, vaikka voittikin ensimmäisen erän 6–1. Murray kärsi avauserässä selkävaivoista, mutta paransi peliään pikku hiljaa, kun Niemisen peli puolestaan meni huonompaan suuntaan. Murray voitti ottelun luvuin 1–6, 6–4, 6–1, 6–2.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/erikoinen_ottelu_-_murray_pudotti_niemisen/6146292 | Nimeke = Erikoinen ottelu - Murray pudotti Niemisen | Ajankohta = 31.5.2012 | Julkaisija = Yle Urheilu | Viitattu = 1.6.2012}}</ref> [[Wimbledonin tennisturnaus 2012|Wimbledonissa]] Nieminen voitti ensimmäisellä kierroksella 14:nneksi sijoitetun [[Feliciano López]]in.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_vaansi_voiton_wimbledonin_avauksesta/6195479 | Nimeke = Nieminen väänsi voiton Wimbledonin avauksesta | Ajankohta = 26.6.2012 | Julkaisija = Yle Urheilu | Viitattu = 29.6.2012}}</ref> Toisella kierroksella kuitenkin [[Brian Baker (tennispelaaja)|Brian Baker]] kukisti Niemisen 6–0, 6–2, 6–4.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/niemiselle_taystyrmays_-_baker_jyrasi_jatkoon/6198799 | Nimeke = Niemiselle täystyrmäys - Baker jyräsi jatkoon | Ajankohta = 28.6.2012 | Julkaisija = Yle Urheilu | Viitattu = 29.6.2012}}</ref>\r\n\r\n[[Kesäolympialaiset 2012|Lontoon olympialaisissa]] Nieminen voitti ensimmäisellä kierroksella maailmanlistan sijalla 418 olleen [[Somdev Devvarman]]in luvuin 6–3, 6–1.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_nieminen_leikitteli_sateessa_jatkoon_-_seuraavaksi_maailmanlistan_nelonen_vastaan/6234734 | Nimeke = Jarkko Nieminen leikitteli sateessa jatkoon - seuraavaksi maailmanlistan nelonen vastaan | Ajankohta = 29.7.2012 | Julkaisija = Yle Urheilu | Viitattu = 4.8.2012}}</ref> Toisella kierroksella Nieminen kohtasi maailmanlistan nelosen ja kotiyleisön suosikin, Andy Murrayn, joka voitti ottelun suoraan kahdessa erässä 6–2, 6–4.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_sai_kylmaa_kyytia_murraylta/6237326 | Nimeke = Nieminen sai kylmää kyytiä Murraylta | Ajankohta = 31.7.2012 | Julkaisija = Yle Urheilu | Viitattu = 4.8.2012}}</ref> [[Winston-Salem Open|Winston Salemin turnauksessa]] Nieminen pääsi suoraan toiselle kierrokselle, jossa hän voitti [[Benjamin Becker]]in.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_kukisti_beckerin/6264936 | Nimeke = Nieminen kukisti Beckerin | Ajankohta = 21.8.2012 | Julkaisija = Yle Urheilu | Viitattu = 23.8.2012}}</ref> Kolmannella kierroksella hän hävisi Tomáš Berdychille.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_putosi_berdychin_kasittelyssa/6266781 | Nimeke = Nieminen putosi Berdychin käsittelyssä | Ajankohta = 23.8.2012 | Julkaisija = Yle Urheilu | Viitattu = 23.8.2012}}</ref> [[Yhdysvaltain avoin tennisturnaus 2012|Yhdysvaltain avoimissa]] Nieminen johti ensimmäisellä kierroksella [[Mihail Kukuškin]]ia vastaan 6–0, 6–2, minkä jälkeen Kukuškin luovutti ottelun.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_nieminen_jatkoon_luovutuksella/6275040 | Nimeke = Jarkko Nieminen jatkoon luovutuksella | Ajankohta = 29.8.2012 | Julkaisija = Yle Urheilu | Viitattu = 29.6.2012}}</ref> Toisella kierroksella Nieminen taisteli kovasyöttöistä Yhdysvaltain ykköspelaajaa, [[John Isner]]iä vastaan, mutta hävisi ottelun neljässä erässä, voitettuaan toisen erän tie breakissa.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_vei_eran_-_isner_jatkaa_us_openissa/6278323 | Nimeke = Nieminen vei erän - Isner jatkaa US Openissa | Ajankohta = 1.9.2012 | Julkaisija = Yle Urheilu | Viitattu = 1.9.2012}}</ref> Syyskuussa pelatussa Thailand Openissa Nieminen voitti puolivälierissä maailmanlistan sijalla 15 olleen [[Milos Raonic]]in 6–3, 7–6.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_niemiselle_maukas_voitto/6314684 | Nimeke = Jarkko Niemiselle maukas voitto | Ajankohta = 28.9.2012 | Julkaisija = Yle Urheilu | Viitattu = 30.9.2012}}</ref> Välierissä Nieminen hävisi [[Richard Gasquet|Richard Gasquet'lle]] kolmessa erässä luvuin 6–3, 5–7, 2–6 johdettuaan toista erää jo 4–0.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_niemiselta_uskomaton_romahdus_bangkokissa/6315020 | Nimeke = Jarkko Niemiseltä uskomaton romahdus Bangkokissa | Ajankohta = 29.9.2012 | Julkaisija = Yle Urheilu | Viitattu = 30.9.2012}}</ref>\r\n[[Tiedosto:Jarkko Nieminen - Roland-Garros 2013 - 005.jpg|pienoiskuva|200px|right|Jarkko Nieminen Ranskan avoimissa 2013.]]\r\nLokakuu sujui Niemiseltä vaisusti, kun hän hävisi ensimmäisellä kierroksella Tokiossa, Shanghaissa ja Baselissa. Tukholmassa hän pääsi toiselle kierrokselle.<ref name=\"ATP Profile\"/> Nieminen vetäytyi loka-marraskuun vaihteessa pelattavasta Pariisin Masters-turnauksesta.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_vetaytyi_pariisin_mastersista/6352826 | Nimeke = Nieminen vetäytyi Pariisin Mastersista | Ajankohta = 27.10.2012 | Julkaisija = Yle Urheilu | Viitattu = 27.10.2012}}</ref> Nieminen päätti kautensa Helsingissä pelattuun haastajaturnaukseen, jonka loppuottelussa hän hävisi [[Lukáš Lacko]]lle.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/niemisen_kausi_paattyi_finaalitappioon/6381018 | Nimeke = Niemisen kausi päättyi finaalitappioon | Ajankohta = 18.11.2012 | Julkaisija = Yle Urheilu | Viitattu = 18.11.2012}}</ref>\r\n\r\n=== Paras kauteen valmistava jakso takana (2013) ===\r\n{{Pääartikkeli|[[Jarkko Niemisen kausi 2013]]}}\r\nNieminen sanoi ennen [[ATP-kausi 2013|kauden]] alkua, että hänen kauteen valmistava jakso sujui paremmin kuin ennen.<ref>{{Verkkoviite | Osoite = http://www.urheilulehti.fi/lisaa-lajeja/niemisen-kausi-alkaa-voi-vielakin-olla-elamansa-kunnossa | Nimeke = Niemisen kausi alkaa - \"Voi vieläkin olla elämänsä kunnossa\" | Julkaisu = urheilulehti.fi | Ajankohta = 30.12.2012 | Julkaisija = Urheilulehti | Viitattu = 8.1.2013}}</ref> Nieminen lähti puolustavana mestarina Sydneyn turnaukseen, jossa hän hävisi tällä kertaa puolivälierissä [[Bernard Tomic]]ille kolmessa erässä luvuin 7–6(6), 4–6, 2–6.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_havisi_kovan_puolivalierataistelun/6444998 | Nimeke = Nieminen hävisi kovan puolivälierätaistelun | Tekijä = Saarinen, Ossi | Julkaisu = Yle Urheilu | Ajankohta = 10.1.2013 | Julkaisija = Yleisradio Oy | Viitattu = 10.1.2013}}</ref> [[Australian avoin tennisturnaus 2013|Australian avointen]] ensimmäisellä kierroksella Nieminen voitti 19:nneksi sijoitetun Tommy Haasin.<ref name=\"AO1\">{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_taisteli_upeaan_voittoon_australiassa/6451090 | Nimeke = Nieminen taisteli upeaan voittoon Australiassa | Tekijä = Lehtisaari, Matti | Julkaisu = Yle Urheilu | Ajankohta = 15.1.2013 | Julkaisija = Yleisradio Oy | Viitattu = 15.1.2013}}</ref> Ottelu venyi ratkaisevaan viidentään erään, jonka Nieminen voitti 8–6. Kolme tuntia ja 45 minuuttia kestäneen ottelun loppulukemat olivat 7–6(3), 4–6, 6–3, 4–6, 8–6. Toista erää Nieminen johti 4–1, mutta Haas voitti viisi peliä putkeen ja lopulta koko erän.<ref name=\"AO1\"/> Toisella kierroksella Nieminen hävisi maailmanlistan sijalla 74 olleelle [[Ivan Dodig]]ille viidessä erässä luvuin 3–6, 7–6(4), 3–6, 7–6(4), 1–6. Yhteensä Niemisellä oli noin 40 asteen lämpötilassa pelatussa ottelussa 18 murtopalloa, joista hän voitti vain yhden.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_ja_dodig_viidenteen_eraan/6454810 | Nimeke = Kaksi maratonottelua liikaa Niemiselle - tappio viidessä erässä | Tekijä = Lund, Sakari | Julkaisu = Yle Urheilu | Ajankohta = 17.1.2013 | Julkaisija = Yleisradio Oy | Viitattu = 17.1.2013}}</ref> [[Montpellier]]in turnauksessa Nieminen eteni ensimmäisen kerran tällä kaudella ATP-turnauksessa välieriin.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_nieminen_eteni_komeasti_valieriin_ranskassa/6487697 | Nimeke = Jarkko Nieminen eteni komeasti välieriin Ranskassa | Tekijä = Härkönen, Matti | Julkaisu = Yle Urheilu | Ajankohta = 8.2.2013 | Julkaisija = Yleisradio Oy | Viitattu = 8.2.2013}}</ref> Välierissä hän hävisi kolmessa erässä maailmanlistan sijalla kymmenen olleelle Richard Gasquet'lle.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_joutui_pettymaan_montpellierissa/6488239 | Nimeke = Nieminen joutui pettymään Montpellierissä | Tekijä = Laaksonen, Antti | Julkaisu = Yle Urheilu | Ajankohta = 9.2.2013 | Julkaisija = Yleisradio Oy | Viitattu = 9.2.2013}}</ref> Rotterdamin turnauksessa Nieminen pääsi puolivälieriin, jossa hän hävisi maailmanlistan sijalla seitsemän olleelle [[Juan Martín del Potro]]lle.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/del_potro_syotti_niemisen_katsomoon/6498758 | Nimeke = Del Potro syötti Niemisen katsomoon | Tekijä = Lund, Sakari | Julkaisu = Yle Urheilu | Ajankohta = 15.2.2013 | Julkaisija = Yleisradio Oy | Viitattu = 17.2.2013}}</ref> Monte Carlo Masters -turnauksessa Nieminen voitti toisella kierroksella maailmanlistan sijalla 15 olleen [[Milos Raonic]]in. Nieminen tarvitsi ottelun voittamiseen vain yhden murron, ja ratkaisevan kolmannen erän hän voitti tie breakissa 7–3.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_niemiselle_jalleen_upea_voitto/6583497 | Nimeke = Jarkko Niemiselle jälleen upea voitto | Tekijä = Lund, Sakari | Julkaisu = Yle Urheilu | Ajankohta = 17.4.2013 | Julkaisija = Yleisradio Oy | Viitattu = 17.4.2013}}</ref> Kolmannella kierroksella Nieminen voitti viidenneksi sijoitetun Juan Martín del Potron 6–4, 4–6, 7–6(4). Aiemmin heidän pelaamissaan viidessä ottelussa Nieminen ei ollut voittanut erääkään Del Potroa vastaan.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_niemiselle_historiallinen_voitto/6586162 | Nimeke = Jarkko Niemiselle historiallinen voitto | Tekijä = Laaksonen, Antti | Julkaisu = Yle Urheilu | Ajankohta = 18.4.2013 | Julkaisija = Yleisradio Oy | Viitattu = 18.4.2013}}</ref> Niemisen kauden tie break -tilasto ottelun jälkeen oli kahdeksan voittoa ja nolla tappiota.<ref>{{Verkkoviite | Osoite = http://www.sportti.com/uutinen.asp?CAT=4-2&ID=239836 | Nimeke = Jarkko Nieminen kaatoi maailmanlistan seiskan | Julkaisu = sportti.com | Ajankohta = 18.4.2013 | Viitattu = 21.4.2013}}</ref> Puolivälierissä Nieminen hävisi maailmanlistan ykköselle, Serbian [[Novak Đoković]]ille suoraan kahdessa erässä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/djokovic_paatti_niemisen_hienon_viikon/6587984 | Nimeke = Djokovic päätti Niemisen hienon viikon | Tekijä = Laaksonen, Antti | Julkaisu = Yle Urheilu | Ajankohta = 19.4.2013 | Julkaisija = Yleisradio Oy | Viitattu = 21.4.2013}}</ref>\r\n\r\nKauden ensimmäisen turnausvoittonsa Nieminen saavutti Münchenin nelinpeliturnauksessa toukokuussa yhdessä [[Dmitri Tursunov]]in kanssa. He etenivät loppuotteluun voittamalla muun muassa ykkössijoitetun parin [[Alexander Peya]] ja [[Bruno Soares]].<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/niemiselle_upea_paanahka_munchenin_nelinpelissa/6616630 | Nimeke = Niemiselle upea päänahka Münchenin nelinpelissä | Tekijä = Salo, Martti | Julkaisu = Yle Urheilu | Ajankohta = 30.4.2013 | Julkaisija = Yleisradio Oy | Viitattu = 5.5.2013}}</ref> Loppuottelussa Nieminen ja Tursunov voittivat [[Marcos Baghdatis]]in ja [[Eric Butorac]]in. Tämä oli Niemisen uran kolmas turnausvoitto nelinpelissä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_niemiselle_nelinpelin_turnausvoitto/6619717 | Nimeke = Jarkko Niemiselle nelinpelin turnausvoitto! | Tekijä = Lund, Sakari | Julkaisu = Yle Urheilu | Ajankohta = 5.5.2013 | Julkaisija = Yleisradio Oy | Viitattu = 5.5.2013}}</ref> [[Düsseldorf]]in turnauksessa Nieminen eteni ensimmäistä kertaa tällä kaudella kaksinpelin loppuotteluun. Loppuottelussa hän hävisi Argentiinan [[Juan Mónaco]]lle suoraan kahdessa erässä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nain_eteni_jarkko_niemisen_finaali_dusseldorfissa/6649070 | Nimeke = Näin eteni Jarkko Niemisen finaali Düsseldorfissa | Tekijä = Lund, Sakari | Julkaisu = Yle Urheilu | Ajankohta = 25.5.2013 | Julkaisija = Yleisradio Oy | Viitattu = 28.5.2013}}</ref> [[Ranskan avoin tennisturnaus 2013|Ranskan avointen]] ensimmäisellä kierroksella Nieminen voitti isäntämaan [[Paul-Henri Mathieu]]n. Viisieräinen, yli kolme ja puoli tuntia kestänyt ottelu päättyi Niemisen voittoon luvuin 6–4, 4–6, 7–6, 4–6, 6–2.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_nieminen_taisteli_voittoon_trilleriottelussa/6661325 | Nimeke = Jarkko Nieminen taisteli voittoon trilleriottelussa | Tekijä = Härkönen, Matti | Julkaisu = Yle Urheilu | Ajankohta = 27.5.2013 | Julkaisija = Yleisradio Oy | Viitattu = 28.5.2013}}</ref> Toisella kierroksella Nieminen hävisi kuudenneksi sijoitetulle Jo-Wilfried Tsongalle suoraan kolmessa erässä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_nieminen_tylysti_katsomoon_ranskan_avoimissa/6664473 | Nimeke = Jarkko Nieminen tylysti katsomoon Ranskan avoimissa | Tekijä = Palomäki, Ilkka | Julkaisu = Yle Urheilu | Ajankohta = 29.5.2013 | Julkaisija = Yleisradio Oy | Viitattu = 29.5.2013}}</ref> [[Wimbledonin tennisturnaus 2013|Wimbledonissa]] Nieminen hävisi ensimmäisellä kierroksella Michaël Llodralle suoraan kolmessa erässä.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_noyrtyi_suoraan_kolmessa_erassa/6704520 | Nimeke = Nieminen nöyrtyi suoraan kolmessa erässä | Tekijä = Talja, Juho | Julkaisu = Yle Urheilu | Ajankohta = 25.6.2013 | Julkaisija = Yleisradio Oy | Viitattu = 25.6.2013}}</ref> [[Yhdysvaltain avoin tennisturnaus 2013|Yhdysvaltain avoimissa 2013]] Nieminen hävisi toisella kierroksella viisieräisessä ottelussa Portugalin [[João Sousa]]lle.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_taipui_viiden_eran_vaannon_jalkeen/6808566 | Nimeke = Nieminen taipui viiden erän väännön jälkeen | Tekijä = Perttilä, Jaakko | Julkaisu = Yle Urheilu | Ajankohta = 30.8.2013 | Julkaisija = Yleisradio Oy | Viitattu = 1.9.2013}}</ref>\r\n\r\nLoppuvuonna Nieminen pääsi vielä kaksi kertaa ATP 500 -turnauksessa kolmannelle kierrokselle. Ensin Tokiossa [[Japan Open Tennis Championships]]issa kaatuivat [[Juan Mónaco]] ja [[Michał Przysiężny]]. Lokakuussa [[Madrid Open (tennis)|Madrid Openissa]] tulivat voitot [[Benoit Paire]]sta ja [[Alejandro Falla]]sta. Vuosi huipentui kauden ensimmäiseen turnausvoittoon, tosin challenger-tasolla kotikentällä Helsingissä [[IPP Open]]issa.<ref name=\"ATP Profile\"/>\r\n\r\n=== Ennätysten kausi (2014) ===\r\n\r\nTultaessa vuoteen 2014 Jarkko Nieminen oli päättänyt jo 13 kautta ATP-maailmanlistan sadan parhaan joukossa, nyt sijalla 39. Vastaavaan nykypelaajista on pystynyt vain muutama, kuten [[Roger Federer]], [[Mihail Južnyi]] ja [[Nikolai Davydenko]]. Maaliskuussa Miamin Masters-turnauksen ensimmäisellä kierroksella Nieminen saavutti Masters-turnausten nopeimman otteluvoiton kukistamalla [[Bernard Tomic]]in, tulevaisuuden lupauksen, 28 minuutissa ja 20 sekunnissa luvuin 6–0, 6–1.<ref>{{Verkkoviite | Osoite = http://www.tennis.fi/sitenews/view/-/nid/13883/ngid/1/| Nimeke = 21.03.2014: Jarkko pelasi ATP Tourin historian lyhyimmän ottelun Miamiassa | Julkaisu = Tennis.fi | Julkaisija = Suomen Tennisliitto ry | Viitattu = 20.7.2014}}</ref> Ottelua pidettiin tuoreeltaan kaikkien aikojen lyhyimpänä loppuun asti pelattuna ATP-otteluna <ref>{{Verkkoviite | Osoite=http://espn.go.com/tennis/story/_/id/10642881/jarkko-nieminen-bernard-tomic-lasts-28-minutes-sets-atp-mark | Nimeke=Bernard Tomic KO'd quickly in return | Julkaisu=espn.go.com | Viitattu = 1.3.2015}}</ref> Myöhemmin kuitenkin selvisi, että ottelu oli ainoastaan Masters Tourin lyhyin, ATP-tasolla on pelattu 2001 myös 25 minuutin mittainen ottelu.<ref>{{Verkkoviite | Osoite=http://www.atpworldtour.com/Share/Match-Facts-Pop-Up.aspx?t=890&y=2001&r=3&p=C252 | Nimeke=Match facts Francisco Clavet - Shan Jiang | Julkaisu=ATPWorldTour.com | Julkaisija = Association of Tennis Professionals | Viitattu = 1.3.2015}}</ref> Niemisen voitto oli kuitenkin nopein loppuun asti pelatuissa ATP-tason otteluissa yli kymmeneen vuoteen. \r\n\r\nWimbledonissa vuorostaan Nieminen pelasi vuoden 2014 pisimmän ammattilaistason katkaisupelin <ref>{{Verkkoviite | Osoite=http://www.atpworldtour.com/News/Tennis/2014/12/50/ATP-By-The-Numbers-2014-Part-3.aspx | Nimeke = 2014 By The Numbers: Longest And Shortest Matches | Julkaisu=ATPWorldTour.com | Julkaisija=Association of Tennis Professionals | Viitattu=1.3.2015}}</ref> ja yhden Grand Slam -historian pisimmistä katkaisupeleistä hävitessään yhdeksänneksi sijoitetulle [[John Isner]]ille 6–7(17), 6–7(3), 5–7.<ref>{{Verkkoviite | Osoite = http://www.sportti.com/uutinen.asp?CAT=4-2&ID=268731 | Nimeke = Jarkko Nieminen hävisi vain yhden syöttöpelin – putosi Wimbledonista | Tekijä = | Julkaisu = Sportti.com | Ajankohta = 26.6.2014 | Julkaisija = Sportti.com | Viitattu = 20.7.2014}}</ref> Tällä kaudella Grand Slam -turnauksissa, Ranskan avoimissa ja Wimbledonissa, nähtiin ensimmäistä kertaa 65 vuoteen suomalainen nelinpelipari, kun Jarkko Nieminen ja [[Henri Kontinen]] pelasivat yhdessä.<ref name =HS14>{{Verkkoviite | Osoite = http://www.hs.fi/urheilu/a1401084580929 | Nimeke = Nieminen ja Kontinen tarjoavat harvinaista herkkua | Tekijä = Seiro, Arno | Julkaisu = Hs.fi | Ajankohta = 27.5.2014 | Julkaisija = Helsingin Sanomat | Viitattu = 20.7.2014}}</ref> Tuloksena oli Ranskan avoimissa voitto sijoitetusta parista [[Juan Sebastián Cabal]] / [[Robert Farah Maksoud|Robert Farah]].\r\n\r\nAlkukausi sujui Niemiseltä kohtalaisesti, parhaina saavutuksinaan pääsy kolmannelle kierrokselle sekä Indian Wellsin että Madridin Masters-turnauksissa. Indian Wellsissä kukistui toisella kierroksella [[Florian Mayer]] ATP-listan sijalta 29.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_nieminen_dominoi_-_eteni_jatkoon_luovutuksella/7127888 | Nimeke = Jarkko Nieminen dominoi - eteni jatkoon luovutuksella | Tekijä = Härkönen, Matti | Julkaisu = Yle Urheilu | Ajankohta = 10.3.2014 | Julkaisija = Yleisradio Oy | Viitattu = 20.7.2014}}</ref> Nieminen selvisi myös ensimmäistä kertaa vuoden 2008 jälkeen toiselle kierrokselle kauden kolmessa ensimmäisessä Grand Slam -turnauksessa. Wimbledonissa tämä vaati voiton ATP-listan 39. sijan [[Federico Delbonis]]ista – voitto tuli suoraan kolmessa erässä 6–3, 7–6(3), 7–5. <ref>{{Verkkoviite | Osoite = http://www.mtv.fi/sport/muutlajit/tennis/uutiset.shtml/2014/06/1908799/niemiselle-komea-voitto-wimbledonin-nurmella | Nimeke = Niemiselle komea voitto Wimbledonin nurmella | Tekijä = | Julkaisu = MTV Sport | Ajankohta = 24.6.2014 | Julkaisija = MTV.fi | Viitattu = 20.7.2014}}</ref>\r\n\r\nHeinäkuussa Nieminen palasi [[Tampere Open]]iin, selviten finaaliin, jossa kuitenkin hävisi tuolloin huikeaa 25 voiton putkea pelanneelle [[David Goffin]]ille. Heti seuraavalla viikolla kahdessa Grand Slam -turnauksessa kokeiltu suomalainen nelinpelipari Jarkko Nieminen – Henri Kontinen saavutti ensimmäisen ATP-turnausvoittonsa Itävallan avoimessa tennisturnauksessa Kitzbühelissa. Tämä oli kautta aikojen toinen suomalaisen nelinpeliparin saama turnausvoitto ATP-turnauksissa. Yhdysvaltain avoimissa tuli tappio ensimmäisellä kierroksella [[Ivo Karlović]]ille, mutta syyskuun lopulla Nieminen pelasi parasta peliään ATP 250 -turnauksessa [[Malaysian Open]]issa, voittaen maailmanlistan sijalla 25 olleen [[Leonardo Mayer]]in ja 45. sijalla olleen [[Pablo Andújar]]in. Tappio tuli vasta välierissä turnauksen voittajalle [[Kei Nishikori]]lle (ATP-8) kolmessa erässä. Haastattelussa Nieminen kertoi uransa jatkuvan myös vuonna 2015.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/jarkko_nieminen_paljasti_yle_urheilulle_miten_ura_jatkuu/7498305 | Nimeke = Jarkko Nieminen paljasti Yle Urheilulle, miten ura jatkuu | Julkaisija = Yle Urheilu | Viitattu = 30.9.2014}}</ref>\r\n\r\n=== Viimeinen ammattilaiskausi tenniksessä (2015) ===\r\nNieminen aloitti kautensa Brisbanen turnauksella, jossa hävisi toisella kierroksella [[James Duckworth]]ille. Sydneyssä hän joutui karsimaan pääsystä pääsarjaan selvittäen karsinnat, mutta hävisi pääsarjan ensimmäisellä kierroksella [[Pablo Andújar]]ille.<ref name=\"ATP Profile\" /> [[Australian avoin tennisturnaus 2015|Australian avoimissa]] Nieminen hävisi kolmannella kierroksella keskuskentällä pelatussa ottelussa Stan Wawrinkalle suoraan kolmessa erässä.<ref>{{Verkkoviite|nimeke = Nieminen antautui Wawrinkalle - mutta taistellen|osoite = http://yle.fi/urheilu/nieminen_antautui_wawrinkalle_-_mutta_taistellen/7758155|viitattu = 23.6.2015}}</ref> Buenos Airesin nelinpelissä Nieminen saavutti uransa viidennen nelinpelin turnausvoittonsa. Hän voitti turnauksen yhdessä [[André Sá]]n kanssa.<ref>{{Verkkoviite|nimeke = Jarkko Nieminen taisteli ATP-turnausvoittoon Argentiinassa|osoite = http://yle.fi/urheilu/jarkko_nieminen_taisteli_atp-turnausvoittoon_argentiinassa/7838126|viitattu = 23.6.2015}}</ref> Sekä Montpellierissä että [[Rio de Janeiro]]ssa Niemisen pelit päättyivät toiselle kierrokselle. Indian Wellsin ja Miamin Masters-turnauksissa hän eteni toiselle kierrokselle, ja jäi Monte-Carlossa karsintoihin.<ref name=\"ATP Profile\" /> [[Ranskan avoin tennisturnaus 2015|Ranskan avoimissa]] Nieminen hävisi avauskierroksella maailmanlistan ykköselle, Novak Đokovićille kolmessa erässä. Nieminen johti toista erää jo 5–2, mutta hävisi sen lopulta 5–7.<ref>{{Verkkoviite|nimeke = Jarkko Niemisen upea taistelu ei riittänyt - maailman ykkönen näytti tasonsa|osoite = http://yle.fi/urheilu/jarkko_niemisen_upea_taistelu_ei_riittanyt_-_maailman_ykkonen_naytti_tasonsa/8019873|viitattu = 23.6.2015}}</ref> Kesäkuussa hän hävisi avauskierroksella sekä [[’s-Hertogenbosch]]issa että Hallessa.<ref name=\"ATP Profile\" />\r\n\r\nKesäkuussa 2015 Nieminen piti tiedotustilaisuuden, jossa ilmoitti päättävänsä ammattilaisuransa kuluvan kauden jälkeen.<ref>{{Verkkoviite|nimeke = Jarkko Nieminen lopettaa upean tennisuransa|osoite = http://www.iltasanomat.fi/tennis/art-1435024664653.html|viitattu = 22.9.2015|julkaisu = iltasanomat.fi}}</ref> [[Wimbledonin tennisturnaus 2015|Wimbledonissa]] Nieminen voitti ensimmäisellä kierroksella vuonna 2002 turnauksen voittaneen Lleyton Hewittin viiden erän kamppailussa lukemin 3–6, 6–3, 4–6, 6–0, 11–9.<ref>{{Verkkoviite|nimeke = Nieminen lannisti Hewittin maratonottelussa|osoite = http://www.ts.fi/urheilu/788388/Nieminen+lannisti+Hewittin+maratonottelussa|viitattu = 22.9.2015|julkaisu = ts.fi}}</ref> Hän hävisi toisella kierroksella maailmanlistan ykköselle, Novak Đokovićille. Tampere Openissa hän hävisi välierissä maailmanlistan sijalla 270 olleelle [[Tristan Lamasine]]lle. [[Yhdysvaltain avoin tennisturnaus 2015|Yhdysvaltain avoimissa]] Nieminen hävisi avauskierroksella Jo-Wilfried Tsongalle.<ref name=\"ATP Profile\" /> Viimeisen ATP-turnauksensa Nieminen pelasi lokakuun lopussa Tukholmassa, jossa hän hävisi ensimmäisen kierroksen ottelunsa Nicolás Almagroa vastaan. <ref>{{Verkkoviite|nimeke = Jarkko Niemisen loistelias kaksinpeliura päättyi tappioon|osoite = http://yle.fi/urheilu/jarkko_niemisen_loistelias_kaksinpeliura_paattyi_tappioon/8395894|julkaisu = Yle Urheilu|julkaisija = |viitattu = 20.10.2015}}</ref> Nelinpelissä hän pelasi Johan Brunströmin kanssa, mutta myös nelinpelissä Niemisen pelit päättyivät avauskierrokselle hänen uransa viimeisessä ATP-ottelussa.<ref>{{Verkkoviite|nimeke = Jarkko Niemisen upea ura lopullisesti päätökseen|osoite = http://www.sportti.com/uutinen.asp?CAT=4-2&ID=298246|julkaisu = sportti.com|viitattu = 21.10.2015}}</ref> Jäähyväiset Nieminen jätti kilpakentille 9. marraskuuta Helsingin [[Hartwall Arena]]lla pelatussa näytösottelussa Roger Federeriä vastaan.<ref>{{Verkkoviite|nimeke = Nieminen ja Federer kohtaavat marraskuun alussa Helsingissä|osoite = http://yle.fi/uutiset/nieminen_ja_federer_kohtaavat_marraskuun_alussa_helsingissa/8304846|viitattu = 22.9.2015|julkaisu = Yle Urheilu}}</ref><ref>{{Verkkoviite|nimeke = Jarkko Nieminen pelaa Tukholmassa 20.10. - tulossa suomalaishuuma|osoite = http://www.tennis.fi/sitenews/view/-/nid/15816/ngid/1/|julkaisu = Suomen Tennisliitto|viitattu = 22.9.2015}}</ref> ″Final Night″ -nimisessä tapahtumassa Nieminen pelasi ensin nelinpeliä [[Teemu Selänne|Teemu Selänteen]] kanssa Roger Federeriä ja [[Peter Forsberg]]ia vastaan. Nieminen ja Selänne voittivat yksieräisen ottelun 6−3. Kaksinpelissä Nieminen hävisi Federerille kahdessa erässä luvuin 6–7(4), 6–7(7).<ref>{{Verkkoviite|nimeke = Nieminen taipui hymyssä suin jäähyväisottelussaan|osoite = http://yle.fi/urheilu/nieminen_taipui_hymyssa_suin_jaahyvaisottelussaan/8443426|julkaisu = Yle Urheilu|julkaisija = |viitattu = 10.11.2015}}</ref> Tapahtuma myytiin loppuun viidessä tunnissa ja täydessä hallissa oli 12 000 ihmistä.<ref>{{Verkkoviite|nimeke = Jarkko Nieminen moshasi juhlailtansa päätteeksi|osoite = http://www.iltalehti.fi/urheilu/2015110920639041_ur.shtml|julkaisu = iltalehti.fi|viitattu = 10.11.2015|kieli = }}</ref><ref>{{Verkkoviite|osoite = http://www.kauppalehti.fi/uutiset/jarkko-nieminen-myi-hartwall-arenan-loppuun-viidessa-tunnissa/JL3Pgffk|nimeke = Jarkko Nieminen myi Hartwall Arenan loppuun viidessä tunnissa|julkaisu = kauppalehti.fi|julkaisija = |viitattu = 10.11.2015|tekijä = |ajankohta = }}</ref> \r\n\r\n=== Siirtyminen salibandyn pariin ja Davis Cup -uran päättyminen (2016) ===\r\nNieminen sanoi edustavansa Suomea Davis Cupissa myös vuonna 2016, ja ilmaisi olevansa valmis edustamaan Suomea olympialaisissa [[Rio de Janeiro|Riossa]], mikäli Henri Kontinen saisi sinne paikan ja valitsisi hänet parikseen [[Tennis kesäolympialaisissa 2016|nelinpeliin]].<ref name=\":0\">{{Verkkoviite|nimeke = Jarkko Nieminen vielä kerran olympialaisiin? \"Olisi vaikea sanoa ei\"|osoite = http://www.mtv.fi/sport/muut-lajit/tennis/artikkeli/jarkko-nieminen-viela-kerran-olympialaisiin-olisi-vaikea-sanoa-ei/5686772|julkaisu = mtv.fi|viitattu = 12.1.2016}}</ref> Suomalaiset eivät kuitenkaan päässeet ITF:n olympialaisten pelaajalistalle.<ref>{{Verkkoviite|osoite=http://yle.fi/urheilu/3-9007584|nimeke=ITF:n Rion pelaajalista julki - ei suomalaisten nimiä|julkaisu=yle.fi|viitattu=2016-11-04}}</ref> Nieminen palasi tenniskentille 15. heinäkuuta 2016 [[Davis Cup 2016|Davis Cupin]] Euroopan-Afrikan lohkon ottelussa Tanskaa vastaan ja voitti avausottelunsa Mikael Torpegaardia vastaan erin 3–0,<ref>{{Verkkoviite|osoite=http://www.iltasanomat.fi/tennis/art-2000001221161.html|nimeke=Jarkko Nieminen palasi tenniskentille – otti Suomelle tärkeän voiton|viitattu=2016-07-15|ajankohta=2016-07-15|ietf-kielikoodi=fi-FI}}</ref> ja myös toisen kaksinpelinsä Frederik Nielseniä vastaan erin 3–1. Nelinpelissä hän kuitenkin hävisi [[Patrik Niklas-Salminen|Patrik Niklas-Salmisen]] kanssa tanskalaisparille erin 2–3. Suomi hävisi koko ottelun 2–3.<ref>{{Verkkoviite|osoite=http://www.iltasanomat.fi/tennis/art-2000001221876.html|nimeke=Jarkko Niemisen voitto nosti Suomen tasoihin Davis cupissa|viitattu=2016-07-17|ajankohta=2016-07-17|ietf-kielikoodi=fi-FI}}</ref> Samalla Nieminen ilmoitti maajoukkueuransa päättämisestä ja keskittyvänsä jatkossa salibandyuraansa. Tulevaisuudessa hän haluaisi olla Suomen Davis Cup -joukkueen kapteeni.<ref>{{Verkkoviite|osoite=http://yle.fi/urheilu/3-9032386|nimeke=Jarkko Niemisen Davis Cup -ura pelaajana päättyi|julkaisu=yle.fi|viitattu=2016-07-17}}</ref>\r\n\r\nHuhtikuussa 2016 salibandyseura [[Classic|SC Classic]] ilmoitti tehneensä yksivuotisen sopimuksen Niemisen kanssa.<ref name=\"säbä\" /><ref name=\"classic\" /> Hänen salibandydebyyttinsä kuitenkin siirtyy loppuvuoteen hänen kärsittyä jalkavammasta.<ref>{{Verkkoviite|osoite=http://yle.fi/urheilu/3-9264405|nimeke=Jarkko Niemisen juoksukielto jatkuu|julkaisu=yle.fi|viitattu=2016-11-04}}</ref>\r\n\r\n== Pelityyli tenniksessä ==\r\nNiemisen pelityyli on monipuolinen. Vasenkätinen Nieminen lyö kahden käden rystylyöntinsä lähes kierteettömänä, mutta kämmenlyönnin kierteisenä.<ref name=\"A&N\">{{Kirjaviite | Tekijä = Aitio, Tommi & Niskakangas, Tuomas | Nimeke = On tour – Ammattilaistenniksen taustat | Vuosi = 2006 | Sivu = 159–164 | Julkaisija = Avain | Tunniste = ISBN 978-952-5524-27-7}}</ref> Niemisen heikkoutena pidetään hänen kierteistä kakkossyöttöään.<ref name=\"A&N\"/><ref>{{Verkkoviite | Osoite = http://www.hs.fi/urheilu/artikkeli/Avauskierroksen+tappiot+alkavat+jo+turhauttaa+Jarkko+Niemist%C3%A4/1135243776234 | Nimeke = Avauskierroksen tappiot alkavat jo turhauttaa Jarkko Niemistä | Tekijä = Koskinen, Mikko | Julkaisu = HS.fi | Ajankohta = 24.2.2009 | Julkaisija = Sanoma News Oy | Viitattu = 9.2.2010}}{{dead link|date=December 2016}}</ref><ref>{{Verkkoviite | Osoite = http://www.iltasanomat.fi/urheilu/Jarkko%20Nieminen%20uskoo%20uuteen%20nousuun/art-1288338480362.html | Nimeke = Jarkko Nieminen uskoo uuteen nousuun | Julkaisu = iltasanomat.fi | Ajankohta = 19.5.2008 | Julkaisija = Sanoma News Oy | Viitattu = 9.2.2010}}</ref>\r\n\r\n{{quote|Jarkolla on uskomattoman hyvä rystylyönti, se on hänen vahvin aseensa. Hän lyö sen mielettömällä voimalla, ja ajoitus on täydellinen.|[[Roger Federer]]<ref>Nieminen, s. 106</ref>}}\r\n\r\nUran alkuaikoina silloinen Suomen Davis Cup -joukkueen valmentaja [[Olli Rahnasto]] piti Niemistä nopeana pelaajana, jolla on hyvä koordinaatio.<ref name=\"City\"/> Nykyinen Davis Cup -joukkueen valmentaja [[Kim Tiilikainen]] pitää Niemisen kahden käden rystylyöntiä yhtenä maailman parhaista.<ref>{{Verkkoviite | Osoite = http://www.mtv3.fi/urheilu/tennis/uutiset.shtml/2009/06/892446 | Nimeke = Kim Tiilikainen arvioi Suomen tennistoivot | Tekijä = Waheeb, Sebastian | Selite = Video | Julkaisu = MTV3.fi | Ajankohta = 4.6.2009 | Julkaisija = MTV Oy | Viitattu = 16.4.2010}}</ref>\r\n\r\n== Varusteet ja sponsorit ==\r\nNieminen pelasi [[Wilson Sporting Goods|Wilsonin]] mailoilla, kengillä ja vaatteilla.<ref>{{Verkkoviite | Osoite = http://www.jarkkonieminen.fi/news.php?id_news=1 | Nimeke = Jarkko will be playing \"head to toe\" with Wilson | Julkaisu = jarkkonieminen.fi | Ajankohta = 1.1.2009 | Julkaisija = Jarkko Nieminen Official Website | Viitattu = 23.8.2010 | Kieli = {{en}}}}</ref> Aikaisemmin hän käytti [[Asics]]in kenkiä ja vaatteita.<ref>{{Lehtiviite | Tekijä = Aitio, Tommi | Otsikko = Toisen viikon pelaaja | Julkaisu = Presso | Ajankohta = 6.1.2007 | Sivut = 14–16 | Julkaisija = Kauppalehti Oy | www = http://www.digipaper.fi/presso/2646/index.php?pgnumb=14 | Viitattu = 23.8.2010}}</ref> Niemisen pääsponsoreita olivat hissi- ja liukuporrasyhtiö [[Kone (yritys)|Kone]], elintarvikealan yritys [[Fazer]], tietoliikennealan yritys [[Nokia (yritys)|Nokia]], urheiluvälinevalmistaja Wilson ja tenniksen tukijärjestö Nordisk Sports Management. Lisäksi häntä sponsoroivat lentoyhtiö [[Finnair]] ja autovalmistaja [[Audi]].<ref>{{Verkkoviite | Osoite = http://www.jarkkonieminen.fi/partners.php | Nimeke = Enabling Jarkko's success | Julkaisu = jarkkonieminen.fi | Julkaisija = Jarkko Nieminen Official Website | Viitattu = 23.8.2010 | Kieli = {{en}}}}</ref>\r\n\r\n== Yksityiselämä ==\r\nNiemisen isä on Kauko ja äiti Leena.<ref name=\"ATP Profile\"/> Nieminen kirjoitti ylioppilaaksi [[Aurajoen lukio]]sta keväällä 2001.<ref name=\"City\"/> Uransa alkuaikoina hän seurusteli Neea Vilkkisen kanssa.<ref name=\"City\"/><ref>{{Verkkoviite | Osoite = http://www2.hs.fi/english/archive/news.asp?id=20020423IE6 | Nimeke = Tennis takes Jarkko Nieminen to all corners of the globe | Tekijä = Färdig, Jarmo | Julkaisu = HS.fi | Ajankohta = 23.4.2002 | Julkaisija = Sanoma News Oy | Viitattu = 17.3.2010 | Kieli = {{en}}}}</ref> Kesällä 2003 Nieminen aloitti seurustelun sulkapalloilija [[Anu Nieminen|Anu Weckströmin]] kanssa, jonka kanssa hän kihlautui saman vuoden joulukuussa. He menivät naimisiin kesäkuussa 2005 [[Temppeliaukion kirkko|Temppeliaukion kirkossa]].<ref>{{Verkkoviite | Osoite = http://www.iltasanomat.fi/viihde/Jarkko%20Nieminen%20ja%20Anu%20Weckstr%C3%B6m%20vihittiin/art-1288335495114.html | Nimeke = Jarkko Nieminen ja Anu Weckström vihittiin | Julkaisu = iltasanomat.fi | Ajankohta = 13.6.2005 | Julkaisija = Sanoma News Oy | Viitattu = 2.12.2009}}</ref> [[Varusmiespalvelus Suomessa|Varusmiespalveluksensa]] Nieminen aloitti marraskuussa 2007 ja suoritti sen puolessa vuodessa Lahden [[urheilukoulu]]ssa.<ref>{{Verkkoviite | Osoite = http://www.iltalehti.fi/urheilu/200711066808225_ur.shtml | Nimeke = Nöyrä alokas | Tekijä = Kunnari, Timo | Julkaisu = iltalehti.fi | Ajankohta = 6.11.2007 | Julkaisija = Kustannusosakeyhtiö Iltalehti | Viitattu = 2.12.2009}}</ref> [[Suomen puolustusvoimat|Puolustusvoimat]] valitsi Niemisen vuoden 2008 varusmiesurheilijaksi.<ref>{{Verkkoviite | Osoite = http://www.iltalehti.fi/urheilu/200901299002594_ur.shtml | Nimeke = Puolustusvoimat palkitsi Niemisen | Julkaisu = iltalehti.fi | Ajankohta = 29.1.2009 | Julkaisija = Kustannusosakeyhtiö Iltalehti | Viitattu = 2.12.2009}}</ref> Niemisen kustannusalalla toimiva isosisko [[Anna-Riikka Carlson]] kirjoitti veljensä kertomusten pohjalta kirjan ''Pelaamisen lumo'', joka julkaistiin 13. toukokuuta 2009.<ref>{{Verkkoviite | Osoite = http://plaza.fi/ellit/kulttuuri-ja-viihde/kulttuuri-kirjat/tyokaluna-tekstit-kohtalona-kirjat | Nimeke = Työkaluna tekstit, kohtalona kirjat | Tekijä = Parkkinen, Laura | Julkaisu = plaza.fi | Ajankohta = 2.3.2006 | Julkaisija = Plaza | Viitattu = 17.1.2010}}{{dead link|date=December 2016}}</ref><ref>{{Verkkoviite | Osoite = http://www.ess.fi/?article=237059 | Nimeke = Jarkko Niemiseltä ei nälkä lopu | Julkaisu = ess.fi | Ajankohta = 18.5.2009 | Julkaisija = Esan Kirjapaino Oy | Viitattu = 17.1.2010}}</ref><ref>{{Verkkoviite | Osoite = http://www.tennis.fi/sitenews/view/-/nid/8260/ngid/1/ | Nimeke = Niemisen kirja Pelaamisen lumo ilmestyi | Julkaisu = Tennisverkko | Ajankohta = 13.5.2009 | Julkaisija = Suomen Tennisliitto | Viitattu = 2.12.2009}}</ref>\r\n\r\nVuonna 2002 Nieminen perusti maskulaisen Jarkko Nieminen Oy:n.<ref>{{Verkkoviite | Osoite = http://www.kauppalehti.fi/yritykset/yritys/jarkko+nieminen+oy/17908496 | Nimeke = Jarkko Nieminen Oy | Julkaisu = kauppalehti.fi | Julkaisija = Kauppalehti Oy | Viitattu = 25.2.2010}}</ref> Nieminen kasvattaa ansaitsemillaan peli- ja sponsorituloilla yrityksen liikevaihtoa, joka ylitti viiden miljoonan rajan vuonna 2008.<ref>{{Verkkoviite | Osoite = http://www.kauppalehti.fi/5/i/talous/uutiset/avoinarkisto/index.jsp?xid=2486262&date=2007/08/01 | Nimeke = Jarkko Nieminen Oy löi 1,4 miljoonan liikevaihdon | Tekijä = Vieno, Niina | Julkaisu = kauppalehti.fi | Ajankohta = 1.8.2007 | Julkaisija = Kauppalehti Oy | Viitattu = 25.2.2010}}{{dead link|date=December 2016}}</ref><ref>{{Verkkoviite | Osoite = http://www.kauppalehti.fi/5/i/talous/uutiset/etusivu/uutinen.jsp?oid=2009/05/22083 | Nimeke = Jarkko Nieminen Oy ylitti maagisen rajan | Julkaisu = kauppalehti.fi | Ajankohta = 12.5.2009 | Julkaisija = Kauppalehti Oy | Viitattu = 25.2.2010}}{{dead link|date=December 2016}}</ref> Vuonna 2011 Nieminen osti 20 prosentin osuuden Nordisk Sports Managementista.<ref>{{Verkkoviite | Osoite = http://www.tennis.fi/sitenews/view/-/nid/10816/ngid/1/ | Nimeke = Jarkko Nieminen osakkaaksi Nordisk Sports Managementiin | Julkaisu = Tennisverkko | Ajankohta = 1.7.2011 | Julkaisija = Suomen Tennisliitto | Viitattu = 1.7.2011}}</ref> Nieminen aloitti kesällä 2012 yhdessä [[Veli Paloheimo]]n kanssa tennisakatemian nimeltä ''Jarkko Nieminen Tennisakatemia''.<ref>{{Verkkoviite | Osoite = http://yle.fi/urheilu/nieminen_ja_paloheimo_luovat_tennisakatemian/6090514 | Nimeke = Nieminen ja Paloheimo luovat tennisakatemian | Julkaisu = yle.fi | Ajankohta = 10.5.2012 | Julkaisija = Yleisradio Oy | Viitattu = 11.5.2012}}</ref> Syyskuussa 2015 Niemisestä tuli isä, kun Anu Nieminen synnytti tyttövauvan.<ref>{{Verkkoviite|nimeke = Jarkko ja Anu Niemisen perheeseen syntyi esikoinen|osoite = http://www.iltasanomat.fi/tennis/art-1442625602674.html|viitattu = 22.9.2015|julkaisu = iltasanomat.fi}}</ref>\r\n\r\n== Kunnianosoitukset ==\r\nJarkko Nieminen palkittiin urheilu-urastaan [[Suomen urheilugaala|Suomen Urheilugaalassa]] 2016.<ref> {{Verkkoviite | Osoite = http://www.suomenurheilugaala.fi/Urheilu-ura_______/| Nimeke = Voittajat | Julkaisija =Suomen Urheilugaala | Ajankohta = 12.1.2016 | Viitattu = 12.1.2016 }}{{dead link|date=December 2016}}</ref> Vuonna 2015 järjestetty ″Final Night″ -tapahtuma palkittiin vuoden urheilukulttuuritekona.<ref name=\":0\" />\r\n\r\n==Tilastot==\r\n\r\n===Loppuottelut kaksinpelissä===\r\n<ref name=\"ATP Profile\"/>\r\n====Voitot (2)====\r\n\r\n{| class=\"wikitable\" cellspacing=\"2\"\r\n|- style=\"background:#eee;\"\r\n|'''Nro'''\r\n|'''Pvm'''\r\n|'''Turnaus'''\r\n|'''Paikka'''\r\n|'''Kenttä'''\r\n|'''Vastustaja'''\r\n|'''Tulos'''\r\n|-\r\n| 1.\r\n| 9.1.2006\r\n| [[Heineken Open]]\r\n| [[Auckland]], [[Uusi-Seelanti]]\r\n| kova\r\n| {{Kroatian lippu}} [[Mario Ančić]]\r\n| 6–2, 6–2\r\n|- \r\n| 2.\r\n| 9.1.2012\r\n| [[Sydney International|Apia International Sydney]]\r\n| [[Sydney]], [[Australia]]\r\n| kova\r\n| {{Ranskan lippu}} [[Julien Benneteau]]\r\n| 6–2, 7–5\r\n|}\r\n\r\n====Tappiot (11)====\r\n\r\n{| class=\"wikitable\" cellspacing=\"2\"\r\n|- style=\"background:#eee;\"\r\n|'''Nro'''\r\n|'''Pvm'''\r\n|'''Turnaus'''\r\n|'''Paikka'''\r\n|'''Kenttä'''\r\n|'''Vastustaja'''\r\n|'''Tulos'''\r\n|-\r\n| 1.\r\n| 22.10.2001\r\n| [[Stockholm Open]]\r\n| [[Tukholma]], [[Ruotsi]]\r\n| kova\r\n| {{Alankomaiden lippu}} [[Sjeng Schalken]]\r\n| 6–3, 3–6, 3–6, 6–4, 3–6\r\n|-\r\n| 2.\r\n| 8.4.2002\r\n| [[Portugal Open|Estoril Open]]\r\n| [[Estoril]], [[Portugali]]\r\n| massa\r\n| {{Argentiinan lippu}} [[David Nalbandian]]\r\n| 4–6, 6–7(5)\r\n|-\r\n| 3.\r\n| 29.4.2002\r\n| [[Valencia Open 500|Valencia Open]]\r\n| [[Mallorca]], [[Espanja]]\r\n| massa\r\n| {{Argentiinan lippu}} [[Gastón Gaudio]]\r\n| 2–6, 3–6\r\n|-\r\n| 4.\r\n| 28.4.2003\r\n| [[BMW Open]]\r\n| [[München]], [[Saksa]]\r\n| massa\r\n| {{Sveitsin lippu}} [[Roger Federer]]\r\n| 1–6, 4–6\r\n|-\r\n| 5.\r\n| 9.10.2006\r\n| [[Stockholm Open]]\r\n| [[Tukholma]], [[Ruotsi]]\r\n| kova\r\n| {{Yhdysvaltain lippu}} [[James Blake]]\r\n| 4–6, 2–6\r\n|-\r\n| 6.\r\n| 22.10.2007\r\n| [[Swiss Indoors|Davidoff Swiss Indoors]]\r\n| [[Basel]], [[Sveitsi]]\r\n| kova\r\n| {{Sveitsin lippu}} [[Roger Federer]]\r\n| 3–6, 4–6\r\n|-\r\n| 7.\r\n| 31.12.2007\t\r\n| [[Brisbane International]]\r\n| [[Adelaide]], [[Australia]]\r\n| kova\r\n| {{Ranskan lippu}} [[Michaël Llodra]]\r\n| 3–6, 4–6\r\n|-\r\n| 8.\r\n| 12.1.2009\r\n| [[Sydney International|Medibank International]]\r\n| [[Sydney]], [[Australia]]\r\n| kova\r\n| {{Argentiinan lippu}} [[David Nalbandian]]\r\n| 3–6, 7–6(9), 2–6\r\n|-\r\n| 9.\r\n| 27.9.2010\r\n| [[Thailand Open]]\r\n| [[Bangkok]], [[Thaimaa]]\r\n| kova\r\n| {{Espanjan lippu}} [[Guillermo García-López]]\r\n| 4–6, 6–3, 4–6\r\n|-\r\n| 10.\r\n| 17.10.2011\r\n| [[Stockholm Open]]\r\n| [[Tukholma]], [[Ruotsi]]\r\n| kova\r\n| {{Ranskan lippu}} [[Gaël Monfils]]\r\n| 5–7, 6–3, 2–6\r\n|-\r\n| 11.\r\n| 20.5.2013\r\n| [[Power Horse Cup]]\r\n| [[Düsseldorf]], [[Saksa]]\r\n| massa\r\n| {{Argentiinan lippu}} [[Juan Mónaco]]\r\n| 4–6, 3–6\r\n|}\r\n\r\n===Loppuottelut nelinpelissä===\r\n<ref name=\"ATP Profile\"/>\r\n====Voitot (5)====\r\n\r\n{| class=\"wikitable\" cellspacing=\"2\"\r\n|- style=\"background:#eee;\"\r\n|'''Nro'''\r\n|'''Pvm'''\r\n|'''Turnaus'''\r\n|'''Paikka'''\r\n|'''Kenttä'''\r\n|'''Pari'''\r\n|'''Vastustaja'''\r\n|'''Tulos'''\r\n|-\r\n| 1.\r\n| 24.9.2007\r\n| [[Kingfisher Airlines Tennis Open]]\r\n| [[Mumbai]], [[Intia]]\r\n| kova\r\n| {{Ruotsin lippu}} [[Robert Lindstedt]]\r\n| {{Intian lippu}} [[Rohan Bopanna]]<br>{{Pakistanin lippu}} [[Aisam-ul-Haq Qureshi]]\r\n| 7–6(3), 7–6(5)\r\n|-\r\n| 2.\r\n| 25.7.2010\r\n| [[Sveitsin avoin tennisturnaus|Allianz Suisse Open Gstaad]]\r\n| [[Gstaad]], [[Sveitsi]]\r\n| massa\r\n| {{Ruotsin lippu}} [[Johan Brunström]]\r\n| {{Brasilian lippu}} [[Marcelo Melo]]<br>{{Brasilian lippu}} [[Bruno Soares]]\r\n| 6–3, 6–7(4), [11–9]\r\n|-\r\n| 3.\r\n| 5.5.2013\r\n| [[BMW Open]]\r\n| [[München]], [[Saksa]]\r\n| massa\r\n| {{Venäjän lippu}} [[Dmitri Tursunov]]\r\n| {{Kyproksen lippu}} [[Marcos Baghdatis]]<br>{{Yhdysvaltain lippu}} [[Eric Butorac]]\r\n| 6–1, 6–4\r\n|-\r\n| 4.\r\n| 2.8.2014\r\n| [[Austrian Open Kitzbühel]]\r\n| [[Kitzbühel]], [[Itävalta]]\r\n| massa\r\n| {{Suomen lippu}} [[Henri Kontinen]]\r\n| {{Italian lippu}} [[Daniele Bracciali]]<br>{{Kazakstanin lippu}} [[Andrey Golubev]]\r\n| 6–1, 6–4\r\n|-\r\n| 5.\r\n| 1.3.2015\r\n|[[ATP Buenos Aires|Argentina Open]]\r\n| [[Buenos Aires]], [[Argentiina]]\r\n| massa\r\n| {{Brasilian lippu}} [[André Sá]]\r\n| {{Espanjan lippu}} [[Pablo Andújar]]<br>{{Itävallan lippu}} [[Olivier Marach]]\r\n| 4–6, 6–4, [10–7]\r\n|}\r\n\r\n====Tappiot (4)====\r\n\r\n{| class=\"wikitable\" cellspacing=\"2\"\r\n|- style=\"background:#eee;\"\r\n|'''Nro'''\r\n|'''Pvm'''\r\n|'''Turnaus'''\r\n|'''Paikka'''\r\n|'''Kenttä'''\r\n|'''Pari'''\r\n|'''Vastustaja'''\r\n|'''Tulos'''\r\n|-\r\n| 1.\r\n| 22.9.2003\r\n| [[Thailand Open]]\r\n| [[Bangkok]], [[Thaimaa]]\r\n| kova\r\n| {{Australian lippu}} [[Andrew Kratzmann]]\r\n| {{Israelin lippu}} [[Jonathan Erlich]]<br>{{Israelin lippu}} [[Andy Ram]]\r\n| 3–6, 6–7(4)\r\n|-\r\n| 2.\r\n| 9.2.2009\r\n| [[SAP Open]]\r\n| [[San José (Kalifornia)|San José]], [[Yhdysvallat]]\r\n| kova\r\n| {{Intian lippu}} [[Rohan Bopanna]]\r\n| {{Saksan lippu}} [[Tommy Haas]]<br>{{Tšekin lippu}} [[Radek Štěpánek]]\r\n| 2–6, 3–6\r\n|-\r\n| 3.\r\n| 18.10.2010\r\n| [[Stockholm Open]]\r\n| [[Tukholma]], [[Ruotsi]]\r\n| kova\r\n| {{Ruotsin lippu}} [[Johan Brunström]]\r\n| {{Yhdysvaltain lippu}} [[Eric Butorac]]<br>{{Curaçaon lippu}} [[Jean-Julien Rojer]]\r\n| 3–6, 4–6\r\n|-\r\n| 4.\r\n| 9.1.2012\r\n| [[Sydney International|Apia International Sydney]]\r\n| [[Sydney]], [[Australia]]\r\n| kova\r\n| {{Australian lippu}} [[Matthew Ebden]]\r\n| {{Yhdysvaltain lippu}} [[Bob Bryan]]<br>{{Yhdysvaltain lippu}} [[Mike Bryan]]\r\n| 1–6, 4–6\r\n|}\r\n\r\n===Kaksinpelimenestys vuosittain===\r\n<ref name=\"ATP Profile\"/>\r\n{| class=\"wikitable\" cellspacing=\"2\"\r\n|- style=\"background:#eee;\"\r\n! Turnaus !!2001!!2002!!2003!!2004!!2005!!2006!!2007!!2008!!2009!!2010!!2011!!2012!!2013!!2014\r\n!2015\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| '''[[Australian avoin tennisturnaus|Australian avoimet]]''' || – || 1. kierros || 3. kierros || 2. kierros || 3. kierros || 3. kierros || 2. kierros || puolivälierät || 1. kierros || 2. kierros || 1. kierros || 1. kierros || 2. kierros || 2. kierros\r\n|3. kierros\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| '''[[Ranskan avoin tennisturnaus|Ranskan avoimet]]''' || – || 3. kierros || 4. kierros || – || 2. kierros || 1. kierros || 3. kierros || 3. kierros || – || 1. kierros || 1. kierros || 2. kierros || 2. kierros || 2. kierros\r\n|1. kierros\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| '''[[Wimbledonin tennisturnaus|Wimbledon]]''' || – || 2. kierros || 3. kierros || – || 1. kierros || puolivälierät || 3. kierros || 2. kierros || – || 2. kierros || 1. kierros || 2. kierros || 1. kierros || 2. kierros\r\n|2. kierros\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| '''[[Yhdysvaltain avoin tennisturnaus|Yhdysvaltain avoimet]]''' || – || 1. kierros || 2. kierros || 1. kierros || puolivälierät || 1. kierros || 1. kierros || 3. kierros || 2. kierros || 1. kierros || 1. kierros || 2. kierros || 2. kierros || 1. kierros\r\n|1. kierros \r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Indian Wells Masters]] || – || – || 1. kierros || 2. kierros || 2. kierros || puolivälierät || 3. kierros || 2. kierros || 2. kierros || – || 2. kierros || 1. kierros || 3. kierros || 3. kierros\r\n|2. kierros\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Miami Masters]] || – || 2. kierros || 3. kierros || 2. kierros || 2. kierros || 3. kierros || 4. kierros || 2. kierros || 2. kierros || – || 1. kierros || 1. kierros || 3. kierros || 2. kierros\r\n|2. kierros\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Monte Carlo Masters]] || – || – || 3. kierros || 2. kierros || – || 1. kierros || 1. kierros || 2. kierros || – || 1. kierros || 2. kierros || 2. kierros || puolivälierät || 1. kierros\r\n|–\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Madrid Open (tennis)|Madrid Masters]] || – || 2. kierros || 1. kierros || – || – || 1. kierros || 1. kierros || 2. kierros || – || – || – || – || – || 3. kierros\r\n|–\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Italian avoin tennisturnaus|Rome Masters]] || – || – || 3. kierros || – || – || 2. kierros || 1. kierros || 1. kierros || – || – || 3. kierros || 1. kierros || 1. kierros || –\r\n|–\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Kanadan avoin tennisturnaus|Canada Masters]] || – || 2. kierros || 1. kierros || – || – || puolivälierät || 2. kierros || 1. kierros || – || 1. kierros || 1. kierros || – || 1. kierros || –\r\n|–\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Cincinnati Masters]] || – || 3. kierros || 2. kierros || – || – || 1. kierros || 3. kierros || 1. kierros || – || – || – || 1. kierros || 2. kierros || –\r\n|–\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Shanghain Masters (tennis)|Shanghai Masters]] || colspan=\"8\" | <small>Ei järjestetty</small> || – || – || – || 1. kierros || 1. kierros ||–\r\n|–\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Paris Masters]] || – || 2. kierros || 1. kierros || – || 1. kierros || puolivälierät || 2. kierros || 1. kierros || – || 2. kierros || – || – || 1. kierros ||–\r\n|–\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| [[Saksan avoin tennisturnaus (miesten turnaus)|Hamburg Masters]] || – || – || 2. kierros || – || – || 3. kierros || 3. kierros || 2. kierros || colspan=\"5\" | <small>Ei enää Masters-turnaus</small>\r\n|- style=\"background:#efefef; text-align:center;\"\r\n| style=\"text-align:left;\"| '''ATP-turnausvoitot''' || – || – || – || – || – || 1 || – || – || – || – || – || 1 || – ||–\r\n|–\r\n|- style=\"background:#efefef; text-align:center;\"\r\n| style=\"text-align:left;\"| '''ATP-loppuottelutappiot''' || 1 || 2 || 1 || – || – || 1 || 1 || 1 || 1 || 1 || 1 || – || 1 ||–\r\n|–\r\n|- style=\"background:#efefef; text-align:center;\"\r\n| style=\"text-align:left;\"| '''ATP-välierätappiot''' || – || – || 2 || 3 || 4 || 3 || 2 || 1 || – || 2 || – || – || 1 || 2\r\n|–\r\n|- style=\"background:#efefef; text-align:center;\"\r\n| style=\"text-align:left;\"| '''ATP-haastajaturnausvoitot''' || 4 || 2 || – || – || 1 || – || – || – || 1 || 1 || – || – || 1 ||–\r\n|–\r\n|- style=\"background:#efefef; text-align:center;\"\r\n| style=\"text-align:left;\"| '''Kauden päätösranking''' || 61 || 40 || 36 || 77 || 28 || 15 || 27 || 37 || 88 || 39 || 77 || 41 || 39 ||73\r\n|153\r\n|}\r\n\r\n===Nelinpelimenestys vuosittain===\r\n<ref name=\"ATP Profile\"/>\r\n{| class=\"wikitable\" cellspacing=\"2\"\r\n|- style=\"background:#eee;\"\r\n! Turnaus !!2001!!2002!!2003!!2004!!2005!!2006!!2007!!2008!!2009!!2010!!2011!!2012!!2013!!2014\r\n!2015\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| '''[[Australian avoin tennisturnaus|Australian avoimet]]''' || – || – || 1. kierros || – || 2. kierros || 2. kierros || 1. kierros || 2. kierros || 2. kierros || välierät || 2. kierros || 1. kierros || 2. kierros || 2. kierros\r\n|1. kierros\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| '''[[Ranskan avoin tennisturnaus|Ranskan avoimet]]''' || – || – || 2. kierros || – || – || 1. kierros || 1. kierros || 2. kierros || – || 1. kierros || 1. kierros || 1. kierros || – || 2. kierros\r\n|1. kierros\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| '''[[Wimbledonin tennisturnaus|Wimbledon]]''' || – || – || 1. kierros || – || – || 1. kierros || 2. kierros || – || – || 1. kierros || 1. kierros || 1. kierros || 1. kierros || 1. kierros\r\n|–\r\n|- style=\"text-align:center;\"\r\n| style=\"text-align:left;\"| '''[[Yhdysvaltain avoin tennisturnaus|Yhdysvaltain avoimet]]''' || – || – || – || – || 1. kierros || 3. kierros || 2. kierros || puolivälierät || 2. kierros || 2. kierros || 1. kierros || 1. kierros || 1. kierros || 1. kierros\r\n|–\r\n|- style=\"background:#efefef; text-align:center;\"\r\n| style=\"text-align:left;\"| '''ATP-turnausvoitot''' || – || – || – || – || – || – || 1 || – || – || 1 || – || – || 1 || 1\r\n|1\r\n|- style=\"background:#efefef; text-align:center;\"\r\n| style=\"text-align:left;\"| '''ATP-loppuottelutappiot''' || – || – || 1 || – || – || – || – || – || 1 || 1 || – || 1 || – ||–\r\n|–\r\n|- style=\"background:#efefef; text-align:center;\"\r\n| style=\"text-align:left;\"| '''Kauden päätösranking''' || 356 || 187 || 60 || 119 || 204 || 56 || 46 || 80 || 128 || 48 || 154 || 165 || 100 ||83\r\n|278\r\n|}\r\n\r\n==Lähteet==\r\n* {{ATP}}\r\n* {{Kirjaviite | Tekijä = Nieminen, Jarkko | Nimeke = Pelaamisen lumo | Vuosi = 2009 | Julkaisija = Avain | Tunniste = ISBN 978-952-5524-69-7}}\r\n===Viitteet===\r\n{{Viitteet|fontti|sarakkeet}}\r\n\r\n==Aiheesta muualla==\r\n{{Commonscat}}\r\n*[http://www.jarkkonieminen.fi/ Jarkko Niemisen kotisivut]\r\n*[http://www.yle.fi/elavaarkisto/?s=s&g=3&ag=19&t=&a=2895 YLE/Elävä arkisto: Kaksi erää Jarkko Niemistä]\r\n*[http://yle.fi/urheilu/maila_pallo_ja_jarkko__30_vuotta_yhteista_taivalta/8428155 Maila, pallo ja Jarkko – 30 vuotta yhteistä taivalta]\r\n\r\n{{Metatieto}}\r\n\r\n{{AAKKOSTUS:Nieminen, Jarkko}}\r\n\r\n[[Luokka:Suomalaiset tennispelaajat]]\r\n[[Luokka:Vuonna 1981 syntyneet]]\r\n[[Luokka:Elävät henkilöt]]\r\n[[Luokka:Seulonnan keskeiset artikkelit]]\r\n[[Luokka:Suomalaiset salibandyn pelaajat]]\r\n\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpSummary\"\r\n\r\nRepairing 5 and tagging 37 external links using [[WP:CHECKLINKS|Checklinks]]\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpWatchthis\"\r\n\r\n1\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpSave\"\r\n\r\nTallenna muutokset\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpTemplateSandboxTemplate\"\r\n\r\nJarkko Nieminen\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpTemplateSandboxPage\"\r\n\r\n\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpEditToken\"\r\n\r\n20813a2955420124481f7e052c7991165866a887+\\\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"mode\"\r\n\r\npreview\r\n-----------------------------324082132622671\r\nContent-Disposition: form-data; name=\"wpUltimateParam\"\r\n\r\n1\r\n-----------------------------324082132622671--\r\n"
"text": "location.search.indexOf(\"printable=yes\")==-1&&$(function($){var translate={'en':{notfound:\"Wikidata-kohdetta ei löydy.\",intro:\"Wikidata: \",nolabel:\"(ei nimeä)\",nodescription:\"kuvausta ei lisätty\",aliases:\"Aliakset: \",noaliases:\"ei ole\"}};var namespace=mw.config.get('wgNamespaceNumber'),lang=mw.config.get('wgContentLanguage'),page=(namespace-=(namespace>0&&namespace%2))===0?mw.config.get('wgTitle'):mw.config.get('wgFormattedNamespaces')[namespace]+':'+mw.config.get('wgTitle');namespace!==2&&namespace!==-1&&$.ajax({url:'//www.wikidata.org/w/api.php',data:{'format':'json','action':'wbgetentities','sites':mw.config.get('wgDBname'),'titles':page,'props':'info|labels|descriptions|aliases','languages':lang,'maxage':mw.config.get(\"wgUserName\")==null?900:30,'smaxage':mw.config.get(\"wgUserName\")==null?900:30,'maxlag':1},dataType:'jsonp',success:function(data){if(data.success){var $d=$(\"<div>\").addClass(\"WDI-box\").appendTo(\"#contentSub\"),m=translate[mw.config.get('wgUserLanguage')]||translate.\nen;mw.messages.set(\"WDI-aliases\",m.aliases);for(var i in data.entities){if(i==-1){$d.append($(\"<a>\").attr(\"href\",\"//www.wikidata.org/wiki/Special:CreateItem?site=\"+mw.config.get(\"wgDBname\")+\"&page=\"+encodeURIComponent(page)+\"&label=\"+encodeURIComponent(page)).text(m.notfound));}else{var item=data.entities[i],i=0,aliases=[],label=item.labels[lang]&&item.labels[lang].value,description=item.descriptions[lang]&&item.descriptions[lang].value;try{for(;i<item.aliases[lang].length;i++){aliases.push(item.aliases[lang][i].value);}}catch(e){}if(window.WDIlimitaliases&&WDIlimitaliases<aliases.length){for(;WDIlimitaliases<aliases.length;aliases.pop());aliases.push(\"...\");}$d.append($(\"<a>\").attr(\"href\",\"//www.wikidata.org/wiki/\"+item.title).text(m.intro+(label||m.nolabel)),\" (\",$(\"<a>\").attr(\"href\",\"//www.wikidata.org/wiki/\"+item.title).text(item.title),\")\",$(\"<span>\").text(\", \"),$(\"<i>\").text(description||m.nodescription).addClass(description?\"WDI-desc\":\"WDI-desc WDI-nodesc\"),$(\"<br>\"),$(\"<span>\")\n.text(mw.msg(\"WDI-aliases\",aliases.length)+(aliases.join(\", \")||m.noaliases)));}}}}});});var conf=mw.config.get('wgDBname');if(['fiwiki','enwiki','wikidatawiki','metawiki'].indexOf(conf)==-1){mw.loader.load('//meta.wikimedia.org/w/index.php?title=User:Snowolf/GS_delete.js&action=raw&ctype=text/javascript');mw.loader.load('//tools-static.wmflabs.org/meta/scripts/pathoschild.forceltr.js');mw.loader.load('//meta.wikimedia.org/w/index.php?title=User:Hoo_man/active_sysops.js&action=raw&ctype=text/javascript');mw.loader.load('//meta.wikimedia.org/w/index.php?title=User:Hoo_man/tagger.js&action=raw&ctype=text/javascript');if(typeof(taggerConfig)=='undefined')taggerConfig={};taggerConfig.tags=[];taggerConfig.editSummary=[];taggerConfig.tags[1]='{{delete|test}}';taggerConfig.editSummary[taggerConfig.tags[1]]='delete';taggerConfig.tags[2]='{{delete|spam}}';taggerConfig.editSummary[taggerConfig.tags[2]]='delete';taggerConfig.tags[3]='{{delete|vandalism}}';taggerConfig.editSummary[taggerConfig.\ntags[3]]='delete';taggerConfig.tags[4]='{{delete|no useful content}}';taggerConfig.editSummary[taggerConfig.tags[4]]='delete';taggerConfig.tags[5]='{{delete|blanked by the author}}';taggerConfig.editSummary[taggerConfig.tags[5]]='delete';taggerConfig.tags[6]='{{delete|wrong language}}';taggerConfig.editSummary[taggerConfig.tags[6]]='delete';taggerConfig.tags[7]='{{delete|out of project scope}}';taggerConfig.editSummary[taggerConfig.tags[7]]='delete';taggerConfig.tags[8]='{{speedy}}';taggerConfig.editSummary[taggerConfig.tags[8]]='delete';taggerConfig.tags.other='This is used for the option you have to select to be able to insert a custom template';}mw.loader.using(['mediawiki.api.options','user.options'],function(){if(mw.user.options.get('visualeditor-hidebetawelcome')===0){new mw.Api().saveOption('visualeditor-hidebetawelcome','1');mw.user.options.set('visualeditor-hidebetawelcome','1');}});mw.loader.state({\"ext.globalCssJs.user\":\"ready\"});"
"text": "// <nowiki>\n\n/*\n HotCat V2.34\n\n Ajax-based simple Category manager. Allows adding/removing/changing categories on a page view.\n Supports multiple category changes, as well as redirect and disambiguation resolution. Also\n plugs into the upload form. Search engines to use for the suggestion list are configurable, and\n can be selected interactively.\n\n Documentation: https://commons.wikimedia.org/wiki/Help:Gadget-HotCat\n List of main authors: https://commons.wikimedia.org/wiki/Help:Gadget-HotCat/Version_history\n\n License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0)\n\n Choose whichever license of these you like best :-)\n*/\n\n/*\n This code is MW version safe. It should run on any MediaWiki installation >= MW 1.15. Note\n that HotCat is supposed to run with or without jQuery, and also on older installations that\n do not yet have window.mw. If you use any of these newer features, make sure you qualify them\n by checking whether they exist at all, and by providing some meaningful fallback implementation\n if not. To start itself, HotCat uses jQuery(document).ready(). If it doesn't exist, HotCat won't\n start.\n*/\n/* jshint ignore:start */ // This old code uses too many coding conventions incompatible with jshint.\n(function () {\n\t// Support: MW 1.16\n\tvar conf = window.mw ? mw.config.get() : window;\n\n\tif (\n\t\t// Guard against double inclusions (in old IE/Opera element ids become window properties)\n\t\t(window.HotCat && !window.HotCat.nodeName)\n\t\t// Not on edit pages\n\t\t|| conf.wgAction == 'edit'\n\n\t) {\n\t\treturn;\n\t}\n\n// Configuration stuff.\nwindow.HotCat = {\n\t// Localize these messages to the main language of your wiki.\n\tmessages :\n\t{cat_removed : 'removed [[Category:$1]]'\n\t,template_removed : 'removed {{[[Category:$1]]}}'\n\t,cat_added : 'added [[Category:$1]]'\n\t,cat_keychange: 'new key for [[Category:$1]]: \"$2\"' // $2 is the new key\n\t,cat_notFound : 'Category \"$1\" not found'\n\t,cat_exists : 'Category \"$1\" already exists; not added.'\n\t,cat_resolved : ' (redirect [[Category:$1]] resolved)'\n\t,uncat_removed: 'removed {{uncategorized}}'\n\t,separator : '; '\n\t,prefix : \"\"\n\t\t// Some text to prefix to the edit summary.\n\t,using : ' using [[Help:Gadget-HotCat|HotCat]]'\n\t\t// Some text to append to the edit summary. Named 'using' for historical reasons. If you prefer\n\t\t// to have a marker at the front, use prefix and set this to the empty string.\n\t,multi_change : '$1 categories'\n\t\t// $1 is replaced by a number. If your language has several plural forms (c.f. [[:en:Dual (grammatical form)]]),\n\t\t// you can set this to an array of strings suitable for passing to mw.language.configPlural().\n\t\t// If that function doesn't exist, HotCat will simply fall back to using the last\n\t\t// entry in the array.\n\t,commit : 'Save'\n\t\t// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage,\n\t\t// see localization hook below.\n\t,ok : 'OK'\n\t\t// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage,\n\t\t// see localization hook below.\n\t,cancel : 'Cancel'\n\t\t// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage,\n\t\t// see localization hook below.\n\t,multi_error : 'Could not retrieve the page text from the server. Therefore, your category changes '\n\t\t\t\t\t+'cannot be saved. We apologize for the inconvenience.'\n\t\t// Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage,\n\t\t// see localization hook below.\n\t,short_catchange : null\n\t\t// Defaults to '[[' + category_canonical + ':$1]]'. Can be overridden if in the short edit summaries\n\t\t// not the standard category name should be used but, say, a shorter namespace alias. $1 is replaced\n\t\t// by a category name.\n\t}\n ,category_regexp : '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]'\n\t// Regular sub-expression matching all possible names for the category namespace. Is automatically localized\n\t// correctly if you're running MediaWiki 1.16 or later. Otherwise, set it appropriately, e.g. at the German\n\t// Wikipedia, use '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]|[Kk][Aa][Tt][Ee][Gg][Oo][Rr][Ii][Ee]', or at the\n\t// Chinese Wikipedia, use '[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]|分类|分類'. Note that namespaces are case-\n\t// insensitive!\n ,category_canonical : 'Category'\n\t// The standard category name on your wiki. Is automatically localized correctly if you're running\n\t// MediaWiki 1.16 or later; otherwise, set it to the preferred category name (e.g., \"Kategorie\").\n ,categories : 'Categories'\n\t// Plural of category_canonical.\n ,disambig_category : 'Disambiguation'\n\t// Any category in this category is deemed a disambiguation category; i.e., a category that should not contain\n\t// any items, but that contains links to other categories where stuff should be categorized. If you don't have\n\t// that concept on your wiki, set it to null. Use blanks, not underscores.\n ,redir_category : 'Category redirects'\n\t// Any category in this category is deemed a (soft) redirect to some other category defined by a link\n\t// to another non-blacklisted category. If your wiki doesn't have soft category redirects, set this to null.\n // If a soft-redirected category contains more than one link to another non-blacklisted category, it's considered\n // a disambiguation category instead.\n ,links : {change: '(±)', remove: '(\\u2212)', add: '(+)', restore: '(×)', undo: '(×)', down: '(\\u2193)', up: '(\\u2191)'}\n\t// The little modification links displayed after category names. U+2212 is a minus sign; U+2193 and U+2191 are\n\t// downward and upward pointing arrows. Do not use ↓ and ↑ in the code!\n ,tooltips : {\n\t change: 'Modify'\n\t,remove: 'Remove'\n\t,add: 'Add a new category'\n\t,restore: 'Undo changes'\n\t,undo: 'Undo changes'\n\t,down: 'Open for modifying and display subcategories'\n\t,up: 'Open for modifying and display parent categories'\n }\n\t// The tooltips for the above links\n ,addmulti : '<span>+<sup>+</sup></span>'\n\t// The HTML content of the \"enter multi-mode\" link at the front.\n ,multi_tooltip : 'Modify several categories'\n\t// Tooltip for the \"enter multi-mode\" link\n ,disable :\n\t\tfunction () { // Return true to disable HotCat.\n\t\t\tvar ns = conf.wgNamespaceNumber;\n\t\t\tvar nsIds = conf.wgNamespaceIds;\n\t\t\treturn ( ns < 0 // Special pages; Special:Upload is handled differently\n\t\t\t\t\t|| ns === 10 // Templates\n\t\t\t\t\t|| ns === 828 // Module (Lua)\n\t\t\t\t\t|| ns === 8 // MediaWiki\n\t\t\t\t\t|| ns === 6 && conf.wgArticleId === 0 // Non-existing file pages\n\t\t\t\t\t|| ns === 2 && /\\.(js|css)$/.test(conf.wgTitle) // User scripts\n\t\t\t\t\t|| nsIds\n\t\t\t\t\t\t&& ( ns === nsIds['creator']\n\t\t\t\t\t\t\t|| ns === nsIds['timedtext']\n\t\t\t\t\t\t\t|| ns === nsIds['institution']\n\t\t\t\t\t\t )\n\t\t\t\t );\n\t\t}\n ,uncat_regexp : /\\{\\{\\s*([Uu]ncat(egori[sz]ed( image)?)?|[Nn]ocat|[Nn]eedscategory)[^}]*\\}\\}\\s*(<\\!--.*?--\\>)?/g\n\t// A regexp matching a templates used to mark uncategorized pages, if your wiki does have that.\n\t// If not, set it to null.\n ,existsYes : '//upload.wikimedia.org/wikipedia/commons/thumb/b/be/P_yes.svg/20px-P_yes.svg.png'\n ,existsNo : '//upload.wikimedia.org/wikipedia/commons/thumb/4/42/P_no.svg/20px-P_no.svg.png'\n\t// The images used for the little indication icon. Should not need changing.\n ,template_regexp : '[Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee]'\n\t// Regexp to recognize templates. Like \"category\" above; autolocalized for MW 1.16+, otherwise set manually here.\n\t// On the German Wikipedia, you might use '[Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee]|[Vv][Oo][Rr][Ll][Aa][Gg][Ee]'.\n ,template_categories : {}\n\t// a list of categories which can be removed by removing a template\n\t// key: the category without namespace\n\t// value: A regexp matching the template name, again without namespace\n\t// If you don't have this at your wiki, or don't want this, set it to an empty object {}.\n ,engine_names : {\n\t searchindex : 'Search index'\n\t,pagelist : 'Page list'\n\t,combined : 'Combined search'\n\t,subcat : 'Subcategories'\n\t,parentcat : 'Parent categories'\n }\n\t// Names for the search engines\n ,capitalizePageNames : true\n\t// Set to false if your wiki has case-sensitive page names. MediaWiki has two modes: either the first letter\n\t// of a page is automatically capitalized (\"first-letter\"; Category:aa == Category:Aa), or it isn't\n\t// (\"case-sensitive\"; Category:aa != Category:Aa). It doesn't currently have a fully case-insensitive mode\n\t// (which would mean Category:aa == Category:Aa == Category:AA == Category:aA)\n\t// HotCat tries to set this correctly automatically using an API query. It's still a good idea to manually\n\t// configure it correctly; either directly here if you copied HotCat, or in the local configuration file\n\t// MediaWiki:Gadget-HotCat.js/local_defaults if you hotlink to the Commons-version, to ensure it is set even\n\t// if that API query should fail for some strange reason.\n ,upload_disabled : false\n\t// If upload_disabled is true, HotCat will not be used on the Upload form.\n ,blacklist : null\n\t// Single regular expression matching blacklisted categories that cannot be changed or\n\t// added using HotCat. For instance /\\bstubs?$/ (any category ending with the word \"stub\"\n\t// or \"stubs\"), or /(\\bstubs?$)|\\bmaintenance\\b/ (stub categories and any category with the\n\t// word \"maintenance\" in its title.\n\n// Stuff changeable by users:\n ,bg_changed : '#F8CCB0'\n\t// Background for changed categories in multi-edit mode. Default is a very light salmon pink.\n ,no_autocommit : false\n\t// If true, HotCat will never automatically submit changes. HotCat will only open an edit page with\n\t// the changes; users must always save explicitly.\n ,del_needs_diff : false\n\t// If true, the \"category deletion\" link \"(-)\" will never save automatically but always show an\n\t// edit page where the user has to save the edit manually. Is false by default because that's the\n\t// traditional behavior. This setting overrides no_autocommit for \"(-)\" links.\n ,suggest_delay : 100\n\t// Time, in milliseconds, that HotCat waits after a keystroke before making a request to the\n\t// server to get suggestions.\n ,editbox_width : 40\n\t// Default width, in characters, of the text input field.\n ,suggestions : 'combined'\n\t// One of the engine_names above, to be used as the default suggestion engine.\n ,fixed_search : false\n\t// If true, always use the default engine, and never display a selector.\n ,use_up_down : true\n\t// If false, do not display the \"up\" and \"down\" links\n ,list_size : 5\n\t// Default list size\n ,single_minor : true\n\t// If true, single category changes are marked as minor edits. If false, they're not.\n ,dont_add_to_watchlist : false\n\t// If true, never add a page to the user's watchlist. If false, pages get added to the watchlist if\n\t// the user has the \"Add pages I edit to my watchlist\" or the \"Add pages I create to my watchlist\"\n\t// options in his or her preferences set.\n ,shortcuts : null\n ,addShortcuts :\n\t\tfunction (map) {\n\t\t\tif (!map) return;\n\t\t\twindow.HotCat.shortcuts = window.HotCat.shortcuts || {};\n\t\t\tfor (var k in map) {\n\t\t\t\tif (!map.hasOwnProperty (k) || typeof k != 'string') continue;\n\t\t\t\tvar v = map[k];\n\t\t\t\tif (typeof v != 'string') continue;\n\t\t\t\tk = k.replace (/^\\s+|\\s+$/g, \"\");\n\t\t\t\tv = v.replace (/^\\s+|\\s+$/g, \"\");\n\t\t\t\tif (k.length === 0 || v.length === 0) continue;\n\t\t\t\twindow.HotCat.shortcuts[k] = v;\n\t\t\t}\n\t\t}\n};\n\n\t// More backwards compatibility. We have a few places where we test for the browser: once for\n\t// Safari < 3.0, twice for WebKit (Chrome or Safari, any versions), twice for IE <= 6, and\n\t// once for IE < 8.\n\tvar ua = navigator.userAgent.toLowerCase();\n\tvar is_ie6 = /msie ([0-9]{1,}[\\.0-9]{0,})/.exec(ua) !== null && parseFloat(RegExp.$1) <= 6.0;\n\tvar is_ie_lt8 = /msie ([0-9]{1,}[\\.0-9]{0,})/.exec(ua) !== null && parseFloat(RegExp.$1) < 8.0;\n\tvar is_webkit = /applewebkit\\/\\d+/.test(ua) && ua.indexOf ('spoofer') < 0;\n\t// And even more compatbility. HotCat was developed without jQuery, and anyway current jQuery\n\t// (1.7.1) doesn't seem to support in jquery.getJSON() or jQuery.ajax() the automatic\n\t// switching from GET to POST requests if the query arguments would make the uri too long.\n\t// (IE has a hard limit of 2083 bytes, and the servers may have limits around 4 or 8kB.)\n\t// Anyway, HotCat is supposed to run on wikis without jQuery, so we'd have to supply some\n\t// ajax routines ourselves in any case. We can't rely on the old sajax_init_object(), newer\n\t// MW versions (>= 1.19) might not have it.\n\tvar getJSON = (function () {\n\t\tfunction getRequest () {\n\t\t\tvar request = null;\n\t\t\ttry {\n\t\t\t\trequest = new window.XMLHttpRequest();\n\t\t\t} catch (anything) {\n\t\t\t\tif (window.ActiveXObject) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\trequest = new window.ActiveXObject('Microsoft.XMLHTTP');\n\t\t\t\t\t} catch (any) {\n\t\t\t\t\t}\n\t\t\t\t} // end if IE\n\t\t\t} // end try-catch\n\t\t\treturn request;\n\t\t}\n\n\t\treturn function (settings) {\n\t\t\tvar req = getRequest();\n\t\t\tif (!req && settings && settings.error) settings.error (req);\n\t\t\tif (!req || !settings || !settings.uri) return req;\n\t\t\tvar uri = armorUri (settings.uri);\n\t\t\tvar args = settings.data || null;\n\t\t\tvar method;\n\t\t\tif (args && uri.length + args.length + 1 > 2000) {\n\t\t\t\t// We lose caching, but at least we can make the request\n\t\t\t\tmethod = 'POST';\n\t\t\t\treq.setRequestHeader ('Content-Type', 'application/x-www-form-urlencoded');\n\t\t\t} else {\n\t\t\t\tmethod = 'GET';\n\t\t\t\tif (args) uri += '?' + args;\n\t\t\t\targs = null;\n\t\t\t}\n\t\t\treq.open (method, uri, true);\n\t\t\treq.onreadystatechange = function () {\n\t\t\t\tif (req.readyState != 4) return;\n\t\t\t\tif (req.status != 200 || !req.responseText || !(/^\\s*[\\{\\[]/.test(req.responseText))) {\n\t\t\t\t\tif (settings.error) settings.error (req);\n\t\t\t\t} else {\n\t\t\t\t\tif (settings.success) settings.success (eval ('(' + req.responseText + ')'));\n\t\t\t\t}\n\t\t\t};\n\t\t\treq.setRequestHeader ('Pragma', 'cache=yes');\n\t\t\treq.setRequestHeader ('Cache-Control', 'no-transform');\n\t\t\treq.send (args);\n\t\t\treturn req;\n\t\t};\n\t})();\n\n\tfunction armorUri (uri) {\n\t\t// Avoid protocol-relative URIs, IE7 has a bug with them in Ajax calls\n\t\tif (uri.length >= 2 && uri.substring(0, 2) == '//') return document.location.protocol + uri;\n\t\treturn uri;\n\t}\n\n\tfunction LoadTrigger (needed) {\n\t\tthis.queue = [];\n\t\tthis.toLoad = needed;\n\t}\n\tLoadTrigger.prototype = {\n\t\tregister : function (callback) {\n\t\t\tif (this.toLoad <= 0) {\n\t\t\t\tcallback (); // Execute directly\n\t\t\t} else {\n\t\t\t\tthis.queue[this.queue.length] = callback;\n\t\t\t}\n\t\t},\n\n\t\tloaded : function () {\n\t\t\tif (this.toLoad > 0) {\n\t\t\t\tthis.toLoad--;\n\t\t\t\tif (this.toLoad === 0) {\n\t\t\t\t\t// Run queued callbacks once\n\t\t\t\t\tfor (var i = 0; i < this.queue.length; i++) this.queue[i]();\n\t\t\t\t\tthis.queue = [];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t};\n\n\tvar setupCompleted = new LoadTrigger(1);\n\t// Used to run user-registered code once HotCat is fully set up and ready.\n\tHotCat.runWhenReady = function (callback) {setupCompleted.register(callback);};\n\n\tvar loadTrigger = new LoadTrigger(2);\n\t// Used to delay running the HotCat setup until /local_defaults and localizations have been loaded.\n\n\tfunction load (uri) {\n\t\tvar head = document.getElementsByTagName ('head')[0];\n\t\tvar s = document.createElement ('script');\n\t\ts.setAttribute ('src', armorUri(uri));\n\t\ts.setAttribute ('type', 'text/javascript');\n\t\tvar done = false;\n\n\t\tfunction afterLoad () {\n\t\t\tif (done) return;\n\t\t\tdone = true;\n\t\t\ts.onload = s.onreadystatechange = s.onerror = null; // Properly clean up to avoid memory leaks in IE\n\t\t\tif (head && s.parentNode) head.removeChild (s);\n\t\t\tloadTrigger.loaded();\n\t\t}\n\n\t\ts.onload = s.onreadystatechange = function () { // onreadystatechange for IE, onload for all others\n\t\t\tif (done) return;\n\t\t\tif (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {\n\t\t\t\tafterLoad ();\n\t\t\t}\n\t\t};\n\t\ts.onerror = afterLoad; // Clean up, but otherwise ignore errors\n\t\thead.insertBefore (s, head.firstChild); // appendChild may trigger bugs in IE6 here\n\t}\n\n\tfunction loadJS (page) {\n\t\tload (conf.wgServer + conf.wgScript + '?title=' + encodeURIComponent (page) + '&action=raw&ctype=text/javascript');\n\t}\n\n\tfunction loadURI (href) {\n\t\tvar url = href;\n\t\tif (url.substring (0, 2) == '//') {\n\t\t\turl = window.location.protocol + url;\n\t\t} else if (url.substring (0, 1) == '/') {\n\t\t\turl = conf.wgServer + url;\n\t\t}\n\t\tload (url);\n\t}\n\n\t// Load local configurations, overriding the pre-set default values in the HotCat object above. This is always loaded\n\t// from the wiki where this script is executing, even if this script itself is hotlinked from the Commons. This can\n\t// be used to change the default settings, or to provide localized interface texts for edit summaries and so on.\n\tloadJS ('MediaWiki:Gadget-HotCat.js/local_defaults');\n\n\t// Load localized UI texts. These are the texts that HotCat displays on the page itself. Texts shown in edit summaries\n\t// should be localized in /local_defaults above.\n\tif (conf.wgUserLanguage != 'en') {\n\t\t// Lupo: somebody thought it would be a good idea to add this. So the default is true, and you have to set it to false\n\t\t// explicitly if you're not on the Commons and don't want that.\n\t\tif (typeof window.hotcat_translations_from_commons == 'undefined') {\n\t\t\twindow.hotcat_translations_from_commons = true;\n\t\t}\n\t\t// Localization hook to localize HotCat messages, tooltips, and engine names for wgUserLanguage.\n\t\tif (window.hotcat_translations_from_commons && conf.wgServer.indexOf('//commons') < 0) {\n\t\t\tloadURI ('//commons.wikimedia.org/w/index.php?title='\n\t\t\t\t+ 'MediaWiki:Gadget-HotCat.js/' + conf.wgUserLanguage\n\t\t\t\t+ '&action=raw&ctype=text/javascript'\n\t\t\t);\n\t\t} else {\n\t\t\t// Load translations locally\n\t\t\tloadJS ('MediaWiki:Gadget-HotCat.js/' + conf.wgUserLanguage);\n\t\t}\n\t} else {\n\t\tloadTrigger.loaded();\n\t}\n\n\t// No further changes should be necessary here.\n\n\t// The following regular expression strings are used when searching for categories in wikitext.\n\tvar wikiTextBlank = '[\\\\t _\\\\xA0\\\\u1680\\\\u180E\\\\u2000-\\\\u200A\\\\u2028\\\\u2029\\\\u202F\\\\u205F\\\\u3000]+';\n\tvar wikiTextBlankRE = new RegExp (wikiTextBlank, 'g');\n\t// Regexp for handling blanks inside a category title or namespace name.\n\t// See http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/Title.php?revision=104051&view=markup#l2722\n\t// See also http://www.fileformat.info/info/unicode/category/Zs/list.htm\n\t// MediaWiki collapses several contiguous blanks inside a page title to one single blank. It also replace a\n\t// number of special whitespace characters by simple blanks. And finally, blanks are treated as underscores.\n\t// Therefore, when looking for page titles in wikitext, we must handle all these cases.\n\t// Note: we _do_ include the horizontal tab in the above list, even though the MediaWiki software for some reason\n\t// appears to not handle it. The zero-width space \\u200B is _not_ handled as a space inside titles by MW.\n\tvar wikiTextBlankOrBidi = '[\\\\t _\\\\xA0\\\\u1680\\\\u180E\\\\u2000-\\\\u200B\\\\u200E\\\\u200F\\\\u2028-\\\\u202F\\\\u205F\\\\u3000]*';\n\t// Whitespace regexp for handling whitespace between link components. Including the horizontal tab, but not \\n\\r\\f\\v:\n\t// a link must be on one single line.\n\t// MediaWiki also removes Unicode bidi override characters in page titles (and namespace names) completely.\n\t// This is *not* handled, as it would require us to allow any of [\\u200E\\u200F\\u202A-\\u202E] between any two\n\t// characters inside a category link. It _could_ be done though... We _do_ handle strange spaces, including the\n\t// zero-width space \\u200B, and bidi overrides between the components of a category link (adjacent to the colon,\n\t// or adjacent to and inside of \"[[\" and \"]]\").\n\n\t// First auto-localize the regexps for the category and the template namespaces.\n\tvar formattedNamespaces = conf.wgFormattedNamespaces;\n\tvar namespaceIds = conf.wgNamespaceIds;\n\tif (formattedNamespaces) {\n\t\tfunction autoLocalize (namespaceNumber, fallback) {\n\t\t\tfunction create_regexp_str (name)\n\t\t\t{\n\t\t\t\tif (!name || name.length === 0) return \"\";\n\t\t\t\tvar regex_name = \"\";\n\t\t\t\tfor (var i = 0; i < name.length; i++){\n\t\t\t\t\tvar initial = name.substr (i, 1);\n\t\t\t\t\tvar ll = initial.toLowerCase ();\n\t\t\t\t\tvar ul = initial.toUpperCase ();\n\t\t\t\t\tif (ll == ul){\n\t\t\t\t\t\tregex_name += initial;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tregex_name += '[' + ll + ul + ']';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn regex_name\n\t\t\t\t\t\t\t.replace(/([\\\\\\^\\$\\.\\?\\*\\+\\(\\)])/g, '\\\\$1')\n\t\t\t\t\t\t\t.replace (wikiTextBlankRE, wikiTextBlank);\n\t\t\t}\n\n\t\t\tfallback = fallback.toLowerCase();\n\t\t\tvar canonical = formattedNamespaces[\"\" + namespaceNumber].toLowerCase();\n\t\t\tvar regexp = create_regexp_str (canonical);\n\t\t\tif (fallback && canonical != fallback) regexp += '|' + create_regexp_str(fallback);\n\t\t\tif (namespaceIds) {\n\t\t\t\tfor (var cat_name in namespaceIds) {\n\t\t\t\t\tif ( typeof cat_name == 'string'\n\t\t\t\t\t\t&& cat_name.toLowerCase() != canonical\n\t\t\t\t\t\t&& cat_name.toLowerCase() != fallback\n\t\t\t\t\t\t&& namespaceIds[cat_name] == namespaceNumber)\n\t\t\t\t\t{\n\t\t\t\t\t\tregexp += '|' + create_regexp_str(cat_name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn regexp;\n\t\t}\n\n\t\tif (formattedNamespaces['14']) {\n\t\t\tHotCat.category_canonical = formattedNamespaces['14'];\n\t\t\tHotCat.category_regexp = autoLocalize (14, 'category');\n\t\t}\n\t\tif (formattedNamespaces['10']) {\n\t\t\tHotCat.template_regexp = autoLocalize (10, 'template');\n\t\t}\n\t}\n\n\t// Utility functions. Yes, this duplicates some functionality that also exists in other places, but\n\t// to keep this whole stuff in a single file not depending on any other on-wiki Javascripts, we re-do\n\t// these few operations here.\n\tfunction bind (func, target) {\n\t\tvar f = func, tgt = target;\n\t\treturn function () { return f.apply (tgt, arguments); };\n\t}\n\tfunction make (arg, literal) {\n\t\tif (!arg) return null;\n\t\treturn literal ? document.createTextNode (arg) : document.createElement (arg);\n\t}\n\tfunction param (name, uri) {\n\t\tif (typeof uri == 'undefined' || uri === null) uri = document.location.href;\n\t\tvar re = new RegExp ('[&?]' + name + '=([^&#]*)');\n\t\tvar m = re.exec (uri);\n\t\tif (m && m.length > 1) return decodeURIComponent(m[1]);\n\t\treturn null;\n\t}\n\tfunction title (href) {\n\t\tif (!href) return null;\n\t\tvar script = conf.wgScript + '?';\n\t\tif (href.indexOf (script) === 0 || href.indexOf (conf.wgServer + script) === 0 || conf.wgServer.substring(0, 2) == '//' && href.indexOf (document.location.protocol + conf.wgServer + script) === 0) {\n\t\t\t// href=\"/w/index.php?title=...\"\n\t\t\treturn param ('title', href);\n\t\t} else {\n\t\t\t// href=\"/wiki/...\"\n\t\t\tvar prefix = conf.wgArticlePath.replace ('$1', \"\");\n\t\t\tif (href.indexOf (prefix) !== 0) prefix = conf.wgServer + prefix; // Fully expanded URL?\n\t\t\tif (href.indexOf (prefix) !== 0 && prefix.substring(0, 2) == '//') prefix = document.location.protocol + prefix; // Protocol-relative wgServer?\n\t\t\tif (href.indexOf (prefix) === 0)\n\t\t\t\treturn decodeURIComponent (href.substring (prefix.length));\n\t\t}\n\t\treturn null;\n\t}\n\tfunction hasClass (elem, name) {\n\t\treturn (' ' + elem.className + ' ').indexOf (' ' + name + ' ') >= 0;\n\t}\n\tfunction capitalize (str) {\n\t\tif (!str || str.length === 0) return str;\n\t\treturn str.substr(0, 1).toUpperCase() + str.substr (1);\n\t}\n\tfunction wikiPagePath (pageName) {\n\t\t// Note: do not simply use encodeURI, it doesn't encode '&', which might break if wgArticlePath actually has the $1 in\n\t\t// a query parameter.\n\t\treturn conf.wgArticlePath.replace('$1', encodeURIComponent (pageName).replace(/%3A/g, ':').replace(/%2F/g, '/'));\n\t}\n\tfunction escapeRE(str) {\n\t\treturn str.replace(/([\\\\\\^\\$\\.\\?\\*\\+\\(\\)\\[\\]])/g, '\\\\$1');\n\t}\n\n\tfunction substituteFactory (options) {\n\t\toptions = options || {};\n\t\tvar lead = options.indicator || '$';\n\t\tvar indicator = escapeRE (lead);\n\t\tvar lbrace = escapeRE (options.lbrace || '{');\n\t\tvar rbrace = escapeRE (options.rbrace || '}');\n\t\tvar re;\n\n\t\tre = new RegExp(\n\t\t\t '(?:' + indicator + '(' + indicator + '))|' // $$\n\t\t\t+'(?:' + indicator + '(\\\\d+))|' // $0, $1\n\t\t\t+'(?:' + indicator + '(?:' + lbrace + '([^' + lbrace + rbrace + ']+)' + rbrace + '))|' // ${key}\n\t\t\t+'(?:' + indicator + '(?!(?:[' + indicator + lbrace + ']|\\\\d))(\\\\S+?)\\\\b)' // $key (only if first char after $ is not $, digit, or { )\n\t\t\t,'g');\n\t\t// Replace $1, $2, or ${key1}, ${key2}, or $key1, $key2 by values from map. $$ is replaced by a single $.\n\t\treturn function (str, map) {\n\t\t\tif (!map) return str;\n\t\t\treturn str.replace(re\n\t\t\t\t,function (match, prefix, idx, key, alpha) {\n\t\t\t\t\tif (prefix == lead) return lead;\n\t\t\t\t\tvar k = alpha || key || idx;\n\t\t\t\t\tvar replacement = typeof map[k] === 'function' ? map[k](match, k) : map[k];\n\t\t\t\t\treturn typeof replacement === 'string' ? replacement : (replacement || match);\n\t\t\t\t}\n\t\t\t);\n\t\t};\n\t}\n\n\tvar substitute = substituteFactory();\n\tvar replaceShortcuts = (function () {\n\t\tvar replaceHash = substituteFactory({indicator:'#',lbrace:'[',rbrace:']'});\n\t\treturn function (str, map) {\n\t\t\tvar s = replaceHash (str, map);\n\t\t\treturn HotCat.capitalizePageNames ? capitalize(s) : s;\n\t\t};\n\t})();\n\n\t// Text modification\n\n\tvar findCatsRE =\n\t\tnew RegExp ('\\\\[\\\\[' + wikiTextBlankOrBidi + '(?:' + HotCat.category_regexp + ')' + wikiTextBlankOrBidi + ':[^\\\\]]+\\\\]\\\\]', 'g');\n\n\tfunction replaceByBlanks (match) {\n\t\treturn match.replace(/(\\s|\\S)/g, ' '); // /./ doesn't match linebreaks. /(\\s|\\S)/ does.\n\t}\n\n\tfunction find_category (wikitext, category, once) {\n\t\tvar cat_regex = null;\n\t\tif(HotCat.template_categories[category]){\n\t\t\tcat_regex = new RegExp ('\\\\{\\\\{' + wikiTextBlankOrBidi + '(' + HotCat.template_regexp + '(?=' + wikiTextBlankOrBidi + ':))?' + wikiTextBlankOrBidi\n\t\t\t\t\t\t\t\t\t+ '(?:' + HotCat.template_categories[category] + ')'\n\t\t\t\t\t\t\t\t\t+ wikiTextBlankOrBidi + '(\\\\|.*?)?\\\\}\\\\}', 'g'\n\t\t\t);\n\t\t} else {\n\t\t\tvar cat_name = escapeRE (category);\n\t\t\tvar initial = cat_name.substr (0, 1);\n\t\t\tcat_regex = new RegExp ('\\\\[\\\\[' + wikiTextBlankOrBidi + '(' + HotCat.category_regexp + ')' + wikiTextBlankOrBidi + ':' + wikiTextBlankOrBidi\n\t\t\t\t\t\t\t\t\t+ (initial == '\\\\' || !HotCat.capitalizePageNames\n\t\t\t\t\t\t\t\t\t\t? initial\n\t\t\t\t\t\t\t\t\t\t: '[' + initial.toUpperCase() + initial.toLowerCase() + ']')\n\t\t\t\t\t\t\t\t\t+ cat_name.substring (1).replace (wikiTextBlankRE, wikiTextBlank)\n\t\t\t\t\t\t\t\t\t+ wikiTextBlankOrBidi + '(\\\\|.*?)?\\\\]\\\\]', 'g'\n\t\t\t);\n\t\t}\n\t\tif (once) return cat_regex.exec (wikitext);\n\t\tvar copiedtext = wikitext\n\t\t\t\t\t\t\t.replace(/<\\!--(\\s|\\S)*?--\\>/g, replaceByBlanks)\n\t\t\t\t\t\t\t.replace(/<nowiki\\>(\\s|\\S)*?<\\/nowiki>/g, replaceByBlanks);\n\t\tvar result = [];\n\t\tvar curr_match = null;\n\t\twhile ((curr_match = cat_regex.exec (copiedtext)) !== null) {\n\t\t\tresult.push ({match : curr_match});\n\t\t}\n\t\tresult.re = cat_regex;\n\t\treturn result; // An array containing all matches, with positions, in result[i].match\n\t}\n\n\tvar interlanguageRE = null;\n\n\tfunction change_category (wikitext, toRemove, toAdd, key, is_hidden) {\n\n\t\tfunction find_insertionpoint (wikitext) {\n\t\t\tvar copiedtext = wikitext\n\t\t\t\t\t\t\t\t.replace(/<\\!--(\\s|\\S)*?--\\>/g, replaceByBlanks)\n\t\t\t\t\t\t\t\t.replace(/<nowiki\\>(\\s|\\S)*?<\\/nowiki>/g, replaceByBlanks);\n\t\t\t// Search in copiedtext to avoid that we insert inside an HTML comment or a nowiki \"element\".\n\t\t\tvar index = -1;\n\t\t\tfindCatsRE.lastIndex = 0;\n\t\t\twhile (findCatsRE.exec(copiedtext) !== null) index = findCatsRE.lastIndex;\n\t\t\tif (index < 0) {\n\t\t\t\t// Find the index of the first interlanguage link...\n\t\t\t\tvar match = null;\n\t\t\t\tif (!interlanguageRE) {\n\t\t\t\t\t// Approximation without API: interlanguage links start with 2 to 3 lower case letters, optionally followed by\n\t\t\t\t\t// a sequence of groups consisting of a dash followed by one or more lower case letters. Exceptions are \"simple\"\n\t\t\t\t\t// and \"tokipona\".\n\t\t\t\t\tmatch = /((^|\\n\\r?)(\\[\\[\\s*(([a-z]{2,3}(-[a-z]+)*)|simple|tokipona)\\s*:[^\\]]+\\]\\]\\s*))+$/.exec (copiedtext);\n\t\t\t\t} else {\n\t\t\t\t\tmatch = interlanguageRE.exec(copiedtext);\n\t\t\t\t}\n\t\t\t\tif (match) index = match.index;\n\t\t\t\treturn {idx : index, onCat : false};\n\t\t\t}\n\t\t\treturn {idx : index, onCat : index >= 0};\n\t\t}\n\n\t\tvar summary = [];\n\t\tvar nameSpace = HotCat.category_canonical;\n\t\tvar cat_point = -1; // Position of removed category;\n\n\t\tif (key) key = '|' + key;\n\t\tvar keyChange = (toRemove && toAdd && toRemove == toAdd && toAdd.length > 0);\n\t\tvar matches;\n\t\tif (toRemove && toRemove.length > 0) {\n\t\t\tmatches = find_category (wikitext, toRemove);\n\t\t\tif (!matches || matches.length === 0) {\n\t\t\t\treturn {text: wikitext, 'summary': summary, error: HotCat.messages.cat_notFound.replace (/\\$1/g, toRemove)};\n\t\t\t} else {\n\t\t\t\tvar before = wikitext.substring (0, matches[0].match.index);\n\t\t\t\tvar after = wikitext.substring (matches[0].match.index + matches[0].match[0].length);\n\t\t\t\tif (matches.length > 1) {\n\t\t\t\t\t// Remove all occurrences in after\n\t\t\t\t\tmatches.re.lastIndex = 0;\n\t\t\t\t\tafter = after.replace (matches.re, \"\");\n\t\t\t\t}\n\t\t\t\tif (toAdd) {\n\t\t\t\t\tnameSpace = matches[0].match[1] || nameSpace;\n\t\t\t\t\tif (key === null) key = matches[0].match[2]; // Remember the category key, if any.\n\t\t\t\t}\n\t\t\t\t// Remove whitespace (properly): strip whitespace, but only up to the next line feed.\n\t\t\t\t// If we then have two linefeeds in a row, remove one. Otherwise, if we have two non-\n\t\t\t\t// whitespace characters, insert a blank.\n\t\t\t\tvar i = before.length - 1;\n\t\t\t\twhile (i >= 0 && before.charAt (i) != '\\n' && before.substr (i, 1).search (/\\s/) >= 0) i--;\n\t\t\t\tvar j = 0;\n\t\t\t\twhile (j < after.length && after.charAt (j) != '\\n' && after.substr (j, 1).search (/\\s/) >= 0)\n\t\t\t\t\tj++;\n\t\t\t\tif (i >= 0 && before.charAt (i) == '\\n' && (after.length === 0 || j < after.length && after.charAt (j) == '\\n'))\n\t\t\t\t\ti--;\n\t\t\t\tif (i >= 0) before = before.substring (0, i+1); else before = \"\";\n\t\t\t\tif (j < after.length) after = after.substring (j); else after = \"\";\n\t\t\t\tif (before.length > 0 && before.substring (before.length - 1).search (/\\S/) >= 0\n\t\t\t\t\t\t&& after.length > 0 && after.substr (0, 1).search (/\\S/) >= 0)\n\t\t\t\t\tbefore += ' ';\n\t\t\t\tcat_point = before.length;\n\t\t\t\tif (cat_point === 0 && after.length > 0 && after.substr(0,1) == '\\n') {\n\t\t\t\t\tafter = after.substr(1);\n\t\t\t\t}\n\t\t\t\twikitext = before + after;\n\t\t\t\tif (!keyChange) {\n\t\t\t\t\tif(HotCat.template_categories[toRemove]) {\n\t\t\t\t\t\tsummary.push (HotCat.messages.template_removed.replace (/\\$1/g, toRemove));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsummary.push (HotCat.messages.cat_removed.replace (/\\$1/g, toRemove));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (toAdd && toAdd.length > 0) {\n\t\t\tmatches = find_category (wikitext, toAdd);\n\t\t\tif (matches && matches.length > 0) {\n\t\t\t\treturn {text: wikitext, 'summary': summary, error : HotCat.messages.cat_exists.replace (/\\$1/g, toAdd)};\n\t\t\t} else {\n\t\t\t\tvar onCat = false;\n\t\t\t\tif (cat_point < 0) {\n\t\t\t\t\tvar point = find_insertionpoint (wikitext);\n\t\t\t\t\tcat_point = point.idx;\n\t\t\t\t\tonCat = point.onCat;\n\t\t\t\t} else {\n\t\t\t\t\tonCat = true;\n\t\t\t\t}\n\t\t\t\tvar newcatstring = '[[' + nameSpace + ':' + toAdd + (key || \"\") + ']]';\n\t\t\t\tif (cat_point >= 0) {\n\t\t\t\t\tvar suffix = wikitext.substring (cat_point);\n\t\t\t\t\twikitext = wikitext.substring (0, cat_point) + (cat_point > 0 ? '\\n' : \"\") + newcatstring + (!onCat ? '\\n' : \"\");\n\t\t\t\t\tif (suffix.length > 0 && suffix.substr(0, 1) != '\\n') {\n\t\t\t\t\t\twikitext += '\\n' + suffix;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twikitext += suffix;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (wikitext.length > 0 && wikitext.substr (wikitext.length - 1, 1) != '\\n')\n\t\t\t\t\t\twikitext += '\\n';\n\t\t\t\t\twikitext += (wikitext.length > 0 ? '\\n' : \"\") + newcatstring;\n\t\t\t\t}\n\t\t\t\tif (keyChange) {\n\t\t\t\t\tvar k = key || \"\";\n\t\t\t\t\tif (k.length > 0) k = k.substr (1);\n\t\t\t\t\tsummary.push (substitute (HotCat.messages.cat_keychange, [null, toAdd, k]));\n\t\t\t\t} else {\n\t\t\t\t\tsummary.push (HotCat.messages.cat_added.replace (/\\$1/g, toAdd));\n\t\t\t\t}\n\t\t\t\tif (HotCat.uncat_regexp && !is_hidden) {\n\t\t\t\t\tvar txt = wikitext.replace (HotCat.uncat_regexp, \"\"); // Remove \"uncat\" templates\n\t\t\t\t\tif (txt.length != wikitext.length) {\n\t\t\t\t\t\twikitext = txt;\n\t\t\t\t\t\tsummary.push (HotCat.messages.uncat_removed);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn {text: wikitext, 'summary': summary, error: null};\n\t}\n\n\t// The real HotCat UI\n\n\tfunction evtKeys (e) {\n\t\te = e || window.event || window.Event; // W3C, IE, Netscape\n\t\tvar code = 0;\n\t\tif (typeof e.ctrlKey != 'undefined') { // All modern browsers\n\t\t\t// Ctrl-click seems to be overloaded in FF/Mac (it opens a pop-up menu), so treat cmd-click\n\t\t\t// as a ctrl-click, too.\n\t\t\tif (e.ctrlKey || e.metaKey) code |= 1;\n\t\t\tif (e.shiftKey) code |= 2;\n\t\t} else if (typeof e.modifiers != 'undefined') { // Netscape...\n\t\t\tif (e.modifiers & (Event.CONTROL_MASK | Event.META_MASK)) code |= 1;\n\t\t\tif (e.modifiers & Event.SHIFT_MASK) code |= 2;\n\t\t}\n\t\treturn code;\n\t}\n\tfunction evtKill (e) {\n\t\te = e || window.event || window.Event; // W3C, IE, Netscape\n\t\tif (typeof e.preventDefault != 'undefined') {\n\t\t\te.preventDefault ();\n\t\t\te.stopPropagation ();\n\t\t} else\n\t\t\te.cancelBubble = true;\n\t\treturn false;\n\t}\n\tfunction addEvent (node, evt, f, capture) {\n\t\tif (window.jQuery && (!capture || !node.addEventListener)) window.jQuery (node).bind (evt, f);\n\t\telse if (node.addEventListener) node.addEventListener (evt, f, capture); // FF etc; IE >= 9\n\t\telse if (node.attachEvent) node.attachEvent ('on' + evt, f); // Older IE; Opera\n\t\telse node['on' + evt] = f; // Very old!\n\t}\n\n\tvar catLine = null;\n\tvar onUpload = false;\n\tvar editors = [];\n\n\tvar commitButton = null;\n\tvar commitForm = null;\n\tvar multiSpan = null;\n\n\tvar pageText = null;\n\tvar pageTime = null;\n\tvar pageWatched = false;\n\tvar watchCreate = false;\n\tvar watchEdit = false;\n\tvar minorEdits = false;\n\tvar editToken = null;\n\n\tvar is_rtl = false;\n\tvar serverTime = null;\n\tvar lastRevId = null;\n\tvar pageTextRevId = null;\n\tvar conflictingUser = null;\n\n\tvar newDOM = false; // true if MediaWiki serves the new UL-LI DOM for categories\n\n\tfunction setMultiInput () {\n\t\tif (commitButton || onUpload) return;\n\t\tcommitButton = make ('input');\n\t\tcommitButton.type = 'button';\n\t\tcommitButton.value = HotCat.messages.commit;\n\t\tcommitButton.onclick = multiSubmit;\n\t\tif (multiSpan) {\n\t\t\tmultiSpan.parentNode.replaceChild (commitButton, multiSpan);\n\t\t} else {\n\t\t\tcatLine.appendChild (commitButton);\n\t\t}\n\t}\n\n\tfunction checkMultiInput () {\n\t\tif (!commitButton) return;\n\t\tvar has_changes = false;\n\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\tif (editors[i].state != CategoryEditor.UNCHANGED) {\n\t\t\t\thas_changes = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcommitButton.disabled = !has_changes;\n\t}\n\n\tfunction currentTimestamp () {\n\t\tvar now = new Date();\n\t\tvar ts = \"\" + now.getUTCFullYear();\n\t\tfunction two (s) { return s.substr (s.length - 2); }\n\t\tts = ts\n\t\t\t+ two ('0' + (now.getUTCMonth() + 1))\n\t\t\t+ two ('0' + now.getUTCDate())\n\t\t\t+ two ('00' + now.getUTCHours())\n\t\t\t+ two ('00' + now.getUTCMinutes())\n\t\t\t+ two ('00' + now.getUTCSeconds());\n\t\treturn ts;\n\t}\n\n\tvar saveInProgress = false;\n\tfunction initiateEdit (doEdit, failure) {\n\t\tif (saveInProgress) return;\n\t\tsaveInProgress = true;\n\t\tvar oldButtonState;\n\t\tif (commitButton) {\n\t\t\toldButtonState = commitButton.disabled;\n\t\t\tcommitButton.disabled = true;\n\t\t}\n\n\t\tfunction fail() {\n\t\t\tsaveInProgress = false;\n\t\t\tif (commitButton) commitButton.disabled = oldButtonState;\n\t\t\tfailure.apply(this, arguments);\n\t\t}\n\n\t\t// Must use Ajax here to get the user options and the edit token.\n\n\t\tgetJSON ({\n\t\t\t uri : conf.wgServer + conf.wgScriptPath + '/api.php'\n\t\t\t,data : 'format=json&action=query&rawcontinue=&titles=' + encodeURIComponent (conf.wgPageName)\n\t\t\t\t+ '&prop=info%7Crevisions%7Clanglinks&inprop=watched&intoken=edit&rvprop=content%7Ctimestamp%7Cids%7Cuser&lllimit=500'\n\t\t\t\t+ '&rvlimit=2&rvdir=newer&rvstartid=' + conf.wgCurRevisionId\n\t\t\t\t+ '&meta=siteinfo%7Cuserinfo&uiprop=options'\n\t\t\t,success : function (json) { setPage(json); doEdit(fail); }\n\t\t\t,error : function (req) { fail(req.status + ' ' + req.statusText); }\n\t\t});\n\t}\n\n\tfunction multiChangeMsg (count) {\n\t\tvar msg = HotCat.messages.multi_change;\n\t\tif (typeof msg != 'string' && msg.length) {\n\t\t\tif (window.mw && mw.language && mw.language.convertPlural) {\n\t\t\t\tmsg = mw.language.convertPlural (count, msg);\n\t\t\t} else {\n\t\t\t\tmsg = msg[msg.length-1];\n\t\t\t}\n\t\t}\n\t\treturn substitute (msg, [null, \"\" + count]);\n\t}\n\n\tfunction performChanges (failure, singleEditor) {\n\t\tif (pageText === null) {\n\t\t\tfailure (HotCat.messages.multi_error);\n\t\t\treturn;\n\t\t}\n\t\t// Backwards compatibility after message change (added $2 to cat_keychange)\n\t\tif (HotCat.messages.cat_keychange.indexOf ('$2') < 0) HotCat.messages.cat_keychange += '\"$2\"';\n\t\t// More backwards-compatibility with earlier HotCat versions:\n\t\tif (!HotCat.messages.short_catchange) HotCat.messages.short_catchange = '[[' + HotCat.category_canonical + ':$1]]';\n\t\t// Create a form and submit it. We don't use the edit API (api.php?action=edit) because\n\t\t// (a) sensibly reporting back errors like edit conflicts is always a hassle, and\n\t\t// (b) we want to show a diff for multi-edits anyway, and\n\t\t// (c) we want to trigger onsubmit events, allowing user code to intercept the edit.\n\t\t// Using the form, we can do (b) and (c), and we get (a) for free. And, of course, using the form\n\t\t// automatically reloads the page with the updated categories on a successful submit, which\n\t\t// we would have to do explicitly if we used the edit API.\n\t\tvar action;\n\t\t// Normally, we don't have to care about edit conflicts. If some other user edited the page in the meantime, the\n\t\t// server will take care of it and merge the edit automatically or present an edit conflict screen. However, the\n\t\t// server suppresses edit conflicts with oneself. Hence, if we have a conflict, and the conflicting user is the\n\t\t// current user, then we set the \"oldid\" value and switch to diff, which gives the \"you are editing an old version;\n\t\t// if you save, any more recent changes will be lost\" screen.\n\t\tvar editingOldVersion = lastRevId !== null && lastRevId != conf.wgCurRevisionId || pageTextRevId !== null && pageTextRevId != conf.wgCurRevisionId;\n\t\tvar selfEditConflict = editingOldVersion && conflictingUser && conflictingUser == conf.wgUserName;\n\t\tif (singleEditor && !singleEditor.noCommit && !HotCat.no_autocommit && editToken && !selfEditConflict) {\n\t\t\t// If we do have an edit conflict, but not with ourself, that's no reason not to attempt to save: the server side may actually be able to\n\t\t\t// merge the changes. We just need to make sure that we do present a diff view if it's a self edit conflict.\n\t\t\tcommitForm.wpEditToken.value = editToken;\n\t\t\taction = commitForm.wpDiff;\n\t\t\tif (action) action.name = action.value = 'wpSave';\n\t\t} else {\n\t\t\taction = commitForm.wpSave;\n\t\t\tif (action) action.name = action.value = 'wpDiff';\n\t\t}\n\t\tvar result = { text : pageText };\n\t\tvar changed = [], added = [], deleted = [], changes = 0;\n\t\tvar toEdit = !!singleEditor ? [singleEditor] : editors;\n\t\tvar error = null;\n\t\tvar i;\n\t\tfor (i=0; i < toEdit.length; i++) {\n\t\t\tif (toEdit[i].state == CategoryEditor.CHANGED) {\n\t\t\t\tresult = change_category (\n\t\t\t\t\t\tresult.text\n\t\t\t\t\t, toEdit[i].originalCategory\n\t\t\t\t\t, toEdit[i].currentCategory\n\t\t\t\t\t, toEdit[i].currentKey\n\t\t\t\t\t, toEdit[i].currentHidden\n\t\t\t\t);\n\t\t\t\tif (!result.error) {\n\t\t\t\t\tchanges++;\n\t\t\t\t\tif (!toEdit[i].originalCategory || toEdit[i].originalCategory.length === 0) {\n\t\t\t\t\t\tadded.push (toEdit[i].currentCategory);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchanged.push ({from : toEdit[i].originalCategory, to : toEdit[i].currentCategory});\n\t\t\t\t\t}\n\t\t\t\t} else if (error === null) {\n\t\t\t\t\terror = result.error;\n\t\t\t\t}\n\t\t\t} else if ( toEdit[i].state == CategoryEditor.DELETED\n\t\t\t\t\t && toEdit[i].originalCategory\n\t\t\t\t\t && toEdit[i].originalCategory.length > 0)\n\t\t\t{\n\t\t\t\tresult = change_category (result.text, toEdit[i].originalCategory, null, null, false);\n\t\t\t\tif (!result.error) {\n\t\t\t\t\tchanges++;\n\t\t\t\t\tdeleted.push (toEdit[i].originalCategory);\n\t\t\t\t} else if (error === null) {\n\t\t\t\t\terror = result.error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (error !== null) { // Do not commit if there were errors\n\t\t\taction = commitForm.wpSave;\n\t\t\tif (action) action.name = action.value = 'wpDiff';\n\t\t}\n\t\t// Fill in the form and submit it\n\t\tcommitForm.wpAutoSummary.value = 'd41d8cd98f00b204e9800998ecf8427e'; // MD5 hash of the empty string\n\t\tcommitForm.wpMinoredit.checked = minorEdits;\n\t\tcommitForm.wpWatchthis.checked = conf.wgArticleId === 0 && watchCreate || watchEdit || pageWatched;\n\t\tif (conf.wgArticleId > 0 || !!singleEditor) {\n\t\t\tif (changes == 1) {\n\t\t\t\tif (result.summary && result.summary.length > 0)\n\t\t\t\t\tcommitForm.wpSummary.value = HotCat.messages.prefix + result.summary.join (HotCat.messages.separator) + HotCat.messages.using;\n\t\t\t\tcommitForm.wpMinoredit.checked = HotCat.single_minor || minorEdits;\n\t\t\t} else if (changes > 1) {\n\t\t\t\tvar summary = [];\n\t\t\t\tvar shortSummary = [];\n\t\t\t\t// Deleted\n\t\t\t\tfor (i = 0; i < deleted.length; i++) {\n\t\t\t\t\tsummary.push ('-' + substitute (HotCat.messages.short_catchange, [null, deleted[i]]));\n\t\t\t\t}\n\t\t\t\tif (deleted.length == 1)\n\t\t\t\t\tshortSummary.push ('-' + substitute (HotCat.messages.short_catchange, [null, deleted[0]]));\n\t\t\t\telse if (deleted.length > 1)\n\t\t\t\t\tshortSummary.push ('- ' + multiChangeMsg (deleted.length));\n\t\t\t\t// Added\n\t\t\t\tfor (i = 0; i < added.length; i++) {\n\t\t\t\t\tsummary.push ('+' + substitute (HotCat.messages.short_catchange, [null, added[i]]));\n\t\t\t\t}\n\t\t\t\tif (added.length == 1)\n\t\t\t\t\tshortSummary.push ('+' + substitute (HotCat.messages.short_catchange, [null, added[0]]));\n\t\t\t\telse if (added.length > 1)\n\t\t\t\t\tshortSummary.push ('+ ' + multiChangeMsg (added.length));\n\t\t\t\t// Changed\n\t\t\t\tvar arrow = is_rtl ? '\\u2190' : '\\u2192'; // left and right arrows. Don't use ← and → in the code.\n\t\t\t\tfor (i = 0; i < changed.length; i++) {\n\t\t\t\t\tif (changed[i].from != changed[i].to) {\n\t\t\t\t\t\tsummary.push ('±' + substitute (HotCat.messages.short_catchange, [null, changed[i].from]) + arrow\n\t\t\t\t\t\t\t\t\t\t+ substitute (HotCat.messages.short_catchange, [null, changed[i].to]));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsummary.push ('±' + substitute (HotCat.messages.short_catchange, [null, changed[i].from]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (changed.length == 1) {\n\t\t\t\t\tif (changed[0].from != changed[0].to) {\n\t\t\t\t\t\tshortSummary.push ('±' + substitute (HotCat.messages.short_catchange, [null, changed[0].from]) + arrow\n\t\t\t\t\t\t\t\t\t\t\t+ substitute (HotCat.messages.short_catchange, [null, changed[0].to]));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tshortSummary.push ('±' + substitute (HotCat.messages.short_catchange, [null, changed[0].from]));\n\t\t\t\t\t}\n\t\t\t\t} else if (changed.length > 1) {\n\t\t\t\t\tshortSummary.push ('± ' + multiChangeMsg (changed.length));\n\t\t\t\t}\n\t\t\t\tif (summary.length > 0) {\n\t\t\t\t\tsummary = summary.join (HotCat.messages.separator);\n\t\t\t\t\tif (summary.length > 200 - HotCat.messages.prefix.length - HotCat.messages.using.length) {\n\t\t\t\t\t\tsummary = shortSummary.join (HotCat.messages.separator);\n\t\t\t\t\t}\n\t\t\t\t\tcommitForm.wpSummary.value = HotCat.messages.prefix + summary + HotCat.messages.using;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcommitForm.wpTextbox1.value = result.text;\n\t\tcommitForm.wpStarttime.value = serverTime || currentTimestamp ();\n\t\tcommitForm.wpEdittime.value = pageTime || commitForm.wpStarttime.value;\n\t\tif (selfEditConflict) commitForm.oldid.value = \"\" + (pageTextRevId || conf.wgCurRevisionId);\n\t\t// Submit the form in a way that triggers onsubmit events: commitForm.submit() doesn't.\n\t\tcommitForm.hcCommit.click();\n\t}\n\n\tfunction resolveMulti (toResolve, callback) {\n\t\tvar i;\n\t\tfor (i = 0; i < toResolve.length; i++) {\n\t\t\ttoResolve[i].dab = null;\n\t\t\ttoResolve[i].dabInput = toResolve[i].lastInput;\n\t\t}\n\t\tif (noSuggestions) {\n\t\t\tcallback (toResolve);\n\t\t\treturn;\n\t\t}\n\t\t// Use %7C instead of |, otherwise Konqueror insists on re-encoding the arguments, resulting in doubly encoded\n\t\t// category names. (That is a bug in Konqueror. Other browsers don't have this problem.)\n\t\tvar args = 'action=query&prop=info%7Clinks%7Ccategories%7Ccategoryinfo&plnamespace=14'\n\t\t\t\t+ '&pllimit=' + (toResolve.length * 10)\n\t\t\t\t+ '&cllimit=' + (toResolve.length * 10)\n\t\t\t\t+ '&format=json&titles=';\n\t\tfor (i = 0; i < toResolve.length; i++) {\n\t\t\tvar v = toResolve[i].dabInput;\n\t\t\tv = replaceShortcuts (v, HotCat.shortcuts);\n\t\t\ttoResolve[i].dabInputCleaned = v;\n\t\t\targs += encodeURIComponent ('Category:' + v);\n\t\t\tif (i+1 < toResolve.length) args += '%7C';\n\t\t}\n\t\tgetJSON({\n\t\t\t uri : conf.wgServer + conf.wgScriptPath + '/api.php'\n\t\t\t,data : args\n\t\t\t,success: function (json) { resolveRedirects (toResolve, json); callback (toResolve); }\n\t\t\t,error: function (req) { if (!req) noSuggestions = true; callback (toResolve); }\n\t\t});\n\t}\n\n\tfunction resolveOne (page, toResolve) {\n\t\tvar cats = page.categories;\n\t\tvar lks = page.links;\n\t\tvar is_dab = false;\n\t\tvar is_redir = typeof page.redirect == 'string'; // Hard redirect?\n\t\tvar is_hidden = page.categoryinfo && typeof page.categoryinfo.hidden == 'string';\n\t\tvar is_missing = typeof page.missing == 'string';\n\t\tvar i;\n\t\tfor (i = 0; i < toResolve.length; i++) {\n\t\t\tif (toResolve.length > 1 && toResolve[i].dabInputCleaned != page.title.substring (page.title.indexOf (':') + 1)) continue;\n\t\t\t// Note: the server returns in page an NFC normalized Unicode title. If our input was not NFC normalized, we may not find\n\t\t\t// any entry here. If we have only one editor to resolve (the most common case, I presume), we may simply skip the check.\n\t\t\ttoResolve[i].currentHidden = is_hidden;\n\t\t\ttoResolve[i].inputExists = !is_missing;\n\t\t\ttoResolve[i].icon.src = armorUri(is_missing ? HotCat.existsNo : HotCat.existsYes);\n\t\t}\n\t\tif (is_missing) return;\n\t\tif (!is_redir && cats && (HotCat.disambig_category || HotCat.redir_category)) {\n\t\t\tfor (var c = 0; c < cats.length; c++) {\n\t\t\t\tvar cat = cats[c]['title'];\n\t\t\t\t// Strip namespace prefix\n\t\t\t\tif (cat) {\n\t\t\t\t\tcat = cat.substring (cat.indexOf (':') + 1).replace(/_/g, ' ');\n\t\t\t\t\tif (cat == HotCat.disambig_category) {\n\t\t\t\t\t\tis_dab = true; break;\n\t\t\t\t\t} else if (cat == HotCat.redir_category) {\n\t\t\t\t\t\tis_redir = true; break;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!is_redir && !is_dab) return;\n\t\tif (!lks || lks.length === 0) return;\n\t\tvar titles = [];\n\t\tfor (i = 0; i < lks.length; i++) {\n\t\t\tif ( lks[i]['ns'] == 14 // Category namespace -- always true since we ask only for the category links\n\t\t\t\t&& lks[i]['title'] && lks[i]['title'].length > 0) // Name not empty\n\t\t\t{\n\t\t\t\t// Internal link to existing thingy. Extract the page name and remove the namespace.\n\t\t\t\tvar match = lks[i]['title'];\n\t\t\t\tmatch = match.substring (match.indexOf (':') + 1);\n\t\t\t\t// Exclude blacklisted categories.\n\t\t\t\tif (!HotCat.blacklist || !HotCat.blacklist.test (match)) {\n\t\t\t\t\ttitles.push (match);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (titles.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tfor (i = 0; i < toResolve.length; i++) {\n\t\t\tif (toResolve.length > 1 && toResolve[i].dabInputCleaned != page.title.substring (page.title.indexOf (':') + 1)) continue;\n\t\t\ttoResolve[i].inputExists = true; // Might actually be wrong if it's a redirect pointing to a non-existing category\n\t\t\ttoResolve[i].icon.src = armorUri(HotCat.existsYes);\n\t\t\tif (titles.length > 1) {\n\t\t\t\ttoResolve[i].dab = titles;\n\t\t\t} else {\n\t\t\t\ttoResolve[i].text.value =\n\t\t\t\t\ttitles[0] + (toResolve[i].currentKey !== null ? '|' + toResolve[i].currentKey : \"\");\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction resolveRedirects (toResolve, params) {\n\t\tif (!params || !params.query || !params.query.pages) return;\n\t\tfor (var p in params.query.pages) resolveOne (params.query.pages[p], toResolve);\n\t}\n\n\tfunction multiSubmit () {\n\t\tvar toResolve = [];\n\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\tif (editors[i].state == CategoryEditor.CHANGE_PENDING || editors[i].state == CategoryEditor.OPEN)\n\t\t\t\ttoResolve.push (editors[i]);\n\t\t}\n\t\tif (toResolve.length === 0) {\n\t\t\tinitiateEdit (function (failure) {performChanges (failure);}, function (msg) {alert (msg);});\n\t\t\treturn;\n\t\t}\n\t\tresolveMulti (\n\t\t\t toResolve\n\t\t\t, function (resolved) {\n\t\t\t\t\tvar firstDab = null;\n\t\t\t\t\tvar dontChange = false;\n\t\t\t\t\tfor (var i = 0; i < resolved.length; i++) {\n\t\t\t\t\t\tif (resolved[i].lastInput != resolved[i].dabInput) {\n\t\t\t\t\t\t\t// We didn't disable all the open editors, but we did asynchronous calls. It is\n\t\t\t\t\t\t\t// theoretically possible that the user changed something...\n\t\t\t\t\t\t\tdontChange = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (resolved[i].dab) {\n\t\t\t\t\t\t\t\tif (!firstDab) firstDab = resolved[i];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (resolved[i].acceptCheck(true)) resolved[i].commit();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (firstDab) {\n\t\t\t\t\t\tshowDab (firstDab);\n\t\t\t\t\t} else if (!dontChange) {\n\t\t\t\t\t\tinitiateEdit (function (failure) {performChanges (failure);}, function (msg) {alert (msg);});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t);\n\t}\n\n\tvar cat_prefix = null;\n\tvar noSuggestions = false;\n\tvar suggestionEngines = {\n\t\topensearch :\n\t\t\t{ uri : '/api.php?format=json&action=opensearch&namespace=14&limit=30&search=Category:$1' // $1 = search term\n\t\t\t ,handler : // Function to convert result of uri into an array of category names\n\t\t\t\tfunction (queryResult, queryKey) {\n\t\t\t\t\tif (queryResult && queryResult.length >= 2) {\n\t\t\t\t\t\tvar key = queryResult[0].substring(queryResult[0].indexOf(':') + 1);\n\t\t\t\t\t\tvar titles = queryResult[1];\n\t\t\t\t\t\tvar exists = false;\n\t\t\t\t\t\tif (!cat_prefix) cat_prefix = new RegExp ('^(' + HotCat.category_regexp + ':)');\n\t\t\t\t\t\tfor (var i = 0; i < titles.length; i++) {\n\t\t\t\t\t\t\tcat_prefix.lastIndex = 0;\n\t\t\t\t\t\t\tvar m = cat_prefix.exec (titles[i]);\n\t\t\t\t\t\t\tif (m && m.length > 1) {\n\t\t\t\t\t\t\t\ttitles[i] = titles[i].substring (titles[i].indexOf (':') + 1); // rm namespace\n\t\t\t\t\t\t\t\tif (key == titles[i]) exists = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttitles.splice (i, 1); // Nope, it's not a category after all.\n\t\t\t\t\t\t\t\ti--;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttitles.exists = exists;\n\t\t\t\t\t\tif (queryKey != key) titles.normalized = key; // Remember the NFC normalized key we got back from the server\n\t\t\t\t\t\treturn titles;\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t,internalsearch :\n\t\t\t{ uri : '/api.php?format=json&action=query&list=allpages&apnamespace=14&aplimit=30&apfrom=$1&apprefix=$1'\n\t\t\t ,handler :\n\t\t\t\tfunction (queryResult, queryKey) {\n\t\t\t\t\tif (queryResult && queryResult.query && queryResult.query.allpages) {\n\t\t\t\t\t\tvar titles = queryResult.query.allpages;\n\t\t\t\t\t\tfor (var i = 0; i < titles.length; i++) {\n\t\t\t\t\t\t\ttitles[i] = titles[i].title.substring (titles[i].title.indexOf (':') + 1); // rm namespace\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn titles;\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t,exists :\n\t\t\t{ uri : '/api.php?format=json&action=query&prop=info&titles=Category:$1'\n\t\t\t ,handler :\n\t\t\t\tfunction (queryResult, queryKey) {\n\t\t\t\t\tif (queryResult && queryResult.query && queryResult.query.pages && !queryResult.query.pages[-1]) {\n\t\t\t\t\t\t// Should have exactly 1\n\t\t\t\t\t\tfor (var p in queryResult.query.pages) {\n\t\t\t\t\t\t\tvar title = queryResult.query.pages[p].title;\n\t\t\t\t\t\t\ttitle = title.substring (title.indexOf (':') + 1);\n\t\t\t\t\t\t\tvar titles = [title];\n\t\t\t\t\t\t\ttitles.exists = true;\n\t\t\t\t\t\t\tif (queryKey != title) titles.normalized = title; // NFC\n\t\t\t\t\t\t\treturn titles;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t,subcategories :\n\t\t\t// I don't understand why they didn't map cmnamespace=14 automatically to cmtype=subcat,\n\t\t\t// which gives better results and is faster.\n\t\t\t{ uri : '/api.php?format=json&action=query&list=categorymembers'\n\t\t\t\t+(function (version) {\n\t\t\t\t\tvar m = version.match(/^(\\d+)\\.(\\d+)/);\n\t\t\t\t\tvar major = 0, minor = 0;\n\t\t\t\t\tif (m && m.length > 1) {\n\t\t\t\t\t\tmajor = parseInt (m[1], 10);\n\t\t\t\t\t\tminor = (m.length > 2 ? parseInt (m[2], 10) : 0);\n\t\t\t\t\t}\n\t\t\t\t\tif (major > 1 || major === 1 && minor > 17) return '&cmtype=subcat'; // Since MW1.18\n\t\t\t\t\treturn '&cmnamespace=14';\n\t\t\t\t }\n\t\t\t\t)(conf.wgVersion)\n\t\t\t\t+'&cmlimit=max&cmtitle=Category:$1'\n\t\t\t ,handler :\n\t\t\t\tfunction (queryResult, queryKey) {\n\t\t\t\t\tif (queryResult && queryResult.query && queryResult.query.categorymembers) {\n\t\t\t\t\t\tvar titles = queryResult.query.categorymembers;\n\t\t\t\t\t\tfor (var i = 0; i < titles.length; i++) {\n\t\t\t\t\t\t\ttitles[i] = titles[i].title.substring (titles[i].title.indexOf (':') + 1); // rm namespace\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn titles;\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t,parentcategories :\n\t\t\t{ uri : '/api.php?format=json&action=query&prop=categories&titles=Category:$1&cllimit=max'\n\t\t\t ,handler :\n\t\t\t\tfunction (queryResult, queryKey) {\n\t\t\t\t\tif (queryResult && queryResult.query && queryResult.query.pages) {\n\t\t\t\t\t\tfor (var p in queryResult.query.pages) {\n\t\t\t\t\t\t\tif (queryResult.query.pages[p].categories) {\n\t\t\t\t\t\t\t\tvar titles = queryResult.query.pages[p].categories;\n\t\t\t\t\t\t\t\tfor (var i = 0; i < titles.length; i++) {\n\t\t\t\t\t\t\t\t\ttitles[i] = titles[i].title.substring (titles[i].title.indexOf (':') + 1); // rm namespace\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn titles;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t};\n\n\tvar suggestionConfigs = {\n\t\t searchindex : {name: 'Search index', engines: ['opensearch'], cache: {}, show: true, temp: false, noCompletion : false}\n\t\t,pagelist : {name: 'Page list', engines: ['internalsearch', 'exists'], cache: {}, show: true, temp: false, noCompletion : false}\n\t\t,combined : {name: 'Combined search', engines: ['opensearch', 'internalsearch'], cache: {}, show: true, temp: false, noCompletion : false}\n\t\t,subcat : {name: 'Subcategories', engines: ['subcategories'], cache: {}, show: true, temp: true, noCompletion : true}\n\t\t,parentcat : {name: 'Parent categories', engines: ['parentcategories'], cache: {}, show: true, temp: true, noCompletion : true}\n\t};\n\n\tfunction CategoryEditor () { this.initialize.apply (this, arguments); }\n\tCategoryEditor.UNCHANGED = 0;\n\tCategoryEditor.OPEN = 1; // Open, but no input yet\n\tCategoryEditor.CHANGE_PENDING = 2; // Open, some input made\n\tCategoryEditor.CHANGED = 3;\n\tCategoryEditor.DELETED = 4;\n\n\t// IE6 sometimes forgets to redraw the list when editors are opened or closed.\n\t// Adding/removing a dummy element helps, at least when opening editors.\n\tvar dummyElement = make ('\\xa0', true);\n\n\tfunction forceRedraw () {\n\t\tif (!is_ie6) return;\n\t\tif (dummyElement.parentNode) {\n\t\t\tdocument.body.removeChild (dummyElement);\n\t\t} else {\n\t\t\tdocument.body.appendChild (dummyElement);\n\t\t}\n\t}\n\n\t// Event keyCodes that we handle in the text input field/suggestion list.\n\tvar BS = 8, TAB = 9, RET = 13, ESC = 27, SPACE = 32, PGUP = 33, PGDOWN = 34, UP = 38, DOWN = 40, DEL = 46, IME = 229;\n\t\n\tfunction makeActive (which) {\n\t\tif (which.is_active) return;\n\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\tif (editors[i] !== which) editors[i].inactivate ();\n\t\t}\n\t\twhich.is_active = true;\n\t\tif (which.dab) {\n\t\t\tshowDab (which);\n\t\t} else {\n\t\t\t// Check for programmatic value changes.\n\t\t\tvar expectedInput = which.lastRealInput || which.lastInput || \"\";\n\t\t\tvar actualValue = which.text.value || \"\";\n\t\t\tif (expectedInput.length === 0 && actualValue.length > 0 || expectedInput.length > 0 && actualValue.indexOf (expectedInput) !== 0) {\n\t\t\t\t// Somehow the field's value appears to have changed, and which.lastSelection therefore is no longer valid. Try to set the\n\t\t\t\t// cursor at the end of the category, and do not display the old suggestion list.\n\t\t\t\twhich.showsList = false;\n\t\t\t\tvar v = actualValue.split('|');\n\t\t\t\twhich.lastRealInput = which.lastInput = v[0];\n\t\t\t\tif (v.length > 1) which.currentKey = v[1];\n\t\t\t\tif (which.lastSelection) which.lastSelection = {start: v[0].length, end: v[0].length};\n\t\t\t}\n\t\t\tif (which.showsList) which.displayList();\n\t\t\tif (which.lastSelection) {\n\t\t\t\tif (is_webkit) {\n\t\t\t\t\t// WebKit (Safari, Chrome) has problems selecting inside focus()\n\t\t\t\t\t// See http://code.google.com/p/chromium/issues/detail?id=32865#c6\n\t\t\t\t\twindow.setTimeout (\n\t\t\t\t\t\t function () { which.setSelection (which.lastSelection.start, which.lastSelection.end); }\n\t\t\t\t\t\t,1\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\twhich.setSelection (which.lastSelection.start, which.lastSelection.end);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction showDab (which) {\n\t\tif (!which.is_active) {\n\t\t\tmakeActive(which);\n\t\t} else {\n\t\t\twhich.showSuggestions (which.dab, false, null, null); // do autocompletion, no key, no engine selector\n\t\t\twhich.dab = null;\n\t\t}\n\t}\n\n\tCategoryEditor.prototype = {\n\n\t\tinitialize : function (line, span, after, key, is_hidden) {\n\t\t\t// If a span is given, 'after' is the category title, otherwise it may be an element after which to\n\t\t\t// insert the new span. 'key' is likewise overloaded; if a span is given, it is the category key (if\n\t\t\t// known), otherwise it is a boolean indicating whether a bar shall be prepended.\n\t\t\tif (!span) {\n\t\t\t\tthis.isAddCategory = true;\n\t\t\t\t// Create add span and append to catLinks\n\t\t\t\tthis.originalCategory = \"\";\n\t\t\t\tthis.originalKey = null;\n\t\t\t\tthis.originalExists = false;\n\t\t\t\tif (!newDOM) {\n\t\t\t\t\tspan = make ('span');\n\t\t\t\t\tspan.className = 'noprint';\n\t\t\t\t\tif (key) {\n\t\t\t\t\t\tspan.appendChild (make (' | ', true));\n\t\t\t\t\t\tif (after) {\n\t\t\t\t\t\t\tafter.parentNode.insertBefore (span, after.nextSibling);\n\t\t\t\t\t\t\tafter = after.nextSibling;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tline.appendChild (span);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (line.firstChild) {\n\t\t\t\t\t\tspan.appendChild (make (' ', true));\n\t\t\t\t\t\tline.appendChild (span);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.linkSpan = make ('span');\n\t\t\t\tthis.linkSpan.className = 'noprint nopopups hotcatlink';\n\t\t\t\tvar lk = make ('a'); lk.href = '#catlinks'; lk.onclick = bind (this.open, this);\n\t\t\t\tlk.appendChild (make (HotCat.links.add, true)); lk.title = HotCat.tooltips.add;\n\t\t\t\tthis.linkSpan.appendChild (lk);\n\t\t\t\tspan = make (newDOM ? 'li' : 'span');\n\t\t\t\tspan.className = 'noprint';\n\t\t\t\tif (is_rtl) span.dir = 'rtl';\n\t\t\t\tspan.appendChild (this.linkSpan);\n\t\t\t\tif (after)\n\t\t\t\t\tafter.parentNode.insertBefore (span, after.nextSibling);\n\t\t\t\telse\n\t\t\t\t\tline.appendChild (span);\n\t\t\t\tthis.normalLinks = null;\n\t\t\t\tthis.undelLink = null;\n\t\t\t\tthis.catLink = null;\n\t\t\t} else {\n\t\t\t\tif (is_rtl) span.dir = 'rtl';\n\t\t\t\tthis.isAddCategory = false;\n\t\t\t\tthis.catLink = span.firstChild;\n\t\t\t\tthis.originalCategory = after;\n\t\t\t\tthis.originalKey = (key && key.length > 1) ? key.substr(1) : null; // > 1 because it includes the leading bar\n\t\t\t\tthis.originalExists = !hasClass (this.catLink, 'new');\n\t\t\t\t// Create change and del links\n\t\t\t\tthis.makeLinkSpan ();\n\t\t\t\tif (!this.originalExists && this.upDownLinks) this.upDownLinks.style.display = 'none';\n\t\t\t\tspan.appendChild (this.linkSpan);\n\t\t\t}\n\t\t\tthis.originalHidden = is_hidden;\n\t\t\tthis.line = line;\n\t\t\tthis.engine = HotCat.suggestions;\n\t\t\tthis.span = span;\n\t\t\tthis.currentCategory = this.originalCategory;\n\t\t\tthis.currentExists = this.originalExists;\n\t\t\tthis.currentHidden = this.originalHidden;\n\t\t\tthis.currentKey = this.originalKey;\n\t\t\tthis.state = CategoryEditor.UNCHANGED;\n\t\t\tthis.lastSavedState = CategoryEditor.UNCHANGED;\n\t\t\tthis.lastSavedCategory = this.originalCategory;\n\t\t\tthis.lastSavedKey = this.originalKey;\n\t\t\tthis.lastSavedExists = this.originalExists;\n\t\t\tthis.lastSavedHidden = this.originalHidden;\n\t\t\tif (this.catLink && this.currentKey) {\n\t\t\t\tthis.catLink.title = this.currentKey;\n\t\t\t}\n\t\t\teditors[editors.length] = this;\n\t\t},\n\n\t\tmakeLinkSpan : function () {\n\t\t\tthis.normalLinks = make ('span');\n\t\t\tvar lk = null;\n\t\t\tif (this.originalCategory && this.originalCategory.length > 0) {\n\t\t\t\tlk = make ('a'); lk.href = '#catlinks'; lk.onclick = bind (this.remove, this);\n\t\t\t\tlk.appendChild (make (HotCat.links.remove, true)); lk.title = HotCat.tooltips.remove;\n\t\t\t\tthis.normalLinks.appendChild (make (' ', true));\n\t\t\t\tthis.normalLinks.appendChild (lk);\n\t\t\t}\n\t\t\tif (!HotCat.template_categories[this.originalCategory]) {\n\t\t\t\tlk = make ('a'); lk.href = '#catlinks'; lk.onclick = bind (this.open, this);\n\t\t\t\tlk.appendChild (make (HotCat.links.change, true)); lk.title = HotCat.tooltips.change;\n\t\t\t\tthis.normalLinks.appendChild (make (' ', true));\n\t\t\t\tthis.normalLinks.appendChild (lk);\n\t\t\t\tif (!noSuggestions && HotCat.use_up_down) {\n\t\t\t\t\tthis.upDownLinks = make ('span');\n\t\t\t\t\tlk = make ('a'); lk.href = '#catlinks'; lk.onclick = bind (this.down, this);\n\t\t\t\t\tlk.appendChild (make (HotCat.links.down, true)); lk.title = HotCat.tooltips.down;\n\t\t\t\t\tthis.upDownLinks.appendChild (make (' ', true));\n\t\t\t\t\tthis.upDownLinks.appendChild (lk);\n\t\t\t\t\tlk = make ('a'); lk.href = '#catlinks'; lk.onclick = bind (this.up, this);\n\t\t\t\t\tlk.appendChild (make (HotCat.links.up, true)); lk.title = HotCat.tooltips.up;\n\t\t\t\t\tthis.upDownLinks.appendChild (make (' ', true));\n\t\t\t\t\tthis.upDownLinks.appendChild (lk);\n\t\t\t\t\tthis.normalLinks.appendChild (this.upDownLinks);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.linkSpan = make ('span');\n\t\t\tthis.linkSpan.className = 'noprint nopopups hotcatlink';\n\t\t\tthis.linkSpan.appendChild (this.normalLinks);\n\t\t\tthis.undelLink = make ('span');\n\t\t\tthis.undelLink.className = 'nopopups hotcatlink';\n\t\t\tthis.undelLink.style.display = 'none';\n\t\t\tlk = make ('a'); lk.href = '#catlinks'; lk.onclick = bind (this.restore, this);\n\t\t\tlk.appendChild (make (HotCat.links.restore, true)); lk.title = HotCat.tooltips.restore;\n\t\t\tthis.undelLink.appendChild (make (' ', true));\n\t\t\tthis.undelLink.appendChild (lk);\n\t\t\tthis.linkSpan.appendChild (this.undelLink);\n\t\t},\n\n\t\tinvokeSuggestions : function (dont_autocomplete) {\n\t\t\tif (this.engine && suggestionConfigs[this.engine] && suggestionConfigs[this.engine].temp && !dont_autocomplete) {\n\t\t\t\tthis.engine = HotCat.suggestions; // Reset to a search upon input\n\t\t\t}\n\t\t\tthis.state = CategoryEditor.CHANGE_PENDING;\n\t\t\tvar self = this;\n\t\t\twindow.setTimeout (function () {self.textchange (dont_autocomplete);}, HotCat.suggest_delay);\n\t\t},\n\n\t\tmakeForm : function () {\n\t\t\tvar form = make ('form');\n\t\t\tform.method = 'POST'; form.onsubmit = bind (this.accept, this);\n\t\t\tthis.form = form;\n\t\t\tvar self = this;\n\t\t\tvar text = make ('input'); text.type = 'text'; text.size = HotCat.editbox_width;\n\t\t\tif (!noSuggestions) {\n\t\t\t\t// Be careful here to handle IME input. This is browser/OS/IME dependent, but basically there are two mechanisms:\n\t\t\t\t// - Modern (DOM Level 3) browsers use compositionstart/compositionend events to signal composition; if the\n\t\t\t\t// composition is not canceled, there'll be a textInput event following. During a composition key events are\n\t\t\t\t// either all suppressed (FF/Gecko), or otherwise have keyDown === IME for all keys (Webkit).\n\t\t\t\t// - Webkit sends a textInput followed by keyDown === IME and a keyUp with the key that ended composition.\n\t\t\t\t// - Gecko doesn't send textInput but just a keyUp with the key that ended composition, without sending keyDown\n\t\t\t\t// first. Gecko doesn't send any keydown while IME is active.\n\t\t\t\t// - Older browsers signal composition by keyDown === IME for the first and subsequent keys for a composition. The\n\t\t\t\t// first keyDown !== IME is certainly after the end of the composition. Typically, composition end can also be\n\t\t\t\t// detected by a keyDown IME with a keyUp of space, tab, escape, or return. (Example: IE8)\n\t\t\t\ttext.onkeyup =\n\t\t\t\t\tfunction (evt) {\n\t\t\t\t\t\tevt = evt || window.event || window.Event; // W3C, IE, Netscape\n\t\t\t\t\t\tvar key = evt.keyCode || 0;\n\t\t\t\t\t\tif (self.ime && self.lastKey === IME && !self.usesComposition && (key === TAB || key === RET || key == ESC || key === SPACE)) self.ime = false;\n\t\t\t\t\t\tif (self.ime) return true;\n\t\t\t\t\t\tif (key === UP || key === DOWN || key === PGUP || key === PGDOWN) {\n\t\t\t\t\t\t\t// In case a browser doesn't generate keypress events for arrow keys...\n\t\t\t\t\t\t\tif (self.keyCount === 0) return self.processKey (evt);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (key === ESC && self.lastKey !== IME) {\n\t\t\t\t\t\t\t\tif (!self.resetKeySelection ()) {\n\t\t\t\t\t\t\t\t\t// No undo of key selection: treat ESC as \"cancel\".\n\t\t\t\t\t\t\t\t\tself.cancel ();\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Also do this for ESC as a workaround for Firefox bug 524360\n\t\t\t\t\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=524360\n\t\t\t\t\t\t\tself.invokeSuggestions (key === BS || key === DEL || key === ESC);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t};\n\t\t\t\ttext.onkeydown =\n\t\t\t\t\tfunction (evt) {\n\t\t\t\t\t\tevt = evt || window.event || window.Event; // W3C, IE, Netscape\n\t\t\t\t\t\tvar key = evt.keyCode || 0;\n\t\t\t\t\t\tself.lastKey = key;\n\t\t\t\t\t\tself.keyCount = 0;\n\t\t\t\t\t\t// DOM Level < 3 IME input\t\n\t\t\t\t\t\tif (!self.ime && key === IME && !self.usesComposition) {\n\t\t\t\t\t\t\t// self.usesComposition catches browsers that may emit spurious keydown IME after a composition has ended\n\t\t\t\t\t\t\tself.ime = true;\n\t\t\t\t\t\t} else if (self.ime && key !== IME && !(key >= 16 && key <= 20 || key >= 91 && key <= 93 || key === 144)) {\n\t\t\t\t\t\t\t// Ignore control keys: ctrl, shift, alt, alt gr, caps lock, windows/apple cmd keys, num lock. Only the windows keys\n\t\t\t\t\t\t\t// terminate IME (apple cmd doesn't), but they also cause a blur, so it's OK to ignore them here.\n\t\t\t\t\t\t\t// Note: Safari 4 (530.17) propagates ESC out of an IME composition (observed at least on Win XP).\n\t\t\t\t\t\t\tself.ime = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (self.ime) return true;\n\t\t\t\t\t\t// Handle return explicitly, to override the default form submission to be able to check for ctrl\n\t\t\t\t\t\tif (key === RET) return self.accept (evt);\n\t\t\t\t\t\t// Inhibit default behavior of ESC (revert to last real input in FF: we do that ourselves)\n\t\t\t\t\t\treturn (key === ESC) ? evtKill(evt) : true;\n\t\t\t\t\t};\n\t\t\t\t// And handle continued pressing of arrow keys\n\t\t\t\ttext.onkeypress = function (evt) {self.keyCount++; return self.processKey (evt);};\n\t\t\t\taddEvent (text, 'focus', function () { makeActive(self); });\n\t\t\t\t// On IE, blur events are asynchronous, and may thus arrive after the element has lost the focus. Since IE\n\t\t\t\t// can get the selection only while the element is active (has the focus), we may not always get the selection.\n\t\t\t\t// Therefore, use an IE-specific synchronous event on IE...\n\t\t\t\t// Don't test for text.selectionStart being defined; FF3.6.4 raises an exception when trying to access that\n\t\t\t\t// property while the element is not being displayed.\n\t\t\t\taddEvent (text\n\t\t\t\t\t, (typeof text.onbeforedeactivate != 'undefined' && text.createTextRange) ? 'beforedeactivate' : 'blur'\n\t\t\t\t\t, bind (this.saveView, this)\n\t\t\t\t);\n\t\t\t\t// DOM Level 3 IME handling\n\t\t\t\ttry {\n\t\t\t\t\t// Setting lastKey = IME provides a fake keyDown for Gecko's single keyUp after a cmposition. If we didn't do this,\n\t\t\t\t\t// cancelling a composition via ESC would also cancel and close the whole category input editor.\n\t\t\t\t\taddEvent(text, 'compositionstart', function (evt) { self.lastKey = IME; self.usesComposition = true; self.ime = true; });\n\t\t\t\t\taddEvent(text, 'compositionend', function (evt) { self.lastKey = IME; self.usesComposition = true; self.ime = false; });\n\t\t\t\t\taddEvent(text, 'textInput', function (evt) { self.ime = false; self.invokeSuggestions(false); });\n\t\t\t\t} catch (any) {\n\t\t\t\t\t// Just in case some browsers might produce exceptions with these DOM Level 3 events\n\t\t\t\t}\n\t\t\t\taddEvent(text, 'blur', function (evt) { self.usesComposition = false; self.ime = false; });\n\t\t\t}\n\t\t\tthis.text = text;\n\n\t\t\tthis.icon = make ('img');\n\n\t\t\tvar list = null;\n\t\t\tif (!noSuggestions) {\n\t\t\t\tlist = make ('select');\n\t\t\t\tlist.onclick = function (e) { if (self.highlightSuggestion(0)) self.textchange (false, true); };\n\t\t\t\tlist.ondblclick = function (e) { if (self.highlightSuggestion(0)) self.accept (e); };\n\t\t\t\tlist.onchange = function (e) { self.highlightSuggestion(0); self.text.focus(); };\n\t\t\t\tlist.onkeyup =\n\t\t\t\t\tfunction (evt) {\n\t\t\t\t\t\tevt = evt || window.event || window.Event; // W3C, IE, Netscape\n\t\t\t\t\t\tif (evt.keyCode === ESC) {\n\t\t\t\t\t\t\tself.resetKeySelection ();\n\t\t\t\t\t\t\tself.text.focus();\n\t\t\t\t\t\t\twindow.setTimeout (function () {self.textchange (true);}, HotCat.suggest_delay);\n\t\t\t\t\t\t} else if (evt.keyCode === RET) {\n\t\t\t\t\t\t\tself.accept (evt);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\tif (!HotCat.fixed_search) {\n\t\t\t\t\tvar engineSelector = make ('select');\n\t\t\t\t\tfor (var key in suggestionConfigs) {\n\t\t\t\t\t\tif (suggestionConfigs[key].show) {\n\t\t\t\t\t\t\tvar opt = make ('option');\n\t\t\t\t\t\t\topt.value = key;\n\t\t\t\t\t\t\tif (key == this.engine) opt.selected = true;\n\t\t\t\t\t\t\topt.appendChild (make (suggestionConfigs[key].name, true));\n\t\t\t\t\t\t\tengineSelector.appendChild (opt);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tengineSelector.onchange =\n\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\tself.engine = self.engineSelector.options[self.engineSelector.selectedIndex].value;\n\t\t\t\t\t\t\tself.text.focus();\n\t\t\t\t\t\t\tself.textchange (true, true); // Don't autocomplete, force re-display of list\n\t\t\t\t\t\t};\n\t\t\t\t\tthis.engineSelector = engineSelector;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.list = list;\n\n\t\t\tfunction button_label (id, defaultText) {\n\t\t\t\tvar label = null;\n\t\t\t\tif ( onUpload\n\t\t\t\t\t&& typeof UFUI != 'undefined'\n\t\t\t\t\t&& typeof UIElements != 'undefined'\n\t\t\t\t\t&& typeof UFUI.getLabel == 'function')\n\t\t\t\t{\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlabel = UFUI.getLabel (id, true);\n\t\t\t\t\t\t// Extract the plain text. IE doesn't know that Node.TEXT_NODE === 3\n\t\t\t\t\t\twhile (label && label.nodeType != 3) label = label.firstChild;\n\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\tlabel = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!label || !label.data) return defaultText;\n\t\t\t\treturn label.data;\n\t\t\t}\n\n\t\t\t// Do not use type 'submit'; we cannot detect modifier keys if we do\n\t\t\tvar OK = make ('input'); OK.type = 'button';\n\t\t\tOK.value = button_label ('wpOkUploadLbl', HotCat.messages.ok);\n\t\t\tOK.onclick = bind (this.accept, this);\n\t\t\tthis.ok = OK;\n\n\t\t\tvar cancel = make ('input'); cancel.type = 'button';\n\t\t\tcancel.value = button_label ('wpCancelUploadLbl', HotCat.messages.cancel);\n\t\t\tcancel.onclick = bind (this.cancel, this);\n\t\t\tthis.cancelButton = cancel;\n\n\t\t\tvar span = make ('span');\n\t\t\tspan.className = 'hotcatinput';\n\t\t\tspan.style.position = 'relative';\n\t\t\t// FF3.6: add the input field first, then the two absolutely positioned elements. Otherwise, FF3.6 may leave the\n\t\t\t// suggestions and the selector at the right edge of the screen if display of the input field causes a re-layout\n\t\t\t// moving the form to the front of the next line.\n\t\t\tspan.appendChild (text);\n\n\t\t\t// IE8/IE9: put some text into this span (a0 is nbsp) and make sure it always stays on the\n\t\t\t// same line as the input field, otherwise, IE8/9 miscalculates the height of the span and\n\t\t\t// then the engine selector may overlap the input field.\n\t\t\tspan.appendChild (make ('\\xa0', true));\n\t\t\tspan.style.whiteSpace = 'nowrap';\n\n\t\t\tif (list) span.appendChild (list);\n\t\t\tif (this.engineSelector) span.appendChild (this.engineSelector);\n\t\t\tif (!noSuggestions) span.appendChild (this.icon);\n\t\t\tspan.appendChild (OK);\n\t\t\tspan.appendChild (cancel);\n\t\t\tform.appendChild(span);\n\t\t\tform.style.display = 'none';\n\t\t\tthis.span.appendChild (form);\n\t\t},\n\n\t\tdisplay : function (evt) {\n\t\t\tif (this.isAddCategory && !onUpload) {\n\t\t\t\tvar newAdder = new CategoryEditor (this.line, null, this.span, true); // Create a new one\n\t\t\t}\n\t\t\tif (!commitButton && !onUpload) {\n\t\t\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\t\t\tif (editors[i].state != CategoryEditor.UNCHANGED) {\n\t\t\t\t\t\tsetMultiInput();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!this.form) {\n\t\t\t\tthis.makeForm ();\n\t\t\t}\n\t\t\tif (this.list) this.list.style.display = 'none';\n\t\t\tif (this.engineSelector) this.engineSelector.style.display = 'none';\n\t\t\tthis.currentCategory = this.lastSavedCategory;\n\t\t\tthis.currentExists = this.lastSavedExists;\n\t\t\tthis.currentHidden = this.lastSavedHidden;\n\t\t\tthis.currentKey = this.lastSavedKey;\n\t\t\tthis.icon.src = armorUri(this.currentExists ? HotCat.existsYes : HotCat.existsNo);\n\t\t\tthis.text.value = this.currentCategory + (this.currentKey !== null ? '|' + this.currentKey : \"\");\n\t\t\tthis.originalState = this.state;\n\t\t\tthis.lastInput = this.currentCategory;\n\t\t\tthis.inputExists = this.currentExists;\n\t\t\tthis.state = this.state == CategoryEditor.UNCHANGED ? CategoryEditor.OPEN : CategoryEditor.CHANGE_PENDING;\n\t\t\tthis.lastSelection = {start: this.currentCategory.length, end: this.currentCategory.length};\n\t\t\tthis.showsList = false;\n\t\t\t// Display the form\n\t\t\tif (this.catLink) this.catLink.style.display = 'none';\n\t\t\tthis.linkSpan.style.display = 'none';\n\t\t\tthis.form.style.display = 'inline';\n\t\t\tthis.ok.disabled = false;\n\t\t\t// Kill the event before focussing, otherwise IE will kill the onfocus event!\n\t\t\tvar result = evtKill (evt);\n\t\t\tthis.text.focus();\n\t\t\tthis.text.readOnly = false;\n\t\t\tcheckMultiInput ();\n\t\t\treturn result;\n\t\t},\n\n\t\tshow : function (evt, engine, readOnly) {\n\t\t\tvar result = this.display (evt);\n\t\t\tvar v = this.lastSavedCategory;\n\t\t\tif (v.length === 0) return result;\n\t\t\tthis.text.readOnly = !!readOnly;\n\t\t\tthis.engine = engine;\n\t\t\tthis.textchange (false, true); // do autocompletion, force display of suggestions\n\t\t\tforceRedraw ();\n\t\t\treturn result;\n\t\t},\n\n\t\topen : function (evt) {\n\t\t\treturn this.show (evt, (this.engine && suggestionConfigs[this.engine].temp) ? HotCat.suggestions : this.engine);\n\t\t},\n\n\t\tdown : function (evt) {\n\t\t\treturn this.show (evt, 'subcat', true);\n\t\t},\n\n\t\tup : function (evt) {\n\t\t\treturn this.show (evt, 'parentcat');\n\t\t},\n\n\t\tcancel : function () {\n\t\t\tif (this.isAddCategory && !onUpload) {\n\t\t\t\tthis.removeEditor(); // We added a new adder when opening\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Close, re-display link\n\t\t\tthis.inactivate();\n\t\t\tthis.form.style.display = 'none';\n\t\t\tif (this.catLink) this.catLink.style.display = \"\";\n\t\t\tthis.linkSpan.style.display = \"\";\n\t\t\tthis.state = this.originalState;\n\t\t\tthis.currentCategory = this.lastSavedCategory;\n\t\t\tthis.currentKey = this.lastSavedKey;\n\t\t\tthis.currentExists = this.lastSavedExists;\n\t\t\tthis.currentHidden = this.lastSavedHidden;\n\t\t\tif (this.catLink) {\n\t\t\t\tif (this.currentKey && this.currentKey.length > 0) {\n\t\t\t\t\tthis.catLink.title = this.currentKey;\n\t\t\t\t} else {\n\t\t\t\t\tthis.catLink.title = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (this.state == CategoryEditor.UNCHANGED) {\n\t\t\t\tif (this.catLink) this.catLink.style.backgroundColor = 'transparent';\n\t\t\t} else {\n\t\t\t\tif (!onUpload) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.catLink.style.backgroundColor = HotCat.bg_changed;\n\t\t\t\t\t} catch (ex) {}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcheckMultiInput ();\n\t\t\tforceRedraw ();\n\t\t},\n\n\t\tremoveEditor : function () {\n\t\t\tif (!newDOM) {\n\t\t\t\tvar next = this.span.nextSibling;\n\t\t\t\tif (next) next.parentNode.removeChild (next);\n\t\t\t}\n\t\t\tthis.span.parentNode.removeChild (this.span);\n\t\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\t\tif (editors[i] == this) {\n\t\t\t\t\teditors.splice (i, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcheckMultiInput ();\n\t\t\tvar self = this;\n\t\t\twindow.setTimeout (function () {delete self;}, 10);\n\t\t},\n\n\t\trollback : function (evt) {\n\t\t\tthis.undoLink.parentNode.removeChild (this.undoLink);\n\t\t\tthis.undoLink = null;\n\t\t\tthis.currentCategory = this.originalCategory;\n\t\t\tthis.currentKey = this.originalKey;\n\t\t\tthis.currentExists = this.originalExists;\n\t\t\tthis.currentHidden = this.originalHidden;\n\t\t\tthis.lastSavedCategory = this.originalCategory;\n\t\t\tthis.lastSavedKey = this.originalKey;\n\t\t\tthis.lastSavedExists = this.originalExists;\n\t\t\tthis.lastSavedHidden = this.originalHidden;\n\t\t\tthis.state = CategoryEditor.UNCHANGED;\n\t\t\tif (!this.currentCategory || this.currentCategory.length === 0) {\n\t\t\t\t// It was a newly added category. Remove the whole editor.\n\t\t\t\tthis.removeEditor();\n\t\t\t} else {\n\t\t\t\t// Redisplay the link...\n\t\t\t\tthis.catLink.removeChild (this.catLink.firstChild);\n\t\t\t\tthis.catLink.appendChild (make (this.currentCategory, true));\n\t\t\t\tthis.catLink.href = wikiPagePath (HotCat.category_canonical + ':' + this.currentCategory);\n\t\t\t\tthis.catLink.title = this.currentKey || \"\";\n\t\t\t\tthis.catLink.className = this.currentExists ? \"\" : 'new';\n\t\t\t\tthis.catLink.style.backgroundColor = 'transparent';\n\t\t\t\tif (this.upDownLinks) this.upDownLinks.style.display = this.currentExists ? \"\" : 'none';\n\t\t\t\tcheckMultiInput ();\n\t\t\t}\n\t\t\treturn evtKill (evt);\n\t\t},\n\n\t\tinactivate : function () {\n\t\t\tif (this.list) this.list.style.display = 'none';\n\t\t\tif (this.engineSelector) this.engineSelector.style.display = 'none';\n\t\t\tthis.is_active = false;\n\t\t},\n\n\t\tacceptCheck : function (dontCheck) {\n\t\t\tthis.sanitizeInput ();\n\t\t\tvar value = this.text.value.split('|');\n\t\t\tvar key = null;\n\t\t\tif (value.length > 1) key = value[1];\n\t\t\tvar v = value[0].replace(/_/g, ' ').replace(/^\\s+|\\s+$/g, \"\");\n\t\t\tif (HotCat.capitalizePageNames) v = capitalize (v);\n\t\t\tthis.lastInput = v;\n\t\t\tv = replaceShortcuts(v, HotCat.shortcuts);\n\t\t\tif (v.length === 0) {\n\t\t\t\tthis.cancel ();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!dontCheck\n\t\t\t\t&& ( conf.wgNamespaceNumber === 14 && v == conf.wgTitle\n\t\t\t\t\t|| HotCat.blacklist && HotCat.blacklist.test(v))\n\t\t\t )\n\t\t\t{\n\t\t\t\tthis.cancel ();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis.currentCategory = v;\n\t\t\tthis.currentKey = key;\n\t\t\tthis.currentExists = this.inputExists;\n\t\t\treturn true;\n\t\t},\n\n\t\taccept : function (evt) {\n\t\t\tthis.noCommit = (evtKeys (evt) & 1) !== 0;\n\t\t\tvar result = evtKill (evt);\n\t\t\tif (this.acceptCheck ()) {\n\t\t\t\tvar toResolve = [this];\n\t\t\t\tvar original = this.currentCategory;\n\t\t\t\tresolveMulti (\n\t\t\t\t\t toResolve\n\t\t\t\t\t,function (resolved) {\n\t\t\t\t\t\tif (resolved[0].dab) {\n\t\t\t\t\t\t\tshowDab (resolved[0]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (resolved[0].acceptCheck(true)) {\n\t\t\t\t\t\t\t\tresolved[0].commit (\n\t\t\t\t\t\t\t\t\t(resolved[0].currentCategory != original)\n\t\t\t\t\t\t\t\t\t\t? HotCat.messages.cat_resolved.replace (/\\$1/g, original)\n\t\t\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t }\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\n\t\tclose : function () {\n\t\t\tif (!this.catLink) {\n\t\t\t\t// Create a catLink\n\t\t\t\tthis.catLink = make ('a');\n\t\t\t\tthis.catLink.appendChild (make ('foo', true));\n\t\t\t\tthis.catLink.style.display = 'none';\n\t\t\t\tthis.span.insertBefore (this.catLink, this.span.firstChild.nextSibling);\n\t\t\t}\n\t\t\tthis.catLink.removeChild (this.catLink.firstChild);\n\t\t\tthis.catLink.appendChild (make (this.currentCategory, true));\n\t\t\tthis.catLink.href = wikiPagePath (HotCat.category_canonical + ':' + this.currentCategory);\n\t\t\tthis.catLink.className = this.currentExists ? \"\" : 'new';\n\t\t\tthis.lastSavedCategory = this.currentCategory;\n\t\t\tthis.lastSavedKey = this.currentKey;\n\t\t\tthis.lastSavedExists = this.currentExists;\n\t\t\tthis.lastSavedHidden = this.currentHidden;\n\t\t\t// Close form and redisplay category\n\t\t\tthis.inactivate();\n\t\t\tthis.form.style.display = 'none';\n\t\t\tthis.catLink.title = this.currentKey || \"\";\n\t\t\tthis.catLink.style.display = \"\";\n\t\t\tif (this.isAddCategory) {\n\t\t\t\tif (onUpload) {\n\t\t\t\t\tvar newAdder = new CategoryEditor (this.line, null, this.span, true); // Create a new one\n\t\t\t\t}\n\t\t\t\tthis.isAddCategory = false;\n\t\t\t\tthis.linkSpan.parentNode.removeChild (this.linkSpan);\n\t\t\t\tthis.makeLinkSpan ();\n\t\t\t\tthis.span.appendChild (this.linkSpan);\n\t\t\t}\n\t\t\tif (!this.undoLink) {\n\t\t\t\t// Append an undo link.\n\t\t\t\tvar span = make ('span');\n\t\t\t\tvar lk = make ('a'); lk.href = '#catlinks'; lk.onclick = bind (this.rollback, this);\n\t\t\t\tlk.appendChild (make (HotCat.links.undo, true)); lk.title = HotCat.tooltips.undo;\n\t\t\t\tspan.appendChild (make (' ', true));\n\t\t\t\tspan.appendChild (lk);\n\t\t\t\tthis.normalLinks.appendChild (span);\n\t\t\t\tthis.undoLink = span;\n\t\t\t\tif (!onUpload) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.catLink.style.backgroundColor = HotCat.bg_changed;\n\t\t\t\t\t} catch (ex) {}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (this.upDownLinks) this.upDownLinks.style.display = this.lastSavedExists ? \"\" : 'none';\n\t\t\tthis.linkSpan.style.display = \"\";\n\t\t\tthis.state = CategoryEditor.CHANGED;\n\t\t\tcheckMultiInput ();\n\t\t\tforceRedraw ();\n\t\t},\n\n\t\tcommit : function (comment) {\n\t\t\t// Check again to catch problem cases after redirect resolution\n\t\t\tif ( ( this.currentCategory == this.originalCategory\n\t\t\t\t\t&& (this.currentKey == this.originalKey\n\t\t\t\t\t\t|| this.currentKey === null && this.originalKey.length === 0\n\t\t\t\t\t )\n\t\t\t\t )\n\t\t\t\t|| conf.wgNamespaceNumber == 14 && this.currentCategory == conf.wgTitle\n\t\t\t\t|| HotCat.blacklist && HotCat.blacklist.test (this.currentCategory)\n\t\t\t )\n\t\t\t{\n\t\t\t\tthis.cancel ();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (commitButton || onUpload) {\n\t\t\t\tthis.close ();\n\t\t\t} else {\n\t\t\t\tthis.close ();\n\t\t\t\tvar self = this;\n\t\t\t\tinitiateEdit (function (failure) {performChanges (failure, self);}, function (msg) {alert (msg);});\n\t\t\t}\n\t\t},\n\n\t\tremove : function (evt) {\n\t\t\tthis.doRemove (evtKeys (evt) & 1);\n\t\t\treturn evtKill (evt);\n\t\t},\n\n\t\tdoRemove : function (noCommit) {\n\t\t\tif (this.isAddCategory) { // Empty input on adding a new category\n\t\t\t\tthis.cancel ();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!commitButton && !onUpload) {\n\t\t\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\t\t\tif (editors[i].state != CategoryEditor.UNCHANGED) {\n\t\t\t\t\t\tsetMultiInput();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (commitButton) {\n\t\t\t\tthis.catLink.title = \"\";\n\t\t\t\tthis.catLink.style.cssText += '; text-decoration : line-through !important;';\n\t\t\t\ttry {\n\t\t\t\t\tthis.catLink.style.backgroundColor = HotCat.bg_changed;\n\t\t\t\t} catch (ex) {}\n\t\t\t\tthis.originalState = this.state;\n\t\t\t\tthis.state = CategoryEditor.DELETED;\n\t\t\t\tthis.normalLinks.style.display = 'none';\n\t\t\t\tthis.undelLink.style.display = \"\";\n\t\t\t\tcheckMultiInput ();\n\t\t\t} else {\n\t\t\t\tif (onUpload) {\n\t\t\t\t\t// Remove this editor completely\n\t\t\t\t\tthis.removeEditor ();\n\t\t\t\t} else {\n\t\t\t\t\tthis.originalState = this.state;\n\t\t\t\t\tthis.state = CategoryEditor.DELETED;\n\t\t\t\t\tthis.noCommit = noCommit || HotCat.del_needs_diff;\n\t\t\t\t\tvar self = this;\n\t\t\t\t\tinitiateEdit (function (failure) {performChanges (failure, self);}, function (msg) {self.state = self.originalState; alert (msg);});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\trestore : function (evt) {\n\t\t\t// Can occur only if we do have a commit button and are not on the upload form\n\t\t\tthis.catLink.title = this.currentKey || \"\";\n\t\t\tthis.catLink.style.textDecoration = \"\";\n\t\t\tthis.state = this.originalState;\n\t\t\tif (this.state == CategoryEditor.UNCHANGED) {\n\t\t\t\tthis.catLink.style.backgroundColor = 'transparent';\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tthis.catLink.style.backgroundColor = HotCat.bg_changed;\n\t\t\t\t} catch (ex) {}\n\t\t\t}\n\t\t\tthis.normalLinks.style.display = \"\";\n\t\t\tthis.undelLink.style.display = 'none';\n\t\t\tcheckMultiInput ();\n\t\t\treturn evtKill (evt);\n\t\t},\n\n\t\t// Internal operations\n\n\t\tselectEngine : function (engineName) {\n\t\t\tif (!this.engineSelector) return;\n\t\t\tfor (var i = 0; i < this.engineSelector.options.length; i++) {\n\t\t\t\tthis.engineSelector.options[i].selected = this.engineSelector.options[i].value == engineName;\n\t\t\t}\n\t\t},\n\n\t\tsanitizeInput : function () {\n\t\t\tvar v = this.text.value || \"\";\n\t\t\tv = v.replace(/^(\\s|_)+/, \"\"); // Trim leading blanks and underscores\n\t\t\tvar re = new RegExp ('^(' + HotCat.category_regexp + '):');\n\t\t\tif (re.test (v)) {\n\t\t\t\tv = v.substring (v.indexOf (':') + 1).replace(/^(\\s|_)+/, \"\");\n\t\t\t}\n\t\t\tif (HotCat.capitalizePageNames) v = capitalize (v);\n\t\t\t// Only update the input field if there is a difference. IE8 appears to reset the selection\n\t\t\t// and place the cursor at the front upon reset, which makes our autocompletetion become a\n\t\t\t// nuisance. FF and IE6 don't seem to have this problem.\n\t\t\tif (this.text.value !== null && this.text.value != v)\n\t\t\t\tthis.text.value = v;\n\t\t},\n\n\t\tmakeCall : function (url, callbackObj, engine, queryKey, cleanKey) {\n\t\t\tvar cb = callbackObj;\n\t\t\tvar e = engine;\n\t\t\tvar v = queryKey;\n\t\t\tvar z = cleanKey;\n\t\t\tvar thisObj = this;\n\n\t\t\tfunction done () {\n\t\t\t\tcb.callsMade++;\n\t\t\t\tif (cb.callsMade === cb.nofCalls) {\n\t\t\t\t\tif (cb.exists) cb.allTitles.exists = true;\n\t\t\t\t\tif (cb.normalized) cb.allTitles.normalized = cb.normalized;\n\t\t\t\t\tif (!cb.dontCache && !suggestionConfigs[cb.engineName].cache[z]) {\n\t\t\t\t\t\tsuggestionConfigs[cb.engineName].cache[z] = cb.allTitles;\n\t\t\t\t\t}\n\t\t\t\t\tthisObj.text.readOnly = false;\n\t\t\t\t\tif (!cb.cancelled) thisObj.showSuggestions (cb.allTitles, cb.noCompletion, v, cb.engineName);\n\t\t\t\t\tif (cb === thisObj.callbackObj) thisObj.callbackObj = null;\n\t\t\t\t\tdelete cb;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgetJSON ({\n\t\t\t uri : url\n\t\t\t ,success : function (json) {\n\t\t\t\tvar titles = e.handler (json, z);\n\t\t\t\tif (titles && titles.length > 0) {\n\t\t\t\t\tif (cb.allTitles === null) {\n\t\t\t\t\t\tcb.allTitles = titles;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcb.allTitles = cb.allTitles.concat (titles);\n\t\t\t\t\t}\n\t\t\t\t\tif (titles.exists) cb.exists = true;\n\t\t\t\t\tif (titles.normalized) cb.normalized = titles.normalized;\n\t\t\t\t}\n\t\t\t\tdone();\n\t\t\t }\n\t\t\t ,error : function (req) {if (!req) noSuggestions = true; cb.dontCache = true; done(); }\n\t\t\t});\n\t\t},\n\n\t\tcallbackObj : null,\n\n\t\ttextchange : function (dont_autocomplete, force) {\n\t\t\t// Hide all other lists\n\t\t\tmakeActive (this);\n\t\t\t// Get input value, omit sort key, if any\n\t\t\tthis.sanitizeInput ();\n\t\t\tvar v = this.text.value;\n\t\t\t// Disregard anything after a pipe.\n\t\t\tvar pipe = v.indexOf ('|');\n\t\t\tif (pipe >= 0) {\n\t\t\t\tthis.currentKey = v.substring (pipe+1);\n\t\t\t\tv = v.substring (0, pipe);\n\t\t\t} else {\n\t\t\t\tthis.currentKey = null;\n\t\t\t}\n\t\t\tif (this.lastInput == v && !force) return; // No change\n\t\t\tif (this.lastInput != v) checkMultiInput ();\n\t\t\tthis.lastInput = v;\n\t\t\tthis.lastRealInput = v;\n\n\t\t\t// Mark blacklisted inputs.\n\t\t\tthis.ok.disabled = v.length > 0 && HotCat.blacklist && HotCat.blacklist.test (v);\n\n\t\t\tif (noSuggestions) {\n\t\t\t\t// No Ajax: just make sure the list is hidden\n\t\t\t\tif (this.list) this.list.style.display = 'none';\n\t\t\t\tif (this.engineSelector) this.engineSelector.style.display = 'none';\n\t\t\t\tif (this.icon) this.icon.style.display = 'none';\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (v.length === 0) { this.showSuggestions([]); return; }\n\t\t\tvar cleanKey = v.replace(/[\\u200E\\u200F\\u202A-\\u202E]/g, \"\").replace(wikiTextBlankRE, ' ');\n\t\t\tcleanKey = replaceShortcuts(cleanKey, HotCat.shortcuts);\n\t\t\tcleanKey = cleanKey.replace(/^\\s+|\\s+$/g, '');\n\t\t\tif (cleanKey.length === 0) { this.showSuggestions([]); return; }\n\n\t\t\tif (this.callbackObj) this.callbackObj.cancelled = true;\n\t\t\tvar engineName = suggestionConfigs[this.engine] ? this.engine : 'combined';\n\n\t\t\tdont_autocomplete = dont_autocomplete || suggestionConfigs[engineName].noCompletion;\n\t\t\tif (suggestionConfigs[engineName].cache[cleanKey]) {\n\t\t\t\tthis.showSuggestions (suggestionConfigs[engineName].cache[cleanKey], dont_autocomplete, v, engineName);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar engines = suggestionConfigs[engineName].engines;\n\t\t\tthis.callbackObj =\n\t\t\t\t{allTitles: null, callsMade: 0, nofCalls: engines.length, noCompletion: dont_autocomplete, engineName: engineName};\n\t\t\tthis.makeCalls (engines, this.callbackObj, v, cleanKey);\n\t\t},\n\n\t\tmakeCalls : function (engines, cb, v, cleanKey) {\n\t\t\tfor (var j = 0; j < engines.length; j++) {\n\t\t\t\tvar engine = suggestionEngines[engines[j]];\n\t\t\t\tvar url = conf.wgServer + conf.wgScriptPath + engine.uri.replace (/\\$1/g, encodeURIComponent (cleanKey));\n\t\t\t\tthis.makeCall (url, cb, engine, v, cleanKey);\n\t\t\t}\n\t\t},\n\n\t\tshowSuggestions : function (titles, dontAutocomplete, queryKey, engineName) {\n\t\t\tthis.text.readOnly = false;\n\t\t\tthis.dab = null;\n\t\t\tthis.showsList = false;\n\t\t\tif (!this.list) return;\n\t\t\tif (noSuggestions) {\n\t\t\t\tif (this.list) this.list.style.display = 'none';\n\t\t\t\tif (this.engineSelector) this.engineSelector.style.display = 'none';\n\t\t\t\tif (this.icon) this.icon.style.display = 'none';\n\t\t\t\tthis.inputExists = true; // Default...\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.engineName = engineName;\n\t\t\tif (engineName) {\n\t\t\t\tif (!this.engineSelector) this.engineName = null;\n\t\t\t} else {\n\t\t\t\tif (this.engineSelector) this.engineSelector.style.display = 'none';\n\t\t\t}\n\t\t\tif (queryKey) {\n\t\t\t\tif (this.lastInput.indexOf (queryKey) !== 0) return;\n\t\t\t\tif (this.lastQuery && this.lastInput.indexOf (this.lastQuery) === 0 && this.lastQuery.length > queryKey.length)\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.lastQuery = queryKey;\n\n\t\t\t// Get current input text\n\t\t\tvar v = this.text.value.split('|');\n\t\t\tvar key = v.length > 1 ? '|' + v[1] : \"\";\n\t\t\tv = (HotCat.capitalizePageNames ? capitalize (v[0]) : v[0]);\n\t\t\tvar vNormalized = v;\n\t\t\tvar knownToExist = titles && titles.exists;\n\t\t\tvar i;\n\t\t\tif (titles) {\n\t\t\t\tif (titles.normalized && v.indexOf(queryKey) === 0) {\n\t\t\t\t\t// We got back a different normalization than what is in the input field\n\t\t\t\t\tvNormalized = titles.normalized + v.substring(queryKey.length);\n\t\t\t\t}\n\t\t\t\tvar vLow = vNormalized.toLowerCase ();\n\t\t\t\t// Strip blacklisted categories\n\t\t\t\tif (HotCat.blacklist) {\n\t\t\t\t\tfor (i = 0; i < titles.length; i++) {\n\t\t\t\t\t\tif (HotCat.blacklist.test (titles[i])) {\n\t\t\t\t\t\t\ttitles.splice(i, 1);\n\t\t\t\t\t\t\ti--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttitles.sort (\n\t\t\t\t\tfunction (a, b) {\n\t\t\t\t\t\tif (a == b) return 0;\n\t\t\t\t\t\tif (a.indexOf (b) === 0) return 1; // a begins with b: a > b\n\t\t\t\t\t\tif (b.indexOf (a) === 0) return -1; // b begins with a: a < b\n\t\t\t\t\t\t// Opensearch may return stuff not beginning with the search prefix!\n\t\t\t\t\t\tvar prefixMatchA = (a.indexOf (vNormalized) === 0 ? 1 : 0);\n\t\t\t\t\t\tvar prefixMatchB = (b.indexOf (vNormalized) === 0 ? 1 : 0);\n\t\t\t\t\t\tif (prefixMatchA != prefixMatchB) return prefixMatchB - prefixMatchA;\n\t\t\t\t\t\t// Case-insensitive prefix match!\n\t\t\t\t\t\tvar aLow = a.toLowerCase(), bLow = b.toLowerCase();\n\t\t\t\t\t\tprefixMatchA = (aLow.indexOf (vLow) === 0 ? 1 : 0);\n\t\t\t\t\t\tprefixMatchB = (bLow.indexOf (vLow) === 0 ? 1 : 0);\n\t\t\t\t\t\tif (prefixMatchA != prefixMatchB) return prefixMatchB - prefixMatchA;\n\t\t\t\t\t\tif (a < b) return -1;\n\t\t\t\t\t\tif (b < a) return 1;\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\t// Remove duplicates and self-references\n\t\t\t\tfor (i = 0; i < titles.length; i++) {\n\t\t\t\t\tif ( i+1 < titles.length && titles[i] == titles[i+1]\n\t\t\t\t\t\t|| conf.wgNamespaceNumber == 14 && titles[i] == conf.wgTitle\n\t\t\t\t\t )\n\t\t\t\t\t{\n\t\t\t\t\t\ttitles.splice (i, 1);\n\t\t\t\t\t\ti--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!titles || titles.length === 0) {\n\t\t\t\tif (this.list) this.list.style.display = 'none';\n\t\t\t\tif (this.engineSelector) this.engineSelector.style.display = 'none';\n\t\t\t\tif (engineName && suggestionConfigs[engineName] && !suggestionConfigs[engineName].temp) {\n\t\t\t\t\tif (this.icon) this.icon.src = armorUri(HotCat.existsNo);\n\t\t\t\t\tthis.inputExists = false;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar firstTitle = titles[0];\n\t\t\tvar completed = this.autoComplete (firstTitle, v, vNormalized, key, dontAutocomplete);\n\t\t\tvar existing = completed || knownToExist || firstTitle == replaceShortcuts(v, HotCat.shortcuts);\n\t\t\tif (engineName && suggestionConfigs[engineName] && !suggestionConfigs[engineName].temp) {\n\t\t\t\tthis.icon.src = armorUri(existing ? HotCat.existsYes : HotCat.existsNo);\n\t\t\t\tthis.inputExists = existing;\n\t\t\t}\n\t\t\tif (completed) {\n\t\t\t\tthis.lastInput = firstTitle;\n\t\t\t\tif (titles.length === 1) {\n\t\t\t\t\tthis.list.style.display = 'none';\n\t\t\t\t\tif (this.engineSelector) this.engineSelector.style.display = 'none';\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// (Re-)fill the list\n\t\t\twhile (this.list.firstChild) this.list.removeChild (this.list.firstChild);\n\t\t\tfor (i = 0 ; i < titles.length ; i++) {\n\t\t\t\tvar opt = make ('option') ;\n\t\t\t\topt.appendChild (make (titles[i], true));\n\t\t\t\topt.selected = completed && (i === 0);\n\t\t\t\tthis.list.appendChild (opt);\n\t\t\t}\n\t\t\tthis.displayList();\n\t\t},\n\n\t\tdisplayList : function () {\n\t\t\tthis.showsList = true;\n\t\t\tif (!this.is_active) {\n\t\t\t\tthis.list.style.display = 'none';\n\t\t\t\tif (this.engineSelector) this.engineSelector.style.display = 'none';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar nofItems = (this.list.options.length > HotCat.list_size ? HotCat.list_size : this.list.options.length);\n\t\t\tif (nofItems <= 1) nofItems = 2;\n\t\t\tthis.list.size = nofItems;\n\t\t\tthis.list.style.align = is_rtl ? 'right' : 'left';\n\t\t\tthis.list.style.zIndex = 5;\n\t\t\tthis.list.style.position = 'absolute';\n\t\t\t// Compute initial list position. First the height.\n\t\t\tvar anchor = is_rtl ? 'right' : 'left';\n\t\t\tvar listh = 0;\n\t\t\tif (this.list.style.display == 'none') {\n\t\t\t\t// Off-screen display to get the height\n\t\t\t\tthis.list.style.top = this.text.offsetTop + 'px';\n\t\t\t\tthis.list.style[anchor] = '-10000px';\n\t\t\t\tthis.list.style.display = \"\";\n\t\t\t\tlisth = this.list.offsetHeight;\n\t\t\t\tthis.list.style.display = 'none';\n\t\t\t} else {\n\t\t\t\tlisth = this.list.offsetHeight;\n\t\t\t}\n\t\t\t// Approximate calculation of maximum list size\n\t\t\tvar maxListHeight = listh;\n\t\t\tif (nofItems < HotCat.list_size) maxListHeight = (listh / nofItems) * HotCat.list_size;\n\n\t\t\tfunction viewport (what) {\n\t\t\t\tif (is_webkit && !document.evaluate)\n\t\t\t\t\treturn window['inner' + what]; // Safari < 3.0\n\t\t\t\tvar s = 'client' + what;\n\t\t\t\tif (window.opera) return document.body[s];\n\t\t\t\treturn (document.documentElement ? document.documentElement[s] : 0)\n\t\t\t\t\t|| document.body[s] || 0;\n\t\t\t}\n\t\t\tfunction scroll_offset (what) {\n\t\t\t\tvar s = 'scroll' + what;\n\t\t\t\tvar result = (document.documentElement ? document.documentElement[s] : 0)\n\t\t\t\t\t\t\t|| document.body[s] || 0;\n\t\t\t\tif (is_rtl && what == 'Left') {\n\t\t\t\t\t// RTL inconsistencies.\n\t\t\t\t\t// FF: 0 at the far right, then increasingly negative values.\n\t\t\t\t\t// IE >= 8: 0 at the far right, then increasingly positive values.\n\t\t\t\t\t// Webkit: scrollWidth - clientWidth at the far right, then down to zero.\n\t\t\t\t\t// IE 7: like webkit; IE6: disabled in RTL anyway since too many problems.\n\t\t\t\t\t// Opera: don't know...\n\t\t\t\t\tif (result < 0) result = - result;\n\t\t\t\t\tif (!is_webkit && !is_ie_lt8) {\n\t\t\t\t\t\tresult = scroll_offset('Width') - viewport('Width') - result;\n\t\t\t\t\t}\n\t\t\t\t\t// Now all have webkit behavior, i.e. zero if at the leftmost edge.\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\tfunction position (node) {\n\t\t\t\t// Stripped-down simplified position function. It's good enough for our purposes.\n\t\t\t\tif (node.getBoundingClientRect) {\n\t\t\t\t\tvar box = node.getBoundingClientRect ();\n\t\t\t\t\treturn { x : Math.round (box.left + scroll_offset ('Left'))\n\t\t\t\t\t\t\t,y : Math.round (box.top + scroll_offset ('Top'))\n\t\t\t\t\t\t };\n\t\t\t\t}\n\t\t\t\tvar t = 0, l = 0;\n\t\t\t\tdo {\n\t\t\t\t\tt = t + (node.offsetTop || 0);\n\t\t\t\t\tl = l + (node.offsetLeft || 0);\n\t\t\t\t\tnode = node.offsetParent;\n\t\t\t\t} while (node);\n\t\t\t\treturn {x : l, y : t};\n\t\t\t}\n\n\t\t\tvar textPos = position (this.text);\n\t\t\tvar nl = 0;\n\t\t\tvar nt = 0;\n\t\t\tvar offset = 0;\n\t\t\t// Opera 9.5 somehow has offsetWidth = 0 here?? Use the next best value...\n\t\t\tvar textBoxWidth = this.text.offsetWidth || this.text.clientWidth;\n\t\t\tif (this.engineName) {\n\t\t\t\tthis.engineSelector.style.zIndex = 5;\n\t\t\t\tthis.engineSelector.style.position = 'absolute';\n\t\t\t\tthis.engineSelector.style.width = textBoxWidth + 'px';\n\t\t\t\t// Figure out the height of this selector: display it off-screen, then hide it again.\n\t\t\t\tif (this.engineSelector.style.display == 'none') {\n\t\t\t\t\tthis.engineSelector.style[anchor] = '-10000px';\n\t\t\t\t\tthis.engineSelector.style.top = '0px';\n\t\t\t\t\tthis.engineSelector.style.display = \"\";\n\t\t\t\t\toffset = this.engineSelector.offsetHeight;\n\t\t\t\t\tthis.engineSelector.style.display = 'none';\n\t\t\t\t} else {\n\t\t\t\t\toffset = this.engineSelector.offsetHeight;\n\t\t\t\t}\n\t\t\t\tthis.engineSelector.style[anchor] = nl + 'px';\n\t\t\t}\n\t\t\tif (textPos.y < maxListHeight + offset + 1) {\n\t\t\t\t// The list might extend beyond the upper border of the page. Let's avoid that by placing it\n\t\t\t\t// below the input text field.\n\t\t\t\tnt = this.text.offsetHeight + offset + 1;\n\t\t\t\tif (this.engineName) this.engineSelector.style.top = this.text.offsetHeight + 'px';\n\t\t\t} else {\n\t\t\t\tnt = - listh - offset - 1;\n\t\t\t\tif (this.engineName) this.engineSelector.style.top = - (offset + 1) + 'px';\n\t\t\t}\n\t\t\tthis.list.style.top = nt + 'px';\n\t\t\tthis.list.style.width = \"\"; // No fixed width (yet)\n\t\t\tthis.list.style[anchor] = nl + 'px';\n\t\t\tif (this.engineName) {\n\t\t\t\tthis.selectEngine (this.engineName);\n\t\t\t\tthis.engineSelector.style.display = \"\";\n\t\t\t}\n\t\t\tthis.list.style.display = 'block';\n\t\t\t// Set the width of the list\n\t\t\tif (this.list.offsetWidth < textBoxWidth ) {\n\t\t\t\tthis.list.style.width = textBoxWidth + 'px';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// If the list is wider than the textbox: make sure it fits horizontally into the browser window\n\t\t\tvar scroll = scroll_offset ('Left');\n\t\t\tvar view_w = viewport ('Width');\n\t\t\tvar w = this.list.offsetWidth;\n\t\t\tvar l_pos = position (this.list);\n\t\t\tvar left = l_pos.x;\n\t\t\tvar right = left + w;\n\t\t\tif (left < scroll || right > scroll + view_w) {\n\t\t\t\tif (w > view_w) {\n\t\t\t\t\tw = view_w;\n\t\t\t\t\tthis.list.style.width = w + 'px';\n\t\t\t\t\tif (is_rtl) {\n\t\t\t\t\t\tleft = right - w;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tright = left + w;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvar relative_offset = 0;\n\t\t\t\tif (left < scroll) {\n\t\t\t\t\trelative_offset = scroll - left;\n\t\t\t\t} else if (right > scroll + view_w) {\n\t\t\t\t\trelative_offset = - (right - scroll - view_w);\n\t\t\t\t}\n\t\t\t\tif (is_rtl) relative_offset = - relative_offset;\n\t\t\t\tif (relative_offset !== 0) {\n\t\t\t\t\tthis.list.style[anchor] = (nl + relative_offset) + 'px';\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tautoComplete : function (newVal, actVal, normalizedActVal, key, dontModify) {\n\t\t\tif (newVal == actVal) return true;\n\t\t\tif (dontModify || this.ime || !this.canSelect()) return false;\n\t\t\t// If we can't select properly or an IME composition is ongoing, autocompletion would be a major annoyance to the user.\n\t\t\tif (newVal.indexOf (actVal) !== 0) {\n\t\t\t\t// Maybe it'll work with the normalized value (NFC)?\n\t\t\t\tif (normalizedActVal && newVal.indexOf(normalizedActVal) === 0) {\n\t\t\t\t\tif (this.lastRealInput == actVal) this.lastRealInput = normalizedActVal;\n\t\t\t\t\tactVal = normalizedActVal;\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Actual input is a prefix of the new text. Fill in new text, selecting the newly added suffix\n\t\t\t// such that it can be easily removed by typing backspace if the suggestion is unwanted.\n\t\t\tthis.text.focus();\n\t\t\tthis.text.value = newVal + key;\n\t\t\tthis.setSelection (actVal.length, newVal.length);\n\t\t\treturn true;\n\t\t},\n\n\t\tcanSelect : function () {\n\t\t\treturn this.text.setSelectionRange\n\t\t\t\t|| this.text.createTextRange\n\t\t\t\t|| typeof this.text.selectionStart != 'undefined'\n\t\t\t\t && typeof this.text.selectionEnd != 'undefined';\n\t\t},\n\n\t\tsetSelection : function (from, to) {\n\t\t\t// this.text must be focused (at least on IE)\n\t\t\tif (!this.text.value) return;\n\t\t\tif (this.text.setSelectionRange) { // e.g. khtml\n\t\t\t\tthis.text.setSelectionRange (from, to);\n\t\t\t} else if (typeof this.text.selectionStart != 'undefined') {\n\t\t\t\tif (from > this.text.selectionStart) {\n\t\t\t\t\tthis.text.selectionEnd = to;\n\t\t\t\t\tthis.text.selectionStart = from;\n\t\t\t\t} else {\n\t\t\t\t\tthis.text.selectionStart = from;\n\t\t\t\t\tthis.text.selectionEnd = to;\n\t\t\t\t}\n\t\t\t} else if (this.text.createTextRange) { // IE\n\t\t\t\tvar new_selection = this.text.createTextRange();\n\t\t\t\tnew_selection.move ('character', from);\n\t\t\t\tnew_selection.moveEnd ('character', to - from);\n\t\t\t\tnew_selection.select();\n\t\t\t}\n\t\t},\n\n\t\tgetSelection : function () {\n\t\t\tvar from = 0, to = 0;\n\t\t\t// this.text must be focused (at least on IE)\n\t\t\tif (!this.text.value) {\n\t\t\t\t// No text.\n\t\t\t} else if (typeof this.text.selectionStart != 'undefined') {\n\t\t\t\tfrom = this.text.selectionStart;\n\t\t\t\tto = this.text.selectionEnd;\n\t\t\t} else if (document.selection && document.selection.createRange) { // IE\n\t\t\t\tvar rng = document.selection.createRange().duplicate();\n\t\t\t\tif (rng.parentElement() === this.text) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar textRng = this.text.createTextRange();\n\t\t\t\t\t\ttextRng.move('character', 0);\n\t\t\t\t\t\ttextRng.setEndPoint('EndToEnd', rng);\n\t\t\t\t\t\t// We're in a single-line input box: no need to care about IE's strange\n\t\t\t\t\t\t// handling of line ends\n\t\t\t\t\t\tto = textRng.text.length;\n\t\t\t\t\t\ttextRng.setEndPoint('EndToStart', rng);\n\t\t\t\t\t\tfrom = textRng.text.length;\n\t\t\t\t\t} catch (notFocused) {\n\t\t\t\t\t\tfrom = this.text.value.length; to = from; // At end of text\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {start: from, end: to};\n\t\t},\n\n\t\tsaveView : function (evt) {\n\t\t\tthis.lastSelection = this.getSelection ();\n\t\t},\n\n\t\tprocessKey : function (evt) {\n\t\t\tvar dir = 0;\n\t\t\tswitch (this.lastKey) {\n\t\t\t\tcase UP: dir = -1;\n\t\t\t\tcase DOWN: if (dir === 0) dir = 1; \n\t\t\t\tcase PGUP: if (dir === 0) dir = -HotCat.list_size;\n\t\t\t\tcase PGDOWN: if (dir === 0) dir = HotCat.list_size;\n\t\t\t\t\tif (this.list.style.display != 'none') {\n\t\t\t\t\t\t// List is visible, so there are suggestions\n\t\t\t\t\t\tthis.highlightSuggestion (dir);\n\t\t\t\t\t\t// Kill the event, otherwise some browsers (e.g., Firefox) may additionally treat an up-arrow\n\t\t\t\t\t\t// as \"place the text cursor at the front\", which we don't want here.\n\t\t\t\t\t\treturn evtKill (evt);\n\t\t\t\t\t} else if ( this.keyCount <= 1\n\t\t\t\t\t\t\t && (!this.callbackObj || this.callbackObj.callsMade == this.callbackObj.nofCalls)\n\t\t\t\t\t\t\t )\n\t\t\t\t\t{\n\t\t\t\t\t\t// If no suggestions displayed, get them, unless we're already getting them.\n\t\t\t\t\t\tthis.textchange ();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase ESC: // Inhibit default behavior (revert to last real input in FF: we do that ourselves)\n\t\t\t\t\treturn evtKill (evt);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\thighlightSuggestion : function (dir) {\n\t\t\tif (noSuggestions || !this.list || this.list.style.display == 'none') return false;\n\t\t\tvar curr = this.list.selectedIndex;\n\t\t\tvar tgt = -1;\n\t\t\tif (dir === 0) {\n\t\t\t\tif (curr < 0 || curr >= this.list.options.length) return false;\n\t\t\t\ttgt = curr;\n\t\t\t} else {\n\t\t\t\ttgt = curr < 0 ? 0 : curr + dir;\n\t\t\t\ttgt = tgt < 0 ? 0 : tgt;\n\t\t\t\tif (tgt >= this.list.options.length) tgt = this.list.options.length - 1;\n\t\t\t}\n\t\t\tif (tgt != curr || dir === 0) {\n\t\t\t\tif (curr >= 0 && curr < this.list.options.length && dir !== 0) this.list.options[curr].selected = false;\n\t\t\t\tthis.list.options[tgt].selected = true;\n\t\t\t\t// Get current input text\n\t\t\t\tvar v = this.text.value.split('|');\n\t\t\t\tvar key = v.length > 1 ? '|' + v[1] : \"\";\n\t\t\t\tvar completed = this.autoComplete (this.list.options[tgt].text, this.lastRealInput, null, key, false);\n\t\t\t\tif (!completed || this.list.options[tgt].text == this.lastRealInput) {\n\t\t\t\t\tthis.text.value = this.list.options[tgt].text + key;\n\t\t\t\t\tif (this.canSelect()) this.setSelection (this.list.options[tgt].text.length, this.list.options[tgt].text.length);\n\t\t\t\t}\n\t\t\t\tthis.lastInput = this.list.options[tgt].text;\n\t\t\t\tthis.inputExists = true; // Might be wrong if from a dab list...\n\t\t\t\tif (this.icon) this.icon.src = armorUri(HotCat.existsYes);\n\t\t\t\tthis.state = CategoryEditor.CHANGE_PENDING;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\tresetKeySelection : function () {\n\t\t\tif (noSuggestions || !this.list || this.list.style.display == 'none') return false;\n\t\t\tvar curr = this.list.selectedIndex;\n\t\t\tif (curr >= 0 && curr < this.list.options.length) {\n\t\t\t\tthis.list.options[curr].selected = false;\n\t\t\t\t// Get current input text\n\t\t\t\tvar v = this.text.value.split('|');\n\t\t\t\tvar key = v.length > 1 ? '|' + v[1] : \"\";\n\t\t\t\t// ESC is handled strangely by some browsers (e.g., FF); somehow it resets the input value before\n\t\t\t\t// our event handlers ever get a chance to run.\n\t\t\t\tvar result = v[0] != this.lastInput;\n\t\t\t\tif (v[0] != this.lastRealInput) {\n\t\t\t\t\tthis.text.value = this.lastRealInput + key;\n\t\t\t\t\tresult = true;\n\t\t\t\t}\n\t\t\t\tthis.lastInput = this.lastRealInput;\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t}; // end CategoryEditor.prototype\n\n\tfunction initialize () {\n\t\t// User configurations. Do this here, called from the onload handler, so that users can\n\t\t// override it easily in their own user script files by just declaring variables. JSconfig\n\t\t// is some feature used at Wikimedia Commons.\n\t\tvar config = (typeof JSconfig != 'undefined' && JSconfig.keys) ? JSconfig.keys : {};\n\t\tHotCat.dont_add_to_watchlist =\n\t\t\t(typeof window.hotcat_dont_add_to_watchlist != 'undefined'\n\t\t\t\t? !!window.hotcat_dont_add_to_watchlist\n\t\t\t\t: (typeof config.HotCatDontAddToWatchlist != 'undefined'\n\t\t\t\t\t? config.HotCatDontAddToWatchlist\n\t\t\t\t\t: HotCat.dont_add_to_watchlist\n\t\t\t\t )\n\t\t\t);\n\t\tHotCat.no_autocommit =\n\t\t\t(typeof window.hotcat_no_autocommit != 'undefined'\n\t\t\t\t? !!window.hotcat_no_autocommit\n\t\t\t\t: (typeof config.HotCatNoAutoCommit != 'undefined'\n\t\t\t\t\t? config.HotCatNoAutoCommit\n\t\t\t\t\t: HotCat.no_autocommit\n\t\t\t\t )\n\t\t\t);\n\t\tHotCat.del_needs_diff =\n\t\t\t(typeof window.hotcat_del_needs_diff != 'undefined'\n\t\t\t\t? !!window.hotcat_del_needs_diff\n\t\t\t\t: (typeof config.HotCatDelNeedsDiff != 'undefined'\n\t\t\t\t\t? config.HotCatDelNeedsDiff\n\t\t\t\t\t: HotCat.del_needs_diff\n\t\t\t\t )\n\t\t\t);\n\t\tHotCat.suggest_delay = window.hotcat_suggestion_delay\n\t\t\t\t\t\t\t|| config['HotCatSuggestionDelay']\n\t\t\t\t\t\t\t|| HotCat.suggest_delay;\n\t\tHotCat.editbox_width = window.hotcat_editbox_width\n\t\t\t\t\t\t\t|| config['HotCatEditBoxWidth']\n\t\t\t\t\t\t\t|| HotCat.editbox_width;\n\t\tHotCat.suggestions = window.hotcat_suggestions\n\t\t\t\t\t\t\t|| config['HotCatSuggestions']\n\t\t\t\t\t\t\t|| HotCat.suggestions;\n\t\tif (typeof HotCat.suggestions != 'string' || !suggestionConfigs[HotCat.suggestions])\n\t\t\tHotCat.suggestions = 'combined';\n\t\tHotCat.fixed_search =\n\t\t\t(typeof window.hotcat_suggestions_fixed != 'undefined'\n\t\t\t\t? !!window.hotcat_suggestions_fixed\n\t\t\t\t: (typeof config.HotCatFixedSuggestions != 'undefined'\n\t\t\t\t\t? config.HotCatFixedSuggestions\n\t\t\t\t\t: HotCat.fixed_search\n\t\t\t\t )\n\t\t\t);\n\t\tHotCat.single_minor =\n\t\t\t(typeof window.hotcat_single_changes_are_minor != 'undefined'\n\t\t\t\t? !!window.hotcat_single_changes_are_minor\n\t\t\t\t: (typeof config.HotCatMinorSingleChanges != 'undefined'\n\t\t\t\t\t? config.HotCatMinorSingleChanges\n\t\t\t\t\t: HotCat.single_minor\n\t\t\t\t )\n\t\t\t);\n\t\tHotCat.bg_changed = window.hotcat_changed_background\n\t\t\t\t\t\t\t|| config.HotCatChangedBackground\n\t\t\t\t\t\t\t|| HotCat.bg_changed;\n\t\tHotCat.use_up_down =\n\t\t\t(typeof window.hotcat_use_category_links != 'undefined'\n\t\t\t\t? !!window.hotcat_use_category_links\n\t\t\t\t: (typeof config.HotCatUseCategoryLinks != 'undefined'\n\t\t\t\t\t? config.HotCatUseCategoryLinks\n\t\t\t\t\t: HotCat.use_up_down\n\t\t\t\t )\n\t\t\t);\n\t\tHotCat.list_size = window.hotcat_list_size\n\t\t\t\t\t\t\t|| config.HotCatListSize\n\t\t\t\t\t\t\t|| HotCat.list_size;\n\t\t// Numeric input, make sure we have a numeric value\n\t\tHotCat.list_size = parseInt (HotCat.list_size, 10);\n\t\tif (isNaN (HotCat.list_size) || HotCat.list_size < 5) HotCat.list_size = 5;\n\t\tif (HotCat.list_size > 15) HotCat.list_size = 15;\n\t\t// Localize search engine names\n\t\tif (HotCat.engine_names) {\n\t\t\tfor (var key in HotCat.engine_names) {\n\t\t\t\tif (suggestionConfigs[key] && HotCat.engine_names[key]) {\n\t\t\t\t\tsuggestionConfigs[key].name = HotCat.engine_names[key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Catch both native RTL and \"faked\" RTL through [[MediaWiki:Rtl.js]]\n\t\tis_rtl = hasClass (document.body, 'rtl');\n\t\tif (!is_rtl) {\n\t\t\tif (document.defaultView && document.defaultView.getComputedStyle) { // Gecko etc.\n\t\t\t\tis_rtl = document.defaultView.getComputedStyle (document.body, null).getPropertyValue ('direction');\n\t\t\t} else if (document.body.currentStyle) { // IE, has subtle differences to getComputedStyle\n\t\t\t\tis_rtl = document.body.currentStyle['direction'];\n\t\t\t} else { // Not exactly right, but best effort\n\t\t\t\tis_rtl = document.body.style['direction'];\n\t\t\t}\n\t\t\tis_rtl = (is_rtl == 'rtl');\n\t\t}\n\t}\n\n\tfunction can_edit () {\n\t\tvar container = null;\n\t\tswitch (mw.config.get('skin')) {\n\t\t\tcase 'cologneblue':\n\t\t\t\tcontainer = document.getElementById ('quickbar');\n\t\t\t\t// Fall through\n\t\t\tcase 'standard':\n\t\t\tcase 'nostalgia':\n\t\t\t\tif (!container) container = document.getElementById ('topbar');\n\t\t\t\tvar lks = container.getElementsByTagName ('a');\n\t\t\t\tfor (var i = 0; i < lks.length; i++) {\n\t\t\t\t\tif ( param ('title', lks[i].href) == conf.wgPageName\n\t\t\t\t\t\t&& param ('action', lks[i].href) == 'edit')\n\t\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\tdefault:\n\t\t\t\t// all modern skins:\n\t\t\t\treturn document.getElementById ('ca-edit') !== null;\n\t\t}\n\t\treturn false;\n\t}\n\n\tfunction setup_upload () {\n\t\tonUpload = true;\n\t\t// Add an empty category bar at the end of the table containing the description, and change the onsubmit handler.\n\t\tvar ip = document.getElementById ('mw-htmlform-description') || document.getElementById ('wpDestFile');\n\t\tif (!ip) {\n\t\t\tip = document.getElementById ('wpDestFile');\n\t\t\twhile (ip && ip.nodeName.toLowerCase() != 'table') ip = ip.parentNode;\n\t\t}\n\t\tif (!ip) return;\n\t\tvar reupload = document.getElementById ('wpForReUpload');\n\t\tvar destFile = document.getElementById ('wpDestFile');\n\t\tif ( (reupload && !!reupload.value)\n\t\t\t|| (destFile && (destFile.disabled || destFile.readOnly)))\n\t\t\treturn; // re-upload form...\n\t\t// Insert a table row with two fields (label and empty category bar)\n\t\tvar labelCell = make ('td');\n\t\tvar lineCell = make ('td');\n\t\t// Create the category line\n\t\tcatLine = make ('div');\n\t\tcatLine.className = 'catlinks';\n\t\tcatLine.id = 'catlinks';\n\t\tcatLine.style.textAlign = is_rtl ? 'right' : 'left';\n\t\t// We'll be inside a table row. Make sure that we don't have margins or strange borders.\n\t\tcatLine.style.margin = '0';\n\t\tcatLine.style.border = 'none';\n\t\tlineCell.appendChild (catLine);\n\t\t// Create the label\n\t\tvar label = null;\n\t\tif ( typeof UFUI != 'undefined'\n\t\t\t&& typeof UIElements != 'undefined'\n\t\t\t&& typeof UFUI.getLabel == 'function'\n\t\t )\n\t\t{\n\t\t\ttry {\n\t\t\t\tlabel = UFUI.getLabel('wpCategoriesUploadLbl');\n\t\t\t} catch (ex) {\n\t\t\t\tlabel = null;\n\t\t\t}\n\t\t}\n\t\tif (!label) {\n\t\t\tlabelCell.id = 'hotcatLabel';\n\t\t\tlabelCell.appendChild (make (HotCat.categories, true));\n\t\t} else {\n\t\t\tlabelCell.id = 'hotcatLabelTranslated';\n\t\t\tlabelCell.appendChild (label);\n\t\t}\n\t\tlabelCell.className = 'mw-label';\n\t\tlabelCell.style.textAlign = 'right';\n\t\tlabelCell.style.verticalAlign = 'middle';\n\t\t// Change the onsubmit handler\n\t\tvar form = document.getElementById('upload') || document.getElementById('mw-upload-form');\n\t\tif (form) {\n\t\t\tvar newRow = ip.insertRow (-1);\n\t\t\tnewRow.appendChild (labelCell);\n\t\t\tnewRow.appendChild (lineCell);\n\t\t\tform.onsubmit = (function (oldSubmit) {\n\t\t\t\treturn function () {\n\t\t\t\t\tvar do_submit = true;\n\t\t\t\t\tif (oldSubmit) {\n\t\t\t\t\t\tif (typeof oldSubmit == 'string')\n\t\t\t\t\t\t\tdo_submit = eval (oldSubmit);\n\t\t\t\t\t\telse if (typeof oldSubmit == 'function')\n\t\t\t\t\t\t\tdo_submit = oldSubmit.apply (form, arguments);\n\t\t\t\t\t}\n\t\t\t\t\tif (!do_submit) return false;\n\t\t\t\t\tcloseForm ();\n\t\t\t\t\t// Copy the categories\n\t\t\t\t\tvar eb = document.getElementById ('wpUploadDescription')\n\t\t\t\t\t\t|| document.getElementById ('wpDesc');\n\t\t\t\t\tvar addedOne = false;\n\t\t\t\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\t\t\t\tvar t = editors[i].currentCategory;\n\t\t\t\t\t\tif (!t) continue ;\n\t\t\t\t\t\tvar key = editors[i].currentKey;\n\t\t\t\t\t\tvar new_cat = '[[' + HotCat.category_canonical + ':' + t + (key ? '|' + key : \"\") + ']]';\n\t\t\t\t\t\t// Only add if not already present\n\t\t\t\t\t\tvar cleanedText = eb.value\n\t\t\t\t\t\t\t\t.replace(/<\\!--(\\s|\\S)*?--\\>/g, \"\")\n\t\t\t\t\t\t\t\t.replace(/<nowiki\\>(\\s|\\S)*?<\\/nowiki>/g, \"\");\n\t\t\t\t\t\tif (!find_category (cleanedText, t, true)) {\n\t\t\t\t\t\t\teb.value += '\\n' + new_cat;\n\t\t\t\t\t\t\taddedOne = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (addedOne) {\n\t\t\t\t\t\t// Remove \"subst:unc\" added by Flinfo if it didn't find categories\n\t\t\t\t\t\teb.value = eb.value.replace(/\\{\\{subst:unc\\}\\}/g, \"\");\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t};\n\t\t\t}) (form.onsubmit);\n\t\t}\n\t}\n\n\tvar cleanedText = null;\n\n\tfunction isOnPage (span) {\n\t\tvar catTitle = title (span.firstChild.getAttribute ('href', 2));\n\t\tif (!catTitle) return null;\n\t\tcatTitle = catTitle.substr (catTitle.indexOf (':') + 1).replace (/_/g, ' ');\n\t\tif (HotCat.blacklist && HotCat.blacklist.test (catTitle)) return null;\n\t\tvar result = { title : catTitle, match : [\"\", \"\", \"\"] };\n\t\tif (pageText === null) return result;\n\t\tif (cleanedText === null) {\n\t\t\tcleanedText = pageText\n\t\t\t\t.replace(/<\\!--(\\s|\\S)*?--\\>/g, \"\")\n\t\t\t\t.replace(/<nowiki\\>(\\s|\\S)*?<\\/nowiki>/g, \"\");\n\t\t}\n\t\tresult.match = find_category (cleanedText, catTitle, true);\n\t\treturn result;\n\t}\n\n\tvar initialized = false;\n\tvar setupTimeout = null;\n\n\tfunction findByClass (scope, tag, className) {\n\t\t// Compatibility routine. Uses jQuery if available, otherwise works with older getElementsByClassName\n\t\tvar result;\n\t\tif (window.jQuery) {\n\t\t\tresult = window.jQuery(scope).find(tag + '.' + className);\n\t\t} else {\n\t\t\tresult = getElementsByClassName(scope, tag, className);\n\t\t}\n\t\treturn (result && result.length) ? result[0] : null;\n\t}\n\n\tfunction setup (additionalWork) {\n\t\tif (initialized) return;\n\t\tinitialized = true;\n\t\tif (setupTimeout) {\n\t\t\twindow.clearTimeout (setupTimeout);\n\t\t\tsetupTimeout = null;\n\t\t}\n\t\t// Find the category bar, or create an empty one if there isn't one. Then add -/+- links after\n\t\t// each category, and add the + link.\n\t\tcatLine = catLine // Special:Upload\n\t\t\t\t|| document.getElementById ('mw-normal-catlinks') // MW >= 1.13alpha\n\t\t\t\t|| findByClass (document , 'p' , 'catlinks'); // MW < 1.13\n\t\tvar hiddenCats = document.getElementById ('mw-hidden-catlinks');\n\t\tif (!catLine) {\n\t\t\tvar footer = null;\n\t\t\tif (!hiddenCats) {\n\t\t\t\tfooter = findByClass (document , 'div' , 'printfooter');\n\t\t\t\tif (!footer) return; // Don't know where to insert the category line\n\t\t\t}\n\t\t\tcatLine = make ('div');\n\t\t\tcatLine.id = 'mw-normal-catlinks';\n\t\t\tcatLine.style.textAlign = is_rtl ? 'right' : 'left';\n\t\t\t// Add a label\n\t\t\tvar label = make ('a');\n\t\t\tlabel.href = conf.wgArticlePath.replace ('$1', 'Special:Categories');\n\t\t\tlabel.title = HotCat.categories;\n\t\t\tlabel.appendChild (make (HotCat.categories, true));\n\t\t\tcatLine.appendChild (label);\n\t\t\tcatLine.appendChild (make (':', true));\n\t\t\t// Insert the new category line\n\t\t\tvar container = (hiddenCats ? hiddenCats.parentNode : document.getElementById ('catlinks'));\n\t\t\tif (!container) {\n\t\t\t\tcontainer = make ('div');\n\t\t\t\tcontainer.id = 'catlinks';\n\t\t\t\tfooter.parentNode.insertBefore (container, footer.nextSibling);\n\t\t\t}\n\t\t\tcontainer.className = 'catlinks noprint';\n\t\t\tcontainer.style.display = \"\";\n\t\t\tif (!hiddenCats) {\n\t\t\t\tcontainer.appendChild (catLine);\n\t\t\t} else {\n\t\t\t\tcontainer.insertBefore (catLine, hiddenCats);\n\t\t\t}\n\t\t} // end if catLine exists\n\t\tif (is_rtl) catLine.dir = 'rtl';\n\n\t\t// Create editors for all existing categories\n\n\t\tfunction createEditors (line, is_hidden) {\n\t\t\tvar i;\n\t\t\tvar cats = line.getElementsByTagName ('li');\n\t\t\tif (cats.length > 0) {\n\t\t\t\tnewDOM = true; line = cats[0].parentNode;\n\t\t\t} else {\n\t\t\t\tcats = line.getElementsByTagName ('span');\n\t\t\t}\n\t\t\t// Copy cats, otherwise it'll also magically contain our added spans as it is a live collection!\n\t\t\tvar copyCats = new Array (cats.length);\n\t\t\tfor (i = 0; i < cats.length; i++) copyCats[i] = cats[i];\n\t\t\tvar editor = null;\n\t\t\tfor (i = 0; i < copyCats.length; i++) {\n\t\t\t\tvar test = isOnPage (copyCats[i]);\n\t\t\t\tif (test !== null && test.match !== null) {\n\t\t\t\t\teditor = new CategoryEditor (line, copyCats[i], test.title, test.match[2], is_hidden);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn copyCats.length > 0 ? copyCats[copyCats.length-1] : null;\n\t\t}\n\n\t\tvar lastSpan = createEditors (catLine, false);\n\t\t// Create one to add a new category\n\t\tvar editor = new CategoryEditor(newDOM ? catLine.getElementsByTagName('ul')[0] : catLine, null, null, lastSpan !== null, false);\n\t\tif (!onUpload) {\n\t\t\tif (pageText !== null && hiddenCats) {\n\t\t\t\tif (is_rtl) hiddenCats.dir = 'rtl';\n\t\t\t\tcreateEditors (hiddenCats, true);\n\t\t\t}\n\t\t\t// And finally add the \"multi-mode\" span. (Do this at the end, otherwise it ends up in the list above.)\n\t\t\tvar enableMulti = make ('span');\n\t\t\tenableMulti.className = 'noprint';\n\t\t\tif (is_rtl) enableMulti.dir = 'rtl';\n\t\t\tcatLine.insertBefore (enableMulti, catLine.firstChild.nextSibling);\n\t\t\tenableMulti.appendChild (make ('\\xa0', true)); // nbsp\n\t\t\tmultiSpan = make ('span');\n\t\t\tenableMulti.appendChild (multiSpan);\n\t\t\tmultiSpan.innerHTML = '(<a>' + HotCat.addmulti + '</a>)';\n\t\t\tvar lk = multiSpan.getElementsByTagName ('a')[0];\n\t\t\tlk.onclick = function (evt) {setMultiInput (); checkMultiInput (); return evtKill (evt);};\n\t\t\tlk.title = HotCat.multi_tooltip;\n\t\t\tlk.style.cursor = 'pointer';\n\t\t}\n\t\tcleanedText = null;\n\t\tif (typeof additionalWork == 'function') additionalWork();\n\t\tsetupCompleted.loaded(); // Trigger signal; execute registered functions\n\t\tif (window.jQuery) jQuery('body').trigger('hotcatSetupCompleted');\n\t}\n\n\tfunction setPage (json) {\n\t\tvar startTime = null;\n\t\tif (json && json.query) {\n\t\t\tif (json.query.pages) {\n\t\t\t\tvar page = json.query.pages[conf.wgArticleId === 0 ? \"-1\" : \"\" + conf.wgArticleId];\n\t\t\t\tif (page) {\n\t\t\t\t\tif (page.revisions && page.revisions.length > 0) {\n\t\t\t\t\t\t// Revisions are sorted by revision ID, hence [0] is the one we asked for, and possibly there's a [1] if we're\n\t\t\t\t\t\t// not on the latest revision (edit conflicts and such).\n\t\t\t\t\t\tpageText = page.revisions[0]['*'];\n\t\t\t\t\t\tif (page.revisions[0].timestamp) pageTime = page.revisions[0].timestamp.replace (/\\D/g, \"\");\n\t\t\t\t\t\tif (page.revisions[0].revid) pageTextRevId = page.revisions[0].revid;\n\t\t\t\t\t\tif (page.revisions.length > 1) conflictingUser = page.revisions[1].user;\n\t\t\t\t\t}\n\t\t\t\t\tif (page.lastrevid) lastRevId = page.lastrevid;\n\t\t\t\t\tif (page.starttimestamp) startTime = page.starttimestamp.replace (/\\D/g, \"\");\n\t\t\t\t\tpageWatched = typeof page.watched == 'string';\n\t\t\t\t\teditToken = page.edittoken;\n\t\t\t\t\tif (page.langlinks && (!json['query-continue'] || !json['query-continue'].langlinks)) {\n\t\t\t\t\t\t// We have interlanguage links, and we got them all.\n\t\t\t\t\t\tvar re = \"\";\n\t\t\t\t\t\tfor (var i = 0; i < page.langlinks.length; i++) {\n\t\t\t\t\t\t\tre += (i > 0 ? '|' : \"\") + page.langlinks[i].lang.replace(/([\\\\\\^\\$\\.\\?\\*\\+\\(\\)])/g, '\\\\$1');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (re.length > 0) {\n\t\t\t\t\t\t\tinterlanguageRE = new RegExp ('((^|\\\\n\\\\r?)(\\\\[\\\\[\\\\s*(' + re + ')\\\\s*:[^\\\\]]+\\\\]\\\\]\\\\s*))+$');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Siteinfo\n\t\t\tif (json.query.general) {\n\t\t\t\tHotCat.capitalizePageNames = (json.query.general['case'] == 'first-letter');\n\t\t\t\tif (json.query.general.time && !startTime) startTime = json.query.general.time.replace (/\\D/g, \"\");\n\t\t\t}\n\t\t\tserverTime = startTime;\n\t\t\t// Userinfo\n\t\t\tif (json.query.userinfo && json.query.userinfo.options) {\n\t\t\t\twatchCreate = !HotCat.dont_add_to_watchlist && json.query.userinfo.options.watchcreations == '1';\n\t\t\t\twatchEdit = !HotCat.dont_add_to_watchlist && json.query.userinfo.options.watchdefault == '1';\n\t\t\t\tminorEdits = json.query.userinfo.options.minordefault == 1;\n\t\t\t\t// If the user has the \"All edits are minor\" preference enabled, we should honor that\n\t\t\t\t// for single category changes, no matter what the site configuration is.\n\t\t\t\tif (minorEdits) HotCat.single_minor = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction createCommitForm () {\n\t\tif (commitForm) return;\n\t\tvar formContainer = make ('div');\n\t\tformContainer.style.display = 'none';\n\t\tdocument.body.appendChild (formContainer);\n\t\tformContainer.innerHTML =\n\t\t\t'<form id=\"hotcatCommitForm\" method=\"post\" enctype=\"multipart/form-data\" action=\"'\n\t\t\t+ conf.wgScript + '?title=' + encodeURIComponent (conf.wgPageName)\n\t\t\t+ '&action=edit\">'\n\t\t\t+ '<input type=\"hidden\" name=\"wpTextbox1\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"model\" value=\"wikitext\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"format\" value=\"text/x-wiki\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"wpSummary\" value=\"\" />'\n\t\t\t+ '<input type=\"checkbox\" name=\"wpMinoredit\" value=\"1\" />'\n\t\t\t+ '<input type=\"checkbox\" name=\"wpWatchthis\" value=\"1\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"wpAutoSummary\" value=\"\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"wpEdittime\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"wpStarttime\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"wpDiff\" value=\"wpDiff\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"oldid\" value=\"0\" />'\n\t\t\t+ '<input type=\"submit\" name=\"hcCommit\" value=\"hcCommit\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"wpEditToken\" />'\n\t\t\t+ '<input type=\"hidden\" name=\"wpUltimateParam\" value=\"1\" />'\n\t\t\t+ '</form>';\n\t\tcommitForm = document.getElementById ('hotcatCommitForm');\n\t}\n\n\tfunction getPage () {\n\t\t// We know we have an article here.\n\t\tif (conf.wgArticleId === 0) {\n\t\t\t// Doesn't exist yet.\n\t\t\tif (conf.wgNamespaceNumber === 2) {\n\t\t\t\t// Disable on non-existing User pages -- might be a global user page.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpageText = \"\";\n\t\t\tpageTime = null;\n\t\t\tsetup (createCommitForm);\n\t\t} else {\n\t\t\tvar url = conf.wgServer + conf.wgScriptPath + '/api.php?format=json&callback=HotCat.start&action=query&rawcontinue=&titles='\n\t\t\t\t\t+ encodeURIComponent (conf.wgPageName)\n\t\t\t\t\t+ '&prop=info%7Crevisions&rvprop=content%7Ctimestamp%7Cids&meta=siteinfo&rvlimit=1&rvstartid='\n\t\t\t\t\t+ conf.wgCurRevisionId;\n\t\t\tvar s = make ('script');\n\t\t\ts.src = armorUri(url);\n\t\t\ts.type = 'text/javascript';\n\t\t\tHotCat.start = function (json) { setPage (json); setup (createCommitForm); };\n\t\t\tdocument.getElementsByTagName ('head')[0].appendChild (s);\n\t\t\tsetupTimeout = window.setTimeout (function () {setup (createCommitForm);}, 4000); // 4 sec, just in case getting the wikitext takes longer.\n\t\t}\n\t}\n\n\tfunction run () {\n\t\tif (HotCat.started) return;\n\t\tHotCat.started = true;\n\t\tloadTrigger.register(really_run);\n\t}\n\n\tfunction really_run () {\n\t\tinitialize ();\n\n\t\tif (is_rtl && is_ie6) return; // Disabled! IE6 with RTL is just too broken...\n\t\tif (!HotCat.upload_disabled && conf.wgNamespaceNumber === -1 && conf.wgCanonicalSpecialPageName == 'Upload' && conf.wgUserName) {\n\t\t\tsetup_upload ();\n\t\t\tsetup (function () {\n\t\t\t\t// Check for state restoration once the setup is done otherwise, but before signalling setup completion\n\t\t\t\tif ( typeof UploadForm != 'undefined'\n\t\t\t\t\t&& typeof UploadForm.previous_hotcat_state != 'undefined'\n\t\t\t\t\t&& UploadForm.previous_hotcat_state !== null)\n\t\t\t\t{\n\t\t\t\t\tUploadForm.previous_hotcat_state = setState (UploadForm.previous_hotcat_state);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tif (!conf.wgIsArticle || conf.wgAction != 'view' || param('diff') !== null || param('oldid') !== null || !can_edit() || HotCat.disable()) return;\n\t\t\tgetPage ();\n\t\t}\n\t}\n\n\t// Legacy stuff\n\n\tfunction closeForm () {\n\t\t// Close all open editors without redirect resolution and other asynchronous stuff.\n\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\tif (editors[i].state == CategoryEditor.OPEN) {\n\t\t\t\teditors[i].cancel();\n\t\t\t} else if (editors[i].state == CategoryEditor.CHANGE_PENDING) {\n\t\t\t\teditors[i].sanitizeInput ();\n\t\t\t\tvar value = editors[i].text.value.split('|');\n\t\t\t\tvar key = null;\n\t\t\t\tif (value.length > 1) key = value[1];\n\t\t\t\tvar v = value[0].replace(/_/g, ' ').replace(/^\\s+|\\s+$/g, \"\");\n\t\t\t\tif (v.length === 0) {\n\t\t\t\t\teditors[i].cancel ();\n\t\t\t\t} else {\n\t\t\t\t\teditors[i].currentCategory = v;\n\t\t\t\t\teditors[i].currentKey = key;\n\t\t\t\t\teditors[i].currentExists = this.inputExists;\n\t\t\t\t\teditors[i].close ();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction getState () {\n\t\tvar result = null;\n\t\tfor (var i = 0; i < editors.length; i++) {\n\t\t\tvar text = editors[i].currentCategory;\n\t\t\tvar key = editors[i].currentKey;\n\t\t\tif (text && text.length > 0) {\n\t\t\t\tif (key !== null) text += '|' + key;\n\t\t\t\tif (result === null)\n\t\t\t\t\tresult = text;\n\t\t\t\telse\n\t\t\t\t\tresult = result + '\\n' + text;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tfunction setState (state) {\n\t\tvar cats = state.split ('\\n');\n\t\tif (cats.length === 0) return null;\n\t\tif (initialized && editors.length == 1 && editors[0].isAddCategory) {\n\t\t\t// Insert new spans and create new editors for them.\n\t\t\tvar newSpans = [];\n\t\t\tvar before = editors.length == 1 ? editors[0].span : null;\n\t\t\tvar i;\n\t\t\tfor (i = 0; i < cats.length; i++) {\n\t\t\t\tif (cats[i].length === 0) continue;\n\t\t\t\tvar cat = cats[i].split ('|');\n\t\t\t\tvar key = cat.length > 1 ? cat[1] : null;\n\t\t\t\tcat = cat[0];\n\t\t\t\tvar lk = make ('a'); lk.href = wikiPagePath (HotCat.category_canonical + ':' + cat);\n\t\t\t\tlk.appendChild (make (cat, true));\n\t\t\t\tlk.title = cat;\n\t\t\t\tvar span = make ('span');\n\t\t\t\tspan.appendChild (lk);\n\t\t\t\tif (i === 0) catLine.insertBefore (make (' ', true), before);\n\t\t\t\tcatLine.insertBefore (span, before);\n\t\t\t\tif (before && i+1 < cats.length) parent.insertBefore (make (' | ', true), before);\n\t\t\t\tnewSpans.push ({element: span, title: cat, 'key': key});\n\t\t\t}\n\t\t\t// And change the last one...\n\t\t\tif (before) {\n\t\t\t\tbefore.parentNode.insertBefore (make (' | ', true), before);\n\t\t\t}\n\t\t\tvar editor = null;\n\t\t\tfor (i = 0; i < newSpans.length; i++) {\n\t\t\t\teditor = new CategoryEditor (catLine, newSpans[i].element, newSpans[i].title, newSpans[i].key);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t// Export legacy functions\n\twindow.hotcat_get_state = function () { return getState(); };\n\twindow.hotcat_set_state = function (state) { return setState (state); };\n\twindow.hotcat_close_form = function () { closeForm (); };\n\n\tif (window.mw) {\n\t\t// Make sure we don't get conflicts with AjaxCategories (core development that should one day\n\t\t// replace HotCat).\n\t\tmw.config.set('disableAJAXCategories', true);\n\t}\n\t// Run as soon as possible. This varies depending on MediaWiki version;\n\t// window's 'load' event is always safe, but usually we can do better than that.\n\n\t// Check for version to avoid MediaWiki bug 32537.\n\tvar mwVersion = conf.wgVersion.split('.');\n\tif (mwVersion[0] >= 1 && parseFloat(mwVersion[1]) > 20) {\n\t\tif (parseFloat(mwVersion[1]) > 21 && conf.wgCanonicalSpecialPageName !== 'Upload') {\n\t\t\t// Use wikipage.content hook so that HotCat reloads after VE edits (bug T103285)\n\t\t\tvar startHotCat = function() {\n\t\t\t\tmw.hook('wikipage.content').add( function() {\n\t\t\t\t\t// Reset HotCat in case this is a soft reload (VE edit)\n\t\t\t\t\tcatLine = null;\n\t\t\t\t\teditors = [];\n\t\t\t\t\tinitialized = false;\n\t\t\t\t\tHotCat.started = false;\n\t\t\t\t\trun ();\n\t\t\t\t} );\n\t\t\t};\n\t\t} else {\n\t\t\t// We are using MediaWiki 1.21, which doesn't support mw.hook. Fall back to dom-ready.\n\t\t\t// OR: We're running on Special:Upload, where the 'wikipage.content' hook is fired for\n\t\t\t// various previewed wikitext snippets, which shouldn't reload HotCat interface.\n\t\t\tvar startHotCat = function() {\n\t\t\t\tjQuery(document).ready(run);\n\t\t\t};\n\t\t}\n\t\t// We can safely trigger just after user configuration is loaded. Also start HotCat if the user module fails to load.\n\t\t// Avoid using Promise methods of mw.loader.using as those aren't supported in older\n\t\t// MediaWiki versions.\n\t\tmw.loader.using('user', startHotCat, startHotCat);\n\t} else {\n\t\t// mw.loader.using('user', ...) could have unintended side-effects on MW <= 1.20. Fall back to dom-ready.\n\t\tjQuery(document).ready(run);\n\t}\n})();\n\n// </nowiki>"