From 5be9480128b2841647b204ba19ec9f45dac438f5 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sat, 7 Jul 2018 17:20:08 -0400 Subject: Added tag autocompletion refs #2 --- Gemfile | 2 ++ Gemfile.lock | 7 +++++++ app/assets/javascripts/admin/records.coffee | 3 +++ app/assets/javascripts/application.js | 2 ++ app/assets/stylesheets/admin.css.scss | 1 + app/controllers/tags_controller.rb | 11 +++++++++++ config/routes.rb | 6 ++++++ vendor/assets/javascripts/tags-input.js | 2 +- 8 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 app/controllers/tags_controller.rb diff --git a/Gemfile b/Gemfile index f0c7c76..4561c51 100644 --- a/Gemfile +++ b/Gemfile @@ -70,3 +70,5 @@ gem 'paperclip' gem 'jquery-rails' gem 'pokeviewer', github: "hatkirby/pokeviewer" gem 'acts-as-taggable-on' +gem 'jquery-ui-rails' +gem 'js-routes' diff --git a/Gemfile.lock b/Gemfile.lock index 09ff6ef..ae55c62 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -132,6 +132,11 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) + jquery-ui-rails (6.0.1) + railties (>= 3.2.16) + js-routes (1.4.4) + railties (>= 3.2) + sprockets-rails libv8 (3.16.14.19) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) @@ -286,6 +291,8 @@ DEPENDENCIES highline jbuilder (~> 2.5) jquery-rails + jquery-ui-rails + js-routes listen (>= 3.0.5, < 3.2) mysql2 normalize-rails diff --git a/app/assets/javascripts/admin/records.coffee b/app/assets/javascripts/admin/records.coffee index 7a11ce1..27cdb78 100644 --- a/app/assets/javascripts/admin/records.coffee +++ b/app/assets/javascripts/admin/records.coffee @@ -25,3 +25,6 @@ $(document).on "turbolinks:load", -> published_field_toggle($(this).prop("checked")) $("input[type=tags]").each -> tagsInput(this) + $(".tags-input input[type=text]").autocomplete({ + source: Routes.suggest_tags_path() + }) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index a81b3b2..58e8fb7 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -15,4 +15,6 @@ //= require turbolinks //= require ckeditor/init //= require tags-input +//= require jquery-ui +//= require js-routes //= require_tree ./admin diff --git a/app/assets/stylesheets/admin.css.scss b/app/assets/stylesheets/admin.css.scss index 95d1ed0..cb6fb96 100644 --- a/app/assets/stylesheets/admin.css.scss +++ b/app/assets/stylesheets/admin.css.scss @@ -1,5 +1,6 @@ /* *= require normalize-rails *= require tags-input + *= require jquery-ui *= require_tree ./admin */ diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb new file mode 100644 index 0000000..7115d28 --- /dev/null +++ b/app/controllers/tags_controller.rb @@ -0,0 +1,11 @@ +class TagsController < ApplicationController + + def suggest + @tags = ActsAsTaggableOn::Tag.pluck(:name).select do |tag| + tag.starts_with? params[:term] + end + + render json: @tags + end + +end diff --git a/config/routes.rb b/config/routes.rb index ac5b84d..2d0a4ec 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -26,5 +26,11 @@ Rails.application.routes.draw do get 'thinks/:slug', to: 'streams#show', as: :stream + resources :tags, only: [], param: :name do + collection do + get 'suggest' + end + end + mount Pokeviewer::Engine => '/poke3' end diff --git a/vendor/assets/javascripts/tags-input.js b/vendor/assets/javascripts/tags-input.js index 878339e..162f1ef 100755 --- a/vendor/assets/javascripts/tags-input.js +++ b/vendor/assets/javascripts/tags-input.js @@ -1,2 +1,2 @@ -(function(global,factory){if(typeof define === 'function' && define.amd){define(['exports','module'],factory);}else if(typeof exports !== 'undefined' && typeof module !== 'undefined'){factory(exports,module);}else {var mod={exports:{}};factory(mod.exports,mod);global.tagsInput = mod.exports;}})(this,function(exports,module){'use strict';module.exports = tagsInput;var BACKSPACE=8,TAB=9,ENTER=13,LEFT=37,RIGHT=39,DELETE=46,COMMA=188;var SEPERATOR=',';var COPY_PROPS='placeholder pattern spellcheck autocomplete autocapitalize autofocus accessKey accept lang minLength maxLength required'.split(' ');function tagsInput(input){function createElement(type,name,text,attributes){var el=document.createElement(type);if(name)el.className = name;if(text)el.textContent = text;for(var key in attributes) {el.setAttribute('data-' + key,attributes[key]);}return el;}function $(selector,all){return all === true?Array.prototype.slice.call(base.querySelectorAll(selector)):base.querySelector(selector);}function getValue(){return $('.tag',true).map(function(tag){return tag.textContent;}).concat(base.input.value || []).join(SEPERATOR);}function setValue(value){$('.tag',true).forEach(function(t){return base.removeChild(t);});savePartialInput(value);}function save(){input.value = getValue();input.dispatchEvent(new Event('change'));}function addTag(text){if(~text.indexOf(SEPERATOR))text = text.split(SEPERATOR);if(Array.isArray(text))return text.forEach(addTag);var tag=text && text.trim();if(!tag)return false;if(!input.getAttribute('duplicates')){var _ret=(function(){var exisingTag=$('[data-tag="' + tag + '"]');if(exisingTag){exisingTag.classList.add('dupe');setTimeout(function(){return exisingTag.classList.remove('dupe');},100);return {v:false};}})();if(typeof _ret === 'object')return _ret.v;}base.insertBefore(createElement('span','tag',tag,{tag:tag}),base.input);}function select(el){var sel=$('.selected');if(sel)sel.classList.remove('selected');if(el)el.classList.add('selected');}function setInputWidth(){var last=$('.tag',true).pop(),w=base.offsetWidth;if(!w)return;base.input.style.width = Math.max(w - (last?last.offsetLeft + last.offsetWidth:5) - 5,w / 4) + 'px';}function savePartialInput(value){if(typeof value !== 'string' && !Array.isArray(value)){value = base.input.value || input.value;}if(addTag(value) !== false){base.input.value = '';save();setInputWidth();}}function refocus(e){if(e.target.classList.contains('tag'))select(e.target);if(e.target === base.input)return select();base.input.focus();e.preventDefault();return false;}var base=createElement('div','tags-input'),sib=input.nextSibling;input.parentNode[sib?'insertBefore':'appendChild'](base,sib);input.style.cssText = 'position:absolute;left:0;top:-99px;width:1px;height:1px;opacity:0.01;';input.tabIndex = -1;base.input = createElement('input');base.input.setAttribute('type','text');COPY_PROPS.forEach(function(prop){if(input[prop] !== base.input[prop]){base.input[prop] = input[prop];try{delete input[prop];}catch(e) {}}});base.appendChild(base.input);input.addEventListener('focus',function(){base.input.focus();});base.input.addEventListener('focus',function(){base.classList.add('focus');select();});base.input.addEventListener('blur',function(){base.classList.remove('focus');select();savePartialInput();});base.input.addEventListener('keydown',function(e){var el=base.input,key=e.keyCode || e.which,selectedTag=$('.tag.selected'),pos=el.selectionStart === el.selectionEnd && el.selectionStart,last=$('.tag',true).pop();setInputWidth();if(key === ENTER || key === COMMA || key === TAB){if(!el.value && key !== COMMA)return;savePartialInput();}else if(key === DELETE && selectedTag){if(selectedTag.nextSibling !== base.input)select(selectedTag.nextSibling);base.removeChild(selectedTag);setInputWidth();save();}else if(key === BACKSPACE){if(selectedTag){select(selectedTag.previousSibling);base.removeChild(selectedTag);setInputWidth();save();}else if(last && pos === 0){select(last);}else {return;}}else if(key === LEFT){if(selectedTag){if(selectedTag.previousSibling){select(selectedTag.previousSibling);}}else if(pos !== 0){return;}else {select(last);}}else if(key === RIGHT){if(!selectedTag)return;select(selectedTag.nextSibling);}else {return select();}e.preventDefault();return false;});base.input.addEventListener('input',function(){input.value = getValue();input.dispatchEvent(new Event('input'));});base.input.addEventListener('paste',function(){return setTimeout(savePartialInput,0);});base.addEventListener('mousedown',refocus);base.addEventListener('touchstart',refocus);base.setValue = setValue;base.getValue = getValue;savePartialInput();}tagsInput.enhance = tagsInput.tagsInput = tagsInput;}); +(function(global,factory){if(typeof define === 'function' && define.amd){define(['exports','module'],factory);}else if(typeof exports !== 'undefined' && typeof module !== 'undefined'){factory(exports,module);}else {var mod={exports:{}};factory(mod.exports,mod);global.tagsInput = mod.exports;}})(this,function(exports,module){'use strict';module.exports = tagsInput;var BACKSPACE=8,TAB=9,ENTER=13,LEFT=37,RIGHT=39,DELETE=46,COMMA=188;var SEPERATOR=',';var COPY_PROPS='placeholder pattern spellcheck autocomplete autocapitalize autofocus accessKey accept lang minLength maxLength required'.split(' ');function tagsInput(input){function createElement(type,name,text,attributes){var el=document.createElement(type);if(name)el.className = name;if(text)el.textContent = text;for(var key in attributes) {el.setAttribute('data-' + key,attributes[key]);}return el;}function $(selector,all){return all === true?Array.prototype.slice.call(base.querySelectorAll(selector)):base.querySelector(selector);}function getValue(){return $('.tag',true).map(function(tag){return tag.textContent;}).concat(base.input.value || []).join(SEPERATOR);}function setValue(value){$('.tag',true).forEach(function(t){return base.removeChild(t);});savePartialInput(value);}function save(){input.value = getValue();input.dispatchEvent(new Event('change'));}function addTag(text){if(~text.indexOf(SEPERATOR))text = text.split(SEPERATOR);if(Array.isArray(text))return text.forEach(addTag);var tag=text && text.trim();if(!tag)return false;if(!input.getAttribute('duplicates')){var _ret=(function(){var exisingTag=$('[data-tag="' + tag + '"]');if(exisingTag){exisingTag.classList.add('dupe');setTimeout(function(){return exisingTag.classList.remove('dupe');},100);return {v:false};}})();if(typeof _ret === 'object')return _ret.v;}base.insertBefore(createElement('span','tag',tag,{tag:tag}),base.input);}function select(el){var sel=$('.selected');if(sel)sel.classList.remove('selected');if(el)el.classList.add('selected');}function setInputWidth(){var last=$('.tag',true).pop(),w=base.offsetWidth;if(!w)return;base.input.style.width = '100%';}function savePartialInput(value){if(typeof value !== 'string' && !Array.isArray(value)){value = base.input.value || input.value;}if(addTag(value) !== false){base.input.value = '';save();setInputWidth();}}function refocus(e){if(e.target.classList.contains('tag'))select(e.target);if(e.target === base.input)return select();base.input.focus();e.preventDefault();return false;}var base=createElement('div','tags-input'),sib=input.nextSibling;input.parentNode[sib?'insertBefore':'appendChild'](base,sib);input.style.cssText = 'position:absolute;left:0;top:-99px;width:1px;height:1px;opacity:0.01;';input.tabIndex = -1;base.input = createElement('input');base.input.setAttribute('type','text');COPY_PROPS.forEach(function(prop){if(input[prop] !== base.input[prop]){base.input[prop] = input[prop];try{delete input[prop];}catch(e) {}}});base.appendChild(base.input);input.addEventListener('focus',function(){base.input.focus();});base.input.addEventListener('focus',function(){base.classList.add('focus');select();});base.input.addEventListener('blur',function(){base.classList.remove('focus');select();savePartialInput();});base.input.addEventListener('keydown',function(e){var el=base.input,key=e.keyCode || e.which,selectedTag=$('.tag.selected'),pos=el.selectionStart === el.selectionEnd && el.selectionStart,last=$('.tag',true).pop();setInputWidth();if(key === ENTER || key === COMMA || key === TAB){if(!el.value && key !== COMMA)return;savePartialInput();}else if(key === DELETE && selectedTag){if(selectedTag.nextSibling !== base.input)select(selectedTag.nextSibling);base.removeChild(selectedTag);setInputWidth();save();}else if(key === BACKSPACE){if(selectedTag){select(selectedTag.previousSibling);base.removeChild(selectedTag);setInputWidth();save();}else if(last && pos === 0){select(last);}else {return;}}else if(key === LEFT){if(selectedTag){if(selectedTag.previousSibling){select(selectedTag.previousSibling);}}else if(pos !== 0){return;}else {select(last);}}else if(key === RIGHT){if(!selectedTag)return;select(selectedTag.nextSibling);}else {return select();}e.preventDefault();return false;});base.input.addEventListener('input',function(){input.value = getValue();input.dispatchEvent(new Event('input'));});base.input.addEventListener('paste',function(){return setTimeout(savePartialInput,0);});base.addEventListener('mousedown',refocus);base.addEventListener('touchstart',refocus);base.setValue = setValue;base.getValue = getValue;savePartialInput();}tagsInput.enhance = tagsInput.tagsInput = tagsInput;}); //# sourceMappingURL=tags-input.js.map \ No newline at end of file -- cgit 1.4.1