1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8function wikiplugin_mouseover_info()
9{
10	global $prefs;
11	include_once('lib/prefs/jquery.php');
12	$jqprefs = prefs_jquery_list();
13	$jqfx = [];
14	foreach ($jqprefs['jquery_effect']['options'] as $k => $v) {
15		$jqfx[] = ['text' => $v, 'value' => $k];
16	}
17
18
19	return [
20		'name' => tra('Mouseover'),
21		'documentation' => 'PluginMouseover',
22		'description' => tra('Display hidden content by mousing over text'),
23		'prefs' => [ 'wikiplugin_mouseover' ],
24		'body' => tra('Hidden content, unless the label parameter is undefined, in which case this is the label.'),
25		'iconname' => 'comment',
26		'introduced' => 3,
27		'tags' => [ 'basic' ],
28		'params' => [
29			'label' => [
30				'required' => true,
31				'name' => tra('Label'),
32				'description' => tra('Text displayed on the page. The body is the hidden content.'),
33				'since' => '3.0',
34				'filter' => 'text',
35				'default' => '',
36			],
37			'url' => [
38				'required' => false,
39				'name' => tra('URL'),
40				'description' => tra('Destination link when mouseover text is clicked. Use http:// for external links'),
41				'since' => '3.0',
42				'filter' => 'url',
43				'default' => 'javascript:void(0)',
44			],
45			'text' => [
46				'required' => false,
47				'name' => tra('Text'),
48				'description' => tra('DEPRECATED') . ' ' . tra('Hidden content. The body contains the label.'),
49				'since' => '3.0',
50				'filter' => 'text',
51				'default' => '',
52				'advanced' => true,
53			],
54			'width' => [
55				'required' => false,
56				'name' => tra('Width'),
57				'description' => tr('Mouseover box width. Default: %0400px%1', '<code>', '</code>'),
58				'since' => '3.0',
59				'filter' => 'digits',
60				'default' => 400,
61				'advanced' => true,
62			],
63			'height' => [
64				'required' => false,
65				'name' => tra('Height'),
66				'description' => tr('Mouseover box height. Default: %0200px%1', '<code>', '</code>'),
67				'since' => '3.0',
68				'filter' => 'digits',
69				'default' => 200,
70				'advanced' => true,
71			],
72			'offsetx' => [
73				'required' => false,
74				'name' => tra('Offset X'),
75				'description' => tr('Shifts the overlay to the right by the specified number of pixels relative to
76					the cursor. Default: %05%1', '<code>', '</code>'),
77				'since' => '3.0',
78				'filter' => 'int',
79				'default' => 5,
80				'advanced' => true,
81			],
82			'offsety' => [
83				'required' => false,
84				'name' => tra('Offset Y'),
85				'description' => tr('Shifts the overlay lower by the specified number of pixels relative to the
86					cursor. Default: %00%1', '<code>', '</code>'),
87				'since' => '3.0',
88				'filter' => 'int',
89				'default' => 24,
90				'advanced' => true,
91			],
92			'parse' => [
93				'required' => false,
94				'name' => tra('Parse Body'),
95				'description' => tra('Parse the body of the plugin as wiki content (parsed by default)'),
96				'since' => '3.0',
97				'filter' => 'alpha',
98				'advanced' => true,
99				'default' => 'y',
100				'options' => [
101					['text' => '', 'value' => ''],
102					['text' => tra('Yes'), 'value' => 'y'],
103					['text' => tra('No'), 'value' => 'n']
104				]
105			],
106			'parselabel' => [
107				'required' => false,
108				'name' => tra('Parse Label'),
109				'description' => tra('Parse the label as wiki content (parsed by default)'),
110				'since' => '5.0',
111				'filter' => 'alpha',
112				'default' => 'y',
113				'advanced' => true,
114				'options' => [
115					['text' => '', 'value' => ''],
116					['text' => tra('Yes'), 'value' => 'y'],
117					['text' => tra('No'), 'value' => 'n']
118				]
119			],
120			'class' => [
121				'required' => false,
122				'name' => tra('CSS Class'),
123				'description' => tra('CSS class to apply'),
124				'since' => '4.0',
125				'filter' => 'text',
126				'default' => 'plugin-mouseover',
127				'advanced' => true,
128			],
129			'bgcolor' => [
130				'required' => false,
131				'name' => tra('Background Color'),
132				'description' => tra('Background color to apply to the popup'),
133				'since' => '3.0',
134				'filter' => 'text',
135				'default' => '',
136				'advanced' => true,
137			],
138			'textcolor' => [
139				'required' => false,
140				'name' => tra('Text Color'),
141				'description' => tra('Color to apply to the text in the popup'),
142				'since' => '3.0',
143				'filter' => 'text',
144				'default' => '',
145				'advanced' => true,
146			],
147			'sticky' => [
148				'required' => false,
149				'name' => tra('Sticky'),
150				'description' => tra('When enabled, popup stays visible until it is clicked.'),
151				'since' => '3.0',
152				'filter' => 'alpha',
153				'default' => '',
154				'options' => [
155					['text' => '', 'value' => ''],
156					['text' => tra('Yes'), 'value' => 'y'],
157					['text' => tra('No'), 'value' => 'n']
158				],
159				'advanced' => true,
160			],
161			'padding' => [
162				'required' => false,
163				'name' => tra('Padding'),
164				'description' => tra('Padding size in pixels'),
165				'since' => '3.0',
166				'filter' => 'digits',
167				'default' => '',
168				'advanced' => true,
169			],
170			'effect' => [
171				'required' => false,
172				'name' => tra('Effect'),
173				'options' => $jqfx,
174				'description' => tra('Set the type of show/hide animation that will be used'),
175				'since' => '4.0',
176				'filter' => 'text',
177				'advanced' => true,
178			],
179			'speed' => [
180				'required' => false,
181				'name' => tra('Effect Speed'),
182				'options' => [
183					['text' => tra('Normal'), 'value' => ''],
184					['text' => tra('Fast'), 'value' => 'fast'],
185					['text' => tra('Slow'), 'value' => 'slow'],
186				],
187				'description' => tra('Set the speed of the animation.'),
188				'since' => '4.0',
189				'filter' => 'alpha',
190				'default' => '',
191				'advanced' => true,
192			],
193			'closeDelay' => [
194				'required' => false,
195				'name' => tra('Close Delay'),
196				'description' => tra('Number of seconds before popup closes'),
197				'since' => '5.0',
198				'filter' => 'digits',
199				'default' => 0,
200				'advanced' => true,
201			],
202			'tag' => [
203				'required' => false,
204				'name' => tra('Tag'),
205				'description' => tr('HTML tag to use for the label. Default %0a%1', '<code>', '</code>'),
206				'since' => '9.2',
207				'filter' => 'word',
208				'default' => 'a',
209				'advanced' => true,
210			],
211		],
212	];
213}
214
215function wikiplugin_mouseover($data, $params)
216{
217	$default = ['parse' => 'y', 'parselabel' => 'y'];
218	$params = array_merge($default, $params);
219
220	$width = isset($params['width']) ? (int) $params['width'] : 400;
221	$height = isset($params['height']) ? (int) $params['height'] : 200;
222	$offsetx = isset($params['offsetx']) ? (int) $params['offsetx'] : 5;
223	$offsety = isset($params['offsety']) ? (int) $params['offsety'] : 24;
224	$parse = ! isset($params['parse']) || (strcasecmp($params['parse'], 'n') != 0);
225	$sticky = isset($params['sticky']) && $params['sticky'] == 'y';
226	$padding = isset($params['padding']) ? 'padding: ' . $params['padding'] . 'px;' : '';
227	$effect = ! isset($params['effect']) || $params['effect'] == 'Default' ? '' : strtolower($params['effect']);
228	$speed = ! isset($params['speed']) ? 'normal' : strtolower($params['speed']);
229	$closeDelay = isset($params['closeDelay']) ? (int) $params['closeDelay'] : 0;
230	$tag = ! empty($params['tag']) ? $params['tag'] : 'a';
231
232	if (empty($params['label']) && empty($params['text'])) {
233		$label = tra('No label specified');
234	} else {
235		$label = ! empty($params['label']) ? $params['label'] : $data;
236		$text = ! empty($params['text']) ? $params['text'] : $data;
237	}
238
239	$url = '';
240	if (isset($params['url'])) {
241		$url = $params['url'];
242		$url = htmlentities($url, ENT_QUOTES, 'UTF-8');
243	}
244
245	$text = trim($text);
246
247	if (empty($text)) {
248		if ($params['parselabel'] == 'y') {
249			return $label;
250		} else {
251			return "~np~$label~/np~";
252		}
253	}
254
255	if ($parse) {
256		$options = ['is_html' => 0];
257		if (containsStringHTML($text)) {
258			$options = ['is_html' => 1];
259		}
260		$text = TikiLib::lib('parser')->parse_data($text, $options);
261	}
262	if ($params['parselabel'] == 'y') {
263		$label = "~/np~$label~np~";
264	}
265
266	static $lastval = 0;
267	$id = "mo" . ++$lastval;
268
269	$headerlib = TikiLib::lib('header');
270	$headerlib->add_css('.plugin-mouseover-anchor:not([href]) { border-bottom: 1px dotted; color: inherit; cursor: help; text-decoration: none; }');
271
272	if ($closeDelay && $sticky) {
273		$closeDelayStr = "setTimeout(function() {hideJQ('#$id', '$effect', '$speed')}, " . ($closeDelay * 1000) . ");";
274	} else {
275		$closeDelayStr = '';
276	}
277
278	$js = "\$('#$id-link').mouseover(function(event) {
279	var pos  = $(this).position();
280	$(this).closest('td').css('position', 'relative');
281	\$('#$id').css('position', 'absolute').css('left', pos.left + $offsetx + 'px').css('top', pos.top + $offsety + 'px');
282	showJQ('#$id', '$effect', '$speed'); $closeDelayStr });
283";
284	if ($sticky) {
285		$js .= "\$('#$id').click(function(event) { hideJQ('#$id', '$effect', '$speed'); }).css('cursor','pointer');\n";
286	} else {
287		$js .= "\$('#$id-link').mouseout(function(event) { setTimeout(function() {hideJQ('#$id', '$effect', '$speed')}, " . ($closeDelay * 1000) . "); });";
288	}
289	$headerlib->add_jq_onready($js);
290
291	$bgcolor   = isset($params['bgcolor']) ? ("background-color: " . $params['bgcolor'] . ';') : '';
292	$textcolor = isset($params['textcolor']) ? ("color:" . $params['textcolor'] . ';') : '';
293	$class     = ! isset($params['class']) ? 'class="plugin-mouseover"' : 'class="plugin-mouseover ' . $params['class'] . '"';
294	$href      = $url ? 'href="' . $url . '"' : '';
295
296	$html = "~np~<$tag id=\"$id-link\" $href class=\"plugin-mouseover-anchor\">$label</$tag>" .
297		"<span id=\"$id\" $class style=\"width: {$width}px; " . (isset($params['height']) ? "height: {$height}px; " : "") . "{$bgcolor} {$textcolor} {$padding} \">$text</span>~/np~";
298
299	return $html;
300}
301
302function containsStringHTML($str)
303{
304	return preg_match('/<[^>]*>/', $str) == 1;
305}
306