1/*! 2// ------------------------------------------------------------------------ 3// (C) CROWNPEAK TECHNOLOGY. 4// ------------------------------------------------------------------------ 5// THIS SOFTWARE IS PROVIDED "AS-IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. 6// IN NO EVENT SHALL CROWNPEAK TECHNOLOGY BE HELD LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THE SOFTWARE. 7// THIS SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 8// THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS (INCLUDING BOTH CROWN PEAK TECHNOLOGY 9// AND THE VARIOUS THIRD PARTY COPYRIGHT HOLDERS PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 10// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU, THE USER. 11// SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 12// WILL ANY COPYRIGHT HOLDER, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE 13// (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER PROGRAMS), 14// EVEN IF SUCH HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 15// Version: 1.0.3 16*/ 17// NOTE: This is the same as the CP CrownPeakSearch Object with some exceptions: _maxRows changed from 200 to 2500 18 //_maxRows changed from 200 to 2500 19 //mergeParameters correctly handles custom params containing "=" sign 20/*HEADERSTART 21 Name: felows-cp-global.js 22 Desc: A clone of CPs SOLR library 23 Notes: We overrode the max rows returned by SOLR 24HEADER END*/ 25function FellowsCrownPeakSearch(options) { 26 var self = this; 27 // Default configuration for properties 28 var protocol = location.protocol == "file:" ? "http:" : location.protocol; 29 /* Search proxy allows all queries to be sent via a proxy url - for security reasons 30 * Search proxy supports the following macros 31 * %%PROTOCOL%% - "https:" if this script was loaded via https, or "http:" if not 32 * %%COLLECTION%% - the collection being requested 33 * %%HANDLER%% - the handler being used 34 * %%URL%% - the entire url for the search 35 * %%URLENCODED%% - the entire url for the search, URI encoded 36 * Leave the proxy blank (or null, or undefined, etc.) if you don't want to use one 37 */ 38 var _searchProxy = ""; 39 /* Endpoint supports the following macros 40 * %%PROTOCOL%% - "https:" if this script was loaded via https, or "http:" if not 41 * %%COLLECTION%% - the collection being requested 42 * %%HANDLER%% - the handler being used 43 * %%QUERY%% - the querystring extension (do not include the "?") 44 */ 45 var _endpoint = "%%PROTOCOL%%//searchg2.crownpeak.net/%%COLLECTION%%/%%HANDLER%%?%%QUERY%%"; 46 var _maxRows = 2500; // Don't let the user specify more than this number of results 47 var _rows = 10; 48 var _collection = "www.crownpeak.com"; 49 var _params = ""; 50 var _facets = []; 51 var _maxFacets = 5; 52 var _sort = []; 53 var _spellcheck = false; 54 var _highlight = false; 55 var _highlightSeparator = "..."; 56 var _resultProxy = ""; 57 var _language = ""; 58 var _handler = "select"; 59 var _queryText = ""; 60 var _timeout = 5000; 61 var _geo = null; 62 parseArguments(options); 63 // Fill for missing console.log for oldIE 64 if (typeof console === "undefined") console = { log: function() { } } 65 else if (!console.log) { console.log = function () { }; } 66 function parseArguments(options) { 67 if (options) { 68 if (typeof options === "string") { 69 // Single string is collection 70 _collection = options; 71 } else { 72 // Otherwise look for properties on the thing they passed in 73 if (options.collection) _collection = options.collection; 74 if (options.endpoint) _endpoint = options.endpoint; 75 if (options.facets) _facets = options.facets; 76 if (options.handler) _handler = options.handler; 77 if (options.highlight || options.highlight == false) _highlight = options.highlight; 78 if (options.highlightSeparator) _highlightSeparator = options.highlightSeparator; 79 if (options.language) _language = options.language; 80 if (options.maxFacets || options.maxfacets == 0) _maxFacets = options.maxFacets; 81 if (options.parameters) _params = options.parameters; 82 if (options.resultProxy) _resultProxy = options.resultProxy; 83 if (options.rows || options.rows == 0) _rows = options.rows; 84 if (options.searchProxy) _searchProxy = options.searchProxy; 85 if (options.sort) _sort = options.sort; 86 if (options.spellcheck || options.spellcheck == false) _spellcheck = options.spellcheck; 87 if (options.timeout || options.timeout == 0) _timeout = options.timeout; 88 } 89 } 90 } 91 /// <summary> 92 /// Extend the document that matches this id with some extra properties 93 /// </summary> 94 function extendDoc(docs, id, props) { 95 for (var i = 0, len = docs.length; i < len; i++) { 96 var doc = docs[i]; 97 if (doc.id === id) { 98 // Copy the properties over to the document 99 var keys = Object.keys(props); 100 for (var k = 0, lenK = keys.length; k < lenK; k++) { 101 var key = keys[k]; 102 doc[key] = props[key]; 103 } 104 break; 105 } 106 } 107 } 108 /// <summary> 109 /// Copy some properties from the highlighting object into the response documents 110 /// </summary> 111 function copyHighlights(data) { 112 // Copy the highlights into the response model 113 var highlights = data.highlighting; 114 var ids = Object.keys(highlights); 115 // Loop through each document that has highlights 116 for (var i = 0, len = ids.length; i < len; i++) { 117 var id = ids[i]; 118 var hh = highlights[id]; 119 var fields = Object.keys(hh); 120 // Create an object that we'll use to extend the response document 121 var o = {}; 122 var lenF = fields.length; 123 if (lenF > 0) { 124 // Loop through each field within the document 125 for (var j = 0; j < lenF; j++) { 126 // Make a new property - e.g. title_hl - with highlights 127 var fieldName = fields[j]; 128 o[fieldName + "_hl"] = _highlightSeparator + hh[fieldName].join(_highlightSeparator) + _highlightSeparator; 129 } 130 // Copy these new properties to the document that has this id 131 extendDoc(data.response.docs, id, o); 132 } 133 } 134 } 135 /// <summary> 136 /// Clean the types property to make it easier to use 137 /// </summary> 138 function cleanTypes(data) { 139 if (data.response && data.response.docs && data.response.docs.length) { 140 var docs = data.response.docs; 141 for (var i = 0, len = docs.length; i < len; i++) { 142 var t = docs[i].type; 143 if (t && t.indexOf && t.indexOf("/") >= 0) { 144 docs[i].type_short = t.split("/")[1]; 145 } 146 } 147 } 148 } 149 /// <summary> 150 /// Clean the suggestions collection to make it easier to use 151 /// </summary> 152 function cleanSuggestions(data) { 153 if (data.spellcheck && data.spellcheck.suggestions && data.spellcheck.suggestions.length) { 154 var len = data.spellcheck.suggestions.length; 155 var suggestions = data.spellcheck.suggestions[len - 1].suggestion; 156 if (suggestions.length) { 157 var results = []; 158 for (var i = 0, len = suggestions.length; i < len; i++) { 159 results.push(suggestions[i]); 160 } 161 data.suggestions = results; 162 } 163 }; 164 } 165 /// <summary> 166 /// Add a proxy_url property to the result, for ease of analytics 167 /// </summary> 168 function addResultProxy(data) { 169 if (_resultProxy && data.response && data.response.docs && data.response.docs.length) { 170 var proxy = _resultProxy; 171 if (proxy.indexOf("%%QUERY%%")) proxy = proxy.replace(/%%QUERY%%/g, encodeURIComponent(_queryText)); 172 var docs = data.response.docs; 173 for (var i = 0, len = docs.length; i < len; i++) { 174 docs[i].proxy_url = proxy.replace(/%%INDEX%%/g, i) + docs[i].url; 175 } 176 } 177 } 178 /// <summary> 179 /// Add a pager property to make it easier to render one 180 /// </summary> 181 function addPager(data) { 182 if (data && data.response && (data.response.start || data.response.start === 0) 183 && (data.response.numFound || data.response.numFound === 0)) { 184 // Add a simple pager to the output - the user can customise it if they like 185 data.pager = { 186 page: data.response.start / _rows + 1, 187 pages: [], 188 total: Math.ceil(data.response.numFound / _rows) 189 }; 190 if (_rows > 0) { 191 // Simple pager just has one entry for each page 192 for (var i = 0; i < data.response.numFound / _rows; i++) { 193 data.pager.pages.push(i + 1); 194 } 195 } 196 } 197 } 198 /// <summary> 199 /// Add a score property to each result, normalized based on the highest score 200 /// </summary> 201 function addNormalizedScores(data) { 202 if (data.response && data.response.maxScore && data.response.docs && data.response.docs.length) { 203 var maxScore = data.response.maxScore || 1.0; 204 var docs = data.response.docs; 205 for (var i = 0, len = docs.length; i < len; i++) { 206 docs[i].normalizedScore = docs[i].score / maxScore; 207 } 208 } 209 } 210 /// <summary> 211 /// Add a didYouMean property to the main, to make suggestions easy to provide later 212 /// </summary> 213 function addDidYouMean(data) { 214 if (data.spellcheck && data.spellcheck.suggestions && data.spellcheck.suggestions.length) { 215 var didYouMean = []; 216 // Results come in name,value pairs 217 for (var i = 0, len = data.spellcheck.suggestions.length; i < len; i += 2) { 218 var name = data.spellcheck.suggestions[i]; 219 var value = data.spellcheck.suggestions[i + 1]; 220 if (name == "collation") { 221 // Collations also come in name,value pairs 222 var query = ""; 223 var html = ""; 224 for (var j = 0, lenC = value.length; j < lenC; j += 2) { 225 var cname = value[j]; 226 var cvalue = value[j + 1]; 227 if (cname == "collationQuery") { 228 query = html = cvalue; 229 } 230 else if (cname == "hits") {
231 html += " (" + cvalue + ")"; 232 } 233 else if (cname == "misspellingsAndCorrections") { 234 // Corrections also come in (what else) name,value pairs 235 for (var k = 0, lenM = cvalue.length; k < lenM; k += 2) { 236 var original = cvalue[k]; 237 var replacement = cvalue[k + 1]; 238 var re = new RegExp("\\b" + replacement + "\\b", "i"); 239 html = html.replace(re, "<em>" + replacement + "</em>"); 240 } 241 } 242 } 243 // Add this to our collection 244 didYouMean.push({ query: query, display: html }); 245 } 246 } 247 if (didYouMean.length > 0) { 248 // Add this to our output 249 data.didYouMean = didYouMean; 250 } 251 } 252 } 253 /// <summary> 254 /// Get the full url to be used to execute a query against Search G2 255 /// </summary> 256 function getSearchUrl(collection, handler, query) { 257 var url = _endpoint 258 .replace(/%%PROTOCOL%%/ig, protocol) 259 .replace(/%%COLLECTION%%/ig, _collection) 260 .replace(/%%HANDLER%%/ig, handler) 261 .replace(/%%QUERY%%/ig, query); 262 if (_searchProxy && _searchProxy.replace) { 263 return _searchProxy 264 .replace(/%%PROTOCOL%%/ig, protocol) 265 .replace(/%%COLLECTION%%/ig, _collection) 266 .replace(/%%HANDLER%%/ig, handler) 267 .replace(/%%URL%%/ig, url) 268 .replace(/%%URLENCODED%%/ig, encodeURIComponent(url)); 269 } 270 return url; 271 } 272 /// <summary> 273 /// Execute the provided query against the configured url and collection 274 /// </summary> 275 function internalRawQuery(query, handler) { 276 // We'll return the promise from this object later 277 var dfd = new Deferred(); 278 handler = handler || _handler || "select"; 279 // Append our JSONP callback 280 query += "&json.wrf=%%CALLBACK%%"; 281 var thisUrl = getSearchUrl(_collection, handler, query); 282 //console.log("Querying " + thisUrl.replace("&json.wrf=%%CALLBACK%%", "")); 283 // Make a JSONP request to our Solr collection 284 getUrl(thisUrl, _timeout) 285 .done(function(data) { 286 if (_highlight && data.highlighting) { 287 copyHighlights(data); 288 } 289 if (handler == "suggest") { 290 cleanSuggestions(data); 291 } 292 else { 293 cleanTypes(data); 294 addResultProxy(data); 295 addDidYouMean(data); 296 addNormalizedScores(data); 297 addPager(data); 298 } 299 // Search complete - resolve the promise 300 dfd.resolve(data); 301 }) 302 .fail(function(status, url, error) { //jqXHR, textStatus, errorThrown) { 303 dfd.reject(status, url, error); 304 }); 305 // Return a promise that we'll resolve later when the search has completed 306 return dfd.promise(); 307 } 308 /// <summary> 309 /// Build a query using the text and page number and execute it 310 /// </summary> 311 function internalQuery(text, page, filterQueries) { 312 _queryText = text; 313 var data = "q=" + encodeURIComponent(text) 314 + (!text ? "&q.alt=*" : "") 315 + "&echoParams=explicit" // change to none when finished debugging 316 + "&fl=*,score" // we want the score field in order to be able to rate results 317 + "&defType=edismax" // handles more complex queries and gracefully fails if it doesn't understand 318 + "&wt=json&start=" + page * _rows + "&rows=" + Math.min(_rows, _maxRows) 319 + (_language !== "" ? "&fq=language:" + _language : "") 320 + (_spellcheck ? "&spellcheck=true&spellcheck.collate=true&spellcheck.collateExtendedResults=true" : "") 321 + (filterQueries && filterQueries.length > 0 ? "&fq=" + filterQueries.join("&fq=") : "") 322 + (_facets.length > 0 ? "&facet=true&facet.mincount=1&facet.field=" + _facets.join("&facet.field=") : "") 323 + (_facets.length > 0 && _maxFacets > 0 ? "&facet.limit=" + _maxFacets : "") 324 + (_sort.length > 0 ? "&sort=" + _sort.join(",") : "") 325 + (_highlight ? "&hl=true&hl.fl=*&hl.snippets=3&hl.simple.pre=" + escape("<b>") + "&hl.simple.post=" + escape("</b>") + "&f.title.hl.fragsize=50000&f.url.hl.fragsize=50000" : ""); 326 var geoPostParams = []; 327 if (_geo) { 328 var geoParams = []; 329 if (_geo.location) { 330 if (typeof _geo.location === "string") 331 geoParams.push("pt=" + _geo.location); 332 else 333 geoParams.push("pt=" + (_geo.location.latitude || _geo.location.lat || 0) + "," + 334 (_geo.location.longitude || _geo.location.lon || 0)); 335 } else { 336 geoParams.push("pt=0,0"); 337 } 338 // It won't work without a field 339 geoParams.push("sfield=" + (_geo.field || "custom_p_location")); 340 // If they didn't already sort by something else, assume they want by ascending distance 341 if (_sort.length == 0) geoParams.push("sort=geodist()%20asc"); 342 // What do they want it called on the output? 343 geoPostParams.push("fl=" + encodeURI(_geo.outputfield || "_dist_") + ":geodist()"); 344 // Filter results by by range 345 if (_geo.range) { 346 var range = _geo.range; 347 if (typeof _geo.range != "number" && _geo.range.distance) { 348 range = _geo.range.distance; 349 var unit = _geo.range.units || _geo.range.unit; 350 if (unit && unit.toLowerCase) { 351 switch (unit.toLowerCase()) { 352 case "mile": case "miles": 353 range *= 1.609344; 354 break; 355 case "metre": case "metres": case "meter": case "meters": 356 range /= 1000; 357 break; 358 default: // KM = nothing to do 359 } 360 } 361 } 362 if (!isNaN(range)) geoParams.push("fq={!geofilt%20d%3d" + (range) + "}"); 363 } 364 data += "&" + geoParams.join("&"); 365 } 366 // If they provided additional parameters, merge them into our set 367 if (_params) data = mergeParameters(data, _params.replace(/^[&]/, "")); 368 // If they asked for highlighting and didn't include the id field, add it now 369 if (data.indexOf("&hl=true") > 0) { 370 if (data.indexOf("&fl=") >= 0) { 371 var start = data.indexOf("&fl=") + 1; 372 var end = data.indexOf("&", start); 373 if (end < 0) end = data.length; 374 var i = data.indexOf(",id,", start); 375 if (i < 0 || i > end) { 376 i = data.indexOf(",id&", start); 377 if (i < 0 || i > end) { 378 i = data.indexOf("=id", start); 379 if (i < 0 || i > end) { 380 data = data.replace(/&fl=/, "&fl=id,"); 381 } 382 } 383 } 384 } 385 } 386 if (geoPostParams && geoPostParams.length) 387 data += "&" + geoPostParams.join("&"); 388 return internalRawQuery(data); 389 } 390 /// <summary> 391 /// Merge together two sets of parameters and return the result, with s2 taking precendence 392 /// </summary> 393 function mergeParameters(s1, s2) { 394 var PARAMS_TO_IGNORE = ",fq,hl.fl,"; // NOTE: keep the leading/trailing commas 395 var result = []; 396 // Immediate exit conditions 397 if (!s1) return s2; 398 if (!s2) return s1; 399 var s1Items = s1.split("&"), s2Items = s2.split("&"); 400 for (var i = 0, len = s1Items.length; i < len; i++) { 401 var item = s1Items[i].split("="); 402 var key = item[0], value = item[1]; 403 // Is this in string 2? 404 var s2Index = indexOfKey(s2Items, key); 405 if (s2Index >= 0) { 406 // Yes, so process it 407 //var item2 = s2Items[s2Index].split("="); //does not work with values containing = sign, like fl=*,content:[value v=""] 408 var key2 = key; 409 var value2 = s2Items[s2Index].replace(key + "=", ""); 410 if (PARAMS_TO_IGNORE.indexOf("," + key + ",") >= 0) { 411 // push key 1 412 result.push(key + "=" + value); 413 } 414 // Push key 2 415 result.push(key2 + "=" + value2); 416 // Remove this item from string 2 417 s2Items.splice(s2Index, 1); 418 } else { 419 // No, so just append it 420 result.push(key + "=" + value); 421 } 422 } 423 // Append anything left in string 2 424 result = result.concat(s2Items); 425 return result.join("&"); 426 } 427 /// <summary> 428 /// Find the index of a key in an array of key=value pairs 429 /// </summary> 430 function indexOfKey(array, key) { 431 if (!array || !array.length) return -1; 432 for (var i = 0, len = array.length; i < len; i++) { 433 if (array[i].split("=")[0] === key) return i; 434 } 435 return -1; 436 } 437 /// <summary> 438 /// Build a suggest query using the text and execute it 439 /// </summary> 440 function internalAutocompleteQuery(text) { 441 _queryText = text; 442 var data = "q=" + encodeURIComponent(text) 443 + "&wt=json&spellcheck.collate=false" 444 + (_params ? "&" + _params.replace(/^[&]/, "") : ""); 445 return internalRawQuery(data, "suggest"); 446 } 447 function getUrl(url, timeout) { 448 var deferred = new Deferred(); 449 function addEvent(element, eventName, fn) { 450 if (element.addEventListener) 451 element.addEventListener(eventName, fn); 452 else if (element.attachEvent) 453 element.attachEvent("on" + eventName, function () { fn.call(element); }); 454 } 455 function tidytimer() { 456 if (timer) { 457 clearTimeout(timer); 458 timer = null; 459 } 460 } 461 function tidyscript() { 462 window[cb] = overwritten; 463 if (script) { 464 script.parentElement.removeChild(script); 465 script = null; 466 } 467 } 468 try { 469 var cb = "searchg2_" + Math.random().toString().substr(2); 470 var overwritten = window[cb]; 471 var timer = null; 472 if (timeout && !isNaN(timeout)) { 473 timer = setTimeout(function () { 474 try { 475 tidytimer(); 476 } 477 catch (ex) { 478 // Ignore errors here 479 } 480 finally { 481 deferred.reject("timeout", url); 482 } 483 }, timeout); 484 } 485 window[cb] = function (data) { 486 tidytimer(); 487 deferred.resolve(data, url); 488 } 489 var script = document.createElement("script"); 490 var loadOrError = function (event) { 491 tidytimer(); 492 tidyscript(); 493 if (event.type === "error") { 494 deferred.reject("error", url); 495 } 496 } 497 addEvent(script, "load", loadOrError); 498 addEvent(script, "error", loadOrError); 499 script.src = url.replace(/%%CALLBACK%%|%25%25CALLBACK%25%25/ig, cb); 500 document.getElementsByTagName("head")[0].appendChild(script); 501 } catch (e) { 502 deferred.reject(url, "error", e); 503 } 504 return deferred.promise(); 505 } 506 function Deferred() { 507 var deferred = { 508 args: null, 509 state: "pending", 510 doneList: [], 511 failList: [], 512 alwaysList: [] 513 },
514 trigger = function (list, args) { 515 for (var i = 0, len = list.length; i < len; i++) { 516 list[i].apply(list[i], args); 517 } 518 }; 519 return { 520 promise: function () { 521 return { 522 status: function () { 523 return state; 524 }, 525 done: function (fn) { 526 if (deferred.state == "resolved") { 527 fn.apply(fn, deferred.args); 528 } else { 529 deferred.doneList.push(fn); 530 } 531 return this; 532 }, 533 fail: function (fn) { 534 if (deferred.state == "rejected") { 535 fn.apply(fn, deferred.args); 536 } else { 537 deferred.failList.push(fn); 538 } 539 return this; 540 }, 541 always: function (fn) { 542 if (deferred.state == "rejected" || deferred.state == "resolved") { 543 fn.apply(fn, deferred.args); 544 } else { 545 deferred.alwaysList.push(fn); 546 } 547 return this; 548 } 549 } 550 }, 551 resolve: function () { 552 if (deferred.state === "pending") { 553 deferred.state = "resolved"; 554 deferred.args = arguments; 555 trigger(deferred.doneList, arguments); 556 trigger(deferred.alwaysList, arguments); 557 } 558 }, 559 reject: function () { 560 if (deferred.state === "pending") { 561 deferred.state = "rejected"; 562 deferred.args = arguments; 563 trigger(deferred.failList, arguments); 564 trigger(deferred.alwaysList, arguments); 565 } 566 } 567 } 568 } 569 // Getters and setters would be nice, but in the meantime... 570 this.rows = function (value) { if (value !== undefined) _rows = value; return _rows; }; 571 this.collection = function (value) { if (value !== undefined) _collection = value; return _collection; }; 572 this.endpoint = function (value) { if (value !== undefined) _endpoint = value; return _endpoint; }; 573 this.facets = function (value) { if (value !== undefined) _facets = (typeof value === "string" ? [value] : value); return _facets; }; 574 this.maxFacets = function (value) { if (value !== undefined) _maxFacets = value; return _maxFacets; }; 575 this.handler = function (value) { if (value !== undefined) _handler = value; return _handler; }; 576 this.highlight = function (value) { if (value !== undefined) _highlight = value; return _highlight; }; 577 this.highlightSeparator = function (value) { if (value !== undefined) _highlightSeparator = value; return _highlightSeparator; }; 578 this.language = function (value) { if (value !== undefined) _language = value; return _language; }; 579 this.searchProxy = function (value) { if (value !== undefined) _searchProxy = value; return _searchProxy; }; 580 this.spellcheck = function (value) { if (value !== undefined) _spellcheck = value; return _spellcheck; }; 581 this.sort = function (value) { if (value !== undefined) _sort = (typeof value === "string" ? [value] : value); return _sort; }; 582 this.timeout = function (value) { if (value !== undefined) _timeout = value; return _timeout; }; 583 this.parameters = function (value) { if (value !== undefined) _params = value; return _params; }; 584 this.resultProxy = function (value) { if (value !== undefined) _resultProxy = value; return _resultProxy; }; 585 this.geo = function (value) { if (value !== undefined) _geo = value; return _geo; }; 586 /// <summary> 587 /// Run a query against the configured CrownPeakSearch object 588 /// </summary> 589 /// <param name="text">The query text. See https://wiki.apache.org/solr/SolrQuerySyntax for more information</param> 590 /// <param name="page">The page number (starting at 1) of results that you wish to retrieve</param> 591 /// <param name="filterQueries">An array of strings in the format "field:value" to apply to the query</param> 592 /// <returns>A Deferred object that will be resolved when the query is complete</returns> 593 this.query = function(text, page, filterQueries) { 594 if (!page) page = 1; 595 return internalQuery(text, page - 1, filterQueries); 596 }; 597 /// <summary> 598 /// Run an autocomplete (suggest) query against the configured CrownPeakSearch object 599 /// </summary> 600 /// <param name="text">The query text. See https://wiki.apache.org/solr/SolrQuerySyntax for more information</param> 601 /// <returns>A Deferred object that will be resolved when the query is complete</returns> 602 this.autocomplete = function (text) { 603 return internalAutocompleteQuery(text); 604 }; 605 /// <summary> 606 /// Run a raw query against the Solr instance that is configured in the CrownPeakSearch object 607 /// </summary> 608 /// <param name="query">The query, sent in an HTTP GET request. See http://lucene.apache.org/solr/3_6_2/doc-files/tutorial.html for more information</param> 609 /// <returns>A Deferred object that will be resolved when the query is complete</returns> 610 this.raw = function(query) { 611 return internalRawQuery(query); 612 }; 613} 614// Old IE support 615// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys 616if (!Object.keys) { 617 Object.keys = (function () { 618 'use strict'; 619 var hasOwnProperty = Object.prototype.hasOwnProperty, 620 hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'), 621 dontEnums = [ 622 'toString',
623 'toLocaleString', 624 'valueOf', 625 'hasOwnProperty', 626 'isPrototypeOf', 627 'propertyIsEnumerable', 628 'constructor' 629 ], 630 dontEnumsLength = dontEnums.length; 631 return function (obj) { 632 if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { 633 throw new TypeError('Object.keys called on non-object'); 634 } 635 var result = [], prop, i; 636 for (prop in obj) { 637 if (hasOwnProperty.call(obj, prop)) { 638 result.push(prop); 639 } 640 } 641 if (hasDontEnumBug) { 642 for (i = 0; i < dontEnumsLength; i++) { 643 if (hasOwnProperty.call(obj, dontEnums[i])) { 644 result.push(dontEnums[i]); 645 } 646 } 647 } 648 return result; 649 }; 650 }()); 651}
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.