Vue with Muuri - how to use? - javascript

I'm very new to Vue and my web dev skills are very limited, so sorry if this is a basic questions.
I just wanted to explore how I could create a draggable grid interface in the browser and found the Muuri package.
Now just following the example code in plain JavaScript/HTML the demo works as expected.
Now I try it with Vue, I get an error saying -
"TypeError: Cannot read property 'getRootNode' of null"
Here is my Vue component that should use Muuri.
<template>
<div class="grid">
<div class="item">
<div class="item-content">
<!-- Safe zone, enter your custom markup -->
This can be anything.
<!-- Safe zone ends -->
</div>
</div>
<div class="item">
<div class="item-content">
<!-- Safe zone, enter your custom markup -->
<div class="my-custom-content">
Yippee!
</div>
<!-- Safe zone ends -->
</div>
</div>
</div>
</template>
<script>
import 'web-animations-js';
import Muuri from 'muuri';
export default {
name: 'Grid',
created() {
var grid = new Muuri('.grid', {dragEnabled:true});
console.log(grid.toString());
}
}
</script>
<style scoped>
.grid {
position: relative;
}
.item {
display: block;
position: absolute;
width: 100px;
height: 100px;
margin: 5px;
z-index: 1;
background: #000;
color: #fff;
}
.item.muuri-item-dragging {
z-index: 3;
}
.item.muuri-item-releasing {
z-index: 2;
}
.item.muuri-item-hidden {
z-index: 0;
}
.item-content {
position: relative;
width: 100%;
height: 100%;
}
</style>
Any help or advice much appreciated!

Your problem is likely that the DOM hasn't loaded when the created event hook gets executed. You could try using mounted instead. I've included a snippet.
new Vue({
el: "#app",
mounted() {
var grid = new Muuri('.grid', {dragEnabled:true});
alert(grid.toString());
}
});
<script src="https://unpkg.com/web-animations-js#2.3.2/web-animations.min.js"></script>
<script src="https://unpkg.com/muuri#0.8.0/dist/muuri.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="grid">
<div class="item">
<div class="item-content">
<!-- Safe zone, enter your custom markup -->
This can be anything.
<!-- Safe zone ends -->
</div>
</div>
<div class="item">
<div class="item-content">
<!-- Safe zone, enter your custom markup -->
<div class="my-custom-content">
Yippee!
</div>
<!-- Safe zone ends -->
</div>
</div>
</div>

Related

How to provide template for gridstack boxes jQuery

I start to working with gridstack.js and i want to build layout dynamically from jquery.
But for this i want to provide some layout for boxes, like this:
So i do this, but problem is how i can build, this layout for boxes from script, because now i just add this to html.
var items = [
{ w: 3,content: 'my first widget' }, // will default to location (0,0) and 1x1
{ w: 3, content: 'another longer widget!' } // will be placed next at (1,0) and 2x1
];
var grid = GridStack.init();
grid.load(items);
.stantion-box {
display: flex;
}
.stantion-text {
justify-content: right;
}
.image-box {
width: 100%;
height: 100%;
}
.grid-stack {
background: lightgoldenrodyellow;
}
.grid-stack-item-content {
color: #2c3e50;
text-align: center;
background-color: #18bc9c;
}
<link href="https://cdn.jsdelivr.net/npm/gridstack#4.3.1/dist/gridstack.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/gridstack#4.3.1/dist/gridstack-h5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div><a class="btn btn-default" onClick="addNewWidget()" href="#">Add Widget</a></div>
<br />
<div class="container-fluid">
<div class="grid-stack">
<div class="text-center card text-white grid-stack-item newWidget ui-draggable" gs-x="0" gs-y="2" gs-w="3" gs-h="1">
<div class="card-body grid-stack-item-content ui-draggable-handle stantion-box">
<div class="stantion-icon">
<img src="https://www.ccifr.ru/wp-content/themes/ccifr/img/no-image.png" class="image-box"/>
</div>
<div class="stantion-text">
<div class="stantion-title">
<span>Drag me into the dashboard!</span>
</div>
<div class="stantion-descr">
<span>some descr</span>
</div>
</div>
</div>
</div>
</div>
</div>
So i want to build first box on the layout use js, to dynamically boxes build from here
var items = [
{ w: 3,content: 'my first widget' }, // will default to location (0,0) and 1x1
{ w: 3, content: 'another longer widget!' } // will be placed next at (1,0) and 2x1
];
How i can defind standart layout for boxes?

Why Collapsible header is not collapsing on dynamic scroll?

The collapsible header on my website doesn't seem to be working, and I'm wondering if it's the way I have the HTML setup? I'm trying to get the header to collapse from 125px down to 75px on scroll, but something I can't seem to get it to work. I've seen the JavaScript I'm using work on other websites, so I'm not entirely clear on what is going on with this site. Does anyone see any issues with my code? It seems like it should work fine to me. Much appreciation!
<header id="masthead" class="site-header">
<section class="header-top" id="header-top">
<div class="container content">
<div class="top-search">
<?php get_search_form( ); ?>
</div>
<div class="site-branding">
<img class="logo" src="<?php echo get_template_directory_uri( ) . '/logo.svg'?>">
</div>
<div class="header-right">
<p class="contribute">Contribute</p>
</div>
</div>
<div class="container">
<div class="top-search">
</div>
<div class="site-branding">
</div>
<div class="header-right">
</div>
</div>
<div class="container header-top-block" id="titles" style="display:block">
<h3 class="header-block-heading-line" id="soup">
<a href="<?php echo home_url(); ?>" target="">
Hello
</a>
</h3>
</div>
</div>
</div>
</div>
</section> <!-- end header main -->
<section class="header-nav">
<div class="container borders">
</div>
</section>
</header><!-- #masthead -->
.header-top {
width: 100%;
z-index: 2;
position: relative;
background: $white;
position:fixed;
min-height: 125px;
&.collapsed {
min-height: 50px;
}
.container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
window.onscroll = function() {myFunction()};
function myFunction() {
if (document.documentElement.scrollTop > 100) {
if(!document.getElementById("header-top").classList.contains('collapsed')){
document.documentElement.scrollTop += 100;
document.getElementById("header-top").className = "header-top collapsed";
}
} else {
if(document.getElementById("header-top").classList.contains('collapsed')){
document.getElementById("header-top").className = "header-top";
document.documentElement.scrollTop = 0;
}
}
}
Seems like you forgot to add } after &.collapsed declaration. Also If you are using plain CSS this code will not work (you are using SCSS syntax)

On sliding the details of particular position should store in local storage?

I am replicating this webpage https://www.modsy.com/project/furniture and I wrote the code On every slide there will be changing of image and phrase like that there are three phrases and images now I want to store the image and phrase in the local storage what the user has finalized My html code is:
window.addEventListener('load', function() {
var rangeslider = document.getElementById("sliderRange");
var output = document.getElementById("sliderOutput");
var images = document.getElementById("sliderImages");
rangeslider.addEventListener('input', function() {
for (var i = 0; i < output.children.length; i++) {
output.children[i].style.display = 'none';
images.children[i].style.display = 'none';
}
i = Number(this.value) - 1;
output.children[i].style.display = 'block';
images.children[i].style.display = 'block';
});
});
.rangeslider {
width: 50%;
margin: 0 auto;
position: absolute;
}
.myslider {
-webkit-appearance: none;
background: white;
width: 100%;
height: 20px;
opacity: 0.8;
margin-top: 180px;
}
.myslider::-webkit-slider-thumb {
-webkit-appearance: none;
cursor: pointer;
background: #000080;
width: 33%;
height: 20px;
}
.col-4 {
text-align: center;
}
.myslider:hover {
opacity: 1;
}
.image {
position: relative;
width: 400px;
margin: 0 auto;
}
.image>img {
position: absolute;
display: none;
}
.image>img.visible,
.image>img:first-child {
display: block;
}
#sliderOutput>div {
display: none;
}
#sliderOutput>div.visible,
#sliderOutput>div:first-child {
display: block;
}
#p1{
height: 10px;
}
<div class="image mt-3 mb-3" id="sliderImages">
<img src="../static/images/1.jpg" width="400" height="180">
<img src="../static/images/2.jpg" width="400" height="180">
<img src="../static/images/3.jpg" width="400" height="180">
</div><br>
<div class="rangeslider">
<input type="range" min="1" max="3" value="1" class="myslider" id="sliderRange">
<div id="sliderOutput">
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
</div>
My main requirement if the slider is in the first that phrase and image should be stored in local storage like that if it is in second that details should store.
Are you just trying to remember what the last slide the user viewed is? If so just use the localStorage.setItem() method and utilise the dataset feature to set a flag of each slide.
If I am right in my presumption your on load function would include the following line to default to the first slide:
localStorage.setItem('currentSlide', '1')
Your HTML slides would each have a dataset tag which could be something like:
data-index="1"
Then, in your change slide function you would get the dataset value and update the localStorage parameter:
function changeSlide() {
// ... Whatever code you have...
localStorage.setItem('currentSlide', this.dataset.index);
}
You could also use the sessionStorage instead, if you do not wish for the website to remember the user's last position after they leave the page: https://developer.mozilla.org/en-US/docs/Web/API/Storage
you can save your image using savImage function
html
<img src="../static/images/1.jpg" id="bannerImg" />
js
function saveImage() {
var bannerImage = document.getElementById('bannerImg');
var canvas = document.createElement("canvas");
canvas.width = bannerImage.width;
canvas.height = bannerImage.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(bannerImage, 0, 0);
var dataURL = canvas.toDataURL("image/png");
localStorage.setItem("imgData", dataURL.replace(/^data:image\/(png|jpg);base64,/,"");
}
after your process you can get your image from local storage
html
<img src="" id="tableBanner" />
js
function getImage() {
var dataImage = localStorage.getItem('imgData');
bannerImg = document.getElementById('tableBanner');
bannerImg.src = "data:image/png;base64," + dataImage;
}
you must run these two function for your problem

Can't manipulate Bootstrap 3 modal

I'm using MVC, have standard scaffolded index.cshtml page.
My goal is to display the details on a modal box. I'm able to display the modal box however whatever I do the modal is always and always displayed on the top left side of the screen. I'm trying to manipulate it using css but it fails whatever I do it does not work
so what I have done is:
Index.cshtml
<div id="myModal" class="modal TestModal">
<div class="modal-dialog TestModal">
<div class="modal-content TestModal">
<div id="myModalContent" class="TestModal"></div>
</div>
</div>
</div>
1- Created a partialView
<div class="modal-header">
<h4 class="modal-title">Validation Error</h4>
</div>
<div class="modal-body">
<p class="text-warning">
<small>Please make an entry before save</small>
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Ok</button>
</div>
2-Created the following method in my controller
public PartialViewResult DisplayModalFor(int id)
{
//var parent = _context.TOURNAMENTS_M.Include(x => x.TOURNAMENTS_D).First(x => x.TM_ROWID.Equals(Id));
return PartialView("_DetailsModal");
}
and finally I have the following function in my javascript file:
function PopUpModalFor(tmRowid) {
const id = tmRowid;
$.ajax({
url: "/TOURNAMENTS_M/DisplayModalFor",
type: "GET",
data: {
id: id
}
})
.done(function (result) {
$("#myModalContent").html(result);
$("#myModal").modal("show");
})
.fail(function () {
alert("I failed :'( ");
});
}
thoughts?
I have a weird problem here!
though I have included
<link rel="stylesheet" href="~/css/MyStyle.css" />
into my _Layout.cshtml, my CSS is not working completely.
for example I have
.YOLO {
background-color: green;
}
.Padded {
margin: 50px 100px 0 100px !important;
}
then I have modified my index.cshtml to look like this
<div class="Padded">
<p class="YOLO">THIS SHOULD BE GREEN</p>
<h2>Index</h2>
//More code..
however the p tag is not green what should I do?
I found this on here. But don't know whether it is working for you or not. Can you just try below? Anyway, by default, it should align into the middle.
#myModal{
text-align: center;
padding: 0!important;
}
.modal:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -4px;
}
.modal-dialog {
display: inline-block;
text-align: left;
vertical-align: middle;
}

Vue: How do I generate a new instance of a div with a buttonclick?

I need to create a function that generates a new instance of a specific div (.container in the template) when a button (#addDiv) is clicked. The button should be the only thing visible on the webpage before that. How do I do?
I know that it may be possible to do this with document.appendChild. Is there a better way?
I am using toggle-function that works great, I have included it in the code to give you the whole picture.
Vue
Vue.component('dynamicdDvs', {
template: `
<div>
<div class="headerDiv">
<button class="addDiv" type="button" v-on:click="createDiv">Create</button>
</div>
<div class="container">
<div class="createdDiv">
<h2>I am dynamic!</h2>
<button class="minimize" v-on:click="expand">Make me smal</button>
</div>
<div class="createdDivMinimized" v-if="!displayDiv">
<p>I am a smal version of the created div!</p>
<button class="maximize" v-on:click="expand">Expand me</button>
</div>
</div>
</div>
`,
data:function () {
return {
displayDiv: false
}
},
methods: {
expand: function () {
this.displayDiv = !this.displayDiv;
},
createDiv: function() {
//The function that creates a new div, with the same code as
//.createdDiv and .createDivMinimized may be placed here
}
}
});
CSS
.headerDiv {
height: 100px;
width: 400px;
background-color: blue;
color: white
}
.createdDiv {
height: 300px;
width: 400px;
background-color: black;
color: white
}
.createdDivMinimized {
height: 300px;
width: 400px;
background-color: red;
color: white
}
HTML
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="parent">
<dynamicDivs></dynamicDivs>
</div>
So what you can do is set a number in data for the number of <div> elements and use v-for with a range. For example
data () {
return {
displayDiv: [false],
divs: 1
}
}
And in your template
<template v-for="n in divs">
<div class="createdDiv">
<!-- snip -->
<button class="minimize" v-on:click="displayDiv[n-1] = !displayDiv[n-1]">Make me small</button>
</div>
<div class="createdDivMinimized" v-if="!displayDiv[n-1]">
<!-- snip -->
</div>
</template>
and in your methods...
createDiv () {
this.divs++
this.displayDiv.push(false)
}

Categories