I need to get a javascript variable in my template ( play framework 1.2.6) :
#{extends 'main.html' /}
#{set title:'My Resa V.1' /}
<div id="content">
<div id="draggable" class="ui-widget-content">
<p>Drag me around</p>
</div>
<div id="circle"> <center>table 1</center></div>
</div>
<script>
$(function() {
$( "#draggable" ).draggable();
$( "#circle" ).draggable({
stop: function(event, ui) {
var circle = $(this).position();
var position= circle.top;
}
});
});
</script>
I want to get var position= circle.top;. Thanks
The main reason of your problem is that the play template engine is executed on a server side, and the javascript code is executed at the client side (i.e. into the web browser).
So if you want to add variable from the server state (from java), you should "write" (inject) your javascript code at server side, so it will be present when the page will load to the client, and thus can be executed there.
In order to do this, first you need to send your circle variable from the controller to the view using the following code:
Circle circle=getYourCircle();
render("path/to/your/view",circle);
Next, in your view file just replace the line where the position is initialized:
var position= ${circle.top};
Again, the ${} expression will be evaluated on the server and the value will be written into the body of the response that will be returned to the client. So, in this case if your circle has value for its top property equal to 40, the browser will get:
var position= 40;
for the corresponding line.
For the other way around (i.e. reading a javascript variable in the template) is not possible, unless you make a request to the server (for instance by using some of the jQuery.ajax variants), and send the value of the javascript variable.
The request should be accepted by a controller, and the value for the variable should be delegated to the view (same procedure as in the first code snippet). Even then the play template engine will be able to access the "javascript" variable (which now is request scope variable) and make additional transformations to it.
I hope this helps :)
thanks! I finally used Ajax mechanism:
...
var allPosition='';
for (var m in map){
allPosition+= m +'-' + map[m].top + '-' + map[m].left+'/';
}
var updateUserRoute = #{jsRoute #Application.saveDisposition() /}
...
function callAjax(updateUserRoute,allPosition){
$.ajax({
url: updateUserRoute.url(),
type: updateUserRoute.method,
data:{ positionTables: allPosition}
});
//.done(function( msg ) {
// alert( "disposition des tables sauvegardé" );
// });
}
Related
I'm trying to create a button that, upon clicking, "saves" the positions of multiple lists from a connected-sortable. I want the script to be able to retain the most recent position of each list item when the page is refreshed (i.e. If list 1 starts as A,B,C and I change it to B,A,C and refresh the page, it stays as B,A,C.).
I'm attempting to accomplish this by creating an array from an html document (published as a web app), save it using the getUserProperities function, and then return it the next time I open the web app.
I am able to log the positions without issue, but I'm having trouble figuring out where to run the getUserProperities function, or what other issue I may be dealing with.
In the console from the web app, I get this error Uncaught TypeError: Cannot read property 'getUserProperties' of undefined at saveList (userCodeAppPanel:4) at HTMLButtonElement.onclick (userCodeAppPanel:1).
Where should I be calling the getUserProperties function? From code.gs or index.html? I have been working off the example provided HERE.
The relevant portions of my code, from index.html are below.
<script>
$( function() {
$( "#myList, #flight1a, #flight1b, #flight2a, #flight2b, #flight3a, #flight3b, #sortable2" ).sortable({
connectWith: ".connectedSortable",
update: function(event, ui) {
var changedList = this.id;
var order = $(this).sortable('toArray');
var positions = order.join(';');
console.log({
id: changedList,
positions: positions
});
}
})
});
</script>
<script>
function saveList() {
google.script.run.PropertiesService.getUserProperties().setProperty('myProperty', JSON.stringify(positions));
var returnedObj = PropertiesService.getUserProperties("myProperty");
returnedObj = JSON.parse(returnedObj);
}
</script>
</head>
<body>
<button onclick="saveList()">Click me</button>
Properties Service can only be accessed through Google Apps Script, so it must be called in one of your *.gs files. To execute a server-side function, you need to use google.script.run (there's also a guide available).
For example, in your code.gs file add this function:
function savePositions(propertyName, value) {
PropertiesService.getUserProperties().setProperty(propertyName, value);
}
Then, in your index.html file modify saveList() to:
function saveList() {
google.script.run.savePositions("myProperty", JSON.stringify(positions));
}
google.script.run could be used to call a server side function not to call directly the Properties Service.
For further details see https://developers.google.com/apps-script/guides/html/reference/run
I am using GeckoWebBrowser within my VB.NET (Windows Form App) program. The GeckoWebBrowser loads a local html file. This html has embed in-line a svg file (human body diagram with bones and internal organs) with a javascript function for picking up all the "ids" of the elements from the svg document. I'd like to call the aforementioned javascript function from VB.NET (Windows form app), but I don't know how to do so. Can anyone help me, or give me a source code example please? All the stuff I've found is based in C#...
This is my javascript function in my html file:
<script type="text/javascript">
(funcion () {
// Function to be called in VB.NET when the DOM is loaded
var SVGHandler = function () {
// Picking up the id Root Node="CUERPO_HUMANO" into svg variable
var svg = document.querySelector('#CUERPO_HUMANO');
// In Items we save all the <g> which have an ID
var items = svg.querySelectorAll('g[id], path[id]');
//var items = svg.querySelectorAll('g[id]');
// We loop all the nodes saved in Items and add them to click event listener
forEach(items, function (index, value) {
value.addEventListener('click', function (event) {
event.preventDefault();
//We avoid the spread of events
event.stopPropagation();
return event.currentTarget.id
// console.log(event.currentTarget.id)
});
});
}
// https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/
var forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]); // passes back stuff we need
}
};
// With this method, we call a SVGHandler when DOM is totally loaded
document.addEventListener('DOMContentLoaded', SVGHandler);
})();
</script>
What code should I use in VB.NET for calling my javascript function each time I click on a specific bone or organ in the human body diagram loaded in GeckoWebBrowser?
I want to save the "id" picked up with the calling into a string variable in order to use it as a parameter in a SQL statement and populate a DataGridView.
I've been searching and all that I could find was related to C#, not a single VB.NET example. Even though I was trying to figure out the equivalence in VB.NET trying to convert the C#'s examples to VB.NET, I have some doubts on how to do the javascript call. According to my javascript function It could be something like this:
browserControl.Navigate("javascript:void(funcion())");
Please, Can anyone help me to solve this? I would be very thankful...
Well since you have set click EventListener's I think that you're not looking for a way to call the eventual function from VB.NET but this is quite unclear according to your post so I'll give you examples on how to call a javascript function and how to trigger a reaction in your VB.NET code through javascript using GeckoWebBrowser.
Your code snippet of your attempt to call a js function from your vb code is correct. The only problem is that you haven't defined any callable js function in your html file. In your case you should do this to trigger your main js function from vb:
//Sorry I don't know vb. I'll give example in c# keeping it as simple as possible so that you can easily convert it to vb
Gecko.GeckoHtmlElement humanBodyPart = (Gecko.GeckoHtmlElement) browserControl.Document.GetElementById("your id");
humanBodyPart.Click();
The above code finds the element with the matching id in the GeckoWebBrowser and clicks it. Since you've set click EventListener's, by clicking one of the elements this will trigger the function assigned to them to run.
Moving on, in order to save the id of the elements to a string variable in your vb code you'll need to add this little bit of js code in to the code that you pass as 'callback' parameter in your forEach function:
var event = document.createEvent('MessageEvent');
var origin = window.location.protocol + '//' + window.location.host;
var event = new MessageEvent('jsCall', { 'view': window, 'bubbles': false, 'cancelable': false, 'data': 'YOUR EVENTUAL ID AS A STRING (THIS STUFF GOES BACK TO THE VB/C# CODE)' });
document.dispatchEvent (event);
Then the above snippet should be handled in your vb code like this:
browserControl.AddMessageEventListener("jsCall", (id) =>
{
//Here in the variable id you have your clicked id as a string. Do what you wanted to do...
});
VB side :
you need wait until the document is completed to add listeners
for example : _DocumentCompleted
Private Sub GeckoWebBrowser1_DocumentCompleted(sender As Object, e As Gecko.Events.GeckoDocumentCompletedEventArgs) Handles GeckoWebBrowser1.DocumentCompleted
GeckoWebBrowser1.AddMessageEventListener("my_function_name JS_side", AddressOf my_sub_for_treatment)
End Sub
JS side :
var event = document.createEvent('MessageEvent');
var origin = window.location.protocol + '//' + window.location.host;
var event = new MessageEvent('my_function_name JS_side', { 'view': window, 'bubbles': false, 'cancelable': false, 'data': my_data_to transfer });
document.dispatchEvent (event);
If I am here asking it is because we are stuck on something that we do not know how to solve. I must admit, we already searched in StackOverflow and search engines about a solution.. but we didn't manage to implement it / solve the problem.
I am trying to create a JavaScript function that:
detects in my html page all the occurrences of an html tag: <alias>
replaces its content with the result of an Ajax call (sending the
content of the tag to the Ajax.php page) + localStorage management
at the end unwraps it from <alias> tag and leaves the content returned from ajax call
the only problem is that in both cases it skips some iterations.
We have made some researches and it seems that the "problem" is that Ajax is asynchronous, so it does not wait for the response before going on with the process. We even saw that "async: false" is not a good solution.
I leave the part of my script that is interested with some brief descriptions
// includes an icon in the page to display the correct change
function multilingual(msg,i) {
// code
}
// function to make an ajax call or a "cache call" if value is in localStorage for a variable
function sendRequest(o) {
console.log(o.variab+': running sendRequest function');
// check if value for that variable is stored and if stored for more than 1 hour
if(window.localStorage && window.localStorage.getItem(o.variab) && window.localStorage.getItem(o.variab+'_exp') > +new Date - 60*60*1000) {
console.log(o.variab+': value from localStorage');
// replace <alias> content with cached value
var cached = window.localStorage.getItem(o.variab);
elements[o.counter].innerHTML = cached;
// including icon for multilingual post
console.log(o.variab+': calling multilingual function');
multilingual(window.localStorage.getItem(o.variab),o.counter);
} else {
console.log(o.variab+': starting ajax call');
// not stored yet or older than a month
console.log('variable='+o.variab+'&api_key='+o.api_key+'&lang='+o.language);
$.ajax({
type: 'POST',
url: my_ajax_url,
data: 'variable='+o.variab+'&api_key='+o.api_key+'&lang='+o.language,
success: function(msg){
// ajax call, storing new value and expiration + replace <alias> inner html with new value
window.localStorage.setItem(o.variab, msg);
var content = window.localStorage.getItem(o.variab);
window.localStorage.setItem(o.variab+'_exp', +new Date);
console.log(o.variab+': replacement from ajax call');
elements[o.counter].innerHTML = content;
// including icon for multilingual post
console.log(o.variab+': calling multilingual function');
multilingual(msg,o.counter);
},
error: function(msg){
console.warn('an error occured during ajax call');
}
});
}
};
// loop for each <alias> element found
//initial settings
var elements = document.body.getElementsByTagName('alias'),
elem_n = elements.length,
counter = 0;
var i = 0;
for(; i < elem_n;i++) {
var flag = 0;
console.info('var i='+i+' - Now working on '+elements[i].innerHTML);
sendRequest({
variab : elements[i].innerHTML,
api_key : settings.api_key,
language : default_lang,
counter : i
});
$(elements[i]).contents().unwrap().parent();
console.log(elements[i].innerHTML+': wrap removed');
}
I hope that some of you may provide me some valid solutions and/or examples, because we are stuck on this problem :(
From our test, when the value is from cache, the 1st/3rd/5th ... values are replaced correctly
when the value is from ajax the 2nd/4th .. values are replaced
Thanks in advance for your help :)
Your elements array is a live NodeList. When you unwrap things in those <alias> tags, the element disappears from the list. So, you're looking at element 0, and you do the ajax call, and then you get rid of the <alias> tag around the contents. At that instant, element[0] becomes what used to be element[1]. However, your loop increments i, so you skip the new element[0].
There's no reason to use .getElementsByTagName() anyway; you're using jQuery, so use it consistently:
var elements = $("alias");
That'll give you a jQuery object that will (mostly) work like an array, so the rest of your code won't have to change much, if at all.
To solve issues like this in the past, I've done something like the code below, you actually send the target along with the function running the AJAX call, and don't use any global variables because those may change as the for loop runs. Try passing in everything you'll use in the parameters of the function, including the target like I've done:
function loadContent(target, info) {
//ajax call
//on success replace target with new data;
}
$('alias').each(function(){
loadContent($(this), info)
});
UPDATE
Added this error, just says "Error caught"
<script type="text/javascript">
window.onerror = function() {
alert("Error caught");
};
xxx();
</script>
This is not working, I don't understand why.
My php script inserts data properly if called by itself without an if{method=post} statement
I tried with and without an if method = post argument on the php side to get the ajax below to work but I can't tell if the script is being called at all.
My aim is to submit the data without the user knowing, it's a coordinate / dimension update for a variable design interface.
This is my ajax insert which is supposed to work when a function is invoked after the stop is triggered eg. after an object is done moving which the function is invoked properly as I have set up sequential alerts to pop up after certain lines.
$("#form").submit(function(event){
event.preventDefault();
var $form = $( this ),
url = $form.attr( 'action' );
var posting = $.post( url, {
id: $('#id').val(),
name: $('#name').val(),
wname: $('#wname').val(),
xcor: $('#xcor').val(xcor),
ycor: $('#ycor').val(ycor),
xwid: $('#xwid').val(xwid),
yhei: $('#yhei').val(yhei),
photo: $('#photo').val(),
targeturl: $('#targeturl').val()
});
posting.done(function( data ){
alert('success');
});
});
This is wrong
xcor: $('#xcor').val(xcor),
ycor: $('#ycor').val(ycor),
xwid: $('#xwid').val(xwid),
yhei: $('#yhei').val(yhei),
Those object are holding jQuery objects, not a value.
Looks like you want to set the value and use the new value. This makes me cringe, but it would do the job
xcor: $('#xcor').val(xcor).val(),
ycor: $('#ycor').val(ycor).val(),
xwid: $('#xwid').val(xwid).val(),
yhei: $('#yhei').val(yhei).val(),
You would be better off updating them before the call and just using the variable when setting the object. Or just use jQuery serialize() and don't deal with grabbing the elements.
I have this JQuery UI sortable list that has draggable elements and when I drag it from the bottom to the top, it saves a value corresponding to it's place in the list and saves it in the database. This works! But I need an image on my webpage to update simultaneously by chaning it's z-index. So once a item from the list has been moved to another place in the list, the z index gets stored in the database (which works) and then I need it to change the specific image to using that same z-index. My AJAX code looks like this:
$(document).ready(function () {
$("#sortable").sortable({
axis: "y",
stop: function (event, ui) {
var data = $(this).sortable("serialize");
//These next 2 lines are just a poor attempt to achieve what I want:
var change_zindex = 1;
document.getElementsByClassName('item2')[0].setAttribute("alt", change_zindex);
// POST to server using $.post or $.ajax
$.ajax({
data: data,
type: "POST",
url: "database/update_settings_sort.php"
});
}
});
$( "#sortable" ).disableSelection();
});
Well I hope you have some suggestions or advice. Thanks in advance, please tell me if you want me to provide more code.
Edit:
This is what I have now:
var change_zindex = 1;
document.getElementsByClassName('item2')[0].setAttribute("alt", change_zindex);
Only problem is to
1. Know what the change_zindex variable shall be equal to.
2. Be able to do it with all items on the list and not just only item2. I could use something like 'item' + img_id but I don't know how to retrieve that id. Hmm Thanks all
Your code works fine but make sure you are getting the value for variable 'img_id' in the following three lines
var zindex = document.getElementsByClassName('item' + img_id)[0].getAttribute('z-index');
var change_zindex = 1;
document.getElementsByClassName('item' + img_id)[0].setAttribute("z-index", change_zindex);