1<?php 2 3 4use ComboStrap\Bootstrap; 5use ComboStrap\Site; 6use ComboStrap\SnippetManager; 7use ComboStrap\PluginUtility; 8use ComboStrap\Tag; 9 10if (!defined('DOKU_INC')) die(); 11 12/** 13 * Class syntax_plugin_combo_tooltip 14 * Implementation of a tooltip 15 */ 16class syntax_plugin_combo_tooltip extends DokuWiki_Syntax_Plugin 17{ 18 19 const TAG = "tooltip"; 20 const TEXT_ATTRIBUTE = "text"; 21 const POSITION_ATTRIBUTE = "position"; 22 23 24 /** 25 * tooltip is used also in page protection 26 */ 27 public static function addToolTipSnippetIfNeeded() 28 { 29 $namespace = Bootstrap::getDataNamespace(); 30 $script = "window.addEventListener('load', function () { jQuery('[data{$namespace}-toggle=\"tooltip\"]').tooltip() })"; 31 PluginUtility::getSnippetManager()->upsertJavascriptForBar(self::TAG, $script); 32 } 33 34 35 /** 36 * Syntax Type. 37 * 38 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 39 * @see https://www.dokuwiki.org/devel:syntax_plugins#syntax_types 40 * @see DokuWiki_Syntax_Plugin::getType() 41 */ 42 function getType() 43 { 44 return 'container'; 45 } 46 47 /** 48 * How Dokuwiki will add P element 49 * 50 * * 'normal' - The plugin can be used inside paragraphs (inline) 51 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 52 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 53 * 54 * @see DokuWiki_Syntax_Plugin::getPType() 55 * @see https://www.dokuwiki.org/devel:syntax_plugins#ptype 56 */ 57 function getPType() 58 { 59 return 'normal'; 60 } 61 62 /** 63 * @return array 64 * Allow which kind of plugin inside 65 * 66 * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 67 * because we manage self the content and we call self the parser 68 * 69 * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 70 */ 71 function getAllowedTypes() 72 { 73 return array('baseonly', 'container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 74 } 75 76 function getSort() 77 { 78 return 201; 79 } 80 81 82 function connectTo($mode) 83 { 84 85 $pattern = PluginUtility::getContainerTagPattern(self::TAG); 86 $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeForComponent($this->getPluginComponent())); 87 88 } 89 90 function postConnect() 91 { 92 93 $this->Lexer->addExitPattern('</' . self::TAG . '>', PluginUtility::getModeForComponent($this->getPluginComponent())); 94 95 } 96 97 /** 98 * 99 * The handle function goal is to parse the matched syntax through the pattern function 100 * and to return the result for use in the renderer 101 * This result is always cached until the page is modified. 102 * @param string $match 103 * @param int $state 104 * @param int $pos - byte position in the original source file 105 * @param Doku_Handler $handler 106 * @return array|bool 107 * @see DokuWiki_Syntax_Plugin::handle() 108 * 109 */ 110 function handle($match, $state, $pos, Doku_Handler $handler) 111 { 112 113 switch ($state) { 114 115 case DOKU_LEXER_ENTER : 116 $attributes = PluginUtility::getTagAttributes($match); 117 118 return array( 119 PluginUtility::STATE => $state, 120 PluginUtility::ATTRIBUTES => $attributes 121 ); 122 123 case DOKU_LEXER_UNMATCHED : 124 return PluginUtility::handleAndReturnUnmatchedData(self::TAG,$match,$handler); 125 126 case DOKU_LEXER_EXIT : 127 128 $tag = new Tag(self::TAG, array(), $state, $handler); 129 130 return array( 131 PluginUtility::STATE => $state, 132 PluginUtility::ATTRIBUTES => $tag->getOpeningTag()->getAttributes() 133 ); 134 135 136 } 137 return array(); 138 139 } 140 141 /** 142 * Render the output 143 * @param string $format 144 * @param Doku_Renderer $renderer 145 * @param array $data - what the function handle() return'ed 146 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 147 * @see DokuWiki_Syntax_Plugin::render() 148 * 149 * 150 */ 151 function render($format, Doku_Renderer $renderer, $data) 152 { 153 if ($format == 'xhtml') { 154 155 /** @var Doku_Renderer_xhtml $renderer */ 156 $state = $data[PluginUtility::STATE]; 157 switch ($state) { 158 159 case DOKU_LEXER_UNMATCHED: 160 $renderer->doc .= PluginUtility::renderUnmatched($data); 161 break; 162 case DOKU_LEXER_ENTER : 163 $attributes = $data[PluginUtility::ATTRIBUTES]; 164 165 if (isset($attributes[self::TEXT_ATTRIBUTE])) { 166 $position = "top"; 167 if (isset($attributes[self::POSITION_ATTRIBUTE])) { 168 $position = $attributes[self::POSITION_ATTRIBUTE]; 169 } 170 171 $dataAttributeNamespace = Bootstrap::getDataNamespace(); 172 $renderer->doc .= "<span class=\"d-inline-block\" tabindex=\"0\" data{$dataAttributeNamespace}-toggle=\"tooltip\" data{$dataAttributeNamespace}-placement=\"${position}\" title=\"" . $attributes[self::TEXT_ATTRIBUTE] . "\">" . DOKU_LF; 173 }; 174 175 break; 176 177 case DOKU_LEXER_EXIT: 178 if (isset($data[PluginUtility::ATTRIBUTES][self::TEXT_ATTRIBUTE])) { 179 180 $text = $data[PluginUtility::ATTRIBUTES][self::TEXT_ATTRIBUTE]; 181 if (!empty($text)) { 182 $renderer->doc .= "</span>"; 183 self::addToolTipSnippetIfNeeded(); 184 } 185 186 } 187 break; 188 189 190 } 191 return true; 192 } 193 194 // unsupported $mode 195 return false; 196 } 197 198 199} 200 201