Undefined variable error in jQuery - json

I am getting a JSON data with jQuery in real-time, later I am printing this data to screen. When I get data from screen and I print this on screen again, I take error "undefined". Codes:
var yenile = setInterval(function() {
$.getJSON("ayarlar.asp",function(veri) {
$(".wfloodnum").html("Şu anki değer:" + veri.floodwarno);
$(".nfloodnum").html("Şu anki değer:" + veri.floodnum);
});
},100);
var anlikwar = $(".wfloodnum").text().split(":")[1];
var anlikflood = $(".nfloodnum").text().split(":")[1];
alert(anlikflood);
What should I do?
EDIT: I cant access this variables' values out of $.getJSON function. And I need accessibilty for these value out of this function. So, I must define variables out of $.getJSON function. That's why I tried to apply .split() to text on a screen.

The problem with your code is that, because of the asynchronous call you have there the order of execution might look like this (of course it can differ because of the interval and multiple calls to the getJSON):
// 1. the call to setInterval is initiated (the function in it will not be called until the sequential instructions after setInterval are finished)
var yenile = setInterval(function() {...}, 100);
// 2
var anlikwar = $(".wfloodnum").text().split(":")[1];
// 3
var anlikflood = $(".nfloodnum").text().split(":")[1];
// 4
alert(anlikflood);
// 5. NOW COMES THE function given to setInterval
$.getJSON("ayarlar.asp",function(veri) { ... });
// 6. now would come any other instructions in the function given to setInterval after the getJSON
// 7.
$(".wfloodnum").html("Şu anki değer:" + veri.floodwarno);
// 8
$(".nfloodnum").html("Şu anki değer:" + veri.floodnum);
In the above sequence you see that at steps 2 and 3 the variables there are undefined because the element you access does not have any text yet. Or, it has empty string, split is by : and you get the array [""] and therefore the index 1 in this array is undefined.
You must re-think the structure of your code. At least the variables anlikwar and anlikwar should be assigned after the JSON request completes.
At least you coud do something like:
var anlikwar;
var anlikflood;
var yenile = setInterval(function() {
$.getJSON("ayarlar.asp",function(veri) {
$(".wfloodnum").html("Şu anki değer:" + veri.floodwarno);
$(".nfloodnum").html("Şu anki değer:" + veri.floodnum);
anlikwar = $(".wfloodnum").text().split(":")[1];
// or simply: anlikwar = veri.floodwarno
anlikflood = $(".nfloodnum").text().split(":")[1];
// or simply: anlikflood = veri.floodnum
});
},100);
It looks like you want to monitor something on the server. This looks like a WebSockets use case. Depending on the server framework you are using, there are different web socket packages you can use.

Related

How do I add a dynamic phone number to the HTML5 phone number link href attribute?

For the telephone numbers on my site, I have the following HTML:
<span class="rTapNumber"></span>
The class here activates a script and a random number is inserted inside the span (for tracking purposes.
I want to use telephone links for mobile i.e. <a href="tel:01234567890"> but the number can't be hard-coded... how can I get the dynamic number that's used in the <span> to go into this href attribute?
The resulting code should be like this:
<span class="rTapNumber">01234567890</span>
Hope you can help.
I used the following (the rTapPostReplacement function is the function which gets called by responsetap after it's replaced all the numbers).
function rTapPostReplacement() {
// loop through all links which are using the HTML5 href="tel:000000" property
$('a[href*="tel:"]').each(function(){
// get the replaced text/number
var number = $(this).text();
// replace all spaces with nothing (in case the tel: property doesn't like spaces)
number = number.replace(/\s+/g, '').toLowerCase();
// update the href attribute to the replaced number
$(this).attr('href', 'tel:' + number);
});
}
UPDATE 6 April, 2016
I've since found out that this callback will only get called once (the first time ResponseTap replacements occur). This is because the default implementation of ResponseTap only replaces numbers which are visible on-screen. Any subsequent number replacements don't trigger the callback for whatever reason.
So the only way to make sure this works reliably, is to modify the ResponseTap tracking code so that:
adiRVO = false; // This is set to true by default
This replaces all numbers in the document at the same time, regardless of visibility.
So the full implementation looks like this
// The ResponseTap tracking code
var adiInit = "00000", adiRVO = false; // Set to false
var adiFunc = null;
(function() {
var adiSrc = document.createElement("script"); adiSrc.type = "text/javascript";
adiSrc.async = true;
adiSrc.src = ("https:" == document.location.protocol ? "https://static-ssl" : "http://static-cdn")
+ ".responsetap.com/static/scripts/rTapTrack.min.js";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(adiSrc, s);
})();
// The ResponseTap callback
function rTapPostReplacement() {
// loop through all links which are using the HTML5 href="tel:000000" property
$('a[href*="tel:"]').each(function(){
// get the replaced text/number
var number = $(this).text();
// replace all spaces with nothing (in case the tel: property doesn't like spaces)
number = number.replace(/\s+/g, '').toLowerCase();
// update the href attribute to the replaced number
$(this).attr('href', 'tel:' + number);
});
}
For some reason this question seems to still be hot despite being 6 years old, so here's my solution using the MutationObserver API
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
let observer = new MutationObserver(callback);
let observerOptions = {
childList: true,
attributes: false,
characterData: false,
subtree: false,
};
let node = document.getElementById('rTapNumber');
function callback(mutations) {
mutations.forEach(el => {
if(el.type === 'childList') {
document.querySelector('.responseTapLink').href = 'tel:' + el.target.innerText;
observer.disconnect();
}
});
}
observer.observe(node, observerOptions);
});
</script>
<a class="responseTapLink" href=""><span id="rTapNumber" class="rTapNumber00000">00000 000 000</span></a>
The general method is as follows
Add your <a> tag around the ResponseTap container with a unique class/ID
Give the responsetap container a unique ID so that we can get the Node Easily
Set up the Mutation Observer to watch the responsetap container for changes to the childList
When a mutation occurs (the new phone number being inserted), set the href of your <a> tag to the innerText of the responseTap container
Disconnect the observer

WinJS variable/object scope, settings, and events?

I am not sure what the proper heading / title for this question should be. I am new to WinJS and am coming from a .NET webform and winclient background.
Here is my scenario. I have a navigation WinJS application. My structure is:
default.html
(navigation controller)
(settings flyout)
pages/Home.html
pages/Page2.html
So at the top of the default.js file, it sets the following variables:
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var nav = WinJS.Navigation;
It seems like I cannot use these variables anywhere inside my settings flyout or any of my pages:ready functions. They are only scoped to the default.js?
In the same regard, are there resources on the interwebs (links) that show how to properly share variables, events, and data between each of my "pages"?
The scenario that I immediately need to overcome is settings. In my settings flyout, I read and allow the user to optionally set the following application setting:
var applicationData = Windows.Storage.ApplicationData.current;
var localSettings = applicationData.localSettings;
localSettings.values["appLocation"] = {string set by the user};
I want to respond to that event in either my default.js file or even one of my navigation pages but I don't know where to "listen". My gut is to listen for the afterhide event but how do I scope that back to the page where I want to listen from?
Bryan. codefoster here. If you move the lines you mentioned...
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var nav = WinJS.Navigation;
...up and out of the immediate function, they'll be in global scope and you'll have access to them everywhere. That's one of the first things I do in my apps. You'll hear warnings about using global scope, but what people are trying to avoid is the pattern of dropping everything in global scope. As long as you control what you put in there, you're fine.
So put them before the beginning of the immediate function on default.js...
//stuff here is scoped globally
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var nav = WinJS.Navigation;
(function () {
//stuff here is scoped to this file only
})();
If you are saving some data and only need it in memory, you can just hang it off the app variable instead of saving it into local storage. That will make it available to the whole app.
//on Page2.js
app.myCustomVariable = "some value";
//on Page3.js
if(app.myCustomVariable == "some value") ...
Regarding your immediate need:
like mentioned in the other answer, you can use datachanged event.
Regards sharing variables:
If there are variables that you would like to keep global to the application, they can be placed outside the anonymous function like mentioned in the Jeremy answer. Typically, that is done in default.js. Need to ensure that scripts using the global variables are placed after the script defining the global variable - in default.html. Typically - such variable will point to singleton class. For example: I use it in one of my apps to store authclient/serviceclient for the backend service for the app. That way - the view models of the multiple pages need not create instance of the object or reference it under WinJS namespace.
WinJS has also concept of Namespace which lets you organize your functions and classes. Example:
WinJS.Namespace.define('Utils.Http',
{
stringifyParameters: function stringifyParameters(parameters)
{
var result = '';
for (var parameterName in parameters)
{
result += encodeURIComponent(parameterName) + '=' + encodeURIComponent(parameters[parameterName]) + '&';
}
if (result.length > 0)
{
result = result.substr(0, result.length - 1);
}
return result;
},
}
When navigating to a page using WinJS.Navigation.navigate, second argument initialState is available as options parameter to the ready event handler for the page. This would be recommended way to pass arguments to the page unless this it is application data or session state. Application data/session state needs to be handled separately and needs a separate discussion on its own. Application navigation history is persisted by the winjs library; it ensures that if the app is launched again after suspension - options will be passed again to the page when navigated. It is good to keep the properties in options object as simple primitive types.
Regards events:
Typically, apps consume events from winjs library. That can be done by registering the event handler using addEventListener or setting event properties like onclick etc. on the element. Event handlers are typically registered in the ready event handler for the page.
If you are writing your own custom control or sometimes in your view model, you may have to expose custom events. Winjs.UI.DOMEventMixin, WinJS.Utilities.createEventProperties can be mixed with your class using WinJS.Class.mix. Example:
WinJS.Class.mix(MyViewModel,
WinJS.Utilities.createEventProperties('customEvent'),
WinJS.UI.DOMEventMixin);
Most often used is binding to make your view model - observable. Refer the respective samples and api documentation for details. Example:
WinJS.Class.mix(MyViewModel,
WinJS.Binding.mixin,
WinJS.Binding.expandProperties({ items: '' }));
Here is what I ended up doing which is kinda of a combination of all the answers given:
Created a ViewModel.Settings.js file:
(function () {
"use strict";
WinJS.Namespace.define("ViewModel", {
Setting: WinJS.Binding.as({
Name: '',
Value: ''
}),
SettingsList: new WinJS.Binding.List(),
});
})();
Added that file to my default.html (navigation container page)
<script src="/js/VMs/ViewModel.Settings.js"></script>
Add the following to set the defaults and start 'listening' for changes
//add some fake settings (defaults on app load)
ViewModel.SettingsList.push({
Name: "favorite-color",
Value: "red"
});
// listen for events
var vm = ViewModel.SettingsList;
vm.oniteminserted = function (e) {
console.log("item added");
}
vm.onitemmutated = function (e) {
console.log("item mutated");
}
vm.onitemchanged = function (e) {
console.log("item changed");
}
vm.onitemremoved = function (e) {
console.log("item removed");
}
Then, within my application (pages) or my settings page, I can cause the settings events to be fired:
// thie fires the oniteminserted
ViewModel.SettingsList.push({
Name: "favorite-sport",
Value: "Baseball"
});
// this fires the itemmutated event
ViewModel.SettingsList.getAt(0).Value = "yellow";
ViewModel.SettingsList.notifyMutated(0);
// this fires the itemchanged event
ViewModel.SettingsList.setAt(0, {
Name: "favorite-color",
Value: "blue"
});
// this fires the itemremoved event
ViewModel.SettingsList.pop(); // removes the last item
When you change data that needs to be updated in real time, call applicationData.signalDataChanged(). Then in the places that care about getting change notifications, listen to the datachanged on the applicationData object. This is also the event that is raised when roaming settings are synchronized between computers.
I've found that many times, an instant notification (raised event) is unnecessary, though. I just query the setting again when the value is needed (in ready for example).

How to Update the value of point in Highchart?

I have a Highchart that is receiving JSON data via AJAX and jQuery in setInterval function,when i use series.data[i].y = response[i].y , the value of y is change ,but dosent Display in chart and the hight of point has previous value but in tooltip show recent value ? and the x value dosent changhe at all, please help me how to update the the x and y value if it is changhed?
chart:{ renderTo: 'container',
zoomType: 'xy',
plotBackgroundImage: 'graphics/skies.jpg',
events: {
load: function () {
var series = this.series[0];setInterval(function () {ajax({type: "POST",url: "/Home/GetData",data: null),contentType: "application/json; charset=utf-8",success: function (response) { for (var i = 0; i < response.length; i++) { if (series.data[i].y =response[i].y || series.data[i].category != response[i].x) { series.data[i].y =response[i].y; series.data[i].category = response[i].x;} }}, dataType: "json",failure: ajaxCallFailed });}, 50000);}
You should not directly modify the this.series[0] object. Highcharts has api calls that you can use, which should be uses for correct results and not breaking anything unintentionally.
Here is a list of methods supported by the series object # http://www.highcharts.com/ref/#series-object
You may want to use addPoint or setData, as per your requirements.
I don't recommend doing it the say you are doing, but try calling the redraw method (this.redraw()) after you do your magic, http://www.highcharts.com/ref/#chart-object

JSON results into a variable and store in hidden input field

I wrote code below that is working perfectly for displaying the results of my sales tax calculation into a span tag. But, I am not understanding how to change the "total" value into a variable that I can work with.
<script type="text/javascript">
function doStateTax(){
var grandtotalX = $('#GRANDtotalprice').val();
var statetaxX = $('#ddl').val();
$.post('statetax.php',
{statetaxX:statetaxX, grandtotalX:grandtotalX},
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
// ...
});
return false;
};
</script>
Currently, $('.total-placeholder').html(data.total); is successfully placing the total number into here:
<span class="total-placeholder"></span>
but how would I make the (data.total) part become a variable? With help figuring this out, I can pass that variable into a hidden input field as a "value" and successfully give a proper total to Authorize.net
I tried this and id didn't work (see the testtotal part to see what I'm trying to accomplish)..
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
$testtotal = (data.total);
// ...
If you are using a hidden field inside a form, you could do:
//inside $.post -> success handler.
$('.total-placeholder').html(data.total);
$('input[name=yourHiddenFieldName]', yourForm).val(data.total);
This will now be submitted along with the usual submit. Or if you want to access the data elsewhere:
var dataValue = $('input[name=yourHiddenFieldName]', yourForm).val();
The "data" object you are calling can be used anywhere within the scope after you have a success call. Like this:
$.post('statetax.php',
{statetaxX:statetaxX, grandtotalX:grandtotalX},
function(data) {
data = $.parseJSON(data);
var total = data.total;
var tax = data.total * 0.19;
});
return false;
};
Whenever you get an object back always try to see with an alert() or console.log() what it is.
alert(data); // This would return <object> or <undefined> or <a_value> etc.
After that try to delve deeper (when not "undefined").
alert(data.total); // <a_value>?
If you want 'testotal' to be recognized outside the function scope, you need to define it outside the function, and then you can use it somewhere else:
var $testtotal;
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
$testtotal = (data.total);
EDIT:
The comments are becoming too long so i'll try and explain here:
variables defined in javascript cannot be accessed by PHP and vice versa, the only way PHP would know about your javascript variable is if you pass it that variable in an HTTP request (regular or ajax).
So if you want to pass the $testtotal variable to php you need to make an ajax request(or plain old HTTP request) and send the variable to the php script and then use $_GET/$_POST to retrieve it.
Hope that answers your question, if not then please edit your question so it'll be clearer.

Can't access XML data after first use using JQUERY html() or append()

I am setting up cycling quotes for a website, and I'm having trouble reloading the data when after it has already been used once.
I've set up a XML file with a bunch of data. The data includes a quote, an author, and the job title of the author (quote, author, title).
I then have a jQuery .ajax call and store it in the variable xmlData.
xmlData is then used to append or add html to specified id tags.
I am using setInterval() in order to move through the xml data.
The idea is to go through it in a loop like: 1 | 2 | 3| 1| 2 | 3 and so on. But when it comes back around, after the data has been appended to an ID, it doesn't show up anymore. It is as if the data was removed from the XML file.
Any help would be appreciated. Code is below, along with the website URL where I am working on the test.
<script language="javascript" type="text/javascript">
var xmlData;
var xmlFAILdata;
var nextE = 0;
var ttlE;
var quote;
var author;
var title;
$(function(){
$.ajax({
type: "GET",
url:"/wp-content/themes/privilegeofpersecution/endorsements.xml",
data: "",
dataType:"xml",
async: false,
success: function(xml){
//alert("XML SUCCESS!");
xmlData = xml;} ,
error: function(xmlFAIL){
alert("XML FAIL");
}
});
ttlE = $(xmlData).find('endorsement').length;
//Since .length return the number starting at 1 rather than 0 subtract 1 for accuracy
ttlE -= 1;
//On pageload, load in the first Endorsement into variables
quote = $(xmlData).find('endorsement').eq(0).children('quote');
author =$(xmlData).find('endorsement').eq(0).children('author');
title =$(xmlData).find('endorsement').eq(0).children('title');
//Append variables to id containers
$("#quote").html(quote);
$("#author").html(author);
$("#title").html(title);
//executes the function "next" which places the next endorsement
setInterval("next()", 5000);
});
function next(){
console.log('Next Function Started');
if(nextE >= ttlE){
nextE = 0;
}
else{
nextE++;
}
console.log('nextE = ' + nextE);
quote = $(xmlData).find('endorsement').eq(nextE).children('quote');
author =$(xmlData).find('endorsement').eq(nextE).children('author');
title =$(xmlData).find('endorsement').eq(nextE).children('title');
$("#quote").html(quote);
$("#author").html(author);
$("#title").html(title);
}
</script>
Here is the website: http://privilegeofpersecution.com/wp-content/themes/privilegeofpersecution/xmltest.html
I was able to fix the problem by adding .clone() to the variable assignment. This way I'm not just placing the XML object in the DOM and overwriting it. rather, I am copying the data from the XML each time I need it so that it stays in tact.
quote = $(xmlData).find('endorsement').eq(0).children('quote').clone();
author =$(xmlData).find('endorsement').eq(0).children('author').clone();
title =$(xmlData).find('endorsement').eq(0).children('title').clone();