How to change data attributes on drag and drop Jquery UI? - javascript

I made a jQuery function where the user can drag and drop divs. But I want to change their data attributes whenever users drag and drop them, eg-
<div data-num="1">one</div>
<div data-num="2">Two</div>
<div data-num="3">Three</div>
<div data-num="4">Four</div>
Whenever user drag div three and place it on the top then it should change its data attribute data-num="3" to data-num="1" and the div after it should change its data attribute to data-num=2 and so on according to their position
What I am Trying
jQuery( "#app" ).sortable({
update: function(a, b) {
parseInt(jQuery(a).attr("data-num"),10) - parseInt(jQuery(b).attr("data-num"),10);
}
});

To achieve your goal you can hook an event handler to the stop event of the sortable. Then you can loop through each child div in #app and update the data-num to match the index of the element. Try this:
jQuery($ => {
$("#app").sortable({
stop: () => {
$('#app > div').each((i, el) => $(el).data('num', i + 1));
}
});
// only for testing...
$('button').on('click', () => {
$('#app > div').each((i, el) => console.log(`${el.textContent} - ${$(el).data('num')}`));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<div id="app">
<div data-num="1">One</div>
<div data-num="2">Two</div>
<div data-num="3">Three</div>
<div data-num="4">Four</div>
</div>
<button>Test</button>

we can also achieve this by using the item index
jQuery("#app").sortable({
update: function(e, ui) {
jQuery("#app div").each(function(i, elm) {
$elm = jQuery(elm);
var elindex = $elm.index("#app div");
$elm.attr("data-num", elindex+1);
});
}
});

Related

In angular 8, drag and drop with custom clone

Drag the content from the one component list and drop the content into another component and content will not be dropped into particular position.
Drag the div any drop any certain position on the page. I have found solution in jquery 1.9.1
<div class="dragger">Drag</div>
<div class="dragger">Drag</div>
<div class="dragger">Drag</div>
<div class="dragger">Drag</div>
<div class="dragger">Drag</div>
<div class="dropper">
<p>Drop</p>
</div>
jquery 1.9.1+javascript
$(document).ready(function () {
$('.dragger').draggable({
revert: "invalid",
helper: function () {
//Code here
return $("<div class='dragger'></div>").append("Hi");
}
});
$(".dropper").droppable({
drop: function (event, ui) {
$(this)
.addClass("ui-state-highlight")
.find("p")
.html("Dropped!");
var element = $('.ui-draggable-dragging');
var currentDrop=$(this);
return element.clone().appendTo(currentDrop);
}
});
});
but when I will implement that code in latest jquery version then it will show ERROR TypeError: $(...).draggable is not a function
how to implement that code in angular 8

How do I light up an entire single row by hovering on a span in one of the columns?

If I hover over the span with class "fromThisSpan", how do I change the background-color of the div that contains classes row and highlightThisRow?
There are a bunch of rows in the ul, and each row has a few columns.
The span is in the last column. The span also has a hover in the css (I didn't include it here).
So far, at one point I did get the desired results, but only for the first row.
I was using id's instead of classes for the div and span.
I've added a couple of my failed attempts of my jquery below.
This is a composite outline of the structure I'm using to show where I'm going with this only.
It's not a working code. The problem I'm having is with the jquery.
[ html/razor ]
<ul>
#foreach(ItemType item in ItemCollection)
<li>
<div class="row highlightThisRow">
<div class="col-md-4">
... item.contents1
</div>
<div class="col-md-4">
... item.contents2
</div>
<div class="col-md-4">
... item.contents3
<span class="fromThisSpan">Delete</span>
</div>
</div>
</li>
</ul>
Here I was trying to attach the hover event using the .on()
[ jquery ]
$(".fromThisSpan").on("hover", $(".fromThisSpan").hover(
(new function () {
$(".highlightThisRow").css("background-color", "#fce2e2");
}),
(new function () {
$(".highlightThisRow").css("background-color", "#ffffff");
})
));
This is an SO post I found and decided to give it a try, but didn't work for me.
The source: Adding hover CSS attributes via jQuery/Javascript
[ jquery ]
$(".fromThisSpan").mouseenter(function () {
$(".highlightThisRow").css("background-color", "#fce2e2");
}).mouseleave(function () {
$(".highlightThisRow").css("background-color", "#ffffff");
});
[ UPDATE ] Solved
This was the solution that worked in my case.
$(".fromThisSpan").hover(function () {
$(this).closest(".highlightThisRow").css("background-color", "#fce2e2");
}, function () {
$(this).closest(".highlightThisRow").css("background-color", "#ffffff");
});
Use closest to get the relative highlightThisRow of the element selected
$(function(){
$(".fromThisSpan").mouseenter(function () {
$(this).closest(".highlightThisRow").css("background-color", "#fce2e2");
}).mouseleave(function () {
$(this).closest(".highlightThisRow").css("background-color", "#ffffff");
});
});
or:
$(function(){
$("body").on('hover','.fromThisSpan',function () {
$(this).closest(".highlightThisRow").css("background-color", "#fce2e2");
},function () {
$(this).closest(".highlightThisRow").css("background-color", "#ffffff");
});
});
demo:https://jsfiddle.net/7bgqfdkj/
try (this).parent
$("#fromThisSpan").on("hover", $("#fromThisSpan").hover(
(new function () {
$(this).parent("#highlightThisRow").css("background-color", "#fce2e2");
}),
(new function () {
$(this).parent("#highlightThisRow").css("background-color", "#ffffff");
})
));

Hide content when clicking outside div with jquery

I'm using jquery to togle content with a button, I would like to hide the content when I click outside my "contentcone" div. The HTML is the following
<div class="togglecone">
</div>
<div class="contentcone">
<div class="contentleft">
<div class="title">
Cone
</div>
<div class="maincopy">
Hello my friends this is a really nice cone that can be placed anywhere
</div>
<a href="https://www.mcnicholas.co.uk/" class="button">
View on website
</a>
</div>
<div class="contentright"> <img src="images/cone.png" alt=""/>
</div>
</div>
This is the script
$(document).ready(function(){
var $content = $(".contentcone").hide();
$(".togglecone").on("click", function(e){
$(this).toggleClass("expandedcone");
$content.slideToggle();
});
});
http://jsfiddle.net/thomastalavera/SCKhf/914/
This should do it:
$(document).ready(function(){
var $content = $(".contentcone").hide();
$(document).on("click", function(e) {
if( $(e.target).is(".togglecone") ) {
$(this).toggleClass("expandedcone");
$content.slideToggle();
} else {
$content.slideUp();
}
});
});
DEMO
You need to set a click event on document to close the box. I tried to keep your original click function intact.
$(document).ready(function(){
var $content = $(".contentcone").hide();
$(".togglecone").on("click", function(e){
$(this).addClass("expandedcone");
$content.slideDown();
});
$(this).on('click', function(e) {
if ($(e.target).is('.togglecone')) { // don't slide up if you click the cone
return;
}
if ($(".togglecone").hasClass('expandedcone')) {
$content.slideUp();
$(this).removeClass("expandedcone");
}
});
});
http://jsfiddle.net/SCKhf/925/
A simple and pretty blunt way to do this is:
$(document).ready(function(){
var $content = $(".contentcone").hide();
$(".togglecone").on("click", function(e){
e.stopImmediatePropagation();
$(this).toggleClass("expandedcone");
$content.slideToggle();
});
$("body").on("click", function(e){
if ($(".contentcone").is(':visible')) {
$(".togglecone").click();
}
});
$(".contentcone").on("click", function(e){
e.stopImmediatePropagation();
return false;
})
});
But note it has a lot of disadvantages, is just a blunt solution to your problem, it must be tweaked to be ok as a permanent choice.
Edit (to answer the question in comment):
Sure, I know more than 1, each depending on your layout. You can:
a) Instead of the "body" part, make a selector for whatever elements you want to toggle event one. This works ok on layouts with a small number of big (as size on screen) elements.
b) Add one more condition to the "body" part, where you get mouse position and use it to see if the mouse is in the place you want. You can do this with e.pageX/e.pageY, or you can find relevant relative position to an element here jQuery get mouse position within an element.
This should do it with lesser code:
$(document).mousedown(function (e) {
var container = $(".togglecone");
if (!container.is(e.target) && container.has(e.target).length === 0)
{
container.fadeOut('slow');
}
});

Fire 2 actions with ONE click on a button

I'm trying to assign two actions to a button in jQuery. The button is supposed to:
open a hidden div, and...
scroll down to get said div into view.
While both actions are working on the button, they currently require 2 clicks. On the first click the div appears, but to scroll it into view I need to click the button a second time.
Any suggestions how I am going wrong?
jQuery
$(document).ready(function () {
"use strict";
$('.footer a').click(function (event) {
event.preventDefault();
$('.impr-text').hide(); // hide previous popup div
var id = $(this).data("id"); // get the div id which to show
$('#' + id).fadeIn(function () { // show cuurent click link's popup
$(this).css({
'display': 'block'
});
});
$.scrollTo( '#impressum-footer', 800, {easing:'elasout'} );
});
});
HTML
<div id="impressum-footer">
<div class="footer">
<div class="inner-wrap-imp">
<ul class="impressum-links">
<li>Impressum</li>
<li>|</li>
<li>Datenschutz</li>
<li class="impressum-button" ></li>
</ul>
</div>
</div>
<div id="impr-text" class="impr-text">
<div class="inner-wrap"> ...
You need to put the scrollTo in the fadeIn completion callback handler. That way callTo is performed on completion of the fadeIn rather than, essentially, at the same time. Currently you seem to also be placing a callback function where another parameter is to go (either duration or options object depending on which method signature you are using). Not sure why you have the css change there at all.
Try something like this:
$(document).ready(function () {
"use strict";
$('.footer a').click(function (event) {
event.preventDefault();
$('.impr-text').hide(); // hide previous popup div
var id = $(this).data("id"); // get the div id which to show
$('#' + id).fadeIn({
duration: 100, // or whatever duration you want to use
complete: function() {
$.scrollTo( '#impressum-footer', 800, {easing:'elasout'} );
}
});
});
});
if you want to assign 2 different actions on one button, set it 2 different classes (or IDs), lets say
<div class="action1 action2">
After, in jQuery you will be able to do:
$('.action1').on('click', function (e) { console.log('#1'); ... });
$('.action2').on('click', function (e) { console.log('#2'); ... });
JsFiddle: http://jsfiddle.net/g2wdd2cb/
I have now managed to get it going. The approach as explained by #euvl was the one...
I changed my code (the scrolling part) after I realized it wasn't working. The final (working) code now looks like this:
jQuery:
$(document).ready(function () {
"use strict";
$('.footer-action-1 a').click(function (event) {
event.preventDefault();
$('.impr-text').hide(); // hide previous popup div
var id = $(this).data("id"); // get the div id which to show
$('#' + id).fadeIn(function () { // show cuurent click link's popup
$(this).css({
'display': 'block'
});
});
});
});
$(document).on('click','.footer-action-2 a', function(event) {
event.preventDefault();
var target = "#" + this.getAttribute('data-target');
$('html, body').animate({
scrollTop: $(target).offset().top
}, 2000);
});
HTML:
<div id="impressum-footer">
<div class="footer footer-action-1 footer-action-2">
<div class="inner-wrap-imp">
<ul class="impressum-links">
<li>Impressum</li>
<li>|</li>
<li>Datenschutz</li>
<li class="impressum-button" ></li>
</ul>
</div>
</div>
<div id="impr-text" class="impr-text">
<div class="inner-wrap">
The only problem now is that it scrolls a little too far. The moment I add an offset it stops working.

Jquery Drag & Drop: Change element from li to div and back

I am trying the following:
Stage 1:
Change the draggable element from li to div on drop in #canvas
Move the draggable element inside #canvas
Stage 2:
Change the draggable element from div to li on drop in #imagelist
Move the draggable element inside #imagelist
Js:
$(function () {
var $imagelist = $("#imagelist");
var $canvas = $("#canvas");
$('li', $imagelist).draggable();
$canvas.droppable({
drop: function (event, ui) {}
});
$imagelist.droppable({
drop: function (event, ui) {}
});
});
Html:
<div id="listwrapper">
<ul id="imagelist">
<li class="draggable>Content that should not be lost on drag/drop</li>
<li class=" draggable>Content that should not be lost on drag/drop</li>
</ul>
</div>
<div id="canvas">
<div class="draggable">Content that should not be lost on drag/drop</div>
</div>
Could someone help me with this?
You can create a new function to change the element type - which is what I think you need:
(function($) {
$.fn.changeElementType = function(newType) {
var attrs = {};
$.each(this[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
this.replaceWith(function() {
return $("<" + newType + "/>", attrs).append($(this).contents());
});
};
})(jQuery);
see here
and here

Categories

Resources