Alien-GvaScript
view release on metacpan or search on metacpan
src/repeat.js view on Meta::CPAN
// repetition block gets an event
placeholder.fireEvent("Add", insertion_block);
// deal with nested repeated sections
this._init_repeat_elements(insertion_block, repeat.path);
// restore initial path
repeat.path = path_ini;
}
return repeat.count;
},
remove: function(repetition_block, live_update) {
// default behavior to live update all blocks below
// the removed block
if(typeof live_update == 'undefined') live_update = true;
// find element, placeholder and repeat info
var elem = $(repetition_block);
elem.id.match(/(.*)\.(\d+)$/);
var repeat_name = RegExp.$1;
var remove_ix = RegExp.$2;
var placeholder = this._find_placeholder(repeat_name);
var max = placeholder.repeat.count;
// fire onRemove event
// remove block from DOM
var block = $(repeat_name + "." + remove_ix);
placeholder.fireEvent("Remove", block);
block.remove();
// if live_update
if(live_update) {
// update repeat.count as first block has been deleted
placeholder.repeat.count -= 1;
// remove all blocks below
var _start_ix = remove_ix;
while(++_start_ix < max) {
block = $(repeat_name + "." + _start_ix);
block.remove();
placeholder.repeat.count -= 1;
}
// re-add the blocks above so that they will be renumbered
var n_add = max - remove_ix - 1;
if (n_add > 0) this.add(placeholder, n_add);
}
},
//-----------------------------------------------------
// Private methods
//-----------------------------------------------------
_find_placeholder: function(name) {
if (typeof name == "string" && !name.match(/.placeholder$/))
name += ".placeholder";
var placeholder = $(name);
if (!placeholder) throw new Error("no such element: " + name);
return placeholder;
},
_init_repeat_elements: function(elem, path) {
elem = $(elem);
if (elem) {
var elements = this._find_repeat_elements(elem);
for (var i = 0; i < elements.length; i++) {
this._init_repeat_element(elements[i], path);
}
}
},
_find_repeat_elements: function(elem) {
var result = [];
// navigate DOM, do not recurse under "repeat" nodes
for (var child = elem.firstChild; child; child = child.nextSibling) {
var has_repeat = child.nodeType == 1 && child.getAttribute('repeat');
result.push(has_repeat ? child : this._find_repeat_elements(child));
}
return result.flatten();
},
_init_repeat_element: function(element, path) {
element = $(element);
path = path || element.getAttribute('repeat-prefix');
// number of initial repetition blocks
var n_blocks = element.getAttribute('repeat-start');
if (n_blocks == undefined) n_blocks = 1;
// hash to hold all properties of the repeat element
var repeat = {};
repeat.name = element.getAttribute('repeat');
repeat.min = element.getAttribute('repeat-min') || 0;
repeat.max = element.getAttribute('repeat-max') || 99;
repeat.count = 0;
repeat.path = (path ? path + "." : "") + repeat.name;
// create a new element (placeholder for new insertion blocks)
var placeholder_tag = element.tagName.match(/^(TR|TD|TBODY|THEAD|TH)$/i)
? element.tagName
: 'SPAN';
var placeholder = document.createElement(placeholder_tag);
placeholder.id = repeat.path + ".placeholder";
placeholder.fireEvent = GvaScript.fireEvent;
element.parentNode.insertBefore(placeholder, element);
// take this elem out of the DOM and into a string ...
{
// a) force the id that will be needed in the template)
element.id = "#{" + repeat.name + ".path}";
// b) remove "repeat*" attributes (don't want them in the template)
var attrs = element.attributes;
var repeat_attrs = [];
for (var i = 0; i < attrs.length; i++) {
var name = attrs[i].name;
if (name.match(/^repeat/i)) repeat_attrs.push(name);
( run in 0.555 second using v1.01-cache-2.11-cpan-119454b85a5 )