diff options
Diffstat (limited to 'lib/jquery.jtable.js')
-rw-r--r-- | lib/jquery.jtable.js | 258 |
1 files changed, 178 insertions, 80 deletions
diff --git a/lib/jquery.jtable.js b/lib/jquery.jtable.js index 5ebd494..7f2af06 100644 --- a/lib/jquery.jtable.js +++ b/lib/jquery.jtable.js @@ -1,6 +1,6 @@ /*
-jTable 2.1.0
+jTable 2.1.1
http://www.jtable.org
---------------------------------------------------------------------------
@@ -138,8 +138,21 @@ THE SOFTWARE. /* Normalizes some options for a field (sets default values).
*************************************************************************/
_normalizeFieldOptions: function (fieldName, props) {
- props.listClass = props.listClass || '';
- props.inputClass = props.inputClass || '';
+ if (props.listClass == undefined) {
+ props.listClass = '';
+ }
+ if (props.inputClass == undefined) {
+ props.inputClass = '';
+ }
+
+ //Convert dependsOn to array if it's a comma seperated lists
+ if (props.dependsOn && $.type(props.dependsOn) === 'string') {
+ var dependsOnArray = props.dependsOn.split(',');
+ props.dependsOn = [];
+ for (var i = 0; i < dependsOnArray.length; i++) {
+ props.dependsOn.push($.trim(dependsOnArray[i]));
+ }
+ }
},
/* Intializes some private variables.
@@ -551,11 +564,14 @@ THE SOFTWARE. }
//remove from DOM
- $rows.remove();
+ $rows.addClass('jtable-row-removed').remove();
//remove from _$tableRows array
$rows.each(function () {
- self._$tableRows.splice(self._findRowIndex($(this)), 1);
+ var index = self._findRowIndex($(this));
+ if (index >= 0) {
+ self._$tableRows.splice(index, 1);
+ }
});
self._onRowsRemoved($rows, reason);
@@ -600,6 +616,10 @@ THE SOFTWARE. /* Adds "no data available" row to the table.
*************************************************************************/
_addNoDataRow: function () {
+ if (this._$tableBody.find('>tr.jtable-no-data-row').length > 0) {
+ return;
+ }
+
var $tr = $('<tr></tr>')
.addClass('jtable-no-data-row')
.appendTo(this._$tableBody);
@@ -649,6 +669,7 @@ THE SOFTWARE. } else if (field.options) { //combobox or radio button list since there are options.
var options = this._getOptionsForField(fieldName, {
record: record,
+ value: fieldValue,
source: 'list',
dependedValues: this._createDependedValuesUsingRecord(record, field.dependsOn)
});
@@ -657,17 +678,24 @@ THE SOFTWARE. return fieldValue;
}
},
-
+
+ /* Creates and returns an object that's properties are depended values of a record.
+ *************************************************************************/
_createDependedValuesUsingRecord: function (record, dependsOn) {
if (!dependsOn) {
return {};
}
var dependedValues = {};
- dependedValues[dependsOn] = record[dependsOn];
+ for (var i = 0; i < dependsOn.length; i++) {
+ dependedValues[dependsOn[i]] = record[dependsOn[i]];
+ }
+
return dependedValues;
},
+ /* Finds an option object by given value.
+ *************************************************************************/
_findOptionByValue: function (options, value) {
for (var i = 0; i < options.length; i++) {
if (options[i].Value == value) {
@@ -697,7 +725,6 @@ THE SOFTWARE. var optionsSource = field.options;
if ($.isFunction(optionsSource)) {
-
//prepare parameter to the function
funcParams = $.extend(true, {
_cacheCleared: false,
@@ -715,10 +742,22 @@ THE SOFTWARE. //Build options according to it's source type
if (typeof optionsSource == 'string') { //It is an Url to download options
- var cacheKey = 'options_' + fieldName + '_' + optionsSource;
+ var cacheKey = 'options_' + fieldName + '_' + optionsSource; //create a unique cache key
if (funcParams._cacheCleared || (!this._cache[cacheKey])) {
- this._cache[cacheKey] = this._downloadOptions(fieldName, optionsSource);
+ //if user calls clearCache() or options are not found in the cache, download options
+ this._cache[cacheKey] = this._buildOptionsFromArray(this._downloadOptions(fieldName, optionsSource));
this._sortFieldOptions(this._cache[cacheKey], field.optionsSorting);
+ } else {
+ //found on cache..
+ //if this method (_getOptionsForField) is called to get option for a specific value (on funcParams.source == 'list')
+ //and this value is not in cached options, we need to re-download options to get the unfound (probably new) option.
+ if (funcParams.value != undefined) {
+ var optionForValue = this._findOptionByValue(this._cache[cacheKey], funcParams.value);
+ if(optionForValue.DisplayText == undefined) { //this value is not in cached options...
+ this._cache[cacheKey] = this._buildOptionsFromArray(this._downloadOptions(fieldName, optionsSource));
+ this._sortFieldOptions(this._cache[cacheKey], field.optionsSorting);
+ }
+ }
}
options = this._cache[cacheKey];
@@ -733,16 +772,45 @@ THE SOFTWARE. return options;
},
+ /* Download options for a field from server.
+ *************************************************************************/
+ _downloadOptions: function (fieldName, url) {
+ var self = this;
+ var options = [];
+
+ self._ajax({
+ url: url,
+ async: false,
+ success: function (data) {
+ if (data.Result != 'OK') {
+ self._showError(data.Message);
+ return;
+ }
+
+ options = data.Options;
+ },
+ error: function () {
+ var errMessage = self._formatString(self.options.messages.cannotLoadOptionsFor, fieldName);
+ self._showError(errMessage);
+ }
+ });
+
+ return options;
+ },
+
+ /* Sorts given options according to sorting parameter.
+ * sorting can be: 'value', 'value-desc', 'text' or 'text-desc'.
+ *************************************************************************/
_sortFieldOptions: function (options, sorting) {
-
+
if ((!options) || (!options.length) || (!sorting)) {
return;
}
-
+
//Determine using value of text
var dataSelector;
if (sorting.indexOf('value') == 0) {
- dataSelector = function(option) {
+ dataSelector = function (option) {
return option.Value;
};
} else { //assume as text
@@ -773,6 +841,8 @@ THE SOFTWARE. }
},
+ /* Creates an array of options from given object.
+ *************************************************************************/
_buildOptionsArrayFromObject: function (options) {
var list = [];
@@ -786,14 +856,13 @@ THE SOFTWARE. return list;
},
- /* Creates an options object (that it's property is value, value is displaytext)
- * from a simple array.
+ /* Creates array of options from giving options array.
*************************************************************************/
_buildOptionsFromArray: function (optionsArray) {
var list = [];
for (var i = 0; i < optionsArray.length; i++) {
- if ($.isPlainObject) {
+ if ($.isPlainObject(optionsArray[i])) {
list.push(optionsArray[i]);
} else { //assumed as primitive type (int, string...)
list.push({
@@ -1102,6 +1171,26 @@ THE SOFTWARE. });
+ /* Fix for array.indexOf method in IE7.
+ * This code is taken from http://www.tutorialspoint.com/javascript/array_indexof.htm */
+ if (!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function (elt) {
+ var len = this.length;
+ var from = Number(arguments[1]) || 0;
+ from = (from < 0)
+ ? Math.ceil(from)
+ : Math.floor(from);
+ if (from < 0)
+ from += len;
+ for (; from < len; from++) {
+ if (from in this &&
+ this[from] === elt)
+ return from;
+ }
+ return -1;
+ };
+ }
+
})(jQuery);
@@ -1311,10 +1400,6 @@ THE SOFTWARE. var $select = $('<select class="' + field.inputClass + '" id="Edit-' + fieldName + '" name="' + fieldName + '"></select>')
.appendTo($containerDiv);
- if (field.dependsOn) {
- $select.attr('data-depends-on', field.dependsOn);
- }
-
//add options
var options = this._getOptionsForField(fieldName, {
record: record,
@@ -1337,19 +1422,26 @@ THE SOFTWARE. }
},
+ /* Creates depended values object from given form.
+ *************************************************************************/
_createDependedValuesUsingForm: function ($form, dependsOn) {
-
if (!dependsOn) {
return {};
}
- var $dependsOn = $form.find('select[name=' + dependsOn + ']');
- if ($dependsOn.length <= 0) {
- return {};
+ var dependedValues = {};
+
+ for (var i = 0; i < dependsOn.length; i++) {
+ var dependedField = dependsOn[i];
+
+ var $dependsOn = $form.find('select[name=' + dependedField + ']');
+ if ($dependsOn.length <= 0) {
+ continue;
+ }
+
+ dependedValues[dependedField] = $dependsOn.val();
}
- var dependedValues = {};
- dependedValues[dependsOn] = $dependsOn.val();
return dependedValues;
},
@@ -1443,34 +1535,46 @@ THE SOFTWARE. _makeCascadeDropDowns: function ($form, record, source) {
var self = this;
- $form.find('select[data-depends-on]')
+ $form.find('select') //for each combobox
.each(function () {
var $thisDropdown = $(this);
+
+ //get field name
var fieldName = $thisDropdown.attr('name');
if (!fieldName) {
return;
}
- var dependsOnField = $thisDropdown.attr('data-depends-on');
- var $dependsOn = $form.find('select[name=' + dependsOnField + ']');
- $dependsOn.change(function () {
-
- //Refresh options
-
- var funcParams = {
- record: record,
- source: source,
- form: $form,
- dependedValues: {}
- };
- funcParams.dependedValues[dependsOnField] = $dependsOn.val();
-
- var options = self._getOptionsForField(fieldName, funcParams);
- self._fillDropDownListWithOptions($thisDropdown, options, undefined);
+ var field = self.options.fields[fieldName];
+
+ //check if this combobox depends on others
+ if (!field.dependsOn) {
+ return;
+ }
- //Thigger change event to refresh multi cascade dropdowns.
-
- $thisDropdown.change();
+ //for each dependency
+ $.each(field.dependsOn, function (index, dependsOnField) {
+ //find the depended combobox
+ var $dependsOnDropdown = $form.find('select[name=' + dependsOnField + ']');
+ //when depended combobox changes
+ $dependsOnDropdown.change(function () {
+
+ //Refresh options
+ var funcParams = {
+ record: record,
+ source: source,
+ form: $form,
+ dependedValues: {}
+ };
+ funcParams.dependedValues = self._createDependedValuesUsingForm($form, field.dependsOn);
+ var options = self._getOptionsForField(fieldName, funcParams);
+
+ //Fill combobox with new options
+ self._fillDropDownListWithOptions($thisDropdown, options, undefined);
+
+ //Thigger change event to refresh multi cascade dropdowns.
+ $thisDropdown.change();
+ });
});
});
},
@@ -1495,13 +1599,20 @@ THE SOFTWARE. //Update field in record according to it's type
if (field.type == 'date') {
- var displayFormat = field.displayFormat || this.options.defaultDateFormat;
- try {
- var date = $.datepicker.parseDate(displayFormat, $inputElement.val());
- record[fieldName] = '/Date(' + date.getTime() + ')/';
- } catch (e) {
- //TODO: Handle incorrect/different date formats
- record[fieldName] = '/Date(' + (new Date()).getTime() + ')/';
+ var dateVal = $inputElement.val();
+ if (dateVal) {
+ var displayFormat = field.displayFormat || this.options.defaultDateFormat;
+ try {
+ var date = $.datepicker.parseDate(displayFormat, dateVal);
+ record[fieldName] = '/Date(' + date.getTime() + ')/';
+ } catch (e) {
+ //TODO: Handle incorrect/different date formats
+ this._logWarn('Date format is incorrect for field ' + fieldName + ': ' + dateVal);
+ record[fieldName] = undefined;
+ }
+ } else {
+ this._logDebug('Date is empty for ' + fieldName);
+ record[fieldName] = undefined; //TODO: undefined, null or empty string?
}
} else if (field.options && field.type == 'radiobutton') {
var $checkedElement = $inputElement.filter(':checked');
@@ -1516,32 +1627,6 @@ THE SOFTWARE. }
},
- /* Download options for a field from server.
- *************************************************************************/
- _downloadOptions: function (fieldName, url) {
- var self = this;
- var options = [];
-
- self._ajax({
- url: url,
- async: false,
- success: function (data) {
- if (data.Result != 'OK') {
- self._showError(data.Message);
- return;
- }
-
- options = data.Options;
- },
- error: function () {
- var errMessage = self._formatString(self.options.messages.cannotLoadOptionsFor, fieldName);
- self._showError(errMessage);
- }
- });
-
- return options;
- },
-
/* Sets enabled/disabled state of a dialog button.
*************************************************************************/
_setEnabledOfDialogButton: function ($button, enabled, buttonText) {
@@ -1940,6 +2025,13 @@ THE SOFTWARE. id: 'EditDialogSaveButton',
text: self.options.messages.save,
click: function () {
+
+ //row maybe removed by another source, if so, do nothing
+ if (self._$editingRow.hasClass('jtable-row-removed')) {
+ self._$editDiv.dialog('close');
+ return;
+ }
+
var $saveButton = self._$editDiv.find('#EditDialogSaveButton');
var $editForm = self._$editDiv.find('form');
if (self._trigger("formSubmitting", null, { form: $editForm, formType: 'edit', row: self._$editingRow }) != false) {
@@ -2311,6 +2403,13 @@ THE SOFTWARE. id: 'DeleteDialogButton',
text: self.options.messages.deleteText,
click: function () {
+
+ //row maybe removed by another source, if so, do nothing
+ if (self._$deletingRow.hasClass('jtable-row-removed')) {
+ self._$deleteRecordDiv.dialog('close');
+ return;
+ }
+
var $deleteButton = $('#DeleteDialogButton');
self._setEnabledOfDialogButton($deleteButton, false, self.options.messages.deleting);
self._deleteRecordFromServer(
@@ -3301,7 +3400,6 @@ THE SOFTWARE. //Reference to base object members
var base = {
- _create: $.hik.jtable.prototype._create,
_normalizeFieldOptions: $.hik.jtable.prototype._normalizeFieldOptions,
_createHeaderCellForField: $.hik.jtable.prototype._createHeaderCellForField,
_createRecordLoadUrl: $.hik.jtable.prototype._createRecordLoadUrl
|