-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpassage.js
176 lines (154 loc) · 4.3 KB
/
passage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//
// Class: Passage
//
// This class represents an individual passage.
// This is analogous to the Tiddler class in the core TiddlyWiki code.
//
// Property: title
// The title of the passage, displayed at its top.
//
// Property: id
// An internal id of the passage. This is never seen by the reader,
// but it is used by the <History> class.
//
// Property: initialText
// The initial text of the passage. This is used by the reset method.
//
// Property: text
// The current text of the passage. This is usually the same as
// the <initialText> property, though macros such as <<choice>>
// may alter it.
//
// Property: tags
// An array of strings, each corresponding to a tag the passage belongs to.
//
//
// Constructor: Passage
//
// Initializes a new Passage object. You may either call this with
// a DOM element, which creates the passage from the text stored in the
// element, or you may pass only a title,
//
// Parameters:
// title - the title of the passage to create. This parameter is required.
// el - the DOM element storing the content of the passage.
// This parameter is optional. If it is omitted, "this passage does not
// exist" is used as the passage's content.
// order - the order in which this passage was retrieved from the
// document's *storeArea* div. This is used to generate the passage's id.
// This parameter is optional, but should be included if el is specified.
//
function Passage (title, el, order)
{
this.title = title;
if (el)
{
this.id = order;
this.initialText = this.text = Passage.unescapeLineBreaks(el.firstChild ? el.firstChild.nodeValue : "");
this.tags = el.getAttribute("tags");
if (typeof this.tags == 'string')
this.tags = this.tags.readBracketedList();
else
this.tags = [];
}
else
{
this.initialText = this.text = '@@This passage does not exist.@@';
this.tags = [];
};
};
//
// Method: render
//
// Renders the passage to a DOM element, including its title, toolbar,
// and content. It's up to the caller to add this to the DOM tree appropriately
// and animate its appearance.
//
// Parameters:
// none
//
// Returns:
// nothing
//
Passage.prototype.render = function()
{
// construct passage
var passage = insertElement(null, 'div', 'passage' + this.title.split(' ').join('_'), 'passage');
passage.style.visibility = 'hidden';
var title = insertElement(passage, 'span', '', 'title', this.title);
var toolbar = insertElement(passage, 'span', '', 'toolbar');
for (var i = 0; i < Passage.toolbarItems.length; i++)
{
var link = insertElement(toolbar, 'a');
insertText(link, Passage.toolbarItems[i].label(passage));
link.passage = this;
if (Passage.toolbarItems[i].href)
link.href = Passage.toolbarItems[i].href(passage)
else
link.href = 'javascript:void(0)';
link.title = Passage.toolbarItems[i].tooltip(passage);
link.onclick = Passage.toolbarItems[i].activate;
};
var body = insertElement(passage, 'div', '', 'body');
new Wikifier(body, this.text);
// event handlers
passage.onmouseover = function() { passage.className += ' selected' };
passage.onmouseout = function() { passage.className = passage.className.replace(' selected', ''); };
return passage;
};
//
// Method: reset
//
// Resets the passage's <text> property to its <initialText> property.
// This does not directly affect anything displayed on the page.
//
// Parameters:
// none
//
// Returns:
// nothing
//
Passage.prototype.reset = function()
{
console.log('resetting "' + this.title + '"');
this.text = this.initialText;
};
Passage.toolbarItems =
[
{
label: function() { return 'bookmark' },
tooltip: function() { return 'Bookmark this point in the story' },
href: function(passage)
{
return(state.save(passage));
},
activate: function() {}
},
{
label: function() { return 'rewind to here' },
tooltip: function() { 'Rewind the story to here' },
activate: function()
{
state.rewindTo(this.passage);
}
}
];
//
// Method: unescapeLineBreaks
//
// A static function used by the constructor to convert string literals
// used by TiddlyWiki to indicate newlines into actual newlines.
//
// Parameters:
// text - a string to unescape
//
// Returns:
// a converted string
//
Passage.unescapeLineBreaks = function (text)
{
if(text && text != "")
return text.replace(/\\n/mg,"\n").replace(/\\/mg,"\\").replace(/\r/mg,"");
else
return "";
};