Resizing one element using jQuery UI changing the position of another - javascript

I am trying to make resizible and draggable lines out of labels using jQuery UI.
The problem is, if I add two labels and try to resize the first label, it changes the position of the second label (but if I resize the second label it does not change the position of the first label).
How to prevent labels from changing other label's position while resizing..?
HTML:
<div id="main">
<button id="s">add line</button>
</div>
<div id="line" class="hidden">
<label class="dra"></label>
</div>
JS:
function makeline() {
$t = $(".dra", "#line").clone(true).draggable().resizable({
handles: "s, n"
});
$("#main").append($t);
}
$("#s").click(function () {
makeline();
});
CSS:
.dra {
display: block;
background-color:red;
width: 7px;
height: 80px;
border: 1px solid red;
}
.hidden {
display: none;
}
#main {
border: 1px solid black;
width:500px;
height: 300px;
}
UPDATE: Full code in JSFiddle

This is happening because the jQuery UI widgets set the position of element to relative by default, leaving it in the normal flow of the document. You can work around this issue by applying position:absolute for the elements like:
.ui-resizable {
position:absolute !important;
}
This will cause them to stack on top of each other rather than one below another since they aren't in the normal flow anymore. You can easily fix this using the jQuery ui position() utility method as shown below:
$("#s").click(function() {
$t = $("#line .dra").clone(true).draggable().resizable({
handles: "s, n"
})
if ($("#main").find(".dra").length) {
$t.position({
at: "left bottom",
of: "#main .dra:last"
})
};
$("#main").append($t);
});
.dra {
display: block;
background-color: red;
width: 7px;
height: 80px;
border: 1px solid red;
}
.hidden {
display: none;
}
#main {
border: 1px solid black;
width: 500px;
height: 300px;
}
.ui-resizable {
position: absolute !important;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<div class="form-group">
<label>ADD two line and RESIZE THE FIRST LINE it will scroll down the line added after it. NOW add a 3rd line and resize the second line it will scroll down the 3rd line and if you resize the very first line you added it will scroll down the other lines</label>
<div id="main">
<button id="s">add line</button>
</div>
<div id="line" class="hidden">
<label class="dra"></label>
</div>
You can adjust the positioning however you want.

If your label is:
<div class="label">Lorem ipsum</div>
add this CSS:
.label {
white-space: nowrap;
}

Related

Is there a way to make SVG className backward compatible?

Many old libraries rely on className to identify their context.
So a click handler can look like this:
function click(event)
{
if (event.target.className.indexOf('something')!= -1){
// Do something
}
}
But this will fail if the target element is an svg element.
The reason is that svg className is an object of type SVGAnimatedString
Is there any temporary workaround to avoid issues with old code?
Change the handler is not an option as it is unclear how many libraries have this code and changing library code could be impossible.
Changing the SVG to some other element is not an option as the SVG is a part of a 3rd party control.
Update:
"Is there any temporary workaround to avoid issues with old code?"
Seems unclear based on the comments. My goal is to see if there is any polyfill or any other technique that I can use to temporarily make SVG elements have their className as string until 3rd party libraries catch up. Then I will update the 3rd party libraries and revert this code.
As of now - simply overwriting the className doesn't seem to be possible as it only seems to have getter and no setter for SVG elements.
function oldModuleHandler(e) {
if (e.className.indexOf("initial") > -1 || e.className.indexOf("fixed") > -1) {
alert('Behaves as expected.');
}
}
function theFix(e) {
e.className = "fixed";
}
<html>
<head>
</head>
<body>
<div style="border:2px solid silver;">
<h2>Demo:</h2>
Click on the left square, it is a div and it will have it's color changed to green because .className.indexOf will go through just fine. Same does not apply for SVG.<br/> <br/><br/>
<div onclick="theFix(this); oldModuleHandler(this)" class="initial">
</div>
<svg class="initial" onclick="theFix(this); oldModuleHandler(this)"></svg>
<div style="clear:both;"></div>
</div>
<style>
.fixed {
background: green !important;
width: 80px;
height: 80px;
float: left;
}
.initial {
background: transparent;
border: 1px solid black;
width: 80px;
height: 80px;
float: left;
}
</style>
</body>
</html>
Update 2
I added a small code to demonstrate the issue. If you click on the left square (it is a div) - it will work just fine. If you click on the right square - the SVG - it will not work because .className.indexOf() will throw an error.
You might use getAttribute and setAttribute OR 'classList methods :
function oldModuleHandler(e) {
var c = e.getAttribute('class');
if (~c.indexOf("initial") || ~c.indexOf("fixed")) {
alert('Behaves as expected.');
}
}
function theFix(e) {
e.className = "fixed";
e.setAttribute('class', 'fixed')
// OR
e.classList.add('fixed')
}
.fixed {
background: green !important;
width: 80px;
height: 80px;
float: left;
}
.initial {
background: transparent;
border: 1px solid black;
width: 80px;
height: 80px;
float: left;
}
<div style="border:2px solid silver;">
<h2>Demo:</h2>
Click on the left square, it is a div and it will have it's color changed to green because .className.indexOf will go through just fine. Same does not apply for SVG.<br/> <br/><br/>
<div onclick="theFix(this); oldModuleHandler(this)" class="initial">
</div>
<svg class="initial" onclick="theFix(this); oldModuleHandler(this)"></svg>
<div style="clear:both;"></div>
</div>
And/Or look at Proxy API.

Scroll smoothly by 100px horizontally

Heyjo,
problem: I am looking for a javascript or jQuery code since a week to get an implemented scrollbutton on my website working. The moment I fail is when the button should work multiple times: his task is not so scroll to a dedicated element, it should scroll left by, for instance, 100px. Furthermore the scrolling is supposed to happen smoothly (in other words, animated) in a proper section.
what I tried: til now I tried to fulfill this task with $('#idofsection').animate({scrollLeft: 100}, 800) but obviously it didn't work. The Problem was, one couldn't use it multiple times, it just scrolled to a position in my section. Afterwards I used javascript's scrollBy(100, 0) or scrollLeft += 100px, but unfortunately didn't got it to scroll smoothly.
I hope someone can help me because I spent so much time on this issue without finding a solution. Thanks a lot, Sven
You can use scrollBy(100, 0) just like you tried and add this css property to the viewport where you want to scroll:
scroll-behavior: smooth;
.window{
width: 200px;
height: 100px;
border: 1px red solid;
overflow: hidden;
scroll-behavior: smooth;
}
.container{
width: 1000px;
height: 200px;
}
.buttons{
width: 200px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
<div id="window" class="window">
<div class="container">
fjsdlf jslkd flsakj flksad jflkjsa dlfj slakd jflskad flksdaj lfk sadlkfj asldk fslkad fjlkasd flksa jdlf jsadlkfj slkda jflksadj flksa jdlkfj sadlk jflksadj flksjadflksadj flksdaj flksdaj flksdaflksjdflk sjdalkfj skdal fjlksadj flksa fklsjadfklj sadklfj salkdjf lksadj flksjad lfkj sadlkf jslakdjf lksdaj flkasj flkjsa dlfskal flsa jdas lkfjskad fj
</div>
</div>
<div class="buttons">
<button onclick="document.getElementById('window').scrollBy(-100,0)">
<-
</button>
<button onclick="document.getElementById('window').scrollBy(100,0)">
->
</button>
</div>
Solution also here: JSFiddle
So use the animation properties += to adjust it from current position.
$("#next").click(function(){
$('#foo').stop().animate({scrollLeft: "+=100"}, 800);
return false;
});
div {
width: 200px;
overflow: auto;
padding: 1em;
border: 1px solid black;
}
div p {
width: 1000px;
border: 2px dashed #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="foo">
<p>TEST</p>
</div>
<button id="next">Next</button>

JQuery Offset issue when div position is fixed

I have a website which has a page layout and style something like mentioned in this JsFiddle
Now Using JQuery when I click on the button, content is being displayed properly as shown below:
But when I first scroll the page and then click the button, content is not displaying properly as shown:
Can you please guide me to handle this situation ?
I have used below jQuery for this. But it seems offset or position is not working
$('#btn').click(function(){
var t = $(this).offset();
console.log(t);
$('.control-container').css('top', t.top + 20 + 'px');
$('.control-container').css('display', 'block');
});
$(document).on('scroll', function(){
$('.control-container').css('display', 'none');
});
You don't need to use offset to achieve that... And if you need to keep CSS with position:fixed, you need to switch it in javascript to static.
The thing you are looking for is simply display:table ...
$('#btn').click(function(){
$('.control-container').css({'display': 'table','position': 'static'});
});
$(document).on('scroll', function(){
$('.control-container').css({'display': 'none','position': 'fixed'});
});
Check out this JSFiddle
But if you really need a solution with position:fixed based on button position, you should try this way:
$('#btn').click(function(){
var button_fixed_position = $('#btn').get(0).getBoundingClientRect();
$('.control-container').css({'display': 'block','left' : button_fixed_position.left, 'top' : button_fixed_position.bottom});
});
$(document).on('scroll', function(){
$('.control-container').css({'display': 'none'});
});
Check out second JSFiddle
There is no need to specifically mention position property here.
Also remove the closing a tag and replace it with </button>
Currently container is occupying full width ,but that can also be set
$('#btn').click(function() {
var t = $(this).offset();
console.log(t);
$('.control-container').css('top', t.top + 30 + 'px');
$('.control-container').css('display', 'block');
});
$(document).on('scroll', function() {
$('.control-container').css('display', 'none');
});
.header {
background-color: maroon;
color: #fafafa;
height: 60px;
position: fixed;
width: 100%;
text-align: center;
line-height: 19px;
font-size: 25px;
z-index: 2;
padding: 0px;
margin: 0px;
top: 0;
}
.content {
background-color: #fff;
border: 1px solid #999;
padding: 5px;
height: 100%;
width: 100%;
position: absolute;
z-index: 1;
top: 60px;
}
.control-container {
width: auto;
background-color: red;
#position: fixed;
color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="header">
Header
</div>
<div style="clear:both">
</div>
<div class="content">
<br/>
<br/>
<br/>
<br/>
<br/>
<button id="btn">Click Me</button>
<div class="control-container" style="display:none;">
Keep me exactly underneath 'Click Me' when Page is scrolled.
</div>
</div>
</div>
CSS position fixed property positions an element referencing view's/body's dimension.
If you have access of modifying CSS, then just remove the position: fixed; property from .control-container.
If you don't have access, then using script add position: static !important property to .control-container.
$('.control-container').css('cssText', 'position: static !important');
Modified JSFiddle

If parent div has no children showing then show a certain different child div

I am seeing simlar questions about hiding parent divs if there is no child but can't find how to show a different div in the parent if no other child is in it.
I have a parent div that is updated with free meeting rooms:
.Parent{
width: 100%;
margin-top: 4px;
overflow: auto;
}
if there is a free room it is display on the board (in the parent). This is done in JS like so:
$('#Parent').addClass("showRooms");
If a room is not free by default it is hidden:
if(roomStatus == "Taken"){
$('#Parent').addClass("hideRooms");
}
The css classes are as so:
.showRooms{
visibility: visible;
background-color: green;
}
.hideRooms{
visibility:hidden;
}
When all the rooms are hidden there is a blank board, I would like to show a different child div in the parent so I can show something more interesting e.g. the company logo.
(I am aware I could have the compnay logo on the parent even if there are rooms showing but I only want it to show if there are no rooms free)
What can I use to achieve this?
Yes!
I've came up with a pure CSS solution, because combining selectors is awesome:
Consider the following setup:
.container {
margin: 10px;
border: 1px solid #000;
}
.room {
width: 100px;
height: 75px;
background-color: #F00;
}
.hidden {
display: none;
}
.placeholder {
display: block;
}
.room:not(.hidden) ~ .placeholder {
display: none;
}
<div class="container">
<div class="room hidden"></div>
<div class="room hidden"></div>
<div class="room hidden"></div>
<div class="room hidden"></div>
<div class="placeholder">No rooms available!</div>
</div>
<div class="container">
<div class="room hidden"></div>
<div class="room"></div>
<div class="room"></div>
<div class="room hidden"></div>
<div class="placeholder">No rooms available!</div>
</div>
Now the magic lies in the following lines:
.room:not(.hidden) ~ .placeholder {
display: none;
}
Explanation:
Take a placeholder, who is a sibling of a .room that does not contain the .hidden class. The placeholder is visible by default, but if it can find a sibling that has a .room without .hidden, it will fall back into display none.
Take note, this requires the placeholder div to always be the last child of it's parent. Since the ~ selector only checks for next siblings, not previous.
I would go something like :
if(allRoomStatusAreTaken()){
$('#Parent').addClass("showLogo");
} else {
$('#Parent').removeClass("showLogo");
}
And
.showLogo{
visibility: visible;
background-image: url(...);
}
In allRoomStatusAreTaken() you have to check if all rooms are taken. I would use a function like every from Lodash :
function allRoomStatusAreTaken() {
return every(allRooms, room => room.status === "Taken");
}
You could hide the logo by default, and change the display using js if the rooms are hidden. Example:
$(function() {
var roomStatus = "Taken";
if (roomStatus == "Taken") {
$('#Parent').addClass("hideRooms");
$('.logo').addClass('show');
}
})
.Parent {
width: 100%;
margin-top: 4px;
overflow: auto;
}
.showRooms {
visibility: visible;
background-color: green;
}
.hideRooms {
visibility: hidden;
}
.logo {
display: none;
width: 200px;
height: 200px;
background: red;
}
.logo.show {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Parent">
<div class="logo">
</div>
</div>
Just Keep the Logo div with class 'companyLogo' inside parent and use the following CSS and will work.
.hideRooms .companyLogo{
visibility:visible;
}
.showRooms .companyLogo{
visibility:hidden;
}
For more specific answer please provide HTML structure.
When the parent is free you have to use append to add anything you want to the parent
if(roomStatus == "Taken"){
$('#Parent').addClass("hideRooms");
$("#Parent").append("<span>somthing to show</span>");
}
You can have a logo wrapped in some div (or anything else, or you can add a class to the logo image, really anything), which will have a 'hidden' class by default which will hide it and then you can also show this whet you have no rooms, something like:
if(roomStatus == "Taken") {
$('#Parent').addClass("hideRooms");
$('.logo').addclass("visible");
$('.logo').removeClass("hidden");
} else {
$('#Parent').addClass("showRooms");
$('.logo').removeClass("visible");
$('.logo').addClass("hidden");
}
```

expand div on click Polymer js without jquery

I'm using Polymer but I'm having some trouble with events and the such. I want to create an expanding search bar, similar to
My current code looks something like the following:
Code:
// This is where things are a little unclear for me. So far, I have tried the following:
expand: function() {
var divToStretch = this.$.stretchMe;
if ( /*search bar is open*/ ) {
//remove "stretched" css from "stretch" div
} else {
//add "stretched" css to "stretch" div
}
}
div.stretch {
border: 1px solid black;
width: 25px;
height: 25px;
border-radius: 25px;
transition: width 1s;
}
.stretched {
width: 500px;
}
<div class="stretch" id="stretchMe">
<iron-icon class="search" icon="search" on-click="expand"></iron-icon>
</div>
May I suggest a pure CSS alternative? You can make your search bar receive focus, by adding tabIndex="0". This way you can provide a style for div.stretch:focus, allowing you to dynamically change its size when the user clicks or focuses on the element and making it small again when the user focuses on something else.
It's really simple, elegant, does not need a lot of code and does what you need. Give it a try!
div.stretch {
border: 1px solid black;
width: 25px;
height: 25px;
border-radius: 25px;
transition: width 1s;
}
div.stretch:focus {
width: 500px;
}
<div class="stretch" id="stretchMe" tabIndex="0">
<iron-icon class="search" icon="search" on-click="expand"></iron-icon>
</div>
Alternatively, you can make it do the same thing on :hover, if that's what you are after, simply by changing the selector. Or combine both, if you prefer. Below is a :hover example.
div.stretch {
border: 1px solid black;
width: 25px;
height: 25px;
border-radius: 25px;
transition: width 1s;
}
div.stretch:hover {
width: 500px;
}
<div class="stretch" id="stretchMe">
<iron-icon class="search" icon="search" on-click="expand"></iron-icon>
</div>
You can use the toggle method of the classList for this:
expand : function() {
this.$.stretchMe.classList.toggle('stretched');
}
The classic way would be as following:
if (/*search bar is open*/) {
divToStretch.style.width = "auto";
} else {
divToStretch.style.width = "500px";
}
But I highly recommend using this.$.stretchMe.classList.toggle('stretched');
Read more here

Categories