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