Dynamic <a> not clickable - javascript

I have done the following code in php so that I can click on the arrow and a form opens below
echo '<div class="editor" id="'.$par_code.'" style=" background-color: #fdfdfd; padding:14px 25px 30px 20px; font-family: Lucida Console, Monaco, monospace; box-shadow: 0 1px 10px 2px rgba(0,0,0,0.2),0 8px 20px 0 rgba(0,0,0,0.03); border-radius: 3px;">'
.'<img width="50" height="50" style="border-radius:50%" src="images/default.png" alt="Image cannot be displayed"/>'
.'<p class="uname"> '.$uname.'</p> '
.'<p class="time">'.$date.'</p>'
.'<p class="comment-text" style="word-break: break-all;">'.$content.'</p>'
.'<a class="link-reply al" id="reply" name="'.$par_code.'" style="padding-top: 18px; float: right;"><i class="fa fa-reply fa-lg" title="Reply"></i></a>';
My javascript code:
$(document).ready(function() {
$("a#reply").one("click" , function() {
var comCode = $(this).attr("name");
var parent = $(this).parent();
var str1 = "new-reply";
var str2 = "tog";
var res = str1.concat(i);
var tes = str2.concat(i);
// Create a new editor inside the <div id="editor">, setting its value to html
parent.append("<br /><center><form action='index.php' method='post' id='"+tes+"'><input class='iptext2' type='text' name='uname2' id='uname2' placeholder='Your Name' required /><div style='padding-bottom:5px'></div><textarea class='ckeditor' name='editor' placeholder='Your Query' id='"+res+"' required></textarea><input type='hidden' name='code' value='"+comCode+"' /><br/><input type='submit' class='form-submit' id='form-reply' name='new_reply' value='Reply' /></form></center>")
CKEDITOR.replace(res);
/*
var x = document.getElementById("tes");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
*/
i++;
});
})
The following is my css code applied to the anchor tag:
.al {
font-size:11.2px;
text-transform: uppercase;
text-decoration: none;
color:#222;
cursor:pointer;
transition:ease 0.3s all;
}
.al:hover {
color:#0072bc;
}
.link-reply {
color:#767676;
}
Here the arrow icon is displayed but is not clickable

Your code fails, because your <a> elements are created dynamically, whereas the event listener is added only to the elements available when the document has loaded.
In order to get your code to work, you need to use event delegation; that is to add the event listener to a common static ancestor, such as the document or the body, that will in turn delegate it to your target elements.
The methods you can use to achieve this effect in jQuery are on and one, with the latter fitting your case better, if you are trying to attach one-time event listeners.
Code:
$(document).one("click", "a#reply", function() {
// ...
});

Use on for dynamic created events on DOM.
$(document).on("click","a#reply" , function() {
console.log('a#reply => clicked!')
});
Or
$(body).on("click","a#reply" , function() {
console.log('a#reply => clicked!')
});

Related

How to add eventlistener to dynamically created divs

How to add event delegation to dynamically created divs, to change property of the target div? I've tried several suggestions that I found for event delegation but none of them work. I think I'm making some mistakes but I don't know how to fix.
I am trying to develop a file thumbnail list interface with HTML and JavaScript. I made a method that draws thumbnails dynamically from an Array. And now I want to add some functions to manipulate the thumbnails, ex. changing border color of the item(div) when it is clicked.
First I tried loop-method to add event listeners to the divs, but it didn't work well. And now I learned that event delegation is better way to add event listeners to dynamically created elements. But the problem is that though I'v tried codes but they didn't work at all.
I think I am making some mistakes or mis-using methods but I don't know what is the problem.
JavaScript
function drawThumbnails(area, list){
var j
var createdList = []
for (j=0; j<list.length; j++){
var thmb = document.getElementById("fileThumb");
var name = document.getElementById("itemName");
var date = document.getElementById("itemDate");
var thmbimg = document.getElementById("fileThumbImage");
var thmbicon = document.getElementById("file_icon_thumb");
name.innerHTML=list[j][0];
date.innerHTML=list[j][1];
if (list[j][2] == "folder"){
thmbimg.src = "thmb_folder.png";
thmbicon.style.display = "none";
}
else {
if (list[j][2] == "img"){
thmbimg.src=getthmbimgsample();
}
else{
thmbimg.src = getThmbimg(list[j][2]);
}
thmbicon.style.display = "block";
thmbicon.src = getThmbicon(list[j][2]);
}
var cln = thmb.cloneNode(true);
cln.style.display = "block";
document.getElementById(area).append(cln);
createdList.push(cln);
}
thmbLists.push(createdList);
}
drawThumbnails("folderArea", folders);
drawThumbnails("fileArea", files);
document.getElementById("folderArea").addEventListener('click',function(e){
if(e.target && e.target.className == "fileThumb"){
e.target.style.borderColor = "#408CFF";
}
});
HTML
<body>
<div class = "contentArea" id="contentArea">
<div class = "thumbArea" id="folderArea">
<div class = "fileThumb" id="fileThumb">
<img src="icon_thumb_folder.png" class="fileThumb_normal" id="fileThumbImage">
<div class="fileName">
<img src="icon_thumb_file.png" style="width: 20px;" id="file_icon_thumb">
<div class="fileNameLine" id = "itemName">File/FolderName</div>
<div class="fileNameDate" id="itemDate">Date</div>
</div>
</div>
</div>
<div class = "contentAreaSectionHeader">
<input type="checkbox" id="chTest2" name="chTest2">
<label for="chTest2"><span>Files</span></label>
</div>
<div class = "thumbArea" id="fileArea">
</div>
</body>
CSS
.fileThumb{
width: 213px;
height: 183px;
border-radius: 2px;
border-style: solid;
border-width: 1px;
border-color: #EEEEEE;
text-align: center;
position: relative;
float:left;
margin: 18px;
display: none;
overflow: hidden;
}

How to get a particular <div>'s data by it's id by using js in android webview?

I'm a beginner in web developement so please do excuse me if my question is foolish . Bascially I'm using a html+css+js script for showing a textEditor in webView which is shown without any problem but now problem is how can I get the particular having id "myEditor"'s content ? Can anyone please help me to fix this issue ?
HTML code:
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-
awesome/4.7.0/css/font-awesome.css">
</head>
<body>
<style>
#editorContainer {
max-width: 600px;
margin: auto;
}
#myEditor {
border: 1px solid #000;
padding: 20px;
}
#toolbar {
padding: 10px 20px;
border: 1px solid #d9d9d9;
background-color: #d9d9d9;
}
#toolbar button {
border: 1px solid transparent;
font-size: 18px;
cursor: pointer;
padding: 5px 10px;
background-color: transparent;
}
#toolbar button:hover {
border: 1px solid #2e2e2e;
}
</style>
<div id="editorContainer">
<div id="toolbar">
<button onclick="document.execCommand('bold',true,'' )"><i class="fa fa-bold" aria-hidden="true"></i></button>
<button onclick="document.execCommand('italic', true, '')"><i class="fa fa-italic" aria-hidden="true"></i></button>
<button onclick="document.execCommand('underline', true, '')"><i class="fa fa-underline" aria-hidden="true"></i></button>
<button onclick="document.execCommand('strikethrough', true, '')"><i class="fa fa-strikethrough" aria-hidden="true"></i></button>
</div>
<div id="myEditor" contenteditable="true">
<h1>Simple Text Editor</h1>
<p>This is a very simple text editor. I will add other features and design elements to it as time goes along.</p>
</div>
</div>
<!-- Based on Codeburst.io Tutorial: https://codeburst.io/how-to-build-your-own-wysiwyg-editor-6002fa3f5ea8 -->
<!--
Features to add:
- Save command state
-->
<script>
var onclick = function() {
var cmd = this.getAttribute('data-role');
switch (cmd) {
case 'h1':
case 'h2':
case 'p':
document.execCommand('formatBlock', false, '<' + cmd + '>');
break;
default:
document.execCommand(cmd, false, null);
break;
}
};
var els = document.querySelectorAll('#editControls a');
Array.prototype.forEach.call(els, function(el) {
el.addEventListener('click', onclick);
});
</script>
Now the following code is returning the complete script of the webView but I wonder how to edit this to get only desired result.
Java Code:
webView.evaluateJavascript(
"(function() { return ('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>'); })();",
new ValueCallback<String>() {
#Override
public void onReceiveValue(String html) {
}
});
using Jsoup Library : https://github.com/jhy/jsoup
Document document = Jsoup.parse(html);
Element sampleDiv = document.getElementById("sampleDiv");
Example:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class JsoupTester {
public static void main(String[] args) {
String html = "<html><head><title>Sample Title</title></head>"
+ "<body>"
+ "<p>Sample Content</p>"
+ "<div id='sampleDiv'><a href='www.google.com'>Google</a>"
+ "<h3><a>Sample</a><h3>"
+"</div>"
+ "<div id='imageDiv' class='header'><img name='google' src='google.png' />"
+ "<img name='yahoo' src='yahoo.jpg' />"
+"</div>"
+"</body></html>";
Document document = Jsoup.parse(html);
//a with href
Elements links = document.select("a[href]");
for (Element link : links) {
System.out.println("Href: " + link.attr("href"));
System.out.println("Text: " + link.text());
}
// img with src ending .png
Elements pngs = document.select("img[src$=.png]");
for (Element png : pngs) {
System.out.println("Name: " + png.attr("name"));
}
// div with class=header
Element headerDiv = document.select("div.header").first();
System.out.println("Id: " + headerDiv.id());
// direct a after h3
Elements sampleLinks = document.select("h3 > a");
for (Element link : sampleLinks) {
System.out.println("Text: " + link.text());
}
}
}
Result:
Href: www.google.com
Text: Google
Name: google
Id: imageDiv
Text: Sample
In your Javascript, document.getElementsByTagName('html')[0].innerHTML finds the first instance of an <html> tag, then retrieves the HTML inside it. Since the <html> tag encloses our entire HTML file, it returns the entire file.
To get the HTML of a particular element with an ID of myEditor, try using document.getElementById('myEditor').innerHTML, which finds the first instance of an element with the matching ID attribute and returns its innerHTML.

Click event not working in Chrome extension options page

In my options page I generate some rows with an input number and a button, related to entries at chrome storage.
The problem is that the event listener i'm creating for the buttons doesn't work at all.
options.html
<html>
<head>
<title>Select the movie's Id</title>
<style>
body: { padding: 10px; }
.style-1 input[type="number"] {
padding: 10px;
border: solid 1px #dcdcdc;
transition: box-shadow 0.3s, border 0.3s;
width: 5em;
}
.style-1 input[type="number"]:focus,
.style-1 input[type="number"].focus {
border: solid 1px #707070;
box-shadow: 0 0 5px 1px #969696;
}
</style>
</head>
<body>
<legend style="border-bottom: solid 1px">Insert</legend>
<input type="number" name="id" id="id" value="">
<button id="save">Insert</button>
<br>
<br>
<legend style="border-bottom: solid 1px">Manage</legend>
<div id="ghost" style="display: none">
<input type="number" name="VAL">
<button name="DEL" id="" >Delete</button>
<br><br>
</div>
<script src="options.js"></script>
</body>
options.js
document.getElementById('save').addEventListener('click', save_options);
chrome.storage.sync.get('movieId', function(result){
for (var i=0; i<result.movieId.length; i++){
createRow(result.movieId[i]);
}
});
function save_options() {
var id = document.getElementById('id').value;
chrome.storage.sync.get('movieId', function(result){
var ids = result.movieId;
ids.push(id);
chrome.storage.sync.set({
'movieId': ids
}, function() {
});
location.reload();
});
}
function createRow(pos){
var newRows= document.getElementById('ghost').cloneNode(true);
newRows.id= '';
newRows.style.display= 'block';
var newRow= newRows.childNodes;
for (var i= 0; i< newRow.length; i++){
var newName= newRow[i].name;
if (newName){
newRow[i].name = newName+pos;
newRow[i].id = pos;
newRow[i].value = pos;
}
}
var insertHere= document.getElementById('ghost');
insertHere.parentNode.insertBefore(newRows,insertHere);
document.getElementById(pos).addEventListener('click', delet());
}
function loop(arrayIds){
console.log('loop');
for (var i=0; i<arrayIds.length; i++){
createRow(i);
}
}
function delet(){
console.log("this.id");
//chrome.storage.sync.remove(id);
}
With this, when I click any of the Delete buttons nothing happens.
I've tried all the combinations I can think for document.getElementById(pos).addEventListener('click', delet()); but none of them work.
document.getElementById(pos).addEventListener('click', delet());
is supposed to be
document.getElementById(pos).addEventListener('click', delet);
In your snippet you are calling delet thus result of that function is added as event listener that is undefined. If you want to bind delet as event handler, pass it to addEventListener without calling it.
EDIT
As I saw your code, you are giving same id to both input and button and when you call document.getElementById it returns input instead of button so, event is binded to input instead of button.
To fix that replace your createRow with this
function createRow(pos) {
var newRow = document.getElementById('ghost').cloneNode(true);
newRow.id= '';
newRow.style.display= 'block';
var value = newRow.querySelector("[name=VAL]");
var button = newRow.querySelector("[name=DEL]");
value.id = "VAL" + pos;
value.value = pos;
button.id = "DEL" + pos;
var insertHere= document.getElementById('ghost');
insertHere.parentNode.insertBefore(newRow, insertHere);
button.addEventListener('click', delet);
}

HTML JS form to div comments (temporary change)

I have seen many similar problems but when I try them they end up failing. It has gotten to the point where my code is totally messed up and I need some help both cleaning it up and fixing my issue. (using chrome)
So far I have tried selecting the value of the form and putting that into a div,
I have tried to use the button as just a link to start the script so that the page doesn't reset and also many other answers found on-line, none of them are helping so I am asking for a personalised help.
function on_comment_add() {
var main = document.getElementById("div1");
var add_user_name = document.createElement("div");
var add_user_comment = document.createElement("div");
add_user_name.setAttribute("id", "add_user_name");
add_user_comment.setAttribute("id", "add_user_comment");
<!-- var node = document.createTextNode("This is new."); -->
var node_1 = document.getElementById("user_name").value;
var node_2 = document.getElementById("user_comment").value;
add_user_name.appendChild(node_1);
add_user_comment.appendChild(node_2);
var element = document.createElement("div");
element.setAttribute("id", "display_comment_div");
element.appendChild(add_user_name);
element.appendChild(add_user_comment);
main.appendChild(element);
main.innerHTML = element;
return false;
}
body {
background-color: lightGreen;
}
div.middle {
width: 80%;
margin-left: 10%;
background-color: #47e077;
height: 940px;
font-size: 10pt;
font-family: aubrey;
border: 3px solid gold;
}
.comments-form {
text-align: center;
}
#display_comment_div {
background: rgba(200, 54, 54, 0.1);
width: 80%;
margin-left: 9%;
border: 0.1px solid lightGreen;
border-radius: 25px;
}
#add_user_name {
width: 45%;
float: left;
}
#add_user_comment {
width: 45%;
display: inline-block;
float: right;
}
<div class="middle">
<div class="comments-form">
<form>
<label for="name" style="width:100px; display:inline-block;">Name</label>
<input id="user_name" type="text" placeholder="name goes here" style="width:300px; margin-left:5px;" />
<br><br>
<label for="comment" style="width:100px; display:inline-block;">Comment</label>
<textarea id="user_comment" placeholder="comment goes here" maxlength="150" style="width:300px;max-width:300px;"></textarea><br>
<button style="margin-left:310px;" onmousedown="return on_comment_add">Submit</button>
</form>
<div id="div1">
</div>
</div>
</div>
I guess what I am asking is if anyone can help me display the username and comment below the form but it seems tricky for me because I have gone through so many answers that don't work for me that I cannot think of any other ways to do it.
For clarification this code is not meant to keep the comments from the form nor is it meant to be a fully functioning site. I am just making slight modifications to some code so that I can hand it in as a college assignment.
Using onclick and pass the event inside:
<button style="margin-left:310px;" onclick="on_comment_add(event)">Submit</button>
And disable the default form submit action:
function on_comment_add(e) {
e.preventDefault()
var main = document.getElementById("div1");
var add_user_name = document.createElement("div");
var add_user_comment = document.createElement("div");
add_user_name.setAttribute("id", "add_user_name");
add_user_comment.setAttribute("id", "add_user_comment");
var node_1 = document.createElement("div");
node_1.innerHTML= document.getElementById("user_name").value;
var node_2 = document.createElement("div");
node_2.innerHTML = document.getElementById("user_comment").value;
add_user_name.appendChild(node_1);
add_user_comment.appendChild(node_2);
var element = document.createElement("div");
element.setAttribute("id", "display_comment_div");
element.appendChild(add_user_name);
element.appendChild(add_user_comment);
main.appendChild(element);
return false;
}
Workable example: https://jsfiddle.net/kingychiu/z6gnqswn/
Change type to "button" to prevent automatical form sending and add parentheses to onmousedown expression:
<button type="button" style="margin-left:310px;" onmousedown="return on_comment_add()">Submit</button>
Then change this
add_user_name.appendChild(node_1);
add_user_comment.appendChild(node_2);
to this (since node_1, node_2 are values, not elements):
add_user_name.innerHTML = node_1;
add_user_comment.innerHTML = node_2;
And remove that line
main.innerHTML = element;
above
return false;
That should work.

jQuery search bar only working one time per page

I am working on a page for pre-registration to events on my website. On this page, people need the ability to add names into as many slots as the event creator would like (so it needs to handle 3 person basketball teams and 50 person banquets). I have had a high quality facebook-like search bar made so that I can neatly search through the database and select the desired people. Sadly I have this search bar being created by a for loop that creates many different ID filled search bars but every one of them is left empty and the first search bar is the only one that is filled.
I found that it deals with the jQuery code at the top of my page. My question/issue is that I need this jQuery to work on multiple search bars on a single page. If anyone can help me accomplish this I'd be greatly appreciative.
The "top code" or JQuery code that pulls from the db successfully is:
$(function(){
$(".search").keyup(function()
{
var inputSearch = $(this).val();
var dataString = 'searchword='+ inputSearch;
if(inputSearch!='')
{
$.ajax({
type: "POST",
url: "../searchMyChap.php",
data: dataString,
cache: false,
success: function(html)
{
$("#divResult").html(html).show();
}
});
}return false;
});
jQuery("#divResult").live("click",function(e){
var $clicked = $(e.target);
var $name = $clicked.find('.name').html();
var decoded = $("<div/>").html($name).text();
$('#inputSearch').val(decoded);
});
jQuery(document).live("click", function(e) {
var $clicked = $(e.target);
if (! $clicked.hasClass("search")){
jQuery("#divResult").fadeOut();
}
});
$('#inputSearch').click(function(){
jQuery("#divResult").fadeIn();
});
});
</script>
<style type="text/css">
body{
font-family: 'lucida grande', tahoma, verdana, arial, sans-serif;
}
.contentArea{
width:600px;
margin:0 auto;
}
/*
#inputSearch
{
width:350px;
border:solid 1px #000;
padding:3px;
}
*/
#divResult
{
position:absolute;
width:545px;
display:none;
margin-top:-1px;
border:solid 1px #dedede;
border-top:0px;
overflow:hidden;
border-bottom-right-radius: 6px;
border-bottom-left-radius: 6px;
-moz-border-bottom-right-radius: 6px;
-moz-border-bottom-left-radius: 6px;
box-shadow: 0px 0px 5px #999;
border-width: 3px 1px 1px;
border-style: solid;
border-color: #333 #DEDEDE #DEDEDE;
background-color: white;
}
.display_box
{
padding:4px; border-top:solid 1px #dedede;
font-size:12px; height:50px;
}
.display_box:hover
{
background:#0088cc;
//background:#3bb998;
color:#FFFFFF;
cursor:pointer;
}
The for-loop code that prints the search bars is as follows:
for($i = 0; $i < $looper; $i++)
{
echo'
<div class="row">
<div class="form-group">
<div class="col-md-12">
<label>Member Name:</label>
<input type="text" class="form-control search" name="member'.$i.'" autocomplete="off" id="inputSearch" placeholder="Search...">
<div id="divResult" style="z-index:999; margin-top: 35px;" ></div>
</div>
</div>
</div>';
}
EDIT: Working JSFiddle
The first issue is that with each iteration of the for loop an element is created with id="divResult". An ID should be used once in the whole document. I have changed the for loop to produce an element with class="divResult" instead. If you use this change, remember that your CSS will need to be changed accordingly.
for ($i = 0; $i < $looper; $i++) {
echo '
<div class="row">
<div class="form-group">
<div class="col-md-12">
<label>Member Name:</label>
<input type="text" class="form-control search" name="member'.$i.'" autocomplete="off" id="inputSearch" placeholder="Search...">
<div class="divResult" style="z-index:999; margin-top: 35px;"></div>
</div>
</div>
</div>';
}
Next we iterate over each .search element. Within each iteration we can find the corresponding 'result' element by using jQuery's next() function, which retrieves the immediately following sibling of an element. If the code is ever changed such that the 'results' element does not appear straight after the `.search' element, this will need changing.
$(function () {
$('.search').each(function(index) {
var $searchElement = $(this);
var $resultElement = $searchElement.next();
console.log(index, $searchElement, $resultElement);
$searchElement.on('keyup', function() {
var inputSearch = $searchElement.val();
var dataString = 'searchword=' + inputSearch;
if (inputSearch != '') {
$.ajax({
type: "POST",
url: "../searchMyChap.php",
data: dataString,
cache: false,
success: function (html) {
$resultElement.html(html).show();
}
});
}
return false;
});
$resultElement.on("click", function (e) {
var $clicked = $(this);
var $name = $clicked.find('.name').html();
var decoded = $("<div/>").html($name).text();
$searchElement.val(decoded);
});
$(document).on("click", function (e) {
var $clicked = $(e.target);
if (!$clicked.hasClass("search")) {
$resultElement.fadeOut();
}
});
$searchElement.on('click', function () {
console.log(index + ' clicked');
$resultElement.fadeIn();
});
});
});

Categories