Skip to content

Commit

Permalink
fixes #474
Browse files Browse the repository at this point in the history
  • Loading branch information
yairEO committed May 3, 2020
1 parent a79d28f commit 11b853b
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 166 deletions.
141 changes: 69 additions & 72 deletions dist/tagify.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }

// console.json = console.json || function(argument){
// for(var arg=0; arg < arguments.length; ++arg)
// console.log( JSON.stringify(arguments[arg], null, 4) )
// }
var isFirefox = typeof InstallTrigger !== 'undefined'; // const isEdge = /Edge/.test(navigator.userAgent)

var sameStr = function sameStr(s1, s2) {
Expand Down Expand Up @@ -971,7 +975,10 @@ Tagify.prototype = {
};
},
onEditTagBlur: function onEditTagBlur(editableElm) {
if (!this.state.hasFocus) this.toggleFocusClass();
this.state.editing = false;
if (!this.state.hasFocus) this.toggleFocusClass(); // one scenario is when selecting a suggestion from the dropdown, when editing, and by selecting it
// the "onEditTagDone" is called directly, already replacing the tag, so the argument "editableElm" node isn't in the DOM

if (!this.DOM.scope.contains(editableElm)) return;
var tagElm = editableElm.closest('.tagify__tag'),
currentValue = this.input.normalize.call(this, editableElm),
Expand Down Expand Up @@ -1073,7 +1080,6 @@ Tagify.prototype = {
that = this,
isValid = true,
delayed_onEditTagBlur = function delayed_onEditTagBlur() {
that.state.editing = false;
setTimeout(_CB.onEditTagBlur.bind(that), 0, editableElm);
};

Expand Down Expand Up @@ -1138,13 +1144,14 @@ Tagify.prototype = {
}

this.trigger("edit:updated", eventData);
this.dropdown.hide.call(this);
this.dropdown.hide.call(this); // need to re-validate all invalid tags, which might not be invalid anymore
// (if one of them was a duplicate of a tag which was edited and not they aren't a duplicate of the edited one)

if (tagData.__isValid === true) this.getTagElms('tagify--notAllowed').forEach(function (notAllowedTag) {
var isValid = _this7.validateTag(notAllowedTag.__tagifyTagData);

if (isValid === true) {
notAllowedTag.__tagifyTagData.__isValid = isValid;
delete _this7.state.editing.locked; // unfortunatly this must be cleaned so "replaceTag" could re-run

_this7.replaceTag(notAllowedTag);
}
Expand All @@ -1157,21 +1164,10 @@ Tagify.prototype = {
* @param {Object} tagData [data to create new tag from]
*/
replaceTag: function replaceTag(tagElm, tagData) {
var _this8 = this;

if (!tagData || !tagData.value) tagData = tagElm.__tagifyTagData; // if tag is invalid, make the according changes in the newly created element

if (tagData.__isValid && tagData.__isValid != true) extend(tagData, this.getInvaildTagParams(tagData, tagData.__isValid));
var newTag = this.createTagElem(tagData); // when editing a tag and selecting a dropdown suggested item, the state should be "locked"
// so "onEditTagBlur" won't run and change the tag also *after* it was just changed.

if (this.state.editing.locked) return;
this.state.editing = {
locked: true
};
setTimeout(function () {
return delete _this8.state.editing.locked;
}, 500); // update DOM
var newTag = this.createTagElem(tagData); // update DOM

tagElm.parentNode.replaceChild(newTag, tagElm);
this.updateValueByDOMTags();
Expand All @@ -1181,13 +1177,13 @@ Tagify.prototype = {
* update value by traversing all valid tags
*/
updateValueByDOMTags: function updateValueByDOMTags() {
var _this9 = this;
var _this8 = this;

this.value = [];
[].forEach.call(this.getTagElms(), function (node) {
if (node.classList.contains('tagify--notAllowed')) return;

_this9.value.push(node.__tagifyTagData);
_this8.value.push(node.__tagifyTagData);
});
this.update();
},
Expand Down Expand Up @@ -1512,7 +1508,7 @@ Tagify.prototype = {
* @param {String} s
*/
parseMixTags: function parseMixTags(s) {
var _this10 = this;
var _this9 = this;

var _this$settings2 = this.settings,
mixTagsInterpolator = _this$settings2.mixTagsInterpolator,
Expand All @@ -1529,17 +1525,17 @@ Tagify.prototype = {
try {
tagData = JSON.parse(preInterpolated);
} catch (err) {
tagData = _this10.normalizeTags(preInterpolated)[0]; //{value:preInterpolated}
tagData = _this9.normalizeTags(preInterpolated)[0]; //{value:preInterpolated}
}

if (s2.length > 1 && (!enforceWhitelist || _this10.isTagWhitelisted(tagData.value)) && !(!duplicates && _this10.isTagDuplicate(tagData.value))) {
transformTag.call(_this10, tagData);
tagElm = _this10.createTagElem(tagData);
if (s2.length > 1 && (!enforceWhitelist || _this9.isTagWhitelisted(tagData.value)) && !(!duplicates && _this9.isTagDuplicate(tagData.value))) {
transformTag.call(_this9, tagData);
tagElm = _this9.createTagElem(tagData);
tagsDataSet.push(tagData);
tagElm.classList.add('tagify--noAnim');
s2[0] = tagElm.outerHTML; //+ "&#8288;" // put a zero-space at the end so the caret won't jump back to the start (when the last input's child element is a tag)

_this10.value.push(tagData);
_this9.value.push(tagData);
} else if (s1) return i ? mixTagsInterpolator[0] + s1 : s1;

return s2.join('');
Expand Down Expand Up @@ -1581,7 +1577,7 @@ Tagify.prototype = {
},

/**
* For selecting a single option (not used for multiple tags)
* For selecting a single option (not used for multiple tags, but for "mode:select" only)
* @param {Object} tagElm Tag DOM node
* @param {Object} tagData Tag data
*/
Expand Down Expand Up @@ -1625,7 +1621,7 @@ Tagify.prototype = {
* @return {Array} Array of DOM elements (tags)
*/
addTags: function addTags(tagsItems, clearInput) {
var _this11 = this;
var _this10 = this;

var skipInvalid = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.settings.skipInvalid;
var tagElems = [],
Expand All @@ -1639,14 +1635,7 @@ Tagify.prototype = {
} // converts Array/String/Object to an Array of Objects


tagsItems = this.normalizeTags(tagsItems); // if in edit-mode, do not continue but instead replace the tag's text.
// the scenario is that "addTags" was called from a dropdown suggested option selected while editing

if (this.state.editing.scope) {
tagsItems[0].__isValid = true; // must be "true" at this point because it must have been coming from the dropdown sugegstions list

return this.onEditTagDone(this.state.editing.scope, tagsItems[0]);
}
tagsItems = this.normalizeTags(tagsItems);

if (_s.mode == 'mix') {
_s.transformTag.call(this, tagsItems[0]); // TODO: should check if the tag is valid
Expand Down Expand Up @@ -1684,60 +1673,60 @@ Tagify.prototype = {

tagData = Object.assign({}, tagData);

_s.transformTag.call(_this11, tagData); ///////////////// ( validation )//////////////////////
_s.transformTag.call(_this10, tagData); ///////////////// ( validation )//////////////////////


tagData.__isValid = _this11.hasMaxTags() || _this11.validateTag(tagData);
tagData.__isValid = _this10.hasMaxTags() || _this10.validateTag(tagData);

if (tagData.__isValid !== true) {
if (skipInvalid) return;
extend(tagElmParams, _this11.getInvaildTagParams(tagData, tagData.__isValid)); // mark, for a brief moment, the tag THIS CURRENT tag is a duplcate of
extend(tagElmParams, _this10.getInvaildTagParams(tagData, tagData.__isValid)); // mark, for a brief moment, the tag THIS CURRENT tag is a duplcate of

if (tagData.__isValid == _this11.TEXTS.duplicate) _this11.markTagByValue(tagData.value);
if (tagData.__isValid == _this10.TEXTS.duplicate) _this10.markTagByValue(tagData.value);
} /////////////////////////////////////////////////////
// add accessibility attributes


tagElmParams.role = "tag";
if (tagData.readonly) tagElmParams["aria-readonly"] = true; // Create tag HTML element

tagElm = _this11.createTagElem(extend({}, tagData, tagElmParams));
tagElm = _this10.createTagElem(extend({}, tagData, tagElmParams));
tagElm.__tagifyTagData = tagData;
tagElems.push(tagElm); // mode-select overrides

if (_s.mode == 'select') {
return _this11.selectTag(tagElm, tagData);
return _this10.selectTag(tagElm, tagData);
} // add the tag to the component's DOM


_this11.appendTag(tagElm);
_this10.appendTag(tagElm);

if (tagData.__isValid && tagData.__isValid === true) {
// update state
_this11.value.push(tagData);
_this10.value.push(tagData);

_this11.update();
_this10.update();

_this11.trigger('add', {
_this10.trigger('add', {
tag: tagElm,
index: _this11.value.length - 1,
index: _this10.value.length - 1,
data: tagData
});
} else {
_this11.trigger("invalid", {
_this10.trigger("invalid", {
data: tagData,
index: _this11.value.length,
index: _this10.value.length,
tag: tagElm,
message: tagData.__isValid
});

if (!_s.keepInvalidTags) // remove invalid tags (if "keepInvalidTags" is set to "false")
setTimeout(function () {
return _this11.removeTags(tagElm, true);
return _this10.removeTags(tagElm, true);
}, 1000);
}

_this11.dropdown.position.call(_this11); // reposition the dropdown because the just-added tag might cause a new-line
_this10.dropdown.position.call(_this10); // reposition the dropdown because the just-added tag might cause a new-line

});

Expand Down Expand Up @@ -1774,20 +1763,20 @@ Tagify.prototype = {
return tagElm;
},
reCheckInvalidTags: function reCheckInvalidTags() {
var _this12 = this;
var _this11 = this;

// find all invalid tags and re-check them
var tagElms = this.DOM.scope.querySelectorAll('.tagify__tag.tagify--notAllowed');
[].forEach.call(tagElms, function (node) {
var tagData = node.__tagifyTagData,
wasNodeDuplicate = node.getAttribute('title') == _this12.TEXTS.duplicate,
isNodeValid = _this12.validateTag(tagData) === true; // if this tag node was marked as a dulpicate, unmark it (it might have been marked as "notAllowed" for other reasons)
wasNodeDuplicate = node.getAttribute('title') == _this11.TEXTS.duplicate,
isNodeValid = _this11.validateTag(tagData) === true; // if this tag node was marked as a dulpicate, unmark it (it might have been marked as "notAllowed" for other reasons)


if (wasNodeDuplicate && isNodeValid) {
tagData.__isValid = true;

_this12.replaceTag(node, tagData);
_this11.replaceTag(node, tagData);
}
});
},
Expand All @@ -1800,15 +1789,15 @@ Tagify.prototype = {
* TODO: Allow multiple tags to be removed at-once
*/
removeTags: function removeTags(tagElms, silent, tranDuration) {
var _this13 = this;
var _this12 = this;

tagElms = tagElms && tagElms instanceof HTMLElement ? [tagElms] : tagElms instanceof Array ? tagElms : tagElms ? [tagElms] : [this.getLastTag()]; // normalize tagElms array values:
// 1. removing invalid items
// 2, if an item is String try to get the matching Tag HTML node

tagElms = tagElms.reduce(function (elms, tagElm) {
if (tagElm) {
if (typeof tagElm == 'string') tagElm = _this13.getTagElmByValue(tagElm);
if (typeof tagElm == 'string') tagElm = _this12.getTagElmByValue(tagElm);
tagElm && elms.push(tagElm);
}

Expand Down Expand Up @@ -1870,9 +1859,9 @@ Tagify.prototype = {

if (!silent) {
tagElms.forEach(function (tagElm) {
var tagIdx = _this13.getTagIdx(tagElm.__tagifyTagData);
var tagIdx = _this12.getTagIdx(tagElm.__tagifyTagData);

if (tagIdx > -1) _this13.value.splice(tagIdx, 1);
if (tagIdx > -1) _this12.value.splice(tagIdx, 1);
}); // that.removeValueById(tagData.__uid)

this.update(); // update the original input with the current value
Expand Down Expand Up @@ -1971,7 +1960,7 @@ Tagify.prototype = {
this.DOM.dropdown.content = this.DOM.dropdown.querySelector('.tagify__dropdown__wrapper');
},
show: function show(value) {
var _this14 = this;
var _this13 = this;

var HTMLContent,
_s = this.settings,
Expand Down Expand Up @@ -2049,7 +2038,7 @@ Tagify.prototype = {
this.dropdown.position.call(this, ddHeight);
document.body.appendChild(this.DOM.dropdown);
setTimeout(function () {
return _this14.DOM.dropdown.classList.remove('tagify__dropdown--initial');
return _this13.DOM.dropdown.classList.remove('tagify__dropdown--initial');
});
} // timeout is needed for when pressing arrow down to show the dropdown,
// so the key event won't get registered in the dropdown events listeners
Expand Down Expand Up @@ -2312,23 +2301,31 @@ Tagify.prototype = {
* @param {Object} elm DOM node to select
*/
selectOption: function selectOption(elm) {
var _this15 = this;
var _this14 = this;

if (!elm) return; // temporary set the "actions" state to indicate to the main "blur" event it shouldn't run
if (!elm) return; // if in edit-mode, do not continue but instead replace the tag's text.
// the scenario is that "addTags" was called from a dropdown suggested option selected while editing
// temporary set the "actions" state to indicate to the main "blur" event it shouldn't run

this.state.actions.selectOption = true;
setTimeout(function () {
return _this15.state.actions.selectOption = false;
return _this14.state.actions.selectOption = false;
}, 50);
var hideDropdown = this.settings.dropdown.closeOnSelect,
value = this.suggestedListItems[this.getNodeIndex(elm)] || this.input.value;
value = this.suggestedListItems[this.getNodeIndex(elm)].value || this.input.value;
this.trigger("dropdown:select", value);
this.addTags([value], true); // Tagify instances should re-focus to the input element once an option was selected, to allow continuous typing
if (this.state.editing) this.onEditTagDone(this.state.editing.scope, _objectSpread({}, this.state.editing.scope.__tagifyTagData, {
value: value,
__isValid: true
})); // Tagify instances should re-focus to the input element once an option was selected, to allow continuous typing
else {
this.addTags([value], true);
} // todo: consider not doing this on mix-mode

if (!this.state.editing) setTimeout(function () {
_this15.DOM.input.focus();
setTimeout(function () {
_this14.DOM.input.focus();

_this15.toggleFocusClass(true);
_this14.toggleFocusClass(true);
});

if (hideDropdown) {
Expand All @@ -2342,7 +2339,7 @@ Tagify.prototype = {
* @return {Array} list of filtered whitelist items according to the settings provided and current value
*/
filterListItems: function filterListItems(value) {
var _this16 = this;
var _this15 = this;

var _s = this.settings,
list = [],
Expand All @@ -2358,7 +2355,7 @@ Tagify.prototype = {

if (!value) {
return (_s.duplicates ? whitelist : whitelist.filter(function (item) {
return !_this16.isTagDuplicate(isObject(item) ? item.value : item);
return !_this15.isTagDuplicate(isObject(item) ? item.value : item);
}) // don't include tags which have already been added.
).slice(0, suggestionsCount); // respect "maxItems" dropdown setting
}
Expand Down Expand Up @@ -2388,18 +2385,18 @@ Tagify.prototype = {
* @return {String}
*/
createListHTML: function createListHTML(optionsArr) {
var _this17 = this;
var _this16 = this;

return optionsArr.map(function (item) {
if (typeof item == 'string') item = {
value: item
};
var mapValueTo = _this17.settings.dropdown.mapValueTo,
var mapValueTo = _this16.settings.dropdown.mapValueTo,
value = mapValueTo ? typeof mapValueTo == 'function' ? mapValueTo(item) : item[mapValueTo] : item.value,
data = extend({}, item, {
value: escapeHTML(value || "")
});
return _this17.settings.templates.dropdownItem.call(_this17, data);
return _this16.settings.templates.dropdownItem.call(_this16, data);
}).join("");
}
}
Expand Down
Loading

0 comments on commit 11b853b

Please sign in to comment.