I am hoping someone may help me to figure out a sticking point I am at. I have tabs that are wrapped in div's that are added dynamically so at any time I do not know how many there will be. Even so, if I was to have 3 tabs, like so:
<div class="tabs">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
</div>
I am using HTML5 Drag and Drop. What I am trying to do is figure out if the current tag that I have is greater than or less than the tab that I am over so I can then drop it before or after the tab. I start to get coordinates for the getBoundingClientRect() for the element that I have, but I have not figured out how to determine whether I am greater than or less than the tab I am hovering over. For example, if I was dragging Tab 2, how would I figure out if I am past Tab 3 to drop it there after or if I dragged it before Tab 1 to drop it there.
Pretty much this gets down to being able to do some math, which I am not good at, and logic to add to my jQuery code to know where to drop the current tab I have.
Thank you for help in advance.
Less math based approach to finding out where you're hovering but requires you add an index to each tab (dynamically or otherwise):
<div class="tabs">
<div class="tab" data-index="0">Tab 1</div>
<div class="tab" data-index="1">Tab 2</div>
<div class="tab" data-index="2">Tab 3</div>
</div>
Find the tab you're currently hovering over:
$('.tab').hover(function () {
var index = $(this).data('index');
console.log(index);
console.log(this); // div itself
});
And people say you don't need math to be a programmer. Hehe!
Just check the left of the dragged div against the center (left + width)/2 of the target divs. If it's less, it's left of that div. If it's higher, it's right of the div.
Here you are: I did an example, that allow drop the element with larger id before element with smaller id.
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
// get id of dragging element
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
if (data > ev.target.id) {
var parent = document.getElementsByClassName('tabs')[0]
parent.insertBefore(
document.getElementById(data), ev.target);
}
}
<div class="tabs">
<div class="tab" id="1" draggable="true" ondragstart="drag(event)" ondrop="drop(event)" ondragover="allowDrop(event)">Tab 1</div>
<div class="tab" id="2" draggable="true" ondragstart="drag(event)" ondrop="drop(event)" ondragover="allowDrop(event)">Tab 2</div>
<div class="tab" id="3" draggable="true" ondragstart="drag(event)" ondrop="drop(event)" ondragover="allowDrop(event)">Tab 3</div>
</div>
Refer here: http://www.w3schools.com/html/html5_draganddrop.asp
Hope this helps.
Related
I have a problem with scrollTop that partially works that I will try to describe. First to get it work I applied the solution found here.
I have an angular component that renders a list of nested angular components in it using *ngFor. Snippet follows (parent):
<div id="scrollable-container" class="scrollable">
<div *ngIf="isAccountsToShow" class="top-row-spacing">
<div *ngIf="accountsToggle">
<div class="grid-x ruler">
<div class="small-4 cell">
<div class="text-left sub-header">Header 1</div>
</div>
<div class="small-1 cell">
<div class="text-left sub-header">Header 2</div>
</div>
<div class="small-2 cell">
<div class="text-center sub-header">Header 3</div>
</div>
<div class="small-2 cell">
<div class="text-center sub-header">Header 4</div>
</div>
<div class="small-3 cell">
<div class="text-center sub-header">Header 5</div>
</div>
</div>
<div *ngFor="let data of displayAccounts">
<member-product
[memberNumber]="mnum"
id={{data.accountNumber}}
(scrollIntoView)="scrollToView(data.accountNumber)"
[product]="data" </member-product>
</div>
</div>
</div>
</div>
The child's html contains info on each header and in addition a ellipsis toggle at the far right that looks like this:
screenshot of a single element (Apparently I need more reputation points to fully add a screenshot. Hope it helps anyway).
The problem: everytime I click the ellipsis it will expand the account information (NOTE: this is NOT another angular nested component) to reveal even more information AND the account clicked will autoscroll to the top. screenshot of expanded widgetThis works for the first accounts considering that there might be dozens or even hundreds but will fail to scroll only for the last few and it will fail gradually, meaning that it will begin to scroll less closer to the top of its container until the very last item which will not scroll at all. Also it fails when only a few elements are displayed causing no overflow-y where the scrolling simply does not happen.
Scroll code: (I'm using event emitter here as you might have already noticed)
scrollToView(accountNumber): void {
var element = document.getElementById(accountNumber);
var topPos = element.offsetTop;
document.getElementById('scrollable-container').scrollTop = topPos - 10;
}
Css code:
.scrollable {
max-height: 24rem;
position: relative;
}
I not quite sure if this is an overflow-y related issue or what. I am completely puzzled with this.
Searching for this very particular problem in Stackoverflow yielded no results, be it angular be it jquery although it doesn't apply to my angular 2 scenario.
I appreciate any insight or help on the matter.
I am using Jquery with HTML and trying to scroll to the next Div with Animation.
Sadly, nothing is helping me out. I want an icon on the bottom left which will scroll to the next div. This is my basic divs
<body>
<div id="scroller"><a class="display" href="#">Link </a></div>
<div class="menu-wrap"></div>
<div id="section1" class="section current"></div>
<div id="section2" class="section"> </div>
<div id="section3" class="section"> </div>
<div id="section4" class="section"></div>
<div id="section5" class="section"></div>
<div id="section6" class="section"></div>
<div id="section7" class="section"></div>
<div id="section8" class="section"></div>
<div id="footer"></div>
</div>
I want to scroll between the "section".I have others Divs inside each of them but different ids. I dont think that should be a problem? Nothing seems to work, My jQUery is
$(document).ready(function(){
$('a.display').on('click', function(e) {
e.preventDefault();
var offset = $(this).next().find('div#section').offset().top;
$('html, body').stop().animate({ scrollTop: offset }, 400);
});
});
Your code is not doing what you think.
First, $(this).next() returns no elements. Event if it did, you should've used .find('div.section') instead of .find('div#section'). Also, for the "scroll to next" capability you have be able to somehow know the current scroll position and compare it to the position of the
anticipated next one.
Considering this I suggest using jquery-scrollTo plugin instead of inventing your own implementation.
Here's an example usage: JSFiddle
I have a page that has a couple image thumbnails that when clicked on they get cloned and appended into another element. The issue that I'm running in to is that all of the elements that I need to appendTo all have the same class. So if I click one thumbnail it gets appended to every single element that has the class view_full_img. Here is the HTML that I have to work with. Simply targeting these with different classes is not going to work for me, this HTML is generated by Drupal.
<div class="view_full_img"></div>
<div class="thumbs">
<div class="img blue"></div>
<div class="img green"></div>
<div class="img yellow"></div>
</div>
<div class="view_full_img"></div>
<div class="thumbs">
<div class="img red"></div>
<div class="img purple"></div>
<div class="img orange"></div>
</div>
Here's my jQuery..
$(".thumbs div").click(function(){
$(".view_full_img div").remove();
$(this).clone().appendTo(".view_full_img");
});
What I want to have happen is that when I click one of the .thumbs divs I want it to get cloned into the .view_full_img div that is directly above it. I've tried using combinations of closest() prev() parent() etc and just can't come up with something that works.
Here's a jsfiddle...
http://jsfiddle.net/dmcgrew/UeTv6/
You need parent(), then prev():
$(".thumbs div").click(function () {
$(this).parent().prev(".view_full_img").empty().append($(this).clone());
});
$(".thumbs div").click(function () {
var t = $(this);
t.appendTo(t.parent().prev(".view_full_img"));
});
Example
I have a list where need to insert the div for the list item, if use the simple .InsertBefore, will multiply infinitely elements
How can insert the div without duplicating other items?
Example: jsfiddle.net/HJCps
Html Code
<div id="sorter">
<div class="item item-1">
<div class="text">Item 1</div>
<div class="insert">Insert Text 1</div>
</div>
<div class="item item-2">
<div class="text">Item 2</div>
<div class="insert">Insert Text 2</div>
</div>
<div class="item item-3">
<div class="text">Item 3</div>
<div class="insert">Insert Text 3</div>
</div>
</div>
JS Code
$('.insert').insertBefore('.text');
DEMO
$('.item .text').each(function(){
$(this).next('.insert').insertBefore(this);
});
References
.next()
.each
$('.item .text') will find all the elements with class text contained in class item
$('.item .text').each will loop through every matched element one by one.
$(this) refers to the current element.
$(this).next('.insert') will find the next element with the class insert
$(this).next('.insert').insertBefore(this); will insertBefore current element the matched
next element with class insert
your code $('.insert').insertBefore('.text'); will insertBefore all the elements with class insert to all elements with class .text
Something like this might suffice (if I assume your main question right):
$('.insert').each(function() {
$this = $(this);
$this.parent().prepend($this);
});
Fiddle: http://jsfiddle.net/HJCps/1/
I know there are a lot of these threads but none seem to really fit me.
I have 5 dives with text like "this is div1, to div5". These are always gonna be shown.
And i have 5 hidden divs with text belonging to each div, that are gonna show if i click on my shown divs.
If I click div1, i want to show the hidden div1.
Right now I'm using a click function(jQuery) for every div which works but doesn't look very good in code. There has to be a better way. Any advise?
I do NOT want any of the divs to be hyperlinks, which seem to be the solution on a lot of similar threads on here.
EDIT: This is my current code.(can't get jsfiddle to work)
html
<div class="showing_div">
<p>This is a showing div</p>
</div>
<div class="hidden_div" style="display: none;>
<p>This div is hidden</p>
</div>
Jquery
$('showing_div').click(function() {
$('hidden_div').toggle();
})
This are the most used techniques:
target element using .index() and .eq()
<div id="clickables">
<div>CLICK 1</div>
<div>CLICK 2</div>
</div>
<div id="togglables">
<div>text 1</div>
<div>text 2</div>
</div>
$(function(){
$("#clickables div").click(function(){
var idx = $(this).index();
$('#togglables div').eq( idx ).slideToggle();
});
});
Pros: you can keep a really clean HTML markup, no need to assign additional classes or ID
Cons: don't put other elements inside the parents otherwise you might mess the index count
target element using .next() or other jQuery traversal methods
<div id="menu">
<div class="clickable">CLICK 1</div>
<div>text 1</div>
<div class="clickable">CLICK 2</div>
<div>text 2</div>
</div>
$(function(){
$("#menu .clickable").click(function(){
$(this).next('div').slideToggle();
});
});
target specific element using ID
<div class="clickable" id="_1" > CLICK 1 </div>
<div class="clickable" id="_2" > CLICK 2 </div>
<div id="togglable_1"> text 1 </div>
<div id="togglable_2"> text 2 </div>
$(function(){
$(".clickable").click(function(){
$("#togglable"+ this.id).slideToggle();
});
});
Pros: You can target elements unlogically positioned in the DOM
Cons: Verbose HTML; Unflexible and hardly maintainable code.
$('div').click(function() {
var text = $(this).text();
$('#'+text).show();
});
FIDDLE DEMO
As #Roko C. Buljan nicely showed there are many ways of doing it.
This is how I usually do using .data() jQuery function:
<div class="clickable" data-hidden="d1">CLICK 1</div>
<div id="d1" class="hidden">text 1</div>
<div class="clickable" data-hidden="d2">CLICK 2</div>
<div id="d2" class="hidden">text 2</div>
$(".clickable").click(function() {
$("#" + $(this).data("hidden")).toggle();
});
This way it does not matter how I organize my DOM elements. I only need to care to identify the right id in every data-hidden attribute.
Working demo