I'm fighting over a way to have text wrap nicely to fit into set div boxes. Browsers wrap the text if it's too long to fit on one line which is expected, but this can often lead to rather nasty looking presentation.
For example, this looks fine:
This is the title
But if I have a longer title, it may end up wrapped like this:
This is a slightly longer
title
As you can see the second one doesn't really look very nice, what I'm aiming for is something like this:
This is a nicer
wrapped title
I know how big the containing DIV will be, so that's not a problematic variable, but I'm trying to wrap my mind around all the possible ways of achieving nicely formatted titles and their flaws. So the question is, what would be the best way of doing this? I can think of a few ways, but they start to get exponentially more complicated if it wraps over more than 2 lines.
EDIT:
I'm currently using this - https://xnode.org/paste/19 - to try and even out the split lines, although I'm sure it's far from perfect.
You can remove the newlines and then use wordwrap function
Sounds like a job for the wordwrap function http://php.net/manual/en/function.wordwrap.php
Try using wordwrap function and give this CSS for the DIV:
div {
text-align: justify;
}
If http://fittextjs.com/ doesn't do the trick, try something along these lines...
Count the characters in your title and decide if it is going to need 1 line, 2 lines 3 lines, etc. (there will be some trial & error involved)
Replace all the spaces apart from where you want line breaks with (non-breaking spaces) and let the browser do the word wrapping.
In other words, in your This is a nicer wrapped title example, there are 29 letters, so you need a break around half way or just after, so replace the first non-breaking space after position 14 or 15 with a regular space ie between 'nicer' and 'wrapped', and that should do the job. Same thing in thirds or quarters for longer lines.
Sorry no code but from the examples you gave above you should be ok coming up with your own implementation.
I've created this jQuery plugin that does what you want
$.fn.prettyBreak = function () {
return this.each(function () {
var element = $(this);
var elementLineHeight = element.css("line-height").replace("px", "");
var elementContent = element.contents();
element.wrapInner("<span style='white-space: nowrap'>");
element.find("br").remove();
var textWidth = element.find("span").width();
element.html(elementContent);
var elementText = $.trim(element.text());
if (element.is(":visible") && textWidth > element.width() && element.height() < elementLineHeight * 2.1) {
var middle = Math.floor(elementText.length / 2);
var before = elementText.lastIndexOf(" ", middle);
var after = elementText.indexOf(" ", middle + 1);
if (middle - before < after - middle) {
middle = before;
} else {
middle = after;
}
var s1 = elementText.substr(0, middle);
var s2 = elementText.substr(middle + 1);
element.html(s1 + "<br> " + s2); // note the space after the tag
} else {
element.html(elementText);
}
if (element.is(":visible")) {
element.css("opacity", 1);
}
});
}
Usage:
$(document).on("ready", function () {
$(".pretty-break:visible").prettyBreak();
setInterval(function () {
$(".pretty-break:visible").prettyBreak();
}, 1000);
});
Github link: https://github.com/SumoSoft/PrettyBreak
Related
I am creating a product configurator with Jquery. My users can add custom text lines to their product. So you could create say... 4 text lines with custom text.
I need to know what the best way to add and delete these lines would be. Currently I have the following code for adding lines...
//Add Text Button
$('a#addText').live('click', function(event) {
event.preventDefault();
//Scroll up the text editor
$('.textOptions').slideUp();
$('#customText').val('');
//count how many items are in the ul textList
var textItems = $('ul#textList li').size();
var nextNumber = textItems + 1;
if(textItems <= 5) {
//Change input to reflect current text being changed
$('input#currentTextNumber').val(nextNumber);
//Append a UL Item to the textList
$('ul#textList').append('<li id="textItem'+nextNumber+'">Text Line. +$5.00 <a class="deleteTextItem" href="'+nextNumber+'">Delete</a></li>');
//Scroll down the text editor
$('.textOptions').slideDown();
}else {
alert('you can have a maximum of 6 textual inputs!');
}
});
I'm probably not doing this the best way, but basically i have an empty UL list to start with. So when they click "Add Text Line" it finds out how many list elements are in the unordered list, adds a value of 1 to that and places a new list element with the id TextItem1 or TextItem2 or whatever number we're on.
The problem i'm running into is that when you click delete item, it screws everything up because when you add an item again all the numbers aren't correct. I thought about writing some kind of logic that says all the numbers above the one you want deleted get 1 subtracted from their value and all the numbers below stay the same. But I think i'm just going about this the wrong way.
Any suggestions on the easiest way to add and delete these text lines is appreciated.
Trying to increment ID's or classes in a situation where you will be adding and removing random ones is usually more of a headache than it is worth
Change to a single class for the items
<li class="textItem">
Your delete would look like
$('#textList').on('click','.textItem a', function(){/* note that live() is deprecated*/
$(this).parent().remove();
$('input#currentTextNumber').val( $('#textList li').length );/* note that size() is deprecated*/
return false;
});
If you have any other dynamic data storage or AJAX going on with server within any of this process there are likely simple ways to configure those too in conjunction with using common class for elements.
This should help
EDIT: Obviously references are something I should have taken into account.
Code was working, but without wanted references.
Well, then use this...
var currentIdx = $('ul#textList li').size();
$('a#addText').click(function(event) {
event.preventDefault();
//Scroll up the text editor
$('.textOptions').slideUp();
//count how many items are in the ul textList
var nextNumber = currentIdx++;
if($('ul#textList li').size() <= 5) {
//Change input to reflect current text being changed
$('input#currentTextNumber').val(nextNumber);
var newLi = $('<li class="textItem' + nextNumber + '">' +
$('#customText').val() +
'<a class="deleteTextItem" href="#">Delete</a></li>');
newLi.find('a.deleteTextItem').click(function() {
$(this).parent('li').remove();
})
//Append a UL Item to the textList
$('ul#textList').append(newLi);
$('#customText').val('');
//Scroll down the text editor
$('.textOptions').slideDown();
} else {
alert('you can have a maximum of 6 textual inputs!');
}
});
Here's the fiddle.
here's the problem:
<h2><b>Progress: </b> <font color="87edff">3 / 5</font> <b>Clicks</b></h2>
I want to make a script in PHP or Javascript to check the first number (3 in this case) and if it's larger than a certain number (5 for example), to do something such as show hidden text, open a link, etc.
Does anyone know how this can (or if it can't) be done? I thought of using POST + GET variables but failed with no success.
Use regex to get the 3/5 and then split on the / after that just compare it from within the array.
You could also as another route, name the element that contains the 3/5 and with jquery get that value. Then you would do the same, split the string on the / and compare it.
POST/GET is only available when submitting a form or sending data to a script on the serer. These are mainly used for textarea and inputs
If you're already using jquery, some fancy jquery selectors will do it:
http://jsfiddle.net/qPPsH/1/
findThings = function(){
// select the first <b> elements that contain "Clicks", AND
// has a sibling before it that is a <font>, AND
// has a sibling THAT has both an <h2> as a parent, and contains the text "Progress".
var firstnumber = -1; // some number that doesn't make sense
var secondnumber = -1;
$('h2 > b:contains("Progress:") + font + b:contains("Clicks"):first').each(
function(){
//alert("Element is:",this);
//alert("Element contains:" + $(this).text());
// "this" is the <b> that contains "Clicks". Find the first sibling that is a <font> and grab the text from it.
text = $(this).siblings("font:first").text();
//alert(text);
numbers = text.split("/"); //split the text by "/" character.
if (numbers.length == 2){ // make sure there are two numbers!
firstnumber = numbers[0];
secondnumber = numbers[1];
}
}
);
alert("First number:" + firstnumber);
alert("Second number:" + secondnumber);
var whatever = 5;
if(firstnumber >= whatever){
alert("YOU WIN!");
}else{
alert("You Lose!");
}
}
But this only works if the code is placed on the same site. If it's on the same site, then this is a horrible idea anyways since you could just stick an id on the element and access the value by id. Still, shows how cool selectors can be.
I have this little php snippet:
// $test='test';
$test='just a test';
echo "<a href=javascript:myfunction($number,$src_req,\"".$test."\")><img style='z-index:$z; src='images/$src'/></a>";
And i have this little ajax snippet...
function myfunction(param1,param2,param3)
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
HandleResponse2(xmlHttp.responseText);
}
}
var p1=param1;
var p2=param2;
var p3=param3;
xmlHttp.open("GET", "config/ajax_pop.php", true);
xmlHttp.send(null);
$( '#ResponseDiv2' ).dialog({
height: 140,
modal: true,
position: [490,140],
title:param3,
});
.....
I like to pass my $test php variable to my javascript function, but unfortunatelly if my $test variable contain space character then the JS script doesnt work. If my $test variable contain only one word, then work well.
In the browser when i check the link i see:
a, if $test variable contain only one word, then: javascript:myfunction(1,1,"test")
b, if $test variable contain more then one words then: javascript:myfunction(1,1,"just
Thank you for the help...
Use json_encode(): http://php.net/json_encode
Update: Here's a usage example:
<?php
$number = 1;
$src_req = 2;
$z = 3;
$src = 4;
$test = 'just a test
with spaces and new lines';
echo "<a href=javascript:myfunction($number,$src_req," . json_encode($test) .")><img style='z-index:$z; src='images/$src'/></a>";
If it doesn't work, try to find out in what exact way it's not working. A "Does not work" question is as useful as a "Then fix it" answer.
In any case, mixing PHP, HTML, JavaScript and CSS in one single line of code is not worth the effort even for quick testing. Separarte stuff in functions and files you'll make your life easier.
You must wrap the href itself with double quotes then the value with single quotes:
href=\"javascript:myfunction($number, $src_req, '".$test."')\"
You can escape the string with php function urlencode and can use javascripts unescape to unescape.
you have to parse the third parameter in your js function with unescape ...
as well you can use json as Álvaro G. Vicario mentioned.
I have a textarea inside a form.
Before the form is submitted, the textarea is validated and checked so it is not empty, not over 2000 characters, not contain forbidden characters etc...
I am working on the last part of the validation, which would need the textarea to be compared to an array of "bad words".
This to help me maintain and keep a good "language" on my site.
I am not very good on js, so does anybody know of a way to compare each word of the textarea to the array of bad words?
Also, would this slow down the validation much? (the array contains at most 100 words).
Thanks
If you wanted to check for the presence of "expletive1" and "expletive2" you'd do the following:
my_textarea = document.getElementById('textarea_id');
if (/\b(?=\w)(expletive1|expletive2)\b(?!\w)/i.test(my_textarea.value)) {
// we found bad words! do something
} else {
// no bad words found, carry on, nothing to see here
}
And you'd just add more words to the list in the same manner (expletive1|expletive2|expletive3|expletive4)
Keep in mind that to keep the words out of your app entirely you'll also need to do server-side filtering.
var bad_words = ['stupid', 'dang']; // watered down
for (var i = 0; i <= bad_words.length; i++) {
if (document.getElementById('my_textarea').value.match(bad_words[i])) {
// has bad word!
}
}
This will keep your code a bit neater, because you don't have to have 100 words in one regex match.
This code replaces bad words with *****
// creating regex
var words = ['bad', 'words'];
var wordsStr = "";
for(var i=0; i<words.length; i++) {
wordsStr += words[i];
if (i < words.length -1) {
wordsStr += "|";
}
}
// wordsStr is "bad|words"
var regex = new RegExp(wordsStr, "gi"); // g: replace all; i:insensitive
// replacing
var text = "I cant say bad words!";
text = text.replace(regex, "****");
// text is "I cant say **** ****!"
See in jsfiddle
var bad_words = new Array('word1', 'word2');
var user_words = document.getElementById('textarea').split(/\W+/);
for( var i in bad_words)
{
if( user_words.indexOf( bad_words[i] ) != -1 )
{
alert( 'The textarea has bad word!');
break;
}
}
You can downvote me if you want, but maybe just don't make the clbuttic mistake of trying to filter in the first place :D
How would I go about displaying a tooltip when the user hover overs some text / keywords? This body of text is directly retrieved from the database so I am unable to add any span or div tags or title information to these keywords. Is there a way to automatically create tooltips for certain words that are contained in the page?
Please let me know if there are any good tutorials available on how to solve this problem.
// Create tooltips dictionary
$tooltips = Array("Word1"=>"This word is word number 1",
"Word2"=>"This word is word number 2");
$content = "Here are Word1 and Word2";
foreach ($tooltips as $word=>$tip){
$content = preg_replace("/(".$word.")/", "<span title='".$tip."'>$1</span>", $content);
}
echo $content;
I had to do this a while ago. Actually I answered a similar question here: javascript: find strings in dom and emphasize it (took me a while to search for it).
Here's what I use to do the dynamic tooltip thing:
// keyword : tooltip
keywords = {
'hello world' : 'a common first example program',
'goodbye cruel world' : 'the opposite of hello world'
};
function insertTooltips (domNode) {
if (domNode.nodeType === Node.ELEMENT_NODE) { // We only want to scan html elements
var children = domNode.childNodes;
for (var i=0;i<children.length;i++) {
var child = children[i];
// Filter out unwanted nodes to speed up processing.
// For example, you can ignore 'SCRIPT' nodes etc.
if (
child.nodeName != 'span' ||
child.className != 'tooltip_span'
) {
insertTooltips(child); // Recurse!
}
}
}
else if (domNode.nodeType === Node.TEXT_NODE) { // Process text nodes
var text = domNode.nodeValue;
// This is another place where it might be prudent to add filters
for (var i in keywords) {
if (keywords.hasOwnProperty(i)) {
var match = text.indexOf(i); // you may use search instead
if (match != -1) {
// This is how you wrap the keyword in a span:
// create a span:
var span = document.createElement('SPAN');
// split text into 3 parts: before, mid and after
var mid = domNode.splitText(match);
mid.splitText(i.length);
// then assign mid part to span
mid.parentNode.insertBefore(span,mid);
mid.parentNode.removeChild(mid);
span.appendChild(mid);
// now we can assign a mouseover event handler to the span
span.onmouseover = function(){
showToolTip(keywords[i]);
}
// give the span a class name to prevent accidental
// recursion into it:
span.className = 'tooltip_span';
}
}
}
}
}
The implementation of the showTooltip function is left as an exercise for the reader.
The idea is basically to use DOM manipulation to dynamically search and wrap the keywords in spans and then assign a mouseover (or mouseclick, up to you) handler to the span to show the tooltip. On my website, the keyword/tooltip hash/object is generated from data pulled out of the database.
This is much more robust than trying to do this using regexp since it prevents accidental processing of words matching the keywords in class name, id and script tags.
Actually you can make use of span or whatever.
You have two options, the first is load the tooltip content at the first page request in a 'display: none' div or span, and then just show it up with an onmouseover event.
The second option is to perform an ajax request.
You should take a look at this: http://www.smashingmagazine.com/2007/06/12/tooltips-scripts-ajax-javascript-css-dhtml/