0

I know there are a lot of similar posts, but I have not thus far been able to solve this.

context:
User selects a home,
homes have unique titles,
depending on title, resize font to prevent overflow

JS Fiddle: https://jsfiddle.net/9uvpun5o/3/

$(function() {
    var that = $('#title'),
        planName = that.html().length
    ;
    // depending on html length, update font-size
    if(planName > 30) {
        that.css('font-size', '10px');
    } else if(planName > 20) {
        that.css('font-size', '12px');
    } else if(planName > 10) {
        that.css('font-size', '15px');
    }
});

Font is sized according to html length, but I need this to be reactive. I tried creating an .on("change") event, but failed to implement correctly. Help?

Right now I'm just updating the title from console,
$('#title').html("big long description thing");

But, this will be done by selecting from a modal menu in the future.

newswim
  • 430
  • 3
  • 7
  • `User selects a unit` How that? Your posted code doesn't implement it at all – A. Wolff Jun 12 '15 at 17:21
  • Without seeing more HTML it's hard to be sure, but you might checkout the css property word-wrap http://www.w3schools.com/cssref/css3_pr_word-wrap.asp – Michael Tallino Jun 12 '15 at 17:21
  • @A.Wolff that's right, it would've been more apt to say context there. The rest of that code hasn't been written yet. As I understand it, jQuery's 'change' function requires some sort of dom event. I might be able to cat this code alongside that. – newswim Jun 12 '15 at 17:33
  • [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/word-wrap) is a much better source of information [than](https://web.archive.org/web/20110117085131/http://w3fools.com/) [w3schools](http://www.w3fools.com/) – Stephen P Jun 12 '15 at 17:40

3 Answers3

2

EDIT

Ok, now I got it. Your JS should be this then:

$(function() {
    $('#title').on('DOMSubtreeModified', function() {
        var title = $('#title'),
            planName = title.html().length;

        // depending on html length, update font-size
        if(planName > 30) {
            title.css('font-size', '10px');
        } else if(planName > 20) {
            title.css('font-size', '12px');
        } else if(planName > 10) {
            title.css('font-size', '15px');
        }
    });

     $('li').on('click', function() {
         $('#title').text( $(this).text() );
     });
});

The DOMSubtreeModified should fire whenever the content of the element changes (as this modifies the DOM Subtree). The 'click' part is not necessary, but I've kept it for testing purposes.

According to Dottoro, Opera doesn't support this event and IE 9 and below may not support or be buggy.

For more options and informations, check these other StackOverflow question:


By what you said, an user will "select a unit":

use case: User selects a unit, units have unique titles, depending on title, resize font to prevent overflow

So, you need to change the font-size as part of this action. I used your code to make an example:

HTML

<ul>
    <li>On load, font size is set depending on length of title.</li>
    <li>However, I want this to be reactive...</li>
    <li>Change the length of Title and hit run</li>
    <li>Try clicking these itens</li>
    <li>You will see</li>
<ul>
<br/><br/>
<span id="title">TEST TEST</span><br/>

JS

$(function() {
    $('li').on('click', function() {
       var titleEl = $('#title').text( $(this).text() ),
           planName = titleEl.text().length;

        // depending on text length, update font-size
        if (planName > 30) {
            titleEl.css('font-size', '10px');
        } else if (planName > 20) {
            titleEl.css('font-size', '12px');
        } else if(planName > 10) {
            titleEl.css ('font-size', '15px');
        } 
    });
});

Try to click in the list itens. You see? As a response to "changing the unit", the title and font-size changes.

If this answer doesn't help you, give more details.

Community
  • 1
  • 1
Maurício Araldi
  • 389
  • 4
  • 12
  • Thanks for the reply, I think I need to edit my description though. Your code is correct and fulfills the dom event firing that 'change' looks for. However I just want a function that detects when the length changes, and then change then font-size. – newswim Jun 12 '15 at 17:43
  • Ok, added new info. See if my answer now solves your problem. – Maurício Araldi Jun 12 '15 at 19:47
  • THIS IS IT. Thank you, brilliant human! I would upvote this but I need 1 more rep. I will be writing a blog post soon and will give you (and the others who helped, like @Jeff Clarke) all the credit. Thank you, thank you. – newswim Jun 12 '15 at 22:16
  • Nice to know it helped you :). You can (and should, if it solved your problem) mark this as the correct answer. – Maurício Araldi Jun 12 '15 at 22:21
1

I might do this with a combination of a bit of CSS to prevent the text from wrapping, then I would use some script to measure the length of the rendered text. If it's longer than whatever your predetermined maximum width is, use the script to apply a CSS transform.

#title {
  white-space: nowrap;
  display: inline-block; /* necessary for the scale to actually work */
  transform-origin: 0% 100%; /* set transform origin to bottom left corner of the title element */
}

.maxwidth-container {
  width: 400px;
}

Then in your script:

var scaleTitle = function() {

  var $title = $("#title");
  var maxWidth = $(".maxwidth-container").width();
  $title.css("transform","scale(1,1)"); //reset to normal scale in order to measure natural width

  if ($title.width() > maxWidth) {
    var scaleAmt = maxWidth / $title.width();
    $title.css("transform" , "scale(" + scaleAmt + "," + scaleAmt + ")");
  }

};

In your case, I have wrapped your #title element in a container that dictates the maximum size, but you could use an explicit set amount.

Call this function every time the user selects a home.

Example here: https://jsfiddle.net/9uvpun5o/5/

Jeff Clarke
  • 1,369
  • 6
  • 7
  • Thank's for the cool answer! This does encounter the same issue i'm having -- how to make the function reactive. I realize that's a major topic and one reason a lot of tools are being developed, but I've got to believe there's a simple means of achieving this with jQuery. – newswim Jun 12 '15 at 17:55
  • I experimented with using `calc()` in the CSS to make this a CSS only solution, but I couldn't figure out how to reference the rendered width of the `#title` element. But `transform: scale( calc(400/450), calc(400/450) );` seems to work in browsers that support `calc`. if you can figure out how to replace `450` in the above example with the element's rendered width, then you would have your pure CSS solution. – Jeff Clarke Jun 12 '15 at 18:10
  • As far as I'm aware, there's no way to fetch html properties directly with css. This would be an amazing feature. Just to note, calc() is pretty widely supported: http://caniuse.com/#search=calc – newswim Jun 12 '15 at 18:23
  • This might be something that's easier to do with AngularJS. Make a variable for the #title name, and set a watch on it for every time it changes. Then call your routine to measure and scale it. – Jeff Clarke Jun 12 '15 at 18:31
  • Definitely. Anything that does a similar effect to object.observe would work, I'm really hoping to find a pure jQuery solution though. – newswim Jun 12 '15 at 18:32
  • Flex will scale the container, but not the font. As the container changes size based on its flex rules, text will wrap when there's no enough horizontal space, much the same way a normal container would. That's specifically why I've used the `scale()` CSS transform, as it will scale the element any all of its content. – Jeff Clarke Jun 12 '15 at 18:33
  • Was the example I gave you not pure jQuery enough? I'm assuming you're looking for it to automatically recognize the change in text. Maybe if you put the text in an INPUT field, styled to look like a regular container. Then you could put an `onChange` event on the field, which fires your rescale routine. – Jeff Clarke Jun 12 '15 at 18:35
0

This will work.TRy this

var planName = $("#title").text().length;

if(planName > 30) {
    $('#title').css("fontSize", "16px");
}else{ if(planName > 20) {
    $("#title").css("fontSize", "12px");
}else if(planName > 8) {
    $("#title").css("fontSize","24px")
}
Zohaib Waqar
  • 1,204
  • 11
  • 18