From 66897c06bd4a577251e5c9975ad1545480fe4f65 Mon Sep 17 00:00:00 2001 From: Nicolas Badia Date: Thu, 23 Jun 2016 10:34:16 +0200 Subject: [PATCH 1/3] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 8ba45bc..72bb2c3 100755 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ + +# The repository has been moved to: https://github.com/sproutcore/sproutcore-table +------ + #Overview This is a table view for [Sproutcore](http://www.github.com/sproutcore/sproutcore). From 77fd7306a5612e9fc3d898db417c63d7e39e523e Mon Sep 17 00:00:00 2001 From: Maurits Lamers Date: Fri, 14 Oct 2016 22:05:30 +0200 Subject: [PATCH 2/3] This fixes the problem that multiple checkboxes were not handled seperately. --- views/table_row.js | 208 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 197 insertions(+), 11 deletions(-) diff --git a/views/table_row.js b/views/table_row.js index ca8027b..314e6e1 100755 --- a/views/table_row.js +++ b/views/table_row.js @@ -33,7 +33,7 @@ SC.TableRowView = SC.ListItemView.extend({ return this.getPath('displayDelegate.tableDelegate'); }.property('displayDelegate').cacheable(), - + render: function(context) { var tableDelegate = this.get('tableDelegate'), left = 3, @@ -62,7 +62,7 @@ SC.TableRowView = SC.ListItemView.extend({ if (contentCheckboxKey && contentCheckboxKey.contains(key)) { var value = SC.get(content, key) || false; - this.renderCheckbox(context, value); + this.renderCheckbox(context, value, key); } else { tableDelegate.renderTableCellContent(this, context, content, contentIndex, col, key); @@ -72,6 +72,7 @@ SC.TableRowView = SC.ListItemView.extend({ left += width; } + }, @@ -106,7 +107,7 @@ SC.TableRowView = SC.ListItemView.extend({ if (contentCheckboxKey && contentCheckboxKey.contains(key)) { var value = SC.get(content, key) || false; - this.updateCheckbox($cell, value); + this.updateCheckbox($cell, value, key); } else { tableDelegate.updateTableCellContent(this, $cell, content, contentIndex, col, key); @@ -132,9 +133,12 @@ SC.TableRowView = SC.ListItemView.extend({ var content = this.get('content'); // There may be a memory leak in SC with _checkboxRenderSource - if (this._checkboxRenderSource) { - this._checkboxRenderSource.destroy(); - this._checkboxRenderSource = this._checkboxRenderDelegate = null; + var sources = this._tr_cbSources; + if (sources) { + this.get('contentCheckboxKey').forEach(function(k) { + sources[k].destroy(); + }); + this._tr_cbSources = this._checkboxRenderDelegate = null; } this.updateContentObservers(null, content); @@ -214,15 +218,59 @@ SC.TableRowView = SC.ListItemView.extend({ // CHECKBOX EDTITING // - updateCheckbox: function (jQuery, state) { + /** @private + Adds a checkbox with the appropriate state to the content. This method + will only be called if the list item view is supposed to have a + checkbox. + + @param {SC.RenderContext} context the render context + @param {Boolean} state YES, NO or SC.MIXED_STATE + @returns {void} + */ + renderCheckbox: function (context, state, key) { var renderer = this.get('theme').checkboxRenderDelegate; - var source = this._checkboxRenderSource; + // note: checkbox-view is really not the best thing to do here; we should do + // sc-list-item-checkbox; however, themes expect something different, unfortunately. + context = context.begin('div') + .addClass('sc-checkbox-view') + .addClass('sc-checkbox-view-for-' + key) + .addClass(this.get('theme').classNames) + .addClass(renderer.get('className')); + + var sources = this._tr_cbSources; + if (!sources) { + sources = this._tr_cbSources = {}; + } + + var source = sources[key]; if (!source) { - source = this._checkboxRenderSource = - SC.Object.create({ renderState: {}, theme: this.get('theme') }); + source = sources[key] = SC.Object.create({ + renderState: {}, + theme: this.get('theme') + }); } + + source + .set('controlSize', SC.SMALL_CONTROL_SIZE) + .set('isSelected', state && (state !== SC.MIXED_STATE)) + .set('isEnabled', this.get('isEnabled') && this.get('contentIsEditable')) + .set('isActive', this._checkboxIsActive) + .set('title', ''); + + renderer.render(source, context); + context = context.end(); + + this._checkboxRenderDelegate = renderer; + }, + + + updateCheckbox: function (jQuery, state, key) { + var renderer = this.get('theme').checkboxRenderDelegate; + + var sources = this._tr_cbSources; + var source = sources[key]; source .set('controlSize', SC.SMALL_CONTROL_SIZE) .set('isSelected', state && (state !== SC.MIXED_STATE)) @@ -230,11 +278,149 @@ SC.TableRowView = SC.ListItemView.extend({ .set('isActive', this._checkboxIsActive) .set('title', ''); - renderer.update(source, jQuery.find('.sc-checkbox-view')); + renderer.update(source, jQuery.find('.sc-checkbox-view-for-' + key)); this._checkboxRenderDelegate = renderer; }, + _isInsideCheckbox: function (evt) { + var del = this.displayDelegate; + var checkboxKey = this.getDelegateProperty('contentCheckboxKey', del); + // should be an array as it is set that way through render and update + + return checkboxKey && checkboxKey.find(function (k) { + return this._isInsideElementWithClassName('sc-checkbox-view-for-' + k, evt); + }, this); + }, + + _addCheckboxActiveState: function (key) { + if (this.get('isEnabled')) { + if (this._checkboxRenderDelegate) { + var sources = this._tr_cbSources; + var source = sources[key]; + + source.set('isActive', YES); + + this._checkboxRenderDelegate.update(source, this.$('.sc-checkbox-view-for-' + key)); + } else { + // for backwards-compatibility. + this.$('.sc-checkbox-view-for-' + key).addClass('active'); + } + } + }, + + _removeCheckboxActiveState: function () { + var key = this._isMouseDownOnCheckboxFor; + if (this._checkboxRenderer) { + var sources = this._tr_cbSources; + var source = sources[key]; + + source.set('isActive', NO); + + this._checkboxRenderDelegate.update(source, this.$('.sc-checkbox-view-for-' + key)); + } else { + // for backwards-compatibility. + this.$('.sc-checkbox-view-for-' + key).removeClass('active'); + } + }, + + + /** @private + mouseDown is handled only for clicks on the checkbox view or or action + button. + */ + mouseDown: function (evt) { + // Fast path, reject secondary clicks. + if (evt.which && evt.which !== 1) return false; + + // if content is not editable, then always let collection view handle the + // event. + if (!this.get('contentIsEditable')) return NO; + + // if occurred inside checkbox, item view should handle the event. + var inCheckboxForKey = this._isInsideCheckbox(evt); + if (inCheckboxForKey) { + this._addCheckboxActiveState(inCheckboxForKey); + this._isMouseDownOnCheckbox = YES; + this._isMouseInsideCheckbox = YES; + this._isMouseDownOnCheckboxFor = inCheckboxForKey; + return YES; // listItem should handle this event + } else if (this._isInsideDisclosure(evt)) { + this._addDisclosureActiveState(); + this._isMouseDownOnDisclosure = YES; + this._isMouseInsideDisclosure = YES; + return YES; + } else if (this._isInsideRightIcon(evt)) { + this._addRightIconActiveState(); + this._isMouseDownOnRightIcon = YES; + this._isMouseInsideRightIcon = YES; + return YES; + } + this.displayDidChange(); + return NO; // let the collection view handle this event + }, + + /** @private */ + mouseUp: function (evt) { + var ret = NO; + + // if mouse was down in checkbox -- then handle mouse up, otherwise + // allow parent view to handle event. + if (this._isMouseDownOnCheckbox) { + // update only if mouse inside on mouse up... + var inCheckboxForKey = this._isInsideCheckbox(evt); + if (inCheckboxForKey && inCheckboxForKey === this._isMouseDownOnCheckboxFor) { + this.toggleCheckbox(inCheckboxForKey); + } + + this._removeCheckboxActiveState(); + ret = YES; + + // if mouse as down on disclosure -- handle mouse up. otherwise pass on + // to parent. + } else if (this._isMouseDownOnDisclosure) { + if (this._isInsideDisclosure(evt)) { + this.toggleDisclosure(); + } + + this._removeDisclosureActiveState(); + ret = YES; + // if mouse was down in right icon -- then handle mouse up, otherwise + // allow parent view to handle event. + } else if (this._isMouseDownOnRightIcon) { + this._removeRightIconActiveState(); + ret = YES; + } + + // clear cached info + this._isMouseInsideCheckbox = this._isMouseDownOnCheckbox = NO; + this._isMouseDownOnDisclosure = this._isMouseInsideDisclosure = NO; + this._isMouseInsideRightIcon = this._isMouseDownOnRightIcon = NO; + // this._isMouseDownOnCheckboxFor = null; + + return ret; + }, + + /** @private */ + mouseMoved: function (evt) { + return NO; + }, + + toggleCheckbox: function (key) { + var content = this.get('content'); + //del = this.displayDelegate; + + if (content && content.get) { + var value = content.get(key); + + value = (value === SC.MIXED_STATE) ? YES : !value; + content.set(key, value); // update content + + this.displayDidChange(); // repaint view... + } + + } + }); From 0e3819e90c93f10c2c0c1db5a4f01d563ef507ce Mon Sep 17 00:00:00 2001 From: Maurits Lamers Date: Sun, 16 Oct 2016 20:50:22 +0200 Subject: [PATCH 3/3] make sure clicks on a checkbox which is not part of the editable keys don't result in a toggle --- views/table_row.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/views/table_row.js b/views/table_row.js index 314e6e1..cc6e23d 100755 --- a/views/table_row.js +++ b/views/table_row.js @@ -61,7 +61,7 @@ SC.TableRowView = SC.ListItemView.extend({ context = context.push('
'); if (contentCheckboxKey && contentCheckboxKey.contains(key)) { - var value = SC.get(content, key) || false; + var value = SC.getPath(content, key) || false; this.renderCheckbox(context, value, key); } else { @@ -106,7 +106,7 @@ SC.TableRowView = SC.ListItemView.extend({ $cell.css({ width: width+'px', left: left+'px', }); if (contentCheckboxKey && contentCheckboxKey.contains(key)) { - var value = SC.get(content, key) || false; + var value = SC.getPath(content, key) || false; this.updateCheckbox($cell, value, key); } else { @@ -251,11 +251,13 @@ SC.TableRowView = SC.ListItemView.extend({ }); } + var editableKeys = this.get('editableKeys'); + var keyInEditableKeys = editableKeys && editableKeys.indexOf(key) !== -1; source .set('controlSize', SC.SMALL_CONTROL_SIZE) .set('isSelected', state && (state !== SC.MIXED_STATE)) - .set('isEnabled', this.get('isEnabled') && this.get('contentIsEditable')) + .set('isEnabled', this.get('isEnabled') && this.get('contentIsEditable') && keyInEditableKeys) .set('isActive', this._checkboxIsActive) .set('title', ''); @@ -271,10 +273,14 @@ SC.TableRowView = SC.ListItemView.extend({ var sources = this._tr_cbSources; var source = sources[key]; + + var editableKeys = this.get('editableKeys'); + var keyInEditableKeys = editableKeys && editableKeys.indexOf(key) !== -1; + source .set('controlSize', SC.SMALL_CONTROL_SIZE) .set('isSelected', state && (state !== SC.MIXED_STATE)) - .set('isEnabled', this.get('isEnabled') && this.get('contentIsEditable')) + .set('isEnabled', this.get('isEnabled') && this.get('contentIsEditable') && keyInEditableKeys) .set('isActive', this._checkboxIsActive) .set('title', ''); @@ -294,7 +300,7 @@ SC.TableRowView = SC.ListItemView.extend({ }, _addCheckboxActiveState: function (key) { - if (this.get('isEnabled')) { + if (this.get('isEnabled') && this.get('editableKeys') && this.get('editableKeys').contains(key)) { if (this._checkboxRenderDelegate) { var sources = this._tr_cbSources; var source = sources[key]; @@ -370,7 +376,9 @@ SC.TableRowView = SC.ListItemView.extend({ // update only if mouse inside on mouse up... var inCheckboxForKey = this._isInsideCheckbox(evt); if (inCheckboxForKey && inCheckboxForKey === this._isMouseDownOnCheckboxFor) { - this.toggleCheckbox(inCheckboxForKey); + if (this.get('editableKeys') && this.get('editableKeys').contains(inCheckboxForKey)) { + this.toggleCheckbox(inCheckboxForKey); + } } this._removeCheckboxActiveState();