<head>
<title>Initail Letter Testing Console</title>
<style>
body {
font-family: sans-serif;
}
input[type=radio] {
margin-right: 1em;
}
label {
font-size: 110%;
margin-left: -10px;
}
select {
font-family: monospace;
font-size: 120%;
width: 20ch;
}
textarea {
width: 80ch;
height: 10em;
}
tt {
color:rgb(0, 30, 0);
}
#custom_content details {
float: left;
margin: 20px;
}
.list_box {
float: left;
margin-left: 20px;
}
.unit {
float: left;
margin-left: 30px;
margin-bottom: 30px;
}
#playfield {
margin: 10px;
}
</style>
<body>
<h1>Initail Letter Testing Console</h1>
<fieldset id="settings">
<legend>Settings</legend>
<fieldset>
<legend>Variations</legend>
<div id="variations_element"></div>
<br clear="both">
Note: text-orientation isn't effective for horizontal writing mode.
</fieldset>
<fieldset id="custom_content">
<legend>Content HTML and CSS rules</legend>
<details>
<summary>
Content HTML
</summary>
<textarea id="sample_content"></textarea>
<div>Note: You can use <tt><float></float></tt> to insert floating items.</div>
<div id="sample_content_en" hidden>The filter() method creates a shallow copy of a portion of a given array, filtered down to just the elements from the given array that pass the test implemented by the provided function.</div>
<div id="sample_content_ja" hidden>吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。</div>
<br>
<fieldset id="sample_lang">
<legend>Samples</legend>
<input type="radio" name="sample_lang" id="sample_lang_en" value="en" checked>
<label for="sample_lang_en">en</label>
<input type="radio" name="sample_lang" id="sample_lang_ja" value="ja">
<label for="sample_lang_ja">ja</label>
</fieldset>
</details>
<details>
<summary>
Content CSS Properties
</summary>
<textarea id="custom_content_css_rules">
#sample {
border: solid 1px green;
font-family: serif;
font-size: 20px;
}
float {
float: inline-start;
width: 50px;
height: 50px;
line-height: 50px;
background: lime;
border: solid 1px;
text-align: center;
vertical-align: middle;
}
</textarea>
</details>
<details>
<summary>
Initail Letter CSS Properties
</summary>
<textarea id="custom_initial_letter_css_properties">
color: red;
</textarea>
</details>
</fieldset>
<br clear="both">
<button id="show_button">Show</button>
</fieldset>
<h2>Samples</h2>
<p>You can get HTML source inside "HTML Source" label in below.</p>
<div id="play_field"></div>
<script>
"use strict";
const kHeight= 'height';
const kHorizontalTb = 'horizontal-tb';
const kInitialLetter = 'initial-letter';
const kMixed = 'mixed';
const kTextOrientation = 'text-orientation';
const kWritingMode = 'writing-mode';
const kWidth = 'width';
const kVariationMap = {
'writing-mode': ['horizontal-tb', 'vertical-lr', 'vertical-rl'],
'direction': ['ltr', 'rtl'],
'text-orientation': ['mixed', 'sideways', 'upright'],
'initial-letter': ['3 drop', '3 raise', '3 2', '3 4', '3 5',
'2 drop', '2 raise', '2 3', '2 4', '2 5'],
};
const kVariationNames = Object.keys(kVariationMap);
function BuildVariation(name) {
const select_element = document.createElement('select');
const variations = kVariationMap[name];
variations.forEach(value => {
const option_element = document.createElement('option');
option_element.value = value;
option_element.textContent = value;
select_element.appendChild(option_element);
});
select_element.id = name;
select_element.multiple = true;
select_element.size = variations.length;
select_element.selectedIndex = 0;
const list_box_element = document.createElement('div');
list_box_element.classList.add('list_box');
list_box_element.innerHTML = `<label>${name}</label><br>`;
list_box_element.appendChild(select_element);
variations_element.appendChild(list_box_element);
}
function BuildSample(container_properties, first_letter_properties) {
function ToCSSProperties(properties, separator = '\n') {
return Object.keys(properties).map(
name => ` ${name}: ${properties[name]};`).join(separator);
}
const sample_content_html = sample_content.value.trim();
const kNumberOfLines = 7;
const width = Math.max(kNumberOfLines,
Math.ceil(sample_content_html.length / kNumberOfLines));
const extra_properties = {};
if (container_properties[kWritingMode] === kHorizontalTb) {
extra_properties[kWidth] = `${width}ch`;
} else {
extra_properties[kHeight] = `${width}lh`;
}
const shadow_root_html = `
<style>
#sample {
${ToCSSProperties(container_properties)}
${ToCSSProperties(extra_properties)}
}
${custom_content_css_rules.value}
#sample::first-letter {
${ToCSSProperties(first_letter_properties)}
${custom_initial_letter_css_properties.value}
}
</style>
<div id="sample">${sample_content_html}</div>
`;
const unit_html = `<div style="font-family: monospace; margin-left: -10px;">
${ToCSSProperties(container_properties, '<br>')}<br>
${ToCSSProperties(first_letter_properties, '<br>')}
</div>
<br><div class="sample_host"></div><br>
<div>
<details style="margin-left: -10px">
<summary>HTML Source</summary>
<textarea cols="80" rows="25"><!doctype html>${shadow_root_html}</textarea>
</details>
</div>`;
const unit_element = document.createElement('div');
unit_element.classList.add('unit');
unit_element.innerHTML = unit_html;
const sample_host = [unit_element.children]
.find(x => x.className == 'sample_host');
sample_host.setAttribute('style', 'clear:both');
const shadow_root = sample_host.attachShadow({mode: 'open'});
shadow_root.innerHTML = shadow_root_html;
play_field.appendChild(unit_element);
}
function CollectVaiations(name) {
const select_element = document.getElementById(name);
return new Set([select_element.options]
.filter(option_element => option_element.selected)
.map(option_element => option_element.value));
}
function DoShow() {
const selected_values_map = new Map();
kVariationNames.forEach(name => {
const values = CollectVaiations(name);
selected_values_map.set(name, values);
});
const selected_text_orientations = selected_values_map.get(kTextOrientation);
const has_mixed = selected_text_orientations.has(kMixed)
const has_horizontal_tb =
selected_values_map.get(kWritingMode).has(kHorizontalTb);
if (has_horizontal_tb && !has_mixed)
selected_text_orientations.add(kMixed)
const total_samples = [selected_values_map.values()].reduce(
(total, selected_values) => total * selected_values.size, 1);
let samples = Array(total_samples);
for (let i = 0; i < total_samples; ++i) {
samples[i] = new Map();
let divisor = 1;
selected_values_map.forEach((values, name) => {
samples[i].set(name, [values].at(i / divisor % values.size));
divisor *= values.size;
});
}
if (selected_text_orientations.size > 1) {
if (has_horizontal_tb) {
samples = samples.filter(
values_map =>
values_map.get(kWritingMode) !== kHorizontalTb ||
values_map.get(kTextOrientation) === kMixed);
}
if (!has_mixed && selected_orientations.has(kMixed)) {
samples = samples.filter(
values_map =>
values_map.get(kWritingMode) === kHorizontalTb ||
values_map.get(kTextOrientation) !== kMixed);
}
}
samples.sort((a, b) => a.get(kWritingMode) < b.get(kWritingMode) ? -1 : 1);
play_field.innerHTML = '';
samples.forEach(sample => {
const content_properties = {};
[sample.keys()].filter(name => name !== kInitialLetter).forEach(
key => content_properties[key] = sample.get(key));
const first_letter_properties = {};
first_letter_properties[kInitialLetter] = sample.get(kInitialLetter);
BuildSample(content_properties, first_letter_properties);
});
}
function UpdateSampleContent() {
const checked = [sample_lang.elements].find(element => element.checked);
sample_content.value =
document.getElementById(`sample_content_${checked.value}`).innerHTML;
DoShow();
}
function Start() {
show_button.addEventListener('click', DoShow);
sample_lang_en.addEventListener('input', UpdateSampleContent);
sample_lang_ja.addEventListener('input', UpdateSampleContent);
kVariationNames.forEach(BuildVariation);
UpdateSampleContent();
}
Start();
</script>
</body>
Output
300px
This bin was created anonymously and its free preview time has expired (learn why). — Get a free unrestricted account
Dismiss xKeyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |