engine/public/javascripts/admin/custom_fields/has_many.js

192 lines
5.5 KiB
JavaScript

$(document).ready(function() {
// add/remove/sort items in a has_many relationship
$('.has-many-selector').hasManySelector();
});
(function($){
$.fn.hasManySelector = function(options) {
var populateSelect = function(context) {
context.select.find('optgroup, option').remove();
for (var i = 0; i < context.data.collection.length; i++) {
var obj = context.data.collection[i];
if (typeof(obj.name) != 'undefined') { // grouped items
var optgroup = $('<optgroup/>').attr('label', obj.name);
var size = 0;
for (var j = 0; j < obj.items.length; j++) {
var innerObj = obj.items[j];
if ($.inArray(innerObj[1], context.data.taken_ids) == -1) {
optgroup.append(new Option(innerObj[0], innerObj[1], true, true));
size++;
}
}
if (size > 0) context.select.append(optgroup);
} else {
if ($.inArray(obj[1], context.data.taken_ids) == -1)
context.select.append(new Option(obj[0], obj[1], true, true));
}
}
if (context.select.find('option').size() == 0)
context.list.find('li.template').hide();
else
context.list.find('li.template').show();
}
var addId = function(context, id) {
context.data.taken_ids.push(id);
populateSelect(context);
if (context.data.taken_ids.length > 0) {
context.empty.hide();
context.list.next('input[type=hidden]').remove();
}
if (context.data.taken_ids.length == context.data.collection.length)
context.sep.hide();
}
var removeId = function(context, id) {
context.data.taken_ids = jQuery.grep(context.data.taken_ids, function(value) {
return value != id;
});
populateSelect(context);
if (context.data.taken_ids.length == 0) {
context.empty.show();
context.list.after('<input type="hidden" name="' + context.baseInputName + '" value="" />');
}
context.sep.show();
}
var registerElementEvents = function(context, data, domElement) {
// remove
domElement.find('a.remove').click(function(e) {
domElement.remove();
removeId(context, data.id);
context.list.sortable('refresh');
e.preventDefault(); e.stopPropagation();
});
}
var registerElementTemplateEvents = function(context, domElement) {
// bind the "Add field" button
domElement.find('button').click(function(e) {
var newElement = {
id: context.select.val(),
label: context.select.find('option:selected').text()
};
addId(context, newElement.id);
addElement(context, newElement, { refreshPosition: true });
context.list.sortable('refresh');
e.preventDefault(); e.stopPropagation();
});
}
/* ___ Add an element into the list ___ */
var addElement = function(context, data, options) {
options = $.extend({
'is_template': false,
'refreshPosition': false
}, options);
data = $.extend({
behaviour_flag: function() { return options.is_template ? 'template' : 'added' },
base_name: function() { return options.is_template ? '' : context.baseInputName },
if_template: function() { return options.is_template }
}, data);
var html = Mustache.to_html(context.template, data);
var domElement = null;
if (options.is_template) {
domElement = context.list.append('<li class="sep">&nbsp;</li>').append(html).find('.template');
context.sep = context.list.find('.sep');
registerElementTemplateEvents(context, domElement);
}
else {
domElement = context.list.find('> .sep').before(html).prev('li');
registerElementEvents(context, data, domElement);
context.error.hide();
context.list.sortable('refresh');
}
}
return this.each(function() {
var wrapper = $(this);
var context = {
list: wrapper.find('ul'),
empty: wrapper.find('p:first'),
template: wrapper.find('script[name=template]').html(),
baseInputName: wrapper.find('script[name=template]').attr('data-base-input-name'),
data: eval(wrapper.find('script[name=data]').html()),
error: wrapper.parent().find('p.inline-errors')
};
// sortable list
context.list.sortable({
handle: 'span.handle',
items: 'li:not(.template)',
axis: 'y'
});
// add the template element used to insert the new ones
addElement(context, null, { is_template: true });
context.select = wrapper.find('select[name=label]');
populateSelect(context);
for (var i = 0; i < context.data.taken_ids.length; i++) {
var data = { id: context.data.taken_ids[i], label: null };
for (var j = 0; j < context.data.collection.length; j++) {
var current = context.data.collection[j];
if (typeof(current.name) == 'undefined') {
if (data.id == current[1]) {
data.label = current[0];
break;
}
} else { // loop thru the groups
for (var k = 0; k < current.items.length; k++) {
var localCurrent = current.items[k];
if (data.id == localCurrent[1]) {
data.label = localCurrent[0];
break;
}
}
}
}
addElement(context, data);
}
if (context.error.size() > 0)
context.error.show();
});
};
})(jQuery);