Hovering Bing Search using jQuery
Taking the Bing API for another test drive, I wrote up a jQuery / JSON Ajax driven website tool as well. The following little thing will show a semi-transparent hovering box as you select text on a web site. If you click the box, a Bing search will be made, and the top 10 results will be shown in the popup.
Feel free to give it a go at the example page. The initial JavaScript is shown in full shortly, but for updated source code and examples, I suggest you head over to the HoverBing CodePlex project I just created.
1: (function()
2: {
3: getSelectedText = function()
4: {
5: if(window.getSelection){
6: return window.getSelection().toString();
7: }
8: else if(document.getSelection){
9: return document.getSelection();
10: }
11: else if(document.selection){
12: return document.selection.createRange().text;
13: }
14: }
15:
16: alternate = function(counter, norm, alt)
17: {
18: return counter % 2 == 0 ? alt : norm;
19: }
20:
21: createHoverBingObject = function(settings)
22: {
23: HoverBingObject =
24: {
25: // Settings
26: appId: settings.appId,
27: numResults: settings.numResults,
28: sources: settings.sources,
29: title: settings.title,
30:
31: activateSearchPopup: function(x, y)
32: {
33: var popup = $("#SearchPopup");
34: if(x && y)
35: {
36: popup
37: .css({
38: cursor: "pointer",
39: left: x + 5,
40: top: y + 5
41: })
42: .show();
43: HoverBingObject.repositionToFitScreen();
44: HoverBingObject.fadePopupByDistance(x, y);
45: }
46: popup.data("SearchPopup_State", "waiting");
47: $().bind('mousemove', HoverBingObject.mouseMoveSearchPopup);
48: },
49:
50: create: function()
51: {
52: HoverBingObject.initSearchPopup();
53: $().mouseup(function(e) {
54: var selText = getSelectedText();
55: var popup = $("#SearchPopup");
56: var state = popup.data("SearchPopup_State");
57: if((state == undefined || state == "hidden") &&
58: selText.length > 0)
59: {
60: popup.data("SearchPopup_Query", HoverBingObject.washQueryText(selText));
61: HoverBingObject.activateSearchPopup(e.pageX, e.pageY);
62: }
63: else if(state != "stapled")
64: {
65: HoverBingObject.deactivateSearchPopup();
66: }
67: });
68: $().mousedown(function(e) {
69: var popup = $("#SearchPopup");
70: var state = popup.data("SearchPopup_State");
71: if(state != undefined && state == "waiting")
72: {
73: HoverBingObject.deactivateSearchPopup();
74: }
75: });
76: },
77:
78: deactivateSearchPopup: function()
79: {
80: var popup = $("#SearchPopup");
81: popup.find("span").empty();
82: popup
83: .fadeTo(0, 0)
84: .hide()
85: .data("SearchPopup_State", "hidden");
86: $().unbind('mousemove', HoverBingObject.mouseMoveSearchPopup);
87: },
88:
89: fadePopupByDistance: function(mouseX, mouseY)
90: {
91: var popup = $("#SearchPopup");
92: var pos = popup.position();
93: pos.left += popup.width() * 0.5;
94: pos.top += popup.height() * 0.5;
95: var dist = Math.round(Math.sqrt(Math.pow(mouseX - pos.left, 2) + Math.pow(mouseY - pos.top, 2)));
96: popup.fadeTo(0, Math.max(1 - dist / 500, 0));
97: },
98:
99: initSearchPopup: function()
100: {
101: // Create box
102: var box = document.createElement("div");
103: $(box)
104: .attr("id", "SearchPopup")
105: .attr("class", "HoverBing")
106: .css({
107: position: "absolute",
108: opacity: 0
109: })
110: .mouseenter(function() {
111: var state = $("#SearchPopup").data("SearchPopup_State");
112: if(state == "waiting")
113: {
114: HoverBingObject.stapleSearchPopup();
115: }
116: })
117: .mouseleave(function() {
118: var popup = $("#SearchPopup");
119: var state = popup.data("SearchPopup_State");
120: if(state == "stapled")
121: {
122: HoverBingObject.activateSearchPopup();
123: }
124: })
125: .data("SearchPopup_State", "hidden");
126:
127: // Create header control
128: var header = document.createElement("div");
129: $(header)
130: .attr("class", "Header")
131: .html(HoverBingObject.title);
132:
133: // Create content control
134: var content = document.createElement("span");
135: $(content)
136: .attr("class", "Content")
137:
138: // Append header and content to outer box
139: $(box)
140: .append(header)
141: .append(content);
142:
143: // Add outer box to body
144: $(document.body).append(box);
145: },
146:
147: mouseMoveSearchPopup: function(e)
148: {
149: HoverBingObject.fadePopupByDistance(e.pageX, e.pageY);
150: },
151:
152: onClickSearchPopup: function()
153: {
154: var popup = $("#SearchPopup");
155: var query = popup.data("SearchPopup_Query");
156: var contents = popup.find("span").empty();
157: $.getJSON("http://api.search.live.net/json.aspx" +
158: "?AppId=" + HoverBingObject.appId +
159: "&Market=en-US&Query=" + query +
160: "&Sources=" + HoverBingObject.sources +
161: "&Web.Count=" + HoverBingObject.numResults +
162: "&JsonType=callback&JsonCallback=?",
163: HoverBingObject.onSearchResultsReceived);
164: },
165:
166: onSearchResultsReceived: function(data)
167: {
168: var popup = $("#SearchPopup");
169: var contents = popup.find("span").empty();
170:
171: if(data.SearchResponse == null)
172: {
173: contents.html("No search results returned");
174: return;
175: }
176:
177: $.each(data.SearchResponse.Web.Results, function(i ,item) {
178: contents.append(
179: $(document.createElement("a"))
180: .attr("class", alternate(i, "ResultLine", "ResultLineAlt"))
181: .css({
182: display: 'block'
183: })
184: .click(function() {
185: HoverBingObject.deactivateSearchPopup();
186: })
187: .mouseenter(function() {
188: $(this).addClass("ResultLineHover");
189: })
190: .mouseleave(function() {
191: $(this).removeClass("ResultLineHover");
192: })
193: .text(item.Title)
194: .attr("href", item.Url)
195: .attr("target", "_blank")
196: );
197: });
198:
199: HoverBingObject.repositionToFitScreen();
200: },
201:
202: repositionToFitScreen: function()
203: {
204: var popup = $("#SearchPopup");
205: var pos = popup.position();
206: if(pos.left + popup.width() > $(window).width())
207: {
208: popup.css({left: $(window).width() - popup.width()});
209: }
210: if(pos.top + popup.height() > $(window).height())
211: {
212: popup.css({top: $(window).height() - popup.height()});
213: }
214: },
215:
216: stapleSearchPopup: function()
217: {
218: $("#SearchPopup")
219: .data("SearchPopup_State", "stapled")
220: .fadeTo(0, 1)
221: .one('click', HoverBingObject.onClickSearchPopup);
222: $().unbind('mousemove', HoverBingObject.mouseMoveSearchPopup);
223: },
224:
225: washQueryText: function(text)
226: {
227: return escape(text.replace(/[^'"A-z0-9]/g, "+")).substr(0, 100);
228: }
229: }
230: }
231:
232: window.HoverBing = function(options)
233: {
234: settings = jQuery.extend({
235: title: "Click to Bing Search",
236: appId: "96AE4D816B34AA03F44EEBC53F4C23F9A146C011",
237: numResults: 10,
238: sources: "web"
239: }, options);
240:
241: if(typeof(HoverBingObject) == 'undefined')
242: {
243: createHoverBingObject(settings);
244: HoverBingObject.create();
245: }
246: }
247: })();And there you have it. To use it, link the jQuery-1.3.2 javascript, include the above JavaScript, and the CSS styles found on the CodePlex site linked from the top, then activate it by using a jQuery ready handler such as:
1: $(function() { HoverBing(); });















