Closed intelligence closed 10 years ago
Hey, thanks for being a personal beta tester. Could you post a jsfiddle?
Ha! No problem :)
http://jsbin.com/EbaR/1 Will this suffice? It's alot of code but it's from the context it's being used.
See http://jsbin.com/EbaR/3/edit
I can't tell without context of the application this code is in, but it seems awfully complicated for what it does. You may be able to get much better results by simply using percentage widths and heights on your centered div, rather than using JS to resize it. For example:
.container {
position: absolute;
height: 20%;
width: 30%;
left: 50%;
top: 50%;
text-align: center;
margin-left: -15%;
margin-top: -10%;
}
I did commit a fix to a bug that occurs when you nest elements inside the element you're resizing - it needed to be display: inline-block so that it resized correctly to its contents.
For example, if I use percentages I can simplify your code dramatically: http://jsbin.com/uMiW/3/edit
I'm keeping this ticket open for now because I want to ensure this works with alignVert, and it doesn't seem to yet.
That did it! But as you say, there's a trouble with alignVert when you cannot use display: table
. Not sure if it can be circumvented without js?
Thanks for your input by the way, my code is very complex for what it does in this demo, but on the site it handles images and videos with specific ratios, that's why, wasn't sure that any of it were interfering with your script.
@STRML Any idea of a work around? Been trying to hack my way around but with no luck. Really need the possibility to center both vertically and horizontally.
Hi STRML,
Firstly, this is a superb bit of JQuery. Love it.
I am relatively new to Javascript, and I have it working perfectly on initial page load, however, I also want the function to work on $(window).resize(function() .....
.
I have a one page website and the top element resizes dynamically with the window resize action as I wanted. As you will see below, the textFit call is in the same function, but does not work like the element resizing code does when resizing window.
function navNscroll(resizing){
var homePage = ("#homepage");
var headerHeight = $("#header").height(); // scrollHeight
var viewportHeight = $(window).height(); //scrollHeight
var homepagePadding = $(homepage).outerHeight() - $(homepage).height(); // scrollHeight
//var homepagePadding = $(homepageh).outerHeight(true);
var percentFactor = 0.66;
var heightAvailable = viewportHeight - headerHeight;
var homepageHeight = heightAvailable - homepagePadding;
homepageHeight = homepageHeight - parseInt($(".midbanner.one").css("margin-top"),10);
homepageHeight = homepageHeight * percentFactor;
remainder = heightAvailable - homepageHeight;
parseInt(homepageHeight);
var paddingVal = 20;
var homepageWidth = parseInt($(homePage).innerWidth(), 10) - (paddingVal * 2);
function fitText() {
$(homePage).height(homepageHeight).css("margin-bottom",remainder);
$(".midbanner.one .text").css("padding", paddingVal);
$('.bigText').css("width",homepageWidth).css("height", (homepageHeight - (paddingVal *2)));
$('.bigText').textFit({multiLine:true, alignVert:true, lineHeight:1.4, maxFontSize:40});
}
fitText();
if (resizing == "yes"){
fitText(); // tried this because I ran out of ideas
}
}
$(window).resize(function() {
navNscroll('yes');
});
I have also slightly changed your textFit.js code so I can control line-height:
(function($) {
$.fn.textFit = function(options) {
var settings = {
alignVert: false, // if true, textFit will align vertically using css tables
alignHoriz: false, // if true, textFit will set text-align: center
multiLine: true, // if true, textFit will not set white-space: no-wrap
detectMultiLine: true, // disable to turn off automatic multi-line sensing
minFontSize: 6,
maxFontSize: 80,
reProcess: false, // if true, textFit will re-process already-fit nodes. Leave to 'false' for better performance
widthOnly: false, // if true, textFit will fit text to element width, regardless of text height
lineHeight: 1.2 // JBReading: default is 1.2 x font-size
};
$.extend(settings, options);
return this.each(function(){
if (this.length === 0 || (!settings.reProcess && $(this).data('boxfitted'))) {
return $(this);
}
if(!settings.reProcess){
$(this).data('boxfitted', 1);
}
var innerSpan, originalHeight, originalText, originalWidth;
var low, mid, high;
originalText = $(this).html();
$(this).html("");
originalWidth = $(this).width();
originalHeight = $(this).height();
// Don't process if we can't find box dimensions
if (!originalWidth || (!settings.widthOnly && !originalHeight)) {
if (window.console != null) {
if(!settings.widthOnly)
console.info('Set a static height and width on the target element' + this.outerHTML +
' before using textFit!');
else
console.info('Set a static width on the target element' + this.outerHTML +
' before using textFit!');
}
return $(this).html(originalText);
} else {
// Add textfitted span
if (originalText.indexOf('textfitted') === -1) {
innerSpan = $("<span></span>").addClass("textfitted").html(originalText);
$(this).html(innerSpan);
} else {
$(this).html(originalText);
innerSpan = $(originalText).find('span.textfitted');
$(innerSpan).addClass("foundit");
// innerSpan = $("span.textfitted");
}
// Prepare & set alignment
if (settings.alignVert) {
$(this).css("display", "table");
innerSpan.css("display", "table-cell");
innerSpan.css("vertical-align", "middle");
}
if (settings.alignHoriz) {
$(this).css("text-align", "center");
innerSpan.css("text-align", "center");
}
// Check if this string is multiple lines
// Not guaranteed to always work if you use wonky line-heights
if (settings.detectMultiLine && !settings.multiLine &&
innerSpan.height() >= parseInt(innerSpan.css('font-size'), 10) * 2){
settings.multiLine = true;
}
if (!settings.multiLine) {
$(this).css('white-space', 'nowrap');
}
low = settings.minFontSize + 1;
high = settings.maxFontSize + 1;
// Binary search for best fit
while ( low <= high) {
mid = parseInt((low + high) / 2, 10);
innerSpan.css('font-size', mid);
if(innerSpan.width() <= originalWidth && (settings.widthOnly || innerSpan.height() <= originalHeight)){
low = mid + 1;
} else {
high = mid - 1;
}
}
// Sub 1
subOne = mid - 1;
innerSpan.css('font-size', subOne);
// JBReading:
newLineHeight = subOne * settings.lineHeight;
$(this).css('line-height', newLineHeight+"px");
}
});
};
})(jQuery);
The HTML:
<div class="midbanner one" id="homepage">
<div class="text fullwidth" >
<span class="bigText" style="width:300px;height:300px">
In eget tellus quis diam imperdiet condimentum sed quis mauris. Praesent enim purus, aliquet et mauris nec, malesuada luctus purus. Sed nec sapien semper, mattis purus vel, vehicula enim. Nulla vitae sagittis eros. Morbi risus magna, convallis in fringilla vitae, tempor sit amet quam. Cras aliquet diam nulla, a accumsan eros elementum sit amet. Duis molestie leo ac lorem convallis, et porttitor enim dictum.
</span>
<p class="clear"> </p>
</div>
</div><!-- end of midbanner one -->
Any ideas on this?
Thanks in advance.
First of all, @intelligence, sorry for not getting back to you. I'm exploring a vertical alignment strategy that eschews the table and table-cell stylings for a simple margin-top property equal to the (height of the container - the height of the inner span) / 2. Should be relatively simple. You could probably hack something like that in yourself, or wait, I'll likely put it in later as your test case has shown that display:table is really quite fiddly. I will need to do some testing to be sure that it doesn't break anything.
If you want to fix it, try the following around your textFit()
calls (with alignVert:false)
$(".textFitted").css("margin-top", 0);
textFit(...)
var margin = ($(".content").height() - $(".textFitted").height()) / 2;
$(".textFitted").css("margin-top", margin + "px");
@JBReading , feel free to open another issue if you have an unrelated question. But since you posted here, I'll answer here for now.
First, textFit has a reProcess
option. If it's set to true
, it will re-process an already-fitted node. This is necessary if you want to resize something again. I may flip the option in the future so it works this way by default; it won't break existing code though. In your case, you'll want to pass {reProcess: true}
.
Secondly, no need to modify the code to add line-height. Simply use CSS to set a line height of 1.2em on the container.
Hey @STRML! That's no problem, I realize that you probably don't maintain the plugin for a living :) I tried your quick fix, it works well! Although it seems it goes a bit off when you resize.
Have a look at my implementation here: http://eplusp.se/spotify-facebook/ Username is: dev Password is: lolboy
I took a look at it. There's something bizarre going on - basically, here's what I see:
Your automatic resizer is moving the container element around and it'll end up with a negative margin of some fractional number of px. I'll give you an example from what I see right now:
style="width: 555px; height: 295.2127659574468px; margin-left: -277.5px; margin-top: -147.6063829787234px; text-align: center;"
The issue is that the browser is doing some rounding here. In this particular case, the container has an offsetWidth of 555px
but the inner span has an offsetWidth of 556px
! On every measurement cycle, textFit
checks the width and sees if it has become bigger than its parent. The problem is, in every single case, it's bigger than its parent because of this bug, even when the text is too small to read. This is something I haven't seen before but it sort of makes sense; basically it's rounding on the fractional amounts a little incorrectly. Best I can tell is, the inner span is being aligned one px farther left on the pixel grid than its parent, resulting in it being one px larger when measured. Pretty weird!
The fix is pretty simple: in your resize function around line 1050, surround all your calculations that are being entered into .css()
in parseInt(value, 10)
calls. This will round them down to an integer value. Be especially careful to round the final values, not the intermediate ones. For example:
$this.find('section .content').each(function(){ // no need for additional $() wrapper
var t = { width: 940, height: 500, retina: false }
var d = ep.projects.calculate( t )
$(this)
.css('width', parseInt(d.w, 10))
.css('height', parseInt(d.h, 10))
.css({ marginTop: '-'+parseInt(d.h/2, 10)+'px', marginLeft: '-'+parseInt(d.w/2, 10)+'px' })
})
Good luck with the app!
Edit: You may have some luck with this novel centering technique.
Edit 2: I've illustrated the inner width problem. Play around with resizing the window and watch your console. It's achievable via simple percentage widths for the same reason. I've only tested in Chrome but it may happen elsewhere.
97a6ecf should help you with alignVert.
Wow, thanks, was not aware of that technique! The vertical align seems to work well but now it seems we're back to the issue where the font-size will not updated on resize. Stays on 32px while I'm narrowing the browser then it jumps straight to 6px.
You didn't update the textFit version.
Are you sure? I checked it and saw that a new class was applied with the new css. I grabbed the minified version.
.textFitAlignVert {
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
}
Edit: Tried with the full aswell, but same issue. Edit2: And the updated version seem to say v2.0.
Please open a new issue if you're still having problems.
Trying to hook this up with to a resize event but it doesn't seem to adjust the sizing. I tried setting reProcess to true but that wouldn't do much either. Do you have a demo or something for handling text resizing on browser resize events?
Thanks for a great piece of code, and that you're so keen on helping out :)