I have a code to put two cameras on my site:
$(document).ready(function(){
var m;
var index;
var IP;
var port;
var name;
var user;
var password;
var image_old;
var image_new;
var cameraFeed;
var topImage;
var urls = [];
$.ajax({
type: "GET",
url: "json.htm?type=cameras",
dataType: "JSON",
async : false,
success: function(data) {
for(m=0; m<=1; m++){
index = data.result[m].idx;
IP = data.result[m].Address;
port = data.result[m].Port;
name = data.result[m].Name;
user = data.result[m].Username;
password = data.result[m].Password;
image_old = data.result[m].ImageURL;
image_new = image_old.replace("#USERNAME", user).replace("#PASSWORD", password);
cameraFeed = "http://" + IP + ":" + port + "/" + image_new;
alert(cameraFeed + m);
urls.push(cameraFeed);
}
setInterval(function() {
var d = Date.now();
$.each(urls, function(i, url) {
$('#topImage' + i).attr('src', url + "×tamp=" + d);
});
}, 100);
},
error: function(data) {
alert("Error")
}
});
});
And html code:
<img id="topImage0" width="640px">
<img id="topImage1" width="640px">
I can not create a script to make setinterval work for both imgs. It works only for one of them. Any suggestions how to make it works ?
Set interval works only for one img.
To give you an idea how to structure your application code:
Get the data from the server
Create the URLs from data
Update each image every X milliseconds with those URLs
In code:
$.ajax({...}).done(function(data) { // get data from server
// create URLs
var urls = [];
for (var m = 0; m < 2; m++) { // why not iterate over data.results?
var cameraFeed;
// build cameraFeed ...
urls.push(cameraFeed);
}
// Update images
setInterval(function() {
var d = Date.now();
$.each(urls, function(i, url) {
$('#topImage' + i).attr('src', url + "×tamp=" + d);
});
}, 100);
});
Of course this can still be approved, but that should point you into the right direction. Note in particular that it is unnecessary to have a setInterval for each image. Just let a single interval update all images.
Especially the for loop can be approved upon. I don't know how many results data.results has and if you only want to get the first two, but this is an excellent use case for Array#map:
var urls = data.results.map(function(result) {
// ...
return cameraFeed;
});
Related
I have an html table on a page with raws that have 'urls', I'm trying to fetch one url at a time from a random row, however my code returns url as http://www.test.com/products/product-namehttp://www.test.com/products/product-name.json, as you can see it returns url twice, one without json and other with json data, hence I'm getting 404.
I just need the .json URL, not the first part.
How do I get rid of the first url which is not json?
Here's the code.
$(document).ready(function() {
$(document).on('click', '#closepopup', function() {
$("#popup").removeClass('popupslidein')
});
var tablelink = "https://test.com/pages/product-listing-for-popups.json"; //products url for json data
$.getJSON(tablelink, function(data) {
var table = data.page.body_html;
$('#popuptable').append(table);
startthepopups()
});
var suburbink = "https://test.com/pages/product-listing-suburbs-for-popups"; //suburb names in table rows
$.getJSON(suburbink, function(data) {
var suburb = data.page.body_html;
$('#popupsuburb').append(suburb)
});
var namelink = "https://test.com/pages/product-listing-names-for-popups"; //names in table rows
$.getJSON(namelink, function(data) {
var name = data.page.body_html;
$('#popupname').append(name)
});
function startthepopups() {
var popupstay = 10000;
var popuptrigger = 100000;
function triggerpopup() {
var getrandomtd = Math.floor((Math.random() * $('#popuptable tr').length) + 1);
var link = $('#popuptable tr:nth-child(' + getrandomtd + ')').text();
console.log(link);
var productname = '';
var getrandomsuburbtd = Math.floor((Math.random() * $('#popupsuburb tr').length) + 1);
var suburblink = $('#popupsuburb tr:nth-child(' + getrandomsuburbtd + ')').text();
var getrandomnametd = Math.floor((Math.random() * $('#popupname tr').length) + 1);
var randomname = $('#popupname tr:nth-child(' + getrandomnametd + ')').text();
$.getJSON(link + '.json', function(data) {
productname = data.product.title;
imagelink = data.product.images[0].src;
if (!$("#popup").hasClass("popupslidein")) {
$('#popupsomeone span.name').empty().append(randomname);
$('#popupsomeone span.location').empty().append(suburblink);
$('#popupimage').css('background-image', 'url(' + imagelink.split('.jpg')[0] + '_small.jpg)');
$('#popupproduct a').attr('href', link).empty().append(productname);
$("#popupagotext").empty().append(Math.round(Math.random() * 15 + 10));
$("#popup").addClass('popupslidein');
setTimeout(function() {
$("#popup").removeClass('popupslidein')
}, popupstay);
}
});
}(function loop() {
var random = Math.round(Math.random() * 10) * 100000 + popuptrigger;
setTimeout(function() {
triggerpopup();
loop()
}, 60000)
}());
}
});
$.getJSON() has a tendency to append your current url to the path you pass it if it thinks it's relative. To make this work, you could try to use $.getJSON() like so. Keep in mind, the protocol used will be the current page this code lives on.
$.getJSON('//test.com/pages/product-listing-for-popups.json')
I also noticed that nowhere in your code do you have a url for http://www.test.com/products/product-name.json, are you sure you're sharing the correct snippet of code?
Working Demo
The following two ways of using $.getJSON() with a fully qualified url work perfectly fine:
$(document).ready(function() {
var url = "https://jsonplaceholder.typicode.com/todos/1";
// Example 1
$.getJSON(url)
.done(function( data ) {
console.log(data);
});
// Example 2
$.getJSON(url, function(data) {
console.log(data)
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I am trying to display several images(PrinurlonPage) that are contained in an array and also position them on the page randomly. I have two issues,
The first and most important is that I cant get the images to display on IE when I look the source attribute on developer tools I just see undefined whereas in chrome I get the full URL that was passed. I was wondering if there was something wrong with the order in which the script was being run that was causing the problem.
The second question is about positioning the images randomly on the page and also prevent overlapping, I would like to know how can I achieve this, what I have implemented at the moment in some iterations the pictures overlap.
I would appreciate any suggestion on this
var getIndividualPersonDetails = function(GetPictureUrl, printurlonPage, getRandom) {
listName = 'TeamInfo';
var PeopleCompleteList = [];
var personName, userName, UserTitle, UserphoneNumber, UserEmail, Id, myuserPicture;
// execute AJAX request
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items?$select=Name/Title,Name/Name,Name/Id,Name/EMail,Name/WorkPhone&$expand=Name/Id",
type: "GET",
headers: {
"ACCEPT": "application/json;odata=verbose"
},
success: function(data) {
for (i = 0; i < data.d.results.length; i++) {
//check if the user exists if he does store the following properties name,title,workphone,email and picture url
if (data.d.results[i]['Name'] != null) {
personName = data.d.results[i]['Name'].Name.split('|')[2];
userName = data.d.results[i]['Name']['Name'];
UserTitle = data.d.results[i]['Name']['Title'];
UserphoneNumber = data.d.results[i]['Name']['WorkPhone'];
UserEmail = data.d.results[i]['Name']['EMail'];
Id = data.d.results[i]['Name']['Id'];
myuserPicture = GetPictureUrl(userName);
PeopleCompleteList.push(PersonConstructor(personName, UserTitle, UserphoneNumber, UserEmail, myuserPicture, Id));
}
}
PeopleObject = PeopleCompleteList;
PrinturlonPage(PeopleCompleteList, getRandom);
},
error: function() {
alert("Failed to get details");
}
});
}
//print all the image links in the peopleCompleteList array and then position them randomly on the page
var PrinturlonPage = function(PeopleCompleteList, getRandom) {
var imageList = [];
for (i = 0; i < PeopleCompleteList.length; i++) {
var top = getRandom(0, 400);
var left = getRandom(0, 400);
var right = getRandom(0, 400);
imageList.push('<img style="top:' + top + ';right:' + right + '" id="image' + PeopleCompleteList[i]['UserId'] + '" alt="' + PeopleCompleteList[i]['Title'] + '"class="imgCircle" src="' + PeopleCompleteList[i]['Picture'] + '"/>');
//imageList +='<img class="img-circle" src="'+PeopleCompleteList[i]['Picture']+ '"/>'
}
var imagesString = imageList.join().replace(/,/g, "");
$('#imageList').append(imagesString);
}
//funtion retrieves the picture
function GetPictureUrl(user) {
var userPicture="";
var imageurls="";
var requestUri = _spPageContextInfo.webAbsoluteUrl +
"/_api/SP.UserProfiles.PeopleManager/GetPropertiesFor(accountName=#v)?#v='"+encodeURIComponent(user)+"'";
$.ajax({
url: requestUri,
type: "GET",
async:false,
headers: { "ACCEPT": "application/json;odata=verbose" },
success: function (data) {
console.log(data);
var loginName = data.d.AccountName.split('|')[2];
console.log(loginName);
var PictureDetails = data.d.PictureUrl != null ? data.d.PictureUrl : 'https://xxxcompany/User%20Photos/Profile%20Pictures/zac_MThumb.jpg?t=63591736810';
imageurls = data.d.PersonalSiteHostUrl+'_layouts/15/userphoto.aspx?accountname='+ loginName+ '&size=M&url=' + data.d.PictureUrl;
userPicture1=imageurls;
}
});
return userPicture1;
}
var getRandom = function(x, y) {
return Math.floor(Math.random() * (y - x)) + x + 'px';
};
$(function() {
getIndividualPersonDetails(GetPictureUrl, PrinturlonPage, getRandom);
$(document).on('click', '.imgCircle', function() {
var theName = jQuery(this).attr('Id');
pullUserObject(theName);
//console.log(theId);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="imageList"></div>
I am developing an web app in which the user will be able to identify the location from map by clicking on the map (I use jquery 3.1). The problem is that I have to make some ajax calls, one depend on other, and on the last call the result it's not returned as a whole (full array) and I received only a part of array.
The problem survives from var a4.
How I can make that a4 result to be send as a full array because I tried with deferred but with no expecting result?
var getLocDetails = function () {
// Parse a web api based on user lat & lon
var a1 = $.ajax({
method: 'GET',
url: 'http://nominatim.openstreetmap.org/reverse?lat=44.43588&lon=26.04745&accept-language=ro&format=json'
});
// Get osm_type & osm_id and parse another web service to get a XML document (Ex.: https://www.openstreetmap.org/api/0.6/way/28240583)
var a2 = a1.then(function (data) {
return $.ajax({
method: 'GET',
url: 'https://www.openstreetmap.org/api/0.6/' + data.osm_type + '/' + data.osm_id
})
});
// Get all 'ref' attribute from every 'nd' node from XML and make an array with this values
var a3 = a2.then(function (data) {
var osmChildren = data.documentElement.childNodes;
var out = [];
for (var i = 0; i < osmChildren.length; i++) {
if (osmChildren[i].nodeName == 'way') {
var wayChildren = osmChildren[i].childNodes;
for (var j = 0; j < wayChildren.length; j++) {
if (wayChildren[j].nodeName == 'nd') {
var ndRef = Number.parseInt(wayChildren[j].getAttribute('ref'));
out.push(ndRef);
}
}
}
}
return out;
});
// HERE IS THE PROBLEM
// Based on array returned from a3, I am parsing every link like 'https://www.openstreetmap.org/api/0.6/node/ + nodeRef' to extract every lat and lon values for extreme points
var a4 = a3.then(function (data) {
var defer = $.Deferred();
var out = [];
for (var i = 0; i < data.length; i++) {
var nodeRef = data[i];
var nodeUrl = 'https://www.openstreetmap.org/api/0.6/node/' + nodeRef;
$.ajax({
method: 'GET',
url: nodeUrl
}).done(function (response) {
var node = response.documentElement.firstElementChild;
var lat = Number.parseFloat(node.getAttribute('lat'));
var lng = Number.parseFloat(node.getAttribute('lon'));
out.push([lat, lng]);
defer.resolve(out);
});
}
return defer.promise();
});
// When a4 is done, based his result, I have to have an array of lat & lon coordonates, but I recived only 1-2 coordonates even I have 10.
a4.done(function (data) {
console.log(data);
// Here I have to draw a polygon
});
}
you need to handle the requests in an array, as what you are doing tends to resolve the callback for a4 before all are complete.
To do this we can use $.when function
var req = [];
// Based on array returned from a3, I am parsing every link like 'https://www.openstreetmap.org/api/0.6/node/ + nodeRef' to extract every lat and lon values for extreme points
var a4 = a3.then(function (data) {
var defer = $.Deferred();
var out = [];
for (var i = 0; i < data.length; i++) {
var nodeRef = data[i];
var nodeUrl = 'https://www.openstreetmap.org/api/0.6/node/' + nodeRef;
req.push(
$.ajax({
method: 'GET',
url: nodeUrl
}).done(function (response) {
var node = response.documentElement.firstElementChild;
var lat = Number.parseFloat(node.getAttribute('lat'));
var lng = Number.parseFloat(node.getAttribute('lon'));
out.push([lat, lng]);
})
);
}
$.when.apply($, req).done(function(){
return defer.resolve(out);
});
return defer.promise();
});
I'm using a tableau web connector to download stock price. The source code is following:
<html>
<meta http-equiv="Cache-Control" content="no-store" />
<head>
<title>Stock Quote Connector-Tutorial</title>
<script src="https://connectors.tableau.com/libs/tableauwdc-1.1.1.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
(function() {
function buildUri(tickerSymbol, startDate, endDate) {
var startDateStr = getFormattedDate(startDate);
var endDateStr = getFormattedDate(endDate);
var queryStatement = 'select * from yahoo.finance.historicaldata where symbol = "' +
tickerSymbol +
'" and startDate = "' + startDateStr +
'" and endDate = "' + endDateStr + '"';
var uri = 'http://query.yahooapis.com/v1/public/yql?q=' +
encodeURIComponent(queryStatement) +
"&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json";
return uri;
}
function getFormattedDate(date) {
// Return a date in the format YYYY-MM-DD
return date.getUTCFullYear() +
'-' +
makeTwoDigits(date.getUTCMonth() + 1) +
'-' +
makeTwoDigits(date.getUTCDate());
}
function makeTwoDigits(num) {
// Pad a digit to be two digits with leading zero
return num <= 9 ? "0" + num.toString() : num.toString();
}
var myConnector = tableau.makeConnector();
myConnector.getColumnHeaders = function() {
var fieldNames = ['Ticker', 'Day', 'Close'];
var fieldTypes = ['string', 'date', 'float'];
tableau.headersCallback(fieldNames, fieldTypes);
}
myConnector.getTableData = function(lastRecordToken) {
var dataToReturn = [];
var hasMoreData = false;
// Get parameter values and build YQL query
var ticker = tableau.connectionData;
var endDate = new Date();
var startDate = new Date();
startDate.setYear(endDate.getFullYear() - 1);
//startDate.setYear(startDate.getFullYear() - 1);
//startDate.setYear(startDate.getFullYear() - 1);
//startDate.setYear(startDate.getFullYear() - 1);
var connectionUri = buildUri(ticker, startDate, endDate);
var xhr = $.ajax({
url: connectionUri,
dataType: 'json',
success: function (data) {
if (data.query.results) {
var quotes = data.query.results.quote;
var ii;
for (ii = 0; ii < quotes.length; ++ii) {
var entry = {'Ticker': quotes[ii].Symbol,
'Day': quotes[ii].Date,
'Close': quotes[ii].Close};
dataToReturn.push(entry);
}
tableau.dataCallback(dataToReturn, lastRecordToken, false);
}
else {
tableau.abortWithError("No results found for ticker symbol: " + ticker);
}
},
error: function (xhr, ajaxOptions, thrownError) {
tableau.log("Connection error: " + xhr.responseText + "\n" + thrownError);
tableau.abortWithError("Error while trying to connect to the Yahoo stock data source.");
}
});
}
tableau.registerConnector(myConnector);
})();
$(document).ready(function() {
$("#submitButton").click(function() {
var tickerSymbol = $('#ticker').val().trim();
if (tickerSymbol) {
tableau.connectionName = "Stock Data for " + tickerSymbol;
tableau.connectionData = tickerSymbol;
tableau.submit();
}
});
});
</script>
</head>
<body>
<p>Enter a stock ticker symbol: <input type="text" id="ticker" /></p>
<p><button type="button" id="submitButton">Get the Data</button></p>
</body>
</html>
The code is workable when we just want to download 1 year data, but if we change the time longer than 1 year(enddate.year - startdate.year > 1), it is not workable.
After debugging the code, I found the issue comes from YQL query:
http://query.yahooapis.com/v1/public/yql?q=select * from yahoo.finance.historicaldata where symbol = "AAPL" and startDate = "2014-08-24" and endDate = "2016-11-23"&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json
when startDate = "2014-08-24" and endDate = "2016-11-23" is longer than 15 month, YQL will return null. I'm trying to fix this issue. If it is python or java, the problem is not hard, first check whether the duration is longer than 1 year, if so, get 1 year result and do the same for rest n-1 year. But this tableau code makes me stuck with it. I have to make the code workable with tableau, which makes me unable to proceed due to lack of knowledge about both js and tableau.
Can any one advise on this issue? My objective is to make the code workable for >10 years for stock symbol like AAPL.
Thanks in advance.
I don't believe YQL supports queries for longer than 15 months or so. Limits like these are fairly common when working with APIs. What you want to do from a web data connector standpoint is to implement paging.
The high level idea is that your getTableData function of your WDC will execute multiple times, and each time, it will gather a single page of data, which is then passed to Tableau. For example, here's how you could get multiple years worth of data in your example:
myConnector.getTableData = function(lastRecordToken) {
var dataToReturn = [];
var hasMoreData = false;
// Get parameter values and build YQL query
var ticker = tableau.connectionData;
var endDate = new Date();
var startDate = new Date();
var maxYear = 5;
var yearOffset = lastRecordToken || 0;
endDate.setYear(endDate.getFullYear() - (yearOffset));
startDate.setYear(endDate.getFullYear() - 1);
var connectionUri = buildUri(ticker, startDate, endDate);
var xhr = $.ajax({
url: connectionUri,
dataType: 'json',
success: function (data) {
if (data.query.results) {
var quotes = data.query.results.quote;
var ii;
for (ii = 0; ii < quotes.length; ++ii) {
var entry = {'Ticker': quotes[ii].Symbol,
'Day': quotes[ii].Date,
'Close': quotes[ii].Close};
dataToReturn.push(entry);
}
var hasMoreData = !(yearOffset == maxYear);
tableau.dataCallback(dataToReturn, yearOffset + 1, hasMoreData)
}
else {
tableau.abortWithError("No results found for ticker symbol: " + ticker);
}
},
error: function (xhr, ajaxOptions, thrownError) {
tableau.log("Connection error: " + xhr.responseText + "\n" + thrownError);
tableau.abortWithError("Error while trying to connect to the Yahoo stock data source.");
}
});
}
tableau.registerConnector(myConnector);
})();
This example uses the two extra parameters of the dataCallback function to implement paging. The documentation for paging in v1 of the web data connector API can be found here: http://onlinehelp.tableau.com/current/api/wdc/en-us/help.htm#WDC/wdc_paging.htm%3FTocPath%3DAdditional%2520Concepts%7C_____2
Additionally, if you are able to use v2 of the WDC API (usable in Tableau 10 and later), I would highly recommend it. The paging model in V2 is more flexible and easier to use.
I have the following javascript code having class named as PurchaseHistory.
var baseUrl = null;
var parameters = null;
var currentPageNumber = null;
var TotalPages = null;
var PageSize = null;
$(document).ready(function () {
baseUrl = "http://localhost/API/service.svc/GetOrderHistory";
parameters = '{"userId":1 , "page":1 ,"pageSize":4}';
currentPageNumber = 1;
var history = new PurchaseHistory();
history.ajaxCall(parameters);
});
function PurchaseHistory() {
/* On ajax error show error message
-------------------------------------------------*/
this.onAjaxError = function() {
$('#error').text('No internet connection.').css('color', 'red');
}
/* Ajax call
-------------------------------------------------*/
this.ajaxCall = function (parameters) {
$.support.core = true;
$.ajax({
type: "POST",
url: baseUrl,
data: parameters,
//dataType: 'json',
contentType: "application/json; charset=UTF-8",
error: function () { this.onAjaxError() }
}).done(function (data) {
var json = data.GetOrderHistoryResult;
var jsonObject = $.parseJSON(json);
var history = new PurchaseHistory();
history.populateOrderHistory(jsonObject);
TotalPages = jsonObject.PgCnt;
currentPageNumber = jsonObject.CrntPg;
});
}
this.populateOrderHistory = function(results) {
var rowOutput = "";
var his = new PurchaseHistory();
for (var i = 0; i < results.Results.length; i++) {
rowOutput += this.renderCartList(results.Results[i], 1);
}
}
this.renderCartList = function(res, i) {
var container = $('#prototype-listelement>li').clone();
container.find('.order-date').text(res.OdrDate);
container.find('.item-count').text(res.Qty);
container.find('.total').text(res.Amt);
container.find('.order-id').text(res.OdrId);
$('#mainul').append(container).listview('refresh');
}
this.loadNextPage = function () {
parameters = '{"userId":1 , "page":' + currentPageNumber + 1 + ',"pageSize":4}';
this.ajaxCall(parameters);
}
}
The ajaxCall is made on the ready function of the javascript.
This ajax calls returns Json object with pages information, which includes current page number, total pages and page size.
Currently I am able to display the information on the UI, when the page gets loaded.
My Issue:-
I want to call the ajax method again, on the button click event.
How this can be made possible and where can I store the information obtained from previous ajax call?
For pagination I would create a link that will load more items onto the page, and save a starting number to pass to your data layer. This example loads 20 at a time.
<a class="more" href="#" data-start="0">show more</a>
$("a.more").click(function(e){
e.preventDefault();
var start = $(this).attr('data-start');
$.get('/more-data, { start: start }, function(d){
var next = start+20;
$("a.more").attr('data-start', next);
//process results here, do something with 'd'
});
});