001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.workplace.tools.searchindex; 029 030import org.opencms.i18n.CmsMessages; 031import org.opencms.jsp.CmsJspActionElement; 032import org.opencms.main.CmsIllegalStateException; 033import org.opencms.main.OpenCms; 034import org.opencms.search.CmsSearch; 035import org.opencms.search.CmsSearchIndex; 036import org.opencms.search.CmsSearchParameters; 037import org.opencms.search.I_CmsSearchIndex; 038import org.opencms.search.fields.CmsLuceneField; 039import org.opencms.search.fields.CmsSearchField; 040import org.opencms.util.CmsStringUtil; 041import org.opencms.widgets.CmsCalendarWidget; 042import org.opencms.widgets.CmsCheckboxWidget; 043import org.opencms.widgets.CmsDisplayWidget; 044import org.opencms.widgets.CmsInputWidget; 045import org.opencms.widgets.CmsMultiSelectWidget; 046import org.opencms.widgets.CmsSelectWidget; 047import org.opencms.widgets.CmsSelectWidgetOption; 048import org.opencms.widgets.CmsVfsFileWidget; 049import org.opencms.workplace.CmsDialog; 050import org.opencms.workplace.CmsWidgetDialogParameter; 051import org.opencms.workplace.CmsWorkplaceSettings; 052 053import java.util.ArrayList; 054import java.util.Iterator; 055import java.util.LinkedList; 056import java.util.List; 057import java.util.Map; 058 059import javax.servlet.http.HttpServletRequest; 060import javax.servlet.http.HttpServletResponse; 061import javax.servlet.jsp.PageContext; 062 063/** 064 * A <code>{@link org.opencms.workplace.CmsWidgetDialog}</code> that performs a 065 * search on the <code>{@link org.opencms.search.CmsSearchIndex}</code> identified 066 * by request parameter 067 * <code>{@link org.opencms.workplace.tools.searchindex.A_CmsEditSearchIndexDialog#PARAM_INDEXNAME}</code> 068 * using an instance of <code>{@link org.opencms.search.CmsSearchParameters}</code> 069 * as widget object to fill. 070 * <p> 071 * 072 * @since 6.0.0 073 */ 074public class CmsSearchWidgetDialog extends A_CmsEditSearchIndexDialog { 075 076 /** The request parameter for the search object. **/ 077 public static final String PARAM_SEARCH_OBJECT = "searchobject"; 078 079 /** The request parameter for the search parameters. **/ 080 public static final String PARAM_SEARCH_PARAMS = "searchparams"; 081 082 /** The search instance used with the search parameters. **/ 083 protected CmsSearch m_search; 084 085 /** The search parameter instance used for storing widget values and performing search. */ 086 protected CmsSearchParameters m_searchParams; 087 088 /** 089 * Public constructor with JSP action element.<p> 090 * 091 * @param jsp an initialized JSP action element 092 */ 093 public CmsSearchWidgetDialog(CmsJspActionElement jsp) { 094 095 super(jsp); 096 097 } 098 099 /** 100 * Public constructor with JSP variables.<p> 101 * 102 * @param context the JSP page context 103 * @param req the JSP request 104 * @param res the JSP response 105 */ 106 public CmsSearchWidgetDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) { 107 108 this(new CmsJspActionElement(context, req, res)); 109 110 } 111 112 /** 113 * Overrides this action that is performed in case an element 114 * has been added to a widget parameter 115 * (<code>{@link org.opencms.workplace.CmsWidgetDialog#ACTION_ELEMENT_ADD}</code>) 116 * or removed 117 * (<code>{@link org.opencms.workplace.CmsWidgetDialog#ACTION_ELEMENT_REMOVE}</code>) 118 * from a widget parameter to additionally commit these values to the 119 * underlying lists.<p> 120 * 121 * This is necessary because this dialog performs a search for every request 122 * (not only if OK is pressed, also if a category or field is added/removed). 123 * The search directly uses the underlying Lists of categories, fields,... . 124 * More precise: The very same lists that are in the search parameter instance used 125 * for search are contained as base collections of the widget parameters. 126 * Therefore before every search the changes of categories, fields,... have to 127 * be committed here.<p> 128 * 129 * @see org.opencms.workplace.CmsWidgetDialog#actionToggleElement() 130 */ 131 @Override 132 public void actionToggleElement() { 133 134 super.actionToggleElement(); 135 commitWidgetValues(); 136 } 137 138 /** 139 * Builds the standard javascript for submitting the dialog.<p> 140 * 141 * Overridden to allow additional validation and encoding of the 142 * search query. <p> 143 * 144 * @return the standard javascript for submitting the dialog 145 */ 146 @Override 147 public String dialogScriptSubmit() { 148 149 StringBuffer html = new StringBuffer(512); 150 html.append(submitJS()); 151 html.append("function submitAction(actionValue, theForm, formName) {\n"); 152 html.append("\tif (theForm == null) {\n"); 153 html.append("\t\ttheForm = document.forms[formName];\n"); 154 html.append("\t}\n"); 155 html.append("\tvar queryOK = validateQuery();\n"); 156 html.append("\ttheForm." + CmsDialog.PARAM_FRAMENAME + ".value = window.name;\n"); 157 html.append("\tif (queryOK) {\n"); 158 html.append("\t\tif (actionValue == '" + CmsDialog.DIALOG_OK + "') {\n"); 159 // html.append("\t\t\talert('action :'+actionValue);\n"); 160 html.append("\t\t\tloadingOn();\n"); 161 html.append("\t\t\treturn queryOK;\n"); 162 html.append("\t\t}\n"); 163 html.append("\t\ttheForm." + CmsDialog.PARAM_ACTION + ".value = actionValue;\n"); 164 html.append("\t\tsubmitForm(theForm);\n"); 165 html.append("\t}\n"); 166 html.append("\treturn queryOK;\n"); 167 html.append("}\n"); 168 return html.toString(); 169 } 170 171 /** 172 * Returns the fields parameter value.<p> 173 * 174 * @return the fields parameter value 175 */ 176 public String getFields() { 177 178 return CmsStringUtil.collectionAsString(m_searchParams.getFields(), ","); 179 } 180 181 /** 182 * Returns the creation date the resources have to have as maximum.<p> 183 * 184 * @return the creation date the resources have to have as maximum 185 */ 186 public String getMaxDateCreated() { 187 188 if (m_searchParams.getMaxDateCreated() == Long.MAX_VALUE) { 189 return ""; 190 } 191 return Long.toString(m_searchParams.getMaxDateCreated()); 192 } 193 194 /** 195 * Returns the last modification date the resources have to have as maximum.<p> 196 * 197 * @return the last modification date the resources have to have as maximum 198 */ 199 public String getMaxDateLastModified() { 200 201 if (m_searchParams.getMaxDateLastModified() == Long.MAX_VALUE) { 202 return ""; 203 } 204 return Long.toString(m_searchParams.getMaxDateLastModified()); 205 } 206 207 /** 208 * Returns the creation date the resources have to have as minimum.<p> 209 * 210 * @return the creation date the resources have to have as minimum 211 */ 212 public String getMinDateCreated() { 213 214 if (m_searchParams.getMinDateCreated() == Long.MIN_VALUE) { 215 return ""; 216 } 217 return Long.toString(m_searchParams.getMinDateCreated()); 218 } 219 220 /** 221 * Returns the last modification date the resources have to have as minimum.<p> 222 * 223 * @return the last modification date the resources have to have as minimum 224 */ 225 public String getMinDateLastModified() { 226 227 if (m_searchParams.getMinDateLastModified() == Long.MIN_VALUE) { 228 return ""; 229 } 230 return Long.toString(m_searchParams.getMinDateLastModified()); 231 } 232 233 /** 234 * Returns the list of searchable fields used in the workplace search index.<p> 235 * 236 * @return the list of searchable fields used in the workplace search index 237 */ 238 public List<CmsSearchField> getSearchFields() { 239 240 I_CmsSearchIndex index = OpenCms.getSearchManager().getIndex(getParamIndexName()); 241 List<CmsSearchField> result = new ArrayList<CmsSearchField>(); 242 Iterator<CmsSearchField> i = index.getFieldConfiguration().getFields().iterator(); 243 while (i.hasNext()) { 244 CmsLuceneField field = (CmsLuceneField)i.next(); 245 if (field.isIndexed() && field.isDisplayed()) { 246 // only include indexed (ie. searchable) fields 247 result.add(field); 248 } 249 } 250 return result; 251 } 252 253 /** 254 * Sets the fields parameter value.<p> 255 * 256 * @param fields the fields parameter value to set 257 */ 258 public void setFields(String fields) { 259 260 String searchPage = getJsp().getRequest().getParameter("searchPage"); 261 if (CmsStringUtil.isEmptyOrWhitespaceOnly(searchPage) && CmsStringUtil.isEmptyOrWhitespaceOnly(fields)) { 262 throw new CmsIllegalStateException( 263 org.opencms.workplace.search.Messages.get().container( 264 org.opencms.workplace.search.Messages.ERR_VALIDATE_SEARCH_PARAMS_0)); 265 } 266 m_searchParams.setFields(CmsStringUtil.splitAsList(fields, ",")); 267 } 268 269 /** 270 * Sets the creation date the resources have to have as maximum.<p> 271 * 272 * @param maxCreationDate the creation date the resources have to have as maximum to set 273 */ 274 public void setMaxDateCreated(String maxCreationDate) { 275 276 if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly(maxCreationDate)) && (!maxCreationDate.equals("0"))) { 277 m_searchParams.setMaxDateCreated(Long.parseLong(maxCreationDate)); 278 } else { 279 m_searchParams.setMaxDateCreated(Long.MAX_VALUE); 280 } 281 } 282 283 /** 284 * Sets the last modification date the resources have to have as maximum.<p> 285 * 286 * @param maxDateLastModified the last modification date the resources have to have as maximum to set 287 */ 288 public void setMaxDateLastModified(String maxDateLastModified) { 289 290 if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly(maxDateLastModified)) && (!maxDateLastModified.equals("0"))) { 291 m_searchParams.setMaxDateLastModified(Long.parseLong(maxDateLastModified)); 292 } else { 293 m_searchParams.setMaxDateLastModified(Long.MAX_VALUE); 294 } 295 } 296 297 /** 298 * Sets the creation date the resources have to have as minimum.<p> 299 * 300 * @param minCreationDate the creation date the resources have to have as minimum to set 301 */ 302 public void setMinDateCreated(String minCreationDate) { 303 304 if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly(minCreationDate)) && (!minCreationDate.equals("0"))) { 305 m_searchParams.setMinDateCreated(Long.parseLong(minCreationDate)); 306 } else { 307 m_searchParams.setMinDateCreated(Long.MIN_VALUE); 308 } 309 } 310 311 /** 312 * Sets the last modification date the resources have to have as minimum.<p> 313 * 314 * @param minDateLastModified the last modification date the resources have to have as minimum to set 315 */ 316 public void setMinDateLastModified(String minDateLastModified) { 317 318 if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly(minDateLastModified)) && (!minDateLastModified.equals("0"))) { 319 m_searchParams.setMinDateLastModified(Long.parseLong(minDateLastModified)); 320 } else { 321 m_searchParams.setMinDateLastModified(Long.MIN_VALUE); 322 } 323 } 324 325 /** 326 * This dialog does not return on commit but stay for many search requests until it is 327 * exited with cancel or up in the workplace. <p> 328 * 329 * @return false always to ensure the dialog is not left 330 * 331 * @see org.opencms.workplace.CmsWidgetDialog#closeDialogOnCommit() 332 */ 333 @Override 334 protected boolean closeDialogOnCommit() { 335 336 return false; 337 } 338 339 /** 340 * @see org.opencms.workplace.CmsWidgetDialog#createDialogHtml(java.lang.String) 341 */ 342 @Override 343 protected String createDialogHtml(String dialog) { 344 345 StringBuffer result = new StringBuffer(1024); 346 347 result.append(createWidgetTableStart()); 348 // show error header once if there were validation errors 349 result.append(createWidgetErrorHeader()); 350 351 if (dialog.equals(PAGES[0])) { 352 353 // first block "Query for index...." 354 result.append(dialogBlockStart(key(Messages.GUI_LABEL_SEARCHINDEX_BLOCK_SEARCH_QUERY_0))); 355 result.append(createWidgetTableStart()); 356 result.append(createDialogRowsHtml(0, 5)); 357 result.append(createWidgetTableEnd()); 358 result.append(dialogBlockEnd()); 359 360 // 2nd block with limiting to time ranges 361 result.append(dialogBlockStart(key(Messages.GUI_LABEL_SEARCHINDEX_BLOCK_SEARCH_TIME_RANGES_0))); 362 result.append(createWidgetTableStart()); 363 result.append(createDialogRowsHtml(6, 9)); 364 result.append(createWidgetTableEnd()); 365 result.append(dialogBlockEnd()); 366 367 // 3rd block "Fields to search in" 368 result.append(dialogBlockStart(key(Messages.GUI_LABEL_SEARCHINDEX_BLOCK_SEARCH_FIELDS_0))); 369 result.append(createWidgetTableStart()); 370 result.append(createDialogRowsHtml(10, 10)); 371 result.append(createWidgetTableEnd()); 372 result.append(dialogBlockEnd()); 373 } 374 375 result.append(createWidgetTableEnd()); 376 377 return result.toString(); 378 } 379 380 /** 381 * Returns the html code for the default action content.<p> 382 * 383 * Overrides <code> {@link org.opencms.workplace.CmsWidgetDialog#defaultActionHtml()}</code> 384 * in order to put additional forms for page links and search results after OK - CANCEL buttons 385 * and outside the main form.<p> 386 * 387 * @return html code 388 */ 389 @Override 390 protected String defaultActionHtmlContent() { 391 392 StringBuffer result = new StringBuffer(2048); 393 result.append("<form name=\"EDITOR\" id=\"EDITOR\" method=\"post\" action=\"").append(getDialogUri()); 394 result.append("\" class=\"nomargin\" onsubmit=\"return submitAction('").append(DIALOG_OK).append( 395 "', null, 'EDITOR');\">\n"); 396 result.append(dialogContentStart(null)); 397 result.append(buildDialogForm()); 398 result.append(dialogContentEnd()); 399 result.append(dialogButtonsCustom()); 400 result.append(paramsAsHidden()); 401 if (getParamFramename() == null) { 402 result.append("\n<input type=\"hidden\" name=\"").append(PARAM_FRAMENAME).append("\" value=\"\">\n"); 403 } 404 405 // add script for filtering categories 406 result.append(filterCategoryJS()); 407 result.append("</form>\n"); 408 409 // get search results if query was more than nothing 410 // we have to retrieve them before category search results are available because 411 // those are collected as a side effect of search iteration. 412 String searchResults = createSearchResults(); 413 414 // append category search results if there... 415 result.append(createCategorySearchResultHtml()); 416 result.append(searchResults); 417 418 result.append(getWidgetHtmlEnd()); 419 // Normalize the previous encoded query value on client side 420 result.append(normalizePreviousQueryJS()); 421 422 return result.toString(); 423 } 424 425 /** 426 * 427 * @see org.opencms.workplace.CmsWidgetDialog#defineWidgets() 428 */ 429 @Override 430 protected void defineWidgets() { 431 432 // initialization -> initUserObject 433 super.defineWidgets(); 434 // first block "Query for search index..." 435 addWidget(new CmsWidgetDialogParameter(m_searchParams, "index", "", PAGES[0], new CmsDisplayWidget(), 1, 1)); 436 addWidget(new CmsWidgetDialogParameter(m_searchParams, "query", "", PAGES[0], new CmsInputWidget(), 1, 1)); 437 addWidget( 438 new CmsWidgetDialogParameter( 439 m_searchParams, 440 "sortName", 441 "", 442 PAGES[0], 443 new CmsSelectWidget(getSortWidgetConfiguration()), 444 0, 445 1)); 446 addWidget( 447 new CmsWidgetDialogParameter( 448 m_searchParams.getRoots(), 449 "roots", 450 "/", 451 PAGES[0], 452 new CmsVfsFileWidget(), 453 1, 454 10)); 455 addWidget( 456 new CmsWidgetDialogParameter( 457 m_searchParams.getCategories(), 458 "categories", 459 "", 460 PAGES[0], 461 new CmsInputWidget(), 462 0, 463 6)); 464 465 addWidget(new CmsWidgetDialogParameter(m_searchParams, "calculateCategories", new CmsCheckboxWidget())); 466 467 // 2nd block with limiting to time ranges 468 addWidget(new CmsWidgetDialogParameter(this, "minDateCreated", PAGES[0], new CmsCalendarWidget())); 469 addWidget(new CmsWidgetDialogParameter(this, "maxDateCreated", PAGES[0], new CmsCalendarWidget())); 470 addWidget(new CmsWidgetDialogParameter(this, "minDateLastModified", PAGES[0], new CmsCalendarWidget())); 471 addWidget(new CmsWidgetDialogParameter(this, "maxDateLastModified", PAGES[0], new CmsCalendarWidget())); 472 473 // 3rd block "fields to search in" 474 addWidget( 475 new CmsWidgetDialogParameter(this, "fields", PAGES[0], new CmsMultiSelectWidget(getFieldList(), true))); 476 } 477 478 /** 479 * Overridden to additionally get a hold on the widget object of type 480 * <code>{@link CmsSearchParameters}</code>.<p> 481 * 482 * @see org.opencms.workplace.tools.searchindex.A_CmsEditSearchIndexDialog#initUserObject() 483 */ 484 @SuppressWarnings("rawtypes") 485 @Override 486 protected void initUserObject() { 487 488 super.initUserObject(); 489 Object o = getDialogObject(); 490 if (o == null) { 491 m_searchParams = new CmsSearchParameters(); 492 // implant a hook upon modifications of the list 493 // this will set the search page to 1 if a restriction to the set of categories is performed 494 m_searchParams.setCategories(new CmsHookListSearchCategory(m_searchParams, m_searchParams.getCategories())); 495 m_search = new CmsSearch(); 496 } else { 497 Map dialogObject = (Map)o; 498 m_searchParams = (CmsSearchParameters)dialogObject.get(PARAM_SEARCH_PARAMS); 499 if (m_searchParams == null) { 500 m_searchParams = new CmsSearchParameters(); 501 } 502 m_search = (CmsSearch)dialogObject.get(PARAM_SEARCH_OBJECT); 503 if (m_search == null) { 504 m_search = new CmsSearch(); 505 } 506 } 507 m_searchParams.setSearchIndex((CmsSearchIndex)getSearchIndexIndex()); 508 } 509 510 /** 511 * Additionally saves <code>{@link #PARAM_SEARCH_PARAMS}</code> to the dialog object map.<p> 512 * 513 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 514 */ 515 @SuppressWarnings({"unchecked", "rawtypes"}) 516 @Override 517 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 518 519 super.initWorkplaceRequestValues(settings, request); 520 Map dialogMap = (Map)getDialogObject(); 521 if (dialogMap != null) { 522 dialogMap.put(PARAM_SEARCH_PARAMS, m_searchParams); 523 dialogMap.put(PARAM_SEARCH_OBJECT, m_search); 524 } 525 } 526 527 /** 528 * Returns the hmtl for the category search results.<p> 529 * 530 * Note that a valid search (<code>{@link CmsSearch#getSearchResult()}</code> with 531 * correct settings and inited) has to be triggered before this call or an empty 532 * String will be returned. <p> 533 * 534 * @return the hmtl for the category search results 535 */ 536 private String createCategorySearchResultHtml() { 537 538 StringBuffer result = new StringBuffer(); 539 if (m_searchParams.isCalculateCategories()) { 540 // trigger calculation of categories, even if we don't need search results 541 // this is cached unless more set operation on CmsSearch are performed 542 Map<String, Integer> categoryMap = m_search.getSearchResultCategories(); 543 if (categoryMap != null) { 544 result.append(dialogContentStart(null)); 545 result.append(result.append(createWidgetTableStart())); 546 // first block "Query for index...." 547 result.append( 548 dialogBlockStart( 549 key( 550 Messages.GUI_LABEL_SEARCHINDEX_BLOCK_SEARCH_CATEGORIES_1, 551 new Object[] {m_searchParams.getQuery()}))); 552 result.append(createWidgetTableStart()); 553 554 // categories: 555 result.append("\n<p>\n"); 556 for (Map.Entry<String, Integer> entry : categoryMap.entrySet()) { 557 result.append(" ").append("<a class=\"searchcategory\" href=\"#\" onClick=\"filterCategory('"); 558 result.append(entry.getKey()).append("')\")>"); 559 result.append(entry.getKey()); 560 result.append("</a> : "); 561 result.append(entry.getValue()).append("<br>\n"); 562 } 563 result.append("</p>\n"); 564 565 result.append(createWidgetTableEnd()); 566 result.append(dialogBlockEnd()); 567 result.append(createWidgetTableEnd()); 568 result.append(dialogContentEnd()); 569 } 570 } 571 return result.toString(); 572 } 573 574 /** 575 * Returns the HTML for the search results.<p> 576 * 577 * @return the HTML for the search results 578 */ 579 private String createSearchResults() { 580 581 String query = m_searchParams.getQuery(); 582 StringBuffer result = new StringBuffer(); 583 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(query) && (query.length() > 3)) { 584 CmsSearchResultView resultView = new CmsSearchResultView(getJsp()); 585 // proprietary workplace admin link for pagelinks of search: 586 resultView.setSearchRessourceUrl( 587 getJsp().link( 588 "/system/workplace/views/admin/admin-main.jsp?path=/searchindex/singleindex/search&indexname=" 589 + getSearchIndexIndex().getName())); 590 m_search.init(getCms()); 591 592 // custom parameters (non-widget controlled) 593 // these are from generated search page links 594 String page = getJsp().getRequest().getParameter("searchPage"); 595 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(page)) { 596 m_searchParams.setSearchPage(Integer.parseInt(page)); 597 } 598 String categories = getJsp().getRequest().getParameter("searchCategories"); 599 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(categories)) { 600 m_searchParams.setCategories(CmsStringUtil.splitAsList(categories, ',')); 601 } 602 603 String searchRoots = getJsp().getRequest().getParameter("searchRoots"); 604 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(searchRoots)) { 605 m_searchParams.setSearchRoots(searchRoots); 606 } 607 m_search.setParameters(m_searchParams); 608 result.append("<div style=\"padding:12px;\">\n").append(resultView.displaySearchResult(m_search)).append( 609 "\n</div>\n"); 610 } else { 611 // Just don't perform search 612 } 613 return result.toString(); 614 } 615 616 /** 617 * Generates the JavaScript to filter categories.<p> 618 * 619 * @return the JavaScript 620 */ 621 private String filterCategoryJS() { 622 623 StringBuffer result = new StringBuffer(); 624 // fool the widget with a hidden categories input field 625 result.append("<input name=\"dummysearchcategory\" id=\"dummysearchcategory\" type=\"hidden\" value=\"\">\n"); 626 result.append("<input name=\"dummysearchpage\" id=\"dummysearchpage\" type=\"hidden\" value=\"\">\n"); 627 // delete all other chosen "cateogries.x" values and put a value here 628 result.append("<script >\n"); 629 result.append(" function filterCategory(category) {\n"); 630 result.append(" var searchform = document.forms['EDITOR'];\n"); 631 result.append(" var inputFields = searchform.elements;\n"); 632 result.append(" for (var i=0; i<inputFields.length; i++) {\n"); 633 result.append(" if(inputFields[i].name != null && inputFields[i].name.indexOf('categories') != -1) {\n"); 634 result.append(" inputFields[i].value='';\n"); 635 result.append(" inputFields[i].name='invalidsearchcategory';\n"); 636 result.append(" }\n"); 637 result.append(" }\n"); 638 // if we found a category field use it, if not, set the name of our 639 // fooling field to "categories.0" or the widget filling will fail 640 result.append(" var categoryField = inputFields['dummysearchcategory'];\n"); 641 result.append(" categoryField.name = 'categories.0';\n"); 642 result.append(" categoryField.value = category;\n"); 643 // additionally set searchpage to zero because filtered results may / will be smaller 644 result.append(" inputFields['dummysearchpage'].value = '0';\n"); 645 result.append(" inputFields['dummysearchpage'].name = 'searchpage.0';\n"); 646 result.append(" validateQuery();\n"); 647 result.append(" searchform.submit();\n"); 648 result.append(" }\n"); 649 result.append("</script>\n"); 650 return result.toString(); 651 } 652 653 /** 654 * Returns a list of <code>{@link CmsSelectWidgetOption}</code> objects for field list selection.<p> 655 * 656 * @return a list of <code>{@link CmsSelectWidgetOption}</code> objects 657 */ 658 private List<CmsSelectWidgetOption> getFieldList() { 659 660 List<CmsSelectWidgetOption> retVal = new ArrayList<CmsSelectWidgetOption>(); 661 try { 662 Iterator<CmsSearchField> i = getSearchFields().iterator(); 663 while (i.hasNext()) { 664 CmsLuceneField field = (CmsLuceneField)i.next(); 665 retVal.add( 666 new CmsSelectWidgetOption( 667 field.getName(), 668 true, 669 getMacroResolver().resolveMacros(field.getDisplayName()))); 670 } 671 } catch (Exception e) { 672 // noop 673 } 674 return retVal; 675 } 676 677 /** 678 * Returns the different select options for sort search result criteria. <p> 679 * 680 * @return the different select options for sort search result criteria 681 */ 682 private List<CmsSelectWidgetOption> getSortWidgetConfiguration() { 683 684 List<CmsSelectWidgetOption> result = new LinkedList<CmsSelectWidgetOption>(); 685 CmsMessages messages = Messages.get().getBundle(getLocale()); 686 result.add( 687 new CmsSelectWidgetOption( 688 CmsSearchParameters.SORT_NAMES[0], 689 true, 690 messages.key(Messages.GUI_SELECT_LABEL_SEARCH_SORT_SCORE_0))); 691 result.add( 692 new CmsSelectWidgetOption( 693 CmsSearchParameters.SORT_NAMES[1], 694 false, 695 messages.key(Messages.GUI_SELECT_LABEL_SEARCH_SORT_DATE_CREATED_0))); 696 result.add( 697 new CmsSelectWidgetOption( 698 CmsSearchParameters.SORT_NAMES[2], 699 false, 700 messages.key(Messages.GUI_SELECT_LABEL_SEARCH_SORT_DATE_LAST_MODIFIED_0))); 701 result.add( 702 new CmsSelectWidgetOption( 703 CmsSearchParameters.SORT_NAMES[3], 704 false, 705 messages.key(Messages.GUI_SELECT_LABEL_SEARCH_SORT_TITLE_0))); 706 return result; 707 } 708 709 /** 710 * Normalizes the JavaScript for the previous search query.<p> 711 * 712 * @return the normalized JavaScript 713 */ 714 private String normalizePreviousQueryJS() { 715 716 StringBuffer result = new StringBuffer(); 717 result.append("<script >\n"); 718 result.append(" function normalizeQueryValue() {\n"); 719 result.append(" var searchform = document.forms['EDITOR'];\n"); 720 result.append(" var query = searchform.elements['query.0'].value;\n"); 721 result.append(" query = decodeURI(query);\n"); 722 result.append(" searchform.elements['query.0'].value = query;\n"); 723 result.append(" return true;\n"); 724 result.append(" }\n"); 725 result.append(" normalizeQueryValue();\n"); 726 result.append("</script>\n"); 727 return result.toString(); 728 } 729 730 /** 731 * Returns the JavaScript for submitting the search form.<p> 732 * 733 * @return the JavaScript for submitting the search form 734 */ 735 private String submitJS() { 736 737 StringBuffer result = new StringBuffer(); 738 result.append(" function validateQuery() {\n"); 739 result.append(" var searchform = document.getElementById(\"EDITOR\");\n"); 740 result.append(" var query = searchform.elements['query.0'].value;\n"); 741 result.append(" searchform.elements['query.0'].value = query;\n"); 742 result.append(" return true;\n"); 743 result.append(" }\n"); 744 return result.toString(); 745 } 746}