Updated the UI.

master
Pacman Ghost 3 years ago
parent 5f9b4e795c
commit f7da2dcad7
  1. 26
      asl_rulebook2/webapp/static/ASOP.js
  2. 4
      asl_rulebook2/webapp/static/Accordian.js
  3. 4
      asl_rulebook2/webapp/static/Collapsible.js
  4. 25
      asl_rulebook2/webapp/static/MainApp.js
  5. 26
      asl_rulebook2/webapp/static/NavPane.js
  6. 81
      asl_rulebook2/webapp/static/RuleInfo.js
  7. 29
      asl_rulebook2/webapp/static/SearchPane.js
  8. 29
      asl_rulebook2/webapp/static/SearchResult.js
  9. 54
      asl_rulebook2/webapp/static/TabbedPages.js
  10. 17
      asl_rulebook2/webapp/static/css/ASOP.css
  11. 4
      asl_rulebook2/webapp/static/css/Accordian.css
  12. 20
      asl_rulebook2/webapp/static/css/ContentPane.css
  13. 11
      asl_rulebook2/webapp/static/css/MainApp.css
  14. 4
      asl_rulebook2/webapp/static/css/NavPane.css
  15. 22
      asl_rulebook2/webapp/static/css/RuleInfo.css
  16. 30
      asl_rulebook2/webapp/static/css/SearchPane.css
  17. 17
      asl_rulebook2/webapp/static/css/SearchResult.css
  18. 7
      asl_rulebook2/webapp/static/css/TabbedPages.css
  19. 13
      asl_rulebook2/webapp/static/css/chapters.css
  20. 12
      asl_rulebook2/webapp/static/css/global.css
  21. 204
      asl_rulebook2/webapp/static/hotkey/jquery.hotkey.js
  22. BIN
      asl_rulebook2/webapp/static/images/bullet.png
  23. BIN
      asl_rulebook2/webapp/static/images/bullet2.png
  24. BIN
      asl_rulebook2/webapp/static/images/bullet3.png
  25. BIN
      asl_rulebook2/webapp/static/images/close-popup.png
  26. BIN
      asl_rulebook2/webapp/static/images/cross.png
  27. BIN
      asl_rulebook2/webapp/static/images/header-bgd-edge.png
  28. BIN
      asl_rulebook2/webapp/static/images/header-bgd.png
  29. 8
      asl_rulebook2/webapp/static/images/nav-buttons/READ-ME.txt
  30. BIN
      asl_rulebook2/webapp/static/images/nav-buttons/asop-inactive.png
  31. BIN
      asl_rulebook2/webapp/static/images/nav-buttons/asop.png
  32. BIN
      asl_rulebook2/webapp/static/images/nav-buttons/chapters-inactive.png
  33. BIN
      asl_rulebook2/webapp/static/images/nav-buttons/chapters.png
  34. BIN
      asl_rulebook2/webapp/static/images/nav-buttons/search-inactive.png
  35. BIN
      asl_rulebook2/webapp/static/images/nav-buttons/search.png
  36. BIN
      asl_rulebook2/webapp/static/images/search.png
  37. BIN
      asl_rulebook2/webapp/static/images/watermark.png
  38. 12
      asl_rulebook2/webapp/static/utils.js
  39. 2
      asl_rulebook2/webapp/templates/index.html

@ -16,19 +16,21 @@ gMainApp.component( "asop", {
} ; },
template: `
<div v-if=isActive :data-chapterid=chapterId id="asop" class="asop" >
<div class="title">
<span v-html=title />
<collapser collapserId="asop-preamble" ref="collapser" />
<div>
<div v-if=isActive id="asop-overlay" />
<div v-if=isActive :data-chapterid=chapterId id="asop" class="asop" >
<div class="title">
<span v-html=title />
<collapser collapserId="asop-preamble" ref="collapser" />
</div>
<collapsible collapsedHeight=5 ref="collapsible">
<div v-html=preamble class="preamble" />
</collapsible>
<div v-if="sections.length > 0" class="sections" :class="{single: isSingleSection}" ref="sections" >
<div v-for="s in sections" :key=s class="section" v-html=s />
</div>
</div>
<collapsible collapsedHeight=5 ref="collapsible">
<div v-html=preamble class="preamble" />
</collapsible>
<div v-if="sections.length > 0" class="sections" :class="{single: isSingleSection}" ref="sections" >
<div v-for="s in sections" :key=s class="section" v-html=s />
</div>
</div>
`,
</div>`,
created() {

@ -39,7 +39,7 @@ gMainApp.component( "accordian", {
gMainApp.component( "accordian-pane", {
props: [ "paneKey", "title", "entries", "getEntryKey", "iconUrl", "backgroundUrl" ],
props: [ "paneKey", "title", "entries", "getEntryKey", "iconUrl", "backgroundUrl", "borderClass" ],
data() { return {
isExpanded: false,
cssBackground: this.backgroundUrl ? "url(" + this.backgroundUrl + ")": null,
@ -47,7 +47,7 @@ gMainApp.component( "accordian-pane", {
template: `
<div class="accordian-pane">
<div class="title" :style="{background: cssBackground}" @click=onToggleExpand >
<div class="title" :style="{background: cssBackground}" :class=borderClass @click=onToggleExpand >
<img v-if=iconUrl :src=iconUrl class="icon" />
{{title}}
</div>

@ -1,4 +1,5 @@
import { gMainApp, gAppConfig, gEventBus } from "./MainApp.js" ;
import { makeImageUrl } from "./utils.js" ;
let gCollapsibleStates = {} ; // nb: we only save the states for the current session
@ -59,8 +60,7 @@ gMainApp.component( "collapser", {
},
getImageUrl() {
return gImagesBaseUrl //eslint-disable-line no-undef
+ "collapser-" + (this.isCollapsed ? "down" : "up") + ".png" ;
return makeImageUrl( "collapser-" + (this.isCollapsed ? "down" : "up") + ".png" ) ;
},
updateCollapsible() {

@ -53,6 +53,22 @@ gMainApp.component( "main-app", {
gutterSize: 2,
} ) ;
// initialize hotkeys
jQuery.hotkeys.options.filterInputAcceptingElements = false ;
jQuery.hotkeys.options.filterContentEditable = false ;
jQuery.hotkeys.options.filterTextInputs = false ;
function selectNav( tabId ) {
$( "#nav .tab-strip .tab[data-tabid='" + tabId + "']" ).click() ;
}
$( "body" ).bind( "keydown", "alt+r", function( evt ) {
selectNav( "search" ) ;
$( "#query-string" ).select() ;
$( "#query-string" ).focus() ;
evt.preventDefault() ;
} ) ;
$( "body" ).bind( "keydown", "alt+c", function( evt ) { selectNav( "chapters" ) ; evt.preventDefault() ; } ) ;
$( "body" ).bind( "keydown", "alt+a", function( evt ) { selectNav( "asop" ) ; evt.preventDefault() ; } ) ;
// initialze the webapp
Promise.all( [
this.getAppConfig(),
@ -62,6 +78,7 @@ gMainApp.component( "main-app", {
] ).then( () => {
this.isLoaded = true ;
gEventBus.emit( "app-loaded" ) ;
$( "#watermark" ).css( "opacity", 0.15 ) ;
this.showStartupMsgs() ;
$( "#query-string" ).focus() ; // nb: because autofocus on the <input> doesn't work :-/
} ).catch( () => {
@ -194,8 +211,12 @@ gMainApp.component( "main-app", {
// check if there are any notification balloons open
if ( $( ".growl" ).length > 0 ) {
// yup - close them all
$( ".growl-close" ).each( function() {
$(this).trigger( "click" ) ;
// FUDGE! We used to trigger a click on the close button, so that the balloons would fade out,
// but there seems to be a bug where they would just build up, hidden. Just removing them
// from the DOM is a bit abrupt visually, but it's arguable that it's more in line with what
// the user wants (i.e. get rid of them!)
$( ".growl" ).each( function() {
$(this).remove() ;
} ) ;
return ;
}

@ -1,4 +1,4 @@
import { gMainApp, gAppConfig, gContentDocs, gEventBus } from "./MainApp.js" ;
import { gMainApp, gAppConfig, gContentDocs, gEventBus, gUrlParams } from "./MainApp.js" ;
import { getJSON, getURL, linkifyAutoRuleids, getASOPChapterIdFromSectionId, showWarningMsg } from "./utils.js" ;
// --------------------------------------------------------------------
@ -13,18 +13,19 @@ gMainApp.component( "nav-pane", {
template: `
<div>
<tabbed-pages tabbedPagesId="nav" >
<tabbed-page tabId="search" caption="Search" >
<tabbed-page tabId="search" image="search" >
<nav-pane-search />
</tabbed-page>
<tabbed-page tabId="chapters" caption="Chapters" >
<tabbed-page tabId="chapters" image="chapters" >
<nav-pane-chapters />
</tabbed-page>
<tabbed-page v-if="asop.chapters && asop.chapters.length > 0"
tabId="asop" caption="ASOP" ref="asop"
tabId="asop" image="asop" ref="asop"
>
<nav-pane-asop :asop=asop />
</tabbed-page>
</tabbed-pages>
<div id="watermark" />
<rule-info :ruleInfo=ruleInfo @close=closeRuleInfo />
</div>`,
@ -67,14 +68,26 @@ gMainApp.component( "nav-pane-search", {
data() { return {
seqNo: 0, // nb: for the test suite
show: gUrlParams.get( "no-animations" ),
} ; },
template: `
<search-box id="search-box" @search=onSearch />
<search-box :style="{display: show ? 'block' : 'none'}" @search=onSearch
id="search-box" ref="searchBox"
/>
<search-results :data-seqno=seqNo id="search-results" />
`,
created() {
// NOTE: We can sometimes see the search box being built during startup (as the background images
// are loaded), so we start it off hidden, and fade it in after the webapp has initialized.
gEventBus.on( "app-loaded", () => {
if ( ! this.show ) {
$( this.$refs.searchBox.$el ).fadeIn( 500, () => {
this.show = true ;
} ) ;
}
} ) ;
// notify the test suite that the search results are now available
gEventBus.on( "search-done", () => {
this.seqNo += 1 ;
@ -107,7 +120,7 @@ gMainApp.component( "nav-pane-chapters", {
<accordian-pane v-if="chapters.length > 0" v-for="c in chapters"
:key=c :paneKey=c
:entries=c[1].sections :getEntryKey=getEntryKey
:title=c[1].title :iconUrl=c[1].icon :backgroundUrl=c[1].background
:title=c[1].title :iconUrl=c[1].icon :backgroundUrl=c[1].background :borderClass=makeBorderClass(c)
@pane-expanded=onChapterPaneExpanded
@entry-clicked=onChapterEntryClicked
/>
@ -142,6 +155,7 @@ gMainApp.component( "nav-pane-chapters", {
},
getEntryKey( entry ) { return entry.ruleid ; },
makeBorderClass( chapter ) { return chapter[1].chapter_id ? "chapter-" + chapter[1].chapter_id.toLowerCase() : null ; },
},

@ -1,5 +1,5 @@
import { gMainApp, gEventBus, gUrlParams } from "./MainApp.js" ;
import { linkifyAutoRuleids, fixupSearchHilites, makeImagesZoomable } from "./utils.js" ;
import { gMainApp, gUrlParams } from "./MainApp.js" ;
import { linkifyAutoRuleids, fixupSearchHilites, makeImagesZoomable, makeImageUrl } from "./utils.js" ;
// --------------------------------------------------------------------
@ -7,22 +7,18 @@ gMainApp.component( "rule-info", {
props: [ "ruleInfo" ],
data() { return {
closeRuleInfoImageUrl: gImagesBaseUrl + "cross.png", //eslint-disable-line no-undef
closeRuleInfoImageUrl: makeImageUrl( "close-popup.png" ),
ruleInfoTransitionName: gUrlParams.get("no-animations") ? "" : "ruleinfo-slide",
} ; },
// FUDGE! We want the "close" button to stay in the top-right corner of the rule info popup as the user
// scrolls around. If we put it in together with the content itself, with an absolute position, it scrolls
// with the content, so we place it outside the content, with an absolute position, and a larger z-index.
// It doesn't look so good when the v-scrollbar appears, but we can live with that.
// NOTE: We have 3 separate transitions to try get the animation timing to look right :-/
template: `
<div>
<img :src=closeRuleInfoImageUrl style="display:none;"
@click="$emit('close')" ref="closeRuleInfoButton"
title="Close the rule info" class="close-rule-info"
/>
<transition :name=ruleInfoTransitionName @after-enter=updateCloseButton >
<div v-show="ruleInfo.length > 0" id="rule-info" ref="ruleInfo" >
<transition :name=ruleInfoTransitionName >
<div v-show=showPopup() id="rule-info-overlay" />
</transition>
<transition :name=ruleInfoTransitionName >
<div v-show=showPopup() id="rule-info" ref="ruleInfo" >
<div class="content" ref="content">
<div v-for="ri in ruleInfo" :key=ri >
<annotation v-if="ri.ri_type == 'errata'" :anno=ri />
@ -33,33 +29,18 @@ gMainApp.component( "rule-info", {
</div>
</div>
</transition>
<transition :name=ruleInfoTransitionName >
<img v-if=showPopup() :src=closeRuleInfoImageUrl
@click="$emit('close')" ref="closeRuleInfoButton"
class="close-rule-info"
/>
</transition>
</div>`,
created() {
// NOTE: Toggling collapsible's can cause the v-scrollbar to appear/hide.
gEventBus.on( "collapsible-toggled", () => {
if ( this.ruleInfo.length > 0 )
this.updateCloseButton() ;
} ) ;
},
beforeUpdate() {
// hide the close button until the "enter" transition has completed
let $closeButton = $( this.$refs.closeRuleInfoButton ) ;
if ( this.ruleInfo.length == 0 )
$closeButton.hide() ;
else {
if ( $closeButton.css( "display" ) == "none" )
$closeButton.hide() ;
else {
// NOTE: If we're already visible, we don't get the transition, so we force
// post-transition processing manually.
this.$nextTick( () => {
this.updateCloseButton() ;
this.$refs.ruleInfo.scrollTop = 0 ;
} ) ;
}
}
this.$nextTick( () => {
this.$refs.ruleInfo.scrollTop = 0 ;
} ) ;
},
updated() {
@ -69,21 +50,9 @@ gMainApp.component( "rule-info", {
methods: {
updateCloseButton() {
// FUDGE! We have to wait until the rule info popup is open before we can check
// if it has a v-scrollbar or not, and hence where we should put the close button.
this.$nextTick( () => {
let ruleInfo = this.$refs.ruleInfo ;
let closeButton = this.$refs.closeRuleInfoButton ;
if ( ruleInfo.clientHeight >= ruleInfo.scrollHeight )
$(closeButton).css( "right", "6px" ) ;
else {
// FUDGE! The v-scrollbar is visible, so we move the "close" button left a bit.
// This adjustment won't update if the pane is resized, but we can live with that.
$(closeButton).css( "right", "18px" ) ;
}
$(closeButton).fadeIn( 200 ) ;
} ) ;
showPopup() {
// figure out if the popup should be shown
return this.ruleInfo.length > 0 ;
},
},
@ -96,9 +65,9 @@ gMainApp.component( "qa-entry", {
props: [ "qaEntry" ],
data() { return {
questionImageUrl: gImagesBaseUrl + "question.png", //eslint-disable-line no-undef
infoImageUrl: gImagesBaseUrl + "info.png", //eslint-disable-line no-undef
answerImageUrl: gImagesBaseUrl + "answer.png", //eslint-disable-line no-undef
questionImageUrl: makeImageUrl( "question.png" ),
infoImageUrl: makeImageUrl( "info.png" ),
answerImageUrl: makeImageUrl( "answer.png" ),
} ; },
template: `
@ -189,7 +158,7 @@ gMainApp.component( "annotation", {
methods: {
makeIconImageUrl() {
if ( this.annoType )
return gImagesBaseUrl + this.annoType+".png" ; //eslint-disable-line no-undef
return makeImageUrl( this.annoType + ".png" ) ;
else
return null ;
},

@ -21,18 +21,21 @@ gMainApp.component( "search-box", {
template: `
<div>
<div class="row">
<input type="text" id="query-string" @keyup=onKeyUp v-model.trim="queryString" ref="queryString" autofocus >
<button @click="$emit('search',this.queryString)" ref="submit"> Go </button>
</div>
<div class="row sr-filters" style="display:none;" ref="srFilters" >
<b> Show: </b>
<input type="checkbox" name="show-index-sr" @click=onClickSrFilter > <label for="show-index-sr"> Index </label>
<input type="checkbox" name="show-qa-sr" @click=onClickSrFilter > <label for="show-qa-sr"> Q+A </label>
<input type="checkbox" name="show-errata-sr" @click=onClickSrFilter > <label for="show-errata-sr"> Errata </label>
<input type="checkbox" name="show-asop-entry-sr" @click=onClickSrFilter > <label for="show-asop-entry-sr"> ASOP </label>
<span v-if=showSrCount :title=srCountInfo class="sr-count"> {{srCount}} </span>
<div class="content">
<div class="row">
<span class="label"> Sea<u>r</u>ch: </span>
<input type="text" id="query-string" @keyup=onKeyUp v-model.trim="queryString" ref="queryString" autofocus >
<button @click="$emit('search',this.queryString)" class="submit" ref="submit" />
</div>
<div class="row sr-filters" style="display:none;" ref="srFilters" >
<span class="label"> Show: </span>
<input type="checkbox" name="show-index-sr" @click=onClickSrFilter > <label for="show-index-sr"> Index </label>
<input type="checkbox" name="show-qa-sr" @click=onClickSrFilter > <label for="show-qa-sr"> Q+A </label>
<input type="checkbox" name="show-errata-sr" @click=onClickSrFilter > <label for="show-errata-sr"> Errata </label>
<input type="checkbox" name="show-asop-entry-sr" @click=onClickSrFilter > <label for="show-asop-entry-sr"> ASOP </label>
</div>
</div>
<div v-if=showSrCount :title=srCountInfo class="sr-count"> {{srCount}} </div>
</div>`,
created() {
@ -61,6 +64,7 @@ gMainApp.component( "search-box", {
if ( nVisible <= 1 ) {
// there's only 1 checkbox - turn it on and leave everything hidden
$( this.$el ).find( "input[type='checkbox']" ).prop( "checked", true ) ;
$( this.$el ).find( ".content" ).css( { "margin-top": "6px", right: "15px" } ) ;
} else {
// there are multiple checkboxes - show them to the user
$( this.$refs.srFilters ).show() ;
@ -147,7 +151,8 @@ gMainApp.component( "search-box", {
if ( $(this).css( "display" ) != "none" )
nVisible += 1 ;
} ) ;
if ( nVisible == 0 && nTotal == 0 ) {
let $srFilters = $( this.$refs.srFilters ) ;
if ( (nVisible == 0 && nTotal == 0) || $srFilters.css("display") == "none" ) {
this.srCount = null ;
this.srCountInfo = null ;
} else {

@ -8,18 +8,26 @@ gMainApp.component( "index-sr", {
props: [ "sr" ],
data() { return {
expandRulerefs: null,
primaryTarget: getPrimaryTarget( this.sr ),
iconUrl: getChapterResource( "icon", this.getChapterId() ),
cssBackground: this.makeCssBackground(),
borderCol: this.makeBorderColor(),
} ; },
template: `
<div class="index-sr" >
<div v-if="sr.title || sr.subtitle" :style="{background: cssBackground}" class="title" >
<div v-if="sr.title || sr.subtitle" :style="{background: cssBackground}"
:class=makeBorderColor() class="caption"
>
<collapser @click=onToggleRulerefs ref="collapser" />
<a v-if=iconUrl href="#" @click=onClickIcon >
<img :src=iconUrl class="icon" />
</a>
<span v-if=sr.title class="title" v-html=sr.title />
<img v-if=iconUrl :src=iconUrl :style="{cursor: this.primaryTarget ? 'pointer' : null}"
@click=onClickIcon
class="icon"
/>
<span v-if=sr.title v-html=sr.title :style="{cursor: this.primaryTarget ? 'pointer' : null}"
@click=onClickIcon
class="title"
/>
<span v-if=sr.subtitle class="subtitle" v-html=sr.subtitle />
</div>
<div class="body">
@ -92,9 +100,8 @@ gMainApp.component( "index-sr", {
onClickIcon() {
// open the search result's primary target
let target = getPrimaryTarget( this.sr ) ;
if ( target )
gEventBus.emit( "show-target", target.cdoc_id, target.ruleid ) ;
if ( this.primaryTarget )
gEventBus.emit( "show-target", this.primaryTarget.cdoc_id, this.primaryTarget.ruleid ) ;
},
onToggleRulerefs() {
@ -121,6 +128,12 @@ gMainApp.component( "index-sr", {
return url ? "url(" + url + ")" : "#ddd" ;
},
makeBorderColor() {
// generate the caption border color
let chapterId = this.getChapterId() ;
return chapterId ? "chapter-" + chapterId.toLowerCase() : null ;
},
getChapterId() {
// figure out which chapter this search result belongs to
// NOTE: This is actually a bit fiddly :-/ An index entry can have multiple main ruleid's associated

@ -1,4 +1,5 @@
import { gMainApp, gEventBus } from "./MainApp.js" ;
import { makeImageUrl } from "./utils.js" ;
// --------------------------------------------------------------------
@ -13,13 +14,17 @@ gMainApp.component( "tabbed-pages", {
template: `
<div class="tabbed-pages" :id="'tabbed-pages-'+tabbedPagesId" >
<slot />
<div class="tab-strip">
<div class="tab-strip" ref="tabStrip" >
<div v-for="tab in tabs"
:key=tab :data-tabid=tab.tabId
:class="{'active': tab.tabId == activeTabId}" class="tab"
@click=onTabClicked
>
{{tab.caption}}
<img v-if=tab.image :src=makeNavButtonImageUrl(tab)
@mousedown=onTabImageMouseDown(tab)
/>
<span v-else-if=tab.caption> {{tab.caption}} </span>
<span v-else> ??? </span>
</div>
</div>
</div>`,
@ -35,27 +40,58 @@ gMainApp.component( "tabbed-pages", {
},
mounted() {
// flag if the tab strip is using images
if ( this.tabs.filter( (tabbedPage) => tabbedPage.image ).length > 0 )
$( this.$refs.tabStrip ).addClass( "images" ) ;
// start with the first tab activated
if ( this.tabs.length > 0 )
this.activateTab( this.tabs[0].tabId ) ;
if ( this.tabs.length > 0 ) {
this.$nextTick( () => {
this.activateTab( this.tabs[0].tabId ) ;
} ) ;
}
},
methods: {
onTabClicked( evt ) {
// activate the selected tab
this.activateTab( evt.target.dataset.tabid ) ;
let tabId = evt.target.dataset.tabid ;
if ( ! tabId )
tabId = evt.target.parentNode.dataset.tabid ; // if we're using images :-/
this.activateTab( tabId ) ;
},
activateTab( tabId ) {
// activate the specified tab
this.activeTabId = tabId ;
$( this.$el ).find( ".tabbed-page" ).each( function() {
$(this).css( "display", ($(this).data("tabid") == tabId) ? "block" : "none" ) ;
$(this).css( "display", ($(this).data("tabid") == tabId) ? "flex" : "none" ) ;
} ) ;
// update the tab strip
if ( $( this.$refs.tabStrip ).hasClass( "images" ) ) {
this.tabs.forEach( (tabbedPage) => {
let $img = $( this.$refs.tabStrip ).find( ".tab[data-tabid='" + tabbedPage.tabId + "'] img" ) ;
let imageUrl = this.makeNavButtonImageUrl( tabbedPage, tabbedPage.tabId == tabId ) ;
$img.attr( "src", imageUrl ) ;
} ) ;
}
// notify everyone about the change
gEventBus.emit( "tab-activated", this, tabId ) ;
},
onTabImageMouseDown( tabbedPage ) {
let $img = $( this.$refs.tabStrip ).find( ".tab[data-tabid='" + tabbedPage.tabId + "'] img" ) ;
$img.attr( "src", this.makeNavButtonImageUrl( tabbedPage, true ) ) ;
},
makeNavButtonImageUrl( tabbedPage, isActive ) {
// generate the URL for the nav button image
if ( ! tabbedPage.image )
return null ;
let fname = tabbedPage.image + (isActive ? "" : "-inactive") + ".png" ;
return makeImageUrl( "/nav-buttons/" + fname ) ;
},
},
} ) ;
@ -64,7 +100,7 @@ gMainApp.component( "tabbed-pages", {
gMainApp.component( "tabbed-page", {
props: [ "tabId", "caption", "isActive" ],
props: [ "tabId", "caption", "image", "isActive" ],
template: `
<div :data-tabid=tabId v-show=isActive class="tabbed-page" >
@ -73,9 +109,7 @@ gMainApp.component( "tabbed-page", {
created() {
// add ourself to the parent's list of child tabs
this.$parent.tabs.push( {
tabId: this.tabId, caption: this.caption
} ) ;
this.$parent.tabs.push( this ) ;
},
} ) ;

@ -7,18 +7,21 @@
* */
#asop {
position: absolute ; top: 5px ; left: 5px ; bottom: 5px ; right: 5px ; z-index: 20 ;
position: absolute ; top: 2px ; left: 2px ; bottom: 2px ; right: 2px ; z-index: 20 ;
display: flex ; flex-direction: column ;
border: 1px solid #444 ; border-radius: 5px ; background: white ;
border: 1px solid #888 ; border-radius: 5px ; background: white ;
padding: 10px ;
}
#asop-overlay {
position: absolute ; top: 0 ; left: 0 ; bottom: 0 ; right: 0 ; z-index: 15 ; background: white ;
}
#nav .tabbed-page[data-tabid="asop"] .wrapper { display: flex ; flex-direction: column ; }
#nav .tabbed-page[data-tabid="asop"] .wrapper { height: 100% ; display: flex ; flex-direction: column ; overflow-y: auto ; }
#nav .tabbed-page[data-tabid="asop"] .accordian { flex-grow: 1 ; overflow-y: auto ; }
#nav .tabbed-page[data-tabid="asop"] .accordian-pane .title { background: #f6edda ; border: 1px solid #e5cea0 ; font-size: 110% ; }
#nav .tabbed-page[data-tabid="asop"] .accordian-pane[data-chapterid="pre-game"] .title { background: #fff6e2 ; }
#nav .tabbed-page[data-tabid="asop"] .accordian .entry { margin: 6px 0 ; }
#asop-footer { border-top: 1px solid #ccc ; margin-top: 5px ; padding: 5px ; }
#asop-footer { border-top: 1px solid #ccc ; margin-top: 5px ; padding: 5px 5px 0 5px ; }
#asop>.title { background: #f6edda ; border: 1px solid #e5cea0 }
#asop[data-chapterid="pre-game"]>.title { background: #fff6e2 ; }
@ -33,8 +36,8 @@
.asop .collapsible { overflow-y: visible ; }
.asop .preamble i, #asop .preamble em { font-style: normal ; }
.asop .sections { flex-grow: 1 ; overflow-y: auto ; }
.asop .section { margin-top: 10px ; border: 1px solid #444 ; border-radius: 5px; padding: 10px ; }
.asop .sections { flex-grow: 1 ; overflow-y: auto ; padding: 0 5px ; }
.asop .section { margin-top: 10px ; border: 1px solid #ccc ; border-radius: 5px; padding: 10px ; }
.asop .section:first-of-type { margin-top: 0 ; }
.asop .sections.single .section { border: none ; padding: 0 5px ; }
.asop .sections.single .section { border: none ; padding: 0 ; }
.asop .section .caption { font-weight: bold ; }

@ -1,5 +1,4 @@
.accordian { padding: 0 5px 0 0 ; }
.accordian { padding: 5px 5px 0 5px ; }
.accordian-pane { margin: 5px ; }
.accordian-pane .title {
@ -11,6 +10,7 @@
.accordian-pane .title .icon { height: 20px ; margin-right: 10px ; }
.accordian-pane .entries { margin: 0 0 5px 15px ; list-style-type: none ; }
.accordian-pane .entries li { list-style-image: none ; }
.accordian-pane .entries .entry { margin: 2px 0 ; }
.accordian-pane .entries .entry a { cursor: pointer ; }
.accordian-pane .entries .entry.disabled { color: #666 ; }

@ -1,21 +1,23 @@
#content { position: relative ; }
#content .tabbed-page { border-bottom: 1px solid #aaa ; }
#content .tab-strip { padding: 0 0.5em ; }
#content .tab-strip .tab { margin-top: -1px ; z-index: 5 ; border-radius: 0 0 5px 5px ; }
#content .tabbed-page { border-bottom: 1px solid #aaa ; background: white ; }
#content .tabbed-page .wrapper { flex-grow: 1 ; }
#content .tab-strip { height: 20px ; padding: 0 5px 2px 5px ; font-size: 12px ; }
#content .tab-strip .tab { height: 14px ; margin-top: -1px ; padding: 2px 6px ; z-index: 5 ; border-radius: 0 0 5px 5px ; }
#content .tab-strip .tab { background: #f0f0f0 ; color: #808080 ; }
#content .tab-strip .tab.active { background: white ; color: #444 ; border-top: none ; }
#content .content-doc iframe { position: absolute ; width: 100% ; height: calc(100% - 40px) ; border: none ; }
#content .content-doc { height: 100% ; }
#content .content-doc iframe { width: 100% ; height: 100% ; border: none ; }
#content .content-doc .disabled { margin-top: 1em ; text-align: center ; font-style: italic ; color: #888 ; }
#growls-br { max-height: 40% ;}
.growl-footnote { background: #f0f0d0 ; border: 1px solid #ccc ; color: black ; width: 120px ; }
.growl-footnote { background: #f0f0d0 ; border: 1px solid #ccc ; width: 120px ; }
/* FUDGE! We would like to set the opacity to 1 on :hover, but it breaks the click handler!?!? :wtf: */
.growl-footnote { opacity: 1 ; }
.growl-footnote .footnote { margin-top: 10px ; height: 100% ; display: flex ; flex-direction: column ; }
.growl-footnote .footnote { margin-top: 10px ; display: flex ; flex-direction: column ; }
.growl-footnote .footnote:first-of-type { margin-top: 0 ; }
.growl-footnote .header { font-weight: bold ; }
.growl-footnote .header .footnote-id { font-size: 90% ; font-style: italic ; color: #666 ; }
.growl-footnote .growl-message { height: 100% ; display: flex ; flex-direction: column ; }
.growl-footnote .growl-message .content { flex-grow: 1 ; overflow-y: auto ; padding: 0 5px 5px 5px ; text-align: justify ; }
.growl-footnote .growl-message { height: 100% ; overflow-y: auto ; display: flex ; flex-direction: column ; }
.growl-footnote .growl-message .content { flex-grow: 1 ; padding: 0 5px 0 5px ; text-align: justify ; }
.growl-footnote .growl-message p { margin-top: 4px ; }

@ -1,6 +1,15 @@
#main-app { width: 100% ; height: 100% ; display: flex ; }
/* splitter */
#nav { min-width: 350px ; }
#nav { min-width: 410px ; }
#content { flex-grow: 1 ; min-width: 500px ; }
#main-app .gutter.gutter-horizontal { cursor: ew-resize ; background: #ccc ; }
#watermark {
position: absolute ; right: -25px ; bottom: 2px;
width: 200px ; height: 200px ;
background: url(../images/watermark.png) left bottom no-repeat ; background-size: 100% ;
transform: scaleX(-1) ;
opacity: 0 ; z-index: -99 ;
transition: opacity 10s ;
}

@ -1,4 +1,4 @@
#nav { margin: 0 5px ; position: relative ; }
#nav { position: relative ; }
#nav .no-chapters { font-style: italic ; color: #888 ; }
#nav .tab-strip { border-top: 1px solid #aaa ; padding: 5px 5px ; }
#nav .tabbed-page[data-tabid="chapters"] .wrapper { overflow-y: auto ; }

@ -1,12 +1,17 @@
#rule-info {
position: absolute ; top: 0 ; left: 0 ; bottom: 0 ; right: 0 ;
position: absolute ; top: 5px ; left: 5px ; bottom: 5px ; right: 5px ;
overflow-y: auto ;
z-index: 10 ;
border: 1px solid #444 ; border-radius: 5px ; background: white ;
}
#rule-info-overlay {
position: absolute ; top: 0 ; left: 0 ; bottom: 0 ; right: 0 ;
background: white ;
z-index: 5 ;
}
#nav img.close-rule-info {
position: absolute ; top: 6px ; z-index: 15 ;
height: 15px ; cursor: pointer ;
position: absolute ; top: 1px ; right: 1px ; z-index: 15 ;
height: 18px ; cursor: pointer ;
}
/* This transition was originally a slide, but it proved to be quite distracting, since the user will be looking at
@ -20,14 +25,16 @@
/* NOTE: Rule info entries can appear in the rule info popup *and* search results, so the following rules need to be global. */
.rule-info { padding: 5px ; }
.rule-info p { margin-top: 5px ; }
.rule-info br { margin-top: 3px ; }
.rule-info .quote { font-style: italic ; color: #406040 ; }
.rule-info .caption .auto-ruleid { color: inherit ; }
.rule-info .caption .auto-ruleid:hover { background: inherit ; }
.qa { margin: 2px ; background: white ; padding: 5px ; }
.qa img.icon { float: left ; margin: 0 6px 0 0 ; height: 18px ; }
.qa .content { clear: left ; margin-top: 5px ; }
.qa .caption { margin-bottom: 2px ; background: #60b0ff ; border-radius: 3px ; padding: 2px 5px ; font-weight: bold ; color: #002850 ; }
.qa .caption { margin-bottom: 2px ; background: #60b0ff ; border: 1px solid #50a0f0 ; border-radius: 3px ; padding: 2px 5px ; font-weight: bold ; color: #002850 ; }
.qa .collapser { height: 16px ; float: right ; margin: 1px 2px 1px 0 ; }
.qa .question { margin-bottom: 5px ; color: #002850 ; }
.qa .question img { float: right ; margin: 0 0 5px 5px ; height: 100px ; }
@ -39,10 +46,9 @@
.qa .info .note a { color: #666 ; }
.qa .see-other { font-size: 80% ; font-style: italic ; color: #0c6905 ; }
.anno { margin: 2px ; background: white ; padding: 5px ; color: #002850 ; }
.anno img.icon { float: left ; margin: 0 6px 0 0 ; height: 18px ; }
.anno .caption { margin-bottom: 2px ; border-radius: 3px ; padding: 2px 5px ; font-weight: bold ; }
.anno .caption.errata { background: #ffc020 ; }
.anno .caption.user-anno { background: #20ff20 ; }
.anno .caption.errata { background: #ffc020 ; border: 1px solid #f0b010 ; }
.anno .caption.user-anno { background: #20ff20 ; border: 1px solid #10f010 ; }
.anno .collapser { height: 16px ; float: right ; margin: 1px 2px 1px 0 ; }
.anno .content { clear: left ; margin-top: 5px ; }

@ -1,17 +1,33 @@
#nav .tabbed-page[data-tabid='search'] .wrapper {
display: flex ; flex-direction: column ;
overflow-y: none ;
overflow-y: hidden ;
}
#nav .tab-strip { margin-top: 5px ; padding: 2px 5px 5px 5px ; }
#nav .tab-strip .tab img { border: 1px solid transparent ; }
#nav .tab-strip .tab img:active { border: 1px solid #888 ; border-radius: 5px ; }
/* search box */
#search-box { display: flex ; flex-direction: column ; padding: 1px ; margin-bottom: 8px ; }
#search-box {
height: 71px ; flex-shrink: 0 ; position: relative ;
background-image: url(../images/header-bgd.png), url(../images/header-bgd-edge.png) ;
background-repeat: no-repeat, repeat-x;
padding: 1px ;
}
#search-box .content {
position: absolute ; top: 10px ; left: 90px ; right: 5px ;
display: flex ; flex-direction: column ;
font-size: 90% ;
}
#search-box .row { display: flex ; }
#search-box input#query-string { margin-right: 5px ; flex-grow: 1 ; }
#search-box span.label { display: inline-block ; width: 70px ; margin-right: 3px ; font-weight: bold ; text-align: right ; }
#search-box input#query-string { margin-right: 5px ; flex-grow: 1 ; height: 16px ; }
#search-box button.submit { width: 18px ; height: 18px ; background: #fff no-repeat center/80% url(../images/search.png) ; }
#search-box .sr-filters { margin-top: 4px ; font-size: 80% ; }
#search-box .sr-filters input[type="checkbox"] { margin: 0 2px 0 6px ; }
#search-box .sr-count { flex-grow: 1 ; text-align: right ; font-style: italic ; color: #888 ; }
#search-box .sr-filters input[type="checkbox"] { margin-right: 2px ; }
#search-box .sr-filters label { margin-right: 6px ; }
#search-box .sr-count { position: absolute ; bottom: 18px ; right: 2px ; font-size: 60% ; font-style: italic ; color: #444 ; }
/* search results */
#search-results { height: 100% ; overflow-y: auto ; }
#search-results .no-results { font-style: italic ; color: #666 ; }
#search-results { flex-grow: 1 ; overflow-y: auto ; }
#search-results .no-results { padding: 10px ; font-style: italic ; color: #666 ; }
#search-results .error .pre { font-family: monospace ; margin: 0.25em 0 0 0.5em ; }

@ -1,18 +1,21 @@
#search-results .sr { margin-bottom: 8px ; padding-right: 5px; }
#search-results .sr { padding: 5px ; }
#search-results .index-sr .title { padding: 3px 6px ; font-weight: bold ; border-radius: 3px ; }
#search-results .index-sr .title img.icon { height: 15px ; float: left ; margin-top: 2px ; }
#search-results .index-sr .collapser { height: 16px ; float: right ; margin: 1px 2px 1px 0 ; }
#search-results .index-sr .subtitle { padding: 2px 5px ; font-weight: normal ; font-size: 80% ; font-style: italic ; }
#search-results .index-sr>.caption { padding: 3px 6px ; border-radius: 3px ; }
#search-results .index-sr>.caption img.icon { height: 14px ; float: left ; margin: 2px 4px 0 0 ; }
#search-results .index-sr>.caption .title { font-weight: bold ; }
#search-results .index-sr>.caption .subtitle { padding-left: 6px ; font-size: 80% ; font-style: italic ; }
#search-results .index-sr>.caption .collapser { height: 16px ; float: right ; margin: 1px 2px 1px 5px ; }
#search-results .index-sr .body { padding: 2px 5px 0 5px ; }
#search-results .index-sr .content { color: #444 ; }
#search-results .index-sr .see-also { color: #444 ; font-style: italic ; cursor: pointer ; }
#search-results .index-sr .see-also { font-style: italic ; cursor: pointer ; }
#search-results .index-sr img.toggle-rulerefs { float: right ; margin: 0 0 0.25em 0.25em ; height: 1.25em ; cursor: pointer ; }
#search-results .index-sr ul.rulerefs .caption { padding-right: 0.5em ; }
#search-results .index-sr ul.rulerefs .ruleid { font-size: 80% ; }
#search-results .index-sr ul.rulerefs .ruleid:hover { background: #ffffcc ; }
#search-results .index-sr ul.rulerefs .ruleid.unknown:hover { background: inherit ; }
#search-results .index-sr .ruleid { margin-right: 0.25em ; font-style: italic ; color: #888 ; }
#search-results .index-sr .ruleid.unknown { color: #888 ; }
#search-results .index-sr .ruleid a { color: red ; cursor: pointer ; }
#search-results .index-sr .ruleid a:hover { background: #ffffcc ; }
/* nb: the real ASOP background color is #b72754, but it's quite dark */
#search-results .asop-entry-sr .caption { padding: 3px 6px ; font-weight: bold ; border-radius: 3px ; background: #f6edda ; }

@ -1,5 +1,6 @@
.tabbed-pages { display: flex ; flex-direction: column ; height: 100% ; }
.tabbed-pages .tabbed-page { height: calc(100% - 35px) ; display: flex ; flex-direction: column ; }
.tabbed-pages .tabbed-page .wrapper { flex-grow: 1 ; margin: 5px 0 2px 0 ; height: calc(100% - 10px) ; overflow-y: auto ; }
.tabbed-pages .tabbed-page { flex-grow: 1 ; overflow-y: hidden ; display: flex ; flex-direction: column ; }
.tabbed-pages .tab-strip { height: 24px ; display: flex ; font-size: 10pt ; font-style: italic ; }
.tabbed-pages .tab-strip .tab { border: 1px solid #aaa ; padding: 2px 5px ; margin-right: 5px ; }
.tabbed-pages .tab-strip .tab { border: 1px solid #aaa ; padding: 2px 5px ; margin-right: 5px ; cursor: pointer ; }
.tabbed-pages .tab-strip.images .tab { border: none ; padding: 0 ; }
.tabbed-pages .tab-strip.images .tab img { height: 22px ; }

@ -0,0 +1,13 @@
.chapter-a { border: 1px solid #ecc2b0 !important ; }
.chapter-b { border: 1px solid #3ca838 !important ; }
.chapter-c { border: 1px solid #05b0e2 !important ; }
.chapter-d { border: 1px solid #949b9e !important ; }
.chapter-e { border: 1px solid #9ad0e9 !important ; }
.chapter-f { border: 1px solid #b4965f !important ; }
.chapter-g { border: 1px solid #c6cf21 !important ; }
.chapter-j { border: 1px solid #6e7723 !important ; }
.chapter-w { border: 1px solid #ad965d !important ; }
.chapter-o { border: 1px solid #e20000 !important ; }
.chapter-p { border: 1px solid #696a65 !important ; }
.chapter-t { border: 1px solid #eea63b !important ; }

@ -4,17 +4,23 @@ html { height: 100% ; }
body { height: 100% ; overflow: hidden ; }
/* general styling */
body { font-family: Arial, Helvetica, sans-serif ; font-size: 16px ; }
body { font-family: Arial, Helvetica, sans-serif ; font-size: 16px ; color: #002850 ; }
input[type="text"] { height: 22px ; padding: 0 5px ; }
button { height: 24px ; padding: 0 5px !important ; }
ul, ol { margin-left: 15px ; }
ul { margin-left: 15px ; }
ol { margin-left: 20px ; }
ul { list-style-image: url(../images/bullet.png) ; }
ul ul { list-style-image: url(../images/bullet2.png) ; }
ul ul ul { list-style-image: url(../images/bullet3.png) ; }
/* content */
.hilite { padding: 0 2px ; background: #ffa ; }
.exc { font-style: italic ; color: #666 ; }
.auto-ruleid { color: red ; cursor: pointer ; }
.auto-ruleid { color: red ; }
.auto-ruleid:hover { background: #ffffcc ; }
/* notification balloons */
#growls-br { bottom: 22px ; right: 0 ; max-height: 40% ; }
.growl { cursor: pointer ; }
.growl .growl-close { position: absolute ; top: 0 ; right: 6px ; }
.growl .growl-title { display: none ; }

@ -0,0 +1,204 @@
/*jslint browser: true*/
/*jslint jquery: true*/
/*
* jQuery Hotkeys Plugin
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Based upon the plugin by Tzury Bar Yochay:
* https://github.com/tzuryby/jquery.hotkeys
*
* Original idea by:
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
*/
/*
* One small change is: now keys are passed by object { keys: '...' }
* Might be useful, when you want to pass some other data to your handler
*/
(function(jQuery) {
jQuery.hotkeys = {
version: "0.2.0",
specialKeys: {
8: "backspace",
9: "tab",
10: "return",
13: "return",
16: "shift",
17: "ctrl",
18: "alt",
19: "pause",
20: "capslock",
27: "esc",
32: "space",
33: "pageup",
34: "pagedown",
35: "end",
36: "home",
37: "left",
38: "up",
39: "right",
40: "down",
45: "insert",
46: "del",
59: ";",
61: "=",
96: "0",
97: "1",
98: "2",
99: "3",
100: "4",
101: "5",
102: "6",
103: "7",
104: "8",
105: "9",
106: "*",
107: "+",
109: "-",
110: ".",
111: "/",
112: "f1",
113: "f2",
114: "f3",
115: "f4",
116: "f5",
117: "f6",
118: "f7",
119: "f8",
120: "f9",
121: "f10",
122: "f11",
123: "f12",
144: "numlock",
145: "scroll",
173: "-",
186: ";",
187: "=",
188: ",",
189: "-",
190: ".",
191: "/",
192: "`",
219: "[",
220: "\\",
221: "]",
222: "'"
},
shiftNums: {
"`": "~",
"1": "!",
"2": "@",
"3": "#",
"4": "$",
"5": "%",
"6": "^",
"7": "&",
"8": "*",
"9": "(",
"0": ")",
"-": "_",
"=": "+",
";": ": ",
"'": "\"",
",": "<",
".": ">",
"/": "?",
"\\": "|"
},
// excludes: button, checkbox, file, hidden, image, password, radio, reset, search, submit, url
textAcceptingInputTypes: [
"text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime",
"datetime-local", "search", "color", "tel"],
// default input types not to bind to unless bound directly
textInputTypes: /textarea|input|select/i,
options: {
filterInputAcceptingElements: true,
filterTextInputs: true,
filterContentEditable: true
}
};
function keyHandler(handleObj) {
if (typeof handleObj.data === "string") {
handleObj.data = {
keys: handleObj.data
};
}
// Only care when a possible input has been specified
if (!handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string") {
return;
}
var origHandler = handleObj.handler,
keys = handleObj.data.keys.toLowerCase().split(" ");
handleObj.handler = function(event) {
// Don't fire in text-accepting inputs that we didn't directly bind to
if (this !== event.target &&
(jQuery.hotkeys.options.filterInputAcceptingElements &&
jQuery.hotkeys.textInputTypes.test(event.target.nodeName) ||
(jQuery.hotkeys.options.filterContentEditable && jQuery(event.target).attr('contenteditable')) ||
(jQuery.hotkeys.options.filterTextInputs &&
jQuery.inArray(event.target.type, jQuery.hotkeys.textAcceptingInputTypes) > -1))) {
return;
}
var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which],
character = String.fromCharCode(event.which).toLowerCase(),
modif = "",
possible = {};
jQuery.each(["alt", "ctrl", "shift"], function(index, specialKey) {
if (event[specialKey + 'Key'] && special !== specialKey) {
modif += specialKey + '+';
}
});
// metaKey is triggered off ctrlKey erronously
if (event.metaKey && !event.ctrlKey && special !== "meta") {
modif += "meta+";
}
if (event.metaKey && special !== "meta" && modif.indexOf("alt+ctrl+shift+") > -1) {
modif = modif.replace("alt+ctrl+shift+", "hyper+");
}
if (special) {
possible[modif + special] = true;
}
else {
possible[modif + character] = true;
possible[modif + jQuery.hotkeys.shiftNums[character]] = true;
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
if (modif === "shift+") {
possible[jQuery.hotkeys.shiftNums[character]] = true;
}
}
for (var i = 0, l = keys.length; i < l; i++) {
if (possible[keys[i]]) {
return origHandler.apply(this, arguments);
}
}
};
}
jQuery.each(["keydown", "keyup", "keypress"], function() {
jQuery.event.special[this] = {
add: keyHandler
};
});
})(jQuery || this.jQuery || window.jQuery);

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

@ -0,0 +1,8 @@
http://dabuttonfactory.com
Calibri ; bold ; size=24 ; padding=16/4
rounded rectangle ; radius=5
bgd=simple gradient ; 4f88e6/2566d2
border=1 ; 1d4edf
inactive: unicolored ; #75a0e7

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 KiB

@ -106,6 +106,7 @@ export function linkifyAutoRuleids( $root )
$(this).on( "click", function() {
gEventBus.emit( "show-target", target.cdoc_id, target.ruleid ) ;
} ) ;
$(this).css( "cursor", "pointer" ) ;
} ) ;
}
@ -178,6 +179,17 @@ export function makeImagesZoomable( $elem )
$elem.find( "img.imageZoom" ).imageZoom( $ ) ;
}
export function makeImageUrl( fname )
{
// generate an image URL
let baseUrl = gImagesBaseUrl ; //eslint-disable-line no-undef
if ( baseUrl[ baseUrl.length-1 ] != "/" )
baseUrl += "/" ;
if ( fname[0] == "/" )
fname = fname.substring( 1 ) ;
return baseUrl + fname ;
}
// --------------------------------------------------------------------
export function getJSON( url )

@ -21,6 +21,7 @@
<link rel="stylesheet" type="text/css" href="{{ url_for( 'static', filename='css/TabbedPages.css' ) }}" />
<link rel="stylesheet" type="text/css" href="{{ url_for( 'static', filename='css/Accordian.css' ) }}" />
<link rel="stylesheet" type="text/css" href="{{ url_for( 'static', filename='css/Collapsible.css' ) }}" />
<link rel="stylesheet" type="text/css" href="{{ url_for( 'static', filename='css/chapters.css' ) }}" />
{%if ASOP_CSS_URL%}
<link rel="stylesheet" type="text/css" href="{{ASOP_CSS_URL}}" />
{%endif%}
@ -52,6 +53,7 @@
<script src="{{ url_for( 'static', filename='js-cookie/js.cookie.js' ) }}"></script>
<script src="{{ url_for( 'static', filename='growl/jquery.growl.js' ) }}"></script>
<script src="{{ url_for( 'static', filename='imageZoom/jquery.imageZoom.min.js' ) }}"></script>
<script src="{{ url_for( 'static', filename='hotkey/jquery.hotkey.js' ) }}"></script>
<script>
gImagesBaseUrl = "{{ url_for( 'static', filename='images/' ) }}" ;

Loading…
Cancel
Save