PageSourceSearch

https://www.carmellimo.com/design/js/limosys/suggestbox/limosys.suggestbox.js?v=1.01

js carmellimo.com collected 2026-10-04 00:18:43 UTC 13,417 bytes, 338 lines download raw bytes

1/* A jQuery UI widget built on the top of jQuery UI autocomplete and Google place library */
2(function($){
3	$.widget("limosys.suggestbox", {
4		options: {
5			source:[],
6			placeSuggestService: null,
7			placeDetailService: null,
8			blockBlur:function(){return false;}
9		},
10		_create: function(){
11			var $acInput = this.element.clone().removeAttr("id").addClass("ac-input").val("");
12			var removeBtn = $("<div></div>").html("x").addClass("ac-remove-btn");
13			var $acItem = $("<div></div>").addClass("ac-item").append($("<div></div>").addClass("ac-label")).append(removeBtn).attr("tabindex", "0");
14			var $wrapper = $("<div>").addClass("ac-wrapper").addClass(this.element.attr("class")).addClass("form-control");
15			this.wrapper = $wrapper;
16			$acInput.appendTo($wrapper);
17			$acItem.appendTo($wrapper).hide().click(function(){
18				$(this).focus();
19			});
20			this.acItem = $acItem;
21			$wrapper.insertAfter(this.element);
22			this.acInput = $acInput;
23			this.element.hide();
24			var $acSearchIcon = $("<span>").attr("aria-hidden", "true").addClass("ac-search-icon").addClass("fa").addClass("fa-search");
25			$acSearchIcon.insertBefore($acInput);
26			this.acSearchIcon = $acSearchIcon;
27			$acSearchIcon.show();
28			var widget = this;
29			removeBtn.click(function(){
30				widget.clear();
31			});
32			$acItem.keydown(function(e){
33				if(e.which == $.ui.keyCode.BACKSPACE || e.which == $.ui.keyCode.DELETE){
34					widget.clear();
35					e.preventDefault();
36				}
37			});
38			this.wrapper.click(function(){
39				if(widget.acItem.is(":visible")){
40					widget.acItem.focus();
41				}
42			});
43			$acInput.autocomplete({
44				source:function(request, response){
45					var respondWithSuggestions = function(items) {
46						$.each(items || [], function(_, item) {
47							var suggestionText = item.description || item.label || item.value || "";
48							item.description = suggestionText;
49							item.label = suggestionText;
50							item.value = suggestionText;
51						});
52						response(items || []);
53					};
54					var suggestCache = getSuggestCache();
55					var responseData = suggestCache[request.term];
56					if(responseData){
57						respondWithSuggestions(responseData);
58					} else {
59						widget.acInput.userInput = request.term;
60						widget.options.placeSuggestService.getSuggestions(request.term, suggestCache, respondWithSuggestions);
61					}
62				},
63				delay:300,
64				autoFocus: true,
65				select:function(event, ui) {
66					widget.options.placeDetailService.getPlaceDetail(ui.item, widget);
67				}
68			});
69			$acInput.blur(function(){
70				if(!widget.isSelected()){
71					$(this).val("");
72				}
73			});
74			$acInput.data("ui-autocomplete")._renderMenu = function( ul, items ) {
75				var that = this;
76				$(ul).attr({
77					role: "listbox",
78					"aria-label": "Address suggestions"
79				});
80				$.each( items, function( index, item ) {
81					that._renderItemData( ul, item );
82				});
83				var logoClass = widget.options.placeSuggestService.getLogoClass();
84				if (logoClass) {
85					$( ul ).append($("<li>").addClass(logoClass));					
86				}
87			};
88			$acInput.data("ui-autocomplete")._renderItem = function( ul, item ) {
89				var suggestionText = item.description || item.label || item.value || "";
90				var $link = $("<a>");
91
92				if (item.imgUrl) {
93					$link.append($("<img>", {
94						src: item.imgUrl,
95						alt: "",
96						"aria-hidden": "true",
97						height: 15,
98						width: 15
99					}).css("margin-right", "10px"));
100				}
101				$link.append($("<span>").text(suggestionText));
102				return $("<li>", {
103					"data-value": suggestionText,
104					role: "option",
105					"aria-label": suggestionText,
106					"aria-selected": "false"
107				}).append($link).appendTo(ul);
108			};
109
110			//Intercept key down event to control enter key down behavior
111			var eventHandler = findEventHandlers("keydown", $acInput)[0];
112			$acInput.unbind("keydown");
113			$acInput.keydown(function(e){
114				if(widget.acItem.is(":visible")) {
115					if(e.which == $.ui.keyCode.BACKSPACE || e.which == $.ui.keyCode.DELETE  || e.which == $.ui.keyCode.ESCAPE){
116						widget.clear();
117					}
118					if(e.which == $.ui.keyCode.TAB){
119						return true;
120					}
121					return false;
122				}
123				//for some reason, $acInput cannot be used here. Need to investigate javascript var scope
124				if(e.which == $.ui.keyCode.ENTER && (!($(this).autocomplete("widget").is(":visible")) || 
125						$(this).autocomplete("widget").find(".ui-menu-item a.ui-state-active").length == 0 ) ){
126					$(this).blur();
127					return;
128				}
129				for(var i=0;i<eventHandler.events.length;i++){
130					eventHandler.events[i].handler(e);
131				}					
132			});
133			$acInput.data("ui-autocomplete")._resizeMenu = function() {
134			    var ul = this.menu.element;
135			    ul.outerWidth(this.element.outerWidth());
136			};
137			this._resize();
138			$(window).resize(function(){
139				widget._resize();
140			});
141			//Initiate Widget
142			if(this.element.val()!=""){
143				var label = this.element.data("label");
144				var value = this.element.val();
145				if(value && $.trim(value)!="" && label && $.trim(label)!=""){
146					this.setItem({
147						value:value,
148						label:label
149					}, false);
150				} else if(value && $.trim(value)!="" && typeof this.options.source == "object"){
151					for(var i=0; i< this.options.source.length; i++){
152						if(this.options.source[i].value == value){
153							this.setItem(this.options.source[i], false);
154						}
155					}
156				}else{
157					this.clear();
158				}
159			}
160		},
161		setItem: function(item, focusAfterSetItem){
162			if(typeof focusAfterSetItem == "undefined") focusAfterSetItem = true;
163			this._resize();
164			this.acItem.find(".ac-label").html(item.label).attr("title", item.label);	
165			this.acInput.hide();//.css("position", "fixed").css("top", "-1000px");
166			this.acSearchIcon.hide();
167			this.acItem.show();
168			//this.acInput.change();
169			//if(focusAfterSetItem) this.acItem.focus();
170			this.element.val(item.description);
171			this.element.data("label", item.label);
172			this._trigger("itemFilled");
173			return $(this);
174		},
175		clear: function(){
176			this.acItem.hide();
177			this.acInput.val("").show();//.css("position", "relative").css("top", "0");
178			this.acInput.focus();
179			this.acSearchIcon.show();
180			this.acInput.val("");
181			this.element.val("");
182			this._trigger("itemCleared", null);
183		},
184		isSelected: function(){
185			return this.acItem.is(":visible");
186		},
187		getDisplayValue: function(){
188			return this.acInput.val();
189		},
190		focusWidget: function(){
191			this.acInput.focus();
192		},
193		blurWidget: function(){
194			this.acInput.blur();
195		},
196		_resize: function(){
197//			this.wrapper.width(this.element.width());
198			var boxWidth = this.acInput.outerWidth(true);
199			var safeMargin = 5;
200			var removeBtnWidth= this.acItem.find(".ac-remove-btn").outerWidth();
201			this.acItem.find(".ac-label").css("max-width", (boxWidth - removeBtnWidth - safeMargin) + "px");
202			var addrItemWidth = this.acItem.find(".ac-item").outerWidth(true);
203			this.acItem.find(".ac-cursor-container").css("width", boxWidth - addrItemWidth);
204		}
205	});
206}(jQuery));
207
208$._isMobile=function() {
209	var check = false;
210	(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
211	return check; 
212};
213
214var getSuggestCache = function(){
215	var suggestCache = $("body").data("suggestCache");
216	if(typeof suggestCache == "undefined"){
217		suggestCache = {};
218		$("body").data("suggestCache", suggestCache);
219	}
220	return suggestCache;
221};
222
223var findEventHandlers = function (eventType, jqSelector) {
224    var results = [];
225    var $ = jQuery;// to avoid conflict between others frameworks like Mootools
226
227    var arrayIntersection = function (array1, array2) {
228        return $(array1).filter(function (index, element) {
229            return $.inArray(element, $(array2)) !== -1;
230        });
231    };
232
233    var haveCommonElements = function (array1, array2) {
234        return arrayIntersection(array1, array2).length !== 0;
235    };
236
237
238    var addEventHandlerInfo = function (element, event, $elementsCovered) {
239        var extendedEvent = event;
240        if ($elementsCovered !== void 0 && $elementsCovered !== null) {
241            $.extend(extendedEvent, { targets: $elementsCovered.toArray() });
242        }
243        var eventInfo;
244        var eventsInfo = $.grep(results, function (evInfo, index) {
245            return element === evInfo.element;
246        });
247
248        if (eventsInfo.length === 0) {
249            eventInfo = {
250                element: element,
251                events: [extendedEvent]
252            };
253            results.push(eventInfo);
254        } else {
255            eventInfo = eventsInfo[0];
256            eventInfo.events.push(extendedEvent);
257        }
258    };
259
260
261    var $elementsToWatch = $(jqSelector);
262    if (jqSelector === "*")//* does not include document and we might be interested in handlers registered there
263        $elementsToWatch = $elementsToWatch.add(document); 
264    var $allElements = $("*").add(document);
265
266    $.each($allElements, function (elementIndex, element) {
267        var allElementEvents = $._data(element, "events");
268        if (allElementEvents !== void 0 && allElementEvents[eventType] !== void 0) {
269            var eventContainer = allElementEvents[eventType];
270            $.each(eventContainer, function(eventIndex, event){
271                var isDelegateEvent = event.selector !== void 0 && event.selector !== null;
272                var $elementsCovered;
273                if (isDelegateEvent) {
274                    $elementsCovered = $(event.selector, element); //only look at children of the element, since those are the only ones the handler covers
275                } else {
276                    $elementsCovered = $(element); //just itself
277                }
278                if (haveCommonElements($elementsCovered, $elementsToWatch)) {
279                    addEventHandlerInfo(element, event, $elementsCovered);
280                }
281            });
282        }
283    });
284    return results;
285};
286
287
288function Addr() {
289	this.streetNum = "";
290	this.streetName = "";
291	this.city = "";
292	this.state = "";
293	this.zip = "";
294	this.lat = null;
295	this.lng = null;
296	this.airportCd = "";
297	this.airlineCd = "";
298	this.remark = "";
299	this.types = [];
300	this.formattedAddress = "";
301	this.areaCode = "";
302	this.userInput = "";
303	this.countryId = null;
304	this.placeId = "";
305	this.placeDetailResponse= "";
306
307	this.setLatLng = function (lat, lng) {
308		this.lat = lat ? Number(lat) : null;
309		this.lng = lng ? Number(lng) : null;
310	};
311	
312	this.setCountryId = function (countryId) {
313		this.countryId = countryId ? Number(countryId) : null;
314	}
315}
316
317
318function setAddr_FromPlaceService(placeResult, userInput) {
319	var addr = new Addr();
320	addr.placeDetailResponse = placeResult;
321	addr.userInput = userInput;
322   	return addr;
323}
324
325function setAddr_FromUserProfile(userAddr) {
326	var parsedAddress = new Addr();
327	parsedAddress.streetNum = userAddr.data('street-num').toString();
328	parsedAddress.streetName = userAddr.data('street-name');
329	parsedAddress.city = userAddr.data('city');
330	parsedAddress.areaCode = userAddr.data('areacd'); 
331	parsedAddress.zip = userAddr.data('zip').toString();
332	parsedAddress.setLatLng(userAddr.data('lat'), userAddr.data('lng'));	
333	parsedAddress.setCountryId(userAddr.data('countryid'));
334	parsedAddress.remark = userAddr.data('remark');	
335	parsedAddress.types = ["street_address"];
336	return parsedAddress;
337	
338}

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.