Last active
August 29, 2015 14:01
-
-
Save jaredcwhite/5bb38aaedb29117b7aa3 to your computer and use it in GitHub Desktop.
First draft of an Opal-based KnockoutView wrapper for Knockout.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# KnockoutView provides a simple Opal-based Ruby wrapper around Knockout.js, a popular | |
# front-end data-binding and events library. It uses the Observable module from Vienna, | |
# another front-end library written in Ruby using Opal. | |
# | |
# Run one or more of these class methods in a KnockoutView subclass, aka | |
# | |
# ko_vars :somevar, :anothervar | |
# ko_methods :clickme | |
# | |
# and then wrappers will be created for the JS model that is passed to Knockout | |
# | |
# You can either do attr_accessor :somevar, :anothervar or write custom methods in your | |
# class | |
# | |
# You'll need to use ko_id on a top-level view to target an id of an element in your DOM | |
# | |
# ko_id :elementid | |
# | |
# Example HTML: | |
# <div id="elementid"> | |
# <span data-bind="text: somevar"> </span>, <span data-bind="html: anothervar"> </span> | |
# </div> | |
# | |
# Methods in your class are passed a jQuery event object, for example: | |
# | |
# <a href="#" data-bind="click: clickme">Click me!</a> | |
# | |
# def clickme(event) | |
# puts event.page_x | |
# end | |
# | |
# | |
# Subview docs forthcoming... | |
# | |
# TODO: Add support for arrays, turn this into a real Gem, add tests, etc. | |
class KnockoutView | |
include Vienna::Observable | |
def self.ko_setup | |
if @ko_defs.nil? | |
@ko_defs = {} | |
end | |
end | |
def self.ko_id(ko_id) | |
ko_setup | |
@ko_defs[:id] = ko_id | |
end | |
def self.ko_vars(*arr) | |
ko_setup | |
@ko_defs[:vars] = arr | |
end | |
def self.ko_subviews(*arr) | |
ko_setup | |
@ko_defs[:subviews] = arr | |
end | |
def self.ko_methods(*arr) | |
ko_setup | |
@ko_defs[:methods] = arr | |
end | |
def self.ko_defs | |
@ko_defs | |
end | |
def initialize | |
@ko_model = `{}` | |
self.class.ko_defs()[:vars].each do |var_label| | |
`self.ko_model[#{var_label}] = ko.observable(null)` | |
self.add_observer(var_label) do |new_val| | |
`self.ko_model[#{var_label}](#{new_val})` | |
end | |
end if self.class.ko_defs()[:vars] | |
self.class.ko_defs()[:subviews].each do |subview_label| | |
`self.ko_model[#{subview_label}] = self[#{subview_label}].ko_model` | |
end if self.class.ko_defs()[:subviews] | |
self.class.ko_defs()[:methods].each do |method_label| | |
`self.ko_model[method_label] = function(data, event) { self['$handle_ko_event'](method_label, event) }` | |
end if self.class.ko_defs()[:methods] | |
if self.class.ko_defs()[:id] | |
`ko.applyBindings(self.ko_model, document.getElementById(#{self.class.ko_defs()[:id]}))` | |
end | |
end | |
def ko_model | |
@ko_model | |
end | |
def handle_ko_event(method_label, event) | |
wrapped_event = Event.new(event) | |
self.send(method_label, wrapped_event) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment