+ // 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();
+ }
+ });