<p class="example">i want to split this paragraph into
words and fade them in one by one</p>
the jquery/js:
$(document).ready(function() {
var $txt = $(".example")
,$words = $txt.text()
,$splitWords = $words.split(" ");
$txt.hide();
for(i = 0; i < $splitWords.length; i++){
// i want fade in each $splitWords[i]
//$splitWords[i].fadeIn(.... - i tried this doesnt work
}
});
im trying to split the paragraph into words, and fade them in one by one, thier might be an easier way to do this without splitting the words, please shed some light on this. thanks
Text by itself can't have an opacity, therefore you must wrap the text with an element that can have opacity (such as a span). You can then fade in those spans.
Try this:
http://jsfiddle.net/6czap/
var $el = $(".example:first"), text = $el.text(),
words = text.split(" "), html = "";
for (var i = 0; i < words.length; i++) {
html += "<span>" + words[i] + " </span>";
}
$el.html(html).children().hide().each(function(i){
$(this).delay(i*500).fadeIn(700);
});
Update for benekastah: http://jsfiddle.net/6czap/3/
var $el = $(".example:first"), text = $.trim($el.text()),
words = text.split(" "), html = "";
for (var i = 0; i < words.length; i++) {
html += "<span>" + words[i] + ((i+1) === words.length ? "" : " ") + "</span>";
};
$el.html(html).children().hide().each(function(i){
$(this).delay(i*200).fadeIn(700);
});
$el.find("span").promise().done(function(){
$el.text(function(i, text){
return $.trim(text);
});
});
You will need to fade in elements, text nodes can't have a opacity.
See demo at jsfiddle.net
var p = $("p.example").hide(); // possible flash! You should add some script
// to the <head> that writes a stylesheet
// to hide them right from the start
(function oneParagraph(i) {
if (p.length <= i)
return;
var cur = p.eq(i),
words = cur.text().split(/\s/),
span = $("<span>"),
before = document.createTextNode("");
cur.empty().show().append(before, span);
(function oneWord(j) {
if (j < words.length) {
span.hide().text(words[j]).fadeIn(200, function() {
span.empty();
before.data += words[j]+" ";
oneWord(j+1);
});
} else {
span.remove();
before.data = words.join(" ");
setTimeout(function(){
oneParagraph(i+1);
}, 500);
}
})(0);
})(0);
If you need only one paragraph, you can leave out all the things beloning to the oneParagraph function - just make cur the selected element.
If you want to have a smoother animation, you'd need to animate multiple words at the same time (demo), or dont fade but append letterwise like in here. Alternatively you could make the fading-time dependent on the length of the current word.
You'll have a couple problems with the suggestions mentioned so far.
First, splitting and then hiding the text in Javascript will result in a Flash of Unstyled Content. Second, the number of reflows is going to be pretty bad for long text.
Rather than hiding the text, consider setting the foreground and background to the same color, and then changing it back.
Related
I am trying to make a hashtag system, so I reached the edit text feature where I want to replace the entered edit with hashtag links if the user type hashtag words. So I am using JavaScript and jQuery to do this but the problem is that the for loop is only replacing the last word in the string and not all the string with a links.
// Turn hashtags into links
var discussionText = "#example #text #string #one #two #three #hashtag #word";
var wordsArray = discussionText.split(" ");
for (i = 0; i < wordsArray.length; i++) {
console.log(i);
if (wordsArray[i].indexOf('#') > -1) {
var wordWithoutHashtag = wordsArray[i].replace("#", "");
console.log(wordWithoutHashtag);
$("#" + editDiscussionButtonId + "-" + editDiscussionButtonUserId + "-spanDiscussionEdit").html(function() {
return $(this).text().replace(wordsArray[i], "<a href='search.php?sec=all&q=" + wordWithoutHashtag + "' class='hashtag_link'>" + wordsArray[i] + "</a>");
});
}
}
Change the html(function) to use the existing html argument. When you use text() it doesn't return the previous <a> you created in previous iterations of the loop, only the text inside the <a>.
$(selector).html(function(index, existingHtml){
return existingHtml.replace(wordsArray[i], ....
});
Similarly if you just changed $(this).text().replace.. to $(this).html().replace... it would work.
A more efficient approach would be the get the existing content once before the loop and do all the modifications to the string stored in variable, then replace the modified content once after the loop completes
After i posted this question, i continue trying with solutions until i came up with the below which works perfectly for all cases tags
var discussionText = "#example #text #string #one #two #three #hashtag #word";
var wordsArray = discussionText.split(" ");
var fullText = "";
for(i=0; i < wordsArray.length; i++) {
if (wordsArray[i].indexOf('#') > -1) {
var wordWithoutHashtag = wordsArray[i].replace("#", "");
var wordLink = wordsArray[i].replace(wordsArray[i], "<a href='search.php?sec=all&q="+wordWithoutHashtag+"' class='hashtag_link'>"+wordsArray[i]+"</a>");
fullText += " " + wordLink;
$("#"+editDiscussionButtonId+"-"+editDiscussionButtonUserId+"-spanDiscussionEdit").html(fullText);
} else {
fullText += " "+wordsArray[i];
}
}
So I have following html:
<div class="container"> some beautiful text here </div>
What I want is:
<div class="container"> some <span class="highlight">beautiful</span> text <span class="highlight">here</span>
I know how to do it knowing the word. Thanks to this question: How to highlight text using javascript
But I have to highlight text at specific positions. I have a start and end positions of the string. I've tried iterating through the list of start and end positions like this:
function highlight(divId, startPos, endPos) {
inputText = document.getElementById(divId);
var wholeText = inputText.innerText;
var inHTML = wholeText.substring(0, startPos) + "<span class='highlight'>" + wholeText.substring(startPos, endPos-1) + "</span> " + wholeText.substring(endPos, wholeText.length);
document.getElementById(divId).innerHTML = inHTML;
}
function highlightAll(fileA, fileB, JSONfile) {
var startPositionsA = extractStartPosA(JSONfile);
var endPositionsA = extractEndPosA(JSONfile);
var startPositionsB = extractStartPosB(JSONfile);
var endPositionsB = extractEndPosB(JSONfile);
for(var i=0; i < startPositionsA.length; i++) {
highlight("TextA", startPositionsA[i]-1, endPositionsA[i]);
}
for(var i=0; i < startPositionsB.length; i++) {
highlight("TextB", startPositionsB[i]-1, startPositionsB[i]);
}
}
But the innerhtml is re-written after every iteration, so in the end I just get one single word highlighted - the one that is left after the last iteration.
Could anyone please help me? I do not have any ideas where to go further. Thank you!
Is this what you want?
function highlight(id, start, end) {
var html = document.getElementById(id).innerHTML;
document.getElementById(id).innerHTML= [html.slice(0, start), '<span class="highlight">', html.slice(start, end), '</span>', html.slice(end)].join('');
}
if yout get the correct position in startPosition and endPosition you can create a var containing the highlighting:
var highlightStart = "<span class='highlight'>";
var highlightEnd = "</span>";
just split your text at the positions into parts and put together the parts and the highlighting vars in the correct order
I have the following javascript function that aims to append a BIDI code to text that matches a specific criteria.The problem with the current function is that it works great with text only content but is problematic with content that has HTML Content. To summarize, I am splitting the text into words and checking if any of the characters in each word is matching a certain criteria to append the BIDI code to it.
The current status:
<div>This is the text that I am processing</div> //This works great
<div><span>This is the text</span><p>that I am processing</p></div> // This doesn't work well.
I want the function to work is for the text but also to keep the wrapping HTML tags in their place in order to keep etc....
function flipper(flipselector) {
var pagetitle = $(flipselector);
var text = pagetitle.text().split(' '); //I know that I am using text function here but .html didn't work either
var newtext="";
for( var i = 1, len = text.length; i < len; i=i+1 ) {
//text[i] = '<span>' + text[i] + '</span>';
newstring="";
if (matches = text[i].match(/\d/))
{
var currentstring=text[i];
for (var x = 0, charlen = currentstring.length; x < charlen; x++) {
if (matches = currentstring[x].match(/\d/)) {
varnewchar=currentstring[x];
}else {
varnewchar= "" + currentstring[x];
}
newstring=newstring + varnewchar;
}
} else {
newstring= text[i];
}
newtext=newtext + " " + newstring;
}
pagetitle.html(newtext);
}
How do i use javascript/jquery to select all $('td.created') and split the html on <br>, then wrap each section in span tags (so that i can add a class to span:first in order to style it).
The format of the string which is returned from $('td.created').html() is something like
posted by User123 <br> Posted on 1/2/12 at 4:15PM
Possible universal solution (works not only for 2 lines):
$("td.created").each(function() {
var text = this.innerHTML.split("<br>");
for (var i = 0; i < text.length; i++) {
var span = $("<span />").html(text[i]);
if (i == 0) span.addClass("first");
span.appendTo("#element");
}
});
DEMO: http://jsfiddle.net/7xQAL/
$('td.created').each(function(i, html) {
var newHtml = $(this).contents(),
spans = [];
newHtml.each(function() {
var html = (this.nodeName.toLowerCase() == 'br') ? '<br>' : '<span>' + this.textContent + '</span>';
spans.push(html);
});
$(this).html(spans.join(''));
});
DEMO ( using DIV Container)
http://jsfiddle.net/PVLek/
I've written a fairly simple script that will take elements (in this case, <p> elements are the main concern) and type their contents out like a typewriter, one by one.
The problem is that as it types, when it reaches the edge of the container mid-word, it reflows the text and jumps to the next line (like word wrap in any text editor).
This is, of course, expected behavior; however, I would like to pre-format the text so that this does not happen.
I figure that inserting <br> before the word that will wrap would be the best solution, but I'm not quite sure what the best way to go about doing that is that supports all font sizes and container widths, while also keeping any HTML tags intact.
I figure something involving a hidden <span> element, adding text to it gradually and checking its width against the container width might be on the right track, but I'm not quite sure how to actually put this together. Any help or suggestions on better methods would be appreciated.
Edit:
I've managed to write something that sort of works using jQuery, although it's very sloppy, and more importantly, sometimes it seems to skip words, and I can't figure out why. #content is the name of the container, and #ruler is the name of the hidden <span>. I'm sure there's a much better way to do this.
function formatText(html) {
var textArray = html.split(" ");
var assembledLine = "";
var finalArray = new Array();
var lastI = 0;
var firstLine = true;
for(i = 0; i <= textArray.length; i++) {
assembledLine = assembledLine + " " + textArray[i];
$('#ruler').html(assembledLine);
var lineWidth = $('#ruler').width();
if ((lineWidth >= $('#content').width()) || (i == textArray.length)) {
if (firstLine) { var tempArray = textArray.slice(lastI, i); }
else { var tempArray = textArray.slice(lastI+1, i); }
var finalLine = tempArray.join(" ");
finalArray.push(finalLine);
assembledLine = "";
if (lineWidth > $('#content').width()) { i = i-1; }
lastI = i;
firstLine = false;
}
}
return finalArray.join("<br>");
}
You could use the pre tag: Which displays pre-formatted text, or you could put the content into a div tag, set a fixed width, and script based upon that.
The best way (IMO) would be to add the whole word, but have the un-"typed" letters invisible. E.g:
H<span style="visibility: hidden;">ello</span>
He<span style="visibility: hidden;">llo</span>
Hel<span style="visibility: hidden;">lo</span>
Hell<span style="visibility: hidden;">o</span>
Hello
To make it easier, give the span a name, and delete it from the DOM each time.
A possible approach is to set p display inline (because default display-block will make p to consume all width even if it has just 1 character) and then as you 'type' check the element width.
Set a tolerance in px (25px for example) and once p's width reaches total available width minus width tolerance you insert <br />
I think this should work...
After playing with the code I edited into the question, I managed to get it working decently.
Code:
function formatText(html) {
var textArray = html.split(" ");
var assembledLine = "";
var finalArray = new Array();
var lastI = 0;
var firstLine = true;
for(i = 0; i <= textArray.length; i++) {
assembledLine = assembledLine + " " + textArray[i];
$('#ruler').html(assembledLine);
var lineWidth = $('#ruler').width();
if ((lineWidth >= $('#content').width()) || (i == textArray.length)) {
if (firstLine) { var tempArray = textArray.slice(lastI, i); }
else { var tempArray = textArray.slice(lastI+1, i); }
var finalLine = tempArray.join(" ");
finalArray.push(finalLine);
assembledLine = "";
if (lineWidth >= $('#content').width()) { i = i-1; }
lastI = i;
firstLine = false;
}
}
return finalArray.join("<br>");
}
Not perfect, but it'll do. Thanks, everyone.