// Shortcut-function (until we update to Prototye v1.5) if(typeof $$ != "Function") $$ = document.getElementsBySelector; TableListField = Class.create(); TableListField.prototype = { errorMessage: "Error talking to server", initialize: function() { var rules = {}; rules['#'+this.id+' table.data a.deletelink'] = { onclick: this.deleteRecord.bind(this) }; rules['#'+this.id+' th a'] = { onclick: this.refresh.bind(this) }; rules['#'+this.id+' th'] = { initialize: function() { var sortLinks = $$('span.sortLinkHidden a', this); if(sortLinks) sortLinks[0].style.visibility = 'hidden'; }, onmouseover: function(e) { var sortLinks = $$('span.sortLinkHidden a', this); if(sortLinks) sortLinks[0].style.visibility = 'visible'; }, onmouseout: function(e) { var sortLinks = $$('span.sortLinkHidden a', this); if(sortLinks) sortLinks[0].style.visibility = 'hidden'; } }; rules['#'+this.id+' div.PageControls a'] = {onclick: this.refresh.bind(this)}; rules['#'+this.id+' table.data tr td.markingcheckbox'] = { onclick : function(e) { // do nothing for clicks in marking box cells (e.g. if checkbox is missed) } }; // rules for selection options on click event rules['#'+this.id+' .selectOptions a'] = { onclick: this.markRecords.bind(this) }; // initialize summary (if needed) // TODO Breaks with nested divs var summaryCols = $$('tfoot tr.summary td', this); this._summaryDefs = []; //should check summaryCols.length, because summaryCols will always be an array, though its length could be 0. if(summaryCols && summaryCols.length) { rules['#'+this.id+' table.data tbody input'] = { onchange: function(e) { if (!e) e = window.event; // stupid IE // workaround for wrong scope with bind(this) and applyTo() var root = Event.findElement(e,'div'); // TODO Fix slow $$()-calls and re-enable clientside summaries //root._summarise(); } }; rules['#'+this.id+' table.data tbody select'] = { onchange: function(e) { if (!e) e = window.event; // stupid IE // workaround for wrong scope with bind(this) and applyTo() var root = Event.findElement(e,'div'); // TODO Fix slow $$()-calls and re-enable clientside summaries //root._summarise(); }.bind(this) }; } Behaviour.register('TableListField_'+this.id,rules); /* if(summaryCols.length) { this._getSummaryDefs(summaryCols); } */ }, /** * Deletes the given dataobject record via an ajax request * to complextablefield->Delete() * @param {Object} e */ deleteRecord: function(e) { var img = Event.element(e); var link = Event.findElement(e,"a"); var row = Event.findElement(e,"tr"); var self = this; // TODO ajaxErrorHandler and loading-image are dependent on cms, but formfield is in framework var confirmed = confirm(ss.i18n._t('TABLEFIELD.DELETECONFIRMMESSAGE', 'Are you sure you want to delete this record?')); if(confirmed) { img.setAttribute("src",'framework/images/network-save.gif'); // TODO doesn't work jQuery.ajax({ 'url': link.getAttribute("href"), 'method': 'post', 'data': {forceajax: 1, SecurityID: jQuery('input[name=SecurityID]').val()}, 'success': function(){ jQuery(row).remove(); // recalculate summary if needed (assumes that TableListField.js is present) // TODO Proper inheritance if(self._summarise) self._summarise(); // custom callback if(self.callback_deleteRecord) self.callback_deleteRecord(e); }, 'error': this.ajaxErrorHandler }); } Event.stop(e); }, removeById: function(id) { var el = jQuery('#record-' + this.id + '-' + id)[0]; if(el) el.parentNode.removeChild(el); this._summarise(); }, /** * according to the clicked element in "Select bar", mark records that have same class as the element. */ markRecords: function(e){ var el = Event.element(e); if(el.nodeName != "a") el = Event.findElement(e,"a"); if(el.rel == "all"){ this.markAll(); }else if(el.rel == 'none') { this.unmarkAll(); }else{ this.unmarkAll(); var records = jQuery('#' + this.id + ' td.' + el.rel + ' input.checkbox'); var i=0; for(i; i<records.length; i++){ records[i].checked = 'checked'; } } return false; }, /** * mark all record in current view of the table */ markAll: function(e){ var records = $$('#'+this.id+' td.markingcheckbox input.checkbox'); var i=0; for(i; i<records.length; i++){ records[i].checked = 'checked'; } }, /** * unmark all records in current view of the table */ unmarkAll: function(e){ var records = $$('#'+this.id+' td.markingcheckbox input.checkbox'); var i=0; for(i; i<records.length; i++){ records[i].checked = ''; } }, refresh: function(e) { var self = this; if(e) { var el = Event.element(e); if(el.nodeName != "a") el = Event.findElement(e,"a"); } else { var el = jQuery('#' + this.id)[0]; } if(el.getAttribute('href')) { jQuery.ajax({ 'url': el.getAttribute('href'), 'data': {'update': 1}, 'success': function(response) { jQuery('#' + self.id).replaceWith(response) // reapply behaviour and reattach methods to TF container node // e.g. <div class="TableListField"> Behaviour.apply(jQuery('#' + self.id)[0], true); } }); } if(e) Event.stop(e); return false; }, ajaxErrorHandler: function(response) { if(typeof(window.ajaxErrorHandler) == 'function') { window.ajaxErrorHandler(); } else { alert(this.errorMessage); } }, _getSummaryDefs: function(summaryCols) { summaryCols.each(function(col, pos) { if( col ) { var func = this._getSummaryFunction(col.className); this._summaryDefs[pos] = {col: col, pos: pos, func: func}; } }.bind(this)); this._summarise(); }, _summarise: function() { var rows = $$('tbody tr', this); if(!rows) return false; var columnData = []; // prepare the array (gets js-errors otherwise) var cols = $$('td', rows[0]); for(colPos=0; colPos<cols.length; colPos++) { columnData[colPos] = []; } for(rowPos=0; rowPos<rows.length; rowPos++) { // avoid wrong calculations for nested lists if(Element.hasClassName(rows[rowPos], "subitem")) continue; var cols = $$('td', rows[rowPos]); var colPos = 0; for(colPos; colPos<cols.length; colPos++) { //if(!columnData[colPos]) columnData[colPos] = []; if(this._summaryDefs[colPos] && this._summaryDefs[colPos].func) { columnData[colPos][rowPos] = this._getValue(cols[colPos]); } else { columnData[colPos][rowPos] = ""; } } } for(colPos=0; colPos<columnData.length; colPos++) { if(this._summaryDefs[colPos] && this._summaryDefs[colPos].func) { var summaryVal = this._summaryDefs[colPos].func.apply(this,[columnData[colPos]]); this._summaryDefs[colPos].col.innerHTML = summaryVal; } } }, _getSummaryFunction: function(func) { if(this[func] && typeof this[func] == "function") { // local return this[func]; } else if(window[func] && typeof window[func] == "function") { // global return window[func]; } else { // not existing return false } }, _getValue: function(col) { var inputNode = $$('input', col); if(inputNode[0]) { return $F(inputNode[0]); } var selectNode = $$('select', col); if(selectNode[0]) { return $F(selectNode[0]); } return col.innerHTML.stripTags(); }, /** * ############# Summary Functions ############## */ sum: function(arr) { var sum = 0; arr.each(function(val) { sum += val*1; // convert to float }); return sum; }, sumCurrency: function(arr) { var sum = 0; arr.each(function(val) { if(!val) return; val = val.replace(/\$/,''); val = val.replace(/\,/,''); sum+= val*1; // convert to float }); return sum.toCurrency(); }, max: function(arr) { return arr.max(); }, min: function(arr) { return arr.min(); } } TableListRecord = Class.create(); TableListRecord.prototype = { onmouseover : function() { Element.addClassName(this,'over'); }, onmouseout : function() { Element.removeClassName(this,'over'); }, ajaxRequest : function(url, subform) { var self = this; // Highlight the new row if(this.parentNode.selectedRow) { Element.removeClassName(this.parentNode.selectedRow,'current'); } this.parentNode.selectedRow = this; Element.addClassName(this,'current'); this.subform = document.getElementById(subform); Element.addClassName(this, 'loading'); statusMessage('loading'); jQuery.ajax({ 'url': url + this.id.replace('record-',''), 'method' : 'post', 'data' : {'ajax': 1}, success : function() { self.select_success(); }, failure : ajaxErrorHandler }); }, getRecordId: function(){ parts = this.id.match( /.*[\-]{1}(\d+)$/ ); if(parts) return parts[1]; else return false; }, select_success : function(response) { Element.removeClassName(this, 'loading'); this.subform.loadNewPage(response.responseText); statusMessage('loaded','good'); } } TableListRecord.applyTo('div.TableListField tr'); TableListField.applyTo('div.TableListField'); Number.prototype.CURRENCIES = { en_GB: '$ ###,###.##' }; /** * Caution: Not finished! * @param iso string (Not used) Please use in combination with Number.CURRENCIES to achieve i18n * @return string * * @see http://www.jibbering.com/faq/faq_notes/type_convert.html * @see http://www.rgagnon.com/jsdetails/js-0063.html * @see http://www.mredkj.com/javascript/nfdocs.html */ Number.prototype.toCurrency = function(iso) { if(!iso) iso = SS_DEFAULT_ISO; // TODO stub, please implement properly return "$" + this.toFixed(2); }