Infinite loop on .hover with backgroundImage - jquery-animate

<script type="text/javascript">
$(document).ready(function() {
$('.istina').hover(function() {
animate_loop = function() {
$(this).css('backgroundImage', 'url(<?php print $base_path . $directory ?>/img/istina-hover.png)').animate({backgroundImage: 'url(/sites/all/themes/ruh/img/istina.png)'}, 500, function() { animate_loop(); } );
}, function() {
$(this).css('backgroundImage', 'url(<?php print $base_path . $directory ?>/img/istina.png)');
}
}
)
});
I have a link with class <a class="istina">some text</a> i want to change backgroundImage of it on hover and while hover i want to switch between istina.png and istina-hover.png
Thanks!

you dont need any javascript to do this, it can be CSS driven...
html:
<a class="istina">some text</a>
css
#istina {
background-image : url(istina.png);
}
#istina :hover {
background-image : url(istina-hover.png);
}

Related

Styling component nested in opened new window

I'm trying to style component mounted in new window but it seems like it's not readable. However inline styling is working. It is possible to style with style section in component?
Code explain:
When component is mounted i'm opening new window with this component as argument.
<template>
<!-- Inline styling works -->
<div style="background-color: red" class="window-wrapper" v-if="open">
<slot />
</div>
</template>
<script>
export default {
name: 'window-portal',
props: {
open: {
type: Boolean,
default: false,
}
},
data() {
return {
windowRef: null,
}
},
watch: {
open(newOpen) {
if(newOpen) {
this.openPortal();
} else {
this.closePortal();
}
}
},
methods: {
openPortal() {
this.windowRef = window.open("", "", "width=800,height=600,left=200,top=200");
this.windowRef.addEventListener('beforeunload', this.closePortal);
//here i'm opening new window with this compomnent
this.windowRef.document.body.appendChild(this.$el);
},
closePortal() {
if(this.windowRef) {
this.windowRef.close();
this.windowRef = null;
this.$emit('close');
}
}
},
mounted() {
if(this.open) {
this.openPortal();
}
},
beforeUnmounted() {
if (this.windowRef) {
this.closePortal();
}
}
}
</script>
<style scoped>
.body {
box-sizing: border-box;
}
/* here styling is not working */
.window-wrapper {
background-color: red;
}
</style>
Also components passed as slot cannot read styles from styles section.

How do I bind this src to an iFrame in vue js?

How should I bind to an iframe src with something received back via the YouTube data api?
Can I set a string inside :src and concatenate onto the end of it?
/embed/'this.param.videoId'
The response returns an Id {{ video.snippet.resourceId.videoId }}, but the url contains other parts src=“https://www.youtube.com/embed/xxx”
Any help greatly appreciated!
Thanks
This worked:
:src="ytEmbedUrl + video.snippet.resourceId.videoId"
iframe resolving only when there's a videoId:
<iframe v-if="videoId" :src="mySrc"></iframe>
computed property:
computed: {
mySrc: {
get: function() {
//concat using template literal
return `https://www.youtube.com/embed/${this.videoId}`
}
}
}
data property:
{
videoId: false
}
Your method to assign to it:
methods: {
getMyVideo() {
video = // get my video code
this.videoId = video.snippet.resourceId.videoId
}
}
Or just inline it if you're super lazy:
<iframe src="`https://www.youtube.com/embed/${videoId}`"></iframe>
Here is what is working for me with Bootstrap V5 css
<template>
<section class="video-player-container">
<div class="video-player-row">
<div
class="video-player ratio"
:class="`ratio-${group.videoAspectRatio}`"
>
<iframe
loading="lazy"
:src="`https://www.youtube.com/embed/${getIdFromURL(group.videoEmbedLink)}?rel=0`"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
/>
</div>
</div>
</section>
</template>
<script>
export default {
name: 'VideoPlayer',
props: {
group: {
type: Object,
required: true
}
},
methods: {
getIdFromURL (url) {
const youtubeRegexp = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig
let id = url.replace(youtubeRegexp, '$1')
if (id.includes(';')) {
const pieces = id.split(';')
if (pieces[1].includes('%')) {
const uriComponent = decodeURIComponent(pieces[1])
id = `http://youtube.com${uriComponent}`.replace(youtubeRegexp, '$1')
} else {
id = pieces[0]
}
} else if (id.includes('#')) {
id = id.split('#')[0]
}
return id
}
}
}
</script>
<style scoped lang="scss">
.video-player {
&-container {
#include make-container();
#include default-max-widths();
}
&-row {
#include make-row();
}
}
</style>

What is the opposite of $set in Vue.js?

In a blog app, I'd like to show/hide comments of each post inside a loop of posts. I know how to show the div containing the comments by setting a showComments on the fly:
this.$set(post, 'showComments', true) ;
But I don't know how to hide the post's comments when the div is already open. What I tried is this:
if (this.$get(post, 'showComments')==true) {
this.$set(post, 'showComments', false) ;
return
}
The code above thoes not work and I get this error:
Uncaught TypeError: this.$get is not a function
So I'm wondering how can I acheive this functionaliry.
You should be able to simply read the dynamic property and reapply the value.
new Vue({
el: '#app',
data() {
return {
posts: [
{ content: 'Post #1' },
{ content: 'Post #2' },
{ content: 'Post #3' }
]
}
},
methods: {
toggleComment(post) {
if ('showComment' in post) {
post.showComment = !post.showComment;
}
else {
this.$set(post, 'showComment', true);
}
}
}
})
.post {
background-color: lightgreen;
margin: 10px 0;
padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="post" v-for="(post, index) in posts" :key="index">
{{post.content}}
<p v-if="post.showComment">
Hidden comments.
</p>
<button #click="toggleComment(post)">Toggle comment</button>
</div>
</div>
Use property name to get property value
if ( typeof this.post.showComments !== 'undefined' && this.post.showComments ) {
Vue.set(post, 'showComments', false);
return;
}
Also note that you should try to avoid using this.$set because it was deprecated due to conflicts with other libraries. Consider using Vue.set instead.
https://v2.vuejs.org/v2/api/#Vue-set

Nuxt/Vue/Bootstrap-vue shrink navbar on scroll

Learning Vue with Nuxt. Want to change navbar classes depending on the page scroll position.
Looked in several places, but haven't found a working solution.
Here's what I have to work with:
``` default.vue
<template lang="pug">
div(v-on:scroll="shrinkNav", v-on:click="shrinkNav")
b-navbar.text-center(toggleable="sm" type="light" sticky v-b-scrollspy)
#myNav.mx-auto.bg-white
b-navbar-toggle(target="nav_collapse")
b-navbar-brand.mx-auto(href="#")
| Example.org
b-collapse#nav_collapse.mx-auto(is-nav='')
b-navbar-nav(justified, style="min-width: 600px").vertical-center
b-nav-item.my-auto(href='#home') Home
b-nav-item.my-auto(href='/how') How
i.fab.fa-earlybirds.fa-2x.mt-2.mb-3
b-nav-item.my-auto(href='/values') Values
b-nav-item.my-auto(href='/join-us') Join Us
#content.container(v-on:scroll="shrinkNav", v-on:click="shrinkNav")
nuxt
nuxt
</template>
<script>
// resize navbar on scroll
export default {
methods: {
shrinkNav() {
var nav = document.getElementById('nav')
var content = document.getElementById('content')
if (nav && content) {
if(content.scrollTop >= 150) {
nav.classList.add('shrink')
} else {
nav.classList.remove('shrink')
}
}
console.log(document.documentElement.scrollTop || document.body.scrollTop)
}
}
}
</script>
```
shrinkNav runs twice on click, but nothing on scroll. What is the Vue/Nuxt way to do this?
In your .vue:
<template> section:
<nav id="nav" class="navbar is-transparent is-fixed-top">
<script> section:
export default {
mounted() {
this.$nextTick(function(){
window.addEventListener("scroll", function(){
var navbar = document.getElementById("nav");
var nav_classes = navbar.classList;
if(document.documentElement.scrollTop >= 150) {
if (nav_classes.contains("shrink") === false) {
nav_classes.toggle("shrink");
}
}
else {
if (nav_classes.contains("shrink") === true) {
nav_classes.toggle("shrink");
}
}
})
})
},
}
Live Demo on codesandbox
Ok, here's a solution using Plugins. There may be a better way:
1) Define a directive in plugins/scroll.js
``` javascript
// https://vuejs.org/v2/cookbook/creating-custom-scroll-directives.html#Base-Example
import Vue from 'vue'
Vue.directive('scroll', {
inserted: function (el, binding) {
let f = function (evt) {
if (binding.value(evt, el)) {
window.removeEventListener('scroll', f)
}
}
window.addEventListener('scroll', f)
}
})
```
2) Add plugin to project in nuxt.config.js
``` javascript
module.exports = {
head: { },
plugins: [
{ src: '~/plugins/scroll.js', },
]
}
```
3) Use the v-scroll directive to define custom behavior in menu in /layouts/default.vue
``` javascript
<template lang="pug">
div(v-scroll="shrinkNav")
b-navbar.text-center(toggleable="sm" type="light" sticky)
#myNav.mx-auto.bg-white
b-navbar-toggle(target="nav_collapse")
b-navbar-brand.mx-auto(href="/#home") Example.org
b-collapse#nav_collapse.mx-auto(is-nav='')
b-navbar-nav(justified, style="min-width: 600px").vertical-center
b-nav-item.my-auto(to='/#home') Home
#content.container
nuxt
</template>
<script>
export default {
methods: {
shrinkNav() {
var scrollPosition = document.documentElement.scrollTop || document.body.scrollTop
var nav = document.getElementById('myNav')
console.log(scrollPosition, nav)
if(scrollPosition >= 150) {
nav.classList.add('shrink')
} else {
nav.classList.remove('shrink')
}
},
},
}
</script>
<style>
nav.navbar {
margin: 0;
padding: 0;
}
#myNav {
border-radius: 0 0 10px 10px;
border: 2px solid purple;
border-top: none;
}
#myNav.shrink {
border: none;
}
</style>
```

VueJS: #click.native.stop = "" possible?

I have several nested components on the page with parents component having #click.native implementation. Therefore when I click on the area occupied by a child component (living inside parent), both click actions executed (parent and all nested children) for example
<products>
<product-details>
<slide-show>
<media-manager>
<modal-dialog>
<product-details>
<slide-show>
<media-manager>
<modal-dialog>
</products>
So I have a list of multiple products, and when I click on "canvas" belonging to modal dialog - I also get #click.native fired on product-details to which modal-dialog belongs. Would be nice to have something like #click.native.stop="code", is this possible?
Right now I have to do this:
#click.native="clickHandler"
and then
methods: {
clickHandler(e) {
e.stopPropagation();
console.log(e);
}
code
<template>
<div class="media-manager">
<div v-if="!getMedia">
<h1>When you're ready please upload a new image</h1>
<a href="#"
class="btn btn--diagonal btn--orange"
#click="upload=true">Upload Here</a>
</div>
<img :src="getMedia.media_url"
#click="upload=true"
v-if="getMedia">
<br>
<a class="arrow-btn"
#click="upload=true"
v-if="getMedia">Add more images</a>
<!-- use the modal component, pass in the prop -->
<ModalDialog
v-if="upload"
#click.native="clickHandler"
#close="upload=false">
<h3 slot="header">Upload Images</h3>
<p slot="body">Hello World</p>
</ModalDialog>
</div>
</template>
<script>
import ModalDialog from '#/components/common/ModalDialog';
export default {
components: {
ModalDialog,
},
props: {
files: {
default: () => [],
type: Array,
},
},
data() {
return {
upload: false,
}
},
computed: {
/**
* Obtain single image from the media array
*/
getMedia() {
const [
media,
] = this.files;
return media;
},
},
methods: {
clickHandler(e) {
e.stopPropagation();
console.log(e);
}
}
};
</script>
<style lang="scss" scoped>
.media-manager img {
max-width: 100%;
height: auto;
}
a {
cursor: pointer;
}
</style>
Did you check the manual? https://v2.vuejs.org/v2/guide/events.html
There is #click.stop="" or #click.stop.prevent=""
So you don't need to use this
methods: {
clickHandler(e) {
e.stopPropagation();
console.log(e);
}
}
In the Vue, modifiers can be chained. So, you are free to use modifiers like this:
#click.native.prevent or #click.stop.prevent
<my-component #click.native.prevent="doSomething"></my-component>
Check events
I had the same problem. I fixed the issue by using following:
<MyComponent #click.native.prevent="myFunction(params)" />