I am trying to integrate a third party js application to my vue.js project. It is a molecular editor that will load on my page as a component.
Link to the js application - https://jsme-editor.github.io/dist/index.html
And this is what I want to achive -
<html><head>
<script type="text/javascript" language="javascript" src="jsme/jsme.nocache.js"></script>
<script>
//this function will be called after the JavaScriptApplet code has been loaded.
function jsmeOnLoad() {
jsmeApplet = new JSApplet.JSME("jsme_container", "380px", "340px");
jsmeApplet.setAfterStructureModifiedCallback(showEvent);
document.getElementById("log").value = "";
}
function showEvent(event) {
var log = document.getElementById("log");
log.value = event.action + " at: " + event.atom + " b: " + event.bond + " m: " + event.molecule + " smiles:" + event.src.smiles() + "\n" + log.value;
}
</script></head>
<body>
<div id="jsme_container"></div>
<textarea id="log" rows="5" cols="50"> </textarea>
</body>
</html>
What I have done so far is I have declared it as component as seen below -
<template>
<div class="hello">
<button #click="notify">Notify</button>
<div id="jsme-container" ref="jsmeContainer"></div>
</div>
</template>
<script>
export default {
name: 'newcomp',
data() {
return {
jsmeIsLoaded : false,
div_select : null
}
},
props: {
txt: String,
height: {
type: String,
required: true
},
width: {
type: String,
required: true
},
smiles: String,
options: String,
onChange: Function
},
mounted() {
let script = document.createElement('script')
script.src = '/home/rathore/Desktop/test_component/src/assets/JSME_2020-12-26/jsme/jsme.nocache.js'
document.head.appendChild(script)
this.$nextTick(
window.jsmeOnLoad = () => {this.jsmeIsLoaded = true;}
)
},
watch: {
jsmeIsLoaded(){
this.div_select = this.$refs.jsmeContainer.id
const div_loader = document.createElement('script')
const applet_txt = 'jsmeApplet = new JSApplet.JSME("'+this.div_select+'","300px","400px");'
//console.log(applet_txt,this.div_select)
const div_applet = document.createTextNode(applet_txt);
div_loader.appendChild(div_applet);
document.head.appendChild(div_loader);
}
},
methods: {
//Unused method
handleJsmeLoad(){
if (this.props.options){
this.jsmeApplet = new window.JSApplet.JSME(this.div_select, this.props.width, this.props.height, {options: this.props.options});
}
else {
this.jsmeApplet = new window.JSApplet.JSME(this.div_select, this.props.width, this.props.height);
}
this.jsmeApplet.setCallBack("AfterStructureModified", this.handleChange);
this.jsmeApplet.readGenericMolecularInput(this.props.smiles)
},
handleChange(jsmeEvent){
if (this.props.onChange) {
this.props.onChange(jsmeEvent.src.smiles())
}
},
notify(){
if (this.jsmeIsLoaded){
alert("JSME LOADED!!");
}
}
},
}
</script>
and called the component -
App.vue
template>
<div id="app">
<newcomp :height="'300px'" :width="'400px'" :onChange="logsmile" />
</div>
</template>
<script>
import newcomp from './components/NewComponenet.vue'
export default {
name: 'App',
components: {
newcomp
},
methods: {
logsmile(smiles){
console.log(smiles)
}
},
}
</script>
Here I have tried injecting <script> tag in the <head>. It is injected as I expected, but it doesn't work it give me error -
Uncaught ReferenceError: JSApplet is not defined. and it doesn't render the editor.
but actually I want it render using handleJSMELoad() method. Please suggest me the resolution.
Related
I have a GetAnimal.vue file that contains this:
<template>
<div>
<form v-on:submit.prevent="getAnimal()">
<textarea v-model = "animal"
name = "animal" type="animal" id = "animal"
placeholder="Enter your animal here">
</textarea>
<button class = "custom-button dark-button"
type="submit">Get animal</button>
</form>
<button class="custom-button" v-on:click = "goTo('/viewanimal')">
View animal
</button>
</div>
</template>
<script>
import axios from 'axios';
export default {
data: function () {
return {
name: 'defaultAnimal',
animal: {
name: 'Cat',
furColor: 'red',
population: '10000',
isExtinct: false,
isDomesticated: true
}
}
},
methods: {
goTo: function(path) {
// alert(path);
this.$router.push({ path });
},
getAnimal: function () {
alert("animals");
this.info = {
"fur-color": "yellow", "population": '51000', "isExtinct":
false, "isDomesticated": true
};
axios({
method: 'get',
url: 'http://localhost:8080/getanimal',
data: {
animal: this.animal
}
});
}
}
}
</script>
inside router.js it is mapped like this:
{
path: "/getanimal",
component: () => import('./views/GetAnimal.vue')
}
When I go to http://localhost:8080/getanimal in browser I see this:
(has some inherited styles from the App.vue)
When I click the Get Animal button it displays the animal alert and then I see this in console:
Why can't I send an axios request to the very page I'm currently at? Why do I get the 404 error and how should I fix it?
I'm new to Vue js - the following is not updating:
<div id="error" class="col s12 red center">
<span v-if="seen">
Error fetching readings: {{ msg }}
</span>
</div>
Vue:
var error = new Vue({
el: '#error',
data: {
msg: '',
seen: false
},
methods: {
show: function(message) {
this.msg = message;
this.seen = true;
},
hide: function() {
this.seen = false;
}
}
});
Post fetch:
fetch( ... )
.then(...)
.catch(err => {
error.show( err );
loader.hide();
});
error.show() displays the previously hidden div, but displays:
Error fetching readings: {}
Why?
i created a CodeSandbox sample based upon your code, you need to have computed property to have the Vue reactivity
Sample can be found, check code in HelloWorld.vue in components folder
https://codesandbox.io/s/x2klzr59wo
<template>
<div id="error" class="col s12 red center">
{{ seen }}
<hr />
<span v-if="computedSeen"> Error fetching readings: {{ msg }} </span>
<hr />
<button #click="show('effe');">SHOW</button>
<button #click="hide();">HIDE</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
msg: "",
seen: false
};
},
methods: {
show: function(message) {
this.msg = message;
this.seen = true;
},
hide: function() {
this.seen = false;
}
},
computed: {
computedSeen: function() {
// `this` points to the vm instance
return this.seen;
}
}
};
</script>
Oops, problem was err from the fetch is an object, and I should have used err.message.
In my code I had a console.log('Error: %s', err) which appears to format the err object into text. Which is what threw me :(
Sorry.
I am learning VueJS 2.0 and I am connecting to an API where I want the value of some data to change on input change. Here is what the output says using the dev tools:
canadianDollar:undefined
europeanEuro:undefined
europeanPound:undefined
usd:"1232"
Whenever I put 1232 in the USD input field it doesn't return anything and leaves those properties as undefined. Here is the code.
new Vue({
el: '#app',
data: {
usd: '',
canadianDollar: '',
europeanPound: '',
europeanEuro: ''
},
// Watch methods
watch: {
usd: function() {
this.convertCurrency()
}
},
// Logic Methods
methods: {
convertCurrency: _.debounce(function() {
var app = this;
if (app.usd.length !== 0) {
// Show that the things are loading in.
app.canadianDollar = 'Searching...'
app.europeanPound = 'Searching...'
app.europeanEuro = 'Searching...'
console.log(app.usd)
axios.get("http://api.fixer.io/latest?base=USD&" + app.usd)
.then(function(response) {
app.canadianDollar = response.data.CAD
app.europeanPound = response.data.GBP
app.europeanEuro = response.data.EUR
})
.catch(function(error){
app.canadianDollar = "ERROR"
app.europeanPound = "ERROR"
app.europeanEuro = "ERROR"
})
}
}, 500)
}
})
and the HTML:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Vue</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" name="" value="" v-model="usd">
<ul>
<li>Canadian Dollar: {{canadianDollar}}</li>
<li>European Pound: {{europeanPound}}</li>
<li>European Euro: {{europeanEuro}}</li>
</ul>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js" charset="utf-8"></script>
<script src="index.js" charset="utf-8"></script>
</body>
</html>
When I type in a number it does give me the "Searching" part but disappears and nothing shows up.
I would recommend changing
then(function(response) {
app.canadianDollar = response.data.CAD
app.europeanPound = response.data.GBP
app.europeanEuro = response.data.EUR
})
to
then(function(response) {
console.log(response);
})
that was you can see what is being returned.
Also, axios.get("http://api.fixer.io/latest?base=USD&" + app.usd) should probably have a name like vulue:axios.get("http://api.fixer.io/latest?base=USD&VALUE=" + app.usd), but you'll have to check their api to see what it is meant to be called.
...
response.data.rates.CAD;
you have
response.data.CAD;
...
app.canadianDollar = response.data.rates.CAD * app.usd;
I'm quite new in vue.js world and I'm lost with a certain case.
I did a little caching system using resource-loader, it preloads my images and videos and puts the data in a array. Everything works fine but now, I don't know how to create my video element and so play it.
I can't do a v-for because sometimes it's an image, and other time it's a video...
I don't know what to do !
Here is my App.vue
<template>
<div>
<div class="loader" v-show="progress < 100">
<h1>{{ progress }}%</h1>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
data () {
return {
progress: 0,
cache: {}
}
},
// Static manifest
manifest: [
'./static/img/intro/test.jpg',
'./static/video/intro/bg.mp4',
'./static/video/intro/bg.webm',
'./static/video/home/scroll.mp4',
'./static/video/home/scroll.webm',
'./static/sound/home/sanik.mp3',
],
ready: function() {
let Loader = require('resource-loader');
let loader = new Loader();
let manifest = this.$options.manifest;
manifest.forEach(function(file) {
loader.add(file);
});
let that = this;
loader.on('progress', function(event, resource){
that.progress = Math.round(event.progress);
console.log('progress', this.progress);
let sequence = [];
sequence = resource.url.split('/');
sequence = sequence[sequence.length - 2];
if(that.cache[sequence] === undefined) that.cache[sequence] = {};
that.cache[sequence][resource.name] =
{
url: resource.url,
data: resource.data
}
;
});
loader.on('complete', function(event, resources){
that.$broadcast('cache-loaded', 'that.cache');
that.$route.router.go('/intro');
});
loader.load();
}
}
And this is my intro.vue
<template>
<h1>INTRO</h1>
<a v-link="{ path: '/home' }">Continue to Home</a>
</template>
<script>
export default {
name: 'Intro',
components: {},
events: {
'cache-loaded' : function(cached){
console.log(this.$root.cache['intro']['./static/img/intro/test.jpg']);
// ok it shows my element and what's next ??
}
}
}
</script>
EDIT : I found the solution to not append the HTML raw element, instead I use the vue's native data binding.
App.vue
<template>
<div class="">
<div class="loader" v-show="progress < 100">
<h1>{{ progress }}%</h1>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
data () {
return {
progress: 0,
img_cache: [],
vid_cache: []
}
},
// Static manifest
manifest: [
'./static/intro/img/test.jpg',
'./static/intro/video/bg.mp4',
'./static/intro/video/bg.webm',
'./static/home/video/scroll.mp4',
'./static/home/video/scroll.webm'
],
ready: function() {
let Loader = require('resource-loader');
let loader = new Loader();
let that = this;
let manifest = that.$options.manifest;
manifest.forEach(function(file) {
loader.add(file, file);
});
loader.on('progress', function(event, resource){
that.progress = Math.round(event.progress);
console.log('progress', this.progress);
if(resource.url.match(/\.(jpe?g|png|gif|bmp)$/i)){
that.img_cache.push({
'name': resource.name,
'src': resource.url
});
}else {
that.vid_cache.push({
'name': resource.name,
'src': resource.url
})
}
});
loader.on('complete', function(event, resources){
console.log('COMPLETE');
that.$route.router.go('/intro');
});
loader.load();
}
}
</script>
Intro.vue
<template>
<h1>INTRO</h1>
<a v-link="{ path: '/home' }">Continue to Home</a>
<div class="" v-for="itm in $root.vid_cache">
<video v-bind:src="itm.src" autoplay loop>
</video>
</div>
</template>
<script>
import Loader from './Loader'
export default {
name: 'Intro',
components: {Loader},
ready: function(){
console.log('READY');
}
}
</script>
I checked in the network inspector, the ressources load only once.
I found the solution to not append the HTML raw element, instead I use the vue's native data binding.
App.vue
<template>
<div class="">
<div class="loader" v-show="progress < 100">
<h1>{{ progress }}%</h1>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
data () {
return {
progress: 0,
img_cache: [],
vid_cache: []
}
},
// Static manifest
manifest: [
'./static/intro/img/test.jpg',
'./static/intro/video/bg.mp4',
'./static/intro/video/bg.webm',
'./static/home/video/scroll.mp4',
'./static/home/video/scroll.webm'
],
ready: function() {
let Loader = require('resource-loader');
let loader = new Loader();
let that = this;
let manifest = that.$options.manifest;
manifest.forEach(function(file) {
loader.add(file, file);
});
loader.on('progress', function(event, resource){
that.progress = Math.round(event.progress);
console.log('progress', this.progress);
if(resource.url.match(/\.(jpe?g|png|gif|bmp)$/i)){
that.img_cache.push({
'name': resource.name,
'src': resource.url
});
}else {
that.vid_cache.push({
'name': resource.name,
'src': resource.url
})
}
});
loader.on('complete', function(event, resources){
console.log('COMPLETE');
that.$route.router.go('/intro');
});
loader.load();
}
}
</script>
Intro.vue
<template>
<h1>INTRO</h1>
<a v-link="{ path: '/home' }">Continue to Home</a>
<div class="" v-for="itm in $root.vid_cache">
<video v-bind:src="itm.src" autoplay loop>
</video>
</div>
</template>
<script>
import Loader from './Loader'
export default {
name: 'Intro',
components: {Loader},
ready: function(){
console.log('READY');
}
}
</script>
I checked in the network inspector, the ressources load only once.
I'm having my practice in VueJS 1.0 and I am learning about Components.
in this example, there is an input element and has to supply coupon or some kind of a code from an API. and I have to validate. I have my <coupon > component and has props of when-applied. The when-applied must call the parent function setCoupon but it won't.
I only got this error this.whenApplied is not a function.
<div id="demo" class="list-group">
<script id="coupon-template" type="x-template">
<input type="text" v-model="coupon" v-on:blur="whenCouponHasBeenEntered">
<div v-text="text"></div>
</script>
<coupon when-applied="setCoupon"></coupon>
</div>
Here is my app.js file
Vue.component('coupon', {
template: '#coupon-template',
props: ['whenApplied'],
data: function() {
return {
coupon: '',
invalid: false,
text: ''
}
},
methods: {
whenCouponHasBeenEntered: function() {
this.validate();
},
validate: function() {
if( this.coupon == 'FOOBAR') {
this.whenApplied(this.coupon);
return this.text = '20% OFF!!';
}
return this.text = 'that coupon doesn`t exists';
}
}
});
new Vue({
el: '#demo',
methods: {
setCoupon: function(coupon) {
alert('set coupon'+ coupon);
}
}
});
Someone pls help. Suggestions pretty much appreciated.
You should bind the property:
<coupon v-bind:when-applied="setCoupon"></coupon>
or you could use the shorthand syntax for v-bind:
<coupon :when-applied="setCoupon"></coupon>
Read more about the props here.