This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript DOM errors
I have my following html code:
<html>
<head>
</head>
<body>
<div id="1" "display:block">
</div>
<div id="2" "display:none"> // no onLoad() anymore!!
</div>
</body>
</html>
My JavaScript code is as follows:
$.ajax({
type: 'GET',
url: ........,
dataType: "json",
complete: function (xhr, statusText) {
alert(xhr.status);
},
success: function (data, textStatus, jqXHR) {
alert(JSON.stringify(data));
if(document.getElementById(1).style.display == "block"){
document.getElementById(1).style.display = "none";
document.getElementById(2).style.display = "block"; }
addBooks(data); // Passing JSON to be replaced on page
},
function (data, textStatus, jqXHR) {
alert(data);
alert('error');
},
});
function addBooks(data) { // USing DOM to populate the tables
//var newdata=document.getElementById('addBooks');
//newdata.setattribute()
//get the unordered list
var newdata = document.getElementById('addBooks');
var parent = document.getElementById('gBookList');
//removeChildrenFromNode(parent);
//create list divider
var listdiv = document.createElement('li');
listdiv.setAttribute('id', 'gBookListDiv');
listdiv.innerHTML = ("Books Found:");
parent.appendChild(listdiv);
// (this is where the first error happens)
//create dynamic list
for (i = 0; i < data.length; i++) {
// (this is where the second error happens)
//create each list item
var listItem = document.createElement('li');
listItem.setAttribute('id', 'gBookListItem');
parent.appendChild(listItem);
//var link = document.createElement('a');
//link.setAttribute('onclick','displayBook(data[i])');
//link.setAttribute('href','#FindBook)');
//listItem.appendChild(link);
var pic = document.createElement('img');
pic.setAttribute('src', data[i].pictureURL);
pic.setAttribute('width', '80px');
pic.setAttribute('height', '100px');
pic.setAttribute('style', 'padding-left: 10px');
link.appendChild(pic);
var brk = document.createElement('br')
link.appendChild(brk);
var title = document.createElement('p');
title.innerHTML = data[i].title;
title.setAttribute = ('style', 'float:right');
link.appendChild(title);
var author = document.createElement('p');
author.innerHTML = data[i].author;
link.appendChild(author);
}
var list = document.getElementById('gBookList');
// $(list).listview("refresh");
}
/*function removeChildrenFromNode(node){
while (node.hasChildNodes()){
node.removeChild(node.firstChild);
}
//}*/
I keep getting the following error which prevents me from populating the list , I am using Chrome
Uncaught TypeError: Cannot call method 'appendChild' of null
Uncaught TypeError: Cannot read property 'length' of undefined
I have posted this question yesterday, but I just wanted a fresh perspective on what the error could be.
There could be a few issues here :-
Are you doing this cross domain? If you are consider using JSONP instead which will solve some of the issues you may be seeing with data being "withheld" due to security policies.
You are also accessing a varible and making a assumption it has a value
var parent = document.getElementById('gBookList');
Before you use the parent tag, you should ensure that its not null (or a empty reference) and that the element (gBookList) does infact exist in your document.
must uncomment
// var link = document.createElement('a');
in
link.appendChild(pic);
this element is not decalred yet (in your case is just commented)!
Related
I have a mobile app.
It consists of 2 screens. The first is for capturing user
credentials and the 2nd is for displaying data.
The idea is to collect the credentials on screen 1.
Then make an ajax call with the credentials to get data and present it on
screen 2 as a series of links.
Then allow the user to touch a link on screen 2. This will return the link data to the javascript and pass it to the ajax call and get more data - THEN delete all the data on screen 2 and repopulate it with the new data.
First thing I want to find out: is showing a page with mobile.changePage(), populating it, deleting the contents and then repopulating it (without another call to mobile.changePage()) a reasonable thing to do?
I'm having a problem and I think its related to how I'm using onclick in the <a>
Each time I display the most recently received data, I want to display it in an <a>. I write each onclick to call the getData routine passing it information to determine the next ajax AND whatever is being displayed in the <a>. The only way I could figure out to access that was in onclick.
Is there a better way?
I'm able to display the results of the first ajax call just fine. But things get weird with the 2nd, 3rd etc.
Sometimes I'll touch a link and I'll progress thru the screens as I expect.
Sometimes I'll touch an <a> on the 1st result screen, the 2nd result screen will display and then (without me selecting data from the 2nd screen) the 3rd screen will display.
I've looked at the logs and the getData() routine is being executed.
What could be causing this? Am I somehow not destroying all the <a> properly? Am I using onclick in a fashion its not designed for? Should I be using buttons styled to look like links instead of <a>
Here's my code:
"use strict";
var app = {
onDeviceReady: function() {
$('#startButton').click(function(){
app.getDeptsForUser();
});
},
getDeptsForUser: function(){
var parms = new Object();
parms.userName = assignedUser;
app.getData(JSON.stringify(parms),"ENDPOINT1", "Departments");
$.mobile.changePage("#index", { transition: 'slide' });
},
getData: function(paramStr, endpoint, displayHeader){
var paramStrObj = JSON.parse(paramStr);
var serverName = server + ":" + port;
var encoded = Base64().encode(paramStrObj.userName + ':' + pass);
var authType = 'Basic ' + encoded;
var option = endpoint+"?action=start¶ms=" + paramStr;
var URL = serverName + "/rest/bpm/wle/v1/service/"+option;
$.ajax({
url: URL,
type: "POST",
crossDomain: true,
jsonp: "callback",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", authType);
},
success: function (result) {
console.log("MobileMockUp getData() ajax success result="+JSON.stringify(result));
if (endpoint === "ENDPOINT1"){
app.displayData(paramStr, endpoint,"Departments", result.data.data.depts.items);
}
else if (endpoint === "ENDPOINT2"){
app.displayData(paramStr, endpoint,displayHeader, result.data.data.checklists.items);
}
else if (endpoint === "ENDPOINT3"){
app.displayData(paramStr, endpoint,displayHeader, result.data.data.checks.items);
}
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Unable to retrieve '+displayHeader);
},
});
},
displayData: function(currParms,currEndPt, headerText, list){
var nextEndpt;
var nextHeaderText;
var currParmsObj = JSON.parse(currParms);
if (currEndPt === "MD#getDeptsForUser"){
nextEndpt = "MD#getCheckLists";
nextHeaderText = "Check Lists";
}
else if (currEndPt === "MD#getCheckLists"){
nextEndpt = "MD#getChecks";
}
var htmlListString="";
var parmObj;
var newLink;
$('#headerText').text(headerText);
for (var i = 0; i < list.length; i++){
parmObj = new Object();
if (currEndPt === "ENDPOINT1"){
parmObj.userName=currParmsObj.userName;
parmObj.dept=list[i];
}
else if (currEndPt === "ENDPOINT2"){
parmObj.userName=currParmsObj.userName;
parmObj.dept=currParmsObj.dept;
parmObj.checklist=list[i];
}
else if (currEndPt === "ENDPOINT3"){
nextHeaderText = list[i];
}
var str = JSON.stringify(parmObj);
str = str.toString().replace(/"/g, '\\"');
newLink = "<a style='background:#ffffff;padding-top:5%;border-top: thin solid black; display:block;font-size:12px;font-weight:normal;color:#000000;text-decoration: none;' href='#' onclick='app.getData(\""+str+"\",\""+nextEndpt+"\",\""+nextHeaderText+"\")'><pre>" + list[i] + " </pre></a><br>";
htmlListString=htmlListString+newLink;
}
$('#taskListUL').empty();
$('#taskListUL').append(htmlListString);
}
};
Could this be multiple binding?
i figured out it was multiple bindings
I have this ajax call here in a script tag at the bottom of my page. Everything works fine! I can set a breakpoint inside the 'updatestatus' action method in my controller. My server gets posted too and the method gets called great! But when I put the javascript inside a js file the ajax call doesn't hit my server. All other code inside runs though, just not the ajax post call to the studentcontroller updatestatus method.
<script>
$(document).ready(function () {
console.log("ready!");
alert("entered student profile page");
});
var statusdropdown = document.getElementById("enumstatus");
statusdropdown.addEventListener("change", function (event) {
var id = "#Model.StudentId";
var url = '#Url.Action("UpdateStatus", "Student")';
var status = $(this).val();
$.post(url, { ID: id, Status: status }, function (data) {
// do something with the returned value e.g. display a message?
// for example - if(data) { // OK } else { // Oops }
});
var e = document.getElementById("enumstatus");
if (e.selectedIndex == 0) {
document.getElementById("statusbubble").style.backgroundColor = "#3fb34f";
} else {
document.getElementById("statusbubble").style.backgroundColor = "#b23f42";
}
}, false);
</script>
Now I put this at the bottom of my page now.
#section Scripts {
#Scripts.Render("~/bundles/studentprofile")
}
and inside my bundle.config file it looks like this
bundles.Add(new ScriptBundle("~/bundles/studentprofile").Include(
"~/Scripts/submitstatus.js"));
and submitstatus.js looks like this. I know it enters and runs this code because it I see the alert message and the background color changes. So the code is running. Its just not posting back to my server.
$(document).ready(function () {
console.log("ready!");
alert("submit status entered");
var statusdropdown = document.getElementById('enumstatus');
statusdropdown.addEventListener("change", function (event) {
var id = "#Model.StudentId";
var url = '#Url.Action("UpdateStatus", "Student")';
var status = $(this).val();
$.post(url, { ID: id, Status: status }, function (data) {
// do something with the returned value e.g. display a message?
// for example - if(data) { // OK } else { // Oops }
});
var e = document.getElementById('enumstatus');
if (e.selectedIndex == 0) {
document.getElementById("statusbubble").style.backgroundColor = "#3fb34f";
} else {
document.getElementById("statusbubble").style.backgroundColor = "#b23f42";
}
}, false);
});
In the console window I'm getting this error message.
POST https://localhost:44301/Student/#Url.Action(%22UpdateStatus%22,%20%22Student%22) 404 (Not Found)
Razor code is not parsed in external files so using var id = "#Model.StudentId"; in the main view will result in (say) var id = 236;, in the external script file it will result in var id = '#Model.StudentId'; (the value is not parsed)
You can either declare the variables in the main view
var id = "#Model.StudentId";
var url = '#Url.Action("UpdateStatus", "Student")';
and the external file will be able to access the values (remove the above 2 lines fro the external script file), or add them as data- attributes of the element, for example (I'm assuming enumstatus is a dropdownlist?)
#Html.DropDownListFor(m => m.enumStatus, yourSelectList, "Please select", new { data_id = Model.StudentId, data_url = Url.Action("UpdateStatus", "Student") })
which will render something like
<select id="enumStatus" name="enumStatus" data-id="236" data-url="/Student/UpdateStatus">
Then in the external file script you can access the values
var statusbubble = $('#statusbubble'); // cache this element
$('#enumStatus').change(function() {
var id = $(this).data('id');
var url = $(this).data('url');
var status = $(this).val();
$.post(url, { ID: id, Status: status }, function (data) {
....
});
// suggest you add/remove class names instead, but if you want inline styles then
if (status == someValue) { // the value of the first option?
statusbubble.css('backgroundColor', '#3fb34f');
} else {
statusbubble.css('backgroundColor', '#b23f42');
};
});
<%#val testId:String %>
<%#val platforms:String %>
<body>
<div class = "conatainer">
<div class="page-header">
<h1>Preview of litmus test ${testId } <small> Platforms chosen for preview : </small></h1>
</div>
<div class ="btn-toolbar bnt-toolbar-lg" id = "buttonsPlace"><br>
<img id="imagePlaces">
</div>
</div>
$( document ).ready(function myFunct() {
var platforms = "${platforms}";
var platformList = platforms.split(",");
var btn = new Array(platformList.length);
var image_id = new Array(platformList.length);
var img = new Array(platformList.length);
for(i=0;i<platformList.length;i++)
{
image_id[i]=100*i-1 + "";
console.log(image_id);
btn[i]=document.createElement("button");
img[i]=document.createElement("image");
btn[i].appendChild(document.createTextNode(platformList[i]));
btn[i].appendChild(img[i]);
$("#buttons").append(btn[i]);
btn[i].setAttribute("id",i+"");
btn[i].setAttribute("class","btn btn-success");
img[i].setAttribute("src","");
img[i].setAttribute("id",image_id[i]);
console.log("button id is: "+i+" and image id is :"+image_id[i]);
console.log("hiding");
$("#"+i).hide();
}
var testId = "${testId}";
console.log("hey");
var is_loaded = false;
var delay = 1;
fetchFunct();
function fetchFunct(){
console.log("entered function");
$.ajax
({
type: "GET",
url: "/content/mosaic/multi/preview/status/"+testId ,
async: true,
dataType : "json",
success : function(response)
{
console.log(response);
console.log(response.images);
if(response.status === false)
{
console.log("Processing details");
//show still in progress
$("#load").show();
$("#heading").hide();
delay=delay*2;
if(delay>60)
{delay=1;}
setTimeout(fetchFunct,delay*1000);
}
else
{
$("#load").hide();
$("#heading").show();
var responses = new Array(platformList.length);
/*for (var m in responses.images){
// var responses[]=responses.images[m];
console.log("heyyeyey "+responses[]);
}*/
for(var m in response.images){
i=0;
// console.log(" response image is : "+response.images[m]);
responses[i++]=response.images[m]; }
for(i=0;i<platformList.length;i++)
{
$("#"+i).show();
console.log("image id is : "+image_id[i]);
console.log(platformList[i]);
console.log("Loading :"+i);
$("#"+i).click(function(){
console.log(this.id);
//console.log("the first child is :"+this.children().first().id);
//alert("you clicked the "+platformList[this.id]+" button");
console.log("The response image you are looking for is "+response.images[platformList[this.id]]);
console.log(image_id[this.id]);
$("#"+image_id[this.id]).attr("src","http://" + response.images[platformList[this.id]]);
})
}
is_loaded = true;
}
}
}).fail(function(data) { console.log("FAIL"); }).done(function(data) { console.log("coming out of ajax");});
}
});
I am dynamically creating buttons according to the input in platformList and then on clicking i wish to display the images corresponding to the URLs received through an AJAX request. However though I am not getting an error , the images are not being displayed. The buttons are being correctly displayed; console is showing the correct URLs have been received through ajax BUT images are not getting displayed. I think this could be because of some mistake in me appending img[i] as child of btn [i] or somehow the attr(src,"") is not changing the source attribute properly. Though I think the former is more likely.Please Help :\ Somehow the image is not attaching to the DOM element I think
I have a problem with my current javascript/ajax request. I'm trying to open a Jquery dialog from inside my .append my code follows:
for (var i in rows)
{
var row = rows[i];
var id = row[0];
var NewEdit = row[0];
var PreviousEdit = row[1];
var FunctionName = row[2];
var FunctionID = row[2]
function ShowInfo()
{
dialog('Original: <br>'+PreviousEdit+'<br><br> New: <br>' +NewEdit);
}
$('#RecentEdits').append("<br>Page: "+FunctionName+" - <a href='#' OnClick='ShowInfo()'>Info</a>");
}
I have only pasted relivant code, if required I can post the entire function.
I know for a fact, my variables are correctly set due to them being printed out.
How can I open up a Dialog box showing more information from inside a Javascript function?
Solution:
As there is no correct replies. I have used OQJF's example and produced this:
<script>
function ShowInfo(a,b)
{
alert('Original: \n'+unescape(a)+'\n\n New: \n'+unescape(b));
};
</script>
<script>
//window.setInterval(function()
//{
$(function ()
{
$.ajax({
url: 'RecentUpdates.php', data: "", dataType: 'json', success: function(rows)
{
$('#RecentEdits').empty();
for (var i in rows)
{
var row = rows[i];
var id = row[0];
var NewEdit = row[0];
var PreviousEdit = row[1];
var FunctionName = row[2];
var FunctionID = row[3];
$('#RecentEdits')
.append("<br>Page: <a href='Page.php?ID="+FunctionID+"'>"+FunctionName+"</a> - ");
$('#RecentEdits').append("<input type='button' onClick=ShowInfo('"+escape(PreviousEdit)+"','"+escape(NewEdit)+"'); value='Show'>");
}
}
});
});
// }, 1000);
</script>
which has enabled me to access the function from my Javascript printout.
I had troubles with the quotes wrapped around my html so i have decided to make two appends. And this seems to work just fine!
While firstly I think you should set the function showInfo outside of the loop and set 2 parameter for it. Below is the sample code that I didn't test but It should be almost like this.
function ShowInfo(orginVal,newVal)
{
var msg =('Original: <br>'+orginVal+'<br><br> New: <br>' +newVal);
$(<div>msg</div>).appendTo('body).dialog();//maybe you can add some options for dialog
}
below part seems be in another function.
for (var i in rows)
{
var row = rows[i];
var id = row[0];
var NewEdit = row[0];
var PreviousEdit = row[1];
var FunctionName = row[2];
var FunctionID = row[2]
$('#RecentEdits').append("<br>Page: "+FunctionName+" - <a href='#' OnClick='ShowInfo(/*add your 2 parameters here*/)'>Info</a>");
} s
this is my javascript code , I am trying to create a dynamic list in HTML with data I recieve from the server , The data is of type "json"
My Javascript snippet
function addBooks(data) { // USing DOM to populate the tables
//var newdata=document.getElementById('addBooks');
//newdata.setattribute()
//get the unordered list
var newdata = document.getElementById('addBooks');
var parent = document.getElementById('gBookList');
//removeChildrenFromNode(parent);
//create list divider
var listdiv = document.createElement('li');
listdiv.setAttribute('id', 'gBookListDiv');
listdiv.innerHTML = ("Books Found:");
parent.appendChild(listdiv);
// (this is where the first error happens)
//create dynamic list
for (i = 0; i < data.length; i++) {
// (this is where the second error happens)
//create each list item
var listItem = document.createElement('li');
listItem.setAttribute('id', 'gBookListItem');
parent.appendChild(listItem);
//var link = document.createElement('a');
//link.setAttribute('onclick','displayBook(data[i])');
//link.setAttribute('href','#FindBook)');
//listItem.appendChild(link);
var pic = document.createElement('img');
pic.setAttribute('src', data[i].pictureURL);
pic.setAttribute('width', '80px');
pic.setAttribute('height', '100px');
pic.setAttribute('style', 'padding-left: 10px');
link.appendChild(pic);
var brk = document.createElement('br')
link.appendChild(brk);
var title = document.createElement('p');
title.innerHTML = data[i].title;
title.setAttribute = ('style', 'float:right');
link.appendChild(title);
var author = document.createElement('p');
author.innerHTML = data[i].author;
link.appendChild(author);
}
var list = document.getElementById('gBookList');
// $(list).listview("refresh");
}
/*function removeChildrenFromNode(node){
while (node.hasChildNodes()){
node.removeChild(node.firstChild);
}
//}*/
My html code is
<!DOCTYPE html>
<head>
<script ...>
<head>
<body onLoad="addBooks()">
<div id="addBooks" class="row-fluid">
<div id="gBookList">
</div>
</div>
</body>
</html>
I keep getting the following error which prevents me from populating the list , I am using chrome
1) Uncaught TypeError: Cannot call method 'appendChild' of null
2) Uncaught TypeError: Cannot read property 'length' of undefined
I do not understand why this should happen as the .length commands returns the correct integer ( amount of json objects) when I debug using a alert box .
the function that calls it
$.ajax({
type: 'GET',
url: ........,
dataType: "json",
complete: function (xhr, statusText) {
alert(xhr.status);
},
success: function (data, textStatus, jqXHR) {
alert(JSON.stringify(data));
window.location.replace("Page2_updated.html");
addBooks(data); // Passing JSON to be replaced on page
},
function (data, textStatus, jqXHR) {
alert(data);
alert('error');
},
});
Edit
I changed my HTML file to the following structure after advice on this forum
<html>
<head>
</head>
<body>
<div id="1" "display:block">
</div>
<div id="2" "display:none"> // no onLoad() anymore!!
</div>
</body>
</html>
I have edited this part int he calling function
$.ajax({
type: 'GET',
url: ........,
dataType: "json",
complete: function (xhr, statusText) {
alert(xhr.status);
},
success: function (data, textStatus, jqXHR) {
alert(JSON.stringify(data));
if(document.getElementById(1).style.display == "block"){
document.getElementById(1).style.display = "none";
document.getElementById(2).style.display = "block"; }
addBooks(data); // Passing JSON to be replaced on page
},
function (data, textStatus, jqXHR) {
alert(data);
alert('error');
},
});
But I still get the following errors
Uncaught TypeError: Cannot call method 'appendChild' of null
Uncaught TypeError: Cannot read property 'length' of undefined
Here is a working version of your code that builds a list. Compare with your version to see where you made the mistakes, in both mark up and code.
The source of your second error is incorrect data (most likely null) being passed to the addBooks function, so you would have to fix that.
Chrome and Firebug have excellent JavaScript debuggers with breakpoints, so use that to your advantage to identify the issues:
http://jsfiddle.net/tgth2/
EDIT:
Your problem is gleamingly obvious, after your comments and updates to the question:
Your first page is loading the JSON data from the service, but then does window.location.replace("Page2 Updated.html");, which sends the browser to the new page (notice that you're calling addBooks(data); immediately after. But that code is never executed because browser has already gone to another page
Your second page has <body onload="addBooks();"> in it, which will cause the function to be called with a null data. This is the cause of your problem.
SOLUTION:
Number one suggestion would be to start using jQuery for everything else you're doing, and not just for the AJAX call.
Secondly, you should have the ajax call and the results rendering in one page, as it does not make any sense to redirect the browser to another page. Because your javascript always works in the context of a single page. As soon as you do something like window.location.replace(..) you end up losing everything you've done in the current page.
If you make these changes, you will see that your list loads just fine!
This line in your loop creates multiple list items with the same ID:
listItem.setAttribute('id','gBookListItem');
try removing it - i don't think you need it.
That's an error :
title.setAttribute=('style','float:right');
do:
var title = document.createElement('p');
title.innerHTML = data[i].title;
title.style.cssFloat = 'right';
link.appendChild(title);
and
var pic = document.createElement('img');
pic.src = data[i].pictureURL;
pic.width = '80px';
pic.height = '100px';
pic.style.paddingLeft = '10px';
link.appendChild(pic);
etc......
Any chance that you're accidentally calling addBooks() somewhere in your code without any data?
I tried to cut it down to the barebones and I'm pretty sure the fact that link is undefined is the reason you get an error when you call appendChild. It's certainly the first error I found in the console in Firebug. The following barebones sequence works in Firefox (sorry I don't have Chrome):
var json =[
{"pictureURL":"/test1.jpg/","title":"test1"},
{"pictureURL":"/test2.jpg/", "title":"test2"},
{"pictureURL":"/test3.jpg", "title":"test3"}
];
function displayBook(title){
alert(title);
return false;
}
function addBooks(data) {
var newdata=document.getElementById('addBooks');
var parent = document.getElementById('gBookList');
var listdiv = document.createElement('li');
listdiv.id = 'gBookListDiv';
listdiv.innerHTML = "Books Found:";
parent.appendChild(listdiv);
for(var i=0;i<data.length;i++){
var listItem = document.createElement('li');
listItem.id = 'gBookListItem-' + i;
parent.appendChild(listItem);
var link = document.createElement('a');
link.id = listItem.id + "-link";
link.href = '#FindBook';
link.innerHTML = data[i].title;
listItem.appendChild(link);
link.setAttribute("onclick", "return displayBook('" + data[i].title + "');");
var pic = document.createElement('img');
pic.src = data[i].pictureURL;
}
var list = document.getElementById('gBookList');
}
I discovered from this answer JavaScript: changing the value of onclick with or without jQuery that I had to use setAttribute to add the onclick handler. I'm used to adding other attributes like id directly as mentioned by adeneo without calling setAttribute.