repeatable marquee that's optional based on text width - javascript

I've spent most of my morning trying to resolve how to create a scrolling marquee on an Angular app; my goal is when the dynamic text is longer than its viewport, it will scroll (repeating, meaning you don't have to wait for the entire title to scroll off the page before you see it again) but when it's short enough to display without being cut off in the viewport width, it does not scroll.
I like examples I'm seeing but need to combine them somehow and I am very beginner when it comes to adding any kind of javascript.
One is using jQuery and marquee:
$('.marquee').marquee({
duplicated: true
});
This one is great because it repeats the text and continues without it having to completely leave the screen to start again. But, my trouble comes when trying to figure out a way to add in javascript to figure out how wide that text will be; either to have it be static or scroll.
For some reason, I am unable to understand how to link to codepen or jsfiddle of the examples I've found that hit close to home. Hoping my inquiry above is enough information. I know commenters can be a bit rough—please be patient with me.

You could use text-shadow(to clone text) and animation if it is only about text.
JS will be necessary to get the width(from text lenght) of the piece to scroll and to update/insert css rule's values.
example inspired from your jsfiddle
function isElementOverflowing(element) {
var overflowX = element.offsetWidth < element.scrollWidth,
overflowY = element.offsetHeight < element.scrollHeight;
return (overflowX || overflowY);
}
// below css updated and injected . can be shorten and nicely rewritten
var element = document.getElementById('ov1');
if (isElementOverflowing(element)) {
var toscroll = element.scrollWidth;
element.style.textShadow = toscroll + 'px 0 ';
element.style.animation = 'marqueeme 5s infinite linear';
var csstyle = document.createElement('style');
csstyle.innerText = '#keyframes marqueeme {100%{ text-indent:-' + toscroll + 'px;}}';
element.appendChild(csstyle)
}
#marquee {
max-width: 15em;
overflow: hidden;
}
#ov1 {
white-space: nowrap;
margin: 0;
}
<div id="marquee">
<p id="ov1">
Yadda yadda overflowing text this line is too long oh noes!
</p>
</div>
example here is using text-indent within the animation, but negative margin-left or translateX will do the same visual.
Another example with
a text-shadow of different color
transform to see it working instead text-indent.
It also sets speed according to text length
# https://codepen.io/gc-nomade/pen/owPNZg

Related

Resizing a font with pure JavaScript based on string length

I know this question is asked multiple times, yet mine is different. I noticed that with the pure JavaScript solution, there is a need to resize the screen, while mine has absolutely nothing to do with resizing a screen.
What I have is a container div with some text in it. All texts have a certain font-size, but I want to change the font-size whenever the text gets a certain length.
I have seen this solution on SO:
Resize font depending on string length
Yet, this absolutely looks horrible in pure JavaScript and it's a post of three years ago. There surely must be a better (shorter, better) solution for this. I have read about the CSS solutions, but as I said: I am not using a certain viewport and I don't want to. I just want to change the font-size when it's too long.
I have made a JSFiddle to illustrate the problem:
https://jsfiddle.net/tpx71aqL/
<div class="test">
Blablabla
</div>
<div class="test">
Blablabla12124e121211asdasasas
</div>
PS: I can't use jQuery and don't want to use ellipsis.
An idea for this solution is actually really simple. Check out my codepen here.
Using a simple while loop which checks clientWidth against scrollWidth which you can learn more about here, we use the javascript .style.fontSize = "smaller" which decreases the font size by 1 unit. This works well when we don't know what unit is assigned in the CSS. You can read more about it here.
Hope this helps.
document.onreadystatechange = () => {
if (document.readyState === 'complete') {
var container = document.getElementById("test");
while (container.scrollWidth > container.clientWidth) {
container.style.fontSize = "smaller";
}
}
};
.test {
width: 200px;
border: 1px solid black;
font-size: 16px;
}
<div class="test">
Blablabla
</div>
<div class="test" id="test">
Blablabla12124e121211asdasasas
</div>
This fiddle shows what I suggested in my comment. You extract the current width of the text wrapper and reduce font size until you have a wrapper the same size or slightly smaller than the parent.
var fit = document.getElementById("fit"),
wrap = document.getElementById("wrap"),
step = 0.5,
currentSize;
while (fit.offsetWidth < wrap.offsetWidth) {
currentSize = parseFloat(window.getComputedStyle(wrap, null).getPropertyValue('font-size'));
wrap.style.fontSize = (currentSize - step) + "px";
}
Note the getComputedStyle to really get the calculated size.
You could improve this by making the reduction step smarter, instead of just going down a step again and again; for example calculate how far a 1px reduction approximated the wrapper width to the parent width and adjust step size accordingly.
Also this does assume that the text indeed needs scaling down, no scaling up - the same idea applies.
I needed something similar and I ended up doing something like this:
var elem = document.getElementById("test");
elem.style.fontSize = 30 - elem.innerHTML.length / 6 + 'px';
The idea is to set the max size and reduce it based on the length of the string.
Not fancy or sophisticated but worked for me.

JS Get Current Position of Animated Element

So I have an element that is using CSS3 transitions to move across the page. I'm trying to see how the actual output FPS of that animation on the page is (for instance, if the page is outputting at 5FPS, a div moving from 0px to 10px at a transition value of 1s should report back 2px, 4px, 6px, etc).
Instead, I just get whatever value I already set the div's position to.
// css has defined a transition of 10s on the moving div
document.getElementById("movingDiv").style.left = "0px";
console.log(document.getElementById("movingDiv").style.left); //outputs 0px
document.getElementById("movingDiv").style.left = "100px";
window.setTimeout(function(){
console.log(document.getElementById("movingDiv").style.left); //outputs 100px instead of, for instance, 43px or wherever the div would visually appear to be
}, 3000);
That's not the exact code, but just some that's generic enough to illustrate my point.
Restating the question, how would I find where an element visually appears to be during its transition between one position and another? I'm not using jQuery animations as many others have answered for, and don't just want to calculate where the element should be. I want to see where the element actually appears to be on the page. I would also like if this works off-screen as well (like to the left of or above the visible window).
To help see why I'm actually trying to do this, is that I'm trying to get the FPS output of the page. I have seen many cases where the page outputs terrible FPS but Javascript still outputs over 100 FPS because the Javascript can run faster than the page can render itself which I'm trying to avoid.
You can use window.requestAnimationFrame:
var moving = false,
el = document.getElementById("mover");
el.className = el.className + " move-right";
el.addEventListener('transitionend', function () {
moving = true;
});
function getPosition() {
var rect = el.getBoundingClientRect()
console.log(rect.top, rect.left);
if (!moving) {
window.requestAnimationFrame(getPosition);
}
}
window.requestAnimationFrame(getPosition);
http://jsfiddle.net/ob7kgmbk/1/

How to make scrollbar to see full content in below case?

see demo url of the framework i'm using: http://alvarotrigo.com/fullPage/examples/navigationH.html#secondPage
However,using almost same kind of code from above,
when I try to achieve below effect in which title text is excluded from slider. (title text to be static, and content is sliding)
jsfiddle url: http://jsfiddle.net/097wvnot/8/
I can't scroll to see all the content; what's the best code to achieve this effect?
if i want to use the top framework, must i do a lot of hack into its core functions?
if not hacking the top animation framework , what are other recommendations to this effect
Use an absolute positioned element for your title. Fullpage.js calculates the height of your content inside the slide elements. (as they are suppose to be full height...).
If you place anything outside any slide, it would have to be absoluted positioned.
Take a look at the solution I propose: http://jsfiddle.net/097wvnot/11/
I added the following style to your title:
#demo{
position:absolute;
top:50px;
margin: 0;
left:0;
right:0;
text-align:center;
}
It looks like the plugin is calculating the height of the fp-scrollable incorrectly. At least for your use case. I was able to get it looking good by just manually adjusting the fp-scrollable's height attribute to a smaller amount (obviously that is not a long term fix, just something I was doing for testing). I'm not sure if the calculating takes into account your font size, and things like that, so that might effect it.
If you want to hack on the plugin, generally the place you need to make your changes is fairly restricted, and wouldn't be too bad. From the github page. https://github.com/alvarotrigo/fullPage.js/blob/master/jquery.fullPage.js
All you need to do is fix the value being placed into the scrollHeight variable. I'm not sure exactly what it's not accounting for in the scroll height calculation (the scrollHeight needs to be smaller in your case, it's too big), but I think that's an exercise you can try your hand at first :) I've got to get to bed z.z
You also may need to mess with the calculation for the contentHeight, since ostensibly you'll be shrinking the scrollHeight, and the script only puts the scroll bar on there if the content is bigger than the scroll.
function createSlimScrolling(element){
//needed to make `scrollHeight` work under Opera 12
element.css('overflow', 'hidden');
//in case element is a slide
var section = element.closest('.fp-section');
var scrollable = element.find('.fp-scrollable');
//if there was scroll, the contentHeight will be the one in the scrollable section
if(scrollable.length){
var contentHeight = scrollable.get(0).scrollHeight;
}else{
var contentHeight = element.get(0).scrollHeight;
if(options.verticalCentered){
contentHeight = element.find('.fp-tableCell').get(0).scrollHeight;
}
}
var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
//needs scroll?
if ( contentHeight > scrollHeight) {
//was there already an scroll ? Updating it
if(scrollable.length){
scrollable.css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
}
//creating the scrolling
else{
if(options.verticalCentered){
element.find('.fp-tableCell').wrapInner('<div class="fp-scrollable" />');
}else{
element.wrapInner('<div class="fp-scrollable" />');
}
element.find('.fp-scrollable').slimScroll({
allowPageScroll: true,
height: scrollHeight + 'px',
size: '10px',
alwaysVisible: true
});
}
}
//removing the scrolling when it is not necessary anymore
else{
removeSlimScroll(element);
}
//undo
element.css('overflow', '');
}

Javascript/jQuery get true width and position of float affected element?

Is it possible to get the width (using javascript or jQuery) of a float-affected element? When text is being pushed over due to a floating image is it possible to get its position and true width? I have attached an image to explain better.
Code example,
<div>
<img style="...float: left"/>
<h1>A title!</h1>
<p>Text!</p>
<h1>New header added.</h1>
</div>
Picture
I need to find the width starting from the arrow, (the gray box is the image)(the dotted line is the width according to Firefox inspect mode).
I would like to avoid changing all the elements display types if possible.
Thank you!
I'm a little late to the party, but I had a similar problem and came up with a solution which (so far) seems to work in all instances of this issue. I like this solution because as far as I can tell, it works independent of the floating element - all you need is the element whose true width/position you want to get, nothing more. I've done it in pure Javascript for speed purposes, but it can easily be streamlined with jQuery and a separate CSS Stylesheet if you so choose.
//Get the rendered bounding box for the content of any HTMLElement "el"
var getLimits = function(el) {
//Set a universal style for both tester spans; use "!important" to make sure other styles don't mess things up!
var testerStyle = 'width: 0px!important; overflow: hidden!important; color: transparent!important;';
//Create a 'tester' span and place it BEFORE the content
var testerStart = document.createElement('SPAN');
testerStart.innerHTML = '|';
var testerFloat = ' float: left!important;';
testerStart.setAttribute('style', testerStyle + testerFloat);
//Insert testerStart before the first child of our element
if (el.firstChild) {
el.insertBefore(testerStart, el.firstChild);
} else {
el.appendChild(testerStart);
}
//Create a 'tester' span and place it AFTER the content
var testerEnd = document.createElement('SPAN');
testerEnd.innerHTML = '|';
testerFloat = ' float: right!important;';
testerEnd.setAttribute('style', testerStyle + testerFloat);
el.appendChild(testerEnd);
//Measure the testers
var limits = {
top: testerStart.offsetTop,
bottom: testerEnd.offsetTop + testerEnd.offsetHeight,
left: testerStart.offsetLeft,
right: testerEnd.offsetLeft
}
//Remove the testers and return
el.removeChild(testerStart);
el.removeChild(testerEnd);
return limits;
};
So, in your case, the code would just be:
var paragraphBoundingBox = getLimits($('div>p').get(0));
A couple things to note:
1) The float direction would be reversed if you are using an RTL language
2) All of the four edge positions in the output object are relative to the el.offsetParent - use this handy function can find their positions relative to the document.
First of all, the "full width" is exactly the true width.
You can watch this picture, it can help you understand why the true width and true position of the affected element is the way firefox tells you.
http://i.stack.imgur.com/mB5Ds.png
To get the width of inline text where it's pushed right by the float image, there's no good way except using the full width minus the float image's width.
var w = $('p').width()
- $('img').width()
- $('img').css('margin-left').replace("px", "")
- $('img').css('margin-right').replace("px", "")
- $('img').css('padding-left').replace("px", "")
- $('img').css('padding-right').replace("px", "")
- $('img').css('border-left-width').replace("px", "")
- $('img').css('border-right-width').replace("px", "");

JS scrollbar with fluid height

I'd like to personalize the scrollbar of a div whith a fluid height :
section {
max-height:70%;
overflow-y:auto;
}
I have found two smart light snippets : a Jquery plugin (http://baijs.nl/tinyscrollbar/) and a pure JS one (http://gondo.webdesigners.sk/javascript-scrollbar/). The problem is that these snippets do not accept % value for the height. For example, with tinyscrollbar, i have to put this :
section .viewport {
width: auto;
height:440px;
overflow: hidden;
position: relative;
}
If I put "height:100%;" or "height:auto;", the content disappears ! Why does it accept px and not % ? I'd like to understand it...
Which part of the JS/JQuery code should I change/add in order to insert the fluid height of the section ?
It's hard to follow without more example code (get in the habit of posting more code please), but I think something like this is what you're after.
--- Why don't you track the height of the context (outer div?) and the height of the inner div (section) and calculate them as they change?
var context_height = $("#context_div").height();
var section_height = $("section#id").height();
var percentage = section_height / context_height;
var measurement = percentage + "%";
$(section_height).css("height", measurement); // trigger this with a callback if heights need updating - possibly even re-initializing any scroll plugins, if necessary.

Categories

Resources