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