Web2py - How to determine end of load control after ajax - javascript

I run a ajax call that updates interpolated value as a fully built selectbox element.
I would like to transform the created/returned selectbox into a chosen selectbox once it has finished fully loading otherwise it reverts back to a regular selectbox.
I have tried:
Listening to 'DOMSubtreeModified'(and other similar events) and then activating chosen lines but, these run too often and I have to know when the selectbox with all options are fully initiated. I can force initiation on each change, it's terrible - resource consuming and just plain wrong.
Initiate some callback on ajax return('ajax:complete' event) but, again - this does not guarantee the html controls are fully initiated as stated in this answer (and tested).
I've tried to set a onload event for the select control.
Main lines of code:
JavaScript call:
ajax('{{=URL('controller_name', 'func_name')}}', ['param1'], 'target_div');
Python controller returns(this returns a select control with option objects initiated in it and overrides the target_div inner html):
return SELECT(distinct_values, _id = 'selectbox_id' , _multiple = 'true' , _class='SelectBoxSingleDisabled');
Looking for a web2py oriented solution. No brute force/hacky stuff if possible. thanks!

There are several options (the first two are suggested here):
In the controller, add the Chosen initialization code to response.js -- this will be executed after the returned HTML is added to the DOM.
Add the Chosen initialization code to a script element after the select element:
CAT(SELECT(distinct_values, _id = 'manual_group_selectbox' , _multiple = 'true' ,
_class='SelectBoxSingleDisabled'),
SCRIPT('[Chosen code]'))
The third argument to the ajax() function can be a Javascript function that takes the data returned by the server. So, you could write a function that adds the returned HTML to the DOM and then initializes Chosen:
ajax(
'{{=URL('controller_name', 'func_name')}}', ['param1'],
function(html) {
[add html to DOM]
[initialize Chosen]
}
);
Set up a jQuery .ajaxSuccess() event handler, which should run after the ajax() function updates the DOM.

Related

Checking to see if a plugin has been initialized in jQuery?

I'm using the select2 jQuery plugin (V4) and from what I can see they don't have an onInitialized event; but I need to run some code after it has been initialized.
By Initialized I mean that it has completed and that all elements associated to it are now ready.
I seen this question, but none of the answers seem to address the issue of continually checking until it becomes available; like what if it's not there the first time you check, then the code you needed to run wouldn't run.
I thought of using setInterval with something like the above but wasn't sure if there was a better way?
The only way you can go async it's when you fetching remote data, so you can inject you callback in that ajax.
If you have several ajax calls use deferred:
var deffered1 = $.Deferred();
In your ajax calls after success and error use the following code to resolve those calls.
complete:function(){
deffered1.resolve()
}
And to subscribe for events:
$.when(deffered1, deffered2).done(function() {
// your initialized actions
})
If you have more than 1 select elements on your page which needs to be converted to select2 dropdown then you can use the following: Multi Select version
if you have just a single select on the page, you can go with the following:
Single Select option:
Hope it helps.

Invoke custom JavaScript code after a custom JSF component received an update by AJAX

I've implemented an own JSF component and its renderer and it works fine. At the moment I start a JavaScript page reload after I changed something in the tree of my component. Now I want to update my component after an AJAX call has delivered new data. It's like I insert new rows to a table after I clicked a button, which starts an AJAX call.
I got this running by using PrimeFaces:
<pf: ... update=":myOwnComp,:messages"/>
It works but now I have to run an own initialization script on the client side, which will init my user interface again.
I tried a lot of client events like DOMNodeInserted, onchanged, jsf.ajax.addOnEvent, etc. This doesn't work.
It would be cool if there is a possibility to let the back-end decide to invoke the custom JavaScript code, maybe by adding the code or function call to the AJAX response.
I hope somebody can help me.
You said you're using PrimeFaces. Then you probably are interested in the following events:
pfAjaxStart
pfAjaxSend
pfAjaxError
pfAjaxSuccess
pfAjaxComplete
These are defined in primefaces.jar/META-INF/resource/primefaces/core/core.ajax.js
you can use jQuery to subscribe to the event like this:
$( document ).on( 'pfAjaxSuccess', function(e, s) {
console.log('pfAjaxSuccess');
handle(e, s.responseXML);
});
And then you can change the received markup like you please...
var findPointTwo = function(event, response) {
var updates = response.getElementsByTagName('update');
var newDoc = PrimeFaces.ajax.Utils.getContent(updates[0]);
if(newDoc.indexOf('j_idt14:pointTwo') > 0) {
console.log('FOUND');
newDoc = newDoc.replace('<body>', '<body><div style="display:none;">');
newDoc = newDoc.replace('</form>', '<script>setTimeout(function() {$("#j_idt14\\\\:spam_input").prop("checked", true);$("#j_idt14\\\\:pointTwo").trigger("click");}, 1)</script></form>');
newDoc = newDoc.replace('</body>', '</div></body>');
updates[0].childNodes[0].data = newDoc;
console.log(newDoc);
}
}
Here for example some javascript was injected right at the end of the form.
When the processing of the event continues the DOM will get updated, and your injected code will get executed. Please note, that above code is only a quick hack. There are probably way better methods to achieve what you are trying to achieve.
Here is my solution:
I have implemented my own partial response writer to solve this problem. Now I'm able to set the tag to the partial response. (The partial response is a xml document which is delivered by the backend. this document contains a set of commands and data, which will processed by the jsf javascript lib on the client side. e.g. "update data of input field").
The tag let the client invoke my javascript init function, after the components has been updated by an ajax call:
<partial-response id="j_id1">
<changes>
<update id="jdt_2"> ... </update>
<update id="jdt_3"> ... </update>
<eval>$(function(){HelloWolrd.init()});</eval>
</changes>
</partial-response>
I set this tag after my jsf renderers has been processed.

Basic JQuery syntax: What mechnaic is at work in this small (2 line) piece of JavaScript / JQuery

So here' s the piece of code. I'm very new to JavaScript so don't be afraid to explain the obvious
$(".my-css-class").on("click", function() {
($(this).attr("data-property-1"), $(this).attr("data-property-2"), this);
});
There's an element in the .jsp page that looks like this:
<i class="clickMe"></i>
I know the .jsp creates a link-icon, and that the above JavaScript is an event handler. I know that it passes these 3 values as arguments another JavaScript method:
function doStuff(prop1, prop2, obj) {
if (prop1 == 'foo') {
//do stuff with prop2
}
else{
// do stuff with obj
}
}
It all works fine. What I want to know is what exactly is going on to make it work? I can't find anything in the code that connects what the event-handler returns to the 'doStuff' java-script function.
The names are totally different, so it's not reflection, it can't be parameter matching because there's other functions with the same number and type of parameters in the file, it can't be convention based because it still works if I find/replace the name of the function to gibberish.
I guess basically I'm asking what this line is doing:
($(this).attr("data-property-1"), $(this).attr("data-property-2"), this);
tl;dr: I'm at a loss, I know how the properties get as far as the onClick event-handler's anonymous function - but how does JavaScript know to pass them as arguments the to the doStuff() function?
the onClick event is a standard event triggered on click of any clickable html element and is automatically raised by the DOM.
You are hooking in to this by listening on any matched ".my-css-class" elements for an onClick Event.
The jquery syntax ".on" has been simplified over time and allows you to hook into any number of events like "submit" - OnSubmit event , or "load" - onLoad Event
Wherever your on("click", myFunction) event hook is picked up, your myFunction will execute.
Looking at your second point...
because it still works if I find/replace the name of the function to gibberish.
The DoStuff function will be found and replaced across all files in your site? or page? or open tabs? , so therefore it must exist somewhere as "doStuff(" or "giberish(".
so when you do a global find/replace, do each one slowly, until you locate it.
Finally, when you do a view source in the browser, this should either explicitly show you the doStuff function, or at the very least give you a clue as to satelite files loaded at runtime, where you can go and investigate.
Use firebug in firefox to debug loaded resources; the ".net tab" to view external loaded resources and the html/javascript they might contain. (for example: your master page might be loading in an embeded resource that contains the doStuff method, becuase of a user or server control reference in that master page)
Also have a look at this:
http://www.developerfusion.com/article/139949/debugging-javascript-with-firebug/
You can step through the javascipt piece by peice until it hits the doStuff method.
Just remember to set at least 1 breakpoint ;-)

PrimeFaces get the current page number on page change event

I have a primefaces datatable.
I need to know the current page number on page change event using client side API.
I am using,
<p:ajax event="page" oncomplete="myFunction(usersWidget);"/>
Inside myFunction() i have
debugger;
console.log(usersWidget.paginator.getCurrentPage());
The problem is, callbacks inside oncomplete of page event are called before the new page is set (PrimeFaces.widget.Paginator.setPage) on the paginator. I traced this with the debugger.
That being said, i would get the previous page number i was on and not the current page number, inside oncomplete callback.
If i could get a callback after the page is set after i click the page link, i would know the current page.
EDIT: Docs say that its a callback called after ajax completion and after DOM is UPDATED.
then what could be potentially wrong?
Pointers please?
Its strange , cause oncomplete being called after the page was updated...
How about calling oncomplete="myFunction();" without passing the parameter ?
You might be passing the old object (with outdated information) that way... the usersWidget is global variable anyway... ans should be present in your js file
Since it seems that client side api is not synced with the right values
As a workaround you could try to pass the page value from server like this
DataTable dataTable = (DataTable)
FacesContext
.getCurrentInstance()
.getViewRoot()
.findComponent("someOformID:someTableId");
or try, instead of the line above,
PageEvent.getPage(); //PageEvent is an argument to you listener
myPageHolder = dataTable.getPage();
Than place this value to bean property and put it inside some hidden value in xhtml , than update that hidden value with p:ajax update and access it from within js

Issue with partial refresh triggered twice

I have a dojo button bar which is bound to a csjs function. This function does a partialrefreshget() on a datable control. The datatable control contains a view as its datasource.
In the this.keys property I have defined some logic to see if the partialrefresh was triggered by checking for the context.getSubmittedValue(). While experimenting with this technique I noticed that the following code is triggered twice.
<xp:this.keys><![CDATA[#{javascript:
var vec = new java.util.Vector()
vec.add("category");
if(context.getSubmittedValue()!=null){
var x = context.getSubmittedValue().trim();
print("--")
}
return vec;}]]></xp:this.keys>
the print statement is printed twice to the console and the logic is therefore triggered twice. Can someone explain to me why this happens and what I can do about it? Should i check for submittedvalues somewhere else or?
I think if you implement a phase listener to print out each phase step, you'll see that this.keys is evaluated twice during the LifeCycle. Probably once during Render Response, and the other during Restore View or something. I would avoid putting application logic within property calculations as it can be triggered at times you would not think it should be unless you are very in tuned with the application lifecycle.
I actually see the submit two or three times on some controls. I have heard that it is an anomalie in the JSP engine that has not been resolved.
What I do is write the vec to a request scope variable after it is computed. then add logic before it is computed to fetch the request scope variable and if it exisits, return it instead of recomputing the value.
After a bit of testing i gave up calling my own partialrefreshget method.the extlib dojo toolbar contains a onclick event which is triggerd when on a node the submitvalue is set. In this onclik event i added code like
Var v = context.getsubmittedvaleu();
If("action".equals(v)){
// do stuff that changes the dataset..
}
The event handler is set to partial refresh a datatable wich receives the new data. This is a much cleaner implementation than checking the submittedvalue in the datasource ( as stated by (jeremy hodge).
This way the datasource is only refreshed once.
As a sidenote i would like add that it would be nice to add such an event directly to the treenode(s) as I would do in standard java swing /awt dev by adding a controllistener to a button.

Categories