As stated in title. Im trying to create a tooltip which will have some buttons inside. The problems is with the onclick function, which is somehow not working. This is the actual code I have.
$('#button_nowtime').popover({
trigger: 'click',
html: 'true',
title: "<b>Čas</b>",
content:
function() {
var returnstring="",button;
for(var i=0; i<files.length; i++){
button = document.createElement("a");
button.innerText = fileNametoButtonTime(files[i]);
button.onclick = (function() {
var currentID = i;
return function() {
alert("asd"); currentTimeIndex=currentID; setNowTimeButton(); drawImage(); $('#button_nowtime').popover('hide');
}
})();
button.href="#";
returnstring+=button.outerHTML;
returnstring+=" | ";
}
return returnstring;
}
});
The buttons appear in the tooltip but not react to the onclick function.
I've adjusted your original question (Demo Fiddle: http://jsfiddle.net/WfcM9/) to use jQuery to instead create the buttons and event handling.
With jQuery, it'll be adding the buttons to the DOM, giving them an class then outside the popover() function, give it a $(document).on('click', 'classname') for the document to wait for.
With jQuery .on('click')
<script>
var files = [ "FileOne", "FiletWO" ],
options = {
trigger: 'click',
html: 'true',
title: "<b>Čas</b>",
content: function() {
var $buttonsContainer = $('<div />');
for( var i=0; i< files.length; i++ ) {
var addLink = $('<a>').addClass('fileclick btn btn-default')
.attr( 'data-id', files[i] )
.html( files[i] );
$buttonsContainer.append( addLink );
}
return $buttonsContainer;
}
};
/**
* Create the Popover with above Options
**/
$('#button_nowtime').popover(options);
/**
* Listen for the Class Click on the buttons created.
**/
$(document).on('click', '.fileclick', function() {
alert( $(this).data('id') );
//Alerts FileOne or FileTwo
});
</script>
Fiddle Demo: http://jsfiddle.net/M2HQD/3/
Related
I'm obviously missing something, but I haven't been able to find what I am doing wrong and I have been staring at this for entirely too long
function message(options) {
...
options.onclose = options.onclose || null;
...
this.gui = document.createElement('div');
this.msg = document.createElement('div');
...
if (options.onclose != null) {
var close = document.createElement('i');
close.innerHTML = 'close';
close.className = 'material-icons close';
close.onclick = options.onclose;
console.log(close.onclick);
this.msg.append(close);
}
this.msg.innerHTML += options.msg;
this.gui.append(this.msg);
...
return this.gui;
}
msgContainer.append(new message({
class: 'update',
sticky: true,
icon: 'mic',
msg: 'You are in a call',
onclose: () => { console.log('click'); }
}));
from the developer console document.querySelector('.close').onclick is null, but if I add an on click document.querySelector('.close').onclick = () => { console.log('click'); }; it works?
Why it wont work is because on click is a function:
document.querySelector('.close').onclick
doesn't do anything so why call it.
document.querySelector('.close').onclick = () {
alert("did something");
}
so the real question is what do you want to do when clicked? create a new link or div.. look below. I would start using jQuery.
jQuery answer:
$(document).ready(function(){
$(".myclass").click(function(){
$(".container_div").append("<a href='test.php'>test link</a>");
// also .prepend, .html are good too
});
});
Here is working example. I changed your code a little bit. You can add more events by passing it to an array. I used addEventListener.
var msgContainer = document.getElementById('msgContainer');
function message(options) {
options.onclose = options.onclose || null;
this.gui = document.createElement('div');
this.msg = document.createElement('div');
if (options.onclose != null) {
var close = document.createElement('i');
close.innerHTML = 'closepp';
close.className = 'material-icons close';
close.dataset.action = 'close';
this.msg.append(close);
}
this.msg.innerHTML += options.msg;
this.gui.append(this.msg);
// Create listeners dynamically later on
events = [
{ selector: close.dataset.action, eventType: 'click', event: options.onclose }
];
renderElement(this.gui, events);
}
function renderElement(element, events) {
msgContainer.append(element);
for (i = 0; i < events.length; i++) {
var currentEvent = events[i];
var selector = element.querySelector('[data-action="' + currentEvent['selector'] + '"]');
selector.addEventListener(currentEvent['eventType'], currentEvent['event'].bind(this), false);
}
}
new message({
class: 'update',
sticky: true,
icon: 'mic',
msg: 'You are in a call',
onclose: () => { console.log('click'); }
});
<div id="msgContainer">
</div>
I finally figured it out! setting innerHTML makes chrome rebuild the dom and in the process it loses the onclick event, onclick works fine if I use textContent instead of innerHTML. In the below example if you comment out the last line of JS the onclick works, here's the same thing in jsFiddle
var blah = document.getElementById('blah');
var div = document.createElement('button');
div.style['background-color'] = 'black';
div.style.padding = '20px;';
div.style.innerHTML = 'a';
div.onclick = () => { alert('wtf');};
blah.appendChild(div);
// Uncomment this to make onclick stop working
blah.innerHTML += ' this is the culprit';
<div id="blah">
</div>
In my sample work, I would like to detect the click event from anywhere of my html element. It works when I click on direct html but not for iFrames - so I would like to hear from any where of my window. What is the correct way to do that using jQuery ?
Even I would like to hear from dynamic htmls too. (my case there is a loop with numbers
here is the demo
my code :
var findAllClicks = function() {
$(document).on('click', '*', function() {
console.log($(this)[0]); //only works on direct html element.
})
}
var outsideFunction = function() {
console.log('loop ends');
}
outsideFunction();
$(function() {
//finding click events from any where.
findAllClicks();
var total = 1000;
var i = 0;
var iterate = function() {
setTimeout(function() {
var place = $('#iFrame1').contents().find('#iFrame2').contents().find('body');
place.append('<ul class="list"></ul>');
for (i = 0; i < total; i++) {
place.find('.list').append('<li>' + i + '</li>');
}
}, 3000);
//how to find all this done from outside of this function?
}
var iFrame1 = $('<iframe />', {
id: 'iFrame1'
});
var iFrame2 = $('<iframe />', {
id: 'iFrame2'
});
var button2 = $('<button />', {
text: 'Child Button',
click: iterate
});
var button = $('<button />', {
text: 'Click Me',
click: function() {
$(this).parents('body').append(iFrame2);
$('#iFrame1').contents().find('#iFrame2').contents().find('body').append(button2);
}
});
setTimeout(function() {
$('.container').append(iFrame1);
$('#iFrame1').contents().find('body').append(button);
}, 1000);
});
Sorry if I misunderstood but if you just wanna log the number of clicks on the window, you could use
window.onclick = function() {count++;console.log(count);};
I would like to know when my iteration completes from outside of my web page, where my iteration happening inside of a frame's child iframe
here my example: Live URL click first button and second button wait 3 sec.
$(function(){
var total = 1000;
var i = 0;
var iterate = function(){
setTimeout(function(){
var place = $('#iFrame1').contents().find('#iFrame2').contents().find('body');
place.append('<ul class="list"></ul>');
for(i=0; i < total; i++) {
place.find('.list').append('<li>'+i+'</li>');
}
}, 3000);
//how to find all this done from outside of this function?
}
var iFrame1 = $('<iframe />', {id:'iFrame1'});
var iFrame2 = $('<iframe />', {id:'iFrame2'});
var button2 = $('<button />', {text:'Child Button', click:iterate});
var button = $('<button />',
{
text:'Click Me',
click:function(){
$(this).parents('body').append(iFrame2);
$('#iFrame1').contents().find('#iFrame2').contents().find('body').append( button2 );
}
}
);
setTimeout(function(){
$('.container').append( iFrame1 );
$('#iFrame1').contents().find('body').append(button);
},1000);
});
After the place had all lis how to I know from outside of the document. I am running my code from chrome browser console.
I have created this fiddle to attempt to answer this question. Here's what I have done:
Added this handler to run when the iteration is complete:
var onIterationDone = function() {
console.log("Iteration Done");
alert("Done!");
};
Wired this handler to a custom event iterationDone on button2 right after it's added:
var button = $('<button />', {
text: 'Click Me',
click: function() {
$(this).parents('body').append(iFrame2);
$('#iFrame1').contents().find('#iFrame2').contents().find('body').append(button2);
button2.on('iterationDone', onIterationDone);
}
});
Fired the custom event as soon as the iteration is done:
setTimeout(function() {
var place = $('#iFrame1').contents().find('#iFrame2').contents().find('body');
place.append('<ul class="list"></ul>');
for (i = 0; i < total; i++) {
place.find('.list').append('<li>' + i + '</li>');
}
// Trigger the custom event.
button2.trigger('iterationDone');
}, 1000);
Is this what you wanted to achieve ?
If I create a new element with jquery and add a click function like above, the click-function do not work certain.
I would like to set focus on the eqivalent element but it focus only the last one.
To better explain I made a jsfiddel here
var newUL = $('<ul />',{
text: "ul text",
'class': 'errorListUl'
});
for ( var i = 0; errorList[i]; i++ ) {
var el = errorList[i]; console.log("element: ",el.element);
$( "<li/>", {
"class": "errorListLi",
html: "<span>"+errorList[i].element.name+"</span><span>"+errorList[i].method+"</span>"+errorList[i].message,
click: function() {
$(el.element).focus(); console.log("go to: ",$(el.element));
}
}).appendTo(newUL);
}
newUL.appendTo( $('#response') );
Your for loop finishes before your element is inserted into dom. Due to this fact, it will add handlers only on the last element. You need an anonymous function (closure) to handle this issue. Updated fiddle.
var newUL = $('<ul />',{
html: "Click on error-message (li) shout focus the equivalent element. But the focus is always set to the last element.<br><br>",
'class': 'errorListUl'
});
for ( var i = 0; errorList[i]; i++ ) {
(function(_i) {
var el = errorList[_i],
htmlText = "<span>" + el.element.name + "</span><span>" + el.method + "</span>" + el.message;
console.log("element: ", el.element);
$( "<li/>", {
"class": "errorListLi",
html: htmlText,
click: function() {
$(el.element).focus(); console.log("go to: ",$(el.element));
}
}).appendTo(newUL);
})(i)
}
newUL.appendTo( $('#response') );
You have a problem of closure: this link will explain better than me :)
check my modifications on your fiddle
var errorList = [];
var check = function( element ) {
errorList.push({
message: "text-message",
element: element,
method: "text-method"
});
}
$(document).find("input, select, textarea").each(function(i, item) {
var checked = check(item);
});
console.log(errorList);
var newUL = $('<ul />',{
html: "Click on error-message (li) shout focus the equivalent element. But the focus is always set to the last element.<br><br>",
'class': 'errorListUl'
});
for ( var i = 0; errorList[i]; i++ ) {
var _item = errorList[i];
(function (item) {
$( "<li/>", {
"class": "errorListLi",
html: "<span>"+item.element.name+"</span><span>"+item.method+"</span>"+item.message,
click: function() {
$(item.element).focus();
}
}).appendTo(newUL);
})(_item)
}
newUL.appendTo( $('#response') );
The problem here is that you are using the el variable in the click handler, which is defined in the outer closure and which will change to be the last of the list, when the for loop has completed. If you want to change the behaviour to be correct, you must write the loop as:
for ( var i = 0; errorList[i]; i++ ) {
var el = errorList[i];
console.log("element: ",el.element);
(function (el2) {
$( "<li/>", {
"class": "errorListLi",
html: "<span>"+errorList[i].element.name+"</span><span>"+errorList[i].method+"</span>"+errorList[i].message,
click: function() {
$(el2.element).focus();
console.log("go to: ",$(el2.element));
}
}).appendTo(newUL);
})(el);
}
This way, you will create a new variable el2, which will not change over the loop, since it is copied to the instantly invoking function body.
Preamble: I'm Italian, sorry for my bad English.
This is my problem:
I want to assign a function to a set of buttons.
I need to send a parameter to the function.
this is the code that I've tried:
function test(atxt) {
var buttons = $('.tblButton');
for (var i = 0; i < buttons.length; i++) {
buttons[i].onClick(sayHello(atxt));
}
}
function sayHello(txt){alert('hello' + txt)};
...getting the following error:
Uncaught TypeError: Object #<HTMLButtonElement> has no method 'onClick'
can you tell me where I went wrong and how can I fix it?
EDIT: I need iteration because I need the 'id of the button as a parameter of the function so i need to do buttons[i].onClick(sayHello(buttons[i].id))
buttons[i].onClick(sayHello(atxt));
Supposed to be
$(buttons[i]).on('click', function() { sayHello(atxt) });
If you want to get the current button id then I think you are looking for this..
for (var i = 0; i < buttons.length; i++) {
$(buttons[i]).on('click', function() { sayHello(this.id) });
}
If you want to iterate through all of the buttons then you have to do that with .each() handler of the jquery:
$(function(){
$(".tblButton").each(function () {
$(this).click(function(){
alert($(this).attr('id'));
});
});
});
checkout the jsbin: http://jsbin.com/usideg/1/edit
Would this not work for your example: Do you have another reason for the iteration?
function test(atxt) {
$('.tblButton').on('click',function(){sayHello(atxt);});
}
function sayHello(txt){alert('hello' + txt)};
OR optionally if the elements are static and present:
function test(atxt) {
$('.tblButton').click(function(){sayHello(atxt);});
}
function sayHello(txt){alert('hello' + txt)};
Alternate approach: just change
to this style:
var txt = "fred";
var atext = "hello" + txt;
function sayHello(atext) {
alert(atext);
}
$('.tblButton').on('click', function() {
sayHello(atext);
});
//below here just to demonstrate
$('.tblButton').eq(0).click();//fires with the fred
txt = "Johnny";// new text
atext = 'hello' + txt;
$('.tblButton').eq(1).click();//fires the Johnny
see it working here:
http://jsfiddle.net/dFBMm/
SO based on your note:
this markup and code:
<button class="tblButton" id="Ruth">Hi</button>
<button class="tblButton" id="Betty">Hi again</button>
$('.tblButton').on('click', function() {
alert("Hello "+$(this).attr("id"));
});
$('.tblButton').eq(0).click();//fires with the Ruth
$('.tblButton').eq(1).click();//fires the Betty
http://jsfiddle.net/dFBMm/1/