Skip to content

Commit 0cd24e3

Browse files
committed
handle risk of orphan blur event listeners by making sure tourId is set
config option to decide if we should focus on target element when the step is visible allow custom focus target Fire custom events guided-tour-show-step, guided-tour-before-show-step on focus or main target element Allow setting pre step display and on step display mouse/pointer events to simulate user performing actions prior to undertaking the step - useful for ensuring elements such as sub menu items are visible New unique tour alias/identifier Start of work on context specific tour triggers Parameters tab when editing a step only shows if its relevant
1 parent 4f73668 commit 0cd24e3

File tree

11 files changed

+387
-16
lines changed

11 files changed

+387
-16
lines changed

administrator/components/com_guidedtours/forms/step.xml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,123 @@
227227
</field>
228228

229229
</fieldset>
230+
231+
<fieldset name="speciaactions" label="COM_GUIDEDTOURS_FIELD_SPECIAL_ACTIONS_LABEL">
232+
233+
<field
234+
name="setfocus"
235+
type="radio"
236+
label="COM_GUIDEDTOURS_SET_FOCUS_LABEL"
237+
description="COM_GUIDEDTOURS_SET_FOCUS_DESC"
238+
showon=".type:0,2"
239+
layout="joomla.form.field.radio.switcher"
240+
filter="integer"
241+
validate="options"
242+
default="1"
243+
>
244+
<option value="0">JNO</option>
245+
<option value="1">JYES</option>
246+
</field>
247+
248+
<field
249+
name="customfocustarget"
250+
type="radio"
251+
label="COM_GUIDEDTOURS_CUSTOM_FOCUS_TARGET_LABEL"
252+
description="COM_GUIDEDTOURS_CUSTOM_FOCUS_TARGET_DESC"
253+
showon=".type:0,2[AND]setfocus:1"
254+
layout="joomla.form.field.radio.switcher"
255+
filter="integer"
256+
validate="options"
257+
default="0"
258+
>
259+
<option value="0">JNO</option>
260+
<option value="1">JYES</option>
261+
</field>
262+
<field
263+
name="focustarget"
264+
type="text"
265+
label="COM_GUIDEDTOURS_FOCUS_TARGET_LABEL"
266+
description="COM_GUIDEDTOURS_FOCUS_TARGET_DESC"
267+
showon=".type:0,2[AND]customfocustarget:1[AND]setfocus:1"
268+
default=""
269+
/>
270+
271+
<field
272+
name="predisplayevents"
273+
type="subform"
274+
label="COM_GUIDEDTOURS_PRE_DISPLAY_EVENTS_LABEL"
275+
description="COM_GUIDEDTOURS_PRE_DISPLAY_EVENTS_DESC"
276+
showon=".type:0,2"
277+
multiple="true"
278+
layout="joomla.form.field.subform.repeatable-table"
279+
>
280+
<form>
281+
<field
282+
name="predisplayeventelement"
283+
type="test"
284+
label="COM_GUIDEDTOURS_PRE_DISPLAY_EVENT_ELEMENT_LABEL"
285+
description="COM_GUIDEDTOURS_PRE_DISPLAY_EVENT_ELEMENT_DESC"
286+
default=""
287+
required="true"
288+
/>
289+
<field
290+
name="predisplayevent"
291+
type="list"
292+
label="COM_GUIDEDTOURS_PRE_DISPLAY_EVENT_LABEL"
293+
description="COM_GUIDEDTOURS_PRE_DISPLAY_EVENT_DESC"
294+
multiple="true"
295+
required="true"
296+
layout="joomla.form.field.list-fancy-select"
297+
default=""
298+
showon="predisplayeventelement!:"
299+
>
300+
<option value="click">COM_GUIDEDTOURS_CLICK</option>
301+
<option value="dblclick">COM_GUIDEDTOURS_DOUBLE_CLICK</option>
302+
<option value="pointerenter">COM_GUIDEDTOURS_POINTERENTER</option>
303+
<option value="mouseover">COM_GUIDEDTOURS_MOUSEOVER</option>
304+
</field>
305+
</form>
306+
</field>
307+
308+
<field
309+
name="ondisplayevents"
310+
type="subform"
311+
label="COM_GUIDEDTOURS_ON_DISPLAY_EVENTS_LABEL"
312+
description="COM_GUIDEDTOURS_ON_DISPLAY_EVENTS_DESC"
313+
showon=".type:0,2"
314+
multiple="true"
315+
layout="joomla.form.field.subform.repeatable-table"
316+
>
317+
<form>
318+
<field
319+
name="ondisplayeventelement"
320+
type="test"
321+
label="COM_GUIDEDTOURS_ON_DISPLAY_EVENT_ELEMENT_LABEL"
322+
description="COM_GUIDEDTOURS_ON_DISPLAY_EVENT_ELEMENT_DESC"
323+
default=""
324+
required="true"
325+
/>
326+
<field
327+
name="ondisplayevent"
328+
type="list"
329+
label="COM_GUIDEDTOURS_ON_DISPLAY_EVENT_LABEL"
330+
description="COM_GUIDEDTOURS_ON_DISPLAY_EVENT_DESC"
331+
multiple="true"
332+
required="true"
333+
layout="joomla.form.field.list-fancy-select"
334+
default=""
335+
showon="ondisplayeventelement!:"
336+
>
337+
<option value="click">COM_GUIDEDTOURS_CLICK</option>
338+
<option value="dblclick">COM_GUIDEDTOURS_DOUBLE_CLICK</option>
339+
<option value="pointerenter">COM_GUIDEDTOURS_POINTERENTER</option>
340+
<option value="mouseover">COM_GUIDEDTOURS_MOUSEOVER</option>
341+
</field>
342+
</form>
343+
</field>
344+
230345
</fieldset>
346+
</fieldset>
231347
</fields>
232348

233349
</form>

administrator/components/com_guidedtours/forms/tour.xml

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@
2727
/>
2828

2929
<field
30-
name="alias"
31-
type="text"
32-
label="COM_GUIDEDTOURS_TOUR_ALIAS"
33-
description="COM_GUIDEDTOURS_TOUR_ALIAS_DESC"
34-
required="false"
30+
name="alias"
31+
type="text"
32+
label="COM_GUIDEDTOURS_TOUR_ALIAS_LABEL"
33+
description="COM_GUIDEDTOURS_TOUR_ALIAS_DESC"
34+
hint="COM_GUIDEDTOURS_TOUR_ALIAS_HINT"
35+
required="false"
3536
/>
3637

3738
<field
@@ -159,4 +160,50 @@
159160
>
160161
<option value="*">JALL</option>
161162
</field>
163+
<!--
164+
<fields name="params">
165+
166+
<fieldset name="options">
167+
168+
<fieldset name="requiredvalues" label="COM_GUIDEDTOURS_CONTEXT_SENSITIVE_FILTERING_LABEL">
169+
170+
<field
171+
name="matchingcriteria_note"
172+
type="note"
173+
label="COM_GUIDEDTOURS_MATCHING_CRITERIA_NOTE_LABEL"
174+
description="COM_GUIDEDTOURS_MATCHING_CRITERIA_NOTE_DESC"
175+
/>
176+
177+
<field
178+
name="matchingcriteria"
179+
type="subform"
180+
label="COM_GUIDEDTOURS_MATCHING_CRITERIA_LABEL"
181+
description="COM_GUIDEDTOURS_MATCHING_CRITERIA_DESC"
182+
multiple="true"
183+
layout="joomla.form.field.subform.repeatable-table"
184+
>
185+
<form>
186+
<field
187+
name="key"
188+
type="text"
189+
size="20"
190+
filter="safehtml"
191+
label="COM_GUIDEDTOURS_MATCHING_CRITERIA_GET_OR_POST_KEY_LABEL"
192+
description="COM_GUIDEDTOURS_MATCHING_CRITERIA_GET_OR_POST_KEY_DESC"
193+
validate="options"
194+
/>
195+
<field
196+
name="value"
197+
type="text"
198+
size="20"
199+
filter="safehtml"
200+
label="COM_GUIDEDTOURS_MATCHING_CRITERIA_GET_OR_POST_VALUE_LABEL"
201+
description="COM_GUIDEDTOURS_MATCHING_CRITERIA_GET_OR_POST_VALUE_DESC"
202+
/>
203+
</form>
204+
</field>
205+
</fieldset>
206+
</fieldset>
207+
</fields>
208+
-->
162209
</form>

administrator/components/com_guidedtours/src/Model/TourModel.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public function getItem($pk = null)
238238
$result->description_translation = Text::_($result->description);
239239
}
240240

241-
if (empty($result->alias)) {
241+
if (empty($result->alias) && (int) $pk > 0) {
242242
$app = Factory::getApplication();
243243
$uri = Uri::getInstance();
244244
$host = $uri->toString(['host']);

administrator/components/com_guidedtours/src/Model/ToursModel.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Joomla\CMS\MVC\Model\ListModel;
1616
use Joomla\Database\ParameterType;
1717
use Joomla\Registry\Registry;
18+
use Joomla\CMS\Uri\Uri;
1819
use Joomla\Utilities\ArrayHelper;
1920

2021
// phpcs:disable PSR1.Files.SideEffects
@@ -82,6 +83,9 @@ protected function populateState($ordering = 'a.ordering', $direction = 'ASC')
8283

8384
$this->setState('filter.extension', $extension);
8485

86+
// By default we don't constrain tours by context
87+
$this->setState('filter.contextspecific', 0);
88+
8589
parent::populateState($ordering, $direction);
8690
}
8791

@@ -166,11 +170,13 @@ public function getListQuery()
166170

167171
// Filter by extension
168172
if ($extensionfilter = $this->getState('filter.extensionfilter')) {
173+
//$query->where(':extensions MEMBER OF(' . $db->quoteName('a.extensions') . ')')->bind([':extensions'], $extensionfilter);
169174
$extension = '%' . $extensionfilter . '%';
170175
$query->where(
171176
$db->quoteName('a.extensions') . ' LIKE :extensions'
172177
)
173178
->bind([':extensions'], $extension);
179+
174180
} elseif ($extension = $this->getState('filter.extension')) {
175181
$extension = '%' . $extension . '%';
176182
$all = '%*%';
@@ -212,6 +218,17 @@ public function getListQuery()
212218
$query->whereIn($db->quoteName('a.language'), $language, ParameterType::STRING);
213219
}
214220

221+
// Filter by context
222+
/*
223+
$contextspecific = $this->getState('filter.contextspecific');
224+
if ($contextspecific) {
225+
$uri = Uri::getInstance();
226+
$url = trim($uri->toString(['path', 'query']), '/');
227+
$url = "administrator/index.php?option=com_content&view=articles";
228+
$query->where($db->quoteName('a.url') . ' = :context')
229+
->bind(':context', $url, ParameterType::STRING);
230+
}
231+
*/
215232
// Filter by search in title.
216233
$search = $this->getState('filter.search');
217234

administrator/components/com_guidedtours/tmpl/step/edit.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
$wa = $this->document->getWebAssetManager();
2121
$wa->useScript('keepalive')
2222
->useScript('form.validate')
23-
->useScript('com_guidedtours.tour-edit');
23+
->useScript('com_guidedtours.tour-edit');
2424

2525
if (empty($this->item->tour_id)) {
2626
throw new GenericDataException("\nThe Tour id was not set!\n", 500);

administrator/components/com_guidedtours/tmpl/tour/edit.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
2525
$wa = $this->document->getWebAssetManager();
2626
$wa->useScript('keepalive')
27-
->useScript('form.validate');
27+
->useScript('form.validate')
28+
->useScript('com_guidedtours.tour-edit');
29+
30+
$this->useCoreUI = true;
2831
?>
2932

3033
<form action="<?php echo Route::_('index.php?option=com_guidedtours&view=tour&layout=edit&id=' .
@@ -76,6 +79,8 @@
7679
</div>
7780
<?php echo HTMLHelper::_('uitab.endTab'); ?>
7881

82+
<?php echo LayoutHelper::render('joomla.edit.params', $this); ?>
83+
7984
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'publishing', Text::_('JGLOBAL_FIELDSET_PUBLISHING')); ?>
8085
<div class="row">
8186
<div class="col-12 col-lg-8">

administrator/language/en-GB/com_guidedtours.ini

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ COM_GUIDEDTOURS_STEP_NEW_STEP="New Step"
5252
COM_GUIDEDTOURS_STEP_POSITION_DESC="Select the position of the step popup, relative to the element it points to."
5353
COM_GUIDEDTOURS_STEP_POSITION_LABEL="Position"
5454
COM_GUIDEDTOURS_STEP_TITLE="Title"
55-
COM_GUIDEDTOURS_TOUR_ALIAS="Tour Identifier"
55+
COM_GUIDEDTOURS_TOUR_ALIAS_LABEL="Tour Identifier"
5656
COM_GUIDEDTOURS_TOUR_ALIAS_DESC="If you are sharing your tour on any other websites then the Tour Identifier needs to be unique.<br>We suggest a format such as AUTHORNAME-TOURNAME, COMPANYNAME-TOURNAME, SITEDOMAIN-TOURNAME.<br/>If no identifier is provided a value will be computed for you."
57+
COM_GUIDEDTOURS_TOUR_ALIAS_HINT="Unique identifier e.g. tour-author-site-domain-tour-name"
5758
COM_GUIDEDTOURS_STEP_TITLE_TRANSLATION="Title (%s)"
5859
COM_GUIDEDTOURS_STEP_TARGET_DESC="The target element the step will be attached to. Options: .classname, #id, any selector following the CSS syntax (make sure it is a focusable element if the step is interactive), or leave blank for a centered step."
5960
COM_GUIDEDTOURS_STEP_TARGET_LABEL="Target"
@@ -88,4 +89,30 @@ COM_GUIDEDTOURS_URL_DESC="Enter the relative URL of the page from where you want
8889
COM_GUIDEDTOURS_XML_DESCRIPTION="Component for managing Guided Tours functionality."
8990
COM_GUIDEDTOURS_FILTER_EXTENSION_LABEL="Selected Component"
9091
COM_GUIDEDTOURS_FILTER_EXTENSION_DESC="Component that restrict a tour to be displayed only when the selected component is active."
91-
COM_GUIDEDTOURS_FILTER_SELECT_TOUR_COMPONENT="Select Component"
92+
COM_GUIDEDTOURS_FILTER_SELECT_TOUR_COMPONENT="Select Component"
93+
COM_GUIDEDTOURS_CONTEXT_SENSITIVE_FILTERING_LABEL="Additional Context Specific Criteria"
94+
COM_GUIDEDTOURS_MATCHING_CRITERIA_NOTE_LABEL="Criteria to match the tour to the user's site actions/page"
95+
COM_GUIDEDTOURS_MATCHING_CRITERIA_NOTE_DESC="You can set a series additional key/value pairs that will be used to match tours that are most relevant to the page being viewed/action undertaken.<br>Key/Value pairs will be taken from the tour URL and added to the list below when matching context sensitive tours.<br>You can add as many criteria as you wish but they must all be matched to take effect."
96+
COM_GUIDEDTOURS_MATCHING_CRITERIA_LABEL="Criteria to match"
97+
COM_GUIDEDTOURS_MATCHING_CRITERIA_DESC="These criteria must all be matched for this tour to be highlights are relevant to the user's actions."
98+
COM_GUIDEDTOURS_MATCHING_CRITERIA_GET_OR_POST_KEY_LABEL="Form or URL key"
99+
COM_GUIDEDTOURS_MATCHING_CRITERIA_GET_OR_POST_KEY_DESC="The variable name to match in the URL or POST variables. The matching takes place after a SET URL has been converted to a native Joomla URL"
100+
COM_GUIDEDTOURS_MATCHING_CRITERIA_GET_OR_POST_VALUE_LABEL="Form or URL key"
101+
COM_GUIDEDTOURS_MATCHING_CRITERIA_GET_OR_POST_VALUE_DESC="The variable value to match in the URL or POST variables."
102+
COM_GUIDEDTOURS_FIELD_SPECIAL_ACTIONS_LABEL="Special Actions"
103+
COM_GUIDEDTOURS_SET_FOCUS_LABEL="Set Focus on Target Element When Step is Displayed"
104+
COM_GUIDEDTOURS_SET_FOCUS_DESC="When the step is displayed sets the browser focus on the target element (or custom target element set below)"
105+
COM_GUIDEDTOURS_CUSTOM_FOCUS_TARGET_LABEL="Custom Focus/Required Value Element"
106+
COM_GUIDEDTOURS_CUSTOM_FOCUS_TARGET_DESC="You can set the focus on a DOM element different to main the target element by specifying a CSS selector here. If a required action or value is set then this will apply to this custom focus element as opposed to the display target element."
107+
COM_GUIDEDTOURS_FOCUS_TARGET_LABEL="Focus/Required Value Target"
108+
COM_GUIDEDTOURS_FOCUS_TARGET_DESC="The DOM Element that should receive focus on this step if different to the main target element. If left blank then the main target element will receive the DOM focus when the step dis displayed"
109+
COM_GUIDEDTOURS_PRE_DISPLAY_EVENTS_LABEL="Pre Step Display Event Triggers"
110+
COM_GUIDEDTOURS_PRE_DISPLAY_EVENTS_DESC="If you wish to trigger DOM events prior to displaying the step you can specify the event element and the DOM event to fire. These should NOT cause a form submission or the page to redirect otherwise the tour will lose its position."
111+
COM_GUIDEDTOURS_PRE_DISPLAY_EVENT_ELEMENT_LABEL="Element on which to trigger an event"
112+
COM_GUIDEDTOURS_PRE_DISPLAY_EVENT_ELEMENT_DESC="CSS selector for the element on which the event should be fired"
113+
COM_GUIDEDTOURS_PRE_DISPLAY_EVENT_LABEL="Event(s) to trigger on the specified element"
114+
COM_GUIDEDTOURS_PRE_DISPLAY_EVENT_DESC="Select one or more DOM events to fire on the specified element"
115+
COM_GUIDEDTOURS_CLICK="Click"
116+
COM_GUIDEDTOURS_DOUBLE_CLICK="Double Click"
117+
COM_GUIDEDTOURS_MOUSEOVER="Mouse Over"
118+
COM_GUIDEDTOURS_POINTERENTER="Pointer Enter"

administrator/modules/mod_guidedtours/src/Helper/GuidedToursHelper.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public function getTours(Registry $params, AdministratorApplication $app)
5252
$tourModel->setState('filter.language', ['*', $app->getLanguage()->getTag()]);
5353
}
5454

55+
$hideLinks = $app->getInput()->getBool('hidemainmenu');
56+
if ($hideLinks) {
57+
$tourModel->setState('filter.contextspecific', 1);
58+
}
59+
5560
$items = $tourModel->getItems();
5661

5762
foreach ($items as $key => $item) {

administrator/modules/mod_guidedtours/tmpl/default.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@
1414
use Joomla\CMS\Language\Text;
1515
use Joomla\CMS\Uri\Uri;
1616

17-
$hideLinks = $app->getInput()->getBool('hidemainmenu');
18-
19-
if ($hideLinks || !$tours) {
17+
if (!$tours) {
2018
return;
2119
}
2220

build/media_source/com_guidedtours/js/tour-edit.es6.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
return;
1616
}
1717
const visibleChildren = fieldset.querySelectorAll(':scope .control-group:not(.hidden)');
18-
if (visibleChildren.length) {
18+
let countVisible = 0;
19+
visibleChildren.forEach((visibleChild) => {
20+
if (!visibleChild.closest('.control-group.hidden')) {
21+
countVisible += 1;
22+
}
23+
});
24+
if (countVisible) {
1925
fieldset.classList.remove('hidden');
2026
} else {
2127
fieldset.classList.add('hidden');
@@ -25,7 +31,13 @@
2531
const tabLabel = document.querySelector(`button[aria-controls="${tabelement.id}"]`);
2632
if (tabLabel) {
2733
const visibleChildren = tabelement.querySelectorAll(':scope .control-group:not(.hidden)');
28-
if (visibleChildren.length) {
34+
let countVisible = 0;
35+
visibleChildren.forEach((visibleChild) => {
36+
if (!visibleChild.closest('.control-group.hidden')) {
37+
countVisible += 1;
38+
}
39+
});
40+
if (countVisible) {
2941
tabLabel.removeAttribute('hidden');
3042
} else {
3143
tabLabel.setAttribute('hidden', 'hidden');

0 commit comments

Comments
 (0)