1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/jappix_ynh.git synced 2024-09-03 19:26:19 +02:00
jappix_ynh/source/app/javascripts/search.js
2014-04-08 20:14:28 +02:00

419 lines
No EOL
11 KiB
JavaScript

/*
Jappix - An open social platform
These are the seach tools JS script for Jappix
-------------------------------------------------
License: AGPL
Author: Valérian Saliou
*/
// Bundle
var Search = (function () {
/**
* Alias of this
* @private
*/
var self = {};
/* Variables */
self.search_filtered = false;
/**
* Searches in the user's buddy list
* @public
* @param {string} query
* @return {object}
*/
self.processBuddy = function(query) {
try {
// No query submitted?
if(!query) {
return;
}
// Wildcard (*) submitted
if(query == '*') {
query = '';
}
// Replace forbidden characters in regex
query = Common.escapeRegex(query);
// Create an empty array
var results = [];
// Search regex
var regex = new RegExp('((^)|( ))' + query, 'gi');
// Search in the roster
var buddies = Roster.getAllBuddies();
for(var i in buddies) {
var xid = buddies[i];
var nick = Name.getBuddy(xid);
// Buddy match our search, and not yet in the array
if(nick.match(regex) && !Utils.existArrayValue(results, xid)) {
results.push(xid);
}
}
// Return the results array
return results;
} catch(e) {
Console.error('Search.processBuddy', e);
}
};
/**
* Resets the buddy search tool
* @public
* @param {string} destination
* @return {undefined}
*/
self.resetBuddy = function(destination) {
try {
$(destination + ' ul').remove();
$(destination + ' input').removeClass('suggested');
} catch(e) {
Console.error('Search.resetBuddy', e);
}
};
/**
* Add the clicked XID to the input
* @public
* @param {string} destination
* @param {string} xid
* @return {boolean}
*/
self.addBuddy = function(destination, xid) {
try {
// Remove the search tool
self.resetBuddy(destination);
// Define a selector
var input = $(destination + ' input');
var value = input.val();
// Get the old value (if there's another value)
var old = '';
if(value.match(/(^(.+)(,)(\s)?)(\w+)$/))
old = RegExp.$1;
// Add the XID to the "to" input and focus on it
$(document).oneTime(10, function() {
input.val(old + xid).focus();
});
} catch(e) {
Console.error('Search.addBuddy', e);
} finally {
return false;
}
};
/**
* Creates the appropriate markup for the search results
* @public
* @param {string} destination
* @return {undefined}
*/
self.createBuddy = function(destination) {
try {
// Reset the search engine
self.resetBuddy(destination);
// Get the entered value
var value = $(destination + ' input').val();
// Separation with a comma?
if(value.match(/^(.+)((,)(\s)?)(\w+)$/))
value = RegExp.$5;
// Get the result array
var entered = self.processBuddy(value);
// Display each result (if any)
if(entered && entered.length) {
// Set a special class to the search input
$(destination + ' input').addClass('suggested');
// Append each found buddy in the container
var regex = new RegExp('((^)|( ))' + value, 'gi');
// Initialize the code generation
var code = '<ul>';
for(var b in entered) {
// Get some values from the XID
var current = Name.getBuddy(entered[b]).htmlEnc();
current = current.replace(regex, '<b>$&</b>');
// Add the current element to the global code
code += '<li onclick="return Search.addBuddy(\'' + Utils.encodeOnclick(destination) + '\', \'' + Utils.encodeOnclick(entered[b]) + '\');" data-xid="' + Common.encodeQuotes(entered[b]) + '">' + current + '</li>';
}
// Finish the code generation
code += '</ul>';
// Creates the code in the DOM
$(destination).append(code);
// Put the hover on the first element
$(destination + ' ul li:first').addClass('hovered');
// Hover event, to not to remove this onblur and loose the click event
$(destination + ' ul li').hover(function() {
$(destination + ' ul li').removeClass('hovered');
$(this).addClass('hovered');
// Add a marker for the blur event
$(destination + ' ul').attr('mouse-hover', 'true');
}, function() {
$(this).removeClass('hovered');
// Remove the mouse over marker
$(destination + ' ul').removeAttr('mouse-hover');
});
}
} catch(e) {
Console.error('Search.createBuddy', e);
}
};
/**
* Handles the keyboard arrows press when searching
* @public
* @param {object} evt
* @param {string} destination
* @return {boolean}
*/
self.arrowsBuddy = function(evt, destination) {
try {
// Down arrow: 40
// Up arrown: 38
// Initialize
var code = evt.keyCode;
// Not the key we want here
if((code != 40) && (code != 38))
return;
// Remove the eventual mouse hover marker
$(destination + ' ul').removeAttr('mouse-hover');
// Create the path & get its size
var path = destination + ' ul li';
var pSize = $(path).size();
// Define the i value
var i = 0;
// Switching yet launched
if(Common.exists(path + '.hovered')) {
var index = $(path).attr('data-hovered');
if(index)
i = parseInt(index);
if(code == 40)
i++;
else
i--;
}
else if(code == 38)
i = pSize - 1;
// We must not override the maximum i limit
if(i >= pSize)
i = 0;
// We must not have negative i
else if(i < 0)
i = pSize - 1;
// Modify the list
$(path + '.hovered').removeClass('hovered');
$(path).eq(i).addClass('hovered');
// Store the i index
$(path).attr('data-hovered', i);
} catch(e) {
Console.error('Search.arrowsBuddy', e);
} finally {
return false;
}
};
/**
* Filters the buddies in the roster
* @public
* @param {object} vFilter
* @return {undefined}
*/
self.goFilterBuddy = function(vFilter) {
try {
// Put a marker
self.search_filtered = true;
// Show the buddies that match the search string
var rFilter = self.processBuddy(vFilter);
// Hide all the buddies
$('#roster .buddy').hide();
// Only show the buddies which match the search
if(!Roster.blist_all) {
for(var i in rFilter)
$('#roster .buddy[data-xid="' + escape(rFilter[i]) + '"]:not(.hidden-buddy)').show();
} else {
for(var j in rFilter)
$('#roster .buddy[data-xid="' + escape(rFilter[j]) + '"]').show();
}
} catch(e) {
Console.error('Search.goFilterBuddy', e);
}
};
/**
* Resets the buddy filtering in the roster
* @public
* @return {undefined}
*/
self.resetFilterBuddy = function() {
try {
// Remove the marker
self.search_filtered = false;
// Show all the buddies
$('#roster .buddy').show();
// Only show available buddies
if(!Roster.blist_all)
$('#roster .buddy.hidden-buddy').hide();
// Update the groups
Roster.updateGroups();
} catch(e) {
Console.error('Search.resetFilterBuddy', e);
}
};
/**
* Funnels the buddy filtering
* @public
* @param {number} keycode
* @return {undefined}
*/
self.funnelFilterBuddy = function(keycode) {
try {
// Get the input value
var input = $('#roster .filter input');
var cancel = $('#roster .filter a');
var value = input.val();
// Security: reset all the groups, empty or not, deployed or not
$('#roster .one-group, #roster .group-buddies').show();
$('#roster .group span').text('-');
// Nothing is entered, or escape pressed
if(!value || (keycode == 27)) {
if(keycode == 27)
input.val('');
self.resetFilterBuddy();
cancel.hide();
}
// Process the filtering
else {
cancel.show();
self.goFilterBuddy(value);
}
// Update the groups
Roster.updateGroups();
} catch(e) {
Console.error('Search.funnelFilterBuddy', e);
}
};
/**
* Searches for the nearest element (with a lower stamp than the current one)
* @public
* @param {number} stamp
* @param {string} element
* @return {number}
*/
self.sortElementByStamp = function(stamp, element) {
try {
var array = [];
var i = 0;
var nearest = 0;
// Add the stamp values to the array
$(element).each(function() {
var current_stamp = parseInt($(this).attr('data-stamp'));
// Push it!
array.push(current_stamp);
});
// Sort the array
array.sort();
// Get the nearest stamp value
while(stamp > array[i]) {
nearest = array[i];
i++;
}
return nearest;
} catch(e) {
Console.error('Search.sortElementByStamp', e);
}
};
/**
* Return class scope
*/
return self;
})();