Introduction
Introduction Statistics Contact Development Disclaimer Help
script.js - jscancer - Javascript crap (relatively small)
git clone git://git.codemadness.org/jscancer
Log
Files
Refs
README
LICENSE
---
script.js (17957B)
---
1 // run atleast once, then every n milliseconds.
2 // if n is 0 just run once.
3 function updateevery(n, fn) {
4 // schedule in parallel now.
5 setTimeout(function() {
6 fn();
7 }, 0);
8 if (!n)
9 return null;
10 return setInterval(fn, n);
11 }
12
13 function pad0(n) {
14 return (parseInt(n) < 10 ? "0" : "") + n.toString();
15 }
16
17 function padspace(n) {
18 return (parseInt(n) < 10 ? " " : "") + n.toString();
19 }
20
21 // dutch weekdays and months.
22 //var strftime_weekdays = [ "Zondag", "Maandag", "Dinsdag", "Woensdag", …
23 //var strftime_months = [ "Januari", "Februari", "Maart", "April", "Mei…
24
25 // subset of strftime()
26 function strftime(fmt, d) {
27 //var locale = locale || navigator.language || "en";
28 //var locale = "nl-NL"; // dutch
29 var locale = "en-US"; // english US
30 d = d || new Date();
31
32 var mon = d.getMonth(); // starts at 0
33 var day = d.getDay(); // weekday, starts at 0 (sunday).
34
35 var s = fmt;
36 s = s.replace(/%Y/g, d.getFullYear().toString());
37 s = s.replace(/%m/g, pad0(mon + 1));
38 s = s.replace(/%d/g, pad0(d.getDate()));
39 s = s.replace(/%e/g, padspace(d.getDate()));
40 s = s.replace(/%H/g, pad0(d.getHours()));
41 s = s.replace(/%M/g, pad0(d.getMinutes()));
42 s = s.replace(/%S/g, pad0(d.getSeconds()));
43
44 s = s.replace(/%A/g, (new Intl.DateTimeFormat(locale, { weekday:…
45 s = s.replace(/%a/g, (new Intl.DateTimeFormat(locale, { weekday:…
46 s = s.replace(/%B/g, (new Intl.DateTimeFormat(locale, { month: "…
47 s = s.replace(/%b/g, (new Intl.DateTimeFormat(locale, { month: "…
48
49 //s = s.replace(/%A/g, strftime_weekdays[day]); // full weekday …
50 //s = s.replace(/%a/g, strftime_weekdays[day].substring(0, 3)); …
51 //s = s.replace(/%B/g, strftime_months[mon]); // full month name
52 //s = s.replace(/%b/g, strftime_months[mon].substring(0, 3)); //…
53
54 return s;
55 }
56
57 // XMLHttpRequest helper function.
58 function xhr(url, fn, timeout) {
59 var x = new(XMLHttpRequest);
60 x.open("get", url, true); // async
61 x.setRequestHeader("X-Requested-With", "XMLHttpRequest");
62 x.timeout = parseInt(timeout || 10000); // default: 10 seconds
63 x.onreadystatechange = function () {
64 if (x.readyState != 4)
65 return;
66 fn(x);
67 };
68 var data = "";
69 x.send(data);
70 }
71
72 // find direct descendent child element with a certain classname.
73 function getdirectchilds(parent, classname) {
74 var els = [];
75
76 for (var i = 0; i < parent.children.length; i++) {
77 var el = parent.children[i];
78 if (el.classList.contains(classname))
79 els.push(el);
80 }
81
82 return els;
83 }
84
85 // news tickers.
86 var tickerels = document.getElementsByClassName("news-ticker");
87 var tickers = [];
88 for (var i = 0; i < tickerels.length; i++) {
89 var url = tickerels[i].getAttribute("data-url") || "";
90 if (url == "")
91 continue;
92
93 // bind element to context
94 var t = (function(tickerel, delay) {
95 var displayfn = function(ticker) {
96 var parent = ticker.el;
97 var items = ticker.items || [];
98 var counter = ticker.counter || 0;
99
100 var node = document.createElement("div");
101 node.innerText = items[counter] || "";
102 parent.appendChild(node); // add new.
103 counter = (counter + 1) % items.length;
104
105 ticker.counter = counter; // update counter
106
107 if (parent.children.length) {
108 // schedule to be removed.
109 setTimeout(function() {
110 if (parent.children.length)
111 parent.children[0].class…
112 setTimeout(function() {
113 if (parent.children.leng…
114 parent.removeChi…
115 }, ticker.fadein);
116 }, ticker.display);
117 }
118 };
119
120 var processfn = function(x) {
121 var feed = JSON.parse(x.responseText || "");
122 var items = [];
123 var feeditems = feed.items || [];
124
125 for (var j = 0; j < feeditems.length; j++) {
126 var title = feeditems[j].title;
127 var ts = feeditems[j].date_published || …
128 // if there is a timestamp prefix it in …
129 if (ts.length) {
130 var d = new Date(Date.parse(ts));
131 title = strftime("%H:%M", d) + "…
132 }
133 items.push(title);
134 }
135 ticker.items = items;
136 };
137
138 // ticker config / context.
139 var ticker = {
140 el: tickerel,
141 url: (tickerel.getAttribute("data-url") || ""),
142 display: parseInt(tickerel.getAttribute("data-di…
143 fadein: parseInt(tickerel.getAttribute("data-fad…
144 update: parseInt(tickerel.getAttribute("data-upd…
145 };
146
147 ticker.processfn = processfn;
148 ticker.displayfn = displayfn;
149
150 // reload RSS/Atom data.
151 var updater = function() {
152 xhr(ticker.url, function(x) {
153 ticker.processfn(x);
154
155 // reset and stop previous timer for cyc…
156 if (ticker.displaytimer)
157 clearInterval(ticker.displaytime…
158
159 ticker.counter = 0; // reset item counter
160 ticker.el.innerHTML = ""; // clear conte…
161 ticker.displayfn(ticker); // immediately…
162
163 // display / cycle existing items.
164 ticker.displaytimer = setInterval(functi…
165 });
166 };
167
168 ticker.updater = updater;
169 ticker.updatetimer = setInterval(updater, ticker.update)…
170 setTimeout(updater, delay); // small delay so the newsti…
171
172 return ticker;
173 })(tickerels[i], 1000 * i);
174
175 tickers.push(t);
176 }
177
178 // elements showing simple HTML content in a placeholder, refresh using …
179 var xhrcontentels = document.getElementsByClassName("xhr-content");
180 for (var i = 0; i < xhrcontentels.length; i++) {
181 var xhrcontentel = xhrcontentels[i];
182 var url = xhrcontentel.getAttribute("data-url") || "";
183 if (url == "")
184 continue;
185
186 // bind element to context.
187 (function(bindel) {
188 var updatefn = function(config) {
189 var parent = config.el;
190 var curcontent = parent.childNodes.length ? pare…
191 var newcontent = config.data || "";
192 // content changed.
193 if (curcontent === newcontent)
194 return;
195
196 // remove previous nodes.
197 while (parent.childNodes.length > 0)
198 parent.removeChild(parent.childNodes[0]);
199
200 // add nodes to force a transition.
201 var node = document.createElement("div");
202 node.innerHTML = newcontent;
203 if (config.animate !== "") {
204 node.classList.add("animate-once");
205 node.classList.add(config.animateclass);
206 }
207 parent.appendChild(node); // add new.
208 };
209
210 var processfn = function(x) {
211 var data = "";
212 if (x.status >= 200 && x.status < 400)
213 data = x.responseText || "";
214 else
215 data = ""; // "ERROR";
216 config.data = data;
217 };
218
219 // config / context.
220 var config = {
221 animateclass: bindel.getAttribute("data-animate-…
222 el: bindel,
223 processfn: processfn,
224 timeout: parseInt(bindel.getAttribute("data-time…
225 update: parseInt(bindel.getAttribute("data-updat…
226 updatefn: updatefn,
227 url: (bindel.getAttribute("data-url") || "")
228 };
229
230 // reload data.
231 var updater = function() {
232 xhr(config.url, function(x) {
233 // process data.
234 config.processfn(x);
235 // update and display data.
236 config.updatefn(config);
237 }, config.timeout);
238 };
239
240 setInterval(updater, config.update);
241 // run almost immediately once the first time.
242 setTimeout(updater, 1);
243 })(xhrcontentel);
244 }
245
246 // object or iframe elements that simply show some HTML and refresh in a…
247 var embedcontentels = document.getElementsByClassName("embed-content");
248 for (var i = 0; i < embedcontentels.length; i++) {
249 var embedcontentel = embedcontentels[i];
250
251 // must have one child node of type "object" or "iframe".
252 if (embedcontentel.children.length <= 0)
253 continue;
254
255 var child = embedcontentel.children[0];
256
257 // bind element to context.
258 (function(bindel, child) {
259 var url = "";
260 var type = "";
261 var tagname = child.tagName;
262 if (tagname === "OBJECT") {
263 url = child.data || "";
264 type = child.getAttribute("data-type") || "text/…
265 } else if (tagname === "IFRAME") {
266 url = child.getAttribute("src") || "";
267 }
268
269 // config / context.
270 var config = {
271 el: bindel,
272 update: parseInt(bindel.getAttribute("data-updat…
273 url: url,
274 type: type
275 };
276
277 var updater;
278 if (tagname === "OBJECT") {
279 // reload data.
280 updater = function() {
281 var objects = Array.from(bindel.childNod…
282
283 var object = document.createElement("obj…
284 object.data = config.url; // reload
285 object.type = config.type;
286 object.style.visibility = "hidden";
287 object.onload = function() {
288 // quickly swap out the old obje…
289 // this prevents some flickering.
290 for (var j = 0; j < objects.leng…
291 bindel.removeChild(objec…
292 this.style.visibility = "visible…
293 };
294 bindel.appendChild(object);
295 };
296 } else if (tagname === "IFRAME") {
297 // reload data.
298 updater = function() {
299 child.contentWindow.location.reload();
300 };
301 }
302
303 setInterval(updater, config.update);
304 // run almost immediately once the first time.
305 setTimeout(updater, 1);
306 })(embedcontentel, child);
307 }
308
309 // pause videos inside element.
310 function pausevideos(el) {
311 var videos = el.getElementsByTagName("video");
312 for (var i = 0; i < videos.length; i++) {
313 videos[i].pause();
314 if ((videos[i].getAttribute("data-reset-on-pause") || ""…
315 videos[i].currentTime = 0; // reset time / seek …
316 }
317 }
318
319 // play / resume videos inside element.
320 function playvideos(el) {
321 var videos = el.getElementsByTagName("video");
322 for (var i = 0; i < videos.length; i++) {
323 videos[i].muted = true; // mute audio by default.
324 if ((videos[i].getAttribute("data-reset-on-play") || "")…
325 videos[i].currentTime = 0; // reset time / seek …
326 videos[i].play(); // NOTE: auto-play must be enabled by …
327 }
328 }
329
330 // date / clocks.
331 var dates = document.getElementsByClassName("datetime");
332 for (var i = 0; i < dates.length; i++) {
333 var format = dates[i].getAttribute("data-format") || "";
334 var freq = dates[i].getAttribute("data-update") || 1000; // defa…
335
336 var fn = (function(el, freq, format) {
337 return function() {
338 el.innerHTML = strftime(format); // allow HTML i…
339 };
340 })(dates[i], freq, format);
341 updateevery(freq, fn);
342 }
343
344 // init slides and timings.
345 function slides_init(rootel) {
346 rootel = rootel || document;
347 var slides = {
348 current: 0,
349 prev: -1,
350 prevprev: -1,
351 slides: []
352 };
353
354 // find direct descendent element with class "slide".
355 var slideels = getdirectchilds(rootel, "slide");
356 for (var i = 0; i < slideels.length; i++) {
357 var attrtiming = slideels[i].getAttribute("data-displayn…
358 var timing = parseInt(attrtiming);
359 if (timing <= 0)
360 timing = 5000;
361
362 var slide = {
363 timing: timing,
364 el: slideels[i]
365 };
366 slides.slides.push(slide);
367 }
368 return slides;
369 }
370
371 function slides_showcurrent(slides) {
372 var el = slides.slides[slides.current].el;
373 if (el === null)
374 return;
375 el.classList.add("visible");
376 playvideos(el);
377 }
378
379 function slides_change(slides) {
380 if (typeof(slides.prev) !== "undefined")
381 slides.slides[slides.prev].elapsed = 0;
382 slides.slides[slides.current].elapsed = 0;
383
384 slides_showcurrent(slides);
385 if (slides.onchange)
386 slides.onchange(slides.prev, slides.prevprev); // curren…
387
388 // completely hidden.
389 if (slides.prevprev !== -1) {
390 var el = slides.slides[slides.prevprev].el;
391 el.classList.remove("pause");
392 }
393
394 // pause / fade out.
395 if (slides.prev !== -1) {
396 var el = slides.slides[slides.prev].el;
397 el.classList.remove("visible");
398 el.classList.add("pause");
399 pausevideos(el);
400 }
401 }
402
403 function slides_go(slides, n) {
404 // out-of-bounds or the same: do nothing.
405 if (n < 0 || n >= slides.slides.length || n == slides.current)
406 return;
407 slides.prevprev = slides.prev;
408 slides.prev = slides.current;
409 slides.current = n;
410 slides_change(slides);
411 }
412
413 function slides_prev(slides) {
414 var n = slides.current - 1;
415 if (n < 0 && slides.slides.length)
416 n = slides.slides.length - 1;
417 slides_go(slides, n);
418 slides_change(slides);
419 }
420
421 function slides_next(slides) {
422 var n = slides.current + 1;
423 if (n >= slides.slides.length)
424 n = 0;
425 slides_go(slides, n);
426 slides_change(slides);
427 }
428
429 function slides_pause(slides) {
430 slides.paused = true;
431 clearTimeout(slides.timernextslide);
432 clearTimeout(slides.timercurrentslide);
433 pausevideos(slides.slides[slides.current].el);
434 }
435
436 function slides_play(slides) {
437 slides_continue(slides);
438 }
439
440 function slides_continue(slides) {
441 slides.paused = false;
442 slides_updater(slides);
443 slides_showcurrent(slides);
444 }
445
446 function slides_updater(slides) {
447 // need more than 1 slide to change it.
448 if (slides.slides.length <= 1)
449 return;
450 var fn = function() {
451 slides_next(slides);
452 var currentslide = slides.slides[slides.current];
453 var timing = currentslide.timing || 5000; // default: 5 …
454 timing -= (currentslide.elapsed || 0); // minus played t…
455 slides.timernextslide = setTimeout(fn, timing);
456 };
457 var currentslide = slides.slides[slides.current];
458 var timing = currentslide.timing || 5000; // default: 5 seconds
459 timing -= (currentslide.elapsed || 0); // minus played time for …
460 slides.timercurrentslide = setTimeout(fn, timing);
461 }
462
463 function progressbar_init(slides, progressbar) {
464 if (slides.slides.length <= 1)
465 return;
466
467 // config: show total progress or progress per slide.
468 var usetotalprogress = parseInt(progressbar.getAttribute("data-t…
469
470 function progressbar_update(slides) {
471 var currentslide = slides.slides[slides.current];
472 var total = currentslide.timing || 5000; // default: 5 s…
473
474 if (usetotalprogress) {
475 total = 0;
476 for (var i = 0; i < slides.slides.length; i++) {
477 total += parseInt(slides.slides[i].timin…
478 }
479 }
480
481 currentslide.elapsed = currentslide.elapsed || 0;
482
483 var perfnow = window.performance.now()
484 slides.prevprogress = slides.prevprogress || 0;
485
486 if (!slides.paused) {
487 currentslide.elapsed += perfnow - slides.prevpro…
488 }
489 slides.prevprogress = perfnow;
490
491 var elapsed = currentslide.elapsed;
492 if (usetotalprogress) {
493 // current slide progress + all finished previou…
494 for (var i = 0; i < slides.current; i++)
495 elapsed += parseInt(slides.slides[i].tim…
496 }
497
498 // generate linear gradient with ticks for the total pro…
499 if (usetotalprogress) {
500 var total = 0;
501 for (var i = 0; i < slides.slides.length; i++) {
502 total += parseInt(slides.slides[i].timin…
503 }
504
505 var pattern = [];
506 var timing = 0;
507 for (var i = 0; i < slides.slides.length; i++) {
508 timing += parseInt(slides.slides[i].timi…
509 var percent = (timing / total) * 100.0;
510
511 pattern.push("rgba(255, 255, 255, 0.0) "…
512
513 // don't show tick for last.
514 if (i !== slides.slides.length - 1) {
515 // tick color
516 pattern.push("rgba(255,255,255, …
517 pattern.push("rgba(255,255,255, …
518 }
519 }
520
521 // ticks gradient;
522 var gradient = "linear-gradient(90deg, " + patte…
523 // progress gradient.
524 var percent = (elapsed / total) * 100.0;
525 gradient += ", linear-gradient(90deg, rgba(255, …
526 "%, rgba(255, 255, 255, 0) " + (percent …
527 "%, rgba(255, 255, 255, 0) 100%)" // act…
528 progressbar.style.background = gradient;
529 progressbar.style.width = "100%";
530 } else {
531 var percent = (elapsed / total) * 100.0;
532 progressbar.style.width = percent + "%";
533 }
534 }
535
536 function progressbar_updater() {
537 var fn = function() {
538 progressbar_update(slides);
539 };
540 setInterval(fn, 16); // 16ms, update at ~60fps
541 }
542
543 progressbar_updater(slides);
544 }
545
546 // initialize slides, can be nested.
547 var rootels = document.getElementsByClassName("slides") || [];
548 for (var i = 0; i < rootels.length; i++) {
549 var rootel = rootels[i];
550
551 var slides = slides_init(rootel);
552 slides_play(slides);
553
554 /* progressbar: shows current slide progress */
555 var progressbars = getdirectchilds(rootel, "progressbar");
556 if (progressbars.length) // use first progressbar.
557 progressbar_init(slides, progressbars[0]);
558 }
559
560 /* mechanism to poll if screen data is updated and needs a full refresh
561 ignoring the cache. */
562 var lasthash = null;
563 var els = document.getElementsByClassName("check-updates");
564 for (var i = 0; i < els.length; i++) {
565 var el = els[i];
566 var interval = parseInt(el.getAttribute("data-update"));
567 if (interval <= 0)
568 continue;
569 var url = el.getAttribute("data-url") || "";
570 if (url === "")
571 continue;
572
573 var fn = function(x) {
574 if (x.status >= 200 && x.status < 400) {
575 var newhash = x.responseText || "";
576 if (lasthash === null) {
577 lasthash = newhash;
578 } else if (newhash !== lasthash) {
579 // reload, ignore cache: works in Chrome…
580 window.location.reload(true);
581 }
582 }
583 };
584
585 setInterval(function() {
586 xhr(url, fn, 10000);
587 }, interval);
588 xhr(url, fn, 10000);
589
590 break;
591 }
592
593 window.addEventListener("keyup", function(e) {
594 switch (e.keyCode) {
595 case 32: // space: toggle pause/play.
596 if (slides.paused)
597 slides_continue(slides);
598 else
599 slides_pause(slides);
600 break;
601 case 37: // left arrow: previous slide.
602 slides_prev(slides);
603 break;
604 case 13: // return or right arrow next slide.
605 case 39:
606 slides_next(slides);
607 break;
608 case 49: // '1': go to slide 1
609 case 50: // '2': go to slide 2
610 case 51: // '3': go to slide 3
611 case 52: // '4': go to slide 4
612 case 53: // '5': go to slide 5
613 case 54: // '6': go to slide 6
614 case 55: // '7': go to slide 7
615 case 56: // '8': go to slide 8
616 case 57: // '9': go to slide 9
617 slides_go(slides, e.keyCode - 49);
618 break;
619 }
620 }, false);
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.