How can I override javascript click event for only certain elements? - javascript

I'm working off of a tutorial from codrops. There is a hover event for each item, as well as a click event that triggers an anime.js function.
I'm trying to work this so certain items (grid cells) don't trigger the anime.js function when clicked, but the hover function still works.
I've tried simple css pointer-events, but that disables the hover function.
I've constructing the two groups as separate items in JS, but then the animation doesn't work the same (it staggers the two different classes).
I've tried things to stop the default javascript behavior, but it seems to have no impact on the code.
Help!!!
I've made a functioning codepen - in the option there I'm trying to disable click event for any grid item with the id="noClick" - to no avail.
$('noClick').observe('click', function(event) {
Event.stop(event);
});
This is the primary function that creates the event
this.DOM.items.forEach((item, pos) => {
// The item's title.
const title = item.dataset.title;
// Show the title next to the cursor.
item.addEventListener('mouseenter', () => cursor.setTitle(title));
item.addEventListener('click', () => {
// Position of the clicked item
this.pos = pos;
this.title = title;
// Start the effect and show the content behind
this.showContent();
// Force to show the title next to the cursor (it might not update because of the grid animation - the item under the mouse can be a different one than the one the user moved the mouse to)
cursor.setTitle(title);
});
});
where 'item' is
this.DOM.grid = this.DOM.el.querySelector('.grid');
// Thr grid items
this.DOM.items = [...this.DOM.grid.children];
// totla number of grid items
this.itemsTotal = this.DOM.items.length;
I've tried to create multiple items
this.DOM.grid = this.DOM.el.querySelector('.grid');
this.DOM.yesClick = this.DOM.el.querySelector('.yes-click');
this.DOM.yesClickTwo = this.DOM.el.querySelector('.yes-click-2');
this.DOM.noClick = this.DOM.el.querySelector('.no-click');
// Thr grid items
this.DOM.items = [...this.DOM.yesClick.children, ...this.DOM.yesClickTwo.children];
this.DOM.itemsNo = [...this.DOM.noClick.children];
this.DOM.allItems = [...this.DOM.noClick.children, ...this.DOM.yesClick.children, ...this.DOM.yesClickTwo.children];
// totla number of grid items
this.itemsTotal = this.DOM.allItems.length;
This works, but messes with the animaton.
Here is the codepen
I feel this is really simple and I'm missing something. Looking to learn, so a push in the right direction or any help would be greatly appreciated!

1. You have multiple elements with the same ID. But ID attribute must be unique.
2. You used $('noClick'), but ID selector would look like #noClick
If you want to mark few elements, use a class and select them like .elementclass. It is possible for element to have multiple classes, separated by space.

Your selector doesn't seem correct so you either need #noClick or .noClick as the selector however you can stop the javascript from bubbling like this :-
$(".noClick").click(function(e) {
// Do something?
e.stopPropagation();
});

Related

How to swap <div> elements by using "mouseover" event?

let wrapperSt = document.querySelector(".wrapper");
for(i=0; i<100; i++){
let divGroup = document.createElement('div');
wrapperSt.append(divGroup);
divGroup.className= 'pixel';
divGroup.textContent= '';
}
I've created the div element called "pixel" by using loop because, i need couple hundreds of them. (I'll use them as a little boxes that could change color)
But, i want these boxes ("pixel" div) to turn brown and sustain (style.backgroundColor ="brown";)
So, i created another div that will replace the previous div ("pixel").
let selectPx = document.getElementsByClassName("pixel");
selectPx.addEventListener("mouseover", function(){
let pxChange = createElement("div");
//This is where i got stuck!
})
I could not finish my code, i found it a bit complicated even if it is probably something very simple.
Any suggestions or piece of information would be very helpful. Thank you.
Not sure exactly what you are trying to do... I think you are trying to change the color of the div that your mouse is over? If so, you have a couple of issues with your code. Instead of adding the event listener to the list of divs, you need to add it to each one individually. Also, you should only need to change the background color of each element instead of creating a new one each time.
let selectPx = document.querySelectorAll(".pixel");
selectPx.forEach(pixel => {
pixel.addEventListener("mouseover", () => {
pixel.style.backgroundColor = "brown";
});
});
I'm not sure why you have to create a new div inside the first one. In your code, when you trigger the mouseover event you can get the div under the mouse and apply the style to it:
let selectPx = document.getElementsByClassName("pixel");
selectPx.addEventListener("mouseover", function(evt){
let divUnderMouse = evt.target;
divUnderMouse.style.backgroundColor ="brown";
})
I haven't tried it but it should work

How can I trigger the click event on a list element?

In a 3rd party web app I want to trigger click on an element in a list with jQuery automatically like a physical mouse click.
The list contains player data and these data are always different because its like an auction. Element classes are always named the same.
Selected named: class="listFUTItem has-auction-data selected"
A non-selected element is named: class="listFUTItem has-auction-data"
The list is looking like this:
With MutationObserver I already edited the heights of an element and if the price is below average of my database its coloured in addition style like seen here:
Now I want to auto select a deal where the Elements class matches '[style*="background-color"]'
I also tried adding a selected class to the element but then the side panel wont have any affect on that.
The trasnferlist HTML looks like this:
with side panel I mean this event:
That's the MutationObserver Code with jQuery inside:
var observeTransferList = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
mutation.addedNodes.forEach(function (node) {
if (node.nodeType === 1 && node.matches(".has-auction-data")) {
$(node).css("height", "37");
$(node).removeClass('selected');
chrome.storage.sync.get(function (items) {
platform = items.platform;
percentage = items.percentage;
var playerData = getPlayerData(node, platform, percentage);
$(node).append(playerData);
if (playerData.colorPicked) {
$(node).css("backgroundColor", playerData.colorPicked); //can be "" by default, or green, yellow etc
//$(node).css("height", "37");
var price = Math.trunc(
parseInt(playerData.binValue.replace(/,/g, "")) / 0.949
);
}
// -------- CODE HERE -----------//
if (node.matches('[style*="background-color"]')) { //works
$(node).css("height", "60"); //works
$(node).addClass('selected')//works
//$(node).click('selected'); // not working
//$(node).click(); // not working
//$(node).trigger('click'); //notworking
//$(node).trigger('click', ['selected']); // not working even when adding a selected class after page load and remove old selected
}
I tried a solution like:
Difference between .click() and actually clicking a button? (javascript/jQuery)
Trigger a click event on an inner element
executing a click function without the user clicking?
too
Somehow I need to trigger the event of the listelement which changes the side panel. Somehow the virtual click has to trigger the events bound to a real mouse click. But what am I missed out?
Every mouse event comes with attribute isTrusted. This attribute is set to false if the event was generated by element.click() method. Therefore, the site you are talking about can implement a check that would prevent javascript browser automatization (.click() method).
I had a similar problem as you and the only solution that I found was to use python-browser-automatization Selenuim for python. Selenium comes with chrome driver (simulating the entire chrome browser) which provides cookies, all the javascript API, and most important for you, it can generate MouseEvents with isTrusted attribute.

I have managed to find a way to get text of my slides by using each but how do I get it to display my can products not text?

I have found a way to display text on each of my empty slides. so far, so good. But at you can see in my codepen project, there's a can displaying on the first slide. Instead of the text 'Hello' on each of my slides, how do I display a loop of cans on each slide?
https://codepen.io/Rosstopherrr/pen/GVRvxJ
I had it like this thinking it will show all cans in each slide but it doesn't show any cans...
$('#products article').each(function() {
$(this).append(initApp())
});
what am I doing wrong?
$('#products article').each(function() {
$(this).append('hello')
});
EDIT - progress so far
so in the each.function(index) - I can add the index, and then in initApp(index) - I can add index. and then in the initApp function I can adjust so that bottle[index] gets selected and then added.
But nothing seems to work?? What am I doing wrong?
I know there is a bunch of ways I can do this.
Like could I skip the initApp() function and add all the code in the .each(function() { my code to append bottle})??
in initApp() you define const $container = getElement('.container'); getElement function calls document.querySelector(selector); that returns just the first element that matches the selector, in this case the first div with class .container in the first article tag. That's the first error.
In order to add a bottle to each container you need a list of .containers, that you can obtain with $containers = [...document.querySelectorAll('.container')]
once you have all .container you can integrate the forEach function call, maybe in this way
[$bottle1, $bottle2, $bottle3].forEach(($bottle, i) => {
$bottle.classList.add('bottle' + i);
$containers[i].append($bottle)
});
it's possible that you will still not find the bottles like in the first item; that's because the single .bottle1, .bottle2, .bottle3 etc have wrong letf and top css properties; in addition, the .side divs miss the background-image property.

Tracking changes in web application

I have an application in which the user needs to see the changes that have been made during the latest edit.
By changes I mean, the changes made in all inputs like a textarea, dropdowns.
I am trying to implement this by showing a background image on the right top and then when the user clicks this background image, a popup is shown which shows the difference.
I am using prototype 1.7.0.
My First question would be:-
1. What would be the best approach to implement this functionality?
2. Can I put a onClick on the background image?
There some functions in the jQuery library that I believe would be helpful to you. If you are using prototype, I would guess that there is some similar functionality you may utilize.
I would suggest writing some code like this:
var $input = $('input').add('textarea').add('select');
$input.each(function() {
var id = $(this).attr('id');
var value = $(this).val();
var hiddenId = 'hidden' + id;
var newHiddenInput = $("<input type='hidden'").val(value).attr('id',hiddenId);
$(this).after(newHiddenInput);
});
The above code will create a new hidden input for each input, textarea, and select on your page. It will have the same value as the input it duplicates. It will have an id equivalent to prepending the id with the word 'hidden'.
I don't know if you can attach a click handler to a background image. If your inputs are enclosed inside a <div>, you may be able to get the result you want by attaching the click handler to your div.
In any case, you should now have the old values where you can easily compare them to the user's input so that you can prepare a summary of the difference.
Prototype gives us the Hash class which is almost perfect for this but lacks a way of calculating the difference with another hash, so let's add that...
Hash.prototype.difference = function(hash)
{
var result = this.clone();
hash.each(function(pair) {
if (result.get(pair.key) === undefined)
// exists in hash but not in this
result.set(pair.key, pair.value);
else if (result.get(pair.key) == pair.value)
// no difference so remove from result
result.unset(pair.key);
// else exists in this but not in hash
});
return result;
};
This is no way to tell if an element was clicked on just it's background image - you can find out the coordinates where it was clicked but that is not foolproof, especially since CSS3 adds complications like multiple backgrounds and transitions. It is better to have an absolutely positioned element to act as a button.
$('button-element').observe('click', function() {
var form_values = $H($('form-id').serialize(true));
if (old_values) {
var differences = old_values.difference(form_values);
if (differences.size()) {
showDiffPopup(differences);
}
}
window.old_values = form_values;
});
// preset current values in advance
window.old_values = $H($('form-id').serialize(true));
All that remains is to implement showDiffPopup to show the calculated differences.

Check/uncheck tree with toggle/slide - few minor coding issues

Whilst this does use some of the code from a question I asked yesterday (Dynamically check / uncheck checkboxes in a tree), I feel that this is a slightly different question as I need to add in clearing divs and also slide data in the tree up and down.
I've taken what I learnt yesterday and added in a slider as per this link - http://jsfiddle.net/3V4hg/ - but now I've added clearing divs the tree is not unchecking all the way to the top if the bottom of the tree has no options selected. If you look at the JSFiddle, if you check A and/or B then uncheck it, the parent and grandparent do not uncheck automatically. Also, for some reason that I haven't figured out yet - the slider decides to slide upon clicking the checkbox in the child area (I've also noticed that the toggle image for the region area to display changes when the continent one toggles - haven't tried to solve that as just noticed when adding to JSFiddle).
I'm also thinking that there may be a better way to code the togglers/sliders (since used by more than one kind of toggle, but I'm unsure).
Fiddle: http://jsfiddle.net/3V4hg/2/
I have applied some modifications to your code. Have a look at the fiddle and comments (at the code, and at the bottom of the answer):
$('#delivery_zones :checkbox').change(function(){
$(this).siblings('ul').find(':checkbox').prop('checked', this.checked);
if(this.checked){
$(this).parentsUntil('#delivery_zones', 'ul').siblings(':checkbox').prop('checked', true);
} else {
$(this).parentsUntil('#delivery_zones', 'ul').each(function() {
var $this = $(this);
var childSelected = $this.find(':checkbox:checked').length;
if(!childSelected){
// Using `prevAll` and `:first` to get the closest previous checkbox
$this.prevAll(':checkbox:first').prop('checked', false);
}
});
}
});
// collapse countries and counties onload
$(".country_wrap").hide();
$(".county_wrap").hide();
// Merged two click handlers
$("#delivery_zones").click(function(event){
var root = event.target; // Get the target of the element
if($.nodeName(root, 'input')) return; // Ignore input
else if(!$.nodeName(root, 'li')) {
root = $(root).parents('li').eq(0); // Get closest <li>
}
// Define references to <img>
var img = $('.toggle img', root).eq(0);
// Define reference to one of the wrap elements *
var c_wrap = $('.country_wrap, .county_wrap', root).eq(0);
if(img.attr('src') == "http://uk.primadonna.eu/images/arrow_white_up.gif"){
img.attr('src', 'http://www.prbuzzer.com/images/downarrow-white.png');
c_wrap.slideUp("slow");
} else {
img.attr('src', 'http://uk.primadonna.eu/images/arrow_white_up.gif');
c_wrap.slideDown("slow");
}
});
* I have defined the root to be a <li> element. The first occurrence of the .count(r)y_wrap element should be selected, which is achieved using .eq(0).
Your previous code contained some logical errors, which I have also fixed: $('.toggle img', this) selects every <img> element which is a child of .toggle, which caused the arrows at the end of the tree to toggle too. My solution using event.target is more neater, and allows your example to be extended to even deeper trees.

Categories