deform.js
194 lines
| 7.0 KiB
| application/javascript
|
JavascriptLexer
r524 | /* | |||
* Register a top-level callback to the deform.load() function | ||||
* this will be called when the DOM has finished loading. No need | ||||
* to include the call at the end of the page. | ||||
*/ | ||||
$(document).ready(function(){ | ||||
deform.load(); | ||||
}); | ||||
var deform_loaded = false; | ||||
var deform = { | ||||
callbacks: [], | ||||
addCallback: function (oid, callback) { | ||||
deform.callbacks.push([oid, callback]); | ||||
}, | ||||
clearCallbacks: function () { | ||||
deform.callbacks = []; | ||||
}, | ||||
load: function() { | ||||
$(function() { | ||||
if (!deform_loaded) { | ||||
deform.processCallbacks(); | ||||
deform.focusFirstInput(); | ||||
deform_loaded = true; | ||||
}}); | ||||
}, | ||||
processCallbacks: function () { | ||||
$(deform.callbacks).each(function(num, item) { | ||||
var oid = item[0]; | ||||
var callback = item[1]; | ||||
callback(oid); | ||||
} | ||||
); | ||||
deform.clearCallbacks(); | ||||
}, | ||||
addSequenceItem: function (protonode, before) { | ||||
// - Clone the prototype node and add it before the "before" node. | ||||
// Also ensure any callbacks are run for the widget. | ||||
// In order to avoid breaking accessibility: | ||||
// | ||||
// - Find each tag within the prototype node with an id | ||||
// that has the string ``deformField(\d+)`` within it, and modify | ||||
// its id to have a random component. | ||||
// - For each label referencing an change id, change the label's | ||||
// for attribute to the new id. | ||||
var fieldmatch = /deformField(\d+)/; | ||||
var namematch = /(.+)?-[#]{3}/; | ||||
var code = protonode.attr('prototype'); | ||||
var html = decodeURIComponent(code); | ||||
var $htmlnode = $(html); | ||||
var $idnodes = $htmlnode.find('[id]'); | ||||
var $namednodes = $htmlnode.find('[name]'); | ||||
var genid = deform.randomString(6); | ||||
var idmap = {}; | ||||
// replace ids containing ``deformField`` and associated label for= | ||||
// items which point at them | ||||
$idnodes.each(function(idx, node) { | ||||
var $node = $(node); | ||||
var oldid = $node.attr('id'); | ||||
var newid = oldid.replace(fieldmatch, "deformField$1-" + genid); | ||||
$node.attr('id', newid); | ||||
idmap[oldid] = newid; | ||||
var labelselector = 'label[for=' + oldid + ']'; | ||||
var $fornodes = $htmlnode.find(labelselector); | ||||
$fornodes.attr('for', newid); | ||||
}); | ||||
// replace names a containing ```deformField`` like we do for ids | ||||
$namednodes.each(function(idx, node) { | ||||
var $node = $(node); | ||||
var oldname = $node.attr('name'); | ||||
var newname = oldname.replace(fieldmatch, "deformField$1-" + genid); | ||||
$node.attr('name', newname); | ||||
}); | ||||
$htmlnode.insertBefore(before); | ||||
$(deform.callbacks).each(function(num, item) { | ||||
var oid = item[0]; | ||||
var callback = item[1]; | ||||
var newid = idmap[oid]; | ||||
if (newid) { | ||||
callback(newid); | ||||
} | ||||
}); | ||||
deform.clearCallbacks(); | ||||
var old_len = parseInt(before.attr('now_len')||'0', 10); | ||||
before.attr('now_len', old_len + 1); | ||||
// we added something to the dom, trigger a change event | ||||
var e = jQuery.Event("change"); | ||||
$('#deform').trigger(e); | ||||
}, | ||||
appendSequenceItem: function(node) { | ||||
var $oid_node = $(node).closest('.deform-seq'); | ||||
var $proto_node = $oid_node.find('.deform-proto').first(); | ||||
var $before_node = $oid_node.find('.deform-insert-before').last(); | ||||
var min_len = parseInt($before_node.attr('min_len')||'0', 10); | ||||
var max_len = parseInt($before_node.attr('max_len')||'9999', 10); | ||||
var now_len = parseInt($before_node.attr('now_len')||'0', 10); | ||||
var orderable = parseInt($before_node.attr('orderable')||'0', 10); | ||||
if (now_len < max_len) { | ||||
deform.addSequenceItem($proto_node, $before_node); | ||||
deform.processSequenceButtons($oid_node, min_len, max_len, | ||||
now_len + 1, orderable); | ||||
} | ||||
return false; | ||||
}, | ||||
removeSequenceItem: function(clicked) { | ||||
var $item_node = $(clicked).closest('.deform-seq-item'); | ||||
var $oid_node = $item_node.closest('.deform-seq'); | ||||
var $before_node = $oid_node.find('.deform-insert-before').last(); | ||||
var min_len = parseInt($before_node.attr('min_len')||'0', 10); | ||||
var max_len = parseInt($before_node.attr('max_len')||'9999', 10); | ||||
var now_len = parseInt($before_node.attr('now_len')||'0', 10); | ||||
var orderable = parseInt($before_node.attr('orderable')||'0', 10); | ||||
if (now_len > min_len) { | ||||
$before_node.attr('now_len', now_len - 1); | ||||
$item_node.remove(); | ||||
deform.processSequenceButtons($oid_node, min_len, max_len, | ||||
now_len-1, orderable); | ||||
} | ||||
// we removed something from the dom, trigger a change event | ||||
var e = jQuery.Event("change"); | ||||
$('#deform').trigger(e); | ||||
return false; | ||||
}, | ||||
processSequenceButtons: function(oid_node, min_len, max_len, now_len, | ||||
orderable) { | ||||
orderable = !!orderable; // convert to bool | ||||
var has_multiple = now_len > 1; | ||||
var $ul = oid_node.find('.deform-seq-container').not(oid_node.find('.deform-seq-container .deform-seq-container')); | ||||
var $lis = $ul.find('.deform-seq-item').not($ul.find('.deform-seq-container .deform-seq-item')); | ||||
var show_closebutton = now_len > min_len; | ||||
var show_addbutton = now_len < max_len; | ||||
$lis.find('.deform-close-button').not($lis.find('.deform-seq-container .deform-close-button')).toggle(show_closebutton); | ||||
oid_node.find('.deform-seq-add').not(oid_node.find('.deform-seq-container .deform-seq-add')).toggle(show_addbutton); | ||||
$lis.find('.deform-order-button').not($lis.find('.deform-seq-container .deform-order-button')).toggle(orderable && has_multiple); | ||||
}, | ||||
focusFirstInput: function (el) { | ||||
el = el || document.body; | ||||
var input = $(el).find(':input') | ||||
.filter('[id ^= deformField]') | ||||
.filter('[type != hidden]') | ||||
.first(); | ||||
if (input) { | ||||
var raw = input.get(0); | ||||
if (raw) { | ||||
if (raw.type === 'text' || raw.type === 'file' || | ||||
raw.type == 'password' || raw.type == 'text' || | ||||
raw.type == 'textarea') { | ||||
if (!input.hasClass("hasDatepicker")) { | ||||
input.focus(); | ||||
} | ||||
} | ||||
} | ||||
} | ||||
}, | ||||
randomString: function (length) { | ||||
var chr='0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'; | ||||
chr = chr.split(''); | ||||
if (! length) { | ||||
length = Math.floor(Math.random() * chr.length); | ||||
} | ||||
var str = ''; | ||||
for (var i = 0; i < length; i++) { | ||||
str += chr[Math.floor(Math.random() * chr.length)]; | ||||
} | ||||
return str; | ||||
} | ||||
}; | ||||