Jump to content
formmailer

Simple "drop down search"

Recommended Posts

Hi,

I am trying to create a simple search form with drop downs, just like the search on the skyscraper demo site.

I know that the selectors should look something like this:

$pages->find("template=citytrips, limit=10, price>=250, price<=400, transportation=airplane, touroperator=xxx inc.");

but I can't really figure out how to use this in a search template.

Therefore I would like to ask Ryan if it's possible to take a look at the source files of the demo site, so I can learn from these?

Of course, all other tips and suggestions to achieve this fairly simple search are greatly appreciated.

Thanks in advance!

//Jasper

Share this post


Link to post
Share on other sites

Here's what draws the form for the skyscrapers search:

<form id='skyscraper_search' method='get' action='<?php echo $config->urls->root?>search/'>
<h3>Skyscraper Search</h3>

<p>
<label for='search_keywords'>Keywords</label>
<input type='text' name='keywords' id='search_keywords' value='<?php 
	if($input->whitelist->keywords) echo htmlentities($input->whitelist->keywords, ENT_QUOTES); ?>' />
</p>

<p>
<label for='search_city'>City</label>
<select id='search_city' name='city'>
		<option value=''>Any</option>
		<?php
		// generate the city options, checking the whitelist to see if any are already selected
		foreach($pages->get("/cities/")->children() as $city) {
				$selected = $city->name == $input->whitelist->city ? " selected='selected' " : '';
				echo "<option$selected value='{$city->name}'>{$city->title}</option>";
		}
		?>

</select>
</p>

<p>
<label for='search_height'>Height</label>
<select id='search_height' name='height'>
		<option value=''>Any</option>
		<?php
		// generate a range of heights, checking our whitelist to see if any are already selected
		foreach(array('0-250', '250-500', '500-750', '750-1000', '1000+') as $range) {
				$selected = $range == $input->whitelist->height ? " selected='selected'" : '';
				echo "<option$selected value='$range'>$range ft.</option>";
		}
		?>

</select>
</p>

<p>
<label for='search_floors'>Floors</label>
<select id='search_floors' name='floors'>
		<option value=''>Any</option>
		<?php
		// generate our range of floors, checking to see if any are already selected
		foreach(array('1-20', '20-40', '40-60', '60-80', '80+') as $range) {
				$selected = $range == $input->whitelist->floors ? " selected='selected'" : '';
				echo "<option$selected value='$range'>$range floors</option>";
		}
		?>

</select>
</p>

<p>
<label for='search_year'>Year</label>
<select id='search_year' name='year'>
		<option value=''>Any</option>
		<?php
		// generate a range of years by decade, checking to see if any are selected
		for($year = 1850; $year <= 2010; $year += 10){
				$endYear = $year+9;
				$range = "$year-$endYear";
				$selected = $input->whitelist->year == $range ? " selected='selected'" : '';
				echo "<option$selected value='$range'>{$year}s</option>";
		}
		?>

</select>
</p>

<p><input type='submit' id='search_submit' name='submit' value='Search' /></p>

</form>

And here's the code that processes it and performs the search:

<?php

/**
* This template looks for search terms as GET vars and formulates a selector to find matching skyscrapers
*
*/

// most of the code in this template file is here to build this selector string
// it will contain the search query that gets sent to $skyscraperList
$selector = '';

// we use this to store the info that generates the summary of what was searched for
// the summary will appear above the search results
$summary = array(
        "city" => "",
        "height" => "",
        "floors" => "",
        "year" => "",
        "keywords" => "",
        );

// if a city is specified, then we limit the results to having that city as their parent
if($input->get->city) {
        $city = $pages->get("/cities/" . $sanitizer->pageName($input->get->city));
        if($city) {
                $selector .= "parent=$city, ";
                $summary["city"] = $city->title;
                $input->whitelist('city', $city->name);
        }
}

// we are allowing these GET vars in the format of 999, 999-9999, or 999+
// so we're using this loop to parse them into a selector
foreach(array('height', 'floors', 'year') as $key) {

        if(!$value = $input->get->$key) continue;

        // see if the value is given as a range (i.e. two numbers separated by a dash)
        if(strpos($value, '-') !== false) {
                list($min, $max) = explode('-', $value);
                $min = (int) $min;
                $max = (int) $max;
                $selector .= "$key>=$min, $key<=$max, ";
                $summary[$key] = (substr($max, 0, 3) == '999') ? "$min and above" : "$min to $max";
                $input->whitelist($key, "$min-$max");

        // see if the value ends with a +, which we used to indicate 'greater than or equal to'
        } else if(substr($value, -1) == '+') {
                $value = (int) $value;
                $selector .= "$key>=$value, ";
                $summary[$key] = "$value and above";
                $input->whitelist($key, "$value+");

        // plain value that doesn't need further parsing
        } else {
                $value = (int) $value;
                $selector .= "$key=$value, ";
                $summary[$key] = $value;
                $input->whitelist($key, $value);
        }
}

// if there are keywords, look in the title and body fields for the words. Note in our selector
// we are using the "~=" operator, rather than the "*=" operator, which means that we want to 
// match all the words, but they don't have to be in a phrase right next to each other.
if($input->get->keywords) {
        $value = $sanitizer->selectorValue($input->get->keywords);
        $selector .= "title|body~=$value, ";
        $summary["keywords"] = htmlentities($value);
        $input->whitelist('keywords', $value);
}

// display a summary of what was searched for above the search results
$content = "<ul id='search_summary'>";
$browserTitle = "Skyscrapers - ";

foreach($summary as $key => $value) {
        if(!$value) continue;
        $key = ucfirst($key); 
        $content .= "\n\t<li><strong>$key:</strong> $value</li>";
        $browserTitle .= "$key: $value, ";
}         
         
$content .= "\n</ul>";  
$skyscrapers = $pages->find($selector); 
$content .= $skyscrapers->render(); // substitute your own output code
$browserTitle = rtrim($browserTitle, ", "); 
$headline = "Skyscraper Search";

include("./main.php"); 
  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Thanks Ryan! I think this covers most (if not all) of my needs right now.

/Jasper

Share this post


Link to post
Share on other sites

Now I just have one issue left regarding this "simple" search...

How can I populate my dropdown with touroperators? I can't do it the same way Ryan did with the cities, because there are no seperate branches in the tree for all touroperators.

As it is now, touroperaror is just a textfield in the "citytrip-template".

Any suggestions?

/Jasper

Share this post


Link to post
Share on other sites

You should be able to do something like this to get an array containing your tour operators:

$touroperators = $fields->find("touroperator"); 

A similar example is on this page: http://processwire.com/api/selectors/

Basically you can use "find" on pretty much anything - templates, fields, users and pages by prefixing find with the object you're looking for.

Share this post


Link to post
Share on other sites

Thanks! I still have some problems to come up with things like that myself, but I am sure I'll learn it one day...  :P

/Jasper

Share this post


Link to post
Share on other sites

No worries - that's what the community is here for :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...