How to catch creation of DOM elements and manipulate them with jQuery - javascript

I'm trying to devise a method of when adding a simple div element with a class and some data-* in it, it will replace it or add into it some other elements. This method should not be called manually, but automatically by some kind of .live() jQuery method, a custom event or some kind like $('body').bind('create.custom'), etc.
I need it this way since I wouldn't know in advance what elements will be created since they will be served through ajax like single empty div's or p's .
<!DOCTYPE html>
<html>
<head>
<title >on create</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" ></script>
<script type="text/javascript" >
jQuery(function($){
$("div.fancyInput").each(function(index,element){
var $div = $(this);
var dataId = $div.attr("data-input-id");
var inputId = '';
var labelId = '';
if(!!dataId){
inputId = 'id="' + dataId + '"';
labelId = 'id="' + dataId + 'Label"';
} // if
var dataValue = $div.attr();
$(
'<p class="fancyInput" >' +
' <label ' + labelId + ' for="' + inputId + '" >A fancy input</label>' +
' <input ' + inputId + ' name="' + inputId + '" value="A fancy input" />' +
'</p>'
).appendTo($div);
}); // .each()
}); // jQuery()
</script>
<script type="text/javascript" >
jQuery(function($){
var counter = 2;
var $form = $('#form');
$('#add').click(function(event){
$('<div class="fancyInput" data-input-id="fancyInput' + counter + '" ></div>').appendTo($form);
counter++;
}); // .click
}); // jQuery()
</script>
</head>
<body>
<a id="add" href="#" > add another one </a>
<form id="form" action="#" >
<p class="normalInput" >
<label id="normalInputLabel" for="normalInput" >A normal input</label>
<input id="normalInput" name="normalInput" value="A normal input" />
</p>
<div class="fancyInput" ></div>
</form>
</body>
</html>
Update:
I checked liveQuery beforehand, it's that kind of functionality that I need, but with the ability to modify DOM elements while the event callback is executed. So it's not just that I need events attached, but the ability to modify the DOM upon element creation. For example: whenever a new is created, it should be filled in (even better if replaced) with the p, label and input tags

You could use a DOM Level 3 Event, like DOMNodeInserted. This could look like:
$(document).bind('DOMNodeInserted', function(event) {
// A new node was inserted into the DOM
// event.target is a reference to the newly inserted node
});
As an alternative, you might checkout the .liveQueryhelp jQuery plugin.
update
In referrence to your comment, have a look at http://www.quirksmode.org/dom/events/index.html, only browser which do not support it are the Internet Explorers of this this world (I guess IE9 does at least).
I can't say much about the performance, but it should perform fairly well.

Related

Accessing Wikipedia API with JSONP

I've been trying for the last few days to make my code work, but I just can't find the problem.
I want to make communication with the Wikipedia server and get their JSON API so I can make a list of items corresponding to the input value of searchInput.
I've been looking into JSONP, finding in the end that I can add "&callback=?" to my API request and that it should work.
Now, even though I've added it, the communication still isn't happening.
I've noticed that the console on codepen.io returns "untitled" for a moment while initializing the code after processing the "#searchInput" input.
Perhaps the problem is in my for...in loop.
Do you have any idea what I should do?
The link to my code: http://codepen.io/nedsalk/pen/zqbqgW?editors=1010
(JQuery is already enabled in the "settings" menu)
If you prefer the .html edition of the code:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Object Oriented JavaScript </title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"> </script>
</head>
<body>
<h1> Wikipedia viewer </h1>
Go random!
<form>
<input type="text" name="searchInput" id="searchInput" placeholder="Search Wikipedia"
onkeydown = "if (event.keyCode == 13)
document.getElementById('submit-button').click()"/>
<input type="submit" id="submit-button"/>
</form>
<div id="list"></div>
<script>
$(document).ready(function() {
$("#submit-button").on("click",function (){
var input=$("#searchInput").val();
$.getJSON('https://en.wikipedia.org/w/api.php?action=query&generator=search&gsrsearch=' + encodeURIComponent(input) + '&prop=extracts&exlimit=10&exintro&exsentences=2&format=json&callback=?',
function(API){
$("#list").empty();
for (var id in API.query.pages)
{if(API.query.pages.hasOwnProperty(id){
$("#list").html('<a target="_blank" href="http://en.wikipedia.org/?curid=' + id + '">'
+'<div id="searchList">'
+ "<h2>" + id.title + "</h2>"
+ "<br>"
+ "<h3>" + id.extract + "</h3>"
+ "</div></a><br>")
}}
})
})
})
</script>
</body>
</html>
You have several issues in your code:
you should hook to the submit event of the form, not the click of the button, and use event.preventDefault() to stop the submission.
you loop through the keys of the returned object and attempt to access properties of those strings, instead of using the keys to access the underlying properties.
you set the html() in each loop, so only the final item will be visible. You should use append() instead.
Try this:
$("form").on("submit", function(e) {
e.preventDefault();
var input = $("#searchInput").val();
$.getJSON('https://en.wikipedia.org/w/api.php?action=query&generator=search&gsrsearch=' + encodeURIComponent(input) + '&prop=extracts&exlimit=10&exintro&exsentences=2&format=json&callback=?', function(response) {
var pages = response.query.pages;
$("#list").empty();
for (var id in pages) {
$("#list").append('<a target="_blank" href="http://en.wikipedia.org/?curid=' + id + '">' +
'<div id="searchList">' +
"<h2>" + pages[id].title + "</h2>" +
"<br>" +
"<h3>" + pages[id].extract + "</h3>" +
"</div></a><br>")
}
});
});
Working example

How to register click events after modifying html inside a jQuery each [duplicate]

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 7 years ago.
THIS IS NOT A DUPLICATE. THE SUGGESTED "DUPLICATE" IS IN REFERENCE TO OBJECTS THAT EXIST IN HTML, BUT HAVE NOT YET DRAWN IN THE DOM WHICH IS USUALLY REMEDIED USING THE ONLOAD EVENT. MY ISSUE IS SIMILAR, BUT THE CONTENT IS BEING CREATED -AFTER- THE PAGE HAS COMPLETELY RENDERED
The issue I am having is after replacing html, I can not register events on the newly formed html. The 'this' in the loop, doesn't seem to propegate with the new change, and there doesn't appear to be anyway to set it up.
What I would like it to do, is :
Completely replace an html element (including itself as the parent, not just the inner content)
Register events on the newly formed html during the replacement.
Following is a very basic demonstration of the problem.
HTML
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" type="text/javascript"></script>
<script src="MyNewSelect.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#SomeOldSelect').MyNewSelect();
});
</script>
</head>
<body>
<select id="SomeOldSelect">
<option value="foo">Bar</option>
</select>
</body>
</html>
jQuery function
(function( $ ) {
$.fn.MyNewSelect = function() {
this.each(function(){
// Rebuild the HTML from select tag
$(this).children('option').each(function(){
nHtml += '<span value="' + $(this).text() + '"><a class="fa" style="color: ' + $(this).val() + ';"></a>' + $(this).text() + '</span>';
});
nHtml += '<div id="' + $(this).attr("id") + '">' + nHtml + '</div>';
// Replace select tag with new html
$(this).replaceWith(nHtml);
// Register click event on new html
$(this).find('span').click(function() {
console.log($(this).text());
});
}
}
}( jQuery ));
An alternative is to wrap the new html into a jQuery object and bind the handlers within that object
nHtml += '<div id="' + $(this).attr("id") + '">' + nHtml + '</div>';
var $html = $(nHtml);
$(this).replaceWith($html);
$html.find('span').click(function() {
console.log($(this).text());
});
this refers to the DOM element you just removed. Try using the id?
...
var id = $(this).attr("id");
$(this).replaceWith(nHtml);
$('#'+id).find('span').click(function() {
console.log($(this).text());
});
...

jquery each loop write data for each div

I hope this makes sense. I have an onclick and I am trying to write this data for each div with this.
jQuery('.circle_counter_div').each(function() {
var tagtext = '[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]';
})
I am cloning items but I can only write the data for one of them. How do I write data for each cloned item?
So with the above example I want tagtext to equal
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
Full Code
HTML
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<input type="submit" class="sc_options circle_counter_div" id="insert" name="insert" value="<?php _e("Insert", 'themedelta'); ?>" onClick="insertcirclecountershortcode();" style="display:none"/>
Script
// Insert the column shortcode
function insertcirclecountershortcode() {
var tagtext;
var start;
var last;
var start = '[circlecounters]';
var last = '[/circlecounters]';
jQuery('.circle_counter_div').each(function() {
var tagtext = '[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]';
})
var finish = start + tagtext + last;
if (window.tinyMCE) {
window.tinyMCE.execInstanceCommand(window.tinyMCE.activeEditor.id, 'mceInsertContent', false, finish);
//Peforms a clean up of the current editor HTML.t
//tinyMCEPopup.editor.execCommand('mceCleanup');
//Repaints the editor. Sometimes the browser has graphic glitches.
tinyMCEPopup.editor.execCommand('mceRepaint');
tinyMCEPopup.close();
}
return;
}
Extended Answer: After some more information was provided perhaps you're just missing the index and value properties on the loop. Its hard to tell, since little sample code is provided.
$('.test').each(function(i,v) {
var tagtext = $(v).html();
console.log(tagtext);
})
http://jsfiddle.net/4xKvh/
Original Answer:
Use use classes instead of an Id. Id's are only suposed to be used once on a page.
Since there should only be one occurance jQuery is filtering the result down to 1, even though the markup may have multiple elements with that Id on the page. This is to make use of the built-in browser function getElementById().
For proof checkout this jsFiddle
Using the class attribute is more appropriate for what you're trying to do.
jQuery('.clone_this').each(function() {
var tagtext = '[something][/something]';
})
And the markup:
<div class="clone_this"></div>
This will allow jQuery to return an array of elements like you're looking for
This is what I needed... Finally got it working.
tagtext = ' ';
jQuery('#circle_counter_div .circlecounter').each(function() {
tagtext += '[circlecounter rel="' + jQuery('.circle_size').val() + '" datathickness="' + jQuery('.circle_thickness').val() + '" datafgcolor="' + jQuery('.circle_color').val() + '" text="' + jQuery('.circle_text').val() + '" fontawesome="' + jQuery('.font_awesome_icon').val() + '" fontsize="' + jQuery('.circle_font_size').val() + '"][/circlecounter]';
});
var start = '[circlecounters]';
var last = '[/circlecounters]';
var finish = start + tagtext + last;

Javascript append/remove elements

I have one question. Is possible delete <span> element added with javascript append?
When i try remove added span then nothing happens.
Like this:
<script type="text/javascript">
$(document).ready(function(){
$('#SelectBoxData span').click(function(){
var StatusID = this.id;
var StatusIDSplit = StatusID.split("_");
var StatusText = $('#SelectBoxData #' + StatusID).text();
$("#SelectBox").append('<span id=' + StatusID + '>' + StatusText + '</span>');
$("#SelectBoxData #" + StatusID).remove();
InputValue = $("#StatusID").val();
if(InputValue == ""){
$("#StatusID").val(StatusIDSplit[1]);
}
else{
$("#StatusID").val($("#StatusID").val() + ',' + StatusIDSplit[1]);
}
});
$('#SelectBox span').click(function(){
var StatusID = this.id;
$("#SelectBox #" + StatusID).remove();
});
});
</script>
<div id="SelectBoxBG">
<div id="SelectBox"><div class="SelectBoxBtn"></div></div>
<div id="SelectBoxData">
<span id="StatusData_1">Admin</span>
<span id="StatusData_2">Editor</span>
<span id="StatusData_4">Test 1</span>
<span id="StatusData_6">Test 2</span>
</div>
<input type="hidden" id="StatusID" />
</div>
Please help me.
Thanks.
Yes, you can delete them. However, you can't add click event handlers to them before they exist. This code:
$('#SelectBox span').click(function(){
var StatusID = this.id;
$("#SelectBox #" + StatusID).remove();
});
will only add a click event handler to <span> elements inside of #SelectBox at the time the code is run (so, based on your provided HTML, zero elements). If you want the event handler to react to dynamically added elements then you need to use a technique called event delegation, using the .on() function:
$('#SelectBox').on('click', 'span', function() {
$(this).remove(); // equivalent to the code you had before
});

Javascript, copy text field to new li class

UPDATED, TO BE MORE CLEAR:
My current field that contains the value ‘1201026404’ (which will change every time) :
<input id="ticket_fields_20323656" name="ticket[fields][20323656]" size="30" style="width:125px;" type="text" value="1201026404" tabindex="11">
The LI where I want the copied value ‘1201026404’ (which will change every time) to go when the page loads:
<ul class="multi_value_field" style="width: 99.5%;">
<li class="choice" choice_id="1201026404">1201026404<a class="close">×</a><input type="hidden" name="ticket[set_tags][]" value="1201026404" style="display: none;"></li>
</ul>
The Javascript that I have already made but need help with:
<script type="text/javascript">
copy = function()
{
var n1 = document.getElementById("ticket_fields_20323656");
var n2 = ‘what goes here??’
n2.value = n1.value;
}
</script>
does this work in firefox:
<script type="text/javascript">
copy = function()
{
var n1 = document.getElementById("ticket_fields_20323656");
var n2 = document.querySelectorAll("ul.multi_value_field li:first");
n2.innerHTML = n1.value;
}
</script>
this uses querySelectorAll which doesnt exist in IE6,7,8 - otherwise you need to use the id of the element which im not sure you have
You're going to have to use an ID on the li element.
<li id="choice_20323656">
then you can copy it like
<script type="text/javascript">
copy = function()
{
var n1 = document.getElementById("ticket_fields_20323656");
var n2 = document.getElementById("choice_20323656");
n2.innerHTML = n1.value;
}
</script>
EDIT:
If you can use jQuery 1.6 or up, this will work:
$("#ticket_fields_20323656").keyup(function(e) {
$(".choice")
.attr("choice_id",e.currentTarget.value)
.html(e.currentTarget.value
+ "<a class=\"close\">×</a><input"
+ " type=\"hidden\" name=\"ticket"
+ "[set_tags][]\" value=\""
+ e.currentTarget.value
+ "\" style=\"display: none;\">");
});​
Here's a demo: http://jsfiddle.net/JKirchartz/V2L25/, However you should know, if you have multiple things with the class choice their value's going to change in the same way like this: http://jsfiddle.net/JKirchartz/V2L25/4/

Categories

Resources