How to init a ES6 module for each on-page element - javascript

I'm trying to create a ES6 module that can be initialized multiple times (once for each instance of an on-page element).
I have a page with 3 video components on it, I want to toggle the class of 'playing' on the video that the click came from. However only the instance of the last video is ever having the class toggled.
Could someone please help..? I can't for the life of me get the code running for each individual instance.
index.html
<div class="video">...</div>
<div class="video">...</div>
<div class="video">...</div>
main.js
import * as video from './video';
var $videos = $('.video');
$.each($videos, function(i, $video) {
video.build($video);
});
video.js
export function build (videoInstance) {
$(videoInstance).on('click', function (e) {
$(this).toggleClass('playing');
});
}

Related

Nuxt.js – script using document working in the whole project

for my CSS framework customization needs I'm using a script for an onClick button "pulse effect". Currently I run it in mounted() part of my default.vue layout in Nuxt.js project running in SSR mode.
This is the script:
if (process.client) {
var elements = document.querySelectorAll(".button");
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener("click", function (event) {
event.preventDefault;
this.classList.remove("pulse");
void this.offsetWidth;
this.classList.add("pulse");
});
}
}
It's an easy script and it's working well but only on reload and only for some buttons which are on the top of my page's DOM.
When I copy-paste this script into a component's script part, it's working in the component well. But I do not want to include it into every component.
Where in my project should I add it to make it working in all components? I've tried to add it into the nuxt-config but it did not work.
Please help.
I would create a plugin that do that stuff for you you need to go to nuxt.config.js
plugins: ['~/plugins/pulse.js']
Now you go to your plugins folder and create that pulse.js and write in
import Vue from 'vue'
Vue.directive('pulse', {
inserted: (el) => {
el.addEventListener("click", function (event) {
event.preventDefault;
el.classList.remove("pulse");
void el.offsetWidth;
el.classList.add("pulse");
});
}
})
After that your directive is global and you can go to any button you want and add simply v-pulse to it
<button v-pulse>Click me</button>
Tell me if it works and if you receive any errors.

How to add ngx-loading-bar as preloader into Angular project

I have a project developed in Angular 6+, when user comes to website, first he sees logo and loading bar underneath it.
I have a problem switching to ngx-loading-bar insted of pace.js
Right now I am using Pace (the last example a fixed width line)
https://github.hubspot.com/pace/docs/welcome/
integrated into the index.html of the root project.
I want to put ngx-loading-bar instead of pace to do same job.
ngx-loading-bar is already implemented and working when adding <ngx-loading-bar></ngx-loading-bar> in some of the components but not in the index.html.
I want to put same style same width loading bar as on example link bellow (4th bullet example, similar to pace)
https://aitboudad.github.io/ngx-loading-bar/
so on the load, users sees the loading bar how it loads and on load, it goes on the next component as project example bellow.
Here is the example of project
www.wowlectures.com/pitchdeck
Not sure why you want it to work in index.html, do it in app.component.
You could create a loading service. A simple way is this:
#Injectable({providedIn: 'root'})
export class LoadingService {
private _loading = true;
get isLoading() {
return this._loading;
}
set isLoading(v: boolean) {
this._loading = v;
}
}
Then in app.component.ts:
export class AppComponent {
constructor(public loading: LoadingService) {}
}
And app.component.html:
<any-loading-component *ngIf="loading.isLoading"></any-loading-component>
<router-outlet></router-outlet>
A cleaner way is to use subjects/observables in the service and subscribe to changes where you want to show the loading-bar and dispatch from anywhere you want it to start loading.
<app-root>
<ngx-loading-bar></ngx-loading-bar>
</app-root>
hey you can add this in your index.html

Where do I put "main.js" file in Gatsby project?

I have a function that grabs an element and adds the class "is-open" in order to toggle an accordion. I have put this function in my "main.js".
In my FAQ component, this function needs to be called when a user clicks the accordion bar.
My question is: How do I import this main.js file within my Gatsby.js / React project?
I tried in the index or the component itself. But it is only called once I make changes to the main.js file. Obviously, I want it to be called right away when the page loads up.
This is the function within my main.js file:
const accordionEl = document.getElementsByClassName("faq-module--accordion-title--2zVOe")
if (accordionEl.length) {
for (let i = 0; i < accordionEl.length; i++) {
accordionEl[i].addEventListener("click", function() {
this.parentNode.classList.toggle("is-open")
const panel = this.nextElementSibling
if (panel.style.maxHeight) {
panel.style.maxHeight = null
} else {
panel.style.maxHeight = `${panel.scrollHeight}px`
}
})
}
}
Like I said, I have tried to add it like so in my FAQ component:
import "../js/main..js"
I have also tried to add it in index.html with tags.
You can put this in your footer (or some place that always loads):
<script src={`path/to/main.js`}></script>
Use the path to the file of the BUILT version. So you should probably put the script in "static/js/", and you should be able to import it from there.
But this is not really how you want to use Gatsby. Gatsby is built upon React, so for the reactive JavaScript, you should really be using React. It can't predict what the state of the DOM is if you start updating it behind its back. Furthermore this should be really easy to recreate in React with a simple onClick handler.

Responding to a click on a Vue element programmatically

Essentially, I want my Vue instance to respond to a click on an uploaded thumbnail.
I'm using the FineUploader Vue package with the template layout per the docs (see end of the question). Upon uploading an image, a tree like this is outputted:
<Root>
<Gallery>
<Thumbnail>
</Gallery>
</Root>
Coming from a jQuery background I really have no idea about the 'correct' way to go about this given that the Thumbnail Template is defined by the package already, and so I'm not creating my own Thumbnail template. I know that I can access elements like this:
let thumb = this.$el.querySelector('.vue-fine-uploader-thumbnail');
And perhaps a listener
thumb.addEventListener('click', function() {
alert('I got clicked');
});
But dealing with the Vue instance being re-rendered etc. I'm not familiar with.
Vue Template:
<template>
<Gallery :uploader="uploader" />
</template>
<script>
import FineUploaderTraditional from 'fine-uploader-wrappers'
import Gallery from 'vue-fineuploader/gallery'
export default {
components: {
Gallery
},
data () {
const uploader = new FineUploaderTraditional({
options: {/*snip*/}
})
return {
uploader
}
}
}
</script>
In order to respond to click events you add the v-on:click (or it's short form: #click) to whatever tag you want.
If you have elements that are nested that respond to the click event you might experience that a click on a child triggers a parents click event. To prevent this you add #click.stop instead, so that it doesn't trigger the parents click.
So you would have something along the lines of:
<Gallery #click="myFunction" />

Creating a global modal using react-redux and foundation reveal

I'm creating a modal that displays information about a specific user and it's triggered by clicking on a picture. The modal should be able to fire up from different components. My approach is as follows (I use React with Redux):
create store with a "modal" property that's set to a reducer "modalReducer"
modal: modalReducer
modal is an object with the following properties: showModal=false, user=undefined, image=undefined
When a div containing picture is clicked, the action is being dispatched that sets showModal to true (with username and url image link as arguments).
export var openModal = (user, image) => {
return {
type: 'OPEN_MODAL',
user,
image
}
}
For the actual modal I use a foundation reveal modal and in its render method I check if modal.showModal == true and use jQuery to open it up.
Now, toggling the modal works as charm but I cannot use the modal.user and modal.image properties inside of the render method as it prints the following error message:
Uncaught Error: findComponentRoot(..., .0.2.0.0.1): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a when using tables, nesting tags like , , or , or using non-SVG elements in an parent. Try inspecting the child nodes of the element with React ID ``.
I'm almost certain the problem lies within the ProfileModal.jsx component. Any idea what I'm doing wrong?
export class ProfileModal extends React.Component {
componentDidMount () {
var elem = new Foundation.Reveal($('#profile-modal'));
$('#profile-modal').on('closed.zf.reveal',()=>{this.props.dispatch(actions.hideModal())});
}
render () {
var {modal} = this.props;
if (modal.showModal) {
$('#profile-modal').foundation('open');
}
return(
<div>
<div id="profile-modal" className="reveal large">
<div className="modal-container">
<div className="modal-picture" style={{backgroundImage: `url(${modal.image})`}}></div>
<p>{modal.user}</p>
...

Categories

Resources