Change direction with selecting Language in Vuejs - javascript

I have a Language select-option. If I choose Arabic then it will change the direction.
* {
direction: rtl!important;
}
While I am using this, then the whole direction changed to right to left. But how can I do that with Methods?
methods: {
languageSelection() {
if(this.lang == 'arb') {
document.getElementsByTagName("*")[0].style.direction = "rtl!important";
document.getElementsByTagName("html")[0].style.direction = "rtl!important";
document.getElementsByTagName("body")[0].style.direction = "rtl!important";
}
}
}
The above code is not working!
If I can add a CSS file then it will be better for me. For example:
languageSelection() {
if(this.lang == 'arb') {
// active a css file like: style-rtl.css
}
}
But how is this possible?

Ok. So when you use getElementsByTagName("*")[0] you will probably get a handle to a <html> element. So the same element you're accessing in the next line.
To change all elements direction you would have to iterate over the collection:
const elems = document.getElementsByTagName("*")
for (let elem of elems) {
elem.style.direction = 'rtl'
}
But this will still include <script>, <style>, <meta> tags, which is not the best solution.
My solution
I would create class in the css
html.is-rtl * {
direction: rtl;
}
then just toggle the class when you select the language which is read from right to left.
languageSelection() {
if (this.lang == 'arb') {
document.querySelector('html').classList.add('is-rtl')
}
}

Could create a stylesheet and append it to the head:
languageSelection() {
if(this.lang == 'arb') {
const style = document.createElement('style');
style.innerHTML = `*{direction:rtl!important}`;
document.head.appendChild(style);
}
}

You should manage it inside App.vue. add custom css class based on chosen language to #App element.
<template>
<div id="app" :class="{'dir-rtl': isRtl}">
...
</div>
</template>
<script>
export default {
computed: {
isRtl () {
return this.lang === 'arb'
}
}
}
</script>
<style lang="scss">
.dir-rtl {
direction: rtl !important;
}
</style>
best place to save and change lang is vuex store.

Related

How to condense 3 IF loops with the toggle() method in Vanilla Javascript?

I have created this lightbulb exercise that toggles the SRC of the lightbulb, the background color, as well as the color of the text. As an extra challenge, I'm trying to see if I can condense my code using the toggle() method as I have 3 separate functions. Does anyone know if this is possible and how I could accomplish this?
<h1 class="title-text" id="title-text">Click the lightbulb to turn it on or off!</h1>
<img id="lightbulb" onclick="toggleLight();toggleColor();toggleText()" src="/personal-projects/pic_bulbon1.gif">
<script>
let lightbulb = document.getElementById("lightbulb");
let titleText = document.getElementById("title-text");
function toggleLight() {
if (lightbulb.src.match("bulbon1")) {
lightbulb.src = "/personal-projects/pic_bulboff1.gif"
} else {
lightbulb.src = "/personal-projects/pic_bulbon1.gif"
}
}
function toggleColor() {
if (lightbulb.src.match("bulboff1")) {
document.body.style.background = "black";
} else {
document.body.style.background = "#FEDD00";
}
}
function toggleText() {
if (lightbulb.src.match("bulboff1")) {
titleText.style.color = "white";
} else {
titleText.style.color = "black";
}
}
</script>
</body>
</html>
The If loops work fine. I just want to know how I could use toggle if its possible. All the tutorials I find for this type of thing involve jquery.
Using toggle method
You want to first create a class for toggling in your css. Each element you want to toggle should have a default state and a toggled state. Toggling will add/remove a single class.
See snippet below
Snippet
const LightBulb = document.getElementById("lightbulb");
const toggleLight = () => {
LightBulb.classList.toggle("lightBulbOn");
document.body.classList.toggle("bodyLightOn");
};
body {
background-color: black;
}
body,
body .title-text {
color: white;
}
body.bodyLightOn {
background-color: #fedd00;
}
body.bodyLightOn .title-text {
color: black;
}
#lightbulb::before {
content: url("https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/Gluehlampe_01_KMJ.png/340px-Gluehlampe_01_KMJ.png");
}
.lightBulbOn::before {
content: url("https://cdn.mos.cms.futurecdn.net/HaPnm6P7TZhPQGGUxtDjAg-320-80.jpg") !important;
}
<h1 class="title-text" id="title-text">Click the lightbulb to turn it on or off!</h1>
<div id="lightbulb" class="" onclick="toggleLight();">
</div>
Codepen

Add CSS rules from textarea using v-html

I am building a WYSIWYG type application where a user can write CSS in a textarea and that CSS rule will be applied to the HTML on page i tried something like this in template
<textarea v-bind="css"></textarea>
<style v-html="css"></style>
VueCompilerError: Tags with side effect ( and ) are ignored in client component templates.
Old answer, below is better one
Add textarea with v-model:
<textarea v-model="css" />
You can create style tag in onMounted hook:
onMounted(() => {
const style = document.createElement("style");
style.type = "text/css";
updateCss(style, css.value);
document.getElementsByTagName("head")[0].appendChild(style);
el.value = style;
});
You must be able to access this element later, so assign style to
el.value.
Then add watch on input value:
watch(css, () => {
updateCss(el.value, css.value);
});
Where updateCss is a function:
const updateCss = (el, css) => {
if (el.styleSheet) {
el.styleSheet.cssText = css.value;
} else {
el.innerHTML = "";
el.appendChild(document.createTextNode(css));
}
};
Demo:
https://codesandbox.io/s/cocky-mestorf-uqz6f?file=/src/App.vue:246-463
Edit
I found much better solution:
<template>
<textarea v-model="css" />
<component :is="'style'" type="text/css" v-text="css"></component>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
const css = ref("body { background-color: blue; }");
return { css };
},
};
</script>
Component doesn't throw the error about style tag:
<component :is="'style'">
Note that there is v-text instead v-html. V-html could be unsafe.
Demo:
https://codesandbox.io/s/festive-germain-q9tg3?file=/src/App.vue:122-281

Disable visual effects of a CSS class

On a site a CSS class is periodically added to an element by JavaScript.
I'd like not to show the visible effect of that class. In other words what I need is an effect similar to switching the class off in the development console of the browser. Let the class exist but without any consequences.
I understand that I can catch events and remove the class when it appears.
But maybe there is just a more simple way in my case?
In other words: there is a CSS class, I would like it to be present but without any visual effects. If it is impossible, that will also be an answer.
You could use something like this. Access the document's stylesheets and apply some sort of regex matching to figure out which rules are associated with the class in question. Then simply unset the styling on the rules. Note that just because the class name is found in the stylesheet rule doesn't mean it is the element being affected by the styles...but this should get you going in the right direction.
function removeClassStyling(clazz) {
var classRegex = new RegExp('\\.'+clazz.toLowerCase()+'\\b','i')
for (var s=0; s<document.styleSheets.length; ++s) {
var sheet = document.styleSheets[s];
for(var r=0; r<sheet.cssRules.length; ++r) {
var rule = sheet.cssRules[r];
if(rule.selectorText && rule.selectorText.match(classRegex)) {
var properties = Object.keys(rule.style);
for(var p=0; p<properties.length; ++p){
if(rule.style[properties[p]]) rule.style[properties[p]] = "";
}
console.log('removed styling for "'+clazz+'"');
}
}
}
}
setTimeout(function(){ removeClassStyling('unwanted-class') }, 1500)
.unwanted-class {
border: 1px solid red;
}
<div class="unwanted-class"> Test </div>
This should do the trick in most circumstances. I imagine there are circumstances that would evade this, but I can't think of them.
Basically you need to iterate document.styleSheets collection, then iterate each rule contained within and compare the CSSStyleRule.selectorText for each rule against a regular expression.
Regular expressions can be faulty, so I've included a check against an element with the supplied class name using the Element#matches() method. That method can also provide false positives in the case where the element matches some other part of the selector, so the two together should reasonably prevent any false positives.
Once you have a list of all the CSS rules that apply to a given class, you can simply delete them all. This can be done in the same step as finding them, but I've done it separately in for example's sake.
function findClassRules(name) {
const element = document.createElement('div')
element.classList.add(name)
const regex = new RegExp(`\\\.${ name }([^\w]|$)`, 'i')
const test = {
rule: rule => {
if('cssRules' in rule) {
return test.sheet(rule)
} else if('selectorText' in rule) {
const selector = rule.selectorText
return selector.match(regex) && element.matches(selector) && rule
}
},
sheet: sheet => {
const rules = Array.from(sheet.cssRules, test.rule).filter(Boolean)
return rules.length && { sheet, rules }
}
}
return Array.from(document.styleSheets, test.sheet).filter(Boolean)
}
function processSheet({ sheet, rules }) {
rules.forEach(rule => {
if('rules' in rule) {
processSheet(rule)
} else {
sheet.deleteRule(rule)
console.log(`Removed: ${ rule.cssText }`)
}
})
}
document.getElementById('clean').addEventListener('click', event => {
findClassRules('test').forEach(processSheet)
}, false)
.test { padding: 5px }
.test2 { padding: 10px }
#media screen {
.test { margin: 15px }
}
<p class="test">Hello world!</p>
<button id="clean">Remove CSS</button>
<style type="text/css">
.test { color: red }
</style>
<style type="text/css">
.test { border: 1px solid red }
</style>
How about you comment the class in your css file

Styling buttons in p5.js

I'm currently working on a project with p5.js and have come against a problem in javascript. I built buttons in javascript to help make certain functions work and I'm looking for a way to style the buttons. For the rest of the project I was using bootstrap so I'm trying to find a way to style it as similar as I can to the rest of the rest off the CSS if possible. The buttons code in javascript follows this.
button1 = createButton('start');
button2 = createButton('stop');
button3 = createButton('play');
button4 = createButton('save');
button1.mousePressed(start_);
button2.mousePressed(stop_);
button3.mousePressed(play_);
button4.mousePressed(save_);
createButton returns a p5.Element object which has a .class() method to set the class property on it. Classes can then be used for styling, either with bootstrap or custom CSS. For example:
let btn;
function setup() {
noCanvas();
const cls = "maroon-bg white-text";
btn = createButton("hello world");
btn.class(cls);
btn.mouseClicked(() => {
btn.class(btn.class() ? "" : cls);
});
}
.maroon-bg {
background-color: maroon;
}
.white-text {
color: white;
}
button {
padding: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
I prefer separating CSS and JS because it promotes reuse and keeps your JS clean, but if you want to inline your styles, you can use .style():
let btn;
function setup() {
noCanvas();
btn = createButton("hello world");
btn.style("background-color", "maroon");
btn.style("color", "white");
btn.style("padding", "1em");
btn.mouseClicked(() => {
if (btn.style("color") === "rgb(0, 0, 0)") {
btn.style("color", "white");
btn.style("background-color", "maroon");
}
else {
btn.style("background-color", "");
btn.style("color", "");
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
This is clearly awkward for this use case, but it can come in handy in other situations and is shown for completeness.

Trying to use React.DOM to set body styles

How can I use React.DOM to change styles on HTML body?
I tried this code and it's not working:
var MyView = React.createClass({
render: function() {
return (
<div>
React.DOM.body.style.backgroundColor = "green";
Stuff goes here.
</div>
);
}
});
If you execute this from the browsers console it works (but I need it working in ReactJS code):
document.body.style.backgroundColor = "green";
Also see this question for similar but different solution:
Change page background color with each route using ReactJS and React Router?
Assuming your body tag isn't part of another React component, just change it as usual:
document.body.style.backgroundColor = "green";
//elsewhere..
return (
<div>
Stuff goes here.
</div>
);
It's recommended to put it at componentWillMount method, and cancel it at componentWillUnmount:
componentWillMount: function(){
document.body.style.backgroundColor = "green";
}
componentWillUnmount: function(){
document.body.style.backgroundColor = null;
}
With functional components and useEffect hook :
useEffect(() => {
document.body.classList.add('bg-black');
return () => {
document.body.classList.remove('bg-black');
};
});
A good solution to load multiple atributes from a js class to the document body can be:
componentWillMount: function(){
for(i in styles.body){
document.body.style[i] = styles.body[i];
}
},
componentWillUnmount: function(){
for(i in styles.body){
document.body.style[i] = null;
}
},
And after you write your body style as long as you want:
var styles = {
body: {
fontFamily: 'roboto',
fontSize: 13,
lineHeight: 1.4,
color: '#5e5e5e',
backgroundColor: '#edecec',
overflow: 'auto'
}
}
The best way to load or append extra classes is by adding the code in componentDidMount().
Tested with react and meteor :
componentDidMount() {
var orig = document.body.className;
console.log(orig); //Just in-case to check if your code is working or not
document.body.className = orig + (orig ? ' ' : '') + 'gray-bg'; //Here gray-by is the bg color which I have set
}
componentWillUnmount() {
document.body.className = orig ;
}
This is what I ended up using.
import { useEffect } from "react";
export function useBodyStyle(style: any){
useEffect(()=>{
for(var key in style){
window.document.body.style[key as any] = style[key];
}
return () => {
window.document.body.style[key as any] = '';
}
}, [style])
}
Even if you can set body styles from react with the provided answer, I prefer if a component is only responsible for setting its own style.
In my case there was an alternative solution. I needed to change the body backgroundColor. This could easily be achieved without changing the body style in a react component.
First I added this style to the index.html header.
<style>
html, body, #react-app {
margin: 0;
height: 100%;
}
</style>
Then, in my outermost component, I set the backgroundColor to the needed value and the height to 100%.

Categories

Resources