I don't have many knowlege in javascript so I don't know what is the problem here,
I create divs dynamically in js and each div call a function when is clicked but the function is not recongized. This is part of the code
for (......) {
var listatema = document.createElement("div");
listatema.innerHTML += "<a href='javascript: void(0)' onClick='functest(" + pag + ")'>" + temat + "</a>";
document.getElementById('menu').appendChild(listatema);}
}
"tema" is a text, the function "functest" has an argument "pag[aux]", this is a number.
The function is:
function functest(arg){
console.log(arg)
}
other alternative that i tried is change that: onClick='"+ functest(pag) +"':
i change the position of Quotation marks "" and the function work good but it is executed when the page is loaded, it don't wait to do click.
Your code should work if you're doing something like:
function functest(arg) {
console.log(arg);
}
for (var i = 0; i < 10; i++) {
var listatema = document.createElement("div");
listatema.innerHTML += "<a href='javascript: void(0)' onClick='functest(" + i + ")'>" + i + "</a>";
document.getElementById('menu').appendChild(listatema);
}
<div id="menu"></div>
I would, however, recommend using addEventListener or setting the onClick handler on the document element object rather than setting the innerHTML. Note that setting innerHTML is not advised, especially when rendering user input. See https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#Security_considerations. In your case, it probably isn't really an issue, but it's good practice to avoid it if you can :)
for (var i = 0; i < 5; i++) {
var wrapper = document.createElement("div");
var listatema = document.createElement("a");
listatema.textContent = i;
listatema.href = "javascript:void(0)";
listatema.addEventListener('click', function(e) {
console.log(this.i);
}.bind({ i : i }));
wrapper.appendChild(listatema);
document.getElementById('menu').appendChild(wrapper);
}
<div id="menu"></div>
onClick='functest(\""+ pag +"\")'
you forgot to quote the parameter.
Related
I'm working on a Blogger widget, trying to rid it of any deprecated or bad practices (based what I read on Stack Overflow), such as document.write
This was working:
<script type="text/javascript">
function introductory(json) {
document.write('<div id="intro-wrapper">');
var i;
for (i = 0; i < json.feed.entry.length; i++) {
var introTitle = json.feed.entry[i].title.$t;
var introContent = json.feed.entry[i].content.$t;
var item = '<h2>' + introTitle + '</h2><p>' + introContent + '</p>';
document.write(item);
}
document.write('</div>');
}
</script>
<script src="https://MYBLOG.blogspot.com/feeds/posts/default/-/intro?max-results=1&alt=json-in-script&callback=introductory"></script>
It displays the title and content (wrapped up within h2 and p tags, respectively) of one single post ( ...max-results=1... ), labeled "intro" ( .../-/intro?... ) by means of Blogger labels.
I've tested various alternatives, lining up my html elements prior to the js, then using getElementById, followed by either innerHTML or appendChild, or even lining up the elements inside the js, by means of createElement, but to no avail, really. Would it be possible for anyone to point me to the right direction?
P.S. I can hardly copy and paste all of my attempts in this question. There have been dozens of them, as I'm more or less clueless when it comes to javascript and I'm just experimenting my way forwards, so I've opted for merely posting the code that is actually working and asking for an alternative that does not utilize document.write, if that's indeed "bad practice".
I greet you at the beginning about trying to rid document.write
Create an element with a unique id before your JS code in the document, then select this element by its id getElementById and add your content to it using innerHTML
<div id="intro-wrapper"></div>
<script type="text/javascript">
function introductory(json) {
var item="";
for (var i = 0; i < json.feed.entry.length; i++) {
var introTitle = json.feed.entry[i].title.$t;
var introContent = json.feed.entry[i].content.$t;
item += '<h2>' + introTitle + '</h2><p>' + introContent + '</p>';
}
document.getElementById('intro-wrapper').innerHTML=item;
}
</script>
<script src="https://MYBLOG.blogspot.com/feeds/posts/default/-/intro?max-results=1&alt=json-in-script&callback=introductory"></script>
You can also use document.createElement instead of document.write.
Here is working example -
<script>
function introductory(json) {
var RecentPostContainer = document.createElement('div');
RecentPostContainer.className = 'RecentPostContainer';
for(i = 0; i < json.feed.entry.length; i++) {
var PostContainer = document.createElement('div');
PostContainer.className = 'PostContainer';
var PostTitle = document.createElement('h2');
PostTitle.className = 'PostTitle';
var PostTitleText = document.createTextNode(json.feed.entry[i].title.$t);
PostTitle.appendChild(PostTitleText);
PostContainer.appendChild(PostTitle);
var PostContent = document.createElement('div');
PostContent.className = 'PostContent';
PostContent.innerHTML = json.feed.entry[i].content.$t;
PostContainer.appendChild(PostContent);
RecentPostContainer.appendChild(PostContainer);
}
document.getElementById('RecentPostContainer').insertAdjacentHTML('afterend', RecentPostContainer.outerHTML);
}
</script>
<script id='RecentPostContainer' src="https://blogger.googleblog.com/feeds/posts/default/?max-results=1&alt=json-in-script&callback=introductory"></script>
I'm have a table with buttons in each row. On every button click I want to pass that row's data to a method. I've done the following
HTML
<body>
<div>
<button onclick="load()" >Click</button>
<table id="roleTable">
<thead>
<tr>
<td>EnterpriseId</td>
<td>Role</td>
<td>UserId</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</body>
Javascript
function load() {
var data = JSON.parse(sessionStorage.getItem("loginInfo"));
var html = "";
for (var i = 0; i < data.length; i++) {
html += "<tr><td>" + data[i].ENTERPRISE_ID + "</td>";
html += "<td><button type='button' onclick='loadSegment(data[" + i + "])'>...</button></td>";
html += "<td>" + data[i].USER_ID + "</td></tr>";
}
document.getElementById('roleTable').getElementsByTagName("TBODY")[0].innerHTML = html;
}
function loadSegment(o) {
alert('reading obj');
alert(JSON.stringify(o));
}
The problem is when I click on the button with given code, nothing happens.
But if I move the code of load() function out, the loadSegment method gets called and I'm able to use the object as I want.
Working JS
//function load() { // Commented the function call
var data = JSON.parse(sessionStorage.getItem("loginInfo"));
var html = "";
for (var i = 0; i < data.length; i++) {
html += "<tr><td>" + data[i].ENTERPRISE_ID + "</td>";
html += "<td><button type='button' onclick='loadSegment(data[" + i + "])'>...</button></td>";
html += "<td>" + data[i].USER_ID + "</td></tr>";
}
document.getElementById('roleTable').getElementsByTagName("TBODY")[0].innerHTML = html;
//}
function loadSegment(o) {
alert('reading obj');
alert(JSON.stringify(o));
}
I don't understand why through the second code the method is reachable but not from the first code. If I don't pass object as parameter in the first code then it is able to reach to the loadSegment() function.
Can anybody please help me understand what is the exact issue her. And how can I achieve the function call from the first JS code.
Update
JSON string
[{"USER_ID":"UID00007","ENTERPRISE_ID":"admin1","ROLE":"ADMIN"},
{"USER_ID":"UID00008","ENTERPRISE_ID":"admin2","ROLE":"TESTER"},
{"USER_ID":"UID00009","ENTERPRISE_ID":"admin3","ROLE":"REVIEWER"},
{"USER_ID":"UID00010","ENTERPRISE_ID":"admin4","ROLE":"PMO"},
{"USER_ID":"UID00011","ENTERPRISE_ID":"admin5","ROLE":"MANAGER"},
{"USER_ID":"UID00012","ENTERPRISE_ID":"admin6","ROLE":"DEVELOPER"},
{"USER_ID":"UID00013","ENTERPRISE_ID":"admin7","ROLE":"DBA"}]
In the first example, the data variable exists only within the scope of the load function:
function load() {
var data = JSON.parse(sessionStorage.getItem("loginInfo"));
//...
}
And then you try to reference it outside of that function:
onclick='loadSegment(data[0])'
It doesn't exist at this point, so you can't reference it. By contrast, in the second example you create the data variable in global scope, so it exists on the window object and can be referenced anywhere.
To encapsulate the data variable within that function, you'll need to supply the HTML you're creating with all of the information it needs to call the loadSegment function, not just an index reference. Maybe serialize the whole value into the function call? Maybe put values on data-* attributes? Maybe move all the code into the function except the data variable and keep that on window scope? You have options, depending on what you're trying to achieve overall.
Side note: You might not want to create something called load on the window object (or any other DOM object). If not actual problems, that could cause confusion with other code.
Changing the functionName will help
function loadfun()
{
var data = JSON.parse(sessionStorage.getItem("loginInfo"));
var html = "";
for (var i = 0; i < data.length; i++) {
html += "<tr><td>" + data[i].ENTERPRISE_ID + "</td>";
html += "<td><button type='button' onclick='loadSegment(data[" + i + "])'>...</button></td>";
html += "<td>" + data[i].USER_ID + "</td></tr>";
}
document.getElementById('roleTable').getElementsByTagName("TBODY")[0].innerHTML = html;
}
function loadSegment(o) {
alert('reading obj');
alert(JSON.stringify(o));
}
I'm having issues dynamically creating content from an array of images. What I want to happen is that when keywords are entered into the searchbar (try "joyride" or "nick"), all of the images that match the keywords show up. Currently, only one image shows up, and it doesn't necessarily match the keyword. I think I'm going wrong with the javascript function - I feel like I shouldn't be using innerHTML to create the photos, especially because when the keyword is deleted, it just leaves the one image.
Would it be easier to do it all in jQuery/javascript, instead of generating the initial gallery of images in jQuery and trying to do the filtering in javascript? I'm lost.
http://scf.usc.edu/~uota/itp301/final/odc-photos.html
This is a working version of the page, with the arrays and other code that I am using.
Thanks in advance!
$(document).ready(function(){
for(var i = 0; i < src.length; i++){
var content = "<div class='pics' id='imagesection" + i + "'>";
content += "<div class='images'><img class='imagesfiles' height='133px' width='200px' src='" + src[i] + "'></div>";
content += "</div>";
$("#gallery").append(content).hide().fadeIn(250);
}
});
var songSearch = function(keyword){
var foundFlag = false;
var content = "";
for (var i = 0; i < src.length; i++){
if (tags[i].toLowerCase().indexOf(keyword) != -1 || keyword == "") {
content = "<div class='pics' id='imagesection" + i + "'>";
content += "<div class='images'><img class='imagesfiles' height='133px' width='200px' src='" + src[i] + "'></div>";
content += "</div>";
findFlag = true;
}
}
if(findFlag){
document.getElementById("gallery").innerHTML = content;
}
else{
content = "Your search did not return any results.";
}
}
</script>
It looks like the problem is on this line in the songSearch function:
content = "<div class='pics' id='imagesection" + i + "'>";
You are redefining the variable content instead of concatenating it. This way it will always be just the last image. Try changing it to:
content += "<div class='pics' id='imagesection" + i + "'>";
There is also have a variable inside the songSearch function called foundFlag that is later referenced as findFlag. That shouldn't be causing the issue though.
I have created a html like this:
<body onload = callAlert();loaded()>
<ul id="thelist">
<div id = "lst"></div>
</ul>
</div>
</body>
The callAlert() is here:
function callAlert()
{
listRows = prompt("how many list row you want??");
var listText = "List Number";
for(var i = 0;i < listRows; i++)
{
if(i%2==0)
{
listText = listText +i+'<p style="background-color:#EEEEEE" id = "listNum' + i + '" onclick = itemclicked(id)>';
}
else
{
listText = listText + i+ '<p id = "listNum' + i + '" onclick = itemclicked(id)>';
}
listText = listText + i;
//document.getElementById("lst").innerHTML = listText+i+'5';
}
document.getElementById("lst").innerHTML = listText+i;
}
Inside callAlert(), I have created id runtime inside the <p> tag and at last of for loop, I have set the paragraph like this. document.getElementById("lst").innerHTML = listText+i;
Now I am confuse when listItem is clicked then how to access the value of the selected item.
I am using this:
function itemclicked(id)
{
alert("clicked at :"+id);
var pElement = document.getElementById(id).value;
alert("value of this is: "+pElement);
}
But getting value as undefined.
Any help would be grateful.
try onclick = itemclicked(this.id) instead of onclick = 'itemclicked(id)'
Dude, you should really work on you CodingStyle. Also, write simple, clean code.
First, the html-code should simply look like this:
<body onload="callAlert();loaded();">
<ul id="thelist"></ul>
</body>
No div or anything like this. ul and ol shall be used in combination with li only.
Also, you should always close the html-tags in the right order. Otherwise, like in your examle, you have different nubers of opening and closing-tags. (the closing div in the 5th line of your html-example doesn't refer to a opening div-tag)...
And here comes the fixed code:
<script type="text/javascript">
function callAlert() {
var rows = prompt('Please type in the number of required rows');
var listCode = '';
for (var i = 0; i < rows; i++) {
var listID = 'list_' + i.toString();
if (i % 2 === 0) {
listCode += '<li style="background-color:#EEEEEE" id="' + listID + '" onclick="itemClicked(this.id);">listItem# ' + i + '</li>';
}
else {
listCode += '<li id="' + listID + '" onclick="itemClicked(this.id);">listItem# ' + i + '</li>';
}
}
document.getElementById('thelist').innerHTML = listCode;
}
function itemClicked(id) {
var pElement = document.getElementById(id).innerHTML;
alert("Clicked: " + id + '\nValue: ' + pElement);
}
</script>
You can watch a working sample in this fiddle.
The problems were:
You have to commit the id of the clicked item using this.id like #Varada already mentioned.
Before that, you have to build a working id, parsing numbers to strings using .toString()
You really did write kind of messy code. What was supposed to result wasn't a list, it was various div-containers wrapped inside a ul-tag. Oh my.
BTW: Never ever check if sth. is 0 using the ==-operator. Better always use the ===-operator. Read about the problem here
BTW++: I don't know what value you wanted to read in your itemClicked()-function. I didn't test if it would read the innerHTML but generally, you can only read information from where information was written to before. In this sample, value should be empty i guess..
Hope i didn't forget about anything. The Code works right now as you can see. If you've got any further questions, just ask.
Cheers!
You can pass only the var i and search the id after like this:
Your p constructor dymanic with passing only i
<p id = "listNum' + i + '" onclick = itemclicked(' + i + ')>
function
function itemclicked(id)
{
id='listNum'+i;
alert("clicked at :"+id);
var pElement = document.getElementById(id).value;
alert("value of this is: "+pElement);
}
is what you want?
I am not sure but shouldn't the onclick function be wrapped with double quotes like so:
You have this
onclick = itemclicked(id)>'
And it should be this
onclick = "itemclicked(id)">'
You have to modify your itemclicked function to retrieve the "value" of your p element.
function itemclicked( id ) {
alert( "clicked at :" + id );
var el = document.getElementById( id );
// depending on the browser one of these will work
var pElement = el.contentText || el.innerText;
alert( "value of this is: " + pElement );
}
demo here
I have asked a question about how to avoiding to write the html in the js,then some people tell me using the javascript template,for example,the jquery/template pugin and ect.
It is a good idea when generate static html,for example:
<ul id="productList"></ul>
<script id="productTemplate" type="text/x-jquery-tmpl">
<li><a>${Name}</a> (${Price})</li>
</script>
<script type="text/javascript">
var products = [
{ Name: "xxx", Price: "xxx" },
{ Name: "yyy", Price: "xxx" },
{ Name: "zzz", Price: "xxx" }
];
// Render the template with the products data and insert
// the rendered HTML under the "productList" element
$( "#productTemplate" ).tmpl( products )
.appendTo( "#productList" );
</script>
However when I try to bind some event to the generated html,I meet some problem.
For example,I have a page which user can search some products by the price/name/location.
So I have three function:
searchByPrice(lowPrice,highPrice,productType,currentPage)
searchByName(name,productType,currentPage);
searchByLocation(location,currentpage);
ALl the above function have a realated method in the server side and they will retrun the products usint the xml format.
Since they will retrun so many items,so I have to paging them,the "currengPage" is used to tell the server side which part of results should be returned.
When the client get the result from the server side,now it is the js for display them int he div and create a Paging Bar if possible.
Before I know the template,I use this manner(which I hate most,try my best to avoid):
function searchByPrice(lowPrice,highPrice,productType,currentPage){
var url="WebService.asmx/searchByPrice?low="+lowPrice="&high="+highPrice+"&curPage="+currentPage;
//code to create the xmlHttp object
xmlhttp.open("GET",url,true);
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
var i=0;
var Prohtml="";
var proList=parseProductList(xmlhttp.responseText);
for(i=0;i<prolist.length;i++){
Prohtml+="<li><a href='#'>"+prolist[i].name+"</a> ("+prolist[i].price"+)</li>";
}
//generate the paging bar:
var totleResult=getTotleResultNumber(xmlhttp.responseText);
if(totleResult>10){
var paghtml="<span>";
//need the paging
var pagNum=totleResult/10+1;
for(i=1;i<=pagenum;i++){
paghtml+="<a onclick='searchByPrice(lowPrice,highPrice,productType,currentPage+1)'>i</a>";
//here the synax is not right,since I am really not good at handle the single or doule '"' in this manner.
//also if in the searchByName function,the click function here should be replaced using the searchByName(...)
}
}
}
}
}
In the example,it is easy to use the template to generate the "Prohtml" since there is no event handling with them,but how about the "paghtml",the click function is different in differnt search type.
So,any good idea to hanld this?
Either:
Create DOM Elements instead of building HTML strings, using document.createElement or a small library if you're doing lots of this, which will allow you to attach events immediately in the usual fashion.
or
Give each element which needs to make use of event handlers a unique ID and build up a list of events to be attached once the HTML has been inserted into the document.
E.g.:
var eventHandlers = []
, eventCount = 0;
for (i = 1; i <= pagenum; i++) {
var id = "search" + eventCount++;
html += "<a id='" + id + "'>" + i + "</a>";
eventHandlers.push([id, 'click',
handler(searchByPrice, lowPrice, highPrice, productType, currentPage + i)])
}
// Later...
someElement.innerHTML = html;
registerEvents(eventHandlers);
Where registerEvents is:
function registerEvents(eventHandlers) {
for (var i = 0, l = eventHandlers.length; i < l; i++) {
var eventHandler = eventHandlers[i],
id = eventHandler[0],
eventName = eventHandler[1],
func = eventHandler[2];
// Where addEvent is your cross-browser event registration function
// of choice...
addEvent(document.getElementById(id), eventName, func);
}
}
And handler is just a quick way to close over all the arguments passed in:
/**
* Creates a fnction which calls the given function with any additional
* arguments passed in.
*/
function handler(func) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
func.apply(this, args);
}
}
I use something like this approach (but automatically adding unique ids when necessary) in the HTML generation portion of my DOMBuilder library, which offers a convenience method for generating HTML from content you've defined, inserting it into a given element with innerHTML and registering any event handlers which were present. Its syntax for defining content is independent of output mode, which allows you to switch between DOM and HTML output seamlessly in most cases.
First of all, you can simply use the $.get() or $.ajax() for your AJAX call.
Secondly, you can use .live() or .delegate() to bind events to elements that do not exist.
Thirdly, you can use the data attributes in the anchor elements as a way to pass in the arguments for the event handler, see .data().
So, to rewrite your function, you have may something like the following:
function searchByPrice(event) {
$this = $(this);
var lowPrice = $this.data('lowPrice'),
highPrice = $this.data('lowPrice'),
productType = $this.data('productType'),
currentPage = $this.data('currentPage');
var url = "WebService.asmx/searchByPrice?low=" + lowPrice = "&high=" + highPrice + "&curPage=" + currentPage;
$.get(url, function(data, textStatus, jqXHR) {
var i = 0;
var Prohtml = "";
var proList = parseProductList(data);
for (i = 0; i < prolist.length; i++) {
Prohtml += "<li><a href='#'>" + prolist[i].name + "</a> (" + prolist[i].price "+)</li>";
}
//generate the paging bar:
var totleResult = getTotleResultNumber(data);
if (totleResult > 10) {
var paghtml = "<span>";
//need the paging
var pagNum = totleResult / 10 + 1;
for (i = 1; i <= pagenum; i++) {
paghtml += '<a class="pagelink" ' +
'data-lowPrice="' + lowPrice + '" ' +
'data-highPrice="' + highPrice + '" ' +
'data-productType="' + productType + '" ' +
'data-currentPage="' + (currentpage + 1) + '">' + i + '</a>';
//here the synax is not right,since I am really not good at handle the single or doule '"' in this manner.
//also if in the searchByName function,the click function here should be replaced using the searchByName(...)
}
}
});
}
$(document).ready(function(){
$("a.pagelink").live('click', searchByPrice);
});