Faster javascript and usability enchancements in book reader.
authorMarek Stępniowski <marek@stepniowski.com>
Thu, 18 Sep 2008 10:06:54 +0000 (12:06 +0200)
committerMarek Stępniowski <marek@stepniowski.com>
Thu, 18 Sep 2008 10:06:54 +0000 (12:06 +0200)
wolnelektury/media/js/book.js
wolnelektury/media/js/jquery.eventdelegation.js [new file with mode: 0644]
wolnelektury/media/js/jquery.highlightfade.js [new file with mode: 0644]
wolnelektury/settings.py

index 108c267..512c86e 100644 (file)
@@ -1,14 +1,21 @@
 $(function() {
 $(function() {
+    $.highlightFade.defaults.speed = 3000;
+    
     $('#toc').hide();
     $('#toc').hide();
+    $.scrollTo('-=50px');
     
     if ($('#toc li').length == 0) {
         $('#menu li a[href="#toc"]').remove();
     }
     
     
     if ($('#toc li').length == 0) {
         $('#menu li a[href="#toc"]').remove();
     }
     
-    $('#toc a, #themes a').click(function(event) {
+    $('body').delegate('click', '#toc a, #themes a, .anchor, .annotation', function(event) {
         event.preventDefault();
         $('#menu li a.selected').click();
         event.preventDefault();
         $('#menu li a.selected').click();
-        $.scrollTo('a[name="' + $(this).attr('href').slice(1) + '"]', {offset: {top: -50, left: 0}});
+        if ($(this).attr('href')) {
+            var name = $(this).attr('href').slice(1);
+            $.scrollTo('a[name="' + name + '"]', 500, {offset: {top: -50, left: 0}});
+            $('a[name="' + name + '"]').highlightFade('yellow');
+        }
     });
     
     $('#menu li a').toggle(function() {
     });
     
     $('#menu li a').toggle(function() {
diff --git a/wolnelektury/media/js/jquery.eventdelegation.js b/wolnelektury/media/js/jquery.eventdelegation.js
new file mode 100644 (file)
index 0000000..5ecba6e
--- /dev/null
@@ -0,0 +1,55 @@
+/* 
+ * jQuery Event Delegation Plugin - jquery.eventdelegation.js
+ * Fast flexible event handling
+ *
+ * January 2008 - Randy Morey (http://dev.distilldesign.com/)
+ */
+
+(function ($) {
+       /* setup list of allowed events for event delegation
+        * only events that bubble are appropriate
+        */
+       var allowed = {};
+       $.each([
+               'click',
+               'dblclick',
+               'mousedown',
+               'mouseup',
+               'mousemove',
+               'mouseover',
+               'mouseout',
+               'keydown',
+               'keypress',
+               'keyup'
+               ], function(i, eventName) {     
+                       allowed[eventName] = true;
+       });
+       
+       $.fn.extend({
+               delegate: function (event, selector, f) {
+                       return $(this).each(function () {
+                               if (allowed[event])
+                                       $(this).bind(event, function (e) {
+                                               var el = $(e.target),
+                                                       result = false;
+                                               
+                                               while (!$(el).is('body')) {
+                                                       if ($(el).is(selector)) {
+                                                               result = f.apply($(el)[0], [e]);
+                                                               if (result === false)
+                                                                       e.preventDefault();
+                                                               return;
+                                                       }
+                                                       
+                                                       el = $(el).parent();
+                                               }
+                                       });
+                       });
+               },
+               undelegate: function (event) {
+                       return $(this).each(function () {
+                               $(this).unbind(event);
+                       });
+               }
+       });
+})(jQuery);
\ No newline at end of file
diff --git a/wolnelektury/media/js/jquery.highlightfade.js b/wolnelektury/media/js/jquery.highlightfade.js
new file mode 100644 (file)
index 0000000..600cfe1
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ *  jQuery Plugin highlightFade (jquery.offput.ca/highlightFade)
+ *  (c) 2006 Blair Mitchelmore (offput.ca) blair@offput.ca
+ */
+/**
+ * This is version 0.7 of my highlightFade plugin. It follows the yellow fade technique of Web 2.0 fame
+ * but expands it to allow any starting colour and allows you to specify the end colour as well.
+ *
+ * For the moment, I'm done with this plug-in. Unless I come upon a really cool feature it should have
+ * this plug-in will only receive updates to ensure future compatibility with jQuery.
+ *
+ * As of now (Aug. 16, 2006) the plugin has been written with the 1.0.1 release of jQuery (rev 249) which
+ * is available from http://jquery.com/src/jquery-1.0.1.js
+ *
+ * A note regarding rgb() syntax: I noticed that most browsers implement rgb syntax as either an integer 
+ * (0-255) or percentage (0-100%) value for each field, that is, rgb(i/p,i/p,i/p); however, the W3C 
+ * standard clearly defines it as "either three integer values or three percentage values" [http://www.w3.org/TR/CSS21/syndata.html] 
+ * which I choose to follow despite the error redundancy of the typical behaviour browsers employ.
+ *
+ * Changelog:
+ *
+ *    0.7:
+ *        - Added the awesome custom attribute support written by George Adamson (slightly modified)
+ *        - Removed bgColor plugin dependency seeing as attr is customizable now...
+ *    0.6:
+ *        - Abstracted getBGColor into its own plugin with optional test and data retrieval functions
+ *        - Converted all $ references to jQuery references as John's code seems to be shifting away
+ *          from that and I don't want to have to update this for a long time.
+ *    0.5:
+ *        - Added simple argument syntax for only specifying start colour of event
+ *        - Removed old style argument syntax
+ *        - Added 'interval', 'final, and 'end' properties
+ *        - Renamed 'color' property to 'start'
+ *        - Added second argument to $.highlightFade.getBGColor to bypass the e.highlighting check
+ *    0.4:
+ *        - Added rgb(%,%,%) color syntax
+ *    0.3:
+ *        - Fixed bug when event was called while parent was also running event corrupting the
+ *          the background colour of the child
+ *    0.2:
+ *        - Fixed bug where an unspecified onComplete function made the page throw continuous errors
+ *        - Fixed bug where multiple events on the same element would speed each subsequent event
+ *    0.1:
+ *        - Initial Release
+ * 
+ * @author          Blair Mitchelmore (blair@offput.ca)
+ * @version         0.5
+ */
+jQuery.fn.highlightFade = function(settings) {
+       var o = (settings && settings.constructor == String) ? {start: settings} : settings || {};
+       var d = jQuery.highlightFade.defaults;
+       var i = o['interval'] || d['interval'];
+       var a = o['attr'] || d['attr'];
+       var ts = {
+               'linear': function(s,e,t,c) { return parseInt(s+(c/t)*(e-s)); },
+               'sinusoidal': function(s,e,t,c) { return parseInt(s+Math.sin(((c/t)*90)*(Math.PI/180))*(e-s)); },
+               'exponential': function(s,e,t,c) { return parseInt(s+(Math.pow(c/t,2))*(e-s)); }
+       };
+       var t = (o['iterator'] && o['iterator'].constructor == Function) ? o['iterator'] : ts[o['iterator']] || ts[d['iterator']] || ts['linear'];
+       if (d['iterator'] && d['iterator'].constructor == Function) t = d['iterator'];
+       return this.each(function() {
+               if (!this.highlighting) this.highlighting = {};
+               var e = (this.highlighting[a]) ? this.highlighting[a].end : jQuery.highlightFade.getBaseValue(this,a) || [255,255,255];
+               var c = jQuery.highlightFade.getRGB(o['start'] || o['colour'] || o['color'] || d['start'] || [255,255,128]);
+               var s = jQuery.speed(o['speed'] || d['speed']);
+               var r = o['final'] || (this.highlighting[a] && this.highlighting[a].orig) ? this.highlighting[a].orig : jQuery.curCSS(this,a);
+               if (o['end'] || d['end']) r = jQuery.highlightFade.asRGBString(e = jQuery.highlightFade.getRGB(o['end'] || d['end']));
+               if (typeof o['final'] != 'undefined') r = o['final'];
+               if (this.highlighting[a] && this.highlighting[a].timer) window.clearInterval(this.highlighting[a].timer);
+               this.highlighting[a] = { steps: ((s.duration) / i), interval: i, currentStep: 0, start: c, end: e, orig: r, attr: a };
+               jQuery.highlightFade(this,a,o['complete'],t);
+       });
+};
+
+jQuery.highlightFade = function(e,a,o,t) {
+       e.highlighting[a].timer = window.setInterval(function() { 
+               var newR = t(e.highlighting[a].start[0],e.highlighting[a].end[0],e.highlighting[a].steps,e.highlighting[a].currentStep);
+               var newG = t(e.highlighting[a].start[1],e.highlighting[a].end[1],e.highlighting[a].steps,e.highlighting[a].currentStep);
+               var newB = t(e.highlighting[a].start[2],e.highlighting[a].end[2],e.highlighting[a].steps,e.highlighting[a].currentStep);
+               jQuery(e).css(a,jQuery.highlightFade.asRGBString([newR,newG,newB]));
+               if (e.highlighting[a].currentStep++ >= e.highlighting[a].steps) {
+                       jQuery(e).css(a,e.highlighting[a].orig || '');
+                       window.clearInterval(e.highlighting[a].timer);
+                       e.highlighting[a] = null;
+                       if (o && o.constructor == Function) o.call(e);
+               }
+       },e.highlighting[a].interval);
+};
+
+jQuery.highlightFade.defaults = {
+       start: [255,255,128],
+       interval: 50,
+       speed: 400,
+       attr: 'backgroundColor'
+};
+
+jQuery.highlightFade.getRGB = function(c,d) {
+       var result;
+       if (c && c.constructor == Array && c.length == 3) return c;
+       if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))
+               return [parseInt(result[1]),parseInt(result[2]),parseInt(result[3])];
+       else if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))
+               return [parseFloat(result[1])*2.55,parseFloat(result[2])*2.55,parseFloat(result[3])*2.55];
+       else if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))
+               return [parseInt("0x" + result[1]),parseInt("0x" + result[2]),parseInt("0x" + result[3])];
+       else if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))
+               return [parseInt("0x"+ result[1] + result[1]),parseInt("0x" + result[2] + result[2]),parseInt("0x" + result[3] + result[3])];
+       else
+               return jQuery.highlightFade.checkColorName(c) || d || null;
+};
+
+jQuery.highlightFade.asRGBString = function(a) {
+       return "rgb(" + a.join(",") + ")";
+};
+
+jQuery.highlightFade.getBaseValue = function(e,a,b) {
+       var s, t;
+       b = b || false;
+       t = a = a || jQuery.highlightFade.defaults['attr'];
+       do {
+               s = jQuery(e).css(t || 'backgroundColor');
+               if ((s  != '' && s != 'transparent') || (e.tagName.toLowerCase() == "body") || (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end)) break; 
+               t = false;
+       } while (e = e.parentNode);
+       if (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end) s = e.highlighting[a].end;
+       if (s == undefined || s == '' || s == 'transparent') s = [255,255,255];
+       return jQuery.highlightFade.getRGB(s);
+};
+
+jQuery.highlightFade.checkColorName = function(c) {
+       if (!c) return null;
+       switch(c.replace(/^\s*|\s*$/g,'').toLowerCase()) {
+               case 'aqua': return [0,255,255];
+               case 'black': return [0,0,0];
+               case 'blue': return [0,0,255];
+               case 'fuchsia': return [255,0,255];
+               case 'gray': return [128,128,128];
+               case 'green': return [0,128,0];
+               case 'lime': return [0,255,0];
+               case 'maroon': return [128,0,0];
+               case 'navy': return [0,0,128];
+               case 'olive': return [128,128,0];
+               case 'purple': return [128,0,128];
+               case 'red': return [255,0,0];
+               case 'silver': return [192,192,192];
+               case 'teal': return [0,128,128];
+               case 'white': return [255,255,255];
+               case 'yellow': return [255,255,0];
+       }
+};
index a978759..12edea3 100644 (file)
@@ -109,7 +109,7 @@ COMPRESS_JS = {
         'output_filename': 'js/all.min.js',
     },
     'book': {
         'output_filename': 'js/all.min.js',
     },
     'book': {
-        'source_filenames': ('js/jquery.scrollto.js', 'js/book.js',),
+        'source_filenames': ('js/jquery.eventdelegation.js', 'js/jquery.scrollto.js', 'js/jquery.highlightfade.js', 'js/book.js',),
         'output_filename': 'js/book.min.js',
     }
 }
         'output_filename': 'js/book.min.js',
     }
 }