0

Can "processing" spinner behavior DEFAULT to making entire screen ALWAYS modal ?

asked 2012-07-03 14:24:19 +0800

rickcr gravatar image rickcr
704 7

I'm working doing things the MVVM way (at least trying to) and currently most of my ViewModels kick of various ajax requests to return data which causes the "processing" dialog to appear.

What I'd love is if I could get the default behavior of the processing dialog to always make my entire screen modal. To do this manually all the time per different windows/components seems a bit tedious and I've posted about my initial attempts with things here http://www.zkoss.org/forum/listComment/19544-ZK6-Handling-a-long-process-event-with-ViewModel-docs-seem-a-bit-off-as-well and and Dennis has some solutions on github (referenced in thread above.)

I've found out how I can center the processing spinner with css, but I'm unable to figure out a way that I could default its behavior to always cause the entire window to become modal? If I could get this to work, I wouldn't really need to anything special as currently the 'processing' dialog is showing up by default under the circumstances that it needs to without me having to code for it.

Is what I'm asking for possible? Or is there some kind of global listener I could set up that will achieve what I want? [ Most of the time I'd think when something is "processing" you don't want the user to be able to click on other things, so to me that's what I'd prefer the default behavior to be.]

delete flag offensive retag edit

6 Replies

Sort by ยป oldest newest

answered 2012-07-09 07:14:00 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi rickcr,

You can override the default action in /WEB-INF/zk.xml as below:

<zk>
	<device-config>
		<device-type>ajax</device-type>
			<embed><![CDATA[
				<script type="text/javascript">
					zk.afterLoad("zk", function () {
						// store the old functions
						var oldShowBusy = zAu.cmd0.showBusy;
						var oldClearBusy = zAu.cmd0.clearBusy;
						zAu.cmd0.showBusy = function (uuid, msg) {
							if (arguments.length == 2) {
								oldShowBusy(null, msg);
							} else
								oldShowBusy.apply(this, arguments);
						};
						zAu.cmd0.clearBusy = function (uuid) {
							oldClearBusy(null);
						}
					});
				</script>
		]]></embed>
	</device-config>
</zk>

Then test with the fragment below, you will see whole window is covered when you click any button.

<zk>
	<label id="lb" value="test label" />
	<button label="busy on page">
		<attribute name="onClick">
			Clients.showBusy("busy...");
			tmOne.start();
		</attribute>
	</button>
	<!-- Show busy on label 'lb' and clear it after 3 seconds -->
	<button label="busy on listbox">
		<attribute name="onClick">
			Clients.showBusy(lb, "busy...");
			tmTwo.start();
		</attribute>
	</button>
	<timer id="tmOne" delay="3000" repeats="false" running="false" onTimer="Clients.clearBusy();" />
	<timer id="tmTwo" delay="3000" repeats="false" running="false" onTimer="Clients.clearBusy(lb);" />
</zk>

Regards,
Ben

link publish delete flag offensive edit

answered 2012-07-09 15:20:47 +0800

rickcr gravatar image rickcr
704 7

Thanks Ben this works great IF it's based off a button (or other UI item) for a direct call to showBusy() like you've shown.

I can't seem to get it to work by default for when my View Models are causing the busy dialog to show up baed on a change of a bound collection. Is there a different device type that I need to associate it with in my zk.xml?

If I add an alert in your zk.afterLoad it never shows up for cases where my view model triggers the load that causes the show busy to show up.

I'm not aware of all that is going on 'under the hood' in the internals of Zk, but to be more specific... I have listboxes backed by view models.

On the zul there are lists like...

<listbox model="@bind(vm.categories)" selectedItems="@bind(vm.selectedCategories)" ... >

When something causes the 'categories' to change backed in the view model (like after a search operation), I'll get the processing dialog, but it's not firing the ajax script for afterLoad so therefore the modal affect is not applied.

Any suggestions how to handle this? Thanks again.

link publish delete flag offensive edit

answered 2012-07-13 08:27:00 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi,

You can change the 'script' as the fragment below to override the progress mask:

	<script type="text/javascript">
		zk.afterLoad("zk", function () {
			var oldProgressbox = zUtl.progressbox;
			zUtl.progressbox = function () {
				oldProgressbox.apply(this, arguments);
				var $mask = jq('.z-loading');
				if ($mask) {
					var $img = jq('.z-loading-indicator'),
						$body = jq(document.body),
						body = $body[0],
						bw = $body.width() + body.scrollLeft - 10,
						bh = $body.height() + body.scrollTop - 10;

					// update mask and image's style
					$mask.width(bw);
					$mask.height(bh);

					$img.width('150px');
					$img.css('margin-left', (bw - $img.width()) / 2 + 'px');
					$img.css('margin-top', (bh - $img.height()) / 2 + 'px');

					// update mask size when window scroll
					if (!window.eventBinded) {
						var $win = jq(window);
						$win.scroll(function () {
							var $maskInst = jq('.z-loading');
							if ($maskInst[0]) {
								$maskInst.width(bw + $win.scrollLeft());
								$maskInst.height(bh + $win.scrollTop());
							}
						});
						window.eventBinded = true;
					}
				}
			}
		});
	</script>

Regards,
Ben

link publish delete flag offensive edit

answered 2012-07-13 13:14:02 +0800

rickcr gravatar image rickcr
704 7

Awesome Ben! Thanks so much!!!!

This should be in a wiki or the core documentation somewhere for sure (if it is my apologies).

In my opinion, this should be the default behavior of "processing," since typically I don't think you want the user to be able to click around while processing is taking place (and if you do, it's usually when you control the dialog to appear in a specific listbox not in the 'general sense' that the default behavior provides out-of-the-box with zk .)

(Side note in case anyone else uses the script.. pretty obvious - but to change the opacity of the mask some I added: $mask.css('opacity', .75); )

link publish delete flag offensive edit

answered 2012-07-16 03:15:30 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi,

I've post a feature request: http://tracker.zkoss.org/browse/ZK-1262

Regards,
Ben

link publish delete flag offensive edit

answered 2012-08-20 14:04:55 +0800

rafaelmaas gravatar image rafaelmaas
51

Thanks benbai for the solution and thanks rickcr for the opacity tip.
Works like a charm :D

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2012-07-03 14:24:19 +0800

Seen: 800 times

Last updated: Aug 20 '12

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More