diff --git a/README.md b/README.md
index 99808825..04d871d6 100644
--- a/README.md
+++ b/README.md
@@ -298,7 +298,7 @@ var tagify = new Tagify(inputElement)
// bind "DragSort" to Tagify's main element and tell
// it that all the items with the below "selector" are "draggable"
var dragsort = new DragSort(tagify.DOM.scope, {
- selector: '.'+tagify.settings.classNames.tag,
+ selector: tagify.settings.tagSelector,
callbacks: {
dragEnd: onDragEnd
}
diff --git a/index.html b/index.html
index 1d8af367..b66775c7 100644
--- a/index.html
+++ b/index.html
@@ -1585,7 +1585,7 @@
+ return `
No suggestion found for: ${data.value}
`
}
@@ -2130,7 +2130,7 @@
JAVASCRIPT
// using 3-party script "dragsort"
// https://github.com/yairEO/dragsort
var dragsort = new DragSort(tagify.DOM.scope, {
- selector:'.'+tagify.settings.classNames.tag,
+ selector: tagify.settings.tagSelector,
callbacks: {
dragEnd: onDragEnd
}
diff --git a/src/parts/defaults.js b/src/parts/defaults.js
index b5554757..04583360 100644
--- a/src/parts/defaults.js
+++ b/src/parts/defaults.js
@@ -62,6 +62,13 @@ export default {
empty : 'tagify--empty',
},
+ inputSelector: "[data-tagify-control='input']",
+ tagSelector: "[data-tagify-control='tag']",
+ tagTextSelector: "[data-tagify-control='tagText']",
+ tagRemoveBtn: "[data-tagify-control='tagRemoveBtn']",
+ dropdownWrapperSelector: "[data-tagify-control='dropdownWrapper']",
+ dropdownItemSelector: "[data-tagify-control='dropdownItem']",
+
dropdown: {
classname : '',
enabled : 2, // minimum input characters to be typed for the suggestions dropdown to show
@@ -82,4 +89,4 @@ export default {
beforePaste: () => Promise.resolve(),
suggestionClick: () => Promise.resolve()
}
-}
\ No newline at end of file
+}
diff --git a/src/parts/dropdown.js b/src/parts/dropdown.js
index 503da7ed..d8186296 100644
--- a/src/parts/dropdown.js
+++ b/src/parts/dropdown.js
@@ -15,7 +15,7 @@ export function initDropdown(){
export default {
init(){
this.DOM.dropdown = this.parseTemplate('dropdown', [this.settings])
- this.DOM.dropdown.content = this.DOM.dropdown.querySelector(this.settings.classNames.dropdownWrapperSelector)
+ this.DOM.dropdown.content = this.DOM.dropdown.querySelector(this.settings.dropdownWrapperSelector)
},
/**
@@ -391,7 +391,7 @@ export default {
},
onMouseOver(e){
- var ddItem = e.target.closest(this.settings.classNames.dropdownItemSelector)
+ var ddItem = e.target.closest(this.settings.dropdownItemSelector)
// event delegation check
ddItem && this.dropdown.highlightOption(ddItem)
},
@@ -404,7 +404,7 @@ export default {
onClick(e){
if( e.button != 0 || e.target == this.DOM.dropdown || e.target == this.DOM.dropdown.content ) return; // allow only mouse left-clicks
- var selectedElm = e.target.closest(this.settings.classNames.dropdownItemSelector),
+ var selectedElm = e.target.closest(this.settings.dropdownItemSelector),
selectedElmData = this.dropdown.getSuggestionDataByNode(selectedElm)
// temporary set the "actions" state to indicate to the main "blur" event it shouldn't run
diff --git a/src/parts/events.js b/src/parts/events.js
index 9877062d..5a9952a6 100644
--- a/src/parts/events.js
+++ b/src/parts/events.js
@@ -116,7 +116,7 @@ export default {
eventData = {relatedTarget:e.relatedTarget},
isTargetSelectOption = this.state.actions.selectOption && (ddEnabled || !_s.dropdown.closeOnSelect),
isTargetAddNewBtn = this.state.actions.addNew && ddEnabled,
- isRelatedTargetX = e.relatedTarget && e.relatedTarget.classList.contains(_s.classNames.tag) && this.DOM.scope.contains(e.relatedTarget),
+ isRelatedTargetX = e.relatedTarget && e.relatedTarget.dataset.tagifyControl === 'tag' && this.DOM.scope.contains(e.relatedTarget),
shouldAddTags;
if( type == 'blur' ){
@@ -188,7 +188,7 @@ export default {
onWindowKeyDown(e){
var focusedElm = document.activeElement,
- isTag = focusedElm.classList.contains(this.settings.classNames.tag),
+ isTag = focusedElm.dataset.tagifyControl === 'tag',
isBelong = isTag && this.DOM.scope.contains(document.activeElement),
nextTag;
@@ -590,7 +590,7 @@ export default {
onClickScope(e){
var _s = this.settings,
- tagElm = e.target.closest('.' + _s.classNames.tag),
+ tagElm = e.target.closest(_s.tagSelector),
timeDiffFocus = +new Date() - this.state.hasFocus;
if( e.target == this.DOM.scope ){
@@ -599,7 +599,7 @@ export default {
return
}
- else if( e.target.classList.contains(_s.classNames.tagX) ){
+ else if( e.target.dataset.tagifyControl === 'tagRemoveBtn'){
this.removeTags( e.target.parentNode )
return
}
@@ -669,7 +669,7 @@ export default {
},
onEditTagInput( editableElm, e ){
- var tagElm = editableElm.closest('.' + this.settings.classNames.tag),
+ var tagElm = editableElm.closest(this.settings.tagSelector),
tagElmIdx = this.getNodeIndex(tagElm),
tagData = this.tagData(tagElm),
value = this.input.normalize.call(this, editableElm),
@@ -721,7 +721,7 @@ export default {
if( !this.DOM.scope.contains(editableElm) ) return;
var _s = this.settings,
- tagElm = editableElm.closest('.' + _s.classNames.tag),
+ tagElm = editableElm.closest(_s.tagSelector),
textValue = this.input.normalize.call(this, editableElm),
originalData = this.tagData(tagElm).__originalData, // pre-edit data
hasChanged = tagElm.innerHTML != tagElm.__tagifyTagData.__originalHTML,
@@ -802,14 +802,14 @@ export default {
},
onDoubleClickScope(e){
- var tagElm = e.target.closest('.' + this.settings.classNames.tag),
+ var tagElm = e.target.closest(this.settings.tagSelector),
_s = this.settings,
isEditingTag,
isReadyOnlyTag;
if( !tagElm ) return
- isEditingTag = tagElm.classList.contains(this.settings.classNames.tagEditing)
+ isEditingTag = tagElm.dataset.tagifyTagStatus === 'editing'
isReadyOnlyTag = tagElm.hasAttribute('readonly')
if( _s.mode != 'select' && !_s.readonly && !isEditingTag && !isReadyOnlyTag && this.settings.editTags )
@@ -819,4 +819,4 @@ export default {
this.trigger('dblclick', { tag:tagElm, index:this.getNodeIndex(tagElm), data:this.tagData(tagElm) })
}
}
-}
\ No newline at end of file
+}
diff --git a/src/parts/templates.js b/src/parts/templates.js
index a7c6ec10..3c112177 100644
--- a/src/parts/templates.js
+++ b/src/parts/templates.js
@@ -12,6 +12,7 @@ export default {
tabIndex="-1">
@@ -25,10 +26,11 @@ export default {
spellcheck='false'
tabIndex="${_s.a11y.focusableTags ? 0 : -1}"
class="${_s.classNames.tag} ${tagData.class || ""}"
+ data-tagify-control='tag'
${this.getAttributes(tagData)}>
- ${tagData[_s.tagTextProp] || tagData.value}
+ ${tagData[_s.tagTextProp] || tagData.value}
`
},
@@ -39,16 +41,17 @@ export default {
className = `${settings.classNames.dropdown}`;
return `
`
},
dropdownItem( item, tagify ){
return `
${item.value}
`
},
dropdownItemNoMatch: null
-}
\ No newline at end of file
+}
diff --git a/src/tagify.js b/src/tagify.js
index 0f64ab54..c84ffd73 100644
--- a/src/tagify.js
+++ b/src/tagify.js
@@ -95,11 +95,6 @@ Tagify.prototype = {
_s.placeholder = input.getAttribute('placeholder') || _s.placeholder || ""
_s.required = input.hasAttribute('required')
- for( let name in _s.classNames )
- Object.defineProperty(_s.classNames, name + "Selector" , {
- get(){ return "."+this[name].split(" ")[0] }
- })
-
if( this.isIE )
_s.autoComplete = false; // IE goes crazy if this isn't false
@@ -262,7 +257,7 @@ Tagify.prototype = {
else {
DOM.originalInput = input
DOM.scope = this.parseTemplate('wrapper', [input, this.settings])
- DOM.input = DOM.scope.querySelector(this.settings.classNames.inputSelector)
+ DOM.input = DOM.scope.querySelector(this.settings.inputSelector)
input.parentNode.insertBefore(DOM.scope, input)
}
},
@@ -416,7 +411,7 @@ Tagify.prototype = {
var _s = this.settings;
function getEditableElm(){
- return tagElm.querySelector(_s.classNames.tagTextSelector)
+ return tagElm.querySelector(_s.tagTextSelector)
}
var editableElm = getEditableElm(),
@@ -430,7 +425,7 @@ Tagify.prototype = {
}
if( !editableElm ){
- console.warn('Cannot find element in Tag template: .', _s.classNames.tagTextSelector);
+ console.warn('Cannot find element in Tag template: .', _s.tagTextSelector);
return;
}
@@ -439,6 +434,7 @@ Tagify.prototype = {
editableElm.setAttribute('contenteditable', true)
tagElm.classList.add( _s.classNames.tagEditing )
+ tagElm.dataset.tagifyTagStatus = 'editing'
// cache the original data, on the DOM node, before any modification ocurs, for possible revert
this.tagData(tagElm, {
@@ -490,6 +486,8 @@ Tagify.prototype = {
//this.validateTag(tagData);
tagElm.classList.toggle(this.settings.classNames.tagNotAllowed, !isValid)
+ if(!isValid)
+ tagElm.dataset.tagifyTagStatus = 'notAllowed'
return tagData.__isValid
},
@@ -558,7 +556,7 @@ Tagify.prototype = {
this.value.length = 0;
[].forEach.call(this.getTagElms(), node => {
- if( node.classList.contains(this.settings.classNames.tagNotAllowed.split(' ')[0]) ) return
+ if( node.dataset.tagifyTagStatus === 'notAllowed' ) return
this.value.push( this.tagData(node) )
})
@@ -740,15 +738,18 @@ Tagify.prototype = {
},
getTagElms( ...classess ){
- var classname = '.' + [...this.settings.classNames.tag.split(' '), ...classess].join('.')
- return [].slice.call(this.DOM.scope.querySelectorAll(classname)) // convert nodeList to Array - https://stackoverflow.com/a/3199627/104380
+ var selector = ''
+ if (classess.length > 0)
+ selector = '.' + classess.join('.')
+ selector += this.settings.tagSelector
+ return [].slice.call(this.DOM.scope.querySelectorAll(selector)) // convert nodeList to Array - https://stackoverflow.com/a/3199627/104380
},
/**
- * gets the last non-readonly, not-in-the-proccess-of-removal tag
+ * gets the last non-readonly, not-in-the-process-of-removal tag
*/
getLastTag(){
- var lastTag = this.DOM.scope.querySelectorAll(`${this.settings.classNames.tagSelector}:not(.${this.settings.classNames.tagHide}):not([readonly])`);
+ var lastTag = this.DOM.scope.querySelectorAll(`${this.settings.tagSelector}:not([data-tagify-tag-status='hide']):not([readonly])`);
return lastTag[lastTag.length - 1];
},
@@ -1432,7 +1433,7 @@ Tagify.prototype = {
// if only a single tag is to be removed
if( tagsToRemove.length == 1 ){
- if( tagsToRemove[0].node.classList.contains(this.settings.classNames.tagNotAllowed) )
+ if( tagsToRemove[0].node.dataset.tagifyTagStatus === 'notAllowed' )
silent = true
}
@@ -1465,6 +1466,7 @@ Tagify.prototype = {
tag.node.style.width = parseFloat(window.getComputedStyle(tag.node).width) + 'px'
document.body.clientTop // force repaint for the width to take affect before the "hide" class below
tag.node.classList.add(this.settings.classNames.tagHide)
+ tag.node.dataset.tagifyTagStatus = 'hide'
// manual timeout (hack, since transitionend cannot be used because of hover)
setTimeout(removeNode.bind(this), tranDuration, tag)
@@ -1584,7 +1586,7 @@ Tagify.prototype = {
if( node.nodeType == 1 ){
const tagData = that.tagData(node);
- if( node.classList.contains(that.settings.classNames.tag) && tagData ){
+ if( node.dataset.tagifyControl === 'tag' && tagData ){
if( tagData.__removed )
return;
else