diff --git a/bower.json b/bower.json index 0976cf5..4a8de33 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "sensei-grid", - "version": "0.1.4", + "version": "0.1.5", "homepage": "https://github.com/datazenit/sensei-grid", "authors": [ "Lauris " diff --git a/dist/sensei-grid.css b/dist/sensei-grid.css index aa12017..98d1675 100644 --- a/dist/sensei-grid.css +++ b/dist/sensei-grid.css @@ -1,5 +1,5 @@ /** - * sensei-grid v0.1.4 + * sensei-grid v0.1.5 * Copyright (c) 2014 Lauris Dzilums * Licensed under MIT */ @@ -47,12 +47,8 @@ .sensei-grid thead>tr>th, .sensei-grid tbody>tr>td { } -.sensei-grid .activeCell { - background: #eff7fc; -} .sensei-grid tr>td>div { } - .sensei-grid .activeCell { background: #d0e9f8; border: 1px double #3399ff; @@ -60,6 +56,9 @@ .sensei-grid .activeRow { background: #eff7fc; } +.sensei-grid .sensei-grid-dirty-row { + color: gray; +} .sensei-grid-editor { position: absolute; diff --git a/dist/sensei-grid.js b/dist/sensei-grid.js index 2a6d8bc..3ddc3da 100644 --- a/dist/sensei-grid.js +++ b/dist/sensei-grid.js @@ -1,5 +1,5 @@ /** - * sensei-grid v0.1.4 + * sensei-grid v0.1.5 * Copyright (c) 2014 Lauris Dzilums * Licensed under MIT */ @@ -15,6 +15,7 @@ }; plugin.isEditing = false; + plugin.$prevRow = null; $.fn.isOnScreen = function(){ @@ -36,20 +37,28 @@ }; $.fn.setActiveCell = function () { - $("tr", plugin.$el).removeClass("activeRow"); + plugin.$prevRow = $("tr>.activeCell", plugin.$el).parent("tr"); + plugin.$prevRow.removeClass("activeRow"); + $("tr>.activeCell", plugin.$el).removeClass("activeCell"); $(this).addClass("activeCell"); $(this).parent("tr").addClass("activeRow"); // trigger cell:select event plugin.events.trigger("cell:select", $(this)); + + if (plugin.$prevRow.index() !== $(this).parent("tr").index()) { + plugin.events.trigger("row:select", $(this).parent("tr")); + if (plugin.$prevRow.hasClass("sensei-grid-dirty-row") && plugin.isEditing) { + plugin.events.trigger("row:save", plugin.getRowData(plugin.$prevRow), plugin.$prevRow, "row:select"); + } + } }; // fixes inconsistent position in firefox/chrome // for this to work a div is needed inside table cell $.fn.cellPosition = function () { var pos = $("div", this).position(); - console.log("cell pos", pos); pos.left = Math.round(pos.left); pos.top = Math.round(pos.top); var paddingH = $(this).outerWidth() - $(this).width(); @@ -71,7 +80,6 @@ if (_.has(this._events, event)) { var events = this._events[event]; _.each(events, function (e) { - console.log("trigger event", event, e); var cbk = _.bind(e["callback"], e["context"]); cbk.apply(this, args); }); @@ -89,8 +97,6 @@ }; plugin.render = function () { - console.log("render"); - plugin.renderBaseTable(); plugin.renderColumns(); plugin.renderData(); @@ -128,7 +134,6 @@ plugin.editorBlur = function (e) { if(plugin.$el.has($(e.target)).length === 0) { - console.log("editorBlur -> is grid event:", plugin.$el.has($(e.target)).length); plugin.exitEditor(); plugin.deactivateCell(); } @@ -138,15 +143,11 @@ $(".sensei-grid-editor", plugin.$el).hide(); }; - plugin.blur = function (e) { + plugin.blur = function () { // check if focus has moved to editor - console.log("blur", e.relatedTarget); // e.relatedTarget && plugin.$el.has($(e.relatedTarget)) // not firefox compatible - if (plugin.isEditing) { - console.log("focus moved to editor"); - } else { - console.log("grid blur, focus not on editor"); + if (!plugin.isEditing) { plugin.exitEditor(); plugin.isEditing = false; plugin.deactivateCell(); @@ -276,11 +277,18 @@ return $("td.activeCell", plugin.$el); }; + plugin.setRowSaved = function ($row) { + $row.removeClass("sensei-grid-dirty-row").removeClass("sensei-grid-empty-row"); + $row.find(">td").data("saved", true); + }; + plugin.deactivateCell = function () { - console.log("deactivateCell"); var $td = plugin.getActiveCell(); $td.removeClass("activeCell"); $td.parent("tr").removeClass("activeRow"); + + // trigger cell:deactivate event + plugin.events.trigger("cell:deactivate", $td); }; plugin.clearActiveCell = function () { @@ -327,7 +335,6 @@ var $td = plugin.getActiveCell(); - console.log("left"); if ($td.prev().length > 0) { $td.prev().setActiveCell(); } else { @@ -369,7 +376,6 @@ if (plugin.isEditing) { // show editor for currently active cell - console.log("move -> edit cell", plugin.getActiveCell()); plugin.editCell(); } @@ -389,7 +395,6 @@ plugin.editCell = function () { // currently this function is just a wrapper around showEditor - console.log("editCell"); plugin.showEditor(); }; @@ -403,7 +408,6 @@ var editorName = $td.data("editor"); if (editorName && _.has(plugin.editors, editorName)) { - console.log("getEditor", editorName); return plugin.editors[editorName]; } else { throw Error("Editor not found: " + editorName); @@ -411,7 +415,6 @@ }; plugin.saveEditor = function () { - console.log("save editor"); // save editor if is active if (plugin.isEditing) { @@ -431,8 +434,11 @@ // remove empty row status from current row and assure that // there is at least one empty row at the end of table - $td.parent("tr").removeClass("sensei-grid-empty-row"); - plugin.assureEmptyRow(); + var $tr = $td.parent("tr"); + if ($tr.hasClass("sensei-grid-empty-row")) { + $tr.removeClass("sensei-grid-empty-row").addClass("sensei-grid-dirty-row"); + plugin.assureEmptyRow(); + } } } @@ -449,18 +455,23 @@ }; plugin.exitEditor = function (skipSave) { - console.log("exit editor"); var $td = plugin.getActiveCell(); if (plugin.isEditing && plugin.activeEditor) { if (!skipSave) { plugin.saveEditor(); + + var $row = $td.parent("tr"); + // if the row was dirty, save it as a whole + if ($row.hasClass("sensei-grid-dirty-row") && plugin.isEditing) { + plugin.events.trigger("row:save", plugin.getRowData($row), $row, "editor:close"); + } + } else { plugin.getEditor().hide(); } } // need to regain focus - console.log("need to regain focus on sensei-grid"); $td.setActiveCell(); plugin.$el.focus(); @@ -470,15 +481,12 @@ plugin.moveEditor = function () { if (plugin.isEditing) { plugin.showEditor(); - console.log("editor is visible, move along"); plugin.editCell(); // previously editCell was called with plugin.getActiveCell } }; plugin.showEditor = function () { - console.log("show editor"); - // set active editor instance plugin.activeEditor = plugin.getEditorInstance(); @@ -490,6 +498,11 @@ // set editing mode after we have gotten active cell plugin.isEditing = true; + // check if we need to save a dirty row +// if (plugin.$prevRow.hasClass("sensei-grid-dirty-row")) { +// plugin.events.trigger("row:save", plugin.getRowData(plugin.$prevRow), plugin.$prevRow, "editor:show"); +// } + // show editor and set correct position $editor.show(); $editor.css($td.cellPosition()); @@ -582,7 +595,6 @@ plugin.clickCell = function (e) { e.preventDefault(); - console.log("clicked cell"); if (plugin.isEditing) { plugin.exitEditor(); } @@ -591,14 +603,11 @@ plugin.dblClickCell = function (e) { e.preventDefault(); - console.log("double clicked cell"); $(this).setActiveCell(); plugin.editCell(); }; plugin.renderColumns = function () { - console.log("renderColumns"); - var $thead = $("thead", plugin.$el); var tr = document.createElement("tr"); _.each(plugin.columns, function (column) { @@ -621,8 +630,6 @@ }; plugin.renderData = function () { - console.log("renderData"); - var $tbody = $("tbody", plugin.$el); _.each(plugin.data, function (item) { var tr = plugin.renderRow(item, true); @@ -663,8 +670,6 @@ }; plugin.renderBaseTable = function () { - console.log("renderBaseTable"); - var table = document.createElement("table"); var thead = document.createElement("thead"); var tbody = document.createElement("tbody"); @@ -678,7 +683,6 @@ }; plugin.init = function (data, columns, options) { - console.log("sensei grid init"); plugin.config = $.extend({}, defaults, options); plugin.data = data; plugin.columns = columns; @@ -730,16 +734,15 @@ this.getElement().show(); }; Editor.prototype.hide = function () { - console.log("Editor hide"); this.getElement().hide(); this.grid.activeEditor.activeCell = null; this.grid.activeEditor = null; }; Editor.prototype.getValue = function () { - console.warn("Editor.getValue not implemented"); + throw Error("Editor.getValue not implemented"); }; Editor.prototype.setValue = function () { - console.warn("Editor.setValue not implemented"); + throw Error("Editor.setValue not implemented"); }; // export editor @@ -749,8 +752,6 @@ types: [], name: "BasicEditor", render: function () { - console.log("BasicEditor.render"); - if (!this.editor) { this.editor = document.createElement("div"); this.editor.className = "sensei-grid-editor sensei-grid-basic-editor"; diff --git a/dist/sensei-grid.min.css b/dist/sensei-grid.min.css index 74da68a..d191023 100644 --- a/dist/sensei-grid.min.css +++ b/dist/sensei-grid.min.css @@ -1 +1 @@ -.sensei-grid{outline:0}.sensei-grid,.sensei-grid-editor input,.sensei-grid-editor select{font:14px Helvetica,Arial,sans-serif;line-height:20px}.sensei-grid *{box-sizing:border-box}.sensei-grid table{border-spacing:0;border-collapse:collapse;width:100%;table-layout:fixed;empty-cells:show;border:1px solid #ddd}.sensei-grid table td,.sensei-grid table th{overflow:hidden;white-space:nowrap;border:1px solid #ddd;text-align:left;padding:5px 7px;vertical-align:top;height:31px}.sensei-grid thead{background:#F5F5F5}.sensei-grid thead>tr>th{vertical-align:bottom;border-bottom-width:1px;font-weight:700}.sensei-grid .activeCell{background:#d0e9f8;border:1px double #39f}.sensei-grid .activeRow{background:#eff7fc}.sensei-grid-editor{position:absolute;background:#fff;border:2px solid #39f;box-shadow:2px 2px 2px rgba(0,0,0,.1)}.sensei-grid-editor input,.sensei-grid-editor select{border:none;width:100%;height:100%;box-shadow:none;outline:0;padding:5px 6px;background:#fff}.sensei-grid th.sensei-grid-sortable{cursor:pointer;user-select:none;-webkit-user-select:none} \ No newline at end of file +.sensei-grid{outline:0}.sensei-grid,.sensei-grid-editor input,.sensei-grid-editor select{font:14px Helvetica,Arial,sans-serif;line-height:20px}.sensei-grid *{box-sizing:border-box}.sensei-grid table{border-spacing:0;border-collapse:collapse;width:100%;table-layout:fixed;empty-cells:show;border:1px solid #ddd}.sensei-grid table td,.sensei-grid table th{overflow:hidden;white-space:nowrap;border:1px solid #ddd;text-align:left;padding:5px 7px;vertical-align:top;height:31px}.sensei-grid thead{background:#F5F5F5}.sensei-grid thead>tr>th{vertical-align:bottom;border-bottom-width:1px;font-weight:700}.sensei-grid .activeCell{background:#d0e9f8;border:1px double #39f}.sensei-grid .activeRow{background:#eff7fc}.sensei-grid .sensei-grid-dirty-row{color:gray}.sensei-grid-editor{position:absolute;background:#fff;border:2px solid #39f;box-shadow:2px 2px 2px rgba(0,0,0,.1)}.sensei-grid-editor input,.sensei-grid-editor select{border:none;width:100%;height:100%;box-shadow:none;outline:0;padding:5px 6px;background:#fff}.sensei-grid th.sensei-grid-sortable{cursor:pointer;user-select:none;-webkit-user-select:none} \ No newline at end of file diff --git a/dist/sensei-grid.min.js b/dist/sensei-grid.min.js index bed5b82..979ec85 100644 --- a/dist/sensei-grid.min.js +++ b/dist/sensei-grid.min.js @@ -1,6 +1,6 @@ /** - * sensei-grid v0.1.4 + * sensei-grid v0.1.5 * Copyright (c) 2014 Lauris Dzilums * Licensed under MIT */ -!function(a){a.fn.grid=function(b,c,d){var e=this,f={emptyRow:!1,sortable:!0,tableClass:""};return e.isEditing=!1,a.fn.isOnScreen=function(){var b=a(window),c={top:b.scrollTop(),left:b.scrollLeft()};c.right=c.left+b.width(),c.bottom=c.top+b.height();var d=this.offset();return d.right=d.left+this.outerWidth(),d.bottom=d.top+this.outerHeight(),!(c.rightd.right||c.bottomd.bottom)},a.fn.setActiveCell=function(){a("tr",e.$el).removeClass("activeRow"),a("tr>.activeCell",e.$el).removeClass("activeCell"),a(this).addClass("activeCell"),a(this).parent("tr").addClass("activeRow"),e.events.trigger("cell:select",a(this))},a.fn.cellPosition=function(){var b=a("div",this).position();console.log("cell pos",b),b.left=Math.round(b.left),b.top=Math.round(b.top);var c=a(this).outerWidth()-a(this).width(),d=a(this).outerHeight()-a(this).height();return b.top-=Math.round(d/2),b.left-=Math.round(c/2),b},e.events={_events:{}},e.events.on=function(a,b,c){_.has(this._events,a)||(this._events[a]=[]),this._events[a].push({callback:b,context:c})},e.events.trigger=function(a){var b=Array.prototype.slice.call(arguments,1);if(_.has(this._events,a)){var c=this._events[a];_.each(c,function(c){console.log("trigger event",a,c);var d=_.bind(c.callback,c.context);d.apply(this,b)})}},e.events.off=function(a){_.has(this._events,a)&&delete this._events[a]},e.registerEditor=function(a){var b=new a(e);e.editors[b.name]=b},e.render=function(){console.log("render"),e.renderBaseTable(),e.renderColumns(),e.renderData(),_.each(e.editors,function(a){a.initialize(),a.render(),a.getElement().hide()}),e.bindEvents()},e.destroy=function(){e.unbindEvents(),e.$el.remove()},e.bindEvents=function(){e.$el.on("click","tr>td",e.clickCell),e.$el.on("dblclick","tr>td",e.dblClickCell),e.$el.on("blur",e.blur),e.$el.on("keydown",e.keydown),a(document).on("click",e.editorBlur)},e.unbindEvents=function(){e.$el.off("click","tr>td"),e.$el.off("dblclick","tr>td"),e.$el.off("blur"),e.$el.off("keydown"),a(document).off("click")},e.editorBlur=function(b){0===e.$el.has(a(b.target)).length&&(console.log("editorBlur -> is grid event:",e.$el.has(a(b.target)).length),e.exitEditor(),e.deactivateCell())},e.hideEditors=function(){a(".sensei-grid-editor",e.$el).hide()},e.blur=function(a){console.log("blur",a.relatedTarget),e.isEditing?console.log("focus moved to editor"):(console.log("grid blur, focus not on editor"),e.exitEditor(),e.isEditing=!1,e.deactivateCell())},e.parsers={},e.parsers.string=function(a){return a.toString()},e.parsers["int"]=function(a){return parseInt(a)},e.parsers["float"]=function(a){return parseFloat(a)},e.getCellData=function(a){var b=a.text(),c=e.getCellType(a);return _.has(e.parsers,c)&&(b=e.parsers[c](b)),b},e.getCellColumn=function(a){return a.data("column")},e.getCellType=function(a){return a.data("type")},e.getCellStatus=function(a){return!!a.data("saved")},e.getCellDataByIndex=function(a,b){var c=e.getRowByIndex(a),d=e.getCellFromRowByIndex(c,b);return e.getCellData(d)},e.getCellDataByKey=function(a,b){var c=e.getRowByIndex(a),d=e.getCellFromRowByKey(c,b);return e.getCellData(d)},e.getCellFromRowByIndex=function(a,b){var c=a.find("td").eq(b);if(0===c.length)throw new Error("Cell does not exist");return c},e.getCellFromRowByKey=function(b,c){var d=b.find("td").filter(function(){return a(this).data("column")===c});if(0===d.length)throw new Error("Cell does not exist");return d},e.getRowCellsByIndex=function(a){return e.getRowByIndex(a).find("td")},e.getRowCells=function(a){return a.find("td")},e.getRowByIndex=function(a){var b=e.$el.find("tbody>tr").eq(a);if(0===b.length)throw new Error("Row does not exist");return b},e.getRowDataByIndex=function(a){var b=e.getRowByIndex(a);return e.getRowData(b)},e.getRowData=function(b){var c=e.getRowCells(b),d={};return c.each(function(){d[e.getCellColumn(a(this))]=e.getCellData(a(this))}),d},e.getRows=function(){return e.$el.find("tbody>tr")},e.getGridData=function(){var b=e.getRows();return b.map(function(){return e.getRowData(a(this))}).get()},e.getActiveCell=function(){return e.isEditing&&e.activeEditor&&e.activeEditor.activeCell?e.activeEditor.activeCell:a("td.activeCell",e.$el)},e.deactivateCell=function(){console.log("deactivateCell");var a=e.getActiveCell();a.removeClass("activeCell"),a.parent("tr").removeClass("activeRow")},e.clearActiveCell=function(){var b=e.getActiveCell(),c=e.getCellData(b);a(">div",b).empty(),e.events.trigger("cell:clear",c,b)},e.moveRight=function(){var b=e.getActiveCell();if(b.next().length>0)b.next().setActiveCell();else{var c=b.parent("tr").next();c.length>0&&a("td:first",c).setActiveCell()}},e.moveUp=function(){var b=e.getActiveCell(),c=b.parent("tr").prev();if(c.length>0){var d=b.index(),f=a("td",c).eq(d);f.length>0?f.setActiveCell():a("td:last",c).setActiveCell()}},e.moveLeft=function(){var b=e.getActiveCell();if(console.log("left"),b.prev().length>0)b.prev().setActiveCell();else{var c=b.parent("tr").prev();c.length>0&&a("td:last",c).setActiveCell()}},e.moveDown=function(){var b=e.getActiveCell(),c=b.parent("tr").next();if(c.length>0){var d=b.index(),f=a("td",c).eq(d);f.length>0?f.setActiveCell():a("td:first",c).setActiveCell()}},e.move=function(a){var b="move"+a.charAt(0).toUpperCase()+a.substr(1);_.has(e,b)?(e[b](),e.isEditing&&e.saveEditor(),e.isEditing&&(console.log("move -> edit cell",e.getActiveCell()),e.editCell()),e.getActiveCell().find(">div").isOnScreen()||e.getActiveCell().get(0).scrollIntoView(_.contains(["up","left"],a)?!0:!1)):console.warn("move method not found",b)},e.editCell=function(){console.log("editCell"),e.showEditor()},e.getEditor=function(){return e.activeEditor},e.getEditorInstance=function(){var a=e.getActiveCell(),b=a.data("editor");if(b&&_.has(e.editors,b))return console.log("getEditor",b),e.editors[b];throw Error("Editor not found: "+b)},e.saveEditor=function(){if(console.log("save editor"),e.isEditing){var b=e.getActiveCell(),c=e.activeEditor.getValue();if(c!==b.text()){b.html(a("
").text(c));var d={};d[b.data("column")]=c,e.events.trigger("editor:save",d,b),b.parent("tr").removeClass("sensei-grid-empty-row"),e.assureEmptyRow()}}e.getEditor().hide()},e.assureEmptyRow=function(){if(e.config.emptyRow&&0===e.$el.find("table>tbody>tr.sensei-grid-empty-row").length){var a=e.$el.find("table>tbody"),b=e.renderRow(null,!1);a.append(b)}},e.exitEditor=function(a){console.log("exit editor");var b=e.getActiveCell();e.isEditing&&e.activeEditor&&(a?e.getEditor().hide():e.saveEditor()),console.log("need to regain focus on sensei-grid"),b.setActiveCell(),e.$el.focus(),e.isEditing=!1},e.moveEditor=function(){e.isEditing&&(e.showEditor(),console.log("editor is visible, move along"),e.editCell())},e.showEditor=function(){console.log("show editor"),e.activeEditor=e.getEditorInstance();var a=e.activeEditor.getElement(),b=e.getActiveCell();e.activeEditor.activeCell=b,e.isEditing=!0,a.show(),a.css(b.cellPosition()),a.css({width:b.outerWidth()+1,height:b.outerHeight()+1});var c=b.data("column"),d=b.text();e.activeEditor.setValue(d);var f={};return f[c]=d,e.events.trigger("editor:load",f,b),a},e.keydown=function(a){var b=!0,c=[8,9,13,27,37,38,39,40],d=[8,37,38,39,40];if(!(0===e.getActiveCell().length&&!e.isEditing||!_.contains(c,a.which)||e.isEditing&&_.contains(d,a.which))){switch(a.preventDefault(),a.which){case 37:e.move("left");break;case 38:e.move("up");break;case 39:e.move("right");break;case 40:e.move("down");break;case 13:e.isEditing?a.ctrlKey&&a.shiftKey?e.move("up"):a.ctrlKey&&!a.shiftKey?e.move("down"):e.exitEditor():e.editCell();break;case 27:e.isEditing?e.exitEditor(!0):e.$el.blur();break;case 9:e.move(a.shiftKey?"left":"right");break;case 8:e.clearActiveCell()}b&&a.preventDefault()}},e.clickCell=function(b){b.preventDefault(),console.log("clicked cell"),e.isEditing&&e.exitEditor(),a(this).setActiveCell()},e.dblClickCell=function(b){b.preventDefault(),console.log("double clicked cell"),a(this).setActiveCell(),e.editCell()},e.renderColumns=function(){console.log("renderColumns");var b=a("thead",e.$el),c=document.createElement("tr");_.each(e.columns,function(b){var d=document.createElement("th"),f=document.createElement("div");e.config.sortable&&(d.className="sensei-grid-sortable"),a(f).text(b.name),d.appendChild(f),a(d).data("type",b.type||"string"),a(d).data("editor",b.editor||"BasicEditor"),c.appendChild(d)}),b.append(c)},e.renderData=function(){console.log("renderData");var b=a("tbody",e.$el);if(_.each(e.data,function(a){var c=e.renderRow(a,!0);b.append(c)}),e.config.emptyRow){var c=e.renderRow(null,!1);b.append(c)}},e.renderRow=function(b,c){var d=document.createElement("tr");return c||(d.className="sensei-grid-empty-row"),_.each(e.columns,function(e){var f=document.createElement("td"),g=document.createElement("div");_.has(b,e.name)&&a(g).text(b[e.name]),a(f).data("column",e.name),a(f).data("type",e.type||"string"),a(f).data("editor",e.editor||"BasicEditor"),a(f).data("saved",c),f.appendChild(g),d.appendChild(f)}),d},e.renderBaseTable=function(){console.log("renderBaseTable");var a=document.createElement("table"),b=document.createElement("thead"),c=document.createElement("tbody");a.appendChild(b),a.appendChild(c),a.className=e.config.tableClass,e.$el.html(a),e.$el.attr("tabindex",-1)},e.init=function(b,c,d){return console.log("sensei grid init"),e.config=a.extend({},f,d),e.data=b,e.columns=c,e.$el=a(this),e.editors={},e},e.init(b,c,d)}}(jQuery),function(a){var b=this,c=function(a){this.grid=a};c.extend=function(a){var b,c=this;b=function(){return c.apply(this,arguments)};var d=function(){this.constructor=b};return d.prototype=c.prototype,b.prototype=new d,a&&_.extend(b.prototype,a),b.__super__=c.prototype,b},c.prototype.getElement=function(){return a(this.editor)},c.prototype.initialize=function(){},c.prototype.render=function(){},c.prototype.show=function(){this.getElement().show()},c.prototype.hide=function(){console.log("Editor hide"),this.getElement().hide(),this.grid.activeEditor.activeCell=null,this.grid.activeEditor=null},c.prototype.getValue=function(){console.warn("Editor.getValue not implemented")},c.prototype.setValue=function(){console.warn("Editor.setValue not implemented")},b.Editor=c,b.BasicEditor=c.extend({types:[],name:"BasicEditor",render:function(){if(console.log("BasicEditor.render"),!this.editor){this.editor=document.createElement("div"),this.editor.className="sensei-grid-editor sensei-grid-basic-editor";var a=document.createElement("input");this.editor.appendChild(a),this.grid.$el.append(this.editor)}},getValue:function(){return a("input",this.editor).val()},setValue:function(b){a("input",this.editor).val(b).focus()}})}(jQuery); \ No newline at end of file +!function(a){a.fn.grid=function(b,c,d){var e=this,f={emptyRow:!1,sortable:!0,tableClass:""};return e.isEditing=!1,e.$prevRow=null,a.fn.isOnScreen=function(){var b=a(window),c={top:b.scrollTop(),left:b.scrollLeft()};c.right=c.left+b.width(),c.bottom=c.top+b.height();var d=this.offset();return d.right=d.left+this.outerWidth(),d.bottom=d.top+this.outerHeight(),!(c.rightd.right||c.bottomd.bottom)},a.fn.setActiveCell=function(){e.$prevRow=a("tr>.activeCell",e.$el).parent("tr"),e.$prevRow.removeClass("activeRow"),a("tr>.activeCell",e.$el).removeClass("activeCell"),a(this).addClass("activeCell"),a(this).parent("tr").addClass("activeRow"),e.events.trigger("cell:select",a(this)),e.$prevRow.index()!==a(this).parent("tr").index()&&(e.events.trigger("row:select",a(this).parent("tr")),e.$prevRow.hasClass("sensei-grid-dirty-row")&&e.isEditing&&e.events.trigger("row:save",e.getRowData(e.$prevRow),e.$prevRow,"row:select"))},a.fn.cellPosition=function(){var b=a("div",this).position();b.left=Math.round(b.left),b.top=Math.round(b.top);var c=a(this).outerWidth()-a(this).width(),d=a(this).outerHeight()-a(this).height();return b.top-=Math.round(d/2),b.left-=Math.round(c/2),b},e.events={_events:{}},e.events.on=function(a,b,c){_.has(this._events,a)||(this._events[a]=[]),this._events[a].push({callback:b,context:c})},e.events.trigger=function(a){var b=Array.prototype.slice.call(arguments,1);if(_.has(this._events,a)){var c=this._events[a];_.each(c,function(a){var c=_.bind(a.callback,a.context);c.apply(this,b)})}},e.events.off=function(a){_.has(this._events,a)&&delete this._events[a]},e.registerEditor=function(a){var b=new a(e);e.editors[b.name]=b},e.render=function(){e.renderBaseTable(),e.renderColumns(),e.renderData(),_.each(e.editors,function(a){a.initialize(),a.render(),a.getElement().hide()}),e.bindEvents()},e.destroy=function(){e.unbindEvents(),e.$el.remove()},e.bindEvents=function(){e.$el.on("click","tr>td",e.clickCell),e.$el.on("dblclick","tr>td",e.dblClickCell),e.$el.on("blur",e.blur),e.$el.on("keydown",e.keydown),a(document).on("click",e.editorBlur)},e.unbindEvents=function(){e.$el.off("click","tr>td"),e.$el.off("dblclick","tr>td"),e.$el.off("blur"),e.$el.off("keydown"),a(document).off("click")},e.editorBlur=function(b){0===e.$el.has(a(b.target)).length&&(e.exitEditor(),e.deactivateCell())},e.hideEditors=function(){a(".sensei-grid-editor",e.$el).hide()},e.blur=function(){e.isEditing||(e.exitEditor(),e.isEditing=!1,e.deactivateCell())},e.parsers={},e.parsers.string=function(a){return a.toString()},e.parsers["int"]=function(a){return parseInt(a)},e.parsers["float"]=function(a){return parseFloat(a)},e.getCellData=function(a){var b=a.text(),c=e.getCellType(a);return _.has(e.parsers,c)&&(b=e.parsers[c](b)),b},e.getCellColumn=function(a){return a.data("column")},e.getCellType=function(a){return a.data("type")},e.getCellStatus=function(a){return!!a.data("saved")},e.getCellDataByIndex=function(a,b){var c=e.getRowByIndex(a),d=e.getCellFromRowByIndex(c,b);return e.getCellData(d)},e.getCellDataByKey=function(a,b){var c=e.getRowByIndex(a),d=e.getCellFromRowByKey(c,b);return e.getCellData(d)},e.getCellFromRowByIndex=function(a,b){var c=a.find("td").eq(b);if(0===c.length)throw new Error("Cell does not exist");return c},e.getCellFromRowByKey=function(b,c){var d=b.find("td").filter(function(){return a(this).data("column")===c});if(0===d.length)throw new Error("Cell does not exist");return d},e.getRowCellsByIndex=function(a){return e.getRowByIndex(a).find("td")},e.getRowCells=function(a){return a.find("td")},e.getRowByIndex=function(a){var b=e.$el.find("tbody>tr").eq(a);if(0===b.length)throw new Error("Row does not exist");return b},e.getRowDataByIndex=function(a){var b=e.getRowByIndex(a);return e.getRowData(b)},e.getRowData=function(b){var c=e.getRowCells(b),d={};return c.each(function(){d[e.getCellColumn(a(this))]=e.getCellData(a(this))}),d},e.getRows=function(){return e.$el.find("tbody>tr")},e.getGridData=function(){var b=e.getRows();return b.map(function(){return e.getRowData(a(this))}).get()},e.getActiveCell=function(){return e.isEditing&&e.activeEditor&&e.activeEditor.activeCell?e.activeEditor.activeCell:a("td.activeCell",e.$el)},e.setRowSaved=function(a){a.removeClass("sensei-grid-dirty-row").removeClass("sensei-grid-empty-row"),a.find(">td").data("saved",!0)},e.deactivateCell=function(){var a=e.getActiveCell();a.removeClass("activeCell"),a.parent("tr").removeClass("activeRow"),e.events.trigger("cell:deactivate",a)},e.clearActiveCell=function(){var b=e.getActiveCell(),c=e.getCellData(b);a(">div",b).empty(),e.events.trigger("cell:clear",c,b)},e.moveRight=function(){var b=e.getActiveCell();if(b.next().length>0)b.next().setActiveCell();else{var c=b.parent("tr").next();c.length>0&&a("td:first",c).setActiveCell()}},e.moveUp=function(){var b=e.getActiveCell(),c=b.parent("tr").prev();if(c.length>0){var d=b.index(),f=a("td",c).eq(d);f.length>0?f.setActiveCell():a("td:last",c).setActiveCell()}},e.moveLeft=function(){var b=e.getActiveCell();if(b.prev().length>0)b.prev().setActiveCell();else{var c=b.parent("tr").prev();c.length>0&&a("td:last",c).setActiveCell()}},e.moveDown=function(){var b=e.getActiveCell(),c=b.parent("tr").next();if(c.length>0){var d=b.index(),f=a("td",c).eq(d);f.length>0?f.setActiveCell():a("td:first",c).setActiveCell()}},e.move=function(a){var b="move"+a.charAt(0).toUpperCase()+a.substr(1);_.has(e,b)?(e[b](),e.isEditing&&e.saveEditor(),e.isEditing&&e.editCell(),e.getActiveCell().find(">div").isOnScreen()||e.getActiveCell().get(0).scrollIntoView(_.contains(["up","left"],a)?!0:!1)):console.warn("move method not found",b)},e.editCell=function(){e.showEditor()},e.getEditor=function(){return e.activeEditor},e.getEditorInstance=function(){var a=e.getActiveCell(),b=a.data("editor");if(b&&_.has(e.editors,b))return e.editors[b];throw Error("Editor not found: "+b)},e.saveEditor=function(){if(e.isEditing){var b=e.getActiveCell(),c=e.activeEditor.getValue();if(c!==b.text()){b.html(a("
").text(c));var d={};d[b.data("column")]=c,e.events.trigger("editor:save",d,b);var f=b.parent("tr");f.hasClass("sensei-grid-empty-row")&&(f.removeClass("sensei-grid-empty-row").addClass("sensei-grid-dirty-row"),e.assureEmptyRow())}}e.getEditor().hide()},e.assureEmptyRow=function(){if(e.config.emptyRow&&0===e.$el.find("table>tbody>tr.sensei-grid-empty-row").length){var a=e.$el.find("table>tbody"),b=e.renderRow(null,!1);a.append(b)}},e.exitEditor=function(a){var b=e.getActiveCell();if(e.isEditing&&e.activeEditor)if(a)e.getEditor().hide();else{e.saveEditor();var c=b.parent("tr");c.hasClass("sensei-grid-dirty-row")&&e.isEditing&&e.events.trigger("row:save",e.getRowData(c),c,"editor:close")}b.setActiveCell(),e.$el.focus(),e.isEditing=!1},e.moveEditor=function(){e.isEditing&&(e.showEditor(),e.editCell())},e.showEditor=function(){e.activeEditor=e.getEditorInstance();var a=e.activeEditor.getElement(),b=e.getActiveCell();e.activeEditor.activeCell=b,e.isEditing=!0,a.show(),a.css(b.cellPosition()),a.css({width:b.outerWidth()+1,height:b.outerHeight()+1});var c=b.data("column"),d=b.text();e.activeEditor.setValue(d);var f={};return f[c]=d,e.events.trigger("editor:load",f,b),a},e.keydown=function(a){var b=!0,c=[8,9,13,27,37,38,39,40],d=[8,37,38,39,40];if(!(0===e.getActiveCell().length&&!e.isEditing||!_.contains(c,a.which)||e.isEditing&&_.contains(d,a.which))){switch(a.preventDefault(),a.which){case 37:e.move("left");break;case 38:e.move("up");break;case 39:e.move("right");break;case 40:e.move("down");break;case 13:e.isEditing?a.ctrlKey&&a.shiftKey?e.move("up"):a.ctrlKey&&!a.shiftKey?e.move("down"):e.exitEditor():e.editCell();break;case 27:e.isEditing?e.exitEditor(!0):e.$el.blur();break;case 9:e.move(a.shiftKey?"left":"right");break;case 8:e.clearActiveCell()}b&&a.preventDefault()}},e.clickCell=function(b){b.preventDefault(),e.isEditing&&e.exitEditor(),a(this).setActiveCell()},e.dblClickCell=function(b){b.preventDefault(),a(this).setActiveCell(),e.editCell()},e.renderColumns=function(){var b=a("thead",e.$el),c=document.createElement("tr");_.each(e.columns,function(b){var d=document.createElement("th"),f=document.createElement("div");e.config.sortable&&(d.className="sensei-grid-sortable"),a(f).text(b.name),d.appendChild(f),a(d).data("type",b.type||"string"),a(d).data("editor",b.editor||"BasicEditor"),c.appendChild(d)}),b.append(c)},e.renderData=function(){var b=a("tbody",e.$el);if(_.each(e.data,function(a){var c=e.renderRow(a,!0);b.append(c)}),e.config.emptyRow){var c=e.renderRow(null,!1);b.append(c)}},e.renderRow=function(b,c){var d=document.createElement("tr");return c||(d.className="sensei-grid-empty-row"),_.each(e.columns,function(e){var f=document.createElement("td"),g=document.createElement("div");_.has(b,e.name)&&a(g).text(b[e.name]),a(f).data("column",e.name),a(f).data("type",e.type||"string"),a(f).data("editor",e.editor||"BasicEditor"),a(f).data("saved",c),f.appendChild(g),d.appendChild(f)}),d},e.renderBaseTable=function(){var a=document.createElement("table"),b=document.createElement("thead"),c=document.createElement("tbody");a.appendChild(b),a.appendChild(c),a.className=e.config.tableClass,e.$el.html(a),e.$el.attr("tabindex",-1)},e.init=function(b,c,d){return e.config=a.extend({},f,d),e.data=b,e.columns=c,e.$el=a(this),e.editors={},e},e.init(b,c,d)}}(jQuery),function(a){var b=this,c=function(a){this.grid=a};c.extend=function(a){var b,c=this;b=function(){return c.apply(this,arguments)};var d=function(){this.constructor=b};return d.prototype=c.prototype,b.prototype=new d,a&&_.extend(b.prototype,a),b.__super__=c.prototype,b},c.prototype.getElement=function(){return a(this.editor)},c.prototype.initialize=function(){},c.prototype.render=function(){},c.prototype.show=function(){this.getElement().show()},c.prototype.hide=function(){this.getElement().hide(),this.grid.activeEditor.activeCell=null,this.grid.activeEditor=null},c.prototype.getValue=function(){throw Error("Editor.getValue not implemented")},c.prototype.setValue=function(){throw Error("Editor.setValue not implemented")},b.Editor=c,b.BasicEditor=c.extend({types:[],name:"BasicEditor",render:function(){if(!this.editor){this.editor=document.createElement("div"),this.editor.className="sensei-grid-editor sensei-grid-basic-editor";var a=document.createElement("input");this.editor.appendChild(a),this.grid.$el.append(this.editor)}},getValue:function(){return a("input",this.editor).val()},setValue:function(b){a("input",this.editor).val(b).focus()}})}(jQuery); \ No newline at end of file diff --git a/package.json b/package.json index 926a689..1873f12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sensei-grid", - "version": "0.1.4", + "version": "0.1.5", "description": "Simple data grid in JavaScript/HTML.", "main": "index.js", "directories": {