I have a div which contains message updates sent by users. How can I assign a javascript variable to this div so that it's value is always the current content of the div which is consistently updating with messages?
var x = document.getElementById("MessageBox"); // only equals value at the
// time rather than present value
The easiest way to accomplish this would be to assign an .onchange event handler to the element, then assign the node's value to a variable held outside the scope of the function:
var myMSGvalue;
document.getElementById("MessageBox").onchange = function () {
myMSGvalue = this.value;
// this will work for <input>, not <div>
}
If you really need to assign your data to an html element, you should use an <input type="hidden">.
However, it would be much better to assign the data to a variable before you append it to the page. For example, let's say you have a web socket:
var messages = [];
socket.on("msg", function (msg) {
messages.push(msg);
// msg: { content: "Hello!", author: "notSure" };
functionToAppendToPage(msg);
})
Now, you can see all the messages received in messages and messages[messages.length - 1] will return the last message received (provided at least one message has been received).
If your message box field getting data using any Api or through Ajax. You can update the variable before assigning value to message box.
Related
I use this code in GTM , that retrieves a number from another domain and stores it on a dataLayer value, with a dL.push. I want the variable to be available on a specific event.
(function ()
{
var callbackMethodName = "adnscallback";
window[callbackMethodName] = function(data) {
(function() {
dataLayer.push({
'event': 'ga_new',
"id2": data.uid
});
})();
}
var sc = document.createElement("script");
sc.id = "script_" + callbackMethodName;
sc.src = "https://example.site.com/getnumber?callback=" + callbackMethodName;
document.body.appendChild(sc);
})();
But I already create an event called ga_new (hardcoded, that creates all sort of values on the page) and when this codes run, it creates another event called ga_new, instead of pushing the values on the existing event. This creates issues with the tags as they are double firing.
What iam doing wrong and the push, instead of appending the data, it creates the event again?
You can not "update" a custom event. The "event" keyword is a signal to GTM that it needs to update its internal data structure with new values.
The datalayer variable in the page is an array of objects, the internal datastructure is a single object into which new values are merged, and existing values for the same keys are overwritten. GTM overwrites the native implementation of the JS "push" method with its own code that watches for the "event" keyword. So every time it encounters the "event" key changes are triggered.
You either need a different name for the event, or you change the trigger so that it only fires when both the "ga_new" event are set and the data.uid field is set.
What I want to do is to set a variable to a value which is set by the first loop execution.
As background information: I'm using CollectionFS to upload multiple files in my meteor app. Now I want to set to all files (beside the first one) the custom field value parent to the id of the first inserted file.
I get the id by data._id.
My attempt:
As I'm using a loop for each uploaded file, I thought data is undefined for the first file, so I check if it has a value. In this case also parent would be undefined. For the second file, data is already set, so parent should get data._id as its value.
But this doesn't work properly, as parent is always undefined:
FS.Utility.eachFile(event, function (file) {
var newFile = new FS.File(file),
parent = (data) ? data._id : undefined;
newFile.metadata = { parent: parent };
var data = Images.insert(newFile);
console.log(data._id); // id of the inserted file
});
data is being redefined on every iteration. Declare it outside of the loop.
var data;
FS.Utility.eachFile(event, function(file) { ... });
Extending a Google Spreadsheet, I run a script showing some data in a sidebar. At the bottom I want to add a button to mail the data.
However I can't figure out how the data can be passed from button to handler:
There's no possibility to pass data into the event call;
There's no way to get the button object from the event info, I can merely get the ID, which is useless if I can't get to the uiInstance (created outside of the handler function).
So what's the trick?
You have to add a callback element (possibly a panel wrapping everything you need) to the server handler before assigning it to the button. For example:
function myFunction() {
var app = UiApp.createApplication();
var panel = app.createVerticalPanel();
panel.setId('myPanel').add(
app.createTextBox().setName('boxExample')).add(
app.createListBox().setName('listExample').addItem('A').addItem('B'));
// ↓↓ this is what you need ↓↓
var handler = app.createServerHandler('callbackFunction').addCallbackElement(panel);
var btn = app.createButton(btn, handler);
app.add(panel.add(btn));
//show app...
}
function callbackFunction(e) {
var app = UiApp.getActiveApplication();
app.getElementById('myPanel').add(
app.createLabel(e.parameter.boxExample)).add(
app.createLabel(e.parameter['listExample']));
return app;
}
Using PropertiesService
I found (I don't know how) Google Script offers a data storage service called PropertiesService.
Assuming, as in this case, the data is for user only, I would need to first store the data as such:
var userProperties = PropertiesService.getUserProperties()
userProperties.setProperty("myKey", "myValue")
// Note myValue will be a string, so to store an array,
// you'd need JSON.stringify(myArray)
Then as the button handler is called, the script can retrieve the data easily:
var userProperties = PropertiesService.getUserProperties()
var myValue = userProperties.getProperty("myKey")
Using Hidden Widget
An alternative seems to be the use of a "hidden" widget.
function doGet() {
var app = UiApp.createApplication();
// Note that the name "appState" for callbacks, and the id "hidden" for
// getting a reference to the widget, are not required to be the same.
var hidden = app.createHidden("appState", "0").setId("hidden");
app.add(hidden);
var handler = app.createServerHandler("click").addCallbackElement(hidden);
app.add(app.createButton("click me!", handler));
app.add(app.createLabel("clicked 0 times").setId("label"));
return app;
}
function click(eventInfo) {
var app = UiApp.createApplication();
// We have the value of the hidden field because it was a callback element.
var numClicks = Number(eventInfo.parameter.appState);
numClicks++;
// Just store the number as a string. We could actually store arbitrarily complex data
// here using JSON.stringify() to turn a JavaScript object into a string to store, and
// JSON.parse() to turn the string back into an object.
app.getElementById("hidden").setValue(String(numClicks));
app.getElementById("label").setText("clicked " + numClicks + " times");
return app;
}
(code from linked reference)
I am using Decarta JS API PIN event handler
I am displaying pins on a map and the click event for each pin is fired correctly. The trouble comes in when I try pass the pin id to the handler. It ALWAYS displays the last id loaded regardless of which pin is clicked on. My code for declaring the listener is:
for (var idx = 0; idx < jsonObjects.devices.length; idx++) {
var device = jsonObjects.devices[idx]
deCarta.Core.EventManager.listen('click', function() {home.pinPushed(device.id);}, device.pin);
}
This is done in a loop through all the locations I am displaying. They are displayed correctly at their respective coordinates, and logging the previous line clearly shows that each pin is declared with the correct id. However, whenever I click on a pin, the LAST id declared is the only id ever passed to the handler:
home.pinPushed(device.id)
How do I get each pin to pass the unique id when the pin is clicked?
Try this :
deCarta.Core.EventManager.listen('click',
(function(id) { return function (){home.pinPushed(id);}})(device.id), device.pin);
Beautify version :
deCarta.Core.EventManager.listen('click', (function (id)
{
return function ()
{
home.pinPushed(id); //<---- id here is the closured variable
}
})(device.id), device.pin);
Explanation :
Js has a function scope ( not braces ({}) scope.)
Your for loop is not creating ANY scope/function.
What I was doing is to create execution context for each iteration.
for each iteration im sending the current device.id to a function which in turn , returns another function which closured the variable.
I'm fetching a JSON response and with that response, I have two values:
Air shipment cost.
Land shipment cost.
I want to save those two values somewhere in the client so that when a user chooses either 1 radio button or the other, I add that value to another element on the page.
Here's what I'm doing:
<script type="text/javascript">
$(document).ready(function () {
var landCost;
var airCost;
$("#ddlCiudad").change(function () {
var idCity = $("#ddlCiudad").val();
$.getJSON("/ProductCheckout/GetPriceForLocation", { cityId: idCity, productId: idProduct, type: "land" },
function (cityData) {
console.log("Recieved json data."); //This part works. It outputs.
var data = $.parseJSON(cityData);
console.log("Parse JSON response."); //This part works. It outputs.
landCost = data.LandCost;
console.log("Assigned value of LandCost"); //FAILS HERE. nothing is shown. not even an error.
airCost = data.AirCost;
console.log("Assigned value of AirCost");
alert(landCost);
console.log("Alerted land!");
alert(airCost);
console.log("Alerted air!");
}
);
});
So what do you suggest? I need to have the values of this JSON response, available for usage on that page, if I declare the variable inside the change() event, it'll be out of scope.
{"DaysToShip":" TER = 48 Hrs / AER = 24 Hrs","LandCost":"25,00","AirCost":""}
try
landCost = cityData.LandCost;
If you really must use global variables, you can attach them directly to the window object.
window.airCost = cityData.AirCost;
Really though you want to have the json request and the 'radio button' handling in the same scope, so that you're not polluting the global namespace at all.
Your call to $.parseJSON() is returning null because the data passed to your callback has already been parsed to JSON.
var json = {LandCost:3, AirCost:5},
results = $.parseJSON(json);
console.log(results); // results == null
IF you want to globally declare your variables, either put them outside the jQuery closure ($(document).ready(function () {...});), or don't use var to declare them. If you don't use the var keyword the variable will default to a global.
Here is a jsfiddle of setting global variables without using the var keyword: http://jsfiddle.net/jasper/JWtbV/
Have you considered using jQuery's $.data() function to attached the values directly to the body element in the DOM and accessing it from there?
// Set Values
$('body').data('landCost', data.LandCost);
$('body').data('airCost', data.AirCost);
// Retrieve Values //
console.log($('body').data('landCost');
console.log($('body').data('airCost');
Hope it helps.