OCaml dynamic function name - function

I have a list of tags:
let tags = ["div", "h1", "p"]
Can I generate a module which contains functions with those tags as names?
/* don't mind the syntax, it's Facebook's Reason (new interface to ocaml) */
let module DOM = {
let div props children => Js.Unsafe.fun_call
(Js.Unsafe.get dom (Js.string "div")) [|Js.Unsafe.inject props, Js.Unsafe.inject children|];
let h1 props children => Js.Unsafe.fun_call
(Js.Unsafe.get dom (Js.string "h1")) [|Js.Unsafe.inject props, Js.Unsafe.inject children|];
let p props children => Js.Unsafe.fun_call
(Js.Unsafe.get dom (Js.string "p")) [|Js.Unsafe.inject props, Js.Unsafe.inject children|];
}
The tag name should become a function in the module...
Is this possible?

Assuming what you want to do is to build a module with names from a string list while program execution,
Short answer: No, OCaml is a static typed language and you cannot build a new variable name while program execution.
Longer answer: you could use meta-programming: build a source code with names your want then compile it and dynamically link the compiled module. But this is not a regular way of using OCaml at all. In addition, looking at your environment, OCaml (or Reason) to output Js code, you likely need to have an OCaml (or Reason) compiler compiled to Js, which is hard and should be avoided.
Conclusion: No, you cannot.

Related

Automatically change the type of the elements in an array

I wrote a class for my project like this using typescript and react.
class myImage extends Image {
oriHeight: number;
}
After I uploaded two images I have an array named 'results' which is full of objects with type myImage.
[myImage, myImage]
When I click it in browser, I could see the data of oriHeight of each element.
Then I try to use results.map() method to traverse all the elements in that array.
results.map((result: myImage) => {
console.log(result);
var tmp = result.oriHeight;
console.log(tmp);
})
However, the output of result is no longer an object but an img tag (because the type of Image is a HTMLElement) which makes the data of result unreadable. So the output of every tmp is undefined.
I am confused about that. Why the myImage object will become an img tag when I want to traverse it? I hope someone could help me with that. Really appreciate it.
I bet your data is actually fine. When you console log an html element, the chrome console displays it as an html tag instead of the javascript object.
Update: It's generally a bad practice to add your own properties to DOM elements because they're harder to debug and you risk them being overwritten by future browser properties. Instead, you could create a javascript object that contains both the image and your custom property. Here's an example interface definition:
interface MyImage {
imageEl: HTMLImageElement;
oriHeight: number;
}

How would you embed atomic partials into a template data object

I'm using handlebars and assemble with yeoman and gulp.
I want to have some globalized partials that are able to be nested or injected into another partial by calling it within the context of a data object.
A simple example of that would be having a list of links that I could reference inside content throughout the site. The reason behind this, is the need for consistency. If for example, if I have a link within text on a page that I reference a 15 times throughout an entire website, but then realize I need to add a trade mark or modify the text, I want to update it once, not 15 times.
This is an example of what I want to do. Define global data inside a json file:
links.json
{
"apple": {
"linktext": "apple",
"target": "_blank",
"href": "http://www.apple.com"
},
"blog-article-foo-bar": {
"linktext": "foo bar",
"href": "http://www.foobar.com"
},
"dell": {
"linktext": "dell",
"target": "_parent",
"href": "http://www.dell.com"
}
}
Generate a partial from that content using a simple or complex template:
links.hbs
<a href="{{href}}" {{#if target}}target="{{target}}"{{/target}}>{{linktext}}</a>
And be able to embed that partial into another one by referencing it some how. This didn't work, but I've been reading about custom helpers, but can't figure out how I would intercept the partial and bind it into the other partial.
text.json
{
"text": "If you need a computer, go to {{> link link.apple}}."
}
text.hbs
<p>
{{text}}
</p>
compiled.html
<p>
If you need a computer, go to apple.
</p>
If you have suggestions or examples that might help me understand how to achieve this, I'd really appreciate the support. Thanks in advance.
There is some information about Handlebars helpers in their docs but not that much.
Since you're trying to use handlebars syntax in the value of a property on the context (e.g. text), handlebars won't render the value since it's already rendering the template. You can create your own helper that can render the value like this:
Handlebars.registerHelper('render', function(template, options) {
// first compile the template
const fn = Handlebars.compile(template);
// render the compiled template passing the current context (this) to
// ensure the same context is use
const str = fn(this);
// SafeString is used to allow HTML to be returned without escaping it
return new Handlebars.SafeString(str);
});
Then you would use the helper in your templates like this:
{{render text}}
Thanks for the example #doowb, your code did work but not for what I was trying to do. I really wanted something more complicated but I simplified my question not knowing it would be an issue. The code you provided worked (I think after a slight tweak) for a simple render of a template, but my templates use helpers such as #each and #if which caused the issue. Where the helpers were in my template, I ended up getting async placeholders. For example: <a $ASYNC$1$3...> I later learned this has to do with how partials are rendered. Understanding that lead me to subexpressions and the below solution.
Keeping my example above with some modifications, this is how I was able to merge partials.
First, I simplified the placeholder in text.json to basically a unique ID, instead of trying to render the partial there.
On the hbs template that I'm rendering to, such as a page or whatever, I included the insert helper with 3 arguments. The first two are subexpressions, each return a flattened partials as strings. The key here is that subexpressions process and return a result before finishing the current process with the helper. So two flattened templates are then sent to the helper along with the placeholder to search for.
The helper uses the third argument in a regex pattern. It searches the second argument (flattened parent template) for this pattern. When found, it replaces each instance of the pattern with the first argument (yes its a global fine replace).
So, the flattened child string gets inserted into parent each time placeholder is found.
First argument
(partial "link" link.apple)
Returns
'apple'
Second argument
(partial "text" text.text-example)
Returns
'<p class="text font--variant">If you need a computer, go to {{linkToApple}}.</p>'
Third argument
'linkToApple'
text.json
{
"text-example": {
"elm": "quote",
"classes": [
"text",
"font--variant"
],
"text": "If you need a computer, go to {{linkToApple}}."
}
}
text.hbs
<{{elm}} class="{{#eachIndex classes}}{{#isnt index 0}} {{/isnt}}{{item}}{{/eachIndex}}">{{text}}</{{elm}}>
compile.hbs
{{insert (partial "link" link.apple) (partial "text" text) 'linkToApple' }}
compile.html
<p class="text font--variant">If you need a computer, go to apple.</p>
gulpfile.js
app.helper('insert', function(child, parent, name) {
const merged = parent.replace(new RegExp('\{\{(?:\\s+)?(' + name + ')(?:\\s+)?\}\}', 'g'), child);
const html = new handlebars.SafeString(merged);
return html;
});
Hope this helps someone else. I know this can use improvements, I'll try to update it when I get back to cleaning up my gulp file.

Scala Play template vararg HtmlContent

I have a generic template in play 2.6, that I want to pass in a variable amount of HtmlContents. I've defined the template like this (including the implicit parameter I have in case that changes anything):
#(foo: String)(content: Html*)(implicit bar: Bar)
On the template side, this works fine-- I can dissect content with for and render it as I want. However, I haven't been able to figure out a clean way to invoke the variable arguments from the underlying template.
e.g, I have a view named "Baz":
#(something: String)(implicit bar: Bar)
In it, I try to invoke the template with multiple Html arguments. I've tried the following:
#template("fooString"){{123},{abc}}
and
#template("fooString")({123}, {abc})
and
#template("fooString"){{123}, {abc}})
And various other permutations, but inside of an enclosing bracket it seems to interpret everything literally as a single parameter in the HtmlContent vararg.
However, this ended up working as I intended, passing in multiple HtmlContents:
#template("fooString")(Html("123"), Html("abc"))
So that works, and I can use a triple-quoted interpolated string for a large Html block-- but it seems like there should be a cleaner way to do this, and the string interpolation is dangerous as it doesn't do html escaping.
Is there a way to do this using the { enclosed syntax? I'd like to understand more what is actually happening on an underlying level, and how play parses and generates HtmlContent in brackets.
So consider you have below template
// main.scala.html
#(title: String)(contents: Html*)
There are different ways you can call this template
Option #1
This is what you already posted in the question
#main("This is a title")(Html("abc"), Html("123"))
Options #2
#html1 = {
Hello
}
#html2 = {
<div>Tarun</div>
}
#main("This is a title")(html1, html2)
Option #3
#main("This is a title")(Html(<div>Tarun
</div>.toString), Html(<div>
Lalwani
</div>.toString))
Options #4
This is not exactly same option, but needs change in Template signature itself
#(title: String)(contents: List[String])
And then calling it like below
#main("This is a title")(List(
"""<div>
Tarun
</div>
""", """Hello"""))
Option #5
This requires code files and was already answered on another SO thread
Paul Draper's answer on Why doesn't this pass multiple HTML parameters to template

Backbone toJSON not rendering

when I use Backbone toJSON method of the model like this:
this.$el.html(this.model.toJSON());
It doesn't render model into view root element ( more than one attribute ).
But when I get one property from the model, like this;
this.$el.html(this.model.get("city"));
It is rendered properly.
Also, when I use template in first case (toJSON) - it is rendered fine.
this.$el.html(this.template(this.model.toJSON());
Why is that ?
Thanks
this.$el.html(this.model.toJSON());
You're using the html method of jQuery, which expects a string (or a DOM element, or a jQuery element), to display a JSON object.
this.$el.html(this.template(this.model.toJSON());
Here you're using a template method which, I assume, is taking a JSON object to evaluate a template that will return you a string. The htmlmethod receives this string and displays it.
this.$el.html(JSON.stringify(this.model.toJSON()));
This would display the result of this.model.toJSON() (but won't do the same as using your template method).
So, basically this.template will be (in most of the cases) a compiled version of the html template which you have for the view.
It will have placeholders in it, and will take parameters with the same key as placeholders in the template. For example (Handlebars templates),
<section id="{{id}}">
<header>{{header_text}}</header>
</section>
Considering the above code as a template, when you compile and store it in this.template, it returns a function, which takes a json object as a parameter, so now this.template is a function.
You can call it like below,
var html_text = this.template({
id : "main_content",
header_text : "Hi Welcome !!"
});
this.$el.html(html_text);
After the execution, el's contents will be
<section id="main_content">
<header>Hi Welcome !!</header>
</section>
So when you do this.$el.html(this.template(this.model.toJSON());, it actually generates the required json parameter for the this.template method for you, hence works fine.
And as Loamhoof said, in this.$el.html(this.model.get("city")); you use the html method which will set the html content of the el based on the property value of the model.

What do you call an object level equivalent of Mixin/Traits system, is there a Pattern name for it?

I previously asked about what Mixins were, and have begun to get the gist of what the pattern means. But it got me wondering if there is a common pattern name for doing something like Mixins at an Object level as opposed to the Class level.
Pseudo code (in some non existent language):
Class MyClass
{
function foo()
{
print("foo")
}
}
function bar()
{
print("bar")
}
object = MyClass.new()
object.xxxx(bar)
object.bar() #output: bar
I know stuff like this can be done in several languages, in one way or another, but I'm wondering what would be the "standard" name for the functionality xxxx represents, and what is the name for this pattern, if there is one.
Thanks!
Edit: Expanding on finnsson's answer I guess something like this might be another case of this would be:
object.xxxx(OtherClass)
object.otherfoo()
Would concatenate be appropriate?
Quote: "Concatenation: Under pure prototyping, which is also referred to as concatenative prototypes..." -wikipedia
This is common in prototype-based programming languages. I belive it's called "import" in ruby but it's some time since I last programmed ruby so I'm not sure.
In js/ruby you would write
object.bar = bar;
object.bar() // output: bar
and than it's no real pattern, since it's just an assignment (o.bar = bar) making perfect sense in a prototype-based language. I guess xxxx in your example could be called prototype or something similar (see http://en.wikipedia.org/wiki/Prototype-based_programming where a language calles this proto).