@coroico
The script outputs opacity="0" as a style attribute, and unfortunately while this is in the CSS3 spec it isn’t part of CSS2 so throws an error in the W3C validator. I removed it from the snippet php code and it seemed to work fine without it.
My CSS classes as follows. I’ve used a contextual selector for the search form inside my #nav-main div and been lazy about the naming of the the close button etc, you will probably want to use your naming scheme. The transparency works for browsers that support 24bit png, so IE6 gets an opaque gif instead. You could use a AlphaImageLoader filter here to get the same effect but you’d need to use javascript to create a div behind the form and apply the filter to that - I didn’t bother in this instance but it would be easy to do.
/* ajax search */
.ajaxSearch_highlight, .AS_ajax_highlight {
color: black;
font-weight: bold;
}
#nav-main form {
width: 200px;
padding: 0 0 0 40px;
margin-top: 9px;
margin-bottom: -9px;
float: left;
}
#nav-main label {
margin-bottom:-1em;
}
#nav-main label em {
display: none;
}
#nav-main label, #nav-main input {
color: #000;
}
#nav-main #ajaxSearch_input {
border:0px;
width: 138px;
padding: 3px 20px 1px 20px;
background: url('/_assets/gfx/searchfield.png') no-repeat 0 0;
float: left;
}
* html #nav-main #ajaxSearch_input {
background: url('/_assets/gfx/searchfieldie.gif') no-repeat 0 0; /* feed ie6 a non-transparent version */
}
#ajaxSearch_submit {
float: right;
}
#searchClose {
position: absolute;
top:13px;
left:201px;
background: url('/_assets/gfx/search_close.png') no-repeat 0 0;
width: 20px;
height: 20px;
z-index: 9999;
}
#indicator {
position: absolute;
top:13px;
left:201px;
width: 20px;
height: 20px;
background: url('/_assets/gfx/search_loading.gif') no-repeat 0 0;
z-index: 10000;
}
#ajaxSearch_form {
color: #444;
width: auto;
}
#ajaxSearch_submit {
display: inline;
}
#ajaxSearch_output {
position: absolute;
left:0;
top: 36px;
width: 241px;
margin-left: 20px;
padding: 0;
display: block;
height: auto;
vertical-align: top;
}
#current-search-results {
padding: 10px;
border: 1px solid #ccc;
border-width: 0 1px 1px 1px;
background: #eee;
}
.AS_ajax_result {
color: #444;
margin-bottom: 3px;
}
.AS_ajax_resultLink {
display: block;
padding: 5px 0 0 0;
}
.AS_ajax_resultDescription{
color: #555;
}
.AS_ajax_more {
margin: 1em 0 0 0;
color: #555;
}
#ajaxSearch_output h3 {
font-size: 1em;
margin: .75em 0 0 0;
}
#ajaxSearch_output h3 a,#ajaxSearch_output h3 a:link,#ajaxSearch_output h3 a:visited {
color: #369;
}
#ajaxSearch_output h2 {
margin-top: 1em;
color: #333;
}
AjaxSearch.js as follows:
//AjaxSearch.js
//Created by: KyleJ ([email protected])
//Created on: 03/14/06
//Description: This code is used to setup the ajax search request.
//My thanks to Steve Smith of orderlist.com for sharing his code on how he did this
//Live Search by Thomas (Shadock)
//Updated: 06/03/07 - Added utf8 fix from atma
//Updated: 01/22/07 - Switched to mootools support
//Updated: 09/18/06 - Added user permissions to searching
//Updated: 01/02/08 by Mark Croxton - OSX style live search
//set the loading image to the correct location for you
//set the close image to the correct location for you
//set the ajax call to the correct location of ajaxSearch.php
//From Thomas : vars for live search
var _oldInputFieldValue="";
var _currentInputFieldValue="";
var _timeoutAdjustment=0;
var newToggle;
var is_searching=false;
var liveTimeout = null;
function activateSearch() {
// IE fix to ensure a carriage return submits the form
$('ajaxSearch_input').addEvent('keypress', checkEnterIE);
var searchForm = $('ajaxSearch_form');
if (searchForm) {
$('ajaxSearch_form').onsubmit = function() { doSearch(); return false; };
var i = new Element('div');
i.setProperties({
id: 'indicator'
});
toggleImage(i);
searchForm.appendChild(i);
var c = new Element('div'); //Close Image
c.setProperties({
id: 'searchClose'
});
c.addEvent('click', function(){closeSearch();});
if (liveSearch) {
c.setStyles({
position: 'absolute',
top: '1px',
right: '1px'
});
} else {
toggleImage(c);
}
var s = $('ajaxSearch_output');
var n = new Element('div'); // New search results div
n.setProperty('id', 'current-search-results');
n.setStyle('opacity', '1 !important');
s.appendChild(n);
newToggle = new Fx.Slide('current-search-results', {duration: 600}).hide();
newToggle.isDisplayed = function() {
return this.wrapper['offset'+this.layout.capitalize()] > 0;
}
if (liveSearch) {
s.appendChild(c);
} else {
searchForm.appendChild(c);
}
is_searching = false;
search_open = false;
if (liveSearch) {
$('ajaxSearch_input').addEvent('keyup', liveSearchReq);
$('ajaxSearch_submit').style.opacity = '0';
}
}
}
function checkEnterIE(){
var key = (window.event)? window.event.keyCode : 0;
if (key == 13) { // carriage return
doSearch();
}
}
function liveSearchReq() {
if (liveTimeout) {
window.clearTimeout(liveTimeout);
}
liveTimeout = window.setTimeout("doSearch()",400);
}
function doSearch() {
// If we're already loading, don't do anything
if (is_searching) return false;
s = $('ajaxSearch_input').value;
// Same if the search is blank
if (s == '') return false;
is_searching = true;
c = $('current-search-results');
toggleImage($('indicator'));
if (!liveSearch) {if (!search_open) {toggleImage($('searchClose'));}}
search_open = true;
b = $('ajaxSearch_submit');
b.disabled = true;
if (newToggle.isDisplayed()) {
newToggle.toggle();
}
// Setup the parameters and make the ajax call
var pars = Object.toQueryString({
q: 'assets/snippets/AjaxSearch/AjaxSearch.php',
search: s,
maxResults: maxResults,
stripHtml: stripHtml,
stripSnip: stripSnip,
stripSnippets: stripSnippets,
useAllWords: useAllWords,
searchStyle: escape(searchStyle),
minChars: minChars,
showMoreResults: showMoreResults,
moreResultsPage: moreResultsPage,
as_language: as_language,
extract: extract,
docgrp: escape(docgrp),
highlightResult: highlightResult
});
var ajaxSearchReq = new Ajax('index-ajax.php', {postBody: pars, onComplete: doSearchResponse});
if (newToggle.isDisplayed()) {
newToggle.toggle();
ajaxSearchReq.request.delay(600, ajaxSearchReq);
} else {
ajaxSearchReq.request();
}
return true;
}
function doSearchResponse(request) {
var o = $('ajaxSearch_output');
o.style.opacity = '1';
$('current-search-results').setHTML(decodeURIComponent(request));
newToggle.toggle();
is_searching = false;
setTimeout('resetForm()',600);
}
function resetForm() {
s = $('ajaxSearch_submit');
s.disabled = false;
toggleImage($('indicator'));
}
function closeSearch() {
newToggle.toggle();
setTimeout('clearSearch()',600);
}
function clearSearch() {
toggleImage($('searchClose'));
search_open = false;
$('current-search-results').innerHTML = '';
var o = $('ajaxSearch_output');
o.style.opacity = '0';
$('ajaxSearch_input').value="";
$('ajaxSearch_input').focus();
}
function toggleImage(imgElement) {
imgStyle = imgElement.getStyle('opacity');
if (imgStyle == '0') {
imgElement.setStyle('opacity', '1');
} else {
imgElement.setStyle('opacity', '0');
}
}
//Event.observe(window, 'load', activateSearch, false);
Window.onDomReady(activateSearch);
For Safari, you can use a real live search field using this javascript (remebering that Safari doesn’t permit CSS styling of form elements at all so the classes above don’t affect it - instead you can use Apple’s own search type input field):
/* Safari search field */
var DEF_VAL = "Search here..."; // Default Value
var isSafari = ((parseInt(navigator.productSub)>=20020000)&& // detecting WebCore
(navigator.vendor.indexOf("Apple Computer")!=-1));
function replaceSearchField() {
if (!document.getElementById) return;
var searchField = document.getElementById('ajaxSearch_input');
if (isSafari) {
searchField.setAttribute('type', 'search');
searchField.setAttribute('autosave', 'whiteheadmonkton');
searchField.setAttribute('results', '0');
searchField.setAttribute('placeholder', DEF_VAL);
searchField.style.width="176px";
} else {
//addEvent(searchField, 'focus', focusSearch, false);
//addEvent(searchField, 'blur', blurSearch, false);
if (searchField.value=='') searchField.value = DEF_VAL;
}
//make visible
searchField.style.visibility="visible";
}
function focusSearch() {
if (this.value==DEF_VAL) {
this.value = '';
this.setAttribute('class', 'focus');
}
}
function blurSearch() {
if (this.value=='') {
this.value = DEF_VAL;
this.removeAttribute('class', 'focus');
}
}
// note- this is my own addEvent function
addEvento(window,'load', replaceSearchField, false);
templates.inc.php as follows:
<?php
/*
templates.inc.php - for AjaxSearch 1.6
Created by: KyleJ ([email protected])
Created on: 01/22/07
Updated: 01/02/08 by Mark Croxton - OSX style live search
Description: Templates used to display AjaxSearch form/results
*/
$asTemplates = array(
//Template for output of all search elements
'layout' => '
[+as.form+]
[+as.intro+]
[+as.results+]',
//Form Template
'form' => '
<form [+as.formId+]action="[+as.formAction+]" method="post">
<label for="ajaxSearch_input" accesskey="2"><em>Search</em>
<input id="ajaxSearch_input" type="text" name="search" value="[+as.inputValue+]"[+as.inputOptions+] />
<input id="ajaxSearch_submit" src="_assets/gfx/search.gif" type="image" value="go" name="sub" alt="Find" />
</label>
</form>',
//Template for each search result
'result' => '
<h3><a href="[+as.resultLink+]" title="[+as.longtitle+]">[+as.pagetitle+]</a></h3>
[+as.description+]
[+as.extract+]',
//Template for results container when ajax search is not enabled or for more results page
'no_ajax_outer' => '
<div class="search-results">
[+as.resultInfo+]
[+as.paging+]
[+as.results+]
</div>
[+as.paging+]',
//Template for wrapper around result description, placed in template 'result' placeholder '[+as.description+]'
'descriptionWrapper' => '
<span class="[+as.descriptionClass+]">[+as.description+]</span>',
//Template for wrapper around extract, placed in template 'result' placeholder '[+as.extract+]'
'extractWrapper' => '<p>[+as.extract+]</p>',
//Template for more results link with ajax search
'ajax_more_results' => '
<div class="[+as.moreClass+]">
<a href="[+as.moreLink+]" title="[+as.moreTitle+]">[+as.moreText+]</a>
</div>',
//Template for no results message
'noResults' => '
<div class="[+as.noResultClass+]">
[+as.noResultText+]
</div>',
//Template for wrapper around paging links
'pagingLinksOuter' => '
<p id="paging">
[+as.pagingText+]
<span class="numbers">[+as.pagingLinks+]</span>
</p>',
//Template for each paging link
'pagingLinks' => '
<a href="[+as.pagingLink+]">[+as.pagingText+]</a><span> | </span>',
//Template for current page paging link
'pagingLinksCurrent' => '
[+as.pagingText+]<span> | </span>',
//Template for result info, i.e. 15 results found for 'MODx'
'resultsInfo' => '
<h2>[+as.resultInfoText+]</h2>',
//Template for intro message
'introMessage' => '
<p class="ajaxSearch_intro" id="ajaxSearch_intro">[+as.introMessage+]</p>',
);
?>
Images used are attached below...