We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 7231
    • 4,205 Posts
    Quote from: ganeshXL at Feb 08, 2008, 01:28 PM

    Well, actually... there’s a little (simple) trick how you can still use <4-char-strings for search.
    Simply check the string-length first: if it’s < 4 chars, perform a LIKE(%’$searchTerm’%) query, else do a regular FULLTEXT search.
    Not pretty, but in cases where changing those system vars is not an option, perhaps a viable alternative.
    I was contemplating this problem today. AjaxSearch could at least give an error that explains that there should be more than 3 chars. It took me a while to understand why I was getting no results for "Jim".
      [font=Verdana]Shane Sponagle | [wiki] Snippet Call Anatomy | MODx Developer Blog | [nettuts] Working With a Content Management Framework: MODx

      Something is happening here, but you don&#39;t know what it is.
      Do you, Mr. Jones? - [bob dylan]
      • 5811
      • 1,717 Posts
      AjaxSearch could at least give an error that explains that there should be more than 3 chars
      Thanks for this suggestion. You are rigth, the message should be improved in this particular case.
      Regarding the relevance mode (Like matching search) , it doesn’t run and I haven’t investigate to understand why. May be in a next step.

      @therebechips
      Very nice and beautiful design. I am very impressed by the header. As I am a bad designer, I will keep some ideas like the transparent menu bar.
      Regarding the ajaxSearch form, I am interesting to know how you have hacked the code and the Css to restyle the form. It could be (again) give me some ideas for the the templating of the next version of ajaxSearch. And then, why do you mean by
      make it generate standards compliant markup
      huh.
      In advance thanks for your answers.
        • 29774
        • 386 Posts
        @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...
          Snippets: GoogleMap | FileDetails | Related Plugin: SSL
          • 29774
          • 386 Posts
          Reached the limit on including files - this is the last one.
            Snippets: GoogleMap | FileDetails | Related Plugin: SSL
            • 5811
            • 1,717 Posts
            Thanks a lot therebychips. I don’t know how for the moment but i will try to take into consideration of your improvements
              • 36527
              • 120 Posts
              Can I ask how you did the DDL filter on the Articles section please?
                • 29774
                • 386 Posts
                Hi Moondawgy

                this was a custom snippet:
                - each article needs to have been assigned a date stored in a TV called ’postdate’
                - the year filter autmoatically ranges from the year of the earliest article to the latest article. So if the earliest article was 2004 and the latest 2008 you get 2004, 2005, 2006, 2007 and 2008 listed as filters.
                - By default the user sees a list of articles in the latest year. If they use the form filters they can narrow the result by year and/or month.
                - You pass the parameter ’archiveId’ to the snippet which should be the id of the folder containing your articles.
                - I’ve hardcoded the output which is not good practice, but if anyone else is interested I could set it up to use chunks and placeholders

                Create a new snippet called NewsArchive and paste in this code:
                <?php
                return include_once($modx->config['base_path'] . 'assets/snippets/NewsArchive/NewsArchive.php');
                ?>
                


                Put NewsArchive.php and the inc folder in /assets/snippets/NewsArchive/

                Use the snippet like this:
                [! NewsListing? &archiveId=`1` !]
                




                  Snippets: GoogleMap | FileDetails | Related Plugin: SSL
                  • 36527
                  • 120 Posts
                  Mr chips,

                  I would be very interested in the chunks etc - could be one for the repository as it is a first class solution.