Template Examples - Toggle Switch"

From Documentation
Line 78: Line 78:
 
* '''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.
  
 +
;[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" high="4">
 
<source lang="xml" high="4">
 
<zk xmlns:x="xhtml" xmlns:n="native">
 
<zk xmlns:x="xhtml" xmlns:n="native">
Line 89: Line 90:
 
</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 112: Line 113:
 
</source>
 
</source>
  
Or even combine with an inline template to apply the settingsRow multiple times with different parameters:
+
Defined as an inline template we can apply the settingsRow multiple times with different parameters saving 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"?>

Revision as of 02:44, 19 May 2017

DocumentationSmall Talks2017JuneTemplate Examples - Toggle Switch
Template Examples - Toggle Switch

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

Introduction

Template-examples-css-toggle-switch.png

The web is full of html5/css based layout examples ...

e.g. this: css-toggle-switch-examples

In case you wonder how to integrate this or similar examples into a ZK application, this article tries to guide through simple and more advanced approaches.


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 require 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 we can apply the settingsRow multiple times with different parameters saving 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 and the generated HTML markup structure for a ZK checkbox almost matches the css styles provide. With a few adjustments ZK's default checkbox can look the same and provide almost all features (except for the dynamic yes/no labels).

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: #Using the original markup and styles FIXME

HTML generated by ZK:

	<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/sclass like this:

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

ZK will generate the folloing HTML:

	<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>

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.

<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 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.

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 enjoyed 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.