Showing posts with label functions. Show all posts
Showing posts with label functions. Show all posts

Monday, March 26, 2012

Listeners Broadcast in Javascript/ Atlas Library

Is there a framework in place for a Atlas JS Control to raise an eventwhich can have other Controls or global functions listen in on andhandle?

Just like in Web User Control, we can raise Events which can be handledby pages or other controls that 'listens' in on the event, can the samebe accomlished in JS?

The Web User Control shouldnt know who has registered to listen in onthe event but somehow the Control has to communicate that something hashappened.Would any of the below code help in what I want to accomplish?Basically different components can listen in or another componentsevents, and when that event is raised, each of the listeners methodsare invoked?


Type.createEnum('Sys.ActionSequence','BeforeEventHandler', 0,'AfterEventHandler', 1);
Sys.IAction = function() {
this.get_sequence = Function.abstractMethod;
this.execute = Function.abstractMethod;
this.setOwner = Function.abstractMethod;
}
Sys.IAction.registerInterface('Sys.IAction');

Type.Event = function(owner, autoInvoke) {
var _owner = owner;
var _handlers =null;
var _actions =null;
var _autoInvoke = autoInvoke;
var _invoked =false;

this.get_autoInvoke = function() {
return _autoInvoke;
}

this._getActions = function() {
if (_actions && _actions.length && !_owner)throw"Actions are only supported on events that have an owner.";
if (_actions ==null) {
_actions = [];
}
return _actions;
}
this._getHandlers = function() {
if (_handlers ==null) {
_handlers = [];
}
return _handlers;
}
this._getOwner = function() {
return _owner;
}

this.isActive = function() {
return ((_handlers !=null) && (_handlers.length != 0)) ||
((_actions !=null) && (_actions.length != 0));
}

this.get_isInvoked = function() {
return _invoked;
}

this.dispose = function() {
if (_handlers) {
for (var h = _handlers.length - 1; h >= 0; h--) {
_handlers[h] =null;
}
_handlers =null;
}
if (_actions) {
for (var i = _actions.length - 1; i >= 0; i--) {
_actions[i].dispose();
}
_actions =null;
}

_owner =null;
}

this._setInvoked = function(value) {
_invoked =true;
}
}
Type.Event.registerSealedClass('Type.Event',null, Sys.IDisposable);

Type.Event.prototype.add = function(handler) {
this._getHandlers().add(handler);
if (this.get_autoInvoke() &&this.get_isInvoked()) {
handler(this._getOwner(),null);
}
}
Type.Event.prototype.addAction = function(action) {
action.setOwner(this._getOwner());
this._getActions().add(action);
}
Type.Event.prototype.remove = function(handler) {
this._getHandlers().remove(handler);
}
Type.Event.prototype.removeAction = function(action) {
action.dispose();
this._getActions().remove(action);
}
Type.Event.prototype.invoke = function(sender, eventArgs) {
if (this.isActive()) {
var actions =this._getActions();
var handlers =this._getHandlers();
var hasPostActions =false;
var i;

for (i = 0; i < actions.length; i++) {
if (actions[i].get_sequence() == Sys.ActionSequence.BeforeEventHandler) {
actions[i].execute(sender, eventArgs);
}
else {
hasPostActions =true;
}
}

for (i = 0; i < handlers.length; i++) {
handlers[i](sender, eventArgs);
}

if (hasPostActions) {
for (i = 0; i < actions.length; i++) {
if (actions[i].get_sequence() == Sys.ActionSequence.AfterEventHandler) {
actions[i].execute(sender, eventArgs);
}
}
}

this._setInvoked();
}
}


Sorry for the message, I forgot to check the Atlas Client sidereference library where it has a nice page on this:http://atlas.asp.net/docs/Client/Type/Event/default.aspx

but anyone with more concrete examples would be much appreciated :)
Hi,

the Atlas framework gives you the ability to declare multiple handlers for an event. Just use the add() method on the exposed event to add a handler.

For example, if the instance myObject exposes a myevent event, you can write a statement like:

myObject.myevent.add(myMethod);

to register a handler for that event.
Thanks for your response Garbin (+ props to your weblog)

Looking at your pager example:

// Events.
// The Pager exposes the pageChanged event, which is raised
// when the page index to be displayed changes.
this.pageChanged =this.createEvent();
...

Which exposes a pageChanged property where I can pass in one method on the initialization of the Atlas Control.

td.addEvent('pageChanged',true);

...

The event is raised by:

this.pageChanged.invoke(this,new AtlasNotes.PagerEventArgs(_pageIndex, _pageSize, _totalRecords));

so going by your post, I can append more methods to be handled by going:

myObject.pageChanged.add(myMethod);

If so, Ill try it on Monday :D


The above code works beautifully :)

Saturday, March 24, 2012

Load in-line javascript functions after UpdatePanel refresh

I have a lot of user controls that have in-line javascript functions specific to the content of the user control, validations and automated reactions. This javascript is written mostly by client side developers. Is there any way to allow them to keep writting their in-line javascript on the user controls, but still have that javascript be active after an updatepanel conditionally makes the user control visible? For example imagine a page with a button and the user control. The user control is in an update panel tiggered by the button click. When clicked the user control has its visibility set to true and the user interacts with the newly visible controls contained within. Because the user control was initially in an update panel, the original page source does not contain the in-line javascript functions so they are never evaluated by the browser. In order to keep the client side group's functionali i've had to recreate the client side code on the server side by building a large string that references controls using the control.ClientID property (just like the client side group does with inline scriplets $get(<%= control.ClientId %>) and then registering this string on the page with ScriptManager. This is too inefficient a process and having the javascript placed on every page that uses the user control seems counter productive with regard to user controls. Placing all the javascript in external files that get loaded by ScriptManager is also not an option as the javascript is often control specfic. Is there no way to get the browser to recognise the in-line javascript after an update panel loads it? Is this something that is planned for the future if not?

Well, I don't know if it is the final solution, but I figured that I could use display:none and display:block on a panel wrapping the user control instead of using the Visible property on the control itself. This way the control (and most importantly the javascript) is initially rendered, but not browser visible. If there is still some way to use the built in Visible property to do what I want, please let me know. I like that the inital page load using the Visible property doesn't have the extra weight of controls that are not usuable.


You can give this approach a try:http://blogs.msdn.com/sburke/archive/2007/06/13/how-to-make-tab-control-panels-load-on-demand.aspx

-Damien


I believe that approach will suffer from the same issue. The tabcontainer content will not be initially visible and so any inline javascript contained in a tabcontainer will not be evaluated by the browser.


Sorry about that I miss read your question. If the JS is embedded in the usercontrols they need to be loaded, so your solution works. I'm a bit confused why you need the JS loaded if they are control specific. Sounds like there may be a design problem with your solution.

-Damien

Wednesday, March 21, 2012

LoadPageStateFromPersistenceMedium and AJAX Beta 2

Anyone else using Load/Save PageFromPesistenceMedium and AJAX Beta 2. In my functions, I'm saving the state in a compressed format to reduce the size of the viewstate as its passed back and forth over the browser. We are talking around 1 MB of viewstate uncompressed here so it's needed...

Anyway, in previous CTPs of the ATLAS framework, this has all worked fine. In the Beta 2 update, it appears as though the viewstate that is created on inital page view remains around. For example, I have a gridview control that contains a dropdown list in each row for sorting the items in the gridview. You click a new value in the drop down and that row is supposed to move to that row in the grid. With the current Beta 2, if I move row 5 to row 1, that works. Then I select row 5 to move to row 3 and the record in row 1 moves to row 3 instead! (row 1 contains the original row 5 so it seems to reference that row on the server and move it to 3).

I've obviously got to look at my own load/save code here but since the Beta 2 update is the only change, I'm starting with something being broken in that. Let me know if you've got any other thoughts?

Thanks.

I use compressed state myself, but again, I use only UpdatePanel.

I have implemented my own PageStatePersister / IStateFormatter instead though. I feel that this is a more proper way than overriding the method in the actual page.

Have you tried without overriding state load / save ?


If I don't use the save/load of state, everything works fine except i have a very large viewstate object being passed around.

I've found one workaround right now. The viewstate can be saved to the server as a temp file instead of going back down to the server. This appears to work so for the time being, I can use this and just have a clean up on application_end to remove the viewstate files. However, this makes me believe that the hidden input values aren't being updated properly in this beta 2.


Try to implement what I mentioned!

 
public class CompressedHiddenPageStatePersister : HiddenFieldPageStatePersisterpublic class CompressedStateFormatter : IStateFormatter

I recommend you to look at these (not garantueed to help though)

You could also just try to compress the whole thing itself, withASPX compression in IIS