Not run script if window's width is smaller than value - javascript

I have a responsive website, with some jQuery code, of which some is the following:
<script>
$(document).ready(function(){
$("#D1000C36LPB3").click(function(){$("#D1000C36LPB3_details").show();});
$("#D1200C36LPB3").click(function(){$("#D1200C36LPB3_details").show();});
$("#D1-3CA36LPB3").click(function(){$("#D1-3CA36LPB3_details").show();});
$("#D1-0CA36LPB3").click(function(){$("#D1-0CA36LPB3_details").show();});
$("#D700S36LPB3").click(function(){$("#D700S36LPB3_details").show();});
$("#D700S24LMB3").click(function(){$("#D700S24LMB3_details").show();});
});
</script>
All of the div elements above (#D1000C36LPB3_details, #D1200C36LPB3_details, #D1-3CA36LPB3_details...) have a CSS display property value of none, so by default they aren't visible until you click on one of the div elements above (#D1000C36LPB3, #D1200C36LPB3, #D1-3CA36LPB3...) and then the corresponding div is displayed.
However, when the jQuery script runs, it sets the corresponding div display value to block. When the viewport's/window's width is smaller than say 400 px, I want the script to display them with position: fixed;.
My suggestion
I've figured out I can display them with fixed position using:
$("#corresponding_ID").css("display", "fixed");
But I still have to not let jQuery run the first script (the one using .show()).

Don't set css styles directly this way. As already commented, use e.g. a .visible class and let css media queries decide. Example:
#media screen and (max-width: 399px) {
.visible {
display: fixed;
}
}
#media screen and (min-width: 400px) {
.visible {
display: block;
}
}
Then, in your click handler, go as follows:
$("#D1000C36LPB3").click(function(){$("#D1000C36LPB3_details").addClass('visible');});
Also, if your details containers all follow that naming scheme with affixing _details to the id, it'd be easier to put all ids in an array and iterate over that:
$(document).ready(function(){
var ids = [ "#D1000C36LPB3", "#D1200C36LPB3", "#D1-3CA36LPB3", "#D1-0CA36LPB3", "#D700S36LPB3", "#D700S24LMB3"];
for (var i = 0; i < ids.length; i++) {
$(ids[i]).on('click', function () { $(ids[i]+'_details').addClass('visible'); }
}
};

Easy way to check for browser width with Jquery:
var width = $(window).width();
if (width >= 1024) {
-- Code to execute here --
}else{
-- Other code to execute here --
}
Then you can adjust the width you are looking and update the >= based on what you want to do.
Let me know if this doesn't make sense.

Related

JavaScript on click change width by class

If I click a button I can assign it a function like bellow
document.getElementById("mySidenav").style.width = "250";
This works fine, however I wish do give it a different width for different screen sizes so I was going to set the width in a class so that i can use a css media query.
instead of .style.width = "250";how can I tell it to take the values of a CSS class instead ?>
Just for reference, CSS names cannot start with digits, per the W3C spec. Your edited post removes the need for this comment but it's worth noting.
To manipulate classes via JavaScript, either use className (as in myElement.className = 'some-class') or the classList interface. However, you specifically mentioned "different screen sizes" and this is a prime candidate for responsive CSS queries using the #media selector.
With all that being said:
JavaScript example
// CSS
#mySidenav {
width: 1000px;
}
#mySidenav.responsive-class {
width: 500px;
}
// JS
const mySidenav = document.querySelector('#mySidenav');
window.addEventListener('resize', function() {
if (window.innerWidth < 200) {
mySidenav.classList.add('responsive-class');
}
else {
mySidenav.classList.remove('responsive-class');
}
});
CSS example
#mySidenav {
width: 1000px;
}
#media query and (max-width: 200px) {
#mySidenav {
width: 500px;
}
}
As you can see, the latter example is much simpler. Go with the CSS approach. A halo will appear over you.
I used #Shenh's answer to work out a solution +1 Sheng.
Please see bellow I added new class and removed class
function openNav() {
document.getElementById("mySidenav").classList.add('popoutwidth');
}
function closeNav() {
document.getElementById("mySidenav").classList.remove('popoutwidth');
}

element css follows jquery declaration, not stylesheet

I have this initially in my .css stylesheet:
#media only screen and (min-width: 901px){
#main_panel {
width: 750px;
}
}
#media only screen and (min-width: 300px) and (max-width: 900px), handheld {
#main_panel {
width: 500px;
}
}
And then after some user interaction, this jQuery command changes this CSS-value:
$("#collapse").click(function() {
if ((($(window).width()) >= 600) && ($(window).width() <= 900)) {
$("#main_panel").animate({width: "500px"}, 'slow');
}
});
When I resize the window to more than 901px, it still follows the recent declaration by the jQuery and not the CSS-declaration in the stylesheet for 901px.
How to prioritize CSS-declaration when resizing the window?
Or how do you handle this better?
Please don't make me rely to $(window).resize() event forever :) That disregards the CSS.
** EDIT **
If you want to give priority to the CSS and still be able to animate it, what you probably need is this:
http://jsfiddle.net/2Fe22/1/
1) create a "normal" panel class and style it
.panel {width:750px;height:400px}
2) create a collapsed class and style it
.collapsed {width:500px}
3) create a function to read the collapsed and normal widths from the css:
function getClassWidth(aClass) {
return parseInt($("<div />").addClass(aClass).css('width'));
}
4) handle the click by first animating and then (at the end of the animation) add or remove the "collapsed" class to the panel and removing inline styles left by the animation:
var collapsed=false;
$("#collapse").click(function() {
collapsed=!collapsed;
if(collapsed) {
$("#main_panel").animate({width: (getClassWidth('collapsed'))+"px"}, 'slow',afterAnimation);
} else {
$("#main_panel").animate({width: (getClassWidth('panel'))+"px"}, 'slow',afterAnimation);
}
});
function afterAnimation() {
if(collapsed) $("#main_panel").addClass( "collapsed" ).removeAttr("style");
else $("#main_panel").removeClass( "collapsed" ).removeAttr("style");
}
You do this, so if the user resizes the window and the css changes your screen updates correctly.
** OLD POST (for reference) **
If you set sizes with JQuery you may go on setting them this way:
var collapsed=false;
$( window ).resize(calculateNewSizes); // When resized
calculateNewSizes(); // At startup
function calculateNewSizes() {
if(collapsed) {
// if screen width < xxx set elemt width to yyy, etc.. collapsed version
} else {
// if screen width < xxx set elemt width to yyy, etc..
}
}
// This toggles the collapsed state if user clicks on an element
$("#collapse").click(function() {
collapsed=!collapsed;
calculateNewSizes(); // or do the animation here
});
This script should be called as fast as possible after the beginning of all the elements to be resized to avoid a FOUC.
<div class="to be resized">
<script>
//do the $( window ).resize(...) here
</script>
... all other stuff </div>.
Warning, this code is UNTESTED. It is just to show an idea.
Since you are using jQuery Animate, the element style will directly receive width value.
Like this:
<el id="mainpanel" style="width: 500px">
This will always override any css on the element unless you use !IMPORTANT:
width: 100px !IMPORTANT;
http://codepen.io/rafaelcastrocouto/pen/suEHn (DEMO)
Notice that you should avoid that since you won't be able to change this if you need.

The size (width) of text in different browsers

I need to fit text in div box with exact width.
Is there a way (for example with javascript) to make the text look the same size in all major browsers?
For example strip some letters if text does not fit 'div' box.
Just add the following properties to the CSS rule for your div:
overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
You can see this in action here (JSFiddle).
First of, set your font face and size with css. Then you will almost always have the same width.
Then you can add overflow: hidden; to your div so it won't show anything that goes past the end.
Depending on how you're doing this, you could use padding and margins without setting a width, that way it will always fit in the div. Although this may not be what you want.
You can truncate your text with CSS or with JavaScript. Here's an example of a simple JQuery truncation plugin I wrote which allows for a "show more" link if the text is truncated:
$.fn.trunc = function(_break_at) {
var _article = jQuery(this).text();
var _leader = [];
var _trailer = [];
var _substr = _article.split(' ');
$(this).wrapInner('<div class="long"></div>');
$.each(_substr, function(i, data) {
if (i < _break_at) {
_leader.push(data);
}
});
if (_substr.length > _break_at) {
$('<div/>').addClass('short').html(_leader.join(' ')).prependTo(this);
$('<span/>').appendTo('.long').addClass('toggle').html(' << Show less');
$('<span/>').appendTo('.short').addClass('toggle').html('... Show more >>');
}
$('.toggle').click(function() {
$('.short, .long').toggle('show');
});
};
$(function() {
// This is how you use it
$('#article_body').trunc(2);
});
http://jsfiddle.net/AlienWebguy/7ZamJ

CSS: Suppressing negative margins of child elements

I have a parent element (e.g. a div) which surrounds some dynamic content. I would like the parent div to fully contain the child elements in as many circumstances as possible.
One problem is child elements with negative margin settings, which cause the child element to be displayed outside of the parent element (and also cause the parent element not to be of the desired size).
So
Is there any css trick that can be applied to the parent in order to suppress the negative margins in the child elements (e.g. without having to modify the styles on the child).
Failing that, is there anyway to detect via javascript whether a particular element has overflowing content? (and in which direction and to what degree the content is overflowing?)
Did you try to put a class to the parent like:
.parentDiv > * {
margin:0 !important;
}
To have the parent with the desired height, you need to set some css too:
.parentDiv{
overflow:hidden;
position:relative;
background:#DFE;
padding:5px;
}
There is a javascript method of handling this, but it's certainly not as clean as #Mic's CSS solution. I haven't completely tested this, and you may need to add some support for various padding/margin adjustments, but it would get somebody started if a JS-solution was the only option. Using prototype.js (jquery would be similar, but plain javascript will be very.. stretchy):
function checkOverflow (child) {
child = $(child);
if (child.descendants().any()) {
child.getElementsBySelector("> *").each(function(e) {
checkOverflow(e);
});
}
var parent = child.up();
var child_left = child.cumulativeOffset()['left'], child_top = child.cumulativeOffset()['top'];
var child_height = child.getDimensions()['height'], child_width = child.getDimensions()['width'];
var parent_left = parent.cumulativeOffset()['left'], parent_top = parent.cumulativeOffset()['top'];
var parent_height = parent.getDimensions()['height'], parent_width = parent.getDimensions()['width'];
if (child_top < parent_top) {
if (child_left < parent_left) {
// adjust element style here
} else if (child_left > parent_left + parent_width) {
// adjust element style here
}
} else if (child_top > parent_top + parent_height) {
if (child_left < parent_left) {
// adjust element style here
} else if (child_left > parent_left + parent_width) {
// adjust element style here
}
}
}
My general feeling, though, is that you should only do this if it can't be explicitly done through CSS.

Need to find height of hidden div on page (set to display:none)

I need to measure the offsetHeight of a div that is inside of a hidden element.
<div id="parent" style="display: none;">
<div id="child">Lorem Ipsum dolor sit amet.</div>
</div>
The parent div must be set to "display:none". I have no control over that. I realize that the offsetHeight of the child div is going to be 0. I need to find a workaround.
Something I've toyed with is when the page loads, I copy the childnodes of parent, inject in a div on the page that is set to "visiblity:hidden". Then I measure the height of those elements, and remove the nodes when done.
Any other thoughts?
Update:
What I wound up having to do was this:
Using YUI 2, on page load, I found all elements of that given classname that were either set to display:none, or whose height and width was 0 (that's one way of measuring whether an element exists, or a parent is set to display:none). I then set that element to display:block. I then checked it's parent for the same thing and showed the parents until it finds a visible parent. Once highest display:none ancestor is set to display:block, I can measure my element.
Once all elements are measured I reset all of the elements back to display:none.
You need to make element's parent visible for that one very short moment while you're getting element's dimensions. In a generic solution, all ancestors are usually traversed and are made visible. Then their display values are set back to original ones.
There are performance concerns of course.
We considered this approach in Prototype.js implementation but ended up with getWidth and getHeight making only actual element visible, without traversing ancestors.
The problem with alternative solutions - such as taking element out of "hidden" parent - is that certain styles might no longer apply to an element once it's out of its "regular" hierarchy. If you have a structure like this:
<div class="foo" style="display:none;">
<div class="bar">...</div>
</div>
and these rules:
.bar { width: 10em; }
.foo .bar { width: 15em; }
then taking element out of its parent will actually result in wrong dimensions.
If you use style.display = "none", the element will have 0 width and height,
but using the style.visibility = "hidden" instead, the element will have the width and height calculated by the browser (as normally).
A workaround is to set the height to 0
.hidden {
height: 0;
overflow: hidden;
}
Then to get the elements scrollHeight.
document.querySelector('.hidden').scrollHeight
The scrollHeight will correctly give you the height though the element does not appear. I don't think it affects element flow either.
Example: https://jsfiddle.net/de3vk8p4/7/
Reference: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements#How_big_is_the_content.3F
You could clone the element, absolutely position it at -10000,-10000, measure the clone and destroy it.
Made a pure js solution with no Jquery and with no cloning (which I guess is faster)
var getHeight = function(el) {
var el_style = window.getComputedStyle(el),
el_display = el_style.display,
el_position = el_style.position,
el_visibility = el_style.visibility,
el_max_height = el_style.maxHeight.replace('px', '').replace('%', ''),
wanted_height = 0;
// if its not hidden we just return normal height
if(el_display !== 'none' && el_max_height !== '0') {
return el.offsetHeight;
}
// the element is hidden so:
// making the el block so we can meassure its height but still be hidden
el.style.position = 'absolute';
el.style.visibility = 'hidden';
el.style.display = 'block';
wanted_height = el.offsetHeight;
// reverting to the original values
el.style.display = el_display;
el.style.position = el_position;
el.style.visibility = el_visibility;
return wanted_height;
}
here is the demo
https://jsfiddle.net/xuumzf9k/1/
Please let me know if you can find any improvements to this (as I use this in my main projects)
So here's working jQuery solution based on lod3n's answer and with help of 999's comment:
var getHiddenElementHeight = function(element){
var tempId = 'tmp-'+Math.floor(Math.random()*99999);//generating unique id just in case
$(element).clone()
.css('position','absolute')
.css('height','auto').css('width','1000px')
//inject right into parent element so all the css applies (yes, i know, except the :first-child and other pseudo stuff..
.appendTo($(element).parent())
.css('left','-10000em')
.addClass(tempId).show()
h = $('.'+tempId).height()
$('.'+tempId).remove()
return h;
}
Enjoy!
A helper function ---
function getElementHeight(el) {
var clone = el.cloneNode(true);
var width = el.getBoundingClientRect().width;
clone.style.cssText = 'position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset; width: ' + width + 'px';
document.body.append(clone);
var height = clone.getBoundingClientRect().height + 'px';
clone.remove();
return height;
}
Creates a clone, appends it to the DOM (hidden), takes the height, then removes it.
Position of fixed and the top/left are in case your app allows scrolling at the body-level - it attempts to prevent a scrollbar rave party - can remove if you handle scrolling in children elements.
Overflow, height, and max-height settings to attempt to 'reset' height settings and let it be it's natural height on the clone.
Visibility for the obvious and pointer-events as a 'just in case' the rendering of the element takes a while and don't want to interrupt user-input.
An example having an 'accordion-like' animated open/close allowing for dynamic heights.
function getElementHeight(el) {
var clone = el.cloneNode(true);
clone.style.cssText = 'position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset';
document.body.append(clone);
var height = clone.getBoundingClientRect().height + 'px';
clone.remove();
return height;
}
var expanded = false;
var timeout;
function toggle() {
var el = document.getElementById('example');
expanded = !expanded;
if (expanded) {
el.style.maxHeight = getElementHeight(el);
// Remove max-height setting to allow dynamic height after it's shown
clearTimeout(timeout);
var openTimeout = timeout = setTimeout(function() {
el.style.maxHeight = 'unset';
clearTimeout(openTimeout);
}, 1000); // Match transition
} else {
// Set max height to current height for something to animate from
el.style.maxHeight = getElementHeight(el);
// Let DOM element update max-height, then set to 0 for animated close
clearTimeout(timeout);
var closeTimeout = timeout = setTimeout(function() {
el.style.maxHeight = 0;
clearTimeout(closeTimeout);
}, 1);
}
}
#example {
overflow: hidden;
max-height: 0;
transition: max-height 1s;
}
<button onclick="toggle()">Toggle</button>
<div id="example">
<textarea>Resize me</textarea>
</div>
In the JS please use 'scrollHeight'
Example Code
Assume that this div is hidden in DOM
<div class="test-div">
//Some contents
<div>
Javascript to find this div height
const testHeight = document.querySelector('.test-div');
testHeight.scrollHeight
Use z-index to hide element under non-transparent element, show it, and get height.
Until the element is rendered, it has no height. Even if you clone the parent object and display it somewhere that can't be seen by the user, there's not guarantee that the clone will have the same height as the final size of the hidden object.
There are many things that can affect the height that wouldn't necessarily be rendered in the clone - anything in the DOM and its interaction with the CSS rules could cause a change in rendering any other element of the DOM. Short of cloning the entire document (and even that's not fool-proof) you have no way of determining the height of the hidden object.
If you must know the height before it's displayed to the user, you'll have to "hack" it by displaying it for as short of a time as possible then hiding it again. Most likely, the user will see this hiccup and not be pleased by the result.
So, you cannot even change the display:none; to height:0; overflow:hidden; ? Maybe you could override that in your own stylesheet like so:
div#parent { display: block !important; height:0; overflow:hidden; }
And then as you are using YUI (assuming YUI 2) you could use this:
var region = YAHOO.util.Dom.getRegion('child');
To get the dimensions and offset of the child.
Try to use:
#parent{ display:block !important; visibility:hidden; position:absolute}
What I wound up having to do was this:
Using YUI 2, on page load, I found all elements of that given classname that were either set to display:none, or whose height and width was 0 (that's one way of measuring whether an element exists, or a parent is set to display:none). I then set that element to display:block. I then checked it's parent for the same thing and showed the parents until it finds a visible parent. Once highest display:none ancestor is set to display:block, I can measure my element.
Once all elements are measured I reset all of the elements back to display:none.
Did you try this ?
setTimeout('alert($(".Var").height());',200);

Categories