aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/assets/javascript
diff options
context:
space:
mode:
authorCesar G <prototech91@gmail.com>2014-04-08 03:54:56 -0700
committerCesar G <prototech91@gmail.com>2014-04-23 09:11:40 -0700
commit2fbae2bb41f63e35f0e7c3a650c78bfa138faf7b (patch)
treeaec5a47d039fe4b1c337356ebc3a1b1a2c7dfab7 /phpBB/assets/javascript
parent1a51ceeabe73423b919266027cc8e86ad47a52e1 (diff)
downloadforums-2fbae2bb41f63e35f0e7c3a650c78bfa138faf7b.tar
forums-2fbae2bb41f63e35f0e7c3a650c78bfa138faf7b.tar.gz
forums-2fbae2bb41f63e35f0e7c3a650c78bfa138faf7b.tar.bz2
forums-2fbae2bb41f63e35f0e7c3a650c78bfa138faf7b.tar.xz
forums-2fbae2bb41f63e35f0e7c3a650c78bfa138faf7b.zip
[ticket/10737] Add a more generic live search implementation.
PHPBB3-10737
Diffstat (limited to 'phpBB/assets/javascript')
-rw-r--r--phpBB/assets/javascript/core.js393
1 files changed, 331 insertions, 62 deletions
diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js
index 6034f81a6e..f9cc3f7a91 100644
--- a/phpBB/assets/javascript/core.js
+++ b/phpBB/assets/javascript/core.js
@@ -248,7 +248,16 @@ phpbb.ajaxify = function(options) {
callback = options.callback,
overlay = (typeof options.overlay !== 'undefined') ? options.overlay : true,
isForm = elements.is('form'),
- eventName = isForm ? 'submit' : 'click';
+ isText = elements.is('input[type="text"], textarea'),
+ eventName;
+
+ if (isForm) {
+ eventName = 'submit';
+ } else if (isText) {
+ eventName = 'keyup';
+ } else {
+ eventName = 'click';
+ }
elements.bind(eventName, function(event) {
var action, method, data, submit, that = this, $this = $(this);
@@ -348,6 +357,7 @@ phpbb.ajaxify = function(options) {
// If the element is a form, POST must be used and some extra data must
// be taken from the form.
var runFilter = (typeof options.filter === 'function');
+ var data = {};
if (isForm) {
action = $this.attr('action').replace('&amp;', '&');
@@ -361,33 +371,41 @@ phpbb.ajaxify = function(options) {
value: submit.val()
});
}
+ } else if (isText) {
+ var name = ($this.attr('data-name') !== undefined) ? $this.attr('data-name') : this['name'];
+ action = $this.attr('data-url').replace('&amp;', '&');
+ data[name] = this.value;
+ method = 'POST';
} else {
action = this.href;
data = null;
method = 'GET';
}
+ var sendRequest = function() {
+ if (overlay && (typeof $this.attr('data-overlay') === 'undefined' || $this.attr('data-overlay') === 'true')) {
+ phpbb.loadingIndicator();
+ }
+
+ var request = $.ajax({
+ url: action,
+ type: method,
+ data: data,
+ success: returnHandler,
+ error: errorHandler
+ });
+ request.always(function() {
+ loadingIndicator.fadeOut(phpbb.alertTime);
+ });
+ };
+
// If filter function returns false, cancel the AJAX functionality,
// and return true (meaning that the HTTP request will be sent normally).
- if (runFilter && !options.filter.call(this, data)) {
+ if (runFilter && !options.filter.call(this, data, event, sendRequest)) {
return;
}
- if (overlay && (typeof $this.attr('data-overlay') === 'undefined' || $this.attr('data-overlay') === 'true')) {
- phpbb.loadingIndicator();
- }
-
- var request = $.ajax({
- url: action,
- type: method,
- data: data,
- success: returnHandler,
- error: errorHandler
- });
- request.always(function() {
- loadingIndicator.fadeOut(phpbb.alertTime);
- });
-
+ sendRequest();
event.preventDefault();
});
@@ -403,6 +421,278 @@ phpbb.ajaxify = function(options) {
return this;
};
+phpbb.search = {cache: {data: []}, tpl: [], container: []};
+
+/**
+ * Get cached search data.
+ *
+ * @param string id Search ID.
+ * @return bool|object. Cached data object. Returns false if no data exists.
+ */
+phpbb.search.cache.get = function(id) {
+ if (this.data[id]) {
+ return this.data[id];
+ }
+ return false;
+};
+
+/**
+ * Set search cache data value.
+ *
+ * @param string id Search ID.
+ * @param string key Data key.
+ * @param string value Data value.
+ *
+ * @return undefined
+ */
+phpbb.search.cache.set = function(id, key, value) {
+ if (!this.data[id]) {
+ this.data[id] = {results: []};
+ }
+ this.data[id][key] = value;
+};
+
+/**
+ * Cache search result.
+ *
+ * @param string id Search ID.
+ * @param string keyword Keyword.
+ * @param array results Search results.
+ *
+ * @return undefined
+ */
+phpbb.search.cache.setResults = function(id, keyword, value) {
+ this.data[id]['results'][keyword] = value;
+};
+
+/**
+ * Trim spaces from keyword and lower its case.
+ *
+ * @param string keyword Search keyword to clean.
+ * @return string Cleaned string.
+ */
+phpbb.search.cleanKeyword = function(keyword) {
+ return $.trim(keyword).toLowerCase();
+};
+
+/**
+ * Get clean version of search keyword. If textarea supports several keywords
+ * (one per line), it fetches the current keyword based on the caret position.
+ *
+ * @param jQuery el Search input|textarea.
+ * @param string keyword Input|textarea value.
+ * @param bool multiline Whether textarea supports multiple search keywords.
+ *
+ * @return string Clean string.
+ */
+phpbb.search.getKeyword = function(el, keyword, multiline) {
+ if (multiline) {
+ var line = phpbb.search.getKeywordLine(el);
+ keyword = keyword.split("\n").splice(line, 1);
+ }
+ return phpbb.search.cleanKeyword(keyword);
+};
+
+/**
+ * Get the textarea line number on which the keyword resides - for textareas
+ * that support multiple keywords (one per line).
+ *
+ * @param jQuery el Search textarea.
+ * @return int
+ */
+phpbb.search.getKeywordLine = function (el) {
+ return el.val().substr(0, el.get(0).selectionStart).split("\n").length - 1;
+};
+
+/**
+ * Set the value on the input|textarea. If textarea supports multiple
+ * keywords, only the active keyword is replaced.
+ *
+ * @param jQuery el Search input|textarea.
+ * @param string value Value to set.
+ * @param bool multiline Whether textarea supports multiple search keywords.
+ *
+ * @return undefined
+ */
+phpbb.search.setValue = function(el, value, multiline) {
+ if (multiline) {
+ var line = phpbb.search.getKeywordLine(el),
+ lines = el.val().split("\n");
+ lines[line] = value;
+ value = lines.join("\n");
+ }
+ el.val(value);
+};
+
+/**
+ * Sets the onclick event to set the value on the input|textarea to the selected search result.
+ *
+ * @param jQuery el Search input|textarea.
+ * @param object value Result object.
+ * @param object container jQuery object for the search container.
+ *
+ * @return undefined
+ */
+phpbb.search.setValueOnClick = function(el, value, row, container) {
+ row.click(function() {
+ phpbb.search.setValue(el, value.result, el.attr('data-multiline'));
+ container.hide();
+ });
+};
+
+/**
+ * Runs before the AJAX search request is sent and determines whether
+ * there is a need to contact the server. If there are cached results
+ * already, those are displayed instead. Executes the AJAX request function
+ * itself due to the need to use a timeout to limit the number of requests.
+ *
+ * @param array data Data to be sent to the server.
+ * @param object event Onkeyup event object.
+ * @param function sendRequest Function to execute AJAX request.
+ *
+ * @return bool Returns false.
+ */
+phpbb.search.filter = function(data, event, sendRequest) {
+ var el = $(this),
+ dataName = (el.attr('data-name') !== undefined) ? el.attr('data-name') : el.attr('name'),
+ minLength = parseInt(el.attr('data-min-length')),
+ searchID = el.attr('data-results'),
+ keyword = phpbb.search.getKeyword(el, data[dataName], el.attr('data-multiline')),
+ cache = phpbb.search.cache.get(searchID),
+ proceed = true;
+ data[dataName] = keyword;
+
+ if (cache['timeout']) {
+ clearTimeout(cache['timeout']);
+ }
+
+ var timeout = setTimeout(function() {
+ // Check min length and existence of cache.
+ if (minLength > keyword.length) {
+ proceed = false;
+ } else if (cache['last_search']) {
+ // Has the keyword actually changed?
+ if (cache['last_search'] === keyword) {
+ proceed = false;
+ } else {
+ // Do we already have results for this?
+ if (cache['results'][keyword]) {
+ var response = {keyword: keyword, results: cache['results'][keyword]};
+ phpbb.search.handleResponse(response, el, true);
+ proceed = false;
+ }
+
+ // If the previous search didn't yield results and the string only had characters added to it,
+ // then we won't bother sending a request.
+ if (keyword.indexOf(cache['last_search']) === 0 && cache['results'][cache['last_search']].length === 0) {
+ phpbb.search.cache.set(searchID, 'last_search', keyword);
+ phpbb.search.cache.setResults(searchID, keyword, []);
+ proceed = false;
+ }
+ }
+ }
+
+ if (proceed) {
+ sendRequest.call(this);
+ }
+ }, 350);
+ phpbb.search.cache.set(searchID, 'timeout', timeout);
+
+ return false;
+};
+
+/**
+ * Handle search result response.
+ *
+ * @param object res Data received from server.
+ * @param jQuery el Search input|textarea.
+ * @param bool fromCache Whether the results are from the cache.
+ * @param function callback Optional callback to run when assigning each search result.
+ *
+ * @return undefined
+ */
+phpbb.search.handleResponse = function(res, el, fromCache, callback) {
+ if (typeof res !== 'object') {
+ return;
+ }
+
+ var searchID = el.attr('data-results'),
+ container = $(searchID);
+
+ if (this.cache.get(searchID)['callback']) {
+ callback = this.cache.get(searchID)['callback'];
+ } else if (typeof callback === 'function') {
+ this.cache.set(searchID, 'callback', callback);
+ }
+
+ if (!fromCache) {
+ this.cache.setResults(searchID, res.keyword, res.results);
+ }
+
+ this.cache.set(searchID, 'last_search', res.keyword);
+ this.showResults(res.results, el, container, callback);
+};
+
+/**
+ * Show search results.
+ *
+ * @param array results Search results.
+ * @param jQuery el Search input|textarea.
+ * @param jQuery container Search results container element.
+ * @param function callback Optional callback to run when assigning each search result.
+ *
+ * @return undefined
+ */
+phpbb.search.showResults = function(results, el, container, callback) {
+ var resultContainer = $('.search-results', container);
+ this.clearResults(resultContainer);
+
+ if (!results.length) {
+ container.hide();
+ return;
+ }
+
+ var searchID = container.attr('id'),
+ tpl,
+ row;
+
+ if (!this.tpl[searchID]) {
+ tpl = $('.search-result-tpl', container);
+ this.tpl[searchID] = tpl.clone().removeClass('search-result-tpl');
+ tpl.remove();
+ }
+ tpl = this.tpl[searchID];
+
+ $.each(results, function(i, item) {
+ row = tpl.clone();
+ row.find('.search-result').html(item.result);
+
+ if (callback === 'function') {
+ callback.call(this, el, item, row, container);
+ }
+ row.appendTo(resultContainer).show();
+ });
+ container.show();
+};
+
+/**
+ * Clear search results.
+ *
+ * @param jQuery container Search results container.
+ * @return undefined
+ */
+phpbb.search.clearResults = function(container) {
+ container.children(':not(.search-result-tpl)').remove();
+};
+
+$('#phpbb').click(function(e) {
+ var target = $(e.target);
+
+ if (!target.is('.live-search') && !target.parents().is('.live-search')) {
+ $('.live-search').hide();
+ }
+});
+
/**
* Hide the optgroups that are not the selected timezone
*
@@ -512,51 +802,6 @@ phpbb.timezonePreselectSelect = function(forceSelector) {
}
};
-// Listen live search box events
-var delay = (function(){
- var timer = 0;
- return function(callback, ms){
- clearTimeout (timer);
- timer = setTimeout(callback, ms);
- };
-})();
-
-$('.live-search-input').keyup(function() {
- var str = this.value;
- delay(function(){
- if (str.length < 3) {
- return;
- }
- var link, name;
- var clone = $("#user-search-row-tpl").clone();
- $("#livesearch").html("");
- clone.appendTo("#livesearch");
- $.ajax({
- url:'memberlist.php?mode=livesearch&'+"&q="+str,
- success:function(result) {
- $.each(result, function(idx, elem) {
- link = "memberlist.php?mode=viewprofile&u=" + elem.id;
- name = elem.name;
- clone = $("#user-search-row-tpl").clone();
- clone.find(".user-search-link").attr("href", link);
- clone.find(".user-search-name").html(name);
- clone.attr("style", "");
- clone.appendTo("#livesearch");
- });
- }
- });
- }, 2000 );
-});
-
-$(document).click(function(event) {
- var target = $( event.target );
- if(!target.is("#livesearch, #livesearch *, .live-search-input")) {
- var clone = $("#user-search-row-tpl").clone();
- $("#livesearch").html("");
- clone.appendTo("#livesearch");
- }
-});
-
// Toggle notification list
$('#notification_list_button').click(function(e) {
$('#notification_list').toggle();
@@ -587,6 +832,12 @@ phpbb.addAjaxCallback = function(id, callback) {
return this;
};
+/**
+ * This callback handles live member searches.
+ */
+phpbb.addAjaxCallback('member_search', function(res) {
+ phpbb.search.handleResponse(res, $(this), false);
+});
/**
* This callback alternates text - it replaces the current text with the text in
@@ -1148,6 +1399,24 @@ phpbb.toggleDisplay = function(id, action, type) {
}
/**
+* Get function from name.
+* Based on http://stackoverflow.com/a/359910
+*
+* @param string functionName Function to get.
+* @return function
+*/
+phpbb.getFunctionByName = function (functionName) {
+ var namespaces = functionName.split('.'),
+ func = namespaces.pop(),
+ context = window;
+
+ for (var i = 0; i < namespaces.length; i++) {
+ context = context[namespaces[i]];
+ }
+ return context[func];
+};
+
+/**
* Apply code editor to all textarea elements with data-bbcode attribute
*/
$(document).ready(function() {