Wrapping meteor.js handlebars templates in coffeescript classes - coffeescript

I'm totally digging on meteor, but I'm stuck trying to cut down on the global-ness of the examples and add a dash of OOP.
Currently, my code looks like this:
# View for Search Form
form = Template.SearchForm
form.events =
'submit #search_form' : query_submitted
'click #load_more' : -> Songs.get_next_page()
'focus #query' : clear_query_field
form.page = -> Songs.page
form.total_pages = -> Songs.total_pages
But, a la spine or backbone, what I'd really like to have is something like this:
class SearchForm extends Template.SearchForm
events:
'submit #search_form' : query_submitted
'click #load_more' : -> Songs.get_next_page()
'focus #query' : clear_query_field
page : -> Songs.page
total_pages : -> Songs.page
# etc etc
form = new SearchForm
What's the right way to wrap a handlebars template in meteor?
I've managed to wrap Meteor.Collection, but because handlebars names the object after the template, I'm not sure the right way to do it for the Template.
UPDATED
#greg pointed out that you can use _.extend to add the properties. That works, but what if I want to fold the event handler methods 'query_submitted' and 'clear_query_field' into the class? Something like this:
_.extend Template.SearchForm,
events :
'submit #search_form' : #query_submitted
'click #load_more' : -> Songs.get_next_page()
'focus #query' : #clear_query_field
page : -> Songs.page
total_pages : -> Songs.total_pages
clear_query_field : (event) ->
console.log 'focus'
query_submitted : (event) ->
event.preventDefault()
Songs.clear()
Songs.query = $('#query')[0].value
Songs.search()
Doesn't quite work. The event handlers aren't being called properly and I get errors in the console like:
Uncaught TypeError: Object [object Window] has no method
'query_submitted'
Similarly,
events :
'submit #search_form' : (e) -> #query_submitted(e)
Gives:
Uncaught TypeError: Cannot call method 'call' of undefined
So what's missing?

Meteor comes with underscore so you could:
_.extend Template.SearchForm,
events:
'submit #search_form' : query_submitted
'click #load_more' : -> Songs.get_next_page()
'focus #query' : clear_query_field
page: -> Songs.page
total_pages: -> Songs.page

Have you tried replacing # with Template.Searchform. in your event bindings?

Related

Elm How to make custom event decoder to get mouse x/y position at mouse-wheel-move

I am trying to get the x and y coordinates of the mouse during a mouse-wheel-move event in the Elm 0.19 programming language.
I attempt it with this package. See under "Advanced Usage":
https://package.elm-lang.org/packages/mpizenberg/elm-pointer-events/3.1.0/Html-Events-Extra-Wheel
The package itself did not describe a clear example so I looked for an example in a similar package.
See the example under "advanced usage" in this page:
https://package.elm-lang.org/packages/mpizenberg/elm-pointer-events/3.1.0/Html-Events-Extra-Mouse
This example is very similar to what I need, but I can also not get this to work. Get exactly the same problem.
Here is my code adapted from the example to fit with mouse wheel:
module WheelDecoder exposing(..)
import Html exposing (div, text)
import Html.Events.Extra.Wheel as Wheel
import Json.Decode as Decode
type alias WheelEventWithOffsetXY =
{ wheelEvent : Wheel.Event
, offsetXY : {x: Float, y: Float}
}
decodeWeelWithOffsetXY : Decode.Decoder WheelEventWithOffsetXY
decodeWeelWithOffsetXY =
Decode.map2 WheelEventWithOffsetXY
Wheel.eventDecoder
offsetXYDecoder
offsetXYDecoder : Decode.Decoder {x: Float, y: Float}
offsetXYDecoder =
Decode.map2 (\a b -> {x=a,y=b})
(Decode.field "offsetY" Decode.float)
(Decode.field "offsetY" Decode.float)
type Msg
= WheelOffsetXY {x: Float, y: Float}
view =
div
[ (onWheelOffsetXY (\wheelEvent -> WheelOffsetXY (wheelEvent.offsetXY))) ]
[ (text "mousewheel here") ]
onWheelOffsetXY : (WheelEventWithOffsetXY -> msg) -> Html.Attribute msg
onWheelOffsetXY tag =
let
options = { stopPropagation = True, preventDefault = True }
func = Decode.map tag decodeWeelWithOffsetXY
attribute = Wheel.onWithOptions options func
in
attribute
When I try to compile with "elm make" I get the following error:
-- TYPE MISMATCH -------------------------------------- src/Map/WheelDecoder.elm
The 2nd argument to `onWithOptions` is not what I expect:
39| attribute = Wheel.onWithOptions options func
^^^^
This `func` value is a:
Decode.Decoder msg
But `onWithOptions` needs the 2nd argument to be:
Wheel.Event -> msg
Hint: I always figure out the argument types from left to right. If an argument
is acceptable, I assume it is “correct” and move on. So the problem may actually
be in one of the previous arguments!
This error message makes sense as I can see there is a type mismatch, but I have no clue about how to solve it.
It seems like Wheel.eventDecoder was meant to work with Html.Events.on or Html.Events.onWithOptions rather than Wheel.onWithOptions. These were removed in 0.19 in favor of Html.Events.custom, however, which is slightly different. Replacing onWheelOffsetXY with this seems to work:
onWheelOffsetXY : (WheelEventWithOffsetXY -> msg) -> Html.Attribute msg
onWheelOffsetXY tag =
let
options message =
{ message = message
, stopPropagation = True
, preventDefault = True
}
decoder =
decodeWeelWithOffsetXY
|> Decode.map tag
|> Decode.map options
in
Html.Events.custom "wheel" decoder
PS: There's a typo in decodeWeelWithOffsetXY, btw. I've left the typo in place.
PPS: Also, you're looking at outdated documentation. Here's the documentation for the latest version.

Hubot Hear Variable

I was hoping to find away to get hubot to here a variable.
Ex
name = "Peter"
module.exports = (robot) ->
robot.hear /hello name/i, (msg) ->
msg.send "Peter?! No I am Hubot."
I have already tried "#{}" syntax like below, but got nowhere with it.
name = "Peter"
module.exports = (robot) ->
robot.hear /hello #{name}/i, (msg) ->
msg.send "Peter?! No I am Hubot."
Any help would be greatly appreciated.
Regards,
Austin
Since your regex is not a constant, you should use new Regex():
Using the constructor function provides runtime compilation of the regular expression. Use the constructor function when you know the regular expression pattern will be changing, or you don't know the pattern and are getting it from another source, such as user input.
Code
name = "Peter"
regx = new Regex("hello #{ name }", 'i')
module.exports = (robot) ->
robot.hear regx, (msg) ->
msg.send "Peter?! No I am Hubot."
Edit
With name as a parameter
module.exports = (robot, name) ->
regx = new Regex("hello #{ name }", 'i')
robot.hear regx, (msg) ->
msg.send "#{ name }?! No I am Hubot."
In case its useful, a hubot example using javascript rather than coffeescript that also takes the option chosen and places it in another variable:
const options = 'now|later|never';
const regexOptions = new RegExp(`starting (${options})`, 'i');
robot.respond(regexOptions, (msg) => {
// this will respond to:
// hubot starting now
// but not to:
// hubot starting notAnOption
const optionChosen = msg.match[1];
msg.send(`option chosen: ${optionChosen}`);
});
I use this technique when I have dynamic lists that I can add or remove names into, that I then want to use within responses - it does require a quick reload of hubot when adding a name to a list used in a command of course.

ractivejs component nesting

The documentation seems to indicate that it is possible to nest custom components within other custom components (http://docs.ractivejs.org/latest/components) :
<Foo on-Bar.foo="barfooed" on-Baz.*="baz-event" on-*.bippy="any-bippy">
<Bar /><Baz /><Baz />
</Foo>
However, the following code only displays the tooltip. The inner custom components al-tt-translation, and al-tt-input are not initialized. In fact, replacing those two components by a string do not lead to that string being passed in anyway to the tooltip custom component .
tooltip = new Ractive({
el: 'airlang-rdt-tt-container',
template: "" +
"<al-tooltip>"+
" <al-tt-translation display='{{display_translation}}' translation_lemma='{{translation_lemma}}' result_rows='{{result_rows}}'/> " +
" <al-tt-input/> "+
"</al-tooltip>",
append: true,
components : {
'al-tooltip': Component_Tooltip,
'al-tt-translation' : Component_TT_Translation,
'al-tt-input' : Component_TT_Input
},
data : {
display_translation : 'block',
translation_lemma : 'example'
}
});
Should I conclude that it is not possible to use the custom tags in the same way than regular HTML tags?
Note : From the documentation, I understand that there is something to do with {{>content}} or {{>yield}} but I can't seem to make it work. What is the right way to do this?
For your example, your <al-tooltip> template needs to have either a {{yield}} or {{>content}} somewhere in it to direct where the contained content should go.
Simple example of how it works:
var Outer = Ractive.extend({ template: '<div>{{yield}}</div>' });
var Inner = Ractive.extend({ template: '<span>hello world</span>' });
var ractive = new Ractive({
el: document.body,
template: '<outer><inner/><inner/></outer>'
components: {
outer: Outer,
inner: Inner
}
})
produces:
<div><span>hello world</span><span>hello world</span></div>
{{yield}} means that the content still runs in the context in which it originated, {{>content}} means import the content as a partial and run it. In your example it probably won't matter because you're using components and not raw templates.

Can not read property 'position' undefined, get Coordinates - CustomTile - Openseadragon

I am trying to get the coordinates with below code : If i am clicking on the canvas to grab the X and Y position : showing me console error : Uncaught TypeError: Cannot read property 'position' of undefined
screenshot : http://screencast.com/t/0LHAae5AicRz
viewer.addHandler('canvas-click', function (target, info) {
var viewportPoint = viewer.viewport.pointFromPixel(info.position);
var imagePoint = viewer.viewport.viewportToImageCoordinates(viewportPoint.x, viewportPoint.y);
console.log(imagePoint.x, imagePoint.y);
});
The info parameter is probably not what you think it is.
Do console.log(info) to see what the variable is in the console.
Perhaps the variable you are looking for is another parameter.
Also log all the arguments that get passed to the function. Write this inside the function:
console.log(arguments)
This way you will be able to inspect the variables and find the data you need.
This way, I can remove the canvas-click related - position of undefined error : Take a look at here for the answer : https://github.com/openseadragon/openseadragon/issues/318
For the //! OpenSeadragon 1.1.1, please updated the code as per below.
viewer.addHandler('canvas-click', function (event)
{
console.log(event);
var viewportPoint = viewer.viewport.pointFromPixel(event.position);
var imagePoint = viewer.viewport.viewportToImageCoordinates(viewportPoint.x, viewportPoint.y);
console.log(imagePoint.x, imagePoint.y);
});

Coffeescript undefined variable

I have the following coffeescript:
$("#complete").click ->
bootbox.dialog "Remember, if you complete the workorder you won't be able to add labor and materials.", [
label: "Complete"
class: "btn-success"
callback: ->
$("td").filter(':contains("ID:")').each ->
woid = $(this).nextAll().text()
$.update "/workorders/" + woid,
workorder:
wostatus_id: 232
,
label: "Cancel"
class: "btn-danger"
callback: ->
return 'false'
]
When it runs, I get this in the browser console:
Uncaught ReferenceError: woid is not defined
Thanks for the help!
Variables are scoped to the function where you first assign to them. To make woid available, initialize it to null outside your filter callback:
woid = null
$("td").filter(':contains("ID:")').each ->
woid = $(this).nextAll().text()
$.update "/workorders/" + woid,
workorder:
wostatus_id: 232
And as always, check your compiled JavaScript when debugging. The answer will usually be quite obvious.