diff --git a/BranchMergeToTrunk.patch b/BranchMergeToTrunk.patch new file mode 100644 index 00000000000..b3b794c4b06 --- /dev/null +++ b/BranchMergeToTrunk.patch @@ -0,0 +1,80 @@ +Index: . +=================================================================== +--- . (revision 1680319) ++++ . (working copy) + +Property changes on: . +___________________________________________________________________ +Modified: svn:mergeinfo + Merged /ofbiz/branches/boostrap_theme:r1641659 +Index: framework/common/widget/CommonScreens.xml +=================================================================== +--- framework/common/widget/CommonScreens.xml (revision 1680314) ++++ framework/common/widget/CommonScreens.xml (working copy) +@@ -191,6 +191,7 @@ + + + ++ + + + +Index: framework/widget/src/org/ofbiz/widget/model/MenuFactory.java +=================================================================== +--- framework/widget/src/org/ofbiz/widget/model/MenuFactory.java (revision 1680329) ++++ framework/widget/src/org/ofbiz/widget/model/MenuFactory.java (working copy) +@@ -88,6 +88,16 @@ + } + + public static ModelMenu getMenuFromLocation(String resourceName, String menuName) throws IOException, SAXException, ParserConfigurationException { ++ Map modelMenuMap = getMenusFromLocation(resourceName); ++ ModelMenu modelMenu = modelMenuMap.get(menuName); ++ if (modelMenu == null) { ++ throw new IllegalArgumentException("Could not find menu with name [" + menuName + "] in location [" + resourceName + "]"); ++ } ++ return modelMenu; ++ } ++ ++ public static Map getMenusFromLocation(String resourceName) throws IOException, SAXException, ++ ParserConfigurationException { + Map modelMenuMap = menuLocationCache.get(resourceName); + if (modelMenuMap == null) { + URL menuFileUrl = FlexibleLocation.resolveLocation(resourceName); +@@ -100,11 +110,6 @@ + if (UtilValidate.isEmpty(modelMenuMap)) { + throw new IllegalArgumentException("Could not find menu file in location [" + resourceName + "]"); + } +- +- ModelMenu modelMenu = modelMenuMap.get(menuName); +- if (modelMenu == null) { +- throw new IllegalArgumentException("Could not find menu with name [" + menuName + "] in location [" + resourceName + "]"); +- } +- return modelMenu; ++ return modelMenuMap; + } + } +Index: framework/widget/src/org/ofbiz/widget/renderer/macro/MacroMenuRenderer.java +=================================================================== +--- framework/widget/src/org/ofbiz/widget/renderer/macro/MacroMenuRenderer.java (revision 1680314) ++++ framework/widget/src/org/ofbiz/widget/renderer/macro/MacroMenuRenderer.java (working copy) +@@ -273,6 +273,7 @@ + StringBuilder sb = new StringBuilder("End Menu Widget "); + sb.append(menu.getBoundaryCommentName()); + parameters.put("boundaryComment", sb.toString()); ++ parameters.put("style", menu.getMenuContainerStyle(context)); + } + try { + executeMacro(writer, "renderMenuEnd", parameters); +Index: framework/widget/templates/htmlMenuMacroLibrary.ftl +=================================================================== +--- framework/widget/templates/htmlMenuMacroLibrary.ftl (revision 1680314) ++++ framework/widget/templates/htmlMenuMacroLibrary.ftl (working copy) +@@ -31,7 +31,7 @@ +
    + + +-<#macro renderMenuEnd boundaryComment=""> ++<#macro renderMenuEnd boundaryComment="" style=""> +
+ + diff --git a/framework/common/data/CommonTypeData.xml b/framework/common/data/CommonTypeData.xml index f27c5072169..d8ef8518be3 100644 --- a/framework/common/data/CommonTypeData.xml +++ b/framework/common/data/CommonTypeData.xml @@ -105,6 +105,10 @@ under the License. + + + + diff --git a/framework/common/widget/CommonScreens.xml b/framework/common/widget/CommonScreens.xml index b8c208eb39b..49d6d458294 100644 --- a/framework/common/widget/CommonScreens.xml +++ b/framework/common/widget/CommonScreens.xml @@ -191,6 +191,7 @@ under the License. + @@ -395,6 +396,8 @@ under the License. + +
@@ -402,7 +405,7 @@ under the License. - +
@@ -431,7 +434,7 @@ under the License. - +
diff --git a/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java b/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java index 9bfe5eb82d8..d8792edb712 100644 --- a/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java +++ b/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java @@ -269,6 +269,7 @@ public void renderMenuClose(Appendable writer, Map context, Mode StringBuilder sb = new StringBuilder("End Menu Widget "); sb.append(menu.getBoundaryCommentName()); parameters.put("boundaryComment", sb.toString()); + parameters.put("style", menu.getMenuContainerStyle(context)); } try { executeMacro(writer, "renderMenuEnd", parameters); diff --git a/framework/widget/src/org/ofbiz/widget/menu/MenuFactory.java b/framework/widget/src/org/ofbiz/widget/menu/MenuFactory.java index ac89855cc3a..8d1f34580a1 100644 --- a/framework/widget/src/org/ofbiz/widget/menu/MenuFactory.java +++ b/framework/widget/src/org/ofbiz/widget/menu/MenuFactory.java @@ -28,6 +28,7 @@ import javax.xml.parsers.ParserConfigurationException; import org.ofbiz.base.location.FlexibleLocation; +import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.UtilHttp; import org.ofbiz.base.util.UtilValidate; import org.ofbiz.base.util.UtilXml; @@ -116,4 +117,32 @@ public static ModelMenu getMenuFromLocation(String resourceName, String menuName } return modelMenu; } + + public static Map getMenusFromLocation(String resourceName) + throws IOException, SAXException, ParserConfigurationException { + Map modelMenuMap = menuLocationCache.get(resourceName); + if (modelMenuMap == null) { + synchronized (MenuFactory.class) { + modelMenuMap = menuLocationCache.get(resourceName); + if (modelMenuMap == null) { + long startTime = System.currentTimeMillis(); + URL menuFileUrl = null; + menuFileUrl = FlexibleLocation.resolveLocation(resourceName); + if (menuFileUrl == null) { + throw new IllegalArgumentException("Could not resolve location to URL: " + resourceName); + } + Document menuFileDoc = UtilXml.readXmlDocument(menuFileUrl, true, true); + modelMenuMap = readMenuDocument(menuFileDoc, resourceName); + menuLocationCache.put(resourceName, modelMenuMap); + double totalSeconds = (System.currentTimeMillis() - startTime)/1000.0; + Debug.logInfo("Got " + modelMenuMap.size() + " screens in " + totalSeconds + "s from: " + menuFileUrl.toExternalForm(), module); + } + } + } + + if (modelMenuMap.isEmpty()) { + throw new IllegalArgumentException("Could not find menu file with name [" + resourceName + "]"); + } + return modelMenuMap; + } } diff --git a/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java b/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java index a3900df8300..10aab6f5be7 100644 --- a/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java +++ b/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.io.Writer; +import java.util.List; +import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -29,8 +31,13 @@ import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.GeneralException; import org.ofbiz.base.util.StringUtil; +import org.ofbiz.base.util.UtilGenerics; import org.ofbiz.base.util.UtilProperties; import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.base.util.collections.MapStack; +import org.ofbiz.service.LocalDispatcher; +import org.ofbiz.service.ModelService; +import org.ofbiz.service.ServiceUtil; import org.ofbiz.webapp.view.AbstractViewHandler; import org.ofbiz.webapp.view.ViewHandlerException; import org.ofbiz.widget.form.FormStringRenderer; @@ -54,7 +61,67 @@ public void init(ServletContext context) throws ViewHandlerException { this.servletContext = context; } - public void render(String name, String page, String info, String contentType, String encoding, HttpServletRequest request, HttpServletResponse response) throws ViewHandlerException { + private ScreenStringRenderer loadRenderers(HttpServletRequest request, HttpServletResponse response, + Map context, Writer writer) throws GeneralException, TemplateException, IOException { + String screenMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".screenrenderer"); + String formMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".formrenderer"); + String treeMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".treerenderer"); + String menuMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".menurenderer"); + Map userPreferences = UtilGenerics.cast(context.get("userPreferences")); + if (userPreferences != null) { + String visualThemeId = (String) userPreferences.get("VISUAL_THEME"); + if (visualThemeId != null) { + LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher"); + Map serviceCtx = dispatcher.getDispatchContext().makeValidContext("getVisualThemeResources", + ModelService.IN_PARAM, context); + serviceCtx.put("visualThemeId", visualThemeId); + Map serviceResult = dispatcher.runSync("getVisualThemeResources", serviceCtx); + if (ServiceUtil.isSuccess(serviceResult)) { + Map> themeResources = UtilGenerics.cast(serviceResult.get("themeResources")); + List resourceList = UtilGenerics.cast(themeResources.get("VT_SCRN_MACRO_LIB")); + if (resourceList != null && !resourceList.isEmpty()) { + String macroLibraryPath = resourceList.get(0); + if (macroLibraryPath != null) { + screenMacroLibraryPath = macroLibraryPath; + } + } + resourceList = UtilGenerics.cast(themeResources.get("VT_FORM_MACRO_LIB")); + if (resourceList != null && !resourceList.isEmpty()) { + String macroLibraryPath = resourceList.get(0); + if (macroLibraryPath != null) { + formMacroLibraryPath = macroLibraryPath; + } + } + resourceList = UtilGenerics.cast(themeResources.get("VT_TREE_MACRO_LIB")); + if (resourceList != null && !resourceList.isEmpty()) { + String macroLibraryPath = resourceList.get(0); + if (macroLibraryPath != null) { + treeMacroLibraryPath = macroLibraryPath; + } + } + resourceList = UtilGenerics.cast(themeResources.get("VT_MENU_MACRO_LIB")); + if (resourceList != null && !resourceList.isEmpty()) { + String macroLibraryPath = resourceList.get(0); + if (macroLibraryPath != null) { + menuMacroLibraryPath = macroLibraryPath; + } + } + } + } + } + ScreenStringRenderer screenStringRenderer = new MacroScreenRenderer(UtilProperties.getPropertyValue("widget", getName() + + ".name"), screenMacroLibraryPath); + FormStringRenderer formStringRenderer = new MacroFormRenderer(formMacroLibraryPath, request, response); + context.put("formStringRenderer", formStringRenderer); + TreeStringRenderer treeStringRenderer = new MacroTreeRenderer(treeMacroLibraryPath, writer); + context.put("treeStringRenderer", treeStringRenderer); + MenuStringRenderer menuStringRenderer = new MacroMenuRenderer(menuMacroLibraryPath, request, response); + context.put("menuStringRenderer", menuStringRenderer); + return screenStringRenderer; + } + + public void render(String name, String page, String info, String contentType, String encoding, HttpServletRequest request, + HttpServletResponse response) throws ViewHandlerException { try { Writer writer = response.getWriter(); @@ -74,28 +141,15 @@ public void render(String name, String page, String info, String contentType, St // to speed up output. writer = new StandardCompress().getWriter(writer, null); } - ScreenStringRenderer screenStringRenderer = new MacroScreenRenderer(UtilProperties.getPropertyValue("widget", getName() + ".name"), UtilProperties.getPropertyValue("widget", getName() + ".screenrenderer")); - ScreenRenderer screens = new ScreenRenderer(writer, null, screenStringRenderer); - screens.populateContextForRequest(request, response, servletContext); - String macroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".formrenderer"); - if (UtilValidate.isNotEmpty(macroLibraryPath)) { - FormStringRenderer formStringRenderer = new MacroFormRenderer(macroLibraryPath, request, response); - screens.getContext().put("formStringRenderer", formStringRenderer); - } - macroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".treerenderer"); - if (UtilValidate.isNotEmpty(macroLibraryPath)) { - TreeStringRenderer treeStringRenderer = new MacroTreeRenderer(macroLibraryPath, writer); - screens.getContext().put("treeStringRenderer", treeStringRenderer); - } - macroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".menurenderer"); - if (UtilValidate.isNotEmpty(macroLibraryPath)) { - MenuStringRenderer menuStringRenderer = new MacroMenuRenderer(macroLibraryPath, request, response); - screens.getContext().put("menuStringRenderer", menuStringRenderer); - } - screens.getContext().put("simpleEncoder", StringUtil.getEncoder(UtilProperties.getPropertyValue("widget", getName() + ".encoder"))); - screenStringRenderer.renderScreenBegin(writer, screens.getContext()); + MapStack context = MapStack.create(); + ScreenRenderer.populateContextForRequest(context, null, request, response, servletContext); + ScreenStringRenderer screenStringRenderer = loadRenderers(request, response, context, writer); + ScreenRenderer screens = new ScreenRenderer(writer, context, screenStringRenderer); + context.put("screens", screens); + context.put("simpleEncoder", StringUtil.getEncoder(UtilProperties.getPropertyValue("widget", getName() + ".encoder"))); + screenStringRenderer.renderScreenBegin(writer, context); screens.render(page); - screenStringRenderer.renderScreenEnd(writer, screens.getContext()); + screenStringRenderer.renderScreenEnd(writer, context); writer.flush(); } catch (TemplateException e) { Debug.logError(e, "Error initializing screen renderer", module); diff --git a/framework/widget/templates/htmlMenuMacroLibrary.ftl b/framework/widget/templates/htmlMenuMacroLibrary.ftl index 3534a39c60b..72681c81895 100644 --- a/framework/widget/templates/htmlMenuMacroLibrary.ftl +++ b/framework/widget/templates/htmlMenuMacroLibrary.ftl @@ -31,7 +31,7 @@ under the License.
    -<#macro renderMenuEnd boundaryComment=""> +<#macro renderMenuEnd boundaryComment="" style="">
diff --git a/themes/bootstrap/README b/themes/bootstrap/README new file mode 100644 index 00000000000..ab8ac61ad36 --- /dev/null +++ b/themes/bootstrap/README @@ -0,0 +1,54 @@ +This is an initial attempt to create a Bootstrap based front-end theme for Apache Ofbiz. + +1. Approach + +The following steps were followed in this implementation: + +1.1 No screen/form/menu modifications were effected. This to ensure that other themes are not broken in the process; +1.2 Existing MacroLibraries were copied from framework/widget/templates to the new theme webapp /includes/templates directory - + at this stage only the htmlFormMacroLibrary.ftl, htmlMenuMacroLibrary.ftl and htmlScreenMacroLibrary.ftl files; + These files were modified where necessary to accommodate Bootstrap. +1.3 Bootstrap files were downloaded and placed in the framework/images directory. +1.4 The Ofbiz Tomahawk theme is used as a base theme (see note on CSS). +1.5 A javaScript file (bootified.js) has been included to transform widgets defined in ftls. MacroLibraries only cater for widgets defined in *Form.xml,*Menus.xml and *Screens.xml files. + It was therefore necessary to provide a small script to perform some DOM manipulations. (See note under issues) +1.6 It was necessary to make small modifications to two framework java files to achieve greater flexibility with regards to the menu widget: + MenuFactory.java - added getMenusFromLocation static method to retieve all menus defined in a particular *Menus.xml; + MacroMenuRenderer.java - added "style" to the Map in renderMenuClose method to provide more flexibility; + Patches are supplied for both cases. (See note on Navigation) + +2. CSS +2.1 A global.css file was created and included as a visualThemeResource. All stylesheets are imported through this file to ensure that style sheets are loaded in the correct order. +2.2 The global.css includes (in loading order): + @import url("/images/bootstrap/css/bootstrap.css"); + @import url("legacy.css"); /* Original ofbiz theme stylesheet - in this case style.css in Tomahawk*/ + @import url("help.css"); + @import url("javascript.css"); + @import url("style.css"); /* Base boostrap-ofbiz style - used to style vanilla boostrap */ +2.3 CSS elements in the legacy stylesheet which override the bootstrap.css are commented out. + The idea is not to add new elements to the legacy.css but to systematically reduce it during the course of the development. + This will decrease css bloat. +2.4 All new css elements are defined in the style.css which is loaded last. +2.5 More css files can optionally be appended after the style.css. This can be used to create different skins for the same theme. + I have included an additional theme to demonstrate skinning. Choose the Bootstrap TomaHawk theme to see this in action. + +3. Navigation +3.1 Main Navigation - i.e. Primary and Secondary Apps: The main navigation is currently not contained/defined in a *Menus.xml file. It is therefore not rendered + through the htmlMenuMacroLibrary.ftl. The header.ftl file is use to produce this nav via getAppBarWebInfosweb method. Is there a case to define this in a *Menus.xml file? +3.2 App Navigation:The appheaderTemplate pattern is issued pattern is followed in this case, along with an empty appbar.ftl. This could have been done through the htmlMenuMacroLibrary.ftl, but this method makes dropdowns impossible. + Is would be possible to produce an app navigation with dropdowns if sub menus were used in menu definitions. Although the framework does allow for sub menu definitions, I am yet to see an example of its + implementation in Ofbiz. (I stand to be corrected offcourse). In this case dropdown menus are generated using the *TabBar naming pattern - a sub menu is linked to the main item based on the item's name and the sub menu name. + Some sub menus are not picked up because of inconsistencies in the naming practices. (See known issues) + To get this to work and empty appbar.ftl is used so that the app-nav is is not displayed twice. Also, the GlobalDecorator screen had to be amended to set the appheaderTemplate location. A patch is provided for this. +3.3 TabBar Navigation: This is rendered through the htmlMenuMacroLibrary.ftl. + +4. Known Issues +4.1 Jerky page rendering: Page initially shows unformatted/styled html for a few seconds before showing properly. This is probably due to the macroLibraries being served as a visualThemeResource. + This issue disappears when the widget.properties defs point to the libraries under bootstrap/includes - a restart is required for this! + The down side of this is that other themes will not display properly. This should only be done if you want to use bootstrap themes exclusively. +4.2 The are probably plenty ftl issues. A pertinent one is the datepicker. The datepicker works fine with forms defined in xml. But FTL forms are problematic. + +5. Work needed +5.1 Lookup screens; +5.2 Iconizing buttontext in FTLs. +5.3 And a lot more .... diff --git a/themes/bootstrap/build.xml b/themes/bootstrap/build.xml new file mode 100644 index 00000000000..420a4e24c35 --- /dev/null +++ b/themes/bootstrap/build.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/bootstrap/data/BootstrapThemeData.xml b/themes/bootstrap/data/BootstrapThemeData.xml new file mode 100644 index 00000000000..2ec81261fbd --- /dev/null +++ b/themes/bootstrap/data/BootstrapThemeData.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/bootstrap/includes/appbar.ftl b/themes/bootstrap/includes/appbar.ftl new file mode 100644 index 00000000000..aef9e9eb82c --- /dev/null +++ b/themes/bootstrap/includes/appbar.ftl @@ -0,0 +1,107 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> +<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)> +<#assign modelMenus = Static["org.ofbiz.widget.menu.MenuFactory"].getMenusFromLocation(applicationMenuLocation)> + +<#assign menus = modelMenus.keySet()> +<#assign menuItemList = appModelMenu.menuItemList> +<#if menuItemList?has_content> + ${applicationTitle} + +
+ \ No newline at end of file diff --git a/themes/bootstrap/includes/appbar.ftl.bk b/themes/bootstrap/includes/appbar.ftl.bk new file mode 100644 index 00000000000..226e853869a --- /dev/null +++ b/themes/bootstrap/includes/appbar.ftl.bk @@ -0,0 +1,87 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> +<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)> +<#assign modelMenus = Static["org.ofbiz.widget.menu.MenuFactory"].getMenusFromLocation(applicationMenuLocation)> +<#-- + +
${appModelMenu?if_exists}
+
${applicationMenuLocation}
+
${applicationMenuName}
+--> +<#assign menus = modelMenus.keySet()> +<#assign menuItemList = appModelMenu.menuItemList> +<#if menuItemList?has_content> + + \ No newline at end of file diff --git a/themes/bootstrap/includes/appbarClose.ftl b/themes/bootstrap/includes/appbarClose.ftl new file mode 100644 index 00000000000..812df5765c1 --- /dev/null +++ b/themes/bootstrap/includes/appbarClose.ftl @@ -0,0 +1,18 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> diff --git a/themes/bootstrap/includes/appbarOpen.ftl b/themes/bootstrap/includes/appbarOpen.ftl new file mode 100644 index 00000000000..828bbd4dc9d --- /dev/null +++ b/themes/bootstrap/includes/appbarOpen.ftl @@ -0,0 +1,90 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> +<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)> +<#assign modelMenus = Static["org.ofbiz.widget.menu.MenuFactory"].getMenusFromLocation(applicationMenuLocation)> +<#-- + +
${appModelMenu?if_exists}
+
${applicationMenuLocation}
+
${applicationMenuName}
+--> +<#assign menus = modelMenus.keySet()> +<#assign menuItemList = appModelMenu.menuItemList> +<#if menuItemList?has_content> + + \ No newline at end of file diff --git a/themes/bootstrap/includes/emptyAppBar.ftl b/themes/bootstrap/includes/emptyAppBar.ftl new file mode 100644 index 00000000000..812df5765c1 --- /dev/null +++ b/themes/bootstrap/includes/emptyAppBar.ftl @@ -0,0 +1,18 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> diff --git a/themes/bootstrap/includes/footer.ftl b/themes/bootstrap/includes/footer.ftl new file mode 100644 index 00000000000..fcf102d0495 --- /dev/null +++ b/themes/bootstrap/includes/footer.ftl @@ -0,0 +1,46 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> + + +<#if layoutSettings.VT_FTR_JAVASCRIPT?has_content> + <#list layoutSettings.VT_FTR_JAVASCRIPT as javaScript> + + + + + diff --git a/themes/bootstrap/includes/header.ftl b/themes/bootstrap/includes/header.ftl new file mode 100644 index 00000000000..6c09fb0083a --- /dev/null +++ b/themes/bootstrap/includes/header.ftl @@ -0,0 +1,323 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> +<#assign docLangAttr = locale.toString()?replace("_", "-")> +<#assign langDir = "ltr"> +<#if "ar.iw"?contains(docLangAttr?substring(0, 2))> + <#assign langDir = "rtl"> + +<#if person?has_content> + <#assign userName = person.firstName?if_exists + " " + person.middleName?if_exists + " " + person.lastName?if_exists> +<#elseif partyGroup?has_content> + <#assign userName = partyGroup.groupName?if_exists> +<#elseif userLogin?exists> + <#assign userName = userLogin.userLoginId> +<#else> + <#assign userName = ""> + +<#if defaultOrganizationPartyGroupName?has_content> + <#assign orgName = " - " + defaultOrganizationPartyGroupName?if_exists> +<#else> + <#assign orgName = ""> + +<#if layoutSettings.headerImageLinkUrl?exists> + <#assign logoLinkURL = "${layoutSettings.headerImageLinkUrl}"> +<#else> + <#assign logoLinkURL = "${layoutSettings.commonHeaderImageLinkUrl}"> + +<#assign organizationLogoLinkURL = "${layoutSettings.organizationLogoLinkUrl?if_exists}"> +<#if layoutSettings.headerImageUrl?exists> + <#assign headerImageUrl = layoutSettings.headerImageUrl> + <#elseif layoutSettings.commonHeaderImageUrl?exists> + <#assign headerImageUrl = layoutSettings.commonHeaderImageUrl> + <#elseif layoutSettings.VT_HDR_IMAGE_URL?exists> + <#assign headerImageUrl = layoutSettings.VT_HDR_IMAGE_URL.get(0)> + +<#-- Get AppBarWebInfos --> +<#if (requestAttributes.externalLoginKey)??><#assign externalKeyParam = "?externalLoginKey=" + requestAttributes.externalLoginKey!> +<#if (externalLoginKey)??><#assign externalKeyParam = "?externalLoginKey=" + requestAttributes.externalLoginKey!> +<#assign ofbizServerName = application.getAttribute("_serverId")?default("default-server")> +<#assign contextPath = request.getContextPath()> +<#assign displayApps = Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, userLogin, ofbizServerName, "main")> +<#assign displaySecondaryApps = Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, userLogin, ofbizServerName, "secondary")> + +<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)> +<#if appModelMenu.getModelMenuItemByName(headerItem)??> + <#if headerItem!="main"> + <#assign show_last_menu = true> + + + +<#if parameters.portalPageId?? && !appModelMenu.getModelMenuItemByName(headerItem)??> + <#assign show_last_menu = true> + + + + + ${layoutSettings.companyName}: <#if (page.titleProperty)?has_content>${uiLabelMap[page.titleProperty]}<#else>${(page.title)?if_exists}</#if> + <#if layoutSettings.shortcutIcon?has_content> + <#assign shortcutIcon = layoutSettings.shortcutIcon/> + <#elseif layoutSettings.VT_SHORTCUT_ICON?has_content> + <#assign shortcutIcon = layoutSettings.VT_SHORTCUT_ICON.get(0)/> + + <#if shortcutIcon?has_content> + + + <#if layoutSettings.javaScripts?has_content> + <#--layoutSettings.javaScripts is a list of java scripts. --> + <#-- use a Set to make sure each javascript is declared only once, but iterate the list to maintain the correct order --> + <#assign javaScriptsSet = Static["org.ofbiz.base.util.UtilMisc"].toSet(layoutSettings.javaScripts)/> + <#list layoutSettings.javaScripts as javaScript> + <#if javaScriptsSet.contains(javaScript)> + <#assign nothing = javaScriptsSet.remove(javaScript)/> + + + + + <#if layoutSettings.VT_HDR_JAVASCRIPT?has_content> + <#list layoutSettings.VT_HDR_JAVASCRIPT as javaScript> + + + + <#if layoutSettings.styleSheets?has_content> + <#--layoutSettings.styleSheets is a list of style sheets. So, you can have a user-specified "main" style sheet, AND a component style sheet.--> + <#list layoutSettings.styleSheets as styleSheet> + + + + <#if layoutSettings.VT_STYLESHEET?has_content> + <#list layoutSettings.VT_STYLESHEET as styleSheet> + + + + <#if layoutSettings.rtlStyleSheets?has_content && langDir == "rtl"> + <#--layoutSettings.rtlStyleSheets is a list of rtl style sheets.--> + <#list layoutSettings.rtlStyleSheets as styleSheet> + + + + <#if layoutSettings.VT_RTL_STYLESHEET?has_content && langDir == "rtl"> + <#list layoutSettings.VT_RTL_STYLESHEET as styleSheet> + + + + <#if layoutSettings.VT_EXTRA_HEAD?has_content> + <#list layoutSettings.VT_EXTRA_HEAD as extraHead> + ${extraHead} + + + <#if lastParameters?exists><#assign parametersURL = "&" + lastParameters> + <#if layoutSettings.WEB_ANALYTICS?has_content> + + + +<#if layoutSettings.headerImageLinkUrl?exists> + <#assign logoLinkURL = "${layoutSettings.headerImageLinkUrl}"> +<#else> + <#assign logoLinkURL = "${layoutSettings.commonHeaderImageLinkUrl}"> + +<#assign organizationLogoLinkURL = "${layoutSettings.organizationLogoLinkUrl?if_exists}"> + + + <#--
--> + + +
+ <#--
--> diff --git a/themes/bootstrap/includes/templates/htmlFormMacroLibrary.ftl b/themes/bootstrap/includes/templates/htmlFormMacroLibrary.ftl new file mode 100644 index 00000000000..45449ebfedb --- /dev/null +++ b/themes/bootstrap/includes/templates/htmlFormMacroLibrary.ftl @@ -0,0 +1,895 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> + +<#macro renderField text> + <#if text??> + ${text}<#lt/> + + + +<#macro renderDisplayField type imageLocation idName description title class alert inPlaceEditorUrl="" inPlaceEditorParams=""> + <#if type?has_content && type=="image"> + <#lt/> + <#else> + <#if inPlaceEditorUrl?has_content || class?has_content || alert=="true" || title?has_content> + id="cc_${idName}" <#if title?has_content>title="${title}" <@renderClass class alert />><#t/> + + + <#if description?has_content> + ${description?replace("\n", "
")}<#t/> + <#else> +  <#t/> + + <#if inPlaceEditorUrl?has_content || class?has_content || alert=="true"> +
<#lt/> + + <#if inPlaceEditorUrl?has_content && idName?has_content> + <#lt/> + + + +<#macro renderHyperlinkField> + +<#macro renderTextField name className alert value textSize maxlength id event action disabled clientAutocomplete ajaxUrl ajaxEnabled mask placeholder=""> + <#if mask?has_content> + + + + <@renderClass className alert /> + <#if value?has_content> value="${value}"<#rt/> + <#if textSize?has_content> size="${textSize}"<#rt/> + <#if maxlength?has_content> maxlength="${maxlength}"<#rt/> + <#if disabled?has_content && disabled> disabled="disabled"<#rt/> + <#if id?has_content> id="${id}"<#rt/> + <#if event?has_content && action?has_content> ${event}="${action}"<#rt/> + <#if clientAutocomplete?has_content && clientAutocomplete=="false"> autocomplete="off"<#rt/> + <#if placeholder?has_content> placeholder="${placeholder}"<#rt/> + /><#t/> + <#if ajaxEnabled?has_content && ajaxEnabled> + <#assign defaultMinLength = Static["org.ofbiz.base.util.UtilProperties"].getPropertyValue("widget.properties", "widget.autocompleter.defaultMinLength")> + <#assign defaultDelay = Static["org.ofbiz.base.util.UtilProperties"].getPropertyValue("widget.properties", "widget.autocompleter.defaultDelay")> + <#lt/> + + + +<#macro renderTextareaField name className alert cols rows id readonly value visualEditorEnable buttons language=""> + <#lt/> + <#if visualEditorEnable?has_content> + <#rt/> + <#if language?has_content && language != "en"> + <#rt/> + + + + + + +<#macro renderDateTimeField name className alert title value size maxlength id dateType shortDateInput timeDropdownParamName defaultDateTimeString localizedIconTitle timeDropdown timeHourName classString hour1 hour2 timeMinutesName minutes isTwelveHour ampmName amSelected pmSelected compositeType formName mask="" event="" action="" step="" timeValues=""> + + <#if dateType!="time" > + <#rt/> + <#if title?has_content> title="${title}" + <#if value?has_content> value="${value}" + <#if size?has_content> size="${size}"<#rt/> + <#if maxlength?has_content> maxlength="${maxlength}" + <#if id?has_content> id="${id}_i18n"/><#rt/> + + <#-- the style attribute is a little bit messy but when using disply:none the timepicker is shown on a wrong place --> + ${event}="${action}" <@renderClass className alert /><#rt/> + <#if title?has_content> title="${title}" + <#if value?has_content> value="${value}" + <#if size?has_content> size="${size}"<#rt/> + <#if maxlength?has_content> maxlength="${maxlength}" + <#if id?has_content> id="${id}"/><#rt/> + <#if dateType!="time" > + + + <#if timeDropdown?has_content && timeDropdown=="time-dropdown"> + : + <#rt/> + <#if isTwelveHour> + + <#rt/> + + + + + + +<#macro renderDropDownField name className alert id multiple formName otherFieldName event action size firstInList currentValue explicitDescription allowEmpty options fieldName otherFieldName otherValue otherFieldSize dDFCurrent ajaxEnabled noCurrentSelectedKey ajaxOptions frequency minChars choices autoSelect partialSearch partialChars ignoreCase fullSearch> + + + + <#if otherFieldName?has_content> + + + + + <#if ajaxEnabled> + + + + +<#macro renderCheckField items className alert id allChecked currentValue name event action> + <#list items as item> + ><#rt/> + id="${id}"<#rt/> + <#if allChecked?has_content && allChecked> checked="checked" <#elseif allChecked?has_content && !allChecked> + <#elseif currentValue?has_content && currentValue==item.value> checked="checked" + name="${name?default("")?html}" value="${item.value?default("")?html}"<#if event?has_content> ${event}="${action}"/><#rt/> + ${item.description?default("")} + + + + +<#macro renderRadioField items className alert currentValue noCurrentSelectedKey name event action> + <#list items as item> + ><#rt/> + <#if currentValue==item.key> checked="checked" + <#elseif noCurrentSelectedKey?has_content && noCurrentSelectedKey == item.key> checked="checked" + name="${name?default("")?html}" value="${item.key?default("")?html}"<#if event?has_content> ${event}="${action}"/><#rt/> + ${item.description} + + + + +<#macro renderSubmitField buttonType className alert formName title name event action imgSrc confirmation containerId ajaxUrl> + <#if buttonType=="text-link"> + href="javascript:document.${formName}.submit()" <#if confirmation?has_content>onclick="return confirm('${confirmation?js_string}');"><#if title?has_content>${title} + <#elseif buttonType=="image"> + <#if name?has_content> name="${name}" + <#if title?has_content> alt="${title}"<#if event?has_content> ${event}="${action}" + <#if confirmation?has_content>onclick="return confirm('${confirmation?js_string}');"/> + <#else> + + <#if name??> name="${name}"<#if title?has_content> value="${title}"<#if event?has_content> ${event}="${action}" + <#if containerId?has_content> onclick="<#if confirmation?has_content>if (confirm('${confirmation?js_string}')) ajaxSubmitFormUpdateAreas('${containerId}', '${ajaxUrl}')" + <#else><#if confirmation?has_content> onclick="return confirm('${confirmation?js_string}');" + /> + + + +<#macro renderResetField className alert name title> + name="${name}"<#if title?has_content> value="${title}"/> + + +<#macro renderHiddenField name value id event action> + value="${value}"<#if id?has_content> id="${id}"<#if event?has_content && action?has_content> ${event}="${action}"/> + + +<#macro renderIgnoredField> + +<#macro renderFieldTitle style title id fieldHelpText="" for="" > + <#t/> + + +<#macro renderSingleFormFieldTitle> + +<#macro renderFormOpen linkUrl formType targetWindow containerId containerStyle autocomplete name viewIndexField viewSizeField viewIndex viewSize useRowSubmit> +
enctype="multipart/form-data"<#if targetWindow?has_content> target="${targetWindow}"<#if containerId?has_content> id="${containerId}" class=<#if containerStyle?has_content>"${containerStyle}"<#else>"form-horizontal" onsubmit="javascript:submitFormDisableSubmits(this)"<#if autocomplete?has_content> autocomplete="${autocomplete}" name="${name}"><#lt/> + <#if useRowSubmit?has_content && useRowSubmit> + + <#if linkUrl?index_of("VIEW_INDEX") <= 0 && linkUrl?index_of(viewIndexField) <= 0> + + + <#if linkUrl?index_of("VIEW_SIZE") <= 0 && linkUrl?index_of(viewSizeField) <= 0> + + + + +<#macro renderFormClose focusFieldName formName containerId hasRequiredField> +
<#lt/> + <#if focusFieldName?has_content> + <#lt/> + + <#if containerId?has_content && hasRequiredField?has_content> + + + +<#macro renderMultiFormClose> + <#lt/> + + +<#macro renderFormatListWrapperOpen formName style columnStyles> + <#lt/> + + +<#macro renderFormatListWrapperClose formName> +
<#lt/> + + +<#macro renderFormatHeaderRowOpen style> + + +<#macro renderFormatHeaderRowClose> + + +<#macro renderFormatHeaderRowCellOpen style positionSpan> + colspan="${positionSpan}"<#if style?has_content>class="${style}"> + +<#macro renderFormatHeaderRowCellClose> + + + +<#macro renderFormatHeaderRowFormCellOpen style> + class="${style}"> + +<#macro renderFormatHeaderRowFormCellClose> + + +<#macro renderFormatHeaderRowFormCellTitleSeparator style isLast> + <#if style?has_content> - <#if style?has_content> + + +<#macro renderFormatItemRowOpen formName itemIndex altRowStyles evenRowStyle oddRowStyle> + <#if itemIndex%2==0><#if evenRowStyle?has_content>class="${evenRowStyle}<#if altRowStyles?has_content> ${altRowStyles}"<#elseif altRowStyles?has_content>class="${altRowStyles}"<#else><#if oddRowStyle?has_content>class="${oddRowStyle}<#if altRowStyles?has_content> ${altRowStyles}"<#elseif altRowStyles?has_content>class="${altRowStyles}" > + +<#macro renderFormatItemRowClose formName> + + +<#macro renderFormatItemRowCellOpen fieldName style positionSpan> + colspan="${positionSpan}"<#if style?has_content>class="${style}"> + +<#macro renderFormatItemRowCellClose fieldName> + + +<#macro renderFormatItemRowFormCellOpen style> + class="${style}"> + +<#macro renderFormatItemRowFormCellClose> + + + +<#macro renderFormatSingleWrapperOpen formName style> + <#-- class="${style}"> --> + +<#macro renderFormatSingleWrapperClose formName> + <#--
--> + + +<#macro renderFormatFieldRowOpen> +
+ +<#macro renderFormatFieldRowClose> +
+ +<#macro renderFormatFieldRowTitleCellOpen style> +
+ +<#macro renderFormatFieldRowTitleCellClose> +
+ +<#macro renderFormatFieldRowSpacerCell> +<#macro renderFormatFieldRowWidgetCellOpen positionSpan style> +
+ +<#macro renderFormatFieldRowWidgetCellClose> + <#--
--> +
+ + +<#-- + Initial work to convert table based layout for "single" form to divs. +<#macro renderFormatSingleWrapperOpen style>
class="${style}" > +<#macro renderFormatSingleWrapperClose>
+ +<#macro renderFormatFieldRowOpen>
+<#macro renderFormatFieldRowClose>
+<#macro renderFormatFieldRowTitleCellOpen style>
+<#macro renderFormatFieldRowTitleCellClose>
+<#macro renderFormatFieldRowSpacerCell> +<#macro renderFormatFieldRowWidgetCellOpen positionSpan style> colspan="${1+positionSpan*3}"<#if style?has_content> class="${style}"> +<#macro renderFormatFieldRowWidgetCellClose> + +--> + + +<#macro renderFormatEmptySpace>  + +<#macro renderTextFindField name value defaultOption opEquals opBeginsWith opContains opIsEmpty opNotEqual className alert size maxlength autocomplete titleStyle hideIgnoreCase ignCase ignoreCase> + <#if opEquals?has_content> + + <#else> + "${name}_op" value="${defaultOption}"/><#rt/> + + name="${name}"<#if value?has_content> value="${value}"<#if size?has_content> size="${size}"<#if maxlength?has_content> maxlength="${maxlength}"<#if autocomplete?has_content> autocomplete="off"/><#rt/> + <#if titleStyle?has_content><#rt/> + <#if hideIgnoreCase> + "Y"<#else> ""/><#rt/> + <#else> + checked="checked" /> ${ignoreCase}<#rt/> + + <#if titleStyle?has_content> + + + +<#macro renderDateFindField className alert name localizedInputTitle value size maxlength dateType formName defaultDateTimeString imgSrc localizedIconTitle titleStyle defaultOptionFrom defaultOptionThru opEquals opSameDay opGreaterThanFromDayStart opGreaterThan opGreaterThan opLessThan opUpToDay opUpThruDay opIsEmpty> + + <#if name?has_content> name="${name?html}_fld0_value"<#if localizedInputTitle?has_content> title="${localizedInputTitle}"<#if value?has_content> value="${value}"<#if size?has_content> size="${size}"<#if maxlength?has_content> maxlength="${maxlength}"/><#rt/> + <#if dateType != "time"> + + <#rt/> + + <#if titleStyle?has_content> + <#rt/> + + name="${name}_fld0_op" class="selectBox"><#rt/> + <#rt/> + <#rt/> + <#rt/> + <#rt/> + <#rt/> + <#if titleStyle?has_content> + <#rt/> + + <#rt/> + <#if name?has_content> name="${name}_fld1_value"<#if localizedInputTitle??> title="${localizedInputTitle?html}"<#if value2?has_content> value="${value2}"<#if size?has_content> size="${size}"<#if maxlength?has_content> maxlength="${maxlength}"/><#rt/> + <#if dateType != "time"> + + <#rt/> + + <#if titleStyle?has_content> + <#rt/> + + <#rt/> + <#if titleStyle?has_content> + + + + + + +<#macro renderRangeFindField className alert name value size maxlength autocomplete titleStyle defaultOptionFrom opEquals opGreaterThan opGreaterThanEquals opLessThan opLessThanEquals value2 defaultOptionThru> + <#if name?has_content>name="${name}_fld0_value"<#if value?has_content> value="${value}"<#if size?has_content> size="${size}"<#if maxlength?has_content> maxlength="${maxlength}"<#if autocomplete?has_content> autocomplete="off"/><#rt/> + <#if titleStyle?has_content> + <#rt/> + + <#rt/> + <#if titleStyle?has_content> + <#rt/> + +
<#rt/> + <#if name?has_content> name="${name}_fld1_value"<#if value2?has_content> value="${value2}"<#if size?has_content> size="${size}"<#if maxlength?has_content> maxlength="${maxlength}"<#if autocomplete?has_content> autocomplete="off"/><#rt/> + <#if titleStyle?has_content> + <#rt/> + + <#rt/> + <#if titleStyle?has_content> + + + + +<#-- +@renderLookupField + +Description: Renders a text input field as a lookup field. + +Parameter: name, String, required - The name of the lookup field. +Parameter: formName, String, required - The name of the form that contains the lookup field. +Parameter: fieldFormName, String, required - Contains the lookup window form name. +Parameter: className, String, optional - The CSS class name for the lookup field. +Parameter: alert, String, optional - If "true" then the "alert" CSS class will be added to the lookup field. +Parameter: value, Object, optional - The value of the lookup field. +Parameter: size, String, optional - The size of the lookup field. +Parameter: maxlength, String or Integer, optional - The max length of the lookup field. +Parameter: id, String, optional - The ID of the lookup field. +Parameter: event, String, optional - The lookup field event that invokes "action". If the event parameter is not empty, then the action parameter must be specified as well. +Parameter: action, String, optional - The action that is invoked on "event". If action parameter is not empty, then the event parameter must be specified as well. +Parameter: readonly, boolean, optional - If true, the lookup field is made read-only. +Parameter: autocomplete, String, optional - If not empty, autocomplete is turned off for the lookup field. +Parameter: descriptionFieldName, String, optional - If not empty and the presentation parameter contains "window", specifies an alternate input field for updating. +Parameter: targetParameterIter, List, optional - Contains a list of form field names whose values will be passed to the lookup window. +Parameter: imgSrc, Not used. +Parameter: ajaxUrl, String, optional - Contains the Ajax URL, used only when the ajaxEnabled parameter contains true. +Parameter: ajaxEnabled, boolean, optional - If true, invokes the Ajax auto-completer. +Parameter: presentation, String, optional - Contains the lookup window type, either "layer" or "window". +Parameter: width, String or Integer, optional - The width of the lookup field. +Parameter: height, String or Integer, optional - The height of the lookup field. +Parameter: position, String, optional - The position style of the lookup field. +Parameter: fadeBackground, ? +Parameter: clearText, String, optional - If the readonly parameter is true, clearText contains the text to be displayed in the field, default is CommonClear label. +Parameter: showDescription, String, optional - If the showDescription parameter is true, a special span with css class "tooltip" will be created at right of the lookup button and a description will fill in (see setLookDescription in selectall.js). For now not when the lookup is read only. +Parameter: initiallyCollapsed, Not used. +Parameter: lastViewName, String, optional - If the ajaxEnabled parameter is true, the contents of lastViewName will be appended to the Ajax URL. +--> +<#macro renderLookupField name formName fieldFormName className="" alert="false" value="" size="" maxlength="" id="" event="" action="" readonly=false autocomplete="" descriptionFieldName="" targetParameterIter="" imgSrc="" ajaxUrl="" ajaxEnabled=javaScriptEnabled presentation="layer" width="" height="" position="" fadeBackground="true" clearText="" showDescription="" initiallyCollapsed="" lastViewName="main" > + <#if Static["org.ofbiz.widget.ModelWidget"].widgetBoundaryCommentsEnabled(context)> + + + <#if (!ajaxUrl?has_content) && ajaxEnabled?has_content && ajaxEnabled> + <#local ajaxUrl = requestAttributes._REQUEST_HANDLER_.makeLink(request, response, fieldFormName)/> + <#local ajaxUrl = id + "," + ajaxUrl + ",ajaxLookup=Y" /> + + <#if (!showDescription?has_content)> + <#local showDescriptionProp = Static["org.ofbiz.base.util.UtilProperties"].getPropertyValue("widget.properties", "widget.lookup.showDescription", "N")> + <#if "Y" == showDescriptionProp> + <#local showDescription = "true" /> + <#else> + <#local showDescription = "false" /> + + + <#if ajaxEnabled?has_content && ajaxEnabled> + + + + <#if size?has_content && size=="0"> + name="${name}"/> + <#else> + <#if name?has_content> name="${name}"<#if value?has_content> value="${value}" + <#if size?has_content> size="${size}"<#if maxlength?has_content> maxlength="${maxlength}"<#if id?has_content> id="${id}"<#rt/> + <#if readonly?has_content && readonly> readonly="readonly"<#rt/><#if event?has_content && action?has_content> ${event}="${action}"<#rt/> + <#if autocomplete?has_content> autocomplete="off"/><#rt/> + + <#if presentation?has_content && descriptionFieldName?has_content && presentation == "window"> + <#rt> + <#elseif presentation?has_content && presentation == "window"> + <#rt> + <#else> + <#if ajaxEnabled?has_content && ajaxEnabled> + <#assign defaultMinLength = Static["org.ofbiz.base.util.UtilProperties"].getPropertyValue("widget.properties", "widget.autocompleter.defaultMinLength")> + <#assign defaultDelay = Static["org.ofbiz.base.util.UtilProperties"].getPropertyValue("widget.properties", "widget.autocompleter.defaultDelay")> + <#local ajaxUrl = ajaxUrl + "&_LAST_VIEW_NAME_=" + lastViewName /> + <#if !ajaxUrl?contains("searchValueFieldName=")> + <#if descriptionFieldName?has_content && showDescription == "true"> + <#local ajaxUrl = ajaxUrl + "&searchValueFieldName=" + descriptionFieldName /> + <#else> + <#local ajaxUrl = ajaxUrl + "&searchValueFieldName=" + name /> + + + + <#assign modalId = "${id}-Modal"> + <#assign fieldName = "${name}"> + + + + <#if readonly?has_content && readonly> + + <#if clearText?has_content>${clearText}<#else>${uiLabelMap.CommonClear} + + + + + + + <#if ajaxEnabled?has_content && ajaxEnabled && (presentation?has_content && presentation == "window")> + <#if ajaxUrl?index_of("_LAST_VIEW_NAME_") < 0> + <#local ajaxUrl = ajaxUrl + "&_LAST_VIEW_NAME_=" + lastViewName /> + + <#t/> + + + + +<#macro renderNextPrev paginateStyle paginateFirstStyle viewIndex highIndex listSize viewSize ajaxEnabled javaScriptEnabled ajaxFirstUrl firstUrl paginateFirstLabel paginatePreviousStyle ajaxPreviousUrl previousUrl paginatePreviousLabel pageLabel ajaxSelectUrl selectUrl ajaxSelectSizeUrl selectSizeUrl commonDisplaying paginateNextStyle ajaxNextUrl nextUrl paginateNextLabel paginateLastStyle ajaxLastUrl lastUrl paginateLastLabel paginateViewSizeLabel> + <#if listSize gt viewSize> + + + + +<#macro renderFileField className alert name value size maxlength autocomplete> + <#if name?has_content> name="${name}"<#if value?has_content> value="${value}"<#if size?has_content> size="${size}"<#if maxlength?has_content> maxlength="${maxlength}"<#if autocomplete?has_content> autocomplete="off"/><#rt/> + +<#macro renderPasswordField className alert name value size maxlength id autocomplete> + <#if name?has_content> name="${name}"<#if value?has_content> value="${value}"<#if size?has_content> size="${size}"<#if maxlength?has_content> maxlength="${maxlength}"<#if id?has_content> id="${id}"<#if autocomplete?has_content> autocomplete="off"/> + +<#macro renderImageField value description alternate style event action> src="${value}"<#if description?has_content> title="${description}" alt="<#if alternate?has_content>${alternate}"<#if style?has_content> class="${style}"<#if event?has_content> ${event?html}="${action}" /> + +<#macro renderBanner style leftStyle rightStyle leftText text rightText> + + <#rt/> + <#if leftText?has_content><#rt/> + <#if text?has_content><#rt/> + <#if rightText?has_content><#rt/> + +
<#if leftStyle?has_content>
${leftText}<#if leftStyle?has_content>
<#if style?has_content>
${text}<#if style?has_content>
<#if rightStyle?has_content>
${rightText}<#if rightStyle?has_content>
+ + +<#macro renderContainerField id className>
+ +<#macro renderFieldGroupOpen style id title collapsed collapsibleAreaId collapsible expandToolTip collapseToolTip> + <#if style?has_content || id?has_content || title?has_content>
id="${id}"> +
+ <#if collapsible> + + <#else> + <#if title?has_content>${title} + <#rt/> +
+
style="display: none;"> + + + +<#macro renderFieldGroupClose style id title><#if style?has_content || id?has_content || title?has_content>
+ +<#macro renderHyperlinkTitle name title showSelectAll="N"> + <#if title?has_content>${title}
+ <#if showSelectAll="Y"> + + +<#macro renderSortField style title linkUrl ajaxEnabled tooltip=""> + class="${style}" href="<#if ajaxEnabled?has_content && ajaxEnabled>javascript:ajaxUpdateAreas('${linkUrl}')<#else>${linkUrl}"<#if tooltip?has_content> title="${tooltip}">${title} + + +<#macro formatBoundaryComment boundaryType widgetType widgetName> + +<#macro renderTooltip tooltip tooltipStyle> + <#if tooltip?has_content>${tooltip}<#rt/> + + +<#macro renderClass className="" alert=""> + <#if className?has_content || (alert?has_content && alert=="true")> class="${className}<#if alert?has_content && alert=="true"> alert" + + +<#macro renderAsterisks requiredField requiredStyle> + <#if requiredField=="true"><#if !requiredStyle?has_content>* + + +<#macro makeHiddenFormLinkForm actionUrl name parameters targetWindow> +
target="${targetWindow}" onsubmit="javascript:submitFormDisableSubmits(this)" name="${name}"> + <#list parameters as parameter> + + +
+ +<#macro makeHiddenFormLinkAnchor linkStyle hiddenFormName event action imgSrc description confirmation> + class="${linkStyle}" href="javascript:document.${hiddenFormName}.submit()" + <#if action?has_content && event?has_content> ${event}="${action}" + <#if confirmation?has_content> onclick="return confirm('${confirmation?js_string}')"> + <#if imgSrc?has_content>${description} + +<#macro makeHyperlinkString linkStyle hiddenFormName event action imgSrc title alternate linkUrl targetWindow description confirmation> + class="${linkStyle}" + href="${linkUrl}"<#if targetWindow?has_content> target="${targetWindow}" + <#if action?has_content && event?has_content> ${event}="${action}" + <#if confirmation?has_content> onclick="return confirm('${confirmation?js_string}')" + <#if imgSrc?length == 0 && title?has_content> title="${title}"> + <#if imgSrc?has_content>${alternate}${description} + diff --git a/themes/bootstrap/includes/templates/htmlMenuMacroLibrary.ftl b/themes/bootstrap/includes/templates/htmlMenuMacroLibrary.ftl new file mode 100644 index 00000000000..7e0dd2ab165 --- /dev/null +++ b/themes/bootstrap/includes/templates/htmlMenuMacroLibrary.ftl @@ -0,0 +1,90 @@ +<#-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> + +<#macro renderMenuBegin boundaryComment="" id="" style="" title=""> + <#if boundaryComment?has_content> + + + <#-- id="${id}"<#elseif style?has_content> class="${style}"> --> + <#if style == "button-bar tab-bar"> +
+<#macro renderContentBegin editRequest enableEditValue editContainerStyle><#if editRequest?has_content && enableEditValue == "true">
+<#macro renderContentBody> +<#macro renderContentEnd urlString editMode editContainerStyle editRequest enableEditValue> +<#if editRequest?? && enableEditValue == "true"> +<#if urlString??>${editMode}<#rt/> +<#if editContainerStyle??>
<#rt/> + + +<#macro renderSubContentBegin editContainerStyle editRequest enableEditValue><#if editRequest?? && enableEditValue == "true">
+<#macro renderSubContentBody> +<#macro renderSubContentEnd urlString editMode editContainerStyle editRequest enableEditValue> +<#if editRequest?? && enableEditValue == "true"> +<#if urlString??>${editMode}<#rt/> +<#if editContainerStyle??>
<#rt/> + + + +<#macro renderHorizontalSeparator id style> id="${id}"<#if style?has_content> class="${style}"/> + +<#macro renderLabel text id style> + <#if text?has_content> + <#-- If a label widget has one of the h1-h6 styles, then it is considered block level element. + Otherwise it is considered an inline element. --> + <#assign idText = ""/> + <#if id?has_content><#assign idText = " id=\"${id}\""/> + <#if style?has_content> + <#if style=="h1"> + ${text} + <#elseif style=="h2"> + ${text} + <#elseif style=="h3"> + ${text} + <#elseif style=="h4"> + ${text} + <#elseif style=="h5"> + ${text} + <#elseif style=="h6"> + ${text} + <#else> + ${text} + + <#else> + ${text} + + + + +<#macro renderLink parameterList targetWindow target uniqueItemName linkType actionUrl id style name height width linkUrl text imgStr> + <#if "ajax-window" != linkType> + <#if "hidden-form" == linkType> +
target="${targetWindow}" onsubmit="javascript:submitFormDisableSubmits(this)" name="${uniqueItemName}"><#rt/> + <#list parameterList as parameter> + <#rt/> + +
<#rt/> + + id="${id}" + <#if style?has_content>class="${style}" + <#if name?has_content>name="${name}" + <#if targetWindow?has_content>target="${targetWindow}" + href="<#if "hidden-form"==linkType>javascript:document.${uniqueItemName}.submit()<#else>${linkUrl}"><#rt/> + <#if imgStr?has_content>${imgStr}<#if text?has_content>${text} + + <#else> +
+ class="${style}"> + <#if text?has_content>${text} + + + + +<#macro renderImage src id style wid hgt border alt urlString> +<#if src?has_content> +id="${id}"<#if style?has_content> class="${style}"<#if wid?has_content> width="${wid}"<#if hgt?has_content> height="${hgt}"<#if border?has_content> border="${border}" alt="<#if alt?has_content>${alt}" src="${urlString}" /> + + + +<#macro renderContentFrame fullUrl width height border>