--- /dev/null
+AUI.add(\r
+ 'liferay-asset-tags-selector',\r
+ function(A) {\r
+ var Lang = A.Lang;\r
+\r
+ var AArray = A.Array;\r
+\r
+ var NAME = 'tagselector';\r
+\r
+ var CSS_INPUT_NODE = 'lfr-tag-selector-input';\r
+\r
+ var CSS_NO_MATCHES = 'no-matches';\r
+\r
+ var CSS_POPUP = 'lfr-tag-selector-popup';\r
+\r
+ var CSS_TAGS_LIST = 'lfr-tags-selector-list';\r
+\r
+ var MAP_INVALID_CHARACTERS = {\r
+ '&': 1,\r
+ '\'': 1,\r
+ '@': 1,\r
+ '\\': 1,\r
+ ']': 1,\r
+ '}': 1,\r
+ ':': 1,\r
+ ',': 1,\r
+ '=': 1,\r
+ '>': 1,\r
+ '/': 1,\r
+ '<': 1,\r
+ '\n': 1,\r
+ '[': 1,\r
+ '{': 1,\r
+ '%': 1,\r
+ '|': 1,\r
+ '+': 1,\r
+ '#': 1,\r
+ '?': 1,\r
+ '"': 1,\r
+ '\r': 1,\r
+ ';': 1,\r
+ '*': 1,\r
+ '~': 1\r
+ };\r
+\r
+ var TPL_CHECKED = ' checked="checked" ';\r
+\r
+ var TPL_INPUT = '<label title="{name}"><input type="checkbox" value="{name}" {checked} />{name}</label>';\r
+\r
+ var TPL_LOADING = '<div class="loading-animation" />';\r
+\r
+ var TPL_MESSAGE = '<div class="lfr-tag-message">{0}</div>';\r
+\r
+ var TPL_URL_SUGGESTIONS = 'http://search.yahooapis.com/ContentAnalysisService/V1/termExtraction?appid=YahooDemo&output=json&context={context}';\r
+\r
+ var TPL_TAGS_CONTAINER = '<div class="' + CSS_TAGS_LIST + '"></div>';\r
+\r
+ /**\r
+ * OPTIONS\r
+ *\r
+ * Required\r
+ * className (string): The class name of the current asset.\r
+ * curEntries (string): The current tags.\r
+ * instanceVar {string}: The instance variable for this class.\r
+ * hiddenInput {string}: The hidden input used to pass in the current tags.\r
+ * textInput {string}: The text input for users to add tags.\r
+ * summarySpan {string}: The summary span to show the current tags.\r
+ *\r
+ * Optional\r
+ * focus {boolean}: Whether the text input should be focused.\r
+ * portalModelResource {boolean}: Whether the asset model is on the portal level.\r
+ *\r
+ * Callbacks\r
+ * contentCallback {function}: Called to get suggested tags.\r
+ */\r
+\r
+ var AssetTagsSelector = A.Component.create(\r
+ {\r
+ ATTRS: {\r
+ allowAnyEntry: {\r
+ //AAPEESC value: true\r
+ value: false\r
+ },\r
+ allowSuggestions: {\r
+ value: false\r
+ },\r
+ className: {\r
+ value: null\r
+ },\r
+ contentCallback: {\r
+ value: null\r
+ },\r
+ curEntries: {\r
+ setter: function(value) {\r
+ var instance = this;\r
+\r
+ if (Lang.isString(value)) {\r
+ value = value.split(',');\r
+ }\r
+\r
+ return value;\r
+ },\r
+ value: ''\r
+ },\r
+ dataSource: {\r
+ valueFn: function() {\r
+ var instance = this;\r
+\r
+ return instance._getTagsDataSource();\r
+ }\r
+ },\r
+ guid: {\r
+ value: ''\r
+ },\r
+ instanceVar: {\r
+ value: ''\r
+ },\r
+ portalModelResource: {\r
+ value: false\r
+ },\r
+ hiddenInput: {\r
+ setter: function(value) {\r
+ var instance = this;\r
+\r
+ return A.one(value + instance.get('guid'));\r
+ }\r
+ },\r
+ matchKey: {\r
+ value: 'value'\r
+ },\r
+ schema: {\r
+ value: {\r
+ resultFields: ['text', 'value']\r
+ }\r
+ }\r
+ },\r
+\r
+ EXTENDS: A.TextboxList,\r
+\r
+ NAME: NAME,\r
+\r
+ prototype: {\r
+ renderUI: function() {\r
+ var instance = this;\r
+\r
+ AssetTagsSelector.superclass.renderUI.apply(instance, arguments);\r
+\r
+ instance._renderIcons();\r
+\r
+ instance.inputNode.addClass(CSS_INPUT_NODE);\r
+\r
+ instance._overlayAlign.node = instance.entryHolder;\r
+ },\r
+\r
+ bindUI: function() {\r
+ var instance = this;\r
+\r
+ AssetTagsSelector.superclass.bindUI.apply(instance, arguments);\r
+\r
+ instance._bindTagsSelector();\r
+\r
+ instance.entries.after('add', instance._updateHiddenInput, instance);\r
+ instance.entries.after('remove', instance._updateHiddenInput, instance);\r
+ },\r
+\r
+ addEntries: function() {\r
+ var instance = this;\r
+\r
+ instance._onAddEntryClick();\r
+ },\r
+\r
+ syncUI: function() {\r
+ var instance = this;\r
+\r
+ AssetTagsSelector.superclass.syncUI.apply(instance, arguments);\r
+\r
+ var curEntries = instance.get('curEntries');\r
+\r
+ A.each(curEntries, instance.add, instance);\r
+ },\r
+\r
+ _bindTagsSelector: function() {\r
+ var instance = this;\r
+\r
+ instance._submitFormListener = A.Do.before(instance._onAddEntryClick, window, 'submitForm', instance);\r
+\r
+ instance.get('boundingBox').on('keypress', instance._onKeyPress, instance);\r
+ },\r
+\r
+ _formatEntry: function(item) {\r
+ var instance = this;\r
+\r
+ var input = Lang.sub(TPL_INPUT, item);\r
+\r
+ instance._buffer.push(input);\r
+ },\r
+\r
+ _getPopup: function() {\r
+ var instance = this;\r
+\r
+ if (!instance._popup) {\r
+ var popup = new A.Dialog(\r
+ {\r
+ bodyContent: TPL_LOADING,\r
+ constrain: true,\r
+ draggable: true,\r
+ hideClass: 'aui-helper-hidden-accessible',\r
+ preventOverlap: true,\r
+ stack: true,\r
+ title: '',\r
+ width: 320,\r
+ zIndex: 1000\r
+ }\r
+ ).render();\r
+\r
+ popup.get('boundingBox').addClass(CSS_POPUP);\r
+\r
+ var bodyNode = popup.bodyNode;\r
+\r
+ bodyNode.html('');\r
+\r
+ var searchField = new A.Textfield(\r
+ {\r
+ defaultValue: Liferay.Language.get('search'),\r
+ labelText: false\r
+ }\r
+ ).render(bodyNode);\r
+\r
+ var entriesNode = A.Node.create(TPL_TAGS_CONTAINER);\r
+\r
+ bodyNode.appendChild(entriesNode);\r
+\r
+ popup.searchField = searchField;\r
+ popup.entriesNode = entriesNode;\r
+\r
+ instance._popup = popup;\r
+\r
+ instance._initSearch();\r
+\r
+ var onCheckboxClick = A.bind(instance._onCheckboxClick, instance);\r
+\r
+ entriesNode.delegate('click', onCheckboxClick, 'input[type=checkbox]');\r
+ }\r
+\r
+ return instance._popup;\r
+ },\r
+\r
+ _getProxyData: function(context) {\r
+ var instance = this;\r
+\r
+ var suggestionsURL = Lang.sub(\r
+ TPL_URL_SUGGESTIONS,\r
+ {\r
+ context: encodeURIComponent(context)\r
+ }\r
+ );\r
+\r
+ var proxyData = {\r
+ url: suggestionsURL\r
+ };\r
+\r
+ return proxyData;\r
+ },\r
+\r
+ _getEntries: function(callback) {\r
+ var instance = this;\r
+\r
+ var portalModelResource = instance.get('portalModelResource');\r
+\r
+ var groupIds = [];\r
+\r
+ if (!portalModelResource && (themeDisplay.getParentGroupId() != themeDisplay.getCompanyGroupId())) {\r
+ groupIds.push(themeDisplay.getParentGroupId());\r
+ }\r
+\r
+ groupIds.push(themeDisplay.getCompanyGroupId());\r
+\r
+ Liferay.Service.Asset.AssetTag.getGroupsTags(\r
+ {\r
+ groupIds: groupIds\r
+ },\r
+ callback\r
+ );\r
+ },\r
+\r
+ _getTagsDataSource: function() {\r
+ var instance = this;\r
+\r
+ var AssetTagSearch = Liferay.Service.Asset.AssetTag.search;\r
+\r
+ AssetTagSearch._serviceQueryCache = {};\r
+\r
+ var serviceQueryCache = AssetTagSearch._serviceQueryCache;\r
+\r
+ var dataSource = new Liferay.Service.DataSource(\r
+ {\r
+ on: {\r
+ request: function(event) {\r
+ var term = event.request;\r
+ var key = term;\r
+\r
+ if (term == '*') {\r
+ term = '';\r
+ }\r
+\r
+ var serviceQueryObj = serviceQueryCache[key];\r
+\r
+ if (!serviceQueryObj) {\r
+ serviceQueryObj = {\r
+ groupId: themeDisplay.getParentGroupId(),\r
+ name: '%' + term + '%',\r
+ properties: '',\r
+ begin: 0,\r
+ end: 20\r
+ };\r
+\r
+ serviceQueryCache[key] = serviceQueryObj;\r
+ }\r
+\r
+ event.request = serviceQueryObj;\r
+ }\r
+ },\r
+ source: AssetTagSearch\r
+ }\r
+ ).plug(\r
+ A.Plugin.DataSourceCache,\r
+ {\r
+ max: 500\r
+ }\r
+ );\r
+\r
+ return dataSource;\r
+ },\r
+\r
+ _initSearch: function() {\r
+ var instance = this;\r
+\r
+ var popup = instance._popup;\r
+\r
+ popup.liveSearch = new A.LiveSearch(\r
+ {\r
+ after: {\r
+ search: function() {\r
+ var fieldsets = popup.entriesNode.all('fieldset');\r
+\r
+ fieldsets.each(\r
+ function(item, index, collection) {\r
+ var visibleEntries = item.one('label:not(.aui-helper-hidden)');\r
+\r
+ var action = 'addClass';\r
+\r
+ if (visibleEntries) {\r
+ action = 'removeClass';\r
+ }\r
+\r
+ item[action](CSS_NO_MATCHES);\r
+ }\r
+ );\r
+ }\r
+ },\r
+ data: function(node) {\r
+ var value = node.attr('title');\r
+\r
+ return value.toLowerCase();\r
+ },\r
+ input: popup.searchField.get('node'),\r
+ nodes: '.' + CSS_TAGS_LIST + ' label'\r
+ }\r
+ );\r
+ },\r
+\r
+ _namespace: function(name) {\r
+ var instance = this;\r
+\r
+ return instance.get('instanceVar') + name + instance.get('guid');\r
+ },\r
+\r
+ _onAddEntryClick: function(event) { \r
+ var instance = this;\r
+\r
+ var text = Liferay.Util.escapeHTML(instance.inputNode.val());\r
+\r
+ if (text) {\r
+ if(text.indexOf(',') > -1) {\r
+ var items = text.split(',');\r
+\r
+ A.each(\r
+ items,\r
+ function(item, index, collection) {\r
+ instance.entries.add(item, {});\r
+ }\r
+ );\r
+ } else {\r
+ instance.entries.add(text, {});\r
+ }\r
+ }\r
+ Liferay.Util.focusFormField(instance.inputNode);\r
+\r
+ },\r
+\r
+\r
+ _onCheckboxClick: function(event) {\r
+ var instance = this;\r
+\r
+ var checkbox = event.currentTarget;\r
+ var checked = checkbox.get('checked');\r
+ var value = checkbox.val();\r
+\r
+ var action = 'remove';\r
+\r
+ if (checked) {\r
+ action = 'add';\r
+ }\r
+\r
+ instance[action](value);\r
+ },\r
+\r
+ _onKeyPress: function(event) {\r
+ /* AAPEESC DEBUT : interdire la saisie\r
+ var instance = this;\r
+\r
+ var charCode = event.charCode;\r
+\r
+ if (charCode == '44') {\r
+ instance._onAddEntryClick();\r
+\r
+ event.preventDefault();\r
+ }\r
+ else if (MAP_INVALID_CHARACTERS[String.fromCharCode(charCode)]) {\r
+ event.halt();\r
+ }\r
+ AAPEESC IN */\r
+ event.halt(); // Interdire saisie\r
+ },\r
+\r
+ _renderIcons: function() {\r
+ var instance = this;\r
+\r
+ var contentBox = instance.get('contentBox');\r
+\r
+ var toolbar = [\r
+ /*AAPEESC\r
+ {\r
+ handler: {\r
+ context: instance,\r
+ fn: instance._onAddEntryClick\r
+ },\r
+ icon: 'plus',\r
+ id: 'add',\r
+ label: Liferay.Language.get('add')\r
+ },\r
+ */\r
+ {\r
+ handler: {\r
+ context: instance,\r
+ fn: instance._showSelectPopup\r
+ },\r
+ icon: 'search',\r
+ id: 'select',\r
+ label: Liferay.Language.get('select')\r
+ }\r
+ ];\r
+\r
+ if (instance.get('contentCallback')) {\r
+ toolbar.push(\r
+ {\r
+ handler: {\r
+ context: instance,\r
+ fn: instance._showSuggestionsPopup\r
+ },\r
+ icon: 'comment',\r
+ id: 'suggest',\r
+ label: Liferay.Language.get('suggestions')\r
+ }\r
+ );\r
+ }\r
+\r
+ instance.icons = new A.Toolbar(\r
+ {\r
+ children: toolbar\r
+ }\r
+ ).render(contentBox);\r
+\r
+ var iconsBoundingBox = instance.icons.get('boundingBox');\r
+\r
+ instance.entryHolder.placeAfter(iconsBoundingBox);\r
+ },\r
+\r
+ _showPopup: function(event) {\r
+ var instance = this;\r
+\r
+ var popup = instance._getPopup();\r
+\r
+ if (event && event.currentTarget) {\r
+ var toolItem = event.currentTarget.get('boundingBox');\r
+\r
+ popup.align(toolItem, ['bl', 'tl']);\r
+ }\r
+\r
+ popup.entriesNode.html(TPL_LOADING);\r
+\r
+ popup.show();\r
+\r
+ if (popup.get('stack')) {\r
+ setTimeout(\r
+ function() {\r
+ A.DialogManager.bringToTop(popup);\r
+ },\r
+ 0\r
+ );\r
+ }\r
+ },\r
+\r
+ _showSelectPopup: function(event) {\r
+ var instance = this;\r
+\r
+ instance._showPopup(event);\r
+\r
+ instance._popup.set('title', Liferay.Language.get('interested-in'));\r
+\r
+ instance._getEntries(\r
+ function(entries) {\r
+ instance._updateSelectList(entries, instance._entriesIterator);\r
+ }\r
+ );\r
+ },\r
+\r
+ _showSuggestionsPopup: function(event) {\r
+ var instance = this;\r
+\r
+ instance._showPopup(event);\r
+\r
+ instance._popup.set('title', Liferay.Language.get('suggestions'));\r
+\r
+ var contentCallback = instance.get('contentCallback');\r
+\r
+ var context = '';\r
+ var data = [];\r
+\r
+ if (contentCallback) {\r
+ context = contentCallback();\r
+\r
+ context = String(context);\r
+ }\r
+\r
+ var length = context.length;\r
+\r
+ var urlSizeLimit = 4096;\r
+\r
+ var end = urlSizeLimit;\r
+ var lastSpaceIndex = 0;\r
+ var start = 0;\r
+\r
+ var suggestionsIO = A.io.request(\r
+ themeDisplay.getPathMain() + '/portal/rest_proxy',\r
+ {\r
+ autoLoad: false,\r
+ dataType: 'json',\r
+ on: {\r
+ success: function(event, id, obj) {\r
+ var results = this.get('responseData');\r
+\r
+ if (results && results.ResultSet && results.ResultSet.Result) {\r
+ data = data.concat(results.ResultSet.Result);\r
+ }\r
+\r
+ queue.run();\r
+ }\r
+ }\r
+ }\r
+ );\r
+\r
+ var queue = new A.AsyncQueue(\r
+ {\r
+ fn: function() {\r
+ queue.pause();\r
+\r
+ var phrase = context.substr(start, end);\r
+\r
+ lastSpaceIndex = urlSizeLimit;\r
+\r
+ if (end < length) {\r
+ lastSpaceIndex = phrase.lastIndexOf(' ');\r
+\r
+ phrase = phrase.substr(0, lastSpaceIndex);\r
+\r
+ end = start + lastSpaceIndex;\r
+ }\r
+\r
+ start += lastSpaceIndex;\r
+ end = start + urlSizeLimit;\r
+\r
+ suggestionsIO.set('data', instance._getProxyData(phrase));\r
+\r
+ suggestionsIO.start();\r
+ },\r
+ until: function () {\r
+ return length <= start;\r
+ }\r
+ }\r
+ );\r
+\r
+ queue.after(\r
+ 'complete',\r
+ function(event) {\r
+ instance._updateSelectList(AArray.unique(data), instance._suggestionsIterator);\r
+ }\r
+ );\r
+\r
+ queue.run();\r
+ },\r
+\r
+ _suggestionsIterator: function(item, index, collection) {\r
+ var instance = this;\r
+\r
+ var checked = instance.entries.indexOfKey(item) > -1 ? TPL_CHECKED : '';\r
+\r
+ var tag = {\r
+ checked: checked,\r
+ name: item\r
+ };\r
+\r
+ instance._formatEntry(tag);\r
+ },\r
+\r
+ _entriesIterator: function(item, index, collection) {\r
+ var instance = this;\r
+\r
+ item.checked = instance.entries.indexOfKey(item.name) > -1 ? TPL_CHECKED : '';\r
+\r
+ instance._formatEntry(item);\r
+ },\r
+\r
+ _updateHiddenInput: function(event) {\r
+ var instance = this;\r
+\r
+ var hiddenInput = instance.get('hiddenInput');\r
+\r
+ hiddenInput.val(instance.entries.keys.join());\r
+\r
+ var popup = instance._popup;\r
+\r
+ if (popup && popup.get('visible')) {\r
+ var checkbox = popup.bodyNode.one('input[value=' + event.attrName + ']');\r
+\r
+ if (checkbox) {\r
+ var checked = false;\r
+\r
+ if (event.type == 'dataset:add') {\r
+ checked = true;\r
+ }\r
+\r
+ checkbox.set('checked', checked);\r
+ }\r
+ }\r
+ },\r
+\r
+ _updateSelectList: function(data, iterator) {\r
+ var instance = this;\r
+\r
+ var popup = instance._popup;\r
+\r
+ popup.searchField.resetValue();\r
+\r
+ instance._buffer = ['<fieldset class="' + (!data || !data.length ? CSS_NO_MATCHES : '') + '">'];\r
+\r
+ A.each(data, iterator, instance);\r
+\r
+ var buffer = instance._buffer;\r
+\r
+ var message = Lang.sub(TPL_MESSAGE, [Liferay.Language.get('no-tags-found')]);\r
+\r
+ buffer.push(message);\r
+ buffer.push('</fieldset>');\r
+\r
+ popup.entriesNode.html(buffer.join(''));\r
+\r
+ popup.liveSearch.get('nodes').refresh();\r
+ popup.liveSearch.refreshIndex();\r
+ },\r
+\r
+ _buffer: []\r
+ }\r
+ }\r
+ );\r
+\r
+ Liferay.AssetTagsSelector = AssetTagsSelector;\r
+ },\r
+ '',\r
+ {\r
+ requires: ['array-extras', 'async-queue', 'aui-autocomplete', 'aui-dialog', 'aui-io-request', 'aui-live-search', 'aui-textboxlist', 'aui-form-textfield', 'datasource-cache', 'liferay-service-datasource']\r
+ }\r
+);
\ No newline at end of file