Random inline styles being applied - mithril.js

I have no code that adds inline styles to div.size-option, but the first one has random inline styles added to it. No where else in the code does anything mess with these elements. The overall setup is too complicated to reproduce in a codepen.
return <div id="options-container">
{ctrl.model.map(function(model) {
return <div class='size-option-container'
onclick={() => { if(model.inStock()) vm.select(model.id()); }}
option={model.id()}>
<div
class={'size-option' +
(model.isSelected() ? ' selected': '') +
(model.inStock() ? '' : ' option-out-of-stock')}>
<span class='size'>{model.name()}</span>
</div>
</div>
})}
</div>
Compiled:
return m(
'div',
{ id: 'options-container' },
ctrl.model.map(function (model) {
return m(
'div',
{ 'class': 'size-option-container',
onclick: function onclick() {
if (model.inStock()) vm.select(model.id());
},
option: model.id() },
m(
'div',
{
'class': 'size-option' + (model.isSelected() ? ' selected' : '') + (model.inStock() ? '' : ' option-out-of-stock') },
m(
'span',
{ 'class': 'size' },
model.name()
)
)
);
})
);
Output:
<div id="options-container">
<div class="size-option-container" option="1428">
<div class="size-option selected" style="width: 127.333px; margin-right: 15px;"><span class="size">S</span></div>
</div>
<div class="size-option-container" option="1366">
<div class="size-option"><span class="size">M</span></div>
</div>
<div class="size-option-container" option="1351">
<div class="size-option"><span class="size">L</span></div>
</div>
<div class="size-option-container" option="1447">
<div class="size-option"><span class="size">XL</span></div>
</div>
<div class="size-option-container" option="953">
<div class="size-option"><span class="size">XXXL</span></div>
</div>
<div class="size-option-container" option="1016">
<div class="size-option"><span class="size">XXXXL</span></div>
</div>
<div class="size-option-container" option="1070">
<div class="size-option"><span class="size">4X</span></div>
</div>
<div class="size-option-container" option="1117">
<div class="size-option"><span class="size">5X</span></div>
</div>
</div>
Specifically the first size-option-container:
<div class="size-option selected" style="width: 127.333px; margin-right: 15px;"><span class="size">S</span></div>
UPDATE
Random changes to the class styles periodically stop adding the inline styles.
UPDATE 2
Adding style='' to div.size-option solves the issue.
UPDATE 3
Changing the HTML around a little I now have a new random style:
<div class="small-4 columns" style="transform: translate3d(0px, 0px, 0px); transition-duration: 300ms;"><div class="size-option-container" option="1428"><div style="" class="size-option"><span class="size">S</span></div></div></div>

Since the code you've posted doesn't involve the style property at all and Mithril is a totally unopinionated about styling, it's clear to me that this is down to external code modifying the contents.
If you're using a modern web browser, you can use DOM breakpoints to identify the script that's causing these modifications. Using Chrome, for example:
Add a config function to the wrapping element and stick a debugger statement in it:
return <div
id="options-container"
config={function(el,init){
if(!init)
debugger
}}
>
Open developer tools by hitting F12 and (re)load the page running your script: the browser will pause script execution immediately after the element is generated by Mithril.
Chrome will show you the value assigned to the el parameter of the config function: right-click it and 'Reveal in navigator' - or right-click the element as it appears in the browser and 'Select' it.
In the elements panel, right-click the element that gets strange styles applied to it, and select 'Break on...' > 'Attributes modifications'.
Hit F8 to resume script execution (it should still be paused from landing on the debugger statement.
The browser will pause script execution whenever a script attempts to modify the attributes of the element in question, and reveal the line of code doing it. When this happens, it will probably be a generic attribute modification method jQuery or similar. By hitting Ctrl+., you can move back to the function that called this one, successively, until you reach a line of code from your source code.

Related

Set focus to first item in v-for using vue

I have a vue app and I'm trying to set the focus to the first item in my v-for list but struggling
HTML
<div class="input-group-append">
<button class="btn btn-light" type="submit" style="border: 1px solid lightgray" #click.prevent="findTest">
<i class="fas fa-search"></i>
</button>
</div>
<div v-if="this.Tests.length >= 2" class="list-group accList">
<a v-for="(test, i) in tests" :key="i" class="list-group-item list-group-item-action" :ref="i" :class="{ 'active': i === 0 }" #click.prevent="selectTest(test)">
{{ test.test1 }} ({{ test.test2 | capitalize }})
</a>
</div>
Note the word 'test' has replaced my actual values
I have tried using the following in my method which is called on button click but I keep getting get an error
methods: {
findTest() {
axios.get(END_POINT).then((response) => {
...SOMEOTHER CODE
//this.$refs.0.$el.focus()
//this.$refs.0.focus();
//this.$refs.a.$el.children[0].focus();
}
}
}
Error
I am relativly new to vue but I have been able to set my focus using:
this.$refs.[INPUT_NAME].$el.focus()
But it doesn't like me using a number
this.$refs.0.$el.focus() //0 being the index number
As WebStorm complains saying:
Expecting newline or semicolon
console.log(this.$refs)
When using v-for, ref maybe array of refs.
Template: use ref="tests" instead of :ref="i"
<a v-for="(test, i) in tests" :key="i" class="list-group-item list-group-item-action" ref="tests" :class="{ 'active': i === 0 }" #click.prevent="selectTest(test)">
{{ test.test1 }} ({{ test.test2 | capitalize }})
</a>
Script
this.$refs.tests[0]
I guess its undefined because you try to access the element while the v-for loop didnt finished its rendering
Try this:
methods: {
findTest() {
axios.get(END_POINT).then((response) => {
...SOMEOTHER CODE
this.$nextTick(()=> {
//put your code here
//this.$refs.0.$el.focus()
//this.$refs.0.focus();
//this.$refs.a.$el.children[0].focus();
})
}
}
}
Put your code into $nextTick() that should ensure that its get executed when the loop is done

Invalid string length at repeat$1 (VueJS) [Resolved: continue is a reserved JavaScript word]

I'm having the Error in execution of function repeat$1 while compiling a very simple VueJS template. This error prevents the app from compiling.
Can't wrap my head against what's wrong whit the template.
Here's the code:
(I replaced parts of the template that consisted solely on text with the word "text".)
<template>
<div class="container">
<div class="row">
<div class="col-lg-10 mx-auto" v-if="showPrivacyDisclaimer">
<div class="card mt-4">
<div class="card-body">
<div class="card-title">
text
</div>
<p>
<b>text</b>
</p>
<p>
text.
</p>
<p>
text
</p>
<div class="text-sm">
<a #click="details = true" style="text-decoration: underline">
Leer más: ¿Qué datos recopilamos?
</a>
<p v-if="details">
text
</p>
<br>
<a #click="rights = true" style="text-decoration: underline">
Leer más: ¿Cómo ejercer tus derechos sobre estos datos?
</a>
<p v-if="rights">
text
</p>
</div>
</div>
<div class="card-footer">
<button type="button"
class="btn btn-primary"
#click="continue()">
Aceptar y continuar
</button>
</div>
</div>
<img :src="baseUrl + '/public/img/eks-logo.svg'"
class="mt-4" style="max-width: 10rem">
<p class="text-muted mt-4 text-sm">
text
<br>
more text
</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Home',
data() {
return {
baseUrl: process.env.VUE_APP_PHP_BASE_URL,
showPrivacyDisclaimer: false,
details: false,
rights: false,
}
},
mounted()
{
let hasPrivacyAccepted = window.localStorage.getItem('pda');
if (!hasPrivacyAccepted) {
this.showPrivacyDisclaimer = true;
} else {
this.continue();
}
},
methods: {
continue()
{
window.localStorage.setItem('pda', 1);
this.$router.replace({
path: '/encuesta/' + this.$route.query.e,
query: this.$route.query
})
}
}
}
</script>
If I completely remove everything between the <template> tags (except the first div that is required), the app starts compiling again.
I have tried progressively deleting parts of the template that use Vue directives (v-if, etc.). But this didn't made the app compile :(
Please help!
Update: I forgot to mention I've already tried deleting and re-installing node_modules
Update 2: I found the source of the bug. continue is a reserved JS word.
You can't use #click="continue()"
This is a reserved word for javascript.
You can see the full list here :
https://www.w3schools.com/js/js_reserved.asp
Update: I started refactoring the template in two views and a more descriptive error message pop'd-up.
The error was that I was using a JavaScript reserved word as a method name (continue is a reserved word).

Vuejs event modifiers

This is from the docs:
#click.prevent.self will prevent all clicks while #click.self.prevent will only prevent clicks on the element itself.
I tried making a fiddle to actually prevent all clicks but am unsuccessful. Can someone elaborate what this line in the docs actually mean?
Fiddle:
var app = new Vue({
el: '#appp',
methods: {
logger(arg) {
console.log(arg);
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<div id="appp">
<div #click.prevent.self="logger('1')"> 1
<br>
<div #click.prevent.self="logger('2')"> ..2
<br>
<div #click.prevent.self="logger('3')"> ....3
</div>
</div>
</div>
</div>
One of the best ways to see how .prevent and .self interact is looking at the output of the Vue compiler:
.prevent.self:
on: {
"click": function($event){
$event.preventDefault();
if($event.target !== $event.currentTarget)
return null;
logger($event)
}
}
.self.prevent
on: {
"click": function($event){
if($event.target !== $event.currentTarget)
return null;
$event.preventDefault();
logger($event)
}
}
The key difference between those 2 code blocks is inside the fact that the order of the operations matters, a .prevent.self will prevent events coming from its children, but doesn't run any code, but a .self.prevent will only cancel events directly created by itself, and ignores child requests completely.
Demo:
var app = new Vue({
el: '#appp',
data: {log:[]},
methods: {
logger(arg) {
this.log.push(arg);
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<div id="appp" style="display: flex; flex-direction: row;">
<form #submit.prevent="logger('form')" style="width: 50%;">
<button>
<p #click.prevent.self="logger('prevent.self')">
prevent.self
<span>(child)</span>
</p>
<p #click.self.prevent="logger('self.prevent')">
self.prevent
<span>(child)</span>
</p>
<p #click.prevent="logger('prevent')">
prevent
<span>(child)</span>
</p>
<p #click.self="logger('self')">
self
<span>(child)</span>
</p>
<p #click="logger('none')">
none
<span>(child)</span>
</p>
</button>
</form>
<pre style="width: 50%;">{{log}}</pre>
</div>
</div>

dojo dnd change the type of the dragged element

I am using Dojo 1.8.3
I want to develop a Customizable Form using dnd. I have a list of form elements in the left dojo/dnd/Source and the container in the right dojo/dnd/Target which is supposed to generate dijits when I drop on it.
<div class="normal" style="width: 99%; height: 99%;" data-dojo-type="dijit/layout/BorderContainer"
data-dojo-props="design:'sidebar', gutters: true, liveSplitters: true">
<div data-dojo-type="dijit/layout/ContentPane" class="normal" style="width: 30%; height: 80%;"
data-dojo-props="splitter: true, region: 'left'">
<div data-dojo-type="dojo/dnd/Source" data-dojo-id="form_tools" id="form_tools" data-dojo-props="copyOnly: true"
class="container" style="width:99%;">
<div class="dojoDndItem" dndtype="heading">Heading</div>
<div class="dojoDndItem" dndtype="textbox">Text Box</div>
...
</div>
</div>
<div data-dojo-type="dijit/layout/ContentPane" class="normal" id="form_container"
style="width: 68%; height: 80%;" data-dojo-props="splitter: true, region: 'center'">
<div data-dojo-type="dojo/dnd/Target" data-dojo-id="form_items" id="form_items" class="container" style="height: 80%;" accept="heading,textbox">
<script type="dojo/on" event="DndDrop"> form.transform_item(arguments[0], arguments[1], arguments[2], arguments[3]);//source, nodes, copy, target </script> </div>
</div>
</div>
In my js function transform_item, I am doing this:
this.transform_item = function(){
var dragged_items = arguments[3].selection;
form_items.forInSelectedItems(function(item, id, map){
var dnditem = dojo.byId(id);
switch(item.type[0]){
case "textbox":
var textbox = new dijit.form.TextBox({
name: "textbox",
value: "This is a TextBox"
}, "textbox_text");
// HERE IS WHERE I SHOULD INSERT THE CODE FOR GENERATING A TEXTBOX
require(['dojo/parser'], function(parser){
parser.parse('textbox_text');
});
break;
}
});
}
At this point I'm getting an error when I drop over the Target :
dojo/parser::parse() error
TypeError: root is null
var node = root.firstChild;
How can I make Dojo generate, for example a dijit.form.TextBox when I drag an "textbox" dndtype?
Solved: I have just inserted the textbox in the wrong parent, textbox_text does not exist.So No need of parse();

jQuery Animation - not working when called thro a function

My objective is to create a generic function for animation which would require to pass in parameters, assuming the function can be used for animating any elements.
I started with simple animation that wouldn't require passing parameters and it seems to work fine. Here is the code and link
<div id="outer" class="box">
<div id="inner" class="box"></div>
</div>
<input type="button" id="animate" value="Animate"/>​
​$("#inner").animate({left: '+=300', top: '+=300'}, 1000);​
BUT its not working when I try to write a genric function... code
$("#animate").Click(function(){
diagonalAnimation("inner");
});
function diagonalAnimation(e){
$('"#'+e+'"').animate({left: '+=300', top: '+=300'}, 1000);
}
jsFiddle( http://jsfiddle.net/5v86F/81/ )
<div id="outer" class="box">
<div id="inner" class="box"></div>
</div>
<input type="button" id="animate" value="Animate" onclick="animate('inner')"/>
<script>
function animate( item )
{
$( "#" + item ).animate({left: '+=300', top: '+=300'}, 1000);
}
</script>