@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"
              + "});");
    }
  }