Auto suggest feature to search records - php

I don't know what is the exact name of this feature, but I need a feature where the user should be given a text box to search things. When they type in this text box, a matching list of values from database should be shown like a drop-down box.
The user can select one of the value and for will got submit.
I know this is already done on Internet anywhere, but what is this feature called?
Where can I find this feature to download and use for free?

Autocomplete from jQuery UI . SAYT opensource from Google.
http://jqueryui.com/demos/autocomplete/
http://code.google.com/p/search-as-you-type/

I found this code somewhere online, very very useful and very fast (tested for 30000 strings), have been using it ever since,
it uses regex
var rx = new RegExp('"([^"]*' + search + '[^"]*)"', 'gi');
var i = 0;
var num;
results = '';
while (result = rx.exec(string)) {
results += "\n" + result[1];
i += 1;
if (i >= 10) break;
}
I've put up the entire code on JSFiddle
NOTE: My code(The HTML part) is extremely messy, was trying too many things at once, just correct it to suit your requirements.

The easiest way to do this is to use the jQuery UI version here.

Related

codeigniter attribute/filter system

I've searched a lot for answers to this question, but I can't find them. Maybe because I'm not searching for the right keywords (because I don't know the right name) or there might be few resources on this subject.
I'd like to build a 'sorting system' in codeigniter for database results. Much like the magento layered navigation or the sorting that's on this site: http://www.wintersporters.nl/skigebieden. On there you can filter ski resorts by price, country, amount of slopes etcetera and the results are automatically updated via AJAX.
another example -> http://www.beslist.nl/products/cddvdrom/cddvdrom_5035278/ where you can sort by date, publisher, genre etcetera.
I'd like the system to be able to pass multiple variables like on wintersporters.nl where you can select multiple countries instead of only one and this way you're able to narrow down your search more and more by selecting multiple attributes until you've found the ski resort that fits you best. So every time you select an option it's preserved in the URL.
How do I achieve something like this? Via the $_GET[] array, with uri's or something totally different? Can anyone point me to a tutorial, snippet of code, explanation or anything related as I can't find out the right way to do this.
I'd be really grateful!
I was also thinking about the component or control which will give me the same functioalities for my web portal but then I developed by own by HTML and Ajax.
In Ajax, you can use
var checkboxValueArray = [];
var val = [];
$('input[name="subcatcheckbox"]:checked').each(function(i){
val[i] = $(this).val();
checkboxValueArray.push($('#subcat'+val[i]).text());
});
checkboxValueString = checkboxValueArray.toString();
checkboxValueString = checkboxValueString.replace(/\ /g, "-");
checkboxValueString = checkboxValueString.replace(/\_/g, "-");
checkboxValueString = checkboxValueString.replace(/\,/g, ":");
var checkboxValueNumberString = val.toString();
var checkboxValueNumberString = checkboxValueNumberString.replace(/\,/g, ":");
var pathName ='';
if(checkboxValueNumberString != ''){
pathName = "events_categories="+checkboxValueString+"&catid="+checkboxValueNumberString;
}
if(pathName != ''){
window.location.hash = "#!" + pathName;
}
if(pathName == ''){
window.location.hash = '';
}
getEventsParsedJSON(val);
By this way, I am creating an array on onClick event and then passing to the string to the URL through window.location.hash(ajax method). I developed this in a day. It's easy to develop.

Routeboxer server side

I'm trying to find out a way to get latitude and longitude bounds from google's routeboxer to php and then query mysql by those limits. I'll then output the results to json or xml to use those with android maps api v2. I found this http://luktek.com/Blog/2011-02-03-google-maps-routeboxer-in-php , but I think that this only does boxes between two points on a map, not boxes around the route itself which makes it not accurate enough. Using javascript is not an option, since I can't use it with google maps api or get the results from my database. Is there any way to accomplish this by using some server side code (preferably PHP, but any other language that works with mysql can be used as well), that can fetch the bounds, query mysql by those and output the data to json or xml so that it can be parsed by android?
I finally found a solution that I'm satisfied with.
I'm not going to paste every step because it's going to take like thousand lines but here's it in a nutshell:
1. Parse this field from Google directions api json(https://developers.google.com/maps/documentation/directions/#JSON): "overview_polyline": {
2. Decode the polyline to latitude and longitude points with this:
http://unitstep.net/blog/2008/08/02/decoding-google-maps-encoded-polylines-using-php/
3. Download this https://github.com/bazo/route-boxer. I piled all the code from GeoTools php-files to a one file but that's not propably necessary if you'll know how to use that :)
4. And here is an example of getting those boxes using those scripts:
...
$from = "(Startup point for example: "Turku,Finland")";
$to = "(Destination point fro example: "Porvoo,Finland")";
$json_string = file_get_contents("http://maps.googleapis.com/maps/api/directions/json?origin=$from&destination=$to&sensor=false");
$parsed_json = json_decode($json_string, true);
$polyline = $parsed_json['routes'][0]['overview_polyline']['points'];
$routepoints = decodePolylineToArray($polyline);
$collection = new LatLngCollection($routepoints);
$boxer = new RouteBoxer();
//calculate boxes with 10km distance from the line between points
$boxes = $boxer->box($collection, $distance = 10);
foreach($boxes as $row){
$southWestLtd = $row->southWest->latitude;
$southWestLng = $row->southWest->longitude;
$northEastLtd = $row->northEast->latitude;
$northEastLng = $row->northEast->longitude;
$query = "SELECT * FROM markers WHERE Latitude > $southWestLtd AND Latitude < $northEastLtd AND Longitude > $southEastLng AND Longitude < $norhtEastLng";
}
Run that query and it'll give you only the markers (or what ever you are querying) that are inside those boxes. If you'll need some more detailed instructions just leave a comment. I'm more than happy to help since I spent many nights trying to find a reasonable solution to this.
Lots of questions here, let me try to tackle some:
Getting lat and long bounds from routeboxer:
Once you have your 'boxes', you can loop through and get these
var northeast = boxes[i].getNorthEast();
var southwest = boxes[i].getSouthWest();
var lat_north = northeast.lat();
var long_east = northeast.lng();
var lat_south = southwest.lat();
var long_west = southwest.lng();
> at this only does boxes between two points on a map, not boxes around the route itself which makes it not accurate enough
I do not know about this persons implementation of Routeboxer but the original Google Routeboxer for the API v3 creates boxes around the entire route. That is what is documented and I can say with confidence, how it works (I've used it)
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/routeboxer/docs/examples.html
> Using javascript is not an option, since I can't use it with google maps api or get the results from my database.
This point makes little sense to me. You DEFINITELY CAN use Google Maps API with Javascript, there is a Javascript Library (version 3 already) specifically FOR THIS PURPOSE. If this is a browser application I would strongly recommend sticking with that, at least initially.
As for getting results from DB, you can use AJAX calls (basically just call your php script via AJAX, have it return JSON data, then use JAVASCRIPT to parse/populate this data onto the screen of the user... Alternately, it doesn't even have to be ajax, you can use routeboxer, then upon some action, submit this to your DB, then have the next page return with results rendered... But AJAX really is the more elegant approach (this case is almost an 'ideal use-case' for it)
BTW: I do not see the logic of putting Routerbox 'server-side' as this programmer has done. He points out rightly to the fact that very long, complex routes, will take time but my thoughts would be: "whether the user is waiting for his PC to crunch the data, or he is waiting for a remote PC (the server) to crunch the data....... all he knows and cares about is that he is waiting, NOT THE BACKEND METHODOLOGY! (with the exception being when one has access to a series of powerful servers and can rewrite the server-side code to take advantage of parallel-runs etc...)

How to make search autocomplete faster?

I have implemented a basic auto-complete feature using jQuery autocomplete. I am querying DB every time which is making auto-complete thing quite slow. I am looking for ways to make it faster much like Quora.
Here is the code from front-end:
<script type="text/javascript">
var URL2 = '<?php e(SITE_URL); ?>fronts/searchKeywords';
jQuery(document).ready(function(){
var CityKeyword = jQuery('#CityKeyword');
CityKeyword.autocomplete({
minLength : 1,
source : URL2
});
});
</script>
Here is the code from server side:
function searchKeywords(){
if ($this->RequestHandler->isAjax() ) {
$this->loadModel('Expertise_area');
Configure::write ( 'debug',0);
$this->autoRender=false;
$expertise=$this->Expertise_area->find('all',array(
'conditions'=>array('Expertise_area.autocomplete_text LIKE'=>'%'.$_GET['term'].'%'),
'fields' => array('DISTINCT (Expertise_area.autocomplete_text) AS autocomplete_text'),
'limit'=>5
));
$i=0;
if(!empty($expertise)){
$len = strlen($_GET['term']);
foreach($expertise as $valueproductname){
$pos = stripos($valueproductname['Expertise_area']['autocomplete_text'],$_GET['term']);
$keyvalue = "";
if($pos == 0) {
$keyvalue= "<strong>".substr($valueproductname['Expertise_area']['autocomplete_text'],$pos,$len)."</strong>"
.substr($valueproductname['Expertise_area']['autocomplete_text'],$len);
}else {
$keyvalue= substr($valueproductname['Expertise_area']['autocomplete_text'],0,$pos)."<strong>"
.substr($valueproductname['Expertise_area']['autocomplete_text'],$pos,$len)."</strong>"
.substr($valueproductname['Expertise_area']['autocomplete_text'],$pos+$len);
}
$response[$i]['value']=$valueproductname['Expertise_area']['autocomplete_text'];
$response[$i]['label']="<span class=\"username\">".$keyvalue."</span>";
$i++;
}
echo json_encode($response);
}else{
}
}
}
I have researched a bit and so far following solutions are worth looking at:
Query data on page load and store it in COOKIE to be used in future.
Implement some caching mechanism (memcache??). But my website is on Cakephp which does it internal cahcing if I am right. So will it be worth to go in this direction.
Use some third party indexing mechanism like Solr, Lucene etc. Don't know much about this.
Implement a much complex "Prefix Search" myself
What is the right way to go about it? Please help me out here.
I've never tried this but will be doing it soon for a project I'm working on.
I always considered the possibility of during the initial page load recieveing some AJAX (or perhaps just including it in the page) the top 10 words for each alphabet letter.. e.g.
A - apples, anoraks, alaska, angela, aha, air, arrgh, any, alpha, america
B - butter, bob etc.....
This way when user presses A-Z you can instantly provide them with 10 of the most popular keywords without any further requests, as you already have them stored in an array in the JS.
I'm not sure of size/memory usage but this could be extended further to handle the first 2 letters, e.g. AA, AB, AC.....BA, BB, BC.... ZA, ZB, ZZ... of course many combinations such as words starting with ZZ won't have any data unless it's a music site and it's ZZ Top! This means it probably won't take up so much memory or bandwidth to send this data during initial page load. Only when the user types the 3rd letter do you need to do any further data lookups/transfers.
You auto-update this data every day, week or whatever depending on site usage and the most popular searches.
I am adding a solution to my question which I figured out after a lot of research.
Problem was:
I was using Ajax to fetch keywords from database every time a user changes text in search box
I was doing a wild card search to match search item within entire strings and not just starting of keywords for ex. "dev" would return "social development", "development" etc
Solution:
I have a fixed array of keywords (200) which is not going to increase exponentially in near future. So, instead of doing complex indexing I am currently sending all keywords in an array.
I am sending this data in an array on page load since it is small. If it becomes large, I will fetch it in background via some ajax in different indexed arrays.
I am using jQuery's Autocomplete widget to do rest of thing for me.
For highlighting search item, I am using a hack by working around __renderItem. (Copied from Stackoverflow. Thanks to that!!)
Code:
function monkeyPatchAutocomplete() { //Hack to color search item
jQuery.ui.autocomplete.prototype._renderItem = function( ul, item) {
var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + this.term + ")(?![^<>]*>)(?![^&;]+;)", "gi");
var t = item.label.replace(re,"<span style='font-weight:bold;color:#434343;'>" +
"$&" +
"</span>");
return jQuery( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + t + "</a>" )
.appendTo( ul );
};
}
function getKeywords(){
//Function that returns list of keywords. I am using an array since my data is small.
//This function can be modified to fetch data in whatever way one want.
//I intend to use indexed arrays in future if my data becomes large.
var allKeywords = <?php echo json_encode($allKeywords); ?>;
return allKeywords;
}
jQuery(document).ready(function(){
monkeyPatchAutocomplete();
var CityKeyword = jQuery('#CityKeyword');
CityKeyword.autocomplete({
minLength : 1,
source : getKeywords()
});
});

Change all domains in links on a website

need some advice on how to fix an ugly situation. our forum has resided on a couple of different domains over the years. we lost one domain that was in use 5-6 yrs ago and apparently some posts on our forum still have links in the threads that point to the old domain. what would be the most efficient way to change all links that point to
http://www.olddomain.com/stuff
point to
http://www.newdomain.com/stuff
the only part that has changed is the domain name, all thread variables in the url remain the same. is this something that is best done client side with javascript/jquery or should it be handled on a server level with a PHP function (dont know where to begin here..)? some pseudocode that doesn't seem to do what I need it to on the client side...
$('a').each(function() {
var domanin = 'newdomain';
if(href.search('olddomain.com') != -1) {
$(this).attr('href', newdomain);
}
});
thank you
I think it will make more sense if you handle this in the back end. Search engines will not notice the change you make through JavaScript.
So I advise you search for those domains in your database and replace them there.
Well you should probably do this on the server side, as it was said before, but if you can't for whatever reason, here is what you could do on the javascript side of things.
$('a').each(function() {
this.host = 'www.newdomain.com';
});
Note that this example uses jQuery, but you could do the same in plain javascript with getElementsByTagName.
To do this in JavaScript (w/ jQuery):
$('a').each(function() {
var link = this.href;
if(link.search('olddomain.com') != -1) {
this.href = link.replace('olddomain.com', 'newdomain.com');
}
});
Here is a jsfiddle: http://jsfiddle.net/tHXxK/
However I would suggest changing the links in the database, just get rid of all the old references. To do this create a script that searches for the old URLs and replaces them, something like:
$query = mysql_query("SELECT [id], [link] FROM [table] WHERE [link] LIKE '%//olddomain.com/%' OR [link] LIKE '%//www.olddomain.com/%'", $db) or trigger_erroR(mysql_error());
while ($row = mysql_query($query)) {
$iQuery = mysql_query("UPDATE [table] SET [link]='" . mysql_real_escape_string(str_replace(array('//olddomain.com/', '//www.olddomain.com/'), array('//newdomain.com/', '//www.newdomain.com/'), $row['link']) . "' WHERE [id]=" . $row['id']), $db) or trigger_error(mysql_error());
}
If it'd be me, I would have used a server side script to replace all instances of the old domain with the new one and be done with it once and for all.
I assume your forum DB is rather a large one. For the sake of system resources you can write a multi-step script and do the job in multiple steps.
This is a better approach as it can improve the data consistency for search engines as well.

How to get the users who like your page? [duplicate]

I was wondering if it was possible to query the following:
List of (all) users who like my facebook page, and
Additional information those users have made publicly available (beyond first and last name)
Basically looking to generate detailed marketing stats of users who like my facebook page, if possible. Any suggestions or alternatives welcome.
Thank you.
I am afraid this is NOT possible, follow this bug for more information.
Another proof is the page_fan table you will notice that only the uid field is indexable so you need to know the user id to search it and not the page_id, as you know if a user "likes" a page this would mean he is a "fan" of that page.
After being actively working with the Facebook API for a while now, and following the announcements and API releases (and deprecations) along with the introduction and changes of policies, I can understand that Facebook will only share info about their users by letting them explicitly do so (a.k.a interact/authorize your Apps).
And hence the best thing to do in the absence of such feature is:
Understand your audience through Page Insights
Collect fans interests & info by creating custom apps through Page Tabs and using other Facebook features like Questions
Alright, nobody wants to break Facebook's TOS but they have tied our hands on our own basic data. So, scraping is illegal, but not saving a page. What I have done (and note that I needed this for offline purpose anyway):
Go to https://www.facebook.com/browse/?type=page_fans&page_id={FAN PAGE ID}
Scroll down until you have all of your fans. Save this page on your local machine, let's say, Facebook.html.
Now, using ruby and nokogiri:
require 'nokogiri'
>true
f = File.open('/your_path/Facebook.html')
doc = Nokogiri::HTML.parse(f.read)
doc.xpath('//div[#class="fsl fwb fcb"]/a').each {|link| puts link.content}
Do a graph search likes this: "People who like [your fanpage's name]". You will all the result.
Then create shortcut on your browser with this javascripts code, it will click on the View more link and scrolling until all result are shown in the page:
javascript: i = 0;minutes = 30;counter = minutes * 60;function repeatScroll() {
if (i < counter) {window.scrollTo(0, document.body.scrollHeight);i++;}
setTimeout(repeatScroll, 1000);}repeatScroll();
After that, create other shortcut and run this js code to retrieve all UID from the search result:
javascript:var txt="";e=document.getElementsByClassName("FriendRequestOutgoing");
for(var i=0; i<e.length; i++) {v=e[i].getAttribute("data-profileid");
if(v) txt+=v+"\n"}document.body.innerHTML="<textarea>"+txt+"</textarea>";
A textarea box will appear in the screen with all uid inside. Just copy it to your notepad and import into your Custom Audience in Facebook Ad Manager.
I created and use this code everyday to get all UID with criterial I need.
You can launch any graph search you want.
This is homemade code, so using it without your own responsibility :)
Enjoy them.
It's possible, just not with FQL anymore.
Do a GET of https://www.facebook.com/browse/?type=page_fans&page_id={FAN PAGE ID} and scrape out the users.
Viola.
Now you can get people on your page with this link, or click on Settings button, than on People on the left sidebar. https://www.facebook.com/[PAGENAME]/settings/?tab=people_and_other_pages
If you want to get all the user's photo, press F12 and add these codes to the Console:
javascript:i=0;minutes=30;counter=minutes*60;function repeatScroll(){if(i<counter){window.scrollTo(0, document.body.scrollHeight);i++;}setTimeout(repeatScroll,1000);}repeatScroll();
than, when you reached the bottom of the page:
javascript:var txt="";e=document.getElementsByClassName("img"); for(var i=0; i<e.length; i++) {v=e[i].getAttribute("src"); if(v) txt+="<img src='"+v+"'>\n"}document.body.innerHTML="<textarea>"+txt+"</textarea>";
To display photos: create a HTML page and first insert these lines into that file:
<meta charset="utf-8">
<style>img { width:21px; margin:-1px; }</style>
<div style="width:851px; height:315px;background-color:white;">
<!-- PASTE HERE PHOTOS' CODE YOU GET -->
<span style="color:#3B5998;font-weight:bold;font-size:20px;margin-bottom:4px;">600 like, thank you!</span>
<!-- PASTE HERE PHOTOS' CODE YOU GET -->
</div>
Then create shortcut on your browser with this javascript code, it will click on the View more link and scrolling until all result are shown in the page:
i = 0;
minutes = 30;
counter = minutes * 60;
function repeatScroll() {
if (i < counter) {
window.scrollTo(0, document.body.scrollHeight);
i++;
}
setTimeout(repeatScroll, 1000);
}
repeatScroll();
After that, create other shortcut and run this js code to retrieve all UID from the search result:
var e=document.getElementsByClassName("fsl fwb fcb");
var ids = [];
for(var i = 0 ; i < e.length; i++){
ids.push(JSON.parse(e[i].childNodes[0].getAttribute("data-gt")).engagement.eng_tid);
}
console.log(ids);
load all list
i = 0;
minutes = 30;
counter = minutes * 60;
function repeatScroll() {
if (i < counter) {
window.scrollTo(0, document.body.scrollHeight);
i++;
}
setTimeout(repeatScroll, 1000);
}
repeatScroll();
get id
var e=document.getElementsByClassName("_3cb8");
var ids = [];
for(var i = 0 ; i < e.length; i++){
ids.push(e[i].getAttribute("href"));
}
console.log(ids);
You can get it using facebook open graph.
https://graph.facebook.com/<your-page-name-or-page-id>/likes
For example :
https://graph.facebook.com/chickfila/likes
You need to send graph api call using "id" for more detail about user who like you page.
However, this call will retrieve the other Facebook objects that the page (Chickfila) has liked, NOT the users who have liked the Chickfila page.

Categories