X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/4df32675217fc9f3a552ffa525995b6a32194e23..ab7f5def04a667ce4e6a6aff8b51d27b82550f42:/resources/assets/js/directives.js diff --git a/resources/assets/js/directives.js b/resources/assets/js/directives.js index 2a0547c97..08b82357f 100644 --- a/resources/assets/js/directives.js +++ b/resources/assets/js/directives.js @@ -1,119 +1,10 @@ "use strict"; -const DropZone = require("dropzone"); const MarkdownIt = require("markdown-it"); const mdTasksLists = require('markdown-it-task-lists'); const code = require('./code'); module.exports = function (ngApp, events) { - /** - * Common tab controls using simple jQuery functions. - */ - ngApp.directive('tabContainer', function() { - return { - restrict: 'A', - link: function (scope, element, attrs) { - const $content = element.find('[tab-content]'); - const $buttons = element.find('[tab-button]'); - - if (attrs.tabContainer) { - let initial = attrs.tabContainer; - $buttons.filter(`[tab-button="${initial}"]`).addClass('selected'); - $content.hide().filter(`[tab-content="${initial}"]`).show(); - } else { - $content.hide().first().show(); - $buttons.first().addClass('selected'); - } - - $buttons.click(function() { - let clickedTab = $(this); - $buttons.removeClass('selected'); - $content.hide(); - let name = clickedTab.addClass('selected').attr('tab-button'); - $content.filter(`[tab-content="${name}"]`).show(); - }); - } - }; - }); - - /** - * Sub form component to allow inner-form sections to act like their own forms. - */ - ngApp.directive('subForm', function() { - return { - restrict: 'A', - link: function (scope, element, attrs) { - element.on('keypress', e => { - if (e.keyCode === 13) { - submitEvent(e); - } - }); - - element.find('button[type="submit"]').click(submitEvent); - - function submitEvent(e) { - e.preventDefault(); - if (attrs.subForm) scope.$eval(attrs.subForm); - } - } - }; - }); - - /** - * DropZone - * Used for uploading images - */ - ngApp.directive('dropZone', [function () { - return { - restrict: 'E', - template: ` -
', '');}; + extraKeys[`${metaKey}-9`] = function(cm) {wrapSelection('
', '
');}; cm.setOption('extraKeys', extraKeys); // Update data on content change @@ -302,12 +196,13 @@ module.exports = function (ngApp, events) { } cm.replaceRange(newLineContent, {line: cursor.line, ch: 0}, {line: cursor.line, ch: lineLen}); - cm.setCursor({line: cursor.line, ch: cursor.ch + (newLineContent.length - lineLen)}); + cm.setCursor({line: cursor.line, ch: cursor.ch + start.length}); } function wrapSelection(start, end) { let selection = cm.getSelection(); if (selection === '') return wrapLine(start, end); + let newSelection = selection; let frontDiff = 0; let endDiff = 0; @@ -361,7 +256,7 @@ module.exports = function (ngApp, events) { // Show the popup link selector and insert a link when finished function showLinkSelector() { let cursorPos = cm.getCursor('from'); - window.showEntityLinkSelector(entity => { + window.EntitySelectorPopup.show(entity => { let selectedText = cm.getSelection() || entity.name; let newText = `[${selectedText}](${entity.link})`; cm.focus(); @@ -495,276 +390,4 @@ module.exports = function (ngApp, events) { } } }]); - - ngApp.directive('entityLinkSelector', [function($http) { - return { - restrict: 'A', - link: function(scope, element, attrs) { - - const selectButton = element.find('.entity-link-selector-confirm'); - let callback = false; - let entitySelection = null; - - // Handle entity selection change, Stores the selected entity locally - function entitySelectionChange(entity) { - entitySelection = entity; - if (entity === null) { - selectButton.attr('disabled', 'true'); - } else { - selectButton.removeAttr('disabled'); - } - } - events.listen('entity-select-change', entitySelectionChange); - - // Handle selection confirm button click - selectButton.click(event => { - hide(); - if (entitySelection !== null) callback(entitySelection); - }); - - // Show selector interface - function show() { - element.fadeIn(240); - } - - // Hide selector interface - function hide() { - element.fadeOut(240); - } - scope.hide = hide; - - // Listen to confirmation of entity selections (doubleclick) - events.listen('entity-select-confirm', entity => { - hide(); - callback(entity); - }); - - // Show entity selector, Accessible globally, and store the callback - window.showEntityLinkSelector = function(passedCallback) { - show(); - callback = passedCallback; - }; - - } - }; - }]); - - - 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(); - - // Detect double click events - let lastClick = 0; - function isDoubleClick() { - let now = Date.now(); - let answer = now - lastClick < 300; - lastClick = now; - return answer; - } - - // 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, isDoubleClick()); - }); - element.on('click', '[data-entity-type]', function(event) { - itemSelect($(this), isDoubleClick()); - }); - - // Select entity action - function itemSelect(item, doubleClick) { - let entityType = item.attr('data-entity-type'); - let entityId = item.attr('data-entity-id'); - let isSelected = !item.hasClass('selected') || doubleClick; - element.find('.selected').removeClass('selected').removeClass('primary-background'); - if (isSelected) item.addClass('selected').addClass('primary-background'); - let newVal = isSelected ? `${entityType}:${entityId}` : ''; - input.val(newVal); - - if (!isSelected) { - events.emit('entity-select-change', null); - } - - if (!doubleClick && !isSelected) return; - - let link = item.find('.entity-list-item-link').attr('href'); - let name = item.find('.entity-list-item-name').text(); - - if (doubleClick) { - events.emit('entity-select-confirm', { - id: Number(entityId), - name: name, - link: link - }); - } - - if (isSelected) { - events.emit('entity-select-change', { - id: Number(entityId), - name: name, - link: link - }); - } - } - - // Get search url with correct types - function getSearchUrl() { - let types = (attrs.entityTypes) ? encodeURIComponent(attrs.entityTypes) : encodeURIComponent('page,book,chapter'); - return window.baseUrl(`/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; - }); - }; - } - }; - }]); - - ngApp.directive('commentReply', [function () { - return { - restrict: 'E', - templateUrl: 'comment-reply.html', - scope: { - pageId: '=', - parentId: '=', - parent: '=' - }, - link: function (scope, element) { - scope.isReply = true; - element.find('textarea').focus(); - scope.$on('evt.comment-success', function (event) { - // no need for the event to do anything more. - event.stopPropagation(); - event.preventDefault(); - scope.closeBox(); - }); - - scope.closeBox = function () { - element.remove(); - scope.$destroy(); - }; - } - }; - }]); - - ngApp.directive('commentEdit', [function () { - return { - restrict: 'E', - templateUrl: 'comment-reply.html', - scope: { - comment: '=' - }, - link: function (scope, element) { - scope.isEdit = true; - element.find('textarea').focus(); - scope.$on('evt.comment-success', function (event, commentId) { - // no need for the event to do anything more. - event.stopPropagation(); - event.preventDefault(); - if (commentId === scope.comment.id && !scope.isNew) { - scope.closeBox(); - } - }); - - scope.closeBox = function () { - element.remove(); - scope.$destroy(); - }; - } - }; - }]); - - - ngApp.directive('commentReplyLink', ['$document', '$compile', function ($document, $compile) { - return { - scope: { - comment: '=' - }, - link: function (scope, element, attr) { - element.on('$destroy', function () { - element.off('click'); - scope.$destroy(); - }); - - element.on('click', function (e) { - e.preventDefault(); - var $container = element.parents('.comment-actions').first(); - if (!$container.length) { - console.error('commentReplyLink directive should be placed inside a container with class comment-box!'); - return; - } - if (attr.noCommentReplyDupe) { - removeDupe(); - } - - compileHtml($container, scope, attr.isReply === 'true'); - }); - } - }; - - function compileHtml($container, scope, isReply) { - let lnkFunc = null; - if (isReply) { - lnkFunc = $compile('