Skip to content

Commit

Permalink
jTable v2.1.1
Browse files Browse the repository at this point in the history
Multiple dependsOn support. [volosoft#94]
Enhanced option caching. [volosoft#63]
Portuguese - Portugal localization. [volosoft#142]
Chinese localization. [volosoft#103]
Fixed some issues. [volosoft#90, volosoft#28, volosoft#130]
  • Loading branch information
hikalkan committed Jan 30, 2013
1 parent c26fddb commit ccb806d
Show file tree
Hide file tree
Showing 10 changed files with 459 additions and 261 deletions.
99 changes: 84 additions & 15 deletions dev/jquery.jtable.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,21 @@
/* 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.
Expand Down Expand Up @@ -522,11 +535,14 @@
}

//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);
Expand Down Expand Up @@ -571,6 +587,10 @@
/* 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);
Expand Down Expand Up @@ -620,6 +640,7 @@
} 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)
});
Expand All @@ -628,17 +649,24 @@
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) {
Expand Down Expand Up @@ -668,7 +696,6 @@
var optionsSource = field.options;

if ($.isFunction(optionsSource)) {

//prepare parameter to the function
funcParams = $.extend(true, {
_cacheCleared: false,
Expand All @@ -686,10 +713,22 @@

//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];
Expand All @@ -704,16 +743,45 @@
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
Expand Down Expand Up @@ -744,6 +812,8 @@
}
},

/* Creates an array of options from given object.
*************************************************************************/
_buildOptionsArrayFromObject: function (options) {
var list = [];

Expand All @@ -757,14 +827,13 @@
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({
Expand Down
7 changes: 7 additions & 0 deletions dev/jquery.jtable.deletion.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@
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(
Expand Down
7 changes: 7 additions & 0 deletions dev/jquery.jtable.editing.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@
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) {
Expand Down
122 changes: 59 additions & 63 deletions dev/jquery.jtable.forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,6 @@
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,
Expand All @@ -230,19 +226,26 @@
}
},

/* 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;
},
Expand Down Expand Up @@ -336,34 +339,46 @@
_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();
});
});
});
},
Expand All @@ -388,13 +403,20 @@

//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');
Expand All @@ -409,32 +431,6 @@
}
},

/* 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) {
Expand Down
Loading

0 comments on commit ccb806d

Please sign in to comment.