<?page id="p" title="Data Profiling Home" contentType="text/html;charset=UTF-8"?>
<zk>
<button label="Procesing" onClick="Clients.showBusy(null)"></button>
</zk>
OnClick of button I see this :
I want to Override the Processing widget so that I can acheive this.
I have searched, in ZK documentation but din't find any help, have any one tried this earlier or any hint,link or reference, can this be acheived In ZK?
Please try
<zk>
<button label="busy">
<attribute name="onClick">
busyWin.doModal();
Div div = busyWin.getFellow("div");
Clients.showBusy(div, null);
</attribute>
</button>
<window id="busyWin" visible="false" position="center"
border="normal" title="busy..." xmlns:w="client">
<attribute w:name="bind_">
function (desktop, skipper, after) {
this.$bind_(desktop, skipper, after);
if (this._drag)
this._drag.opts.ignoredrag = true; // prevent dragging
}
</attribute>
<hbox>
<div id="div" height="30px" width="30px" style="color: transparent;">a</div>
<button label="abort">
<attribute name="onClick">
Clients.clearBusy(div);
busyWin.setMode("embedded");
busyWin.setVisible(false);
</attribute>
</button>
</hbox>
</window>
</zk>
Edit:
The new sample
<zk>
<script type="text/javascript"><![CDATA[
function showBusy () {
// show busy mask
zAu.cmd0.showBusy('Loading...');
// move abort button under busy message
jq('.z-loading')[0].appendChild(jq('$abortButton')[0]);
}
function clearBusy () {
// move abort button back under abort div
jq('$abortDiv')[0].appendChild(jq('$abortButton')[0]);
// clear busy mask
zAu.cmd0.clearBusy(null);
}
]]></script>
<zscript><![CDATA[
class AbortableRunnable implements Runnable {
boolean aborted = false;
int i = 0;
public void run () {
while (true) {
// do somoething
i++;
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println(e);
}
// finish
if (i == 5 || aborted)
break;
}
}
public void abort () {
aborted = true;
}
public int getI () {
return i;
}
}
AbortableRunnable ar = new AbortableRunnable();
void start () {
// start
System.out.println("started");
new Thread(ar).start();
}
void abort () {
// abort
System.out.println("aborted");
ar.abort();
// reset
ar = new AbortableRunnable();
}
void finish () {
// finish
System.out.println("finished");
// reset
ar = new AbortableRunnable();
}
]]></zscript>
<!-- abort div to keep the abort button,
display outside the screen -->
<div id="abortDiv" style="position: absolute; left: -1000px; top: -1000px">
<button id="abortButton" label="abort">
<attribute name="onClick">
// abort the running process
abort();
// stop the checking timer
checkTimer.stop();
// move self element back to abort div
// and clear the busy mask
Clients.evalJavaScript("clearBusy();");
</attribute>
</button>
</div>
<button label="do something long">
<attribute name="onClick">
// start to run the process
start();
// start the checking timer
checkTimer.start();
// show busy mask and move
// the element of abort button under busy message
Clients.evalJavaScript("showBusy();");
</attribute>
</button>
<timer id="checkTimer" running="false" repeats="true" delay="1000">
<attribute name="onTimer">
// check whether it is finished
// similar to the abort part
if (ar.getI() == 5) {
finish();
self.stop();
Clients.evalJavaScript("clearBusy();");
}
</attribute>
</timer>
</zk>
Regards,
Ben
Related
I'm trying to create a compound view component in Xamarin Forms called FormElement which is composed of two labels and an Entry:
<?xml version="1.0" encoding="UTF-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:custom="clr-namespace:Mynamespace;assembly=Mynamespace"
x:Class="Mynamespace.Components.FormEntry">
<StackLayout Orientation="Horizontal">
<Label x:Name="formRequiredStar"
IsVisible="{Binding IsRequired}"
Text="*" TextColor="Red"
FontSize="15"
FontAttributes="Bold"
Margin="-12,0,0,0"
HorizontalOptions="Start" />
<Label x:Name="formLabel"
HorizontalOptions="Start"
Text="{Binding LabelText}"
TextColor="{Binding LabelTextColor}"
FontSize="{Binding LabelTextFontSize}"
FontAttributes="{Binding LabelTextFontStyle}" />
</StackLayout>
<Frame BorderColor="Black"
CornerRadius="7"
Padding="5,0"
Margin="0,-3,0,0"
HasShadow="false">
<Entry x:Name="mainEntry"
Keyboard="{Binding KeybdType}"
Placeholder="{Binding EntryPlaceHolder}"
TextColor="Black"
FontSize="Default"
HeightRequest="{Binding EntryHeight}" />
</Frame>
</StackLayout>
Next, I want to switch focus from the Entry to a "next" element when the user taps the DONE button, so I do:
namespace Mynamespace.Components
{
public partial class FormEntry : StackLayout
{
public VisualElement NextFocus
{
get { return (VisualElement)GetValue(NextFocusProperty); }
set { SetValue(NextFocusProperty, value); }
}
public static readonly BindableProperty NextFocusProperty =
BindableProperty.Create(nameof(NextFocus),
typeof(VisualElement),
typeof(FormEntry),
null,
Xamarin.Forms.BindingMode.OneWay);
public FormEntry()
{
InitializeComponent();
BindingContext = this;
mainEntry.Completed += (s, e) =>
{
if (NextFocus != null)
{
NextFocus.Focus();
}
};
}
}
}
Next, in order for a FormEntry to be the target of NextFocus, I tried adding
this.Focused += (s,e) => { mainEntry.Focus(); };
to the constructor, but the handler is never called, and I also tried overriding
public new void Focus() {
mainEntry.Focus();
}
but this method is never called. Layout classes are descended from VisualElement so they should inherit Focused. Is there something about Layout objects that I'm missing? I could understand that Layout objects aren't usually the target of focus, but the event handler is supposedly there so I ought to be able to use it.
Here's an example of how I utilize the FormEntry on a login screen:
<!-- Email -->
<controls:FormEntry x:Name="usernameEntry"
Margin="25,40,25,0"
IsRequired="true"
EntryHeight="40"
KeybdType="Email"
NextFocus="{x:Reference passwordEntry}"
LabelText="{il8n:Translate Emailorusername}"
EntryPlaceHolder="{il8n:Translate EnterUsername}">
</controls:FormEntry>
<!-- Password -->
<controls:FormEntry x:Name="passwordEntry"
Margin="25,0,25,0"
IsRequired="true"
EntryHeight="40"
LabelText="{il8n:Translate Password}"
EntryPlaceHolder="{il8n:Translate EnterPassword}" />
I think you have get the nextfocus element, you can get mainEntry from nextfocus, like this:
public FormEntry ()
{
InitializeComponent ();
BindingContext = this;
mainEntry.Completed += (s, e) =>
{
if (NextFocus != null)
{
FormEntry formentry = (FormEntry)NextFocus;
Entry entry = formentry.mainEntry;
entry.Focus();
}
};
}
Then you can find you will get focus.
Part of my application is recording the finish times of a race. Since this will most likely be done on a phone or tablet I would like to implement a small popup to easily modify the time without having to set the focus exactly and type it in. However having the time start as 00:00:00 for every finish time will make the process very laborious so I want to have it initialise to the last entered finish time. I want the popup to appear directly below the timebox, if times being entered are at the top of the grid, or above the timebox for times being entered which are at the bottom of the grid. Below is stripped down versions of my code which hopefully helps explain the concept.
My popup window: entertime.zul
<window viewModel="#id('vmtp') #init('EnterTimeVM')" onBlur="#command('close')">
<caption>
<toolbarbutton label="Save" onClick="#command('save')"/>
<toolbarbutton label="Cancel" onClick="#command('close')"/>
</caption>
<hlayout>
<vlayout>
<button label="+" onClick="#command('changeHours', amount='1')" />
<intbox value="#load(vmtp.hours)" readonly="true" />
<button label="-" onClick="#command('changeHours', amount='-1')" />
</vlayout>
<vlayout>
<button label="+" onClick="#command('changeMinutes', amount='1')" />
<intbox value="#load(vmtp.minutes)" readonly="true" />
<button label="-" onClick="#command('changeMinutes', amount='-1')" />
</vlayout>
<vlayout>
<button label="+" onClick="#command('changeSeconds', amount='1')" />
<intbox value="#load(vmtp.seconds)" readonly="true" />
<button label="-" onClick="#command('changeSeconds', amount='-1')" />
</vlayout>
</hlayout>
</window>
EnterTimeVM.java
public class EnterTimeVM {
private LocalDateTime ldt;
private Component view;
#Init
public void init(#ExecutionArgParam("initTime") LocalDateTime initTime,
#ContextParam(ContextType.VIEW) Component view) {
ldt = initTime;
this.view = view;
}
public int getHours() {
return ldt.getHour();
}
public int getMinutes() {
return ldt.getMinute();
}
public int getSeconds() {
return ldt.getSecond();
}
#Command
#NotifyChange("hours")
public void changeHours(#BindingParam("amount") int amount) {
ldt = ldt.plusHours(amount);
}
#Command
#NotifyChange({ "hours", "minutes" })
public void changeMinutes(#BindingParam("amount") int amount) {
ldt = ldt.plusMinutes(amount);
}
#Command
#NotifyChange({ "hours", "minutes", "seconds" })
public void changeSeconds(#BindingParam("amount") int amount) {
ldt = ldt.plusSeconds(amount);
}
#Command
public void save() {
Map<String, Object> args = new HashMap<>();
args.put("finishTime", ldt);
BindUtils.postGlobalCommand(null, null, "finishTime", args);
close();
}
#Command
public void close() {
view.detach();
}
}
Here is my main zul and view model.
timekeeper.zul (excess columns removed for brevity)
<window viewModel="#id('vmtk') #init('TimeKeeperVM')">
<grid model="#load(vmtk.competitors)">
<columns>
<column label="Name" />
<column label="Finish time" />
</columns>
<template name="model">
<row>
<label value="#load(each.name)" />
<timebox format="HH:mm:ss" value="#bind(each.finishTime)"
onFocus="#command('changeFinishTime', comp=each)" />
</row>
</template>
</grid>
</window>
Competitor.java
public class Competitor {
private String name;
private LocalDateTime finishTime;
// getters and setters
}
TimeKeeperVM.java
public class TimeKeeperVM {
private List<Competitor> competitors;
private Competitor selectedCompetitor;
private LocalDateTime prevFinishTime;
#Init
public void timeKeeperInit() {
prevInitTime = LocalDateTime.now();
}
public List<Competitor> getCompetitors() {
return competitors;
}
#Command
public void changeFinishTime(#BindingParam("comp") Competitor competitor,
#ContextParam(ContextType.COMPONENT) Component timebox) {
selectedCompetitor = competitor;
Map<String, Object> args = new HashMap<>();
LocalDateTime currentFinishTime = competitor.getFinishTime();
args.put("initTime", (currentFinishTime != null) ? currentFinishTime : prevFinishTime);
Window win = (Window) Executions.createComponents("entertime.zul", timebox.getParent(), args);
// Need to use the parent of timebox in this case
win.setPosition("parent,bottom,right"); // positions the popup relative to timebox parent, not timebox
win.doPopup();
}
#GlobalCommand
#NotifyChange("competitors")
public void finishTime(#BindingParam("finishTime") LocalDateTime finishTime) {
if (selectedCompetitor != null && finishTime != null) {
selectedCompetitor.setFinishTime(finishTime);
prevFinishTime = finishTime;
}
}
}
The code as I have it at the moment (i.e programatically create the popup - see changeFinishTime method) displays the popup but not in the ideal position. As per the zk popup demo I could generate the popup in the zul by having somewhere in the zul file:
<popup id="timepop">
<include src="entertime.zul" />
</popup>
and then displaying it by:
onFocus='timepop.open(self,#load(vm.popupPosition))'
The problem with this is that I can't pass args to entertime.zul. Also I can't modify the position of the popup as popupPosition will be resolved at render time; not runtime. This is the same problem if the include line (from above) is changed to:
<include initTime="#load(vm.prevFinishTime)" src="entertime.zul" />
initTime is initialised at render time; not runtime.
Any thoughts/advice greatly appreciated.
I would prefer to use the Executions.createComponents solution.
If the position of the modal win is the same for all the windows, I usually tag directly the position in window component:
<window viewModel="#id('vmtp') #init('EnterTimeVM')" onBlur="#command('close')" position="parent, bottom, right" width="100px">
instead of set it VM.
Then, did you try to remove the position? In my testing project with your code the popup is opened next the timebox.getParent().
With your code, the timebox.getParent is the component Row, so maybe there can be problems with row width, for example.
You can bypass the problem use a parent component before timebox like hbox.
<hbox>
<timebox format="HH:mm:ss" value="#bind(each.finishTime)" onFocus="#command('changeFinishTime', comp=each)" />
</hbox>
so that the parent result a little more usable.
I was hoping to position the popup relative to the row the popup is attached to. I didn't read the api of Window's setPosition properly. It says Position the window relative to its parent. That is, the left and top is an offset to his parent's left-top corner. But I can manipulate the position using session attributes:
#Command
public void changeFinishTime(#BindingParam("comp") Competitor competitor,
#ContextParam(ContextType.COMPONENT) Component timebox) {
selectedCompetitor = competitor;
// set args map
Window win = (Window) Executions.createComponents("entertime.zul", timebox.getParent(), args);
Sessions.getCurrent().setAttribute("top", "-20px");
win.doPopup();
}
And then change entertime.zul:
<window viewModel="#id('vmtp') #init('EnterTimeVM')" onBlur="#command('close')" position="parent" top="${sessionScope.top}" width="100px">
This solution is a little clunky and will have to look into how much of an issue it is if the font size changes but it does achieve what I want.
I could also remove all the positioning from the entertime.zul window element and do it in java:
Window win = (Window) Executions.createComponents("entertime.zul", timebox.getParent(), args);
win.setPosition("parent");
win.setTop("-20px");
win.doPopup();
I was wrote this code for showing button after scrolling is more than 500px, but "showButton" didn't get new value.
<ion-content (ionScroll)="onScroll($event)">
<button *ngIf="showButton">Scroll Top</button>
</ion-content>
my.ts file:
showButton= false;
onScroll($event) {
if ($event.scrollTop > 500) {
console.log(this.showButton);
this.showButton= true;
}
}
This console.log shows change of "showButton", but in html it doesn't change.
"showButton" for first time get value "false" but when value change to "true" it can not listen to change, how I can solve this?
From the ionic docs, Scroll Events Scroll events happen outside of
Angular's Zones. This is for performance reasons. So if you're trying
to bind a value to any scroll event, it will need to be wrapped in a
zone.run()
<ion-content (ionScroll)="onScroll($event)">
<button *ngIf="showButton">Scroll Top</button>
</ion-content>
//add import in .ts file
import { Component, NgZone } from '#angular/core';
//in constructor
constructor(
public zone: NgZone,
showButton= false;
onScroll($event) {
this.zone.run(() => {
if ($event.scrollTop > 500) {
console.log(this.showButton);
this.showButton = true;
}
})
}
//Method 1) use boolean variable
<ion-content (ionScroll)="onScroll($event)">
<button *ngIf="showButton">Scroll Top</button>
</ion-content>
showButton:boolean= false;
onScroll($event) {
if ($event.scrollTop > 500) {
console.log(this.showButton);
this.showButton= true;
}
}
OR
//Method 2) use number variable
<ion-content (ionScroll)="onScroll($event)">
<button *ngIf="showButton==1">Scroll Top</button>
</ion-content>
showButton:number= 0;
onScroll($event) {
if ($event.scrollTop > 500) {
console.log(this.showButton);
this.showButton= 1;
}
}
In my main page, i have a listview of all the items, and once user clicks on one of them, it will navigate to a detail page.
In the detail page, i create a last button to jump to last item,
<Button Content="Last" HorizontalAlignment="Center" >
<Interactivity:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="Click">
<Interactions:InvokeCommandAction Command="{x:Bind Path=ViewModel.LastCommand, Mode=OneWay}"/>
</Interactions:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
and here is part of my viewmodel for the page
class DetailPageViewModel : ViewModelBase
{
private MyItem item;
public MyItem Item
{
get { return item; }
set { SetProperty(ref item, value); }
}
public DetailPageViewModel()
{
LastCommand = new DelegateCommand(LastItemExecute, CanLastItemExecute);
LastCommand.ObservesProperty(() => Item);
}
private DelegateCommand lastCommand;
public DelegateCommand LastCommand
{
get { return lastCommand; }
set { SetProperty(ref lastCommand, value); }
}
private bool CanLastItemExecute()
{
if (Item.Index!= 1)
{
return true;
}
else
{
return false;
}
}
private void LastItemExecute()
{
Item= _context.Items.Single(p => p.Index== Item.Index- 1);
}
}
Everything works fine here, except that if i click on the first item in the listview, or jump from second item, the last button will not be disabled, click on it won't do anything though.
But i would like to disable the button if the detail page is showing the first item, any help plz?
But i would like to disable the button if the detail page is showing the first item.
Your "Last Button" is in the DetailPage, I don't know how you bind data to controls in this DetaiPage, but if you are using Mater/Detail pattern, you can refer to the official Master/detail sample, in the ItemViewModel model, there is a property Item_ID. My suggestion is that you can also add a ID properity into your data model for ListView in the Master page, so can the ID be passed within the selected Item to detail page after navigation.
Then in the DetailPageViewModel, you can get this ID and bind to the Button's IsEnable property with Converter:
<Page.Resources>
<local:ButtonEnableConverter x:Key="cvt" />
</Page.Resources>
...
<Button VerticalAlignment="Center" HorizontalAlignment="Center" Content="Last Item" Grid.Row="3"
IsEnabled="{x:Bind Item.ID, Mode=OneWay, Converter={StaticResource cvt}}">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:InvokeCommandAction Command="{Binding Path=LastCommand, Mode=OneWay}" />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
The code of ButtonEnableConverter is like this:
public class ButtonEnableConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var itemID = (int)value;
if (itemID != 0)
return true;
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Update:
I didn't wrote a full sample to test it, but it should be something like this:
<Button Content="Last Item" Grid.Row="1" HorizontalAlignment="Center" >
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding Item.ID, Mode=OneWay}" ComparisonCondition="NotEqual" Value="100">
<Core:ChangePropertyAction PropertyName="IsEnabled" Value="True"/>
</Core:DataTriggerBehavior>
<Core:DataTriggerBehavior Binding="{Binding Item.ID, Mode=OneWay}" ComparisonCondition="Equal" Value="100">
<Core:ChangePropertyAction PropertyName="IsEnabled" Value="False"/>
</Core:DataTriggerBehavior>
<Core:EventTriggerBehavior EventName="Click">
<Core:InvokeCommandAction Command="{Binding Path=LastCommand, Mode=OneWay}" />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
You can have a try.
I have a tab layout panel in my ui.xml :
<g:TabLayoutPanel ui:field="tabPanel" barHeight='30'>
<g:tab>
<g:header size='7'>tab1</g:header>
<g:SimplePanel ui:field="tab1" height="100%"/>
</g:tab>
<g:tab>
<g:header size='7'>tab2</g:header>
<g:SimplePanel ui:field="tab2" height="100%"/>
</g:tab>
</g:TabLayoutPanel>
how do I handle the event generated on clicking Tab2?
Handle the SelectionEvent<Integer> or BeforeSelectionEvent<Integer> depending on your requirements.
e.g:
tabPanel.addSelectionHandler(new SelectionHandler<Integer>() {
#Override
public void onSelection(SelectionEvent<Integer> event) {
if (event.getSelectedItem() == 1) {
// Code
}
}
});
or:
#UiHandler("tabPanel")
void onTabSelection(SelectionEvent<Integer> event) {
if (event.getSelectedItem() == 1) {
// Code
}
}