I want to create a paragraph that contains: name, cost (like "3.66$"). But the problem is that I want to fill the space in dots ("......") and I dont know how.
I take the values (name & cost) from database and each name is diffrent so I can not think about way that makes the space be filled with dots.
For instance, the rows:
"apple 20.58$"
"banana and ice cream 4.99$"
need to be:
"apple ...................... 20.58$"
"banana and ice cream ........ 4.99$"
this is the code:
for (var i = 0; i < data.d.length; i++) {
$(document).ready(function () {
$("#ShowMenu").append(
"<p style='text-align: left;margin: 0px;'>" +
"<span style='font-size: large;font-weight: bold;float:left;'>" + data.d[i].title + "</span>" +
"<span style='float:right;'>" + data.d[i].cost + "</span>" +
"</p>"
);
});
}
If you are replacing a value (and not a regular expression), only the
first instance of the value will be replaced. To replace all
occurrences of a specified value, use the global (g) modifier (see
"More Examples" below).
Souce.
The problem is that replace replaces the first found occurrence. You can do it like this:
function replaceAll(input, what, withWhat) {
while (input.indexOf(what) !== 0) {
input = input.replace(what, withWhat);
}
return input;
}
But this is not performant and not elegant. To improve it, you need to use regular expressions:
function replaceAll(input, what, withWhat) {
return input.replace(new RegExp(what, 'g'), withWhat);
}
and call replaceAll. If you want this to make it more general, you can do something like this:
String.prototype.replaceAll = replaceAll;
EDIT:
The answer above came from the assumption that the text is generated by Javascript. My assumption was wrong as can be seen from the comment section and the question edit. The real situation is that the spaces appear because of CSS styling with float.
A possible solution is to create an image of a dot character and another image with the desired background for the other contents. Set the background image of the paragraph to be the dot image with repeat and the background image of the span to be the colored image.
Another possible solution is not to use float, but to write the dots using javascript until the width is the desired one. This involves tag measuring and is slow.
You can use function like this:
function getReceiptItem(name, cost, maxLength) {
var dotsLength = maxLength - name.length - cost.length - '$'.length;
if (dotsLength < 0) {
name = name.substring(0, name.length + dotsLength);
dotsLength = 0;
}
return name + Array(dotsLength).join('.') + cost + '$';
}
Full example
Don`t forget set monospace font for receipt, like:
* {
font-family: 'monospace';
}
Related
I have a form now, and the number of words in the form is different.Now assume that the table size does not change and I want the font size in the table to change with the number of words.That is to say, the more words, the smaller the font and the last words, the bigger the front. Could you please tell me how to achieve this?
There may be a better way to do this, but you could use javascript. Example below:
var allTDs = document.querySelectorAll('td');
for (i=0; i<allTDs.length; i++){
var tdLength = allTDs[i].innerText.length;
if (tdLength<=100){
allTDs[i].style.fontSize="large";
} else if (tdLength>100 && tdLength<=200){
allTDs[i].style.fontSize="medium";
} else if (tdLength>200 && tdLength<=400){
allTDs[i].style.fontSize="small";
} else if (tdLength>400){
allTDs[i].style.fontSize="x-small";
};
};
Note: This example counts the number of characters in the innerText instead of the number of words. You could change it to count words instead - one way to get a rough count of words is to actually count the spaces " " in the innerText:
var tdLength = allTDs[i].innerText.split(" ").length;
Not certain if this can be done in regexp under javascript, but thought it would be interesting to see if it is possible.
So thought I would clean up a piece of html to remove most tags, literally just dropping them, so <H1><img><a href ....>. And that would be relatively simple (well, stole the basis from another post, thanks karim79 Remove HTML Tags in Javascript with Regex).
function(inString, maxlength, callback){
console.log("Sting is " + inString)
console.log("Its " + inString.length)
var regex = /(<([^>]+)>)/ig
var outString = inString.replace(regex, "");
console.log("No HTML sting " + outString);
if ( outString.length < maxlength){
callback(outString)
} else {
console.log("Lets cut first bit")
}
}
But then I started thinking, is there a way where I can control regex execution. So lets say that I want to keep certain tabs, like b,br,i and maybe change H1-6 to b. So in pseudo code, something like:
for ( var i in inString.regex.hits ) {
if ( hits[i] == H1 ) {
hits[i] = b;
}
}
The issue is that I want the text thats not HTML tags to stay as it is, and I want it to just cut out by default. One option would of course be to change the ones I want to keep. Say change <b> to [[b]], once that is done to all the ones of interest. Then put them back to <b> once all unknown have been removed. So like this (only for b, and not certain the code below would work):
function(inString, maxlength, callback){
console.log("Sting is " + inString)
console.log("Its " + inString.length)
var regex-remHTML = /(<([^>]+)>)/ig
var regex-hideB = /(<b>)/ig
var regex-showB = /([b])/ig
var outString = inString.replace(regex-hideB, "[b]");
outString = outString.replace(regex-remHTML, "");
outString = outString.replace(regex-showB, "<b>");
console.log("No HTML sting " + outString);
if ( outString.length < maxlength){
callback(outString)
} else {
console.log("Lets cut first bit")
}
}
But would it be possible to be smarter, writing cod ethat says here is a peice of HTML tag, run this code against the match.
As Tim Biegeleisen sai in its comment, maybe a better solution could be using a parser instead of a Regex...
By the way, if you want to control what is going to be changed by the regex you can pass a callback to the String.prototype.replace:
var input = "<div><h1>CIAO Bello</h1></div>";
var output = input.replace(/(<([^>]+)>)/gi, (val) => {
if(val.indexOf("div") > -1) {
return "";
}
return val;
})
;
console.log("output", output);
Following on from a previous question from 2011 titled Dynamic word swapping animation.
Thanks to Marek's answer I have been able to create an animation for text on a page that, every few seconds, changes one word out with another word from a list. However where previous question/ example was: "I have a header that says, "This is cool," but I want "cool" to be replaced every few seconds by "neat/awesome/groovy/etc".
I need my header to say eg, (for the sake of continuity) "This is cool man". The problem I have is that because the alternate words are longer it makes the sentence vary in length as it rotates through each of the words. Is there a way to specify, using Pure JS, for "man" to stay a set distance from "is", therefore the alternate words fill the gap between and the overall sentence remains the same length?
And, if the above is possible, can the alternate words be centred between "man" and "is"?
Any help greatly appreciated! Phil
The Pure JS I currently have (from previous post mentioned) reads:
<script>
var words = ["neat", "great", "best", "groovy"];
var i = 0;
var text = "This is cool";
function _getChangedText() {
i = (i + 1) % words.length;
console.log(words[i]);
return text.replace(/cool/, words[i]);
}
function _changeText() {
var txt = _getChangedText();
console.log(txt);
$("#changer").text(txt);
}
setInterval("_changeText()", 1000);
</script>
<span id="changer">This is cool</span>
This is more html/css thing... however, after few mods:
http://jsfiddle.net/X3wZV/1/
var words = ["neat", "great", "best", "groovy"];
var i = 0;
var text = "<span id='first'>This is</span> <span id='inner'>cool</span> <span id='sec'>man</span>";
function _getChangedText() {
i = (i + 1) % words.length;
console.log(words[i]);
return text.replace(/cool/, words[i]);
}
function _changeText() {
var txt = _getChangedText();
console.log(txt);
$("#changer").html(txt);
}
setInterval("_changeText()", 1000);
and a little styling (check CSS, change it according to your needs)...i think this is close to what you want, if i understand your question correctly... :)
Just use the 8th index of the string everytime and append man after the new word.
Is this what you mean?
I count the words in a contenteditable. I split it using spaces. The problem comes when you enter a new line. It doesn’t count the word you’re currently writing on the new line until you add a space.
On top of that, in the following example if you split the example text into two lines, it will “eat up” one word when you do that:
http://jsfiddle.net/MrbUK/
I’m guessing this issue exists because between HTML elements there are no spaces:
<div>some things</div><div>are cool</div> its string would be “some thingsare cool”.
Here’s the code that I have:
function wordCount() {
var content_text = $('#post_content').text(),
char_count = content_text.length,
word_count = 0;
// if no characters, words = 0
if (char_count != 0)
word_count = content_text.replace(/[^\w ]/g, "").split(/\s+/).length;
$('.word_count').html(word_count + " words • " + char_count + " characters");
}
I tried replacing some HTML tags:
word_count = content_text.replace(/ /g, " ").replace(/<div>/g, "<p>").replace(/<\/div>/g, "</p>").replace(/<\/p><p>/g, " ").split(/\s+/).length;
without any luck. I need to discard whether it’s a <p> or <div> and some browsers add when merging lines together.
Any ideas? Thanks!
EDIT:
Thanks to Jefferson below for his clever method, I managed to solve this. For some reason I have to do -1 on the word_count to display the correct number of words:
function wordCount() {
var content_div = $('#post_content'),
content_text,
char_count = content_div.text().length,
word_count = 0;
// if no characters, words = 0
if (char_count != 0)
content_div.children().each(function(index, el) {
content_text += $(el).text()+"\n";
});
// if there is content, splits the text at spaces (else displays 0 words)
if (typeof content_text !== "undefined")
word_count = content_text.split(/\s+/).length - 1;
$('.word_count').html(word_count + " words • " + char_count + " characters");
}
You can use this:
$("#post_content").children().each(function(index, el){buffer += $(el).text()+"\n"})
This way you iterate by all elements inside your div and get only the text, put a "\n" between them.
Jefferson's answer was great, and it helped me with this exact same issue.
The problem I encountered was the contents of my contenteditable div was not entirely wrapped in HTML tags.
For example, my div contained the following HTML code:
This is my first line<div>This is my second line</div>
By using $.children(), it was ignoring the first line and only returning a word count of 5. To get round this I used $.contents() instead. Modified code is below:
$("#post_content").contents().each(function(index, el){buffer += $(el).text()+"\n"})
This returned a line count of 10.
Apologies for adding this as an answer and not as a comment to Jefferson's answer, however my reputation is too low to allow me to do that. I felt it was worth pointing the above out though.
I have the below chunk of code. I've debugged through and located the snippet that is causing a long delay in IE6.
Basically the code loops through a document converting it to XML and sending to a PDF. On Ubuntu and Firefox 4 it takes 3 seconds. On IE it can take up to 40 seconds regularly.
/**
* This function builds up the XML to be saved to the DM.
*/
function getXMLToSave(){
var text="<workbook><sheet><name>Adv4New</name>";
//show_props(document.adv4.row10col1, "document.adv4.row10col1");
for(i=1;i<157;i++){
text = text + "<row number='" + i + "'>";
for(j=1;j<=7;j++){
text = text + "<col ";
//alert(eval('document.adv4.row'+i+'col'+j+'.readonly'));
try{
text = text + "number='" + j + "' label='" + eval('document.adv4.row'+i+'col'+j+'.className')+ "'";
}
catch (e) {
text = text + "number='" + j + "' label=''";
}
try {
if(eval('document.adv4.row'+i+'col'+j).readOnly)
text = text + " type='readonly'";
else
text = text + " type=''";
}
catch (e) {
text = text + " type=''";
}
try {
text = text + " color='" + eval('document.adv4.row'+i+'col'+j+'.style.color') + "'";
}
catch (e) {
text = text + " color=''";
}
text = text + ">";
try {
// don't wrap in a CDATA (like previously), but run cleanNode
// this fixes html entities
var content = eval('document.adv4.row'+i+'col'+j+'.value');
text = text + cleanNode(content);
}
catch (e) {
text = text + "0";
}
text = text + "</col>";
}
text = text + "</row>";
}
text = text + "</sheet></workbook>";
return text;
}
I believe its the eval function causing the delay in IE6. Is there a neat solution to fix this. Thanks very much
Why are you using eval in the firts place?
eval('document.adv4.row'+i+'col'+j+'.style.color')
Use bracket notation!
document.adv4["row"+i+"col"+j].style.color
You don't need eval() at all:
text = text + "number='" + j + "' label='" + document.adv4['row' + i + 'col' + j].className + "'";
Also, in IE6 (but not in newer browsers), building up large strings by repeatedly adding more content is really, really slow. It was way faster in that browser to build up strings by creating an array of substrings and then joining them all together when finished with all the pieces.
Don't use eval EVAL is EVIL. Having said that, you really shouldn't care about IE6: Even MS doesn't support it any longer, why should you bother?
Anyhow, change all eval calls like:
eval('document.adv4.row'+i+'col'+j+'.value');
to
document.adv4['row' + i + 'col' + j].value;
To access the elements directly. Remember that Nodes are objects, so their properties can be accessed either using the dot-notation (foo.bar) or the "associative array" notation: foo['bar'], the latter being very useful when you need the value of a variable to access properties
Don't use eval - period. The eval() should be renamed to evil(). There is almost no situation where you really need to use the eval function.
In this case you can use document.getElementById() to find a DOM node with a specific id.
It's likely that it's all the string concatentation that makes it slow. Each time you add something to the text, it will copy all the previous text into a new string.
Newer browsers have optimised code for this special case, so for them the impact is less.
Instead of concatenating strings like this:
text = text + "something";
use an array instead:
var text = [];
then add items to the array using the push method:
text.push("<workbook><sheet><name>Adv4New</name>");
Finally just join the strings together:
return text.join('');
One solution could be generating a color array (or maybe an object if you need it) and then using it.
But then, ask yourself the question "Should I really support IE6?"