1<?php
2/*
3 * Plugin pgn4web: PGN Viewer pgn4web for dokuwiki
4 *
5 * @name       pgn4web Plugin
6 * @license    GPL 3 (http://www.gnu.org/licenses/gpl.html)
7 * @author     Michael Arlt <michael.arlt@sk-schwanstetten.de>
8 * @version    2018-05-12
9 *
10 * pgn4web.js changes: "=" -> "||" ; "+" -> "\u2192"
11 *
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 *
25*/
26
27if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
28if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
29require_once(DOKU_PLUGIN.'syntax.php');
30
31/**
32 * All DokuWiki plugins to extend the parser/rendering mechanism
33 * need to inherit from this class
34 */
35class syntax_plugin_pgn4web extends DokuWiki_Syntax_Plugin {
36
37    /**
38     * function constructor
39     */
40    function syntax_plugin_pgn4web(){
41      // enable direct access to language strings
42      $this->setupLocale();
43    }
44
45    /**
46     * return some info
47     */
48    function getInfo(){
49        return array(
50            'author' => 'Michael Arlt',
51            'email'  => 'michael.arlt@sk-schwanstetten.de',
52            'date'   => '2016-07-24',
53            'name'   => 'pgn4web Plugin',
54            'desc'   => $this->getLang('desc') ,
55            'license'=> 'GPL v3 (http://www.gnu.org/licenses/gpl.html)',
56            'url'    => 'http://wiki.splitbrain.org/plugin:pgn4web'
57        );
58    }
59
60    /**
61     * What kind of syntax are we?
62     */
63    function getType(){
64        return 'substition';
65    }
66
67    /**
68     * Where to sort in?
69     */
70    function getSort(){
71        return 38;
72    }
73
74    /**
75     * Connect pattern to lexer
76     */
77    function connectTo($mode) {
78        $this->Lexer->addSpecialPattern('<pgn>.+?</pgn>',$mode,'plugin_pgn4web');
79    }
80
81    /**
82     * Handle the match
83     */
84    function handle($match, $state, $pos, Doku_Handler $handler) {
85        $match=substr($match,6,-7);
86        return $match;
87    }
88
89    /**
90     * Create output
91     */
92    function render($mode, Doku_Renderer $renderer,$data)
93    {
94        if($mode == 'xhtml')
95        {
96            $shadow_size=20;
97
98            // defaults
99            $set = $this->getConf('set');
100            $setsizeportrait = $this->getConf('setsizeportrait');
101            $setsizelandscape = $this->getConf('setsizelandscape');
102            $pluginwidthportrait = $this->getConf('pluginwidthportrait');
103            $pluginwidthlandscape = $this->getConf('pluginwidthlandscape');
104            $font = $this->getConf('font');
105            $infowidth = $this->getConf('infowidth');
106            $textheight = $this->getConf('textheight');
107            $layout = $this->getConf('layout');
108            //error_log("set:$set setsizeportrait:$setsizeportrait font:$font");
109            $squaresizeportrait=intval($setsizeportrait/2);
110            $squaresizelandscape=intval($setsizelandscape/2);
111            $boardsizeportrait=8*($squaresizeportrait+12)+16;
112            $boardsizelandscape=8*($squaresizelandscape+12)+16;
113            if ($layout == "portrait") {
114              $boardsizelandscape = $boardsizeportrait;
115              $setsizelandscape = $setsizeportrait;
116              $pluginwidthlandscape = $pluginwidthportrait;
117            }
118            if ($layout == "landscape") {
119              $boardsizeportrait = $boardsizelandscape;
120              $setsizeportrait = $setsizelandscape;
121              $pluginwidthportrait = $pluginwidthlandscape;
122            }
123
124            $renderer->doc .= '
125<div id=\'pgn4web_fontcontainer\'>
126<style type="text/css">
127.move, .variation, .commentMove { font-family: "pgn4web ' . $font . '", "pgn4web Liberation Sans", sans-serif; }
128</style>
129</div>';
130
131            $renderer->doc .= '
132<style type="text/css">
133label.pgn4web { width:' . $infowidth . '; }
134
135@media all and (orientation:portrait) {
136  <!--  .pieceImage { width: ' . $setsizeportrait . 'px; height: ' . $setsizeportrait . 'px; } -->
137  .pieceImage { width: auto; height: auto; }
138  .whiteSquare, .blackSquare, .highlightWhiteSquare, .highlightBlackSquare {
139    width: ' . $squaresizeportrait . 'px !important;
140    height: ' . $squaresizeportrait . 'px !important;
141    border-style: solid; border-width: 2px;
142  }
143  #GameBoard, #boardTable { width: ' . $boardsizeportrait . 'px !important; height: ' . $boardsizeportrait . 'px !important; }
144  #boardTable { table-layout: fixed !important; }
145  #boardTable td { border: 0px; height: 12.5% !important; width: 12.5% !important; }
146  #GameButtons table {
147    width:100% !important;
148  }
149  #GameButtons td {
150    padding:0px !important;
151    width: 12.5% !important;
152  }
153  #GameButtons td input {
154    width:100% !important;
155  }
156  td.buttonControlSpace {
157    display: none;
158  }
159}
160@media not all and (orientation:portrait) {
161  <!-- .pieceImage { width: ' . $setsizelandscape . 'px; height: ' . $setsizelandscape . 'px; } -->
162  .pieceImage { width: auto; height: auto; }
163  .whiteSquare, .blackSquare, .highlightWhiteSquare, .highlightBlackSquare {
164    width: ' . $squaresizelandscape . 'px !important;
165    height: ' . $squaresizelandscape . 'px !important;
166    border-style: solid; border-width: 2px;
167  }
168  #GameBoard, #boardTable { width: ' . $boardsizelandscape . 'px !important; height: ' . $boardsizelandscape . 'px !important; }
169  #boardTable { table-layout: fixed !important; }
170  #boardTable td { border: 0px; height: 12.5% !important; width: 12.5% !important; }
171  #GameButtons table {
172    width:100% !important;
173  }
174  #GameButtons td {
175     padding:0px !important;
176     width: 12.5% !important;
177  }
178  #GameButtons td input {
179    width:100% !important;
180  }
181  td.buttonControlSpace {
182    display: none;
183  }
184}
185
186</style>';
187            // check set folder
188            // TODO!
189            if (! is_dir( DOKU_PLUGIN . "pgn4web/pgn4web/images/$relative_pieces_path")) {
190                $problem = true;
191                if (preg_match("/svg/",$set)) {
192                    $renderer->doc .= pgn4web_error(sprintf($this->getLang('err_font_dir'),$pieces_fs_path));
193                } else {
194                  if ($set >=0 && $set <= 6) { # set is valid -> err_size if folder not found
195                    $renderer->doc .= pgn4web_error(sprintf($this->getLang('err_size'),$setsizeportrait,$set+1));
196                  }
197                }
198            }
199            // check single pgn4web instance
200            if (defined('PGN4WEB')) {
201                $problem = true;
202                $renderer->doc .= pgn4web_info($this->getConf('err_instance'));
203                if (auth_quickaclcheck($ID) >= AUTH_EDIT) {
204                    $renderer->doc .= pgn4web_info($this->getConf('err_instance_author'));
205                }
206            } else {
207                define('PGN4WEB',true);
208            }
209            if ($problem) {
210              return true;
211            }
212
213            // ausgabe
214            $renderer->doc .= '<script src="' . DOKU_BASE . 'lib/plugins/pgn4web/pgn4web/pgn4web.js" type="text/javascript"></script>';
215            $renderer->doc .= '<form style="display: none;"><textarea style="display: none;" id="pgnText">';
216            $renderer->doc .= $data;
217            $renderer->doc .= '</textarea></form>';
218            $renderer->doc .= '
219<script type="text/javascript">
220
221  function autoScrollToCurrentMove(objId) {
222    if (!objId) { return; }
223    var theContainerObj = document.getElementById(objId);
224    if (theContainerObj) {
225      if (CurrentPly == StartPly) { theContainerObj.scrollTop = 0; }
226      else {
227        var theMoveObj = document.getElementById("Var" + CurrentVar + "Mv" + CurrentPly);
228        if (theMoveObj) {
229          var theContainerObjOffsetVeryTop = objOffsetVeryTop(theContainerObj);
230          var theMoveObjOffsetVeryTop = objOffsetVeryTop(theMoveObj);
231          theContainerObj.scrollTop = theMoveObjOffsetVeryTop - theContainerObjOffsetVeryTop;
232        }
233      }
234    }
235  }
236  "use strict";
237
238  var pgn4web_set = "' . $set . '".split(" ",1);
239  var pgn4web_setsizeportrait = "' . $setsizeportrait . '";
240  var pgn4web_setsizelandscape = "' . $setsizelandscape . '";
241  var pgn4web_font = "' . $font . '";
242  var pgn4web_infowidth = "' . $infowidth . '";
243  var pgn4web_textheight = "' . $textheight . '";
244  var pgn4web_layout = "' . $layout . '";
245  var pgn4web_squaresizeportrait = ' . $squaresizeportrait . ';
246  var pgn4web_squaresizelandscape = ' . $squaresizelandscape . ';
247  var pgn4web_boardsizeportrait = ' . $boardsizeportrait . ';
248  var pgn4web_boardsizelandscape = ' . $boardsizelandscape . ';
249  var pgn4web_pluginwidthlandscape = "' . $pluginwidthlandscape . '";
250  var pgn4web_pluginwidthportrait = "' . $pluginwidthportrait . '";
251
252  var pgn4web_textheightlandscape = pgn4web_boardsizelandscape + 28 + "px";
253  var pgn4web_textheightportrait = pgn4web_textheight;
254
255  function pgn4web_orientationdata() {
256    var w=window,d=document,e=d.documentElement,g=d.getElementsByTagName("body")[0],x=w.innerWidth||e.clientWidth||g.clientWidth,y=w.innerHeight||e.clientHeight||g.clientHeight;
257    if (pgn4web_layout == "portrait" || (y > x && pgn4web_layout == "auto")) {
258      return [pgn4web_boardsizeportrait + "px", pgn4web_pluginwidthportrait, pgn4web_setsizeportrait, pgn4web_textheightportrait];
259    } else {
260      return [pgn4web_boardsizelandscape + "px", pgn4web_pluginwidthlandscape, pgn4web_setsizelandscape, pgn4web_textheightlandscape];
261    }
262  }
263  pgn4web_od = pgn4web_orientationdata();
264  pgn4web_boardsize = pgn4web_od[0];
265  pgn4web_pluginwidth = pgn4web_od[1];
266  pgn4web_setsize = pgn4web_od[2];
267  pgn4web_activetextheight = pgn4web_od[3];
268
269  function pgn4web_getpiecepathandtype(set) {
270    var path = "' . DOKU_BASE . 'lib/plugins/pgn4web/pgn4web/images/" + set;
271    if (/svg/.test(set)) {
272      var type = "svg";
273    } else {
274      path += "/" + pgn4web_setsize;
275      var type = "png";
276    }
277    return [path,type];
278  }
279
280  function pgn4web_setchessset(index) {
281    if (index >= 0 && index < pgn4web_sets.length) {
282      var set = pgn4web_sets[index].split(" ",1);
283      var images = document.images;
284      var pgn4web_imagedata = pgn4web_getpiecepathandtype(set);
285      var path = pgn4web_imagedata[0];
286      var type = pgn4web_imagedata[1];
287      SetImagePath(path);
288      SetImageType(type);
289      InitImages();
290      for (var i=0; i<images.length; i++) {
291        if (images[i].className == "pieceImage") {
292          figure=images[i].src.match(/([^\/]+)(?=\.\w+$)/)[0];
293          images[i].src=path+"/"+figure+"."+type;
294        }
295      }
296    }
297  }
298  function pgn4web_setchessfont(index) {
299    if (index >= 0 && index < pgn4web_fonts.length) {
300      var showpgntextelement = document.getElementById("ShowPgnText").childNodes;
301      for (var i=0; i<showpgntextelement.length; i++) {
302        var classes = showpgntextelement[i].className.split(" ");
303        for (var j=0; j<classes.length; j++) {
304          if (classes[j] == "move" || classes[j] == "variation" || classes[j] == "commentMove") {
305            showpgntextelement[i].style.fontFamily = "\'pgn4web " + pgn4web_fonts[index] + "\', \'pgn4web Liberation Sans\', sans-serif";
306            break;
307          }
308        }
309      }
310    }
311  }
312
313
314  var board = "<div id=\'GameBoard\'></div><div id=\'GameButtons\'></div>";
315  var game_text = "<div id=\'GameText\' style=\'height:" + pgn4web_activetextheight + "; overflow-y:auto; resize:vertical; padding-right:1ex;\'></div>";
316
317  document.writeln("<div style=\'width:" + pgn4web_pluginwidth + ";\'>");
318  document.writeln("<form><fieldset class=\'pgn4web\' style=\'width:100%;\'><ul class=\'pgn4web\'>");
319
320  // select set
321  var pgn4web_sets  = new Array ("alpha","merida","uscf","igorsvg","svgchess","tilesvg");';
322
323if ($this->getConf('showsetselect')) {
324$renderer->doc .= '
325  document.writeln("<li class=\'pgn4web\'><label class=\'pgn4web\' for=\'pgn4web_set\'>' . $this->getLang('selectset') . '</label>");
326  document.writeln("<select name=\'pgn4web_set\' size=\'1\' onchange=\'pgn4web_setchessset(this.form.pgn4web_set.selectedIndex)\'>");
327  document.writeln("<optgroup label=\'png\'>");
328  for (var i=0; i<3; i++) {
329    if (pgn4web_sets[i] == pgn4web_set) {
330      document.writeln("<option selected>" + pgn4web_sets[i] + "</option>");
331    } else {
332      document.writeln("<option>" + pgn4web_sets[i] + "</option>");
333    }
334  }
335  document.writeln("</optgroup>");
336  document.writeln("<optgroup label=\'svg\'>");
337  for (var i=3; i<pgn4web_sets.length; i++) {
338    if (pgn4web_sets[i] == pgn4web_set) {
339      document.writeln("<option selected>" + pgn4web_sets[i] + "</option>");
340    } else {
341      document.writeln("<option>" + pgn4web_sets[i] + "</option>");
342    }
343  }
344  document.writeln("</optgroup>");
345  document.writeln("</select>");
346  document.writeln("</li>");';
347}
348
349$renderer->doc .= '
350  // select font
351  var pgn4web_fonts = new Array ("ChessSansAlpha","ChessSansMerida","ChessSansPiratf","ChessSansUscf","ChessSansUsual");
352';
353
354if ($this->getConf('showfontselect')) {
355$renderer->doc .= '
356  document.writeln("<li class=\'pgn4web\'><label class=\'pgn4web\' for=\'pgn4web_set\'>' . $this->getLang('selectfont') . '</label>");
357  document.writeln("<select name=\'pgn4web_font\' size=\'1\' onchange=\'pgn4web_setchessfont(this.form.pgn4web_font.selectedIndex)\'>");
358  for (var i=0; i<pgn4web_fonts.length; i++) {
359    if (pgn4web_fonts[i] == "' . $font . '") {
360      document.writeln("<option selected>" + pgn4web_fonts[i] + "</option>");
361    } else {
362      document.writeln("<option>" + pgn4web_fonts[i] + "</option>");
363    }
364  }
365  document.writeln("</select>");
366  document.writeln("</li>");';
367}
368
369$renderer->doc .= '
370  // game_info
371  document.writeln("<li class=\'pgn4web\'> <label class=\'pgn4web\' for=\'GameSelector\'>' . $this->getLang('GameSelector') . '</label> <span id=\'GameSelector\'></span> </li> <li class=\'pgn4web\'> <label class=\'pgn4web\' for=\'GameDate\'>' . $this->getLang('GameDate') . '</label> <span id=\'GameDate\'></span> </li> <li class=\'pgn4web\'> <label class=\'pgn4web\' for=\'GameSite\'>' . $this->getLang('GameSite') . '</label> <span id=\'GameSite\'></span> </li> <li class=\'pgn4web\'> <label class=\'pgn4web\' for=\'GameEvent\'>' . $this->getLang('GameEvent') . '</label> <span id=\'GameEvent\'></span> </li> <li class=\'pgn4web\'> <label class=\'pgn4web\' for=\'GameWhite\'>' . $this->getLang('GameWhite') . '</label> <span id=\'GameWhite\'></span> </li> <li class=\'pgn4web\'> <label class=\'pgn4web\' for=\'GameBlack\'>' . $this->getLang('GameBlack') . '</label> <span id=\'GameBlack\'></span> </li> <li class=\'pgn4web\'> <label class=\'pgn4web\' for=\'GameResult\'>' . $this->getLang('GameResult') . '</label> <span id=\'GameResult\'></span> </li>");
372
373  document.writeln("</ul></fieldset></form>");
374  document.writeln("<div id=\'pgn4web_container\'>");
375  document.writeln(" <div id=\'pgn4web_boarddiv\' style=\'float:left; padding-right:1ex;\'>" + board + "</div>");
376  document.writeln(" <div id=\'pgn4web_textdiv\' style=\'float:left; width:100%; \'>" + game_text + "</div>");
377  document.writeln(" <div style=\'clear:both\'></div>");
378  document.writeln("</div>");
379  document.writeln("</div>");
380
381  var pgn4web_imagedata = pgn4web_getpiecepathandtype(pgn4web_set);
382  SetImagePath(pgn4web_imagedata[0]);
383  SetImageType(pgn4web_imagedata[1]);
384  SetHighlightOption(true);
385  SetCommentsIntoMoveText(true);
386  SetCommentsOnSeparateLines(true);
387  SetAutoplayDelay(1000); // milliseconds
388  SetAutostartAutoplay(false);
389  SetAutoplayNextGame(false); // if set, move to the next game at the end of the current game during autoplay
390  SetInitialVariation(0); // number for the variation to be shown at load, 0 (default) for main variation
391  SetInitialHalfmove(0,false); // halfmove number to be shown at load, 0 (default) for start position; values (keep the quotes) of "start", "end", "random", "comment" (go to first comment or variation), "variation" (go to the first variation) are also accepted. Second parameter if true applies the setting to every selected game instead of startup only
392enableAutoScrollToCurrentMove("GameText");
393  window.addEventListener("resize", autoScrollToCurrentMoveIfEnabled);
394
395function orientationChange() {
396  pgn4web_od = pgn4web_orientationdata();
397  pgn4web_boardsize = pgn4web_od[0];
398  pgn4web_pluginwidth = pgn4web_od[1];
399  document.getElementById("pgn4web_textdiv").style.width="100%";
400  document.getElementById("GameText").style.height = pgn4web_activetextheight;
401  pgn4web_setsize = pgn4web_od[2];
402  pgn4web_activetextheight = pgn4web_od[3];
403  document.getElementById("pgn4web_boarddiv").style.width = pgn4web_boardsize;
404  document.getElementById("GameText").style.height = pgn4web_activetextheight;
405  remainingwidth=document.getElementById("pgn4web_container").clientWidth - document.getElementById("pgn4web_boarddiv").clientWidth;
406  if (remainingwidth > 80) {
407    document.getElementById("pgn4web_textdiv").style.width = remainingwidth - 4 + "px";
408  } else {
409    document.getElementById("pgn4web_textdiv").style.width = "100%";
410  }
411}
412
413window.addEventListener("resize", orientationChange);
414orientationChange();
415  </script>';
416
417
418            return true;
419        }
420        return false;
421    }
422}
423
424function pgn4web_info($text) {
425    return "<div class='info'>$text</div>";
426}
427function pgn4web_error($text) {
428    $problem = true;
429    return "<div class='error'>$text</div>";
430}
431
432//Setup VIM: ex: et ts=4 :
433