-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
81935c0
commit 5f5fdf4
Showing
6 changed files
with
256 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
module.exports = { | ||
"root": true, | ||
"extends": "eslint:recommended", | ||
"env": { | ||
"node": true, | ||
"es6": true, | ||
"amd": true, | ||
"browser": true | ||
}, | ||
"parserOptions": { | ||
"ecmaFeatures": { | ||
"globalReturn": true, | ||
"generators": false, | ||
"objectLiteralDuplicateProperties": false, | ||
"experimentalObjectRestSpread": true | ||
}, | ||
"ecmaVersion": 2017, | ||
"sourceType": "module" | ||
}, | ||
"plugins": [ | ||
"import" | ||
], | ||
"settings": { | ||
"import/core-modules": [], | ||
"import/ignore": [ | ||
"node_modules", | ||
"\\.(coffee|scss|css|less|hbs|svg|json)$" | ||
] | ||
}, | ||
"rules": { | ||
"no-console": 0, | ||
"comma-dangle": [ | ||
"error", | ||
{ | ||
"arrays": "always-multiline", | ||
"objects": "always-multiline", | ||
"imports": "always-multiline", | ||
"exports": "always-multiline", | ||
"functions": "ignore" | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,25 @@ | ||
# cocoon-vanilla-js | ||
# cocoon-vanilla-js (private) | ||
|
||
A vanilla JS replacement for (Rails) Cocoon's jQuery script | ||
|
||
|
||
## Usage | ||
|
||
Replace `<token>` and `<commit>` with the corresponding values: | ||
|
||
``` | ||
yarn add git+https://<token>:[email protected]/kollegorna/cocoon-vanilla-js.git#<commit> | ||
``` | ||
|
||
Import as ES6 module: | ||
|
||
```js | ||
import 'cocoon-vanilla-js' | ||
``` | ||
|
||
## Notes | ||
|
||
To broaden browser support, use the following polyfills: | ||
|
||
- [Element.closest](https://www.npmjs.com/package/element-closest) | ||
- [Element.classList](https://www.npmjs.com/package/classlist-polyfill) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
let cocoon_element_counter = 0; | ||
|
||
const create_new_id = function() { | ||
return (new Date().getTime() + cocoon_element_counter++); | ||
}; | ||
|
||
const newcontent_braced = function(id) { | ||
return '[' + id + ']$1'; | ||
}; | ||
|
||
const newcontent_underscord = function(id) { | ||
return '_' + id + '_$1'; | ||
}; | ||
|
||
const getInsertionNodeElem = function(insertionNode, insertionTraversal, btn) { | ||
if(!insertionNode){ | ||
return btn.parentNode; | ||
} | ||
else { // string | ||
if(insertionTraversal) { | ||
// TODO: | ||
// https://github.com/nathanvda/cocoon/blob/master/app/assets/javascripts/cocoon.js#L32 | ||
// data-association-insertion-traversal: the jquery traversal method to | ||
// allow node selection relative to the link. closest, next, children, etc. | ||
// return $this[insertionTraversal](insertionNode); | ||
return null; | ||
} | ||
else { | ||
return document.querySelector(insertionNode); | ||
} | ||
} | ||
}; | ||
|
||
const addFieldsHandler = (btn) => { | ||
const assoc = btn.getAttribute('data-association'); | ||
const assocs = btn.getAttribute('data-associations'); | ||
const content = btn.getAttribute('data-association-insertion-template'); | ||
const insertionNode = btn.getAttribute('data-association-insertion-node'); | ||
const insertionTraversal = btn.getAttribute('data-association-insertion-traversal'); | ||
let insertionMethod = btn.getAttribute('data-association-insertion-method') || btn.getAttribute('data-association-insertion-position') || 'before'; | ||
let new_id = create_new_id(); | ||
let count = parseInt(btn.getAttribute('data-count'), 10); | ||
let regexp_braced = new RegExp('\\[new_' + assoc + '\\](.*?\\s)', 'g'); | ||
let regexp_underscord = new RegExp('_new_' + assoc + '_(\\w*)', 'g'); | ||
let new_content = content.replace(regexp_braced, newcontent_braced(new_id)); | ||
let 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; | ||
} | ||
|
||
const insertionNodeElem = getInsertionNodeElem(insertionNode, insertionTraversal, btn); | ||
|
||
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((node) => { | ||
const event = new CustomEvent('cocoon:before-insert', {detail: node}); | ||
insertionNodeElem.dispatchEvent(event); | ||
|
||
if(!event.defaultPrevented) { | ||
switch(insertionMethod) { | ||
default: | ||
case 'before': | ||
insertionMethod = 'beforebegin'; | ||
break; | ||
case 'after': | ||
insertionMethod = 'afterend'; | ||
break; | ||
case 'append': | ||
insertionMethod = 'beforeend'; | ||
break; | ||
case 'prepend': | ||
insertionMethod = 'afterbegin'; | ||
break; | ||
} | ||
|
||
insertionNodeElem.insertAdjacentHTML(insertionMethod, node); | ||
insertionNodeElem.dispatchEvent( | ||
CustomEvent('cocoon:before-insert', {detail: node}) | ||
); | ||
} | ||
}); | ||
}; | ||
|
||
document.addEventListener('click', (e) => { | ||
if(e.target.matches('.add_fields')) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
addFieldsHandler(e.target); | ||
} | ||
}); | ||
|
||
const removeFieldsHandler = (btn) => { | ||
const wrapperClass = btn.getAttribute('data-wrapper-class') || 'nested-fields'; | ||
const nodeToDelete = btn.closest(`.${wrapperClass}`); | ||
const triggerNode = nodeToDelete.parentNode; | ||
|
||
const event = new CustomEvent('cocoon:before-remove', {detail: nodeToDelete}); | ||
triggerNode.dispatchEvent(event); | ||
|
||
if(!event.defaultPrevented) { | ||
const timeout = triggerNode.getAttribute('data-remove-timeout') || 0; | ||
|
||
setTimeout(() => { | ||
if(btn.classList.contains('dynamic')) { | ||
// nodeToDelete.remove(); | ||
nodeToDelete.parentNode.removeChild(nodeToDelete); | ||
} | ||
else { | ||
const input = btn.previousElementSibling; | ||
if(input && input.matches('input[type=hidden]')) { | ||
input.value = 1; | ||
} | ||
nodeToDelete.style.display = 'none'; | ||
} | ||
|
||
triggerNode.dispatchEvent( | ||
CustomEvent('cocoon:after-remove', {detail: nodeToDelete}) | ||
); | ||
}, timeout); | ||
} | ||
}; | ||
|
||
document.addEventListener('click', (e) => { | ||
if( | ||
e.target.matches('.remove_fields.dynamic') || | ||
e.target.matches('.remove_fields.existing') | ||
) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
removeFieldsHandler(e.target); | ||
} | ||
}); | ||
|
||
const hideFields = () => { | ||
[...document.querySelectorAll('.remove_fields.existing.destroyed')].forEach((btn) => { | ||
const wrapperClass = btn.getAttribute('data-wrapper-class') || 'nested-fields'; | ||
btn.closest(`.${wrapperClass}`).style.display = 'none'; | ||
}); | ||
}; | ||
|
||
document.addEventListener('DOMContentLoaded', hideFields); | ||
document.addEventListener('turbolinks:load', hideFields); | ||
document.addEventListener('page:load', hideFields); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "cocoon-vanilla-js", | ||
"version": "1.0.0", | ||
"description": "A vanilla JS replacement for (Rails) Cocoon's jQuery script", | ||
"main": "index.js", | ||
"engines": { | ||
"node": "<=9.11.2" | ||
}, | ||
"repository": "git+https://github.com/kollegorna/cocoon-vanilla-js.git", | ||
"author": "Kollegorna", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/kollegorna/cocoon-vanilla-js/issues" | ||
}, | ||
"homepage": "https://github.com/kollegorna/cocoon-vanilla-js#readme", | ||
"devDependencies": {}, | ||
"dependencies": {}, | ||
"private": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | ||
# yarn lockfile v1 | ||
|
||
|
||
"js-utils@git+https://8265015e18616ae2d58e38f4fd9ca111b8beaff8:[email protected]/kollegorna/js-utils.git#6507589": | ||
version "1.0.0" | ||
resolved "git+https://8265015e18616ae2d58e38f4fd9ca111b8beaff8:[email protected]/kollegorna/js-utils.git#6507589ae81c91ff2db72d7c4905a3d2d52674f9" |