mirror of https://github.com/apache/cloudstack.git
bug 11798 (WIP)
-Add UI for sticky policy -Create sticky policy functionality
This commit is contained in:
parent
79e9e292dd
commit
3e365ad8c2
|
|
@ -5646,6 +5646,8 @@ div.panel.ui-dialog div.list-view div.fixed-header {
|
|||
-webkit-border-radius: 5px;
|
||||
-khtml-border-radius: 5px;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
width: 74px;
|
||||
text-align: center;
|
||||
padding: 6px 9px 4px 0px;
|
||||
background: url(../images/bg-gradients.png) repeat-x 0px -220px;
|
||||
/*+placement:shift 4px 0px;*/
|
||||
|
|
@ -5663,6 +5665,28 @@ div.panel.ui-dialog div.list-view div.fixed-header {
|
|||
box-shadow: inset 0px 1px 1px #000000;
|
||||
}
|
||||
|
||||
.multi-edit .button.custom-action {
|
||||
background: url(../images/bg-gradients.png) 0px -271px;
|
||||
border: 1px solid #B7B7B7;
|
||||
color: #485867;
|
||||
font-size: 11px;
|
||||
/*+text-shadow:0px 1px #FFFFFF;*/
|
||||
-moz-text-shadow: 0px 1px #FFFFFF;
|
||||
-webkit-text-shadow: 0px 1px #FFFFFF;
|
||||
-o-text-shadow: 0px 1px #FFFFFF;
|
||||
text-shadow: 0px 1px #FFFFFF;
|
||||
}
|
||||
|
||||
.multi-edit .button.custom-action:hover {
|
||||
background: #808080 url(../images/bg-gradients.png);
|
||||
color: #FFFFFF;
|
||||
/*+text-shadow:0px 1px 1px #000000;*/
|
||||
-moz-text-shadow: 0px 1px 1px #000000;
|
||||
-webkit-text-shadow: 0px 1px 1px #000000;
|
||||
-o-text-shadow: 0px 1px 1px #000000;
|
||||
text-shadow: 0px 1px 1px #000000;
|
||||
}
|
||||
|
||||
.multi-edit-add-list .ui-button.ok,
|
||||
.multi-edit-add-list .ui-button.cancel {
|
||||
float: right;
|
||||
|
|
@ -5791,6 +5815,10 @@ div.panel.ui-dialog div.list-view div.fixed-header {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.multi-edit .data .data-body .data-item tr td .custom-action {
|
||||
margin: -6px 0 0 -1px;
|
||||
}
|
||||
|
||||
.multi-edit .data .data-body .data-item tr td.add-vm:hover {
|
||||
color: #0060FF;
|
||||
font-weight: bold;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
vlan: { label: 'VLAN' }
|
||||
},
|
||||
dataProvider: testData.dataProvider.listView('networks'),
|
||||
|
||||
|
||||
detailView: {
|
||||
name: 'Network details',
|
||||
viewAll: { path: 'network.ipAddresses', label: 'IP Addresses' },
|
||||
|
|
@ -513,6 +513,124 @@
|
|||
});
|
||||
}
|
||||
},
|
||||
'sticky': {
|
||||
label: 'Sticky Policy',
|
||||
custom: {
|
||||
buttonLabel: 'Configure',
|
||||
action: function(args) {
|
||||
var success = args.response.success;
|
||||
var fields = {
|
||||
method: {
|
||||
label: 'Stickiness method',
|
||||
select: function(args) {
|
||||
var $select = args.$select;
|
||||
var $form = $select.closest('form');
|
||||
|
||||
args.response.success({
|
||||
data: [
|
||||
{
|
||||
id: 'none',
|
||||
description: 'None'
|
||||
},
|
||||
{
|
||||
id: 'lb',
|
||||
description: 'LB-based'
|
||||
},
|
||||
{
|
||||
id: 'cookie',
|
||||
description: 'Cookie-based'
|
||||
},
|
||||
{
|
||||
id: 'source',
|
||||
description: 'Source-based'
|
||||
}
|
||||
]
|
||||
}, 500);
|
||||
|
||||
$select.change(function() {
|
||||
var value = $select.val();
|
||||
var showFields = [];
|
||||
|
||||
switch (value) {
|
||||
case 'none':
|
||||
showFields = [];
|
||||
break;
|
||||
case 'lb':
|
||||
showFields = ['name', 'mode', 'nocache', 'indirect', 'postonly', 'domain'];
|
||||
break;
|
||||
case 'cookie':
|
||||
showFields = ['name', 'length', 'holdtime', 'request-learn', 'prefix', 'mode'];
|
||||
break;
|
||||
case 'source':
|
||||
showFields = ['tablesize', 'expire'];
|
||||
break;
|
||||
}
|
||||
|
||||
$select.closest('.form-item').siblings('.form-item').each(function() {
|
||||
var $field = $(this);
|
||||
var id = $field.attr('rel');
|
||||
|
||||
if ($.inArray(id, showFields) > -1) {
|
||||
$field.css('display', 'inline-block');
|
||||
} else {
|
||||
$field.hide();
|
||||
}
|
||||
});
|
||||
|
||||
$select.closest(':ui-dialog').dialog('option', 'position', 'center');
|
||||
});
|
||||
}
|
||||
},
|
||||
name: { label: 'Name', validation: { required: true }, isHidden: true },
|
||||
mode: { label: 'Mode', isHidden: true },
|
||||
length: { label: 'Length', validation: { required: true }, isHidden: true },
|
||||
holdtime: { label: 'Hold Time', validation: { required: true }, isHidden: true },
|
||||
tablesize: { label: 'Table size', isHidden: true },
|
||||
expire: { label: 'Expire', isHidden: true },
|
||||
requestlearn: { label: 'Request-Learn', isBoolean: true, isHidden: true },
|
||||
prefix: { label: 'Prefix', isBoolean: true, isHidden: true },
|
||||
nocache: { label: 'No cache', isBoolean: true, isHidden: true },
|
||||
indirect: { label: 'Indirect', isBoolean: true, isHidden: true },
|
||||
postonly: { label: 'Is post-only', isBoolean: true, isHidden: true },
|
||||
domain: { label: 'Domain', isBoolean: true, isHidden: true }
|
||||
};
|
||||
|
||||
if (args.data) {
|
||||
var populatedFields = $.map(fields, function(field, id) {
|
||||
return id;
|
||||
});
|
||||
|
||||
$(populatedFields).each(function() {
|
||||
var id = this;
|
||||
var field = fields[id];
|
||||
var dataItem = args.data[id];
|
||||
|
||||
if (field.isBoolean) {
|
||||
field.isChecked = dataItem ? true : false;
|
||||
} else {
|
||||
field.defaultValue = dataItem;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cloudStack.dialog.createForm({
|
||||
form: {
|
||||
title: 'Configure Sticky Policy',
|
||||
desc: 'Please complete the following fields',
|
||||
fields: fields
|
||||
},
|
||||
after: function(args) {
|
||||
var data = cloudStack.serializeForm(args.$form);
|
||||
success({
|
||||
data: $.extend(data, {
|
||||
_buttonLabel: data.method.toUpperCase()
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
'add-vm': {
|
||||
label: 'Add VMs',
|
||||
addButton: true
|
||||
|
|
@ -569,7 +687,17 @@
|
|||
testData.data.instances[1],
|
||||
testData.data.instances[2],
|
||||
testData.data.instances[3]
|
||||
]
|
||||
],
|
||||
sticky: {
|
||||
_buttonLabel: 'lb'.toUpperCase(),
|
||||
method: 'lb',
|
||||
name: 'StickyTest',
|
||||
mode: '123',
|
||||
nocache: true,
|
||||
indirect: false,
|
||||
postonly: true,
|
||||
domain: false
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
@ -864,9 +992,9 @@
|
|||
'icmptype': { edit: true, label: 'ICMP Type', isHidden: true },
|
||||
'icmpcode': { edit: true, label: 'ICMP Code', isHidden: true },
|
||||
'cidr': { edit: true, label: 'CIDR', isHidden: true },
|
||||
'accountname': {
|
||||
edit: true,
|
||||
label: 'Account, Security Group',
|
||||
'accountname': {
|
||||
edit: true,
|
||||
label: 'Account, Security Group',
|
||||
isHidden: true,
|
||||
range: ['accountname', 'securitygroupname']
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1507,6 +1507,124 @@
|
|||
});
|
||||
}
|
||||
},
|
||||
'sticky': {
|
||||
label: 'Sticky Policy',
|
||||
custom: {
|
||||
buttonLabel: 'Configure',
|
||||
action: function(args) {
|
||||
var success = args.response.success;
|
||||
var fields = {
|
||||
methodname: {
|
||||
label: 'Stickiness method',
|
||||
select: function(args) {
|
||||
var $select = args.$select;
|
||||
var $form = $select.closest('form');
|
||||
|
||||
args.response.success({
|
||||
data: [
|
||||
{
|
||||
id: 'none',
|
||||
description: 'None'
|
||||
},
|
||||
{
|
||||
id: 'LbCookie',
|
||||
description: 'LB-based'
|
||||
},
|
||||
{
|
||||
id: 'AppCookie',
|
||||
description: 'Cookie-based'
|
||||
},
|
||||
{
|
||||
id: 'SourceBased',
|
||||
description: 'Source-based'
|
||||
}
|
||||
]
|
||||
}, 500);
|
||||
|
||||
$select.change(function() {
|
||||
var value = $select.val();
|
||||
var showFields = [];
|
||||
|
||||
switch (value) {
|
||||
case 'none':
|
||||
showFields = [];
|
||||
break;
|
||||
case 'LbCookie':
|
||||
showFields = ['name', 'mode', 'nocache', 'indirect', 'postonly', 'domain'];
|
||||
break;
|
||||
case 'AppCookie':
|
||||
showFields = ['name', 'length', 'holdtime', 'request-learn', 'prefix', 'mode'];
|
||||
break;
|
||||
case 'SourceBased':
|
||||
showFields = ['tablesize', 'expire'];
|
||||
break;
|
||||
}
|
||||
|
||||
$select.closest('.form-item').siblings('.form-item').each(function() {
|
||||
var $field = $(this);
|
||||
var id = $field.attr('rel');
|
||||
|
||||
if ($.inArray(id, showFields) > -1) {
|
||||
$field.css('display', 'inline-block');
|
||||
} else {
|
||||
$field.hide();
|
||||
}
|
||||
});
|
||||
|
||||
$select.closest(':ui-dialog').dialog('option', 'position', 'center');
|
||||
});
|
||||
}
|
||||
},
|
||||
name: { label: 'Name', validation: { required: true }, isHidden: true },
|
||||
mode: { label: 'Mode', isHidden: true },
|
||||
length: { label: 'Length', validation: { required: true }, isHidden: true },
|
||||
holdtime: { label: 'Hold Time', validation: { required: true }, isHidden: true },
|
||||
tablesize: { label: 'Table size', isHidden: true },
|
||||
expire: { label: 'Expire', isHidden: true },
|
||||
requestlearn: { label: 'Request-Learn', isBoolean: true, isHidden: true },
|
||||
prefix: { label: 'Prefix', isBoolean: true, isHidden: true },
|
||||
nocache: { label: 'No cache', isBoolean: true, isHidden: true },
|
||||
indirect: { label: 'Indirect', isBoolean: true, isHidden: true },
|
||||
postonly: { label: 'Is post-only', isBoolean: true, isHidden: true },
|
||||
domain: { label: 'Domain', isBoolean: true, isHidden: true }
|
||||
};
|
||||
|
||||
if (args.data) {
|
||||
var populatedFields = $.map(fields, function(field, id) {
|
||||
return id;
|
||||
});
|
||||
|
||||
$(populatedFields).each(function() {
|
||||
var id = this;
|
||||
var field = fields[id];
|
||||
var dataItem = args.data[id];
|
||||
|
||||
if (field.isBoolean) {
|
||||
field.isChecked = dataItem ? true : false;
|
||||
} else {
|
||||
field.defaultValue = dataItem;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cloudStack.dialog.createForm({
|
||||
form: {
|
||||
title: 'Configure Sticky Policy',
|
||||
desc: 'Please complete the following fields',
|
||||
fields: fields
|
||||
},
|
||||
after: function(args) {
|
||||
var data = cloudStack.serializeForm(args.$form);
|
||||
success({
|
||||
data: $.extend(data, {
|
||||
_buttonLabel: data.methodname.toUpperCase()
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
'add-vm': {
|
||||
label: 'Add VMs',
|
||||
addButton: true
|
||||
|
|
@ -1516,13 +1634,20 @@
|
|||
label: 'Add VMs',
|
||||
action: function(args) {
|
||||
var openFirewall = g_firewallRuleUiEnabled == "true" ? false : true;
|
||||
var data = {
|
||||
algorithm: args.data.algorithm,
|
||||
name: args.data.name,
|
||||
privateport: args.data.privateport,
|
||||
publicport: args.data.publicport
|
||||
};
|
||||
var stickyData = $.extend(true, {}, args.data.sticky);
|
||||
|
||||
$.ajax({
|
||||
url: createURL('createLoadBalancerRule'),
|
||||
|
||||
data: $.extend(args.data, {
|
||||
data: $.extend(data, {
|
||||
openfirewall: openFirewall,
|
||||
publicipid: args.context.ipAddresses[0].id
|
||||
publicipid: args.context.ipAddresses[0].id,
|
||||
networkid: args.context.networks[0].id
|
||||
}),
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
|
|
@ -1547,7 +1672,73 @@
|
|||
},
|
||||
notification: {
|
||||
label: 'Add load balancer rule',
|
||||
poll: pollAsyncJobResult
|
||||
poll: function(args) {
|
||||
var complete = args.complete;
|
||||
var error = args.error;
|
||||
|
||||
pollAsyncJobResult({
|
||||
_custom: args._custom,
|
||||
complete: function(args) {
|
||||
// Create stickiness policy
|
||||
if (stickyData && stickyData.methodname != 'none') {
|
||||
var stickyURLData = '';
|
||||
var stickyParams;
|
||||
|
||||
switch (stickyData.methodname) {
|
||||
case 'LbCookie':
|
||||
stickyParams = ['name', 'mode', 'nocache', 'indirect', 'postonly', 'domain'];
|
||||
break;
|
||||
case 'AppCookie':
|
||||
stickyParams = ['name', 'length', 'holdtime', 'request-learn', 'prefix', 'mode'];
|
||||
break;
|
||||
case 'SourceBased':
|
||||
stickyParams = ['tablesize', 'expire'];
|
||||
break;
|
||||
}
|
||||
|
||||
$(stickyParams).each(function(index) {
|
||||
var param = '¶m[' + index + ']';
|
||||
var name = this;
|
||||
var value = stickyData[name];
|
||||
|
||||
if (!value) return true;
|
||||
if (value == 'on') value = true;
|
||||
|
||||
stickyURLData += param + '.name=' + name + param + '.value=' + value;
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: createURL('createLBStickinessPolicy' + stickyURLData),
|
||||
data: {
|
||||
lbruleid: args.data.loadbalancer.id,
|
||||
name: stickyData.name,
|
||||
methodname: stickyData.methodname
|
||||
},
|
||||
success: function(json) {
|
||||
var addStickyCheck = setInterval(function() {
|
||||
pollAsyncJobResult({
|
||||
_custom: {
|
||||
jobId: json.createLBStickinessPolicy.jobid,
|
||||
},
|
||||
complete: function(args) {
|
||||
clearInterval(addStickyCheck);
|
||||
complete();
|
||||
},
|
||||
error: function(args) {
|
||||
clearInterval(addStickyCheck);
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
},
|
||||
error: error
|
||||
});
|
||||
} else {
|
||||
complete();
|
||||
}
|
||||
},
|
||||
error: error
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ var pollAsyncJobResult = function(args) {
|
|||
});
|
||||
}
|
||||
else {
|
||||
args.complete();
|
||||
args.complete({ data: json.queryasyncjobresultresponse.jobresult });
|
||||
}
|
||||
}
|
||||
else if (result.jobstatus == 2) { // Failed
|
||||
|
|
|
|||
|
|
@ -36,30 +36,36 @@
|
|||
.appendTo($form);
|
||||
|
||||
// Render fields and events
|
||||
$.each(args.form.fields, function(key, field) {
|
||||
var fields = $.map(args.form.fields, function(value, key) {
|
||||
return key;
|
||||
})
|
||||
$(fields).each(function() {
|
||||
var key = this;
|
||||
var field = args.form.fields[key];
|
||||
|
||||
var $formItem = $('<div>')
|
||||
.addClass('form-item')
|
||||
.attr({ rel: key });
|
||||
.addClass('form-item')
|
||||
.attr({ rel: key });
|
||||
|
||||
if (this.hidden || this.isHidden) $formItem.hide();
|
||||
if (field.hidden || field.isHidden) $formItem.hide();
|
||||
|
||||
$formItem.appendTo($form);
|
||||
|
||||
// Label field
|
||||
var $name = $('<div>').addClass('name')
|
||||
.appendTo($formItem)
|
||||
.append(
|
||||
$('<label>').html(this.label + ':')
|
||||
);
|
||||
.appendTo($formItem)
|
||||
.append(
|
||||
$('<label>').html(field.label + ':')
|
||||
);
|
||||
|
||||
// Input area
|
||||
var $value = $('<div>').addClass('value')
|
||||
.appendTo($formItem);
|
||||
.appendTo($formItem);
|
||||
var $input, $dependsOn, selectFn, selectArgs;
|
||||
var dependsOn = this.dependsOn;
|
||||
var dependsOn = field.dependsOn;
|
||||
|
||||
// Depends on fields
|
||||
if (this.dependsOn) {
|
||||
if (field.dependsOn) {
|
||||
$formItem.attr('depends-on', dependsOn);
|
||||
$dependsOn = $form.find('input, select').filter(function() {
|
||||
return $(this).attr('name') === dependsOn;
|
||||
|
|
@ -105,7 +111,7 @@
|
|||
}
|
||||
|
||||
// Determine field type of input
|
||||
if (this.select) {
|
||||
if (field.select) {
|
||||
selectArgs = {
|
||||
context: args.context,
|
||||
response: {
|
||||
|
|
@ -120,17 +126,21 @@
|
|||
description = this.description;
|
||||
|
||||
var $option = $('<option>')
|
||||
.appendTo($input)
|
||||
.val(id)
|
||||
.html(description);
|
||||
.appendTo($input)
|
||||
.val(id)
|
||||
.html(description);
|
||||
});
|
||||
|
||||
if (field.defaultValue) {
|
||||
$input.val(field.defaultValue);
|
||||
}
|
||||
|
||||
$input.trigger('change');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
selectFn = this.select;
|
||||
selectFn = field.select;
|
||||
$input = $('<select>')
|
||||
.attr({ name: key })
|
||||
.data('dialog-select-fn', function() {
|
||||
|
|
@ -170,12 +180,12 @@
|
|||
} else {
|
||||
selectFn(selectArgs);
|
||||
}
|
||||
} else if (this.isBoolean) {
|
||||
if (this.multiArray) {
|
||||
} else if (field.isBoolean) {
|
||||
if (field.multiArray) {
|
||||
$input = $('<div>')
|
||||
.addClass('multi-array').addClass(key).appendTo($value);
|
||||
|
||||
$.each(this.multiArray, function(itemKey, itemValue) {
|
||||
$.each(field.multiArray, function(itemKey, itemValue) {
|
||||
$input.append(
|
||||
$('<div>').addClass('item')
|
||||
.append(
|
||||
|
|
@ -191,16 +201,16 @@
|
|||
|
||||
} else {
|
||||
$input = $('<input>').attr({ name: key, type: 'checkbox' }).appendTo($value);
|
||||
if (this.isChecked) {
|
||||
if (field.isChecked) {
|
||||
$input.attr('checked', 'checked');
|
||||
}
|
||||
}
|
||||
} else if (this.dynamic) {
|
||||
} else if (field.dynamic) {
|
||||
// Generate a 'sub-create-form' -- append resulting fields
|
||||
$input = $('<div>').addClass('dynamic-input').appendTo($value);
|
||||
$form.hide();
|
||||
|
||||
this.dynamic({
|
||||
field.dynamic({
|
||||
response: {
|
||||
success: function(args) {
|
||||
var form = cloudStack.dialog.createForm({
|
||||
|
|
@ -221,18 +231,18 @@
|
|||
});
|
||||
} else {
|
||||
// Text field
|
||||
if (this.range) {
|
||||
if (field.range) {
|
||||
$input = $.merge(
|
||||
// Range start
|
||||
$('<input>').attr({
|
||||
type: 'text',
|
||||
name: this.range[0]
|
||||
name: field.range[0]
|
||||
}),
|
||||
|
||||
// Range end
|
||||
$('<input>').attr({
|
||||
type: 'text',
|
||||
name: this.range[1]
|
||||
name: field.range[1]
|
||||
})
|
||||
).appendTo(
|
||||
$('<div>').addClass('range-edit').appendTo($value)
|
||||
|
|
@ -242,16 +252,16 @@
|
|||
} else {
|
||||
$input = $('<input>').attr({
|
||||
name: key,
|
||||
type: this.password || this.isPassword ? 'password' : 'text'
|
||||
type: field.password || field.isPassword ? 'password' : 'text'
|
||||
}).appendTo($value);
|
||||
|
||||
if (this.defaultValue) {
|
||||
$input.val(this.defaultValue);
|
||||
if (field.defaultValue) {
|
||||
$input.val(field.defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$input.data('validation-rules', this.validation);
|
||||
$input.data('validation-rules', field.validation);
|
||||
$('<label>').addClass('error').appendTo($value).html('*required');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,27 @@
|
|||
_medit.details(itemData[0], $browser, { context: options.context });
|
||||
}
|
||||
});
|
||||
} else if (field.custom) {
|
||||
$td.data('multi-custom-data', data[fieldName]);
|
||||
$('<div>').addClass('button add-vm custom-action')
|
||||
.html(data && data[fieldName] && data[fieldName]['_buttonLabel'] ?
|
||||
data[fieldName]['_buttonLabel'] : field.custom.buttonLabel)
|
||||
.click(function() {
|
||||
var $button = $(this);
|
||||
field.custom.action({
|
||||
context: {},
|
||||
data: $td.data('multi-custom-data'),
|
||||
response: {
|
||||
success: function(args) {
|
||||
if (args.data['_buttonLabel']) {
|
||||
$button.html(args.data['_buttonLabel']);
|
||||
}
|
||||
$td.data('multi-custom-data', args.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.appendTo($td);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -413,6 +434,20 @@
|
|||
.attr('disabled', field.isDisabled ? 'disabled' : false)
|
||||
.appendTo($td);
|
||||
}
|
||||
} else if (field.custom) {
|
||||
$('<div>').addClass('button add-vm custom-action')
|
||||
.html(field.custom.buttonLabel)
|
||||
.click(function() {
|
||||
field.custom.action({
|
||||
context: context,
|
||||
data: $td.data('multi-custom-data'),
|
||||
response: {
|
||||
success: function(args) {
|
||||
$td.data('multi-custom-data', args.data);
|
||||
}
|
||||
}
|
||||
})
|
||||
}).appendTo($td);
|
||||
} else if (field.addButton) {
|
||||
$addVM = $('<div>').addClass('button add-vm').html(
|
||||
args.add.label
|
||||
|
|
@ -483,6 +518,19 @@
|
|||
}
|
||||
});
|
||||
|
||||
// Append custom data
|
||||
var $customFields = $multi.find('tbody td').filter(function() {
|
||||
return $(this).data('multi-custom-data');
|
||||
});
|
||||
|
||||
$customFields.each(function() {
|
||||
var $field = $(this);
|
||||
var fieldID = $field.attr('rel');
|
||||
var fieldData = $field.data('multi-custom-data');
|
||||
|
||||
data[fieldID] = fieldData;
|
||||
});
|
||||
|
||||
// Loading appearance
|
||||
var $loading = _medit.loadingItem($multi, 'Adding...');
|
||||
$dataBody.prepend($loading);
|
||||
|
|
|
|||
Loading…
Reference in New Issue