I'm creating button which allows to enter post section. I'm checking if the body has class 'logged-in'. If test is false I want to create div container for message " You have to logi in" and append it to my section. My problem: Everytime when I click this button, new node is appended.
- How to invoke handler only once ?
if( !isOnline ) {
e.preventDefault();
var divForLog = document.createElement('div'),
linkElement = document.createElement('a');
linkElement.setAttribute('href', 'http://domain/login');
linkElement.text = "log in"
divForLog.innerHTML = "You have to ";
divForLog.appendChild(linkElement);
document.getElementById('last_questions').appendChild(divForLog);
}
There are several potential solutions, but I'll only list a couple here.
"Global"
Create a variable var loginShown in the scope where the handler is created. Then, change the ! isOnline check to ! isOnline && ! loginShown in the if statement, and set loginShown = true once you've appended the div.
Fiddle the DOM
Depending on the other content of #last_questions you can simply test whether or not the login element has already been appended using:
if ( ! document.getElementById('last_questions').querySelector('div > a[href="http://domain/login"]' ) ) {
...
}
Failing that, you can do as #NewToJS mentioned in the comments and add an attribute to the parent (once the div has been appended) which you can test for, such as an ID or data- attribute.
Unbind the Event
Easier if you're using jQuery, as mentioned by #Pawel you can simply unbind the event once the div has been appended. Probably the cleanest solution, but also trickier to implement. It also depends what else the handler is doing.
Try to set an attribute id to your div (container in my example) and when the user click check if the element with id already exist in document, if not add it :
if( !isOnline && document.getElementById('container').length==0) {
e.preventDefault();
var divForLog = document.createElement('div'),
linkElement = document.createElement('a');
linkElement.setAttribute('href', 'http://domain/login');
linkElement.text = "log in"
divForLog.innerHTML = "You have to ";
divForLog.appendChild(linkElement);
divForLog.setAttribute('id', 'container'); //Add id attribute
document.getElementById('last_questions').appendChild(divForLog);
}
Hope this helps.
If you're using jQuery something you could do(from the documentation .one | jQuery).
$("#button" ).one( "click", function() {
var divForLog = document.createElement('div'),
linkElement = document.createElement('a');
linkElement.setAttribute('href', 'http://domain/login');
linkElement.text = "log in"
divForLog.innerHTML = "You have to ";
divForLog.appendChild(linkElement);
document.getElementById('last_questions').appendChild(divForLog);
});
However another way I could think of would be to use jQuery's
$('#last_questions').html(divForLog);
Update
If thats not an option(most likely, as the #last_questions div may contain other stuff), you can create a <div id="log-in-alert"></div> which will live inside the #last_questions and only replace the html in this
Hope I was able to help??
Related
So I have a list of items with anchor a that successfully listen to the following event:
$('body[data-link="media"] #media_content a').on('click',function(e){
e.preventDefault();
var page = $('.page.active a')[0].innerHTML;
var date = $('.year_sorting .filter_years').val();
var id = $(e.currentTarget).data('media');
window.location.href = 'http://'+basePath+'media/content/'+id+'?date='+date+'&page='+page;
})
However in the same page, there is a filter allowing the user to change the year filter and once changed, the following execute and append a list of items that has the exact same layout as the a above $('body[data-link="media"] #media_content a'), which supposes to listen to the above event as well. the filter event is below:
$('.activity.filter_years').on('change',function(){
$('.pagination_ul').remove();
r_year = $(this).val();
$.get("media/getActivity",{type:'0',key:r_year}).done(function(d){
if(d.length>0){
$('#media_content').html('');
var ul = '<ul class="ap pagination-sm pagination_ul"></ul>';
$('.pagination_menu').append(ul);
for(var i=0;i<d.length;i++){
var p = ['',''];
if(!d[i].event_period){
p = ['style="color:#8A8A8A;"','style="color:#C7C7C7;"'];
}
if(locale=='en'){
var event = $('<div class="div_media_content_f2 '+d[i].pagination+' pagination-tr"> <div class="div_media_content_f2_3"> <span class="font12_bold">'+d[i].event_date+'</span> <div>'+d[i].event_title+'</div></div></div>')
}else if(locale=='hk'){
var event = $('<div class="div_media_content_f2 '+d[i].pagination+' pagination-tr"> <div class="div_media_content_f2_3"> <span class="font12_bold">'+d[i].event_date+'</span> <div>'+d[i].event_title_zh+'</div></div></div>')
}else {
var event = $('<div class="div_media_content_f2 '+d[i].pagination+' pagination-tr"> <div class="div_media_content_f2_3"> <span class="font12_bold">'+d[i].event_date+'</span> <div>'+d[i].event_title_cn+'</div></div></div>')
}
$('#media_content').append(event);
}
pagination('.pagination_ul','.pagination-tr',Math.ceil(d.length/20),false);
}else{
$('#div_news_content_right').html('').append('<div class="not_available">No content available</div>');
}
})
})
in which you can see the list of items are being appended into the layout by JS. However, even with the same layout $('body[data-link="media"] #media_content a'), such appended list of items do not listen to the onclick event. the above js codes are together in a separate js file apart from the html file where I tried to put the first a event into the html file but the new appended list of items still do not listen.
Cannot think of other work around at the moment, please help to see what would be the cause of it. Thank you.
Maybe simple try this.
$(document).on('click', 'body[data-link="media"] #media_content a')
If your element is dynamic create you should bind the click event on document and target what's element should dispatch the event.This is different to bind click only on element because the event will unbind while you remove the element.
Updated:
I'm not sure I've understand all the script you have but I try to simplify the issue.
This is the jsbin and its work correctly.
JSBin
I try to write a script based on JavaScript for replacing the current selected anchor element with it's inner HTML.
You can also find a simple running example in JSFiddle. To run the example, click on the first link, and the click the button.
So, for example, if I have the following HTML:
<p>
Wawef awef <em>replace</em> <strong>me</strong>
falwkefi4hjtinyoh gf waf eerngl nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg
<a href="http://www.anothersite.com/>replace me</a> klserng sreig klrewr
</p>
and I like when I click on some of the two anchors to remove the anchor with it's inner HTML. This mean, that if I click on the first anchor element, and click the appropriate button to replace the anchor the result should be like that:
<p>
Wawef awef <em>replace</em> <strong>me</strong> falwkefi4hjtinyoh gf waf eerngl
nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg <a href="http://www.anothersite.com/>replace me</a>
klserng sreig klrewr
</p>
My JavaScript code for this functionality is the following:
// Start tracking the click event on the document
document.addEventListener(
'click',
function(event)
{
// If right click, return
if(event.button == 2)
{
return;
}
// Get the current clicked document element
var link = event.target;
while(link && !(link instanceof HTMLAnchorElement))
{
link = link.parentNode;
}
// Get the element with ID wpf-remove-element-now
var clickedLink = document.getElementById("wpf-remove-element-now");
// If the element exists
if(clickedLink !== null)
{
// By executing this code, I am ensuring that I have only
// one anchor element in my document with this ID
// Remove the id attribute
clickedLink.removeAttribute('id');
}
// If ther is no link element
if(!link)
{
// Disable my "unlink" button
editor.commands.customunlinkcmd.disable();
// and return
return;
}
event.preventDefault();
event.stopPropagation();
// If the user has clickde on an anchor element then
// enable my "unlink" button in order to allow him to
// to replace the link if he like to.
editor.commands.customunlinkcmd.enable();
// Set the id attribute of the current selected anchor
// element to wpf-remove-element-now
link.setAttribute('id', 'wpf-remove-element-now');
}
);
var $unlink_button = document.getElementById('unlink');
$unlink_button.addEventListener(
'click',
function(event)
{
// Get the element with ID wpf-remove-element-now
var link = document.getElementById("wpf-remove-element-now");
// Create a new text node that contains the link inner HTML
var text = document.createTextNode(link.innerHTML);
// Make the replacement
link.parentNode.replaceChild(text, link);
}
);
Everything until now is correct, appart of the replacement of the link. I have try the above code, but the result I get is like the following one:
Wawef awef <em>replace</em> <strong>me</strong> falwkefi4hjtinyoh gf waf eerngl
nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg replace me klserng sreig klrewr
I mean the anchor is replaced with the text form of the inner HTML and not with the HTML form of the inner HTML.
So the question is, how can I do this kind of replacement.
You're creating a text node, so whatever you put in it will be interpreted as text. Instead, since you have the replacement tags predefined, you should create actual DOM elements to replace it with. Something like this could work: JSFiddle
var em_elem = document.createElement('em');
em_elem.appendChild(document.createTextNode("replace"));
var strong_elem = document.createElement('strong');
strong_elem.appendChild(document.createTextNode("me"));
var container_span = document.createElement('span');
container_span.appendChild(em_elem);
container_span.appendChild(strong_elem);
// Make the replacement
link.parentNode.replaceChild(container_span, link);
The answer was much simpler that I thought. I placed the solution below for anybody that need an equivalent solution :) :
$unlink_button.addEventListener(
'click',
function(event)
{
// Get the element with ID wpf-remove-element-now
var link = document.getElementById("wpf-remove-element-now");
// By this code you replace the link outeHTML (the link itself) with
// the link innerHTML (anything inside the link)
link.outerHTML = link.innerHTML;
}
);
Here you can find the running solution : JSFiddle
Note: The inspiration for this solution found in the web page.
I'm generating a div dynamically and I've to check whether a dynamically generated div exists or not ? How can I do that?
Currently I'm using the following which does not detects the div generated dynamically. It only detects if there is already an element with the id contained in the HTML template.
$(function() {
var $mydiv = $("#liveGraph_id");
if ($mydiv.length){
alert("HHH");
}
});
How can I detect the dynamically generated div?
If mutation observes aren't an option due to their browser compatibility, you'll have to involve the code that's actually inserting the <div> into the document.
One options is to use a custom event as a pub/sub.
$(document).on('document_change', function () {
if (document.getElementById('liveGraph_id')) {
// do what you need here
}
});
// without a snippet to go on, assuming `.load()` for an example
$('#container').load('/path/to/content', function () {
$(this).trigger('document_change');
});
If it is added dinamically, you have to test again. Let's say, a click event
$("#element").click(function()
{
if($("#liveGraph_id").length)
alert("HHH");
});
How you inserting your dynamic generated div?
It works if you do it in following way:
var div = document.createElement('div');
div.id = 'liveGraph_id';
div.innerHTML = "i'm dynamic";
document.getElementsByTagName('body')[0].appendChild(div);
if ($(div).length > 0) {
alert('exists'); //will give alert
}
if ($('#liveGraph_id').length > 0) {
alert('exists'); //will give alert
}
if ($('#liveGraph_id_extra').length > 0) {
alert('exists'); //wont give alert because it doesn't exist.
}
jsfiddle.
Just for interest, you can also use a live collection for this (they are provided as part of the DOM). You can setup a collection of all divs in the page (this can be done in the head even before the body is loaded):
var allDivs = document.getElementsByTagName('div');
Any div with an id is available as a named property of the collection, so you can do:
if (allDivs.someId) {
// div with someId exists
}
If the ID isn't a valid identifier, or it's held in a variable, use square bracket notation. Some play code:
<button onclick="
alert(!!allDivs.newDiv);
">Check for div</button>
<button onclick="
var div = document.createElement('div');
div.id = 'newDiv';
document.body.appendChild(div);
">Add div</button>
Click the Check for div button and you'll get false. Add the div by clicking the Add div button and check again—you'll get true.
is very simple as that
if(document.getElementById("idname")){
//div exists
}
or
if(!document.getElementById("idname")){
// don't exists
}
I want to select the id of the current div when I click on it in jQuery.
For example, say I have HTML like this:
<div class="item" id="10">hello world</div>
<div class="item_10">hello people</div>
When I click on the first div on .item class, I want to copy the id of the current div + adding to it the number (10), so it will be ("div id" + 10) equal to the second dev class = item_10.
I tried to use currentid = this.id; but it doesnt work :( !
First, note that id attributes starting with numbers are syntactically illegal in HTML4. If you're using id="10" make sure that you're using the HTML5 doctype (<!DOCTYPE html>).
It's hard to say why what you were doing didn't work without seeing your actual code. Presumably it is because you were registering for the event on a higher element (like the body) and this.id was the id of that higher element and not the element you clicked on.
In this case, you want to use the target property of the event to find what you clicked on. For example:
$(document.body).click(function(evt){
var clicked = evt.target;
var currentID = clicked.id || "No ID!";
$(clicked).html(currentID);
})
Seen in action: http://jsfiddle.net/Gra2P/
If you were registering on the specific elements instead, then this.id does work:
$('div').click(function(evt){
var currentID = this.id || "No ID!";
$(this).html(currentID);
})
Seen in action: http://jsfiddle.net/Gra2P/1/
This is sub-ideal, however, because:
It makes many event handler registrations instead of 1, and
If additional divs are added to the document after this code is run, they will not be processed.
Under jQuery 1.7, you use the .on method to create a single event handler on a parent element with selectors for the kinds of elements you want to catch the event on, and have this set to them. In code:
$(document.body).on('click','div',function(evt){
var currentID = this.id || "No ID!";
$(this).html(currentID);
})
Seen in action: http://jsfiddle.net/Gra2P/2/
I think you're trying to do something like:
$(".item").click(function(){
var id = $(this).attr("id");
var el = $(".item_" + id);
});
Now el is your second div.
You can simply use this.id
$('div').click(function() {
var divid = this.id;
alert($('.item_'+divid).html());
});
Demo
Something like this?:
$('div').click(function() {
theId = $(this).attr('id');
//Do whatever you want with theId.
});
This can be done as:
$('.item').click(function() {
var divId = $(this).attr("id");
});
I have a bunch of links with non-pre-determined id's like so:
Remove 123
Remove 234
Remove 567
Remove 890
I have an event handler like so:
$$('.remove_pid').addEvents({
'click': removePid
});
which calls this function
function removePid(event)
{
alert('yo what is my element id???');
}
So the question is how do i get the element id in the function removePid()?
UPDATE:
#Aishwar, event.target.id seems to work in the following case, but not specifically in my case
<img src="/123.jpg" id="pid_123">
UPDATE 2:
I thought it was inconsequential, but instead of the text "Remove 123" I actually have an image like so:
<img src="/123.jpg">
So, thanks for #Dimitra for pointing it out. I was surprised with the de-vote but am happy to say i probably deserve it.
I do not have experience working with mootools. But I would guess you can just do something along these lines, in removePid:
var element = event.srcElement || event.target
element.id // is the element's id, element is the DOM element itself
as per the markup posted in the FINAL update:
http://www.jsfiddle.net/dimitar/Sr8LC/
$$('.remove_pid').addEvents({
'click': function(e) {
new Event(e).stop();
var id = this.getProperty("id");
alert(id);
alert(id.replace("pid_", ""));
}
});
to use a named function and keep the event:
var removeProduct = function(e) {
new Event(e).stop();
var id = this.getProperty("id");
alert(id);
alert(id.replace("pid_", ""));
};
$$('a.remove_pid').each(function(el) {
el.addEvents({
'click': removeProduct.bind(el)
});
});
within both functions, this will refer to the trigger element (the anchor), so you can read it's property, etc. this.getFirst() will reference the image (if you want it).
Think I found it:
function removePid(event)
{
//alert('yo what is my element id???');
$(event.target).getParent('a').getProperty('id');
}
This works in FF 3.6