How are objects passed between the plugin's javascript and the javascript of the view? I'm playing around with an example code from the "apache cordova 3 programming" book and i'm stuck...
In my plugin.xml I set the namespace to "mool"
<js-module src="plugin.js" name="moool">
<clobbers target="mool" />
</js-module>
plugin.js
var mol = {
calculateMOL : function() {
return 42;
}
};
var molll = {
calculateMOLLL : function() {
return 42222;
}
};
module.exports = molll;
module.exports = mol;
index.html
<!DOCTYPE html> <html>
<head>
<title>Meaning of Life Demo</title>
<meta http-equiv="Content-type" content="text/html;
charset=utf-8">
<meta name="viewport" content="user-scalable=no,
initial-scale=1, maximum-scale=1, minimum-scale=1,
width=device-width;" />
<script type="text/javascript" charset="utf-8"
src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function onBodyLoad() {
document.addEventListener("deviceready", onDeviceReady,
false);
};
function onDeviceReady() {
//alert("onDeviceReady");
};
function doMOL() {
var res = mool.calculateMOL();
alert('Meaning of Life = ' + res);
};
function doMOLL() {
var res = mool.calculateMOLLL();
alert('Meaning of Life = ' + res);
};
</script>
</head>
<body onload="onBodyLoad()">
<h1>MoL Demo</h1>
<p>This is a Cordova application that uses my custom
Meaning of Life plugin. </p>
<button onclick="doMOL();">Button1</button>
<button onclick="doMOLL();">Button2</button>
</body>
</html>
But when I run it only the second button works ... can somebody give me an explanation to this?
I already tried exporting both objects at once like:
module.exports = molll, mol;
but it still won't work...
This is a late comment but might benefit someone else. What worked for me was something similar to the following:
Try rewriting the plugin.js functions as follows:
module.exports.calculateMOL = function() { return 42; };
module.exports.calculateMOLLL = function() { return 42222; };
Drop the two export statements at the end (i.e. module.export = mol; and = molll;)
This should allow the two methods to be accessed as shown in the index.html file above.
It seems as if per definition it only assignes one object!
"The clobbers element specifies the JavaScript object assigned to the loaded JavaScript object."
I notice that in an app I had built, the module.exports property is taking an array, like below. That would allow you to put both your items in there(?) (I am just showing one object of the array in this snippet.)
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
{
"file": "plugins/org.apache.cordova.dialogs/www/notification.js",
"id": "org.apache.cordova.dialogs.notification",
"merges": [
"navigator.notification"
]
}, etc
Related
I defined Class in my javascript file...I imported that file into html page:
<script type="module" src="./js/controller.js"></script>
How can I now acces to classes inside of that js file?
I want to have something like this (in my html file):
<script>
let app = null;
document.addEventListener('DOMContentLoaded', function () {
//Init app on DOM load
app = new MyApp();
});
</script>
But it doesn't work (I get Uncaught ReferenceError: MyApp is not defined)...If I include this DOMContentLoaded listener into end of my controller.js file, It works. But I lost reference to app variable this way (which I don't want)... Is there way to have reference to something defined in modules?
Most important reason why I want to have that reference is ability to access to my app object from google chrome console...
Thanks!
You can access your class in js file from html in the following way-
My Home.html file:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<script type="module">
import { Car } from "./main.js";
let obj= null;
alert("Working! ");
obj = new Car("Mini", 2001);
obj.PrintDetails();
document.addEventListener('DOMContentLoaded', function () {
let obj2 = new Car("Merc", 2010);
obj2.PrintDetails();
});
</script>
</head>
<body>
<h1> Lets try something <br></h1>
</body>
</html>
My main.js file:
export class Car {
constructor(name, year) {
this.name = name;
this.year = year;
}
PrintDetails() {
console.log(" Name = "+ this.name);
console.log(" year = "+ this.year);
}
}
Whenever I try to load a page specific script with RequireJS, it will tell me that Builds is undefined.
<script type="text/javascript">
requirejs(["../../js/builds/builds"], function(Builds) {
console.log(Builds);
Builds.createFunc(window.location.href.substring(window.location.href.lastIndexOf("/") + 1))
});
</script>
js/builds/builds.js
"use strict";
define(["../../classes/builds/builds"], (Builds) => {
const Create = (classID) => {
return new Builds(classID);
}
return {
createFunc: Create
}
});
classes/builds/builds.js
"use strict";
define(() => {
return class Builds {
constructor(arg) {
this.arg = arg;
this.init();
}
init() {
console.log("Build loaded with class ID " + this.arg);
}
}
});
The only time I've got it to work is when I bind Create to window but that's not what I want to do. I want to be able to access the Builds parameter in my page script.
Folder structure:
resources (where the source files are, I'm compiling them with WebPack)
resources/js/app/modules/builds/builds.js compiles into public/js/builds/builds.js
public folder
Config:
requirejs.config({
baseUrl: "js/lib",
paths: {
app: "../app"
}
});
What am I missing here?
I got it working but I put all the files in one scripts folder except for the index.html. Four .js files: require.js, main.js, builds.js and class.js. But I did not use webpack. I was just testing if your code was correct (I have never used requireJS, before).
Index.html:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script data-main="./scripts/main" src="./scripts/require.js"></script>
</body>
</html>
main.js:
console.log(Builds);
Builds.createFunc(window.location.href.substring(window.location.href.lastIndexOf("/") + 1))
});
builds.js:
"use strict";
define(["./class"], (Builds) => {
const Create = (classID) => {
return new Builds(classID);
}
return {
createFunc: Create
}
});
class.js:
"use strict";
define(() => {
return class Builds {
constructor(arg) {
this.arg = arg;
this.init();
}
init() {
console.log("Build loaded with class ID " + this.arg);
}
}
});
I am using modern Javascript MyClass.js
export default class MyClass {
constructor(x) {
this.val=x? x: "Hello!"
console.log("MyClass:",x)
}
}
at my http://localhost/myfolder/mypage.htm, with the source below,
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel='shortcut icon' type='image/x-icon' href='./favicon.ico' />
<script type="module" src="./MyClass.js"></script>
<script>
'use strict';
document.addEventListener('DOMContentLoaded', function(){
alert(123)
let x = new MyClass(11);
}, false); //ONLOAD
</script>
</head>
<body> <p>Hello1!</p> </body>
</html>
Why console say "Uncaught ReferenceError: MyClass is not defined"?
PS: this question is a complement for this other about using ES6+ with browser+NodeJs.
NOTE: using UBUNTU ith Apache's Localhost... Some problem with myfolder a symbolic link to real folder? at /var/www/html I used ln -s /home/user/myRealFolder/site myfolder
you need to import the module before using it
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta charset="utf-8" />
<script type="module" src="./MyClass.js"></script>
<script type="module" id="m1">
// script module is an "island", not need onload.
'use strict';
import MyClass from './MyClass.js';
let x = new MyClass(11); // we can use here...
console.log("debug m1:", x) // working fine!
window.MyClassRef = MyClass; // "globalizing" class
window.xRef = x // "globalizing" instance
</script>
<script> // NON-module global script
document.addEventListener('DOMContentLoaded',function(){
// only works after all modules loaded:
console.log("debug:", window.xRef) // working fine!
let x = new window.MyClassRef(22); // using class also here,
console.log("debug:", x) // working fine!
}, false); //ONLOAD
</script>
</head>
<body> <p>Hello1!</p> </body>
</html>
There are two ways to use an imported class:
at module scope (script m1): you can use new MyClass(), and can "globalize" instances (e.g. xRef) or the costructor's class (MyClassRef).
at global scope: to work together other libraries or with main script, use a global reference, e.g. new window.MyClassRef().
All this solution relies upon "static import"...
Optional dynamic import
You can use also import with ordinary default <script> (no type="module"), and no "onload", using this solution, instead the last script:
<script>
'use strict';
import('./MyClass.js').then(({default: MyClass}) => {
alert(123) // async block
let x = new MyClass(11);
});
</script>
See dynamic import.
I created a custom element called "memory-box" like the below code.
Please pay attention to the function "logthis" which is in "memory-box-template".
memory-box.html
<template id="memory-box-template">
<input id="memory-box" type="form" />
<input type="button" id="testbutton" />
<script type="text/javascript">
function logthis(me){
console.log(me);
}
</script>
</template>
<script type="text/javascript">
(function() {
var thisDoc = document.currentScript.ownerDocument;
var storage = localStorage;
var proto = Object.create(HTMLElement.prototype, {
createdCallback: {
value: function() {
var temp = thisDoc.querySelector('#memory-box-template');
var con = document.importNode(temp.content, true);
this.createShadowRoot().appendChild(con);
var input = this.querySelector('::shadow #memory-box');
var data = storage.getItem(this.id);
input.value = data;
input.addEventListener('input', saveData.bind(input, this.id));
}
},
});
document.registerElement('memory-box', {
prototype: proto
});
function saveData(id, e) {
storage.setItem(id, this.value);
}
})();
</script>
Now, I uses the custom element "memory-box" like the below code.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="import" href="/html/memory-box.html">
</head>
<body>
<div><memory-box id="memory1"></memory-box></div>
<div><memory-box id="memory2"></memory-box></div>
<div><memory-box id="memory3"></memory-box></div>
<div><memory-box id="memory4"></memory-box></div>
</body>
<script type="text/javascript">
logthis(this);
</script>
</html>
As you can see, I putted a script in the index.html and called the function "logthis" just because I was curious. And no error occurred.
Why?
The function "logthis" is in each shadow doms. It's supposed not able to be called outside the shadow dom, I think.
As explained here, while the HTML within Shadow DOM is encapsulated, any JavaScript is NOT -- it is in the global scope, unless you utilize specific javascript techniques (namescaping, IIFE) to do so.
Hope this helps,
Jonathan Dodd
I have two scripts and I need to use script1 function in script2. Whats the best way to do it and Is there any simplification using prototype to access function in more scripts. I am using jquery.
script1
$(function(){
function process(){
// some code
}
})
script2
$(function(){
// I would like to use the process function here
}
Sample.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
</HEAD>
<script type="text/javascript" charset="utf-8" src="Script1.js" ></script>
<script type="text/javascript" charset="utf-8" src="Script2.js" ></script>
<script>
</script>
<BODY onload='calling();'>
</BODY>
</HTML>
Scrip1.jc
function call(){
alert("Hi i am called from script2");
}
Scrip2.js
function calling(){
call();
}
Hope this help you.
You can use javascript functions as variables. So just reread your question about the same stuff about variables - Unable to access variable
So just do so your function will be available from global scope.
Just move the function declaration outside the ready event handler, that will make it globally available.
Another idea: use objects:
var Ob = {
process: function(callback) {
callback();
}
}
script1
$(function(){
Ob.process(function(){
... // code
});
});
script 2 (do same)
$(function(){
Ob.process(function(){
... //another code
});
});
If you are using same process function (means same body content, make same thing in both script) then
var Ob = {
process: function() {
...//put code
}
}
script1
$(function(){
Ob.process();
});
script 2 (do same)
$(function(){
Ob.process();
});