Completed
Push — development ( 5236fa...488938 )
by Stephen
20s
created

smc_AutoSuggest.addItemLink   B

Complexity

Conditions 4
Paths 9

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 4
nc 9
nop 3
dl 0
loc 33
rs 8.5806
c 2
b 0
f 1
1
/*!
2
 * @name      ElkArte Forum
3
 * @copyright ElkArte Forum contributors
4
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
5
 *
6
 * This file contains code covered by:
7
 * copyright:	2011 Simple Machines (http://www.simplemachines.org)
8
 * license:		BSD, See included LICENSE.TXT for terms and conditions.
9
 *
10
 * @version 1.1
11
 */
12
13
/**
14
 * This file contains javascript associated with a autosuggest control.
15
 */
16
17
/**
18
 * The autosuggest class, used to display a selection list of members
19
 *
20
 * @param {object} oOptions
21
 */
22
function smc_AutoSuggest(oOptions)
23
{
24
	this.opt = oOptions;
25
26
	// Store the handle to the text box.
27
	this.oTextHandle = document.getElementById(this.opt.sControlId);
28
	this.oRealTextHandle = null;
29
	this.oSuggestDivHandle = null;
30
31
	this.sLastSearch = '';
32
	this.sLastDirtySearch = '';
33
	this.oSelectedDiv = null;
34
	this.aCache = [];
35
	this.aDisplayData = [];
36
	this.sRetrieveURL = 'sRetrieveURL' in this.opt ? this.opt.sRetrieveURL : '%scripturl%action=suggest;xml';
37
38
	// How many objects can we show at once?
39
	this.iMaxDisplayQuantity = 'iMaxDisplayQuantity' in this.opt ? this.opt.iMaxDisplayQuantity : 12;
40
41
	// How many characters shall we start searching on?
42
	this.iMinimumSearchChars = 'iMinimumSearchChars' in this.opt ? this.opt.iMinimumSearchChars : 2;
43
44
	// Should selected items be added to a list?
45
	this.bItemList = 'bItemList' in this.opt ? this.opt.bItemList : false;
46
47
	// Are there any items that should be added in advance?
48
	this.aListItems = 'aListItems' in this.opt ? this.opt.aListItems : [];
49
50
	this.sItemTemplate = 'sItemTemplate' in this.opt ? this.opt.sItemTemplate : '<input type="hidden" name="%post_name%[]" value="%item_id%" /><a href="%item_href%" class="extern" onclick="window.open(this.href, \'_blank\'); return false;">%item_name%</a>&nbsp;<img src="%images_url%/pm_recipient_delete.png" alt="%delete_text%" title="%delete_text%" />';
51
	this.sTextDeleteItem = 'sTextDeleteItem' in this.opt ? this.opt.sTextDeleteItem : '';
52
	this.oCallback = {};
53
	this.bDoAutoAdd = false;
54
	this.iItemCount = 0;
55
	this.oHideTimer = null;
56
	this.bPositionComplete = false;
57
58
	this.oXmlRequestHandle = null;
59
60
	// Just make sure the page is loaded before calling the init.
61
	window.addEventListener("load", this.init.bind(this));
62
}
63
64
// Initialize our autosuggest object, adds events and containers to the element we monitor
65
smc_AutoSuggest.prototype.init = function()
66
{
67
	// Create a div that'll contain the results later on.
68
	this.oSuggestDivHandle = document.createElement('div');
69
	this.oSuggestDivHandle.className = 'auto_suggest_div';
70
	document.body.appendChild(this.oSuggestDivHandle);
71
72
	// Create a backup text input.
73
	this.oRealTextHandle = document.createElement('input');
74
	this.oRealTextHandle.type = 'hidden';
75
	this.oRealTextHandle.name = this.oTextHandle.name;
76
	this.oRealTextHandle.value = this.oTextHandle.value;
77
	this.oTextHandle.form.appendChild(this.oRealTextHandle);
78
79
	// Disable autocomplete in any browser by obfuscating the name.
80
	this.oTextHandle.name = 'dummy_' + Math.floor(Math.random() * 1000000);
81
	this.oTextHandle.autocomplete = 'off';
82
83
	// Set up all the event monitoring
84
	this.oTextHandle.onkeydown = this.handleKey.bind(this);
85
	this.oTextHandle.onkeyup = this.autoSuggestUpdate.bind(this);
86
	this.oTextHandle.onchange = this.autoSuggestUpdate.bind(this);
87
	this.oTextHandle.onblur = this.autoSuggestHide.bind(this);
88
	this.oTextHandle.onfocus = this.autoSuggestUpdate.bind(this);
89
90
	// Adding items to a list, then we need a place to insert them
91
	if (this.bItemList)
92
	{
93
		if ('sItemListContainerId' in this.opt)
94
			this.oItemList = document.getElementById(this.opt.sItemListContainerId);
95
		else
96
		{
97
			this.oItemList = document.createElement('div');
98
			this.oTextHandle.parentNode.insertBefore(this.oItemList, this.oTextHandle.nextSibling);
99
		}
100
	}
101
102
	// Items provided to add to the top of the selection list?
103
	if (this.aListItems.length > 0)
104
		for (var i = 0, n = this.aListItems.length; i < n; i++)
105
			this.addItemLink(this.aListItems[i].sItemId, this.aListItems[i].sItemName);
106
107
	return true;
108
};
109
110
/**
111
 * Handle keypress events for the suggest controller
112
 *
113
 * @param oEvent
114
 */
115
smc_AutoSuggest.prototype.handleKey = function(oEvent)
116
{
117
	// Grab the event object, one way or the other
118
	if (!oEvent)
119
		oEvent = window.event;
120
121
	// Get the keycode of the key that was pressed.
122
	var iKeyPress = 0;
123
	if ('which' in oEvent)
124
		iKeyPress = oEvent.which;
125
	else if ('keyCode' in oEvent)
126
		iKeyPress = oEvent.keyCode;
127
128
	// Check what key they have pressed
129
	switch (iKeyPress)
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
130
	{
131
		// Tab.
132
		case 9:
133
			if (this.aDisplayData.length > 0)
134
			{
135
				if (this.oSelectedDiv !== null)
136
					this.itemClicked(this.oSelectedDiv);
137
				else
138
					this.handleSubmit();
139
			}
140
141
			// Continue to the next control.
142
			return true;
143
		break;
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
Unused Code introduced by
The code break after return is not reachable.
Loading history...
144
145
		// Was it an Enter key - if so assume they are trying to select something.
146
		case 13:
147
			if (this.aDisplayData.length > 0 && this.oSelectedDiv !== null)
148
			{
149
				this.itemClicked(this.oSelectedDiv);
150
151
				// Do our best to stop it submitting the form!
152
				return false;
153
			}
154
			else
155
				return true;
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
156
		break;
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
157
158
		// Up/Down arrow?
159
		case 38:
160
		case 40:
161
			if (this.aDisplayData.length && this.oSuggestDivHandle.style.visibility !== 'hidden')
162
			{
163
				// Loop through the display data trying to find our entry.
164
				var bPrevHandle = false,
165
					oToHighlight = null;
166
167
				for (var i = 0; i < this.aDisplayData.length; i++)
168
				{
169
					// If we're going up and yet the top one was already selected don't go around.
170
					if (this.oSelectedDiv !== null && this.oSelectedDiv === this.aDisplayData[i] && i === 0 && iKeyPress === 38)
171
					{
172
						oToHighlight = this.oSelectedDiv;
173
						break;
174
					}
175
176
					// If nothing is selected and we are going down then we select the first one.
177
					if (this.oSelectedDiv === null && iKeyPress === 40)
178
					{
179
						oToHighlight = this.aDisplayData[i];
180
						break;
181
					}
182
183
					// If the previous handle was the actual previously selected one and we're hitting down then this is the one we want.
184
					if (bPrevHandle !== false && bPrevHandle === this.oSelectedDiv && iKeyPress === 40)
185
					{
186
						oToHighlight = this.aDisplayData[i];
187
						break;
188
					}
189
190
					// If we're going up and this is the previously selected one then we want the one before, if there was one.
191
					if (bPrevHandle !== false && this.aDisplayData[i] === this.oSelectedDiv && iKeyPress === 38)
192
					{
193
						oToHighlight = bPrevHandle;
194
						break;
195
					}
196
197
					// Make the previous handle this!
198
					bPrevHandle = this.aDisplayData[i];
199
				}
200
201
				// If we don't have one to highlight by now then it must be the last one that we're after.
202
				if (oToHighlight === null)
203
					oToHighlight = bPrevHandle;
204
205
				// Remove any old highlighting.
206
				if (this.oSelectedDiv !== null)
207
					this.itemMouseOut(this.oSelectedDiv);
208
209
				// Mark what the selected div now is.
210
				this.oSelectedDiv = oToHighlight;
211
				this.itemMouseOver(this.oSelectedDiv);
212
			}
213
		break;
214
	}
215
	return true;
216
};
217
218
// Functions for integration.
219
smc_AutoSuggest.prototype.registerCallback = function(sCallbackType, sCallback)
220
{
221
	switch (sCallbackType)
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
222
	{
223
		case 'onBeforeAddItem':
224
			this.oCallback.onBeforeAddItem = sCallback;
225
		break;
226
227
		case 'onAfterAddItem':
228
			this.oCallback.onAfterAddItem = sCallback;
229
		break;
230
231
		case 'onAfterDeleteItem':
232
			this.oCallback.onAfterDeleteItem = sCallback;
233
		break;
234
235
		case 'onBeforeUpdate':
236
			this.oCallback.onBeforeUpdate = sCallback;
237
		break;
238
	}
239
};
240
241
// User hit submit?
242
smc_AutoSuggest.prototype.handleSubmit = function()
243
{
244
	var bReturnValue = true,
245
		oFoundEntry = null;
246
247
	// Do we have something that matches the current text?
248
	for (var i = 0; i < this.aCache.length; i++)
249
	{
250
		if (this.sLastSearch.toLowerCase() === this.aCache[i].sItemName.toLowerCase().substr(0, this.sLastSearch.length))
251
		{
252
			// Exact match?
253
			if (this.sLastSearch.length === this.aCache[i].sItemName.length)
254
			{
255
				// This is the one!
256
				oFoundEntry = {
257
					sItemId: this.aCache[i].sItemId,
258
					sItemName: this.aCache[i].sItemName
259
				};
260
261
				break;
262
			}
263
			// Not an exact match, but it'll do for now.
264
			else
265
			{
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
266
				// If we have two matches don't find anything.
267
				if (oFoundEntry !== null)
268
					bReturnValue = false;
269
				else {
270
					oFoundEntry = {
271
						sItemId: this.aCache[i].sItemId,
272
						sItemName: this.aCache[i].sItemName
273
					};
274
				}
275
			}
276
		}
277
	}
278
279
	if (oFoundEntry === null || bReturnValue === false)
280
		return bReturnValue;
281
	else
282
	{
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
283
		this.addItemLink(oFoundEntry.sItemId, oFoundEntry.sItemName, true);
284
		return false;
285
	}
286
};
287
288
// Positions the box correctly on the window.
289
smc_AutoSuggest.prototype.positionDiv = function()
290
{
291
	// Only do it once.
292
	if (this.bPositionComplete)
293
		return true;
294
295
	this.bPositionComplete = true;
296
297
	// Put the div under the text box.
298
	var aParentPos = elk_itemPos(this.oTextHandle);
299
300
	this.oSuggestDivHandle.style.left = aParentPos[0] + 'px';
301
	this.oSuggestDivHandle.style.top = (aParentPos[1] + this.oTextHandle.offsetHeight) + 'px';
302
	this.oSuggestDivHandle.style.width = this.oTextHandle.clientWidth + 'px';
303
304
	return true;
305
};
306
307
// Do something after clicking an item.
308
smc_AutoSuggest.prototype.itemClicked = function(oEvent)
309
{
310
	// Is there a div that we are populating?
311
	if (this.bItemList)
312
		this.addItemLink(oEvent.target.sItemId, oEvent.target.innerHTML);
313
	// Otherwise clear things down.
314
	else
315
		this.oTextHandle.value = oEvent.target.innerHTML.php_unhtmlspecialchars();
316
317
	this.oRealTextHandle.value = this.oTextHandle.value;
318
	this.autoSuggestActualHide();
319
	this.oSelectedDiv = null;
320
};
321
322
// Remove the last searched for name from the search box.
323
smc_AutoSuggest.prototype.removeLastSearchString = function ()
324
{
325
	// Remove the text we searched for from the div.
326
	var sTempText = this.oTextHandle.value.toLowerCase(),
327
		iStartString = sTempText.indexOf(this.sLastSearch.toLowerCase());
328
329
	// Just attempt to remove the bits we just searched for.
330
	if (iStartString !== -1)
331
	{
332
		while (iStartString > 0)
333
		{
334
			if (sTempText.charAt(iStartString - 1) === '"' || sTempText.charAt(iStartString - 1) === ',' || sTempText.charAt(iStartString - 1) === ' ')
335
			{
336
				iStartString--;
337
				if (sTempText.charAt(iStartString - 1) === ',')
338
					break;
339
			}
340
			else
341
				break;
342
		}
343
344
		// Now remove anything from iStartString upwards.
345
		this.oTextHandle.value = this.oTextHandle.value.substr(0, iStartString);
346
	}
347
	// Just take it all.
348
	else
349
		this.oTextHandle.value = '';
350
};
351
352
// Add a result if not already done.
353
smc_AutoSuggest.prototype.addItemLink = function (sItemId, sItemName, bFromSubmit)
354
{
355
	// Increase the internal item count.
356
	this.iItemCount ++;
357
358
	// If there's a callback then call it.
359
	if (typeof(this.oCallback.onBeforeAddItem) === 'function')
360
	{
361
		// If it returns false the item must not be added.
362
		if (!this.oCallback.onBeforeAddItem.call(this, sItemId))
363
			return;
364
	}
365
366
	var oNewDiv = document.createElement('div');
367
	oNewDiv.id = 'suggest_' + this.opt.sSuggestId + '_' + sItemId;
368
	oNewDiv.innerHTML = this.sItemTemplate.replace(/%post_name%/g, this.opt.sPostName).replace(/%item_id%/g, sItemId).replace(/%item_href%/g, elk_prepareScriptUrl(elk_scripturl) + this.opt.sURLMask.replace(/%item_id%/g, sItemId)).replace(/%item_name%/g, sItemName).replace(/%images_url%/g, elk_images_url).replace(/%delete_text%/g, this.sTextDeleteItem);
0 ignored issues
show
Bug introduced by
The variable elk_scripturl seems to be never declared. If this is a global, consider adding a /** global: elk_scripturl */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Bug introduced by
The variable elk_images_url seems to be never declared. If this is a global, consider adding a /** global: elk_images_url */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
369
370
	oNewDiv.getElementsByTagName('img')[0].addEventListener("click", this.deleteAddedItem.bind(this));
371
	this.oItemList.appendChild(oNewDiv);
372
373
	// If there's a registered callback, call it.
374
	if (typeof(this.oCallback.onAfterAddItem) === 'function')
375
		this.oCallback.onAfterAddItem.call(this, oNewDiv.id);
376
377
	// Clear the div a bit.
378
	this.removeLastSearchString();
379
380
	// If we came from a submit, and there's still more to go, turn on auto add for all the other things.
381
	this.bDoAutoAdd = this.oTextHandle.value !== '' && bFromSubmit;
382
383
	// Update the fellow..
384
	this.autoSuggestUpdate();
385
};
386
387
// Delete an item that has been added, if at all?
388
smc_AutoSuggest.prototype.deleteAddedItem = function (oEvent)
389
{
390
	var oDiv = oEvent.target.parentNode;
391
392
	// Remove the div if it exists.
393
	if (typeof(oDiv) === 'object' && oDiv !== null)
394
	{
395
		this.oItemList.removeChild(oDiv);
396
397
		// Decrease the internal item count.
398
		this.iItemCount --;
399
400
		// If there's a registered callback, call it.
401
		if (typeof(this.oCallback.onAfterDeleteItem) === 'function')
402
			this.oCallback.onAfterDeleteItem.call(this);
403
	}
404
405
	return false;
406
};
407
408
// Hide the box.
409
smc_AutoSuggest.prototype.autoSuggestHide = function ()
410
{
411
	// Delay to allow events to propagate through....
412
	this.oHideTimer = setTimeout(this.autoSuggestActualHide.bind(this), 250);
413
};
414
415
// Do the actual hiding after a timeout.
416
smc_AutoSuggest.prototype.autoSuggestActualHide = function()
417
{
418
	this.oSuggestDivHandle.style.display = 'none';
419
	this.oSuggestDivHandle.style.visibility = 'hidden';
420
	this.oSelectedDiv = null;
421
};
422
423
// Show the box.
424
smc_AutoSuggest.prototype.autoSuggestShow = function()
425
{
426
	if (this.oHideTimer)
427
	{
428
		clearTimeout(this.oHideTimer);
429
		this.oHideTimer = false;
430
	}
431
432
	this.positionDiv();
433
	this.oSuggestDivHandle.style.visibility = 'visible';
434
	this.oSuggestDivHandle.style.display = '';
435
};
436
437
// Populate the actual div.
438
smc_AutoSuggest.prototype.populateDiv = function(aResults)
439
{
440
	// Cannot have any children yet.
441
	while (this.oSuggestDivHandle.childNodes.length > 0)
442
	{
443
		// Tidy up the events etc too.
444
		this.oSuggestDivHandle.childNodes[0].onmouseover = null;
445
		this.oSuggestDivHandle.childNodes[0].onmouseout = null;
446
		this.oSuggestDivHandle.childNodes[0].onclick = null;
447
448
		this.oSuggestDivHandle.removeChild(this.oSuggestDivHandle.childNodes[0]);
449
	}
450
451
	// Something to display?
452
	if (typeof(aResults) === 'undefined')
453
	{
454
		this.aDisplayData = [];
455
		return false;
456
	}
457
458
	var aNewDisplayData = [];
459
	for (var i = 0; i < (aResults.length > this.iMaxDisplayQuantity ? this.iMaxDisplayQuantity : aResults.length); i++)
460
	{
461
		// Create the sub element
462
		var oNewDivHandle = document.createElement('div');
463
464
		oNewDivHandle.sItemId = aResults[i].sItemId;
465
		oNewDivHandle.className = 'auto_suggest_item';
466
		oNewDivHandle.innerHTML = aResults[i].sItemName;
467
		//oNewDivHandle.style.width = this.oTextHandle.style.width;
468
469
		this.oSuggestDivHandle.appendChild(oNewDivHandle);
470
471
		// Attach some events to it so we can do stuff.
472
		oNewDivHandle.onmouseover = function ()
473
		{
474
			this.className = 'auto_suggest_item_hover';
475
		};
476
		oNewDivHandle.onmouseout = function ()
477
		{
478
			this.className = 'auto_suggest_item';
479
		};
480
		oNewDivHandle.onclick = this.itemClicked.bind(this);
481
482
		aNewDisplayData[i] = oNewDivHandle;
483
	}
484
485
	this.aDisplayData = aNewDisplayData;
486
487
	return true;
488
};
489
490
// Callback function for the XML request, should contain the list of users that match
491
smc_AutoSuggest.prototype.onSuggestionReceived = function (oXMLDoc)
492
{
493
	var sQuoteText = '',
0 ignored issues
show
Unused Code introduced by
The variable sQuoteText seems to be never used. Consider removing it.
Loading history...
494
		aItems = oXMLDoc.getElementsByTagName('item');
495
496
	// Go through each item received
497
	this.aCache = [];
498
	for (var i = 0; i < aItems.length; i++)
499
	{
500
		this.aCache[i] = {
501
			sItemId: aItems[i].getAttribute('id'),
502
			sItemName: aItems[i].childNodes[0].nodeValue
503
		};
504
505
		// If we're doing auto add and we found the exact person, then add them!
506
		if (this.bDoAutoAdd && this.sLastSearch === this.aCache[i].sItemName)
507
		{
508
			var oReturnValue = {
509
				sItemId: this.aCache[i].sItemId,
510
				sItemName: this.aCache[i].sItemName
511
			};
512
			this.aCache = [];
513
			return this.addItemLink(oReturnValue.sItemId, oReturnValue.sItemName, true);
514
		}
515
	}
516
517
	// Check we don't try to keep auto updating!
518
	this.bDoAutoAdd = false;
519
520
	// Populate the div.
521
	this.populateDiv(this.aCache);
522
523
	// Make sure we can see it - if we can.
524
	if (aItems.length === 0)
525
		this.autoSuggestHide();
526
	else
527
		this.autoSuggestShow();
528
529
	return true;
530
};
531
532
// Get a new suggestion.
533
smc_AutoSuggest.prototype.autoSuggestUpdate = function ()
534
{
535
	// If there's a callback then call it.
536
	if (typeof(this.oCallback.onBeforeUpdate) === 'function')
537
	{
538
		// If it returns false the item must not be added.
539
		if (!this.oCallback.onBeforeUpdate.call(this))
540
			return false;
541
	}
542
543
	this.oRealTextHandle.value = this.oTextHandle.value;
544
545
	if (isEmptyText(this.oTextHandle))
546
	{
547
		this.aCache = [];
548
		this.populateDiv();
549
		this.autoSuggestHide();
550
551
		return true;
552
	}
553
554
	// Nothing changed?
555
	if (this.oTextHandle.value === this.sLastDirtySearch)
556
		return true;
557
	this.sLastDirtySearch = this.oTextHandle.value;
558
559
	// We're only actually interested in the last string.
560
	var sSearchString = this.oTextHandle.value.replace(/^("[^"]+",[ ]*)+/, '').replace(/^([^,]+,[ ]*)+/, '');
561
	if (sSearchString.substr(0, 1) === '"')
562
		sSearchString = sSearchString.substr(1);
563
564
	// Stop replication ASAP.
565
	var sRealLastSearch = this.sLastSearch;
566
	this.sLastSearch = sSearchString;
567
568
	// Either nothing or we've completed a sentence.
569
	if (sSearchString === '' || sSearchString.substr(sSearchString.length - 1) === '"')
570
	{
571
		this.populateDiv();
572
		return true;
573
	}
574
575
	// Nothing?
576
	if (sRealLastSearch === sSearchString)
577
		return true;
578
	// Too small?
579
	else if (sSearchString.length < this.iMinimumSearchChars)
580
	{
581
		this.aCache = [];
582
		this.autoSuggestHide();
583
		return true;
584
	}
585
	else if (sSearchString.substr(0, sRealLastSearch.length) === sRealLastSearch)
586
	{
587
		// Instead of hitting the server again, just narrow down the results...
588
		var aNewCache = [],
589
			j = 0,
590
			sLowercaseSearch = sSearchString.toLowerCase();
591
592
		for (var k = 0; k < this.aCache.length; k++)
593
		{
594
			if (this.aCache[k].sItemName.substr(0, sSearchString.length).toLowerCase() === sLowercaseSearch)
595
				aNewCache[j++] = this.aCache[k];
596
		}
597
598
		this.aCache = [];
599
		if (aNewCache.length !== 0)
600
		{
601
			this.aCache = aNewCache;
602
603
			// Repopulate.
604
			this.populateDiv(this.aCache);
605
606
			// Check it can be seen.
607
			this.autoSuggestShow();
608
609
			return true;
610
		}
611
	}
612
613
	// In progress means destroy!
614
	if (typeof(this.oXmlRequestHandle) === 'object' && this.oXmlRequestHandle !== null)
615
		this.oXmlRequestHandle.abort();
616
617
	// Clean the text handle.
618
	sSearchString = sSearchString.php_urlencode();
619
620
	// Get the document.
621
	var obj = {
622
			"suggest_type": this.opt.sSearchType,
623
			"search": sSearchString,
624
			"time": new Date().getTime()
625
		},
626
		postString;
627
628
	// Post values plus session
629
	postString = "jsonString=" + JSON.stringify(obj) + "&" + this.opt.sSessionVar + "=" + this.opt.sSessionId;
630
631
	sendXMLDocument.call(this, this.sRetrieveURL.replace(/%scripturl%/g, elk_prepareScriptUrl(elk_scripturl)), postString, this.onSuggestionReceived);
0 ignored issues
show
Bug introduced by
The variable elk_scripturl seems to be never declared. If this is a global, consider adding a /** global: elk_scripturl */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Bug introduced by
The variable sendXMLDocument seems to be never declared. If this is a global, consider adding a /** global: sendXMLDocument */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
632
633
	return true;
634
};