Jump to content
Sign in to follow this  
Flashmaster82

Help with filtering based on the Skyscraper functions

Recommended Posts

Hi, i need some help with the filtering based on the Skyscrapers demo/func. I´m not that great with php so be patient.

My structure looks like this

Youtube videos > Youtube channel > Video

on the video template (youtube_channel_video) i have multiple drop down fields and other fields that i would like to filter on the front end. I also have other pages that need this functions with search/filter etc but with different filters.

 

This is the code i have in my search-form.php. Right now i experimenting with the field/option (category) that every video have in their template. The first filter (youtube_channel) works but im trying to get the category filter to work.

<div id='skyscraper-search' class='uk-panel uk-panel-box xuk-panel-box-primary uk-margin-bottom'>
	
	<h3 class='h3'>Youtube videos</h3>
	
	<form class='uk-form uk-form-stacked' method='get' action='<?php echo $config->urls->root?>search/'>

		<div class='row'>
			<label class='uk-form-label' for='search_keywords'>Keywords</label>
			<div class='uk-form-controls'>
				<input type='text' class='uk-form-width-large' name='keywords' id='search_keywords' value='<?php 
					if($input->whitelist('keywords')) echo $sanitizer->entities($input->whitelist('keywords')); ?>' />
			</div>
		</div>

		
			<div class='col-6'>
				<div class='row'>
					<label class='uk-form-label' for='youtube_channel'>Youtube channel</label>
					<div class='uk-form-controls'>
						<select id='youtube_channel' name='youtube_channel' class='uk-form-width-large'>
							<option value=''></option>
							<?php 
							// generate the youtube_channel options, checking the whitelist to see if any are already selected
							foreach($pages->find("template=youtube_channel_page") as $youtube_channel) {
								$selected = $youtube_channel->name == $input->whitelist->youtube_channel ? " selected='selected' " : ''; 
								echo "<option$selected value='{$youtube_channel->name}'>{$youtube_channel->title}</option>"; 
							}
							?>
						</select>
					</div>	
				</div>
			</div>


			<div class='col-6'>
				<div class='row'>
					<label class='uk-form-label' for='category'>Category</label>
					<div class='uk-form-controls'>
						<select id='category' name='category' class='uk-form-width-large'>
							<option value=''></option>
							<?php 
							// generate the category options, checking the whitelist to see if any are already selected
							foreach($pages->find("template=youtube_channel_video") as $category) {
								$selected = $category->youtube_video_category == $input->whitelist->youtube_video_category ? " selected='selected' " : ''; 
								echo "<option$selected value='{$category->youtube_video_category}'>{$category->youtube_video_category->title}</option>"; 
							}
							?>
						</select>
					</div>	
				</div>
			</div>
		
		
		

		<div class='uk-margin-top'>
			<button type='submit' id='search_submit' class='uk-button uk-button-primary' name='submit' value='1'>
				<i class='uk-icon-search'></i>
				Search
			</button>
		</div>

	</form>
</div>

 

This is my search.php

<?php namespace ProcessWire;

$selector = '';



$summary = array(
	"title" => "",
	"youtube_channel" => "",
	"category" => "",
	"country" => "", 
	);




if($input->get('youtube_channel')) {
	$youtube_channelName = $sanitizer->pageName($input->get('youtube_channel'));
	$youtube_channel = pages("/youtube-videos/$youtube_channelName/");
	if($youtube_channel->id) {
		$selector .= "parent=$youtube_channel, ";
		$summary['youtube_channel'] = $youtube_channel->title;
		$input->whitelist('youtube_channel', $youtube_channel->name); 
	}
}




foreach(array('category') as $key) {

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

	 else {	
		$value = (int) $value; 
		$selector .= "$key=$value, ";
		$summary[$key] = $value;
		$input->whitelist($key, $value); 
	}
}




if($input->get('keywords')) {
	$value = $sanitizer->selectorValue($input->get('keywords'));
	$selector .= "title|body|category%=$value, sort=title"; 
	$summary["keywords"] = $sanitizer->entities($value); 
	$input->whitelist('keywords', $value); 
}


$videos = findSkyscrapers($selector);




$browserTitle = 'Youtube video search - ';

foreach($summary as $key => $value) {
	if($value) {
		$key = ucfirst($key);
		$browserTitle .= ucfirst($key) . ": $value, ";
	} else {
		unset($summary[$key]);
	}
}




region('browserTitle', rtrim($browserTitle, ', '));
region('content',
	files()->render('./includes/search-summary.php', array('items' => $summary)) . 
	renderSkyscraperList($videos)
);

 

This is my skyscraper-list-item.php file

 

<?php
echo " 
<div class='col-12 col-sm-12 col-md-6 col-lg-6 col-xl-4 col-xxl-4 col-xxxl-4 bmar10'>
<div class='youtube_search_holder'>
<a data-fancybox data-autoclose='true' data-width='1500' data-height='844' data-height='360' href='{$skyscraper->youtube}autoplay=1'>
<div class='youtube_thumbnail_placeholder'><img src='{$skyscraper->youtube_thumbnail->url}' class='youtube_thumbnail_image w-100'>
 <div class='playicon'></div></div></a>
 <div class='youtube_search_thumbnail_content'>
 <div class='h6 text-uppercase green tmar3 title'><a href='{$skyscraper->parent->channel_url}' target='_blank' title='{$skyscraper->parent->title}'>{$skyscraper->parent->title}</a></div><div class='text-uppercase white h3 limit'><a href='{$skyscraper->youtube}' data-fancybox data-width='1500' data-height='844' data-height='360'>{$skyscraper->title}</a></div>
 <div class='h5 text-uppercase gray date'>{$skyscraper->youtube_video_publishdate}</div>
<span class='white h7'>
{$skyscraper->youtube_video_category->title}
{$skyscraper->countries->title}
{$skyscraper->competition->title}
{$skyscraper->competition->parent->parent->title}
{$skyscraper->armwrestler_competition_gender->title}
{$skyscraper->armwrestler_arm->title}
{$skyscraper->armwrestler_age_category->title}
{$skyscraper->competition_weight_class->title}
{$skyscraper->competition_video_match->title}
{$skyscraper->videotags}
</span>

</div></div></div>
";
?>

This is the front end right now (no styling 🙂

bild.thumb.png.e94245452d70ab29307d3b084438f2a0.png

In the category filter, right now there is multiple categories with the same name, i would also like to restrict it to just one result per category.

Please help!

Share this post


Link to post
Share on other sites
17 hours ago, Flashmaster82 said:

i have multiple drop down fields and other fields that i would like to filter on the front end.

Hi. I didn't have time to go through all your code, so you might have already answered this.

  1. It is not clear to me which is the search form that triggers the initial search. Is it the keywords or the channel or both and the category as well?
  2. Normally, with search dynamic selects, you need both PHP and JavaScript. Do you need help with the JavaScript as well?
  3. How do you want the results returned? For instance, if you fetch a parent, do you want it to come with all its children in one go?

Share this post


Link to post
Share on other sites

Hi Kongondo and thanks for replying.

 

Here is the _func.php. All files are straight from the Skyscrapers demo btw.

<?php namespace ProcessWire;

/***************************************************************************************
 * SHARED SKYSCRAPER FUNCTIONS
 *
 * The following functions find and render skyscrapers are are defined here so that
 * they can be used by multiple template files.
 *
 */

/**
 * Returns an array of valid skyscraper sort properties
 *
 * The keys for the array are the field names
 * The values for the array are the printable labels
 *
 * @return array
 *
 */
function getValidSorts() {
	return array(
		// field => label
		'name' => 'Name (A-Z)',
		'-name' => 'Name (Z-A)',
		'date' => 'Publish date (asc)',
		'-date' => 'Publish date (desc)',
	);
}

/**
 * Find Skyscraper pages using criteria from the given selector string.
 *
 * Serves as a front-end to $pages->find(), filling in some of the redundant
 * functionality used by multiple template files.
 *
 * @param string $selector
 * @return PageArray
 *
 */
function findSkyscrapers($selector) {

	$validSorts = getValidSorts();

	// check if there is a valid 'sort' var in the GET variables
	$sort = sanitizer('name', input()->get('sort'));

	// if no valid sort, then use 'title' as a default
	if(!$sort || !isset($validSorts[$sort])) $sort = 'name';

	// whitelist the sort value so that it is retained in pagination
	if($sort != 'name') input()->whitelist('sort', $sort);

	// expand on the provided selector to limit it to 10 sorted skyscrapers
	$selector = "template=youtube_channel_video, limit=20, " . trim($selector, ", ");

	// check if there are any keyword searches in the selector by looking for the presence of 
	// ~= operator. if present, then omit the 'sort' param, since ProcessWire sorts by 
	// relevance when no sort specified.
	if(strpos($selector, "~=") === false) $selector .= ", sort=$sort";

	// now call upon ProcessWire to find the skyscrapers for us
	$skyscrapers = pages($selector);

	// save skyscrapers for possible display in a map
	mapSkyscrapers($skyscrapers);

	return $skyscrapers;
}

/**
 * Serves as a place to store and retrieve loaded skyscrapers that will be displayed in a google map.
 *
 * To add skyscrapers, pass in a PageArray of them.
 * To retrieve skyscreapers, pass in nothing and retrieve the returned value.
 *
 * @param null|PageArray $items Skyscraper pages to store
 * @return PageArray All Skyscraper pages stored so far
 *
 */
function mapSkyscrapers($items = null) {
	static $skyscrapers = null;
	if(is_null($skyscrapers)) $skyscrapers = new PageArray();
	if(!is_null($items) && $items instanceof PageArray) $skyscrapers->add($items);
	return $skyscrapers;
}

/**
 * Render the <thead> portion of a Skyscraper list table
 *
 * @return string
 *
 */
function renderSkyscraperListSort() {

	// query string that will be used to retain other GET variables in searches
	input()->whitelist->remove('sort');
	$queryString = input()->whitelist->queryString();
	if($queryString) $queryString = sanitizer('entities', "&$queryString");

	// get the 'sort' property, if it's present
	$sort = input()->get('sort');
	$validSorts = getValidSorts();
	
	// validate the 'sort' pulled from input
	if(!$sort || !isset($validSorts[$sort])) $sort = 'name';

	$options = array();
	$selectedLabel = '';

	// generate options
	foreach($validSorts as $key => $label) {
		if($key === $sort) $selectedLabel = $label;
		$options["./?sort=$key$queryString"] = $label;
	}

	// render output
	$out = files()->render('./includes/skyscraper-list-sort.php', array(
		'options' => $options, 
		'selectedLabel' => $selectedLabel
	));
	
	return $out;
}


/**
 * Render a list of skyscrapers
 *
 * @param PageArray $skyscrapers Skyscrapers to render
 * @param bool $showPagination Whether pagination links should be shown
 * @param string $headline
 * @return string The rendered markup
 *
 */
function renderSkyscraperList(PageArray $skyscrapers, $showPagination = true, $headline = '') {

	$pagination = '';
	$sortSelect = '';
	$items = array();
	
	if($showPagination && $skyscrapers->count()) {
		$headline = $skyscrapers->getPaginationString('Skyscrapers'); // i.e. Skyscrapers 1-10 of 500
		$pagination = renderPagination($skyscrapers); // pagination links
		$sortSelect = renderSkyscraperListSort();
	}

	foreach($skyscrapers as $skyscraper) {
		$items[] = renderSkyscraperListItem($skyscraper);
	}

	$selector = (string) $skyscrapers->getSelectors();
	if($selector) $selector = makePrettySelector($selector);
	
	$out = files()->render('./includes/skyscraper-list.php', array(
		'skyscrapers' => $skyscrapers, 
		'headline' => $headline, 
		'items' => $items, 
		'pagination' => $pagination, 
		'sortSelect' => $sortSelect, 
		'selector' => $selector
	));
		
	return $out;
}

/**
 * Render a single skyscraper for presentation in a skyscraper list
 *
 * @param Page $skyscraper The Skyscraper to render
 * @return string
 *
 */
function renderSkyscraperListItem(Page $skyscraper) {


	// here's a fun trick, set what gets displayed when value isn't available.
	// the property "unknown" is just something we made up and are setting to the page.
	$skyscraper->set('unknown', '??');

	// send to our view file in includes/skyscraper-list-item.php
	$out = files()->render('./includes/skyscraper-list-item.php', array(
		'skyscraper' => $skyscraper,
		'title' => $skyscraper->title, 
		'category' => $skyscraper->youtube_video_category->title,
	));
	
	return $out;
}

/**
 * ProcessWire pagination nav for UIkit
 *
 * @param PageArray $items
 * @return string
 *
 */
function renderPagination(PageArray $items) {

	if(!$items->getLimit() || $items->getTotal() <= $items->getLimit()) return '';
	$page = page();
	if(!$page->template->allowPageNum) {
		return "Pagination is not enabled for this template";
	}

	// customize the MarkupPagerNav to output in Foundation-style pagination links
	$options = array(
		'numPageLinks' => 5, 
		'nextItemLabel' => '<i class="uk-icon-angle-double-right"></i>',
		'nextItemClass' => '',
		'previousItemLabel' => '<span><i class="uk-icon-angle-double-left"></i></span>',
		'previousItemClass' => '',
		'lastItemClass' => '',
		'currentItemClass' => 'uk-active',
		'separatorItemLabel' => '<span>&hellip;</span>',
		'separatorItemClass' => 'uk-disabled',
		'listMarkup' => "<ul class='uk-pagination uk-text-left'>{out}</ul>",
		'itemMarkup' => "<li class='{class}'>{out}</li>",
		'linkMarkup' => "<a href='{url}'>{out}</a>",
		'currentLinkMarkup' => "<span>{out}</span>"
	);

	$pager = modules('MarkupPagerNav');
	$pager->setBaseUrl($page->url);

	return $pager->render($items, $options);
}

/**
 * Make the selector better for display readability
 *
 * Since we're displaying the selector to screen for demonstration purposes, this method optimizes the
 * selector is the most readable fashion and removes any parts that aren't necessary
 *
 * This is not something you would bother with on a site that wasn't demonstrating a CMS. :)
 * 
 * @param string $selector
 * @return string
 *
 */
function makePrettySelector($selector) {
	if(preg_match('/(architects|parent)=(\d+)/', $selector, $matches)) {
		if($page = pages()->get($matches[2]))
			$selector = str_replace($matches[0], "$matches[1]={$page->path}", $selector);
		if($matches[1] == 'parent') $selector = str_replace("template=youtube_channel_video, ", "", $selector); // template not necessary here
	}
	$selector = sanitizer('entities', $selector);
	$span = "<span class='uk-text-nowrap'>";
	$selector = $span . str_replace(", ", ",</span> $span ", $selector) . "</span>";
	return $selector;
}


/**
 * Generate a summary from the given block of text or HTML and truncate to last sentence
 *
 * @param string $text
 * @param int $maxLength
 * @return string
 *
 */
function summarizeText($text, $maxLength = 500) {

	if(!strlen($text)) return '';
	$summary = trim(strip_tags($text));
	if(strlen($summary) <= $maxLength) return $summary;

	$summary = substr($summary, 0, $maxLength);
	$lastPos = 0;

	foreach(array('. ', '!', '?') as $punct) {
		// truncate to last sentence
		$pos = strrpos($summary, $punct);
		if($pos > $lastPos) $lastPos = $pos;
	}

	if(!$lastPos) {
		// if no last sentence was found, truncate to last space
		$lastPos = strrpos($summary, ' ');
	}

	if($lastPos) {
		$summary = substr($summary, 0, $lastPos + 1); // and truncate to last sentence
	}

	return trim($summary);
}

 

The main thing i want to fix is how to add more filters. The one that i working with is (categories).

 

If i only filter with youtube channel (which is a modifyed by the city filter) it works and the result are visible, but then the category filter is not working.

 

bild.thumb.png.ac98017f6e3cecbb126cecd44c34139e.png

 

 

So in the search-form.php i have this. The first section in the code below is the drop down for the channels and the second is the category filter.

	<div class='col-6'>
				<div class='row'>
					<label class='uk-form-label' for='youtube_channel'>Youtube channel</label>
					<div class='uk-form-controls'>
						<select id='youtube_channel' name='youtube_channel' class='uk-form-width-large'>
							<option value=''></option>
							<?php 
							// generate the youtube_channel options, checking the whitelist to see if any are already selected
							foreach($pages->find("template=youtube_channel_page") as $youtube_channel) {
								$selected = $youtube_channel->name == $input->whitelist->youtube_channel ? " selected='selected' " : ''; 
								echo "<option$selected value='{$youtube_channel->name}'>{$youtube_channel->title}</option>"; 
							}
							?>
						</select>
					</div>	
				</div>
			</div>


			<div class='col-6'>
				<div class='row'>
					<label class='uk-form-label' for='category'>Category</label>
					<div class='uk-form-controls'>
						<select id='category' name='category' class='uk-form-width-large'>
							<option value=''>Category</option>
							<?php 
							// generate the category options, checking the whitelist to see if any are already selected
							foreach($pages->find("template=youtube_channel_video, sort=youtube_video_category") as $category) {
								$selected = $category->youtube_video_category == $input->whitelist->youtube_video_category->title ? " selected='selected' " : ''; 
								echo "<option$selected value='{$category->youtube_video_category}'>{$category->youtube_video_category->title}</option>"; 
							}
							?>
						</select>
					</div>	
				</div>
			</div>

 

and then in the search.php i have this.

<?php namespace ProcessWire;

$selector = '';



$summary = array(
	"title" => "",
	"youtube_channel" => "",
	"category" => "",
	);






if($input->get('youtube_channel')) {
	$youtube_channelName = $sanitizer->pageName($input->get('youtube_channel'));
	$youtube_channel = pages("/youtube-videos/$youtube_channelName/");
	if($youtube_channel->id) {
		$selector .= "parent=$youtube_channel, ";
		$summary['youtube_channel'] = $youtube_channel->title;
		$input->whitelist('youtube_channel', $youtube_channel->name); 
	}
}





foreach(array('category', '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($input->get('keywords')) {
	$value = $sanitizer->selectorValue($input->get('keywords'));
	$selector .= "title|body%=$value, sort=title"; 
	$summary["keywords"] = $sanitizer->entities($value); 
	$input->whitelist('keywords', $value); 
}


$videos = findSkyscrapers($selector);




$browserTitle = 'Youtube video search - ';

foreach($summary as $key => $value) {
	if($value) {
		$key = ucfirst($key);
		$browserTitle .= ucfirst($key) . ": $value, ";
	} else {
		unset($summary[$key]);
	}
}




region('browserTitle', rtrim($browserTitle, ', '));
region('content',
	files()->render('./includes/search-summary.php', array('items' => $summary)) . 
	renderSkyscraperList($videos)
);

 

The code that starts with this is what im trying to modify from the demo, but its wrong of course, because in the demo it targets a field and a range (floors/year). My filter with category is an drop down option field in the backend. When im loading the page website/search.php it shows all the youtube videos and the pagination, so it works but its only the category filter that is wrong just to be clear.

foreach(array('category', 'floors', 'year') as $key) {

Share this post


Link to post
Share on other sites

Ok to make it more understandable. This is the other filter (dropdown) in the skyscraper demo. This works but in my case i dont want to be filtering with any range only specific category.

search-form.php

<div class='uk-width-1-2'>
				<div class='uk-form-row'>
					<label class='uk-form-label' for='search_floors'>Floors</label>
					<div class='uk-form-controls'>
						<select id='search_floors' name='floors' class='uk-form-width-large'>
							<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>
					</div>	
				</div>
			</div>	

 

and in the search.php

foreach(array('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);
        }
}

 

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Bacelo
      Hi there,
      I have a bit of trouble on filtering correctly some event pages by some selectors...
      I do have the following 2 date fields:
      - start date (fieldname = date)
      - end date (fieldname = enddate)

      Some events are a single day event (only start date) - some are a multi day event (end date).
      Past single day events should not show up.
      Current multi day events should show up (even if start day is in the past, but end date is future).
      So I have the following selector:
      if ($standort == '') { $termine = $page->children("sort=date, limit=10, (date>=today, enddate=''), (enddate>=today)"); } else { $termine = $page->children( "(standort_reference~=$standort), (standort_alle=1), (date>=today, enddate=''), (enddate>=today), sort=date, limit=10"); } This selector
      $termine = $page->children("sort=date, limit=10, (date>=today, enddate=''), (enddate>=today)"); works fine, but the follwing does not work (all past entries are also shown):
      $termine = $page->children( "(standort_reference~=$standort), (standort_alle=1), (date>=today, enddate=''), (enddate>=today), sort=date, limit=10"); I have no clue what I'm missing - any ideas?
    • By Moritz Both
      Greetings,
      when I give users the user-admin-* permission to administer users who have a certain role, they can indeed see and edit those users. However the filter / column panel does not show in the admin interface. How can I enable the filter functionality for user-admin-* members?
      ProcessWire 3.0.123
      Moritz
    • By j00st
      Hi all,

      I've set up a filter on my product-page, which I then use to...filter my products!
      – I've got pagination set up, and 30 items per page.
      – When I active the filter it works perfectly (in my opinion).
       
      Here's what I'm struggling with though:
      When I'm on another page (filtered as well/or the total overview) and I put my GET request in for the filter,
      it gives back the result, but still with the page-number there. In some cases, this is no problem – like a A-Z or Z-A filter,
      but others (say, per location) I might have less pages.
      Visual/code ref: (I DO have 3 pages of authors, but I don't have 3 pages from London)
      url: books/page3?author=ascending url: books/page3?studio=london  
      The current setup for my pages that get rendered are as follows:
      $allbooks = $pages->find("template=book, sort=$sort, $q, $tagged, $select_studio, start=0, limit=$limit"); As you can see I have the start=0 in there, but I read that's for the start of the pagination, not so much where it'll drop me in the search results.
      $q, $tagged and $select_studio are all empty values, unless they're returned from the GET request
      To repeat it, in it's most simplest form:
      When I click a filter, and a GET request is done, I want to 'reset' the page-number to 0, and get my results...
      Perhaps I'm missing something obvious, but I'd be really grateful to have your input.
    • By Vigilante
      This is a pretty typical thing. Open a page, it does a $pages query, finds 112 things and I list them on the page. There is pagination too, 20 per page.
      I want a sort dropdown box so the visitor can change alpha sort or whatever other sorts and filters I eventually use.
      My first thought is to just refresh the page with a url query like "page/?sort=az" and then adjust the query in the template code. But to do this, it will require a page refresh, which means the sort box goes back to its default, and not sure how it effects pagination.
      If I do a page refresh, I'll have to keep the sort settings in the session or something, to make sure I always apply correct sort on page load.
      But at the same time, I've already got the $pages array, it would be much nicer to shuffle it and update the page without a page refresh, rather than run the query over and over again.
      But then again, the pagination buttons already cause page refreshes, so that is already happening anyway, unless I convert the pagination buttons to also be no-refresh somehow.
       
      I figure this is a very common problem, to paginate results and give users a sorting/filtering option. What is the common methods for handling it? Session, url query, ajax? If I just add the sort to the url query, how do I make that work in the pagination links?
    • By dscONE
      Found myself needing to filter repeater items based upon start and end date fields.  These fields aren't required, so repeater items with no dates should be included and those with dates (or a just one date -- start or end) should be evaluated for inclusion.
      I slowly figured out that I was dealing with in-memory filtering (of a RepeaterPageArray) and not a database-driven operation.  So, that eliminated the possibility of using or-groups in my selector.  I still thought I could use the 'filter' and 'not' functions to get the job done.  Turns out the way selectors are handled for in-memory filtering is quite different from database-driven selectors.
      Here is what I want(ed) to do to filter the dates:
      // Start date not specified or in the past $repeater->filter('start_time<='.$now); // Not when end date is specified and has passed $repeater->not('end_time>0, end_time<'.$now); The first one worked exactly as expected.  The second it where I ran into problems.  The 'filter' function (which calls the 'filterData' function) takes a $selector argument.  From everything I read about selectors, I assumed that the entire selector would have to match.  In other words, each comma represented an 'and' scenario.  Turns out that each separate comma-separated-selector in the $selector as a whole gets evaluated independently.  In the case of the 'filterData' function, the elements are removed if any one of those selectors matches.  Essentially, we have an 'or' scenario instead of an 'and' scenario.
      In my case above, there was no way for me to filter for a non-empty date AND one that occurs before a given date...at least that I could think of.
      So, my main question is if the filter (and related) function should operate on the entire selector passed to the function instead of its individual parts in some sequence.  That is what I would have assumed a selector to do.
      In my project, altering the segment of the WireArray::filterData function solved my problem for now.  ...at least till I forget about it and overwrite it when I upgrade next.  Here is the code I changed within the function
      // now filter the data according to the selectors that remain foreach($this->data as $key => $item) { $filter_item = true; foreach($selectors as $selector) { if(is_array($selector->field)) { $value = array(); foreach($selector->field as $field) $value[] = (string) $this->getItemPropertyValue($item, $field); } else { $value = (string) $this->getItemPropertyValue($item, $selector->field); } if($not === $selector->matches($value)) continue; $filter_item = false; break; } if($filter_item && isset($this->data[$key])) { $this->trackRemove($this->data[$key], $key); unset($this->data[$key]); } } I would love to hear what you all think.  If I have misunderstood something, then I would welcome a different solution.
      Thanks!
×
×
  • Create New...