PageSourceSearch

https://www.udap.com/mm5/clientside.mvc?T=1ea7b997&Module_Code=cmp-cssui-searchfield&Filename=runtime.js

js udap.com collected 2026-09-24 21:01:50 UTC 14,682 bytes, 577 lines download raw bytes

1// Miva Merchant
2//
3// This file and the source codes contained herein are the property of
4// Miva, Inc.  Use of this file is restricted to the specific terms and
5// conditions in the License Agreement associated with this file.  Distribution
6// of this file or portions of this file for uses not covered by the License
7// Agreement is not allowed without a written agreement signed by an officer of
8// Miva, Inc.
9//
10// Copyright 1998-2026 Miva, Inc.  All rights reserved.
11// http://www.miva.com
12//
13
14/*
15	Required elements:
16		$unique_id = some_unique_to_DOM_value;
17
18		<input type="[any text supported input]" class="any" data-mm_searchfield="Yes" data-mm_searchfield_id="$unique_id" value="&mvte:global:Search;" />
19		<[HTMLElement] data-mm_searchfield_menu="Yes" data-mm_searchfield_id="$unique_id"></[HTMLElement]>
20*/
21
22(function( obj, eventType, fn )
23{
24	if ( obj.addEventListener )
25	{
26		obj.addEventListener( eventType, fn, false );
27	}
28	else if ( obj.attachEvent )
29	{
30		obj.attachEvent( 'on' + eventType, fn );
31	}
32})( window, 'load', function() { MMSearchField_Initialize(); } );
33
34var mm_searchfields = new Object();
35
36function MMSearchField_Initialize()
37{
38	var i, id, i_len, lookup, elements;
39
40	FireEvent( window, 'mmsearchfield_override' );
41
42	lookup			= new Object();
43	elements		= document.getElementsByTagName( '*' );
44
45	for ( i = 0, i_len = elements.length; i < i_len; i++ )
46	{
47		if ( id = elements[ i ].getAttribute( 'data-mm_searchfield_id' ) )
48		{
49			if ( !lookup[ id ] )
50			{
51				lookup[ id ] = new Object();
52			}
53
54			if ( elements[ i ].getAttribute( 'data-mm_searchfield' ) )				lookup[ id ].element_search	= elements[ i ];
55			else if ( elements[ i ].getAttribute( 'data-mm_searchfield_menu' ) )	lookup[ id ].element_menu	= elements[ i ];
56		}
57	}
58
59	for ( id in lookup )
60	{
61		if ( !lookup.hasOwnProperty( id )						||
62			 !lookup[ id ].element_search						||
63			 !lookup[ id ].element_menu							||
64			 ( lookup[ id ].element_search.nodeType !== 1 )		||
65			 ( lookup[ id ].element_menu.nodeType !== 1 )		||
66			 ( lookup[ id ].element_search.nodeName.toLowerCase() !== 'input' ) )
67		{
68			continue;
69		}
70
71		mm_searchfields[ id ] = new MMSearchField( lookup[ id ].element_search, lookup[ id ].element_menu );
72	}
73
74	FireEvent( window, 'mmsearchfield_initialized' );
75}
76
77function MMSearchField( element_search, element_menu )
78{
79	var self = this;
80
81	// Elements
82	this.element_search					= element_search;
83	this.element_menu					= element_menu;
84
85	// Values
86	this.current_search					= '';
87	this.search_timeout					= null;
88	this.search_delay					= 400;
89	this.menu_visible					= false;
90	this.menu_items						= new Array();
91	this.selected_item					= null;
92	this.product_count					= 5;
93	this.has_focus						= false;
94	this.delegator						= new AJAX_ThreadPool( 1 );
95	this.last_displayed_search_value	= null;
96
97	// Events
98	this.event_search_focus				= function( event ) { return self.Event_Focus( event ? event : window.event ); };
99	this.event_search_keydown			= function( event ) { return self.Event_Keydown( event ? event : window.event ); };
100	this.event_search_keyup				= function( event ) { return self.Event_Keyup( event ? event : window.event ); };
101	this.event_search_blur				= function( event ) { return self.Event_Blur( event ? event : window.event ); };
102	this.event_search_paste				= function( event ) { setTimeout( function() { self.Search( self.element_search.value ); }, 0 ); };
103	this.event_search_click				= function( event ) { eventStopPropagation( event ? event : window.event ); };
104	this.event_document_mousedown		= function( event ) { return self.Event_Document_MouseDown( event ? event : window.event ); };
105	this.event_document_mousemove		= function( event ) { return self.Event_Document_MouseMove( event ? event : window.event ); };
106
107	AddEvent( this.element_search, 'focus',		this.event_search_focus );
108	AddEvent( this.element_search, 'keydown',	this.event_search_keydown );
109	AddEvent( this.element_search, 'keyup',		this.event_search_keyup );
110	AddEvent( this.element_search, 'blur',		this.event_search_blur );
111	AddEvent( this.element_search, 'paste',		this.event_search_paste );
112	AddEvent( this.element_search, 'click',		this.event_search_click );
113
114	// Initial Setup
115
116	this.Menu_Empty();
117	this.Menu_Hide();
118}
119
120MMSearchField.prototype.GetSearchURL = function()
121{
122	return MMSearchField_Search_URL_sep;
123}
124
125MMSearchField.prototype.SetLoadCount = function( count )
126{
127	this.product_count = count;
128}
129
130MMSearchField.prototype.SetSearchDelay = function( delay )
131{
132	this.search_delay = delay;
133}
134
135MMSearchField.prototype.Menu_Empty = function()
136{
137	this.menu_items						= new Array();
138	this.element_menu.innerHTML 		= '';
139	this.last_displayed_search_value	= null;
140
141	this.Menu_Item_Select( null );
142}
143
144MMSearchField.prototype.Menu_Show = function()
145{
146	if ( this.menu_visible )
147	{
148		return;
149	}
150
151	this.menu_visible = true;
152	this.element_menu.style.display = 'block';
153}
154
155MMSearchField.prototype.Menu_Hide = function()
156{
157	if ( !this.menu_visible )
158	{
159		return;
160	}
161
162	this.menu_visible = false;
163	this.element_menu.style.display = 'none';
164}
165
166MMSearchField.prototype.Menu_Append_Header = function()
167{
168	var item;
169
170	if ( item = this.onMenuAppendHeader() )
171	{
172		this.element_menu.appendChild( item );
173	}
174}
175
176MMSearchField.prototype.Menu_Append_Item = function( data )
177{
178	var item;
179
180	if ( item = this.onMenuAppendItem( data.menuitem ) )
181	{
182		item.mm_data		= data;
183		item.action			= data.product_link;
184		item.onclick		= ( e ) => { this.Menu_Item_OnClick( e, item.action ); };
185		item.onauxclick		= ( e ) => { this.Menu_Item_OnClick( e, item.action ); };
186		item.onmousemove	= ( e ) => { this.Event_MenuItem_MouseMove( e, item ); };
187		this.element_menu.appendChild( item );
188		this.menu_items.push( item );
189	}
190}
191
192MMSearchField.prototype.Menu_Append_StoreSearch = function()
193{
194	var item;
195
196	if ( item = this.onMenuAppendStoreSearch( this.element_search.value ) )
197	{
198		item.action			= this.GetSearchURL() + encodeURIComponent( this.element_search.value );
199		item.onclick		= ( e ) => { this.Menu_Item_OnClick( e, item.action ); };
200		item.onauxclick		= ( e ) => { this.Menu_Item_OnClick( e, item.action ); };
201		item.onmousemove	= ( e ) => { this.Event_MenuItem_MouseMove( e, item ); };
202
203		this.element_menu.appendChild( item );
204
205		this.menu_item_storesearch	= item;
206		this.menu_items.push( item );
207	}
208}
209
210MMSearchField.prototype.Menu_Replace_StoreSearch = function()
211{
212	var item;
213
214	if ( item = this.onMenuAppendStoreSearch( this.element_search.value ) )
215	{
216		item.action			= this.GetSearchURL() + encodeURIComponent( this.element_search.value );
217		item.onclick		= ( e ) => { this.Menu_Item_OnClick( e, item.action ); };
218		item.onauxclick		= ( e ) => { this.Menu_Item_OnClick( e, item.action ); };
219		item.onmousemove	= ( e ) => { this.Event_MenuItem_MouseMove( e, item ); };
220
221		this.element_menu.appendChild( item );
222
223		if ( this.menu_item_storesearch && ( ( index = this.menu_items.indexOf( this.menu_item_storesearch ) ) != -1 ) )
224		{
225			this.menu_item_storesearch.parentNode.removeChild( this.menu_item_storesearch );
226			this.menu_items.splice( index, 1 );
227		}
228
229		if ( this.selected_item === this.menu_item_storesearch )
230		{
231			this.Menu_Item_Select( item );
232		}
233
234		this.menu_item_storesearch = item;
235		this.menu_items.push( item );
236	}
237}
238
239MMSearchField.prototype.Menu_Item_Select = function( item )
240{
241	this.selected_item = item;
242
243	if ( item !== null )
244	{
245		this.selected_item.className = classNameAdd( this.selected_item, 'mm_searchfield_menuitem_selected' );
246	}
247}
248
249MMSearchField.prototype.Menu_Item_OnClick = function( e, url )
250{
251	window.open( url, ( e.ctrlKey || e.metaKey || e.button === 1 ) ? '_blank' : '_self', 'noreferrer' );
252}
253
254MMSearchField.prototype.SetFocus = function()
255{
256	this.element_search.focus();
257}
258
259MMSearchField.prototype.Search = function( value )
260{
261	var self = this;
262
263	if ( ( typeof value !== 'string' ) || ( value.length == 0 ) )
264	{
265		this.Menu_Empty();
266		this.Menu_Hide();
267
268		return;
269	}
270	else if ( value.length < 3 )
271	{
272		this.Menu_Empty();
273		this.Menu_Show();
274		this.Menu_Replace_StoreSearch();
275
276		return;
277	}
278
279	AJAX_Call_Module( function( response ) { self.Search_Callback( response, value ); }, 'runtime',
280					  'cmp-cssui-searchfield',
281					  'Search',
282					  'Search=' + encodeURIComponent( value ) +
283					  '&Count=' + this.product_count,
284					  this.delegator );
285
286	this.delegator.LimitQueueToCount( 1 );
287	this.delegator.Run();
288}
289
290MMSearchField.prototype.Search_Callback = function( response, original_search_value )
291{
292	var i, i_len, last_selected;
293
294	last_selected			= this.selected_item;
295
296	this.Menu_Empty();
297
298	if ( !this.has_focus || this.element_search.value.length == 0 )
299	{
300		this.Menu_Empty();
301		this.Menu_Hide();
302
303		return;
304	}
305
306	this.Menu_Show();
307
308	if ( !response.success || ( response.data.length == 0 ) || ( this.element_search.value != original_search_value ) )
309	{
310		return this.Menu_Append_StoreSearch();
311	}
312
313	this.last_displayed_search_value = this.element_search.value;
314
315	this.Menu_Append_Header();
316
317	for ( i = 0, i_len = response.data.length; i < i_len; i++ )
318	{
319		this.Menu_Append_Item( response.data[ i ] );
320	}
321
322	this.Menu_Append_StoreSearch();
323
324	if ( last_selected )
325	{
326		for ( i = 0, i_len = this.menu_items.length; i < i_len; i++ )
327		{
328			if ( this.menu_items[ i ].action == last_selected.action )
329			{
330				this.Menu_Item_Select( this.menu_items[ i ] );
331				break;
332			}
333		}
334	}
335}
336
337MMSearchField.prototype.Event_Keydown = function( e )
338{
339	var keycode, modifier;
340
341	keycode				= e.keyCode || e.which;
342	modifier			= e.metaKey || e.ctrlKey || e.shiftKey || e.altKey;
343	this.current_search = this.element_search.value;
344
345	if ( keycode == 9 && !modifier )			return this.Menu_Hide();
346	else if ( keycode == 13 && !modifier )		return this.Event_Enter( e );
347	else if ( keycode == 27 && !modifier )		return this.Event_ESC( e );
348	else if ( keycode == 38 && !modifier )		return this.Event_ArrowUp( e );
349	else if ( keycode == 40 && !modifier )		return this.Event_ArrowDown( e );
350
351	if ( keycode == 85 && keySupportsMultiSelect( e ) )
352	{
353		this.element_search.value	= '';
354		this.current_search			= '';
355
356		cursorToEnd( this.element_search );
357		this.Menu_Empty();
358		this.Menu_Hide();
359
360		return eventPreventDefault( e );
361	}
362
363	if ( this.element_search.value.length == 0 )
364	{
365		this.Menu_Empty();
366		this.Menu_Hide();
367	}
368	else
369	{
370		this.Menu_Show();
371		this.Menu_Replace_StoreSearch();
372	}
373
374	return true;
375}
376
377MMSearchField.prototype.Event_Keyup = function( e )
378{
379	var self = this;
380	var keycode = e.keyCode || e.which;
381
382	if ( keycode == 13 )		return;	/* Enter Key */
383	else if ( keycode == 27 )	return; /* Esc Key */
384	else if ( keycode == 38 )	return;	/* Up Arrow */
385	else if ( keycode == 40 )	return;	/* Down Arrow */
386
387	if ( this.element_search.value.length == 0 )
388	{
389		this.Menu_Empty();
390		this.Menu_Hide();
391	}
392	else
393	{
394		this.Menu_Show();
395		this.Menu_Replace_StoreSearch();
396	}
397
398	if ( this.current_search == this.element_search.value )
399	{
400		return;
401	}
402
403	if ( this.search_timeout )
404	{
405		clearTimeout( this.search_timeout );
406	}
407
408	this.search_timeout = setTimeout( function()
409	{
410		self.Search( self.element_search.value );
411		self.search_timeout = null;
412	}, this.search_delay );
413}
414
415MMSearchField.prototype.Event_Focus = function( e )
416{
417	if ( this.has_focus )
418	{
419		return;
420	}
421
422	this.has_focus					= true;
423	this.element_search.className	= classNameAdd( this.element_search, 'focu
423s' );
424
425	this.onFocus( e );
426
427	if ( this.element_search.value === this.last_displayed_search_value )
428	{
429		this.Menu_Show();
430	}
431	else if ( this.element_search.value.length )
432	{
433		this.Menu_Empty();
434		this.Menu_Show();
435		this.Menu_Replace_StoreSearch();
436		this.Search( this.element_search.value );
437	}
438
439	AddEvent( document, 'mousedown', this.event_document_mousedown );
440}
441
442MMSearchField.prototype.Event_Blur = function( e )
443{
444	if ( !this.has_focus )
445	{
446		return;
447	}
448
449	this.has_focus					= false;
450	this.element_search.className	= classNameRemove( this.element_search, 'focus' );
451
452	this.Menu_Hide();
453	this.onBlur( e );
454
455	RemoveEvent( document, 'mousedown', this.event_document_mousedown );
456}
457
458MMSearchField.prototype.Event_Enter = function( e )
459{
460	if ( this.selected_item && this.selected_item.action )	this.Menu_Item_OnClick( e, this.selected_item.action );
461	else													this.Menu_Item_OnClick( e, this.GetSearchURL() + encodeURIComponent( this.element_search.value ) );
462
463	eventStopPropagation( e );
464	return eventPreventDefault( e );
465}
466
467MMSearchField.prototype.Event_ESC = function( e )
468{
469	if ( this.menu_visible )
470	{
471		this.Menu_Hide();
472	}
473	else
474	{
475		this.element_search.value	= '';
476		this.current_search			= '';
477
478		this.Menu_Empty();
479		this.Menu_Hide();
480	}
481
482	eventStopPropagation( e );
483	return eventPreventDefault( e );
484}
485
486MMSearchField.prototype.Event_ArrowUp = function( e )
487{
488	var i, i_len, index, next_index;
489
490	if ( !this.menu_visible )
491	{
492		this.Search( this.element_search.value );
493
494		return eventPreventDefault( e );
495	}
496
497	for ( i = 0, i_len = this.menu_items.length; i < i_len; i++ )
498	{
499		this.menu_items[ i ].className = classNameRemove( this.menu_items[ i ], 'mm_searchfield_menuitem_selected' );
500	}
501
502	if ( this.menu_items.length == 0 )
503	{
504		this.Menu_Item_Select( null );
505	}
506
507	if ( ( index = this.menu_items.indexOf( this.selected_item ) ) != -1 )
508	{
509		next_index = ( index - 1 < 0 ) ? ( this.menu_items.length - 1 ) : ( index - 1 );
510	}
511	else
512	{
513		next_index = ( this.menu_items.length - 1 );
514	}
515
516	this.Menu_Item_Select( this.menu_items[ next_index ] );
517
518	return eventPreventDefault( e );
519}
520
521MMSearchField.prototype.Event_ArrowDown = function( e )
522{
523	var i, i_len, index, next_index;
524
525	if ( !this.menu_visible )
526	{
527		this.Search( this.element_search.value );
528
529		return eventPreventDefault( e );
530	}
531
532	for ( i = 0, i_len = this.menu_items.length; i < i_len; i++ )
533	{
534		this.menu_items[ i ].className = classNameRemove( this.menu_items[ i ], 'mm_searchfield_menuitem_selected' );
535	}
536
537	if ( this.menu_items.length == 0 )
538	{
539		this.Menu_Item_Select( null );
540	}
541
542	if ( ( index = this.menu_items.indexOf( this.selected_item ) ) != -1 )
543	{
544		next_index = ( index + 1 > this.menu_items.length - 1 ) ? 0 : ( index + 1 );
545	}
546	else
547	{
548		next_index = 0;
549	}
550
551	this.Menu_Item_Select( this.menu_items[ next_index ] );
552
553	return eventPreventDefault( e );
554}
555
556MMSearchField.prototype.Event_Document_MouseDown = function( e )
557{
558	var target = e.target || e.srcElement;
559
560	if ( target === this.element_menu || containsChild( this.element_menu, target ) )
561	{
562		eventStopPropagation( e );
563		return eventPreventDefault( e );
564	}
565}
566
567MMSearchField.prototype.Event_MenuItem_MouseMove = function( e, item )
568{
569	var i, i_len;
570
571	for ( i = 0, i_len = this.menu_items.length; i < i_len; i++ )
572	{
573		this.menu_items[ i ].className	= classNameRemove( this.menu_items[ i ], 'mm_searchfield_menuitem_selected' );
574	}
575
576	this.Menu_Item_Select( item );
577}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.