Skip to content

Instantly share code, notes, and snippets.

@matiaskorhonen
Created May 15, 2017 07:25
Show Gist options
  • Save matiaskorhonen/f79b04a73e49b2aa26e10aa987e472b0 to your computer and use it in GitHub Desktop.
Save matiaskorhonen/f79b04a73e49b2aa26e10aa987e472b0 to your computer and use it in GitHub Desktop.
// matches polyfill
this.Element && function(ElementPrototype) {
ElementPrototype.matches = ElementPrototype.matches ||
ElementPrototype.matchesSelector ||
ElementPrototype.webkitMatchesSelector ||
ElementPrototype.msMatchesSelector ||
function(selector) {
var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
while (nodes[++i] && nodes[i] != node);
return !!nodes[i];
}
}(Element.prototype);
// closest polyfill
this.Element && function(ElementPrototype) {
ElementPrototype.closest = ElementPrototype.closest ||
function(selector) {
var el = this;
while (el.matches && !el.matches(selector)) el = el.parentNode;
return el.matches ? el : null;
}
}(Element.prototype);
(function($) {
var cocoon_element_counter = 0;
var create_new_id = function() {
return (new Date().getTime() + cocoon_element_counter++);
}
var newcontent_braced = function(id) {
return '[' + id + ']$1';
}
var newcontent_underscord = function(id) {
return '_' + id + '_$1';
}
var getInsertionNodeElem = function(insertionNode, insertionTraversal, $this){
if (!insertionNode){
return $this.parentNode;
}
if (typeof insertionNode == 'function') {
if (insertionTraversal) {
console.warn('association-insertion-traversal is ignored, because association-insertion-node is given as a function.')
}
return insertionNode($this);
}
if(typeof insertionNode == 'string'){
if (insertionTraversal) {
return $this[insertionTraversal](insertionNode);
} else {
return insertionNode == "this" ? $this : insertionNode;
}
}
}
function hasClass(el, className) {
if (el.classList) {
return el.classList.contains(className);
} else {
return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
}
}
function trigger(el, customEvent, data) {
if (window.CustomEvent) {
var event = new CustomEvent(customEvent, {detail: data});
} else {
var event = document.createEvent('CustomEvent');
event.initCustomEvent(customEvent, true, true, data);
}
el.dispatchEvent(event);
}
document.addEventListener('click', function(e) {
var el = event.target;
if (hasClass(el, 'add_fields')) {
e.preventDefault();
var //self = $(this),
assoc = el.getAttribute('data-association'),
assocs = el.getAttribute('data-associations'),
content = el.getAttribute('data-association-insertion-template'),
insertionMethod = el.getAttribute('data-association-insertion-method') || el.getAttribute('data-association-insertion-position') || 'before',
insertionNode = el.getAttribute('data-association-insertion-node'),
insertionTraversal = el.getAttribute('data-association-insertion-traversal'),
count = parseInt(el.getAttribute('data-count'), 10),
regexp_braced = new RegExp('\\[new_' + assoc + '\\](.*?\\s)', 'g'),
regexp_underscord = new RegExp('_new_' + assoc + '_(\\w*)', 'g'),
new_id = create_new_id(),
new_content = content.replace(regexp_braced, newcontent_braced(new_id)),
new_contents = [];
if (new_content == content) {
regexp_braced = new RegExp('\\[new_' + assocs + '\\](.*?\\s)', 'g');
regexp_underscord = new RegExp('_new_' + assocs + '_(\\w*)', 'g');
new_content = content.replace(regexp_braced, newcontent_braced(new_id));
}
new_content = new_content.replace(regexp_underscord, newcontent_underscord(new_id));
new_contents = [new_content];
count = (isNaN(count) ? 1 : Math.max(count, 1));
count -= 1;
while (count) {
new_id = create_new_id();
new_content = content.replace(regexp_braced, newcontent_braced(new_id));
new_content = new_content.replace(regexp_underscord, newcontent_underscord(new_id));
new_contents.push(new_content);
count -= 1;
}
var insertionNodeElem = getInsertionNodeElem(insertionNode, insertionTraversal, el)
if( !insertionNodeElem || (insertionNodeElem.length == 0) ){
console.warn("Couldn't find the element to insert the template. Make sure your `data-association-insertion-*` on `link_to_add_association` is correct.")
}
new_contents.forEach(function(node, index) {
var contentNode = node;
trigger(insertionNodeElem, 'cocoon:before-insert', [contentNode])
// allow any of the jquery dom manipulation methods (after, before, append, prepend, etc)
// to be called on the node. allows the insertion node to be the parent of the inserted
// code and doesn't force it to be a sibling like after/before does. default: 'before'
var addedContent = insertionNodeElem[insertionMethod](contentNode);
trigger(insertionNodeElem, 'cocoon:after-insert', [contentNode])
});
}
});
document.addEventListener('click', function(e) {
var el = event.target;
if (hasClass(el, 'remove_fields') && (hasClass(el, 'dynamic') || hasClass(el, 'existing'))) {
var self = this,
wrapper_class = this.getAttribute('data-wrapper-class') || 'nested-fields',
node_to_delete = this.closest('.' + wrapper_class),
trigger_node = node_to_delete.parentNode;
e.preventDefault();
trigger_node.trigger('cocoon:before-remove', [node_to_delete]);
var timeout = trigger_node.data('remove-timeout') || 0;
setTimeout(function() {
if (hasClass(self, 'dynamic')) {
node_to_delete.remove();
} else {
$this.prev("input[type=hidden]").val("1");
node_to_delete.hide();
}
trigger_node.trigger('cocoon:after-remove', [node_to_delete]);
}, timeout);
}
});
function onPageLoad() {
// $('.remove_fields.existing.destroyed').each(function(i, obj) {
// var wrapper_class = this.fgetAttribute('data-wrapper-class') || 'nested-fields',
// el = this.closest('.' + wrapper_class);
//
// if (el) {
// el.style.display = 'none'
// };
// });
}
document.addEventListener('ready', onPageLoad);
document.addEventListener('page:load', onPageLoad);
document.addEventListener('turbolinks:load', onPageLoad);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment