1<?php
2/**
3 * DokuWiki Plugin SketchCanvas (Action Component)
4 *
5 * @license ???
6 * @author  Masahiro Sakuta
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) die();
11
12require_once("CanvasElement.php");
13
14/**
15 * Add scripts via an event handler
16 */
17class action_plugin_sketchcanvas extends DokuWiki_Action_Plugin {
18
19    /**
20     * Register handler for the TPL_METAHEADER_OUTPUT event
21     */
22    public function register(Doku_Event_Handler $controller) {
23       $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaheader');
24
25       $controller->register_hook('HTML_SECEDIT_BUTTON', 'BEFORE', $this, 'editButton');
26       $controller->register_hook('HTML_EDIT_FORMSELECTION', 'BEFORE', $this, 'editForm');
27       // After Igor
28       $controller->register_hook('EDIT_FORM_ADDTEXTAREA', 'BEFORE', $this, 'editFormNew');
29       $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_newfigure');
30
31       $controller->register_hook('TOOLBAR_DEFINE', 'AFTER', $this, 'toolbarDefine');
32    }
33
34    /**
35     * Add <script> blocks to the headers
36     *
37     * Scripts are ought to be included via script.js on the plugin root directory, but
38     * it doesn't work if compress option (discarding whitespaces) is ative, so we have to
39     * include the necessary scripts individually in the header.
40     *
41     * @param Doku_Event $event
42     * @param            $param
43     */
44    public function metaheader(Doku_Event &$event, $param) {
45        $event->data['link'][] = array(
46            'type'   => 'text/css',
47            "rel" => "stylesheet",
48            "href" => (is_ssl() ? "https" : "http") . "://fonts.googleapis.com/earlyaccess/notosansjapanese.css",
49             );
50        $files = array('SketchCanvas.js', 'draw.js', /*'i18next-1.7.2.min.js', 'js-yaml.min.js',*/ 'translation.js');
51        foreach($files as $file)
52            $event->data['script'][] = array(
53                'type'    => 'text/javascript',
54                'charset' => 'utf-8',
55                'src'     => DOKU_BASE . 'lib/plugins/' . $this->getPluginName() . '/script/' . $file,
56                '_data'   => '',
57    	           );
58        $event->data['script'][] = array(
59            'type'    => 'text/javascript',
60            'charset' => 'utf-8',
61            '_data'   => <<<EOT
62document.addEventListener('DOMContentLoaded', function(){
63    var canvas;
64    for(var i = 1; (canvas = document.getElementById("__sketchcanvas" + i)); i++) {
65        var text = document.getElementById("__sketchcanvas_text" + i);
66        if(text) {
67            var skcanvas = new SketchCanvas(canvas);
68            skcanvas.loadData(text.innerHTML);
69            var form = document.forms['__sketchcanvas_form' + i];
70            if(form){
71                var input = document.createElement('input');
72                input.type = 'hidden';
73                input.name = "data";
74                input.value = text.innerHTML;
75                form.appendChild(input);
76            }
77        }
78    }
79});
80EOT
81               );
82    }
83
84    public function editButton(Doku_Event $event, $param){
85        if($event->data['target'] !== 'plugin_sketchcanvas')
86            return;
87
88        $event->data['name'] = /*$this->getLang*/('Edit Figure');
89    }
90
91    public function editForm(Doku_Event $event, $param){
92        global $TEXT;
93        if($event->data['target'] !== 'plugin_sketchcanvas')
94            return;
95        $event->preventDefault();
96
97        $event->data['media_manager'] = false;
98
99        $escText = '"' . str_replace(array("\r", "\n"), array('\r', '\n'), addslashes($TEXT)) . '"';
100
101        $form =& $event->data['form'];
102        $canvasText = <<<EOT
103<canvas id="editcanvas"></canvas>
104<script type="text/javascript"><!--
105var skcanvas;
106document.addEventListener('DOMContentLoaded', function(){
107    skcanvas = new SketchCanvas(document.getElementById('editcanvas'), {editmode: true});
108    skcanvas.loadData($escText);
109    skcanvas.onUpdateData = function(data){
110        var wikitext = document.getElementById('wiki__text');
111        wikitext.value = data;
112    }
113});
114--></script>
115<input type="button" value="Load data from text" onclick="skcanvas.loadData(document.getElementById('wiki__text').value)">
116<textarea name="wikitext" id="wiki__text" class="edit" cols="80" rows="10">$TEXT</textarea>
117EOT;
118        $form->addElement($canvasText);
119
120        // Pass wikitext through POSTs for previewing and saving
121        if(isset($_POST['editfigure__new'])) {
122            foreach($_POST['editfigure__new'] as $k => $v) {
123                $form->addHidden("editfigure__new[$k]", $v);
124            }
125        }
126    }
127
128    /**
129     * An event handler for newer versions of DokuWiki, starting from Igor.
130     *
131     * @param Doku_Event $event
132     */
133    public function editFormNew(Doku_Event $event, $param){
134        global $TEXT;
135        if($event->data['target'] !== 'plugin_sketchcanvas')
136            return;
137        $event->preventDefault();
138
139        $event->data['media_manager'] = false;
140
141        $form =& $event->data['form'];
142        $canvasElem = new CanvasElement();
143        $canvasElem->val($TEXT);
144        $form->addElement($canvasElem);
145
146        // Pass wikitext through POSTs for previewing and saving
147        if(isset($_POST['editfigure__new'])) {
148            foreach($_POST['editfigure__new'] as $k => $v) {
149                $form->addHidden("editfigure__new[$k]", $v);
150            }
151        }
152    }
153
154    /**
155     * Add a toolbar button to add a new figure
156     *
157     * @param Doku_Event $event
158     */
159    public function toolbarDefine(Doku_Event $event, $param){
160        $event->data[] = array(
161            'type' => 'NewFigure',
162            'title' => 'New Figure',
163            'icon' => '../../plugins/' . $this->getPluginName() . '/images/figure.png',
164            'block' => true);
165    }
166
167    /**
168     * Handle the click on the new figure button in the toolbar
169     *
170     * @param Doku_Event $event
171     */
172    function handle_newfigure($event) {
173        global $INPUT;
174        global $TEXT;
175        global $ACT;
176
177        if(!$INPUT->post->has('editfigure__new')) return;
178
179        /*
180         * $fields['pre']  has all data before the selection when the "Insert table" button was clicked
181         * $fields['text'] has all data inside the selection when the "Insert table" button was clicked
182         * $fields['suf']  has all data after the selection when the "Insert table" button was clicked
183         * $TEXT has the table created by the editor (from action_plugin_edittable_editor::handle_table_post())
184         */
185        $fields = $INPUT->post->arr('editfigure__new');
186
187        // clean the fields (undos formText()) and update the post and request arrays
188        $fields['pre'] = cleanText($fields['pre']);
189        $fields['text'] = cleanText($fields['text']);
190        $fields['suf'] = cleanText($fields['suf']);
191        $INPUT->post->set('editfigure__new', $fields);
192
193
194        $ACT = act_clean($ACT);
195        switch($ACT){
196            case 'preview':
197                // preview view of a table edit
198                $INPUT->post->set('target', 'plugin_sketchcanvas');
199                break;
200            case 'edit':
201                // edit view of a table (first edit)
202                $INPUT->post->set('target', 'plugin_sketchcanvas');
203                $TEXT = "";
204                $lines = explode("\n", $fields['text']);
205
206                // Delete opening and closing <skcanvas> tags from the input because they're not part of
207                // the figure source and the tags will be added on the save button anyway
208                if(preg_match('/^<skcanvas.*?>/', $lines[0]))
209                    array_shift($lines);
210                if(preg_match('/^<\/skcanvas>/', end($lines)))
211                    array_pop($lines);
212
213                foreach($lines as $line) {
214                    $TEXT .= "$line\n";
215                }
216                break;
217            case 'draftdel':
218                // not sure if/how this would happen, we restore all data and hand over to section edit
219                $INPUT->post->set('target', 'section');
220                $TEXT = $fields['pre'].$fields['text'].$fields['suf'];
221                $ACT  = 'edit';
222                break;
223            case 'save':
224                // return to edit page
225                $INPUT->post->set('target', 'section');
226                $TEXT = $fields['pre']."<skcanvas>\n".$TEXT."</skcanvas>".$fields['suf'];
227                $ACT  = 'edit';
228                break;
229        }
230    }
231}
232