From 5763766248f42ea6a6f9660a22273d2c34aa9657 Mon Sep 17 00:00:00 2001 From: Prateeksha Singh Date: Fri, 15 Dec 2017 14:18:53 +0530 Subject: [PATCH] [tags] Remove taggle (#4631) --- frappe/public/build.json | 6 +- frappe/public/css/tags.css | 19 ++ frappe/public/js/frappe/ui/tag_editor.js | 129 +++++++++++ frappe/public/js/frappe/ui/tags.js | 240 +++++++++++---------- frappe/public/js/lib/taggle/taggle.min.css | 103 --------- frappe/public/js/lib/taggle/taggle.min.js | 8 - frappe/public/less/tags.less | 22 ++ 7 files changed, 295 insertions(+), 232 deletions(-) create mode 100644 frappe/public/css/tags.css create mode 100644 frappe/public/js/frappe/ui/tag_editor.js delete mode 100644 frappe/public/js/lib/taggle/taggle.min.css delete mode 100644 frappe/public/js/lib/taggle/taggle.min.js create mode 100644 frappe/public/less/tags.less diff --git a/frappe/public/build.json b/frappe/public/build.json index 6d6a4283e7..33b6c6d659 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -122,7 +122,8 @@ "public/css/form.css", "public/css/mobile.css", "public/css/kanban.css", - "public/css/controls.css" + "public/css/controls.css", + "public/css/tags.css" ], "css/frappe-rtl.css": [ "public/css/bootstrap-rtl.css", @@ -132,7 +133,6 @@ "js/libs.min.js": [ "public/js/lib/awesomplete/awesomplete.min.js", "public/js/lib/Sortable.min.js", - "public/js/lib/taggle/taggle.min.js", "public/js/lib/jquery/jquery.hotkeys.js", "public/js/lib/summernote/summernote.js", "public/js/lib/bootstrap.min.js", @@ -292,7 +292,6 @@ "public/js/frappe/form/quick_entry.js" ], "css/list.min.css": [ - "public/js/lib/taggle/taggle.min.css", "public/css/list.css", "public/css/calendar.css", "public/css/role_editor.css", @@ -307,6 +306,7 @@ "public/js/frappe/ui/filters/filters.js", "public/js/frappe/ui/filters/edit_filter.html", "public/js/frappe/ui/tags.js", + "public/js/frappe/ui/tag_editor.js", "public/js/frappe/ui/like.js", "public/js/frappe/ui/liked_by.html", "public/html/print_template.html", diff --git a/frappe/public/css/tags.css b/frappe/public/css/tags.css new file mode 100644 index 0000000000..fb77c61e81 --- /dev/null +++ b/frappe/public/css/tags.css @@ -0,0 +1,19 @@ +.tags-list { + float: left; + width: 100%; + padding-left: 3px; +} +.tags-input { + width: 100px; + font-size: 11px; + border: none; + outline: none; +} +.tags-list-item { + display: inline-block; + margin: 0px 3px; +} +.tags-placeholder { + display: inline-block; + font-size: 11px; +} diff --git a/frappe/public/js/frappe/ui/tag_editor.js b/frappe/public/js/frappe/ui/tag_editor.js new file mode 100644 index 0000000000..3efab96aa4 --- /dev/null +++ b/frappe/public/js/frappe/ui/tag_editor.js @@ -0,0 +1,129 @@ +frappe.ui.TagEditor = Class.extend({ + init: function(opts) { + /* docs: + Arguments + + - parent + - user_tags + - doctype + - docname + */ + $.extend(this, opts); + + this.setup_tags(); + + if (!this.user_tags) { + this.user_tags = ""; + } + this.initialized = true; + this.refresh(this.user_tags); + }, + setup_tags: function() { + var me = this; + + // hidden form, does not have parent + if (!this.parent) { + return; + } + + this.wrapper = $('
').appendTo(this.parent); + if(!this.wrapper.length) return; + + this.tags = new frappe.ui.Tags({ + parent: this.wrapper, + placeholder: "Add a tag ...", + onTagAdd: (tag) => { + if(me.initialized && !me.refreshing) { + tag = toTitle(tag); + return frappe.call({ + method: 'frappe.desk.tags.add_tag', + args: me.get_args(tag), + callback: function(r) { + var user_tags = me.user_tags ? me.user_tags.split(",") : []; + user_tags.push(tag) + me.user_tags = user_tags.join(","); + me.on_change && me.on_change(me.user_tags); + } + }); + } + }, + onTagRemove: (tag) => { + if(!me.refreshing) { + return frappe.call({ + method: 'frappe.desk.tags.remove_tag', + args: me.get_args(tag), + callback: function(r) { + var user_tags = me.user_tags.split(","); + user_tags.splice(user_tags.indexOf(tag), 1); + me.user_tags = user_tags.join(","); + me.on_change && me.on_change(me.user_tags); + } + }); + } + } + }); + this.setup_awesomplete(); + this.setup_complete = true; + }, + setup_awesomplete: function() { + var me = this; + var $input = this.wrapper.find("input.tags-input"); + var input = $input.get(0); + this.awesomplete = new Awesomplete(input, { + minChars: 0, + maxItems: 99, + list: [] + }); + $input.on("awesomplete-open", function(e){ + $input.attr('state', 'open'); + }); + $input.on("awesomplete-close", function(e){ + $input.attr('state', 'closed'); + }); + $input.on("input", function(e) { + var value = e.target.value; + frappe.call({ + method:"frappe.desk.tags.get_tags", + args:{ + doctype: me.frm.doctype, + txt: value.toLowerCase(), + cat_tags: me.list_sidebar ? + JSON.stringify(me.list_sidebar.get_cat_tags()) : '[]' + }, + callback: function(r) { + me.awesomplete.list = r.message; + } + }); + }); + $input.on("focus", function(e) { + if($input.attr('state') != 'open') { + $input.trigger("input"); + } + }); + }, + get_args: function(tag) { + return { + tag: tag, + dt: this.frm.doctype, + dn: this.frm.docname, + } + }, + refresh: function(user_tags) { + var me = this; + if (!this.initialized || !this.setup_complete || this.refreshing) return; + + me.refreshing = true; + try { + me.tags.clearTags(); + if(user_tags) { + me.tags.addTags(user_tags.split(',')); + } + } catch(e) { + me.refreshing = false; + // wtf bug + setTimeout( function() { me.refresh(); }, 100); + } + me.refreshing = false; + + } +}) diff --git a/frappe/public/js/frappe/ui/tags.js b/frappe/public/js/frappe/ui/tags.js index f99da28ff7..e520d56978 100644 --- a/frappe/public/js/frappe/ui/tags.js +++ b/frappe/public/js/frappe/ui/tags.js @@ -1,131 +1,135 @@ // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // MIT License. See license.txt -frappe.ui.TagEditor = Class.extend({ - init: function(opts) { - /* docs: - Arguments - - - parent - - user_tags - - doctype - - docname - */ - $.extend(this, opts); - - this.setup_taggle(); - - if (!this.user_tags) { - this.user_tags = ""; - } - this.initialized = true; - this.refresh(this.user_tags); - }, - setup_taggle: function() { - var me = this; - - // hidden form, does not have parent - if (!this.parent) { - return; - } +frappe.ui.Tags = class { + constructor({ + parent, placeholder, tagsList, + onTagAdd, + onTagRemove, + onTagClick, + onChange + }) { + this.tagsList = tagsList || []; + this.onTagAdd = onTagAdd; + this.onTagRemove = onTagRemove; + this.onTagClick = onTagClick; + this.onChange = onChange; + + this.setup(parent, placeholder); + } + + setup(parent, placeholder) { + this.$wrapper = $(`
`).appendTo(parent); + this.$ul = $(``).appendTo(this.$wrapper); + this.$input = $(``); + + this.$inputWrapper = this.getListElement(this.$input); + this.$placeholder = this.getListElement($(`${placeholder}`)); + this.$inputWrapper.appendTo(this.$ul); + this.$placeholder.appendTo(this.$ul); - this.wrapper = $('
').appendTo(this.parent); - if(!this.wrapper.length) return; - var id = frappe.dom.set_unique_id(this.wrapper); - this.taggle = new Taggle(id, { - placeholder: __('Add a tag') + "...", - onTagAdd: function(e, tag) { - if(me.initialized && !me.refreshing) { - tag = toTitle(tag); - return frappe.call({ - method: 'frappe.desk.tags.add_tag', - args: me.get_args(tag), - callback: function(r) { - var user_tags = me.user_tags ? me.user_tags.split(",") : []; - user_tags.push(tag) - me.user_tags = user_tags.join(","); - me.on_change && me.on_change(me.user_tags); - } - }); - } - }, - onTagRemove: function(e, tag) { - if(!me.refreshing) { - return frappe.call({ - method: 'frappe.desk.tags.remove_tag', - args: me.get_args(tag), - callback: function(r) { - var user_tags = me.user_tags.split(","); - user_tags.splice(user_tags.indexOf(tag), 1); - me.user_tags = user_tags.join(","); - me.on_change && me.on_change(me.user_tags); - } - }); - } + this.deactivate(); + this.bind(); + this.boot(); + } + + bind() { + this.$input.keypress((e) => { + if(e.which == 13 || e.keyCode == 13) { + this.addTag(this.$input.val()); + this.$input.val(''); } }); - this.setup_awesomplete(); - this.setup_complete = true; - }, - setup_awesomplete: function() { - var me = this; - var $input = this.wrapper.find("input.taggle_input"); - var input = $input.get(0); - this.awesomplete = new Awesomplete(input, { - minChars: 0, - maxItems: 99, - list: [] + + this.$input.on('blur', () => { + this.deactivate(); }); - $input.on("awesomplete-open", function(e){ - $input.attr('state', 'open'); + + this.$placeholder.on('click', () => { + this.activate(); }); - $input.on("awesomplete-close", function(e){ - $input.attr('state', 'closed'); + } + + boot() { + this.addTags(this.tagsList); + } + + activate() { + this.$placeholder.hide(); + this.$inputWrapper.show(); + this.$input.focus(); + } + + deactivate() { + this.$inputWrapper.hide(); + this.$placeholder.show(); + } + + refresh() { + this.deactivate(); + this.activate(); + } + + addTag(label) { + if(label && !this.tagsList.includes(label)) { + let $tag = this.getTag(label); + this.getListElement($tag).insertBefore(this.$inputWrapper); + this.tagsList.push(label); + this.onTagAdd && this.onTagAdd(label); + + this.refresh(); + } + } + + removeTag(label) { + if(this.tagsList.includes(label)) { + let $tag = this.$ul.find(`.frappe-tag[data-tag-label="${label}"]`); + $tag.remove(); + this.tagsList = this.tagsList.filter(d => d !== label); + this.onTagRemove && this.onTagRemove(label); + } + } + + addTags(labels) { + labels.map(this.addTag.bind(this)); + } + + clearTags() { + this.$ul.find('.frappe-tag').remove(); + this.tagsList = []; + } + + getListElement($element, className) { + let $li = $(`
  • `); + $element.appendTo($li); + return $li; + } + + getTag(label) { + let $tag = $(`
    + +
    `); + + let $removeTag = $tag.find(".remove-tag"); + + $removeTag.on("click", () => { + this.removeTag($removeTag.attr('data-tag-label')); }); - $input.on("input", function(e) { - var value = e.target.value; - frappe.call({ - method:"frappe.desk.tags.get_tags", - args:{ - doctype: me.frm.doctype, - txt: value.toLowerCase(), - cat_tags: me.list_sidebar ? - JSON.stringify(me.list_sidebar.get_cat_tags()) : '[]' - }, - callback: function(r) { - me.awesomplete.list = r.message; - } + + if(this.onTagClick) { + let $toggle_tag = $tag.find(".toggle-tag"); + $toggle_tag.on("click", () => { + this.onTagClick($toggle_tag.attr('data-tag-label')); }); - }); - $input.on("focus", function(e) { - if($input.attr('state') != 'open') { - $input.trigger("input"); - } - }); - }, - get_args: function(tag) { - return { - tag: tag, - dt: this.frm.doctype, - dn: this.frm.docname, - } - }, - refresh: function(user_tags) { - var me = this; - if (!this.initialized || !this.setup_complete || this.refreshing) return; - - me.refreshing = true; - try { - me.taggle.removeAll(); - if(user_tags) { - me.taggle.add(user_tags.split(',')); - } - } catch(e) { - me.refreshing = false; - // wtf bug - setTimeout( function() { me.refresh(); }, 100); } - me.refreshing = false; + return $tag; } -}) +} diff --git a/frappe/public/js/lib/taggle/taggle.min.css b/frappe/public/js/lib/taggle/taggle.min.css deleted file mode 100644 index 310525ba71..0000000000 --- a/frappe/public/js/lib/taggle/taggle.min.css +++ /dev/null @@ -1,103 +0,0 @@ -.taggle_list { - float: left; - width: 100%; -} - -.taggle_input { - border: none; - outline: none; - font-size: 16px; - font-weight: 300; -} - -.taggle_list li { - float: left; - display: inline-block; - white-space: nowrap; - font-weight: 500; - margin-bottom: 5px; -} - -.taggle_list .taggle { - margin-right: 8px; - background: #E2E1DF; - padding: 5px 10px; - border-radius: 3px; - position: relative; - cursor: pointer; - transition: all .3s; - animation-duration: 1s; - animation-fill-mode: both; -} - -.taggle_list .taggle_hot { - background: #cac8c4; -} - -.taggle_list .taggle .close { - font-size: 1.1rem; - position: absolute; - top: 5px; - right: 3px; - text-decoration: none; - padding-left: 2px; - padding-top: 3px; - line-height: 0.5; - color: #ccc; - color: rgba(0, 0, 0, 0.2); - padding-bottom: 4px; - display: none; - border: 0; - background: none; - cursor: pointer; -} - -.taggle_list .taggle:hover { - padding: 5px; - padding-right: 15px; - background: #ccc; - transition: all .3s; -} - -.taggle_list .taggle:hover > .close { - display: block; -} - -.taggle_list .taggle .close:hover { - color: #333; -} - -.taggle_placeholder { - position: absolute; - color: #CCC; - top: 12px; - left: 8px; - transition: opacity, .25s; - user-select: none; -} - -.taggle_input { - padding: 8px; - padding-left: 0; - float: left; - margin-top: -5px; - background: none; - width: 100%; - max-width: 100%; -} - -.taggle_sizer { - padding: 0; - margin: 0; - position: absolute; - top: -500px; - z-index: -1; - visibility: hidden; -} - -.clearfix:before, .clearfix:after { - display: block; - content: ""; - line-height: 0; - clear: both; -} \ No newline at end of file diff --git a/frappe/public/js/lib/taggle/taggle.min.js b/frappe/public/js/lib/taggle/taggle.min.js deleted file mode 100644 index a70859315e..0000000000 --- a/frappe/public/js/lib/taggle/taggle.min.js +++ /dev/null @@ -1,8 +0,0 @@ -/*! -* @author Sean Coker -* @version 1.10.1 -* @url http://sean.is/poppin/tags -* @license MIT -* @description Taggle is a dependency-less tagging library -*/ -!function(){Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),window.getComputedStyle||(window.getComputedStyle=function(a){return a.currentStyle}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){"use strict";if(null==this)throw new TypeError;var b,c,d=Object(this),e=d.length>>>0;if(0===e)return-1;if(b=0,arguments.length>1&&(b=Number(arguments[1]),b!=b?b=0:0!=b&&b!=1/0&&b!=-(1/0)&&(b=(b>0||-1)*Math.floor(Math.abs(b)))),b>=e)return-1;for(c=b>=0?b:Math.max(e-Math.abs(b),0);e>c;c++)if(c in d&&d[c]===a)return c;return-1}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c,d;if(null==this)throw new TypeError(" this is null or not defined");var e=Object(this),f=e.length>>>0;if("function"!=typeof a)throw new TypeError(a+" is not a function");for(arguments.length>1&&(c=b),d=0;f>d;){var g;d in e&&(g=e[d],a.call(c,g,d,e)),d++}}),Array.prototype.map||(Array.prototype.map=function(a,b){var c,d,e;if(null==this)throw new TypeError(" this is null or not defined");var f=Object(this),g=f.length>>>0;if("function"!=typeof a)throw new TypeError(a+" is not a function");for(arguments.length>1&&(c=b),d=new Array(g),e=0;g>e;){var h,i;e in f&&(h=f[e],i=a.call(c,h,e,f),d[e]=i),e++}return d})}(),function(){"undefined"==typeof document||"classList"in document.documentElement||!function(a){"use strict";if("HTMLElement"in a||"Element"in a){var b="classList",c="prototype",d=(a.HTMLElement||a.Element)[c],e=Object,f=String[c].trim||function(){return this.replace(/^\s+|\s+$/g,"")},g=Array[c].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1},h=function(a,b){this.name=a,this.code=DOMException[a],this.message=b},i=function(a,b){if(""===b)throw new h("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(b))throw new h("INVALID_CHARACTER_ERR","String contains an invalid character");return g.call(a,b)},j=function(a){for(var b=f.call(a.className),c=b?b.split(/\s+/):[],d=0,e=c.length;e>d;d++)this.push(c[d]);this._updateClassName=function(){a.className=this.toString()}},k=j[c]=[],l=function(){return new j(this)};if(h[c]=Error[c],k.item=function(a){return this[a]||null},k.contains=function(a){return a+="",-1!==i(this,a)},k.add=function(){var a,b=arguments,c=0,d=b.length,e=!1;do a=b[c]+"",-1===i(this,a)&&(this.push(a),e=!0);while(++cb;b++){var d=arguments[b];for(var e in d)d.hasOwnProperty(e)&&(a[e]=d[e])}return a}function b(a){return Array.isArray?Array.isArray(a):"[object Array]"===Object.prototype.toString.call(a)}function c(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent?a.attachEvent("on"+b,c):a["on"+b]=c}function d(a){return a.replace(/^\s+|\s+$/g,"")}function e(a,b){window.attachEvent&&!window.addEventListener?a.innerText=b:a.textContent=b}var f=function(){},g=function(){return!0},h=8,i=188,j=9,k=13,l={additionalTagClasses:"",allowDuplicates:!1,saveOnBlur:!1,duplicateTagClass:"",containerFocusClass:"active",focusInputOnContainerClick:!0,hiddenInputName:"taggles[]",tags:[],delimeter:",",attachTagId:!1,allowedTags:[],disallowedTags:[],maxTags:null,tabIndex:1,placeholder:"Enter tags...",submitKeys:[i,j,k],preserveCase:!1,inputFormatter:f,tagFormatter:f,onBeforeTagAdd:f,onTagAdd:f,onBeforeTagRemove:g,onTagRemove:f},m=function(b,c){this.settings=a({},l,c),this.measurements={container:{rect:null,style:null,padding:null}},this.container=b,this.tag={values:[],elements:[]},this.list=document.createElement("ul"),this.inputLi=document.createElement("li"),this.input=document.createElement("input"),this.sizer=document.createElement("div"),this.pasting=!1,this.placeholder=null,this.settings.placeholder&&(this.placeholder=document.createElement("span")),"string"==typeof b&&(this.container=document.getElementById(b)),this._id=0,this._setMeasurements(),this._setupTextarea(),this._attachEvents()};return m.prototype._setMeasurements=function(){this.measurements.container.rect=this.container.getBoundingClientRect(),this.measurements.container.style=window.getComputedStyle(this.container);var a=this.measurements.container.style,b=parseInt(a["padding-left"]||a.paddingLeft,10),c=parseInt(a["padding-right"]||a.paddingRight,10),d=parseInt(a["border-left-width"]||a.borderLeftWidth,10),e=parseInt(a["border-right-width"]||a.borderRightWidth,10);this.measurements.container.padding=b+c+d+e},m.prototype._setupTextarea=function(){var a;if(this.list.className="taggle_list",this.input.type="text",this.input.style.paddingLeft=0,this.input.style.paddingRight=0,this.input.className="taggle_input",this.input.tabIndex=this.settings.tabIndex,this.sizer.className="taggle_sizer",this.settings.tags.length)for(var b=0,c=this.settings.tags.length;c>b;b++){var d=this._createTag(this.settings.tags[b]);this.list.appendChild(d)}this.placeholder&&(this.placeholder.style.opacity=0,this.placeholder.classList.add("taggle_placeholder"),this.container.appendChild(this.placeholder),e(this.placeholder,this.settings.placeholder),this.settings.tags.length||(this.placeholder.style.opacity=1));var f=this.settings.inputFormatter(this.input);f&&(this.input=f),this.inputLi.appendChild(this.input),this.list.appendChild(this.inputLi),this.container.appendChild(this.list),this.container.appendChild(this.sizer),a=window.getComputedStyle(this.input).fontSize,this.sizer.style.fontSize=a},m.prototype._attachEvents=function(){var a=this;this.settings.focusInputOnContainerClick&&c(this.container,"click",function(){a.input.focus()}),c(this.input,"focus",this._focusInput.bind(this)),c(this.input,"blur",this._blurEvent.bind(this)),c(this.input,"keydown",this._keydownEvents.bind(this)),c(this.input,"keyup",this._keyupEvents.bind(this))},m.prototype._fixInputWidth=function(){var a,b,c,d,e;this._setMeasurements(),this._setInputWidth(),b=this.input.getBoundingClientRect(),c=this.measurements.container.rect,a=~~c.width,a||(a=~~c.right-~~c.left),d=~~b.left-~~c.left,e=this.measurements.container.padding,this._setInputWidth(a-d-e)},m.prototype._canAdd=function(a,b){if(!b)return!1;var c=this.settings.maxTags;if(null!==c&&c<=this.getTagValues().length)return!1;if(this.settings.onBeforeTagAdd(a,b)===!1)return!1;if(!this.settings.allowDuplicates&&this._hasDupes(b))return!1;var d=this.settings.preserveCase,e=this.settings.allowedTags;if(e.length&&!this._tagIsInArray(b,e,d))return!1;var f=this.settings.disallowedTags;return!f.length||!this._tagIsInArray(b,f,d)},m.prototype._tagIsInArray=function(a,b,c){if(c)return-1!==b.indexOf(a);var d=[].slice.apply(b).map(function(a){return a.toLowerCase()});return-1!==d.indexOf(a)},m.prototype._add=function(a,b){var c=this,e=b||"";"string"!=typeof b&&(e=d(this.input.value)),e.split(this.settings.delimeter).map(function(a){return c._formatTag(a)}).forEach(function(b){if(c._canAdd(a,b)){var d=c._createTag(b),e=c.list.children,f=e[e.length-1];c.list.insertBefore(d,f),b=c.tag.values[c.tag.values.length-1],c.settings.onTagAdd(a,b),c.input.value="",c._fixInputWidth(),c._focusInput()}})},m.prototype._checkLastTag=function(a){a=a||window.event;var b=this.container.querySelectorAll(".taggle"),c=b[b.length-1],d="taggle_hot",e=this.input.classList.contains("taggle_back");""!==this.input.value||a.keyCode!==h||e?c.classList.contains(d)&&c.classList.remove(d):c.classList.contains(d)?(this.input.classList.add("taggle_back"),this._remove(c,a),this._fixInputWidth(),this._focusInput()):c.classList.add(d)},m.prototype._setInputWidth=function(a){this.input.style.width=(a||10)+"px"},m.prototype._hasDupes=function(a){var b,c=this.tag.values.indexOf(a),d=this.container.querySelector(".taggle_list");if(this.settings.duplicateTagClass){b=d.querySelectorAll("."+this.settings.duplicateTagClass);for(var e=0,f=b.length;f>e;e++)b[e].classList.remove(this.settings.duplicateTagClass)}return c>-1?(this.settings.duplicateTagClass&&d.childNodes[c].classList.add(this.settings.duplicateTagClass),!0):!1},m.prototype._isConfirmKey=function(a){var b=!1;return this.settings.submitKeys.indexOf(a)>-1&&(b=!0),b},m.prototype._focusInput=function(){this._fixInputWidth(),this.container.classList.contains(this.settings.containerFocusClass)||this.container.classList.add(this.settings.containerFocusClass),this.placeholder&&(this.placeholder.style.opacity=0)},m.prototype._blurEvent=function(a){if(this.container.classList.contains(this.settings.containerFocusClass)&&this.container.classList.remove(this.settings.containerFocusClass),!this.tag.values.length&&this.placeholder&&(this.placeholder.style.opacity=1),this.settings.saveOnBlur){if(a=a||window.event,this._listenForEndOfContainer(),""!==this.input.value)return void this._confirmValidTagEvent(a);this.tag.values.length&&this._checkLastTag(a)}else this.input.value="",this._setInputWidth()},m.prototype._keydownEvents=function(a){a=a||window.event;var b=a.keyCode;return this.pasting=!1,this._listenForEndOfContainer(),86===b&&a.metaKey&&(this.pasting=!0),this._isConfirmKey(b)&&""!==this.input.value?void this._confirmValidTagEvent(a):void(this.tag.values.length&&this._checkLastTag(a))},m.prototype._keyupEvents=function(a){a=a||window.event,this.input.classList.remove("taggle_back"),e(this.sizer,this.input.value),this.pasting&&""!==this.input.value&&(this._add(a),this.pasting=!1)},m.prototype._confirmValidTagEvent=function(a){a=a||window.event,a.preventDefault?a.preventDefault():a.returnValue=!1,this._add(a)},m.prototype._listenForEndOfContainer=function(){var a=this.sizer.getBoundingClientRect().width,b=this.measurements.container.rect.width-this.measurements.container.padding,c=parseInt(this.sizer.style.fontSize,10);a+1.5*c>parseInt(this.input.style.width,10)&&(this.input.style.width=b+"px")},m.prototype._createTag=function(a){var b=document.createElement("li"),d=document.createElement("button"),f=document.createElement("input"),g=document.createElement("span");a=this._formatTag(a),d.innerHTML="×",d.className="close",d.type="button",c(d,"click",this._remove.bind(this,d)),e(g,a),g.className="taggle_text",b.className="taggle "+this.settings.additionalTagClasses,f.type="hidden",f.value=a,f.name=this.settings.hiddenInputName,b.appendChild(g),b.appendChild(d),b.appendChild(f);var h=this.settings.tagFormatter(b);if("undefined"!=typeof h&&(b=h),!(b instanceof HTMLElement)||"LI"!==b.tagName)throw new Error("tagFormatter must return an li element");return this.settings.attachTagId&&(this._id+=1,a={text:a,id:this._id}),this.tag.values.push(a),this.tag.elements.push(b),b},m.prototype._remove=function(a,b){function c(c){c||(a.parentNode.removeChild(a),g.tag.elements.splice(f,1),g.tag.values.splice(f,1),g.settings.onTagRemove(b,d),g._focusInput())}var d,e,f,g=this;"li"!==a.tagName.toLowerCase()&&(a=a.parentNode),e="a"===a.tagName.toLowerCase()?a.parentNode:a,f=this.tag.elements.indexOf(e),d=this.tag.values[f];var h=this.settings.onBeforeTagRemove(b,d,c);h&&c()},m.prototype._formatTag=function(a){return this.settings.preserveCase?a:a.toLowerCase()},m.prototype.getTags=function(){return{elements:this.getTagElements(),values:this.getTagValues()}},m.prototype.getTagElements=function(){return this.tag.elements},m.prototype.getTagValues=function(){return[].slice.apply(this.tag.values)},m.prototype.getInput=function(){return this.input},m.prototype.getContainer=function(){return this.container},m.prototype.add=function(a){var c=b(a);if(c)for(var d=0,e=a.length;e>d;d++)"string"==typeof a[d]&&this._add(null,a[d]);else this._add(null,a);return this},m.prototype.remove=function(a,b){for(var c=this.tag.values.length-1,d=!1;c>-1;){var e=this.tag.values[c];if(this.settings.attachTagId&&(e=e.text),e===a&&(d=!0,this._remove(this.tag.elements[c])),d&&!b)break;c--}return this},m.prototype.removeAll=function(){for(var a=this.tag.values.length-1;a>=0;a--)this._remove(this.tag.elements[a]);return this},m.prototype.setOptions=function(b){return this.settings=a({},this.settings,b||{}),this},m}); \ No newline at end of file diff --git a/frappe/public/less/tags.less b/frappe/public/less/tags.less new file mode 100644 index 0000000000..6887a1df85 --- /dev/null +++ b/frappe/public/less/tags.less @@ -0,0 +1,22 @@ +.tags-list { + float: left; + width: 100%; + padding-left: 3px; +} + +.tags-input { + width: 100px; + font-size: 11px; + border: none; + outline: none; +} + +.tags-list-item { + display: inline-block; + margin: 0px 3px; +} + +.tags-placeholder { + display: inline-block; + font-size: 11px; +}