How do I stop a "fixed" element using following code? - javascript

For my current project I want to make a sort of fixed element in my DOM.
I am not using position: fixed because the element will lose its existence within the DOM and thus its original position (which in my opinion only makes things look worse). I made the element behave like a fixed element by just adding/removing margin-top: somevalue to the scrollable element, everytime when the user scrolls and the code I use was made possible within the JavaScript. Using this method also adds a nice looking animation to this whole "interaction".
The problem I am experiencing is that when the (browser) window has such a small height, that the element will reach for the footer, it will expand the container, body or whatever parent is on it. How do I prevent this from happening?
I made a JSFiddle per example of this issue.
$(document).ready(function() {
var topPadding = 10;
//Set the scrollable offset before starting the scroll
var scrollableTopOffset = $(".scrollable").offset().top;
$(window).scroll(function() {
/* When scrolling, determine wether the browser window still contains
scrollable: */
if (scrollableTopOffset < $(window).scrollTop()) {
//Code when scrollable is within the browser window...
//$(".shopping-cart").addClass("scrollable-fixed");
$(".scrollable").stop().animate({
marginTop: $(window).scrollTop() - scrollableTopOffset + topPadding
});
} else {
//Code when scrollable is not within the browser window...
//$(".shopping-cart").removeClass("scrollable-fixed");
$(".scrollable").stop().animate({
marginTop: 0
});
}
});
});
.some-content-block {
height: 150px;
margin-bottom: 5px;
background-color: red;
}
.scrollable {
height: 75px;
background-color: cyan;
}
footer {
height: 200px;
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div class="container" style="background-color: blue;">
<div class="row">
<div class="col-md-12">
<div class="some-content-block">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-10 col-sm-10 col-md-10">
<div class="col-md-4">
<div class="some-content-block">
</div>
</div>
<div class="col-md-4">
<div class="some-content-block">
</div>
</div>
<div class="col-md-4">
<div class="some-content-block">
</div>
</div>
<div class="col-md-4">
<div class="some-content-block">
</div>
</div>
<div class="col-md-4">
<div class="some-content-block">
</div>
</div>
<div class="col-md-4">
<div class="some-content-block">
</div>
</div>
<div class="col-md-4">
<div class="some-content-block">
</div>
</div>
</div>
<div class="col-xs-2 col-sm-2 col-md-2">
<div class="scrollable">
</div>
</div>
</div>
</div>
<footer></footer>
Edit: Here is my fiddle updated with the answer of SamGhatak: JSFiddle

I think I found a solution here:
https://jsfiddle.net/rv4mg8uq/2/
Added this code there:
if(($('footer').offset().top -scrollableTopOffset +topPadding)<$(window).scrollTop()){
//do nothing
}

Related

Change the Page layout when a button is clicked

I want to change the layout of a page that has 3 columns:
<div>
<div class="container">
<div class="row" >
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
</div>
... to 4 columns when a button is clicked:
<div>
<div class="container">
<div class="row" >
<div class="col-md-3"></div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
</div>
</div>
</div>
I have no clue on how to do this.
There are many ways you can add another div. Here is my approach :
function appendDiv(){
let row = document.getElementsByClassName('row');
// change className for all the col-md-4 div
document.querySelectorAll('.col-md-4').forEach(function(item) {
item.className = 'col-md-3';
})
//create new div;
let col = document.createElement('div');
// add classname to div
col.className = "col-md-3"
row[0].appendChild(col)
}
.col-md-4{
border : 1px solid blue;
height : 20px;
}
.col-md-3{
border : 1px solid green;
height : 20px;
}
<div>
<div class="container">
<div class="row" >
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
<button onClick='appendDiv()'>click</button>
</div>
</div>
There's a few ways this could be done depending on your data, however, here's one angle.
If you have both your 4 column & 3 column versions of the data loaded on the page (but one hidden with css). You could run something like this.
HTML
<div id="colsThree" class="displayArea show">
<div class="container">
<div class="row" >
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
</div>
<div id="colsFour" class="displayArea">
<div class="container">
<div class="row" >
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
</div>
<button id="changeColumns">Click Me To Change Columns</button>
Javascript
const buttonEl = document.querySelector("#changeColumns");
buttonEl.addEventListener('click', () => {
const outputEls = document.querySelectorAll('.displayArea')
outputEls.forEach((outputEl) => {
outputEl.toggle("show")
})
});
CSS
.displayArea {
display: none;
}
.displayArea.show {
display: block;
}
Use forEach and appendChild method.
const btn = document.querySelector('#btn')
btn.onclick = function() {
const targetClasses = document.querySelectorAll('.col-md-4')
targetClasses.forEach((tag, idx) => {
tag.className = 'col-md-3'
const lastIdx = targetClasses.length - 1
if (idx === lastIdx) {
const tag = document.createElement('div')
, row = document.querySelector('.row')
tag.className = 'col-md-3'
tag.innerText = '4'
row.appendChild(tag)
}
})
console.log(targetClasses)
return
}
<div>
<button id="btn">Click me</button>
<div class="container">
<div class="row" >
<div class="col-md-4">1</div>
<div class="col-md-4">2</div>
<div class="col-md-4">3</div>
</div>
</div>
</div>
If you're only using vanilla HTML, CSS, and JavaScript, then one of the ways to achieve this is by adding a click listener to the button beforehand. FYI: for brevity's sake, I'll call the div element with row class as parent. When user clicks the button, then it should
remove col-md-4 class and add col-md-3 class to all the children elements of parent.
add a new div element with col-md-3 class into parent.
Here's a link to the codepen for your reference.
const button = document.querySelector('button');
const rowDiv = document.querySelector('.row');
button.addEventListener('click', (e) => {
Array.from(rowDiv.children).forEach(childDiv => {
childDiv.classList.remove('col-md-4');
childDiv.classList.add('col-md-3');
});
const newDiv = document.createElement('div');
newDiv.classList.add('col-md-3');
rowDiv.appendChild(newDiv);
// I disabled the button to prevent the user
// from clicking it the second time.
e.target.disabled = true;
});
.button-parent {
margin: 15px 0;
}
.row {
height: 100vh;
}
.row > div:nth-child(1) {
background: red;
}
.row > div:nth-child(2) {
background: blue;
}
.row > div:nth-child(3) {
background: yellow;
}
.row > div:nth-child(4) {
background: green;
}
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
<div>
<div class="container">
<div class="button-parent">
<button class="btn btn-primary">Add div</button>
</div>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
</div>
</body>

Stacking and placing draggable elements on top without affecting others?

I'm fooling around with draggable elements and found myself stuck on the stacking part.
I have three windows that are draggable and when clicked the specific element stacks on top the other two. However the stacking order seem to be "reset" on the other two when a window is clicked. For example if I click on .window1 and .window2 is in the back it ends up on top of .window3.
I'm using javascript with a onmouse z-index property for the stacking. Is there a way to make only the clicked element stack on top without affecting the other two? Any help or pointing in the right direction is welcome, cheers!
HTML:
<div class="window1">
<div class="header">header</div>
<div class="content">content</div>
</div>
<div class="window2">
<div class="header">header</div>
<div class="content">content</div>
</div>
<div class="window3">
<div class="header">header</div>
<div class="content">content</div>
</div>
My javascript for drag and z-index for stacking:
$( ".window1, .window2, .window3" ).draggable({ handle: ".header" });
$('.window1, .window2, .window3').on('mousedown', function(event) {
$('.window1, .window2, .window3').css('z-index','1');
$( this ).css('z-index','1000');
});
Use the Stack option to bring the current dragged item to the front without affecting the other items:
$( ".window1, .window2, .window3" ).draggable({ handle: ".header", stack: ".window" });
.window1 {
background-color: orange;
width: 100px;
}
.window2 {
background-color: lightgreen;
width: 100px;
}
.window3 {
background-color: yellow;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="window window1">
<div class="header">header</div>
<div class="content">content</div>
</div>
<div class="window window2">
<div class="header">header</div>
<div class="content">content</div>
</div>
<div class="window window3">
<div class="header">header</div>
<div class="content">content</div>
</div>

Why jquery height and javascript height returns 0?

I have a visible div on screen, but when I gets its height, it always returns 0. How it is possible? I have tried many jquery and javascript methods to get hight but it returns 0. This is my div:
<div class="option-content">
<div class="row">
<div class="col-sm-12">
<div class="dropDownStyling" id="filterDropdowns">
</div>
</div>
</div>
<!-- Other contents -->
</div>
I have tried following methods to get height:
var $element = $("#filterDropdowns");
$element.css("height")
$element.height()
$element.innerHeight()
$element.outerHeight()
Also I tried javascript:
document.getElementById('filterDropdowns').offsetHeight
document.getElementById('filterDropdowns').clientHeight
But in all cases, it returns 0 while it returns the width value. Then why height value gets 0?
if you use blank DIV without any content than you will always get 0 height.
For Example :
<div id="demo" class="text">
<div id="abc">
</div>
</div>
so you must add content in DIV
Second way to get height of DIV you can use clientHeight.
document.getElementById("xxx").clientHeight;
create one function & Call after DOM ready
function test () {
var height = $('#filterDropdowns').innerHeight();
alert(height)
}
$(document).ready(function(){
$('#filterDropdowns').append('23');
test();
})
<div class="option-content">
<div class="row">
<div class="col-sm-12">
<div class="dropDownStyling" id="filterDropdowns">
</div>
</div>
</div>
//Other contents
</div>
https://jsfiddle.net/azL0070r/3/
HTML
<div class="option-content">
<div class="row">
<div class="col-sm-12">
<div class="dropDownStyling" id="filterDropdowns">
</div>
</div>
</div>
Javascript
var height = $('#filterDropdowns').height();
alert(height)<br>
CSS
#filterDropdowns {
height: 150px;
}

With jQuery 'draggable', the text wraps for some reason when colliding with container. Why? and how to fix?

I'm trying to design a page where there is a task list on the left and many boxes (one for each employee) on the right so I can dispatch all the tasks quickly.
I don't know if it is relevant, but I use Bootstrap. Here is my list's markup :
<div class="col-md-3">
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">Tasks</div>
</div>
<div class="panel-body panel-body-table">
<div id="Unassigned_1" style="margin-left:0px">Task 1</div>
<div id="Unassigned_4" style="margin-left:10px">Task 1.1</div>
<div id="Unassigned_8" style="margin-left:20px">Task 1.1.1 Some long name so I can test</div>
<div id="Unassigned_9" style="margin-left:20px">Task 1.1.2</div>
<div id="Unassigned_5" style="margin-left:10px">Task 1.2</div>
<div id="Unassigned_8" style="margin-left:20px">Task 1.2.1</div>
<div id="Unassigned_9" style="margin-left:20px">Task 1.2.2</div>
<div id="Unassigned_2" style="margin-left:0px">Task 2</div>
<div id="Unassigned_3" style="margin-left:0px">Task 3</div>
<div id="Unassigned_6" style="margin-left:10px">Task 3.1</div>
<div id="Unassigned_7" style="margin-left:10px">Task 3.2</div>
</div>
</div>
</div>
And here's the javascript (I'm just begining this page, so the 'drop' code is not there yet)
<script>
$(document).ready(function() {
$('div[id^="Unassigned_"]').draggable({ helper: 'clone', containment: '.page-content-wrap' });
});
</script>
For some reason I don't know, if I drag any task (such as the one with the long name) to the right, the text wraps when it "hits" the right border of the panel, then when I pass the border with the cursor, the item follows, but it is still wrapped.
Does anyone know why it does that? Is there a way to fix it?
Thanks a lot
You can fix a width of the dragging element using classes .ui-draggable.ui-draggable-dragging
.ui-draggable.ui-draggable-dragging {
width: 100%;
border: 1px solid #eee;
padding: 5px;
color: #888;
}
Fiddle demo

How can I reorder vertical columns in Bootstrap?

I wan to know if it's possible to re-order vertical columns on Bootstrap 3.
.col-xs-8 {
background: magenta;
}
.col-xs-4 {
background: cyan;
}
.col-xs-12 {
background: yellow;
}
<div class="container">
<div class="row">
<div class="col-xs-8">Content</div>
<div class="col-xs-4">
<div class="row">
<div class="col-xs-12 col-xs-push-12">A</div>
<div class="col-xs-12">B</div>
<div class="col-xs-12">C</div>
<div class="col-xs-12">D</div>
</div>
</div>
</div>
</div>
JSFiddle
What I want it's to move the items on the sidebar from ABCD to BCAD
What you want to achieve can not be done for responsive layout.....but assuming you have static content then, it can be done using margins :
Here is a demo
Wrap your ordering divs in some parent div and apply responsive layout to it....in the demo, i have dome that through abcd class ( its not responsive though since its in pixels)
HTML
<div class="abcd">
<div class="col-xs-12 " style="margin-top:-110px;color:#000">A</div>
<div class="col-xs-12" style="margin-top:-150px;color:#000">B</div>
<div class="col-xs-12" style="margin-top:-130px;color:#000">C</div>
<div class="col-xs-12" style="margin-top:-90px;color:#000">D</div>
<div>
EDIT :
demo with percentage value
In %ge, you can vreate something like :
<div class="abcd">
<div class="col-xs-12" style="margin-top:-13%;color:#000;">A</div>
<div class="col-xs-12" style="margin-top:-33%;color:#000">B</div>
<div class="col-xs-12" style="margin-top:-23%;color:#000">C</div>
<div class="col-xs-12" style="margin-top:-3%;color:#000">D</div>
<div>
CSS
.abcd {
margin-top:33%;/* keep this equal to margin of B, but with opposite sign */
}
Assuming you have to insert first child just before the last child.
You can do it with jquery. See Demo
$( ".flexbox div:first" ).append().insertBefore( ".flexbox div:last" );

Categories

Resources