You have a file that outputs as such:
<div id="first">1</div>
2
<div id="third">
<? $i = 3; echo(i) ?>
</div>
Which outputs:
1
2
3
Now if I want to have an output as below:
?
?
?
Well, I was hoping I could output the Arabic/Farsi version of 1,2,3 instead of '?'. How can I use HTML/CSS convert to numbers to Arabic/Farsi?
And why does everything change except numbers when I change my language (Windows XP)?
If you want to number a list, you could use an ol element and change the list-style-type of it like:
ol {
list-style: arabic-indic;
}
Expanding on ShirzITCo and Kirk Woll's answer above -- which saved my but when client decided all the content in a WordPress CMS should use Eastern-Arabic numerals instead of the Western Arabic they started with:
function recursiveReplace(node) {
if (node.nodeType === 3) { // text node
node.nodeValue = node.nodeValue
.replace(/0/g,'۰')
.replace(/1/g,'۱')
.replace(/2/g,'۲')
.replace(/3/g,'۳')
.replace(/4/g,'۴')
.replace(/5/g,'۵')
.replace(/6/g,'۶')
.replace(/7/g,'۷')
.replace(/8/g,'۸')
.replace(/9/g,'۹');
} else if (node.nodeType === 1) { // element
$(node).contents().each(function () {
recursiveReplace(this);
});
}
}
recursiveReplace(document.body);
There is no automated way to change numbers, or even digits. Set up a mapping between then and convert manually.
Numbers are never localized, because unlike natural language words, Arabic numerals are understood across most of the world.
Simply use CSS:
ol {
list-style-type: persian
}
Use the following JavaScript code. This will replace numbers:
function recursiveReplace(node) {
if (node.nodeType == 3) { // text node
node.nodeValue = node.nodeValue.replace("1", "۱");
} else if (node.nodeType == 1) { // element
$(node).contents().each(function () {
recursiveReplace(this);
});
}
}
recursiveReplace(document.body);
Related
There are many possible values for list-style-type CSS property (e. g. decimal, lower-latin, upper-greek and so on). However there are none for the Cyrillic alphabet (which, btw, has different variations for different languages).
What is the best way to style an ordered list with Cyrillic letters?
(I'm providing a solution I ended up with despite I'm not very happy with it.)
I know nothing about Cyrillic list schemes so I’m at risk of a bit of cultural embarrassment here, but CSS3 Lists module (still in working draft) defines quite a few Cyrillic alphabetic list types: lower-belorussian, lower-bulgarian, lower-macedonian, lower-russian, lower-russian-full, lower-serbo-croatian, lower-ukrainian, lower-ukrainian-full, upper-belorussian, upper-bulgarian, upper-macedonian, upper-russian, upper-russian-full, upper-serbo-croatian, upper-ukrainian, upper-ukrainian-full. As expected, the state of support for these is deplorable currently (certainly nothing in Gecko or WebKit), but hopefully going forwards these will start to be implemented.
Update: some changes have been made – the definition of list types has been moved into the CSS3 Counter Styles module whose current draft (Feb 2015) has unfortunately lost all alphabetical Cyrillic types. This is in Candidate Recommendation stage so it’s unlikely that additions will be made at the point. Perhaps in CSS4 List Styles?
In this method I'm using CSS-generated content in before each list item.
.lower-ukrainian {
list-style-type: none;
}
.lower-ukrainian li:before {
display: inline-block;
margin-left: -1.5em;
margin-right: .55em;
text-align: right;
width: .95em;
}
.lower-ukrainian li:first-child:before {
content: "а.";
}
.lower-ukrainian li:nth-child(2):before {
content: "б.";
}
/* and so on */
Disadvantages
Hardcoded, restrict list to a certain max length.
Not pixel-perfect as compared to a regular order list
Here is another solution for Cyrillic letters with pretty clear code: jsfiddle.net
(() => {
const selector = 'ol.cyrillic',
style = document.createElement('style');
document.head.appendChild( style );
'абвгдежзиклмнопрстуфхцчшщэюя'.split('').forEach((c, i) =>
style.sheet.insertRule(
`${selector} > li:nth-child(${i+1})::before {
content: "${c})"
}`, 0)
);
})();
PS. You can convert this next-gen code to old one with Babel: babeljs.io
I'm surprised that there is no Cyrillic numbering. Here's a quick JS solution for you:
function base_convert(n, base) {
var dictionary = '0123456789abcdefghijklmnopqrstuvwxyz';
var m = n.toString(base);
var digits = [];
for (var i = 0; i < m.length; i++) {
digits.push(dictionary.indexOf(m.charAt(i)) - 1);
}
return digits;
}
var letters = {
'russian': {
'lower': 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя',
'upper': 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
}
}
$('ul, ol').each(function() {
if (!(results = $(this).prop('class').match(/(upper|lower)-([a-z]+)/i))) return;
var characters = letters[results[2]][results[1]];
$('> li', this).each(function(index, element) {
var number = '', converted = base_convert(++index, characters.length);
for (var i = 0; i < converted.length; i++) {
number += characters.charAt(converted[i]);
}
$(this).attr('data-letter', number);
});
});
My written Russian is admittedly bad, as you can see by my inability to count with letters, so change the letters object appropriately.
Demo: http://jsfiddle.net/JFFqn/14/
I would like to replace the content of an h1 element containing a character chain with the same chain but each character should be wrapped in a span.
That seemed easy enough to me, but I maybe underestimated it.
Here's what I tried (css only for debug purposes) :
var titleLen = $("#title").length - 1;
for (i=0; i<titleLen; i++) {
letter = $("#title").charAt(i);
$("#title").append("<span>" + letter + "</span>");
};
h1 span {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id=title>
Hello World !
</h1>
It isn't working but I can't find the problem. Any help ?
Part of the reason your current code isn't working is that you're calling length and charAt on the DOM element instead of on its contents -- but even with that corrected you're modifying the contents of the div at each step of the iteration, so the second charAt would wind up reaching part of the span you just inserted instead of the second character of the original string. (Edit: I've just realize this description isn't quite right; you would wind up with a span-wrapped copy after the original text, because you append instead of replacing.)
Here are a couple of different ways you could use your original algorithm:
// keep a copy of the original string and work from that:
var title = $("#title").html();
$('#title').html('');
for (i = 0; i < title.length; i++) {
letter = title.charAt(i);
$("#title").append("<span>" + letter + "</span>");
};
// Alternatively, build a string and dump it into the DOM all at once:
/*
let output = '';
for (i = 0; i < $('#title').html().length; i++) {
letter = $('#title').html().charAt(i);
output +="<span>" + letter + "</span>";
};
$('#title').html(output);
*/
h1 span {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id=title>
Hello World !
</h1>
Or a simpler way to do this is to split the string into an array for each character, then use 'join' to include the span tags:
$('#title').html(
'<span>' +
$('#title').html().split('').join('</span><span>') +
'</span>'
)
h1 span {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id=title>
Hello World !
</h1>
I realise that similar questions have been asked, but none quite like this.
I have a situation where I am using BEM to display some classes in code tags. Below is an example:
Obviously the default behaviour is to break words at a hyphen, as we can see is happening in the example. Is there a way that I can control what characters the line-break occurs at? I would like to be able to have class name integrity maintained so that the line break occurs before each period . if necessary.
I have another solution using jquery,
$('.mypara').each(function () {
var str = $(this).html();
var htmlfoo = str.split('.').join('</br>');
$(this).html(htmlfoo);
});
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<code class="mypara">
This is-the HTML if its - characters exceed 50. characters it should go-to next line
</code>
<code class="mypara">
This is the HTM-if its. characters exceed 50 - characters it should. go-to next-line
</code>
Unfortunately I don't think there is a way to do everything you want with pure CSS.
UPDATE: removed spaces before periods in JS solution.
If you are able to use JavaScript you could process the code tag's contents to disable wrapping for words with hyphens and you could wrap each block starting with a period in an inline-block span.
The following code breaks the contents of each code tag into a list of blocks that start with either space or period. Each block is wrapped with a span that prevents wrapping, and blocks that begin with a period are additionally marked as display: inline-block;. This should give the behaviour you are looking for, and additionally preserve all content when copy-pasting text.
CSS:
.no-wrap-hyphen {
white-space: nowrap;
}
.wrap-period {
display: inline-block;
}
JavaScript (run this function on window load and resize):
function wrapPeriodsNotHyphens() { // run on window load or resize
var codes = document.getElementsByTagName( "code" );
for ( var i = 0; i < codes.length; i++ ) {
currentCode = codes[ i ].innerHTML.split(/(?=[ .])/); // split by spaces and periods
for ( var c = 0; c < currentCode.length; c++ ) {
// surround each item with nowrap span
currentCode[ c ] = '<span class="no-wrap-hyphen">' + currentCode[ c ] + '</span>';
if ( currentCode[ c ].indexOf( '.' ) > -1 ) {
// add a zero size space at the start for periods
currentCode[ c ] = '<span class="wrap-period">' + currentCode[ c ] + '</span>';
}
}
codes[ i ].innerHTML = currentCode.join('');
}
}
I am using Groovy's handy MarkupBuilder to build an HTML page from various source data.
One thing I am struggling to do nicely is build an HTML table and apply different style classes to the first and last rows. This is probably best illustrated with an example...
table() {
thead() {
tr(){
th('class':'l name', 'name')
th('class':'type', 'type')
th('description')
}
}
tbody() {
// Add a row to the table for each item in myList
myList.each {
tr('class' : '????????') {
td('class':'l name', it.name)
td('class':'type', it.type)
td(it.description)
}
}
}
}
In the <tbody> section, I would like to set the class of the <tr> element to be something different depending whether the current item in myList is the first or the last item.
Is there a nice Groovy-ified way to do this without resorting to something manual to check item indexes against the list size using something like eachWithIndex{}?
You could use
if(it == myList.first()) {
// First element
}
if(it == myList.last()) {
// Last element
}
The answer provided by sbglasius may lead to incorrect result like when the list contains redundants elements so an element from inside the list may equals the last one.
I'm not sure if sbglasius could use is() instead of == but a correct answer could be :
myList.eachWithIndex{ elt, i ->
if(i == 0) {
// First element
}
if(i == myList.size()-1) {
// Last element
}
}
if (it.after.value != null) {
......
}
Works for maps
The implementations of the major browsers seem to have problems with text-transform: uppercase with Turkish characters. As far as I know (I'm not Turkish.) there are four different i characters: ı i I İ where the last two are the uppercase representations of the former two.
However applying text-transform:uppercase to ı i, the browsers (checked IE, Firefox, Chrome and Safari) results in I I which is not correct and may change the meaning of the words so much so that they become insults. (That's what I've been told)
As my research for solutions did not reveal any my question is: Are there workarounds for this issue? The first workaround might be to remove text-transform: uppercase entirely but that's some sort of last resort.
Funny thing, the W3C has tests for this problem on their site, but lack of further information about this issue. http://www.w3.org/International/tests/tests-html-css/tests-text-transform/generate?test=5
I appreciate any help and looking forward to your answers :-)
Here's a codepen
You can add lang attribute and set its value to tr to solve this:
<html lang="tr"> or <div lang="tr">
Here is working example.
Here's a quick and dirty workaround example - it's faster than I thought (tested in a document with 2400 tags -> no delay). But I see that js workarounds are not the very best solution
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-3">
</head>
<body>
<div style="text-transform:uppercase">a b c ç d e f g ğ h ı i j k l m n o ö p r s ş t u ü v y z (source)</div> <div>A B C Ç D E F G Ğ H I İ J K L M N O Ö P R S Ş T U Ü V Y Z (should be like this)</div>
<script>
function getStyle(element, style) {
var result;
if (document.defaultView && document.defaultView.getComputedStyle) {
result = document.defaultView.getComputedStyle(element, '').getPropertyValue(style);
} else if(element.currentStyle) {
style = style.replace(/\-(\w)/g, function (strMatch, p1) {
return p1.toUpperCase();
});
result = element.currentStyle[style];
}
return result;
}
function replaceRecursive(element) {
if (element && element.style && getStyle(element, 'text-transform') == 'uppercase') {
element.innerHTML = element.innerHTML.replace(/ı/g, 'I');
element.innerHTML = element.innerHTML.replace(/i/g, 'İ'); // replaces 'i' in tags too, regular expression should be extended if necessary
}
if (!element.childNodes || element.childNodes.length == 0) return;
for (var n in element.childNodes) {
replaceRecursive(element.childNodes[n]);
}
}
window.onload = function() { // as appropriate 'ondomready'
alert('before...');
replaceRecursive(document.getElementsByTagName('body')[0]);
alert('...after');
}
</script>
</body>
</html>
Here's my enhanced version of alex's code that I am using in production:
(function($) {
function getStyle(element, style) {
var result;
if (document.defaultView && document.defaultView.getComputedStyle) {
result = document.defaultView.getComputedStyle(element, '').getPropertyValue(style);
} else if(element.currentStyle) {
style = style.replace(/\-(\w)/g, function (strMatch, p1) {
return p1.toUpperCase();
});
result = element.currentStyle[style];
}
return result;
}
function replaceRecursive(element, lang) {
if(element.lang) {
lang = element.lang; // Maintain language context
}
if (element && element.style && getStyle(element, 'text-transform') == 'uppercase') {
if (lang == 'tr' && element.value) {
element.value = element.value.replace(/ı/g, 'I');
element.value = element.value.replace(/i/g, 'İ');
}
for (var i = 0; i < element.childNodes.length; ++i) {
if (lang == 'tr' && element.childNodes[i].nodeType == Node.TEXT_NODE) {
element.childNodes[i].textContent = element.childNodes[i].textContent.replace(/ı/g, 'I');
element.childNodes[i].textContent = element.childNodes[i].textContent.replace(/i/g, 'İ');
} else {
replaceRecursive(element.childNodes[i], lang);
}
}
} else {
if (!element.childNodes || element.childNodes.length == 0) return;
for (var i = 0; i < element.childNodes.length; ++i) {
replaceRecursive(element.childNodes[i], lang);
}
}
}
$(document).ready(function(){ replaceRecursive(document.getElementsByTagName('html')[0], ''); })
})(jQuery);
Note that I am using jQuery here only for the ready() function. The jQuery compatibility wrapper is also as a convenient way to namespace the functions. Other than that, the two functions do not rely on jQuery at all, so you could pull them out.
Compared to alex's original version this one solves a couple problems:
It keeps track of the lang attribute as it recurses through, since if you have mixed Turkish and other latin content you will get improper transforms on the non-Turkish without it. Pursuant to this I pass in the base html element, not the body. You can stick lang="en" on any tag that is not Turkish to prevent improper capitalization.
It applies the transformation only to TEXT_NODES because the previous innerHTML method did not work with mixed text/element nodes such as labels with text and checkboxes inside them.
While having some notable deficiencies compared to a server side solution, it also has some major advantages, the chief of which is guaranteed coverage without the server-side having to be aware of what styles are applied to what content. If any of the content is being indexed and shown in Google summaries (for example) it is much better if it stays lowercase when served.
The next version of Firefox Nightly (which should become Firefox 14) has a fix for this problem and should handle the case without any hack (as the CSS3 specs request it).
The gory details are available in that bug : https://bugzilla.mozilla.org/show_bug.cgi?id=231162
They also fixed the problem for font-variant I think (For those not knowing what font-variant does, see https://developer.mozilla.org/en/CSS/font-variant , not yet up-to-date with the change but the doc is browser-agnostic and a wiki, so...)
The root cause of this problem must be incorrect handling of these turkish characters by unicode library used in all these browsers. So I doubt there is an front-end-side fix for that.
Someone has to report this issue to the developers of these unicode libs, and it would be fixed in few weeks/months.
If you can't rely on text-transform and browsers you will have to render your text in uppercase yourself on the server (hope you're not uppercasing the text as the user types it).
You should have a better support for internationalisation there.
This work-around requires some Javascript. If you don't want to do that, but have something server side that can preprocess the text, this idea will work there too (I think).
First, detect if you are running in Turkish. If you are, then scan whatever you are going to uppercase to see if it contains the problem characters. If they do, replace all of those characters with the uppercase version of them. Then apply the uppercase CSS. Since the problem characters are already uppercase, that should be a totally fine (ghetto) work around. For Javascript, I envision having to deal with some .innerHTML on your impacted elements.
Let me know if you need any implementation details, I have a good idea of how to do this in Javascript using Javascript string manipulation methods. This general idea should get you most of the way there (and hopefully get me a bounty!)
-Brian J. Stinar-