1/*  DokuWiki MoaiEditor Default.js file
2    Version : 0.5 (May 5, 2026)
3    Author  : MoaiTools <info@moaitools.org>
4    License : GPL 3 (http://www.gnu.org/licenses/gpl.html) */
5
6/*  Template class
7    ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
8    This is the class for handling templates. It serves 2 purposes:
9
10      1. Add a button to the edit page of Dokuwiki in order to start the editor.
11      2. Find all the necessary elements in the page needed by the editor
12         (e.g. textarea, toolbar, save and cancel buttons, etc).
13
14    If you are using a template that has the HTML elements in different locations
15    in the DOM tree or they have different ids, the elements might not be found
16    by this class, and in that case you can create a new class that overrides
17    specific methods in order to support you template.
18
19    Also you can override the method that positions the toggle button that
20    starts MoaiEditor, to put it anywhere you want in the page.
21
22    See 'templates/sprintdoc.js' for an example of such a class.
23
24    If you want to style MoaiEditor according to specific needs of your template,
25    you can add a CSS file with the same name of your template file in this folder.
26
27    See 'templates/sprintdoc.css' for an example of such a css file.
28
29    See 'README' to learn how to support a new template.
30*/
31MoaiEditor.Template = class {
32
33    constructor(name) {
34
35        // Template name for console messages
36        this.name = name;
37        this.prefix = "moaiEditor templates/"+name+".js :: ";
38        this.suffix = ".\nThis is usually due to an incompatibility with your template, which is easy to fix.\nSee the README file in lib/plugins/moaieditor/ for instructions on how to make your template compatible with this editor.\nMoaiEditor will not run until this problem is resolved.";
39
40        // Flag to inform others that all HTML elements have been found and the editor toggle button has been added
41        this.ready = false;
42
43        // Methods for finding each element we need for the editor
44        this.finders = {
45            hide        : this.find_ElementsToHide,
46            messages    : this.find_Messages,
47            toolbar     : this.find_Toolbar,
48            editSummary : this.find_EditSummary,
49            editForm    : this.find_EditForm,
50            editBar     : this.find_EditBar,
51            textarea    : this.find_Textarea,
52            editButtons : this.find_EditButtons,
53            //pagetools   : this.find_Pagetools,
54        };
55        // Handles of each element found (to be used later)
56        this.elements = {};
57    }
58    // ────────────────────────────────────
59    detectTemplate() {
60        return true;
61    }
62    // ────────────────────────────────────
63    findElements() {
64        this.counter = -1;
65        this.interval = setInterval(this.onInterval.bind(this), 150);
66    }
67    // ────────────────────────────────────
68    onInterval() {
69        var element;
70        this.counter += 1;
71        var not_found = [];
72        for (let name in this.finders) {
73            try {
74                element = this.finders[name].bind(this)();
75            } catch(error) {
76                this.warn("The following problem occured while trying to find the '"+name+"' element(s):\n   >> "+error+this.suffix);
77                moaiEditor.enabled.value = 'off';
78                clearInterval(this.interval);
79                return;
80            }
81            if (element === undefined  ||  element === null)
82                not_found.push(name);
83            this.elements[name] = element;
84        }
85        // Show retries
86        if (this.counter > 0)
87            this.log("Finding html elements - retry #"+this.counter+" - Missing: "+JSON.stringify(not_found));
88
89        // Timeout
90        if (this.counter >= 50) {
91            this.warn("Failed to find all HTMl elements - Missing: "+JSON.stringify(not_found)+this.suffix);
92            clearInterval(this.interval);
93                return;
94        }
95        // Success
96        if (not_found.length == 0) {
97            this.log("All elements found");
98            clearInterval(this.interval);
99            this.addStartButton.bind(this)();
100            this.ready = true;
101            // Start the editor automatically if it is enabled
102            if (moaiEditor.enabled.value == 'on')
103                moaiEditor.startEditor();
104        }
105    }
106    // ────────────────────────────────────
107    log (message) {
108    }
109    warn (message) {
110        console.warn (this.prefix + message);
111    }
112    // ╭─────────────────────────────────────────────╮
113    // ╰─────────────────────────────────────────────╯
114    addStartButton() {
115        // Option 1: Add a proper button
116        this.elements.editButtons.appendChild(moaiEditor.start.button);
117        // Option 2: Add a small image (to blend well in the size control buttons area of the DokuWiki native editor)
118        //document.body.querySelector("#size__ctl").appendChild(moaiEditor.start.png);
119    }
120    find_ElementsToHide() {
121        // Find the elements which contain the old editor in order to be hidden.
122        // This method can return a single element or an array of elements.
123        return document.body.querySelector("#dokuwiki__site");
124    }
125    find_Messages() {
126        // Find the displayed messages (info, error, success, notify) usually rendered by inc/html.php -> html_msgarea().
127        // Some templates like bootstrap3 implement their own message rendering function and don't use html_msgarea().
128        // In order to check how (and if) your template's messages are being displayed in this editor, you can simulate
129        // fake messages by either:
130        //    a) Adding '&fakemsg' to the browser's URL while in edit mode.
131        //    b) Set the MOAIED_FAKE_MESSAGES constant to true in: lib/plugins/moaieditor/action.php
132        var query = "";
133        var container = "#dokuwiki__content div.pad.group ";
134        query += container + "div.error,   ";
135        query += container + "div.info,    ";
136        query += container + "div.success, ";
137        query += container + "div.notify   ";
138        var messages = document.body.querySelectorAll(query);
139        return messages;
140    }
141    find_Pagetools() {
142        // Find the page-tools (the right-side vertical tool bar).
143        // We are not showing it now, but someone might need it in the future.
144        return document.body.querySelector("#dokuwiki__pagetools");
145    }
146    find_Toolbar() {
147        // Find the toolbar (which holds the buttons above the textarea: bold, italics, underline, etc)
148        return document.body.querySelector("#tool__bar");
149    }
150    find_EditForm() {
151        // Find the HTML form (which sends the changes back to the server)
152        return document.body.querySelector("#dw__editform");
153    }
154    find_EditBar() {
155        // Find the container for the form buttons (save, preview, cancel) and size control buttons
156        return document.body.querySelector("#wiki__editbar");
157    }
158    find_Textarea() {
159        // Find the textarea (where you edit the document)
160        return document.body.querySelector("#wiki__text");
161    }
162    find_EditButtons() {
163        // Find the edit-buttons container (so we can insert the moaiEditor toggle button here)
164        return document.body.querySelector("#wiki__editbar .editButtons");
165    }
166    find_EditSummary() {
167        // Find the container for the edit summary input fields (text input and checkbox)
168        return document.body.querySelector("#wiki__editbar .summary");
169    }
170}; // End Class
171
172
173
174