Template Examples - Toggle Switch"

From Documentation
m (correct highlight (via JWB))
 
(48 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
{{Template:Smalltalk_Author|
 
{{Template:Smalltalk_Author|
 
|author=Robert Wenzel, Engineer, Potix Corporation
 
|author=Robert Wenzel, Engineer, Potix Corporation
|date=May 2017
+
|date=June 1, 2017
 
|version=ZK 8.0
 
|version=ZK 8.0
 
}}
 
}}
 +
 +
Styling example adapted from: http://callmenick.com/_development/css-toggle-switch/
  
 
= Introduction =
 
= Introduction =
  
[[File:template-examples-css-toggle-switch.png | right]]
+
The web is full of html5/css based layout examples ... e.g. this: [http://callmenick.com/post/css-toggle-switch-examples css-toggle-switch-examples]
 
 
The web is full of html5/css based layout examples ...
 
  
e.g. this: [http://callmenick.com/post/css-toggle-switch-examples css-toggle-switch-examples]
+
[[File:template-examples-css-toggle-switch.gif | center]]
  
In case you wonder how to integrate this or similar examples in ZK, this article tries to guide through simple and more advanced approaches.
+
The author of the example explains in detail how the styles work so I'll not repeat that here and focus instead on how to integrate this or similar examples into a ZK application. This article tries to guide through simple and more advanced approaches. To start with the simple one first:
  
 
= Using the original markup and styles =
 
= Using the original markup and styles =
Line 31: Line 31:
 
</source>
 
</source>
  
ZK's xhtml component set can be combined with ZUL components - using the xhtml namespace '''LINKME'''.
+
ZK's [[ZK_Developer's_Reference/UI_Patterns/HTML_Tags/The_XHTML_Component_Set | xhtml component set]] can be combined with ZUL components - using the [[ZUML_Reference/ZUML/Languages/XHTML | xhtml namespace]]. ('''Note:''' the xhtml namespace requires an optional jar file - zhtml.jar - which needs to be added to the maven/gradle dependencies)
  
'''LINKME source file:'''
+
;[https://github.com/zkoss-demo/zk-template-examples/blob/toggle-switch/src/main/webapp/css-toggle-switch/cmn-toggle-original.zul cmn-toggle-original.zul]
 
<source lang="xml">
 
<source lang="xml">
 
<zk xmlns:x="xhtml">
 
<zk xmlns:x="xhtml">
Line 57: Line 57:
 
</source>
 
</source>
  
There you are.
+
There you are. Layout integrated!?
 +
 
 +
Read on there's more.
  
 
= Streamlining with templates =
 
= Streamlining with templates =
  
Assume there were no surprises in the previous paragraph, it only looks a bit repetitive. Let's make our lives a little easier writing less code using a template, for the actual toggle switch.
+
I assume there were no surprises in the previous paragraph, it only looks a bit repetitive. Let's make our lives a little easier writing less code using a template, for the actual toggle switch.
  
'''LINKME source file:'''
+
;[https://github.com/zkoss-demo/zk-template-examples/blob/toggle-switch/src/main/webapp/css-toggle-switch/template/cmn-toggle-template-xhtml.zul template/cmn-toggle-template-xhtml.zul]
<source lang="xml" high="3,4">
+
<source lang="xml" highlight="3,4">
 
<zk xmlns:x="xhtml">
 
<zk xmlns:x="xhtml">
 
<x:div class="switch">
 
<x:div class="switch">
Line 72: Line 74:
 
</zk></zk>
 
</zk></zk>
 
</source>
 
</source>
* '''Line 3:''' Avoiding the whitespace to keep both nodes direct siblings otherwise there would be a Text containing whitespace between them
+
* '''Line 3:''' Avoiding the whitespace to keep both nodes direct siblings - otherwise there would be a Text containing whitespace between them.
  
As xhtml elements create a server side component for each usage this can be further optimized using native elements for the non dynamic surrounding element and the static label. Only the input remains a zk component available at server side as we are only interested in the actual value.
+
As xhtml elements create a server side component for each element this can be further optimized using [[ZK_Developer's_Reference/UI_Patterns/HTML_Tags/The_native_Namespace | native elements]] (of the [[ZUML_Reference/ZUML/Namespaces/Native | native namespace]]) for the static surrounding div element and label. Only the <input>-element remains a xhtml component which is available at server side because we might be interested in it's checked/unchecked state.
  
<source lang="xml" high="4">
+
;[https://github.com/zkoss-demo/zk-template-examples/blob/toggle-switch/src/main/webapp/css-toggle-switch/template/cmn-toggle-template.zul template/cmn-toggle-template.zul]
 +
<source lang="xml" highlight="4">
 
<zk xmlns:x="xhtml" xmlns:n="native">
 
<zk xmlns:x="xhtml" xmlns:n="native">
 
<n:div class="switch">
 
<n:div class="switch">
Line 85: Line 88:
 
</source>
 
</source>
  
* '''Line 4:''' Seems weird at first: Since the native elements optimize by joining into a single component, the n:label gets combined with the surrounding n:div leaving the input the firstChild of the combined surrounding element (just a little trick to avoid having to hard code IDs)
+
* '''Line 4:''' Seems weird at first: Since the native elements are optimized by joining them into a single component, the <n:label> gets combined with the surrounding <n:div>, leaving the input the firstChild of the combined surrounding element (just a little trick to avoid having to hard code IDs.)
  
Once we have a template we can declare and use it in our page layout as often as needed.
+
Once we have a template we can declare and use it in our page layout as often as needed. While both templates will produce the same DOM elements, the second one will be more efficient and consume less memory (at the cost of being mainly static).
  
'''LINKME source file:'''
+
;[https://github.com/zkoss-demo/zk-template-examples/blob/toggle-switch/src/main/webapp/css-toggle-switch/cmn-toggle-original-with-template.zul cmn-toggle-original-with-template.zul]
 
<source lang="xml">
 
<source lang="xml">
<?component name="toggle" templateURI="template/cmn-toggle-template.zul"?>
+
<?component name="toggle" templateURI="template/cmn-toggle-template-xhtml.zul"?>
  
 
<zk xmlns:x="xhtml">
 
<zk xmlns:x="xhtml">
Line 108: Line 111:
 
</source>
 
</source>
  
Or even combine with an inline template to apply the settingsRow multiple times with different parameters:
+
Defined as an inline template, the "settingsRow" can be applied multiple times with different parameters to save a few more lines of code:
  
'''LINKME source file:'''
+
;[https://github.com/zkoss-demo/zk-template-examples/blob/toggle-switch/src/main/webapp/css-toggle-switch/cmn-toggle-original-with-template-even-less.zul cmn-toggle-original-with-template-even-less.zul]
 
<source lang="xml">
 
<source lang="xml">
 
<?component name="toggle" templateURI="template/cmn-toggle-template.zul"?>
 
<?component name="toggle" templateURI="template/cmn-toggle-template.zul"?>
Line 134: Line 137:
 
= Customize ZK's <checkbox> component =
 
= Customize ZK's <checkbox> component =
  
In this case we are lucky and the generated HTML markup structure for a ZK checkbox almost matches the css styles provide.
+
In this case we are lucky: the generated HTML markup structure for a ZK checkbox almost matches the css styles provided by the cmn-toggle example. With a few adjustments ZK's default checkbox can look the same and provide almost all features (except for the dynamic yes/no labels).
With a few adjustments ZK's default checkbox can look the same and provide almost all features (except for the dynamic yes/no labels).
+
 
 +
Original HTML suggested by cmn-toggle:
 +
<source lang="html" highlight="1">
 +
<div class="switch">
 +
<input id="cmn-toggle-1" class="cmn-toggle cmn-toggle-round" type="checkbox">
 +
<label for="cmn-toggle-1"></label>
 +
</div>
 +
</source>
 +
* '''Line 1:''' same DOM structure mentioned [[#Using the original markup and styles | above]]
  
ZK:
+
By default ZK will generate this HTML for a checkbox:
 
<source lang="html">
 
<source lang="html">
 
<span id="i8iY9" class="z-checkbox">
 
<span id="i8iY9" class="z-checkbox">
Line 145: Line 156:
 
</source>
 
</source>
  
cmn-toggle:
+
After adding a zclass and sclass ...
<source lang="html">
 
<div class="switch">
 
<input id="cmn-toggle-1" class="cmn-toggle cmn-toggle-round" type="checkbox">
 
<label for="cmn-toggle-1"></label>
 
</div>
 
</source>
 
 
 
After adding a zclass/sclass like this:
 
  
 
<source lang="xml">
 
<source lang="xml">
Line 159: Line 162:
 
</source>
 
</source>
  
We get this:
+
... ZK will generate the following HTML elements:
  
 
<source lang="html">
 
<source lang="html">
Line 168: Line 171:
 
</source>
 
</source>
  
Now the cmn-toggle styles require only little adjustment to fit this structure ('''LINKME''') (this is not a CSS tutorial so I'll spare you the details) and then we can build the same settings UI even without the cmn-toggle-template.zul.
+
Notice how the style class cmn-toggle moved from input element to the surrounding span element.
 +
 
 +
Because of that the original cmn-toggle styles require a little adjustment to fit this structure (resulting in [https://github.com/zkoss-demo/zk-template-examples/blob/toggle-switch/src/main/webapp/css-toggle-switch/css/cmn-toggle-for-zk-checkbox.css cmn-toggle-for-zk-checkbox.css]).
 +
As this is not a CSS tutorial so I'll spare you the details. Below just a simple example of what kind of changes are needed:
 +
 
 +
;[https://github.com/zkoss-demo/zk-template-examples/blob/toggle-switch/src/main/webapp/css-toggle-switch/css/cmn-toggle-original.css#L30 css/cmn-toggle-original.css]
 +
<source lang="css" highlight="1, 6">
 +
.cmn-toggle {
 +
  position: absolute;
 +
  margin-left: -9999px;
 +
  visibility: hidden;
 +
}
 +
.cmn-toggle + label {
 +
  display: block;
 +
  position: relative;
 +
...
 +
</source>
 +
 
 +
;[https://github.com/zkoss-demo/zk-template-examples/blob/toggle-switch/src/main/webapp/css-toggle-switch/css/cmn-toggle-for-zk-checkbox.css#L21 css/cmn-toggle-for-zk-checkbox.css]
 +
<source lang="css" highlight="1, 6">
 +
.cmn-toggle > input {
 +
  position: absolute;
 +
  margin-left: -9999px;
 +
  visibility: hidden;
 +
}
 +
.cmn-toggle > label {
 +
  display: block;
 +
  position: relative;
 +
...
 +
</source>
 +
 
 +
Most changes reuse the existing styles and only the css-selectors are changed to reflect which DOM elements actually have the style classes.
 +
 
 +
Now we can build the same UI even without an additional external template as cmn-toggle-template.zul. Still the inline template helps to avoid repeating the layout markup within the our page.
  
<source lang="xml" high="11">
+
<source lang="xml" highlight="11">
 
<zk xmlns:n="native">
 
<zk xmlns:n="native">
 
<div sclass="settings">
 
<div sclass="settings">
Line 188: Line 224:
 
</source>
 
</source>
  
Without changing ZK's markup structure we can't use the data-on/-off attributes directly. Instead we can define additional css classes for different labels. If that's too limiting it is still possible to provide a custom mold '''LINKME''' to adapt the ZK checkbox to render the same markup as required by the cmn-toggle-switch.
+
Without changing ZK's markup structure we can't use the data-on/-off attributes (which define alternative labels or font icons) directly.
 +
Instead we can define additional css classes (e.g. the '''thumbs''' and '''large-icon''' class) to specify a different content within our CSS.
 +
 
 +
<source lang="css">
 +
.cmn-toggle-yes-no.large-icon > label:before,
 +
.cmn-toggle-yes-no.large-icon > label:after {
 +
  font-family: FontAwesome;
 +
  font-size: 50px;
 +
}
 +
 
 +
.cmn-toggle-yes-no.thumbs > label:before {
 +
  content: '\f088';
 +
}
 +
.cmn-toggle-yes-no.thumbs > label:after {
 +
  content: '\f087';
 +
}
 +
</source>
 +
 
 +
The codes '\f087' and '\f088' represent the character codes of the font-awesome icons [http://fontawesome.io/icon/thumbs-o-up/ thumbs-o-up] and [http://fontawesome.io/icon/thumbs-o-down/ thumbs-o-down]
 +
 
 +
If that's too limiting it is always possible to [[ZK_Component_Development_Essentials/Creating_a_simple_ZK_Component/Rendering_Widgets/Implementing_Molds | implement a custom mold]] to render the ZK checkbox using the same markup as required by the cmn-toggle-switch (If you are interested in this please let me know in the comments.)
  
 
= Summary =
 
= Summary =
  
As demonstrated above there are many options in ZK which you can choose based on your personal preference or experience. I hope you enjoyed this little smalltalk and I wish you happy styling.
+
As demonstrated above there are many options in ZK you can choose from depending on your requirements, personal preference or experience. I hope you enjoy this little smalltalk and I wish you happy styling.
  
 
== Example Sources ==
 
== Example Sources ==
Line 198: Line 254:
 
The code examples are available on github in the [https://github.com/zkoss-demo/zk-template-examples zk-template-examples repository]
 
The code examples are available on github in the [https://github.com/zkoss-demo/zk-template-examples zk-template-examples repository]
  
:zul files: https://github.com/zkoss-demo/zk-template-examples/tree/master/src/main/webapp/css-toggle-switch
+
:files: https://github.com/zkoss-demo/zk-template-examples/tree/toggle-switch/src/main/webapp/css-toggle-switch
 
 
:java classes: https://github.com/zkoss-demo/zk-template-examples/tree/master/src/main/java/zk/example/template/stepbar
 
  
 
== Running the Example ==
 
== Running the Example ==

Latest revision as of 04:31, 20 January 2022

DocumentationSmall Talks2017JuneTemplate Examples - Toggle Switch
Template Examples - Toggle Switch

Author
Robert Wenzel, Engineer, Potix Corporation
Date
June 1, 2017
Version
ZK 8.0

Styling example adapted from: http://callmenick.com/_development/css-toggle-switch/

Introduction

The web is full of html5/css based layout examples ... e.g. this: css-toggle-switch-examples

Template-examples-css-toggle-switch.gif

The author of the example explains in detail how the styles work so I'll not repeat that here and focus instead on how to integrate this or similar examples into a ZK application. This article tries to guide through simple and more advanced approaches. To start with the simple one first:

Using the original markup and styles

A very basic way to integrate a 3rd party layout is to re-use the markup as-is. Here the original source html example.

	<div class="settings">
		<div class="row">
			<div class="switch">
				<input id="cmn-toggle-1" class="cmn-toggle cmn-toggle-round" type="checkbox">
				<label for="cmn-toggle-1"></label>
			</div>
		</div>
...
	</div>

ZK's xhtml component set can be combined with ZUL components - using the xhtml namespace. (Note: the xhtml namespace requires an optional jar file - zhtml.jar - which needs to be added to the maven/gradle dependencies)

cmn-toggle-original.zul
<zk xmlns:x="xhtml">
	<div sclass="settings"><!-- zul-div -->
		<x:div class="row"><!-- xhtml-div -->
			<x:div class="question" textContent="Enable Cookies" />
			<x:div class="switch">
				<x:input id="cmn-toggle-1" class="cmn-toggle cmn-toggle-round" type="checkbox" checked="true" />
				<x:label for="cmn-toggle-1" />
			</x:div>
		</x:div>

		<x:div class="row">
			<x:div class="question" textContent="Share Location" />
			<x:div class="switch">
				<x:input id="cmn-toggle-2" class="cmn-toggle cmn-toggle-round-flat" type="checkbox" />
				<x:label for="cmn-toggle-2" />
			</x:div>
		</x:div>
...
	</div>
</zk>

There you are. Layout integrated!?

Read on there's more.

Streamlining with templates

I assume there were no surprises in the previous paragraph, it only looks a bit repetitive. Let's make our lives a little easier writing less code using a template, for the actual toggle switch.

template/cmn-toggle-template-xhtml.zul
<zk xmlns:x="xhtml">
	<x:div class="switch">
		<x:input class="cmn-toggle cmn-toggle-${toggleClass}" type="checkbox" checked="${checked}" /><!-- no whitespace
	 --><x:label for="${self.previousSibling.uuid}" data-on="${labelOn}" data-off="${labelOff}" />
	</x:div>
</zk></zk>
  • Line 3: Avoiding the whitespace to keep both nodes direct siblings - otherwise there would be a Text containing whitespace between them.

As xhtml elements create a server side component for each element this can be further optimized using native elements (of the native namespace) for the static surrounding div element and label. Only the <input>-element remains a xhtml component which is available at server side because we might be interested in it's checked/unchecked state.

template/cmn-toggle-template.zul
<zk xmlns:x="xhtml" xmlns:n="native">
	<n:div class="switch">
		<x:input class="cmn-toggle cmn-toggle-${toggleClass}" type="checkbox" checked="${checked}"/>
		<n:label for="${self.firstChild.uuid}" data-on="${labelOn}" data-off="${labelOff}" />
	</n:div>
</zk>
  • Line 4: Seems weird at first: Since the native elements are optimized by joining them into a single component, the <n:label> gets combined with the surrounding <n:div>, leaving the input the firstChild of the combined surrounding element (just a little trick to avoid having to hard code IDs.)

Once we have a template we can declare and use it in our page layout as often as needed. While both templates will produce the same DOM elements, the second one will be more efficient and consume less memory (at the cost of being mainly static).

cmn-toggle-original-with-template.zul
<?component name="toggle" templateURI="template/cmn-toggle-template-xhtml.zul"?>

<zk xmlns:x="xhtml">
	<div sclass="settings">
		<x:div class="row">
			<x:div class="question" textContent="Enable Cookies"/>
			<toggle toggleClass="round" checked="true"/>
		</x:div>
	
		<x:div class="row">
			<x:div class="question" textContent="Share Location"/>
			<toggle toggleClass="round-flat" />
		</x:div>
...
	</div>

Defined as an inline template, the "settingsRow" can be applied multiple times with different parameters to save a few more lines of code:

cmn-toggle-original-with-template-even-less.zul
<?component name="toggle" templateURI="template/cmn-toggle-template.zul"?>

<zk xmlns:x="xhtml" xmlns:n="native">
	<div sclass="settings">
		<apply template="settingsRow" question="Enable Cookies" toggleClass="round" checked="true"/>
		<apply template="settingsRow" question="Share Location" toggleClass="round-flat"/>
...
		
		<template name="settingsRow">
			<n:div class="row">
				<n:div class="question">${question}</n:div>
				<toggle/><!-- inherits the parameters passed into the settingsRow template -->
			</n:div>
		</template>
	</div>
</zk>

It won't get much shorter ... or does it?

Customize ZK's <checkbox> component

In this case we are lucky: the generated HTML markup structure for a ZK checkbox almost matches the css styles provided by the cmn-toggle example. With a few adjustments ZK's default checkbox can look the same and provide almost all features (except for the dynamic yes/no labels).

Original HTML suggested by cmn-toggle:

	<div class="switch">
		<input id="cmn-toggle-1" class="cmn-toggle cmn-toggle-round" type="checkbox">
		<label for="cmn-toggle-1"></label>
	</div>
  • Line 1: same DOM structure mentioned above

By default ZK will generate this HTML for a checkbox:

	<span id="i8iY9" class="z-checkbox">
		<input type="checkbox" id="i8iY9-real">
		<label for="i8iY9-real" id="i8iY9-cnt" class="z-checkbox-content"></label>
	</span>

After adding a zclass and sclass ...

	<checkbox zclass="cmn-toggle" sclass="switch cmn-toggle-round"/>

... ZK will generate the following HTML elements:

	<span id="nECY2" class="switch cmn-toggle-round cmn-toggle">
		<input type="checkbox" id="nECY2-real" checked="checked">
		<label for="nECY2-real" id="nECY2-cnt" class="cmn-toggle-content"></label>
	</span>

Notice how the style class cmn-toggle moved from input element to the surrounding span element.

Because of that the original cmn-toggle styles require a little adjustment to fit this structure (resulting in cmn-toggle-for-zk-checkbox.css). As this is not a CSS tutorial so I'll spare you the details. Below just a simple example of what kind of changes are needed:

css/cmn-toggle-original.css
.cmn-toggle {
  position: absolute;
  margin-left: -9999px;
  visibility: hidden;
}
.cmn-toggle + label {
  display: block;
  position: relative;
...
css/cmn-toggle-for-zk-checkbox.css
.cmn-toggle > input {
  position: absolute;
  margin-left: -9999px;
  visibility: hidden;
}
.cmn-toggle > label {
  display: block;
  position: relative;
...

Most changes reuse the existing styles and only the css-selectors are changed to reflect which DOM elements actually have the style classes.

Now we can build the same UI even without an additional external template as cmn-toggle-template.zul. Still the inline template helps to avoid repeating the layout markup within the our page.

<zk xmlns:n="native">
	<div sclass="settings">
		<apply template="settingsRow" question="Enable Cookies" toggleClass="round" checked="true"/>
		<apply template="settingsRow" question="Share Location" toggleClass="round-flat"/>
		<apply template="settingsRow" question="Do you agree?" toggleClass="yes-no" />
		<apply template="settingsRow" question="Like it?" toggleClass="yes-no large-icon thumbs" checked="true"/>
		
		<template name="settingsRow">
			<n:div class="row">
				<n:div class="question">${question}</n:div>
				<checkbox zclass="cmn-toggle" sclass="switch cmn-toggle-${toggleClass}" checked="${checked}"/>
			</n:div>
		</template>
	</div>
</zk>

Without changing ZK's markup structure we can't use the data-on/-off attributes (which define alternative labels or font icons) directly. Instead we can define additional css classes (e.g. the thumbs and large-icon class) to specify a different content within our CSS.

.cmn-toggle-yes-no.large-icon > label:before,
.cmn-toggle-yes-no.large-icon > label:after {
  font-family: FontAwesome;
  font-size: 50px;
}

.cmn-toggle-yes-no.thumbs > label:before {
  content: '\f088';
}
.cmn-toggle-yes-no.thumbs > label:after {
  content: '\f087';
}

The codes '\f087' and '\f088' represent the character codes of the font-awesome icons thumbs-o-up and thumbs-o-down

If that's too limiting it is always possible to implement a custom mold to render the ZK checkbox using the same markup as required by the cmn-toggle-switch (If you are interested in this please let me know in the comments.)

Summary

As demonstrated above there are many options in ZK you can choose from depending on your requirements, personal preference or experience. I hope you enjoy this little smalltalk and I wish you happy styling.

Example Sources

The code examples are available on github in the zk-template-examples repository

files: https://github.com/zkoss-demo/zk-template-examples/tree/toggle-switch/src/main/webapp/css-toggle-switch

Running the Example

Clone the repo

   git clone [email protected]:zkoss-demo/zk-template-examples.git

The example war file can be built using the gradle-wrapper (on windows simply omit the prefix './'):

   ./gradlew war

Execute using jetty:

   ./gradlew appRun

Then access the example http://localhost:8080/zk-template-examples/css-toggle-switch/


Comments



Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.