jQuery UI Sortable on Click - javascript

I have the jQuery UI sorting functionality working fine, but I would also like to add in a basic click action to cause the draggable items to change <ul>. I have the <div class="click_area"> disabled from dragging. What I would like is in the first <ul> if the click_area is clicked then the sortable <li> would move to the second <ul> just as if I had dragged it over. Same deal if the click_area is clicked in the second <ul> it will be moved to the first <ul>. I have created a JS Fiddle for testing: http://jsfiddle.net/helpinspireme/wMnsa/
Any suggestions would be greatly appreciated. Thanks.

$("#unassigned_list, #recipients_list").sortable({
connectWith: ".connected_sortable",
items: "li",
handle: ".draggable_area",
stop: function(event, ui) {
updateLi(ui.item);
}
}).disableSelection().on("click", ".click_area", function() {
// First figure out which list the clicked element is NOT in...
var otherUL = $("#unassigned_list, #recipients_list").not($(this).closest("ul"));
var li = $(this).closest("li");
// Move the li to the other list. prependTo() can also be used instead of appendTo().
li.detach().appendTo(otherUL);
// Finally, switch the class on the li, and change the arrow's direction.
updateLi(li);
});
function updateLi(li) {
var clickArea = li.find(".click_area");
if (li.closest("ul").is("#recipients_list")) {
li.removeClass("ui-state-default").addClass("ui-state-highlight");
clickArea.html('←');
} else {
li.removeClass("ui-state-highlight").addClass("ui-state-default");
clickArea.html('→');
}
}
​

Here is a starting place for you,
.on('click', '.click_area', function(){
$(this).parent().appendTo($("#unassigned, recipients").not($(this).closest("ul")));
})
The trick being that the click handler is on the parent container not the individual children, so when they are moved you don't need to keep managing their handlers.
All you need to do is update the stylings.
jsFiddle

Related

jQuery hiding child element opens its child

Im using a table and rows can have child rows and it can go down a few levels,
what is happening now is that when hiding a child element it then opens that childs child element.
Heres my jQuery:
$(document).ready(function() {
function getChildren($row) {
var children = [], level = $row.attr('data-level');
while($row.next().attr('data-level') > level) {
children.push($row.next());
$row = $row.next();
}
return children;
}
$('.parent').on('click', function() {
var children = getChildren($(this));
$.each(children, function() {
$(this).toggle();
})
});
$(".parent a").click(function(e) {
e.stopPropagation();
})
})
I have set up a jsfiddle so you can see whats happening
https://jsfiddle.net/rhvye8k0/4/
If you click the first "+" you will see what im trying to describe.
Cant think how to sort it out
Update,
have sorted it and updated jsfiddle https://jsfiddle.net/rhvye8k0/5/
There may be a way to reduce the jQuery but it works for now
Your problem is the $(this).toggle(); in .parent's onclick handler. The tr at level 3 has style="display:none", the others don't. toggle() will toggle the receiving element(s) visibility so the others are show (their display is implicitly block) and level 3's is hidden.

remove onclick when attached to children

I have the following code:
layoutOverlaysBldg = $("#layout-overlays-bldg")
layoutOverlaysBldg.on("click", "div", function(event) {
var floor;
console.log("floornum: " + this.dataset.floornum);
floor = parseInt(this.dataset.floornum);
...
$("#choose-floor").fadeOut();
$("#choose-apt").fadeIn();
});
later - based on data I'm getting back from the DB - I want to remove some of the .on("click", "div", ...) from only some of the divs. I already have the selector that is getting the right divs but I cannot figure out how to remove the click event. I have tried .off("click") after selecting the right div but it has no effect.
This issue here is because you are using a delegated event. You can add or remove the event for all child elements, but not individual ones given your div selector.
With that in mind the easiest way to do what you need is to add the event based on a class, then add and remove that class on the children as needed. Something like this:
layoutOverlaysBldg = $("#layout-overlays-bldg")
layoutOverlaysBldg.on("click", "div.clickable", function(event) {
// your code...
});
You can then enable/disable the event on the child div by adding or removing the .clickable class.
You can try like this :
Example :
<div id="test">
<div id="first">first</div>
<div id="second">second</div>
</div>
<div onclick="unbindSecondDiv();">UNBIND</div>
<script>
function unbindSecondDiv()
{
test = $("#second")
test.unbind("click");
alert('Selected Area Click is Unbind');
}
$(document).ready(function(){
//BIND SELECTED DIV CLICK EVENT
test = $("#test > div")
test.bind("click" , function(event) {
alert($(this).attr('id'));
});
});
</script>
In the above example , selected DIV elements click event is bind.
And after execute function unbindSecondDiv() , second DIV click event will be unbind.
Have a try , may helps you.

JQuery .not(next) - is it possible?

Example HTML:
<div class=blah>
<div class=moreCats></div>
</div>
<div class=subCats>.......</div>
<div class=blah>
<div class=moreCats></div>
</div>
<div class=subCats>.......</div>
<div class=blah>
<div class=moreCats></div>
</div>
<div class=subCats>.......</div>
Using slideToggle, if I click the first div moreCats I want next subCats to slideDown, which it does. At the same time I want to slideUp any other open subCats, but, NOT the one I'm toggling or else it would close then reopen, which is what its doing.
Question: is this valid? If not is there something similar?
$('div.subCats').not($(this).next('.subCats')).slideUp();
Here's the full JQuery I'm trying
// show children cat items
$('#sideNav').on("click", ".moreCats", function() {
$('div.subCats').not($(this).next('.subCats')).slideUp(); // close all except next
$(this).next('.subCats').slideToggle(); // slideToggle next
});
You can combine them by placing the slideToggle for the current target (which will return that element) inside .not and you want to select the parent's next as well
$('#sideNav').on("click", ".moreCats", function() {
$('div.subCats').not($(this).parent().next('.subCats').slideToggle()).slideUp();
//or do $(this).closest('.blah').next('.subCats');
});
Demo
If you want to split them, then better cache the next instead of selecting it again.
$('#sideNav').on("click", ".moreCats", function() {
var $target = $(this).parent().next('.subCats');
$('div.subCats').not($target.slideToggle()).slideUp();
//or just do as below
//$('div.subCats').not($target).slideUp();
//$target.slideToggle()
});
.moreCats doesn't have any siblings so you can't use .next(). What you really need is to get the next sibling of this's parent. So you go from $(this) > .parent() > .next('.subCats')
$('body').on("click", ".moreCats", function() {
console.log($(this).parent().next('.subCats'));
$('div.subCats').not($(this).parent().next('.subCats')).slideUp(); // close all except next
$(this).parent().next('.subCats').slideToggle(); // slideToggle next
});
See this JSFiddle for an example.
What you have is valid but it doesn't do what you expect, .next() selects the next immediate sibling element, you should first select the parent element:
$('div.subCats').not($(this.parentNode).next('.subCats')).slideUp();
You can also use .index() method:
$('#sideNav').on({
click: function() {
var $sub = $('div.subCats'),
i = $('#sideNav .moreCats').index(this);
$sub.not( $sub.eq(i).slideToggle() ).slideUp();
}
}, ".moreCats");

show hidden div on list items

html:
I have a ul list with each li counstructed like this:
<li class="A">list-item
<div>1</div>
<div class="B">2
<div class="C">3</div>
</div>
</li>
where div C has css property display:none;
I wrote this js:
$(".A").hover(function () {
$(".C").toggle();
});
that shows hidden divs on li hover, but I would like js working only on active li item.
So when i hover li item it shows only that list item hidden div.
any suggestions? I am new with js, so any help would be appreciated, thnx!
Try something like this, it will find class C within this (which will be the element being hovered)
$(".A").hover(function() {
$(this).find(".C").toggle();
});
Use context to narrow the lookup to the desired element's children.
$(".A").hover(function () {
$(".C", this).toggle();
});
Using the hover(), the correct format of hover function is:
$(".A").hover(
function () {
// A function to execute when the mouse pointer enters the element.
$(this).find(".C").show();
},
function () {
// A function to execute when the mouse pointer leaves the element.
$(this).find(".C").hide();
}
);

javascript set element background color

i have a little javascript function that does something when one clicks on the element having onclick that function.
my problem is:
i want that, into this function, to set a font color fot the html element having this function onclick. but i don't suceed. my code:
<script type="text/javascript">
function selecteazaElement(id,stock){
document.addtobasket.idOfSelectedItem.value=id;
var number23=document.addtobasket.number;
number23.options.length=0;
if (stock>=6) stock=6;
for (i=1;i<=stock;i++){
//alert ('id: '+id+'; stock: '+stock);
number23.options[number23.options.length]=new Option(i, i);
}
}
</script>
and how i use it:
<li id = "product_types">
<a href="#" onclick='selecteazaElement(<?= $type->id; ?>,<?= $type->stock_2; ?>);'><?= $type->label; ?></a>
</li>
any suggestions? thanks!
i have added another function (jquery one) that does partially what i need. the new problem is: i want that background color to be set only on the last clicked item, not on all items that i click. code above:
$(document).ready(function() {
$('.product_types > li').click(function() {
$(this)
.css('background-color','#EE178C')
.siblings()
.css('background-color','#ffffff');
});
});
any ideas why?
thanks!
I would suggest
$(document).ready(function() {
$('.product_types > li').click(function() {
$('.product_types > li').css('background-color','#FFFFFF');
$(this).css('background-color','#EE178C');
});
});
Your element could have this code:
<li id = "product_types" onclick="selecteazaElement(this);" <...> </li>
To change the foreground color of that element:
function selecteazaElement(element)
{
element.style.foregroundColor="#SOMECOLOR";
}
If you want to change the background color on only the last element clicked, each element must have a different id. I'd suggest naming each one something like product_types1, product_types2, ..., product_typesN, and so on. Then have a reset function:
function Reset()
{
for (var i = 1; i <= N; i = i + 1)
{
document.getElementById('product_types'+i).style.backgroundColor="#RESETCOLOR";
}
}
When you call your selecteazaElement(this) function, first call the Reset function, then set the new element:
function selecteazaElement(element)
{
Reset();
element.style.backgroundColor="#SOMECOLOR";
}
This way all of the elements that start with product_types followed by a number will be reset to one particular color, and only the element clicked on will have the background changed.
The 'scope' of the function when invoked is the element clicked, so you should be able to just do:
function selecteazaElement(id,stock){
document.addtobasket.idOfSelectedItem.value=id;
var number23 = document.addtobasket.number;
number23.options.length=0;
if (stock>=6){
stock=6;
}
for (var i=1;i<=stock;i++){
//alert ('id: '+id+'; stock: '+stock);
number23.options[number23.options.length]=new Option(i, i);
}
// Alter 'this', which is the clicked element in this case
this.style.backgroundColor = '#000';
}
$(function() {
/*if product_types is a class of element ul the code below
will work otherwise use $('li.product_types') if it's a
class of li elements */
$('.product_types li').click(function() {
//remove this class that causes background change from any other sibling
$('.altBackground').removeClass('altBackground');
//add this class to the clicked element to change background, color etc...
$(this).addClass('altBackground');
});
});
Have your css something like this:
<style type='text/css'>
.altBackground {
background-color:#EE178C;
/* color: your color ;
foo: bar */
}
</style>
Attach a jQuery click event to '#product_types a' that removes a class from the parent of all elements that match that selector; then, add the class that contains the styles you want back to the parent of the element that was just clicked. It's a little heavy handed and can be made more efficient but it works.
I've made an example in jsFiddle: http://jsfiddle.net/jszpila/f6FDF/
try this instead:
//ON PAGE LOAD
$(document).ready(function() {
//SELECT ALL OF THE LIST ITEMS
$('.product_types > li').each(function () {
//FOR EACH OF THE LIST ITEMS BIND A CLICK EVENT
$(this).click(function() {
//GRAB THE CURRENT LIST ITEM, CHANGE IT BG, RESET THE REST
$(this)
.css('background-color','#EE178C')
.siblings()
.css('background-color','transparent');
});
});
});
If I am correct, the problem is that the click event is being binded to all of the list items (li). when one list item is clicked the event is fired on all of the list items.
I added a simple .each() to your code. It will loop through each of the list items and bind a event to each separately.
Cheers,
-Robert Hurst

Categories

Resources