Div with a simple variable height - javascript

So, I want to make a div that has the height of a value I'm going to get from my database. To make it better do understand, the value is a the number of times a client has bought in the website. I'm thinking of a way to make my div go up as the value go up.
Something like this:
var divHeight = numberOfValues;
numberOfValues = heightOfDiv; (div's height property)
if (numberOfValues == 0) {
divHeight = 0;
} else {
divHeight = numberOfValues + 10;
}
The logic is to have my div increase in 10px for every value number. So if the value is 10 the height should be 100px.
What is the best way for me to achieve this solution? Is it as simple as I think? (Simple != easy).

<?php
$numberOfPurchases = getNumberOfPurchases(); // call the function that queries the database
?>
<script>
var defaultDivHeight = 10;
var purchaseDiv = document.getElementById('purchaseDiv');
if (<?= numberOfPurchases; ?> > 0)
{
purchaseDiv.style.height = <?= numberOfPurchases; ?> * defaultDivHeight + 'px';
}
else
{
purchaseDiv.style.height = defaultDivHeight + 'px';
}
</script>
I suggest looking into using PDO in PHP for querying the database.

<script>
var divHeight = numOfVisits * 10;
var divDisplay = document.getElementById("display");
if(divHeight>0)
divDisplay.style.height = divHeight + "px";
else
divDisplay.style.height = "1px";
</script>

Related

Word Wrap detection in JavaScript

I am trying to work out a way to detect wordwrap in a specific span tag inside a banner. If it wraps to 2 lines then increase the overall height of the container by 56px. There is also a sub headline (headline2) which also needs to increase (or decrease) the height by 40px.
I have written some basic JS code here which checks the div height of the span but its not great & also will only work for 3 lines.
// Variable banner heights
var hl11sub = 368;
var hl21sub = 448;
var hl31sub = 548;
var hl12sub = 416;
var hl22sub = 496;
var hl32sub = 576;
var hLFontSizeCSS = window.getComputedStyle(headlineText, null).getPropertyValue("font-size");
var hL2FontSizeCSS = window.getComputedStyle(headline2text, null).getPropertyValue("font-size");
var bannerHeightCSS = window.getComputedStyle(banner, null).getPropertyValue("height");
var headlineHeight = headlineText.offsetHeight;
var hL2HeadHeight = headline2text.offsetHeight;
var headHeight = headlineText.style.lineHeight = parseInt(hLFontSizeCSS) + 10 + "px";
var hL2Height = headline2text.style.lineHeight = parseInt(hL2FontSizeCSS) + 10 + "px";
// Text Height values
var hL1LineHeight = parseInt(headHeight); // 8 is line height & padding
var hL2LinesHeight = 140;
var hL3LinesHeight = 195;
// HL2 height values
var hL2TextOver1LineHeight = parseInt(hL2Height); // 8 is line height & padding
var hL2TextOver2LineHeight = 84;
if(hL2HeadHeight == hL2TextOver1LineHeight && headlineHeight == hL1LineHeight){
banner.style.height = hl11sub + "px";
}
else if(hL2HeadHeight == hL2TextOver1LineHeight && headlineHeight == hL2LinesHeight){
banner.style.height = hl21sub + "px";
}
else if(hL2HeadHeight == hL2TextOver1LineHeight && headlineHeight >= hL3LinesHeight){
banner.style.height = hl31sub + "px";
}
else if(hL2HeadHeight == hL2TextOver2LineHeight && headlineHeight == hL1LineHeight){
// Single headline with 2 lines sub
banner.style.height = hl12sub + "px";
}
else if(hL2HeadHeight == hL2TextOver2LineHeight && headlineHeight == hL2LinesHeight){
// 2 headlines with 2 lines sub
banner.style.height = hl22sub + "px";
}
else {
banner.style.height = hl32sub + "px";
// 3 headlines with 2 lines sub
It needs to only change the height of the banner depending on if the span words wrap once, twice, three times etc.
Any suggestions or help with this would be greatly appreciated.
Here is a very basic implementation on how to detect when a line is wrapped hopefully this gives you a good idea where to start and integrate it into your app.
Heres the docs for stuff used
https://developer.mozilla.org/en/docs/Web/API/EventTarget/addEventListener
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
You mentioned the height changing and you needing to know when its wrapped you can use a mutation observer to check when the style has changed then check if its wrapped.
Resize the demo window to see results
any questions i'll try get to them asap if i've misunderstood i'll happily change :)
const h1 = document.querySelector('h1');
const banner = document.querySelector('.banner');
//handles style changes on banner to check wrapping
const observer = new MutationObserver(mutations =>
mutations.forEach(mutationRecord => onLineWrapDoSomething())
);
observer.observe(banner, { attributes : true, attributeFilter : ['style'] });
// handles window resize events
window.addEventListener('resize', onLineWrapDoSomething)
function onLineWrapDoSomething() {
const { lineHeight } = getComputedStyle(h1);
const lineHeightParsed = parseInt(lineHeight.split('px')[0]);
const amountOfLinesTilAdjust = 2;
if (h1.offsetHeight >= (lineHeightParsed * amountOfLinesTilAdjust)) {
console.log('your h1 now wrapped')
} else {
console.log('your h1 on one line')
}
}
// shows it logs when style changes and it wraps, ignore the disgusting code below
setTimeout(() => {
banner.style.width = '50%'
setTimeout(() => {
banner.style.width = '100%'
}, 1500)
}, 1500)
.banner {
width: 100%;
}
h1 {
line-height: 1.5
}
<div class="banner">
<h1>This is some text that will eventually wrap</h1>
</div>

Textarea that expands as you type and pushes down content below it

I am looking for a way to make a <textarea> expand as the user types, but when it expands i want it to push down all content below it. I managed to make it expandable as the user types (with javascript) but i can't make it push down content that it's below the textarea
i am using a javascript code i took from another post here on stackoverflow:
function setNewSize (textarea) {
if (textarea.value.length > 5){
textarea.cols = 90;
textarea.rows = 15;
} else {
textarea.cols = 90;
textarea.rows = 5;
}
}
and then calling it in <textarea onkeyup="setNewSize(this)"></textarea>
You could try this method to resize your textarea. If this does not work you should probably set some properties to the container of the textarea.
<script language="javascript">
function increaseHeight(e){
e.style.height = 'auto';
var newHeight = (e.scrollHeight > 32 ? e.scrollHeight : 32);
e.style.height = newHeight.toString() + 'px';
}
</script>
<textarea onkeyup="increaseHeight(this);"></textarea>

window scroll don't work properly

this is my code JS
var elem3 = document.createElement('DIV');
elem3.setAttribute('id', 'eye');
elem3.style.display = "block";
elem3.style.width = "100px";
elem3.style.height = "100px";
elem3.style.zIndex = "301";
elem3.style.position = "absolute";
elem3.style.top = "0px";
elem3.style.left = "0px";
document.body.appendChild(elem3);
var danger, up = 0;
window.onscroll = function(e) {
up += 10;
document.getElementById('eye').style.top = up + "px";
}
function check() {
danger = setInterval(function() {
if (document.getElementById('eye').style.top >= 2000 + "px") {
location.href = "http://www.google.com";
clearInterval(danger);
}
})
};
check();
I want to create a div (eye) and with scroll I want that this div fall by 10px.1 scroll=10px, 10 scroll=100px. If the top of eye is greater then 2000px this will redirect the page. But this don't work because when I begin scroll, the page redirect automatically and the div don't scroll to 2000px.
if (document.getElementById('eye').style.top>=2000+"px"){
That check is wrong, the check is a string comparison, not a number comparison.
You should be using parseInt to get the number value of the position.
if (parseInt(document.getElementById('eye').style.top,10)>=2000) { ...
Why are you checking the style when the variable up should hold the value?
if (up>=2000){ ...
Don't use window.onscroll=function(e){up+=10;document.getElementById('eye').style.top=up+"px";}
1) use scrollTop and added delay in setInterval.
2) Your "if" not work, use integer instead of string
Try this:
var elem3=document.createElement('DIV');
elem3.setAttribute('id','eye');
elem3.style.display="block";
elem3.style.width="100px";
elem3.style.height="100px";
elem3.style.zIndex="301";
elem3.style.position="absolute";
elem3.style.top="0px";
elem3.style.left="0px";
document.body.appendChild(elem3);
var danger, up=0;
window.onscroll=function(e){
up = window.scrollTop() + 10; //or `up = window.scrollTop();`
document.getElementById('eye').style.top = up +"px";
};
function check(){
danger = setInterval(function(){
if (parseInt(String(document.getElementById('eye').style.top).replace(/[a-zA-Z]/g)) >= 2000){
location.href="http://www.google.com";
clearInterval(danger);
}
}, 100);//Added delay
};
check();

Text pagination inside a DIV with image

I want to paginate a text in some div so it will fit the allowed area
Logic is pretty simple:
1. split text into words
2. add word by word into and calculate element height
3. if we exceed the height - create next page
It works quite good
here is JS function i've used:
function paginate() {
var newPage = $('<pre class="text-page" />');
contentBox.empty().append(newPage);
var betterPageText='';
var pageNum = 0;
var isNewPage = false;
var lineHeight = parseInt(contentBox.css('line-height'), 10);
var wantedHeight = contentBox.height() - lineHeight;
for (var i = 0; i < words.length; i++) {
if (isNewPage) {
isNewPage = false;
} else {
betterPageText = betterPageText + ' ' + words[i];
}
newPage.text(betterPageText + ' ...');
if (newPage.height() >= wantedHeight) {
pageNum++;
if (pageNum > 0) {
betterPageText = betterPageText + ' ...';
}
newPage.text(betterPageText);
newPage.clone().insertBefore(newPage)
betterPageText = '...';
isNewPage = true;
} else {
newPage.text(betterPageText);
}
}
contentBox.craftyslide({ height: wantedHeight });
}
But when i add an image it break everything. In this case text overflows 'green' area.
Working fiddle: http://jsfiddle.net/74W4N/7/
Is there a better way to paginate the text and calculate element height?
Except the fact that there are many more variables to calculate,not just only the word width & height, but also new lines,margins paddings and how each browser outputs everything.
Then by adding an image (almost impossible if the image is higher or larger as the max width or height) if it's smaller it also has margins/paddings. and it could start at the end of a line and so break up everything again.basically only on the first page you could add an image simply by calculating it's width+margin and height+margin/lineheight. but that needs alot math to get the wanted result.
Said that i tried some time ago to write a similar script but stopped cause of to many problems and different browser results.
Now reading your question i came across something that i read some time ago:
-webkit-column-count
so i made a different approach of your function that leaves out all this calculations.
don't judge the code as i wrote it just now.(i tested on chrome, other browsers need different prefixes.)
var div=document.getElementsByTagName('div')[0].firstChild,
maxWidth=300,
maxHeigth=200,
div.style.width=maxWidth+'px';
currentHeight=div.offsetHeight;
columns=Math.ceil(currentHeight/maxHeigth);
div.style['-webkit-column-count']=columns;
div.style.width=(maxWidth*columns)+'px';
div.style['-webkit-transition']='all 700ms ease';
div.style['-webkit-column-gap']='0px';
//if you change the column-gap you need to
//add padding before calculating the normal div.
//also the line height should be an integer that
// is divisible of the max height
here is an Example
http://jsfiddle.net/HNF3d/10/
adding an image smaller than the max height & width in the first page would not mess up everything.
and it looks like it's supported by all modern browsers now.(with the correct prefixes)
In my experience, trying to calculate and reposition text in HTML is almost an exercise in futility. There are too many variations among browsers, operating systems, and font issues.
My suggestion would be to take advantage of the overflow CSS property. This, combined with using em sizing for heights, should allow you to define a div block that only shows a defined number of lines (regardless of the size and type of the font). Combine this with a bit of javascript to scroll the containing div element, and you have pagination.
I've hacked together a quick proof of concept in JSFiddle, which you can see here: http://jsfiddle.net/8CMzY/1/
It's missing a previous button and a way of showing the number of pages, but these should be very simple additions.
EDIT: I originally linked to the wrong version for the JSFiddle concept
Solved by using jQuery.clone() method and performing all calculations on hidden copy of original HTML element
function paginate() {
var section = $('.section');
var cloneSection = section.clone().insertAfter(section).css({ position: 'absolute', left: -9999, width: section.width(), zIndex: -999 });
cloneSection.css({ width: section.width() });
var descBox = cloneSection.find('.holder-description').css({ height: 'auto' });
var newPage = $('<pre class="text-page" />');
contentBox.empty();
descBox.empty();
var betterPageText = '';
var pageNum = 0;
var isNewPage = false;
var lineHeight = parseInt(contentBox.css('line-height'), 10);
var wantedHeight = contentBox.height() - lineHeight;
var oldText = '';
for (var i = 0; i < words.length; i++) {
if (isNewPage) {
isNewPage = false;
descBox.empty();
}
betterPageText = betterPageText + ' ' + words[i];
oldText = betterPageText;
descBox.text(betterPageText + ' ...');
if (descBox.height() >= wantedHeight) {
if (i != words.length - 1) {
pageNum++;
if (pageNum > 0) {
betterPageText = betterPageText + ' ...';
}
oldText += ' ... ';
}
newPage.text(oldText);
newPage.clone().appendTo(contentBox);
betterPageText = '... ';
isNewPage = true;
} else {
descBox.text(betterPageText);
if (i == words.length - 1) {
newPage.text(betterPageText).appendTo(contentBox);
}
}
}
if (pageNum > 0) {
contentBox.craftyslide({ height: wantedHeight });
}
cloneSection.remove();
}
live demo: http://jsfiddle.net/74W4N/19/
I actually came to an easier solution based on what #cocco has done, which also works in IE9.
For me it was important to keep the backward compatibility and the animation and so on was irrelevant so I stripped them down. You can see it here: http://jsfiddle.net/HNF3d/63/
heart of it is the fact that I dont limit height and present horizontal pagination as vertical.
var parentDiv = div = document.getElementsByTagName('div')[0];
var div = parentDiv.firstChild,
maxWidth = 300,
maxHeigth = 200,
t = function (e) {
div.style.webkitTransform = 'translate(0,-' + ((e.target.textContent * 1 - 1) * maxHeigth) + 'px)';
div.style["-ms-transform"] = 'translate(0,-' + ((e.target.textContent * 1 - 1) * maxHeigth) + 'px)';
};
div.style.width = maxWidth + 'px';
currentHeight = div.offsetHeight;
columns = Math.ceil(currentHeight / maxHeigth);
links = [];
while (columns--) {
links[columns] = '<span>' + (columns + 1) + '</span>';
}
var l = document.createElement('div');
l.innerHTML = links.join('');
l.onclick = t;
document.body.appendChild(l)

elementFromPoint() full document alternative

I am trying to recover a value from a cookie, which is somewhere on the Y-axis where the user clicked. I then want to find the parent <h2> from that click (if it helps, all the <h2>s are the first child of a <div class="_bdnable_">). Here is what I have so far:
var bookmarkLocation;
function getBookmarkPos() {
if ($.cookie("bookmark-position") !== null) {
$(".bdnable").each(function(i) {
var scrollTopTop = $(this).offset.top;
var scrollTopBottom = $(this).offset.top + $(this).height();
// var screenWidth = parseInt(screen.width/2);
// alert(screenWidth);
// var bookmarkPosition = parseInt($.cookie("bookmark-position"));
// alert(bookmarkPosition);
// var query = document.elementFromPoint(screenWidth, 50).nodeName;
// alert(query);
if ($.cookie("bookmark-position")>=scrollTopTop && $.cookie("bookmark-position")<=scrollTopBottom) {
bookmarkLocation = $(this).closest("div").children(":nth-child(1)").text();
}
});
if (bookmarkLocation == null) {
bookmarkLocation = "Unknown";
}
} else {
bookmarkLocation = "No bookmark set";
}
$("#bookmarklocationspan").html(bookmarkLocation);
}
In the commented out section is where I tried to use getElementFromPoint and then realized that it only checks the visible area. Not good, because the scrollable Y-axis on the page is 1000s of pixels tall.
Any ideas are greatly appreciated!!!
If you already have the y-coordinate of the click from the cookie, why not simply compare all H2's y-position and pick the one which is the next "higher" one? Your approach looks like it's compares whether the user has clicked directly on the H2 instead of the article/button below it?
Just an idea - don't rate it's style, think its prettey messy:
var $myH2 = $('h2');
var clickY = <COOKIE_VALUE>;
var currentY = 0;
var foundH2ID = '';
for (var i = 0; i < $myH2.length; i++) {
var h2Y = $($myH2[i]).position().top;
if (h2Y <= clickY && h2Y > currentY) {
currentY = h2Y;
foundH2ID = $myH2[i].id;
}
}
Or maybe I got you wrong?

Categories