X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/5942d796b51ef9f565ebd88ebeabe40e1f078a47..refs/pull/154/head:/resources/assets/js/directives.js diff --git a/resources/assets/js/directives.js b/resources/assets/js/directives.js index 43d55f092..e50f5c6dd 100644 --- a/resources/assets/js/directives.js +++ b/resources/assets/js/directives.js @@ -149,14 +149,30 @@ module.exports = function (ngApp, events) { }; }]); - + /** + * Dropdown + * Provides some simple logic to create small dropdown menus + */ ngApp.directive('dropdown', [function () { return { restrict: 'A', link: function (scope, element, attrs) { - var menu = element.find('ul'); + const menu = element.find('ul'); element.find('[dropdown-toggle]').on('click', function () { menu.show().addClass('anim menuIn'); + let inputs = menu.find('input'); + let hasInput = inputs.length > 0; + if (hasInput) { + inputs.first().focus(); + element.on('keypress', 'input', event => { + if (event.keyCode === 13) { + event.preventDefault(); + menu.hide(); + menu.removeClass('anim menuIn'); + return false; + } + }); + } element.mouseleave(function () { menu.hide(); menu.removeClass('anim menuIn'); @@ -166,6 +182,10 @@ module.exports = function (ngApp, events) { }; }]); + /** + * TinyMCE + * An angular wrapper around the tinyMCE editor. + */ ngApp.directive('tinymce', ['$timeout', function ($timeout) { return { restrict: 'A', @@ -231,6 +251,10 @@ module.exports = function (ngApp, events) { } }]); + /** + * Markdown input + * Handles the logic for just the editor input field. + */ ngApp.directive('markdownInput', ['$timeout', function ($timeout) { return { restrict: 'A', @@ -263,6 +287,10 @@ module.exports = function (ngApp, events) { } }]); + /** + * Markdown Editor + * Handles all functionality of the markdown editor. + */ ngApp.directive('markdownEditor', ['$timeout', function ($timeout) { return { restrict: 'A', @@ -342,6 +370,11 @@ module.exports = function (ngApp, events) { } }]); + /** + * Page Editor Toolbox + * Controls all functionality for the sliding toolbox + * on the page edit view. + */ ngApp.directive('toolbox', [function () { return { restrict: 'A', @@ -378,6 +411,11 @@ module.exports = function (ngApp, events) { } }]); + /** + * Tag Autosuggestions + * Listens to child inputs and provides autosuggestions depending on field type + * and input. Suggestions provided by server. + */ ngApp.directive('tagAutosuggestions', ['$http', function ($http) { return { restrict: 'A', @@ -460,7 +498,7 @@ module.exports = function (ngApp, events) { changeActiveTo(newActive, suggestionElems); } // Enter or tab key - else if (event.keyCode === 13 || event.keyCode === 9) { + else if ((event.keyCode === 13 || event.keyCode === 9) && !event.shiftKey) { let text = suggestionElems[active].textContent; currentInput[0].value = text; currentInput.focus(); @@ -557,6 +595,67 @@ module.exports = function (ngApp, events) { } } }]); + + + ngApp.directive('entitySelector', ['$http', '$sce', function ($http, $sce) { + return { + restrict: 'A', + scope: true, + link: function (scope, element, attrs) { + scope.loading = true; + scope.entityResults = false; + scope.search = ''; + + // Add input for forms + const input = element.find('[entity-selector-input]').first(); + + // Listen to entity item clicks + element.on('click', '.entity-list a', function(event) { + event.preventDefault(); + event.stopPropagation(); + let item = $(this).closest('[data-entity-type]'); + itemSelect(item); + }); + element.on('click', '[data-entity-type]', function(event) { + itemSelect($(this)); + }); + + // Select entity action + function itemSelect(item) { + let entityType = item.attr('data-entity-type'); + let entityId = item.attr('data-entity-id'); + let isSelected = !item.hasClass('selected'); + element.find('.selected').removeClass('selected').removeClass('primary-background'); + if (isSelected) item.addClass('selected').addClass('primary-background'); + let newVal = isSelected ? `${entityType}:${entityId}` : ''; + input.val(newVal); + } + + // Get search url with correct types + function getSearchUrl() { + let types = (attrs.entityTypes) ? encodeURIComponent(attrs.entityTypes) : encodeURIComponent('page,book,chapter'); + return `/ajax/search/entities?types=${types}`; + } + + // Get initial contents + $http.get(getSearchUrl()).then(resp => { + scope.entityResults = $sce.trustAsHtml(resp.data); + scope.loading = false; + }); + + // Search when typing + scope.searchEntities = function() { + scope.loading = true; + input.val(''); + let url = getSearchUrl() + '&term=' + encodeURIComponent(scope.search); + $http.get(url).then(resp => { + scope.entityResults = $sce.trustAsHtml(resp.data); + scope.loading = false; + }); + }; + } + }; + }]); };