Get text using jquery with text-transform - javascript

I have an html element and i toggle its class and show capital/small letters with text-transform.
Is it possible to get the text its text-transform?
$('#toggle').click(function(){
$('#char').toggleClass('upper');
});
$('#getdata').click(function(){
var text = $('#char').text();
alert(text); /// here i need to get the actual word with capital/lower i selected
});
.upper{
text-transform:uppercase;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span contenteditable="true" id="char">a</span>
<br/>
<button id="toggle">Toggle case</button>
<button id="getdata">gat data</button>

you can check for the class and use toUpperCase:-
$('#toggle').click(function(){
$('#char').toggleClass('upper');
});
$('#getdata').click(function(){
var $char = $('#char');
var text = $char.hasClass('upper') ? $char.text().toUpperCase() : $char.text();
alert(text); /// here i need to get the actual word with capital/lower i selected
});
.upper{
text-transform:uppercase;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span contenteditable="true" id="char">a</span>
<br/>
<button id="toggle">Toggle case</button>
<button id="getdata">gat data</button>

There is currently no way to get the rendered text with JavaScript.
When you are using English, toUpperCase and toLowerCase works well for the CSS value uppercase and lowercase.
But when you need it for non-English, or when you use capitalize, full-width etc., you have to reproduce the CSS logic (mostly unicode logic) with JS.
Below is a few rules that Firefox is doing. Chrome also knows some of them.
In German (de), the ß becomes SS in uppercase.
In Dutch (nl), the ij digraph becomes IJ, even with text-transform: capitalize, which only put the first letter of a word in uppercase.
In Greek (el), vowels lose their accent when the whole word is in uppercase (ά/Α), except for the disjunctive eta (ή/Ή). Also, diphthongs with an accent on the first vowel lose the accent and gain a diaeresis on the second vowel (άι/ΑΪ).
And so on...
It's also fun when you need to apply other CSS values:
capitalize - What constitutes a "word"? How do browsers split iPhone-6s+? Behold, Unicode consortium to the rescue!
full-width - The MDN example looks easy, but it does not show them all, for example [] to [], and maybe someday they will convert ... to … instead of ...
full-size-kana - How's your Japanese? No worry, this CSS4 proposals is dropped - in preference of a (future) fully customisable character mapping rules! Hope your CSS parser skill is up to par.
So, count yourself lucky if you use only English. You have my consolation if you, like me, work with multilingual systems. Timezone is nothing at all.

Maybe like this?
// Store css to javascript values in this object
var textTypes = {
"uppercase": "toUpperCase",
"lowercase": "toLowerCase"
}
// get the element
var div = document.getElementsByTagName('div')[0];
// get the computed style type
var type = window.getComputedStyle(div)['text-transform'];
// print the transformed text
console.log(div.innerHTML[textTypes[type]]());
Working Fiddle

Related

JavaScript: Is there a way to revert or undo .innerHTML.toLowerCase();?

Is there a way to "reverse" changing the innerHTML of an element to lowercase? Example:
HTML:
<div class="wrapper">
<p>Some text.</p>
</div>
JavaScript:
someText = document.querySelector(".wrapper").innerHTML.toLowerCase();
console.log(someText)
// Console Log Output: "<p>some text.</p>"
Is there then a way to reverse, remove or undo the toLowerCase();, in order to return the paragraph text back to its original case? Obviously I can't just change it to UpperCase, as it will change all the text to uppercase instead of original case.
someText = document.querySelector(".wrapper").innerHTML.toLowerCase();
console.log(someText);
// Console Log Output: "<p>some text.</p>"
someText = document.querySelector(".wrapper").innerHTML.toUpperCase();
console.log(someText);
// Console Log Output: "<p>SOME TEXT.</p>"
However, toLowerCase(); and toUpperCase; were the only options I could find, nothing like toOriginalCase();. I want the console log to return <p>Some text.</p> again after I revert the change.
I am trying to use this method in a search functionality.
Currently on my website, https://www.codeeverydamnday.com/, if you search, for example, "Javascript" from the home page, you'll be brought to a page of search results that do indeed match and highlight the search term, but that is because I have lowercased everything on the page (as you can see in the first post, "day twenty-four", where I have several variations of the word "Javascript", like "javaScript" and "Javascript", that are all showing lowercase).
That is because I changed the search term to lowercase, then changed all the text on the results page to lowercase before I started matching the search term to its instances on the page and highlighting them. Once matched and highlighted, I would like to revert the text back to its original case and return that to the UI.
Edit: I also tried adding and then removing a style.textTransform = "lowercase"; , but kept running into issues with that.
You can simply store the original HTML on the element.
// nothing stops you from creating your own property on the div#wrapper element
// which you can use to store the original HTML in
wrapper.originalHTML = wrapper.innerHTML;
<div id="wrapper">
<p>Some text.</p>
</div>
<button onclick="wrapper.innerHTML = wrapper.innerHTML.toLowerCase()">toLowerCase()</button>
<button onclick="wrapper.innerHTML = wrapper.originalHTML">and back</button>
That being said, your whole toLowerCase() approach for searching is not what you need to do.
Instead, use regular expressions to do case-insensitive matching.
See this simple example:
s.addEventListener('input', () => {
let regex = new RegExp(s.value, 'gi');
console.log(text.innerText.match(regex));
})
<div id="text">foobar <span>FooBAR <i>fooBar</i> Foo</span>Bar foObAR</div>
<input type="search" id="s" placeholder="type "foobar" here">
Different answer, because the original post (prior to a fairly heavy edit) didn't mention this was for effecting text highlighting, having fallen in the trap of being a classic XY question (asking about how to undo property assignment when the real problem was how to get to look lowercase).
The actual solution here is to not do text replacement at all, but to make sure that the highlighting markup is tied to CSS, not JS, that ensures that no matter what case the text actually is in, it's presented as lowercase to the user, with a highlight background color:
p {
font-family: Verdana;
}
.highlight {
text-transform: lowercase;
background: #FFFF0050;
}
<p>
For example, to highlight <span class="highlight">JavaScript</span> in
this "paragraph" of <span class="highlight">TEXT</span>.
</p>
The page text casing never changes, but the presentation does. We get "everything in lowercase" entirely for free without needing any textContent or innerHTML caching, or needing to "undo" anything with respect to the source. CSS only changes the way our source is presented, and the moment we take the highlight class (or outer tags) away, the effect goes away and we see the original text case again.
You can refer to the first letter of the text by converting that letter to toUpperCase():
someText.charAt(0).toUpperCase() + someText.substring(1)
The first console shows the result from toLowerCase(). And the second console simulates the primary state of the text based on toLowerCase() above.
let someText = document.querySelector(".wrapper p").innerHTML.toLowerCase();
console.log(someText);
console.log(someText.charAt(0).toUpperCase() + someText.substring(1));
<div class="wrapper">
<p>Some text.</p>
</div>
Short answer: no.
Longer answer: no, because innerHTML (and textContent, which you should be using instead for text, never use innerHTML unless you're actually building HTML, and even then, using the DOM methods is almost always better) are standard object properties on DOM nodes, and if you overwrite a property with a new value, that's its new value. There is nothing to restore, because the only thing that exists is the current value.
Of course, you can certainly reformat the string after the fact (e.g. capitalising every first letter in a sentence) but the original value is lost: this will be a new operation, based the exising lowercase string.

Contenteditable regex whitespace not working

I am trying to validate if the contenteditiable value has only whitespace/blank space. In my example if the value have only whitespace/blank space it should not match according to my regex string, but it not working as intended. It keeps matching when I enter complete blank spaces.
edit: the black space is where you can enter text.
https://jsfiddle.net/j1kcer26/5/
JS
var checkTitle = function() {
var titleinput = document.getElementById("artwork-title").innerHTML;
var titleRegexp = new RegExp("^(?!\s*$).+"); //no blank spaces allowed
if (!titleRegexp.test(titleinput)) {
$('.start').removeClass('active-upload-btn');
console.log('no match')
} else if (titleRegexp.test(titleinput)) {
$('.start').addClass('active-upload-btn');
console.log('match')
}
};
$('#artwork-title').on('keyup change input', function() {
checkTitle();
});
HTML
<div class="post-title-header">
<span class="user-title-input title-contenteditable maxlength-contenteditable" placeholder="enter text here" contenteditable="true" name="artwork-title" id="artwork-title" autocomplete="off" type="text" spellcheck="false">
</span>
</div>
<div class="start">
turn red if match
</div>
If you look at the actual inner HTML, you'll see things like <br> elements or entities. Your regex doesn't look equipped to handle these.
You may want to consider using textContent instead of innerHTML if you just care about the text, not the HTML. Or alternatively, if you really want plain text, use a <textarea/> instead of a content-editable div, which is for rich-text-style editing that produces HTML.
Edit:
Your regex is not quite right either. Because you're using the RegExp constructor with new RegExp("^(?!\s*$).+"), the \s in your string literal is going to turn into a plain s; you have to use a \\s if you want the regex to have an actual \s in it. IMO, it's always better to use a regexp literal unless you're building one dynamically, like /^(?!\s*$).+/, or I find this to be a simpler alternative to tell you if a string is entirely whitespace: /^\s+$/.

Spacing different in original html rendering vs dynamic JS rendering

Here is a small part of my page:
<a href="#" onclick="PolicyViolation(<%: ViewBag.DeviceData[i].DeviceID%>); return false;">
<span class="policyViolationsNumber"><%= ViewBag.DeviceData[i].ViolationCount%></span>
<span>Policy Violations</span>
</a>
This renders out to have some space between the two spans.
In code, we update this in JS:
var spanViolationNumber = $('<span>')
.html(statusModel.Violations)
.addClass('policyViolationsNumber');
var spanViolationString = $('<span>')
.html('<%=ServiceSite.Resources.Resources.DEVICES_POLICY_VIOLATIONS%>');
var imageTag = $('<img>')
.attr('src', '/Content/images/error_error.png')
.attr('align', 'absmiddle');
var anchorTag = $('<a href="#">')
.append(spanViolationNumber)
.append(spanViolationString);
cell.empty();
cell.append(imageTag)
.append(anchorTag);
However, this renders out with no space between the spans. I've seen small issues like this before but never figured out what it is. You can ignore the image tag stuff, it is irrelevant.
EDIT:
Didn't know about this, I guess it's expected behaivor: http://jsfiddle.net/2MMuA/
The extra space is happening because of the way you are formatting your HTML.
The "span" tag is an inline HTML element. This basically means you need to treat it just as you would treat text on the page.
<span>Hello</span> <span>World</span>
<!-- Prints Hello World -->
<span>Hello</span>
<span>World</span>
<!-- Prints Hello World
The line break is where your extra space is coming from. -->
<span>Hello</span><span>World</span>
<!-- prints HelloWorld
This is how the ".append()" function is formatting the HTML.
It adds it literally right after the last character in the HTML. -->
In order to normalize this across the two different techniques, you either have to butt your "span" tags right up next to each other so the HTML doesn't add an extra space...
<span></span><span></span>
..or you need to manually add the space in your ".append()" function.
obj.append(' ' + spanTag);
I hope that helps!
Perhaps you could clarify .. are you talking about there being space between these spans?
<span class="policyViolationsNumber">12</span>
<span>Policy Violations</span>
Either way I would look at adding some padding or margin to your css to insure you get the space that you want OR at minimum (though not recommended) use an HTML encoded space like so
There is most likely spaces between your spans. If you put the spans exactly next to each other then there should be no spaces.
<span></span><span></span>

Jquery replace character and apply classes

I have several string in the following format
<span class="label">20€</span>
And want to convert it all to something like this:
<span class="label">20<small>€</small></span>
How could I achieve this in Jquery?
I'd suggest:
$('.label').html(function(i,h){
return h.replace(/([^\d+])/,'<span class="small">$1</span>');
});
JS Fiddle demo.
Bearing in mind that I'm choosing to use span with a class of small, rather than a small element.
Under HTML 5, though, remember that the small element is:
repurposed to represent side-comments and small print, including copyright and legal text, independent of its styled presentation.
Source: https://developer.mozilla.org/en-US/docs/HTML/Element/small.
If the currency symbol is predictable, you could explicitly replace the € character (rather than using the above to replace, essentially, 'not-numbers'):
$('.label').html(function(i,h){
return h.replace(/(€)/,'<span class="small">$1</span>');
});​
JS Fiddle demo.
Or, assuming the currency symbols are known in advance, you could specify the symbols to be replaced (using regular expressions again, though):
$('.label').html(function(i,h){
return h.replace(/([€£$])/,'<span class="small">$1</span>');
});​
JS Fiddle demo.
References:
html().
Regular expressions.
String.replace().
It works, but is affecting other strings that doesn't have the €
character. I mean other spans with the same class, it changes the
first letter or those strings. Figure I have other strings with this
syntax: <span class="label">request price</span>
HTML:
<span class="label currency">20€</span>
Note 1: Added additional class currency to identify the span that needs to be modified.
Note 2: Use a span instead of small as all styles elements are re purposed. (Thanks #David). Read more info #MDN https://developer.mozilla.org/en-US/docs/HTML/Element/small
You can use replace function like below,
$(function () {
$('span.label.currency').html(function(i, v) {
return v.replace('€', '<small>€</small>');
});
});

Javascript regex not working as intended

I have the HTML from a page in a variable as just plain text. Now I need to remove some parts of the text. This is a part of the HTML that I need to change:
<div class="post"><a name="6188729"></a>
<div class="igmline small" style="height: 20px; padding-top: 1px;">
<span class="postheader_left">
RuneRifle
op 24.08.2012 om 21:41 uur
</span>
<span class="postheader_right">
Citaat Bewerken
</span>
<div style="clear:both;"></div>
</div>
<div class="text">Testforum</div>
<!-- Begin Thank -->
<!-- Thank End -->
</div>
These replaces work:
pageData = pageData.replace(/href=\".*?\"/g, "href=\"#\"");
pageData = pageData.replace(/target=\".*?\"/g, "");
But this replace does not work at all:
pageData = pageData.replace(
/<span class=\"postheader_right\">(.*?)<\/span>/g, "");
I need to remove every span with the class postheader_right and everything in it, but it just doesn't work. My knowledge of regex isn't that great so I'd appreciate if you would tell me how you came to your answer and a small explanation of how it works.
The dot doesn't match newlines. Use [\s\S] instead of the dot as it will match all whitespace characters or non-whitespace characters (i.e., anything).
As Mike Samuel says regular expressions are not really the best way to go given the complexity allowed in HTML (e.g., if say there is a line break after <a), especially if you have to look for attributes which may occur in different orders, but that's the way you can do it to match the case in your example HTML.
I need to remove every span with the class postheader_right and everything in it, but it just doesn't work.
Don't use regular expressions to find the spans. Using regular expressions to parse HTML: why not?
var allSpans = document.getElementsByClassName('span');
for (var i = allSpans.length; --i >= 0;) {
var span = allSpans[i];
if (/\bpostheader_right\b/.test(span.className)) {
span.parentNode.removeChild(span);
}
}
should do it.
If you only need to work on newer browsers then getElementsByClassName makes it even easier:
Find all div elements that have a class of 'test'
var tests = Array.filter( document.getElementsByClassName('test'), function(elem){
return elem.nodeName == 'DIV';
});

Categories