remoteFunction callback doesn't work, js function isn't called [closed] - grails

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have one g:select with an onchange event that fires a remoteFunction that is calling the request method as well, however, the callback JS function isn't been calling.
This is the g:select:
<g:select id="categories"
name="categories"
from="${Category.findAll('from Category where master is null')}"
noSelection="['':'- Selecione -']" optionKey="id" optionValue="description"
onchange="${remoteFunction(
controller: 'event',
action: 'subCategoriesJSON',
params:'\'id=\' + escape(this.value)',
onSuccess: 'updateSubs(data,textStatus)'
)}"
/>
The subCategoriesJSON is called as well, but there is no way to remoteFunction calls after that the updateSubs function. My page is rendering the scope of the function correctly on the head tag.
This is the function:
<script type="text/javascript">
$(document).ready(function() {
function updateSubs(data, textStatus) {
alert('call me!!!');
var subs = eval("(" + e.responseText + ")");
if (subs) {
$("span#saida").html(subs);
}
}
});
</script>
Any clue will be very welcome. Thanks a lot!

It looks like updateSubs is defined as a local function, which means it isn't accessible from the global scope. Basically move your updateSubs function out of the $(document).ready() - it doesn't need to be there really as there is no need for your code to wait until the dom is ready before defining that function.
That should solve your main problem, however you'll have to edit your code further as you are trying to access e.responseText when you have no access to a variable named e - this will just trip an error until it is fixed. I've commented the problem code for now.
Anyway, once updateSubs is in the global scope the onSuccess handler should be able to access it.
<script type="text/javascript">
function updateSubs(data, textStatus) {
alert('call me!!!');
//var subs = eval("(" + e.responseText + ")");
//if (subs) {
// $("span#saida").html(subs);
//}
}
// I'm not sure if you actually need this ready function..?
$(document).ready(function() {
// if you define a function in here it will only be accessible
// from within the scope of this function.
});
</script>
For further information about function scope, have a read about Nested functions and closures.

Related

knockout + partials + mvc + correct way to bind

Dear fellow programmers
I got myself into a pickle. Ive been in to knockout for like 2 weeks now and im afraid i dont understand the basic idea of it. So be gentle with me.
Situation:
I got a master view layout page /Master to make it simple. Here i got 2 column layout.
On the left a listbox with patients, after clicking one, you will see prescriptions added to the listbox below it. pretty simple...
Dont mind the renderbody here, this is faulty. Just use this image to see 2 big parts. The red en and the yellow.
Now i got the Master working pretty well, when i click on a patient i want to load a specific partial view on the yellow part of the screen. The same with clicking a prescription , then i want to load the prescription partial on the yellow part.
I got these 2 editscreens working but without the master included. these pages look like this:
#model FysioNotes.WebMVC.Models.ViewModels.EditPatientViewModel
form + bindings here
#section scripts {
<script src="~/MyScripts/patientVm.js" />
<script>
$(function () {
ko.applyBindings(new editPatientVm(#Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model))));
});
</script>
}
You see that i use razor here to fill in the data in the editPatientVm. the js file looks like this :
var patientVm = function (data) ...
var editPatientVm = function (data) ...
var createPatientVm = function (data) ...
This is the same with the prescriptions .
Now when i try to load the prescription partial into the yellow part of the screen, i try to do it like this. And this is probably very faulty....
-- this is at the bottom of the master view --
<script type="text/javascript">
$(document).ready(function () {
$('#tablePrescriptions').on('click', 'tr', function (event) {
var selectedId = $(this).data("prescriptionid");
// this data gets filled without troubles
$(this).addClass('selectedrow').siblings().removeClass('selectedrow');
openDetail("prescription", selectedId);
});
and then this function
function openDetail(type, selectedId) {
if (debug)
alert(type + " : " + selectedId);
var url = baseurl + "/Prescription/Edit?prescriptionId=" + selectedId;
$("#mainContent").load(url);
//CHECK THIS
ko.cleanNode($("#mainContent")[0]);
$("#mainContent").load(url, function () {
//ko.applyBindings(new viewModel(), $("#mainContent")[0]);
ko.applyBindings(new editPrescriptionVm(#Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(new FysioNotes.WebMVC.Models.ViewModels.EditPrescriptionViewModel(12836)))), document.getElementById("mainContent"));
});
}
like you see , the fixed number 12836 is totally wrong to do it like this. But i wanted to just try if this would work and it did. But apparantly i cant send a js var to razor , because this is impossible.... so this let me to the idea that im doing something completely wrong
the master view has this at the bottom:
<script src="~/MyScripts/patientVm.js"></script>
<script src="~/MyScripts/prescriptionVm.js"></script>
<script>
$(function () {
ko.applyBindings(new masterVm(#Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model))));
})
</script>
I think i need to put the viewmodels that i need in the partial into my viewmodel of the master maybe ? and then send it trough but this will mean that EVERY viewmodel needs to be on the master. This cant be good for initial loading ! And this seems wrong to me to do it like this , but ive been wrong before....
please help :(
#section scripts cannot work in partials views that are retrieved through ajax... you'll have to execute your code between those tags after the code that retrieves the view in the first place. #section scripts is kept into the request items and rendered when the page is rendered. But since this is ajax, the server has long passed the point where it would keep into account scripts defined between this section

I want the Mapquest OSM Geolocation to automatically show your current location but it's not?

Currently I have to press a on the top right-hand corner of the map to show my current location (it is the little person in the picture), is there a way for when the map load it automatically shows your location? I attached the code as well and a picture to explain. Thanks, I apologize in advance for my lack of knowledge.
<html>
<head>
<script src="http://open.mapquestapi.com/sdk/js/v7.0.s/mqa.toolkit.js?key=Kmjtd%7Cluua2qu7n9%2C7a%3Do5-lzbgq"></script>
<script type="text/javascript">
/*An example of using the MQA.EventUtil to hook into the window load event and execute defined function
passed in as the last parameter. You could alternatively create a plain function here and have it
executed whenever you like (e.g. <body onload="yourfunction">).*/
MQA.EventUtil.observe(window, 'load', function() {
/*Create an object for options*/
var options={
elt:document.getElementById('map'), /*ID of element on the page where you want the map added*/
zoom:13, /*initial zoom level of map*/
latLng:{lat:40.735383, lng:-73.984655}, /*center of map in latitude/longitude*/
mtype:'osm' /*map type (osm)*/
};
/*Construct an instance of MQA.TileMap with the options object*/
window.map = new MQA.TileMap(options);
MQA.withModule('geolocationcontrol', function() {
map.addControl(
new MQA.GeolocationControl()
);
});
});
</script>
</head>
<body>
<div id='map' style='width:750px; height:280px;'></div>
</body>
</html>
Based on the documentation, you could try calling activate on the geolocation control after you create it.
If that does not cause a re-center/zoom then you may need to register a handler for the onLocate callback (also in the control). When your callback is called you can manually re-center/zoom the map.
Bear in mind that geolocation can be very inaccurate, doing it automatically will probably annoy users for whom that is the case.

Suppress the “are you sure you want to leave this page” popup in the Delphi TWebbrowser control

I have an Delphi application that uses TWebbrowser component to automate navigation to another web application we have.
My problem is that sometimes IE shows the infamous 'Are you sure you want to leave this page' message and when this happens, my app can't navigate to another pages unless an user clicks on 'Leave this page' button. I can't edit the website code to remove this warning, unfortunately.
This message is plaguing my app for weeks, and I could not reach to a proper solution anymore. What I did is to keep a background process do manually send a keystroke when this window is show, but this is not a good solution because nobody can use the computer while my app is working.
I saw possible solution for C# in the topic below but I need a Delphi code instead.
Supress the "are you sure you want to leave this page" popup in the .NET webbrowser control
Any help is very, very appreciated.
Thanks :)
This message is shown by the underlying MSHTML engine if the web page handles window.onbeforeunload event. Usually, it's there for a reason, to let the user know his/her input hasn't been saved or submitted yet. The prompt suppression script from the answer you linked doesn't work for cases when the page uses addEventListener("beforeonload", handler) or attachEvent("onbeforeunload", handler). I don't think there's a reliable way of doing this, without resorting to low-level Windows hooks.
[UPDATE] The following script (look for "Inject this script") is a hack which aggressively suppresses the page's own handlers for onbeforeunload event, via setInterval. It should work in 99% of cases, but it still leaves a gap for the page to override onbeforeonload right before navigating away.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
<script type="text/javascript">
window.attachEvent("onbeforeunload", function (ev) {
window.event.returnValue = "onbeforeunload via window.attachEvent()";
});
window.addEventListener("beforeunload", function (ev) {
window.event.returnValue = "onbeforeunload via window.addEventListener()";
});
window.onbeforeunload = function (ev) {
window.event.returnValue = "onbeforeunload via window.onbeforeunload";
};
</script>
<script type="text/javascript">
//
// Inject this script
//
(function () {
var onbeforeunloadHandler = function (ev) {
if (ev) {
if (ev.stopPropagation)
ev.stopPropagation();
if (ev.stopImmediatePropagation)
ev.stopImmediatePropagation();
ev.returnValue = undefined;
}
window.event.returnValue = undefined;
}
var handler = null;
var intervalHandler = function () {
if (handler)
window.detachEvent("onbeforeunload", handler);
// window.attachEvent works best
handler = window.attachEvent("onbeforeunload", onbeforeunloadHandler);
// handler = window.addEventListener("beforeunload", onbeforeunloadHandler);
// handler = window.onload = onbeforeunloadHandler;
};
window.setInterval(intervalHandler, 500);
intervalHandler();
})();
</script>
</head>
<body>
Go away
</body>
</html>
To inject this script with Delphi, you'd probably need to resort to low-level WebBrowser/MSHTML COM interfaces, like IWebBrowser2, IHTMLDocument2, IHTMLScriptElement, in a very similar way it's done in the linked answer. With some more efforts, the same can also be done via late binding, using IDispatch::GetIDsOfNames and IDispatch::Invoke only. If you're asking for exact Delphi code, I don't have one.
The other answer you link to handles the browser's Navigated event. In it, it injects a script element into the page and into each frame on the page. That script assigns a new value to window.alert so that when other code on the page calls it, it does nothing.
This code resets the event handler:
var
WrkIHTMLWindow2: IHTMLWindow2;
WrkIHTMLWindow2Disp: IHTMLWindow2Disp;
begin
WrkIHTMLWindow2 := IHTMLDocument2Disp(WrkIWebBrowser2.Document).parentWindow;
if WrkIHTMLWindow2.QueryInterface(IHTMLWindow2Disp, WrkIHTMLWindow2Disp) = S_OK then
if not VarIsNull(WrkIHTMLWindow2Disp.onbeforeunload) then
WrkIHTMLWindow2Disp.onbeforeunload := NULL;
end;

Cannot simply force focus on text input in stand-alone Google App using HtmlService?

I want to script a click on an input box.
Here is an example where the focus() should do just that, but it doesn't! Why?
Code.gs:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('myFile');
}
myFile.html:
<input type="text" id="new" onchange="adding(this)"/>
<div id="data"></div>
<script>
document.getElementById('new').focus();
function adding(a){
document.getElementById('data').innerHTML += a.value;
a.value = '';
}
</script>
I have also tried without success putting the focus() in its own function and having a body element whose onload calls that function.
What DOES work is having a button whose onclick calls that function, so focus() does eventually become active. Is there some other event I can use to trigger it?
I am using a Chromebook. Could that be the problem?
This is an intentional security decision in Caja. Certain functions that are prone (across the web) to serious malicious misuse, such as submit() and focus(), can only be executed while in the context of a user-initiated event (such as a button click).

Combining jQuery Mobile and MathJax on a mobile site?

There seems to be some issues when combining MathJax and jQuery Mobile on the same page. Sometimes the MathJax renders correctly and other times it does not - and this can happen to the same page.
The HTML that loads both of them looks like this:
<script type='text/javascript' src='http://code.jquery.com/jquery.min.js'>
</script>
<script type='text/javascript'
src='http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js'>
</script>
<link rel='stylesheet' type='text/css'
href='http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.css' />
<script src='/beta/mathjax/MathJax.js'>
</script>
You can see an example page here: http://stackmobile.com/beta/math.stackexchange.com/questions/view/?id=47772
Edit: It seems to be a problem with MathJax not recognizing a new page being loaded via AJAX - here is an example that doesn't seem to work: http://stackmobile.com/beta/#/beta/physics.stackexchange.com/questions/view/?id=11678
Well I found a solution... and it goes something like this:
First assign unique numbers to the pages. Since these pages are generated in PHP, this can be accomplished by using uniqid().
Assign the following function the the pageshow event:
$('#page_id').live('pageshow', function(event, ui) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'path_to_mathjax/MathJax.js';
script.onload = callback;
document.getElementsByTagName('head')[0].appendChild(script);
});
This loads MathJax and inserts it into the DOM - this script should be included within the page element. Also note that we mention a 'callback'. This will be called when the script loads.
This function (the callback) needs to go outside of any pages. This will prevent it from being included twice after a new page is loaded.
var mathjax_loaded = false;
function callback()
{
if(mathjax_loaded)
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
else
{
MathJax.Hub.Startup.onload();
mathjax_loaded = true;
}
}
There's a lot here. First of all, we keep track of whether this callback has been called once before. If not, we tell MathJax to parse the page as if it were invoked from the window.onload event. If this has already happened (and we're on a new page) then we simply need to have MathJax run through the new page.
I'm probably missing something and there may be a better way of doing this. But I haven't found any other way that works.
Not sure if this is easier/better way to add a script but here is what I found:
http://api.jquery.com/jQuery.getScript/
Can't append <script> element
(Untested) Maybe (using your post: Combining jQuery Mobile and MathJax on a mobile site?)
$('#page_id').live('pageshow', function(event, ui) {
$.getScript('http://path_to_mathjax/MathJax.js', function() {
callback();
});
});
var mathjax_loaded = false;
function callback()
{
if(mathjax_loaded)
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
else
{
MathJax.Hub.Startup.onload();
mathjax_loaded = true;
}
}

Resources