diff --git a/KiwixWebApp.jsproj.user b/KiwixWebApp.jsproj.user index 790da55e..1a8add84 100644 --- a/KiwixWebApp.jsproj.user +++ b/KiwixWebApp.jsproj.user @@ -14,7 +14,7 @@ False False neutral - True + False AppHostLocalDebugger diff --git a/bin/Release/AppX/AppxManifest.xml b/bin/Release/AppX/AppxManifest.xml index 907b64a2..685cac1d 100644 --- a/bin/Release/AppX/AppxManifest.xml +++ b/bin/Release/AppX/AppxManifest.xml @@ -7,7 +7,7 @@ For more information on package manifest files, see http://go.microsoft.com/fwlink/?LinkID=241727 --> - + Kiwix JS @@ -23,7 +23,7 @@ - + diff --git a/bin/Release/AppX/vs.appxrecipe b/bin/Release/AppX/vs.appxrecipe index eee4ce28..23f344b5 100644 --- a/bin/Release/AppX/vs.appxrecipe +++ b/bin/Release/AppX/vs.appxrecipe @@ -20,19 +20,19 @@ C:\Users\geoff\Source\Repos\kiwix-js-windows\bin\Release\AppX - 9A9EBEE34C79521406F56EE6FA01E6B1D67B4C061ECF82699F1925D8F696C732 - a1a5e0b9-13d4-41fb-810d-518949f03df4_0.7.7.0_neutral__zfxmafgedzx24 + FC84D54C3CB93DCEECDA38109B66AAAC606513716087165A0127AECF9B4E8402 + a1a5e0b9-13d4-41fb-810d-518949f03df4_0.7.8.0_neutral__zfxmafgedzx24 a1a5e0b9-13d4-41fb-810d-518949f03df4_zfxmafgedzx24!App a1a5e0b9-13d4-41fb-810d-518949f03df4 CN=geoff - 0.7.7.0 + 0.7.8.0 True AppxManifest.xml true - 2017-07-24T21:03:15.856 + 2017-07-30T16:56:39.265 @@ -315,15 +315,15 @@ www\-\s\css_modules\ext.kartographer.frame.css - 2017-07-24T07:09:44.456 + 2017-07-27T16:48:23.938 www\-\s\css_modules\ext.kartographer.link.css - 2017-07-24T07:09:30.454 + 2017-07-25T06:35:48.777 www\-\s\css_modules\ext.kartographer.style.css - 2017-07-24T06:34:16.389 + 2017-07-25T06:35:48.785 www\-\s\css_modules\ext.scribunto.logs.css @@ -351,11 +351,11 @@ www\-\s\style-mobile.css - 2017-07-24T07:29:37.830 + 2017-07-27T16:54:05.551 www\-\s\style.css - 2017-07-24T09:09:00.703 + 2017-07-27T16:49:07.370 www\-\s\vector.css @@ -363,7 +363,7 @@ www\css\app.css - 2017-07-20T16:30:44.744 + 2017-07-30T16:51:21.044 www\css\bootstrap-theme.css @@ -379,7 +379,7 @@ www\index.html - 2017-07-24T21:02:52.363 + 2017-07-30T16:33:39.640 www\favicon.ico @@ -419,11 +419,11 @@ www\js\app.js - 2017-07-24T21:00:00.918 + 2017-07-30T10:07:20.947 www\js\init.js - 2017-07-23T20:35:25.720 + 2017-07-28T10:11:24.706 www\js\lib\abstractFilesystemAccess.js @@ -451,11 +451,11 @@ www\js\lib\transformStyles.js - 2017-07-24T07:10:02.639 + 2017-07-27T21:15:17.117 www\js\lib\uiUtil.js - 2017-07-19T10:03:58.143 + 2017-07-30T10:09:14.258 www\js\lib\utf8.js @@ -492,7 +492,7 @@ resources.pri true - 2017-07-24T16:09:22.044 + 2017-07-30T16:24:03.374 diff --git a/bin/Release/AppX/www/-/s/css_modules/ext.kartographer.frame.css b/bin/Release/AppX/www/-/s/css_modules/ext.kartographer.frame.css index d461ce40..a40ce3be 100644 --- a/bin/Release/AppX/www/-/s/css_modules/ext.kartographer.frame.css +++ b/bin/Release/AppX/www/-/s/css_modules/ext.kartographer.frame.css @@ -3,4 +3,4 @@ * * This sheet returns an empty css from the ZIM, so it is included here * to prevent useless retrieval of empty data. - */ + */ \ No newline at end of file diff --git a/bin/Release/AppX/www/-/s/style-mobile.css b/bin/Release/AppX/www/-/s/style-mobile.css index fd803db0..dfb1a4db 100644 --- a/bin/Release/AppX/www/-/s/style-mobile.css +++ b/bin/Release/AppX/www/-/s/style-mobile.css @@ -87,4 +87,991 @@ table.climate-table { table.climate-table th { background: #CEE0E7; } -/* END: CSS for Template:Climate */ \ No newline at end of file +/* END: CSS for Template:Climate */ + + +/* +MediaWiki:Common.css +*/ +/* Le CSS placé ici sera appliqué à tous les habillages. */ + +/* https://phabricator.wikimedia.org/T134352 */ +#banner-drapeau a { + display: inline-block; + width: auto; + height: auto; +} + +/* DEBUT des styles pour pagebanner extension */ +h1.wpb-name a { + margin-right: 5px; +} +h1.wpb-name { + font-family: sans-serif; + border-bottom: none; +} +.ext-wpb-pagebanner { + clear: both; +} + +/* Fix problem with banner overlay */ +div.toctitle {display:none;} + +/* Remove when https://phabricator.wikimedia.org/T113642 fixed */ +.client-js #contentSub { display: none; } +.client-js .ext-wpb-pagebanner { padding-top: 1em; } +.client-js #contentSub.visible { font-size: 0.875em; margin: 0; display: block; } +.client-js .ext-wpb-pagebanner.bugfix-T113642 { padding-top: 0; } +/* end https://phabricator.wikimedia.org/T113642 */ + +/* hide upload link in toolbox */ + +.routeBox { + font-size: small; + border-style: none; + border-spacing: 0 0; + border-collapse: collapse; + margin: 0 auto; +} + +/* Styles for Geo template */ + +#geoCoord table { + border-collapse: collapse; + background: transparent; +} +#geoCoord td { + font-size: 0.9em; + line-height: 100%; + vertical-align: middle; + padding: 0 0 0 10px; + text-align: right; + border-left: 1px solid #88a; +} +#geoCoord td.icon { + border-left: none; + height: 27px; + width: 35px; + padding: 0 10px 0 0; +} + +#DoM { + background: transparent; + padding: 0; +} + +/* Styles pour les bannières de pages */ + +.topbanner { + position: relative; + overflow: hidden; + max-width: 1800px; + height: auto; +} + +.topbanner img { + max-width: 100%; + height: auto; + width: auto; +} + +.topbanner-box { + position: absolute; + z-index: 2; + margin-top: 1.5em; + color: white; + width: 50%; + min-width: 20em; + left: 2%; + text-align: left; +} + +.topbanner .name { + position: absolute; + z-index: 2; + margin: 0.6em 0 0 0.4em; + padding: 8px 7px; + font-size: 2.2em; + background: rgb(16,16,16); + background: rgba(0,0,0,0.5); + border-radius: 4px; + color: white; + white-space: nowrap; + line-height: 0.9em; +} + +/* Styles pour les infos du coin supérieur droit des bannières de pages */ +.iconbox { + position: absolute; + top: 6px; + right: 0; + padding: 3px; + z-index: 3; + background: rgb(16,16,16); + background: rgba(0,0,0,0.7); + border-bottom-left-radius: 5px; +} + +/* Style pour table des matières horizontale copiée de Common.css sur en.wikivoyage le 19 mai 2013 + Style for hlist class - pulled from Wikipedia's Common.css file on 20 Mar 2013 + Style for horizontal lists (separator following item). + Note: hlist formatting will break if the resulting HTML lacks a breakable character + between list items. This happens when the following conditions are true: + 1) The list is made using wiki markup (where HTML is built by parser.php) + 2) HTMLTidy is disabled or unavailable (such as on Special: pages) + In such cases, building lists with .hlist using HTML instead of wiki markup + will work around this problem. See also [[Bugzilla:39617]]. + IE8-specific classes are assigned in [[MediaWiki:Common.js/IEFixes.js]]. + Last updated: January 24, 2013 + @source mediawiki.org/wiki/Snippets/Horizontal_lists + @maintainer: [[User:Edokter]] + @revision: 3.1 +*/ +.skin-monobook .hlist dl, +.skin-modern .hlist dl, +.skin-vector .hlist dl { + line-height: 1.1em; +} +.hlist dl, +.hlist ol, +.hlist ul { + margin: 0; + padding: 0; + line-height: 1.1em; +} +/* Display list items inline and make them nowrap */ +.hlist dd, +.hlist dt, +.hlist li { + display: inline; + white-space: nowrap; +} +/* Allow wrapping for list items (in tight spaces) */ +.hlist.hwrap dd, +.hlist.hwrap dt, +.hlist.hwrap li { + white-space: normal; +} +/* Display nested lists inline and allow them to wrap */ +.hlist dl dl, .hlist dl ol, .hlist dl ul, +.hlist ol dl, .hlist ol ol, .hlist ol ul, +.hlist ul dl, .hlist ul ol, .hlist ul ul { + display: inline; + white-space: normal; +} +/* Generate interpuncts */ +.hlist dt:after { + content: ":"; +} +.hlist dd:after, +.hlist li:after { + content: " ·"; + font-weight: bold; + padding: 0 0.3em; +} +.hlist dd:last-child:after, +.hlist dt:last-child:after, +.hlist li:last-child:after { + content: none; +} +/* For IE8 */ +.hlist dd.hlist-last-child:after, +.hlist dt.hlist-last-child:after, +.hlist li.hlist-last-child:after { + content: none; +} +/* Add parentheses around nested lists */ +.hlist dd dd:first-child:before, .hlist dd dt:first-child:before, .hlist dd li:first-child:before, +.hlist dt dd:first-child:before, .hlist dt dt:first-child:before, .hlist dt li:first-child:before, +.hlist li dd:first-child:before, .hlist li dt:first-child:before, .hlist li li:first-child:before { + content: "("; + font-weight: normal; +} +.hlist dd dd:last-child:after, .hlist dd dt:last-child:after, .hlist dd li:last-child:after, +.hlist dt dd:last-child:after, .hlist dt dt:last-child:after, .hlist dt li:last-child:after, +.hlist li dd:last-child:after, .hlist li dt:last-child:after, .hlist li li:last-child:after { + content: ")"; + font-weight: normal; +} +/* For IE8 */ +.hlist dd dd.hlist-last-child:after, .hlist dd dt.hlist-last-child:after, .hlist dd li.hlist-last-child:after, +.hlist dt dd.hlist-last-child:after, .hlist dt dt.hlist-last-child:after, .hlist dt li.hlist-last-child:after, +.hlist li dd.hlist-last-child:after, .hlist li dt.hlist-last-child:after, .hlist li li.hlist-last-child:after { + content: ")"; + font-weight: normal; +} +/* allow ToC to stretch across screen when it is part of a horizontal list, change background and font colours */ +.hlist #toc.tocFloat { + width: 100%; + max-width: 170em; + color: black; +} + +.hlist.tocbox-s #toc.tocFloat { + width: 100%; + max-width: 170em; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; + background-color: #e0e0e0; +} + +.hlist.tocbox-b #toc.tocFloat { + width: 100%; + max-width: 170em; + margin: 0; + padding: 0; + line-height: 1.1em; + color: white; + background: rgb(16,16,16); + background: rgba(0,0,0,0.5); + border: none; +} + +.hlist.tocbox-w #toc.tocFloat { + width: 100%; + max-width: 170em; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; + background: rgb(225,225,225); + background: rgba(160,160,160,0.6); + border: none; +} + +.hlist #toc table, +.hlist #toc tr, +.hlist #toc td { + margin: 0; + padding: 0; + line-height: 1.1em; +} + +/* links in the horizontal ToC should be black... */ +.hlist #toc a { + color: black; + font-size: 0.8em; + font-weight: bold; +} + +/* ... except when the ToC box is black ... */ +.hlist.tocbox-b #toc a { + color: white; + font-size: 0.8em; + font-weight: bold; +} + +/* ... or except when being hovered over */ +.hlist #toc.tocFloat a:hover { + color: #bdddfd; +} + +/* don't display ToC title when in horizontal ToC */ +.hlist #toctitle { + display: none; +} + +.mf-mobile-only { + display: none; +} + +/* Prevent display of subheadings in horizontal ToC */ +.hlist #toc .toclevel-2, +.hlist #toc .toclevel-3, +.hlist #toc .toclevel-4, +.hlist #toc .toclevel-5, +.hlist #toc .toclevel-6 { + display: none; +} + +.hlist .toggleNode { + display: none; +} + +/* Corporate Design */ + +.containerTabs { + border: 1px solid #6cc8f3; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -khtml-border-radius-topleft: 5px; + -khtml-border-radius-topright: 5px; + + margin: 0 0 0 0.75em; + padding: 0.2em 1em; + background: #f0f0f0; + float: left; + position: relative; + top: 1px; +} +#content div.mainTab { + border-bottom: 1px solid #f0f0f0; +} +#content > .boxTabsEnd { /* Verstecken vor IE 6 */ + display: none; +} +.tabbedContainers .containerTabs { + font-weight: normal; + text-decoration: none; + color: #002bb8; + cursor: pointer; + display: none; +} +.tabbedContainers .mainTab { + font-weight: bold; + text-decoration: none; + color: #000000; + cursor: text; + display: none; +} +.tabbedContainers .showIt { + display: block; +} +@media print { + .tabbedContainers .containerTabs, .tabbedContainers .mainTab, + .tabbedContainers .showIt, .tabbedContainers .boxTabsEnd { + display: none; + } +} + +.container { + border: 1px solid #6cc8f3; + padding: 0 0 3px; + margin: 0.75em 0 0; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; +} + +/* Color border's variations */ +/* Light green */ +#content .var2 { + border-color: #80f000; +} + +/* Dark green */ +#content .var3 { + border-color: #158200; +} + +/* Orange */ +#content .var4 { + border-color: #EDAA02; +} + +/* Red */ +#content .var5 { + border-color: #DB0003; +} + +/* Brown */ +#content .var6 { + border-color: #AD5A1B; +} + +/* Violet */ +#content .var7 { + border-color: #9154AD; +} + +/* Black */ +#content .var8 { + border-color: #000000; +} + +/* Dark blue */ +#content .var9 { + border-color: #0400FF; +} + +.container .header, .infobox .header { + background: #f0f0f0; + color: #004f80; + margin-top: 0; + margin-bottom: 0.4em; + padding: 0.3em 0.35em; + border-bottom: none; + font-size: 1.3em; +} + +.container .header:first-child, .container .editLink:first-child + .header, .infobox .header:first-child { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -khtml-border-radius-topleft: 5px; + -khtml-border-radius-topright: 5px; + margin-top: 0; + border-top: none; +} + +.container * ~ .header { + margin-top: 0.75em; + border-top: 1px solid #c0c0c0; +} + +.container .centered { + text-align: center; +} + +.container .justified { + text-align: justify; +} + +/* Color title's variations */ +/* Light green */ +.var2 .header, .var2 .header a { + color: #00804f; +} + +/* Dark green */ +.var3 .header, .var3 .header a { + color: #158200; +} + +/* Orange */ +.var4 .header, .var4 .header a { + color: #EDAA02; + } + +/* Red */ +.var5 .header, .var5 .header a { + color: #DB0003; +} + +/* Brown */ +.var6 .header, .var6 .header a { + color: #AD5A1B; +} + +/* Violet */ +.var7 .header, .var7 .header a { + color: #9154AD; +} + +/* Black */ +.var8 .header, .var8 .header a { + color: #000000; +} + +/* Dark blue */ +.var9 .header, .var9 .header a { + color: #0400FF; +} + +.container .editLink { + float: right; + font-size: 90%; + background: transparent; + margin: 0.5em 0.75em; +} + +.container h2 { + padding: 0.5em 0.35em; +} + +.container h3 { + padding: 0.3em 0.35em; +} + +.container p, .container ul, .container .div { + padding: 0 0.5em; + margin-bottom: 0.3em; +} + +.container .emph { + font-size: 110%; + font-weight: bold; +} + +.container ul ul { + padding: 0; +} + +@media print { + .container ul, .container ul ul { + padding-left: 1em; + } +} + +.container ol { + padding-right: 0.5em; +} + +.container ol ol { + padding-right: 0em; +} + +.container h4, .container h5, .container h6, .container dl { + padding-left: 0.5em; + padding-right: 0.5em; +} + +.container > .divBox, .container > .prettytable, .container > .multiline, +.container > .gallery, .container > div.center { + margin-left: 0.5em; + margin-right: 0.5em; +} + +.container div.floatleft { + margin-left: 0.5em; +} + +.container div.floatright { + margin-right: 0.5em; +} + +.container .usr-code div.center { + margin: 0; +} + +.container hr { + margin: 0 0.5em; +} + +table.container { + margin: 0; + border-style: none; + border-spacing: 0 0; + border-collapse: collapse; +} + +div.cFirst, table.cFirst, .containerTabs + .container, .boxTabsEnd + .container { + margin: 0; + clear: both; +} + +div.cInner, table.cInner { + margin: 0.75em; +} + +table.container td { + margin: 0; + padding: 0 0 0 0.75em; + vertical-align: top; +} + +table.container td:first-child { + padding: 0; +} + +* html table.container td { /* Stern-HTML-Hack fuer IE6 */ + padding-left: expression((this.parentNode.firstChild == this)? "0" : "0.75em" ); +} + +@media print { + .container { border: 0.25mm solid #6cc8f3; } + .container .header, .infobox .header { + font-size: 1em; + border-top: 0.25mm solid #c0c0c0; + } +} + +.regionFlag { + border: 1px solid #404040; + width: 20px; + height: 15px; + margin: 0 0.5em 0 0; + float: left; +} + +#socialbm iframe { + display: inline; + height: 45px; + margin: 0; +} +#socialbm a img { + vertical-align: 23px; +} + +.ImageGroup { + text-align: center; + border: 1px solid #6cc8f3; + background-color: #ffffff; +} +* html .ImageGroup { // IE6-Hack; + width: 220px; +} +.ImageGroup .header { + font-size: 110%; + font-weight: bold; + padding: 0 3px; + background: #f0f0f0; +} +.ImageGroup .thumb { + margin-bottom: 0; +} +.ImageGroup .thumbinner { + margin: 0 auto; +} +.ImageGroup .ImageGrUnitHeader { + background: #f0f0f0; +} + +.topicsTable { + width: 100%; + border-collapse: collapse; + empty-cells: show; + background: transparent; + border-spacing: 0 0; +} +.topicsTable td { + width: 50%; + vertical-align: top; + padding: 1em 0; +} +.topicsTable td:first-child { + padding-right: 1em; +} +.topicsTable td .floatright { + border: solid 1px #cccccc; + background: #eeeeee; + padding: 3px; + margin: 5px 0 0 1em; +} + +@media print { + .ImageGroup { + border: none; + padding: 0; + } + .ImageGroup .header, .ImageGroup .ImageGrUnitHeader { + display: none; + } +} + +#altIsIn { + line-height: 1.8em; +} + +/* Quickbar styles */ + +#content .qb { + border: 1px solid #6cc8f3; + margin: 0 0 1em; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; +} +#content .qbRight { + clear: right; + float: right; + margin: 0 0 1em 1em; + width: 300px; +} +#content .qbRightDiv { + clear: right; + float: right; + margin: 0 0 1em 1em; +} +#content .qbTopBorder { +} +#content .qbLeft { + clear: left; + float: left; + margin: 0 1em 0 1em; + width: 300px; +} +.qb td { + padding: 2px 0.4em; + vertical-align: baseline; +} +.qb th { + padding: 2px 0.4em; + vertical-align: baseline; + text-align: left; + font-weight: bold; +} +#content .qb .qbHeader { + text-align: center; + color: #004f80; + padding: 0.3em 0.35em; + font-size: 1.2em; + background: #f0f0f0; + border-top: 1px solid #c0c0c0; +} +#content .qb tr:first-child .qbHeader { + border-top: none; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -khtml-border-radius-topleft: 5px; + -khtml-border-radius-topright: 5px; +} +.qbImage { +/* border-top: 1px solid #4D64CF; */ + text-align: center; + padding: 5px 2px; + margin-left: auto; + margin-right: auto; +} +.qbImage div.thumb { + border-style: none; + margin-bottom: 0; +} +.qbImage div.thumbinner { + border-style: none; + padding: 0 !important; + background: transparent; + margin: 0 auto; +} +.qbImage div.tright { + float: none; + margin: 0; +} +.qb .qbImageCell { + padding: 0; +} +.qbImageCell .qbHeader { + border-bottom: none; +} +.qbEmpty { + display: none; +} +.qbEmpty td { + height: 1px; +} +.breakable { + font-size: 7%; + line-height: 0.1%; + text-decoration: none !important; + visibility: hidden; +} +@media print { + #content .qb { border-width: 0.25mm; } + #content .qb .qbHeader { + font-size: 1em; + background: #f0f0f0; + border-top: 0.25mm solid #c0c0c0; + border-bottom: 0.25mm solid #c0c0c0; + } +} + +/*** styles and counter for mapping listings ***/ +@media screen { + .printonly { display:none !important; } +} + +@media screen, print { + span.listing-map { + display: inline-block; + width: 12px; height: 13px; + text-align: right; + color: white; + font-size: 0.85em; + font-family: Arial,Verdana,sans-serif; + padding: 0px 2px 3px 1px; + -webkit-print-color-adjust: exact; //force printing on safari and chrome + } + + h2 { counter-reset: mapnumber; } + span.listing-map:before { + content: counter(mapnumber); + counter-increment: mapnumber; + } + + body { counter-reset: generalnumber; } + span.listing-map.listing-general:before { + content: counter(generalnumber); + counter-increment: generalnumber; + } + +} + +/* Externalisation des modèles de style pour améliorer les performances - Auslagerung von Stil-Vorlagen zur Performance-Steigerung */ + +#contentSub img { + vertical-align: baseline; +} + +.prettytable { + border: 1px solid #6cc8f3; + border-collapse: collapse; + empty-cells: show; + margin: 1em 0; + background: transparent; + border-spacing: 0 0; +} +.prettytable td, .prettytable th { + border: 1px solid #6cc8f3; + padding: 0.25em; + vertical-align: baseline; +} +.prettytable th { /* hightlighting */ + text-align: center; + border-bottom: 1px solid #6cc8f3; + border-top: 1px solid #6cc8f3; + background: #f0f0f0; + color: #004f80; +} +.sortable th { /* ab Version 1.9 */ + text-align: left; +} +.verticalCentered td, .verticalCentered th { + vertical-align: middle; +} +.textCentered td, .textCentered th { + text-align: center; +} +.framedBox { + margin: 1em 0; + padding: 0.5em; + border: 1px solid #6cc8f3; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + -o-border-radius: 5px; +} +.noFloat { + clear: both; + float: none; + margin: 0; +} + +/**** STYLES AIDE ET ACCUEIL ****/ +/* contruction des éléments */ +#aa-bloc-tete { + display:table; + width: 100%; +} + +#aa-bloc-gauche, +#aa-bloc-droite { + display:table-cell; + vertical-align:center; +} +#aa-bloc-droite { + width:30%; +} +#aa-bloc-dessous { + padding:5px 10px; +} +#aa-bloc-tete h2 { + margin-top:4pt; /* Correction du style des titres par défaut pour une meilleure intégration */ +} +/* Couleur et apparence des éléments */ +.aa-fond-gris { + background-color:#F6F6F6; + padding:10px; + font-size: 1.1em; + } +.aa-filet-gris { + border:1px solid #CCC; + } +.aa-fond-blanc { + background-color:#FFF; + padding:10px; + } +.aa-fond-avertissement { + display:block; + border-bottom:1px solid #C00; + background-color:#FFF; + padding: 10px; +} +.aa-titre-bleu { + color:#3366BB; + border:none; +} + +.aa-titre-rouge { + color:#C00; + border:none; +} +.aa-titre-vert { + color:#008769; + border:none; +} +.aa-faux-h2 { + font-weight:normal; + font-size:150%; +} +.aa-faux-h3 { + font-weight:normal; + font-size:132%; +} + +/* Styles pour [[Modèle:Animation]] */ + +.diaporamaControl img { + background-color: white; + border: 1px solid #DDDDDD; +} + +.diaporamaControl .ScrollBar { + background-image: url(//upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Round_Edge.png/5px-Round_Edge.png); + background-position: top; + background-repeat: repeat-x; +} + +.diaporamaControl .ScrollBarContainer { + background-image: url(//upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Round_Edge_bis.png/5px-Round_Edge_bis.png); + background-position: top; + background-repeat: repeat-x; +} + +.diaporama .magnify { + display: none; +} + +.diaporama select { + font-size: 12px; +} + +/* CHIFFRES ROMAINS */ + +/* Affichage des chiffres romains, voir [[modèle:Rom]] ou [[modèle:Romain]]. */ + +.romain { + text-transform: lowercase; + font-variant: small-caps; +} + +/* [[Modèle:Indication de langue]] */ + +.indicateur-langue { + font-family: monospace; + font-weight: bold; + font-size: small; + font-style: normal; +} + +.indicateur-format { + font-family: monospace; + font-weight: bold; + font-size: small; + font-style: normal; +}/* +MediaWiki:Vector.css +*/ +/* CSS placed here will affect users of the Vector skin */ + +#contentSub, #contentSub2 { font-size: 100% } + +.ns-8 pre { font-size: 125% } + +#geoCoord, #DoM { + position: absolute; + z-index: 1; + right: 12px; + right: 0; + top: -36px; + float: right; +} + +#DoM { + top: -4px; +} \ No newline at end of file diff --git a/bin/Release/AppX/www/-/s/style.css b/bin/Release/AppX/www/-/s/style.css index 878c9ad6..c3d0d537 100644 --- a/bin/Release/AppX/www/-/s/style.css +++ b/bin/Release/AppX/www/-/s/style.css @@ -108,4 +108,992 @@ table.climate-table { table.climate-table th { background: #CEE0E7; } -/* END: CSS for Template:Climate */ \ No newline at end of file +/* END: CSS for Template:Climate */ + + + +/* +MediaWiki:Common.css +*/ +/* Le CSS placé ici sera appliqué à tous les habillages. */ + +/* https://phabricator.wikimedia.org/T134352 */ +#banner-drapeau a { + display: inline-block; + width: auto; + height: auto; +} + +/* DEBUT des styles pour pagebanner extension */ +h1.wpb-name a { + margin-right: 5px; +} +h1.wpb-name { + font-family: sans-serif; + border-bottom: none; +} +.ext-wpb-pagebanner { + clear: both; +} + +/* Fix problem with banner overlay */ +div.toctitle {display:none;} + +/* Remove when https://phabricator.wikimedia.org/T113642 fixed */ +.client-js #contentSub { display: none; } +.client-js .ext-wpb-pagebanner { padding-top: 1em; } +.client-js #contentSub.visible { font-size: 0.875em; margin: 0; display: block; } +.client-js .ext-wpb-pagebanner.bugfix-T113642 { padding-top: 0; } +/* end https://phabricator.wikimedia.org/T113642 */ + +/* hide upload link in toolbox */ + +.routeBox { + font-size: small; + border-style: none; + border-spacing: 0 0; + border-collapse: collapse; + margin: 0 auto; +} + +/* Styles for Geo template */ + +#geoCoord table { + border-collapse: collapse; + background: transparent; +} +#geoCoord td { + font-size: 0.9em; + line-height: 100%; + vertical-align: middle; + padding: 0 0 0 10px; + text-align: right; + border-left: 1px solid #88a; +} +#geoCoord td.icon { + border-left: none; + height: 27px; + width: 35px; + padding: 0 10px 0 0; +} + +#DoM { + background: transparent; + padding: 0; +} + +/* Styles pour les bannières de pages */ + +.topbanner { + position: relative; + overflow: hidden; + max-width: 1800px; + height: auto; +} + +.topbanner img { + max-width: 100%; + height: auto; + width: auto; +} + +.topbanner-box { + position: absolute; + z-index: 2; + margin-top: 1.5em; + color: white; + width: 50%; + min-width: 20em; + left: 2%; + text-align: left; +} + +.topbanner .name { + position: absolute; + z-index: 2; + margin: 0.6em 0 0 0.4em; + padding: 8px 7px; + font-size: 2.2em; + background: rgb(16,16,16); + background: rgba(0,0,0,0.5); + border-radius: 4px; + color: white; + white-space: nowrap; + line-height: 0.9em; +} + +/* Styles pour les infos du coin supérieur droit des bannières de pages */ +.iconbox { + position: absolute; + top: 6px; + right: 0; + padding: 3px; + z-index: 3; + background: rgb(16,16,16); + background: rgba(0,0,0,0.7); + border-bottom-left-radius: 5px; +} + +/* Style pour table des matières horizontale copiée de Common.css sur en.wikivoyage le 19 mai 2013 + Style for hlist class - pulled from Wikipedia's Common.css file on 20 Mar 2013 + Style for horizontal lists (separator following item). + Note: hlist formatting will break if the resulting HTML lacks a breakable character + between list items. This happens when the following conditions are true: + 1) The list is made using wiki markup (where HTML is built by parser.php) + 2) HTMLTidy is disabled or unavailable (such as on Special: pages) + In such cases, building lists with .hlist using HTML instead of wiki markup + will work around this problem. See also [[Bugzilla:39617]]. + IE8-specific classes are assigned in [[MediaWiki:Common.js/IEFixes.js]]. + Last updated: January 24, 2013 + @source mediawiki.org/wiki/Snippets/Horizontal_lists + @maintainer: [[User:Edokter]] + @revision: 3.1 +*/ +.skin-monobook .hlist dl, +.skin-modern .hlist dl, +.skin-vector .hlist dl { + line-height: 1.1em; +} +.hlist dl, +.hlist ol, +.hlist ul { + margin: 0; + padding: 0; + line-height: 1.1em; +} +/* Display list items inline and make them nowrap */ +.hlist dd, +.hlist dt, +.hlist li { + display: inline; + white-space: nowrap; +} +/* Allow wrapping for list items (in tight spaces) */ +.hlist.hwrap dd, +.hlist.hwrap dt, +.hlist.hwrap li { + white-space: normal; +} +/* Display nested lists inline and allow them to wrap */ +.hlist dl dl, .hlist dl ol, .hlist dl ul, +.hlist ol dl, .hlist ol ol, .hlist ol ul, +.hlist ul dl, .hlist ul ol, .hlist ul ul { + display: inline; + white-space: normal; +} +/* Generate interpuncts */ +.hlist dt:after { + content: ":"; +} +.hlist dd:after, +.hlist li:after { + content: " ·"; + font-weight: bold; + padding: 0 0.3em; +} +.hlist dd:last-child:after, +.hlist dt:last-child:after, +.hlist li:last-child:after { + content: none; +} +/* For IE8 */ +.hlist dd.hlist-last-child:after, +.hlist dt.hlist-last-child:after, +.hlist li.hlist-last-child:after { + content: none; +} +/* Add parentheses around nested lists */ +.hlist dd dd:first-child:before, .hlist dd dt:first-child:before, .hlist dd li:first-child:before, +.hlist dt dd:first-child:before, .hlist dt dt:first-child:before, .hlist dt li:first-child:before, +.hlist li dd:first-child:before, .hlist li dt:first-child:before, .hlist li li:first-child:before { + content: "("; + font-weight: normal; +} +.hlist dd dd:last-child:after, .hlist dd dt:last-child:after, .hlist dd li:last-child:after, +.hlist dt dd:last-child:after, .hlist dt dt:last-child:after, .hlist dt li:last-child:after, +.hlist li dd:last-child:after, .hlist li dt:last-child:after, .hlist li li:last-child:after { + content: ")"; + font-weight: normal; +} +/* For IE8 */ +.hlist dd dd.hlist-last-child:after, .hlist dd dt.hlist-last-child:after, .hlist dd li.hlist-last-child:after, +.hlist dt dd.hlist-last-child:after, .hlist dt dt.hlist-last-child:after, .hlist dt li.hlist-last-child:after, +.hlist li dd.hlist-last-child:after, .hlist li dt.hlist-last-child:after, .hlist li li.hlist-last-child:after { + content: ")"; + font-weight: normal; +} +/* allow ToC to stretch across screen when it is part of a horizontal list, change background and font colours */ +.hlist #toc.tocFloat { + width: 100%; + max-width: 170em; + color: black; +} + +.hlist.tocbox-s #toc.tocFloat { + width: 100%; + max-width: 170em; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; + background-color: #e0e0e0; +} + +.hlist.tocbox-b #toc.tocFloat { + width: 100%; + max-width: 170em; + margin: 0; + padding: 0; + line-height: 1.1em; + color: white; + background: rgb(16,16,16); + background: rgba(0,0,0,0.5); + border: none; +} + +.hlist.tocbox-w #toc.tocFloat { + width: 100%; + max-width: 170em; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; + background: rgb(225,225,225); + background: rgba(160,160,160,0.6); + border: none; +} + +.hlist #toc table, +.hlist #toc tr, +.hlist #toc td { + margin: 0; + padding: 0; + line-height: 1.1em; +} + +/* links in the horizontal ToC should be black... */ +.hlist #toc a { + color: black; + font-size: 0.8em; + font-weight: bold; +} + +/* ... except when the ToC box is black ... */ +.hlist.tocbox-b #toc a { + color: white; + font-size: 0.8em; + font-weight: bold; +} + +/* ... or except when being hovered over */ +.hlist #toc.tocFloat a:hover { + color: #bdddfd; +} + +/* don't display ToC title when in horizontal ToC */ +.hlist #toctitle { + display: none; +} + +.mf-mobile-only { + display: none; +} + +/* Prevent display of subheadings in horizontal ToC */ +.hlist #toc .toclevel-2, +.hlist #toc .toclevel-3, +.hlist #toc .toclevel-4, +.hlist #toc .toclevel-5, +.hlist #toc .toclevel-6 { + display: none; +} + +.hlist .toggleNode { + display: none; +} + +/* Corporate Design */ + +.containerTabs { + border: 1px solid #6cc8f3; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -khtml-border-radius-topleft: 5px; + -khtml-border-radius-topright: 5px; + + margin: 0 0 0 0.75em; + padding: 0.2em 1em; + background: #f0f0f0; + float: left; + position: relative; + top: 1px; +} +#content div.mainTab { + border-bottom: 1px solid #f0f0f0; +} +#content > .boxTabsEnd { /* Verstecken vor IE 6 */ + display: none; +} +.tabbedContainers .containerTabs { + font-weight: normal; + text-decoration: none; + color: #002bb8; + cursor: pointer; + display: none; +} +.tabbedContainers .mainTab { + font-weight: bold; + text-decoration: none; + color: #000000; + cursor: text; + display: none; +} +.tabbedContainers .showIt { + display: block; +} +@media print { + .tabbedContainers .containerTabs, .tabbedContainers .mainTab, + .tabbedContainers .showIt, .tabbedContainers .boxTabsEnd { + display: none; + } +} + +.container { + border: 1px solid #6cc8f3; + padding: 0 0 3px; + margin: 0.75em 0 0; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; +} + +/* Color border's variations */ +/* Light green */ +#content .var2 { + border-color: #80f000; +} + +/* Dark green */ +#content .var3 { + border-color: #158200; +} + +/* Orange */ +#content .var4 { + border-color: #EDAA02; +} + +/* Red */ +#content .var5 { + border-color: #DB0003; +} + +/* Brown */ +#content .var6 { + border-color: #AD5A1B; +} + +/* Violet */ +#content .var7 { + border-color: #9154AD; +} + +/* Black */ +#content .var8 { + border-color: #000000; +} + +/* Dark blue */ +#content .var9 { + border-color: #0400FF; +} + +.container .header, .infobox .header { + background: #f0f0f0; + color: #004f80; + margin-top: 0; + margin-bottom: 0.4em; + padding: 0.3em 0.35em; + border-bottom: none; + font-size: 1.3em; +} + +.container .header:first-child, .container .editLink:first-child + .header, .infobox .header:first-child { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -khtml-border-radius-topleft: 5px; + -khtml-border-radius-topright: 5px; + margin-top: 0; + border-top: none; +} + +.container * ~ .header { + margin-top: 0.75em; + border-top: 1px solid #c0c0c0; +} + +.container .centered { + text-align: center; +} + +.container .justified { + text-align: justify; +} + +/* Color title's variations */ +/* Light green */ +.var2 .header, .var2 .header a { + color: #00804f; +} + +/* Dark green */ +.var3 .header, .var3 .header a { + color: #158200; +} + +/* Orange */ +.var4 .header, .var4 .header a { + color: #EDAA02; + } + +/* Red */ +.var5 .header, .var5 .header a { + color: #DB0003; +} + +/* Brown */ +.var6 .header, .var6 .header a { + color: #AD5A1B; +} + +/* Violet */ +.var7 .header, .var7 .header a { + color: #9154AD; +} + +/* Black */ +.var8 .header, .var8 .header a { + color: #000000; +} + +/* Dark blue */ +.var9 .header, .var9 .header a { + color: #0400FF; +} + +.container .editLink { + float: right; + font-size: 90%; + background: transparent; + margin: 0.5em 0.75em; +} + +.container h2 { + padding: 0.5em 0.35em; +} + +.container h3 { + padding: 0.3em 0.35em; +} + +.container p, .container ul, .container .div { + padding: 0 0.5em; + margin-bottom: 0.3em; +} + +.container .emph { + font-size: 110%; + font-weight: bold; +} + +.container ul ul { + padding: 0; +} + +@media print { + .container ul, .container ul ul { + padding-left: 1em; + } +} + +.container ol { + padding-right: 0.5em; +} + +.container ol ol { + padding-right: 0em; +} + +.container h4, .container h5, .container h6, .container dl { + padding-left: 0.5em; + padding-right: 0.5em; +} + +.container > .divBox, .container > .prettytable, .container > .multiline, +.container > .gallery, .container > div.center { + margin-left: 0.5em; + margin-right: 0.5em; +} + +.container div.floatleft { + margin-left: 0.5em; +} + +.container div.floatright { + margin-right: 0.5em; +} + +.container .usr-code div.center { + margin: 0; +} + +.container hr { + margin: 0 0.5em; +} + +table.container { + margin: 0; + border-style: none; + border-spacing: 0 0; + border-collapse: collapse; +} + +div.cFirst, table.cFirst, .containerTabs + .container, .boxTabsEnd + .container { + margin: 0; + clear: both; +} + +div.cInner, table.cInner { + margin: 0.75em; +} + +table.container td { + margin: 0; + padding: 0 0 0 0.75em; + vertical-align: top; +} + +table.container td:first-child { + padding: 0; +} + +* html table.container td { /* Stern-HTML-Hack fuer IE6 */ + padding-left: expression((this.parentNode.firstChild == this)? "0" : "0.75em" ); +} + +@media print { + .container { border: 0.25mm solid #6cc8f3; } + .container .header, .infobox .header { + font-size: 1em; + border-top: 0.25mm solid #c0c0c0; + } +} + +.regionFlag { + border: 1px solid #404040; + width: 20px; + height: 15px; + margin: 0 0.5em 0 0; + float: left; +} + +#socialbm iframe { + display: inline; + height: 45px; + margin: 0; +} +#socialbm a img { + vertical-align: 23px; +} + +.ImageGroup { + text-align: center; + border: 1px solid #6cc8f3; + background-color: #ffffff; +} +* html .ImageGroup { // IE6-Hack; + width: 220px; +} +.ImageGroup .header { + font-size: 110%; + font-weight: bold; + padding: 0 3px; + background: #f0f0f0; +} +.ImageGroup .thumb { + margin-bottom: 0; +} +.ImageGroup .thumbinner { + margin: 0 auto; +} +.ImageGroup .ImageGrUnitHeader { + background: #f0f0f0; +} + +.topicsTable { + width: 100%; + border-collapse: collapse; + empty-cells: show; + background: transparent; + border-spacing: 0 0; +} +.topicsTable td { + width: 50%; + vertical-align: top; + padding: 1em 0; +} +.topicsTable td:first-child { + padding-right: 1em; +} +.topicsTable td .floatright { + border: solid 1px #cccccc; + background: #eeeeee; + padding: 3px; + margin: 5px 0 0 1em; +} + +@media print { + .ImageGroup { + border: none; + padding: 0; + } + .ImageGroup .header, .ImageGroup .ImageGrUnitHeader { + display: none; + } +} + +#altIsIn { + line-height: 1.8em; +} + +/* Quickbar styles */ + +#content .qb { + border: 1px solid #6cc8f3; + margin: 0 0 1em; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; +} +#content .qbRight { + clear: right; + float: right; + margin: 0 0 1em 1em; + width: 300px; +} +#content .qbRightDiv { + clear: right; + float: right; + margin: 0 0 1em 1em; +} +#content .qbTopBorder { +} +#content .qbLeft { + clear: left; + float: left; + margin: 0 1em 0 1em; + width: 300px; +} +.qb td { + padding: 2px 0.4em; + vertical-align: baseline; +} +.qb th { + padding: 2px 0.4em; + vertical-align: baseline; + text-align: left; + font-weight: bold; +} +#content .qb .qbHeader { + text-align: center; + color: #004f80; + padding: 0.3em 0.35em; + font-size: 1.2em; + background: #f0f0f0; + border-top: 1px solid #c0c0c0; +} +#content .qb tr:first-child .qbHeader { + border-top: none; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -khtml-border-radius-topleft: 5px; + -khtml-border-radius-topright: 5px; +} +.qbImage { +/* border-top: 1px solid #4D64CF; */ + text-align: center; + padding: 5px 2px; + margin-left: auto; + margin-right: auto; +} +.qbImage div.thumb { + border-style: none; + margin-bottom: 0; +} +.qbImage div.thumbinner { + border-style: none; + padding: 0 !important; + background: transparent; + margin: 0 auto; +} +.qbImage div.tright { + float: none; + margin: 0; +} +.qb .qbImageCell { + padding: 0; +} +.qbImageCell .qbHeader { + border-bottom: none; +} +.qbEmpty { + display: none; +} +.qbEmpty td { + height: 1px; +} +.breakable { + font-size: 7%; + line-height: 0.1%; + text-decoration: none !important; + visibility: hidden; +} +@media print { + #content .qb { border-width: 0.25mm; } + #content .qb .qbHeader { + font-size: 1em; + background: #f0f0f0; + border-top: 0.25mm solid #c0c0c0; + border-bottom: 0.25mm solid #c0c0c0; + } +} + +/*** styles and counter for mapping listings ***/ +@media screen { + .printonly { display:none !important; } +} + +@media screen, print { + span.listing-map { + display: inline-block; + width: 12px; height: 13px; + text-align: right; + color: white; + font-size: 0.85em; + font-family: Arial,Verdana,sans-serif; + padding: 0px 2px 3px 1px; + -webkit-print-color-adjust: exact; //force printing on safari and chrome + } + + h2 { counter-reset: mapnumber; } + span.listing-map:before { + content: counter(mapnumber); + counter-increment: mapnumber; + } + + body { counter-reset: generalnumber; } + span.listing-map.listing-general:before { + content: counter(generalnumber); + counter-increment: generalnumber; + } + +} + +/* Externalisation des modèles de style pour améliorer les performances - Auslagerung von Stil-Vorlagen zur Performance-Steigerung */ + +#contentSub img { + vertical-align: baseline; +} + +.prettytable { + border: 1px solid #6cc8f3; + border-collapse: collapse; + empty-cells: show; + margin: 1em 0; + background: transparent; + border-spacing: 0 0; +} +.prettytable td, .prettytable th { + border: 1px solid #6cc8f3; + padding: 0.25em; + vertical-align: baseline; +} +.prettytable th { /* hightlighting */ + text-align: center; + border-bottom: 1px solid #6cc8f3; + border-top: 1px solid #6cc8f3; + background: #f0f0f0; + color: #004f80; +} +.sortable th { /* ab Version 1.9 */ + text-align: left; +} +.verticalCentered td, .verticalCentered th { + vertical-align: middle; +} +.textCentered td, .textCentered th { + text-align: center; +} +.framedBox { + margin: 1em 0; + padding: 0.5em; + border: 1px solid #6cc8f3; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + -o-border-radius: 5px; +} +.noFloat { + clear: both; + float: none; + margin: 0; +} + +/**** STYLES AIDE ET ACCUEIL ****/ +/* contruction des éléments */ +#aa-bloc-tete { + display:table; + width: 100%; +} + +#aa-bloc-gauche, +#aa-bloc-droite { + display:table-cell; + vertical-align:center; +} +#aa-bloc-droite { + width:30%; +} +#aa-bloc-dessous { + padding:5px 10px; +} +#aa-bloc-tete h2 { + margin-top:4pt; /* Correction du style des titres par défaut pour une meilleure intégration */ +} +/* Couleur et apparence des éléments */ +.aa-fond-gris { + background-color:#F6F6F6; + padding:10px; + font-size: 1.1em; + } +.aa-filet-gris { + border:1px solid #CCC; + } +.aa-fond-blanc { + background-color:#FFF; + padding:10px; + } +.aa-fond-avertissement { + display:block; + border-bottom:1px solid #C00; + background-color:#FFF; + padding: 10px; +} +.aa-titre-bleu { + color:#3366BB; + border:none; +} + +.aa-titre-rouge { + color:#C00; + border:none; +} +.aa-titre-vert { + color:#008769; + border:none; +} +.aa-faux-h2 { + font-weight:normal; + font-size:150%; +} +.aa-faux-h3 { + font-weight:normal; + font-size:132%; +} + +/* Styles pour [[Modèle:Animation]] */ + +.diaporamaControl img { + background-color: white; + border: 1px solid #DDDDDD; +} + +.diaporamaControl .ScrollBar { + background-image: url(//upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Round_Edge.png/5px-Round_Edge.png); + background-position: top; + background-repeat: repeat-x; +} + +.diaporamaControl .ScrollBarContainer { + background-image: url(//upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Round_Edge_bis.png/5px-Round_Edge_bis.png); + background-position: top; + background-repeat: repeat-x; +} + +.diaporama .magnify { + display: none; +} + +.diaporama select { + font-size: 12px; +} + +/* CHIFFRES ROMAINS */ + +/* Affichage des chiffres romains, voir [[modèle:Rom]] ou [[modèle:Romain]]. */ + +.romain { + text-transform: lowercase; + font-variant: small-caps; +} + +/* [[Modèle:Indication de langue]] */ + +.indicateur-langue { + font-family: monospace; + font-weight: bold; + font-size: small; + font-style: normal; +} + +.indicateur-format { + font-family: monospace; + font-weight: bold; + font-size: small; + font-style: normal; +}/* +MediaWiki:Vector.css +*/ +/* CSS placed here will affect users of the Vector skin */ + +#contentSub, #contentSub2 { font-size: 100% } + +.ns-8 pre { font-size: 125% } + +#geoCoord, #DoM { + position: absolute; + z-index: 1; + right: 12px; + right: 0; + top: -36px; + float: right; +} + +#DoM { + top: -4px; +} \ No newline at end of file diff --git a/bin/Release/AppX/www/css/app.css b/bin/Release/AppX/www/css/app.css index 0aa0e28b..ef6ec8f3 100644 --- a/bin/Release/AppX/www/css/app.css +++ b/bin/Release/AppX/www/css/app.css @@ -84,6 +84,16 @@ color : orange; } +.settings { + float: left; + margin: 5px; + padding: 10px; + max-width: 300px; + height: 150px; + border: 1px solid black; +} + + /* Réduction de la taille des éléments en haut pour les petits écrans */ @media (max-width: 768px) { /* Pour réduire la taille du menu en haut */ @@ -91,7 +101,7 @@ min-height: 20px !important; margin-bottom: 1px !important; } - .navbar-brand { + .navbar-brand, .navbar-nav a { /* GK added navbar-nav a*/ padding-top: 2px !important; padding-bottom: 1px !important; height: 25px !important; @@ -102,6 +112,21 @@ margin-top: 2px !important; margin-bottom: 0px !important; } +/* Pour réduire la taille des éléments et boutons dans l'aréa de navégation - GK + .navbar-nav, .navbar-nav > li { + padding-top: 2px !important; + padding-bottom: 2px !important; + margin-top: 2px !important; + margin-bottom: 0px !important; + } */ + .navbar-nav { + margin-top: 0px !important; + margin-bottom: 0px !important; + } + .navbar-nav > li > a { /*Make sure these align correctly rather than stacking at full width - GK*/ + float: left !important; + } + [role=region] > header { margin-bottom: 0px !important; } @@ -123,5 +148,5 @@ padding-top: 1px !important; padding-bottom: 1px !important; font-size: 16px !important; - } + } } \ No newline at end of file diff --git a/bin/Release/AppX/www/index.html b/bin/Release/AppX/www/index.html index d045c056..42cdb8b7 100644 --- a/bin/Release/AppX/www/index.html +++ b/bin/Release/AppX/www/index.html @@ -45,21 +45,17 @@ @@ -206,20 +202,18 @@ -
-
+

Please select the display style:

- -  Use Wikipedia desktop display style (for Wikipedia files) + +  Use Wikimedia desktop display style (for Wikipedia files)

-  Use Wikipedia mobile display style (for Wikipedia files) +  Use Wikimedia mobile display style (for Wikipedia files)

-
-
+

Please select the display option:

diff --git a/bin/Release/AppX/www/js/app.js b/bin/Release/AppX/www/js/app.js index 7009c970..49de1b96 100644 --- a/bin/Release/AppX/www/js/app.js +++ b/bin/Release/AppX/www/js/app.js @@ -35,7 +35,15 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles */ var MAX_SEARCH_RESULT_SIZE = module.config().results; //This is set in init.js - /** +//TESTING + // Get the app's installation folder. + //var appFolder = Windows.ApplicationModel.Package.current.installedLocation; + var appfolder = ""; + // Print the folder's path to the Visual Studio Output window. + //console.log(appFolder.name, "folder path:", appFolder.path); +//END TESTING + + /** * @type ZIMArchive */ var selectedArchive = null; @@ -200,17 +208,18 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles $('input:checkbox[name=imageDisplayMode]').on('change', function (e) { params['imageDisplay'] = this.checked ? true : false; }); - $('input:radio[name=cssInjectionMode]').on('change', function (e) { + $('input:radio[name=cssInjectionMode]').on('click', function (e) { params['cssSource'] = this.value; - document.getElementById('returntoArticle_top').innerHTML = ""; - document.getElementById('returntoArticle_bottom').innerHTML = ""; + //document.getElementById('returntoArticle_top').innerHTML = ""; + //document.getElementById('returntoArticle_bottom').innerHTML = ""; }); $(document).ready(function (e) { // Set checkbox for cssCache and radio for cssSource document.getElementById('cssCacheModeCheck').checked = params['cssCache']; document.getElementById('imageDisplayModeCheck').checked = params['imageDisplay']; + $('input:radio[name=cssInjectionMode]').filter('[value="' + params['cssSource'] + '"]').prop('checked', true); }); - + /** * Displays or refreshes the API status shown to the user */ @@ -393,6 +402,7 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles * @type Array. */ var storages = []; + //var storages = [appFolder.path]; //UWP function searchForArchivesInPreferencesOrStorage() { // First see if the list of archives is stored in the cookie var listOfArchivesFromCookie = cookies.getItem("listOfArchives"); @@ -422,8 +432,9 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles // Make a fake first access to device storage, in order to ask the user for confirmation if necessary. // This way, it is only done once at this moment, instead of being done several times in callbacks // After that, we can start looking for archives - storages[0].get("fake-file-to-read").then(searchForArchivesInPreferencesOrStorage, - searchForArchivesInPreferencesOrStorage); + //storages[0].get("fake-file-to-read").then(searchForArchivesInPreferencesOrStorage, + //searchForArchivesInPreferencesOrStorage); + searchForArchivesInPreferencesOrStorage; } else { // If DeviceStorage is not available, we display the file select components @@ -808,6 +819,7 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles * Display the the given HTML article in the web page, * and convert links to javascript calls * NB : in some error cases, the given title can be null, and the htmlArticle contains the error message + * * @param {DirEntry} dirEntry * @param {String} htmlArticle */ @@ -822,11 +834,12 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles //Fast-replace img src with data-kiwixsrc and hide image [kiwix-js #272] htmlArticle = htmlArticle.replace(/(]*\b)src(\s*=)/ig, "$1data-kiwixsrc$2"); - //Ensure 24px clickable image height so user can request images by clicking [kiwix-js #173] - htmlArticle = htmlArticle.replace(/(]*\b)height(\s*=\s*)/ig, - '$1height="24" alt="Image" style="color: lightblue; background-color: lightblue;" ' + - 'onload="this.height = this.getAttribute(\'data-kiwixheight\'); this.style.background = \'\';" ' + - 'data-kiwixheight$2'); + if (!params['imageDisplay']) { + //Ensure 36px clickable image height so user can request images by clicking [kiwix-js #173] + htmlArticle = htmlArticle.replace(/(]*\b)height(\s*=\s*)/ig, + '$1height="36" alt="Placeholder" style="color: lightblue; background-color: lightblue;" ' + + 'data-kiwixheight$2'); + } //Preload stylesheets [kiwix-js @149] //Set up blobArray of promises @@ -870,7 +883,8 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles function (dirEntry) { selectedArchive.readBinaryFile(dirEntry, function (readableTitle, content, namespace, url) { - //var cssContent = util.uintToString(content); //Uncomment this line and break on next to capture cssContent for local filesystem cache + //DEV: Uncomment line below and break on next to capture cssContent for local filesystem cache + //var cssContent = util.uintToString(content); var cssBlob = new Blob([content], { type: 'text/css' }, { oneTimeOnly: true }); var newURL = [namespace + "/" + url, URL.createObjectURL(cssBlob)]; //blobArray[index] = newURL; //Don't bother with "index" -- you don't need to track the order of the blobs TODO: delete this logic @@ -1006,182 +1020,669 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles } }); - // Load images + loadImages(); + //loadJavascript(); //Disabled for now, since it does nothing + } - //TESTING - console.log("** First Paint complete **"); - console.timeEnd("Time to First Paint"); + } //End of injectHTML() - //var imageURLs = htmlContent.match(/kiwixsrc\s*=\s*["'](?:\.\.\/|\/)+(I\/)/ig); - var imageDisplay = params['imageDisplay']; - var images = $('#articleContent').contents().find('body').find('img'); - var countImages = 0; - //DEV: firstSliceSize determines maximum number of images loaded above the fold (should be <= 10) - //Smaller numbers give faster subjective experience, but too small may delay load of visible images above the fold - var firstSliceSize = 10; - //DEV: sliceSize determines minimum batch size of background image extraction for remaining images - //Larger numbers marginally increase speed of background extraction but take longer for directory lookup and conflict with user scrolling - var sliceSize = 20; - var remainder = (images.length - firstSliceSize) % (sliceSize); - var imageSlice = {}; - var slice$x = 0; - var slice$y = 0; - var windowScroll = false; - if (images.length && imageDisplay) { //If there are images in the article, set up a listener function for onscroll event - if (images.length > firstSliceSize) { - $("#articleContent").contents().on("scroll", function () { - //Ensure event doesn't fire multiple times and waits for previous slice to be retrieved - if (windowScroll && countImages == slice$y) { - windowScroll = false; //Indicate we no longer need to delay execution because user has scrolled - sliceImages(); - } - }); - } - sliceImages(); - } else { //User did not request images, so give option of loading one by one {kiwix-js #173] - if (images.length) { - images.each(function () { - // Attach an onclick function to load the image - var img = $(this); - $(this).on('click', function () { - loadOneImage(img.attr('data-kiwixsrc'), function (url) { - img[0].src = url; - }); - }); - }); - } + if (contentInjectionMode === 'jquery') { + //loadImages(); + //loadJavascript(); //Disabled for now, since it does nothing + } + + } //End of displayArticleInForm() + + /** This is the main image loading function. + * Contains four sub functions: prepareImages, triageImages, displaySlices, loadImageSlice + * and a utility function checkVisibleImages + */ + function loadImages() { + + //TESTING + console.log("** First Paint complete **"); + console.timeEnd("Time to First Paint"); + + //Set up tracking variables + var countImages = 0; + //DEV: Set this to the number of images you want to prefetch after the on-screen images have been fetched + var prefetchSliceSize = 20; + //DEV: SVG images are currently very taxing: keep this number at 5 or below and test on your system with Sine.html + var svgSliceSize = 3; + var visibleSlice = []; + var svgSlice = []; + var prefetchSlice = []; + var windowScroll = true; + var imageDisplay = params['imageDisplay']; + + //Establish master image array + var images = $('#articleContent').contents().find('body').find('img'); + var allImages = images.length; + + //If user wants to display images... + if (imageDisplay) { + + //Set up a listener function for onscroll event + if (allImages > prefetchSliceSize) { + //Polyfill scrollStopped event + $.fn.scrollStopped = function (callback) { + var that = this, $this = $(that); + $this.scroll(function (ev) { + clearTimeout($this.data('scrollTimeout')); + $this.data('scrollTimeout', setTimeout(callback.bind(that), 250, ev)); + }); } + $("#articleContent").contents().scrollStopped(prepareImages); + /*(function () { + //Ensure event doesn't fire multiple times before launched process has finished + if (windowScroll) { + //scrollEnded = true; + windowScroll = false; + prepareImages(); + } + }); + /*$("#articleContent").contents().on("scroll", function () { + //Ensure event doesn't fire multiple times before scrollStopped "event" + if (windowScroll && scrollEnded) { + scrollEnded = false; + windowScroll = false; + prepareImages(); + } + });*/ + } + if (allImages) { + prepareImages(); + } else { + console.log("There are no images to display in this article."); + } + } else { + console.log("Image retrieval disabled by user"); + //User did not request images, so give option of loading one by one {kiwix-js #173] + if (images.length) { + images.each(function () { + // Attach an onclick function to load the image + var img = $(this); + img.on('click', function () { + this.height = this.getAttribute('data-kiwixheight'); + this.style.background = ""; + //loadImageSlice(this, 0, 0, function (sliceID, sliceCount, sliceEnd, url) { + // img[0].src = url; + //}); //Both the blob method and the src="data:" method work - if changing check parameters carefully + //loadImageSlice(this.getAttribute('data-kiwixsrc'), 0, 0, function (sliceID,sliceCount,sliceEnd,mimetype,data) { + loadImageSlice(this, 0, 0, function (sliceID, sliceCount, sliceEnd, mimetype, data) { + img[0].src = "data:" + mimetype + ";base64," + btoa(data); + }, true); + }); + }); + } //TESTING - if (!images.length) { - console.log("No images in document"); - console.timeEnd("Time to Document Ready"); + console.timeEnd("Time to Document Ready"); + } + + /** Prepares the main array of images remaining for triage + * and determines which images are visible + */ + function prepareImages() { + //Ensure the function isn't launched multiple times + if (!windowScroll) { return; } + windowScroll = false; + + //Reload images array because we may have spliced it on a previous loop + images = $('#articleContent').contents().find('body').find('img'); + + //Remove images that have already been loaded + var visibleImage = null; + var lastRemovedPosition = 0; + for (var i = 0; i < images.length; i++) { + if (images[i].src) { + visibleImage = uiUtil.isElementInView(images[i], true) ? lastRemovedPosition : visibleImage; + images.splice(i, 1); + i--; //If we removed an image, reset the index + lastRemovedPosition++; + } + } + + if (images.length) { + console.log("Processing " + images.length + " images..."); + //Determine first and last visible images in the current window + var view = checkVisibleImages(); + //windowScroll = true; + //return; + + //If there are undisplayed images in the current window... + if (view.lastVisible >= 0) { + triageImages(view.firstVisible, view.lastVisible); } else { - if (!imageDisplay) { - console.log("Image retrieval disabled by user"); - console.timeEnd("Time to Document Ready"); - } - } - //END TESTING - - /** - * Loads images in batches or "slices" according to firstSliceSize and sliceSize parameters set above - * Slices after firstSlice are delayed until the user scrolls the iframe window - **/ - function sliceImages() { - //If starting loop or slice batch is complete AND we still need images for article - if ((countImages >= slice$y) && (countImages < images.length)) { - if (!windowScroll) { //If we haven't requested the next loop to be on scroll - slice$x = slice$y; - slice$y = slice$y > 0 ? slice$y + sliceSize : slice$y + firstSliceSize; //Increment by standard or initial sliceSize - //If all images can be obtained in one batch, set slice$y to number of images - slice$y = slice$y > images.length ? images.length : slice$y; - //Last batch should be increased to include any remainder - if (slice$x > 0 && (slice$y + remainder === images.length)) { slice$y += remainder; } - console.log("Requesting images # " + (slice$x + 1) + " to " + slice$y + "..."); - imageSlice = images.slice(slice$x, slice$y); - serializeImages(); + //If the currently visible image(s) have already been loaded... + if (visibleImage != null) { + //If we are viewing an image within 5 images of the next unloaded image + if (lastRemovedPosition - visibleImage <= 5) { + triageImages(); } else { - console.log("** Waiting for user to scroll the window..."); - } - } else { //All images requested, so Unload the scroll listener - if (images && images.length > firstSliceSize) { - if (countImages == images.length) { - console.log("Unloading scroll listener"); - $("#articleContent").contents().off('scroll'); - } - } + console.log("No images need prefetching\n\n" + + "** Waiting for user to scroll **"); + windowScroll = true; + } + } else { + //We don't know where we are because no images are in view, so we'd better fetch some more + triageImages(); } } + } else { + //Unload scroll listener + console.log("Unloading scroll listener"); + $("#articleContent").contents().off('scroll'); + windowScroll = true; //Check if it's really unloaded... + } - function serializeImages() { - $(imageSlice).each(function () { - var image = $(this); - // It's a standard image contained in the ZIM file - // We try to find its name (from an absolute or relative URL) - var imageMatch = image.attr('data-kiwixsrc').match(regexpImageUrl); //kiwix-js #272 - if (imageMatch) { - var title = decodeURIComponent(imageMatch[1]); - selectedArchive.getDirEntryByTitle(title).then(function (dirEntry) { - selectedArchive.readBinaryFile(dirEntry, function (readableTitle, content) { - // TODO : use the complete MIME-type of the image (as read from the ZIM file) - uiUtil.feedNodeWithBlob(image, 'src', content, 'image'); - countImages++ + } //End of prepareImages() - //TESTING - console.log("Extracted image " + (countImages) + " of " + images.length + "..."); - if (countImages == firstSliceSize || (countImages <= firstSliceSize && countImages == images.length)) { - console.log("** First image slice extracted: document ready **"); - console.timeEnd("Time to Document Ready"); - console.log(""); - } - if (countImages == images.length) { - console.log("** All images extracted **"); - } - //END TESTING + /** + * Sort the images into three arrays: + * visibleSlice (visible images which will be loaded first) + * svgSlice (groups together SVG images) + * prefetchSlice (preload set number of non-visible images) + * Pass the index of the first and last images of visible area if known + * + * @param {number} firstVisible + * @param {number} lastVisible + */ + function triageImages(firstVisible, lastVisible) { + //Set the window of images to be requested + if (typeof firstVisible === 'undefined' || firstVisible == null) { firstVisible = -1; } //No first images was set + if (typeof lastVisible === 'undefined' || lastVisible == null) { lastVisible = -1; } //No first images was set + var lengthSlice = lastVisible + prefetchSliceSize + 1; + var startSlice = firstVisible; + //If the requested images window extends beyond the end of the image array... + if (lengthSlice > images.length) { + //Move the window backwards + startSlice -= lengthSlice - images.length; + lengthSlice = images.length; + } + //Check that the start of the window isn't before the beginning of the array + startSlice = startSlice < 0 ? 0 : startSlice; - if (countImages == slice$y) { - windowScroll = true; //Once slice is complete, delay the loop - } - sliceImages(); - }); - }).fail(function (e) { - console.error("Could not find DirEntry for image:" + title, e); - countImages++; - if (countImages == slice$y) { - windowScroll = true; //Once slice is complete, delay the loop - } - sliceImages(); - }); + + //Sort through images to put them in the appropriate slice arrays + var svgGroup1 = [], svgGroup2 = []; + for (var i = startSlice; i < lengthSlice; i++) { + if (/\.svg$/i.test(images[i].getAttribute('data-kiwixsrc'))) { + if (i < firstVisible || i > lastVisible) { + svgGroup2.push(images[i]); + } else { + svgGroup1.push(images[i]); + } + } else { + if (i <= lastVisible) { + visibleSlice.push(images[i]); + } else { + prefetchSlice.push(images[i]); + } + } + } + svgSlice = svgGroup1.concat(svgGroup2); + + //Call displaySlices with all counters zeroed + //This lets the function know that it should initialize display process + displaySlices(0, 0, 0); + + } //End of triageImages() + + /** + * This controls the order in which slices will be displayed and acts as a callback function for loadImageSlice + * sliceID (callback value) identifies the slices: 1=visibleSlice; 2=prefetchSlice; 3=svgSlice + * sliceCount (callback value) keeps count of the images loaded in the current slice + * sliceEnd (callback value) is the index of the last image in the current slice + * Start the function with all values zeroed + * + * @callback requestCallback + * @param {number} sliceID + * @param {number} sliceCount + * @param {number} sliceEnd + */ + function displaySlices(sliceID, sliceCount, sliceEnd) { + //Only respond to callback if all slice images have been extracted (or on startup) + if (sliceCount === sliceEnd) { + sliceID++; //Get ready to process next slice + if (sliceID == 1) { + if (visibleSlice.length) { + console.log("** About to request " + visibleSlice.length + " visible image(s)..."); + loadImageSlice(visibleSlice, 1, visibleSlice.length, displaySlices); + visibleSlice = []; + //TESTING + console.timeEnd("Time to Document Ready"); + } else { //No images in this slice so move on to next + sliceID++; + } + } + if (sliceID == 2) { + if (prefetchSlice.length) { + console.log("Prefetching " + prefetchSlice.length + " offscreen images..."); + loadImageSlice(prefetchSlice, 2, prefetchSlice.length, displaySlices); + prefetchSlice = []; + } else { //No images in this slice so move on to next + sliceID++; + } + } + if (sliceID == 3) { + if (svgSlice.length) { + //Set up variables to hold visible image range (to check whether user scrolls during lengthy procedure) + var startSVG; + var endSVG; + iterateSVGSlice(3, 0, 0); + } else { //No images in this slice so move on to next + sliceID++; + } + } + if (sliceID > 3) { + if (countImages === allImages) { + console.log("** All images extracted from current document **") + windowScroll = true; //Go back to prove this! + } else { + console.log("All images extracted from requested slices\n" + + "** Waiting for user scroll... **"); + windowScroll = true; + } + } + } + + /** + * This is a specialized callback to iterate the SVGSlice + * This slice needs special handling because svg images can hang the program + * + * @callback requestCallback + * @param {number} sliceID + * @param {number} sliceCount + * @param {number} sliceEnd + */ + function iterateSVGSlice(sliceID, sliceCount, sliceEnd) { + if (sliceCount === sliceEnd) { + //Check to see if visible images have changed (i.e. if user has scrolled) + if (!sliceCount) { + console.log("startSVG"); + startSVG = checkVisibleImages(); + } else { + console.log("endSVG"); + endSVG = checkVisibleImages(); + } + if (endSVG) { + if (startSVG.firstVisible != endSVG.firstVisible || startSVG.lastVisible != endSVG.lastVisible) { + //Visible images have changed, so abandon this svgSlice + console.log("** Abandoning svgSlice due to user scroll **"); + svgSlice = []; + windowScroll = true; + prepareImages(); + return; + } + } + var batchSize = svgSliceSize > svgSlice.length ? svgSlice.length : svgSliceSize; + if (batchSize) { + //Split svgSlice into chunks to avoid hanging the program + var svgSubSlice = svgSlice.slice(0, batchSize); + svgSlice = svgSlice.slice(batchSize, svgSlice.length); + console.log("Requesting batch of " + batchSize + " SVG image(s)..."); + loadImageSlice(svgSubSlice, 3, batchSize, iterateSVGSlice); + } else { + console.log("** Finished iterating svgSlice"); + displaySlices(3, 0, 0); + } + } + } //End of iterateSVGSlice() + + } //End of displaySlices() + + /** + * Loads images in the array passed as images + * sliceID will be passed to the callback + * sliceEnd is the index of the last image in the current slice + * dataRequested == true returns the content and disables creation of blob + * + * @param {Array} imnages + * @param {number} sliceID + * @param {number} sliceEnd + * @param {requestCallback} callback + * @param {Boolean} dataRequested + */ + function loadImageSlice(images, sliceID, sliceEnd, callback, dataRequested) { + var sliceCount = 0; + $(images).each(function () { + var image = $(this); + // It's a standard image contained in the ZIM file + // We try to find its name (from an absolute or relative URL) + var imageMatch = image.attr('data-kiwixsrc').match(regexpImageUrl); //kiwix-js #272 + if (imageMatch) { + var title = decodeURIComponent(imageMatch[1]); + selectedArchive.getDirEntryByTitle(title).then(function (dirEntry) { + selectedArchive.readBinaryFile(dirEntry, function (readableTitle, content, namespace, url) { + var mimetype = url.match(/\.(\w{2,4})$/); + mimetype = mimetype ? "image/" + mimetype[1].toLowerCase() : "image"; + mimetype = /\.jpg$/i.test(url) ? "image/jpeg" : mimetype; + mimetype = /\.tif$/i.test(url) ? "image/tiff" : mimetype; + mimetype = /\.ico$/i.test(url) ? "image/x-icon" : mimetype; + mimetype = /\.svg$/i.test(url) ? "image/svg+xml" : mimetype; + if (!dataRequested) { + uiUtil.feedNodeWithBlob(image, 'src', content, mimetype); + } + sliceCount++; + console.log("Extracted image #" + countImages + "..."); + countImages++; + if (!dataRequested) { + callback(sliceID, sliceCount, sliceEnd, url); + } else { + callback(sliceID, sliceCount, sliceEnd, mimetype, util.uintToString(content)); + } + }); + }).fail(function (e) { + sliceCount++; + console.error("Could not find DirEntry for image:" + title, e); + countImages++; + callback(sliceID, sliceCount, sliceEnd, "Error!"); + }); + } + }); + } //End of loadImageRange() + + /** + * This is a utility function to check the window of images visible to the user. + * It needs to be run within the scope of the main images array. + * Returns an object with attributes .firstVisible and .lastVisible + * They return null if no images are currently visible. + */ + function checkVisibleImages() { + var firstVisible = null; + var lastVisible = null; + //Determine first and last visible images in the current window + for (var i = 0; i < images.length; i++) { + //console.log("Checking #" + i + ": " + images[i].getAttribute("data-kiwixsrc")); + if (uiUtil.isElementInView(images[i], true)) { + //console.log("#" + i + " *is* visible"); + if (firstVisible == null) { firstVisible = i; } + lastVisible = i; + } else { + //console.log("#" + i + " is not visible"); + if (firstVisible != null && lastVisible != null) { + console.log("First visible image is #" + firstVisible + "\n" + + "Last visible image is #" + lastVisible); + break; //We've found the last visible image, so stop the loop + } + } + } + return { + firstVisible: firstVisible, + lastVisible: lastVisible + }; + } + + + + /*** Image functions below this comment are deprecated **** + + function prePrepImages() { + //var imageURLs = htmlContent.match(/kiwixsrc\s*=\s*["'](?:\.\.\/|\/)+(I\/)/ig); + var imageDisplay = params['imageDisplay']; + var images = $('#articleContent').contents().find('body').find('img'); + var countImages = 0; + //DEV: firstSliceSize determines maximum number of images loaded above the fold (should be <= 10) + //Smaller numbers give faster subjective experience, but too small may delay load of visible images above the fold + var firstSliceSize = 7; + //DEV: sliceSize determines minimum batch size of background image extraction for remaining images + //Larger numbers marginally increase speed of background extraction but take longer for directory lookup and conflict with user scrolling + var sliceSize = 10; + var svgSliceSize = 5; + var imageSlice = {}; + var slice$x = 0; + var slice$y = 0; + var svg = 0; + var windowScroll = false; + + //If there are images in the article, set up a listener function for onscroll event + if (images.length && imageDisplay) { + if (images.length > firstSliceSize) { + $("#articleContent").contents().on("scroll", function () { + //Ensure event doesn't fire multiple times and waits for previous slice to be retrieved + if (windowScroll && countImages == slice$y) { + windowScroll = false; //Indicate we no longer need to delay execution because user has scrolled + sliceImages(); } }); } - // Load Javascript content - function loadJavascript() { - //$('#articleContent').contents().find('script').each(function () { - var script = $(this); - // We try to find its name (from an absolute or relative URL) - if (script) { var srcMatch = script.attr("src").match(regexpMetadataUrl) } - // TODO check that the type of the script is text/javascript or application/javascript - if (srcMatch) { - // It's a Javascript file contained in the ZIM file - var title = uiUtil.removeUrlParameters(decodeURIComponent(srcMatch[1])); - selectedArchive.getDirEntryByTitle(title).then(function (dirEntry) { - if (dirEntry === null) - console.log("Error: js file not found: " + title); - else - selectedArchive.readBinaryFile(dirEntry, function (readableTitle, content) { - // TODO : I have to disable javascript for now - // var jsContent = encodeURIComponent(util.uintToString(content)); - //script.attr("src", 'data:text/javascript;charset=UTF-8,' + jsContent); - }); - }).fail(function (e) { - console.error("could not find DirEntry for javascript : " + title, e); + sliceImages(); + + } else { //User did not request images, so give option of loading one by one {kiwix-js #173] + if (images.length) { + images.each(function () { + // Attach an onclick function to load the image + var img = $(this); + img.on('click', function () { + this.height = this.getAttribute('data-kiwixheight'); + this.style.background = ""; + //loadOneImage(this.getAttribute('data-kiwixsrc'), function (url) { + // img[0].src = url; + //}); //Both the blob method and the src="data:" method work - if changing, edit loadOneImage() also + loadOneImage(this.getAttribute('data-kiwixsrc'), function (mimetype, data) { + img[0].src = "data:" + mimetype + ";base64," + btoa(data); + }); }); + }); + } + } + //TESTING + if (!images.length) { + console.log("No images in document"); + console.timeEnd("Time to Document Ready"); + } else { + if (!imageDisplay) { + console.log("Image retrieval disabled by user"); + console.timeEnd("Time to Document Ready"); + } + } + //END TESTING + } + + /** + * Loads images in batches or "slices" according to firstSliceSize and sliceSize parameters set above + * Slices after firstSlice are delayed until the user scrolls the iframe window + ** + function sliceImages() { + //Chrome seems to lose the number of images between loops, so we repeat this statement: + images = $('#articleContent').contents().find('body').find('img'); + + //If starting loop or slice batch is complete AND we still need images for article + if ((countImages >= slice$y) && (countImages < images.length)) { + if (!windowScroll) { //If we haven't requested the next loop to be on scroll + //Filter out images we've already extracted + for (var i = 0; i < images.length; i++) { + if (images[i].src) { + images.splice(i, 1); + countImages--; //Don't count already displayed images + } + } + //TESTING: Reset everything! NOPE - causes infinite loop + //countImages = 0; + //slice$x = 0; + //slice$y = 0; + + //slice$x = slice$y; //Not needed, because we'll always start again now + var remainder = (images.length - firstSliceSize) % (sliceSize); + slice$y = slice$y > 0 ? slice$y + sliceSize : slice$y + firstSliceSize; //Increment by standard or initial sliceSize + //If all images can be obtained in one batch, set slice$y to number of images + slice$y = slice$y > images.length ? images.length : slice$y; + //Last batch should be increased to include any remainder + if (slice$x > 0 && (slice$y + remainder === images.length)) { slice$y += remainder; } + + //Find visible images + var firstVisible, lastVisible; + for (var n = 0; n < images.length; n++) { + var visibility = uiUtil.isElementInView(images[n], false); + if (visibility) { + firstVisible = firstVisible >= 0 ? firstVisible : n; + lastVisible = n; + } else { + if (firstVisible >= 0 && lastVisible >= 0) { + console.log("** First visible image is #" + firstVisible + "\n" + + "** Last visible image is #" + lastVisible); + break; + } + } + } + + //Extend slice$y if it doesn't cover all visible images + slice$y = slice$y < lastVisible ? lastVisible : slice$y; + + console.log("Requesting images # " + (slice$x + 1) + " to " + slice$y + "..."); + imageSlice = images.slice(slice$x, slice$y); + + // Check to see if the slice contains svg images... + if (imageSlice.length > svgSliceSize) { + for (var t = 0; t < imageSlice.length; t++) { + if (/\.svg$/i.test(imageSlice[t].getAttribute('data-kiwixsrc'))) { + var tempimageSlice = imageSlice.slice(0, svgSliceSize); + slice$y = slice$x + svgSliceSize //Reduce sliceSize to prevent app from hanging + imageSlice = tempimageSlice; + //Increment svg loop detector unless we reach end of visible images + svg = svg < (Math.ceil((lastVisible - slice$y)/svgSliceSize)) ? svg + 1 : 0; //Resetting svg to 0 will cause wait on scroll on next sliceImages loop + console.log("SVG images detected in slice, reducing image sliceSize..."); + break; + } + } + } + + serializeImages(); + + } else { + console.log("** Waiting for user to scroll the window..."); + } + } else { //All images requested, so Unload the scroll listener + if (images && images.length > firstSliceSize) { + if (countImages == images.length) { + console.log("Unloading scroll listener"); + $("#articleContent").contents().off('scroll'); } } - } } - } - function loadOneImage(image, callback) { - // It's a standard image contained in the ZIM file - // We try to find its name (from an absolute or relative URL) - var imageMatch = image.match(regexpImageUrl); - if (imageMatch) { - var title = decodeURIComponent(imageMatch[1]); - selectedArchive.getDirEntryByTitle(title).then(function (dirEntry) { - selectedArchive.readBinaryFile(dirEntry, function (readableTitle, content, namespace, url) { - var imageBlob = new Blob([content], { type: 'text/css' }, { oneTimeOnly: true }); - var newURL = URL.createObjectURL(imageBlob); - callback(newURL); - }); - }).fail(function (e) { - console.error("Could not find DirEntry for image:" + title, e); - callback(""); + function serializeImages() { + $(imageSlice).each(function () { + var image = $(this); + //TESTING: If the image isn't in the viewport, abandon it + if (!uiUtil.isElementInView(image[0], false)) { + //countImages++; + slice$y--; + windowScroll = countImages == slice$y ? true : windowScroll; + sliceImages(); + return; + } + + /*TEST + var isInView = uiUtil.isElementInView(image[0], false); + console.log("The next image is " + (isInView ? "" : "not ") + "visible"); + //* + + // It's a standard image contained in the ZIM file + // We try to find its name (from an absolute or relative URL) + var imageMatch = image.attr('data-kiwixsrc').match(regexpImageUrl); //kiwix-js #272 + if (imageMatch) { + var title = decodeURIComponent(imageMatch[1]); + selectedArchive.getDirEntryByTitle(title).then(function (dirEntry) { + selectedArchive.readBinaryFile(dirEntry, function (readableTitle, content, namespace, url) { + // TODO : use the complete MIME-type of the image (as read from the ZIM file) + var mimetype = url.match(/\.(\w{2,4})$/); + mimetype = mimetype ? "image/" + mimetype[1].toLowerCase() : "image"; + mimetype = /\.jpg$/i.test(url) ? "image/jpeg" : mimetype; + mimetype = /\.tif$/i.test(url) ? "image/tiff" : mimetype; + mimetype = /\.ico$/i.test(url) ? "image/x-icon" : mimetype; + mimetype = /\.svg$/i.test(url) ? "image/svg+xml" : mimetype; + uiUtil.feedNodeWithBlob(image, 'src', content, mimetype); + //Alternative way of loading images below also works + //var data = util.uintToString(content); + //image[0].src = "data:" + mimetype + ";base64," + btoa(data); + countImages++ + + //TESTING + console.log("Extracted image " + (countImages) + " of " + images.length + "..."); + if (countImages == firstSliceSize || (countImages <= firstSliceSize && countImages == images.length)) { + console.log("** First image slice extracted: document ready **"); + console.timeEnd("Time to Document Ready"); + console.log(""); + } + if (countImages == images.length) { + console.log("** All images extracted **"); + } + //END TESTING + + if (countImages == slice$y) { + //Once slice is complete, delay the loop unless there are SVG images in slice + windowScroll = svg ? false : true; //If svg is 0, waits for user scroll on next sliceImages loop + } //Explanation: extraction of svg images is slow and memory-hungry, so keep going while detecting SVG, in slices of 5 (see code above) + sliceImages(); + }); + }).fail(function (e) { + console.error("Could not find DirEntry for image:" + title, e); + countImages++; + if (countImages == slice$y) { + windowScroll = true; //Once slice is complete, delay the loop + } + sliceImages(); + }); + } }); } + + function loadOneImage(image, callback) { + // It's a standard image contained in the ZIM file + // We try to find its name (from an absolute or relative URL) + var imageMatch = image.match(regexpImageUrl); + if (imageMatch) { + var title = decodeURIComponent(imageMatch[1]); + selectedArchive.getDirEntryByTitle(title).then(function (dirEntry) { + selectedArchive.readBinaryFile(dirEntry, function (readableTitle, content, namespace, url) { + var mimetype = url.match(/\.(\w{2,4})$/); + mimetype = mimetype ? "image/" + mimetype[1].toLowerCase() : "image"; + mimetype = /\.jpg$/i.test(url) ? "image/jpeg" : mimetype; + mimetype = /\.tif$/i.test(url) ? "image/tiff" : mimetype; + mimetype = /\.ico$/i.test(url) ? "image/x-icon" : mimetype; + mimetype = /\.svg$/i.test(url) ? "image/svg+xml" : mimetype; + //var imageBlob = new Blob([content], { type: mimetype }, { oneTimeOnly: true }); + //var newURL = URL.createObjectURL(imageBlob); + var data = util.uintToString(content); + //callback(newURL); //If using blob method, no need to send mimetype + callback(mimetype, data); + }); + }).fail(function (e) { + console.error("Could not find DirEntry for image:" + title, e); + callback(""); + }); + } + } */ + + } //End of loadImages() + + // Load Javascript content + function loadJavascript() { + $('#articleContent').contents().find('script').each(function () { + var script = $(this); + // We try to find its name (from an absolute or relative URL) + if (script) { var srcMatch = script.attr("src").match(regexpMetadataUrl) } + // TODO check that the type of the script is text/javascript or application/javascript + if (srcMatch) { + // It's a Javascript file contained in the ZIM file + var title = uiUtil.removeUrlParameters(decodeURIComponent(srcMatch[1])); + selectedArchive.getDirEntryByTitle(title).then(function (dirEntry) { + if (dirEntry === null) + console.log("Error: js file not found: " + title); + else + selectedArchive.readBinaryFile(dirEntry, function (readableTitle, content) { + // TODO : I have to disable javascript for now + // var jsContent = encodeURIComponent(util.uintToString(content)); + //script.attr("src", 'data:text/javascript;charset=UTF-8,' + jsContent); + }); + }).fail(function (e) { + console.error("could not find DirEntry for javascript : " + title, e); + }); + } + }); } diff --git a/bin/Release/AppX/www/js/lib/transformStyles.js b/bin/Release/AppX/www/js/lib/transformStyles.js index e53dae86..d2a2225a 100644 --- a/bin/Release/AppX/www/js/lib/transformStyles.js +++ b/bin/Release/AppX/www/js/lib/transformStyles.js @@ -100,7 +100,8 @@ define(['uiUtil'], function (uiUtil) { html = html.replace(/class\s*=\s*["']\s*thumbcaption\s*["']\s*/ig, 'style="margin: 0.5em 0 0.5em; font-size: 0.8em; line-height: 1.5; padding: 0 !important; color: #54595d; width: auto !important;"'); //If it's in desktop position, move info-box below lead paragraph like on Wikipedia mobile //html = zim == "desktop" ? /<\/p>[\s\S]*?]*(?:infobox|vertical-navbox)/i.test(html) ? html : html.replace(/(]*(?:infobox|vertical-navbox))[\s\S]+?<\/table>[^<]*)((?:\s*)?]*>(?:(?=([^<]+))\3|<(?!p\b[^>]*>))*?<\/p>(?:)?)/i, "$2\r\n$1") : html; - html = zim == "desktop" ? html.replace(/(]*(?:infobox|vertical-navbox))[\s\S]+?<\/table>[^<]*)((?:\s*)?]*>(?:(?=([^<]+))\3|<(?!p\b[^>]*>))*?<\/p>(?:)?)/i, "$2\r\n$1") : html; + //var test = html.getElementById("qbRight") + html = zim == "desktop" ? html.replace(/(]*(?:infobox|vertical-navbox|qbRight))[\s\S]+?<\/table>[^<]*)((?:\s*)?]*>(?:(?=([^<]+))\3|<(?!p\b[^>]*>))*?<\/p>(?:)?)/i, "$2\r\n$1") : html; //Set infobox styling hard-coded in Wikipedia mobile html = html.replace(/(table\s+(?=[^>]*class\s*=\s*["'][^"']*infobox)[^>]*style\s*=\s*["'][^"']+[^;'"]);?\s*["']/ig, '$1; position: relative; border: 1px solid #eaecf0; text-align: left; background-color: #f8f9fa;"'); //Wrap

tags in
to control bottom border width if there's an infobox diff --git a/bin/Release/AppX/www/js/lib/uiUtil.js b/bin/Release/AppX/www/js/lib/uiUtil.js index a7449c7f..307e3052 100644 --- a/bin/Release/AppX/www/js/lib/uiUtil.js +++ b/bin/Release/AppX/www/js/lib/uiUtil.js @@ -53,6 +53,23 @@ define([], function() { } } + /** + * Checks whether an element is fully or partially in view + * This is useful for progressive download of images inside an article + * + * @param {Object} el + * @param {Boolean} fully + */ + function isElementInView(el, fully) { + var elemTop = el.getBoundingClientRect().top; + var elemBottom = el.getBoundingClientRect().bottom; + + var isVisible = fully ? elemTop < window.innerHeight && elemBottom >= 0 : + elemTop >= 0 && elemBottom <= window.innerHeight; + return isVisible; + } + + function makeReturnLink(title) { //Abbreviate title if necessary var shortTitle = title.substring(0, 25); @@ -78,6 +95,7 @@ define([], function() { return { feedNodeWithBlob: feedNodeWithBlob, removeUrlParameters: removeUrlParameters, + isElementInView: isElementInView, makeReturnLink: makeReturnLink, poll: poll, clear: clear diff --git a/bin/Release/AppxManifest.xml b/bin/Release/AppxManifest.xml index bc3ca432..685cac1d 100644 --- a/bin/Release/AppxManifest.xml +++ b/bin/Release/AppxManifest.xml @@ -23,7 +23,7 @@ - + diff --git a/bin/Release/KiwixWebApp.build.appxrecipe b/bin/Release/KiwixWebApp.build.appxrecipe index 4e0b7900..4ae1f7d8 100644 --- a/bin/Release/KiwixWebApp.build.appxrecipe +++ b/bin/Release/KiwixWebApp.build.appxrecipe @@ -376,7 +376,7 @@ www\js\lib\zimfile.js - + resources.pri true diff --git a/bin/Release/resources.pri b/bin/Release/ReverseMap/resources.pri similarity index 56% rename from bin/Release/resources.pri rename to bin/Release/ReverseMap/resources.pri index c953922b..8f828639 100644 Binary files a/bin/Release/resources.pri and b/bin/Release/ReverseMap/resources.pri differ diff --git a/bld/Release/KiwixWebApp.jsproj.FileListAbsolute.txt b/bld/Release/KiwixWebApp.jsproj.FileListAbsolute.txt index 77952dbc..e1291aca 100644 --- a/bld/Release/KiwixWebApp.jsproj.FileListAbsolute.txt +++ b/bld/Release/KiwixWebApp.jsproj.FileListAbsolute.txt @@ -45,4 +45,4 @@ C:\Users\geoff\Source\Repos\kiwix-js-windows\bld\Release\qualifiers.txt C:\Users\geoff\Source\Repos\kiwix-js-windows\bld\Release\qualifiers.txt.intermediate C:\Users\geoff\Source\Repos\kiwix-js-windows\bld\Release\MultipleQualifiersPerDimensionFound.txt C:\Users\geoff\Source\Repos\kiwix-js-windows\bld\Release\ProjectArchitectures.txt -C:\Users\geoff\Source\Repos\kiwix-js-windows\bin\Release\resources.pri +C:\Users\geoff\Source\Repos\kiwix-js-windows\bin\Release\ReverseMap\resources.pri diff --git a/bld/Release/PackageLayout/www/js/app.js b/bld/Release/PackageLayout/www/js/app.js index 7009c970..43ded3e2 100644 --- a/bld/Release/PackageLayout/www/js/app.js +++ b/bld/Release/PackageLayout/www/js/app.js @@ -35,7 +35,14 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles */ var MAX_SEARCH_RESULT_SIZE = module.config().results; //This is set in init.js - /** +//TESTING + // Get the app's installation folder. + var appFolder = Windows.ApplicationModel.Package.current.installedLocation; + // Print the folder's path to the Visual Studio Output window. + console.log(appFolder.name, "folder path:", appFolder.path); +//END TESTING + + /** * @type ZIMArchive */ var selectedArchive = null; @@ -392,7 +399,8 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles * * @type Array. */ - var storages = []; + //var storages = []; + var storages = [appFolder.path]; //UWP function searchForArchivesInPreferencesOrStorage() { // First see if the list of archives is stored in the cookie var listOfArchivesFromCookie = cookies.getItem("listOfArchives"); @@ -422,8 +430,9 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles // Make a fake first access to device storage, in order to ask the user for confirmation if necessary. // This way, it is only done once at this moment, instead of being done several times in callbacks // After that, we can start looking for archives - storages[0].get("fake-file-to-read").then(searchForArchivesInPreferencesOrStorage, - searchForArchivesInPreferencesOrStorage); + //storages[0].get("fake-file-to-read").then(searchForArchivesInPreferencesOrStorage, + //searchForArchivesInPreferencesOrStorage); + searchForArchivesInPreferencesOrStorage; } else { // If DeviceStorage is not available, we display the file select components diff --git a/bld/Release/PackageLayout/www/js/lib/uiUtil.js b/bld/Release/PackageLayout/www/js/lib/uiUtil.js index a7449c7f..307e3052 100644 --- a/bld/Release/PackageLayout/www/js/lib/uiUtil.js +++ b/bld/Release/PackageLayout/www/js/lib/uiUtil.js @@ -53,6 +53,23 @@ define([], function() { } } + /** + * Checks whether an element is fully or partially in view + * This is useful for progressive download of images inside an article + * + * @param {Object} el + * @param {Boolean} fully + */ + function isElementInView(el, fully) { + var elemTop = el.getBoundingClientRect().top; + var elemBottom = el.getBoundingClientRect().bottom; + + var isVisible = fully ? elemTop < window.innerHeight && elemBottom >= 0 : + elemTop >= 0 && elemBottom <= window.innerHeight; + return isVisible; + } + + function makeReturnLink(title) { //Abbreviate title if necessary var shortTitle = title.substring(0, 25); @@ -78,6 +95,7 @@ define([], function() { return { feedNodeWithBlob: feedNodeWithBlob, removeUrlParameters: removeUrlParameters, + isElementInView: isElementInView, makeReturnLink: makeReturnLink, poll: poll, clear: clear diff --git a/package.appxmanifest b/package.appxmanifest index 45a49f37..05306393 100644 --- a/package.appxmanifest +++ b/package.appxmanifest @@ -16,7 +16,7 @@ - +