I'm quite confused from Dojo's documentation. How can I use dojo.require() without actually using dojo.declare()? The reason I don't want to use dojo.declare() is that it exposes declared class as global variable.
Right now my code looks like this:
HTML file:
dojo.require('module.test');
Module/test.js:
dojo.provide('module.test');
function test() {
return 'found me';
}
I just can't get Dojo to return test() method anywhere. What's the correct pattern for using dojo.require() without declaring?
I think you are confusing dojo.provide/dojo.require with dojo.declare. They are completely different concepts.
Things that relate to modules
dojo.provide defines a module.
dojo.require requires that a module be defined before running any code later.
Things that relate to JavaScript classes
dojo.declare is something completely different. It declares a Dojo-style class.
You can have multiple classes in a module, or several modules making up one class. In general, modules !== classes and they are completely unrelated concepts.
dojo.provide defines the code module so that the loader will see it and creates an object from the global namespace by that name. From that point, you can anchor code directly to that global variable, e.g.
Module/test.js:
dojo.provide('module.test');
module.test.myFunc = function() {
return 'found me';
}
There are various patterns you can use, such as creating a closure and hiding "private" function implementations, exposing them via the global reference you created in dojo.provide:
dojo.provide('module.test');
function(){
// closure to keep top-level definitions out of the global scope
var myString = 'found me';
function privateHelper() {
return myString;
}
module.test.myFunc = function() {
return privateHelper();
}
}();
Note that the above simply puts methods directly on an object. Now, there's also dojo.declare, which is often used with dojo.provide to create an object with prototypes and mixins so that you can create instances with the 'new' keyword with some inheritance, even simulating multiple inheritance vai mixins. This sort of OO abstraction is often overused. It does approximate the patterns required by languages like Java, so some folks are used to declaring objects for everything.
Note that as of Dojo 1.5, dojo.declare returns an object and does not necessarily need to declare anything in the global scope.
Here's a pattern I sometimes use (this would be the contents of test.js):
(function() {
var thisModule = dojo.provide("module.test");
dojo.mixin(thisModule, {
test: function() {
return "found me";
}
});
})();
Now you can reference module.test.test() in your HTML page.
Related
On https://github.com/mozilla/rust-android-gradle/blob/8183f9e927336011c7c09d75efd4f5f411940db1/plugin/src/main/kotlin/com/nishtahir/CargoBuildTask.kt#L19 we have this kotlin code:
open class CargoBuildTask : DefaultTask() {
var toolchain: Toolchain? = null
#Suppress("unused")
#TaskAction
fun build() = with(project) {
extensions[CargoExtension::class].apply {
I'm very confused as from where does extensions come from, as well as project. They aren't local variables, they aren't in a scope or something. What are they?
Inheritance is the answer to project.
CargoBuildTask : DefaultTask()
Do you see how CargoBuildTask inherits properties of DefaultTask?
Thus project is a property from DefaultTask. However, extensions is a property from project which is of Type Project.
Read this documentation on DefaultTask and you will have more understanding.
Kotlin's with is the answer to extensions.
In short, with with you can invoke methods without explicitly stating its subject. (Read more here)
For example, these two code snippets mean the exact same thing:
with("string") {
substring(3) //invoke method without subject
}
"string".substring(3) //Same as above
Here is the method from org.gradle.api.Project
ExtensionContainer getExtensions();
Now, If you are wondering how Java's getExtensions() turned into Kotlin's extensions, read this. Basically states that traditional Getters and Setters in Java are interpreted as Properties in Kotlin.
PS: If you are unsure of what Inheritance is in OOP/Kotlin, read this.
The projectcomes from the DefaultTask() inherited in the current class. Inheritance is used here which is a very basic concept. Read more about Kotlin's inheritance here.
The extensions comes from project using with which is one of the scope functions.
Read more about with here.
.
For example. Suppose you've a Data class.
data class PersonModel(val name: String, var age: Int)
And you create a model of it as
val personModel = PersonModel("Adam", 30)
Now, if you pass it to a with function as a reciever, you can access 'personModel`'s properties directly in the with's scope as:
with(personModel) {
//name is the property of personModel
val nameWas = name
//Declared var and can be editable.
age = 31
}
with works with functions as well where you can pass a function as a reciever to it and it returns the returned value of the function.
These scope functions (let, run, with, apply, also) are extremely useful in production environment.
Vue.js official docs about plugins describes global methods and properties and Vue instance methods.
// 1. add global method or property
Vue.myGlobalMethod = function () {
// some logic ...
}
// 4. add an instance method
Vue.prototype.$myMethod = function (methodOptions) {
// some logic ...
}
But it isn't clear which of this approach is better fit to define global functionality? Can someone explain difference or indicate some resource about different use cases of this two approaches?
An instance method will have an instance (this) to be called from an operate on. A global-on-Vue function would have Vue itself as its this, which probably means you wouldn't want to use this in it.
So: instance method if it should operate on an instance, global function if it is some sort of utility that doesn't operate on a Vue instance.
I've just been trying to work out how to do this, and didn't find much on google, so I'll document what I found here.
I needed to define a JS class in an external library and also define some properties and method on it. I could do methods and the class, but was hitting a wall with properties.
So how is it done?
OK, let's imagine I've got an external JS class called 'Bob'.
My closure externs for this would be:
/** #constructor */ var Bob = function() {};
If I had a method (flyAway(speed)) I would add:
Bob.prototype.flyAway = function(speed) {};
And if I had a property (currentSpeed) I would add:
Bob.prototype.currentSpeed;
(the last one, I was doing (stupidly in hindsight) Bob.currentSpeed;)
I'm going to use the official example from the documentation that implements a DSL for some HTML creation.
Since Kotlin 1.1, the #DslMarker annotation allows us to restrict the scope of the functions in our classes, like the example does with the #HtmlTagMarker annotation. This gives us an error when trying to write incorrectly structured code like this:
html {
body {
body { // this in an error, as it's a function call on the outside Html element
}
}
}
However, this doesn't prevent nesting the outermost function, which is the entry point to the DSL. For example, with the example as it is now, this can be written down without problems:
html {
html {
}
}
Is there any way to make a DSL safer in this regard?
Probably this can somehow be done in a more elegant way, but I can suggest using the #Deprecated annotation with DeprecationLevel.ERROR on a function with a matching signature defined for the receiver type, for example:
#Deprecated("Cannot be used in a html block.", level = DeprecationLevel.ERROR)
fun HtmlReceiver.html(action: HtmlReceiver.() -> Unit): Nothing = error("...")
Or this can be a member function. By the way, the IDE completion behaves a bit differently based on whether it is an extension or a member.
This will make the calls like the inner one invalid:
html {
html { // Error: Cannot be used in a html block.
}
}
(demo of this code)
The top-level function can still be called inside a DSL block by its FQN e.g. com.example.html { }, so this trick only protects the users from calling the top level function by mistake.
Geb uses a static field called content to define the contents of a page or module. The value of the content field is a closure.
class GebishOrgHomePage extends Page {
static content = {
manualsMenu {
module MenuModule, $("#header-content ul li", 0)
}
links { $('.link-list li a') }
}
}
Intellij already has support for this content dsl, however it does not support the module and moduleList methods. This causes limited auto-complete support when working with modules.
To fix this I'd like to write a GroovyDSL script that adds the missing method definitions to the content closure and its nested closures. However, I've no idea how to add methods to a closure that is not passed to a method, since enclosingCall requires a concrete method name.
And the other thing is that those methods must have a generic return type like this:
<T extends Module> T module(Class<T> m) {
// return an instance of T
}
If you use the latest snapshot then module() calls will be understood by your IDE. This is down to moving module() to Navigator exactly for what you are after - autocompletion and strong typing.
Have a look at the current version of section 6.4 of the Book of Geb. The moduleList() will be gone in a future release and that section explains what to use instead. The module() method taking a map argument to initialise module properties will also go, you now initialise the module yourself and pass the instance to module() and there is an example of doing this in 6.4. Thanks to all that you will get autocompletion around module defintions and usage in IntelliJ.