diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index a629c8f681..c6024f9831 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -1297,10 +1297,13 @@ workflow_duration=Duration: workflow_duration_ms=ms # OpenSearch messages +show=Show opensearch=OpenSearch opensearch_desc=Provides ability to search across multiple OpenSearch supported search engines. -perform_search_in=Perform Search In +search_in=Search In no_engines_registered=Failed to find any registered OpenSearch engines! +current_repo=Current Alfresco Repository +toggle_options=Toggle Options # UI Page Titles title_about=About Alfresco diff --git a/config/alfresco/web-api-config.xml b/config/alfresco/web-api-config.xml index e70897c44f..0fb5ee0fa3 100644 --- a/config/alfresco/web-api-config.xml +++ b/config/alfresco/web-api-config.xml @@ -22,7 +22,7 @@ - + /service/search/textsearchdescription.xml diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index a0351696ec..0902b0e62c 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -211,6 +211,8 @@ + false diff --git a/source/java/org/alfresco/web/app/servlet/ajax/InvokeCommand.java b/source/java/org/alfresco/web/app/servlet/ajax/InvokeCommand.java index beb03b1e38..077129ed28 100644 --- a/source/java/org/alfresco/web/app/servlet/ajax/InvokeCommand.java +++ b/source/java/org/alfresco/web/app/servlet/ajax/InvokeCommand.java @@ -93,20 +93,21 @@ public class InvokeCommand extends BaseAjaxCommand " on variable " + variableName + " with method " + methodName); - // retrieve the managed bean, this is really weak but if the - // request comes from a portal server the bean we need to get - // is in the session with a prefix chosen by the portal vendor, - // to cover this scenario we have to go through the names of - // all the objects in the session to find the bean we want. - Object bean = null; - + Object bean = null; if (Application.inPortalServer()) { + // retrieve the managed bean, this is really weak but if the + // request comes from a portal server the bean we need to get + // is in the session with a prefix chosen by the portal vendor, + // to cover this scenario we have to go through the names of + // all the objects in the session to find the bean we want. + + String beanNameSuffix = "?" + variableName; Enumeration enumNames = request.getSession().getAttributeNames(); while (enumNames.hasMoreElements()) { String name = (String)enumNames.nextElement(); - if (name.endsWith(variableName)) + if (name.endsWith(beanNameSuffix)) { bean = request.getSession().getAttribute(name); @@ -118,8 +119,7 @@ public class InvokeCommand extends BaseAjaxCommand } } - // if we didn't find the bean it may be a request scope bean, in which - // case go through the variable resolver to create it. + // if we don't have the bean yet try and get it via the variable resolver if (bean == null) { VariableResolver vr = facesContext.getApplication().getVariableResolver(); diff --git a/source/java/org/alfresco/web/ui/common/component/data/UIDataPager.java b/source/java/org/alfresco/web/ui/common/component/data/UIDataPager.java index 05a3a85f7e..517b866b46 100644 --- a/source/java/org/alfresco/web/ui/common/component/data/UIDataPager.java +++ b/source/java/org/alfresco/web/ui/common/component/data/UIDataPager.java @@ -111,7 +111,7 @@ public class UIDataPager extends UICommand Integer.toString(pageCount) })); - buf.append(" "); + buf.append("  "); // output HTML links or labels to render the paging controls // first page @@ -128,6 +128,8 @@ public class UIDataPager extends UICommand buf.append(Utils.buildImageTag(context, WebResources.IMAGE_FIRSTPAGE_NONE, 16, 16, null)); } + buf.append(" "); + // previous page if (currentPage != 0) { @@ -228,6 +230,8 @@ public class UIDataPager extends UICommand buf.append(Utils.buildImageTag(context, WebResources.IMAGE_NEXTPAGE_NONE, 16, 16, null)); } + buf.append(" "); + // last page if ((dataContainer.getCurrentPage() < dataContainer.getPageCount() - 1) == true) { diff --git a/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java b/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java index 05f60c779f..a8a4c73139 100644 --- a/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java +++ b/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java @@ -55,7 +55,7 @@ public class UIOpenSearch extends SelfRenderingComponent return; } - String clientId = this.getClientId(context); + String clientId = this.getId(); // output the scripts required by the component (checks are // made to make sure the scripts are only written once) @@ -78,17 +78,17 @@ public class UIOpenSearch extends SelfRenderingComponent // write out the javascript initialisation required out.write("\n"); // write out the HTML - out.write("
\n"); + out.write("
"); out.write(""); out.write("
"); + out.write("-search-term' type='text' size='30' onkeyup='return "); + out.write(clientId); + out.write(".handleKeyPress(event);' />"); out.write("
\n"); + out.write("
"); out.write(Application.getMessage(context, "options")); - out.write("' />
\n"); - out.write("
"); + out.write("\n"); + + out.write("
"); + out.write(Application.getMessage(context, "show")); out.write(""); + out.write("-page-size' type='text' value='5' style='width: 25px; margin-left: 5px; margin-right: 5px;' />"); out.write(Application.getMessage(context, "items_per_page")); - out.write("
"); - out.write(Application.getMessage(context, "perform_search_in")); + out.write("
"); + out.write(Application.getMessage(context, "search_in")); out.write(":
"); for (OpenSearchEngine engine : engines) { out.write(""); } - out.write("
"); out.write(""); out.write(engine.getLabel()); out.write("
\n"); - out.write("
\n
\n"); + out.write("
\n"); + + out.write("
\n
\n"); } /** diff --git a/source/web/css/main.css b/source/web/css/main.css index 842e4f4bc9..05ce5f20c4 100644 --- a/source/web/css/main.css +++ b/source/web/css/main.css @@ -435,7 +435,7 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl .pager { - padding: 3px; + padding: 6px 4px 3px 4px; border: 1px dotted #cccccc; } diff --git a/source/web/css/opensearch.css b/source/web/css/opensearch.css index 1f82e578d3..a54dee9732 100644 --- a/source/web/css/opensearch.css +++ b/source/web/css/opensearch.css @@ -1,59 +1,60 @@ .osSidebarPanel { - min-width: 190px; + background-color: #f5f5f5; + padding: 4px; + min-width: 212px; *width: 100%; } .osPanel { - margin: 4px; + margin-bottom: 3px; +} + +.osControls +{ + padding: 4px; + background-color: white; + border: 1px solid #babfc5; + -moz-border-radius: 7px; } .osOptions { - margin: 6px; - display: none; + margin-top: 6px; + margin-left: 4px; } .osResults { margin-top: 6px; padding: 3px; - background: url(../images/parts/os-background.gif) 0 0 repeat-x; + background-color: white; + border: 1px solid #babfc5; + -moz-border-radius: 7px; + *width: 100%; } .osEngineTitle { + padding: 1px 2px 2px 2px; margin-bottom: 2px; - border-bottom: 1px dashed #bbb; -} - -.osEngineTitleText -{ font-weight: bold; - color: #003366; - padding-bottom: 2px; -} - -.osResultsPosition -{ - font-size: 9px; - text-align: right; - padding-right: 2px; - _padding-right: 6px; + color: #004488; + white-space: nowrap; + border-bottom: 1px dotted #bbb; } .osResultsPaging { + padding: 6px 4px 4px 4px; font-size: 9px; text-align: right; - padding: 4px; - padding-top: 6px; } -.osResultsPaging a, .osResultsPaging a:hover, .osResultsPaging a:link, .osResultsPaging a:visited +.osResultsPaging img { - font-size: 9px; + vertical-align: -4px; } .osResultNoMatch diff --git a/source/web/images/icons/FirstPage.gif b/source/web/images/icons/FirstPage.gif index e3b74d83bc..21c965fde8 100644 Binary files a/source/web/images/icons/FirstPage.gif and b/source/web/images/icons/FirstPage.gif differ diff --git a/source/web/images/icons/FirstPage_unavailable.gif b/source/web/images/icons/FirstPage_unavailable.gif index cf91b77df1..c027850a14 100644 Binary files a/source/web/images/icons/FirstPage_unavailable.gif and b/source/web/images/icons/FirstPage_unavailable.gif differ diff --git a/source/web/images/icons/LastPage.gif b/source/web/images/icons/LastPage.gif index b30349d494..3dec543e0c 100644 Binary files a/source/web/images/icons/LastPage.gif and b/source/web/images/icons/LastPage.gif differ diff --git a/source/web/images/icons/LastPage_unavailable.gif b/source/web/images/icons/LastPage_unavailable.gif index 5ef9633860..79aab13b4d 100644 Binary files a/source/web/images/icons/LastPage_unavailable.gif and b/source/web/images/icons/LastPage_unavailable.gif differ diff --git a/source/web/images/icons/NextPage.gif b/source/web/images/icons/NextPage.gif index 784fbe91c4..7609c90e3a 100644 Binary files a/source/web/images/icons/NextPage.gif and b/source/web/images/icons/NextPage.gif differ diff --git a/source/web/images/icons/NextPage_unavailable.gif b/source/web/images/icons/NextPage_unavailable.gif index 12c6a5c154..4ee968e844 100644 Binary files a/source/web/images/icons/NextPage_unavailable.gif and b/source/web/images/icons/NextPage_unavailable.gif differ diff --git a/source/web/images/icons/PreviousPage.gif b/source/web/images/icons/PreviousPage.gif index 96ff132f0a..877c6daee8 100644 Binary files a/source/web/images/icons/PreviousPage.gif and b/source/web/images/icons/PreviousPage.gif differ diff --git a/source/web/images/icons/PreviousPage_unavailable.gif b/source/web/images/icons/PreviousPage_unavailable.gif index 05f9588d96..be2f939cca 100644 Binary files a/source/web/images/icons/PreviousPage_unavailable.gif and b/source/web/images/icons/PreviousPage_unavailable.gif differ diff --git a/source/web/images/icons/opensearch_controls.gif b/source/web/images/icons/opensearch_controls.gif new file mode 100644 index 0000000000..1cb3ddfdd5 Binary files /dev/null and b/source/web/images/icons/opensearch_controls.gif differ diff --git a/source/web/images/parts/os-background.gif b/source/web/images/parts/os-background.gif deleted file mode 100644 index a0b7b82b46..0000000000 Binary files a/source/web/images/parts/os-background.gif and /dev/null differ diff --git a/source/web/jsp/dashboards/dashlets/opensearch.jsp b/source/web/jsp/dashboards/dashlets/opensearch.jsp new file mode 100644 index 0000000000..cf055c611a --- /dev/null +++ b/source/web/jsp/dashboards/dashlets/opensearch.jsp @@ -0,0 +1,22 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + + \ No newline at end of file diff --git a/source/web/jsp/sidebar/opensearch.jsp b/source/web/jsp/sidebar/opensearch.jsp index 0ee0966b75..de7196e82b 100644 --- a/source/web/jsp/sidebar/opensearch.jsp +++ b/source/web/jsp/sidebar/opensearch.jsp @@ -21,6 +21,6 @@
- +
\ No newline at end of file diff --git a/source/web/scripts/ajax/common.js b/source/web/scripts/ajax/common.js index e1e83cdadb..6242ee3cbe 100644 --- a/source/web/scripts/ajax/common.js +++ b/source/web/scripts/ajax/common.js @@ -3,8 +3,33 @@ // Gavin Cornwell 14-07-2006 // +// Global Alfresco namespace object +if (typeof Alfresco == "undefined") +{ + var Alfresco = {}; +} + var _alfContextPath = null; +/** + * Error handler for errors caught in a catch block + */ +function handleCaughtError(err) +{ + var msg = null; + + if (err.message) + { + msg = err.message; + } + else + { + msg = err; + } + + alert("An error occurred: " + msg); +} + /** * Default handler for errors when using the dojo toolkit */ diff --git a/source/web/scripts/ajax/opensearch.js b/source/web/scripts/ajax/opensearch.js index fafd737c64..c8172a01d6 100644 --- a/source/web/scripts/ajax/opensearch.js +++ b/source/web/scripts/ajax/opensearch.js @@ -1,5 +1,5 @@ // -// Alfresco OpenSearch library +// Alfresco OpenSearch client library // Gavin Cornwell 09-01-2007 // // NOTE: This script relies on common.js so therefore needs to be loaded @@ -7,25 +7,19 @@ var _OS_NS_PREFIX = "opensearch"; var _OS_NS_URI = "http://a9.com/-/spec/opensearch/1.1/"; - -var _searchTermFieldId = null; -var _pageSizeFieldId = null; - -var _resultsDivId = "os-results"; -var _optionsDivId = "os-options"; -var _resultSetPanelId = "-osresults-panel"; -var _resultSetListId = "-osresults-list"; -var _resultSetPositionId = "-osresults-position"; -var _resultSetPagingId = "-osresults-paging"; - -var _engineEnabledId = "-engine-enabled"; -var _engines = []; -var _enginesById = []; +var _RESULTS_DIV_ID_SUFFIX = "-os-results"; +var _OPTIONS_DIV_ID_SUFFIX = "-os-options"; +var _RESULTSET_PANEL_DIV_ID_SUFFIX = "-osresults-panel"; +var _RESULTSET_LIST_DIV_ID_SUFFIX = "-osresults-list"; +var _RESULTSET_PAGING_DIV_ID_SUFFIX = "-osresults-paging"; +var _ENGINE_ENABLED_FIELD_ID = "-engine-enabled"; +var _SEARCH_TERM_FIELD_ID = "-search-term"; +var _PAGE_SIZE_FIELD_ID = "-page-size"; /** - * Define an object to hold the definition of an OpenSearch engine + * Constructor for an object to hold the definition of an OpenSearch engine */ -function OpenSearchEngine(id, label, url) +Alfresco.OpenSearchEngine = function(id, label, url) { this.id = id; this.label = label; @@ -33,211 +27,573 @@ function OpenSearchEngine(id, label, url) } /** - * Sets the field id of the search term input control + * Constructor for an OpenSearchClient object */ -function setSearchTermFieldId(id) +Alfresco.OpenSearchClient = function(id) { - _searchTermFieldId = id; + this.id = id; + this.engines = []; + this.enginesById = []; } -/** - * Sets the field id of the page size input control - */ -function setPageSizeFieldId(id) +Alfresco.OpenSearchClient.prototype = { - _pageSizeFieldId = id; -} - -/** - * Registers an OpenSearch engine to be called when performing queries - */ -function registerOpenSearchEngine(id, label, url) -{ - var se = new OpenSearchEngine(id, label, url); - _engines[_engines.length] = se; - _enginesById[id] = se; -} - - -/** - * Handles the key press event, if ENTER is pressed execute the query - */ -function handleKeyPress(e) -{ - var keycode; + id: null, - // get the keycode - if (window.event) + engines: null, + + enginesById: null, + + /** + * Registers an OpenSearch engine to be called when performing queries + */ + registerOpenSearchEngine: function(id, label, url) { - keycode = window.event.keyCode; - } - else if (e) - { - keycode = e.which; - } - - // if ENTER was pressed execute the query - if (keycode == 13) - { - executeQuery(); - return false; - } - - return true; -} + var se = new Alfresco.OpenSearchEngine(id, label, url); + this.engines[this.engines.length] = se; + this.enginesById[id] = se; + }, -/** - * Toggles the visibility of the options panel - */ -function toggleOptions(icon) -{ - var currentState = icon.className; - var optionsDiv = document.getElementById(_optionsDivId); - - if (currentState == "collapsed") + /** + * Handles the key press event, if ENTER is pressed execute the query + */ + handleKeyPress: function(e) { - icon.src = getContextPath() + "/images/icons/expanded.gif"; - icon.className = "expanded"; + var keycode; - // show the div holding the options - if (optionsDiv != null) + // get the keycode + if (window.event) { - optionsDiv.style.display = "block"; + keycode = window.event.keyCode; + } + else if (e) + { + keycode = e.which; } - } - else - { - icon.src = getContextPath() + "/images/icons/collapsed.gif"; - icon.className = "collapsed"; - // hide the div holding the options - if (optionsDiv != null) - { - optionsDiv.style.display = "none"; + // if ENTER was pressed execute the query + if (keycode == 13) + { + this.executeQuery(); + return false; } - } -} + + return true; + }, -/** - * Executes the query against all the registered and selected opensearch engines - */ -function executeQuery() -{ - // gather the required parameters - var term = document.getElementById(_searchTermFieldId).value; - var count = document.getElementById(_pageSizeFieldId).value; - - // default the count if its invalid - if (count.length == 0 || isNaN(count)) + /** + * Toggles the visibility of the options panel + */ + toggleOptions: function(icon) { - count = 5; - } - - // issue the queries if there is enough search criteria - if (term != null && term.length > 1) - { - // issue the search request for each enabled engine - for (var e = 0; e < _engines.length; e++) + var currentState = icon.className; + var optionsDiv = document.getElementById(this.id + _OPTIONS_DIV_ID_SUFFIX); + + if (currentState == "collapsed") { - // get the checkbox for the current engine - var ose = _engines[e]; - var engCheckbox = document.getElementById(ose.id + _engineEnabledId); - if (engCheckbox != null && engCheckbox.checked) + icon.src = getContextPath() + "/images/icons/expanded.gif"; + icon.className = "expanded"; + + // show the div holding the options + if (optionsDiv != null) { - issueSearchRequest(ose, term, count); + optionsDiv.style.display = "block"; } } - } -} + else + { + icon.src = getContextPath() + "/images/icons/collapsed.gif"; + icon.className = "collapsed"; + + // hide the div holding the options + if (optionsDiv != null) + { + optionsDiv.style.display = "none"; + } + } + }, -/** - * Issues an Ajax request for the given OpenSearchEngine - * using the given search term and page size. - */ -function issueSearchRequest(ose, term, pageSize) -{ - // generate the search url - var searchUrl = generateSearchUrl(ose.url, term, pageSize); - - // issue the request - if (searchUrl != null) + /** + * Executes the query against all the registered and selected opensearch engines + */ + executeQuery: function() { - YAHOO.util.Connect.asyncRequest("GET", searchUrl, + // gather the required parameters + var term = document.getElementById(this.id + _SEARCH_TERM_FIELD_ID).value; + var count = document.getElementById(this.id + _PAGE_SIZE_FIELD_ID).value; + + // default the count if its invalid + if (count.length == 0 || isNaN(count)) + { + count = 5; + } + + // issue the queries if there is enough search criteria + if (term != null && term.length > 1) + { + // remove previous results (if necessary) + var resultsPanel = document.getElementById(this.id + _RESULTS_DIV_ID_SUFFIX); + if (resultsPanel != null) + { + while (resultsPanel.firstChild) + { + resultsPanel.removeChild(resultsPanel.firstChild); + }; + } + + // issue the search request for each enabled engine + for (var e = 0; e < this.engines.length; e++) + { + // get the checkbox for the current engine + var ose = this.engines[e]; + var engCheckbox = document.getElementById(this.id + "-" + ose.id + _ENGINE_ENABLED_FIELD_ID); + if (engCheckbox != null && engCheckbox.checked) + { + this.issueSearchRequest(ose, term, count); + } + } + } + }, + + /** + * Issues an Ajax request for the given OpenSearchEngine + * using the given search term and page size. + */ + issueSearchRequest: function(ose, term, pageSize) + { + // generate the search url + var searchUrl = this.calculateSearchUrl(ose.url, term, pageSize); + + // issue the request + if (searchUrl != null) + { + YAHOO.util.Connect.asyncRequest("GET", searchUrl, + { + success: Alfresco.processSearchResults, + failure: Alfresco.handleSearchError, + argument: [ose.id, this] + }, + null); + } + else + { + handleErrorYahoo("Failed to generate url for search engine '" + ose.label + + "'.\n\nThis is probably caused by missing required parameters, check the template url for the search engine."); + } + }, + + /** + * Shows another page of the current search results for the + * given engineId + */ + showPage: function(engineId, url) + { + // execute the query and process the results + YAHOO.util.Connect.asyncRequest("GET", url, { - success: processSearchResults, - failure: handleSearchError, - argument: [ose.id] + success: Alfresco.processShowPageResults, + failure: Alfresco.handleSearchError, + argument: [engineId, this] }, null); - } - else - { - handleErrorYahoo("Failed to generate url for search engine '" + ose.label + - "'.\n\nThis is probably caused by missing required parameters, check the template url for the search engine."); - } -} + }, -/** - * Generates a concrete url for the given template url and parameters. - * - * All parameters (inside { and }) have to be replaced. We only need to populate - * the 'searchTerms' and 'count' parameters, all optional ones will use the - * empty string. If there is a mandatory parameter present (other than searchTerms - * and count) null will be returned. - */ -function generateSearchUrl(templateUrl, term, count) -{ - var searchUrl = null; - - // define regex pattern to look for params - var pattern = /\{+\w*\}+|\{+\w*\?\}+|\{+\w*:\w*\}+|\{+\w*:\w*\?\}+/g; - - var params = templateUrl.match(pattern); - if (params != null && params.length > 0) + /** + * Generates a concrete url for the given template url and parameters. + * + * All parameters (inside { and }) have to be replaced. We only need to populate + * the 'searchTerms' and 'count' parameters, all optional ones will use the + * empty string. If there is a mandatory parameter present (other than searchTerms + * and count) null will be returned. + */ + calculateSearchUrl: function(templateUrl, term, count) { - searchUrl = templateUrl; + var searchUrl = null; - // go through the parameters and replace the searchTerms and count - // parameters with the given values and then replace all optional - // parameters with an empty string. - for (var p = 0; p < params.length; p++) + // define regex pattern to look for params + var pattern = /\{+\w*\}+|\{+\w*\?\}+|\{+\w*:\w*\}+|\{+\w*:\w*\?\}+/g; + + var params = templateUrl.match(pattern); + if (params != null && params.length > 0) { - var param = params[p]; + searchUrl = templateUrl; - if (param == "{searchTerms}") + // go through the parameters and replace the searchTerms and count + // parameters with the given values and then replace all optional + // parameters with an empty string. + for (var p = 0; p < params.length; p++) { - searchUrl = searchUrl.replace(param, term); - } - else if (param == "{count}" || param == "{count?}") - { - searchUrl = searchUrl.replace(param, count); - } - else if (param.indexOf("?") != -1) - { - // replace the optional parameter with "" - searchUrl = searchUrl.replace(param, ""); - } - else - { - // an unknown manadatory parameter return - searchUrl = null; - break; + var param = params[p]; + + if (param == "{searchTerms}") + { + searchUrl = searchUrl.replace(param, term); + } + else if (param == "{count}" || param == "{count?}") + { + searchUrl = searchUrl.replace(param, count); + } + else if (param.indexOf("?") != -1) + { + // replace the optional parameter with "" + searchUrl = searchUrl.replace(param, ""); + } + else + { + // an unknown manadatory parameter return + searchUrl = null; + break; + } } } - } + + return searchUrl; + }, + + /** + * Renders the results for the given feed element. + */ + renderSearchResults: function(engineId, feed) + { + // look up the label from the osengine registry + var engineLabel = this.enginesById[engineId].label; + + // create the div to hold the results and the header bar + var sb = []; + sb[sb.length] = "
"; + sb[sb.length] = "
"; + sb[sb.length] = engineLabel; + sb[sb.length] = "
"; + + // create the actual results to display, start with the containing div + sb[sb.length] = "
"; + sb[sb.length] = this.generateResultsListHTML(feed); + sb[sb.length] = "
"; + + // create the paging controls + sb[sb.length] = "
"; + sb[sb.length] = this.generatePagingHTML(engineId, feed); + sb[sb.length] = "
"; - return searchUrl; + // close the containing div + sb[sb.length] = "
"; + + // create a div element to hold the results + var d = document.createElement("div"); + d.innerHTML = sb.join(""); + + // return the div + return d; + }, + + /** + * Generates the HTML to display the search results from the + * given feed. + */ + generateResultsListHTML: function(feed) + { + var isAtom = true; + + // if the name of the feed element is "channel" this is an RSS feed + if (feed.tagName == "channel") + { + isAtom = false; + } + + var results = null; + if (isAtom) + { + results = feed.getElementsByTagName("entry"); + } + else + { + results = feed.getElementsByTagName("item"); + } + + if (results == null || results.length == 0) + { + return "
No results
"; + } + else + { + var sb = []; + sb[sb.length] = ""; + + for (var x = 0; x < results.length; x++) + { + // get the current entry + var elResult = results[x]; + + // get the title, icon and summary + var title = getElementTextByTagName(elResult, "title"); + var icon = getElementTextByTagName(elResult, "icon"); + var summary = null; + if (isAtom) + { + summary = getElementTextByTagName(elResult, "summary"); + } + else + { + summary = getElementTextByTagName(elResult, "description"); + } + + // get the link href + var link = null; + var elLink = getElementByTagName(elResult, "link"); + if (elLink != null) + { + if (isAtom) + { + link = elLink.getAttribute("href"); + } + else + { + link = getElementText(elLink); + } + } + + // generate the row to represent the result + sb[sb.length] = ""; + } + + // close the table + sb[sb.length] = "
"; + if (icon != null) + { + sb[sb.length] = ""; + } + sb[sb.length] = "
"; + if (title != null) + { + if (link != null) + { + sb[sb.length] = ""; + } + sb[sb.length] = title; + if (link != null) + { + sb[sb.length] = ""; + } + } + sb[sb.length] = "
"; + if (summary != null) + { + sb[sb.length] = summary; + } + sb[sb.length] = "
"; + + return sb.join(""); + } + }, + + /** + * Generates the HTML to display the paging information i.e. the first, next, previous + * and last buttons and the position info i.e. "x - y of z". + */ + generatePagingHTML: function(engineId, feed) + { + var totalResults = 0; + var pageSize = 5; + var startIndex = 0; + + // check there are results + var elTotalResults = getElementByTagNameNS(feed, _OS_NS_URI, _OS_NS_PREFIX, "totalResults"); + if (elTotalResults != null) + { + totalResults = getElementText(elTotalResults); + } + + // if there are no results return an empty string + if (totalResults == 0) + { + return ""; + } + + var elStartIndex = getElementByTagNameNS(feed, _OS_NS_URI, _OS_NS_PREFIX, "startIndex"); + if (elStartIndex != null) + { + startIndex = getElementText(elStartIndex); + } + + var elItemsPerPage = getElementByTagNameNS(feed, _OS_NS_URI, _OS_NS_PREFIX, "itemsPerPage"); + if (elItemsPerPage != null) + { + pageSize = getElementText(elItemsPerPage); + } + + // calculate the number of pages the results span + /*var noPages = Math.floor(totalResults / pageSize); + var remainder = totalResults % pageSize; + if (remainder != 0) + { + noPages++; + }*/ + + var endIndex = (Number(startIndex) + Number(pageSize)) - 1; + if (endIndex > totalResults) + { + endIndex = totalResults; + } + + // extract the navigation urls + var firstUrl = null; + var nextUrl = null; + var previousUrl = null; + var lastUrl = null; + + var links = feed.getElementsByTagName("link"); + if (links != null && links.length > 0) + { + for (var x = 0; x < links.length; x++) + { + var elNavLink = links[x]; + var linkType = elNavLink.getAttribute("rel"); + if (linkType == "first") + { + firstUrl = elNavLink.getAttribute("href"); + } + else if (linkType == "next") + { + nextUrl = elNavLink.getAttribute("href"); + } + else if (linkType == "previous") + { + previousUrl = elNavLink.getAttribute("href"); + } + else if (linkType == "last") + { + lastUrl = elNavLink.getAttribute("href"); + } + } + } + + var sb = []; + + if (firstUrl != null) + { + sb[sb.length] = ""; + } + else + { + sb[sb.length] = ""; + } + + sb[sb.length] = " "; + + if (previousUrl != null) + { + sb[sb.length] = ""; + } + else + { + sb[sb.length] = ""; + } + + sb[sb.length] = "  "; + sb[sb.length] = startIndex; + sb[sb.length] = " - "; + sb[sb.length] = endIndex; + sb[sb.length] = " of "; + sb[sb.length] = totalResults; + sb[sb.length] = "  "; + + if (nextUrl != null) + { + sb[sb.length] = ""; + } + else + { + sb[sb.length] = ""; + } + + sb[sb.length] = " "; + + if (lastUrl != null) + { + sb[sb.length] = ""; + } + else + { + sb[sb.length] = ""; + } + + return sb.join(""); + } } +/*********************************/ +/** Handlers for AJAX callbacks **/ +/*********************************/ + /** * Processes the XML search results */ -function processSearchResults(ajaxResponse) +Alfresco.processSearchResults = function(ajaxResponse) { try { // render the results from the Ajax response var engineId = ajaxResponse.argument[0]; + var clientInstance = ajaxResponse.argument[1]; var feed = ajaxResponse.responseXML.documentElement; // if the name of the feed element is "rss", get the channel child element @@ -246,18 +602,12 @@ function processSearchResults(ajaxResponse) feed = getElementByTagName(feed, "channel"); } - var resultsDiv = renderSearchResults(engineId, feed); + var resultsDiv = clientInstance.renderSearchResults(engineId, feed); // create the div to hold the results and add the results - var resultsPanel = document.getElementById(_resultsDivId); + var resultsPanel = document.getElementById(clientInstance.id + _RESULTS_DIV_ID_SUFFIX); if (resultsPanel != null) { - // first remove any existing results - while (resultsPanel.firstChild) - { - resultsPanel.removeChild(resultsPanel.firstChild); - }; - // add the new results resultsPanel.appendChild(resultsDiv); } @@ -269,87 +619,22 @@ function processSearchResults(ajaxResponse) } catch (e) { - handleError(e); + handleCaughtError(e); } } -/** - * Renders the results for the given feed element. - */ -function renderSearchResults(engineId, feed) -{ - // look up the label from the osengine registry - var engineLabel = _enginesById[engineId].label; - - // create the div to hold the results and the header bar - var sb = []; - sb[sb.length] = "
"; - sb[sb.length] = "
"; - sb[sb.length] = "
"; - sb[sb.length] = engineLabel; - sb[sb.length] = ""; - sb[sb.length] = generatePostionHTML(feed); - sb[sb.length] = "
"; - - // create the actual results to display, start with the containing div - sb[sb.length] = "
"; - sb[sb.length] = generateResultsListHTML(feed); - sb[sb.length] = "
"; - - // create the paging controls - sb[sb.length] = "
"; - sb[sb.length] = generatePagingHTML(engineId, feed); - sb[sb.length] = "
"; - - // close the containing div - sb[sb.length] = "
"; - - // create a div element to hold the results - var d = document.createElement("div"); - d.innerHTML = sb.join(""); - - // return the div - return d; -} - -/** - * Shows another page of the current search results for the - * given engineId - */ -function showPage(engineId, url) -{ - // execute the query and process the results - YAHOO.util.Connect.asyncRequest("GET", url, - { - success: processShowPageResults, - failure: handleSearchError, - argument: [engineId] - }, - null); -} /** * Processes the search results and updates the postion, result list * and paging controls. */ -function processShowPageResults(ajaxResponse) +Alfresco.processShowPageResults = function(ajaxResponse) { try { // render the results from the Ajax response var engineId = ajaxResponse.argument[0]; + var clientInstance = ajaxResponse.argument[1]; var feed = ajaxResponse.responseXML.documentElement; // if the name of the feed element is "rss", get the channel child element @@ -357,330 +642,38 @@ function processShowPageResults(ajaxResponse) { feed = getElementByTagName(feed, "channel"); } - - // find the position div and update the count - var positionDiv = document.getElementById(engineId + _resultSetPositionId); - if (positionDiv != null) - { - positionDiv.innerHTML = generatePostionHTML(feed); - } // append the results list to the results list div - var resultsListDiv = document.getElementById(engineId + _resultSetListId); + var resultsListDiv = document.getElementById(clientInstance.id + "-" + + engineId + _RESULTSET_LIST_DIV_ID_SUFFIX); if (resultsListDiv != null) { - resultsListDiv.innerHTML = generateResultsListHTML(feed); + resultsListDiv.innerHTML = clientInstance.generateResultsListHTML(feed); } - // update the paging div with new urls - var pagingDiv = document.getElementById(engineId + _resultSetPagingId); + // update the paging div with new urls and position info + var pagingDiv = document.getElementById(clientInstance.id + "-" + + engineId + _RESULTSET_PAGING_DIV_ID_SUFFIX); if (pagingDiv != null) { - pagingDiv.innerHTML = generatePagingHTML(engineId, feed); + pagingDiv.innerHTML = clientInstance.generatePagingHTML(engineId, feed); } } catch (e) { - handleError(e); + handleCaughtError(e); } } -/** - * Generates the HTML required to display the current position i.e. "x - y of z". - */ -function generatePostionHTML(feed) -{ - var totalResults = 0; - var pageSize = 5; - var startIndex = 0; - - // extract position information from results - var elTotalResults = getElementByTagNameNS(feed, _OS_NS_URI, _OS_NS_PREFIX, "totalResults"); - if (elTotalResults != null) - { - totalResults = getElementText(elTotalResults); - } - - // if there are no results just return an empty string - if (totalResults == 0) - { - return ""; - } - - var elStartIndex = getElementByTagNameNS(feed, _OS_NS_URI, _OS_NS_PREFIX, "startIndex"); - if (elStartIndex != null) - { - startIndex = getElementText(elStartIndex); - } - - var elItemsPerPage = getElementByTagNameNS(feed, _OS_NS_URI, _OS_NS_PREFIX, "itemsPerPage"); - if (elItemsPerPage != null) - { - pageSize = getElementText(elItemsPerPage); - } - - // calculate the number of pages the results span - /*var noPages = Math.floor(totalResults / pageSize); - var remainder = totalResults % pageSize; - if (remainder != 0) - { - noPages++; - }*/ - - // calculate the endIndex for this set of results - var endIndex = (Number(startIndex) + Number(pageSize)) - 1; - if (endIndex > totalResults) - { - endIndex = totalResults; - } - - // make sure the startIndex is correct - if (totalResults == 0) - { - startIndex = 0; - } - - var sb = []; - sb[sb.length] = startIndex; - sb[sb.length] = " - "; - sb[sb.length] = endIndex; - sb[sb.length] = " of "; - sb[sb.length] = totalResults; - - return sb.join(""); -} - -/** - * Generates the HTML to display the search results from the - * given feed. - */ -function generateResultsListHTML(feed) -{ - var isAtom = true; - - // if the name of the feed element is "channel" this is an RSS feed - if (feed.tagName == "channel") - { - isAtom = false; - } - - var results = null; - if (isAtom) - { - results = feed.getElementsByTagName("entry"); - } - else - { - results = feed.getElementsByTagName("item"); - } - - if (results == null || results.length == 0) - { - return "
No results
"; - } - else - { - var sb = []; - sb[sb.length] = ""; - - for (var x = 0; x < results.length; x++) - { - // get the current entry - var elResult = results[x]; - - // get the title, icon and summary - var title = getElementTextByTagName(elResult, "title"); - var icon = getElementTextByTagName(elResult, "icon"); - var summary = null; - if (isAtom) - { - summary = getElementTextByTagName(elResult, "summary"); - } - else - { - summary = getElementTextByTagName(elResult, "description"); - } - - // get the link href - var link = null; - var elLink = getElementByTagName(elResult, "link"); - if (elLink != null) - { - if (isAtom) - { - link = elLink.getAttribute("href"); - } - else - { - link = getElementText(elLink); - } - } - - // generate the row to represent the result - sb[sb.length] = ""; - } - - // close the table - sb[sb.length] = "
"; - if (icon != null) - { - sb[sb.length] = ""; - } - sb[sb.length] = "
"; - if (title != null) - { - if (link != null) - { - sb[sb.length] = ""; - } - sb[sb.length] = title; - if (link != null) - { - sb[sb.length] = ""; - } - } - sb[sb.length] = "
"; - if (summary != null) - { - sb[sb.length] = summary; - } - sb[sb.length] = "
"; - - return sb.join(""); - } -} - -/** - * Generates the HTML to display the paging links i.e. first, next, previous and last. - */ -function generatePagingHTML(engineId, feed) -{ - // check there are results - var totalResults = 0; - var elTotalResults = getElementByTagNameNS(feed, _OS_NS_URI, _OS_NS_PREFIX, "totalResults"); - if (elTotalResults != null) - { - totalResults = getElementText(elTotalResults); - } - - // if there are no results return an empty string - if (totalResults == 0) - { - return ""; - } - - // extract the navigation urls - var firstUrl = null; - var nextUrl = null; - var previousUrl = null; - var lastUrl = null; - - var links = feed.getElementsByTagName("link"); - if (links != null && links.length > 0) - { - for (var x = 0; x < links.length; x++) - { - var elNavLink = links[x]; - var linkType = elNavLink.getAttribute("rel"); - if (linkType == "first") - { - firstUrl = elNavLink.getAttribute("href"); - } - else if (linkType == "next") - { - nextUrl = elNavLink.getAttribute("href"); - } - else if (linkType == "previous") - { - previousUrl = elNavLink.getAttribute("href"); - } - else if (linkType == "last") - { - lastUrl = elNavLink.getAttribute("href"); - } - } - } - - var sb = []; - - if (firstUrl != null) - { - sb[sb.length] = "first | "; - } - if (previousUrl != null) - { - sb[sb.length] = "previous"; - if (nextUrl != null) - { - sb[sb.length] = " | "; - } - } - if (nextUrl != null) - { - sb[sb.length] = "next | "; - } - if (lastUrl != null) - { - sb[sb.length] = "last"; - } - - return sb.join(""); -} - -/** - * Error handler for errors caught in a catch block - */ -function handleError(o) -{ - var msg = null; - - if (e.message) - { - msg = e.message; - } - else - { - msg = e; - } - - alert("Error occurred processing search results: " + msg); -} - /** * Error handler for Ajax call to search engine */ -function handleSearchError(o) +Alfresco.handleSearchError = function(ajaxResponse) { - // TODO: find out which search engine results could not be found! - - handleErrorYahoo("Error: Failed to retrieve search results"); -} - -/** - * Error handler for Ajax call to initialise component - */ -function handleInitError(o) -{ - handleErrorYahoo("Failed to initialise OpenSearch component: " + - o.status + " " + o.statusText); + var engineId = ajaxResponse.argument[0]; + var clientInstance = ajaxResponse.argument[1]; + var engineLabel = clientInstance.enginesById[engineId].label; + + handleErrorYahoo("Failed to retrieve search results for '" + engineLabel + + "': " + ajaxResponse.status + " " + ajaxResponse.statusText); }