mirror of
https://github.com/Oreolek/gamebookformat.git
synced 2024-07-01 06:05:11 +03:00
Split out html gamebook scripts (most of them) and style.
This commit is contained in:
parent
1fac366e19
commit
3a75168d02
15
Makefile
15
Makefile
|
@ -4,7 +4,8 @@ all: rtf pdf html debug png txt
|
||||||
|
|
||||||
rtf: $(examples:.gamebook=.rtf)
|
rtf: $(examples:.gamebook=.rtf)
|
||||||
pdf: $(examples:.gamebook=.pdf)
|
pdf: $(examples:.gamebook=.pdf)
|
||||||
html: $(examples:.gamebook=.html)
|
html: $(examples:.gamebook=.html) examples/gamebookformatplay.js \
|
||||||
|
examples/gamebookformat.css
|
||||||
debug: $(examples:.gamebook=.debug)
|
debug: $(examples:.gamebook=.debug)
|
||||||
png: $(examples:.gamebook=.png)
|
png: $(examples:.gamebook=.png)
|
||||||
txt: $(examples:.gamebook=.txt)
|
txt: $(examples:.gamebook=.txt)
|
||||||
|
@ -14,6 +15,12 @@ uploadto=$(shell cat .uploadto)
|
||||||
readme.html: readme.org
|
readme.html: readme.org
|
||||||
emacs -Q --batch --visit=readme.org --funcall org-export-as-html-batch
|
emacs -Q --batch --visit=readme.org --funcall org-export-as-html-batch
|
||||||
|
|
||||||
|
examples/gamebookformatplay.js:
|
||||||
|
cp gamebookformatplay.js $@
|
||||||
|
|
||||||
|
examples/gamebookformat.css:
|
||||||
|
cp gamebookformat.css $@
|
||||||
|
|
||||||
%.rtf: %.gamebook *.py templates/rtf/*.rtf
|
%.rtf: %.gamebook *.py templates/rtf/*.rtf
|
||||||
./formatgamebook.py --no-shuffle $< $@
|
./formatgamebook.py --no-shuffle $< $@
|
||||||
|
|
||||||
|
@ -41,7 +48,8 @@ readme.html: readme.org
|
||||||
test: unittest checkexpected templatejstest
|
test: unittest checkexpected templatejstest
|
||||||
|
|
||||||
expected: all
|
expected: all
|
||||||
$(RM) expected/* && cp examples/*.{rtf,tex,html,debug,txt,dot,map} \
|
$(RM) expected/* && \
|
||||||
|
cp examples/*.{rtf,tex,html,debug,txt,dot,map} \
|
||||||
expected
|
expected
|
||||||
|
|
||||||
checkexpected: clean all
|
checkexpected: clean all
|
||||||
|
@ -72,7 +80,8 @@ clean:
|
||||||
examples/*.pdf examples/*.out *~ examples/*~ *.pyc \
|
examples/*.pdf examples/*.out *~ examples/*~ *.pyc \
|
||||||
examples/*.dot examples/*.aux examples/*.toc $(png) \
|
examples/*.dot examples/*.aux examples/*.toc $(png) \
|
||||||
examples/*.map templates/*~ templates/*/*~ \
|
examples/*.map templates/*~ templates/*/*~ \
|
||||||
$(examples:.gamebook=.png) readme.html
|
$(examples:.gamebook=.png) readme.html \
|
||||||
|
examples/*.js examples/*.css
|
||||||
|
|
||||||
fixmes:
|
fixmes:
|
||||||
grep FIXME *.py
|
grep FIXME *.py
|
||||||
|
|
2
examples/.gitignore
vendored
2
examples/.gitignore
vendored
|
@ -6,3 +6,5 @@
|
||||||
*.txt
|
*.txt
|
||||||
*.png
|
*.png
|
||||||
!testimage.png
|
!testimage.png
|
||||||
|
*.js
|
||||||
|
*.css
|
||||||
|
|
|
@ -4,364 +4,13 @@
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||||
<title>Gamebook</title>
|
<title>Gamebook</title>
|
||||||
|
<script type="text/javascript" src="gamebookformatplay.js"></script>
|
||||||
|
<link rel="stylesheet" href="gamebookformat.css"
|
||||||
|
type="text/css" />
|
||||||
<script>
|
<script>
|
||||||
|
gamebook.id = 'codewords';
|
||||||
|
|
||||||
var gamebook = {
|
|
||||||
'id' : 'codewords',
|
|
||||||
|
|
||||||
'player' : {
|
|
||||||
'started' : false,
|
|
||||||
'currentSection' : -1,
|
|
||||||
'collections' : {},
|
|
||||||
|
|
||||||
'collect' : function(type, name) {
|
|
||||||
if (type in this.collections) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.collections[type] = {
|
|
||||||
'name' : name,
|
|
||||||
'contents' : [],
|
|
||||||
'dropped' : {},
|
|
||||||
'add' : function(what) {
|
|
||||||
if (this.contents.indexOf(what) === -1
|
|
||||||
&& !(what in this.dropped)) {
|
|
||||||
this.contents.push(what);
|
|
||||||
this.contents.sort();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'drop' : function(what) {
|
|
||||||
var i = this.contents.indexOf(what);
|
|
||||||
if (i >= 0) {
|
|
||||||
this.contents.splice(i, 1);
|
|
||||||
this.dropped[what] = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'has' : function(what) {
|
|
||||||
return this.contents.indexOf(what) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
gamebook.addCollectionView(type, name);
|
|
||||||
},
|
|
||||||
|
|
||||||
'add' : function(type, what) {
|
|
||||||
this.collections[type].add(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'drop' : function(type, what) {
|
|
||||||
this.collections[type].drop(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'has' : function(type, what) {
|
|
||||||
return this.collections[type].has(what);
|
|
||||||
},
|
|
||||||
|
|
||||||
'getState' : function() {
|
|
||||||
return JSON.stringify({
|
|
||||||
'collections' : this.collections,
|
|
||||||
'currentSection' : this.currentSection
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'setState' : function(state) {
|
|
||||||
var parsedState = JSON.parse(state);
|
|
||||||
this.currentSection = parsedState.currentSection;
|
|
||||||
for (var c in parsedState.collections) {
|
|
||||||
var collection = parsedState.collections[c];
|
|
||||||
if (!(c in this.collections)) {
|
|
||||||
this.collect(c, collection.name);
|
|
||||||
} else {
|
|
||||||
this.collections[c].name = collection.name;
|
|
||||||
}
|
|
||||||
this.collections[c].contents = collection.contents;
|
|
||||||
this.collections[c].dropped = collection.dropped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'sections' : {},
|
|
||||||
|
|
||||||
'turnToFunctions' : {},
|
|
||||||
|
|
||||||
'addSection' : function(nr, element) {
|
|
||||||
var section = {'element' : element, 'nr' : nr};
|
|
||||||
this.sections[nr] = section;
|
|
||||||
},
|
|
||||||
|
|
||||||
'turnTo' : function(nr) {
|
|
||||||
if (!gamebook.player.started) {
|
|
||||||
gamebook.start();
|
|
||||||
}
|
|
||||||
if (!nr in this.sections) {
|
|
||||||
throw new Exception("Can not turn to non-existing section "
|
|
||||||
+ nr + ".");
|
|
||||||
}
|
|
||||||
this.displaySection(nr);
|
|
||||||
},
|
|
||||||
|
|
||||||
'start' : function() {
|
|
||||||
this.hideIntroSections();
|
|
||||||
this.addClassToClass('startlink', 'nodisplay');
|
|
||||||
this.addClassToClass('resumelink', 'nodisplay');
|
|
||||||
gamebook.player.started = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
'displaySection' : function(nr) {
|
|
||||||
if (this.player.currentSection > 0) {
|
|
||||||
var section = this.sections[this.player.currentSection];
|
|
||||||
section.element.style.display = 'none';
|
|
||||||
}
|
|
||||||
var e = this.sections[nr].element;
|
|
||||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
|
||||||
e.style.display = 'block';
|
|
||||||
this.player.currentSection = nr;
|
|
||||||
this.saveGame();
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'saveGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
window.localStorage.setItem(this.getSavedGameName(),
|
|
||||||
this.player.getState());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'hasSavedGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
return window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'loadGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
var state = window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
this.player.setState(state);
|
|
||||||
this.turnTo(this.player.currentSection);
|
|
||||||
this.updateCollectionsView();
|
|
||||||
} else {
|
|
||||||
//FIXME some kind of error, because we should never get here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'getSavedGameName' : function() {
|
|
||||||
return 'savedGamebookPlayer-' + this.id;
|
|
||||||
},
|
|
||||||
|
|
||||||
'hideIntroSections' : function() {
|
|
||||||
this.addClassToClass('introsection', 'nodisplay');
|
|
||||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
|
||||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
|
||||||
},
|
|
||||||
|
|
||||||
'showIntroSections' : function() {
|
|
||||||
this.runActionsInIntroSections();
|
|
||||||
this.removeClassFromClass('introsection', 'nodisplay');
|
|
||||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
|
||||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
|
||||||
document.body.scrollIntoView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActionsInIntroSections' : function() {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName('introsectionbody'),
|
|
||||||
gamebook.runActions);
|
|
||||||
},
|
|
||||||
|
|
||||||
'addClassToClass' : function(className, addClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.add(addClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'removeClassFromClass' : function(className, removeClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.remove(removeClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActions' : function(e) {
|
|
||||||
var enableNextLink = true;
|
|
||||||
var hasXorScope = false;
|
|
||||||
var hasAutoScope = false;
|
|
||||||
var xorEnableNext = false;
|
|
||||||
var autoDisableAllRemainingLinks = (
|
|
||||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
|
||||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
|
||||||
if (!c.classList) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c.classList.contains('sectionref')) {
|
|
||||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
|
||||||
gamebook.enableLink(c);
|
|
||||||
if (hasAutoScope) {
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gamebook.disableLink(c);
|
|
||||||
}
|
|
||||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
|
||||||
hasAutoScope = false;
|
|
||||||
hasXorScope = false;
|
|
||||||
} else if (c.classList.contains('collect')) {
|
|
||||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
|
||||||
} else if (c.classList.contains('add')) {
|
|
||||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('drop')) {
|
|
||||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('has')) {
|
|
||||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('hasnot')) {
|
|
||||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('xor')) {
|
|
||||||
hasXorScope = true;
|
|
||||||
xorEnableNext = !enableNextLink;
|
|
||||||
} else if (c.classList.contains('auto')) {
|
|
||||||
hasAutoScope = true;
|
|
||||||
} else if (c.classList.contains('random')) {
|
|
||||||
c.addEventListener('click',
|
|
||||||
gamebook.enableRandomLinkAfter);
|
|
||||||
c.classList.add("enabledlink");
|
|
||||||
c.classList.remove("disabledlink");
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableLink' : function(e) {
|
|
||||||
e.addEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.add("enabledlink");
|
|
||||||
e.classList.remove("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'disableLink' : function(e) {
|
|
||||||
e.removeEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.remove("enabledlink");
|
|
||||||
e.classList.add("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableRandomLinkAfter' : function(event) {
|
|
||||||
this.classList.remove("enabledlink");
|
|
||||||
this.classList.add("disabledlink");
|
|
||||||
var links = [];
|
|
||||||
var e = this.nextSibling;
|
|
||||||
while (e) {
|
|
||||||
if (e.classList && e.classList.contains('sectionref')) {
|
|
||||||
links.push(e);
|
|
||||||
}
|
|
||||||
e = e.nextSibling;
|
|
||||||
}
|
|
||||||
if (links.length > 0) {
|
|
||||||
var selected = links[Math.floor(Math.random()*links.length)]
|
|
||||||
gamebook.enableLink(selected);
|
|
||||||
} else {
|
|
||||||
console.log("Random with nothing to select?");
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
'addCollectionView' : function(type, name) {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
var template = document.getElementById('collectionTemplate');
|
|
||||||
var e = template.cloneNode(true);
|
|
||||||
e.className = "collection";
|
|
||||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
|
||||||
e.dataset.type = type;
|
|
||||||
ce.appendChild(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
'updateCollectionsView' : function() {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
|
||||||
if (c.className === 'collection') {
|
|
||||||
var type = c.dataset.type;
|
|
||||||
var collection = gamebook.player.collections[type];
|
|
||||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
|
||||||
cc.innerHTML = collection.contents.join(', ');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'getTurnToFunction' : function(nr) {
|
|
||||||
if (nr in this.turnToFunctions) {
|
|
||||||
return this.turnToFunctions[nr];
|
|
||||||
} else {
|
|
||||||
var f = function () {
|
|
||||||
gamebook.turnTo(nr);
|
|
||||||
};
|
|
||||||
this.turnToFunctions[nr] = f;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// little hack to make easy to test from node.js
|
|
||||||
if (typeof exports !== 'undefined') {
|
|
||||||
exports.gamebook = gamebook;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random,
|
|
||||||
.resumelink{
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0.2em;
|
|
||||||
vertical-align: middle;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionref.enabledlink {
|
|
||||||
padding-left: 1.5em;
|
|
||||||
padding-right: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random,
|
|
||||||
.resumelink {cursor: pointer;}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
|
||||||
.random,.resumelink {background: #eef;
|
|
||||||
}
|
|
||||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
|
||||||
.hideintrolink:hover,.resumelink:hover {background: #a9f;}
|
|
||||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
|
||||||
.disabledlink:hover {background: inherit;}
|
|
||||||
.sectionnumber,.introsectionheading {font-weight: bolder;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;}
|
|
||||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
|
||||||
.sectiontext {margin-top: 0.5em;}
|
|
||||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
|
||||||
.collections {margin-top: 4em;}
|
|
||||||
.collection {background: #ddd; margin-top: 1em;}
|
|
||||||
.collectionheading {}
|
|
||||||
.collectionheading::after {content: ": ";}
|
|
||||||
.collectioncontents {}
|
|
||||||
.collect {}
|
|
||||||
.add {font-weight: bold;}
|
|
||||||
.drop {font-style: italic;}
|
|
||||||
.has {font-style: italic;}
|
|
||||||
.hasnot {font-style: italic;}
|
|
||||||
.collectionTemplate {display: none;}
|
|
||||||
.sectionimage {width: 100%; padding: 1em;}
|
|
||||||
.nodisplay {display: none;}
|
|
||||||
.resumenr {font-weight: bold;}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="hideintrolink nodisplay"
|
<div class="hideintrolink nodisplay"
|
||||||
|
|
|
@ -4,364 +4,13 @@
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||||
<title>Format</title>
|
<title>Format</title>
|
||||||
|
<script type="text/javascript" src="gamebookformatplay.js"></script>
|
||||||
|
<link rel="stylesheet" href="gamebookformat.css"
|
||||||
|
type="text/css" />
|
||||||
<script>
|
<script>
|
||||||
|
gamebook.id = 'format2';
|
||||||
|
|
||||||
var gamebook = {
|
|
||||||
'id' : 'format2',
|
|
||||||
|
|
||||||
'player' : {
|
|
||||||
'started' : false,
|
|
||||||
'currentSection' : -1,
|
|
||||||
'collections' : {},
|
|
||||||
|
|
||||||
'collect' : function(type, name) {
|
|
||||||
if (type in this.collections) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.collections[type] = {
|
|
||||||
'name' : name,
|
|
||||||
'contents' : [],
|
|
||||||
'dropped' : {},
|
|
||||||
'add' : function(what) {
|
|
||||||
if (this.contents.indexOf(what) === -1
|
|
||||||
&& !(what in this.dropped)) {
|
|
||||||
this.contents.push(what);
|
|
||||||
this.contents.sort();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'drop' : function(what) {
|
|
||||||
var i = this.contents.indexOf(what);
|
|
||||||
if (i >= 0) {
|
|
||||||
this.contents.splice(i, 1);
|
|
||||||
this.dropped[what] = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'has' : function(what) {
|
|
||||||
return this.contents.indexOf(what) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
gamebook.addCollectionView(type, name);
|
|
||||||
},
|
|
||||||
|
|
||||||
'add' : function(type, what) {
|
|
||||||
this.collections[type].add(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'drop' : function(type, what) {
|
|
||||||
this.collections[type].drop(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'has' : function(type, what) {
|
|
||||||
return this.collections[type].has(what);
|
|
||||||
},
|
|
||||||
|
|
||||||
'getState' : function() {
|
|
||||||
return JSON.stringify({
|
|
||||||
'collections' : this.collections,
|
|
||||||
'currentSection' : this.currentSection
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'setState' : function(state) {
|
|
||||||
var parsedState = JSON.parse(state);
|
|
||||||
this.currentSection = parsedState.currentSection;
|
|
||||||
for (var c in parsedState.collections) {
|
|
||||||
var collection = parsedState.collections[c];
|
|
||||||
if (!(c in this.collections)) {
|
|
||||||
this.collect(c, collection.name);
|
|
||||||
} else {
|
|
||||||
this.collections[c].name = collection.name;
|
|
||||||
}
|
|
||||||
this.collections[c].contents = collection.contents;
|
|
||||||
this.collections[c].dropped = collection.dropped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'sections' : {},
|
|
||||||
|
|
||||||
'turnToFunctions' : {},
|
|
||||||
|
|
||||||
'addSection' : function(nr, element) {
|
|
||||||
var section = {'element' : element, 'nr' : nr};
|
|
||||||
this.sections[nr] = section;
|
|
||||||
},
|
|
||||||
|
|
||||||
'turnTo' : function(nr) {
|
|
||||||
if (!gamebook.player.started) {
|
|
||||||
gamebook.start();
|
|
||||||
}
|
|
||||||
if (!nr in this.sections) {
|
|
||||||
throw new Exception("Can not turn to non-existing section "
|
|
||||||
+ nr + ".");
|
|
||||||
}
|
|
||||||
this.displaySection(nr);
|
|
||||||
},
|
|
||||||
|
|
||||||
'start' : function() {
|
|
||||||
this.hideIntroSections();
|
|
||||||
this.addClassToClass('startlink', 'nodisplay');
|
|
||||||
this.addClassToClass('resumelink', 'nodisplay');
|
|
||||||
gamebook.player.started = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
'displaySection' : function(nr) {
|
|
||||||
if (this.player.currentSection > 0) {
|
|
||||||
var section = this.sections[this.player.currentSection];
|
|
||||||
section.element.style.display = 'none';
|
|
||||||
}
|
|
||||||
var e = this.sections[nr].element;
|
|
||||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
|
||||||
e.style.display = 'block';
|
|
||||||
this.player.currentSection = nr;
|
|
||||||
this.saveGame();
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'saveGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
window.localStorage.setItem(this.getSavedGameName(),
|
|
||||||
this.player.getState());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'hasSavedGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
return window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'loadGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
var state = window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
this.player.setState(state);
|
|
||||||
this.turnTo(this.player.currentSection);
|
|
||||||
this.updateCollectionsView();
|
|
||||||
} else {
|
|
||||||
//FIXME some kind of error, because we should never get here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'getSavedGameName' : function() {
|
|
||||||
return 'savedGamebookPlayer-' + this.id;
|
|
||||||
},
|
|
||||||
|
|
||||||
'hideIntroSections' : function() {
|
|
||||||
this.addClassToClass('introsection', 'nodisplay');
|
|
||||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
|
||||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
|
||||||
},
|
|
||||||
|
|
||||||
'showIntroSections' : function() {
|
|
||||||
this.runActionsInIntroSections();
|
|
||||||
this.removeClassFromClass('introsection', 'nodisplay');
|
|
||||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
|
||||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
|
||||||
document.body.scrollIntoView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActionsInIntroSections' : function() {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName('introsectionbody'),
|
|
||||||
gamebook.runActions);
|
|
||||||
},
|
|
||||||
|
|
||||||
'addClassToClass' : function(className, addClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.add(addClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'removeClassFromClass' : function(className, removeClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.remove(removeClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActions' : function(e) {
|
|
||||||
var enableNextLink = true;
|
|
||||||
var hasXorScope = false;
|
|
||||||
var hasAutoScope = false;
|
|
||||||
var xorEnableNext = false;
|
|
||||||
var autoDisableAllRemainingLinks = (
|
|
||||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
|
||||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
|
||||||
if (!c.classList) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c.classList.contains('sectionref')) {
|
|
||||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
|
||||||
gamebook.enableLink(c);
|
|
||||||
if (hasAutoScope) {
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gamebook.disableLink(c);
|
|
||||||
}
|
|
||||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
|
||||||
hasAutoScope = false;
|
|
||||||
hasXorScope = false;
|
|
||||||
} else if (c.classList.contains('collect')) {
|
|
||||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
|
||||||
} else if (c.classList.contains('add')) {
|
|
||||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('drop')) {
|
|
||||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('has')) {
|
|
||||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('hasnot')) {
|
|
||||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('xor')) {
|
|
||||||
hasXorScope = true;
|
|
||||||
xorEnableNext = !enableNextLink;
|
|
||||||
} else if (c.classList.contains('auto')) {
|
|
||||||
hasAutoScope = true;
|
|
||||||
} else if (c.classList.contains('random')) {
|
|
||||||
c.addEventListener('click',
|
|
||||||
gamebook.enableRandomLinkAfter);
|
|
||||||
c.classList.add("enabledlink");
|
|
||||||
c.classList.remove("disabledlink");
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableLink' : function(e) {
|
|
||||||
e.addEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.add("enabledlink");
|
|
||||||
e.classList.remove("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'disableLink' : function(e) {
|
|
||||||
e.removeEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.remove("enabledlink");
|
|
||||||
e.classList.add("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableRandomLinkAfter' : function(event) {
|
|
||||||
this.classList.remove("enabledlink");
|
|
||||||
this.classList.add("disabledlink");
|
|
||||||
var links = [];
|
|
||||||
var e = this.nextSibling;
|
|
||||||
while (e) {
|
|
||||||
if (e.classList && e.classList.contains('sectionref')) {
|
|
||||||
links.push(e);
|
|
||||||
}
|
|
||||||
e = e.nextSibling;
|
|
||||||
}
|
|
||||||
if (links.length > 0) {
|
|
||||||
var selected = links[Math.floor(Math.random()*links.length)]
|
|
||||||
gamebook.enableLink(selected);
|
|
||||||
} else {
|
|
||||||
console.log("Random with nothing to select?");
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
'addCollectionView' : function(type, name) {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
var template = document.getElementById('collectionTemplate');
|
|
||||||
var e = template.cloneNode(true);
|
|
||||||
e.className = "collection";
|
|
||||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
|
||||||
e.dataset.type = type;
|
|
||||||
ce.appendChild(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
'updateCollectionsView' : function() {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
|
||||||
if (c.className === 'collection') {
|
|
||||||
var type = c.dataset.type;
|
|
||||||
var collection = gamebook.player.collections[type];
|
|
||||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
|
||||||
cc.innerHTML = collection.contents.join(', ');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'getTurnToFunction' : function(nr) {
|
|
||||||
if (nr in this.turnToFunctions) {
|
|
||||||
return this.turnToFunctions[nr];
|
|
||||||
} else {
|
|
||||||
var f = function () {
|
|
||||||
gamebook.turnTo(nr);
|
|
||||||
};
|
|
||||||
this.turnToFunctions[nr] = f;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// little hack to make easy to test from node.js
|
|
||||||
if (typeof exports !== 'undefined') {
|
|
||||||
exports.gamebook = gamebook;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random,
|
|
||||||
.resumelink{
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0.2em;
|
|
||||||
vertical-align: middle;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionref.enabledlink {
|
|
||||||
padding-left: 1.5em;
|
|
||||||
padding-right: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random,
|
|
||||||
.resumelink {cursor: pointer;}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
|
||||||
.random,.resumelink {background: #eef;
|
|
||||||
}
|
|
||||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
|
||||||
.hideintrolink:hover,.resumelink:hover {background: #a9f;}
|
|
||||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
|
||||||
.disabledlink:hover {background: inherit;}
|
|
||||||
.sectionnumber,.introsectionheading {font-weight: bolder;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;}
|
|
||||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
|
||||||
.sectiontext {margin-top: 0.5em;}
|
|
||||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
|
||||||
.collections {margin-top: 4em;}
|
|
||||||
.collection {background: #ddd; margin-top: 1em;}
|
|
||||||
.collectionheading {}
|
|
||||||
.collectionheading::after {content: ": ";}
|
|
||||||
.collectioncontents {}
|
|
||||||
.collect {}
|
|
||||||
.add {font-weight: bold;}
|
|
||||||
.drop {font-style: italic;}
|
|
||||||
.has {font-style: italic;}
|
|
||||||
.hasnot {font-style: italic;}
|
|
||||||
.collectionTemplate {display: none;}
|
|
||||||
.sectionimage {width: 100%; padding: 1em;}
|
|
||||||
.nodisplay {display: none;}
|
|
||||||
.resumenr {font-weight: bold;}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="hideintrolink nodisplay"
|
<div class="hideintrolink nodisplay"
|
||||||
|
|
|
@ -4,364 +4,13 @@
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||||
<title>Items</title>
|
<title>Items</title>
|
||||||
|
<script type="text/javascript" src="gamebookformatplay.js"></script>
|
||||||
|
<link rel="stylesheet" href="gamebookformat.css"
|
||||||
|
type="text/css" />
|
||||||
<script>
|
<script>
|
||||||
|
gamebook.id = 'items';
|
||||||
|
|
||||||
var gamebook = {
|
|
||||||
'id' : 'items',
|
|
||||||
|
|
||||||
'player' : {
|
|
||||||
'started' : false,
|
|
||||||
'currentSection' : -1,
|
|
||||||
'collections' : {},
|
|
||||||
|
|
||||||
'collect' : function(type, name) {
|
|
||||||
if (type in this.collections) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.collections[type] = {
|
|
||||||
'name' : name,
|
|
||||||
'contents' : [],
|
|
||||||
'dropped' : {},
|
|
||||||
'add' : function(what) {
|
|
||||||
if (this.contents.indexOf(what) === -1
|
|
||||||
&& !(what in this.dropped)) {
|
|
||||||
this.contents.push(what);
|
|
||||||
this.contents.sort();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'drop' : function(what) {
|
|
||||||
var i = this.contents.indexOf(what);
|
|
||||||
if (i >= 0) {
|
|
||||||
this.contents.splice(i, 1);
|
|
||||||
this.dropped[what] = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'has' : function(what) {
|
|
||||||
return this.contents.indexOf(what) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
gamebook.addCollectionView(type, name);
|
|
||||||
},
|
|
||||||
|
|
||||||
'add' : function(type, what) {
|
|
||||||
this.collections[type].add(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'drop' : function(type, what) {
|
|
||||||
this.collections[type].drop(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'has' : function(type, what) {
|
|
||||||
return this.collections[type].has(what);
|
|
||||||
},
|
|
||||||
|
|
||||||
'getState' : function() {
|
|
||||||
return JSON.stringify({
|
|
||||||
'collections' : this.collections,
|
|
||||||
'currentSection' : this.currentSection
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'setState' : function(state) {
|
|
||||||
var parsedState = JSON.parse(state);
|
|
||||||
this.currentSection = parsedState.currentSection;
|
|
||||||
for (var c in parsedState.collections) {
|
|
||||||
var collection = parsedState.collections[c];
|
|
||||||
if (!(c in this.collections)) {
|
|
||||||
this.collect(c, collection.name);
|
|
||||||
} else {
|
|
||||||
this.collections[c].name = collection.name;
|
|
||||||
}
|
|
||||||
this.collections[c].contents = collection.contents;
|
|
||||||
this.collections[c].dropped = collection.dropped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'sections' : {},
|
|
||||||
|
|
||||||
'turnToFunctions' : {},
|
|
||||||
|
|
||||||
'addSection' : function(nr, element) {
|
|
||||||
var section = {'element' : element, 'nr' : nr};
|
|
||||||
this.sections[nr] = section;
|
|
||||||
},
|
|
||||||
|
|
||||||
'turnTo' : function(nr) {
|
|
||||||
if (!gamebook.player.started) {
|
|
||||||
gamebook.start();
|
|
||||||
}
|
|
||||||
if (!nr in this.sections) {
|
|
||||||
throw new Exception("Can not turn to non-existing section "
|
|
||||||
+ nr + ".");
|
|
||||||
}
|
|
||||||
this.displaySection(nr);
|
|
||||||
},
|
|
||||||
|
|
||||||
'start' : function() {
|
|
||||||
this.hideIntroSections();
|
|
||||||
this.addClassToClass('startlink', 'nodisplay');
|
|
||||||
this.addClassToClass('resumelink', 'nodisplay');
|
|
||||||
gamebook.player.started = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
'displaySection' : function(nr) {
|
|
||||||
if (this.player.currentSection > 0) {
|
|
||||||
var section = this.sections[this.player.currentSection];
|
|
||||||
section.element.style.display = 'none';
|
|
||||||
}
|
|
||||||
var e = this.sections[nr].element;
|
|
||||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
|
||||||
e.style.display = 'block';
|
|
||||||
this.player.currentSection = nr;
|
|
||||||
this.saveGame();
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'saveGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
window.localStorage.setItem(this.getSavedGameName(),
|
|
||||||
this.player.getState());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'hasSavedGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
return window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'loadGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
var state = window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
this.player.setState(state);
|
|
||||||
this.turnTo(this.player.currentSection);
|
|
||||||
this.updateCollectionsView();
|
|
||||||
} else {
|
|
||||||
//FIXME some kind of error, because we should never get here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'getSavedGameName' : function() {
|
|
||||||
return 'savedGamebookPlayer-' + this.id;
|
|
||||||
},
|
|
||||||
|
|
||||||
'hideIntroSections' : function() {
|
|
||||||
this.addClassToClass('introsection', 'nodisplay');
|
|
||||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
|
||||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
|
||||||
},
|
|
||||||
|
|
||||||
'showIntroSections' : function() {
|
|
||||||
this.runActionsInIntroSections();
|
|
||||||
this.removeClassFromClass('introsection', 'nodisplay');
|
|
||||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
|
||||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
|
||||||
document.body.scrollIntoView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActionsInIntroSections' : function() {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName('introsectionbody'),
|
|
||||||
gamebook.runActions);
|
|
||||||
},
|
|
||||||
|
|
||||||
'addClassToClass' : function(className, addClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.add(addClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'removeClassFromClass' : function(className, removeClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.remove(removeClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActions' : function(e) {
|
|
||||||
var enableNextLink = true;
|
|
||||||
var hasXorScope = false;
|
|
||||||
var hasAutoScope = false;
|
|
||||||
var xorEnableNext = false;
|
|
||||||
var autoDisableAllRemainingLinks = (
|
|
||||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
|
||||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
|
||||||
if (!c.classList) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c.classList.contains('sectionref')) {
|
|
||||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
|
||||||
gamebook.enableLink(c);
|
|
||||||
if (hasAutoScope) {
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gamebook.disableLink(c);
|
|
||||||
}
|
|
||||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
|
||||||
hasAutoScope = false;
|
|
||||||
hasXorScope = false;
|
|
||||||
} else if (c.classList.contains('collect')) {
|
|
||||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
|
||||||
} else if (c.classList.contains('add')) {
|
|
||||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('drop')) {
|
|
||||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('has')) {
|
|
||||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('hasnot')) {
|
|
||||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('xor')) {
|
|
||||||
hasXorScope = true;
|
|
||||||
xorEnableNext = !enableNextLink;
|
|
||||||
} else if (c.classList.contains('auto')) {
|
|
||||||
hasAutoScope = true;
|
|
||||||
} else if (c.classList.contains('random')) {
|
|
||||||
c.addEventListener('click',
|
|
||||||
gamebook.enableRandomLinkAfter);
|
|
||||||
c.classList.add("enabledlink");
|
|
||||||
c.classList.remove("disabledlink");
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableLink' : function(e) {
|
|
||||||
e.addEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.add("enabledlink");
|
|
||||||
e.classList.remove("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'disableLink' : function(e) {
|
|
||||||
e.removeEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.remove("enabledlink");
|
|
||||||
e.classList.add("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableRandomLinkAfter' : function(event) {
|
|
||||||
this.classList.remove("enabledlink");
|
|
||||||
this.classList.add("disabledlink");
|
|
||||||
var links = [];
|
|
||||||
var e = this.nextSibling;
|
|
||||||
while (e) {
|
|
||||||
if (e.classList && e.classList.contains('sectionref')) {
|
|
||||||
links.push(e);
|
|
||||||
}
|
|
||||||
e = e.nextSibling;
|
|
||||||
}
|
|
||||||
if (links.length > 0) {
|
|
||||||
var selected = links[Math.floor(Math.random()*links.length)]
|
|
||||||
gamebook.enableLink(selected);
|
|
||||||
} else {
|
|
||||||
console.log("Random with nothing to select?");
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
'addCollectionView' : function(type, name) {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
var template = document.getElementById('collectionTemplate');
|
|
||||||
var e = template.cloneNode(true);
|
|
||||||
e.className = "collection";
|
|
||||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
|
||||||
e.dataset.type = type;
|
|
||||||
ce.appendChild(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
'updateCollectionsView' : function() {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
|
||||||
if (c.className === 'collection') {
|
|
||||||
var type = c.dataset.type;
|
|
||||||
var collection = gamebook.player.collections[type];
|
|
||||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
|
||||||
cc.innerHTML = collection.contents.join(', ');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'getTurnToFunction' : function(nr) {
|
|
||||||
if (nr in this.turnToFunctions) {
|
|
||||||
return this.turnToFunctions[nr];
|
|
||||||
} else {
|
|
||||||
var f = function () {
|
|
||||||
gamebook.turnTo(nr);
|
|
||||||
};
|
|
||||||
this.turnToFunctions[nr] = f;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// little hack to make easy to test from node.js
|
|
||||||
if (typeof exports !== 'undefined') {
|
|
||||||
exports.gamebook = gamebook;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random,
|
|
||||||
.resumelink{
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0.2em;
|
|
||||||
vertical-align: middle;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionref.enabledlink {
|
|
||||||
padding-left: 1.5em;
|
|
||||||
padding-right: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random,
|
|
||||||
.resumelink {cursor: pointer;}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
|
||||||
.random,.resumelink {background: #eef;
|
|
||||||
}
|
|
||||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
|
||||||
.hideintrolink:hover,.resumelink:hover {background: #a9f;}
|
|
||||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
|
||||||
.disabledlink:hover {background: inherit;}
|
|
||||||
.sectionnumber,.introsectionheading {font-weight: bolder;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;}
|
|
||||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
|
||||||
.sectiontext {margin-top: 0.5em;}
|
|
||||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
|
||||||
.collections {margin-top: 4em;}
|
|
||||||
.collection {background: #ddd; margin-top: 1em;}
|
|
||||||
.collectionheading {}
|
|
||||||
.collectionheading::after {content: ": ";}
|
|
||||||
.collectioncontents {}
|
|
||||||
.collect {}
|
|
||||||
.add {font-weight: bold;}
|
|
||||||
.drop {font-style: italic;}
|
|
||||||
.has {font-style: italic;}
|
|
||||||
.hasnot {font-style: italic;}
|
|
||||||
.collectionTemplate {display: none;}
|
|
||||||
.sectionimage {width: 100%; padding: 1em;}
|
|
||||||
.nodisplay {display: none;}
|
|
||||||
.resumenr {font-weight: bold;}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="hideintrolink nodisplay"
|
<div class="hideintrolink nodisplay"
|
||||||
|
|
|
@ -4,364 +4,13 @@
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||||
<title>Gamebook</title>
|
<title>Gamebook</title>
|
||||||
|
<script type="text/javascript" src="gamebookformatplay.js"></script>
|
||||||
|
<link rel="stylesheet" href="gamebookformat.css"
|
||||||
|
type="text/css" />
|
||||||
<script>
|
<script>
|
||||||
|
gamebook.id = 'references';
|
||||||
|
|
||||||
var gamebook = {
|
|
||||||
'id' : 'references',
|
|
||||||
|
|
||||||
'player' : {
|
|
||||||
'started' : false,
|
|
||||||
'currentSection' : -1,
|
|
||||||
'collections' : {},
|
|
||||||
|
|
||||||
'collect' : function(type, name) {
|
|
||||||
if (type in this.collections) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.collections[type] = {
|
|
||||||
'name' : name,
|
|
||||||
'contents' : [],
|
|
||||||
'dropped' : {},
|
|
||||||
'add' : function(what) {
|
|
||||||
if (this.contents.indexOf(what) === -1
|
|
||||||
&& !(what in this.dropped)) {
|
|
||||||
this.contents.push(what);
|
|
||||||
this.contents.sort();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'drop' : function(what) {
|
|
||||||
var i = this.contents.indexOf(what);
|
|
||||||
if (i >= 0) {
|
|
||||||
this.contents.splice(i, 1);
|
|
||||||
this.dropped[what] = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'has' : function(what) {
|
|
||||||
return this.contents.indexOf(what) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
gamebook.addCollectionView(type, name);
|
|
||||||
},
|
|
||||||
|
|
||||||
'add' : function(type, what) {
|
|
||||||
this.collections[type].add(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'drop' : function(type, what) {
|
|
||||||
this.collections[type].drop(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'has' : function(type, what) {
|
|
||||||
return this.collections[type].has(what);
|
|
||||||
},
|
|
||||||
|
|
||||||
'getState' : function() {
|
|
||||||
return JSON.stringify({
|
|
||||||
'collections' : this.collections,
|
|
||||||
'currentSection' : this.currentSection
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'setState' : function(state) {
|
|
||||||
var parsedState = JSON.parse(state);
|
|
||||||
this.currentSection = parsedState.currentSection;
|
|
||||||
for (var c in parsedState.collections) {
|
|
||||||
var collection = parsedState.collections[c];
|
|
||||||
if (!(c in this.collections)) {
|
|
||||||
this.collect(c, collection.name);
|
|
||||||
} else {
|
|
||||||
this.collections[c].name = collection.name;
|
|
||||||
}
|
|
||||||
this.collections[c].contents = collection.contents;
|
|
||||||
this.collections[c].dropped = collection.dropped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'sections' : {},
|
|
||||||
|
|
||||||
'turnToFunctions' : {},
|
|
||||||
|
|
||||||
'addSection' : function(nr, element) {
|
|
||||||
var section = {'element' : element, 'nr' : nr};
|
|
||||||
this.sections[nr] = section;
|
|
||||||
},
|
|
||||||
|
|
||||||
'turnTo' : function(nr) {
|
|
||||||
if (!gamebook.player.started) {
|
|
||||||
gamebook.start();
|
|
||||||
}
|
|
||||||
if (!nr in this.sections) {
|
|
||||||
throw new Exception("Can not turn to non-existing section "
|
|
||||||
+ nr + ".");
|
|
||||||
}
|
|
||||||
this.displaySection(nr);
|
|
||||||
},
|
|
||||||
|
|
||||||
'start' : function() {
|
|
||||||
this.hideIntroSections();
|
|
||||||
this.addClassToClass('startlink', 'nodisplay');
|
|
||||||
this.addClassToClass('resumelink', 'nodisplay');
|
|
||||||
gamebook.player.started = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
'displaySection' : function(nr) {
|
|
||||||
if (this.player.currentSection > 0) {
|
|
||||||
var section = this.sections[this.player.currentSection];
|
|
||||||
section.element.style.display = 'none';
|
|
||||||
}
|
|
||||||
var e = this.sections[nr].element;
|
|
||||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
|
||||||
e.style.display = 'block';
|
|
||||||
this.player.currentSection = nr;
|
|
||||||
this.saveGame();
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'saveGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
window.localStorage.setItem(this.getSavedGameName(),
|
|
||||||
this.player.getState());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'hasSavedGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
return window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'loadGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
var state = window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
this.player.setState(state);
|
|
||||||
this.turnTo(this.player.currentSection);
|
|
||||||
this.updateCollectionsView();
|
|
||||||
} else {
|
|
||||||
//FIXME some kind of error, because we should never get here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'getSavedGameName' : function() {
|
|
||||||
return 'savedGamebookPlayer-' + this.id;
|
|
||||||
},
|
|
||||||
|
|
||||||
'hideIntroSections' : function() {
|
|
||||||
this.addClassToClass('introsection', 'nodisplay');
|
|
||||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
|
||||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
|
||||||
},
|
|
||||||
|
|
||||||
'showIntroSections' : function() {
|
|
||||||
this.runActionsInIntroSections();
|
|
||||||
this.removeClassFromClass('introsection', 'nodisplay');
|
|
||||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
|
||||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
|
||||||
document.body.scrollIntoView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActionsInIntroSections' : function() {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName('introsectionbody'),
|
|
||||||
gamebook.runActions);
|
|
||||||
},
|
|
||||||
|
|
||||||
'addClassToClass' : function(className, addClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.add(addClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'removeClassFromClass' : function(className, removeClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.remove(removeClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActions' : function(e) {
|
|
||||||
var enableNextLink = true;
|
|
||||||
var hasXorScope = false;
|
|
||||||
var hasAutoScope = false;
|
|
||||||
var xorEnableNext = false;
|
|
||||||
var autoDisableAllRemainingLinks = (
|
|
||||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
|
||||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
|
||||||
if (!c.classList) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c.classList.contains('sectionref')) {
|
|
||||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
|
||||||
gamebook.enableLink(c);
|
|
||||||
if (hasAutoScope) {
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gamebook.disableLink(c);
|
|
||||||
}
|
|
||||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
|
||||||
hasAutoScope = false;
|
|
||||||
hasXorScope = false;
|
|
||||||
} else if (c.classList.contains('collect')) {
|
|
||||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
|
||||||
} else if (c.classList.contains('add')) {
|
|
||||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('drop')) {
|
|
||||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('has')) {
|
|
||||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('hasnot')) {
|
|
||||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('xor')) {
|
|
||||||
hasXorScope = true;
|
|
||||||
xorEnableNext = !enableNextLink;
|
|
||||||
} else if (c.classList.contains('auto')) {
|
|
||||||
hasAutoScope = true;
|
|
||||||
} else if (c.classList.contains('random')) {
|
|
||||||
c.addEventListener('click',
|
|
||||||
gamebook.enableRandomLinkAfter);
|
|
||||||
c.classList.add("enabledlink");
|
|
||||||
c.classList.remove("disabledlink");
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableLink' : function(e) {
|
|
||||||
e.addEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.add("enabledlink");
|
|
||||||
e.classList.remove("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'disableLink' : function(e) {
|
|
||||||
e.removeEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.remove("enabledlink");
|
|
||||||
e.classList.add("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableRandomLinkAfter' : function(event) {
|
|
||||||
this.classList.remove("enabledlink");
|
|
||||||
this.classList.add("disabledlink");
|
|
||||||
var links = [];
|
|
||||||
var e = this.nextSibling;
|
|
||||||
while (e) {
|
|
||||||
if (e.classList && e.classList.contains('sectionref')) {
|
|
||||||
links.push(e);
|
|
||||||
}
|
|
||||||
e = e.nextSibling;
|
|
||||||
}
|
|
||||||
if (links.length > 0) {
|
|
||||||
var selected = links[Math.floor(Math.random()*links.length)]
|
|
||||||
gamebook.enableLink(selected);
|
|
||||||
} else {
|
|
||||||
console.log("Random with nothing to select?");
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
'addCollectionView' : function(type, name) {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
var template = document.getElementById('collectionTemplate');
|
|
||||||
var e = template.cloneNode(true);
|
|
||||||
e.className = "collection";
|
|
||||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
|
||||||
e.dataset.type = type;
|
|
||||||
ce.appendChild(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
'updateCollectionsView' : function() {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
|
||||||
if (c.className === 'collection') {
|
|
||||||
var type = c.dataset.type;
|
|
||||||
var collection = gamebook.player.collections[type];
|
|
||||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
|
||||||
cc.innerHTML = collection.contents.join(', ');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'getTurnToFunction' : function(nr) {
|
|
||||||
if (nr in this.turnToFunctions) {
|
|
||||||
return this.turnToFunctions[nr];
|
|
||||||
} else {
|
|
||||||
var f = function () {
|
|
||||||
gamebook.turnTo(nr);
|
|
||||||
};
|
|
||||||
this.turnToFunctions[nr] = f;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// little hack to make easy to test from node.js
|
|
||||||
if (typeof exports !== 'undefined') {
|
|
||||||
exports.gamebook = gamebook;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random,
|
|
||||||
.resumelink{
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0.2em;
|
|
||||||
vertical-align: middle;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionref.enabledlink {
|
|
||||||
padding-left: 1.5em;
|
|
||||||
padding-right: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random,
|
|
||||||
.resumelink {cursor: pointer;}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
|
||||||
.random,.resumelink {background: #eef;
|
|
||||||
}
|
|
||||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
|
||||||
.hideintrolink:hover,.resumelink:hover {background: #a9f;}
|
|
||||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
|
||||||
.disabledlink:hover {background: inherit;}
|
|
||||||
.sectionnumber,.introsectionheading {font-weight: bolder;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;}
|
|
||||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
|
||||||
.sectiontext {margin-top: 0.5em;}
|
|
||||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
|
||||||
.collections {margin-top: 4em;}
|
|
||||||
.collection {background: #ddd; margin-top: 1em;}
|
|
||||||
.collectionheading {}
|
|
||||||
.collectionheading::after {content: ": ";}
|
|
||||||
.collectioncontents {}
|
|
||||||
.collect {}
|
|
||||||
.add {font-weight: bold;}
|
|
||||||
.drop {font-style: italic;}
|
|
||||||
.has {font-style: italic;}
|
|
||||||
.hasnot {font-style: italic;}
|
|
||||||
.collectionTemplate {display: none;}
|
|
||||||
.sectionimage {width: 100%; padding: 1em;}
|
|
||||||
.nodisplay {display: none;}
|
|
||||||
.resumenr {font-weight: bold;}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="hideintrolink nodisplay"
|
<div class="hideintrolink nodisplay"
|
||||||
|
|
|
@ -4,364 +4,13 @@
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||||
<title>Gamebook</title>
|
<title>Gamebook</title>
|
||||||
|
<script type="text/javascript" src="gamebookformatplay.js"></script>
|
||||||
|
<link rel="stylesheet" href="gamebookformat.css"
|
||||||
|
type="text/css" />
|
||||||
<script>
|
<script>
|
||||||
|
gamebook.id = 'unreachable';
|
||||||
|
|
||||||
var gamebook = {
|
|
||||||
'id' : 'unreachable',
|
|
||||||
|
|
||||||
'player' : {
|
|
||||||
'started' : false,
|
|
||||||
'currentSection' : -1,
|
|
||||||
'collections' : {},
|
|
||||||
|
|
||||||
'collect' : function(type, name) {
|
|
||||||
if (type in this.collections) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.collections[type] = {
|
|
||||||
'name' : name,
|
|
||||||
'contents' : [],
|
|
||||||
'dropped' : {},
|
|
||||||
'add' : function(what) {
|
|
||||||
if (this.contents.indexOf(what) === -1
|
|
||||||
&& !(what in this.dropped)) {
|
|
||||||
this.contents.push(what);
|
|
||||||
this.contents.sort();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'drop' : function(what) {
|
|
||||||
var i = this.contents.indexOf(what);
|
|
||||||
if (i >= 0) {
|
|
||||||
this.contents.splice(i, 1);
|
|
||||||
this.dropped[what] = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'has' : function(what) {
|
|
||||||
return this.contents.indexOf(what) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
gamebook.addCollectionView(type, name);
|
|
||||||
},
|
|
||||||
|
|
||||||
'add' : function(type, what) {
|
|
||||||
this.collections[type].add(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'drop' : function(type, what) {
|
|
||||||
this.collections[type].drop(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'has' : function(type, what) {
|
|
||||||
return this.collections[type].has(what);
|
|
||||||
},
|
|
||||||
|
|
||||||
'getState' : function() {
|
|
||||||
return JSON.stringify({
|
|
||||||
'collections' : this.collections,
|
|
||||||
'currentSection' : this.currentSection
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'setState' : function(state) {
|
|
||||||
var parsedState = JSON.parse(state);
|
|
||||||
this.currentSection = parsedState.currentSection;
|
|
||||||
for (var c in parsedState.collections) {
|
|
||||||
var collection = parsedState.collections[c];
|
|
||||||
if (!(c in this.collections)) {
|
|
||||||
this.collect(c, collection.name);
|
|
||||||
} else {
|
|
||||||
this.collections[c].name = collection.name;
|
|
||||||
}
|
|
||||||
this.collections[c].contents = collection.contents;
|
|
||||||
this.collections[c].dropped = collection.dropped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'sections' : {},
|
|
||||||
|
|
||||||
'turnToFunctions' : {},
|
|
||||||
|
|
||||||
'addSection' : function(nr, element) {
|
|
||||||
var section = {'element' : element, 'nr' : nr};
|
|
||||||
this.sections[nr] = section;
|
|
||||||
},
|
|
||||||
|
|
||||||
'turnTo' : function(nr) {
|
|
||||||
if (!gamebook.player.started) {
|
|
||||||
gamebook.start();
|
|
||||||
}
|
|
||||||
if (!nr in this.sections) {
|
|
||||||
throw new Exception("Can not turn to non-existing section "
|
|
||||||
+ nr + ".");
|
|
||||||
}
|
|
||||||
this.displaySection(nr);
|
|
||||||
},
|
|
||||||
|
|
||||||
'start' : function() {
|
|
||||||
this.hideIntroSections();
|
|
||||||
this.addClassToClass('startlink', 'nodisplay');
|
|
||||||
this.addClassToClass('resumelink', 'nodisplay');
|
|
||||||
gamebook.player.started = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
'displaySection' : function(nr) {
|
|
||||||
if (this.player.currentSection > 0) {
|
|
||||||
var section = this.sections[this.player.currentSection];
|
|
||||||
section.element.style.display = 'none';
|
|
||||||
}
|
|
||||||
var e = this.sections[nr].element;
|
|
||||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
|
||||||
e.style.display = 'block';
|
|
||||||
this.player.currentSection = nr;
|
|
||||||
this.saveGame();
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'saveGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
window.localStorage.setItem(this.getSavedGameName(),
|
|
||||||
this.player.getState());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'hasSavedGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
return window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'loadGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
var state = window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
this.player.setState(state);
|
|
||||||
this.turnTo(this.player.currentSection);
|
|
||||||
this.updateCollectionsView();
|
|
||||||
} else {
|
|
||||||
//FIXME some kind of error, because we should never get here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'getSavedGameName' : function() {
|
|
||||||
return 'savedGamebookPlayer-' + this.id;
|
|
||||||
},
|
|
||||||
|
|
||||||
'hideIntroSections' : function() {
|
|
||||||
this.addClassToClass('introsection', 'nodisplay');
|
|
||||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
|
||||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
|
||||||
},
|
|
||||||
|
|
||||||
'showIntroSections' : function() {
|
|
||||||
this.runActionsInIntroSections();
|
|
||||||
this.removeClassFromClass('introsection', 'nodisplay');
|
|
||||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
|
||||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
|
||||||
document.body.scrollIntoView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActionsInIntroSections' : function() {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName('introsectionbody'),
|
|
||||||
gamebook.runActions);
|
|
||||||
},
|
|
||||||
|
|
||||||
'addClassToClass' : function(className, addClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.add(addClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'removeClassFromClass' : function(className, removeClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.remove(removeClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActions' : function(e) {
|
|
||||||
var enableNextLink = true;
|
|
||||||
var hasXorScope = false;
|
|
||||||
var hasAutoScope = false;
|
|
||||||
var xorEnableNext = false;
|
|
||||||
var autoDisableAllRemainingLinks = (
|
|
||||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
|
||||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
|
||||||
if (!c.classList) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c.classList.contains('sectionref')) {
|
|
||||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
|
||||||
gamebook.enableLink(c);
|
|
||||||
if (hasAutoScope) {
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gamebook.disableLink(c);
|
|
||||||
}
|
|
||||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
|
||||||
hasAutoScope = false;
|
|
||||||
hasXorScope = false;
|
|
||||||
} else if (c.classList.contains('collect')) {
|
|
||||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
|
||||||
} else if (c.classList.contains('add')) {
|
|
||||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('drop')) {
|
|
||||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('has')) {
|
|
||||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('hasnot')) {
|
|
||||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('xor')) {
|
|
||||||
hasXorScope = true;
|
|
||||||
xorEnableNext = !enableNextLink;
|
|
||||||
} else if (c.classList.contains('auto')) {
|
|
||||||
hasAutoScope = true;
|
|
||||||
} else if (c.classList.contains('random')) {
|
|
||||||
c.addEventListener('click',
|
|
||||||
gamebook.enableRandomLinkAfter);
|
|
||||||
c.classList.add("enabledlink");
|
|
||||||
c.classList.remove("disabledlink");
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableLink' : function(e) {
|
|
||||||
e.addEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.add("enabledlink");
|
|
||||||
e.classList.remove("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'disableLink' : function(e) {
|
|
||||||
e.removeEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.remove("enabledlink");
|
|
||||||
e.classList.add("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableRandomLinkAfter' : function(event) {
|
|
||||||
this.classList.remove("enabledlink");
|
|
||||||
this.classList.add("disabledlink");
|
|
||||||
var links = [];
|
|
||||||
var e = this.nextSibling;
|
|
||||||
while (e) {
|
|
||||||
if (e.classList && e.classList.contains('sectionref')) {
|
|
||||||
links.push(e);
|
|
||||||
}
|
|
||||||
e = e.nextSibling;
|
|
||||||
}
|
|
||||||
if (links.length > 0) {
|
|
||||||
var selected = links[Math.floor(Math.random()*links.length)]
|
|
||||||
gamebook.enableLink(selected);
|
|
||||||
} else {
|
|
||||||
console.log("Random with nothing to select?");
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
'addCollectionView' : function(type, name) {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
var template = document.getElementById('collectionTemplate');
|
|
||||||
var e = template.cloneNode(true);
|
|
||||||
e.className = "collection";
|
|
||||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
|
||||||
e.dataset.type = type;
|
|
||||||
ce.appendChild(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
'updateCollectionsView' : function() {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
|
||||||
if (c.className === 'collection') {
|
|
||||||
var type = c.dataset.type;
|
|
||||||
var collection = gamebook.player.collections[type];
|
|
||||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
|
||||||
cc.innerHTML = collection.contents.join(', ');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'getTurnToFunction' : function(nr) {
|
|
||||||
if (nr in this.turnToFunctions) {
|
|
||||||
return this.turnToFunctions[nr];
|
|
||||||
} else {
|
|
||||||
var f = function () {
|
|
||||||
gamebook.turnTo(nr);
|
|
||||||
};
|
|
||||||
this.turnToFunctions[nr] = f;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// little hack to make easy to test from node.js
|
|
||||||
if (typeof exports !== 'undefined') {
|
|
||||||
exports.gamebook = gamebook;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random,
|
|
||||||
.resumelink{
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0.2em;
|
|
||||||
vertical-align: middle;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionref.enabledlink {
|
|
||||||
padding-left: 1.5em;
|
|
||||||
padding-right: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random,
|
|
||||||
.resumelink {cursor: pointer;}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
|
||||||
.random,.resumelink {background: #eef;
|
|
||||||
}
|
|
||||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
|
||||||
.hideintrolink:hover,.resumelink:hover {background: #a9f;}
|
|
||||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
|
||||||
.disabledlink:hover {background: inherit;}
|
|
||||||
.sectionnumber,.introsectionheading {font-weight: bolder;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;}
|
|
||||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
|
||||||
.sectiontext {margin-top: 0.5em;}
|
|
||||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
|
||||||
.collections {margin-top: 4em;}
|
|
||||||
.collection {background: #ddd; margin-top: 1em;}
|
|
||||||
.collectionheading {}
|
|
||||||
.collectionheading::after {content: ": ";}
|
|
||||||
.collectioncontents {}
|
|
||||||
.collect {}
|
|
||||||
.add {font-weight: bold;}
|
|
||||||
.drop {font-style: italic;}
|
|
||||||
.has {font-style: italic;}
|
|
||||||
.hasnot {font-style: italic;}
|
|
||||||
.collectionTemplate {display: none;}
|
|
||||||
.sectionimage {width: 100%; padding: 1em;}
|
|
||||||
.nodisplay {display: none;}
|
|
||||||
.resumenr {font-weight: bold;}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="hideintrolink nodisplay"
|
<div class="hideintrolink nodisplay"
|
||||||
|
|
43
gamebookformat.css
Normal file
43
gamebookformat.css
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random,
|
||||||
|
.resumelink{
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0.2em;
|
||||||
|
vertical-align: middle;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionref.enabledlink {
|
||||||
|
padding-left: 1.5em;
|
||||||
|
padding-right: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random,
|
||||||
|
.resumelink {cursor: pointer;}
|
||||||
|
|
||||||
|
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
||||||
|
.random,.resumelink {background: #eef;
|
||||||
|
}
|
||||||
|
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
||||||
|
.hideintrolink:hover,.resumelink:hover {background: #a9f;}
|
||||||
|
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
||||||
|
.disabledlink:hover {background: inherit;}
|
||||||
|
.sectionnumber,.introsectionheading {font-weight: bolder;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;}
|
||||||
|
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
||||||
|
.sectiontext {margin-top: 0.5em;}
|
||||||
|
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
||||||
|
.collections {margin-top: 4em;}
|
||||||
|
.collection {background: #ddd; margin-top: 1em;}
|
||||||
|
.collectionheading {}
|
||||||
|
.collectionheading::after {content: ": ";}
|
||||||
|
.collectioncontents {}
|
||||||
|
.collect {}
|
||||||
|
.add {font-weight: bold;}
|
||||||
|
.drop {font-style: italic;}
|
||||||
|
.has {font-style: italic;}
|
||||||
|
.hasnot {font-style: italic;}
|
||||||
|
.collectionTemplate {display: none;}
|
||||||
|
.sectionimage {width: 100%; padding: 1em;}
|
||||||
|
.nodisplay {display: none;}
|
||||||
|
.resumenr {font-weight: bold;}
|
300
gamebookformatplay.js
Normal file
300
gamebookformatplay.js
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
var gamebook = {
|
||||||
|
'player' : {
|
||||||
|
'started' : false,
|
||||||
|
'currentSection' : -1,
|
||||||
|
'collections' : {},
|
||||||
|
|
||||||
|
'collect' : function(type, name) {
|
||||||
|
if (type in this.collections) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.collections[type] = {
|
||||||
|
'name' : name,
|
||||||
|
'contents' : [],
|
||||||
|
'dropped' : {},
|
||||||
|
'add' : function(what) {
|
||||||
|
if (this.contents.indexOf(what) === -1
|
||||||
|
&& !(what in this.dropped)) {
|
||||||
|
this.contents.push(what);
|
||||||
|
this.contents.sort();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'drop' : function(what) {
|
||||||
|
var i = this.contents.indexOf(what);
|
||||||
|
if (i >= 0) {
|
||||||
|
this.contents.splice(i, 1);
|
||||||
|
this.dropped[what] = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'has' : function(what) {
|
||||||
|
return this.contents.indexOf(what) >= 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
gamebook.addCollectionView(type, name);
|
||||||
|
},
|
||||||
|
|
||||||
|
'add' : function(type, what) {
|
||||||
|
this.collections[type].add(what);
|
||||||
|
gamebook.updateCollectionsView();
|
||||||
|
},
|
||||||
|
|
||||||
|
'drop' : function(type, what) {
|
||||||
|
this.collections[type].drop(what);
|
||||||
|
gamebook.updateCollectionsView();
|
||||||
|
},
|
||||||
|
|
||||||
|
'has' : function(type, what) {
|
||||||
|
return this.collections[type].has(what);
|
||||||
|
},
|
||||||
|
|
||||||
|
'getState' : function() {
|
||||||
|
return JSON.stringify({
|
||||||
|
'collections' : this.collections,
|
||||||
|
'currentSection' : this.currentSection
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'setState' : function(state) {
|
||||||
|
var parsedState = JSON.parse(state);
|
||||||
|
this.currentSection = parsedState.currentSection;
|
||||||
|
for (var c in parsedState.collections) {
|
||||||
|
var collection = parsedState.collections[c];
|
||||||
|
if (!(c in this.collections)) {
|
||||||
|
this.collect(c, collection.name);
|
||||||
|
} else {
|
||||||
|
this.collections[c].name = collection.name;
|
||||||
|
}
|
||||||
|
this.collections[c].contents = collection.contents;
|
||||||
|
this.collections[c].dropped = collection.dropped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'sections' : {},
|
||||||
|
|
||||||
|
'turnToFunctions' : {},
|
||||||
|
|
||||||
|
'addSection' : function(nr, element) {
|
||||||
|
var section = {'element' : element, 'nr' : nr};
|
||||||
|
this.sections[nr] = section;
|
||||||
|
},
|
||||||
|
|
||||||
|
'turnTo' : function(nr) {
|
||||||
|
if (!gamebook.player.started) {
|
||||||
|
gamebook.start();
|
||||||
|
}
|
||||||
|
if (!nr in this.sections) {
|
||||||
|
throw new Exception("Can not turn to non-existing section "
|
||||||
|
+ nr + ".");
|
||||||
|
}
|
||||||
|
this.displaySection(nr);
|
||||||
|
},
|
||||||
|
|
||||||
|
'start' : function() {
|
||||||
|
this.hideIntroSections();
|
||||||
|
this.addClassToClass('startlink', 'nodisplay');
|
||||||
|
this.addClassToClass('resumelink', 'nodisplay');
|
||||||
|
gamebook.player.started = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
'displaySection' : function(nr) {
|
||||||
|
if (this.player.currentSection > 0) {
|
||||||
|
var section = this.sections[this.player.currentSection];
|
||||||
|
section.element.style.display = 'none';
|
||||||
|
}
|
||||||
|
var e = this.sections[nr].element;
|
||||||
|
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
||||||
|
e.style.display = 'block';
|
||||||
|
this.player.currentSection = nr;
|
||||||
|
this.saveGame();
|
||||||
|
},
|
||||||
|
|
||||||
|
//FIXME move out from gamebook object
|
||||||
|
'saveGame' : function() {
|
||||||
|
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
||||||
|
window.localStorage.setItem('savedGamebookPlayer',
|
||||||
|
this.player.getState());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
//FIXME move out from gamebook object
|
||||||
|
'hasSavedGame' : function() {
|
||||||
|
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
||||||
|
return window.localStorage.getItem('savedGamebookPlayer');
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
//FIXME move out from gamebook object
|
||||||
|
'loadGame' : function() {
|
||||||
|
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
||||||
|
var state = window.localStorage.getItem('savedGamebookPlayer');
|
||||||
|
this.player.setState(state);
|
||||||
|
this.turnTo(this.player.currentSection);
|
||||||
|
this.updateCollectionsView();
|
||||||
|
} else {
|
||||||
|
//FIXME some kind of error, because we should never get here
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'hideIntroSections' : function() {
|
||||||
|
this.addClassToClass('introsection', 'nodisplay');
|
||||||
|
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
||||||
|
this.addClassToClass('hideintrolink', 'nodisplay');
|
||||||
|
},
|
||||||
|
|
||||||
|
'showIntroSections' : function() {
|
||||||
|
this.runActionsInIntroSections();
|
||||||
|
this.removeClassFromClass('introsection', 'nodisplay');
|
||||||
|
this.addClassToClass('displayintrolink', 'nodisplay');
|
||||||
|
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
||||||
|
document.body.scrollIntoView();
|
||||||
|
},
|
||||||
|
|
||||||
|
'runActionsInIntroSections' : function() {
|
||||||
|
Array.prototype.forEach.call(
|
||||||
|
document.getElementsByClassName('introsectionbody'),
|
||||||
|
gamebook.runActions);
|
||||||
|
},
|
||||||
|
|
||||||
|
'addClassToClass' : function(className, addClass) {
|
||||||
|
Array.prototype.forEach.call(
|
||||||
|
document.getElementsByClassName(className),
|
||||||
|
function(e) {
|
||||||
|
e.classList.add(addClass);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'removeClassFromClass' : function(className, removeClass) {
|
||||||
|
Array.prototype.forEach.call(
|
||||||
|
document.getElementsByClassName(className),
|
||||||
|
function(e) {
|
||||||
|
e.classList.remove(removeClass);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'runActions' : function(e) {
|
||||||
|
var enableNextLink = true;
|
||||||
|
var hasXorScope = false;
|
||||||
|
var hasAutoScope = false;
|
||||||
|
var xorEnableNext = false;
|
||||||
|
var autoDisableAllRemainingLinks = (
|
||||||
|
gamebook.player.started && e.classList.contains('introsectionbody'));
|
||||||
|
Array.prototype.forEach.call(e.childNodes, function(c) {
|
||||||
|
if (!c.classList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c.classList.contains('sectionref')) {
|
||||||
|
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
||||||
|
gamebook.enableLink(c);
|
||||||
|
if (hasAutoScope) {
|
||||||
|
autoDisableAllRemainingLinks = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gamebook.disableLink(c);
|
||||||
|
}
|
||||||
|
enableNextLink = !(hasXorScope && !xorEnableNext);
|
||||||
|
hasAutoScope = false;
|
||||||
|
hasXorScope = false;
|
||||||
|
} else if (c.classList.contains('collect')) {
|
||||||
|
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
||||||
|
} else if (c.classList.contains('add')) {
|
||||||
|
gamebook.player.add(c.dataset.type, c.dataset.what);
|
||||||
|
} else if (c.classList.contains('drop')) {
|
||||||
|
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
||||||
|
} else if (c.classList.contains('has')) {
|
||||||
|
enableNextLink = gamebook.player.has(c.dataset.type,
|
||||||
|
c.dataset.what);
|
||||||
|
} else if (c.classList.contains('hasnot')) {
|
||||||
|
enableNextLink = !gamebook.player.has(c.dataset.type,
|
||||||
|
c.dataset.what);
|
||||||
|
} else if (c.classList.contains('xor')) {
|
||||||
|
hasXorScope = true;
|
||||||
|
xorEnableNext = !enableNextLink;
|
||||||
|
} else if (c.classList.contains('auto')) {
|
||||||
|
hasAutoScope = true;
|
||||||
|
} else if (c.classList.contains('random')) {
|
||||||
|
c.addEventListener('click',
|
||||||
|
gamebook.enableRandomLinkAfter);
|
||||||
|
c.classList.add("enabledlink");
|
||||||
|
c.classList.remove("disabledlink");
|
||||||
|
autoDisableAllRemainingLinks = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'enableLink' : function(e) {
|
||||||
|
e.addEventListener('click',
|
||||||
|
gamebook.getTurnToFunction(e.dataset.ref));
|
||||||
|
e.classList.add("enabledlink");
|
||||||
|
e.classList.remove("disabledlink");
|
||||||
|
},
|
||||||
|
|
||||||
|
'disableLink' : function(e) {
|
||||||
|
e.removeEventListener('click',
|
||||||
|
gamebook.getTurnToFunction(e.dataset.ref));
|
||||||
|
e.classList.remove("enabledlink");
|
||||||
|
e.classList.add("disabledlink");
|
||||||
|
},
|
||||||
|
|
||||||
|
'enableRandomLinkAfter' : function(event) {
|
||||||
|
this.classList.remove("enabledlink");
|
||||||
|
this.classList.add("disabledlink");
|
||||||
|
var links = [];
|
||||||
|
var e = this.nextSibling;
|
||||||
|
while (e) {
|
||||||
|
if (e.classList && e.classList.contains('sectionref')) {
|
||||||
|
links.push(e);
|
||||||
|
}
|
||||||
|
e = e.nextSibling;
|
||||||
|
}
|
||||||
|
if (links.length > 0) {
|
||||||
|
var selected = links[Math.floor(Math.random()*links.length)]
|
||||||
|
gamebook.enableLink(selected);
|
||||||
|
} else {
|
||||||
|
console.log("Random with nothing to select?");
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
|
||||||
|
'addCollectionView' : function(type, name) {
|
||||||
|
var ce = document.getElementById('collections');
|
||||||
|
var template = document.getElementById('collectionTemplate');
|
||||||
|
var e = template.cloneNode(true);
|
||||||
|
e.className = "collection";
|
||||||
|
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
||||||
|
e.dataset.type = type;
|
||||||
|
ce.appendChild(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
'updateCollectionsView' : function() {
|
||||||
|
var ce = document.getElementById('collections');
|
||||||
|
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
||||||
|
if (c.className === 'collection') {
|
||||||
|
var type = c.dataset.type;
|
||||||
|
var collection = gamebook.player.collections[type];
|
||||||
|
var cc = c.getElementsByClassName('collectioncontents')[0];
|
||||||
|
cc.innerHTML = collection.contents.join(', ');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'getTurnToFunction' : function(nr) {
|
||||||
|
if (nr in this.turnToFunctions) {
|
||||||
|
return this.turnToFunctions[nr];
|
||||||
|
} else {
|
||||||
|
var f = function () {
|
||||||
|
gamebook.turnTo(nr);
|
||||||
|
};
|
||||||
|
this.turnToFunctions[nr] = f;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// little hack to make easy to test from node.js
|
||||||
|
if (typeof exports !== 'undefined') {
|
||||||
|
exports.gamebook = gamebook;
|
||||||
|
}
|
|
@ -3,15 +3,14 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
#include "viewport"
|
#include "viewport"
|
||||||
<title>%(title)s</title>
|
<title>%(title)s</title>
|
||||||
|
<script type="text/javascript" src="gamebookformatplay.js"></script>
|
||||||
|
<link rel="stylesheet" href="gamebookformat.css"
|
||||||
|
type="text/css" />
|
||||||
<script>
|
<script>
|
||||||
#include "script"
|
gamebook.id = '%(id)s';
|
||||||
#include "override-script"
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
#include "head-overrides"
|
||||||
#include "style"
|
|
||||||
#include "override-style"
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
#include "hideintro"
|
#include "hideintro"
|
||||||
|
|
|
@ -1,233 +0,0 @@
|
||||||
'id' : '%(id)s',
|
|
||||||
|
|
||||||
'player' : {
|
|
||||||
#include "playerscript"
|
|
||||||
#include "extra-playerscript"
|
|
||||||
},
|
|
||||||
|
|
||||||
'sections' : {},
|
|
||||||
|
|
||||||
'turnToFunctions' : {},
|
|
||||||
|
|
||||||
'addSection' : function(nr, element) {
|
|
||||||
var section = {'element' : element, 'nr' : nr};
|
|
||||||
this.sections[nr] = section;
|
|
||||||
},
|
|
||||||
|
|
||||||
'turnTo' : function(nr) {
|
|
||||||
if (!gamebook.player.started) {
|
|
||||||
gamebook.start();
|
|
||||||
}
|
|
||||||
if (!nr in this.sections) {
|
|
||||||
throw new Exception("Can not turn to non-existing section "
|
|
||||||
+ nr + ".");
|
|
||||||
}
|
|
||||||
this.displaySection(nr);
|
|
||||||
},
|
|
||||||
|
|
||||||
'start' : function() {
|
|
||||||
this.hideIntroSections();
|
|
||||||
this.addClassToClass('startlink', 'nodisplay');
|
|
||||||
this.addClassToClass('resumelink', 'nodisplay');
|
|
||||||
gamebook.player.started = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
'displaySection' : function(nr) {
|
|
||||||
if (this.player.currentSection > 0) {
|
|
||||||
var section = this.sections[this.player.currentSection];
|
|
||||||
section.element.style.display = 'none';
|
|
||||||
}
|
|
||||||
var e = this.sections[nr].element;
|
|
||||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
|
||||||
e.style.display = 'block';
|
|
||||||
this.player.currentSection = nr;
|
|
||||||
this.saveGame();
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'saveGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
window.localStorage.setItem(this.getSavedGameName(),
|
|
||||||
this.player.getState());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'hasSavedGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
return window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//FIXME move out from gamebook object
|
|
||||||
'loadGame' : function() {
|
|
||||||
if (typeof window !== 'undefined' && 'localStorage' in window) {
|
|
||||||
var state = window.localStorage.getItem(this.getSavedGameName());
|
|
||||||
this.player.setState(state);
|
|
||||||
this.turnTo(this.player.currentSection);
|
|
||||||
this.updateCollectionsView();
|
|
||||||
} else {
|
|
||||||
//FIXME some kind of error, because we should never get here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'getSavedGameName' : function() {
|
|
||||||
return 'savedGamebookPlayer-' + this.id;
|
|
||||||
},
|
|
||||||
|
|
||||||
'hideIntroSections' : function() {
|
|
||||||
this.addClassToClass('introsection', 'nodisplay');
|
|
||||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
|
||||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
|
||||||
},
|
|
||||||
|
|
||||||
'showIntroSections' : function() {
|
|
||||||
this.runActionsInIntroSections();
|
|
||||||
this.removeClassFromClass('introsection', 'nodisplay');
|
|
||||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
|
||||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
|
||||||
document.body.scrollIntoView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActionsInIntroSections' : function() {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName('introsectionbody'),
|
|
||||||
gamebook.runActions);
|
|
||||||
},
|
|
||||||
|
|
||||||
'addClassToClass' : function(className, addClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.add(addClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'removeClassFromClass' : function(className, removeClass) {
|
|
||||||
Array.prototype.forEach.call(
|
|
||||||
document.getElementsByClassName(className),
|
|
||||||
function(e) {
|
|
||||||
e.classList.remove(removeClass);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'runActions' : function(e) {
|
|
||||||
var enableNextLink = true;
|
|
||||||
var hasXorScope = false;
|
|
||||||
var hasAutoScope = false;
|
|
||||||
var xorEnableNext = false;
|
|
||||||
var autoDisableAllRemainingLinks = (
|
|
||||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
|
||||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
|
||||||
if (!c.classList) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c.classList.contains('sectionref')) {
|
|
||||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
|
||||||
gamebook.enableLink(c);
|
|
||||||
if (hasAutoScope) {
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gamebook.disableLink(c);
|
|
||||||
}
|
|
||||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
|
||||||
hasAutoScope = false;
|
|
||||||
hasXorScope = false;
|
|
||||||
} else if (c.classList.contains('collect')) {
|
|
||||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
|
||||||
} else if (c.classList.contains('add')) {
|
|
||||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('drop')) {
|
|
||||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
|
||||||
} else if (c.classList.contains('has')) {
|
|
||||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('hasnot')) {
|
|
||||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
|
||||||
c.dataset.what);
|
|
||||||
} else if (c.classList.contains('xor')) {
|
|
||||||
hasXorScope = true;
|
|
||||||
xorEnableNext = !enableNextLink;
|
|
||||||
} else if (c.classList.contains('auto')) {
|
|
||||||
hasAutoScope = true;
|
|
||||||
} else if (c.classList.contains('random')) {
|
|
||||||
c.addEventListener('click',
|
|
||||||
gamebook.enableRandomLinkAfter);
|
|
||||||
c.classList.add("enabledlink");
|
|
||||||
c.classList.remove("disabledlink");
|
|
||||||
autoDisableAllRemainingLinks = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableLink' : function(e) {
|
|
||||||
e.addEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.add("enabledlink");
|
|
||||||
e.classList.remove("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'disableLink' : function(e) {
|
|
||||||
e.removeEventListener('click',
|
|
||||||
gamebook.getTurnToFunction(e.dataset.ref));
|
|
||||||
e.classList.remove("enabledlink");
|
|
||||||
e.classList.add("disabledlink");
|
|
||||||
},
|
|
||||||
|
|
||||||
'enableRandomLinkAfter' : function(event) {
|
|
||||||
this.classList.remove("enabledlink");
|
|
||||||
this.classList.add("disabledlink");
|
|
||||||
var links = [];
|
|
||||||
var e = this.nextSibling;
|
|
||||||
while (e) {
|
|
||||||
if (e.classList && e.classList.contains('sectionref')) {
|
|
||||||
links.push(e);
|
|
||||||
}
|
|
||||||
e = e.nextSibling;
|
|
||||||
}
|
|
||||||
if (links.length > 0) {
|
|
||||||
var selected = links[Math.floor(Math.random()*links.length)]
|
|
||||||
gamebook.enableLink(selected);
|
|
||||||
} else {
|
|
||||||
console.log("Random with nothing to select?");
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
'addCollectionView' : function(type, name) {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
var template = document.getElementById('collectionTemplate');
|
|
||||||
var e = template.cloneNode(true);
|
|
||||||
e.className = "collection";
|
|
||||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
|
||||||
e.dataset.type = type;
|
|
||||||
ce.appendChild(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
'updateCollectionsView' : function() {
|
|
||||||
var ce = document.getElementById('collections');
|
|
||||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
|
||||||
if (c.className === 'collection') {
|
|
||||||
var type = c.dataset.type;
|
|
||||||
var collection = gamebook.player.collections[type];
|
|
||||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
|
||||||
cc.innerHTML = collection.contents.join(', ');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'getTurnToFunction' : function(nr) {
|
|
||||||
if (nr in this.turnToFunctions) {
|
|
||||||
return this.turnToFunctions[nr];
|
|
||||||
} else {
|
|
||||||
var f = function () {
|
|
||||||
gamebook.turnTo(nr);
|
|
||||||
};
|
|
||||||
this.turnToFunctions[nr] = f;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
'started' : false,
|
|
||||||
'currentSection' : -1,
|
|
||||||
'collections' : {},
|
|
||||||
|
|
||||||
'collect' : function(type, name) {
|
|
||||||
if (type in this.collections) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.collections[type] = {
|
|
||||||
'name' : name,
|
|
||||||
'contents' : [],
|
|
||||||
'dropped' : {},
|
|
||||||
'add' : function(what) {
|
|
||||||
if (this.contents.indexOf(what) === -1
|
|
||||||
&& !(what in this.dropped)) {
|
|
||||||
this.contents.push(what);
|
|
||||||
this.contents.sort();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'drop' : function(what) {
|
|
||||||
var i = this.contents.indexOf(what);
|
|
||||||
if (i >= 0) {
|
|
||||||
this.contents.splice(i, 1);
|
|
||||||
this.dropped[what] = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'has' : function(what) {
|
|
||||||
return this.contents.indexOf(what) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
gamebook.addCollectionView(type, name);
|
|
||||||
},
|
|
||||||
|
|
||||||
'add' : function(type, what) {
|
|
||||||
this.collections[type].add(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'drop' : function(type, what) {
|
|
||||||
this.collections[type].drop(what);
|
|
||||||
gamebook.updateCollectionsView();
|
|
||||||
},
|
|
||||||
|
|
||||||
'has' : function(type, what) {
|
|
||||||
return this.collections[type].has(what);
|
|
||||||
},
|
|
||||||
|
|
||||||
'getState' : function() {
|
|
||||||
return JSON.stringify({
|
|
||||||
'collections' : this.collections,
|
|
||||||
'currentSection' : this.currentSection
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
'setState' : function(state) {
|
|
||||||
var parsedState = JSON.parse(state);
|
|
||||||
this.currentSection = parsedState.currentSection;
|
|
||||||
for (var c in parsedState.collections) {
|
|
||||||
var collection = parsedState.collections[c];
|
|
||||||
if (!(c in this.collections)) {
|
|
||||||
this.collect(c, collection.name);
|
|
||||||
} else {
|
|
||||||
this.collections[c].name = collection.name;
|
|
||||||
}
|
|
||||||
this.collections[c].contents = collection.contents;
|
|
||||||
this.collections[c].dropped = collection.dropped;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
var gamebook = {
|
|
||||||
#include "gamebookscript"
|
|
||||||
#include "extra-gamebookscript"
|
|
||||||
};
|
|
||||||
|
|
||||||
// little hack to make easy to test from node.js
|
|
||||||
if (typeof exports !== 'undefined') {
|
|
||||||
exports.gamebook = gamebook;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random,
|
|
||||||
.resumelink{
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0.2em;
|
|
||||||
vertical-align: middle;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionref.enabledlink {
|
|
||||||
padding-left: 1.5em;
|
|
||||||
padding-right: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random,
|
|
||||||
.resumelink {cursor: pointer;}
|
|
||||||
|
|
||||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
|
||||||
.random,.resumelink {background: #eef;
|
|
||||||
}
|
|
||||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
|
||||||
.hideintrolink:hover,.resumelink:hover {background: #a9f;}
|
|
||||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
|
||||||
.disabledlink:hover {background: inherit;}
|
|
||||||
.sectionnumber,.introsectionheading {font-weight: bolder;
|
|
||||||
width: 100%%;
|
|
||||||
text-align: center;}
|
|
||||||
.section {display: none; width: 90%%; margin-left: 5%%; margin-right: 5%%;}
|
|
||||||
.sectiontext {margin-top: 0.5em;}
|
|
||||||
.gamebook {max-width: 30em; padding: 1em; width: 100%%; font-size: 133%%;}
|
|
||||||
.collections {margin-top: 4em;}
|
|
||||||
.collection {background: #ddd; margin-top: 1em;}
|
|
||||||
.collectionheading {}
|
|
||||||
.collectionheading::after {content: ": ";}
|
|
||||||
.collectioncontents {}
|
|
||||||
.collect {}
|
|
||||||
.add {font-weight: bold;}
|
|
||||||
.drop {font-style: italic;}
|
|
||||||
.has {font-style: italic;}
|
|
||||||
.hasnot {font-style: italic;}
|
|
||||||
.collectionTemplate {display: none;}
|
|
||||||
.sectionimage {width: 100%%; padding: 1em;}
|
|
||||||
.nodisplay {display: none;}
|
|
||||||
.resumenr {font-weight: bold;}
|
|
Loading…
Reference in a new issue