Masonry not working with dynamic content - javascript

Masonry is not working with my dynamic content, I don't know why. I don't think it's a bug on my side, at least I've looked at the code for a few hours now and I can't find anything that isn't working.
//reads listbox.php and cycles through the array calling createbox
function listboxs() {
$.ajax({
url: '_php/listbox.php',
success: function (output) {
var jsonArray = $.parseJSON(output);
$.each(jsonArray, function (i, box) {
createbox(box.id, box.name, box.link, box.description, box.tags);
});
}
});
}
//create the code for 1 box
function createbox(id, name, link, description, tags) {
var boxHtml = "",
tagsHtml = "",
descriptionHtml = "";
boxHtml = '' + '<div class="box" id="' + id + '">' + '<div class="boxinfo">' + '<label class="boxname">' + name + '</label>';
$.each(tags, function (i, tag) {
tagsHtml += '<label class="boxtag">' + ((!tag.name) ? tags[i] : tag.name) + '</label>';
});
//if(description.trim().length > 0){
descriptionHtml = '<textarea class="boxdescription" readonly rows="1">' + description + '</textarea>';
//}
boxHtml += tagsHtml + '</div>' + descriptionHtml + '</div>';
$content.html($content.html() + boxHtml);
}
Below is the simplified HTML:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="_css/index.css" />
<link href='http://fonts.googleapis.com/css?family=Marck+Script' rel='stylesheet'
type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Rosario' rel='stylesheet'
type='text/css'>
<script src="_resources/jquery-2.0.3.min.js" type="text/javascript" language="javascript"></script>
<script src="_resources/masonry.pkgd.min.js"></script>
<script type="text/javascript" language="javascript">
$('#content').masonry();
</script>
</head>
<body>
<div id="content" class="js-masonry"></div>
</body>
</html>
I know that I don't need the inline javascript calling masonry on content but it's one of my many tests...
Below is part of the CSS:
#content{
padding: 15px;
min-height: 400px;
}
/*
################################
box
*/
.box{
border: 1px solid black;
float: left;
padding: 5px;
background: #F0F0F0;
margin-left: 5px;
margin-bottom: 5px;
}
.boxinfo{
border-bottom: 1px solid black;
}
.boxname{
font-weight: bold;
}
.boxdescription{
border: none;
outline: none;
background: white;
overflow: hidden;
}
.boxtag{
margin-left: 5px;
}
#boxdecoy{
height: 45px;
}
.boxname, .boxtag, .boxdescription{
font-family: 'Rosario', sans-serif;
font-size: 12px;
}
.boxlink{
text-decoration: none;
color: black;
}
.boxlink:hover{
text-decoration: underline;
}
I'm really going crazy with all of it because I tested creating boxes by hand (this means writting in the html) in content, and if i do masonry works fine. If i create them through the function that you see there it doesn't work... i call listboxs right in the begining of the javascript file after I declare all my vars...
Hope I was clear and you can help me.

You should use appended method. From docs:
Add and lay out newly appended item elements.
Look at this jsfiddle
Try to change your code to
boxHtml += tagsHtml +
'</div>' +
descriptionHtml +
'</div>';
var $boxHtml = $(boxHtml);
$content.append($boxHtml).masonry('appended', $boxHtml);

Adding up to Grin's answer:
You should also apply data-masonry-options='{ "columnWidth": 200, "itemSelector": ".item" }' to your #container.
<div id="content" class="js-masonry" data-masonry-options='{ "columnWidth": 200, "itemSelector": ".item" }'></div>
Like so. It might help with your comment response. I don't have the rep to answer as a comment.

Related

no error on console, making little circles change colour on refresh

I have been trying to complete a small exercise and I have it running in codepen but when I put it through sublime and open it in my browser it doesn't show anything! I have tried running it through JSHint, read over and over it. Would love if someone one could please take a moment to have a quick read through.
..This is what it's supposed to do.. http://codepen.io/hellojessicagraham/pen/Ropgob
var htmlDot = "";
var red;
var green;
var blue;
var rgbColor;
function colourSelect() {
return Math.floor(Math.random() * 256 );
}
for(var i = 1; i<=100; i+=1) {
red = colourSelect();
green = colourSelect();
blue = colourSelect();
rgbColor = "rgb(" + red + "," + green + "," + blue + ")";
htmlDot += "<div style=\"background-color:"+ rgbColor + " \"></div>";
}
document.write(htmlDot);
The HTML is as follows
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="main.css">
</head>
<body>
<script src="script.js"></script>
</body>
</html>
CSS as follows
div{
width: 50px;
height: 50px;
display: inline-block;
border-radius: 50%;
margin: 5px;
}
Thank you in advance
Since it seems to work with all the code on your html document, are you sure the links to your js/css files are correct ? Use the inspector in your navigator (F12) if you're not sure.
Edit : It's just working fine. Like Dejan said, your error is probably in your stylesheet.
var htmlDot = "";
var red;
var green;
var blue;
var rgbColor;
function colourSelect() {
return Math.floor(Math.random() * 256 );
}
for(var i = 1; i<=100; i+=1) {
red = colourSelect();
green = colourSelect();
blue = colourSelect();
rgbColor = "rgb(" + red + "," + green + "," + blue + ")";
htmlDot += "<div style=\"background-color:"+ rgbColor + " \"></div>";
}
document.write(htmlDot);
button {
width:50px;
height: 50px;
border-radius: 50%;
margin: 0px;
display: inline-block;
}
div{
width: 50px;
height: 50px;
display: inline-block;
border-radius: 50%;
margin: 5px;
}
Your javascript code is fine, all u forgot is the css of the div element. Your divs are all collapesed into oneand not displaying. Give them some love :D LIke in the link u posted they created circles with the folowing css.
.div {
width: 50px;
height: 50px;
display: inline-block;
border-radius: 50%;
margin: 5px;
}
There is no
<body>
Also, try to remove
<!doctype html>
Actually, it works fine.Try to make sure about the path and the file name.

Close a particular content without deleting from database

I am facing small problem here. here it comes all the output. But if I delete those it will delete from database also. I want to close the content only from html page rather deleting it from database.
I am using javascript of that. Any help will be greatly helpful for me.
HTML
<html>
<head>
<meta charset="utf-8">
<title>My Parse App</title>
<meta name="description" content="My Parse App">
<meta name="viewport" content="width=device-width">
<!-- <link rel="stylesheet" href="css/reset.css">-->
<!-- <link rel="stylesheet" href="css/styles.css">-->
<!--
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
-->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://www.parsecdn.com/js/parse-latest.js"></script>
<style>
/* my CSS here */
</style>
</head>
<body bgcolor="#45a049">
<div>
<form id=post-form>
<label for="fname">First Name :</label>
<input type="text" id="post-fname" name="firstname"><br>
<label for="lname">Last Name :</label>
<input type="text" id="post-lname" name="lastname"><br>
<label for="image">Select Image :</label>
<input type="file" id="post-image" ><br>
<input type="submit" value="Submit">
</form>
</div>
<list id="list-posts" style="list-style-type:circle; width:50%" border="2" cellspacing="1" cellpadding="100" >
</list>
<script type="text/javascript">
/* my JS here */
</script>
</body>
</html>
CSS
input[type=text],
select {
width: 50%;
/*align-content:center;*/
align-self: center;
padding: 5px 20px;
margin: 30px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=file],
select {
/*padding: 20px 5px;*/
padding-right: -5px;
padding-left: 50px;
margin: 20px 10px;
}
input[type=submit] {
width: 40%;
/*align-self: center;*/
background-color: #4CAF50;
color: white;
padding: 7px 30px;
/*align:center;*/
margin: 20px 10px;
margin-left: 5px;
margin-right: 5px;
text-align: center;
border: none;
border-radius: 10px;
cursor: pointer;
}
input[type=submit]:hover {
background-color: #45a049;
}
div {
border-radius: 10px;
background-color: #f2f2f2;
background-position: center;
background-size: contain;
/*background-position: 30px 60px;*/
position: absolute;
padding: 10px 10px;
margin: 80px 500px;
text-align: center;
align-self: center;
left=50%;
top=50%;
}
JS
Parse.initialize("", "");
var Post = Parse.Object.extend("UpdateDelete");
$("#post-form").submit(function(event) {
event.preventDefault();
var Firstname = $("#post-fname").val();
var Lastname = $("#post-lname").val();
var Image = $("#post-image").val();
var new_post = new Post;
new_post.set("Firstname", Firstname);
new_post.set("Lastname", Lastname);
var fileElement = $("#post-image")[0];
var filePath = $("#post-image").val();
var fileName = filePath.split("\\").pop();
console.log("sumbit for post clicked");
if (fileElement.files.length > 0) {
var file = fileElement.files[0];
var newFile = new Parse.File(fileName, file);
newFile.save({
success: function() {
console.log("Inserted");
},
error: function(file, error) {
console.log("Error");
}
}).then(function(theFile) {
new_post.set("Image", theFile);
new_post.save({
success: function() {
console.log("Image Saved");
},
error: function(error) {
console.log("Post Save with file error " + error.message);
}
});
});
} else {
new_post.save(Firstname, Lastname, {
success: function(new_post) {
console.log("All posted");
getPosts();
},
error: function(new_post, error) {
console.log("Error" + error.message);
}
});
}
});
// deleting item form list
$("#list-posts").on("click", "#delitem", function() {
close();
var id = $(this).attr("href");
console.log("ID retrieved" + id);
var query = new Parse.Query(Post);
var delobj = id;
query.equalTo("objectId", id);
query.get(delobj, {
success: function(delobj) {
delobj.destroy({});
location.reload();
console.log("Object deleted successfully");
},
error: function(delobj, error) {
console.log("error deleting");
}
});
});
function showDialog() {
$("#list-posts").on("click", "#showDialog()", function(e) {
e.preventDefault();
var x = document.getElementById("myDialog");
function showDialog() {
x.show();
}
})
}
// Retrieving
function getPosts() {
var query = new Parse.Query(Post);
query.find({
success: function(results) {
console.log("Retrieving");
var output = "";
for (var i in results) {
var Firstname = results[i].get("Firstname");
var Lastname = results[i].get("Lastname");
var id = results[i].id;
// console.log(results[i].get("file"));
var img = "";
if (results[i].get("Image")) {
var file = results[i].get("Image");
var url = file.url();
console.log("url:" + url);
img = "<img src='" + url + "' style='width:170px;height:170px; margin:20px 10px'/>";
}
output += "<li style= 'list-style-type:circle' reversed='reversed' >";
output += "<h3 id='Firstname' href='" + id + "'>" + Firstname + "</h3>";
output += "<li style= 'list-style-type:circle' reversed='reversed' >";
output += "<h3 id='Lastname' href='" + id + "' >" + Lastname + "</h3>";
output += img;
output += "<button id='delitem' href='" + id + "' style='display:inline-block; margin:20px 10px'>delete</button>";
output += "<button id='mydialog' style='display:inline-block; margin:20px 10px'>User Info</button>";
output += "<dialog id='myDialog'> This is dialog window</dialog>";
output += "<button id='modals_close' style='display:inline-block; margin:20px 10px'>Close Info</button>";
output += "</li>";
$("#list-posts").html(output);
};
},
error: function(error) {
console.log("Query Error" + error.message);
}
});
}
getPosts();
First of all: you iterate through a list of items and create HTML for every item. This HTML contains DOM elements having ID. So a single ID occurs multiple times in your HTML, which it isn't allowed. Use classes instead.
There aren't the same amount of closing <LI> tags as opening ones.
I created a fiddle from your supplied code: https://jsfiddle.net/1muc0460/
But since accessing api.parse.com is unauthorized (due to initialize fails, because we need an app-key and a js-id), we can't get pretty far with it.
There are a lot errors in it. Selectors containing special character. There are Function definitions inside function definitions with the same name. Those add event handlers, but are never called (initialized).
I started some fixing: https://jsfiddle.net/1muc0460/1/
But I gave up. I don't know what logic you were trying to go after, so it's pretty hard to repair.
I added a test item as your JS would create, but none of your buttons had any effect.
As soon as you provide proper functional code, I can update this answer.

Using jquery append() puts the appended content outside of the appended background

I'm using the append function to add different divs, images, links and text onto my html. When I do this though, the content that I get from a JSON file that I'm trying to append is being placed outside of the background that I want it to be placed on. Here is what the content is supposed to look like:
http://i.stack.imgur.com/iShVe.png
The image and text is placed onto the gray background when I create this html content myself, but when I try to create all this content with append(), it puts all the content to the left of the background:
Here is also the codepen that I'm doing it on if you needed to see that: http://codepen.io/JaGr/pen/XXMPQY
html:
<link href='https://fonts.googleapis.com/css?family=Oswald' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Droid+Serif' rel='stylesheet' type='text/css'>
<div>
<div class="header">
<div>
Camper
</div>
<div>
News
</div>
</div>
<div class="stories">
<div class="story">
<img src="http://a5.mzstatic.com/us/r30/Purple5/v4/5a/2e/e9/5a2ee9b3-8f0e-4f8b-4043-dd3e3ea29766/icon128-2x.png" class="profilePicture">
<div class="headline">Test Headline</div>
<div class="author">by - TestName</div>
<div class="likes"><img src="https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-heart-128.png" class="heartIcon"> 13</div>
</div>
</div>
</div>
css:
body {
background-image: url("http://s22.postimg.org/bondz7241/grey_wash_wall.png")
}
.header {
font-family: 'Oswald', sans-serif;
font-size: 100px;
float: left;
color: #A9A9A9;
border-right-style: solid;
border-bottom-style: solid;
margin-left: 20px;
margin-top: 10px;
padding-right: 135px;
padding-bottom: 18px;
width: 210px;
margin-bottom: 29px;
}
.story {
text-align: center;
float: right;
background-color: #A9A9A9;
width: 230px;
height: 330px;
margin-bottom: 30px;
margin-right: 30px;
box-shadow: 2px 2px 13px;
}
.headline, .author, .likes {
padding-top: 7px;
font-family: 'Droid Serif', serif;
}
.likes {
vertical-align:middle
padding-top: 5px;
}
a {
text-decoration: none;
color: #0052cc;
}
.profilePicture {
width: 230px;
height: 230px;
}
.heartIcon {
width: 15px;
height: 15px;
}
javascript:
$(document).ready(function() {
$.getJSON("http://www.freecodecamp.com/news/hot", function(json) {
for (var x = 0; x < json.length; x++) {
var headline = json[x].headline;
var headlineLink = json[x].link;
var authorName = json[x].author.username;
var authorNameLink = "http://www.freecodecamp.com/" + authorName;
var authorPicture = json[x].author.picture;
var likes = json[x].rank;
if (headline.length > 15) {
headline = headline.slice(0, 16);
}
var divStory = '<div class="story">'
var profilePic = '<img src="' + authorPicture + '"' + ' class="profilePicture">'
var divHeadline = '<div class="headline">' + headline + '</div>'
var divAuthor = '<div class="author">by - ' + authorName + '</div>'
var divLikes = '<div class="likes"><img src="https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-heart-128.png" class="heartIcon">' + likes + '</div>'
var lastDiv = '</div>'
$(".stories").append(divStory, profilePic, divHeadline, divAuthor, divLikes, lastDiv)
}
});
});
I think my html and css is OK, it works alright when I type in the code myself; it's just the javascript that introduces the problem. I've checked the variables and incoming JSON and they both seem fine as well, so I think the problem is just with append() itself, but I don't know exactly whats causing it.
It is the jquery append multiple elements.
$(".stories").append(divStory, profilePic, divHeadline, divAuthor, divLikes, lastDiv)
I haven't found out exactly why it created the issue, but change it to will fix the problem.
$(".stories").append(divStory + profilePic + divHeadline + divAuthor + divLikes + lastDiv)
Check fix here
Did u ever use the devtools? (F12)
They're pretty useful, and you can see on first sight that your elements aren't wrapped into the .story-tags.
I'd do it like this:
var tplStory = '\
<div class="story">\
<img src="{{authorPicture}}" class="profilePicture">\
<div class="headline">{{headline}}</div>\
<div class="author">by - {{authorName}}</div>\
<div class="likes"><img src="https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-heart-128.png" class="heartIcon">{{likes}}</div>\
</div>';
$(".stories").append(
divStory
.replace('{{authorPicture}}', authorPicture)
.replace(...)
)

JS: document.write (calling CSS)

I'm dealing with the calling classes with document write. I defined two classes in CSS. First is "sahovnica" (chessboard) and second are "svetlo" (light) and "temno"(dark). With both classes I defined style for my table. And then I wanted to built a table with:
document.write( document.write('<td class="' + svetlo + '"></td>'););
Tried many different ways, but my code don't works. If I comment document.write(), page show up.
<!DOCTYPE html>
<html>
<head>
<title>Šahovska partija 2014</title>
<meta charset="UTF-8">
<style>
h1 {
color:blue;
font-family:verdana;
font-size:125%;
}
.sahovnica { border-spacing: 0; border-collapse: collapse; }
.sahovnica th { padding: .5em; }
.sahovnica td { border: 1px solid; width: 2em; height: 2em; }
.sahovnica .svetlo { background: #eee; }
.sahovnica .temno { background: #000; }
</style>
</head>
<body>
<table class="sahovnica">
<script>
var vrstica = parseInt(prompt("Vnesite številko vrstice", ""));
var stolpec = parseInt(prompt("Vnesite zaporedno številko stolpca", ""));
stolpec = stolpec -1
var value = vrstica + stolpec
value = value%2
if (value == 0) {
document.write( document.write('<td class="' + svetlo + '"></td>'););
}
else {
document.write( document.write('<td class="' + temno + '"></td>'););
}
</script>
</table>
</body>
</html>
You have a few sytax errors on your lines with the document.write calls. First of all, you had extra misplaced semicolons at the ends of the lines. Second, you were using svetlo and temno as variables without defining them as such. Here is what the offending lines look like with those errors removed:
if (value == 0) {
document.write( document.write('<td class="svetlo"></td>'));
} else {
document.write( document.write('<td class="temno"></td>'));
}
Alternatively, you can define your css classes through variables if you define them, in case those classes may need to change.
var s = 'svetlo';
var t = 'temno';
if (value == 0) {
document.write( document.write('<td class="'+s+'"></td>'));
} else {
document.write( document.write('<td class="'+t+'"></td>'));
}
You'll be able to see these sorts of errors yourself in the future by using a javascript debugger, which are built into most modern browsers. For instance, on Chrome, if you go to View > Developer > Javascript Console, you should be able to see these errors as your run the javascript.
This is Working
<!DOCTYPE html>
<html>
<head>
<title>Šahovska partija 2014</title>
<meta charset="UTF-8">
<style>
h1 {
color: blue;
font-family: verdana;
font-size: 125%;
}
.sahovnica {
border-spacing: 0;
border-collapse: collapse;
}
.sahovnica th {
padding: .5em;
}
.sahovnica td {
border: 1px solid;
width: 2em;
height: 2em;
}
.sahovnica .svetlo {
background: #eee;
}
.sahovnica .temno {
background: #000;
}
</style>
</head>
<body>
<table class="sahovnica" id="my_table">
<script>
var vrstica = parseInt(prompt("Vnesite številko vrstice", ""));
var stolpec = parseInt(prompt("Vnesite zaporedno številko stolpca", ""));
stolpec = stolpec - 1
var value = vrstica + stolpec
value = value % 2;
var classType =value? 'temno':'svetlo';
document.getElementById("my_table").innerHTML += '<td class="' + classType + '"></td>';
</script>
</table>
</body>
</html>
That's because document.write() will delete all page contents, if called after page rendering, as you can see in this other SO answer
You should use element.innerHTML()
<table id="myTable">
</table>
<script type="text/javascript">
function write(content){
document.getElementById('myTable').innerHTML += content;
}
var vrstica = parseInt(prompt("Vnesite številko vrstice", ""));
var stolpec = parseInt(prompt("Vnesite zaporedno številko stolpca", ""));
stolpec = stolpec -1;
var value = vrstica + stolpec;
value = value % 2;
write (value == 0 ? svetlo : temlo);
</script>

JavaScript $.getJSON Issue

I have a problem with a piece of JavaScript code - a snippet is shown below. Basically the code is issuing a getJSON request to a rails controller and then should process the returned data, building an HTML table and then embedding it in a Div. It doesn't work. I have tried stepping through it with alerts, etc - all to no avail. The data is retrieved from the rails controller and I can verify that. I have placed the piece of code that issues and processes the getJSON request in the niddle of the Rails Welcome page - this is not all mine. The code is below:
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails: Welcome aboard</title>
<style type="text/css" media="screen">
body {
margin: 0;
margin-bottom: 25px;
padding: 0;
background-color: #f0f0f0;
font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
font-size: 13px;
color: #333;
}
h1 {
font-size: 28px;
color: #000;
}
a {color: #03c}
a:hover {
background-color: #03c;
color: white;
text-decoration: none;
}
#page {
background-color: #f0f0f0;
width: 750px;
margin: 0;
margin-left: auto;
margin-right: auto;
}
#content {
float: left;
background-color: white;
border: 3px solid #aaa;
border-top: none;
padding: 25px;
width: 500px;
}
#sidebar {
float: right;
width: 175px;
}
#footer {
clear: both;
}
#header, #about, #getting-started {
padding-left: 75px;
padding-right: 30px;
}
#header {
background-image: url("images/rails.png");
background-repeat: no-repeat;
background-position: top left;
height: 64px;
}
#header h1, #header h2 {margin: 0}
#header h2 {
color: #888;
font-weight: normal;
font-size: 16px;
}
#about h3 {
margin: 0;
margin-bottom: 10px;
font-size: 14px;
}
#about-content {
background-color: #ffd;
border: 1px solid #fc0;
margin-left: -55px;
margin-right: -10px;
}
#about-content table {
margin-top: 10px;
margin-bottom: 10px;
font-size: 11px;
border-collapse: collapse;
}
#about-content td {
padding: 10px;
padding-top: 3px;
padding-bottom: 3px;
}
#about-content td.name {color: #555}
#about-content td.value {color: #000}
#about-content ul {
padding: 0;
list-style-type: none;
}
#about-content.failure {
background-color: #fcc;
border: 1px solid #f00;
}
#about-content.failure p {
margin: 0;
padding: 10px;
}
#getting-started {
border-top: 1px solid #ccc;
margin-top: 25px;
padding-top: 15px;
}
#getting-started h1 {
margin: 0;
font-size: 20px;
}
#getting-started h2 {
margin: 0;
font-size: 14px;
font-weight: normal;
color: #333;
margin-bottom: 25px;
}
#getting-started ol {
margin-left: 0;
padding-left: 0;
}
#getting-started li {
font-size: 18px;
color: #888;
margin-bottom: 25px;
}
#getting-started li h2 {
margin: 0;
font-weight: normal;
font-size: 18px;
color: #333;
}
#getting-started li p {
color: #555;
font-size: 13px;
}
#sidebar ul {
margin-left: 0;
padding-left: 0;
}
#sidebar ul h3 {
margin-top: 25px;
font-size: 16px;
padding-bottom: 10px;
border-bottom: 1px solid #ccc;
}
#sidebar li {
list-style-type: none;
}
#sidebar ul.links li {
margin-bottom: 5px;
}
</style>
<script src="/javascripts/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
function about() {
info = document.getElementById('about-content');
if (window.XMLHttpRequest)
{ xhr = new XMLHttpRequest(); }
else
{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
xhr.open("GET","rails/info/properties",false);
xhr.send("");
info.innerHTML = xhr.responseText;
info.style.display = 'block'
}
</script>
<script type="text/javascript">
alert('Start of JSON Routine');
$(document).ready( function() {
alert('Attach a JQuery Live event to the button');
$('#getdata-button').live('click', function() {
alert("Get JSON data");
$.getJSON('http://0.0.0.0:3000/getjson/1', function(data) {
alert('Processing returned JSON data');
var tmp = '<table border=1>';
for (i=0;i<data.length;i++)
{
tmp = tmp +'<tr>';
tmp = tmp + '<td>' + data[i].book.price + '</td>';
tmp = tmp + '<td>' + data[i].book.title + '</td>';
tmp = tmp + '<td>' + data[i].book.author + '</td>';
tmp = tmp + '<td>' + data[i].book.ISBN + '</td>';
tmp = tmp + '<td>' + data[i].book.yearPublished + '</td>';
tmp = tmp + '<td>' + data[i].book.volume + '</td>';
tmp = tmp + '<td>' + data[i].book.publisher + '</td>';
tmp = tmp + '<td>' + data[i].book.edition + '</td>';
tmp = tmp + '<td>View</td>';
tmp = tmp + '</tr>';
}
tmp = tmp + '</table>';
alert('About to insert Table into DOM in content Div');
$('#showdata').html(tmp);
}); //getJSON end
}); //getdata-button end
}); //document.ready end
alert('End of JSON routine');
</script>
</head>
<body>
<div id="page">
<div id="sidebar">
<ul id="sidebar-items">
<li>
<h3>Browse the documentation</h3>
<ul class="links">
<li>Rails API</li>
<li>Ruby standard library</li>
<li>Ruby core</li>
<li>Rails Guides</li>
</ul>
</li>
</ul>
</div>
Get JSON Data
<script>alert("Before the JMC div");</script>
<div id="showdata">JMC</div>
<script>alert("Past the JMC div");</script>
<div id="content">
<h1>Welcome aboard</h1>
<h2>You’re riding Ruby on Rails!</h2>
</div>
<div id="about">
<h3>About your application’s environment</h3>
<div id="about-content" style="display: none"></div>
</div>
<div id="getting-started">
<h1>Getting started</h1>
<h2>Here’s how to get rolling:</h2>
<ol>
<li>
<h2>Use <code>rails generate</code> to create your models and controllers</h2>
<p>To see all available options, run it without parameters.</p>
</li>
<li>
<h2>Set up a default route and remove or rename this file</h2>
<p>Routes are set up in config/routes.rb.</p>
</li>
<li>
<h2>Create your database</h2>
<p>Run <code>rake db:migrate</code> to create your database. If you're not using SQLite (the default), edit <code>config/database.yml</code> with your username and password.</p>
</li>
</ol>
</div>
</div>
<div id="footer"> </div>
</div>
</body>
</html>
Here is the JSON data I get back when I just invoked the URL/ Controller action directly from the browser:
[
{
"book":{
"price":"25.52",
"created_at":"2011-10-27T22:35:04Z",
"ISBN":"",
"author":"Obie Fernandez",
"title":"Rails 3 Way, The (2nd Edition)",
"updated_at":"2011-10-27T22:35:04Z",
"yearPublished":"2010",
"id":1,
"publisher":"Addison-Wesley",
"volume":"2",
"edition":"second edition"
}
},
{
"book":{
"price":"23.94",
"created_at":"2011-10-27T22:39:37Z",
"ISBN":"",
"author":"Michael Hartl",
"title":"Ruby on Rails 3 Tutorial: Learn Rails by Example",
"updated_at":"2011-10-27T22:39:37Z",
"yearPublished":"2010",
"id":2,
"publisher":"Addison-Wesley",
"volume":"",
"edition":"first edition"
}
},
{
"book":{
"price":"24.97",
"created_at":"2011-10-27T22:42:42Z",
"ISBN":"",
"author":"Cloves Carneiro Jr. and Rida Al Barazi",
"title":"Beginning Rails 3 ",
"updated_at":"2011-10-27T22:42:42Z",
"yearPublished":"2009",
"id":3,
"publisher":"Apress",
"volume":"",
"edition":"first edition"
}
}
]
Anything else that might be useful. The Rails logs show the request being handled correctly.
When I step through the script, the alerts come up in a starnge sequence:
THe first alert I get is "Here at start of JSON Routine", followed by "Finished document ready routine" and then "Attach a JQuery Live event to the button". I then click the button for getdata and then a # appears at the end of the URL and then nothing.
MOved the script into the head - same outcome.
SWitched #content to #showdata - same outcome.
Final Edit:
The problem is solved thanks to the input of many people.
There were a number of issues, but the final issue was a same origin error in that the URL on the getJSON request was different to the URL making the request. The request had 0.0.0.0:3000/getjson/1 whereas the requesting URL was localhost:3000/getjson/1. Very hard to spot and the lack of return / status info with getJSON made it more difficult. Anyway thanks is due to all contributors, who all made valid contributions. I hope I have the expertise to contribute myself someday.
This is most related to same origin policy (cross domain blocking) and can be resolved by using a JSONP call. Add a ?callback=? to the end of the URL:
$(document).ready( function() {
alert('Attach a JQuery Live event to the button');
$('#getdata-button').live('click', function() {
$.getJSONP('http://0.0.0.0:3000/getjson/1?callback=?, function(data) {
// ... Omiting for brevity
$('#content').html(tmp);
});
});
});
Alright Joe, you need to start with the simplest case possible... clean up all of your HTML and get rid of everything that you do not need. I tested this and verified that it works on my local Rails server.
I mocked up the Rails controller action to return your JSON data using:
def getjson
json_data = '[{ "book": { "price": 18.75, "title": "Moby Dick", "author": "Herman Melville", "ISBN": "0393972836", "yearPublished": 2001, "volume": 1, "publisher": "W. W. Norton & Company", "edition": "2nd Edition" }}]'
render :json => json_data, :status => :ok
end
You shouldn't need to change your Rails controller code since you said it was working. I just wanted to show you how I mocked it up for your future reference.
Now, replace the contents of your HTML file with this:
<!DOCTYPE html>
<html>
<head>
<title>JSON Test example</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#getdata-button').live('click', function() {
// clear out the old data:
$('#content').html('');
alert("Getting JSON data");
$.ajax({
dataType: 'json',
type: 'GET',
url: '/getjson/1',
success: function(json) {
console.log(json);
alert('Processing returned JSON data');
var tmp = '<table border=1>';
for (i = 0; i < json.length; i++) {
tmp = tmp + '<tr>';
tmp = tmp + '<td>' + json[i].book.price + '</td>';
tmp = tmp + '<td>' + json[i].book.title + '</td>';
tmp = tmp + '<td>' + json[i].book.author + '</td>';
tmp = tmp + '<td>' + json[i].book.ISBN + '</td>';
tmp = tmp + '<td>' + json[i].book.yearPublished + '</td>';
tmp = tmp + '<td>' + json[i].book.volume + '</td>';
tmp = tmp + '<td>' + json[i].book.publisher + '</td>';
tmp = tmp + '<td>' + json[i].book.edition + '</td>';
tmp = tmp + '<td>View</td>';
tmp = tmp + '</tr>';
}
tmp = tmp + '</table>';
alert('About to insert the following data into DOM: ' + tmp);
// Show the div we are looking for in the browser's console
console.log($('#content'));
$('#content').html(tmp);
},
error: function(response) {
alert('There was an error: ' + response.status);
}
}); // $.ajax end
}); //getdata-button end
}); //document.ready end
</script>
</head>
<body>
Get JSON Data
<br/><br/>
<div id="content">The data will be placed here.</div>
</body>
</html>
Notice that I am using the $.ajax method which allows me to specify an error handler callback. I would recommend using this way of doing things until you become more familiar with jQuery and feel confident that you can start using the other AJAX helpers.
I hope this helps!
Your page is being refreshed and the data is likely getting dropped. Try:
$('#getdata-button').live('click', function(evt) {
evt.preventDefault();
}
$('#content') doesn't seem to exist.
EDIT
After another look, it seems to problem hinges on the button click event not firing. Since this is added via live, and as another user has posted, works on jsfiddle: I wonder what version of jQuery you are using? Looks like it could be very old indeed. Try upgrading to a newer version.

Categories