private void buildHiddenSelectorWidget( SerialisationContext pSerialisationContext, HTMLSerialiser pSerialiser, EvaluatedNodeInfoItem pEvalNode, List<FieldSelectOption> pSelectOptions) { Map<String, Object> lTemplateVars = super.getGenericTemplateVars(pSerialisationContext, pSerialiser, pEvalNode); // Force the style to be off screen lTemplateVars.put("Style", "position: absolute; left: -999em;"); if (pEvalNode.getSelectorMaxCardinality() > 1) { lTemplateVars.put("Multiple", true); } // Always set size greater than 2, otherwise all fields post back with first value lTemplateVars.put("Size", Math.max(2, pSelectOptions.size())); List<Map<String, Object>> lOptions = new ArrayList<>(); OPTION_LOOP: for (FieldSelectOption lOption : pSelectOptions) { if (lOption.isHistorical() && !lOption.isSelected()) { // Skip un-selected historical items continue OPTION_LOOP; } Map<String, Object> lOptionVars = new HashMap<>(3); lOptionVars.put("Key", lOption.getDisplayKey()); lOptionVars.put("Value", lOption.getExternalFieldValue()); if (lOption.isSelected()) { lOptionVars.put("Selected", true); } if (lOption.isDisabled()) { lOptionVars.put("Disabled", true); } lOptions.add(lOptionVars); } lTemplateVars.put("Options", lOptions); MustacheFragmentBuilder.applyMapToTemplate( SELECTOR_MUSTACHE_TEMPLATE, lTemplateVars, pSerialiser.getWriter()); }
@Override public void buildWidgetInternal( SerialisationContext pSerialisationContext, HTMLSerialiser pSerialiser, EvaluatedNodeInfoItem pEvalNode) { FieldMgr lFieldMgr = pEvalNode.getFieldMgr(); List<FieldSelectOption> lSelectOptions = filteredOptionList(pEvalNode); if (!pEvalNode.isPlusWidget() && lFieldMgr.getVisibility() == NodeVisibility.VIEW) { SelectorWidgetBuilder.outputReadOnlyOptions(pSerialiser, pEvalNode); } else { // Create a hidden select element similar to the selector widget buildHiddenSelectorWidget(pSerialisationContext, pSerialiser, pEvalNode, lSelectOptions); // Find image base URL (the static servlet path) RequestURIBuilder lURIBuilder = pSerialisationContext.createURIBuilder(); // Mapset var name, could be cache key but then possible issues with itemrec String lMapsetJSONVariableName = lFieldMgr.getExternalFieldName() + pEvalNode .getStringAttribute(NodeAttribute.MAPSET, "missing-map-set") .replaceAll("[^a-zA-Z0-9]*", ""); // Static servlet requires app mnem appended String lJSON = mapsetToJSON( pEvalNode, StaticServlet.getURIWithAppMnem( lURIBuilder, pSerialisationContext.getApp().getAppMnem())); // Add the JSON to the page pSerialisationContext.addConditionalLoadJavascript( "var " + lMapsetJSONVariableName + " = " + lJSON + ";"); // Add a placeholder element String lLoadingElementName = "loading" + lFieldMgr.getExternalFieldName(); pSerialiser.append("<input type=\"text\" id=\""); pSerialiser.append(lLoadingElementName); pSerialiser.append("\" class=\"tagger tagger-loading\" />"); // Use the field width as the tagger width if tight field is specified, otherwise tagger // should use 100% of the cell String lFieldWidth; if (pEvalNode.getBooleanAttribute(NodeAttribute.TIGHT_FIELD, false)) { lFieldWidth = "$('#" + lLoadingElementName + "').css('width')"; } else { lFieldWidth = "'100%'"; } // Config for the jqueryTagger widget JSONObject lTaggerConfig = new JSONObject(); lTaggerConfig.put("baseURL", lURIBuilder.buildServletURI(StaticServlet.SERVLET_PATH)); lTaggerConfig.put("imgDownArrow", "/img/tagger-dropdown.png"); lTaggerConfig.put("imgRemove", "/img/tagger-remove.png"); lTaggerConfig.put("imgSearch", "/img/tagger-search.png"); lTaggerConfig.put("fieldWidth", lFieldWidth); // Add optinal values to pass to tagger lTaggerConfig.putAll(establishExtraParams(pEvalNode)); // Variable is passed in as a raw variable name to be resolved at runtime lTaggerConfig.put("availableTags", new JSONNonEscapedValue(lMapsetJSONVariableName)); // Pass through lSelectedIdList JSONArray lSelectedTags = new JSONArray(); for (FieldSelectOption lOption : lSelectOptions) { if (lOption.isSelected()) { lSelectedTags.add(lOption.getExternalFieldValue()); } } lTaggerConfig.put("preselectedTags", lSelectedTags); boolean lAJAXMapSet = pEvalNode.getMapSet() instanceof JITMapSet; if (lAJAXMapSet) { lTaggerConfig.put( "ajaxURL", MapSetWebService.AjaxSearchEndPoint.buildEndPointURI( pSerialisationContext.createURIBuilder(), pSerialisationContext.getThreadInfoProvider().getThreadId())); lTaggerConfig.put( "ajaxErrorFunction", new JSONNonEscapedValue( "function(self, data){self._showMessageSuggestion('The application has experienced an unexpected error, please try again or contact support. Error reference: <strong>' + data.responseJSON.errorDetails.reference + '</strong>', 'error');}")); } // Add in the JS to construct the tagger for the select pSerialisationContext.addConditionalLoadJavascript( "$(function(){\n" + " $('#" + lFieldMgr.getExternalFieldName() + "').tagger(" + lTaggerConfig.toJSONString() + ");\n" + "});"); } }
/** * Take in all the lists from the mapset and generate a JSON object array for each entry, to be * used by the search-selector widget * * @param pEvalNode Current ENI to get options from * @param pBaseURL Base URL of static servlet to replace %IMAGE_BASE% with in suggestion text * @return String of the JSON array to be set at the top of the page */ private String mapsetToJSON(EvaluatedNodeInfoItem pEvalNode, String pBaseURL) { JSONArray lMapsetJSON = new JSONArray(); JSONObject lMapsetObject = new JSONObject(); JSONObject lJSONEntry; int i = 1; for (FieldSelectOption lItem : filteredOptionList(pEvalNode)) { FieldSelectOption lSearchableItem = lItem; String lHiddenSearchable = lItem.getAdditionalProperty(HIDDEN_SEARCHABLE_MS_PROPERTY); String lSuggestion = lItem.getAdditionalProperty(SUGGESTION_DISPLAY_MS_PROPERTY); String lLevel = lItem.getAdditionalProperty(LEVEL_MS_PROPERTY); if ((pEvalNode.getFieldMgr().getVisibility() == NodeVisibility.VIEW && !lItem.isSelected())) { // Skip putting it in the JSON if it's got null entries or in read only mode and not // selected continue; } lJSONEntry = new JSONObject(); lJSONEntry.put("id", lSearchableItem.getExternalFieldValue()); lJSONEntry.put(KEY_JSON_PROPERTY, lSearchableItem.getDisplayKey()); lJSONEntry.put(SORT_JSON_PROPERTY, i++); // Add suggestion text (if none in mapset the JS will use the key safely escaped) if (!XFUtil.isNull(lSuggestion)) { lJSONEntry.put( SUGGESTION_DISPLAY_JSON_PROPERTY, StringEscapeUtils.escapeHtml4(lSuggestion.replaceAll("%IMAGE_BASE%", pBaseURL))); } lJSONEntry.put(HIDDEN_SEARCHABLE_JSON_PROPERTY, XFUtil.nvl(lHiddenSearchable, "")); // Add entry for hierarchical data if (lLevel != null) { lJSONEntry.put(LEVEL_JSON_PROPERTY, lLevel); } // If it was selected add that entry if (lSearchableItem.isSelected()) { lJSONEntry.put(SELECTED_JSON_PROPERTY, true); } // If it's a historical entry add that entry if (lSearchableItem.isHistorical()) { lJSONEntry.put(HISTORICAL_JSON_PROPERTY, true); lJSONEntry.put(SUGGESTABLE_JSON_PROPERTY, false); } else { lJSONEntry.put(SUGGESTABLE_JSON_PROPERTY, true); } if (lSearchableItem.getAdditionalProperty(OptionFieldMgr.FREE_TEXT_ADDITIONAL_PROPERTY) != null) { lJSONEntry.put(FREE_TEXT_JSON_PROPERTY, true); } lJSONEntry.put(DISABLED_JSON_PROPERTY, lSearchableItem.isDisabled()); lMapsetJSON.add(lJSONEntry); lMapsetObject.put(lSearchableItem.getExternalFieldValue(), lJSONEntry); } return lMapsetObject.toJSONString(); }