Prevent inner div from triggering outer-div events - javascript

I created a basic row click-and-drag selection function. However the issue is click-and-dragging over the columns toggles them on and off. I am looking for some sort of return false or stopPropagation of some sort but I cannot get these to work.
return false does help by preventing text selection, but it does not prevent column selection from affecting row selection.
To demonstrate, http://jsfiddle.net/sjwcztre/, try to select the rows from the right side - no problem. But try to select the rows where column text is present - it goes wonky
var isMouseDown = false;
$('.row').each(function () {
$(this).mousedown(function () {
isMouseDown = true;
rowClickHandler(this);
console.log('mdown');
return false;
})
.mouseover(function () {
if (isMouseDown) rowClickHandler(this);
});
$(document).mouseup(function () {
isMouseDown = false;
});
});
function rowClickHandler(obj) {
$(obj).toggleClass('highlight');
}

Check this, see if it works for you. Basically you need to create events for the children of your rows and handle them differently, adding a hoverChild control variable helped to prevent the hover from the parent activating once again.

Related

Javascript help-Menu

Want to make it so when my menu items transition away, the search bar pops up.
let menuItemsQuerySelector = document.querySelectorAll(".menu-item");
searchElement.addEventListener("click", function() {
console.log("Clicked search");
menuItemsQuerySelector.forEach(function(menuItem) {
console.log("Boom");
menuItem.classList.toggle("hide-item");
});
});
};
this is what i have so far to make the toggle animation work. my claases for the search bar are, search-from, i need to make it active somehow when the menu disappears. The css class is already set up.
You can use the "transitionend" event to execute code after the transition ends.
You would have to add a boolean to check whether the transition was hidden-visible or visible-hidden
let hidden = false;
searchElement.addEventListener("click", function() {
hidden = true;
//your other code
});
//Further down the line when showing your elements again
hidden = false;
However seeing that you have multiple elements that transition at the same time, you could either:
Hook the event only on one of them
menuItemsQuerySelector[0].on('transitionend', () => {
if(hidden)
//your code here
});
or Use a timed function
setTimeout(() => {
if(hidden)
//your code here
}, <delay in millisecods>);

Moving rows to and from Gridviews using .clone, .cloneNode and .append

I have two Gridviews, one loaded with data and the other not. When I double click an item from gvDisplayAvailItems, I want the row to go to gvDisplaySelectedItems, and vice-versa. The Grids are also multi-select, with a button allowing all selected items to be moved. gvDisplaySelectedItems differs by 1 additional input column.
AddDisplayParams() is called when the button is pressed.
function AddDisplayParams() {
var rows = $("#gvDisplayAvailItems").find('tr.selected');
rows.each(function (index, element) {
element.classList.remove("selected");
var newRow = element.cloneNode(true);
newRow.appendChild(customIdTb.cloneNode(true));
$("#gvDisplaySelectedItems").append(newRow);
element.remove();
});
}
AddDisplayParam is called on double-click.
function AddDisplayParam(param) {
var newRow = param.clone(true);
newRow.append(customIdTb.cloneNode(true));
$("#gvDisplaySelectedItems").append(newRow);
param.remove();
}
And here is how I trigger the selection and double clicks.
$("#gvDisplaySelectedItems tr").click(function () {
$(this).toggleClass("selected");
});
$("#gvDisplaySelectedItems tr").dblclick(function () {
RemoveDisplayParam($(this));
});
$("#gvDisplayAvailItems tr").click(function () {
$(this).toggleClass("selected");
});
$("#gvDisplayAvailItems tr").dblclick(function () {
AddDisplayParam($(this));
});
When I both double click and mass select rows on gvDisplayAvailItems, the rows are moved to gvDisplaySelectedItems correctly. However, nothing is triggered for the functions of gvDisplaySelectedItems for rows that were added via AddDisplayParams. Those added by AddDisplayParam can be highligted, but when double clicked only append another textbox to the row in gvDisplaySelectedItems.
So it seems that .clone and .cloneNode are doing something very different here despite having basically the same function. Could someone please explain why one partially works, while the other does not? And also, why my functions for the second grid are not triggered upon single and double click?
I'd suggest to try delegated event handlers.
E.g.
$("#gvDisplaySelectedItems").on("click", "tr", function () {
$(this).toggleClass("selected");
});
instead of
$("#gvDisplaySelectedItems tr").click(function () {
$(this).toggleClass("selected");
});
and so on for other event handlers.
More info
Regarding other improvements - you don't have to clone()/append()/remove() to move an element. Just doing append() to a new parent will effectively move it since an element can have only one parent each moment of time.
Example: JSFiddle

Fixing toggle all behavior in checkbox element

I'm trying to toggle all checkboxes on a table and my code works but has a few issues and I don't find how to get ride of them. So here is the code:
$(function () {
$('#toggleCheckbox').on('click', function () {
var $toggle = $(this).is(':checked');
$("#codigoArancelarioBody").find("input:checkbox").click();
});
});
Take a look at this Fiddle I setup for testing and do this tests:
Mark the first checkbox (the one at table heading level) the rest of them inside #codigoArancelarioBody get checked and this is right
Mark first the checkbox at the first row (the only at table body level) and then mark the toggleAll you will see how things goes wrong since if I check the toggleAll them all should remain checked and that's the wrong part on my code
How I can fix this? Also I'll like to add a class 'removedAlert' to those TR I mark, how?
You need two click event handlers, one for the check/uncheck all box and one for the other ones
JS
$('#toggleCheckbox').on('click', function () {
var $toggle = $(this).is(':checked');
$("#codigoArancelarioBody").find("input:checkbox").prop("checked", $toggle);
});
$("#codigoArancelarioBody input:checkbox").on('click', function () {
if (!$(this).is(':checked')) {
$('#toggleCheckbox').prop("checked", false);
} else if ($("#codigoArancelarioBody input:checkbox").length == $("#codigoArancelarioBody input:checkbox:checked").length) {
$('#toggleCheckbox').prop("checked", true);
}
});
DEMO
since the same code will be applied in a lot of places on my code and
to avoid DRY, I'll like to pass the selector as a parameter in all
your code solution could you edit your post to achieve this?
$toggleCheckBox = $('#toggleCheckbox');
$checkBoxTbody = $("#codigoArancelarioBody");
$toggleCheckBox.on('click', function () {
var $toggle = $(this).is(':checked');
$checkBoxTbody.find("input:checkbox").prop("checked", $toggle);
});
$checkBoxTbody.find("input:checkbox").on('click', function () {
if (!$(this).is(':checked')) {
$toggleCheckBox.prop("checked", false);
} else if ($checkBoxTbody.find("input:checkbox").length == $checkBoxTbody.find("input:checkbox:checked").length) {
$toggleCheckBox.prop("checked", true);
}
});
DEMO
If you don't need the "click" event for something else you can do this:
$(function () {
$('#toggleCheckbox').on('change', function () {
var toggle = $(this).is(':checked');
$("#codigoArancelarioBody").find("input:checkbox").prop('checked', toggle ).closest('tr').addClass('removedAlert');
});
});
The code is actually executing what you told it to do, i.e. every time I click the checkbox on top click to other checkboxes. This way if a box is checked it will uncheck itself, because it won't mind if the top is checked or not.
What you really want is "when I check the box on top, check all the others, when I uncheck it, then uncheck all the others", which is sort of different as you see.
Try this:
$(function () {
// best practice: always store the selectors you access multiple times
var checkboxes = $("#codigoArancelarioBody").find("input:checkbox"),
toggleAll = $('#toggleCheckbox');
toggleAll.on('click', function () {
// is the top checkbox checked? return true, is it unchecked? Then return false.
var $toggle = $(this).is(':checked');
// .prop('checked', true) makes it checked, .prop('checked', false) makes it unchecked
checkboxes.prop('checked', $toggle);
});
});
see: http://jsfiddle.net/gleezer/nnfg80x1/3/

Prevent click after focus event

When user clicks on input field, two consecutive events are being executed: focus and click.
focus always gets executed first and shows the notice. But click which runs immediately after focus hides the notice. I only have this problem when input field is not focused and both events get executed consecutively.
I'm looking for the clean solution which can help me to implement such functionality (without any timeouts or weird hacks).
HTML:
<label for="example">Example input: </label>
<input type="text" id="example" name="example" />
<p id="notice" class="hide">This text could show when focus, hide when blur and toggle show/hide when click.</p>
JavaScript:
$('#example').on('focus', _onFocus)
.on('blur', _onBlur)
.on('click', _onClick);
function _onFocus(e) {
console.log('focus');
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
$('#notice').removeClass('hide');
}
function _onClick(e) {
console.log('click');
$('#notice').toggleClass('hide');
}
function _onBlur(e) {
console.log('blur');
$('#notice').addClass('hide');
}
UPDATED Fiddle is here:
I think you jumbled up the toggles. No need to prevent propagation and all that. Just check if the notice is already visible when click fires.
Demo: http://jsfiddle.net/3Bev4/13/
Code:
var $notice = $('#notice'); // cache the notice
function _onFocus(e) {
console.log('focus');
$notice.removeClass('hide'); // on focus show it
}
function _onClick(e) {
console.log('click');
if ($notice.is('hidden')) { // on click check if already visible
$notice.removeClass('hide'); // if not then show it
}
}
function _onBlur(e) {
console.log('blur');
$notice.addClass('hide'); // on blur hide it
}
Hope that helps.
Update: based on OP's clarification on click toggling:
Just cache the focus event in a state variable and then based on the state either show the notice or toggle the class.
Demo 2: http://jsfiddle.net/3Bev4/19/
Updated code:
var $notice = $('#notice'), isfocus = false;
function _onFocus(e) {
isFocus = true; // cache the state of focus
$notice.removeClass('hide');
}
function _onClick(e) {
if (isFocus) { // if focus was fired, show/hide based on visibility
if ($notice.is('hidden')) { $notice.removeClass('hide'); }
isFocus = false; // reset the cached state for future
} else {
$notice.toggleClass('hide'); // toggle if there is only click while focussed
}
}
Update 2: based on OP's observation on first click after tab focus:
On second thought, can you just bind the mousedown or mouseup instead of click? That will not fire the focus.
Demo 3: http://jsfiddle.net/3Bev4/24/
Updated code:
$('#example').on('focus', _onFocus)
.on('blur', _onBlur)
.on('mousedown', _onClick);
var $notice = $('#notice');
function _onFocus(e) { $notice.removeClass('hide'); }
function _onClick(e) { $notice.toggleClass('hide'); }
function _onBlur(e) { $notice.addClass('hide'); }
Does that work for you?
Setting a variable for "focus" seems to do the trick : http://jsfiddle.net/3Bev4/9/
Javascript:
$('#example').on('focus', _onFocus)
.on('click', _onClick)
.on('blur', _onBlur);
focus = false;
function _onFocus(e) {
console.log('focus');
$('#notice').removeClass('hide');
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
focus = true;
}
function _onClick(e) {
console.log('click');
if (!focus) {
$('#notice').toggleClass('hide');
} else {
focus = false;
}
}
function _onBlur(e) {
console.log('blur');
$('#notice').addClass('hide');
}
If you want to hide the notice onBlur, surely it needs to be:
function _onBlur(e) {
console.log('blur');
$('#notice').addClass('hide'); // Add the hidden class, not remove it
}
When doing this in the fiddle, it seemed to fix it.
The code you have written is correct, except that you have to replae $('#notice').removeClass('hide'); with $('#notice').addClass('hide');
Because onBlur you want to hide so add hide class, instead you are removing the "hide" calss.
I hope this is what the mistake you have done.
Correct if I am wrong, Because I don't know JQuery much, I just know JavaScript.
you can use many jQuery methods rather than add or move class:
Update: add a params to deal with the click function
http://jsfiddle.net/3Bev4/23/
var showNotice = false;
$('#example').focus(function(){
$('#notice').show();
showNotice = true;
}).click(function(){
if(showNotice){
$('#notice').show();
showNotice = false;
}else{
showNotice = true;
$('#notice').hide();
}
}).blur(function(){
$('#notice').hide();
});

how to hide submenu after click

I'm creating a dropdown menu for mobile site
http://gthost.dyndns.org/kudu/en/
when I click on My Account and click on Who we are, submenu still show,,
I Want to hide it after I click on the link.
this is JavaScript code
var $j = jQuery.noConflict();
$j(document).ready(function () {
$j(".account").click(function () {
var X = $j(this).attr('id');
if (X == 1) {
$j(".submenu").hide();
$j(this).attr('id', '0');
} else {
$j(".submenu").show();
$j(this).attr('id', '1');
}
});
//Mouseup textarea false
$j(".submenu").mouseup(function () {
return false
});
$j(".account").mouseup(function () {
return false
});
//Textarea without editing.
$j(document).mouseup(function () {
$j(".submenu").hide();
$j(".account").attr('id', '');
});
});
i would try using:
$('.submenu').css({display:"none"});
instead of .hide();
Two things strike me as odd here.
Why are your ID's integers - valid names start with [a-z_] etc.
Why are you changing the ID? An ID is meant to be a unique identifier and should persist as long as the element does. If you wish to store information about the state of an element within the element itself, then perhaps look into data attributes.
Without seeing your HTML structure everyone is going to be guessing but rather than whatever you are trying to do with the ID's it looks like you could logically use jQuery.toggle:
$j(".account").click(function(){
$j(".submenu").toggle();
});

Categories