Sticky headers not maintaining width when scrolling - javascript

I have some table headers which I planned on making sticky (fixed) as the user scrolls down the page, but they currently shrink when the sticky is activated, I would like them to inherit the widths of the headers, but they shrink to the size of the text at the moment.
My JS:
$(document).ready(function() {
var stickyNavTop = $('.th').offset().top;
SOLUTION:
$(".th th").each(function(){$(this).width($(this).width());});
$('.th').width($('.th').width());
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('.th').addClass('sticky');
} else {
$('.th').removeClass('sticky');
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
});
My HTML:
<table class="mGrid" cellspacing="0" rules="all" border="1" id="1"
style="width:98%;border-collapse:collapse;">
<tr class="th">
<th scope="col">Membership No.</th>
<th scope="col">Surname</th>
<th scope="col">Other Name(s)</th>
</tr>
<tr>
<td>
<div id="2" class="formInput">
<label for="2">Membership No.</label>
<input name="2" type="text" value="AH6973" id="2"
class="required" style="width:60px;" />
</div>
</td>
<td>
<div id="3" class="formInput">
<label for="3">Surname</label>
<input name="3" type="text" value="CARTER" id="3"
style="width:100px;" />
</div>
</td>
<td>
<div id="4" class="formInput">
<label for="4">Other Name(s)</label>
<input name="4" type="text" value="RAYMOND" id="4"
style="width:150px;" />
</div>
</td>
</tr>
</table>
my CSS:
.sticky {
position: fixed;
width: 100%;
top: 0;
z-index: 100;
border-top: 0;
color: #fff !important;
background: #666;
border-left: solid 1px #525252;
font-size: 1.0em;
}
(This is modelled to be the same as the header style, it's just the width shrinks to fit the width of the text at the moment. I tried to edit the header style but it's apparently read-only "'HeaderStyle' property is read-only and cannot be set."

Just add this line before your function definition:
$('th').width($('th').width());
Full JavaScript code:
$(document).ready(function() {
var stickyNavTop = $('.th').offset().top;
$('th').width($('th').width());
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('.th').addClass('sticky');
} else {
$('.th').removeClass('sticky');
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
});

here is a common solution, it auto detects each sub-element's width and height and reflect when scrolling, it is something like following:
var $this = $(this),
top = $this.offset().top,
left = $this.offset().left,
width = $this.width(),
height = $this.height(),
widthArr = [],
heightArr = [];
$this.find("*").each(function(i, e) {
widthArr.push($(this).width());
heightArr.push($(this).height());
});
$(window).scroll(function() {
if($(window).scrollTop() >= top) {
$this.css({
position: "fixed",
top: 0,
left: left,
"z-index": 100,
width: width,
height: height
});
$this.find("*").each(function(i, e) {
$(this).width(widthArr[i]);
$(this).height(heightArr[i]);
});
} else {
// to be implemented
}
});

My solution to avoid column width changes : cloning the header. (Thanks to #Matt for the line: $('th').width($('th').width()); and his solution.)
JS
var stickyNavTop = jQuery('thead tr:first-child').offset().top;
// init state
var stickState = (jQuery(window).scrollTop() > stickyNavTop);
var stickyNav = function() {
var scrollTop = jQuery(window).scrollTop();
// state has changed?
if (stickState != (scrollTop > stickyNavTop)) {
// remember/catch new state
stickState = (scrollTop > stickyNavTop);
if (stickState) {
jQuery('thead tr:first-child th').each(
function() { jQuery(this).width( jQuery(this).width() ); }
);
// cloning the header : the original columns won't move
jQuery('thead tr:first-child')
.clone()
.prependTo(jQuery('thead'))
.addClass('sticky');
} else {
jQuery('tr.sticky').remove();
}
}
};
jQuery(window).scroll(function() {
stickyNav();
});
stickyNav();
CSS
.sticky {
position: fixed;
top: 0;
z-index: 100;
}

Related

Making equal div height even if the browser is resized

I am trying to make all my divs the same height even if the browser is resized. I have 4 icon boxes. each box has an icon, a title, and a description. I want to make all of them same size. that means if the highest height of the icon container div is 100px all icon holder div will be 100px. the following code is working but if I resize the browser some time the height of the container divs is much bigger than the actual height. what I am doing wrong? (Note the resize will only happen screen size above 767px) thanks
function allSameHeight(sameSec, sameImg, sameTitle, sameDesc) {
jQuery(sameSec).each(function () {
let highestImg = 0;
let highestTitle = 0;
let highestTxt = 0;
jQuery(sameSec).find(sameImg).each(function () {
if (jQuery(this).height() > highestImg) {
highestImg = jQuery(this).height();
}
});
jQuery(sameSec).find(sameTitle).each(function () {
if (jQuery(this).height() > highestTitle) {
highestTitle = jQuery(this).height();
}
});
jQuery(sameSec).find(sameDesc).each(function () {
if (jQuery(this).height() > highestTxt) {
highestTxt = jQuery(this).height();
}
});
if (jQuery(window).width() > 768) {
jQuery(sameSec).find(sameImg).css("min-height", highestImg);
jQuery(sameSec).find(sameTitle).css("min-height", highestTitle);
jQuery(sameSec).find(sameDesc).css("min-height", highestTxt);
} else {
jQuery(sameSec).find(sameImg).css("min-height", "auto");
jQuery(sameSec).find(sameTitle).css("min-height", "auto");
jQuery(sameSec).find(sameDesc).css("min-height", "auto");
}
});
}
Give a class to all four items. I've used myItem for instance.
const setHeights = () => {
let highestHeight = 0;
//Loop through all elements and get the highest height
$('.myItem').each((index, element) => {
if($(element).outerHeight() > highestHeight) {
highestHeight = $(element).outerHeight();
}
});
//Set the height of all elements to highest
$('.myItem').height(highestHeight);
};
$(window).resize(() => {
//Run each time window is resized
setHeights();
});
.myItem {
width: 25%;
color: white;
float: right;
}
.one {
background: red;
}
.two {
background: blue;
}
.three {
background: purple;
}
.four {
background: orange;
}
h3 {
word-wrap: break-word;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button onclick="setHeights()">Make them equal</button>
</div>
<div class="myItem one">
<h3>
aaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaa
aaaaaaaaaa
</h3>
</div>
<div class="myItem two">
<h3>
bbbbbbbb
</h3>
</div>
<div class="myItem three">
<h3>
ccccccccccccccc
ccccccccc
</h3>
</div>
<div class="myItem four">
<h3>
ddddddddddddddd
ddddddddddd
ddddddddddddd
ddddddddddddddd
ddddddddddddddddd
</h3>
</div>
For this case there are multiple approaches, I'll mention the two most common (in my opinion):
https://www.w3schools.com/howto/howto_css_equal_height.asp
Using flexbox: https://moderncss.dev/equal-height-elements-flexbox-vs-grid/

Support resizing two side by side iframes in JavaScript

I have a web page where I need to show two iFrames side by side, and allow a user to resize them horizontally (so they can easily see the complete contents of either side).
My code looks like this:
<div style="padding:30px">
<table style="width:100%;border:0px;border-collapse:collapse;">
<tr>
<td class="cLeft cSide">
<iframe class="cFrame" src="{MyLeftPage}">
</iframe>
</td>
<td class="cRight cSide">
<iframe class="cFrame" src="{MyRightPage}">
</iframe>
</td>
</tr>
</table>
</div>
Finally managed it: jsFiddle
The problem with using the standard approaches as mentioned here (Thanks user!) is that when you have iFrames and you move the mouse over them, the $(document).mousemove() stops firing.
The trick is to have a column in the middle, and have a div that shows up when you click the column. Since the div is in the parent page, the mousemove event keeps firing, allowing you to easily resize it.
Here's what the final HTML looks like:
<div style="user-select:none;padding:30px">
<table style="width:100%;border:0px;border-collapse:collapse;">
<tr>
<td class="cLeft cSide">
<iframe class="cFrame" src="{MyLeftPage}">
</iframe>
</td>
<td class="resize-bar">
<div class="resize-panel"></div>
</td>
<td class="cRight cSide">
<iframe class="cFrame" src="{MyRightPage}">
</iframe>
</td>
</tr>
</table>
</div>
This is the CSS
.resize-bar {
width: 5px;
cursor: col-resize;
position:relative;
background-color: #AAA;
margin:20px;
}
.resize-panel {
height: 100%;
background-color: #DDDDDD00;
display: inline-block;
position: absolute;
top:0px;
left:-2px;
right:-2px;
cursor: col-resize;
}
.resize-panel.rx {
left:-400px;
right:-400px;
}
.cSide {
min-width:200px;
}
.cFrame {
width: 100%;
border: 1px solid #DDD;
height: calc(100vh - 170px);
overflow-x:scroll;
}
And this is the JavaScript:
$(function() {
var pressed = false;
$("table td").mousedown(function(e) {
pressed = true;
$(".resize-panel").addClass("rx");
e.stopPropagation();
});
$(".resize-panel").mousedown(function(e) {
pressed = false;
});
$(document).mousemove(function(e) {
if (e.which == 1 && pressed) {
var ww = $(window).width();
var cPos = e.pageX;
if (cPos < 0.20 * ww) cPos = 0.2 * ww;
if (cPos > 0.80 * ww) cPos = 0.8 * ww; {
$(".cLeft").width(cPos);
}
}
});
$(document).mouseup(function() {
if (pressed) {
$(".resize-panel").removeClass("rx");
pressed = false;
}
});
});

How to convert jQuery function into angular js?

I am very new to AngularJs, I have written a slider function in jQuery. Now I want to convert thih function into Angular. Here is my code below::
<div class="slide-container">
<div class="slide-scroller" style="left: 0px;">
<div class="slideContent" style="background-color: #f00;">one</div>
<div class="slideContent" style="background-color: #0f0;">two</div>
<div class="slideContent" style="background-color: #00f;">three</div>
</div>
</div>
<input type="button" id="left">
<input type="button" id="right">
.slide-container {height: 100px; overflow: hidden; position: relative;}
.slide-scroller { height: 100px; overflow:hidden; position: absolute; top: 0px;}
.slide-scroller .slideContent { height: 100px; overflow: hidden; float: left;}
function slider() {
var slideWidth, speed, sc, slideScroller, scSlide, totalSlide, scrollerWidth, maxLeft;
slideWidth = $(window).width(); // [ get the device width ]
speed = 0.6; // [ control speed 1 = 1s]
sc = $(".slide-container"); // [ getting the container ]
slideScroller = $('.slide-scroller'); // [ getting slider scroller ]
scSlide = $('.slideContent'); // [ getting slide contetnts ]
totalSlide = $(scSlide).length; // [ total slide contents ]
scrollerWidth = totalSlide * slideWidth; // [ slide scroller width ]
maxLeft = -parseInt(scrollerWidth) + parseInt(slideWidth); // [maxmimum left slide value]
// adding some initial attributes
$(sc && scSlide).css({width: slideWidth});
$(slideScroller).css({width: scrollerWidth});
$(slideScroller).css('transition', 'all ease '+speed+'s');
// left click function
$("#left").click(function () {
var xvalue = $(slideScroller).css('left'); //console.log('left :: ', xvalue);
var newvalue = parseInt(xvalue) - parseInt(slideWidth); // console.log('newValue :: ', newvalue);
if (newvalue >= maxLeft) {//console.info('no more left left');
$(slideScroller).css('left', newvalue);
}
else {
return false;
}
});
// right click function
$("#right").click(function () {
var xvaluetwo = $(slideScroller).css('left'); console.log('lefttwo :: ', xvaluetwo);
var newvaluetwo = parseInt(xvaluetwo) + parseInt(slideWidth); console.log('newValuetwo :: ', newvaluetwo);
if (newvaluetwo <= 0) {//console.info('no more right left');
$(slideScroller).css('left', newvaluetwo);
}
else {
return false;
}
});
}
$(document).ready(function () {
slider();
});
I have linked jQuery.min library and called the function in document.ready
Please help me how to make in AngularJS
in HTML:
<div class="slide-container" ng-init="initSlider()">
<div class="slide-scroller" ng-repeat="item in sliderList" style="left: 0px;">
<div class="slideContent" style="background-color: {{item.bgColor}}">{item.content}</div>
</div>
</div>
<input type="button" id="left">
<input type="button" id="right">
in Controller:
$scope.initSlider = function(){
slider()
}

Safari calculates wrong width in table

I'm working on developing a simple column resize functionality for HTML tables.
The table works OK so far - except in Safari (ver 5.1.4). For some reason Safari gives the cell widths a negative(!) value.
a JSFiddle is available here: simple-resize
The negative column width values can be seen if the style="width" attributes are removed from the <th> elements (or disabled in the code inspector)
HTML:
<div class="tblcont" id="cont">
<table id="table1" class="pivot-table pivot-fixed-layout">
<thead>
<tr id="tr1">
<th style="width: 52px;">city</th>
<th style="width: 26px;"># c</th>
<th style="width: 37px;"># id</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tel Aviv</td>
<td>814</td>
<td>1,047</td>
</tr>
<tr>
<td>Natanya</td>
<td>805</td>
<td>1,016</td>
</tr>
</tbody>
</table>
</div>
CSS:
.pivot-table.pivot-fixed-layout {
border-collapse: collapse;
table-layout: fixed;
width: 0;
}
.pivot-table td, .pivot-table th {
overflow: hidden;
padding: 0 6px;
border-right: 1px solid;
border-bottom: 1px solid;
text-overflow: ellipsis;
}
.pivot-table th {
cursor: col-resize;
}
Javascript:
var pressed = false,
$column,
$table = $("table"),
startX, startWidth,
tableInitialWidth = $('#cont').width() - 100,
currentTableWidth, newTableWidth;
$("table th").mousedown(function(e) {
$column = $(this);
pressed = true;
startX = e.pageX;
startWidth = $column.width();
$column.addClass("resizing");
});
$(document).mousemove(function(e) {
if(pressed) {
var delta = e.pageX - startX,
currentColumnWidth,
newColumnWidth;
currentColumnWidth = $column.width();
newColumnWidth = startWidth + delta;
currentTableWidth = $table.width();
newTableWidth = currentTableWidth + delta;
// no not make columns smaller than min width
if (newColumnWidth > 2) {
$column.width(newColumnWidth);
}
}
});
$(document).mouseup(function() {
if(pressed) {
$column.removeClass("resizing");
pressed = false;
}
});

window resize determine controls parent is smaller or greater

I need a script to determine when the parent element width of the conrol is resized. This is determined on the windows resize event all i need is to know weither the parent is smaller or larger than before instantaneously. please leave a working example - would be apreciated thanks
JavaScript:
(function ($) {
$.fn.quicklist = function () {
var _this = this;
var config = {
quicklistParentWidth: $(_this).parent().width(),
}
var parentWidth = config.quicklistParentWidth;
$(window).resize(function (event) {
var currWidth = config.quicklistParentWidth;
$(_this).parent().css('width', config.quicklistParentWidth);
if (currWidth > parentWidth) {
$('#width').text('greater');
} else if(parentWidth < currWidth) {
$('#smaller').text('smaller');
}
parentWidth = currWidth;
});
};
})(jQuery);
$(document).ready(function () {
$('#quicklist').quicklist();
});
HTML:
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr style="height:34px">
<td style="background:url(images/classic/quicklink_bar.png) 0px 0px; background-repeat:repeat-x; width:100%;">
<ul id="quicklist">
<li>List Goes here</li>
</ul>
</td>
<td style="background:url(images/classic/quicklink_bar.png) 0px 0px; background-repeat:repeat-x; ">
<a id="link" href="#">Link</a>
</td>
</tr>
</table>
<span id="width"></span>
Here's a working version in javascript. http://jsfiddle.net/ZhG8N/
<div style="width:50%; background:#F00">not yet resized
<div id="child"></div>
</div>
<script>
var parent = document.getElementById('child').parentNode,
lastSize = parent.offsetWidth,
newSize, timer;
window.onresize = function(){
newSize = parent.offsetWidth;
if(lastSize > newSize){
parent.innerHTML = 'smaller';
}
else if(lastSize< newSize){
parent.innerHTML = 'wider';
}
lastSize = newSize;
}
</script>

Categories