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

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.

Related

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.

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

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

Link to leanModal.js works fine in rendered by HTML link but not within React

I am using Lean Modal: http://leanmodal.finelysliced.com.au/ in a Rails app with a React front-end.
When I put the link to the modal in application.html.erb it works fine but when loaded through a React link using the same code, nothing happens.
I have jQuery loaded and checked 10 times if the code is the same. What could cause such an issue?
Here is the link code in React:
<a rel="leanModal" name="login" href="#login">
The template file (html.erb) script:
<script type="text/javascript">
$(function() {
$('a[rel*=leanModal]').leanModal({ top : 200, closeButton: ".modal_close" });
});
And I am loading the modal JS from my application.js file in Rails.
Thanks for any help!
You should wrap things that interact with DOM (e.g. jQuery plugins) in a component.
var LeanModal = React.createClass({
componentDidMount: function(){
$(this.getDOMNode()).leanModal({
top: this.props.top || 200
});
},
render: function(){
return <div>{this.props.children}</div>;
}
});
Note that you also need to provide a componentWillUnmount to handle clean up, and that the plugin can't do things like add/remove elements. Plugins that don't allow cleanup or make destructive changes are incompatible with react.
Sometimes implementing it with just the existing CSS and using react components instead of the jQuery plugin can be very simple and end up with a better result.

Loading data ajax style

I jsut started learning angular.js. Can you guys show me the right way to make a page that initially presents an ajax loader element saying 'Loading data' or something like that. Then after data's been fetched it would update the view and hide the element. I can put stuff in page load event using jquery, but how do you do that using pure angular? So far I figured out how to put that in click event:
<div ng-app="VideoStatus" ng-controller="VideoStatusCtrl">
<button ng-click="getVideos()">get videos</button>
</div>
<script type="text/javascript">
angular.module('VideoStatus', ['ngResource']).run(function(){
// I guess somehow I can start fetching data from the server here,
// but I don't know how to call Controller methods passing the right scope
});
function VideoStatusCtrl($scope, $resource) {
$scope.videoStatus = $resource('/Videos/GetStatuses', { callback: 'JSON_CALLBACK' });
$scope.getVideos = function () {
$scope.videoResult = $scope.videoStatus.get();
console.log('videos fetched');
};
};
</script>
Kudos to Adam Webber & Peter Bacon Darwin
Here is the working plunker
Here is my version plunker that make loading as a directive with modal popup feature
Here is the tutorial to use my version
you only need loading.js and modal.js and reference jQuery and twitterbootstrap css.
in your code,
Only 2 steps you need to do with your code.
Add the following code to HTML
< div data-loading> < /div>
Add LoadingModule module to your application module.
angular.module('YourApp', ['LoadingModule'])

ExtJS: starting HtmlEditor defaulting to source

I'm using ExtJS 3.2.1 and I need a component almost identical to the bundled HtmlEditor, with one exception: it must start editing the HTML source code directly. The reason I don't use a normal TextArea is that the user should be able to preview the result of his actions before submitting.
I've tried calling toggleSourceEdit(), as per ExtJS documentation, with no success. Debugging, I see that the editor object has the sourceEditMode property set to true, and the Source Edit button seems as if it was "pressed", but clicking on it does not render the typed HTML, and clicking it again goes to the Source Mode.
I've tried calling toggleSourceEdit() after the container show() method, on the container afterLayout listener and on the editor afterRender listener. I've tried also calling it on another button that I added to the container. The result is the same on every try.
The only other option I see is updating ExtJS to 3.3.0, but I haven't seem anything related on the changelogs. Either way, it's going to be my next step. EDIT: The app had another problems when updating, we'll make a bigger effort to update later. As of right now, we are using the HtmlEditor in its original setting.
Thanks!
ran into the same problem (using 3.3.0 by the way)
stumbled upon a fix by dumb luck. i have no idea why this works, but second time is the charm. call it twice in a row to achieve the desired effect..
HTMLEditor.toggleSourceEdit(true);
HTMLEditor.toggleSourceEdit(true);
hope that helps!
Rather calling toggleSourceEdit(), try to setup the configuration while you create HtmlEditor Object
Using toggleSourceEdit() caused some problems for me. One was that this seemed to put the editor somewhere in limbo between source edit and WYSIWYG mode unless I used a timeout of 250ms or so. It also puts the focus in that editor, and I don't want to start the form's focus in the editor, especially since it's below the fold and the browser scrolls to the focused html editor when it opens.
The only thing that worked for me was to extend Ext.form.HtmlEditor and then overwrite toggleSourceEdit, removing the focus command. Then adding a listener for toggling to the source editor when the component is initialized. This is for Ext 4.1 and up. For older versions, replace me.updateLayout() with me.doComponentLayout().
var Namespace = {
SourceEditor: Ext.define('Namespace.SourceEditor', {
extend: 'Ext.form.HtmlEditor',
alias: 'widget.sourceeditor',
initComponent: function() {
this.callParent(arguments);
},
toggleSourceEdit: function (sourceEditMode) {
var me = this,
iframe = me.iframeEl,
textarea = me.textareaEl,
hiddenCls = Ext.baseCSSPrefix + 'hidden',
btn = me.getToolbar().getComponent('sourceedit');
if (!Ext.isBoolean(sourceEditMode)) {
sourceEditMode = !me.sourceEditMode;
}
me.sourceEditMode = sourceEditMode;
if (btn.pressed !== sourceEditMode) {
btn.toggle(sourceEditMode);
}
if (sourceEditMode) {
me.disableItems(true);
me.syncValue();
iframe.addCls(hiddenCls);
textarea.removeCls(hiddenCls);
textarea.dom.removeAttribute('tabindex');
//textarea.focus();
me.inputEl = textarea;
} else {
if (me.initialized) {
me.disableItems(me.readOnly);
}
me.pushValue();
iframe.removeCls(hiddenCls);
textarea.addCls(hiddenCls);
textarea.dom.setAttribute('tabindex', -1);
me.deferFocus();
me.inputEl = iframe;
}
me.fireEvent('editmodechange', me, sourceEditMode);
me.updateLayout();
}
})
}
Then to use it:
Ext.create('Namespace.SourceEditor', {
/*regular options*/
listeners: {
initialize: function(thisEditor) {
thisEditor.toggleSourceEdit();
}
}
});
htmlEditor.toggleSourceEdit(true);
one time should be enough if you do this listening to the afterrender event of the editor.

Categories

Resources