diff lightbox/js/stupidtable.js @ 8:adc01e560eae

Uploaded
author rlegendre
date Mon, 20 Oct 2014 11:34:11 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lightbox/js/stupidtable.js	Mon Oct 20 11:34:11 2014 -0400
@@ -0,0 +1,152 @@
+// Stupid jQuery table plugin.
+
+// Call on a table
+// sortFns: Sort functions for your datatypes.
+(function($) {
+
+  $.fn.stupidtable = function(sortFns) {
+    return this.each(function() {
+      var $table = $(this);
+      sortFns = sortFns || {};
+
+      // ==================================================== //
+      //                  Utility functions                   //
+      // ==================================================== //
+
+      // Merge sort functions with some default sort functions.
+      sortFns = $.extend({}, $.fn.stupidtable.default_sort_fns, sortFns);
+
+      // Return the resulting indexes of a sort so we can apply
+      // this result elsewhere. This returns an array of index numbers.
+      // return[0] = x means "arr's 0th element is now at x"
+      var sort_map = function(arr, sort_function) {
+        var map = [];
+        var index = 0;
+        var sorted = arr.slice(0).sort(sort_function);
+        for (var i=0; i<arr.length; i++) {
+            index = $.inArray(arr[i], sorted);
+
+            // If this index is already in the map, look for the next index.
+            // This handles the case of duplicate entries.
+            while ($.inArray(index, map) != -1) {
+                index++;
+            }
+            map.push(index);
+        }
+
+        return map;
+      };
+
+      // Apply a sort map to the array.
+      var apply_sort_map = function(arr, map) {
+        var clone = arr.slice(0),
+            newIndex = 0;
+        for (var i=0; i<map.length; i++) {
+          newIndex = map[i];
+          clone[newIndex] = arr[i];
+        }
+        return clone;
+      };
+
+      // ==================================================== //
+      //                  Begin execution!                    //
+      // ==================================================== //
+
+      // Do sorting when THs are clicked
+      $table.on("click", "th", function() {
+        var trs = $table.children("tbody").children("tr");
+        var $this = $(this);
+        var th_index = 0;
+        var dir = $.fn.stupidtable.dir;
+
+        $table.find("th").slice(0, $this.index()).each(function() {
+          var cols = $(this).attr("colspan") || 1;
+          th_index += parseInt(cols,10);
+        });
+
+        // Determine (and/or reverse) sorting direction, default `asc`
+        var sort_dir = $this.data("sort-default") || dir.ASC;
+        if ($this.data("sort-dir"))
+           sort_dir = $this.data("sort-dir") === dir.ASC ? dir.DESC : dir.ASC;
+
+        // Choose appropriate sorting function. 
+        var type = $this.data("sort") || null;
+
+        // Prevent sorting if no type defined
+        if (type === null) {
+          return;
+        }
+
+        // Trigger `beforetablesort` event that calling scripts can hook into;
+        // pass parameters for sorted column index and sorting direction
+        $table.trigger("beforetablesort", {column: th_index, direction: sort_dir});
+        // More reliable method of forcing a redraw
+        $table.css("display");
+
+        // Run sorting asynchronously on a timout to force browser redraw after
+        // `beforetablesort` callback. Also avoids locking up the browser too much.
+        setTimeout(function() {
+          // Gather the elements for this column
+          var column = [];
+          var sortMethod = sortFns[type];
+
+          // Push either the value of the `data-order-by` attribute if specified
+          // or just the text() value in this column to column[] for comparison.
+          trs.each(function(index,tr) {
+            var $e = $(tr).children().eq(th_index);
+            var sort_val = $e.data("sort-value");
+            var order_by = typeof(sort_val) !== "undefined" ? sort_val : $e.text();
+            column.push(order_by);
+          });
+
+          // Create the sort map. This column having a sort-dir implies it was
+          // the last column sorted. As long as no data-sort-desc is specified,
+          // we're free to just reverse the column.
+          var theMap;
+          if (sort_dir == dir.ASC)
+            theMap = sort_map(column, sortMethod);
+          else
+            theMap = sort_map(column, function(a, b) { return -sortMethod(a, b); });
+
+          // Reset siblings
+          $table.find("th").data("sort-dir", null).removeClass("sorting-desc sorting-asc");
+          $this.data("sort-dir", sort_dir).addClass("sorting-"+sort_dir);
+
+          var sortedTRs = $(apply_sort_map(trs, theMap));
+          $table.children("tbody").remove();
+          $table.append("<tbody />").append(sortedTRs);
+
+          // Trigger `aftertablesort` event. Similar to `beforetablesort`
+          $table.trigger("aftertablesort", {column: th_index, direction: sort_dir});
+          // More reliable method of forcing a redraw
+          $table.css("display");
+        }, 10);
+      });
+    });
+  };
+
+  // Enum containing sorting directions
+  $.fn.stupidtable.dir = {ASC: "asc", DESC: "desc"};
+
+  $.fn.stupidtable.default_sort_fns = {
+    "int": function(a, b) {
+      return parseInt(a, 10) - parseInt(b, 10);
+    },
+    "float": function(a, b) {
+      return parseFloat(a) - parseFloat(b);
+    },
+    "string": function(a, b) {
+      if (a < b) return -1;
+      if (a > b) return +1;
+      return 0;
+    },
+    "string-ins": function(a, b) {
+      a = a.toLowerCase();
+      b = b.toLowerCase();
+      if (a < b) return -1;
+      if (a > b) return +1;
+      return 0;
+    }
+  };
+
+})(jQuery);