diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index a0531a397..a06c6670a 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -9,6 +9,8 @@ require('jquery-ujs'); require('hammerjs'); require('dropzone'); require('spark-md5'); +require('stupid-table-plugin'); +require('jquery-hotkeys'); // should start looking for nodejs replacements importAll(require.context('../vendor', true, /\.js$/)); diff --git a/app/javascript/vendor/jquery-hotkeys.js b/app/javascript/vendor/jquery-hotkeys.js deleted file mode 100644 index 3e5095e4f..000000000 --- a/app/javascript/vendor/jquery-hotkeys.js +++ /dev/null @@ -1,204 +0,0 @@ -/*jslint browser: true*/ -/*jslint jquery: true*/ - -/* - * jQuery Hotkeys Plugin - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * - * Based upon the plugin by Tzury Bar Yochay: - * https://github.com/tzuryby/jquery.hotkeys - * - * Original idea by: - * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ - */ - -/* - * One small change is: now keys are passed by object { keys: '...' } - * Might be useful, when you want to pass some other data to your handler - */ - -(function(jQuery) { - - jQuery.hotkeys = { - version: "0.8", - - specialKeys: { - 8: "backspace", - 9: "tab", - 10: "return", - 13: "return", - 16: "shift", - 17: "ctrl", - 18: "alt", - 19: "pause", - 20: "capslock", - 27: "esc", - 32: "space", - 33: "pageup", - 34: "pagedown", - 35: "end", - 36: "home", - 37: "left", - 38: "up", - 39: "right", - 40: "down", - 45: "insert", - 46: "del", - 59: ";", - 61: "=", - 96: "0", - 97: "1", - 98: "2", - 99: "3", - 100: "4", - 101: "5", - 102: "6", - 103: "7", - 104: "8", - 105: "9", - 106: "*", - 107: "+", - 109: "-", - 110: ".", - 111: "/", - 112: "f1", - 113: "f2", - 114: "f3", - 115: "f4", - 116: "f5", - 117: "f6", - 118: "f7", - 119: "f8", - 120: "f9", - 121: "f10", - 122: "f11", - 123: "f12", - 144: "numlock", - 145: "scroll", - 173: "-", - 186: ";", - 187: "=", - 188: ",", - 189: "-", - 190: ".", - 191: "/", - 192: "`", - 219: "[", - 220: "\\", - 221: "]", - 222: "'" - }, - - shiftNums: { - "`": "~", - "1": "!", - "2": "@", - "3": "#", - "4": "$", - "5": "%", - "6": "^", - "7": "&", - "8": "*", - "9": "(", - "0": ")", - "-": "_", - "=": "+", - ";": ": ", - "'": "\"", - ",": "<", - ".": ">", - "/": "?", - "\\": "|" - }, - - // excludes: button, checkbox, file, hidden, image, password, radio, reset, search, submit, url - textAcceptingInputTypes: [ - "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", - "datetime-local", "search", "color", "tel"], - - // default input types not to bind to unless bound directly - textInputTypes: /textarea|input|select/i, - - options: { - filterInputAcceptingElements: true, - filterTextInputs: true, - filterContentEditable: true - } - }; - - function keyHandler(handleObj) { - if (typeof handleObj.data === "string") { - handleObj.data = { - keys: handleObj.data - }; - } - - // Only care when a possible input has been specified - if (!handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string") { - return; - } - - var origHandler = handleObj.handler, - keys = handleObj.data.keys.toLowerCase().split(" "); - - handleObj.handler = function(event) { - // Don't fire in text-accepting inputs that we didn't directly bind to - if (this !== event.target && - (jQuery.hotkeys.options.filterInputAcceptingElements && - jQuery.hotkeys.textInputTypes.test(event.target.nodeName) || - (jQuery.hotkeys.options.filterContentEditable && jQuery(event.target).attr('contenteditable')) || - (jQuery.hotkeys.options.filterTextInputs && - jQuery.inArray(event.target.type, jQuery.hotkeys.textAcceptingInputTypes) > -1))) { - return; - } - - var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which], - character = String.fromCharCode(event.which).toLowerCase(), - modif = "", - possible = {}; - - jQuery.each(["alt", "ctrl", "shift"], function(index, specialKey) { - - if (event[specialKey + 'Key'] && special !== specialKey) { - modif += specialKey + '+'; - } - }); - - // metaKey is triggered off ctrlKey erronously - if (event.metaKey && !event.ctrlKey && special !== "meta") { - modif += "meta+"; - } - - if (event.metaKey && special !== "meta" && modif.indexOf("alt+ctrl+shift+") > -1) { - modif = modif.replace("alt+ctrl+shift+", "hyper+"); - } - - if (special) { - possible[modif + special] = true; - } - else { - possible[modif + character] = true; - possible[modif + jQuery.hotkeys.shiftNums[character]] = true; - - // "$" can be triggered as "Shift+4" or "Shift+$" or just "$" - if (modif === "shift+") { - possible[jQuery.hotkeys.shiftNums[character]] = true; - } - } - - for (var i = 0, l = keys.length; i < l; i++) { - if (possible[keys[i]]) { - return origHandler.apply(this, arguments); - } - } - }; - } - - jQuery.each(["keydown", "keyup", "keypress"], function() { - jQuery.event.special[this] = { - add: keyHandler - }; - }); - -})(jQuery || this.jQuery || window.jQuery); diff --git a/app/javascript/vendor/stupidtable.js b/app/javascript/vendor/stupidtable.js deleted file mode 100644 index 8db085e59..000000000 --- a/app/javascript/vendor/stupidtable.js +++ /dev/null @@ -1,281 +0,0 @@ -// Stupid jQuery table plugin. - -(function($) { - $.fn.stupidtable = function(sortFns) { - return this.each(function() { - var $table = $(this); - sortFns = sortFns || {}; - sortFns = $.extend({}, $.fn.stupidtable.default_sort_fns, sortFns); - $table.data('sortFns', sortFns); - $table.stupidtable_build(); - - $table.on("click.stupidtable", "thead th", function() { - $(this).stupidsort(); - }); - - // Sort th immediately if data-sort-onload="yes" is specified. Limit to - // the first one found - only one default sort column makes sense anyway. - var $th_onload_sort = $table.find("th[data-sort-onload=yes]").eq(0); - $th_onload_sort.stupidsort(); - }); - }; - - // ------------------------------------------------------------------ - // Default settings - // ------------------------------------------------------------------ - $.fn.stupidtable.default_settings = { - should_redraw: function(sort_info){ - return true; - }, - will_manually_build_table: false - }; - $.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) { - return a.toString().localeCompare(b.toString()); - }, - "string-ins": function(a, b) { - a = a.toString().toLocaleLowerCase(); - b = b.toString().toLocaleLowerCase(); - return a.localeCompare(b); - } - }; - - // Allow specification of settings on a per-table basis. Call on a table - // jquery object. Call *before* calling .stuidtable(); - $.fn.stupidtable_settings = function(settings) { - return this.each(function() { - var $table = $(this); - var final_settings = $.extend({}, $.fn.stupidtable.default_settings, settings); - $table.stupidtable.settings = final_settings; - }); - }; - - - // Expects $("#mytable").stupidtable() to have already been called. - // Call on a table header. - $.fn.stupidsort = function(force_direction){ - var $this_th = $(this); - var datatype = $this_th.data("sort") || null; - - // No datatype? Nothing to do. - if (datatype === null) { - return; - } - - var dir = $.fn.stupidtable.dir; - var $table = $this_th.closest("table"); - - var sort_info = { - $th: $this_th, - $table: $table, - datatype: datatype - }; - - - // Bring in default settings if none provided - if(!$table.stupidtable.settings){ - $table.stupidtable.settings = $.extend({}, $.fn.stupidtable.default_settings); - } - - sort_info.compare_fn = $table.data('sortFns')[datatype]; - sort_info.th_index = calculateTHIndex(sort_info); - sort_info.sort_dir = calculateSortDir(force_direction, sort_info); - - $this_th.data("sort-dir", sort_info.sort_dir); - $table.trigger("beforetablesort", {column: sort_info.th_index, direction: sort_info.sort_dir, $th: $this_th}); - - // 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() { - if(!$table.stupidtable.settings.will_manually_build_table){ - $table.stupidtable_build(); - } - var table_structure = sortTable(sort_info); - var trs = getTableRowsFromTableStructure(table_structure, sort_info); - - if(!$table.stupidtable.settings.should_redraw(sort_info)){ - return; - } - $table.children("tbody").append(trs); - - updateElementData(sort_info); - $table.trigger("aftertablesort", {column: sort_info.th_index, direction: sort_info.sort_dir, $th: $this_th}); - $table.css("display"); - - }, 10); - return $this_th; - }; - - // Call on a sortable td to update its value in the sort. This should be the - // only mechanism used to update a cell's sort value. If your display value is - // different from your sort value, use jQuery's .text() or .html() to update - // the td contents, Assumes stupidtable has already been called for the table. - $.fn.updateSortVal = function(new_sort_val){ - var $this_td = $(this); - if($this_td.is('[data-sort-value]')){ - // For visual consistency with the .data cache - $this_td.attr('data-sort-value', new_sort_val); - } - $this_td.data("sort-value", new_sort_val); - return $this_td; - }; - - - $.fn.stupidtable_build = function(){ - return this.each(function() { - var $table = $(this); - var table_structure = []; - var trs = $table.children("tbody").children("tr"); - trs.each(function(index,tr) { - - // ==================================================================== - // Transfer to using internal table structure - // ==================================================================== - var ele = { - $tr: $(tr), - columns: [], - index: index - }; - - $(tr).children('td').each(function(idx, td){ - var sort_val = $(td).data("sort-value"); - - // Store and read from the .data cache for display text only sorts - // instead of looking through the DOM every time - if(typeof(sort_val) === "undefined"){ - var txt = $(td).text(); - $(td).data('sort-value', txt); - sort_val = txt; - } - ele.columns.push(sort_val); - }); - table_structure.push(ele); - }); - $table.data('stupidsort_internaltable', table_structure); - }); - }; - - // ==================================================================== - // Private functions - // ==================================================================== - var sortTable = function(sort_info){ - var table_structure = sort_info.$table.data('stupidsort_internaltable'); - var th_index = sort_info.th_index; - var $th = sort_info.$th; - - var multicolumn_target_str = $th.data('sort-multicolumn'); - var multicolumn_targets; - if(multicolumn_target_str){ - multicolumn_targets = multicolumn_target_str.split(','); - } - else{ - multicolumn_targets = []; - } - var multicolumn_th_targets = $.map(multicolumn_targets, function(identifier, i){ - return get_th(sort_info.$table, identifier); - }); - - table_structure.sort(function(e1, e2){ - var multicolumns = multicolumn_th_targets.slice(0); // shallow copy - var diff = sort_info.compare_fn(e1.columns[th_index], e2.columns[th_index]); - while(diff === 0 && multicolumns.length){ - var multicolumn = multicolumns[0]; - var datatype = multicolumn.$e.data("sort"); - var multiCloumnSortMethod = sort_info.$table.data('sortFns')[datatype]; - diff = multiCloumnSortMethod(e1.columns[multicolumn.index], e2.columns[multicolumn.index]); - multicolumns.shift(); - } - // Sort by position in the table if values are the same. This enforces a - // stable sort across all browsers. See https://bugs.chromium.org/p/v8/issues/detail?id=90 - if (diff === 0) - return e1.index - e2.index; - else - return diff; - - }); - - if (sort_info.sort_dir != $.fn.stupidtable.dir.ASC){ - table_structure.reverse(); - } - return table_structure; - }; - - var get_th = function($table, identifier){ - // identifier can be a th id or a th index number; - var $table_ths = $table.find('th'); - var index = parseInt(identifier, 10); - var $th; - if(!index && index !== 0){ - $th = $table_ths.siblings('#' + identifier); - index = $table_ths.index($th); - } - else{ - $th = $table_ths.eq(index); - } - return {index: index, $e: $th}; - }; - - var getTableRowsFromTableStructure = function(table_structure, sort_info){ - // Gather individual column for callbacks - var column = $.map(table_structure, function(ele, i){ - return [[ele.columns[sort_info.th_index], ele.$tr, i]]; - }); - - /* Side effect */ - sort_info.column = column; - - // Replace the content of tbody with the sorted rows. Strangely - // enough, .append accomplishes this for us. - return $.map(table_structure, function(ele) { return ele.$tr; }); - - }; - - var updateElementData = function(sort_info){ - var $table = sort_info.$table; - var $this_th = sort_info.$th; - var sort_dir = $this_th.data('sort-dir'); - var th_index = sort_info.th_index; - - - // Reset siblings - $table.find("th").data("sort-dir", null).removeClass("sorting-desc sorting-asc"); - $this_th.data("sort-dir", sort_dir).addClass("sorting-"+sort_dir); - }; - - var calculateSortDir = function(force_direction, sort_info){ - var sort_dir; - var $this_th = sort_info.$th; - var dir = $.fn.stupidtable.dir; - - if(!!force_direction){ - sort_dir = force_direction; - } - else{ - sort_dir = force_direction || $this_th.data("sort-default") || dir.ASC; - if ($this_th.data("sort-dir")) - sort_dir = $this_th.data("sort-dir") === dir.ASC ? dir.DESC : dir.ASC; - } - return sort_dir; - }; - - var calculateTHIndex = function(sort_info){ - var th_index = 0; - var base_index = sort_info.$th.index(); - sort_info.$th.parents("tr").find("th").slice(0, base_index).each(function() { - var cols = $(this).attr("colspan") || 1; - th_index += parseInt(cols,10); - }); - return th_index; - }; - -})(jQuery); diff --git a/package.json b/package.json index d0ee16f33..e0d587700 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,14 @@ "dropzone": "^5.5.1", "expose-loader": "^0.7.5", "hammerjs": "^2.0.8", + "jquery-hotkeys": "^0.2.2", "jquery-ui": "^1.12.1", "jquery-ujs": "^1.2.2", "qtip2": "^3.0.3", "rails-erb-loader": "^5.4.2", "script-loader": "^0.7.2", "spark-md5": "^3.0.0", + "stupid-table-plugin": "^1.1.3", "webpack-cli": "^3.0.8" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 111ba3dda..24ab738af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3938,6 +3938,11 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" +jquery-hotkeys@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/jquery-hotkeys/-/jquery-hotkeys-0.2.2.tgz#69a8fc921596c8bde842d461070380006b3c30c4" + integrity sha1-aaj8khWWyL3oQtRhBwOAAGs8MMQ= + jquery-ui@^1.12.1: version "1.12.1" resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.12.1.tgz#bcb4045c8dd0539c134bc1488cdd3e768a7a9e51" @@ -6931,6 +6936,11 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +stupid-table-plugin@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/stupid-table-plugin/-/stupid-table-plugin-1.1.3.tgz#e0d72038da8299727ada73545d2eb9c1be443056" + integrity sha1-4NcgONqCmXJ62nNUXS65wb5EMFY= + style-loader@^0.23.1: version "0.23.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925"