about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-07-07 17:20:08 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-07-07 17:20:08 -0400
commit5be9480128b2841647b204ba19ec9f45dac438f5 (patch)
treeb83441962e485e70d239a3ad8b9bf6ae6d9d5db6
parenta4779bdb3baf50b477bbe166f7b1d873d75e506f (diff)
downloadthoughts-5be9480128b2841647b204ba19ec9f45dac438f5.tar.gz
thoughts-5be9480128b2841647b204ba19ec9f45dac438f5.tar.bz2
thoughts-5be9480128b2841647b204ba19ec9f45dac438f5.zip
Added tag autocompletion
refs #2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock7
-rw-r--r--app/assets/javascripts/admin/records.coffee3
-rw-r--r--app/assets/javascripts/application.js2
-rw-r--r--app/assets/stylesheets/admin.css.scss1
-rw-r--r--app/controllers/tags_controller.rb11
-rw-r--r--config/routes.rb6
-rwxr-xr-xvendor/assets/javascripts/tags-input.js2
8 files changed, 33 insertions, 1 deletions
diff --git a/Gemfile b/Gemfile index f0c7c76..4561c51 100644 --- a/Gemfile +++ b/Gemfile
@@ -70,3 +70,5 @@ gem 'paperclip'
70gem 'jquery-rails' 70gem 'jquery-rails'
71gem 'pokeviewer', github: "hatkirby/pokeviewer" 71gem 'pokeviewer', github: "hatkirby/pokeviewer"
72gem 'acts-as-taggable-on' 72gem 'acts-as-taggable-on'
73gem 'jquery-ui-rails'
74gem '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
132 rails-dom-testing (>= 1, < 3) 132 rails-dom-testing (>= 1, < 3)
133 railties (>= 4.2.0) 133 railties (>= 4.2.0)
134 thor (>= 0.14, < 2.0) 134 thor (>= 0.14, < 2.0)
135 jquery-ui-rails (6.0.1)
136 railties (>= 3.2.16)
137 js-routes (1.4.4)
138 railties (>= 3.2)
139 sprockets-rails
135 libv8 (3.16.14.19) 140 libv8 (3.16.14.19)
136 listen (3.1.5) 141 listen (3.1.5)
137 rb-fsevent (~> 0.9, >= 0.9.4) 142 rb-fsevent (~> 0.9, >= 0.9.4)
@@ -286,6 +291,8 @@ DEPENDENCIES
286 highline 291 highline
287 jbuilder (~> 2.5) 292 jbuilder (~> 2.5)
288 jquery-rails 293 jquery-rails
294 jquery-ui-rails
295 js-routes
289 listen (>= 3.0.5, < 3.2) 296 listen (>= 3.0.5, < 3.2)
290 mysql2 297 mysql2
291 normalize-rails 298 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", ->
25 published_field_toggle($(this).prop("checked")) 25 published_field_toggle($(this).prop("checked"))
26 $("input[type=tags]").each -> 26 $("input[type=tags]").each ->
27 tagsInput(this) 27 tagsInput(this)
28 $(".tags-input input[type=text]").autocomplete({
29 source: Routes.suggest_tags_path()
30 })
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 @@
15//= require turbolinks 15//= require turbolinks
16//= require ckeditor/init 16//= require ckeditor/init
17//= require tags-input 17//= require tags-input
18//= require jquery-ui
19//= require js-routes
18//= require_tree ./admin 20//= 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 @@
1/* 1/*
2 *= require normalize-rails 2 *= require normalize-rails
3 *= require tags-input 3 *= require tags-input
4 *= require jquery-ui
4 *= require_tree ./admin 5 *= require_tree ./admin
5 */ 6 */
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 @@
1class TagsController < ApplicationController
2
3 def suggest
4 @tags = ActsAsTaggableOn::Tag.pluck(:name).select do |tag|
5 tag.starts_with? params[:term]
6 end
7
8 render json: @tags
9 end
10
11end
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
26 26
27 get 'thinks/:slug', to: 'streams#show', as: :stream 27 get 'thinks/:slug', to: 'streams#show', as: :stream
28 28
29 resources :tags, only: [], param: :name do
30 collection do
31 get 'suggest'
32 end
33 end
34
29 mount Pokeviewer::Engine => '/poke3' 35 mount Pokeviewer::Engine => '/poke3'
30end 36end
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 @@
1(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;}); 1(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;});
2//# sourceMappingURL=tags-input.js.map \ No newline at end of file 2//# sourceMappingURL=tags-input.js.map \ No newline at end of file