Skip to content

Commit 49df2c7

Browse files
committed
Implement live search on the duplicate field
1 parent d6e1339 commit 49df2c7

3 files changed

Lines changed: 97 additions & 46 deletions

File tree

language/en/common.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
'DATE' => 'Date',
3131
'DELETE_IDEA' => 'Delete idea',
3232
'DUPLICATE' => 'Duplicate',
33+
'DUPLICATE_PLACEHOLDER' => 'Start typing a title',
3334

3435
'EDIT' => 'Edit',
3536
'ENABLE_JS' => 'Please enable JavaScript in your browser to use phpBB Ideas effectively.',
@@ -38,7 +39,6 @@
3839
'IDEA_DELETED' => 'Idea successfully deleted.',
3940
'IDEA_ID' => 'Idea ID',
4041
'IDEA_LIST' => 'Idea List',
41-
'IDEA_NUM' => 'Idea #',
4242
'IDEA_NOT_FOUND' => 'Idea not found',
4343
'IDEA_STORED_MOD' => 'Your idea has been submitted successfully, but it will need to be approved by a moderator before it is publicly viewable. You will be notified when your idea has been approved.<br /><br /><a href="%s">Return to Ideas</a>.',
4444
'IDEAS_TITLE' => 'phpBB Ideas',
@@ -78,7 +78,7 @@
7878

7979
'TICKET' => 'Ticket',
8080
'TICKET_ERROR' => 'Ticket ID must be of the format “PHPBB3-#####”.',
81-
'TICKET_ERROR_DUP' => 'Please use the Idea ID number.',
81+
'TICKET_ERROR_DUP' => 'You must click on an idea title from the live search results. To delete the duplicate, clear the field and hit ENTER. To exit this field click ESC.',
8282
'TITLE' => 'Title',
8383
'TITLE_TOO_LONG' => 'Subject must be under %d characters long.',
8484
'TITLE_TOO_SHORT' => 'You must specify a subject when posting a new idea.',

styles/prosilver/template/idea_body.html

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,33 @@
9090
{% if IDEA_DUPLICATE or S_IS_MOD %}
9191
<dt class="duplicatetoggle idealabel"{% if IDEA_STATUS_ID != STATUS_ARY.DUPLICATE %} style="display:none"{% endif %}>{{ lang('DUPLICATE') ~ lang('COLON') }}</dt>
9292
<dd class="duplicatetoggle" {% if IDEA_STATUS_ID != STATUS_ARY.DUPLICATE %}style="display:none"{% endif %}>
93-
<a id="duplicatelink" data-link="{{ U_IDEA_DUPLICATE }}" data-l-msg="{{ lang('IDEA_NUM') }}" {% if IDEA_DUPLICATE %}href="{{ U_IDEA_DUPLICATE }}">{{ lang('IDEA_NUM') ~ IDEA_DUPLICATE }}{% else %}style="display:none">{% endif %}</a>
93+
<a id="duplicatelink" data-link="{{ U_IDEA_DUPLICATE }}" {% if IDEA_DUPLICATE %}href="{{ U_IDEA_DUPLICATE }}">{{ IDEA_DUPLICATE }}{% else %}style="display:none">{% endif %}</a>
9494
{% if S_IS_MOD %}
9595
<a href="{{ U_EDIT_DUPLICATE }}" id="duplicateedit" data-l-add="{{ lang('ADD') }}" data-l-edit="{{ lang('EDIT') }}">{% if IDEA_DUPLICATE %}<i class="icon fa-fw fa-pencil"></i>{{ lang('EDIT') }}{% else %}<i class="icon fa-fw fa-plus-circle"></i>{{ lang('ADD') }}{% endif %}</a>
96-
<input type="text" id="duplicateeditinput" class="ideainput"{% if IDEA_DUPLICATE %} value="{{ IDEA_DUPLICATE }}"{% endif %} placeholder="###" data-l-err="{{ lang('ERROR') }}" data-l-msg="{{ lang('TICKET_ERROR_DUP') }}" />
96+
<div class="dropdown-container dropdown-{{ S_CONTENT_FLOW_END }}">
97+
<input
98+
type="text"
99+
name="duplicateeditinput"
100+
id="duplicateeditinput"
101+
value="{{ IDEA_DUPLICATE ? IDEA_DUPLICATE }}"
102+
placeholder="{{ lang('DUPLICATE_PLACEHOLDER') }}"
103+
class="ideainput"
104+
autocomplete="off"
105+
data-filter="phpbb.search.filter"
106+
data-ajax="idea_search"
107+
data-min-length="3"
108+
data-url="{{ U_TITLE_LIVESEARCH }}"
109+
data-results="#live-search"
110+
data-l-err="{{ lang('ERROR') }}"
111+
data-l-msg="{{ lang('TICKET_ERROR_DUP') }}"
112+
/>
113+
<div class="dropdown live-search hidden" id="live-search">
114+
<div class="pointer"><div class="pointer-inner"></div></div>
115+
<ul class="dropdown-contents search-results">
116+
<li class="search-result-tpl"><span class="search-result"></span></li>
117+
</ul>
118+
</div>
119+
</div>
97120
{% endif %}
98121
</dd>
99122
{% endif %}

styles/prosilver/template/ideas.js

Lines changed: 70 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -254,53 +254,81 @@
254254
$obj.duplicateEditInput.show().trigger('focus');
255255
});
256256

257-
$obj.duplicateEditInput.on('keydown', function(e) {
258-
if (e.keyCode === keymap.ENTER) {
259-
e.preventDefault();
260-
e.stopPropagation();
257+
/**
258+
* This callback handles live idea title searches for duplicate ideas.
259+
*/
260+
phpbb.addAjaxCallback('idea_search', function(res) {
261+
phpbb.search.handleResponse(res, $(this), false, phpbb.getFunctionByName('phpbb.search.setDuplicateOnEvent'));
262+
});
261263

262-
var $this = $(this),
263-
url = $obj.duplicateEdit.attr('href'),
264-
value = $this.val();
264+
/**
265+
* This performs actions on each result from the live idea title search for duplicate ideas.
266+
*
267+
* @param {jQuery|JQuery} $input Search input|textarea.
268+
* @param {object} value Result object.
269+
* @param {jQuery|JQuery} $row Result element.
270+
* @param {jQuery|JQuery} $container jQuery object for the search container.
271+
*/
272+
phpbb.search.setDuplicateOnEvent = function($input, value, $row, $container) {
273+
$row.on('click', function() {
274+
setDuplicate($input, value);
275+
phpbb.search.closeResults($input, $container);
276+
});
277+
};
265278

266-
if (value && isNaN(Number(value))) {
267-
phpbb.alert($this.attr('data-l-err'), $this.attr('data-l-msg'));
268-
return;
279+
/**
280+
* Assign a duplicate idea identifier to a given idea.
281+
*
282+
* @param {jQuery|JQuery} $input Search input|textarea.
283+
* @param {object} value Result object.
284+
*/
285+
function setDuplicate($input, value) {
286+
if (value.result && isNaN(Number(value.result))) {
287+
phpbb.alert($input.attr('data-l-err'), $input.attr('data-l-msg'));
288+
return;
289+
}
290+
$input.val(value.clean_title);
291+
showLoadingIndicator();
292+
$.get($obj.duplicateEdit.attr('href'), {duplicate: Number(value.result)}, function(res) {
293+
if (res) {
294+
if (value.result) {
295+
$obj.duplicateLink
296+
.text(value.clean_title)
297+
.attr('href', $obj.duplicateLink.attr('data-link').replace(/^(.*\/)(\d+)$/, '$1') + value.result)
298+
.show();
299+
} else {
300+
$obj.duplicateLink
301+
.empty()
302+
.removeAttr('href');
303+
}
304+
$input.hide();
305+
$obj.duplicateEdit.toggleAddEdit(value.result);
269306
}
307+
}).always(hideLoadingIndicator);
308+
}
270309

271-
showLoadingIndicator();
272-
$.get(url, {duplicate: Number(value)}, function(res) {
273-
if (res) {
274-
if (value) {
275-
var msg = $obj.duplicateLink.attr('data-l-msg');
276-
var link = $obj.duplicateLink.attr('data-link').replace(/^(.*\/)(\d+)$/, '$1');
277-
278-
$obj.duplicateLink
279-
.text(msg + value)
280-
.attr('href', link + value)
281-
.show();
282-
} else {
283-
$obj.duplicateLink
284-
.text(value)
285-
.attr('href', value);
286-
}
287-
288-
$this.hide();
289-
290-
$obj.duplicateEdit.toggleAddEdit(value);
310+
/**
311+
* Handling of the duplicate idea input field.
312+
* ENTER: When the input field is empty clear any existing duplicate entry. Otherwise just show an alert message.
313+
* ESC: Will clear and close the input field (if it isn't cleared, live search may unexpectedly run).
314+
*/
315+
$obj.duplicateEditInput.on('keydown.duplicate', function(e) {
316+
var $this = $(this),
317+
key = e.keyCode || e.which;
318+
switch (key) {
319+
case keymap.ESC:
320+
$this.val('').hide();
321+
$obj.duplicateEdit.show();
322+
$obj.duplicateLink.toggle($obj.duplicateLink.html().length !== 0);
323+
break;
324+
case keymap.ENTER:
325+
if ($this.val().length === 0) {
326+
setDuplicate($this, {'result': '', 'clean_title': ''});
327+
} else {
328+
e.stopPropagation();
329+
phpbb.alert($this.attr('data-l-err'), $this.attr('data-l-msg'));
291330
}
292-
}).always(hideLoadingIndicator);
293-
} else if (e.keyCode === keymap.ESC) {
294-
e.preventDefault();
295-
296-
var $link = $obj.duplicateLink;
297-
298-
$(this).hide();
299-
$obj.duplicateEdit.show();
300-
301-
if ($link.html()) {
302-
$link.show();
303-
}
331+
break;
304332
}
305333
});
306334

0 commit comments

Comments
 (0)