Menu

#6 onClick for TableColumn.link

open
nobody
None
5
2012-12-11
2009-07-20
No

Added the ability to use onclick with TableColumn.link().

Documentation:

link now takes userClick optional param
param must be wrapped in an anonymous function with a single param. This param represents the value of element. This enhancement does not add an onclick to the anchor, but rather binds an event listener.

Example:
control: Rico.TableColumn.link('#',null, function(val){ mycustomonclick(val) });

Discussion

  • Anonymous

    Anonymous - 2009-07-24

    Fixed minor bug in link to call =this._format(v) instead of =v - in this way type: * formatting would apply properly.

    Also added a new control: binary. This method allows you to specify values for binary elements as well as a default value for non-binary cells. If no default value is provided non-binary cells are formatted and returned as is.

    Example:
    control: new Rico.TableColumn.binary('Yes', 'No', '-');
    //Data source
    1
    0
    null
    2
    //Output:
    Yes
    No
    -
    -

    Example 2:
    control: new Rico.TableColumn.binary('Yes', 'No');
    //Data source
    1
    0
    null
    2
    //Output:
    Yes
    No
     
    2

     
  • Anonymous

    Anonymous - 2009-07-24

    Additional behaviour note regarding onclick for link: If the value is formatted the onclick will send the original, unformatted value to function(row).

     
  • Anonymous

    Anonymous - 2009-07-25

    Fixed yet another bug in .link whereby multiple columns that used a common class where whipped out and only the last column displayed. Logic now assigns to gridCell instead of _anchor[windowRow]. Also fixed speed issues in all controls that used split

     
  • Anonymous

    Anonymous - 2009-07-28

    Major upgrades to .link functionality overall. Latest fix: child element bugfix

     
  • Anonymous

    Anonymous - 2009-07-28

    With any luck this is the final bug fix. Fixed issue with type: 'number' where prototype added a span element around the content of a cell. This caused the _userClick to receive a null value even though it displayed correctly. Now if the tag name being passed to _display is not an A it goes to the parent element to retrieve the ID. This is not fully robust and could be improved (perhaps get the gridCell id in another manner?) it does fix all current "type" issues - it would fail if the user changed the cell data to include a multi-level html structure without appending a proper gridCell ID. I also added an Event.stopObserving to _clear to remove the onclick watches if they were not being used. Also cleared the gridCell value on top of the existing _anchor[] clearing.

    To sum up all changes/improvements:
    Link can now return a custom cell value
    Links from the same class can now be applied to multiple columns
    All split() calls (for all controls not just element) have been replaced with indexOf() techniques to improve speed
    binary control added to allow custom values to display in place of 0/1 binary values
    Added null value default to binary control to allow custom value to display in place of null/empty cell

     
  • Matt Brown

    Matt Brown - 2009-08-15

    I don't understand the need for Rico.TableColumn.binary. Can't you use Rico.TableColumn.lookup instead?

    Adding the userClick function to the link control is a good idea, but you've added more code to the control than I expected. For example:

    _clear: function(gridCell,windowRow) {
    this._anchors[windowRow].href='';
    this._anchors[windowRow].innerHTML='';

    // this is incorrect. The last parameter to stopObserving needs to be the
    // bindAsEventListener result passed to Event.observe.
    if (this._userClick) Event.stopObserving(this._anchors[windowRow], 'click', this._onclick.bindAsEventListener(this));

    // The following loop just finds the id to this._anchors[windowRow]
    // which has already had its innerHTML set to '' above.
    // Why are you using this approach to now set it to  ?
    if (gridCell.hasChildNodes()) {
    for(var i=0;i<gridCell.childNodes.length;i++) {
    if (gridCell.childNodes[i].id == this.liveGrid.tableId+'_a_'+this.index+'_'+windowRow) {
    gridCell.childNodes[i].innerHTML='&nbsp;';
    }
    }
    }
    },

     
  • Nobody/Anonymous

    Re: Binary

    I added this because lookup became expensive for binary values. Adding 3 separate (relatively complex) lookups in place of a single simple binary seemed overkill.

    Re: link code

    There maybe a better way of doing this. I'm not 100% on the mechanism available in Rico/Prototype (yet).

    _onclick: function(e) {
    var elem=Event.element(e);
    //this is weak and should be improved. There was only one case (number format)
    //where prototype.js added a span inside the anchor tag. There will probably be user
    //cases where additional elements are added and this will fail. Ideally it would be
    //recursive but that would be difficult in this scenario. prototype probably has a method
    //that can be used here to ensure the correct element is being set to elem.
    if(elem.nodeName != 'A') elem=elem.parentNode;
    //lastIndexOf is faster than split. This change was made to all uses of split in all the controls
    var windowRow=parseInt(elem.id.substr(elem.id.lastIndexOf('_',elem.id.length)+1));
    var v=this.getValue(windowRow);
    this._userClick(v);
    },
    _clear: function(gridCell,windowRow) {
    this._anchors[windowRow].href='';
    this._anchors[windowRow].innerHTML='';
    //What would be the correct code for this if this._onclick.bindAsEventListener(this) is incorrect?
    //This was my understanding from the prototype documentation but there may be something
    //I am missing about how it's applied.
    if (this._userClick) Event.stopObserving(this._anchors[windowRow], 'click', this._onclick.bindAsEventListener(this));
    //The reason for the code below is a change in logic from _anchors[windowRow]. You'll note above that this._anchors[windowRow].innerHTML
    //is being set to ''. This applies to the entire row, it does not clear the value from gridCell any longer due to the change in
    //how _display sets its values. In the current version of Rico if you apply a class with link it will apply it's value to the entire row
    //instead of just one column. Note: columnSpecs: [control: new Rico.TableColumn.link(...), control: new Rico.TableColumn.link(...)]
    //works correctly in current version, but Rico.TableColumn._CLASS = {control: new Rico.TableColumn.link(...)} would cause the last column
    //to overwrite any previous columns that used ._CLASS See changes to display for more.
    if (gridCell.hasChildNodes()) {
    for(var i=0;i<gridCell.childNodes.length;i++) {
    if (gridCell.childNodes[i].id == this.liveGrid.tableId+'_a_'+this.index+'_'+windowRow) {
    //set to &nbsp to prevent the cell from collapsing
    gridCell.childNodes[i].innerHTML='&nbsp;';
    }
    }
    }
    },

    _display: function(v,gridCell,windowRow) {
    //Note that _anchors[windowRow] is no longer being used here. Instead of setting the value to the row it is now
    //set to the individual cell in the proper format (this is a bug fix as well. _format would not work properly
    //with the current version of Rico.) The original value is bound to ensure lookups for _userClick works as expected.
    if (gridCell.hasChildNodes()) {
    for(var i=0;i<gridCell.childNodes.length;i++) {
    if (gridCell.childNodes[i].id == this.liveGrid.tableId+'_a_'+this.index+'_'+windowRow) {
    gridCell.childNodes[i].innerHTML=this._format(v);
    var getWindowValue=this.liveGrid.buffer.getWindowValue.bind(this.liveGrid.buffer);
    //Set the href to the anchor set in the _create method on a cell by cell basis no longer on a row basis.
    gridCell.childNodes[i].href=this._href.replace(/\{\d+\}/g,
    function ($1) {
    var colIdx=parseInt($1.substr(1),10);
    return getWindowValue(windowRow,colIdx);
    }
    );
    }
    }
    }
    }

    Current version of RicoGridControls:
    - .link breaks when Rico.TableColumn._CLASS is used on multiple columns
    - _format(v) isn't applied and if it is it breaks .link
    - .link doesn't have an onClick

    This version:
    - adds onclick
    - allows Rico.TableColumn._CLASS with .link to be applied to multiple columns
    - allows _format(v) to be applied (and does so by default)
    - speeds up all controls that used .split()
    - simplified binary value rewriting
    - applies .link on a cell basis instead of a row basis while maintaining a row based event listener

    I hope this clears it up a bit. If you need more, please feel free to email me (mlegate@phpdev.ca)

     
  • Anonymous

    Anonymous - 2009-08-16

    Cleaned up version of the comment below.

    Re: Binary

    I added this because lookup became expensive for binary values. Adding 3
    separate (relatively complex) lookups in place of a single simple binary
    seemed overkill.

    Re: link code

    There maybe a better way of doing this. I'm not 100% on the mechanism
    available in Rico/Prototype (yet).

    _onclick: function(e) {
    var elem=Event.element(e);
    //this is weak and should be improved. There was only one case
    //(number format) where prototype.js added a span inside the anchor
    //tag. There will probably be user cases where additional elements are
    //added and this will fail. Ideally it would be recursive but that would be
    //difficult in this scenario. prototype probably has a method that can be
    //used here to ensure the correct element is being set to elem.

    if(elem.nodeName != 'A') elem=elem.parentNode;

    //lastIndexOf is faster than split. This change was made to all uses
    //of split in all the existing controls
    var windowRow=parseInt(elem.id.substr(elem.id.lastIndexOf('_',elem.id.length)+1));
    var v=this.getValue(windowRow);
    this._userClick(v);
    },
    _clear: function(gridCell,windowRow) {
    this._anchors[windowRow].href='';
    this._anchors[windowRow].innerHTML='';

    //What would be the correct code for this if
    //this._onclick.bindAsEventListener(this) is incorrect?
    //This was my understanding from the prototype documentation
    //but there may be something I am missing about how it's applied.
    if (this._userClick) Event.stopObserving(this._anchors[windowRow],
    'click', this._onclick.bindAsEventListener(this));

    //The reason for the code below is a change in logic from
    //_anchors[windowRow]. You'll note above that
    //this._anchors[windowRow].innerHTML is being set to ''. This
    //applies to the entire row, it does not clear the value from gridCell
    //any longer due to the change in how _display sets its values.
    //In the current version of Rico if you apply a class with link it will
    //apply it's value to the entire row instead of just one column.
    //Note: columnSpecs: [control: new Rico.TableColumn.link(...),
    //control: new Rico.TableColumn.link(...)] works correctly in the
    //current version, but Rico.TableColumn._CLASS =
    //{control: new Rico.TableColumn.link(...)} would cause the last
    //column to overwrite any previous columns that used ._CLASS
    //See changes to display for more.
    if (gridCell.hasChildNodes()) {
    for(var i=0;i<gridCell.childNodes.length;i++) {
    if (gridCell.childNodes[i].id ==
    this.liveGrid.tableId+'_a_'+this.index+'_'+windowRow) {

    //set to &nbsp to prevent the cell from collapsing
    gridCell.childNodes[i].innerHTML='&nbsp;';
    }
    }
    }
    },

    _display: function(v,gridCell,windowRow) {

    //Note that _anchors[windowRow] is no longer being used here. Instead
    //of setting the value to the row it is now set to the individual cell in
    //the proper format (this is a bug fix as well. _format would not work
    //properly with the current version of Rico.) The original value is bound to
    //ensure lookups for _userClick works as expected.
    if (gridCell.hasChildNodes()) {
    for(var i=0;i<gridCell.childNodes.length;i++) {
    if (gridCell.childNodes[i].id ==
    this.liveGrid.tableId+'_a_'+this.index+'_'+windowRow) {
    gridCell.childNodes[i].innerHTML=this._format(v);
    var
    getWindowValue=this.liveGrid.buffer.getWindowValue.bind(this.liveGrid.buffer);

    //Set the href to the anchor set in the _create method on a cell by
    //cell basis no longer on a row basis.
    gridCell.childNodes[i].href=this._href.replace(/\{\d+\}/g,
    function ($1) {
    var colIdx=parseInt($1.substr(1),10);
    return getWindowValue(windowRow,colIdx);
    }
    );
    }
    }
    }
    }

    Current version of RicoGridControls:
    - .link breaks when Rico.TableColumn._CLASS is used on multiple columns
    - _format(v) isn't applied and if it is it breaks .link
    - .link doesn't have an onClick

    This version:
    - adds onclick
    - allows Rico.TableColumn._CLASS with .link to be applied to multiple
    columns
    - allows _format(v) to be applied (and does so by default)
    - speeds up all controls that used .split()
    - simplified binary value rewriting
    - applies .link on a cell basis instead of a row basis while maintaining a
    row based event listener

    I hope this clears it up a bit. If you need more, please feel free to
    email me (mlegate@phpdev.ca)

     
  • Matt Brown

    Matt Brown - 2009-08-16

    //Note: columnSpecs: [control: new Rico.TableColumn.link(...),
    //control: new Rico.TableColumn.link(...)] works correctly in the
    //current version, but Rico.TableColumn._CLASS =
    //{control: new Rico.TableColumn.link(...)}

    That is why you should use:
    columnSpecs: [
    control: new Rico.TableColumn.link(...),
    control: new Rico.TableColumn.link(...)]
    if you need links in more than one column.

     
  • Anonymous

    Anonymous - 2009-08-16

    Is there a particular value or desired result in applying it on a row basis instead of a cell basis?

     

Log in to post a comment.