on line 30 i am facing an issue with $.each(data.menu, function (). I am being told by the console that "data is null". can anyone explain whats going on? thanks
function getFoodMenuData () {
var url = 'http://localhost:8888/Tom_Carp_Final_Project/Chorizios/foodMenu.json';
$.getJSON(url, function (data) {
window.localStorage.setItem('choriziosMenu333', JSON.stringify(data));
});
}
function showFoodMenuData () {
var data = JSON.parse(window.localStorage.getItem('choriziosMenu333'));
var images = "";
$.each(data.menu, function () {
images += '<li class="list-group-item"><img style="width: 100%;" src= "' + this.url + '"></li>';
images += '<li class="list-group-item">' + this.description + '</li>';
});
$('#foodMenu').append(images);
}
showFoodMenuData();
You have to call getFoodMenuData(), and then inside the callback for the asynchronous $.getJSON, call showFoodMenuData().
function getFoodMenuData() {
var url = 'http://localhost:8888/Tom_Carp_Final_Project/Chorizios/foodMenu.json';
$.getJSON(url, function(data) {
window.localStorage.setItem('choriziosMenu333', JSON.stringify(data));
showFoodMenuData(); // <--- call this inside the callback
});
}
function showFoodMenuData() {
var data = JSON.parse(window.localStorage.getItem('choriziosMenu333'));
var images = "";
$.each(data.menu, function() {
images += '<li class="list-group-item"><img style="width: 100%;" src= "' + this.url + '"></li>';
images += '<li class="list-group-item">' + this.description + '</li>';
});
$('#foodMenu').append(images);
}
getFoodMenuData(); // <--- call this first
I wouldn't use $ for the loop. I am not sure of the structure of the data you are receiving but you will probably need a nested loop to get all the data either way this should do the trick.
As a point the for in loop works great for objects. One reason is that the iterator is the key in the object. In this example if you console.log( ii ) inside the second loop you will see either name or url.
HTML
<ul></ul>
Javascript
var menu = {
item1 : {
name : "Food1",
url : "https://s-media-cache-ak0.pinimg.com/736x/79/82/de/7982dec0cc2537665a5395ac18c2accb.jpg"
},
item2 : {
name : "Food2",
url : "http://i.huffpost.com/gen/1040796/images/o-CANADIAN-FOODS-facebook.jpg"
}
};
$( document ).ready( function () {
for ( var i in menu ) {
for ( var ii in menu[ i ] ) {
var elem = ii === "name" ? "<p>" + menu[ i ][ ii ] + "</p>" : "<img src=" + menu[ i ][ ii ] + " height='100px'/>"
$( "ul" ).append( "<li>" + elem + "</li>" );
}
}
});
https://jsfiddle.net/dh3ozpxk/
Related
I'm trying to display RSS using the following JS code. But when I execute this, both the RSS feeds are changed to same content (the one that is execute later) and all the feeds are appended to the same div. I think rss = this is causing the problem. Any workaround ?
HTML:
<div id="rss1" class="rss-widget">
<ul></ul>
</div>
<div id="rss2" class="rss-widget">
<ul></ul>
</div>
<div id="rss3" class="rss-widget">
<ul></ul>
</div>
JS:
function RSSWidget(id, url) {
rss = this;
rss.FEED_URL = url;
rss.JSON = new Array();
rss.widgetHolder = $('#' + id + ' ul ');
rss.storiesLimit = 15;
rss.renderBlogItem = function (object) {
var item = '<li class="blog-item">';
item += '<a href="' + object.link + '">';
item += '<div class="blog-item-title">' + object.title + '</div>';
item += '<div class="blog-item-author">' + object.author + '</div>';
// item += '<div class="blog-item-content">' + object.content + '</div>';
item += '</a>'
item += '</li>';
rss.widgetHolder.append(item);
}
return $.ajax({
url: 'http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=10&callback=?&q=' + encodeURIComponent(rss.FEED_URL),
dataType: 'json',
success: function (data) {
if (data.responseData.feed && data.responseData.feed.entries) {
$.each(data.responseData.feed.entries, function (i, e) {
rss.JSON.push({ //add objects to the array
title: e.title,
author: e.author,
content: e.content || "",
link: e.link
});
});
if (rss.storiesLimit > rss.JSON.length)
rss.storiesLimit = rss.JSON.length;
for (var i = 0; i < rss.storiesLimit; i++) {
rss.renderBlogItem(rss.JSON[i]);
}
$('#' + id + ' li ').each(function () {
var delay = ($(this).index() / rss.storiesLimit) + 's';
$(this).css({
webkitAnimationDelay: delay,
mozAnimationDelay: delay,
animationDelay: delay
});
});
}
}
});
}
$.when(RSSWidget('rss1', "http://rss.cnn.com/rss/money_markets.rss"))
.then(function () {
RSSWidget('rss2', "http://feeds.reuters.com/reuters/financialsNews")
})
.then(function () {
RSSWidget('rss3', "http://finance.yahoo.com/rss/topfinstories")
});
.then(RSSWidget('rss2', "http://feeds.reuters.com/reuters/financialsNews"));
is immediately invoked. Try calling second RSSWidget within .then() anonymous function
.then(function() {
RSSWidget('rss2', "http://feeds.reuters.com/reuters/financialsNews")
})
Also, no promise is returned from RSSWidget; you can include return $.ajax(/* settings */) from RSSWidget to return the jQuery promise object from RSSWidget.
I'm looking to create an exception which creates 2 groupds based on their .php ID numbers.
I currently have a form that fills a table of images, and want to split them into groups using javascript.
currently the script looks like this:
var currentResults;
function init() {
getProducts();}
function getProducts() {
$.ajax({
url:"php/products.php",
dataType: "json",
data: { public: true },
success:function(result){
processResults(result);
}
});}
function processResults(results) {
currentResults = null;
if (!results && !results.products)
return;
currentResults = results.products;
for (var i = 0; i < results.products.length; i++) {
processResult(results.products[i]);}
$(".galleryitem").click(handleThumbnailClick);}
function processResult(result) {
var newDiv = '<div id="galleryitem' + result.id + '" class="galleryitem">';
newDiv += '<div class="imageHover" style="background: ' + result.color + '"> </div>';
newDiv += '<img class="galleryImage" src="' + encodeImagePath(result.thumbnail) + '" />';
if (result.artist)
newDiv += '<div class="imageArtist">' + result.artist + '</div>';
newDiv += '</div>';
$('#gallery').append(newDiv);}
function handleThumbnailClick(e) {
if (!e || !e.currentTarget || !e.currentTarget.id)
return;
var id = e.currentTarget.id.substring(11);
window.location = 'product.php?id=' + id;}
function encodeImagePath(path) {
return path.replace(/#/g, '%23');}
I am looking for some simple advice on how to split this into multiple div's based on the product's ID number to do sections of 6 images at a time with different header text.
please advise!! thanks much!
Not sure if I got your idea right but something like this should solve your problem (in case you have a "parent" property in the products JSON you're getting from the server):
function processResult(result) {
if (typeof(result.parent) !== 'undefined') { // see if the element has a parent
var newDiv = 'markup goes here'; // if some of the markup would be reused you can create a new function for this
$('#galleryitem' + result.parent).append(newDiv); // just make sure the parent is already there
} else {
var newDiv = '<div id="galleryitem' + result.id + '" class="galleryitem">'; // default behavior that you alreay had
// code skipped for brevity
$('#gallery').append(newDiv);
}
}
P.S. You should work on your code formatting -- it can be much easier to read if formatted well.
I'm trying to populate an array in JavaScript using an anonymous function in the jQuery getJSON() function as follows.
$(document).ready(function() {
function Link(url, title) {
this.url = url;
this.title = title;
}
var links = [];
$.getJSON("http://reddit.com/r/programming/.json?jsonp=?", function(data) {
$.each(data.data.children, function(i, item) {
var title = item.data.title;
var url = item.data.url;
links.push(new Link(url, title));
})
});
for(var i=0; i< links.length; i++) {
var output = "<a href='" + k + "'>" + links[k] + "</a>";
$('<p>' + link + '</p>').appendTo('#content');
}
});
But, when I hit the for loop, the links array shows up empty. What's going on here?
Try that :
$(document).ready(function() {
function Link(url, title) {
this.url = url;
this.title = title;
}
$.getJSON("http://reddit.com/r/programming/.json?jsonp=?", function(data) {
var links = [];
$.each(data.data.children, function(i, item) {
var title = item.data.title;
var url = item.data.url;
links.push(new Link(url, title));
})
for(var i=0; i< links.length; i++) {
var output = "<a href='" + k + "'>" + links[k] + "</a>";
$('<p>' + link + '</p>').appendTo('#content');
}
});
});
Your loop was probably executed before your callback ;)
That's because $.getJSON is an asynchronous method. The code execution continues even after $.getJSON and reaches the for loop, by which time, your async request hasn't completed yet. You should move the loop within $.getJSON.
This jsFiddle http://jsfiddle.net/cArYg/2/ shows the iteration occuring before the getJson callback
Buildgames returns rows:
<a>....</a>
<a>....</a>
When I click on each a the Buildcar_s function returns all the data inside an alert.
Instead of this alert I want to put all the results in a div under each a, so it would look like:
<a>.....clicked ...</a>
<div>....
...
</div>
<a>....not clicked...</a>
<a>....not clicked...</a>
<a>....not clicked...</a>
How can we put a div only under the a which was clicked?
function Buildcar_s(items) {
var div = $('<div/>');
$.each(items, function() {
var car_ = this.car_;
$('<a>' + this.car_ + '----' + this.Names + '---' + '</a>').click(function() {
_Services.invoke({
method: 'GetgamesRows',
data: {
car_Number: car_
},
success: function(car_s) {
var div = Buildgames(car_s);
$(div).insertAfter($a);
}
});
}).appendTo(div);
$('<br/>').appendTo(div);
});
$("#leftRows").append(div);
}
function Buildgames(items) {
var place = '<div>';
$.each(items, function() {
place += 'mmmmmm<br/>';
});
place += '</div>';
return place;
}
Try this, relevant changes have been commented:
function Buildcar_s(items) {
var div = $('<div/>');
$.each(items, function() {
var car_ = this.car_;
$('<a>' + this.car_ + '----' + this.Names + '---' + '</a>').click(function() {
var $a = this;
_Services.invoke({
method: 'GetgamesRows',
data: {
car_Number: car_
},
success: function(car_s) {
var div = Buildgames(car_s);
// this inserts the HTML generated from the function,
// under the A element which was clicked on.
$(div).insertAfter($a);
}
});
}).appendTo(div);
$('<br/>').appendTo(div);
});
$("#leftRows").append(div);
}
function Buildgames(items) {
var place = '<div>';
$.each(items, function() {
place += '<div style="float: right;"> ' + this.CITY + ' ' + '</div><BR />' + +'<br/><br/>';
});
place += '</div>';
return place; // returns the string created, as opposed to alerting it.
}
Is there a better, more concise way to do this:
function getTweets(){
$.getJSON("http://search.twitter.com/search.json?callback=?&q=superfad",
function(data){
tweetsLoaded = true;
$.each(data.results, function(i,item){
var textPlain = item.text;
var textLinked = linkify(textPlain);
var textHashed = hashify(textLinked);
var textListed = listify(textHashed);
function linkify(tweet){
return tweet.replace(/(http:\/\/[^\s]*)/g, "<a class='twtr-link' target=\"_blank\" href=\"$1\">$1</a>");
}
function hashify(tweet){
return tweet.replace(/(^|\s+)#(\w+)/gi, function(m, before, hash) {
return before + '<a target="_blank" class="twtr-hashtag" href="http://twitter.com/search?q=%23' + hash + '">#' + hash + '</a>';
});
}
function listify(tweet) {
return tweet.replace(/\B[#@]([a-zA-Z0-9_]{1,20})/g, function(m, username) {
return '<a target="_blank" class="twtr-atreply" href="http://twitter.com/intent/user?screen_name=' + username + '">#' + username + '</a>';
});
}
$("#twitter_results").append('<li class="twitter"><img class="twitter_img" src="' + item.profile_image_url + '"/>'+ textListed + '</li>');
});
});
} //end getTweets
// define this globally
function stuffify(match, group1, group2) {
switch (group1 || group2) {
case 'http':
return '<a class="twtr-link" target="_blank" href="' + match + '">' + match + '</a>';
case '#':
return '<a class="twtr-hashtag" target="_blank" href="http://twitter.com/search?q=' + encodeURIComponent(match) + '">#' + match + '</a>'
case '#':
return '<a class="twtr-atreply" target="_blank" href="http://twitter.com/intent/user?screen_name=' + encodeURIComponent(match) + '">#' + match + '</a>';
default:
return match;
}
}
function(data){
tweetsLoaded = true;
var interestingParts = /(http):\/\/\S+|(#|#)[^\s.,!?;^()\[\]<>{}]+/g;
$.each(data.results, function(i,item) {
var newText = item.text.replace(interestingParts, stuffify);
$("#twitter_results").append('<li class="twitter"><img class="twitter_img" src="' + item.profile_image_url + '"/>'+ newText + '</li>');
});
}
I would realign the code such that the text manipulation functions (linkify, hashify, listify) are not inside of the each function, nor are they even inside of getTweets itself. If it's in getTweets, then every time you call that function they have to be redefined. Worse, inside of the each where you had them, those functions are redefined for every item in the returned tweet-set.
Also, there is no need to store the return of each of those functions in it's own var since you only use them once afterward and aren't performing any checks before using them. Just nest the function calls.
Finally, since you're calling append over and over on the same element (inside the each) I pre-queried that element instead of querying for it every time the each function is executed
Those changes, along with some things I do for my own performance preferences are exhibited in the code sample pasted below.
There are other things I would do, however I won't show them here--you can see it in my posted answer at Trouble Converting jQuery Script to Plugin -- a question about making a jQuery plugin which does the same ting as your code). You should store the formatted tweets in an array rather than append each as you get it. Having built that array, you should then combine it into one string and call append once with that string. Making this a jQuery plugin would also be nice for you as it would not require you modify the code to change the targeted DOM element. Looking into use of String.prototype.link would be good as well.
(demo: http://jsfiddle.net/JAAulde/fQ3Lp/2/ )
var getTweets = ( function()
{
/* Privatized text manipulation functions */
var linkify = function( tweet )
{
return tweet.replace( /(http:\/\/[^\s]*)/g, "<a class='twtr-link' target=\"_blank\" href=\"$1\">$1</a>" );
};
var hashify = function( tweet )
{
return tweet.replace( /(^|\s+)#(\w+)/gi, function(m, before, hash)
{
return before + '<a target="_blank" class="twtr-hashtag" href="http://twitter.com/search?q=%23' + hash + '">#' + hash + '</a>';
} );
};
var listify = function( tweet )
{
return tweet.replace(/\B[#@]([a-zA-Z0-9_]{1,20})/g, function(m, username)
{
return '<a target="_blank" class="twtr-atreply" href="http://twitter.com/intent/user?screen_name=' + username + '">#' + username + '</a>';
} );
};
var $twitterResultTarget = $( "#twitter_results" );
/* The actual function which is stored in `getTweets` */
return function()
{
$.getJSON( "http://search.twitter.com/search.json?callback=?&q=superfad", function( data )
{
tweetsLoaded = true;
$.each( data.results, function( i, item )
{
$twitterResultTarget
.append( [
'<li class="twitter"><img class="twitter_img" src="',
item.profile_image_url,
'"/>',
listify( hashify( linkify( item.text ) ) ),
'</li>'
].join( '' ) );
} );
} );
}
}() );
Try to avoid using anonymous functions, its always less confusing if they all have names and are declared outside of any other functions.
I'd probably write in in the jQuery plugin style, and use split as opposed to replace with HTML in callbacks:
(function($){
function getTweets(q) {
var
$set = this,
prefixes = {
'h': 'h',
'#': 'http://twitter.com/search?q=%23',
'#': 'http://twitter.com/intent/user?screen_name='
},
classes = {
'h': 'twtr-link',
'#': 'twtr-hashtag',
'#': 'twtr-atreply'
};
$.getJSON(
"http://search.twitter.com/search.json?callback=?&q=" + encodeURIComponent(q),
function(data){
$.each(data.results, function(i, item){
var
$li = $('<li class="twitter"></li>')
.append('<img class="twitter_img" src="' + item.profile_image_url + '"/> ');
$.each(
item.text.split(
/(\s+)|(https?:\/\/[^\s]*)|(#\w+)|(#[a-zA-Z0-9_]{1,20})/g
),
function(i, chunk) {
if (/^(https?:\/\/|#|#)/.test(chunk)) {
$('<a target="_blank"></a>')
.addClass(classes[chunk[0]])
.attr('href', prefixes[chunk[0]] + chunk.substr(1))
.text(chunk)
.appendTo($li);
} else if (chunk) {
$li.append(document.createTextNode(chunk));
}
}
);
$li.appendTo($set);
});
}
);
}
$.fn.getTweets = getTweets;
})(jQuery);
Then call it like this:
$('#twitter_results').getTweets('superfad');
My $0.02