#focus event is not bubble by default - events

Vue version:
3.2.39
While click on the button, the focus does not bubble to the wrapper, and that is why it does not show the "wrapper focus". How to fix this?
<template>
<div tabindex="-1" #focus="onWrapperFocus" #blur="onWrapperBlur">
<button #focus="onInnerFocus" #blur="onInnerBlur">Hello</button>
</div>
</template>
<script >
export default {
setup() {
return {
onWrapperFocus() {
console.log("wrapper focus");
},
onWrapperBlur() {
console.log("wrapper blur");
},
onInnerFocus() {
console.log("inner focus");
},
onInnerBlur() {
console.log("inner blur");
},
};
},
};
</script>
Expected behavior:
inner focus
wrapper focus

There is another phase of event called "capturing". It is rarely used in real code, but can be usefull in this case.
You can add the capturing phase by adding .capture after the event name like shown below:
<div tabindex="-1" #focus.capture="onWrapperFocus" #blur.capture="onWrapperBlur">
<button #focus="onInnerFocus" #blur="onInnerBlur">Hello</button>
</div>

As it turned out, this is not related to vue. 😆 Just needs to read the documentation time to time. About focusin/focusout -
https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event
Instead focus/blur, I use focusin/focusout and it's work how I wanted.

Related

Reactive Vue Data Does Not Render in Firefox Columns

I've run into an extremely strange problem while developing a Vue SPA in Firefox (v89.0.1). Reactive data will not render on the page when it is contained within columns. Here is an example:
<template>
<div style="column-count: 2">
<div style="break-inside: avoid;">
Column 1
</div>
<div style="break-inside: avoid;">
Column 2
<div v-if="test">{{ test }}</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
test: ''
};
},
mounted() {
setTimeout(() => {
this.test = 'tested';
}, 2000);
}
};
</script>
In Chrome, the word "tested" is correctly rendered in the second column. In Firefox the word "tested" does not immediately appear, but it will appear later if the window is resized. The issue is resolved if the column-count style is removed.
Is this a known issue and, if so, does anyone have a suggested work around? Really scratching my head on this. (Note: I'm using column-count to create a masonry layout, so I can't easily substitute another grid solution.)

localStorage persisting with looped Vue component

I'm having the strangest time getting localStorage to work on my local machine. I seem to be losing indexes in the array I built, I've been trying for hours to figure out why with absolutely no luck. I've even tried different ways of building the array.
Here is the component I am loading with a v-for loop. this is working as expected.
home.vue
<tweets
v-for="tweet in tweets"
v-bind:key="tweet.id"
v-bind:tweet="tweet"
></tweets>
And here is the trouble-maker component. It loads a number of tweets that can be voted on. (Feel free to ignore the HTML, I'm not sure it's relevant.)
tweets.vue
<template>
<div class="col-2 d-flex">
<div class="align-self-center ml-3">
<div class="row py-1">
<i
class="fas fa-arrow-up"
style="font-size: 30px"
v-on:click="voteUp"
></i>
</div>
<div class="row py-1">
<i class="fas fa-arrow-down" style="font-size: 30px"></i>
</div>
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
localStorage: [],
};
},
props: {
tweet: Object,
},
created: function () {
this.localStorage = JSON.parse(localStorage.storageData);
console.log(this.localStorage);
},
methods: {
voteUp: function () {
axios
.get("/api/vote/2/1")
.then(({ data }) => {
var test = {
"tweet_id": 1,
"vote_status": 1
};
this.localStorage.push(test);
console.log(this.localStorage);
localStorage.setItem("storageData", JSON.stringify(this.localStorage));
console.log("go");
//persist?
})
.catch(function (error) {
alert("Take a screen shot and send this to me." + error);
console.log(error);
});
},
},
};
</script>
So if you take a look at my localStorage variable, I have it being set to the current localStorage found in the browser, however...it's having this strange problem where if I click on the button that triggers the voteUp function, it will sometimes delete some of the indexes in the array. I'm having trouble explaining so I've make a quick video to demonstrate.
https://streamable.com/kkhnrx
as you can see, I'm firing the event and the array starts growing, but as I scroll down to different buttons (remember the tweets are looped) the array will lose a few of it's indexes. I have no idea why this is happening. I assume it has something to do with the component being looped and scope problems?
This looks exactly like race condition. There are multiple component instances that compete over the storage, and it becomes overwritten eventually.
This makes an early copy that won't contain updates from other instances:
this.localStorage = JSON.parse(localStorage.storageData)
this.localStorage should be assigned immediately before updating the storage, or there should be a common state for all component instances (e.g. by using Vuex with persistence).
You have an error in your created function, right?
If you want to get "storageData" from local storage it should be:
created: function () {
this.localStorage = JSON.parse(localStorage.getItem('storageData'));
console.log(this.localStorage);
},

Vuetify / Mouseover does not work with v-system-nav

Is there a way to make mouseover work with v-system-nav? I have the following fiddle which demonstrates my issue:
https://jsfiddle.net/6dqfz3j2/1/
<div>
<div id="content">
<v-card #mouseover="abc">Mouseover this and look at the console. Mouseover works!</v-card>
<v-system-bar #mouseover="abc">Mouseover this and look at the console. Mouseover does not work!</v-system-bar>
</div>
</div>
...
methods: {
abc() {
console.log('hi');
},
},
Is it a bug? Is there some property I can overwrite to make it work?
Thanks!
Got it. It needs to be #mouseover.native="abc" for the v-system-nav

Kendo UI Gantt - Custom Task Edit Template

I have created a custom template for a task using this example:
http://docs.telerik.com/kendo-ui/api/javascript/ui/gantt#configuration-editable.template
<script id="editor" type="text/x-kendo-template">
<h3>Edit meeting</h3>
<p><label>Title: <input name="title" /></label></p>
<p><label>Start: <input data-role="datetimepicker" name="start" /></label></p>
<p><label>End: <input data-role="datetimepicker" name="end" /></label></p>
</script>
Now I need to add a 'Resources - Assign' button, just like the one in this example (Edit Task Form):
http://demos.telerik.com/kendo-ui/gantt/resources
What do I need to do to create this button? I can't find any API documentation for this part of the Gantt control.
There are a few steps needed to accomplish this.
First, add something like this to your Kendo template:
<div>
<label for='resources'>Resources:</label>
<div class='k-gantt-resources' style='display: none;'>
</div>
<div class='k-edit-field' data-container-for='resources'>
<a class='k-button' href='\\#'>Assign</a>
</div>
</div>
Next, you'll want to add the following two event handlers to the options when you initialize the widget:
edit: editHandler,
save: saveHandler
Finally, you'll want to create the two handlers referenced above. You are basically intercepting the default functionality and opening the popup yourself, then saving the results when complete (if they were modified).
var resoucesdEdited = false;
function editHandler(e)
{
var gantt = e.sender;
resoucesdEdited = false;
if (e.task)
{
e.container.on('click', 'div[data-container-for="resources"] > a', function (event)
{
event.preventDefault();
resoucesdEdited = true;
gantt._createResourceEditor(e.container.find('div.k-gantt-resources'), e.task);
});
}
}
function saveHandler(e)
{
if (e.task && resoucesdEdited)
{
this._updateAssignments(e.task.get("id"), e.task.get(this.resources.field));
}
}
I'm glad you asked this question because it's something I needed to know too, and you're right, the Telerik/Kendo documentation doesn't mention anything on how to do this!

jQuery, stopping clicking during animations

:D
I am currently having much trouble with a jQuery animation. Basically, a button click will quickly start a short animation and collapse a sidebar, widening the main content box to full width (and back again if wanted). The issue is that with quick consecutive clicks, the layout goes all crazy. I have tried this condition:
if (!$(this).is(":animated"))
{
// Code
}
But it doesn't work. So I have tried .off(), and it shuts off, but I cannot find out how to turn it back .on(). Can someone help me please? Here is what I have:
<script type="text/javascript">
$(document).ready(function(){
var $button = $("a#toggle");
var $content = $("div#index_main-content");
var $sidebar = $("div#sidebar");
// Disable quicky clicky
$button.click(function() {
$button.off().delay(1000).on();
});
// Hide sidebar
$button.toggle(function sidebarToggle() {
$sidebar.fadeOut(500, function() {
$content.animate({width: '100%'}, 500, function() {
$button.attr("title", "Click to show the sidebar!").addClass("hiding").removeClass("showing");
});
});
},
// Show sidebar
function sidebarToggle() {
$content.animate({width: '69.5%'}, 500, function() {
$sidebar.fadeIn(500, function() {
$button.attr("title", "Click to hide the sidebar!").addClass("showing").removeClass("hiding");
});
});
});
});
</script>
<div id="index_content">
<a title="Click to hide the sidebar" class="showing" id="toggle"></a>
<div id="sidebar">
<!-- Sidebar: float-right/width-28.5% -->
</div>
<div id="index_main-content">
<!-- Content: float-left/width-69.5% -->
</div>
</div>
Also, there is a live demo here. Like I said before, for some reason, the .on() does not happen. :(
Thank you. :)
$content.stop(true,true).animate({ //code });
Try using stop before issuing the animation the second time, for example:
$content.stop().animate(
This will stop and previous animations before starting the new one.
Also use true in the stop statement to cancel other animation and complete the animations.
$content.stop(true,true).animate(
See:
http://api.jquery.com/stop/
stop() to stop the current animation,
clear the animation queue and go to the end of the animation .stop(true,true)
or
turn the button to OFF before you start the animation
turn the button to ON within the animation callback function, so that
is turned on again after the animation finished
OR more easy
<div id="index_content">
<a title="Click to hide the sidebar" class="showing" id="toggle">Click me</a>
<div id="sidebar">sidebar
<!-- Sidebar: float-right/width-28.5% -->
</div>
<div id="index_main-content">content
<!-- Content: float-left/width-69.5% -->
</div>
</div>
$(document).ready(function(){
$('#toggle').click(function(){
$('#sidebar:visible').fadeOut('slow')
$('#sidebar:hidden').fadeIn('slow')
})
})
take a look#
http://jsfiddle.net/jdFrR/

Resources