Permalink
Browse files

jTable v2.1.0

Added cascade dropdowns and creating dynamically option list support.
[#63, #94]
Added field options: dependsOn and optionsSorting.
Polish localization (by Grzegorz Zbucki). [#97]
Lithuanian localization (by Vygandas Šimkus). [#103]
Portuguese - Brazilian localization (by Renato Bigliazzi). [#129]
Fixed some issues.
  • Loading branch information...
1 parent b296ed7 commit 844ee6c862cfc3221de4d22e9014a5eae357cabd @hikalkan committed Jan 25, 2013
View
@@ -1,10 +1,33 @@
-jtable
+What is jTable
======
-A JQuery plugin to create AJAX based CRUD tables.
+http://www.jtable.org
+
+jTable is a jQuery plugin that is used to create AJAX based CRUD tables without coding HTML or Javascript. It has several features including:
+
+* Automatically creates HTML table and loads records from server using AJAX.
+* Creates 'create new record' jQueryUI dialog form. When user creates a record, it sends data to server using AJAX and adds the same record to the table in the page.
+* Creates 'edit record' jQueryUI dialog form. When user edits a record, it updates server using AJAX and updates all cells on the table in the page.
+* Allow user to 'delete a record' by jQueryUI dialog based confirmation. When user deletes a record, it deletes the record from server using AJAX and deletes the record from the table in the page.
+* Shows animations for create/delete/edit operations on the table.
+* Supports server side paging using AJAX.
+* Supports server side sorting using AJAX.
+* Supports master/child tables.
+* Allows user to select rows.
+* Allows user to resize columns.
+* Allows user to show/hide columns.
+* Exposes some events to enable validation with forms.
+* It can be localized easily.
+* All styling of table and forms are defined in a CSS file, so you can easily change style of everything to use plugin in your pages. CSS file is well defined and commented.
+* It comes with pre-defined color themes.
+* It is not depended on any server side technology.
+* It is platform independed and works on all common browsers.
+
+Notes
+======
lib folder contains all necessary files to use jTable.
dev folder contains parts of library that can be helpful for development of jTable.
-See http://www.jtable.org for documantation, demos, themes and more...
+See http://www.jtable.org for documantation, demos, themes and more...
View
@@ -617,12 +617,37 @@
return this._getDisplayTextForDateRecordField(field, fieldValue);
} else if (field.type == 'checkbox') {
return this._getCheckBoxTextForFieldByValue(fieldName, fieldValue);
- } else if (field.options) {
- return this._getOptionsWithCaching(fieldName)[fieldValue];
- } else {
+ } else if (field.options) { //combobox or radio button list since there are options.
+ var options = this._getOptionsForField(fieldName, {
+ record: record,
+ source: 'list',
+ dependedValues: this._createDependedValuesUsingRecord(record, field.dependsOn)
+ });
+ return this._findOptionByValue(options, fieldValue).DisplayText;
+ } else { //other types
return fieldValue;
}
},
+
+ _createDependedValuesUsingRecord: function (record, dependsOn) {
+ if (!dependsOn) {
+ return {};
+ }
+
+ var dependedValues = {};
+ dependedValues[dependsOn] = record[dependsOn];
+ return dependedValues;
+ },
+
+ _findOptionByValue: function (options, value) {
+ for (var i = 0; i < options.length; i++) {
+ if (options[i].Value == value) {
+ return options[i];
+ }
+ }
+
+ return {}; //no option found
+ },
/* Gets text for a date field.
*************************************************************************/
@@ -636,6 +661,122 @@
return $.datepicker.formatDate(displayFormat, date);
},
+ /* Gets options for a field according to user preferences.
+ *************************************************************************/
+ _getOptionsForField: function (fieldName, funcParams) {
+ var field = this.options.fields[fieldName];
+ var optionsSource = field.options;
+
+ if ($.isFunction(optionsSource)) {
+
+ //prepare parameter to the function
+ funcParams = $.extend(true, {
+ _cacheCleared: false,
+ dependedValues: {},
+ clearCache: function () {
+ this._cacheCleared = true;
+ }
+ }, funcParams);
+
+ //call function and get actual options source
+ optionsSource = optionsSource(funcParams);
+ }
+
+ var options;
+
+ //Build options according to it's source type
+ if (typeof optionsSource == 'string') { //It is an Url to download options
+ var cacheKey = 'options_' + fieldName + '_' + optionsSource;
+ if (funcParams._cacheCleared || (!this._cache[cacheKey])) {
+ this._cache[cacheKey] = this._downloadOptions(fieldName, optionsSource);
+ this._sortFieldOptions(this._cache[cacheKey], field.optionsSorting);
+ }
+
+ options = this._cache[cacheKey];
+ } else if (jQuery.isArray(optionsSource)) { //It is an array of options
+ options = this._buildOptionsFromArray(optionsSource);
+ this._sortFieldOptions(options, field.optionsSorting);
+ } else { //It is an object that it's properties are options
+ options = this._buildOptionsArrayFromObject(optionsSource);
+ this._sortFieldOptions(options, field.optionsSorting);
+ }
+
+ return options;
+ },
+
+ _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) {
+ return option.Value;
+ };
+ } else { //assume as text
+ dataSelector = function (option) {
+ return option.DisplayText;
+ };
+ }
+
+ var compareFunc;
+ if ($.type(dataSelector(options[0])) == 'string') {
+ compareFunc = function (option1, option2) {
+ return dataSelector(option1).localeCompare(dataSelector(option2));
+ };
+ } else { //asuume as numeric
+ compareFunc = function (option1, option2) {
+ return dataSelector(option1) - dataSelector(option2);
+ };
+ }
+
+ if (sorting.indexOf('desc') > 0) {
+ options.sort(function (a, b) {
+ return compareFunc(b, a);
+ });
+ } else { //assume as asc
+ options.sort(function (a, b) {
+ return compareFunc(a, b);
+ });
+ }
+ },
+
+ _buildOptionsArrayFromObject: function (options) {
+ var list = [];
+
+ $.each(options, function (propName, propValue) {
+ list.push({
+ Value: propName,
+ DisplayText: propValue
+ });
+ });
+
+ return list;
+ },
+
+ /* Creates an options object (that it's property is value, value is displaytext)
+ * from a simple array.
+ *************************************************************************/
+ _buildOptionsFromArray: function (optionsArray) {
+ var list = [];
+
+ for (var i = 0; i < optionsArray.length; i++) {
+ if ($.isPlainObject) {
+ list.push(optionsArray[i]);
+ } else { //assumed as primitive type (int, string...)
+ list.push({
+ Value: optionsArray[i],
+ DisplayText: optionsArray[i]
+ });
+ }
+ }
+
+ return list;
+ },
+
/* Parses given date string to a javascript Date object.
* Given string must be formatted one of the samples shown below:
* /Date(1320259705710)/
@@ -229,9 +229,16 @@
$fieldContainer.append(self._createInputLabelForRecordField(fieldName));
//Create input element
- $fieldContainer.append(self._createInputForRecordField(fieldName));
+ $fieldContainer.append(
+ self._createInputForRecordField({
+ fieldName: fieldName,
+ formType: 'create',
+ form: $addRecordForm
+ }));
}
+ self._makeCascadeDropDowns($addRecordForm, undefined, 'create');
+
//Open the form
self._$addRecordDiv.append($addRecordForm).dialog('open');
self._trigger("formCreated", null, { form: $addRecordForm, formType: 'create' });
@@ -29,8 +29,8 @@
deleteConfirmation: 'This record will be deleted. Are you sure?',
deleteText: 'Delete',
deleting: 'Deleting',
- canNotDeletedRecords: 'Can not deleted {0} of {1} records!',
- deleteProggress: 'Deleted {0} of {1} records, processing...'
+ canNotDeletedRecords: 'Can not delete {0} of {1} records!',
+ deleteProggress: 'Deleting {0} of {1} records, processing...'
}
},
@@ -76,7 +76,7 @@
click: function () {
var $saveButton = self._$editDiv.find('#EditDialogSaveButton');
var $editForm = self._$editDiv.find('form');
- if (self._trigger("formSubmitting", null, { form: $editForm, formType: 'edit' }) != false) {
+ if (self._trigger("formSubmitting", null, { form: $editForm, formType: 'edit', row: self._$editingRow }) != false) {
self._setEnabledOfDialogButton($saveButton, false, self.options.messages.saving);
self._saveEditForm($editForm, $saveButton);
}
@@ -85,7 +85,7 @@
close: function () {
var $editForm = self._$editDiv.find('form:first');
var $saveButton = $('#EditDialogSaveButton');
- self._trigger("formClosed", null, { form: $editForm, formType: 'edit' });
+ self._trigger("formClosed", null, { form: $editForm, formType: 'edit', row: self._$editingRow });
self._setEnabledOfDialogButton($saveButton, true, self.options.messages.save);
$editForm.remove();
}
@@ -250,13 +250,22 @@
//Create input element with it's current value
var currentValue = self._getValueForRecordField(record, fieldName);
- $fieldContainer.append(self._createInputForRecordField(fieldName, currentValue, record));
+ $fieldContainer.append(
+ self._createInputForRecordField({
+ fieldName: fieldName,
+ value: currentValue,
+ record: record,
+ formType: 'edit',
+ form: $editForm
+ }));
}
+ self._makeCascadeDropDowns($editForm, record, 'edit');
+
//Open dialog
self._$editingRow = $tableRow;
self._$editDiv.append($editForm).dialog('open');
- self._trigger("formCreated", null, { form: $editForm, formType: 'edit', record: record });
+ self._trigger("formCreated", null, { form: $editForm, formType: 'edit', record: record, row: $tableRow });
},
/* Saves editing form to the server and updates the record on the table.
@@ -275,11 +284,11 @@
}
var record = self._$editingRow.data('record');
-
- self._updateRecordValuesFromEditForm(record, $editForm);
+
+ self._updateRecordValuesFromForm(record, $editForm);
self._updateRecordValuesFromServerResponse(record, data);
self._updateRowTexts(self._$editingRow);
-
+
self._$editingRow.attr('data-record-key', self._getKeyValueOfRecord(record));
self._onRecordUpdated(self._$editingRow, data);
@@ -296,45 +305,6 @@
});
},
- /* Updates values of a record from given edit form
- *************************************************************************/
- _updateRecordValuesFromEditForm: function (record, $form) {
- for (var i = 0; i < this._fieldList.length; i++) {
- var fieldName = this._fieldList[i];
- var field = this.options.fields[fieldName];
-
- //Do not update non-editable fields
- if (field.edit == false) {
- continue;
- }
-
- //Get field name and the input element of this field in the form
- var $inputElement = $form.find('[name="' + fieldName + '"]');
-
- //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() + ')/';
- }
- } else if (field.options && field.type == 'radiobutton') {
- var $checkedElement = $inputElement.filter('[checked="true"]');
- if ($checkedElement.length) {
- record[fieldName] = $checkedElement.val();
- } else {
- record[fieldName] = undefined;
- }
- } else {
- record[fieldName] = $inputElement.val();
- }
- }
- },
-
-
/* This method ensures updating of current record with server response,
* if server sends a Record object as response to updateAction.
*************************************************************************/
@@ -367,7 +337,7 @@
var displayItem = this._getDisplayTextForRecordField(record, this._columnList[i]);
$columns.eq(this._firstDataColumnOffset + i).html(displayItem || '');
}
-
+
this._onRowUpdated($tableRow);
},
Oops, something went wrong.

0 comments on commit 844ee6c

Please sign in to comment.