kindred 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +316 -0
- data/Rakefile +2 -0
- data/app/assets/javascripts/app.coffee +1 -0
- data/app/assets/javascripts/kindred.js +13 -0
- data/app/assets/javascripts/models/active_page.coffee +97 -0
- data/app/assets/javascripts/models/base.coffee +153 -0
- data/app/assets/javascripts/models/setup.coffee +97 -0
- data/app/assets/javascripts/utilities/binder.coffee +29 -0
- data/app/assets/javascripts/utilities/listener.coffee +74 -0
- data/app/assets/javascripts/utilities/logger.coffee +12 -0
- data/app/assets/javascripts/utilities/stack_trace.js +511 -0
- data/app/assets/javascripts/utilities/template.coffee +3 -0
- data/app/assets/javascripts/utilities/uuid.coffee +9 -0
- data/app/assets/javascripts/utilities/virtual_class.coffee +25 -0
- data/app/helpers/template_helper.rb +59 -0
- data/kindred.gemspec +26 -0
- data/lib/kindred/engine.rb +8 -0
- data/lib/kindred/version.rb +3 -0
- data/lib/kindred.rb +5 -0
- metadata +123 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
class App.Setup
|
2
|
+
constructor: (@opts) ->
|
3
|
+
@_set_name_properties()
|
4
|
+
@_set_self()
|
5
|
+
|
6
|
+
@opts ||= {}
|
7
|
+
|
8
|
+
@attributes = {}
|
9
|
+
template = @opts.template || App[@constructor.name].template
|
10
|
+
|
11
|
+
@_set_opts_to_attributes()
|
12
|
+
|
13
|
+
@_setup_route()
|
14
|
+
|
15
|
+
@uuid = @opts.uuid || @attributes.uuid || App.UUID.generate()
|
16
|
+
@id = @opts.id || @attributes.id
|
17
|
+
@target_uuid = @opts.target_uuid || @attributes.target_uuid
|
18
|
+
|
19
|
+
@attributes["uuid"] = @uuid
|
20
|
+
|
21
|
+
if template?
|
22
|
+
@template = template.replace(/\b(data-k-uuid)\.?[^\s|>]+/g, "data-k-uuid=" + @uuid)
|
23
|
+
@template = @template.replace(/\b(data-id)\.?[^\s|>]+/g, "data-id=" + @id)
|
24
|
+
@_build_attrs_template()
|
25
|
+
@_setup_interpolated_vars()
|
26
|
+
|
27
|
+
@set_class_name: (class_name) ->
|
28
|
+
@class_name = class_name
|
29
|
+
@dash_name = @_get_dash_name(class_name)
|
30
|
+
@snake_name = @_get_snake_name(class_name)
|
31
|
+
|
32
|
+
@_get_class_name: ->
|
33
|
+
@name
|
34
|
+
|
35
|
+
@_get_dash_name: (name) ->
|
36
|
+
dash_str = name.replace /([A-Z])/g, ($1) ->
|
37
|
+
"-" + $1.toLowerCase()
|
38
|
+
dash_str[1 .. dash_str.length - 1]
|
39
|
+
|
40
|
+
@_get_snake_name: (name) ->
|
41
|
+
under_str = name.replace /([A-Z])/g, ($1) ->
|
42
|
+
"_" + $1.toLowerCase()
|
43
|
+
under_str[1 .. under_str.length - 1]
|
44
|
+
|
45
|
+
_set_self: ->
|
46
|
+
@_self = @
|
47
|
+
|
48
|
+
_set_name_properties: =>
|
49
|
+
@class_name ||= App[@constructor.name].class_name
|
50
|
+
@dash_name = App[@constructor.name]._get_dash_name(@class_name)
|
51
|
+
@snake_name = App[@constructor.name].snake_name
|
52
|
+
|
53
|
+
_build_attrs_template: ->
|
54
|
+
$.each @attributes, (attr, val) =>
|
55
|
+
j_attr = $(@template).find("[data-k-uuid='" + @uuid + "'][data-attr='" + attr + "']")
|
56
|
+
clone = j_attr.clone()
|
57
|
+
|
58
|
+
replace_string = clone.wrap('<span/>').parent().html()
|
59
|
+
|
60
|
+
cloned_template = $(@template).clone()
|
61
|
+
updated_template = $("<div />").append($(@template).clone()).html()
|
62
|
+
|
63
|
+
if replace_string? && replace_string.length
|
64
|
+
replace_regex = new RegExp(replace_string)
|
65
|
+
|
66
|
+
new_attr_string = replace_string.replace(/\b(data-val)\.?[^\s]+/g, "data-val='" + val + "'")
|
67
|
+
|
68
|
+
@template = updated_template.replace(replace_regex, new_attr_string)
|
69
|
+
|
70
|
+
_setup_interpolated_vars: =>
|
71
|
+
template_match = new RegExp(/{{([^{}]+)}}/g)
|
72
|
+
|
73
|
+
new_template = @template.replace(template_match, (match, p1) =>
|
74
|
+
class_name = match.split(".")[0].substr(2)
|
75
|
+
attribute = match.split(".")[1].slice(0, - 2)
|
76
|
+
|
77
|
+
if class_name == @snake_name && (typeof @get(attribute) != 'undefined')
|
78
|
+
@get(attribute)
|
79
|
+
else
|
80
|
+
match
|
81
|
+
)
|
82
|
+
|
83
|
+
@template = new_template
|
84
|
+
|
85
|
+
_set_opts_to_attributes: ->
|
86
|
+
if @opts?
|
87
|
+
$.each @opts, (key, val) =>
|
88
|
+
@set key, val
|
89
|
+
|
90
|
+
_setup_route: =>
|
91
|
+
url_match = new RegExp(/{{([^{}]+)}}/g)
|
92
|
+
@route ||= App[@constructor.name].route
|
93
|
+
@route ||= "/" + @snake_name + "s"
|
94
|
+
@route = @route.replace(url_match, (match, p1) =>
|
95
|
+
attribute = match.slice(2, - 2)
|
96
|
+
@get(attribute)
|
97
|
+
)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
App.DataBinder = (object_id, model_name) ->
|
2
|
+
# Use a jQuery object as simple PubSub
|
3
|
+
pubSub = jQuery({})
|
4
|
+
|
5
|
+
# We expect a `data` element specifying the binding
|
6
|
+
# in the form: data-bind-<object_id>="<property_name>"
|
7
|
+
data_attr = "input"
|
8
|
+
message = object_id + ":change"
|
9
|
+
|
10
|
+
jQuery(document).on "keydown", "[data-input]", (evt) ->
|
11
|
+
$input = jQuery(this)
|
12
|
+
pubSub.trigger message, [
|
13
|
+
$input.data(data_attr)
|
14
|
+
$input.val()
|
15
|
+
]
|
16
|
+
|
17
|
+
# PubSub propagates changes to all bound elements, setting value of
|
18
|
+
# input tags or HTML content of other tags
|
19
|
+
pubSub.on message, (evt, prop_name, new_val, id) ->
|
20
|
+
# model_name = "purchase-order"
|
21
|
+
model_elem = jQuery("[data-model-" + model_name + "=" + object_id + "]")
|
22
|
+
|
23
|
+
attr_elm = model_elem.find("[data-attr=" + prop_name + "]")
|
24
|
+
input_elm = $("[data-input=" + prop_name + "]")
|
25
|
+
|
26
|
+
input_elm.val new_val
|
27
|
+
attr_elm.html new_val
|
28
|
+
|
29
|
+
pubSub
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class App.Listener
|
2
|
+
# Create a closure so that we can define intermediary
|
3
|
+
# method pointers that don't collide with other items
|
4
|
+
# in the global name space.
|
5
|
+
(->
|
6
|
+
# Store a reference to the original remove method.
|
7
|
+
originalOnMethod = jQuery.fn.on
|
8
|
+
|
9
|
+
# Define overriding method.
|
10
|
+
jQuery.fn.on = ->
|
11
|
+
if (jQuery.type( arguments[0] ) == "string")
|
12
|
+
listener_function = arguments[2]
|
13
|
+
element = arguments[1]
|
14
|
+
|
15
|
+
listener_namespace = arguments[0].split(".")
|
16
|
+
event_trigger = listener_namespace[0]
|
17
|
+
listener_name = listener_namespace[listener_namespace.length - 1]
|
18
|
+
namespaces = listener_namespace.slice(1, -1)
|
19
|
+
|
20
|
+
listener_info = {
|
21
|
+
trigger: event_trigger,
|
22
|
+
element: element,
|
23
|
+
name: listener_name,
|
24
|
+
funct: listener_function
|
25
|
+
}
|
26
|
+
|
27
|
+
App.Listener.createNestedObject(App, namespaces, listener_info)
|
28
|
+
|
29
|
+
# Execute the original method.
|
30
|
+
originalOnMethod.apply this, arguments
|
31
|
+
|
32
|
+
else
|
33
|
+
originalOnMethod.apply this, arguments
|
34
|
+
)()
|
35
|
+
|
36
|
+
@createNestedObject = (base, names, value) ->
|
37
|
+
|
38
|
+
# If a value is given, remove the last name and keep it for later:
|
39
|
+
lastName = (if arguments.length is 3 then names.pop() else false)
|
40
|
+
|
41
|
+
# Walk the hierarchy, creating new objects where needed.
|
42
|
+
# If the lastName was removed, then the last object is not set yet:
|
43
|
+
i = 0
|
44
|
+
|
45
|
+
while i < names.length
|
46
|
+
base = base[names[i]] = base[names[i]] or {}
|
47
|
+
i++
|
48
|
+
|
49
|
+
# If a value was given, set it to the last name:
|
50
|
+
if Array.isArray(base[lastName])
|
51
|
+
base[lastName].push(value)
|
52
|
+
else
|
53
|
+
base[lastName] = [value]
|
54
|
+
|
55
|
+
# Return the last object in the hierarchy:
|
56
|
+
base
|
57
|
+
|
58
|
+
@params: (obj) ->
|
59
|
+
# Stupid hack because jQuery converts data to camelCase
|
60
|
+
keys = Object.keys(obj)
|
61
|
+
n = keys.length
|
62
|
+
newobj = {}
|
63
|
+
while n--
|
64
|
+
key = keys[n]
|
65
|
+
|
66
|
+
if keys[n] == "kUuid"
|
67
|
+
snake_key = "uuid"
|
68
|
+
else
|
69
|
+
snake_key = key.replace(/([A-Z])/g, ($1) ->
|
70
|
+
"_" + $1.toLowerCase()
|
71
|
+
)
|
72
|
+
newobj[snake_key] = obj[key]
|
73
|
+
|
74
|
+
newobj
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class App.Logger
|
2
|
+
@add_error: (error_object) ->
|
3
|
+
@errors ||= []
|
4
|
+
@errors.push(error_object)
|
5
|
+
|
6
|
+
jQueryInit = $.fn.init
|
7
|
+
$.fn.init = (selector, context) ->
|
8
|
+
element = new jQueryInit(selector, context)
|
9
|
+
if selector and element.length is 0
|
10
|
+
App.Logger.add_error({selector_not_found: selector, stack_trace: printStackTrace()})
|
11
|
+
|
12
|
+
element
|