Setting css class with variable in Xaringan with remark.js - css

I often need to change dynamically the font size or other properties for xaringan slides. Instead of defining a lot of different CSS classes I would like to define a general fontsize class and then passing a % value as variable. Something like this https://stackoverflow.com/a/17894116/9032257:
# Header 1
.fontsize50[
- some text
- some text
]
But fontisize50 is not hard coded on the CSS file. Is that possible?
Update
I have tried to use the approach proposed on Remark documentation https://github.com/gnab/remark/issues/72#issuecomment-62225566. I am able to dynamically the font size of a single word but not applying the font-size property to an entire section.
Adding this function to a macro.js file and setting the beforeInit YAML:
remark.macros.fontsize = function (size = "100%") {
var txt = this;
tag = "<span style=" + "'font-size:" + size + "'>" + txt + "</span>";
return tag
};
Then using this:
# Header 1
<!-- This Works -->
Hello ![:fontsize 200%](World)!
<!-- This Not -->
Hello ![:fontsize 200%](
- bullet 1
- bullet 2
- bullet 3
)
Change the fontsize according to the percentage only in the first case. I would like to have the same behavior as having a CSS class:
.font50 {
font-size: 50%;
}
And then using:
Hello
.font50[
- bullet 1
- bullet 2
- bullet 3
]
But I am not able to do this.

Related

Updating styles outside of a components scope - Angular 2

I am creating a very simple web app using Angular 2 that asks the user to input an RGB color code. After the user inputs the code, the page background should change to the inputted color.
Currently, this is what I have in my app.component.ts file:
/**
* Fired when the user clicks the #update-background button. This function will read the current input values and set the background color to these values.
*
* #param rgb: RGB object bound to the input fields. Holds the rgb(,,) values for the new background
*/
updateBackgroundColor(rgb) {
// 1. Construct the new background color
var updatedBackgroundColor = "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")";
// 2. Set the background of the <body> to the new background color. Right now I am using direct DOM manipulation because I could not find a way to access the <body> via typescript.
document.body.style.background = updatedBackgroundColor;
}
Is this best way to update the <body> element's style? The code is currently working (demo), but I just want to be sure this is the most efficient way to access the <body> element via typescript and Angular 2.
Your answer is right, we can't dynamically change style of an element using class selector.

Automatically change image-url by 1 for next div?

I'm making a bunch of stacked divs that will expand when moused-over to show an image, but I have a lot of images.
Is there a way in CSS or JS (I don't really know anything about JS) to have each div automatically use the next image in a folder? ex: the images are named map1.jpg, map2.jpg ... map91.jpg. and be able to use the same background-image:url but have something telling it to add 1 to the next image for each new div so I don't have to manually specify 90+ different images.
I hope I was able to explain that well enough. Thanks =)
In CSS this is impossible, cause you can't concatenate the url path for background-image.
in javascript this is pretty simple, using jQuery you can simply load all div you need when body is ready:
// on page load
$(document).ready(function(){
// 10 images to div #image-board
for(var i=0; i<10; i++){
// create a div with image #i
$('#image-board').append('<div><img src="my/collection/folder/Image'+i+'.jpg"></div>');
}
});
don't forget to create in your HTML page a <div id="image-board"></div> where all images will be listed to
I'll try to include lots of detail since you say you're unfamiliar with JavaScript. When you say stacked divs, I assume you mean one inside another. Start with a div with appropriate id and background in your html <div id="div0" style="background-image:url('map0.jpg')"></div> Here's some Javascript using jQuery (a very common javascript library you can include with a script tag) that will add a new div inside your first div with the updated url name.
for (var i = 0; i < number_of_images - 1; i++) {
var oldId = '#div' + i;
var newId = 'div' + (i + 1);
var newUrl = 'map'+(i+1)+'.jpg';
var newdiv = '<div id="' + newId + '" style="background-image:url('+newUrl+')></div>';
$(oldId).append(newdiv);
}
The for loop will go over every image, then a string is created in a series of concatenations that becomes your updated div. The '$' searches for the DOM element with that id, then adds the new div inside it. If by stacked you meant a new div underneath but not contained by the previous div, use .insertAfter instead of .append. Assuming your webpage can reach all of the images, this should work. Also notice I've 0 indexed this (the standard in Javascript) but your question referred to map1 as the first map. If you have already named these maps, you may need to re-index the for loop to 1.

How to create a button in TinyMCE 4 that increments font size

Has anyone managed to create a button in TinyMCE 4 that will increment the font size of the selected text by, say, 1px?
The problem I'm having is getting ahold of the selected text, whether it's in a span already or not.
I'm willing to modify the TinyMCE source.
Thanks for any ideas.
You don't need to modify the source code, you can create a plugin.
Here is the documentation of how to create a plugin for TinyMCE:
http://www.tinymce.com/wiki.php/Tutorials:Creating_a_plugin
based on that you can create your own button (see working example)
here is part of the code:
var currentFontSize = new Number($(tinyMCE.activeEditor.selection.getNode()).css('font-size').replace('px','')); //remove the px part
currentFontSize = currentFontSize + 1; //increase font by one
tinymce.activeEditor.formatter.register('mycustomformat', {
inline : 'span',
styles : {'font-size' : currentFontSize + 'px'} //this is the font size incremented by one
});
tinymce.activeEditor.formatter.apply('mycustomformat'); //apply the format to the selected text

How do I add OnClick event on part of the text?

I need to add OnClick event to part of the text in installer.
So it will be like this "bla bla bla clickable text bla bla bla".
Also this text should be with WordWrap property set to True, since I don't know exact size of it because of bunch of localizations.
I was trying to split text into 3 parts so it will be like this
"Not-clickable-text1 clickable-text2 Not-clickable-text3"
but the problem begins when text3 should go to the next line of installer. It starts from position of text3.Left property, but I need it to start on next line from text1.Left property
There is no such thing like click-able part of the text in Inno.
You really need to use 3 "texts"- either TLabel or TNewStaticText - to build the whole sentence. The middle one will have set Font property to bold, underline or blue color (depends you want the link) and Cursor set to Hand, ... and of course the OnClick event.
Both components have property AutoSize and WordWrap which you can use.
AutoSize property set to true makes your component to fit width and height to text size. Set it to True for all 3 texts.
Position texts like this:
Text1.Left := 10; // 10 is just example
Text1.Top := 10; // 10 is just example
Text2.Left := Text1.Left + Text1.Width + 3; // 3 is space
if(Text1.Height > $Constant$) then
Text3.Top := Text1.Top + Text1.Height + 3 // Create new line
else
Text3.Left := Text2.Left + Text2.Width + 3;

Last line of a paragraph contains a single word only [duplicate]

This question already has answers here:
Widow/Orphan Control with JavaScript?
(7 answers)
Closed 8 years ago.
A common problem when working with typography in HTML/CSS is something we call "horunge" in Swedish ("widow" in english).
What it is:
Let's say you have a box with a width of 200px and with the text "I love typograpy very much". Now the text breaks and becomes:
I love typography very
much
As a designer I don't want a word bastard (single word / row). If this was a document/PDF etc. I would break the word before very and look like this:
I love typography
very much
which looks much better.
Can I solve this with a CSS rule or with a javascript? The rule should be to never let a word stand empty on a row.
I know it can be solved by adding a <br /> but that's not a solution that works with dynamic widths, feed content, different translations, browser font rendering issues etc.
Update (solution)
I solved my problem with this jquery plugin: http://matthewlein.com/widowfix/
A simple jQuery / regrex solution could look like the following, if you add the class "noWidows" to the tag of any element that contains text you are worried about.
Such as:
<p class="noWidows">This is a very important body of text.</p>
And then use this script:
$('.noWidows').each(function(i,d){
$(d).html( $(d).text().replace(/\s(?=[^\s]*$)/g, " ") )
});
This uses regex to find and replace the last space in the string with a non-breaking character. Which means the last two words will be forced onto the same line. It's a good solution if you have space around the end of the line because this could cause the text to run outside of an element with a fixed width, or if not fixed, cause the element to become larger.
Just wanted to add to this page as it helped me a lot.
If you have (widows) actually should be orphans as widows are single words that land on the next page and not single words on a new line.
Working with postcodes like "N12 5GG" will result in the full postcode being on a new line together but still classed as an orphan so a work around is this. (changed the class to "noWidow2" so you can use both versions.
123 Some_road, Some_town, N12 5GG
$('.noWidows2').each(function(i,d){
var value=" "
$(d).html($(d).text().replace(/\s(?=[^\s]*$)/g, value).replace(/\s(?=[^\s]*$)/g, value));
});
This will result is the last 3 white spaces being on a new line together making the postcode issue work.
End Result
123 Some_road,
Some_town, N12 5GG
I made a little script here, with the help of this function to find line height.
It's just an approach, it may or may not work, didn't have time to test throughly.
As of now, text_element must be a jQuery object.
function avoidBastardWord( text_element )
{
var string = text_element.text();
var parent = text_element.parent();
var parent_width = parent.width();
var parent_height = parent.height();
// determine how many lines the text is split into
var lines = parent_height / getLineHeight(text_element.parent()[0]);
// if the text element width is less than the parent width,
// there may be a widow
if ( text_element.width() < parent_width )
{
// find the last word of the entire text
var last_word = text_element.text().split(' ').pop();
// remove it from our text, creating a temporary string
var temp_string = string.substring( 0, string.length - last_word.length - 1);
// set the new one-word-less text string into our element
text_element.text( temp_string );
// check lines again with this new text with one word less
var new_lines = parent.height() / getLineHeight(text_element.parent()[0]);
// if now there are less lines, it means that word was a widow
if ( new_lines != lines )
{
// separate each word
temp_string = string.split(' ');
// put a space before the second word from the last
// (the one before the widow word)
temp_string[ temp_string.length - 2 ] = '<br>' + temp_string[ temp_string.length - 2 ] ;
// recreate the string again
temp_string = temp_string.join(' ');
// our element html becomes the string
text_element.html( temp_string );
}
else
{
// put back the original text into the element
text_element.text( string );
}
}
}
Different browsers have different font settings. Try to play a little to see the differences. I tested it on IE8 and Opera, modifying the string every time and it seemed to work ok.
I would like to hear some feedback and improve because I think it may come in handy anyway.
Just play with it! :)
There are also CSS widows and orphans properties: see the about.com article.
Not sure about browser support...
EDIT: more information about WebKit implementation here: https://bugs.webkit.org/buglist.cgi?quicksearch=orphans.
Manually, you could replace the space in between with
I've been looking for ways to dynamically add it in. I found a few, but haven't been able to make it work myself.
$('span').each(function() {
var w = this.textContent.split(" ");
if (w.length > 1) {
w[w.length - 2] += " " + w[w.length - 1];
w.pop();
this.innerHTML = (w.join(" "));
}
});
#foo {
width: 124px;
border: 1px solid #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
<span class="orphan">hello there I am a string really really long, I wonder how many lines I have</span>
</div>

Resources