In a firebase-login element I have
<paper-button id="btnLogin" data-dialog="login-modal" on-tap="toggleLogin">
<iron-icon icon="account-box"></iron-icon>
Login
</paper-button>
Where toggleLogin calls:
toggleLogin: function() {this.$.loginModal.toggle();},
In the Polymer test suite I am using:
Polymer.dom(element.root).querySelector('#btnLogin').click();
But Selenium is giving me the error of:
this.$.loginModal.toggle is not a function
Long story short, how can I click the button and check the modal pops up?
Note: Polymer team's test looks like:
Polymer.dom(myEl.root).querySelector('button').click()
Since they are naming their element myEl instead of element and looking for the button tag instead of the tag with id of btnLogin I felt that my solution was suitable. What am I doing wrong here?
UPDATE:
While looking at the bind event I still have not gotten things working.
CODE:
var btnLogin = Polymer.dom(myEl.root).querySelector('#btnLogin');
// This does the same thing as
// var btnLogin = element.$.btnLogin;
btnLogin.click.bind(btnLogin);
The above code allows me to move past the line but does not actually toggle the dialog. I am not sure why. When I add in click() instead of click it gives me the this.$.loginModal.toggle() is not defined error that I have been struggling with.
UPDATE:
Still have not found a good answer to this. Was looking into some code that may help and found the submenu element that wants to know information about it's content elements. I will include their testing below.
CODE:
suite('<paper-submenu>', function() {
var menu,
sub1, sub2, sub3,
collapse1, collapse2, collapse3,
trigger1, trigger2, trigger3;
setup(function() {
menu = fixture('basic');
sub1 = menu.querySelectorAll('paper-submenu')[0];
sub2 = menu.querySelectorAll('paper-submenu')[1];
sub3 = menu.querySelectorAll('paper-submenu')[2];
collapse1 = Polymer.dom(sub1.root).querySelector('iron-collapse');
collapse2 = Polymer.dom(sub2.root).querySelector('iron-collapse');
collapse3 = Polymer.dom(sub3.root).querySelector('iron-collapse');
trigger1 = sub1.querySelector('.menu-trigger');
trigger2 = sub2.querySelector('.menu-trigger');
trigger3 = sub3.querySelector('.menu-trigger');
});
test('selecting an item expands the submenu', function() {
assert.isFalse(collapse1.opened);
assert.isFalse(collapse2.opened);
assert.isFalse(collapse3.opened);
MockInteractions.tap(trigger1);
assert.isTrue(collapse1.opened);
assert.isFalse(collapse2.opened);
assert.isFalse(collapse3.opened);
});
Following the above example I tried the following:
test('Login Modal Opens', function(done) {
expect(loginModal).to.exist;
console.log(loginModal);
console.dir(loginModal);
expect(loginModal.opened).to.exist;
assert.isFalse(loginModal.opened);
btnLogin.click.bind(btnLogin);
assert.isTrue(loginModal.opened);
});
Unfortunately I am getting loginModal.opened as undefined. loginModal.toggle() gives toggle is not a function error.
UPDATE:
I found that bind does not actually call the function. It only binds the this to a new location. So when I was doing btnLogin.click.bind(btnLogin) it was doing the binding so when I called btnLogin.click() it would have a binding to btnLogin rather than ... btnLogin. Therefore it would have been the same to just call btnLogin.click() without ever calling the bind function.
Now that this is figured out, I decided to mess with call instead of bind but again I only was binding the this to the same scope so that was no help. I then tried btnLogin.click.call(element) but it still gave me the error that this.$.loginModal.toggle is not a function.
Just a wild guess, I don't know JS well
var el = Polymer.dom(element.root).querySelector('#btnLogin');
el.click().bind(el)();
Related
Background:
I am using ElectronJS to make a game and I have a class for a shop which I named Shop.
It has a method that I call 'createItemElement' which takes an object named 'item' and creates an li element to be later added to a ul element. The code for this can be found below.
class Shop {
// ...
createItemElement(item) {
// Item Container
const li = document.createElement("li");
// Title
const title = document.createElement("h3");
title.textContent = item.title;
// Info
const info = document.createElement("p");
info.textContent = `Type: ${item.type}`;
// Add to Cart
const addButton = document.createElement("button");
addButton.textContent = "Add to Cart";
addButton.onclick = () => console.log("Adding to cart!");
li.appendChild(title);
li.appendChild(info);
li.appendChild(addButton);
return li;
}
// ...
}
Problem:
Interestingly, all of the HTML is correctly rendered and everything looks as it should, but the 'onclick' event just plain does not work.
Since all of these elements are in fact being rendered, it should be safe to assume that the code is indeed being run in the renderer process.
For some reason, however, the event is not being carried over to the app.
When I click the button in the app, nothing happens.
I checked the devTools and looked at the elements individually.
As expected, all of the elements were listed out correctly in element inspector, but when I inspected that 'addButton' button, there was no 'onclick' property to be seen.
Also, there are no errors in the console whatsoever, so that's nice (sarcasm).
And I am aware that there are many seemingly similar questions asked on StackOverflow, but none of the answers that I found have helped or applied to my situation.
It is extremely confusing as to why the elements are being rendered perfectly but the event listener is not working.
The full project can be found here and the file being excerpted below can be found here.
I looked at your shop.js page, and you incorrectly camel-case the onclick event in one place, but not in another. Using the camel-cased version of onclick will yield no error and do nothing.
Won't work:
empty_cart_button.onClick = (evt) => this.emptyCart();
Works:
addButton.onclick = () => this.addToCart(item);
As I can see from you're code, you're using el.innerHTML in the shop instance .getHTML() method. this will return the inner HTML as a raw string without any event listeners, this is why you see the rendered content as expected but the click listener doesn't work.
In the sketch.js file, the toggleShop function should use appendChild so instead of:
document.querySelector("#shop-container").innerHTML = shop.getHTML();
you should do:
document.querySelector("#shop-container").appendChild(shop.getElement())
and in the Shop class add the getElement method:
getElement() {
return this.el;
}
Be sure to toggle the shop and remove the #shop-container innerHTML when you want to toggle it off.
Also, as #Andy Hoffman answered, you should set the onclick property and not the onClick.
I'm sorry, this question is irrelevant to ol3 and there were some evident code errors (Note from the author)
I'm rewriting a Ol 2 map application with the most recent version of Openlayers 3.15.1. I need to add custom controls to manipulate sea surface temperature maps. I want to place the custom controls over the map . However after trying to recreate the code of some examples showing how to write custom controls with Ol3, I have found some drawbacks to correctly recreate it.
The custom control is composed by a small icon and clicking over it does some stutf. Here below I show several versions of the code used. Basically the controls are created by a function that loads initially.
Only one of them works properly and I would like to understand why the others do not. All examples are almost equivalent two are with pure javascript and two with JQuery trying to look for a optimal solution.
Code 1: Pure Javascript but using innerHTML to insert the image into a . The image seems to be not inserted into the DOM.
var texto = "<img id=\"tool_draw\" src=\"/js/Saidin/Image/draw_line_off.png\">";
var element = document.createElement('div');
element.innerHTML=texto;
element.className = 'ol-unselectable ol-mycontrol';
element.style.position="absolute";
element.style.width="24px";
element.style.top= "70px";
element.style.left= "9px";;
var action= function(e){ alert('hola'); }
document.getElementById("tool_draw").addEventListener("click", action, false);
var okk= new ol.control.Control({
element:element
});
map.addControl(okk);
This code does not work. The error is: document.getElementById(...) is null
Code 2: Pure Javascript but creating the image with the constructor and that's all!
var texto = "/js/Saidin/Image/draw_line_off.png";
var boton = document.createElement('img');
boton.src=texto;
boton.className = 'ol-unselectable ol-mycontrol';
boton.setAttribute("id","tool_draw");
boton.style.position="absolute";
boton.style.top= "70px";
boton.style.left= "9px";
var action= function(e){ alert('hola'); }
boton.addEventListener("click", action, false);
var okk= new ol.control.Control({
element:boton
});
map.addControl(okk);
This code works fine !
Code 3: I think is Equivalent to Code 1 but using JQuery library
var texto ="<img id=\"tool_draw\" src=\"/js/Saidin/Image/draw_line_off.png\">";
$('body').append($('<div/>', {
id:'hola',
'class' : 'ol-unselectable ol-mycontrol',
texto:texto,
css: { "position":"absolute","top": "70px", "left":"9px" }
}));
element=$('#hola');
var cont= function(e){ alert('hola'); }
$("#tool_draw").on('click', cont );
var okk= new ol.control.Control({
element:element
});
map.addControl(okk);
This code does not work. The error is: TypeError: Argument 1 of Node.appendChild does not implement interface Node..
Code 4: I think is equivalent to Code 2 but using JQuery library
var element=$('<img>', {
id:'tool_draw',
src:'/js/Saidin/Image/draw_line_off.png',
'class' : 'ol-unselectable ol-mycontrol',
css: { "position":"absolute","top": "70px", "left":"9px" }
});
$('#map').append(element);
var cont= function(e){ alert('hola'); }
element.on('click', cont );
var okk= new ol.control.Control({
element:element
});
map.addControl(okk);
This code works fine ! but... the same error from ol.js appear TypeError: Argument 1 of Node.appendChild does not implement interface Node.
Can somebody explain me what's wrong with the failing codes ?. I apologize for this long question and I'm not sure if the problem comes from JQuery, JavaScript or is related with the new OL3 version. Any explanation is welcome !. Thanks
code1 doesnt work cause you use getElementById while the element is not ready on dom. You may use element.addEventListener("click", action, false); but I am not sure if it would work.
Code 2 works cause you attach the listener directly to the element (like the way I suggest on 1) and you are not searching for it in the DOM (getElementById)
Code 3 doesnt work cause appendChild is a native DOM method and only accepts DOM nodes as a parameter. The element you're trying to append ($('body').append($('<div/>'.....) is a jQuery object, not a DOM element.
Code 4 shouldnt work for the same reason as 3.
Your problems have nothing to do with ol3. It is jquery & js problems. Hope I helped you a bit
TL;DR: Trying to fire a manual javascript click event on the chat button of twitch, won't send the message. Don't understand why the event doesn't do the same as a normal click and don't know how to make it work.
So I am trying to make a custom bot for twitch.tv, only reading his info from the HTML directly. I've got it perfectly working up to the point at where it can recognize commands and put text in the textbox. Now the problem I have is, as soon as I try to fire a manual click event on the "chat" button, it just doesn't seem to work. My guess is it has something to do with ember.js, and I frankly don't know anything about that. Anyway, here is the part of the code that doesn't work. EDIT: this works if I enter it as single in the console, doesn't work in context of the rest of my code though.
$('.send-chat-button').click();
What happens here is that I acquire a piece of html that contains the chat submit button, which is this:
<button class="button primary float-right send-chat-button" data-bindattr-3945="3945">
<span>
Chat
</span>
</button>
When I try to manually fire a click event on this, nothing happens. However, when I fire a manual click event on buttonContain.children[0] and buttonContain.children1 (which are, respectively, the settings and list of viewers buttons), it does work. They look like this:
<a data-ember-action="3943" class="button glyph-only float-left" title="Chat Settings"></a>
I'm guessing the difference is in the data-ember-action and the data-bindattr-*, but I don't know how to make it work. Anyone here knows why the click() event doesn't work and directly clicking does?
EDIT: If you have any questions about my question, feel free to ask.
EDIT2: I experimented a little more, and I can remove all HTML attributes from the button, and clicking on it will still work. I have no idea what is going on :(.
EDIT3: Okay, so it seems it only stops working when i remove the
Span within the button
Still no idea what is going on. (Yes, have also tried to fire the click event on the span)
EDIT4: As requested, here is all the code from my side. Note that I'm trying to click a button from twitch itself, of which ember side I do not own any code. This code is used by pasting it in the console on a twitch.tv stream and then starting it by calling initiateMessageProcessing. I'm sorry for the lot of hardcoded values, those are twitch' fields that I need. For now I'm just looking for a proof of concept.
var frequency = 5000;
var myInterval = 0;
var lastMessageId = 0;
function initiateMessageProcessing() {
if (myInterval > 0) {
clearInterval(myInterval);
}
myInterval = setInterval("checkMessages()", frequency);
}
function checkMessages() {
var chat = document.getElementsByClassName("chat-lines")[0];
processMessages(extractUnprocessedMessages(chat.children));
lastMessageId = parseInt(chat.lastElementChild.getAttribute("id").substring(5, 10));
}
function extractUnprocessedMessages(chat) {
var unprocessedMessages = [];
var chatId = 0;
for ( i = 0; i < chat.length; i++) {
chatId = parseInt(chat[i].getAttribute("id").substring(5, 10));
if (chatId > lastMessageId) {
unprocessedMessages.push(chat[i]);
}
}
return unprocessedMessages;
}
function processMessages(unprocessedMessages) {
var messageElement;
for ( i = 0; i < unprocessedMessages.length; i++) {
messageElement = unprocessedMessages[i].children[0].getElementsByClassName("message")[0];
if (messageElement != undefined && messageElement != null) {
if (messageElement.innerHTML.search("!test") !== -1) {
sendMessage('Hello world!');
}
}
}
}
function sendMessage(message) {
fillTextArea(message);
var button = $('.send-chat-button').get(0);
var event = new MouseEvent('click', {
bubbles : true
});
button.dispatchEvent(event);
}
function fillTextArea(message){
var textArea;
var chatInterface = document.getElementsByClassName("chat-interface")[0];
var textAreaContain = chatInterface.children[0];
textArea = textAreaContain.children[0].children[0];
textArea.value = message;
}
EDIT5: Eventlistener screenshot:
EDIT6: Edited source code to use $('.send-chat-button').click();
I have tried this, does not work in the current code, it does work if I manually fire this single command in the console when there is text in the chat. But sadly does not work in my code.
EDIT7: used Ember.run, still doesn't work.
EDIT8: used dispatchmouseevent, still doesn't work in context of code
It seems that the target site attaches event listeners without help of JQuery. If it is so, you cannot trigger it using jquery .click() method.
You can try directly mocking the browser event like this:
var button = $('.send-chat-button').get(0);
var event = new MouseEvent('click', {bubbles: true});
button.dispatchEvent(event);
This code will not work in IE8 and lower, but I guess it is not your case.
I know this post is quite old but I had been looking for an answer on this for a while and nothing really worked, after trying out A LOT of stuff I found it works when you focus the chatbox first then focus the button then triggering the click event!!! uuuhm yeah...
$('.chat_text_input').focus();
$('.send-chat-button').focus().trigger('click');
I have no idea why this works (and why it doesn't in any other way), but leaving any of the focusses out makes it fail or bug out.
Programmatically clicking a DOM element to make some action done is somewhat a wrong approach.
You should have define a method myAction() which will be called in two ways. First, from your ember action triggerMyAction() and second, after listening to a custom event, "myEvent".
Instead of $('.send-chat-button').click(); you will code $('something').trigger("myEvent") then.
Something like:
Em.Controller.extend({
myAction:function(){
//do your stuff
},
onMyEvent:function(){
$('something').on('myEvent',this.myAction);
}.on('didInsertElement'),
actions:{
triggerMyAction:function(){
this.myAction();
}
}
})
I have a script, which I'm using to try and display only one section of a webpage at a time.
function showMe(id){ clearPage(); changeDisplay(id, "block"); console.log(id)}
Currently, I'm using buttons to change which section is displayed.
var aBtn = document.getElementById("a-btn");
var otherBtn = document.getElementById("other-btn");
aBtn.onclick=showMe("a-btn-section-id");
otherBtn.onclick=showMe("other-btn-section-id");
However, when I load the page, the following happens:
I see the function attached to each button activate once in sequence in the console.
The page refuses to respond to further button inputs.
Testing with the console shows that showMe() and the functions it calls still all work properly. I'm sure I'm making a very basic, beginner mistake (which, hopefully, is why I can't find this problem when I Google/search StackOverflow/read event handling docs), but I'm at a loss for what that mistake is. Why would my script assume my buttons are clicked on load, and why won't it let me click them again?
You're calling the function an assign the value to onclick property instead of attach the function, try defining your onclick property as:
aBtn.onclick=function(){showMe("a-btn-section-id");};
otherBtn.onclick=function(){showMe("other-btn-section-id");};
Try the follow jsfiddle:
function showMe(id){ // some stuff..
console.log(id)
}
var aBtn = document.getElementById("a-btn");
var otherBtn = document.getElementById("other-btn");
aBtn.onclick=function(){showMe("a-btn-section-id");};
otherBtn.onclick=function(){showMe("other-btn-section-id");};
<input type="button" value="a-btn" id="a-btn"/>
<input type="button" value="other-btn" id="other-btn"/>
Hope this helps,
I am currently learning JavaScript using O'Reilly's "Learning Web Application Development". In the example, we are constructing a website using HTML and CSS, which includes 3 tabs which should be able to be selected and become the "active" tab. The books claims that the following two ways of writing the tab code are equivalent:
1)
var main = function() {
"use strict";
var tabNumber;
for (tabNumber=1;tabNumber<=3;tabNumber++) {
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$(tabSelector).on("click",function() {
$(".tabs span").removeClass("active");
$(tabSelector).addClass("active");
$("main .content").empty();
return false;
});
}
}
$(document).ready(main);
2)
var main = function() {
"use strict";
$(".tabs a span").toArray().forEach(function(element) {
$(element).on("click", function() {
console.print("this element: " + element);
$(".tabs span").removeClass("active");
$(element).addClass("active");
$("main .content").empty();
return false;
});
});
}
$(document).ready(main);
However, they do not output the same result. The version using forEach works correctly, so that when I click one of the tabs the attention moves to that tab and it becomes highlighted. However, in the version using a for loop, whenever I click any tab, the attention always moves to the last tab. To confirm what is happening, I printed out the name of the element inside the event listener with both methods, using 3 tabs total. And using the for loop, no matter which tab I click I am getting a response of
"this element: .tabs a:nth-child(3) span"
Could someone please help me explain why this is happening? Why is the output different using for or forEach? And why, using for, is it always passing the last element of tabs to the event listener?
Looks like there's a problem here:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$tabSelector.on("click",function(){
You've created a variable that doesn't have the $ at the beginning, then attached the event to a variable (not sure what it would refer to) with a $ at the beginning.
It should be changed to this, I believe:
$(tabSelector).on("click",function(){
In the for loop solution, you are setting tabSelector multiple times like so:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
This selector is, in the end, going to be set to the last tabNumber, which is always going to be called when you make a reference to it:
$(tabSelector).addClass("active");
To avoid that, replace it by this, which will be different for each of them:
$(this).addClass("active");
JS Fiddle Demo