// vim: ts=4 et sw=4 sts=4 $(function () { // Micro-plugin for positioning the cursor $.fn.setCursor = $.fn.setCursor || function(pos) { return this.each(function() { if (this.setSelectionRange) { this.focus(); this.setSelectionRange(pos, pos); } else if (this.createTextRange) { var range = this.createTextRange(); range.collapse(true); range.moveEnd('character', pos); range.moveStart('character', pos); range.select(); } }); }; // Micro-plugin for getting the position of the cursor $.fn.getCursor = $.fn.getCursor || function () { // IE doesn't have selectionStart, and I'm too lazy to implement // the IE specific version of this, so we'll just assume // the cursor is at the end of the input for this case. if (typeof this[0].selectionStart === 'undefined') { return this.value.length; } else { return this[0].selectionStart; } }; // Micro-plugin for collecting all the listener and search inputs $.fn.getGridParams = $.fn.getGridParams || function (extras) { var listeners = this.data("listeners"), params = $.extend({}, this.find("thead").data("params"), {'magic_grid_id' : this.attr('id')}, extras || {}), $input, param_key, listened_id; for (listened_id in listeners) { param_key = listeners[listened_id]; $input = $("#" + listened_id); if ($input.is(":checkbox")) { params[param_key] = $input.is(":checked"); } else if ($input.is("select")) { params[param_key] = $input.find("option:selected").val(); } else { params[param_key] = $input.val(); } } if (this.is("[data-searcher]")) { params[this.attr('id') + '_q'] = $("#" + this.data("searcher")).val(); } return $.extend({}, params); } // Default handler for ajax events that displays 'Loading...' in // the head of the table. $(".magic_grid[data-default-ajax-handler=true]").on("magic_grid:loading", function (e) { $(".magic_grid_spinner", this). addClass("ui-icon-spinner"). html("Loading..."); }); $(".magic_grid[data-remote=true]").on( "click", ".pagination a, .sorter a", function (e) { var $grid = $(e.delegateTarget), url = this.href; $grid.trigger("magic_grid:loading"); $grid.load(url + ' #' + $grid.attr('id') + " > *", function () { $grid.trigger("magic_grid:loaded"); }); return false; }); $(".magic_grid[data-searcher]").each( function () { var $grid = $(this), grid_id = this.id, input_id = "#" + $grid.data("searcher"), live = $grid.data("live-search"), // keydown seems to be the only reliable and portable way to capture // things like backspace and delete events = (live ? "keydown change search" : "change search"), timer = null, internal = ($grid.has(input_id).length > 0), listener = (internal ? $grid : $(input_id).parent()), minLength = $(input_id).data("min-length") || 3; listener.on(events, input_id, function (e) { var is_manual = (e.type == 'search' || e.type == 'change' || (e.type == 'keydown' && e.which == '13')), base_url = $grid.data("current") || "", //40 wpm typists == 280ms/keystroke //90 wpm typists == 120ms/keystroke delay = is_manual ? 1 : (parseInt(live) || 500); clearTimeout(timer); timer = setTimeout(function () { var $input = $(input_id), current = $input.data("current"), value = $input.val(), length = value.length, base_url_path = base_url.split("?", 2)[0], relevant = is_manual || (value != current && (length >= minLength || length == 0)), pos = $input.getCursor(), url = base_url_path + '?' + $.param($grid.getGridParams()); clearTimeout(timer); if (relevant) { $grid.trigger("magic_grid:loading"); if ($grid.data("remote")) { if (internal && live && !is_manual) { $(input_id).prop('disabled', true); } $grid.load(url + ' #' + grid_id + ' > *', function () { // Move the cursor back to where it was, // less surprising that way. // EXCEPT FOR IE, that is $grid.trigger("magic_grid:loaded"); if (internal) { $(input_id).setCursor(pos); } }); } else { window.location = url; } } }, delay); }); }); $(".magic_grid[data-listeners]").each( function () { var $grid = $(this), listeners = $grid.data("listeners"), grid_id = this.id, handler = function (change) { if (! $("#"+change.data.field).hasClass("ready")) { return; } var base_url = $grid.data("current").split("?", 2)[0]; var url = base_url + '?' + $.param($grid.getGridParams()); $grid.trigger("magic_grid:loading"); if ($grid.data("remote")) { $grid.load(url + ' #' + grid_id + " > *", function () { $grid.trigger("magic_grid:loaded"); }); } else { window.location = url; } }; for (var k in listeners) { $("#" + k).on("change", {"field": listeners[k]}, handler); $("#" + k).on("ready", function (ready) { $(this).addClass("ready"); }); } }); $(".magic_grid").trigger("magic_grid:loaded"); });