bibcite_footnotes-8.x-1.0-beta3/js/bibciteFootnotes.js

js/bibciteFootnotes.js
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["CKEditor5"] = factory();
	else
		root["CKEditor5"] = root["CKEditor5"] || {}, root["CKEditor5"]["bibciteFootnotes"] = factory();
})(self, () => {
return /******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./js/ckeditor5_plugins/bibciteFootnotes/src/bibciteFootnotes.js":
/*!***********************************************************************!*\
  !*** ./js/ckeditor5_plugins/bibciteFootnotes/src/bibciteFootnotes.js ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ BibciteFootnotes)
/* harmony export */ });
/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");
/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ "ckeditor5/src/ui.js");
/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/widget */ "ckeditor5/src/widget.js");






class BibciteFootnotes extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {
  _currentElement = null;
  _references = [];

  static get requires() {
    return [ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ContextualBalloon, ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_2__.Widget];
  }

  init() {
    const editor = this.editor;
    const t = editor.t;

    this._balloon = editor.plugins.get(ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ContextualBalloon);

    // Initialize references immediately
    this._loadReferences();

    // Register the schema
    editor.model.schema.register('bibciteFootnote', {
      inheritAllFrom: '$inlineObject',
      allowAttributes: ['entityId', 'pageRange']
    });

    this._setupSimpleConversion();

    // Add Alt+C keyboard shortcut
    editor.keystrokes.set('Alt+C', (data, cancel) => {
      const selection = editor.model.document.selection;
      const selectedElement = selection.getSelectedElement();

      if (selectedElement && selectedElement.is('element', 'bibciteFootnote')) {
        this.showUI(selectedElement);
      } else {
        this.showUI();
      }

      cancel();
    });

    // UI component factory
    editor.ui.componentFactory.add('bibciteFootnotes', locale => {
      const button = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);

      button.set({
        label: t('Cite'),
        withText: true,
        tooltip: t('Insert citation (Alt+C)'),
      });

      button.on('execute', () => {
        this.showUI();
      });

      return button;
    });

    // Click and keyboard handlers
    this.listenTo(editor.editing.view.document, 'click', (evt, data) => {
      const modelElement = editor.editing.mapper.toModelElement(data.target);
      if (modelElement?.is('element', 'bibciteFootnote')) {
        this.showUI(modelElement);
      }
    });

    this.listenTo(editor.editing.view.document, 'keydown', (evt, data) => {
      const modelElement = editor.editing.mapper.toModelElement(data.target);
      if (modelElement?.is('element', 'bibciteFootnote')) {
        if (data.keyCode === 13 || data.keyCode === 32) {
          data.preventDefault();
          this.showUI(modelElement);
        }
      }
    });

    editor.accessibility.addKeystrokeInfos({
      keystrokes: [
        {
          label: t('Insert citation'),
          keystroke: "Alt+c",
        }
      ]
    });
  }

  _loadReferences() {
    try {
      this._references = window.parent.drupalSettings?.bibcite_footnotes?.references || [];
    } catch (e) {
      console.error('Could not access Drupal settings:', e);
    }
  }

  _setupSimpleConversion() {
    const editor = this.editor;

    const truncateText = (text, maxLength = 20) => {
      if (!text || text.length <= maxLength) return text;
      const commaIndex = text.substring(0, maxLength).lastIndexOf(',');
      if (commaIndex > 0 && commaIndex <= maxLength) {
        return text.substring(0, commaIndex) + '…';
      }
      const spaceIndex = text.substring(0, maxLength).lastIndexOf(' ');
      if (spaceIndex > 0 && spaceIndex <= maxLength) {
        return text.substring(0, spaceIndex) + '…';
      }
      return text.substring(0, maxLength - 1) + '…';
    };

    // Create a mapping of entity IDs to reference titles
    const referenceMap = {};
    this._references.forEach(ref => {
      referenceMap[ref[1]] = ref[0];
    });

    // Editing downcast
    editor.conversion.for('editingDowncast').elementToElement({
      model: 'bibciteFootnote',
      view: (modelElement, { writer }) => {
        const entityId = modelElement.getAttribute('entityId');
        const pageRange = modelElement.getAttribute('pageRange');
        const fullTitle = referenceMap[entityId] || `Citation ${entityId}`;
        const truncatedTitle = truncateText(fullTitle);
        const labelText = `Citation: ${fullTitle}${pageRange ? ', pages ' + pageRange : ''}`;
        const visibleText = pageRange ?
          `[${truncatedTitle}, pp. ${pageRange}]` :
          `[${truncatedTitle}]`;

        const span = writer.createContainerElement(
          'span',
          {
            class: 'bibcite-footnote-placeholder',
            role: 'button',
            'aria-haspopup': 'dialog',
            'aria-label': labelText,
            tabindex: '0'
          },
          writer.createText(visibleText)
        );

        return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_2__.toWidget)(span, writer, { label: labelText });
      }
    });

    // Data downcast for output
    editor.conversion.for('dataDowncast').elementToElement({
      model: 'bibciteFootnote',
      view: (modelElement, { writer }) => {
        const entityId = modelElement.getAttribute('entityId');
        const pageRange = modelElement.getAttribute('pageRange') || '';
        return writer.createContainerElement('bibcite-footnote', {
          'data-entity-id': entityId,
          'data-page-range': pageRange
        });
      }
    });

    // Upcast conversion
    editor.conversion.for('upcast').elementToElement({
      view: {
        name: 'bibcite-footnote',
        attributes: ['data-entity-id']
      },
      model: (viewElement, { writer }) => {
        return writer.createElement('bibciteFootnote', {
          entityId: viewElement.getAttribute('data-entity-id'),
          pageRange: viewElement.getAttribute('data-page-range') || ''
        });
      }
    });
  }

  _createFormView() {
    const editor = this.editor;
    const t = editor.t;
    const formView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.View(editor.locale);

    formView.saveButtonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(editor.locale);
    formView.saveButtonView.set({
      label: t('Save'),
      withText: true,
      class: 'ck-button-save'
    });

    formView.saveButtonView.on('execute', () => {
      this._handleFormSubmit();
    });

    formView.cancelButtonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(editor.locale);
    formView.cancelButtonView.set({
      label: t('Cancel'),
      withText: true,
      class: 'ck-button-cancel'
    });

    formView.cancelButtonView.on('execute', () => {
      this._hideUI();
    });

    // Create a simple template that we can update dynamically
    formView.setTemplate({
      tag: 'div',
      attributes: {
        class: ['ck', 'ck-bibcite-form'],
        tabindex: '-1',
      },
      children: [
        {
          tag: 'div',
          attributes: { class: ['ck', 'ck-bibcite-form__row'] },
          children: [
            {
              tag: 'label',
              attributes: { for: 'work-select', class: ['ck', 'ck-label'] },
              children: [t('Work to cite')]
            },
            {
              tag: 'select',
              attributes: {
                class: ['ck', 'ck-input', 'ck-bibcite-work-select'],
                id: 'work-select',
              },
              children: [] // Will be populated dynamically
            }
          ]
        },
        {
          tag: 'div',
          attributes: { class: ['ck', 'ck-bibcite-form__row'] },
          children: [
            {
              tag: 'label',
              attributes: { for: 'page-input', class: ['ck', 'ck-label'] },
              children: [t('Page(s)')]
            },
            {
              tag: 'input',
              attributes: {
                class: ['ck', 'ck-input', 'ck-bibcite-page-input'],
                type: 'text',
                id: 'page-input',
                placeholder: t('e.g., 42-45'),
              }
            }
          ]
        },
        {
          tag: 'div',
          attributes: { class: ['ck', 'ck-bibcite-form__actions'] },
          children: [
            formView.cancelButtonView,
            formView.saveButtonView
          ]
        }
      ]
    });

    // Add keydown event listener for Escape and Enter keys
    formView.on('render', () => {
      if (formView.element) {
        formView.element.addEventListener('keydown', (event) => {
          if (event.key === 'Escape') {
            event.preventDefault();
            event.stopPropagation();
            this._hideUI();
          } else if (event.key === 'Enter') {
            event.preventDefault();
            event.stopPropagation();
            this._handleFormSubmit();
          }
        });
      }
    });

    return formView;
  }

  _updateFormViewReferences() {
    if (!this.formView || !this.formView.element) {
      return;
    }

    const workSelect = this.formView.element.querySelector('.ck-bibcite-work-select');
    if (!workSelect) {
      return;
    }

    // Store current selection
    const currentSelection = workSelect.value;

    // Clear all options
    workSelect.innerHTML = '';

    // Add default option
    const defaultOption = document.createElement('option');
    defaultOption.value = '';
    defaultOption.textContent = this.editor.t('-- Select --');
    workSelect.appendChild(defaultOption);

    // Add current references
    this._references.forEach(ref => {
      const option = document.createElement('option');
      option.value = ref[1];
      option.textContent = ref[0];
      workSelect.appendChild(option);
    });

    // Restore selection if possible
    if (currentSelection && Array.from(workSelect.options).some(opt => opt.value === currentSelection)) {
      workSelect.value = currentSelection;
    } else if (this._currentElement) {
      const entityId = this._currentElement.getAttribute('entityId');
      if (entityId && Array.from(workSelect.options).some(opt => opt.value === entityId)) {
        workSelect.value = entityId;
      }
    }

    console.log('Dropdown updated with', this._references.length, 'references');
  }

  showUI(modelElement = null) {
    this._currentElement = modelElement;

    // Always reload references and update the form when showing UI
    this._loadReferences();

    // Create form view if it doesn't exist
    if (!this.formView) {
      this.formView = this._createFormView();
    }

    // Update the form view with current references
    if (!this._balloon.hasView(this.formView)) {
      this._balloon.add({
        view: this.formView,
        position: this._getBalloonPositionData()
      });

      // Wait for the form to render, then populate the dropdown
      setTimeout(() => {
        this._updateFormViewReferences();
        this._focusForm();
      }, 50);
    } else {
      // Form is already visible, just update it
      this._updateFormViewReferences();
      this._focusForm();
    }
  }

  _focusForm() {
    if (this.formView.element) {
      const workSelect = this.formView.element.querySelector('.ck-bibcite-work-select');
      const pageInput = this.formView.element.querySelector('.ck-bibcite-page-input');

      if (this._currentElement) {
        const entityId = this._currentElement.getAttribute('entityId');
        if (workSelect) {
          workSelect.value = entityId || '';
        }
        if (pageInput) {
          pageInput.value = this._currentElement.getAttribute('pageRange') || '';
        }
      } else {
        if (workSelect) {
          workSelect.selectedIndex = 0;
        }
        if (pageInput) {
          pageInput.value = '';
        }
      }

      if (workSelect) {
        workSelect.focus();
      }
    }
  }

  _handleFormSubmit() {
    const editor = this.editor;
    const formElement = this.formView.element;
    const workSelect = formElement.querySelector('.ck-bibcite-work-select');
    const pageInput = formElement.querySelector('.ck-bibcite-page-input');

    if (!workSelect) return;

    const entityId = workSelect.value;
    const pages = pageInput.value.trim();

    if (entityId) {
      editor.model.change(writer => {
        if (this._currentElement) {
          writer.setAttribute('entityId', entityId, this._currentElement);
          writer.setAttribute('pageRange', pages, this._currentElement);
        } else {
          const selection = editor.model.document.selection;
          const position = selection.getFirstRange().start;
          const citationElement = writer.createElement('bibciteFootnote', { entityId, pageRange: pages });
          writer.insert(citationElement, position);
        }
      });
    }

    this._hideUI();
  }

  _hideUI() {
    if (this.formView && this._balloon.hasView(this.formView)) {
      this._balloon.remove(this.formView);
    }
    this._currentElement = null;
    this.editor.editing.view.focus();
  }

  _getBalloonPositionData() {
    const view = this.editor.editing.view;
    const target = view.domConverter.viewRangeToDom(
      view.document.selection.getFirstRange()
    );
    return { target };
  }
}


/***/ }),

/***/ "ckeditor5/src/core.js":
/*!************************************************************!*\
  !*** delegated ./core.js from dll-reference CKEditor5.dll ***!
  \************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");

/***/ }),

/***/ "ckeditor5/src/ui.js":
/*!**********************************************************!*\
  !*** delegated ./ui.js from dll-reference CKEditor5.dll ***!
  \**********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");

/***/ }),

/***/ "ckeditor5/src/widget.js":
/*!**************************************************************!*\
  !*** delegated ./widget.js from dll-reference CKEditor5.dll ***!
  \**************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");

/***/ }),

/***/ "dll-reference CKEditor5.dll":
/*!********************************!*\
  !*** external "CKEditor5.dll" ***!
  \********************************/
/***/ ((module) => {

"use strict";
module.exports = CKEditor5.dll;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
(() => {
"use strict";
/*!************************************************************!*\
  !*** ./js/ckeditor5_plugins/bibciteFootnotes/src/index.js ***!
  \************************************************************/
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _bibciteFootnotes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./bibciteFootnotes */ "./js/ckeditor5_plugins/bibciteFootnotes/src/bibciteFootnotes.js");



/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
    BibciteFootnotes: _bibciteFootnotes__WEBPACK_IMPORTED_MODULE_0__["default"]
});

})();

__webpack_exports__ = __webpack_exports__["default"];
/******/ 	return __webpack_exports__;
/******/ })()
;
});
//# sourceMappingURL=bibciteFootnotes.js.map

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc