Limited tag value autosuggestions based on tag name
As requested on #121
Showing
4 changed files
with
34 additions
and
14 deletions
| ... | @@ -67,7 +67,8 @@ class TagController extends Controller | ... | @@ -67,7 +67,8 @@ class TagController extends Controller |
| 67 | public function getValueSuggestions(Request $request) | 67 | public function getValueSuggestions(Request $request) |
| 68 | { | 68 | { |
| 69 | $searchTerm = $request->get('search'); | 69 | $searchTerm = $request->get('search'); |
| 70 | - $suggestions = $this->tagRepo->getValueSuggestions($searchTerm); | 70 | + $tagName = $request->has('name') ? $request->get('name') : false; |
| 71 | + $suggestions = $this->tagRepo->getValueSuggestions($searchTerm, $tagName); | ||
| 71 | return response()->json($suggestions); | 72 | return response()->json($suggestions); |
| 72 | } | 73 | } |
| 73 | 74 | ... | ... |
| ... | @@ -72,15 +72,20 @@ class TagRepo | ... | @@ -72,15 +72,20 @@ class TagRepo |
| 72 | /** | 72 | /** |
| 73 | * Get tag value suggestions from scanning existing tag values. | 73 | * Get tag value suggestions from scanning existing tag values. |
| 74 | * @param $searchTerm | 74 | * @param $searchTerm |
| 75 | + * @param $tagName | ||
| 75 | * @return array | 76 | * @return array |
| 76 | */ | 77 | */ |
| 77 | - public function getValueSuggestions($searchTerm) | 78 | + public function getValueSuggestions($searchTerm, $tagName = false) |
| 78 | { | 79 | { |
| 79 | if ($searchTerm === '') return []; | 80 | if ($searchTerm === '') return []; |
| 80 | $query = $this->tag->where('value', 'LIKE', $searchTerm . '%')->groupBy('value')->orderBy('value', 'desc'); | 81 | $query = $this->tag->where('value', 'LIKE', $searchTerm . '%')->groupBy('value')->orderBy('value', 'desc'); |
| 82 | + if ($tagName !== false) { | ||
| 83 | + $query = $query->where('name', '=', $tagName); | ||
| 84 | + } | ||
| 81 | $query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); | 85 | $query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); |
| 82 | return $query->get(['value'])->pluck('value'); | 86 | return $query->get(['value'])->pluck('value'); |
| 83 | } | 87 | } |
| 88 | + | ||
| 84 | /** | 89 | /** |
| 85 | * Save an array of tags to an entity | 90 | * Save an array of tags to an entity |
| 86 | * @param Entity $entity | 91 | * @param Entity $entity | ... | ... |
| ... | @@ -378,7 +378,7 @@ module.exports = function (ngApp, events) { | ... | @@ -378,7 +378,7 @@ module.exports = function (ngApp, events) { |
| 378 | } | 378 | } |
| 379 | }]); | 379 | }]); |
| 380 | 380 | ||
| 381 | - ngApp.directive('autosuggestions', ['$http', function($http) { | 381 | + ngApp.directive('tagAutosuggestions', ['$http', function($http) { |
| 382 | return { | 382 | return { |
| 383 | restrict: 'A', | 383 | restrict: 'A', |
| 384 | link: function(scope, elem, attrs) { | 384 | link: function(scope, elem, attrs) { |
| ... | @@ -403,6 +403,8 @@ module.exports = function (ngApp, events) { | ... | @@ -403,6 +403,8 @@ module.exports = function (ngApp, events) { |
| 403 | let $input = $(this); | 403 | let $input = $(this); |
| 404 | let val = $input.val(); | 404 | let val = $input.val(); |
| 405 | let url = $input.attr('autosuggest'); | 405 | let url = $input.attr('autosuggest'); |
| 406 | + let type = $input.attr('autosuggest-type'); | ||
| 407 | + | ||
| 406 | // No suggestions until at least 3 chars | 408 | // No suggestions until at least 3 chars |
| 407 | if (val.length < 3) { | 409 | if (val.length < 3) { |
| 408 | if (isShowing) { | 410 | if (isShowing) { |
| ... | @@ -410,12 +412,21 @@ module.exports = function (ngApp, events) { | ... | @@ -410,12 +412,21 @@ module.exports = function (ngApp, events) { |
| 410 | isShowing = false; | 412 | isShowing = false; |
| 411 | } | 413 | } |
| 412 | return; | 414 | return; |
| 413 | - }; | 415 | + } |
| 416 | + | ||
| 417 | + // Add name param to request if for a value | ||
| 418 | + if (type.toLowerCase() === 'value') { | ||
| 419 | + let $nameInput = $input.closest('tr').find('[autosuggest-type="name"]').first(); | ||
| 420 | + let nameVal = $nameInput.val(); | ||
| 421 | + if (nameVal === '') return; | ||
| 422 | + url += '?name=' + encodeURIComponent(nameVal); | ||
| 423 | + console.log(url); | ||
| 424 | + } | ||
| 414 | 425 | ||
| 415 | let suggestionPromise = getSuggestions(val.slice(0, 3), url); | 426 | let suggestionPromise = getSuggestions(val.slice(0, 3), url); |
| 416 | - suggestionPromise.then((suggestions) => { | 427 | + suggestionPromise.then(suggestions => { |
| 417 | if (val.length > 2) { | 428 | if (val.length > 2) { |
| 418 | - suggestions = suggestions.filter((item) => { | 429 | + suggestions = suggestions.filter(item => { |
| 419 | return item.toLowerCase().indexOf(val.toLowerCase()) !== -1; | 430 | return item.toLowerCase().indexOf(val.toLowerCase()) !== -1; |
| 420 | }).slice(0, 4); | 431 | }).slice(0, 4); |
| 421 | displaySuggestions($input, suggestions); | 432 | displaySuggestions($input, suggestions); |
| ... | @@ -448,15 +459,17 @@ module.exports = function (ngApp, events) { | ... | @@ -448,15 +459,17 @@ module.exports = function (ngApp, events) { |
| 448 | let newActive = (active === 0) ? suggestCount-1 : active - 1; | 459 | let newActive = (active === 0) ? suggestCount-1 : active - 1; |
| 449 | changeActiveTo(newActive, suggestionElems); | 460 | changeActiveTo(newActive, suggestionElems); |
| 450 | } | 461 | } |
| 451 | - // Enter key | 462 | + // Enter or tab key |
| 452 | - else if (event.keyCode === 13) { | 463 | + else if (event.keyCode === 13 || event.keyCode === 9) { |
| 453 | let text = suggestionElems[active].textContent; | 464 | let text = suggestionElems[active].textContent; |
| 454 | currentInput[0].value = text; | 465 | currentInput[0].value = text; |
| 455 | currentInput.focus(); | 466 | currentInput.focus(); |
| 456 | $suggestionBox.hide(); | 467 | $suggestionBox.hide(); |
| 457 | isShowing = false; | 468 | isShowing = false; |
| 458 | - event.preventDefault(); | 469 | + if (event.keyCode === 13) { |
| 459 | - return false; | 470 | + event.preventDefault(); |
| 471 | + return false; | ||
| 472 | + } | ||
| 460 | } | 473 | } |
| 461 | }); | 474 | }); |
| 462 | 475 | ||
| ... | @@ -523,7 +536,8 @@ module.exports = function (ngApp, events) { | ... | @@ -523,7 +536,8 @@ module.exports = function (ngApp, events) { |
| 523 | 536 | ||
| 524 | // Get suggestions & cache | 537 | // Get suggestions & cache |
| 525 | function getSuggestions(input, url) { | 538 | function getSuggestions(input, url) { |
| 526 | - let searchUrl = url + '?search=' + encodeURIComponent(input); | 539 | + let hasQuery = url.indexOf('?') !== -1; |
| 540 | + let searchUrl = url + (hasQuery?'&':'?') + 'search=' + encodeURIComponent(input); | ||
| 527 | 541 | ||
| 528 | // Get from local cache if exists | 542 | // Get from local cache if exists |
| 529 | if (localCache[searchUrl]) { | 543 | if (localCache[searchUrl]) { | ... | ... |
| ... | @@ -10,12 +10,12 @@ | ... | @@ -10,12 +10,12 @@ |
| 10 | <h4>Page Tags</h4> | 10 | <h4>Page Tags</h4> |
| 11 | <div class="padded tags"> | 11 | <div class="padded tags"> |
| 12 | <p class="muted small">Add some tags to better categorise your content. <br> You can assign a value to a tag for more in-depth organisation.</p> | 12 | <p class="muted small">Add some tags to better categorise your content. <br> You can assign a value to a tag for more in-depth organisation.</p> |
| 13 | - <table class="no-style" autosuggestions style="width: 100%;"> | 13 | + <table class="no-style" tag-autosuggestions style="width: 100%;"> |
| 14 | <tbody ui-sortable="sortOptions" ng-model="tags" > | 14 | <tbody ui-sortable="sortOptions" ng-model="tags" > |
| 15 | <tr ng-repeat="tag in tags track by $index"> | 15 | <tr ng-repeat="tag in tags track by $index"> |
| 16 | <td width="20" ><i class="handle zmdi zmdi-menu"></i></td> | 16 | <td width="20" ><i class="handle zmdi zmdi-menu"></i></td> |
| 17 | - <td><input autosuggest="/ajax/tags/suggest/names" class="outline" ng-attr-name="tags[@{{$index}}][name]" type="text" ng-model="tag.name" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag"></td> | 17 | + <td><input autosuggest="/ajax/tags/suggest/names" autosuggest-type="name" class="outline" ng-attr-name="tags[@{{$index}}][name]" type="text" ng-model="tag.name" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag"></td> |
| 18 | - <td><input autosuggest="/ajax/tags/suggest/values" class="outline" ng-attr-name="tags[@{{$index}}][value]" type="text" ng-model="tag.value" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag Value (Optional)"></td> | 18 | + <td><input autosuggest="/ajax/tags/suggest/values" autosuggest-type="value" class="outline" ng-attr-name="tags[@{{$index}}][value]" type="text" ng-model="tag.value" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag Value (Optional)"></td> |
| 19 | <td width="10" ng-show="tags.length != 1" class="text-center text-neg" style="padding: 0;" ng-click="removeTag(tag)"><i class="zmdi zmdi-close"></i></td> | 19 | <td width="10" ng-show="tags.length != 1" class="text-center text-neg" style="padding: 0;" ng-click="removeTag(tag)"><i class="zmdi zmdi-close"></i></td> |
| 20 | </tr> | 20 | </tr> |
| 21 | </tbody> | 21 | </tbody> | ... | ... |
-
Please register or sign in to post a comment