37 require_once realpath(dirname(__FILE__).
"/search_form.inc");
38 require_once realpath(dirname(__FILE__).
"/auto_form_layout.inc");
39 require_once realpath(dirname(__FILE__).
"/field_renderers/select_field_renderer.inc");
40 require_once realpath(dirname(__FILE__).
"/field_renderers/date_field_renderer.inc");
41 require_once realpath(dirname(__FILE__).
"/field_renderers/boolean_field_renderer.inc");
42 require_once realpath(dirname(__FILE__).
"/field_renderers/checklist_field_renderer.inc");
134 $this->formCSS =
"filter";
140 return str_replace(
"{url}", $url, $this->navigationFunction);
149 $this->navigationMode = $mode;
150 if ($mode ==
"panel")
152 $this->navigationFunction =
"loadPanel(form, '{url}');";
153 $this->onSubmitHandler =
"{$this->id}_loadPanel";
154 $this->action = Fakoli::scriptName();
160 return "onSubmit{$this->id}";
165 if ($this->navigationMode ==
"panel")
167 $script = <<<ENDSCRIPT
168 <script type=
"text/javascript">
169 function {$this->
id}_loadPanel(form)
171 var form =
new Element(form);
172 var url = form.action +
"?" + form.toQueryString();
179 return $script . parent::writeScript();
182 private function sessionKey()
184 $base = preg_replace(
"/\\?.*/",
"", $_SERVER[
"REQUEST_URI"]);
185 return "filter:{$this->id}:{$base}";
188 private function loadFilterFromSession()
190 if (isset($_SESSION[$this->sessionKey()]))
192 $this->params->copy(unserialize($_SESSION[$this->sessionKey()]));
193 $this->data =& $this->params->target;
197 private function saveFilterToSession()
199 if (!$this->params->isDefaultState)
201 $_SESSION[$this->sessionKey()] = serialize($this->params);
205 unset($_SESSION[$this->sessionKey()]);
212 $pk = $obj->getPrimaryKey();
213 if ($this->preserveQueryString)
222 echo
"<form id='{$this->id}' method='{$this->method}' action='{$this->action}' enctype='multipart/form-data'";
223 if (!$this->ajaxSubmitHandler)
225 echo
" onsubmit='return onSubmit{$this->id}(this);'";
228 if ($this->navigationMode ==
'panel')
230 echo
" data-mode='ajax'";
235 if ($this->formCSS) echo
" class='{$this->formCSS}'";
236 if ($this->style) echo
" style='{$this->style}'";
239 foreach(array_keys($this->hidden) as
$hidden)
241 if ($obj->filter && $obj->filter->isExcluded(
$hidden))
continue;
243 echo
"<input id='{$this->id}_{$hidden}' type='hidden' name='$hidden' value='".htmlSafe($obj->get(
$hidden)).
"'/>\n";
246 if ($this->preserveQueryString)
248 foreach($_GET as $key => $value)
250 if ($key ==
"identifier" || $key ==
"section" || $key ==
"submit" || array_key_exists($this->hidden, $key) || $obj->hasField($key))
continue;
251 echo
"<input id='{$this->id}_{$key}' type='hidden' name='$key' value='".htmlSafe($value).
"'/>\n";
255 $this->layout->startUngrouped();
257 if ($this->formLabel) echo
"<div class='filter_form_label'><label>{$this->formLabel}</label></div>";
259 if ($this->showSubmitButton)
261 echo
"<input type='submit' class='button' value='{$this->submitButtonLabel}'/>";
266 echo
"<input type='submit' style='display: none'/>";
269 $this->layout->endUngrouped();
271 $this->layout->finalizeLayout();
274 echo
"<div style=\"clear: both\">\n</div>\n";
284 $filter = $obj->getFilter();
286 if (count($this->groups) > 0)
288 $this->layout->endUngrouped();
290 foreach($this->groups as $legend =>
$fields)
292 $collapsible = array_key_exists($legend, $this->collapsibleGroups);
295 $cf = $this->collapsibleGroups[$legend];
296 $collapsed = !$this->data->$cf;
299 $this->layout->startGroup($legend, $collapsible, $collapsed);
303 if ($field != $pk && !array_key_exists($field, $this->hidden) && !array_key_exists($field, $this->renderedFields) && !($filter && $filter->isExcluded($field)))
309 $this->layout->endGroup();
312 $this->layout->startUngrouped();
316 foreach(array_keys($this->fields) as $field)
318 if ($field != $pk && !array_key_exists($field, $this->hidden) && !array_key_exists($field, $this->renderedFields) && !($filter && $filter->isExcluded($field)))
321 if(get_class($renderer) == DateRangeFilterRenderer)
323 $dateRangeField = $field;
330 foreach($this->additional as $r)
332 $renderer = $r[
'renderer'];
333 $field = $r[
'field'];
335 $field = $renderer->field;
336 if (!array_key_exists($field, $this->renderedFields))
338 if(get_class($renderer) == DateRangeFilterRenderer)
340 $dateRangeField = $field;
362 $this->params->paramHandlers[$field] = $handler;
381 foreach(array_keys(
$fields) as $field)
383 if (!array_key_exists($field, $this->hidden) &&
384 !($obj->filter && $obj->filter->isExcluded($field))
387 $value = $obj->get($field);
393 $this->params->setParam($field,
"equal", $value);
400 if ($this->rememberFilter)
402 if ($this->params->isDefaultState)
404 $this->loadFilterFromSession();
408 $this->saveFilterToSession();
412 return $this->params->generateConstraint($first, $firstText);
417 $this->params->setParam($field, $mode, $value);
443 if ($form->getData()->hasField($field))
447 $form->override($field,
$label, $this);
448 if ($this->options ==
null)
450 $opt = $form->getData()->distinctValues($field,
true);
453 $this->options = array_combine($opt, $opt);
457 $this->options = array();
463 $form->add($this, $field);
465 $form->overrides[$field][
'label'] =
$label;
471 $this->
default = $title;
472 $this->defaultValue = $value;
477 $this->_startField($field, $this->styles);
481 $styles .=
"style='width: {$this->width}'";
484 $onSubmit = $this->parent->getOnSubmitFunction();
485 echo
"<select name='{$field}' {$styles} onchange='if ({$onSubmit}(this.form)) this.form.manager.submit();'>";
490 <
option value=
"<?php echo $this->defaultValue ?>"><?echo $this->
default?></
option>
497 <
option value=
"<?php echo $this->all_value ?>">All</
option>
501 $fieldValue = $this->parent->data->get(
"$field");
502 foreach($this->options as $value => $name)
504 $name = htmlSafe($name);
505 $trunced = $this->max_chars ?
ellipsis($name, $this->max_chars,
true) : $name;
507 $selected = (!strcmp($value, $fieldValue)) ?
" selected" :
"";
508 $optionTitle = ($name != $trunced) ?
" title='$name'" :
"";
510 echo
"<option value='{$value}' $selected>$trunced</option>\n";
513 echo
"</select> ";
515 $this->_endField($field);
533 if(!preg_match(
"/^\{/", $template))
534 $template =
"{" . $template .
"}";
536 if(count($items) == 0)
539 foreach($items as $item)
541 $pk = $item->getPrimaryKey();
542 $options[$item->$pk] = $item->format(
"$template");
581 var $cssClass =
"boolean";
593 $this->label = ($label) ? $label :
prettify($field);
595 $this->
default = $default;
598 if ($parent->data->hasField($field))
600 $parent->override($field, $label, $this);
604 $parent->add($this, $field);
605 $parent->overrides[$field][
'label'] = $this->label;
608 $value = $this->getValue($field);
610 $this->parent->params->clearParam($field);
611 $this->parent->params->setParam($field,
"checked", $value);
614 private function getValue($field)
616 if ($this->parent->data->hasField($field))
618 $value = $this->parent->data->get($field);
619 if(!$value && !is_numeric($value))
621 return $this->default;
629 if (isset($_REQUEST[$field]))
634 return $this->default;
643 $selChanged =
"selChanged_" . $field .
"_box";
644 $onSubmit = $this->parent->getOnSubmitFunction();
646 <script type=
"text/javascript">
648 function <? echo $selChanged ?>(elt)
650 var value_field = document.id(
'<?php echo $field ?>');
653 if(value_field && elt)
655 if(elt.checked ==
true)
658 value_field.set(
"value", new_value);
660 if (<?php echo $onSubmit?>(elt.form)) elt.form.manager.submit();
668 $this->_startField($field, $this->styles);
670 echo
"<input type='checkbox' value='1' name='{$field}_box'";
672 $value = $this->getValue($field);
676 echo
" checked='checked'";
678 echo
" onclick='selChanged_{$field}_box(this);'/>\n";
680 if(!$value) $value = 0;
681 echo
"<input id='{$field}' type='hidden' name='{$field}' value='$value'/>\n";
682 echo
" <label for='{$field}'>{$label}</label>";
684 $this->_endField($field);
704 var $cssClass =
'checklist';
716 parent::CheckListFieldRenderer($form, $field, $label, $options);
717 $this->horizontal =
true;
719 $value = $this->parent->data->get($field);
720 if(!$value && !is_numeric($value) && ((!isset($_GET[
"{$field}_submitted"]) || !$_GET[
"{$field}_submitted"])) && $defaults)
722 $defaults = preg_replace(
"/'/",
"", $defaults);
723 $defaults = array_flip(explode(
",", preg_replace(
"/,\s*/",
",", $defaults)));
726 $this->parent->data->set($field, $defaults);
728 if(!is_numeric(array_flip($defaults[0])))
730 $value =
"'" . implode(
"','", array_keys($defaults)) .
"'";
734 $value = implode(
",", array_keys($defaults));
739 $this->parent->params->clearParam($field);
741 $this->parent->params->setParam($field,
"member", $value);
749 $this->_startField($field, $this->styles);
751 $searchValues = $this->parent->data->get($field);
753 if(is_array($searchValues))
755 $searchValues = explode(
",", implode(
",", array_keys($searchValues)));
759 $searchValues = array();
764 $onSubmit = $this->parent->getOnSubmitFunction();
765 if(count($this->options) > 0)
767 foreach($this->options as $value => $text)
769 trace(
"CheckListFieldRenderer value $value and text $text", 3);
771 $onchange =
" onchange='if ({$onSubmitFunction}(this.form)) this.form.manager.submit();'";
772 $checked = (array_search($value, $searchValues) !== FALSE) ?
" checked" :
"";
773 echo
"<input type='checkbox' class='checkbox' name='{$field}[$value]' value='{$value}'$checked$onchange/> $text$divider";
784 echo
"<input type='hidden' name='{$field}_submitted' value='1' />";
787 $this->_endField($field);
792 echo
"<div class='{$this->cssClass}'>\n";
795 $this->parent->layout->printLabel($field, $this, $styles,
"");
802 $this->parent->layout->endField($field, $this);
803 echo
"<div style='clear: both'></div>\n";
809 var $cssClass =
"radio";
813 parent::RadioButtonFieldRenderer($parent, $field, $label, $options);
814 $this->horizontal =
true;
819 $this->_startField($field, $this->styles);
821 $onSubmit = $this->parent->getOnSubmitFunction();
822 $onchange =
" onchange='if ({$onSubmit}(this.form)) this.form.manager.submit();'";
824 $searchValue = $this->parent->data->get($field);
826 foreach($this->options as $value => $name)
828 $selected = ($searchValue == $value) ?
" checked" :
"";
829 echo
"<input style='border: none' type='radio' name='$field' value='$value'$selected$onchange>$name</option>";
830 echo ($this->horizontal) ?
" " :
"<br/>";
833 $this->_endField($field);
838 echo
"<div class='{$this->cssClass}'>\n";
839 $this->parent->layout->printLabel($field, $this, $styles,
"");
847 $this->parent->layout->endField($field, $this);
848 echo
"<div style='clear: both'></div>\n";
900 var $startParam =
"startDate";
901 var $endParam =
"endDate";
903 var $fiscal_year_start = 1;
914 var $dateRangeLabel =
"Reporting Period";
918 var $cssClass =
"date_range";
920 function __construct($parent, $field, $endDateField =
"", $stepMode =
"month", $fiscal_year_start = 1, $startParam =
null, $endParam =
null)
922 $this->stepMode = $stepMode;
923 $this->field = $field;
925 $this->endDateField = (!$endDateField) ? $field : $endDateField;
926 $this->fiscal_year_start = $fiscal_year_start;
928 if ($startParam) $this->startParam = $startParam;
929 if ($endParam) $this->endParam = $endParam;
931 $this->calculateDateRange();
934 if ($parent->data->hasField($field))
936 $parent->override($field, $label, $this);
940 $parent->add($this, $field);
945 $parent->setParam($this->startParam,
"to", $this->to);
947 $parent->setHandler($this->startParam, array($this, getConstraint));
952 $this->startDate = $_REQUEST[$this->startParam];
953 $this->endDate = $_REQUEST[$this->endParam];
955 if ($this->startDate || $this->endDate)
958 $validator->required =
false;
959 $this->msg = $validator->validate();
967 $validator->required =
false;
969 $this->msg = $validator->validate();
976 if ($this->startDate) $this->startDate =
new DateTime($this->startDate);
977 if ($this->endDate) $this->endDate =
new DateTime($this->endDate);
979 if ($this->startDate && $this->endDate)
981 $this->subTitle = $this->startDate->format(
"jS F Y").
" to ".$this->endDate->format(
"jS F Y");
987 $this->month = $this->startDate->format(
"m");
988 $this->year = $this->startDate->format(
"Y");
994 if (!$this->year) $this->year = date(
"Y");
998 if ($this->stepMode ==
"year")
1001 $this->setStepModeYear();
1008 elseif($this->stepMode ==
"fiscal_year")
1010 if(!
checkNumeric($_REQUEST[
'year']) && $this->fiscal_year_start > date(
"n"))
1012 $this->setStepModeYear($this->fiscal_year_start);
1017 $this->setStepModeMonth();
1020 $this->from = $this->startDate->format(
"Y-m-d");
1021 $this->to = $this->endDate->format(
"Y-m-d");
1022 $this->calculated =
true;
1031 for($i=1;$i<=12;$i++)
1033 if(date(
"F", mktime(0, 0, 0, $i, 1, 0)) == $month)
1039 return $month_number;
1046 $this->year = date(
"Y");
1047 $this->month = date(
"m");
1050 $this->prevMonth = $this->month - 1;
1051 $this->prevYear = $this->year;
1052 if ($this->prevMonth == 0)
1055 $this->prevMonth = 12;
1058 $this->nextMonth = $this->month + 1;
1059 $this->nextYear = $this->year;
1060 if ($this->nextMonth > 12)
1062 $this->nextMonth = 1;
1066 if(!$this->startDate)
1067 $this->startDate =
new DateTime(
"{$this->year}-{$this->month}-01T00:00:00");
1071 $this->endDate = clone $this->startDate;
1072 $this->endDate->modify(
"+1 months");
1074 $this->endDate->modify(
"-1 days");
1077 if(!$this->subTitle)
1079 $this->subTitle = $this->startDate->format(
"F Y");
1085 $this->month = $startMonth;
1087 $this->prevMonth = $startMonth;
1088 $this->prevYear = $this->year - 1;
1090 $this->nextMonth = $startMonth;
1091 $this->nextYear = $this->year + 1;
1092 $this->subTitle= $this->year;
1094 if(!$this->startDate)
1096 $this->startDate =
new DateTime(
"{$this->year}-{$this->month}-01T00:00:00");
1101 $this->endDate = clone $this->startDate;
1102 $this->endDate->modify(
"+1 years");
1103 $this->endDate->modify(
"-1 days");
1109 if(is_array($this->handler) && method_exists($this->handler[0], $this->handler[1]))
1111 return call_user_func($this->handler, $this);
1115 $to = $this->to .
" 23:59:59.999";
1117 if($this->field == $this->endDateField)
1119 $name = $this->field;
1120 $constraint =
"$name BETWEEN '{$this->from}' AND '{$to}'";
1124 $constraint =
"{$this->endDateField} <= '{$to}' AND {$this->field} >= '{$this->from}' ";
1132 $this->handler = $handler;
1137 if (array_key_exists($field, $this->parent->hidden))
return "";
1139 $script .= <<<ENDSCRIPT
1141 <script src=
'/fakoli/calendar/sonjara_calendar.js' type=
'text/javascript'></script>
1142 <link href=
'/fakoli/calendar/sonjara_calendar.css' type=
'text/css' rel=
'stylesheet'></link>
1143 <script type=
"text/javascript">
1144 var startDateCalendar =
new Calendar(
'startDateCalendar',
'{$this->parent->id}',
'{$this->startParam}');
1145 var endDateCalendar =
new Calendar(
'endDateCalendar',
'{$this->parent->id}',
'{$this->endParam}');
1164 $this->_startField($field);
1166 if (!array_key_exists($this->startParam, $this->parent->hidden))
1168 $this->writeFilter();
1172 $this->writeDateHiddenFields();
1175 $this->writeButtons();
1177 $this->_endField($field);
1182 if(!$_REQUEST[
"month"] || !$_REQUEST[
"year"])
1185 <input type=
"hidden" name=
"<?php echo $this->startParam ?>" value=
"<?echo $this->startDate->format("m/d/Y
")?>">
1186 <input type=
"hidden" name=
"<?php echo $this->endParam ?>" value=
"<?echo $this->endDate->format("m/d/Y
")?>">
1192 <input type=
"hidden" name=
"year" value=
"<? echo $this->year ?>">
1193 <input type=
"hidden" name=
"month" value=
"<? echo $this->month ?>">
1200 if (!$this->calculated) $this->calculateDateRange();
1201 $endDate = clone $this->endDate;
1204 <div style=
"clear: both; float: left; padding-bottom: 4px">
1205 <label><?php echo $this->dateRangeLabel ?> From: </label>
1206 <input type=
"text" size=
"10" name=
"<?php echo $this->startParam ?>" value=
"<?echo $this->startDate->format("m/d/Y
")?>">
1207 <img src=
'/fakoli/calendar/calendar.gif' alt=
'Popup Calendar' style=
'vertical-align: middle; border:0' onclick=
'startDateCalendar.toggle(this)'/>
1208 <label> To: </label><input type=
"text" size=
"10" name=
"<?php echo $this->endParam ?>" value=
"<?echo $endDate->format("m/d/Y
")?>">
1209 <img src=
'/fakoli/calendar/calendar.gif' alt=
'Popup Calendar' style=
'vertical-align: middle; border:0' onclick=
'endDateCalendar.toggle(this)'/>
1210 <input type=
"submit" class=
"button" value=
" Update View "/>
1217 if ($this->stepMode ==
"none")
return;
1219 if (!$this->calculated) $this->calculateDateRange();
1221 $queryString =
"?".$_SERVER[
"QUERY_STRING"];
1223 $queryString = preg_replace(
"/identifier=\\w+\\&?/",
"", $queryString);
1224 $queryString = preg_replace(
"/year=\\d+\\&?/",
"", $queryString);
1225 $queryString = preg_replace(
"/month=\\d+\\&?/",
"", $queryString);
1226 $queryString = preg_replace(
"/startDate=\\d+\\&?/",
"", $queryString);
1227 $queryString = preg_replace(
"/endDate=\\d+\\&?/",
"", $queryString);
1229 $prevLink =
appendToQueryString($queryString,
"year=$this->prevYear&month=$this->prevMonth");
1230 $nextLink =
appendToQueryString($queryString,
"year=$this->nextYear&month=$this->nextMonth");
1232 $stepLabel = ($this->stepLabel) ? $this->stepLabel :
prettify($this->stepMode);
1234 <div
class=
"<?php echo $this->cssClass ?>">
1235 <div style=
"float: right; z-index:2; padding-bottom: 10px;">
1236 <input type=
"button" class=
"button" value=
" Next <?echo $stepLabel ?> » " onclick=
"go('<?echo $nextLink?>');">
1238 <input type=
"button" class=
"button" value=
" « Previous <?echo $stepLabel ?> " onclick=
"go('<?echo $prevLink?>');">
1245 class ProgressiveSearchFilterFieldRenderer
extends FieldRenderer
1247 var $cssClass =
'prog_search';
1248 var $searchOptions =
"";
1260 function ProgressiveSearchFilterFieldRenderer(&$parent, $field, $label =
"", $searchOptions)
1263 if ($field && !$parent->data->hasField($field))
1265 $parent->add($this, $field);
1266 $parent->overrides[$field][
'label'] = $label;
1270 $parent->override($field, $label, $this);
1273 $this->searchOptions = $searchOptions;
1280 echo
"<input id='$field' type='text' name='$field'
1281 value='".$this->parent->data->get($field).
"' autocomplete='off'
1282 size='{$this->size}'/>";
1290 <script type=
"text/javascript">
1291 window.addEvent(
'domready',
function()
1293 new ProgressiveSearch(
'<?php echo $field ?>', <?php echo $this->searchOptions ?>);
1308 function __construct(&$form, $field, $label, $relatedClass, $constraint, $nameField, $valueField =
"", $maxChars = 80)
1310 $this->RelatedItemSelectFieldRenderer($form, $field, $label, $relatedClass, $constraint, $nameField, $valueField =
"",
false,
true, $maxChars);
1316 $onSubmit = $this->parent->getOnSubmitFunction();
1317 $onchange =
" onchange='if ({$onSubmit}(this.form)) this.form.manager.submit();'";
1319 $this->getRelatedItems();
1322 $style =
"style='width: {$this->width}'";
1325 $this->_printLabel($field);
1326 echo
"<select name='{$field}'$onchange $style>\n";
1329 $value = $this->parent->data->get($field);
1331 foreach($this->items as $item)
1333 $valueField = ($this->valueField !=
"") ? $this->valueField : $item->getPrimaryKey();
1334 $name = $this->formatName($item, $this->nameField);
1336 echo
"<option value='{$item->get($valueField)}'";
1337 if ($item->get($valueField) == $value) echo
" selected";
1338 echo
">".ellipsis($name, $this->max_chars).
"</option>\n";
1340 echo
"</select> ";
Field renderer for boolean data fields.
CheckListFieldRenderer: Renders the specified list of options as a list of checkboxes from which mult...
FieldRenderer is the abstract base class for all FieldRenderers.
_startField($field, $styles="")
Internal method to generate the starting HTML for the field (including the label)
renderSearchScript($field, $mode)
FieldRenderers can override this method to provide any Javascript that the control requires when bein...
_endField($field)
Internal method to generate the closing HTML for the field.
renderSearchField($field, $mode)
FieldRenderers must override this method to provide the HTML implementation of the control displayed ...
FieldRenderer($parent)
Constructor.
renderSearchScript($field)
renderSearchField($field)
BooleanFilterFieldRenderer(&$parent, $field="", $label="", $default=0)
_endField($field, $styles="")
CheckListFilterFieldRenderer(&$form, $field, $label, $options, $defaults="")
renderSearchField($field)
_startField($field, $styles="")
Internal method to generate the starting HTML for the field (including the label)
Adds a Date Range Filter with start and end dates and Next and Previous buttons to a FilterForm.
__construct($parent, $field, $endDateField="", $stepMode="month", $fiscal_year_start=1, $startParam=null, $endParam=null)
renderSearchField($field)
If the user hides the startParm field, then don't display the calendar picker and input fields for da...
renderSearchScript($field)
static convertMonthStringToNumber($month)
setStepModeYear($startMonth=1)
setDefault($title, $value)
renderSearchField($field)
static formatOptions($items, $template)
FilterFieldRenderer(&$form, $field, $label="", $options=null)
The SearchParameters class interprets the set of input parameters for a search and generates the corr...
checkNumeric($p)
Security helper function.
trace($msg, $lvl=3, $callStack=null)
Send output to the trace log.
option($value, $text, $sel="")
Write out an option tag, marking as selected if applicable.
ellipsis($txt, $max, $wholeWord=false)
Truncate the supplied text at the given maximum length.
appendToQueryString($qs, $params)
Appends the specified parameters to the supplied query string.
prettify($name)
Takes a variable or field name and converts it into a human-readable version (assuming that the origi...