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

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);
}
}
}

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>

Header in QML column

I have this piece of code in QML, but I'm not able to add a STATIC text as the header of each column.
I tried looking online but I don't seem to find the asnwer. Or I just don't get it.
Component {
id: pedido
Item {
id: item
width: parent.width;
Row {
id: row
width: parent.width
anchors.verticalCenter: parent.verticalCenter
Column {
width: parent.width * 0.3
Text {
text: " " + codigo;
font.family: "Helvetica"
font.pointSize: 14
font.bold: true
color: item.ListView.isCurrentItem ? "white" : "black" }
Column {
width: parent.width * 0.5
Text {
text: " " + nombre;
font.family: "Helvetica"
font.pointSize: 14
font.bold: true
color: item.ListView.isCurrentItem ? "white" : "black"
}
}
Column {
width: parent.width * 0.2
Text {
text: " " + fecha;
font.family: "Helvetica"
font.pointSize: 14
font.bold: true
}
}
Don't worry if there are missing {} .
You should implement your own header. More info in the documentation.
Let me show you an example with a simple ListModel & ListView:
import QtQuick 2.5
import QtQuick.Window 2.2
Window {
visible: true
width: 500
height: 500
Rectangle {
width: 300
height: 400
Component {
id: listDelegate
Item {
width: 400;
height: 50;
Row {
Column {
width: 100
Text { text: codigo }
}
Column {
width: 100
Text { text: nombre }
}
Column {
width: 100
Text { text: fecha }
}
}
}
}
ListModel {
id: listModel
ListElement {
codigo: "111"
nombre: "AAA"
fecha: "28/08/2001"
}
ListElement {
codigo: "222"
nombre: "BBB"
fecha: "28/08/2002"
}
ListElement {
codigo: "333"
nombre: "CCC"
fecha: "28/08/2003"
}
}
ListView {
id: listView
anchors.fill: parent
model: listModel
delegate: listDelegate
focus: true
header: myheader
}
}
Component { //instantiated when header is processed
id: myheader
Rectangle {
gradient: mygradient
border {color: "#9EDDF2"; width: 2}
width: parent.width; height: 50
Row {
Column {
width: 100
Text { text: "Codigo" }
}
Column {
width: 100
Text { text: "Nombre" }
}
Column {
width: 100
Text { text: "Fecha" }
}
}
}
}
Gradient {
id: mygradient
GradientStop { position: 0.0; color: "#8EE2FE"}
GradientStop { position: 0.66; color: "#7ED2EE"}
}
}

how to inherit and customise a class

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;
}
}
}