grails remoteFunction onComplete, passing an event? Bug? - grails

Per the remoteFunction documentation one can cause a javascript function to be called when the remoteFunction finishes, using the onComplete parameter. From examples I've seen on the web, one can supply a function with an event parameter, i.e.
onComplete: 'finishUp(e)'
Then I found this is broken in 1.3.6, per Grails bugs filed, here and here, which was supposed to be fixed for 1.3.7 (perhaps 1.3.6), per the bug resolutions.
However, this is still broken in my 1.3.7. Are you able to get this to work? Is there a bug in my syntax. Note if I drop the 'e', I get the function to be called (can tell by an alert). But, if I add in the "e", the function doesn't get called.
Thanks

Try this:
onComplete: 'finishUp'
And see if it calls the function and if the event object is present in
function finishUp(e) { ... }

Related

How to setInterval() in Electron BrowserWindow?

I have a simple Electron application that queries a SQL database and displays the output via an HTML table. I have everything working correctly, but now I need to "refresh" the HTML table every X minutes (with the new results of the SQL query).
Right now, I have it working correctly using the meta tag directly in the HTML with: http-equiv="refresh" content="300". This correctly refreshes the page every 5 minutes, which is exactly what I want.
Although, the problem is that the refresh causes the screen to go white while the SQL query executes and the HTML is built. Obviously, the better solution would be to use the DOM and only modify the cells that have actually changed, since the last refresh. The problem I am running into, is getting "setInterval" to work correctly.... Once again, this is a VERY SIMPLE electron application. I am using their starting boiler plate. I have tried adding the "setInterval" in the <body> tag, using code like this:
<body onload='setInterval(updateTable(), 300000);'>
but the code only fires once... I have also tried adding the following code at the end of the body (just inside the </body> tag):
<script>
window.onload=function(e){
setInterval(updateTable(), 300000);
}
</script>
...removing it from the window.onload handler...:
<script>
setInterval(updateTable(), 300000);
</script>
...and also by moving it to the "renderer.js" file:
setInterval(updateTable(), 300000);
in all cases, it only fires once...I know this because the first line of code in updateTable() outputs the current date and time to the console, via console.log()..
I have tried lowering the timeout value to 10 seconds (from 300000 to 10000), just so I don't have to wait so long while testing and that didn't make any difference. I suspect the problem I am having has something to do with my lack of knowledge of the electron framework (like, perhaps the different "processes") and I have been searching for solutions for two days now, with no luck. Any advice on how I can accomplish this, is MUCH APPRECIATED!
TL;DR
Your issue has nothing to do with Electron and more with what exactly you pass to setInterval. You're not passing the function updateTable, but the result of the function call updateTable(). Remove the parentheses after the function name.
Analysis
Both functions setInterval and setTimeout expect a function as their first parameter, which they will call at a specific time or regularly. What you pass to setInterval is, however, not a function. You write:
setInterval(updateTable(), 10000)
When this line is executed, updateTable is called and its return value is passed to setInterval. (If the function doesn't explicitly return anything, it returns undefined.) That's why your function is just called a single time (when setting up the timer).
If you write
setInterval(updateTable, 10000) // no parentheses
you're actually passing the function to setInterval, which will then run it repeatedly.
You may wonder why your workaround using setTimeout works. This is because you actually pass a function to it. You're specifying the function inline, but don't call it at that time. It does not matter that inside that function, you make the call to updateTable. What matters is what you pass to the timer functions.
I have found a fix/workaround... either there is a "bug" with setInterval or (most likely) I am just missing something due to my "newness" to the frakework. But, instead of using setInterval, I switched to setTimeout, then in the callback, after calling updateTable(), I just set another setTimeout. For whatever reason, this works perfectly.... basically, in "renderer.js", I replaced:
setInterval(updateTable(), 10000);
with
let timer = setTimeout(function refreshTimer() {
updateTable();
timer = setTimeout(refreshTimer, 10000);
}, 10000);
Even though these are functionally equivalent, for some reason it now works perfectly.

Geb: Element is no longer attached to the DOM inside waitFor

I am getting an "Element is no longer attached to the DOM" error from Geb tests. The thing that's confusing me is that the error is from within waitFor itself -- I inserted the wait specifically to allow the async activity on the page to complete before moving ahead with clicking a link, which was previously the source of the same error. If the wait itself fails, now I'm at a loss.
The code is something like
waitFor { $("div", text: "... search string ... ") }
$("a", id: "element-id").click()
and the stack trace shows that the waitFor itself is actually the problem:
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:187)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:554)
at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:268)
at org.openqa.selenium.remote.RemoteWebElement.getText(RemoteWebElement.java:152)
at geb.navigator.NonEmptyNavigator.matches_closure28(NonEmptyNavigator.groovy:474)
at geb.navigator.NonEmptyNavigator.matches(NonEmptyNavigator.groovy:471)
at geb.navigator.NonEmptyNavigator.filter_closure2(NonEmptyNavigator.groovy:63)
at geb.navigator.NonEmptyNavigator.filter(NonEmptyNavigator.groovy:63)
at geb.navigator.NonEmptyNavigator.find(NonEmptyNavigator.groovy:48)
at geb.content.NavigableSupport.$(NavigableSupport.groovy:96)
at geb.Browser.methodMissing(Browser.groovy:193)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:51)
at [my test]_closure7([my test].groovy:147)
at [my test]_closure7([my test].groovy)
at geb.waiting.Wait.waitFor(Wait.groovy:106)
From the stacktrace I can see that you use that selector inside of a test class and not a module so the possibility of a module base element being detached can be ruled out.
If this is happening consistently for you then it means that one of the elements selected by the div selector gets removed from DOM before its text is being retrieved to filter on it.
There are two reasons why this can happen:
Your selector is very slow - selecting all div elements in a page and then filtering them based on text in the JVM can take a lot of time. Assuming that you use the default waiting preset then if that selector takes more than 5 seconds then the waitFor {} block will simply run once, get the exception and never retry because it runs out of time. You should do as much filtering as possible in the browser, that is use a CSS3 compatible selector and use Geb's text filtering extension on an as small as possible element set.
Your page is async in a periodic way and it changes quicker than the selector is able to filter based on element text. This would be again possible because your selector looks like it could be potentially very slow.
Basically I would suggest coming up with a more specific selector than what you have there currently.

there doesn't seem to be a polymer-layout event

I'm looking for an event fired by polymer-layout when it's finished laying out, similar to the polymer-grid-layout event. Doesn't seem to be one. Am I missing something?
After my attempts at polymer-grid-layout (Autosizing canvas inside a polymer grid layout) I've decided to convert everything to nested polymer-layouts instead. After a few hiccups (e.g. the dart version of polymer-layout doesn't work if you put polymer-layout as an element directly under template, whereas the js version does - don't know which is wrong) the approach seems to be working.
The one exception is that I was previously relying on polymer-grid-layout to tell me when the canvas had been resized properly. But with polymer-layout I have the same timing problem but without the same solution it appears.
Any way around this?
thanks
Anders
Dart polymer_element/polymer_ui_element are a bit outdated. I'll take a look at what changes were be made in JS polymer-layout since I last revisited Dart polymer-layout (probably Mo/Di).
Can you please create an issue in https://github.com/ErikGrimes/polymer_elements so you get notified when the update is made.
You are right that polymer-layout is missing a layout event. I filed an issue here https://github.com/Polymer/polymer-layout/issues/3
In the meantime, you should be able to capture the timeline in attached.
attached: function() {
this.async(function() {
this.async(this.layoutHappened);
});
},
layoutHappened: function() {
}
I used nested async because I don't want to worry about whose attached is called first (this one, or the one in the polymer-layout). And yes, this is exactly the kind of fiddly construction that is avoided by having an event.

Usage of _super for _setOption Seems Inconsistent With Documentation?

I believe that I have found a bug in the new _super method of jQuery UI 1.9.x but wanted to run it by you guys first before I reported it. I figure it will be an easy vote for someone out there.
Here's the ticket that I was going to submit. It details the bug:
According to the documentation, _super() takes no arguments. However,
this doesn't work as expected when used in _setOption():
http://jsfiddle.net/grinn/8jKk8/1/
As you can see by clicking the Change Text button, the value of the
text option is not updated even though _super was called properly,
according to the docs at
http://api.jqueryui.com/jQuery.widget/#method-_super
But, if you pass key and value to _super, it does work properly:
http://jsfiddle.net/grinn/8jKk8/2/
I discovered this work-around by viewing the use of _super in the
jQuery UI code, itself.
I'm submitting this as a bug and not a documentation issue because it
would seem _super is expected to work as the documentation states.
Tested in Firefox 17, Chrome 23, and IE 9.
I decided not to report this issue. Judging from the fact that inside jQuery UI they use it as I've described below, I'm thinking that the documentation is just a little vague. For those of you experiencing this same issue, the correct way to use _super appears to be to pass through your arguments, like:
_setOption: function (key, value) {
// Your code goes here...
this._super(key, value);
}
...or more generically:
_setOption: function (key, value) {
// Your code goes here...
this._superApply(arguments);
}

Railscast doesn't recommend a solution for production, I'm looking for a reason why

In this railscast our good friend Mr. Bates walks through a solution to creating an app that can search, sort, and paginate a set of data. When going through AJAX searching he provides a solution that will display results of the search the moment a user enters input into the search box. Here is his solution:
$('#products_search input').keyup(function () {
$.get($('#products_search').attr('action'), ↵
$('#products_search').serialize(), null, 'script');
return false;
});
However he states "Note that this is only a quick demo and isn’t the best way to do this. There are several jQuery plugins that you can use if you do something like this in a production app." I'm looking for an explanation on why he believes this isn't suitable for production. Thanks in advance!
There are two major issues I see with this solution. The first is that you are making an HTTP (AJAX) request every time a key is pressed, which will not be the most efficient way of doing this. The second is that you are basically calling eval in the response, and eval is bad as it can lead to malicious users executing code you don't want to be executed.
Some suggestions on improving:
Use a proper JSON parser and pass the data back as JSON. (you can use $.getJSON)
Throttle the request - don't do it on every keyUp, maybe start a timer and only submit the request if no keys have been pressed in the last second, meaning it won't make lots of calls for people who type fast.
Cache the response. If you have already searched for something, then there is no point fetching the data twice. Keep a note (in a JS Object) of previous calls in this session and their results.

Resources