In Masonry, it is possible to delete an element by clicking on it. The catch is, that You have to click directly on that element - so if you use these "bricks" as an image gallery (as long as these photos are included as a background image) You can delete them, by clicking on the element. The problem is, when you use these as some messages/info/other content containers. Then, due to formatting-related stuff the parent element gets "hidden" behind other tags, and You can't actually click on it.
The problem is shown here:
http://jsfiddle.net/dan1410/SfU5T/
You can close red boxes, but not green ones, as they are overlapped by another elements.
I've tried code like:
eventie.bind( container, 'click', function( event ) {
// don't proceed if item was not clicked on
if ( !classie.has( event.target, 'closeable' ) ) {
return;
}
// remove clicked element
msnry.remove( event.target );
// layout remaining item elements
msnry.layout();
});
});
and
var todelete = document.querySelector('.closeable');
eventie.bind( container, 'click', function( event ) {
// remove clicked element
msnry.remove( todelete );
// layout remaining item elements
msnry.layout();
});
});
but You still have to click directly on the element You'd like to close...
My masonry content structure looks like
<div id="masonry" >
<div class="item blue closeable">
<div id="itheader"><h2 class="secsectiontitle">Space available</h2></div>
<div id="itcontent">
some statistics here...<br/>
and here, too
</div>
</div>
Only elements with .closeable class are supposed to be closeable.
So, the question is: how to close an element using a button/a link?
I'm not very familiar with JS, so I'd like to ask You guys for help. Thank You in advance!
Unless there are handlers that stops the propagation of the click event on children elements, the click event should bubble up without any issues.
Also, if you are using jQuery, you should use the jQuery Masonry's API.
Note: I couldn't access your fiddle and couldn't test the solution
var $container = $('#masonry').on('click', '.closeable', function (e) {
$container.masonry('remove', e.currentTarget);
$container.masonry(); //layout
$container.masonry('reloadItems'); //OP said it was also required
});
Related
Hello I made drawer which appears when you click on it and then expands it's width, after second click, it back to it's minimalized form, inside this drawer I have table with checkboxes etc which I will use later to filter things. Thing is that if I click on checkbox inside the table, drawer is hiding. How to do it that event which allow for toggling of width of drawer would work only if I click on it except place where is table? As far as I know it should do something with stopPropagation but somehow I was unabled to implement it in working form.
<div class="filter_drawer" onclick="show_stat()">
<Table class="stat_table">
...some content
</Table>
</div>
function show_stat() {
event.stopPropagation()
var stats = document.querySelector('.filter_drawer')
var table = stats.querySelector('.stat_table')
var panels = document.querySelector('.main_container')
stats.classList.toggle('expanded_stat')
table.classList.toggle('show')
panels.classList.toggle('expanded_stat_panel')
}
Attach the listener to the element properly using Javascript instead, and then you can check if the event.target is the .filter_drawer element. If so, then it was a click directly on the element, and not one of its descendants:
document.querySelector('.filter_drawer').addEventListener('click', (e) => {
if (e.target.matches('.filter_drawer')) {
showStat();
}
});
(If the click was on a descendant element, and not the filter_drawer itself, then the e.target test won't match)
No need for stopPropagation.
I have a accordion menu which have for each parent menu a icon, and this icon is animated with css transition and transform. I added a class with a if condition to the click event. The problem is that when I click for example on Menu1, the icon animation does very well, but if I click directly on Menu2, the menu2 dropdown appear but icon from the menu1 don't take his original position.
This problem applies to each icon in each menu/submenu, I thinks that I have a mistake in my code.
$(document).ready(function() {
// Icons effect
$('#mw_nav .toggle').click(function() {
if($(this).hasClass('rotate_close'))
{
$(this).addClass('rotate_open').removeClass('rotate_close');
}
else {
$(this).addClass('rotate_close').removeClass('rotate_open');
}
});
// Toggle Menu Items
$(function () {
$("#m_nav > ul ul").hide();
$('#m_nav .toggle').click(function (e) {
e.preventDefault();
e.stopPropagation();
var $parentli = $(this).closest('li');
$parentli.siblings('li').find('ul:visible').slideToggle(400);
$parentli.find('> ul').stop().slideToggle(400);
$(this).remove;
});
});
});
FIDDLE
Any help would be appreciated
There are 2 issues I see with your code. The first is a recommendation to NOT have $(function() { // your code }) inside of $(document).ready(). $(function() {}) is actually just shorthand for $(document).ready() so you are adding code you do not need.
The second is an issue with your logic.
$('#mw_nav .toggle') and $('#m_nav .toggle') click listeners are essentially adding a click listener on the same exact element, but both run different logic. When the $('#mw_nav .toggle') click listener is getting called it checks for a class to exist to decide what class it needs to remove and add. When $('#m_nav .toggle') click listener is getting called it calls a slideToggle function on the current nested <ul> regardless if another menu is opened or closed and there is no check in place of whether or not the rotate_open/rotate_close classes exist allowing for the classes to get swapped. There is no relation between the swapping of rotate_open/rotate_close classes and the logic that slideToggles <ul> up/down.
UPDATE
I have edited your code and made updates that will now work seen here: https://jsfiddle.net/vhfn0q5a/9/
I have added a class of .top_level to the top level items in your HTML. I use this as a way of differentiating the top level <li> from the sub menus. Next, at the end of the click event listener I check to see if the .toggle element clicked is a top level element, if so I target all top level elements that are not the current selected and make sure they have the .rotate_close class.
$(function() {}) shorthand reference
Use this code in your first click handler:
$('#mw_nav .toggle').click(function() {
$(this).toggleClass('rotate_close rotate_open');
if ($('#mw_nav .toggle').not(this).hasClass('rotate_open')) {
$('#mw_nav .toggle').not(this).removeClass('rotate_open').addClass('rotate_close');
}
});
I've updated your FIDDLE with an working example.
Cheers!
I have an element inside an element, when I click the element underneath I want the slider to open. When I click on the outermost element I want the slider to close.
Unfortunately when I click on the outermost it clicks the underneath element as well. Is there a way to click only on the outermost element ignoring the click on the underneath element? The events are triggered on click and executed with javascript.
I tried with z-index but it still captures the underneath element clicked as well, and because the functions are contrary to one another nothing happens.
edit: on a "code is worth 1000 words" tip
var $target = $(this).data('pos', i) //give each li an index #
$target.data('hpaneloffsetw', $target.find('.hpanel:eq(0)').outerWidth()) //get offset width of each .hpanel DIV (config.dimensions.fullw + any DIV padding)
$target[haccordion.ismobile? "click" : "mouseenter"](function(){
haccordion.expandli(config.accordionid, this)
config.$lastexpanded=$(this)
})
if (config.collapsecurrent){ //if previous content should be contracted when expanding current
$('.close').click(function(){
$target.stop().animate({width:config.paneldimensions.peekw}, config.speed) //contract previous content
})
$target.dblclick(function(){
$(this).stop().animate({width:config.paneldimensions.peekw}, config.speed) //contract previous content
})
}
Because the code is borrowed, I don't understand much of it. But basically I want the "click" : "mousteenter" function to work on click, without interfering with the .close().click
It sounds like you need to stop the click event bubbling up the DOM to be caught by parent elements. You can use stopPropagation() to do this:
$('.close').click(function(e) {
e.stopPropagation();
$target.stop().animate({ width: config.paneldimensions.peekw }, config.speed);
})
$target.dblclick(function(e) {
e.stopPropagation();
$(this).stop().animate({ width: config.paneldimensions.peekw }, config.speed);
})
Try the following fiddle
$("#outer").click(function(){alert("outer clicked")});
$("#inner").click(function(e){
alert("inner clicked")
e.stopPropagation();
});
To identify the element you have "really" clicked on, you can try to identify it through accessing the target property of the jquery-event-object.
After you identified the target you clicked on, you could prevent other event handlers from firing.
Use CSS specific jquery to point exact element like below, use > to point exact child
table > tbody > tr > td > input[type='text']
like this.
I have a pretty simple jQuery draggable/sortable/droppable combination going on where I'm sorting several divs, each of which contain an image wrapped in an anchor element with an href.
The problem is, when I drag a sortable item to the "trash" droppable area (to destroy it), the page sometimes changes its location and goes to the href URL from within the draggable!
I have debugged the hell out of the page and it is not any of my code causing this. The drop event happens normally and returns (I've tried returning true and false) just fine. It's something in jQuery UI's code causing the href to be fired.
It doesn't happen every time. I'm not "clicking" the element - just dragging.
Can anyone offer a suggestion please?
Example of my droppable code:
var trash = this._area_trash.droppable({
drop: this.eventtrashDrop,
hoverClass: 'highlight'
});
// ...
this.eventtrashDrop = function(event,ui) {
var o = ui.draggable;
if( typeof(o)=='object' && o!=null ) {
if( o.parents(obj._selector_stack_area).length>0 ) {
var id = parseInt(o.attr('lang'));
o.remove();
obj.eventStateRemove(id);
}
}
// Page location hasn't been changed yet!
return true;
}
EDIT: the original issue still remains, and I suspect it's some kind of bug in jQuery UI. However a workaround is to replace the anchor element with a div before destroying the sortable item so it can't change to the anchor's href:
var anchor = jQuery(o).find("a");
var img = jQuery(anchor).html();
jQuery(anchor).replaceWith("<div/>").html(img);
Sounds to me like the anchor is being triggered on the click.
You need to listen for event and prevent the default action.
Something like this:
$('a').click(function(event){
event.preventDefault();
});
I have a click function bound to many elements. It is possible that sometimes these elements may sit within one another. So, the click event is bound to a child and also bound to its parent. The method is specific to the element clicked. Naturally, because of event bubbling, the child's event is fired first, and then the parents. I cannot have them both called at the same time because the parents event overwrites the event of the child. So I could use event.stopPropagation() so only the first element clicked receives the event. The problem is that there are other click events also attached to the element, for example, I am using jQuery's draggable on these elements. If I stop the propagation of the click event, then draggable doesn't work, and the following click events are not called.
So my question is: Is there a way to stop the event bubbling of the method the event will call and not the entire event?
Brilliant John, but here is the problem:
<div id="Elm1"><!-- relative -->
<div class="Elmchildren"></div><!-- absolute-->
<div class="Elmchildren"></div><!-- absolute-->
<div class="Elmchildren"></div><!-- absolute-->
<div id="Elm2"><!-- relative -->
<div class="Elmchildren"></div><!-- absolute-->
<div class="Elmchildren"></div><!-- absolute-->
<div class="Elmchildren"></div><!-- absolute-->
</div>
</div>
Click event is bound to #Elm1 and #Elm2. The .Elmchildren are width and height 100%. So they are actually the current targets.
try someting like this
$(mySelector).click(function(evt) {
if (evt.target == evt.currentTarget) {
///run your code. The if statment will only run this click event on the target element
///all other click events will still run.
}
});
The suggested solution
evt.target == evt.currentTarget
is nice, but there are cases where it does not help.
Example: A (suckerfish-style) menu structure with nested ul/li lists.
The mousemove event comes from a link inside a list item, which is a child of an ul-list, which is again a child of another list item. Typical for a html menu structure with submenus.
The evt.target would be the link tag, but we are interested in the mousemove on the list item.
Even worse: The link tag could contain span or img tags or other nested stuff. Then evt.target would be this span or img.
What seems to work here is to catch the event on a parent / root item, and then check the parents of evt.target.
Like this (with jQuery),
var $menu = $('div#menu');
$('body').mousemove(function(evt){
var element = evt.target;
// find the deepest list item that was affected by this mouseover event.
var list_item;
var in_menu = false;
while (element) {
if (element == $menu[0]) {
in_menu = true;
break;
}
else if (!list_item && element.tagName == 'LI') {
// we found a list item, but we are not sure if we are inside the menu tree.
list_item = element;
}
}
// do something with the result.
if (!in_menu) {
.. // close all submenus
}
if (list_item) {
.. // open the submenu for this list item.
}
else {
// mouse in menu, but not hovering an item.
// leave the submenus open. (?)
}
});
Maybe some of this could be abbreviated with jQuery like $(evt.target).parents().is($menu), but I did not get this to work. Also, I would guess that this explicit loop with element.tagName is faster.