Permalink
Browse files

Added the search functionality

If you ever need to add search functionality for your module:

1. Add a Helper-class called `<module>Helper`
2. Add a method called `search` which accepts one parameter (the search string)
3. Make sure the method returns an array of items. Each item should have at
	least a `label`-field. If there is a `url`-field the user will be
	redirected to that url when he/she selects the item
	If there is a `value`-field this value will be used to populate the field
	instead of the `label`-field.
  • Loading branch information...
1 parent c1b4c7a commit 94a06cb52261fd316d66b357046b303f358d9cc0 @tijsverkoyen tijsverkoyen committed Nov 17, 2012
Showing with 220 additions and 18 deletions.
  1. +2 −1 TODO.md
  2. +73 −0 core/ajax/search.php
  3. +8 −1 core/classes/url.php
  4. +77 −0 core/js/script.js
  5. +14 −16 core/layout/templates/nav.tpl
  6. +46 −0 modules/users/model/model.php
View
@@ -2,4 +2,5 @@
* Make it possible to delete users (flag them in the database)
* Port other jQuery-plugins
-* Implement locale in js-files
+* Implement locale in js-files
+* Use interface for search method
View
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * AjaxCoreBug
+ *
+ * @package core
+ * @subpackage search
+ *
+ * @author Tijs Verkoyen <tijs@sumocoders.be>
+ * @since 1.0
+ */
+class AjaxCoreSearch extends AjaxBaseAction
+{
+ /**
+ * Execute the action
+ *
+ * @return void
+ */
+ public function execute()
+ {
+ $q = SpoonFilter::getPostValue('q', null, '');
+
+ if($q != '')
+ {
+ // get all modules
+ $modules = SpoonDirectory::getList(PATH_WWW . '/modules');
+ $items = array();
+
+ // loop modules
+ foreach($modules as $module)
+ {
+ $path = PATH_WWW . '/modules/' . $module . '/model/model.php';
+
+ if(SpoonFile::exists($path))
+ {
+ // require the class
+ require_once $path;
+
+ // build classname
+ $className = SpoonFilter::toCamelCase($module) . 'Helper';
+
+ // check if search method exists
+ if(is_callable(array($className, 'search')))
+ {
+ $return = (array) call_user_func(array($className, 'search'), $q);
+
+ foreach($return as $row)
+ {
+ $row['module'] = $module;
+ $items[] = $row;
+ }
+ }
+ }
+ }
+
+ // return
+ $response['code'] = 200;
+ $response['message'] = 'ok';
+ $response['data'] = $items;
+ }
+ else
+ {
+ // return
+ $response['code'] = 400;
+ $response['message'] = 'no query';
+ }
+
+ // output
+ SpoonHTTP::setHeaders(array('Content-Type: application/json'));
+ echo json_encode($response);
+ exit;
+ }
+}
View
@@ -77,8 +77,15 @@ public function __construct()
// set host for later use
$this->setHost($_SERVER['HTTP_HOST']);
+ $isAjax = (substr($this->getQueryString(), 0, 8) == 'ajax.php');
+
// process url
- $this->processQueryString();
+ if($isAjax)
+ {
+ $language = SpoonFilter::getGetValue('language', SiteLocale::$possibleLanguages, '');
+ $this->setLanguage($language);
+ }
+ else $this->processQueryString();
}
/**
View
@@ -29,6 +29,7 @@ var jsSite = {
jsSite.forms.init();
jsSite.layout.init();
jsSite.links.init();
+ jsSite.search.init();
try {
// build method
@@ -336,4 +337,80 @@ jsSite.links = {
}
}
+jsSite.search = {
+ results: [],
+ init: function() {
+ $('#searchQuery').typeahead({
+ source: jsSite.search.autocomplete,
+ matcher: function(item) { return true },
+ updater: jsSite.search.updater,
+ highlighter: function(items) { return items; }
+ });
+ },
+ autocomplete: function(query, process) {
+ $.ajax({
+ url: '/ajax.php?module=core&action=search&language=' + jsSite.current.language,
+ data: { q: query },
+ success: function(data, textStatus, jqXHR) {
+ jsSite.search.results = [];
+ if(data.code == 200) {
+ var items = [];
+ for(var i in data.data) {
+ var key = data.data[i].label + ' <small class="muted">(' + data.data[i].module + ')</small>';
+ items.push(key);
+ jsSite.search.results[key] = data.data[i]
+ }
+ process(items);
+ }
+ else alert(data.message);
+ }
+ });
+ },
+ updater: function(item) {
+ if(typeof jsSite.search.results[item].url != 'undefined') {
+ document.location = jsSite.search.results[item].url;
+ } else if(typeof jsSite.search.results[item].value != 'undefined') {
+ return jsSite.search.results[item].value;
+ } else {
+ return item;
+ }
+ }
+}
+
+jsSite.prestations =
+{
+ init: function()
+ {
+ $('#userId').multipleSelectbox({ emptyMessage: 'Geen personen gekozen.', addLabel: 'toevoegen', removeLabel: 'verwijderen', showIconOnly: true });
+
+ $('#quickNav').change(function(e) {
+ // replace
+ var newDate = $(this).val().replace(new RegExp('/', 'g'), '-');
+
+ // alter url
+ document.location.href = '/'+ jsSite.current.module + '/' + jsSite.current.action +'/'+ newDate;
+ });
+
+ $('#addAndAddAnother').click(function(e)
+ {
+ // prevent default
+ e.preventDefault();
+
+ // search form
+ var form = $($(this).parents('form')[0]);
+
+ // append new field and submit
+ form.append('<input type="hidden" name="next" value="add_another" />').submit();
+ });
+
+ $('td.dont_invoice input:checkbox').change(function() { $('#dontInvoice').attr('checked', ($('td.dont_invoice input:checkbox').length == $('td.dont_invoice input:checked').length) ? 'checked' : ''); })
+ $('td.dont_send input:checkbox:first').change();
+ $('#dontInvoice').change(function() { $('td.dont_invoice input:checkbox').attr('checked', $(this).attr('checked')); });
+
+ $('td.is_invoiced input:checkbox').change(function() { $('#isInvoiced').attr('checked', ($('td.is_invoiced input:checkbox').length == $('td.is_invoiced input:checked').length) ? 'checked' : ''); })
+ $('td.is_invoiced input:checkbox:first').change();
+ $('#isInvoiced').change(function() { $('td.is_invoiced input:checkbox').attr('checked', $(this).attr('checked')); });
+ }
+}
+
$(jsSite.init);
@@ -7,23 +7,21 @@
</ul>
</nav>
- {* @later: implement a side-wide search
- <div id="search" class="span3">
- <form class="form-search">
- <div class="control-group">
- <label for="searchQuery" class="hide control-label">{$lblSearch|ucfirst}</label>
- <div class="controls">
- <div class="input-append">
- <input id="searchQuery" name="q" type="search" placeholder="{$lblSearch|ucfirst}" class="input-medium">
- <button type="submit" class="btn hidden-phone hidden-tablet">
- <i class="icon-search"></i>
- <span class="hide">{$lblSearch|ucfirst}</span>
- </button>
- </div>
+ <div id="search" class="span3">
+ <form>
+ <div class="control-group">
+ <label for="searchQuery" class="hide control-label">{$lblSearch|ucfirst}</label>
+ <div class="controls">
+ <div class="input-append">
+ <input id="searchQuery" name="q" type="search" placeholder="{$lblSearch|ucfirst}" class="input-medium">
+ <button type="submit" class="btn hidden-phone hidden-tablet">
+ <i class="icon-search"></i>
+ <span class="hide">{$lblSearch|ucfirst}</span>
+ </button>
</div>
</div>
- </form>
- </div>
- *}
+ </div>
+ </form>
+ </div>
</div>
</div>
@@ -219,3 +219,49 @@ public function toArray()
return $item;
}
}
+
+/**
+ * UsersHelper
+ *
+ * @package users
+ * @subpackage helper
+ *
+ * @author Tijs Verkoyen <tijs@sumocoders.be>
+ * @since 1.0
+ */
+class UsersHelper
+{
+ /**
+ * Search for users
+ *
+ * @param $query The data to look for
+ * @return array
+ */
+ public static function search($query)
+ {
+ $return = array();
+
+ $data = Site::getDB()->getRecords(
+ 'SELECT id, name
+ FROM users AS i
+ WHERE i.deleted = ? AND (i.name LIKE ? OR i.email LIKE ?)',
+ array('N', $query . '%', $query . '%')
+ );
+
+ if(!empty($data))
+ {
+ $urlObject = new SiteURL();
+ $url = $urlObject->buildUrl('edit', 'users');
+
+ foreach($data as $row)
+ {
+ $return[] = array(
+ 'label' => $row['name'],
+ 'url' => $url . '/' . $row['id'],
+ );
+ }
+ }
+
+ return $return;
+ }
+}

0 comments on commit 94a06cb

Please sign in to comment.