-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathknowl.js
More file actions
255 lines (229 loc) · 9.46 KB
/
knowl.js
File metadata and controls
255 lines (229 loc) · 9.46 KB
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*
* Knowl - Feature Demo for Knowls
* Copyright (C) 2011 Harald Schilly
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* 4/11/2012 Modified by David Guichard to allow inline knowl code.
* Sample use:
* This is an <a knowl="" class="internal"
* value="Hello World!">inline knowl.</a>
*/
/* 8/14/14 Modified by David Farmer to allow knowl content to be
* taken from the element with a given id.
*
* The syntax is <a knowl="" class="id-ref" refid="proofSS">Proof</a>
*/
/* javascript code for the knowl features
* global counter, used to uniquely identify each knowl-output element
* that's necessary because the same knowl could be referenced several times
* on the same page */
var knowl_id_counter = 0;
var knowl_focus_stack_uid = [];
var knowl_focus_stack = [];
function knowl_click_handler($el) {
// the knowl attribute holds the id of the knowl
var knowl_id = $el.attr("knowl");
// the uid is necessary if we want to reference the same content several times
var uid = $el.attr("knowl-uid");
var output_id = '#knowl-output-' + uid;
var $output_id = $(output_id);
// create the element for the content, insert it after the one where the
// knowl element is included (e.g. inside a <h1> tag) (sibling in DOM)
var idtag = "id='"+output_id.substring(1) + "'";
var kid = "id='kuid-"+ uid + "'";
// if we already have the content, toggle visibility
// Note that for tracking knowls, this setup is not optimal
// because it applies to open knowls and also knowls which
// were opened and then closed.
if ($output_id.length > 0) {
thisknowlid = "kuid-"+uid
// when this is an entry in a table, then it is the parents parent we need to toggle
// also need to clean this up
if($("#kuid-"+uid).parent().is("td.knowl-td")) {
$("#kuid-"+uid).parent().parent().slideToggle("fast");
}
else {
$("#kuid-"+uid).slideToggle("fast");
}
if($el.attr("replace")) {
$($el.attr("replace")).slideToggle("fast");
}
this_knowl_focus_stack_uidindex = knowl_focus_stack_uid.indexOf(uid);
if($el.hasClass("active")) {
if(this_knowl_focus_stack_uidindex != -1) {
knowl_focus_stack_uid.splice(this_knowl_focus_stack_uidindex, 1);
knowl_focus_stack.splice(this_knowl_focus_stack_uidindex, 1);
}
}
else {
knowl_focus_stack_uid.push(uid);
knowl_focus_stack.push($el);
document.getElementById(thisknowlid).focus();
}
$el.toggleClass("active");
// otherwise download it or get it from the cache
} else {
// where_it_goes is the location the knowl will appear *after*
// knowl is the variable that will hold the content of the output knowl
var where_it_goes = $el;
var knowl = "<div class='knowl-output' "+kid+"><div class='knowl'><div class='knowl-content' " +idtag+ ">loading '"+knowl_id+"'</div><div class='knowl-footer'>"+knowl_id+"</div></div></div>";
// addafter="#id" means to put the knowl after the element with that id
if($el.attr("addafter")) {
where_it_goes = $($el.attr("addafter"));
} else if($el.attr("replace")) {
where_it_goes = $($el.attr("replace"));
} else if($el.hasClass("kohere")) {
where_it_goes = $el;
} else {
// otherwise, typically put it after the nearest enclosing block element
// check, if the knowl is inside a td or th in a table
if($el.parent().is("td") || $el.parent().is("th") ) {
// assume we are in a td or th tag, go 2 levels up
where_it_goes = $el.parent().parent();
var cols = $el.parent().parent().children().length;
knowl = "<tr><td colspan='"+cols+"' class='knowl-td'>"+knowl+"</td></tr>";
} else if ($el.parent().is("li")) {
where_it_goes = $el.parent();
}
// not sure it is is worth making the following more elegant
else if ($el.parent().parent().is("li")) {
where_it_goes = $el.parent().parent();
// the '.is("p")' is for the first paragraph of a theorem or proof
} else if ($el.parent().css('display') == "block" || $el.parent().is("p") || $el.parent().hasClass("hidden-knowl-wrapper") || $el.parent().hasClass("kohere")) {
where_it_goes = $el.parent();
} else if ($el.parent().parent().css('display') == "block" || $el.parent().parent().is("p") || $el.parent().parent().hasClass("hidden-knowl-wrapper") || $el.parent().parent().hasClass("kohere")) {
where_it_goes = $el.parent().parent();
} else {
// is this a reasonable last case?
// if we omit the else, then if goes after $el
where_it_goes = $el.parent().parent().parent();
}
}
// now that we know where the knowl goes, insert the knowl content
if($el.attr("replace")) {
where_it_goes.before(knowl);
}
else {
where_it_goes.after(knowl);
}
// "select" where the output is and get a hold of it
var $output = $(output_id);
var $knowl = $("#kuid-"+uid);
$output.addClass("loading");
$knowl.hide();
// DRG: inline code
if ($el.hasClass('internal')) {
$output.html($el.attr("value"));
// } else if ($el.attr("class") == 'id-ref') {
} else if ($el.hasClass('id-ref')) {
//get content from element with the given id
$output.html($("#".concat($el.attr("refid"))).html());
} else {
// Get code from server.
$output.load(knowl_id,
function(response, status, xhr) {
$knowl.removeClass("loading");
if (status == "error") {
$el.removeClass("active");
$output.html("<div class='knowl-output error'>ERROR: " + xhr.status + " " + xhr.statusText + '</div>');
$output.show();
} else if (status == "timeout") {
$el.removeClass("active");
$output.html("<div class='knowl-output error'>ERROR: timeout. " + xhr.status + " " + xhr.statusText + '</div>');
$output.show();
}
else {
// this is sloppy, because this is called again later.
MathJax.Hub.Queue(['Typeset', MathJax.Hub, $output.get(0)]);
// not sure of the use case for this:
$(".knowl-output .hidden-sagecell-sage").attr("class", "sagecell-sage");
sagecell.makeSagecell({inputLocation: ".sagecell-sage"});
}
});
};
// we have the knowl content, and put it hidden in the right place,
// so now we show it
$knowl.hide();
$el.addClass("active");
// if we are using MathJax, then we reveal the knowl after it has finished rendering the contents
if(window.MathJax == undefined) {
$knowl.slideDown("slow");
} else {
$knowl.addClass("processing");
// $(".knowl-output .hidden-sagecell-sage").attr("class", "sagecell-sage");
// sagecell.makeSagecell({inputLocation: ".sagecell-sage"});
MathJax.Hub.Queue(['Typeset', MathJax.Hub, $output.get(0)]);
MathJax.Hub.Queue([ function() {
$knowl.removeClass("processing");
$knowl.slideDown("slow");
// if replacing, then need to hide what was there
// (and also do some other things so that toggling works -- not implemented yet)
if($el.attr("replace")) {
var the_replaced_thing = $($el.attr("replace"));
the_replaced_thing.hide("slow");
}
var thisknowlid = 'kuid-'.concat(uid)
document.getElementById(thisknowlid).tabIndex=0;
document.getElementById(thisknowlid).focus();
knowl_focus_stack_uid.push(uid);
knowl_focus_stack.push($el);
$("a[knowl]").attr("href", "");
}]);
// if this is before th MathJaxm big problems
$(".knowl-output .hidden-sagecell-sage").attr("class", "sagecell-sage");
sagecell.makeSagecell({inputLocation: ".sagecell-sage"});
}
}
} //~~ end click handler for *[knowl] elements
/** register a click handler for each element with the knowl attribute
* @see jquery's doc about 'live'! the handler function does the
* download/show/hide magic. also add a unique ID,
* necessary when the same reference is used several times. */
$(function() {
$("body").on("click", "*[knowl]", function(evt) {
evt.preventDefault();
var $knowl = $(this);
if(!$knowl.attr("knowl-uid")) {
$knowl.attr("knowl-uid", knowl_id_counter);
knowl_id_counter++;
}
knowl_click_handler($knowl, evt);
});
});
$(window).load(function() {
$("a[knowl]").attr("href", "");
});
//window.onload = function() {
/*
window.addEventListener("load",function(event) {
document.onkeyup = function(event)
{
var e = (!event) ? window.event : event;
switch(e.keyCode)
{
case 27: //esc
if(knowl_focus_stack.length > 0 ) {
most_recently_opened = knowl_focus_stack.pop();
knowl_focus_stack_uid.pop();
most_recently_opened.focus();
} else {
console.log("no open knowls being tracked");
break;
}
};
};
},
false);
*/