Skip to content

Instantly share code, notes, and snippets.

@jaredcwhite
Last active August 29, 2015 14:01
Show Gist options
  • Save jaredcwhite/5bb38aaedb29117b7aa3 to your computer and use it in GitHub Desktop.
Save jaredcwhite/5bb38aaedb29117b7aa3 to your computer and use it in GitHub Desktop.
First draft of an Opal-based KnockoutView wrapper for Knockout.js
# 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