Dublicate live event handlers on ajax

I so all possibilities, but i didn’t have the mechanism to control default CHtml::clientChange() behavior and attaching events method too. I can do this in CClientScript by simple reg. expr., but this is the bad way.

Why do you think it would be slow? The jQuery documentation and all the posts of the jQuery core team explains this in great details and they say just the opposite… even if you look at only one page… the delegate way is faster than the classic bind… but this is not the point here… so…

There is a way to turn change the way we “bind”… it’s the “live” option… so would we solve you problem if we would have a global way to turn it on or off like you suggested ?

Note that anyway even if we add this and it works for you… somebody (like an extension author)… can explicitly use "live"=>true in his code… and than the global option would be overridden…

Guys, last page goes in a bad way. Let’s calm down. You both made some good points. I’ll try to sum up.

First of all, there are at least three ways of using on in current jQuery version. These are compatible with live, delegate and bind. I’m sure you both aware of it and we really don’t need to discuss it. When one is talking about delegate he really means on in a delegate-like style.

Some history

  1. Initially Yii used the simplest approach to events: bind.

  2. Since people started trying to use Yii-generated code by loading it via AJAX w/o rendering scripts we’ve changed default to live. Now I think that was a big mistake.

  3. Then it was changed to delegate.

  4. Event handler duplication on AJAX-reloads was solved by adding undelegate.

Problems and possinle solutions

  1. delegate/undelegate are used in simple CHtml-generated code. The proper way is to render scripts when you’re using renderPartial (if you’re not going to create custom code to handle everything). In this case jQuery properly re-binds events and everything works just fine. No real need to use delegate there. It will work with both non-ajax applications and ajax ones.

So the obvious change is to revert back to simplest bind. The only problem I see here is backwards compatibility.

  1. For more complex widgets dealing with a lot of input or their own AJAX-reloads it’s better to bind event handlers to widget container and not to render scripts when responding to AJAX-request. If bind is used, widget should use it with its own container. No need to bind to <body> causing all sort of issues.

This should not cause huge BC-problems.

Changing to live was not a mistake at all… note that we are here restricting our view to non-ajax and full ajax apps… there are some in the middle too…

We still need the "live" option… with this option a user can choose if to "bind" or to "delegate"… as IMO we cannot automatically decide what is best… as only the developer knows what he is doing in his code… we just need to document this very good… so that developers know what and when to use…

So the delegate type of binding is still needed even in your solution no. 1… as only with this type of binding you can affect future DOM elements… those “new” DOM elements can come from an ajax call but even be created on the fly with custom user jQuery code… - that is the reason why live() was introduced… it’s only that live() has some problems that it’s now nicely documented in the jQuery doc… that’s why they later change it to delegate and now as a final solution to on()…

I agree with the no. 2 to bind with the container as it’s advised by the jQuery team… and to solve the possible problem with the fuill-ajax page we just need to prevent the script rendering on ajax calls.

So as I understood Ekstazi when ‘live’=> false is used… his app works good… but the problem is that he cannot add that parameter to every possible call as some code can be from 3rd party (extension/library/…)…

To solve this (like he suggested many posts before)… we can introduce a global switch for this like I asked in the post before yours, still waiting for Ekstazi to respond to this…

It no more needing for me. I already find a universal solution that works with both of cases. I can’t explain all details of this solution, but it must works. So if you can introduce a global switch for bind and delegate-like style it’ll help me partially(my solution will work faster because it controls the delegate container). So no more debuts, lets go. I want to help to optimize gridview.js (to use a proper container and other optimizations) and other yii widgets also.

Would be nice if you would try to explain your solution… first to see if it can be implemented in Yii… and second if it cannot be implemented… then at least for other users to see it here so they can use it too.

No, i’ll provide a big complex extension which will support form submitting, loading pages, menu, message system, custom response type,document.write and others(already finished approximately 70% i.e form submitting, scripts, styles, title, forms, html5 and menu). The main idea is in handling of $.on() calling and analyze it. Also i am in waiting of adding event in CWebApplication::beforeControllerAction, CController::beforeRender, CController::afterRender. These events will simplify my solution. I already describe it in this issue

Great… from the description it will be a nice extension…

So in the end… the global switch is not needed at all for your solution ?

The global switching can accelerate my solution(because the solution need to do $.off() for each delegated event). So if you can add this switching(as an option) it can help not only for me.

mdomba,

Right, I forgot about non-edge cases… thanks for reminding me about these.

As I understand, Ekstazi’s solution will work either way but he has to take additional safety-measures and off(unbind) registered handlers all the time. Also, if I’m correct, he doesn’t want to disclosure details too much not to have tons of extensions doing nearly same thing. That’s fine.

Ekstazi,

If you have suggestions on how to improve Yii’s JavaScript code while keeping it backwards compatible when possible you’re very welcome to post your suggestions.

I think we can close the issue until there will be more requests and instead focus on JavaScript code improvements and http://code.google.com/p/yii/issues/detail?id=2362

Is it OK we’ll do it this way?

Hmm, looks like an option to globally change event handlers to bind/live style will be handy. If one doesn’t need AJAX he can get some clientside performance by switching to bind style. Also it doesn’t break BC.

mdomba, are you OK implementing it? I can take it if needed.

getting performace is in question… and not a point of this discussion… :D

The global settigs is good for situation like "full-ajax" app… if not… users has to know what they are doing with the code (for exampe if they are using a non-edge case mentioned before)

I’m not sure about how to implement this… would that be a static property of CHtml? how would it be set CHtml::liveEvents = true/false;

But more important is how to document this feature so that is clear to users what it means and what it does.

Not only for ajax. Delegate many(1000 for ex.) handlers in one container (now body) of one event type will be slower than bind-like style. Please see this(first loop where make list of handlers to execution). You can call this option like this $liveEventsAsDelault=true. If the option is false then live events will be delegated only manually ($htmlOptions[‘live’]=true). And argument its with performance and this topic issue like full ajax issue.

Static properly looks OK for me. liveEvents name is fine.

Description can be something like the following:

Sets the default event handler style. If set to true (default), live-style is used. That means all event handlers are attached to body instead of the DOM node itself. These handlers are checking for all bubbling events and are triggered if event bubbled corresponds to the original DOM node. If set to false, simplest bind-style is used. That means handlers are attached to DOM nodes directly. You can override this setting for particular element by setting htmlOptions.live. See http://www.yiiframework.com/doc/api/1.1/CHtml#clientChange-detail

Thank you for closing this issue.

Just to update all those users that will read this topic up to here…

We added liveEvents as a static property to CHtml and changed the jQuery method for binding events to on()

http://code.google.com/p/yii/source/detail?r=3473

I tried that and I like it is good for small apps to have modern look (like backbone js apps), I will try to modify it to make it work with deep linking by using jquery address.

Thank you