how to inherit and customise a class - less

I want to inherit a parent and add few classes in the middle. Like
.parent {
li {
a {
color: red;
}
}
}
.child {
li {
a, button {
color: red;
}
}
}

In LESS you can extend mixins, but at present (LESS 1.5) it requires just a class definition, so this:
.parent {
li {
a {
color: red;
}
}
}
.child {
&:extend(.parent);
li {
a, button {
color: red;
}
}
}

Related

Vue-Chart-js, How to make doughnut chart with reactive text in the middle

How do I make a doughnut chart with text in the middle? I understand that I have to use plugins but I don't get how to pass props through to the plugin. I currently am on Vue2 and vue-chart-js3.
Everytime I try to pass anything dynamically through to the plugin it gets it as null.
//*** Doughnut chat ***//
import { Doughnut } from "vue-chartjs/legacy";
import { Chart } from "chart.js";
export default {
extends: Doughnut,
data: () => ({
chartdata: {
labels: ["Cambodia", "Thailand", "Vietnam", "Laos"],
datasets: [
{
backgroundColor: ["#a3c7c9", "#889d9e", "#647678", "f87979"],
data: [91, 3, 3, 3]
}
]
},
options: {
legend: {
display: false
},
responsive: true,
maintainAspectRatio: false
}
}),
mounted() {
this.renderChart(this.chartdata, this.options);
this.textCenter(880);
},
methods: {
textCenter(val) {
Chart.pluginService.register({
beforeDraw: function(chart) {
var width = chart.chart.width;
var height = chart.chart.height;
var ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 114).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
var text = val;
var textX = Math.round((width - ctx.measureText(text).width) / 2);
var textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
});
Chart.plugins.unregister(this.chartdata);
}
}};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>```

how to create a barcode scanner with quagga with fixed scanning canvas

I'm on Nuxt 2.15.4 and using Quagga2. I want to create a scanner like mobile scanners where the camera is full screen and there is a blue rectangle that the barcode must be placed inside of, and after scanning there will be a red line through the barcode canvas. With Quagga.js I can manipulate the CSS and area property in canvas but it cause 2 problems:
The actual scanning zone will be messed up and I don't know where the scanning exactly happens.
The successful red line-through style will be messed up.
Also, after a successful scan I need the red line-through to remain and not disappear and no scanning happen for a period of time (so I can decide to continue scanning or do something with result).
Here is the code I implemented on in app (also need help on activating torch and zoom):
<template>
<section id="container" class="container">
<div id="interactive" class="viewport"></div>
{{code}}
</section>
</template>
<script>
import Quagga from '#ericblade/quagga2';
export default {
data() {
return {
code:[]
};
},
methods:{
async checkDevice() {
let md = navigator.mediaDevices;
if (!md || !md.enumerateDevices) return false;
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.some((device) => "videoinput" === device.kind);
},
initQuagga(){
Quagga.init({
inputStream : {
name : "Live",
type : "LiveStream",
area: {
top: "0%",
right: "0%",
left: "0%",
bottom: "0%",
},
},
locate: false,
decoder : {
readers : [
"ean_reader",
],
}
},(err)=>{
if(err){
return
}
// this.checkCapabilities();
this.startQuagga()
});
},
// checkCapabilities(){
// var track = Quagga.CameraAccess.getActiveTrack();
// var capabilities = {};
// if (typeof track.getCapabilities === 'function') {
// capabilities = track.getCapabilities();
// }
// this.applySettingsVisibility('zoom', capabilities.zoom);
// this.applySettingsVisibility('torch', capabilities.torch);
// },
// applySetting: function(setting, value) {
// var track = Quagga.CameraAccess.getActiveTrack();
// if (track && typeof track.getCapabilities === 'function') {
// switch (setting) {
// case 'zoom':
// return track.applyConstraints({advanced: [{zoom: parseFloat(value)}]});
// case 'torch':
// return track.applyConstraints({advanced: [{torch: !!value}]});
// }
// }
// },
startQuagga(){
Quagga.start()
Quagga.onProcessed(function (result) {
let drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#008", lineWidth: 2});
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
}
}
})
Quagga.onDetected(this.onDetected);
},
onDetected(data) {
let barCodeData = data.codeResult.code;
console.log(barCodeData);
},
},
async mounted(){
let data = await this.checkDevice();
if (data) {
this.initQuagga();
}
},
beforeDestroy(){
Quagga.stop()
}
}
</script>
<style lang="scss">
#container {
width: 640px;
margin: 20px auto;
padding: 10px;
}
#interactive.viewport {
width: 640px;
height: 480px;
}
#interactive.viewport canvas, video {
float: left;
width: 640px;
height: 480px;
}
#interactive.viewport canvas.drawingBuffer, video.drawingBuffer {
margin-left: -640px;
}
</style>

Convert Pell.js to Vue component for Customizing

I am trying to convert from pell rich text editor to vue component. I have downloaded pell.js and converted it to vue component but I meet some issues now.
I transfer all datas and methods from pell to vue component.
And I called this.init function in created() method. And it shows that this.defaultActions which defined in datas() is not defined in init functions.
Please give me any advice. Thanks..
Here is my vue component
<template>
<div class="content">
<h1>pell</h1>
<div id="editor" class="pell"></div>
<div style="margin-top:20px;">
<h3>Text output:</h3>
<div id="text-output"></div>
</div>
<div style="margin-top:20px;">
<h3>HTML output:</h3>
<pre id="html-output"></pre>
</div>
</div>
</template>
<script>
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
export default {
data: ()=> ({
defaultParagraphSeparatorString : 'defaultParagraphSeparator',
formatBlock : 'formatBlock',
defaultActions: {
bold: {
icon: '<b>B</b>',
title: 'Bold',
state: function state() {
return this.queryCommandState('bold');
},
result: function result() {
return this.exec('bold');
}
},
italic: {
icon: '<i>I</i>',
title: 'Italic',
state: function state() {
return this.queryCommandState('italic');
},
result: function result() {
return this.exec('italic');
}
},
underline: {
icon: '<u>U</u>',
title: 'Underline',
state: function state() {
return this.queryCommandState('underline');
},
result: function result() {
return this.exec('underline');
}
},
strikethrough: {
icon: '<strike>S</strike>',
title: 'Strike-through',
state: function state() {
return this.queryCommandState('strikeThrough');
},
result: function result() {
return this.exec('strikeThrough');
}
},
heading1: {
icon: '<b>H<sub>1</sub></b>',
title: 'Heading 1',
result: function result() {
return this.exec('formatBlock', '<h1>');
}
},
heading2: {
icon: '<b>H<sub>2</sub></b>',
title: 'Heading 2',
result: function result() {
return this.exec('formatBlock', '<h2>');
}
},
paragraph: {
icon: '¶',
title: 'Paragraph',
result: function result() {
return this.exec('formatBlock', '<p>');
}
},
quote: {
icon: '“ ”',
title: 'Quote',
result: function result() {
return this.exec('formatBlock', '<blockquote>');
}
},
olist: {
icon: '#',
title: 'Ordered List',
result: function result() {
return this.exec('insertOrderedList');
}
},
ulist: {
icon: '•',
title: 'Unordered List',
result: function result() {
return this.exec('insertUnorderedList');
}
},
code: {
icon: '</>',
title: 'Code',
result: function result() {
return this.exec('formatBlock', '<pre>');
}
},
line: {
icon: '―',
title: 'Horizontal Line',
result: function result() {
return this.exec('insertHorizontalRule');
}
},
link: {
icon: '🔗',
title: 'Link',
result: function result() {
var url = window.prompt('Enter the link URL');
if (url) this.exec('createLink', url);
}
},
image: {
icon: '📷',
title: 'Image',
result: function result() {
var url = window.prompt('Enter the image URL');
if (url) this.exec('insertImage', url);
}
}
},
defaultClasses: {
actionbar: 'pell-actionbar',
button: 'pell-button',
content: 'pell-content',
selected: 'pell-button-selected'
},
}),
created(){
console.log("this.defaultActions", this.defaultActions);
this.init(
{
element: document.getElementById('editor'),
defaultParagraphSeparator: 'p',
// actions: [
// 'bold',
// 'italic',
// 'underline',
// 'strikethrough'
// ],
onChange: function (html) {
document.getElementById('text-output').innerHTML = html
document.getElementById('html-output').textContent = html
}
}
);
},
methods:{
addEventListener(parent, type, listener) {
return parent.addEventListener(type, listener);
},
appendChild(parent, child) {
return parent.appendChild(child);
},
createElement(tag) {
return document.createElement(tag);
},
queryCommandState(command) {
return document.queryCommandState(command);
},
queryCommandValue(command) {
return document.queryCommandValue(command);
},
exec(command) {
var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
return document.execCommand(command, false, value);
},
init(settings){
Object.keys(this.defaultActions).map(function (action) {
console.log("action", action)
});
var actions = settings.actions ? settings.actions.map(function (action) {
if (typeof action === 'string') return this.defaultActions[action];
else if (this.defaultActions[action.name]) return _extends({}, this.defaultActions[action.name], action);
return action;
}) : Object.keys(this.defaultActions).map(function (action) {
console.log("action", action)
console.log("sss", this.defaultActions)
// return this.defaultActions[action];
});
var classes = _extends({}, this.defaultClasses, settings.classes);
var defaultParagraphSeparator = settings[this.defaultParagraphSeparatorString] || 'div';
var actionbar = this.createElement('div');
actionbar.className = classes.actionbar;
this.appendChild(settings.element, actionbar);
var content = settings.element.content = this.createElement('div');
content.contentEditable = true;
content.className = classes.content;
content.oninput = function (_ref) {
var firstChild = _ref.target.firstChild;
if (firstChild && firstChild.nodeType === 3) this.exec(this.formatBlock, '<' + defaultParagraphSeparator + '>');else if (content.innerHTML === '<br>') content.innerHTML = '';
settings.onChange(content.innerHTML);
};
content.onkeydown = function (event) {
if (event.key === 'Enter' && this.queryCommandValue(this.formatBlock) === 'blockquote') {
setTimeout(function () {
return this.exec(this.formatBlock, '<' + defaultParagraphSeparator + '>');
}, 0);
}
};
this.appendChild(settings.element, content);
actions.forEach(function (action) {
var button = this.createElement('button');
button.className = classes.button;
button.innerHTML = action.icon;
button.title = action.title;
button.setAttribute('type', 'button');
button.onclick = function () {
return action.result() && content.focus();
};
if (action.state) {
var handler = function handler() {
return button.classList[action.state() ? 'add' : 'remove'](classes.selected);
};
this.addEventListener(content, 'keyup', handler);
this.addEventListener(content, 'mouseup', handler);
this.addEventListener(button, 'click', handler);
}
this.appendChild(actionbar, button);
});
if (settings.styleWithCSS) this.exec('styleWithCSS');
this.exec(this.defaultParagraphSeparatorString, defaultParagraphSeparator);
return settings.element;
}
}
}
</script>
<style>
.content {
box-sizing: border-box;
margin: 0 auto;
max-width: 600px;
padding: 20px;
}
#html-output {
white-space: pre-wrap;
}
.pell {
border: 1px solid rgba(10, 10, 10, 0.1);
box-sizing: border-box; }
.pell-content {
box-sizing: border-box;
height: 300px;
outline: 0;
overflow-y: auto;
padding: 10px; }
.pell-actionbar {
background-color: #FFF;
border-bottom: 1px solid rgba(10, 10, 10, 0.1); }
.pell-button {
background-color: transparent;
border: none;
cursor: pointer;
height: 30px;
outline: 0;
width: 30px;
vertical-align: bottom; }
.pell-button-selected {
background-color: #F0F0F0; }
</style>
You should use arrow functions in the block mapping actions, preserves this from the surrounding scope
var actions = settings.actions
? settings.actions.map(action => { // arrow function here
if (typeof action === "string") return this.defaultActions[action];
else if (this.defaultActions[action.name])
return _extends({}, this.defaultActions[action.name], action);
return action
})
: Object.keys(this.defaultActions).map(action => { // arrow function here
console.log("action", action)
console.log("sss", this.defaultActions);
// return this.defaultActions[action];
});
Just for reference, you can also use the sample Vue code given in the pell repository
(or parts thereof, e.g styles)
<template>
<div>
<h6>Editor:</h6>
<div id="pell" class="pell" />
<h6>HTML Output:</h6>
<pre id="pell-html-output"></pre>
</div>
</template>
<script>
import pell from 'pell'
export default {
methods: {
ensureHTTP: str => /^https?:\/\//.test(str) && str || `http://${str}`
},
mounted () {
pell.init({
element: document.getElementById('pell'),
onChange: html => {
window.document.getElementById('pell-html-output').textContent = html
},
actions: [
'bold', 'italic', 'underline', 'strikethrough', 'heading1', 'heading2',
'paragraph', 'quote', 'olist', 'ulist', 'code', 'line',
{
name: 'image',
result: () => {
const url = window.prompt('Enter the image URL')
if (url) pell.exec('insertImage', this.ensureHTTP(url))
}
},
{
name: 'link',
result: () => {
const url = window.prompt('Enter the link URL')
if (url) pell.exec('createLink', this.ensureHTTP(url))
}
}
]
})
}
}
</script>
<style>
.pell {
border: 2px solid #000;
border-radius: 0;
box-shadow: none;
}
#pell-html-output {
margin: 0;
white-space: pre-wrap;
}
</style>

How to improve LESS code to get a compact CSS result?

My attempt:
.breadcrumb {
&.main,
&.path {
& a:hover {
color: red;
}
}
}
.left-sidepanel {
.panel {
&-heading,
&-body a {
color: red;
}
}
}
Result:
.breadcrumb.main a:hover,
.breadcrumb.path a:hover {
color: red;
}
.left-sidepanel .panel-heading,
.left-sidepanel .panel-body a {
color: red;
}
The required result
.breadcrumb.main a:hover,
.breadcrumb.path a:hover,
.left-sidepanel .panel-heading,
.left-sidepanel .panel-body a {
color: red;
}
I would be grateful for your ideas.
.breadcrumb {
&.main,
&.path {
a:hover {
color: red;
}
}
}
.left-sidepanel {
.panel {
&-heading,
&-body a {
&:extend(.breadcrumb.path a:hover);
}
}
}

Specify row in TableView

How I can change background color to red for row if row had timeToReply>15. I can't get timeToReply in rowDelegate. How I can do this ?
TableView
{
model: someModel
TableViewColumn{title:"Time";role: "timeToReply";width: 170}
rowDelegate: Item {
clip: true
Text {
anchors.verticalCenter: parent.verticalCenter
color: {
if(timeToReply>15) //problem
{
color="red"
}
else
{
color="black"
}
}
text: styleData.value
elide: Text.ElideMiddle
}
}
}