123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- define(["dojo/_base/kernel", "dojo/_base/array", "dojo/on", "dojo/aspect", "dojo/_base/sniff", "put-selector/put"],
- function(kernel, arrayUtil, on, aspect, has, put){
- return function(column, type){
-
- var listeners = [],
- grid, headerCheckbox;
-
- if(!column){ column = {}; }
-
- if(column.type){
- column.selectorType = column.type;
- kernel.deprecated("columndef.type", "use columndef.selectorType instead", "dgrid 0.4");
- }
- // accept type as argument to Selector function, or from column def
- column.selectorType = type = type || column.selectorType || "checkbox";
- column.sortable = false;
- function disabled(item) {
- return !grid.allowSelect(grid.row(item));
- }
-
- function changeInput(value){
- // creates a function that modifies the input on an event
- return function(event){
- var rows = event.rows,
- len = rows.length,
- state = "false",
- selection, mixed, i;
-
- for(i = 0; i < len; i++){
- var element = grid.cell(rows[i], column.id).element;
- if(!element){ continue; } // skip if row has been entirely removed
- element = (element.contents || element).input;
- if(element && !element.disabled){
- // only change the value if it is not disabled
- element.checked = value;
- element.setAttribute("aria-checked", value);
- }
- }
- if(headerCheckbox.type == "checkbox"){
- selection = grid.selection;
- mixed = false;
- // see if the header checkbox needs to be indeterminate
- for(i in selection){
- // if there is anything in the selection, than it is indeterminate
- if(selection[i] != grid.allSelected){
- mixed = true;
- break;
- }
- }
- headerCheckbox.indeterminate = mixed;
- headerCheckbox.checked = grid.allSelected;
- if (mixed) {
- state = "mixed";
- } else if (grid.allSelected) {
- state = "true";
- }
- headerCheckbox.setAttribute("aria-checked", state);
- }
- };
- }
-
- function onSelect(event){
- // we would really only care about click, since other input sources, like spacebar
- // trigger a click, but the click event doesn't provide access to the shift key in firefox, so
- // listen for keydown's as well to get an event in firefox that we can properly retrieve
- // the shiftKey property from
- if(event.type == "click" || event.keyCode == 32 || (!has("opera") && event.keyCode == 13) || event.keyCode === 0){
- var row = grid.row(event),
- lastRow = grid._lastSelected && grid.row(grid._lastSelected);
- grid._selectionTriggerEvent = event;
-
- if(type == "radio"){
- if(!lastRow || lastRow.id != row.id){
- grid.clearSelection();
- grid.select(row, null, true);
- grid._lastSelected = row.element;
- }
- }else{
- if(row){
- if(event.shiftKey){
- // make sure the last input always ends up checked for shift key
- changeInput(true)({rows: [row]});
- }else{
- // no shift key, so no range selection
- lastRow = null;
- }
- lastRow = event.shiftKey ? lastRow : null;
- grid.select(lastRow || row, row, lastRow ? undefined : null);
- grid._lastSelected = row.element;
- }else{
- // No row resolved; must be the select-all checkbox.
- put(this, (grid.allSelected ? "!" : ".") + "dgrid-select-all");
- grid[grid.allSelected ? "clearSelection" : "selectAll"]();
- }
- }
- grid._selectionTriggerEvent = null;
- }
- }
-
- function setupSelectionEvents(){
- // register one listener at the top level that receives events delegated
- grid._hasSelectorInputListener = true;
- listeners.push(grid.on(".dgrid-selector:click,.dgrid-selector:keydown", onSelect));
- var handleSelect = grid._handleSelect;
- grid._handleSelect = function(event){
- // ignore the default select handler for events that originate from the selector column
- if(this.cell(event).column != column){
- handleSelect.apply(this, arguments);
- }
- };
-
- // Set up disabled and grid.allowSelect to match each other's behaviors
- if(typeof column.disabled == "function"){
- var originalAllowSelect = grid.allowSelect,
- originalDisabled = column.disabled;
- // Wrap allowSelect to consult both the original allowSelect and disabled
- grid.allowSelect = function(row){
- var allow = originalAllowSelect.call(this, row);
- if (originalDisabled === disabled) {
- return allow;
- } else {
- return allow && !originalDisabled.call(column, row.data);
- }
- };
- // Then wrap disabled to simply call the new allowSelect
- column.disabled = disabled;
- }else{
- // If no disabled function was specified, institute a default one
- // which honors allowSelect
- column.disabled = disabled;
- }
- // register listeners to the select and deselect events to change the input checked value
- listeners.push(grid.on("dgrid-select", changeInput(true)));
- listeners.push(grid.on("dgrid-deselect", changeInput(false)));
- }
-
- var renderInput = typeof type == "function" ? type : function(value, cell, object){
- var parent = cell.parentNode,
- disabled;
-
- if(!grid._hasSelectorInputListener){
- setupSelectionEvents();
- }
-
- // column.disabled gets initialized or wrapped in setupSelectionEvents
- disabled = column.disabled;
- // must set the class name on the outer cell in IE for keystrokes to be intercepted
- put(parent && parent.contents ? parent : cell, ".dgrid-selector");
- var input = cell.input || (cell.input = put(cell, "input[type="+type + "]", {
- tabIndex: isNaN(column.tabIndex) ? -1 : column.tabIndex,
- disabled: disabled && (typeof disabled == "function" ?
- disabled.call(column, object) : disabled),
- checked: value
- }));
- input.setAttribute("aria-checked", !!value);
-
- return input;
- };
-
- aspect.after(column, "init", function(){
- grid = column.grid;
- });
-
- aspect.after(column, "destroy", function(){
- arrayUtil.forEach(listeners, function(l){ l.remove(); });
- grid._hasSelectorInputListener = false;
- });
-
- column.renderCell = function(object, value, cell, options, header){
- var row = object && grid.row(object);
- value = row && grid.selection[row.id];
- renderInput(value, cell, object);
- };
- column.renderHeaderCell = function(th){
- var label = "label" in column ? column.label :
- column.field || "";
-
- if(type == "radio" || !grid.allowSelectAll){
- th.appendChild(document.createTextNode(label));
- if(!grid._hasSelectorInputListener){
- setupSelectionEvents();
- }
- }else{
- renderInput(false, th, {});
- }
- headerCheckbox = th.lastChild;
- };
-
- return column;
- };
- });
|