diff --git a/Readme.md b/Readme.md index 877767d..5078383 100644 --- a/Readme.md +++ b/Readme.md @@ -99,7 +99,7 @@ the ShareJS server. Any chanegs you make to the object will be properly applied In your application initialize function construct your models and views. ```coffee -Todo = AS.Namespace.create("Todo") +Todo = AS.Namespace.new("Todo") Todo.Application = AS.Application.extend initialize: -> @list = Todo.Models.List.open(@params.list_id) diff --git a/lib/alpha_simprini.coffee b/lib/alpha_simprini.coffee index 1cc2e84..3459d51 100644 --- a/lib/alpha_simprini.coffee +++ b/lib/alpha_simprini.coffee @@ -4,17 +4,17 @@ Taxi = require "taxi" require "./alpha_simprini/string" require "./alpha_simprini/core/logging" -AS = module.exports = Pathology.Namespace.create("AlphaSimprini") +AS = module.exports = Pathology.Namespace.new("AlphaSimprini") AS.part = (name) -> exports[name] = require: (libraries) -> AS.require name.toLowerCase(), libraries # Namespaces -AS.Models = Pathology.Namespace.create() -AS.Views = Pathology.Namespace.create() +AS.Models = Pathology.Namespace.new() +AS.Views = Pathology.Namespace.new() AS.Object = Pathology.Object -AS.Mixin = Pathology.Mixin +AS.Module = Pathology.Module AS.Namespace = Pathology.Namespace AS.Property = Taxi.Property diff --git a/lib/alpha_simprini/client.coffee b/lib/alpha_simprini/client.coffee index de9705b..4e10935 100644 --- a/lib/alpha_simprini/client.coffee +++ b/lib/alpha_simprini/client.coffee @@ -3,7 +3,7 @@ Client = AS.part("Client") _ = require "underscore" Client.require """ - dom view view_events view_model binding binding_group + dom view view_model binding_group binding view_events views/panel views/region diff --git a/lib/alpha_simprini/client/application.coffee b/lib/alpha_simprini/client/application.coffee index f5067b4..9dcfbfd 100644 --- a/lib/alpha_simprini/client/application.coffee +++ b/lib/alpha_simprini/client/application.coffee @@ -4,8 +4,10 @@ Taxi = require("taxi") jwerty = require("jwerty").jwerty domready = $ = require("jquery") -AS.Application = AS.Object.extend - initialize: () -> +AS.Application = AS.Object.extend ({def, include}) -> + include Taxi.Mixin + + def initialize: () -> @params = AS.params @god_given_key_handlers() domready => @@ -13,9 +15,9 @@ AS.Application = AS.Object.extend @el ?= $("body") - boot: -> + def boot: -> - god_given_key_handlers: -> + def god_given_key_handlers: -> handlers = '⎋': 'esc' '⌘+↩': 'accept' @@ -25,11 +27,10 @@ AS.Application = AS.Object.extend jwerty.key key, (event) => @trigger(trigger, event) - view: (constructor, options={}) -> + def view: (constructor, options={}) -> options.application = this - constructor.create options + constructor.new options - append: (view) -> + def append: (view) -> @el.append view.el -Taxi.Mixin.extends AS.Application diff --git a/lib/alpha_simprini/client/binding.coffee b/lib/alpha_simprini/client/binding.coffee index 123976b..b8c7446 100644 --- a/lib/alpha_simprini/client/binding.coffee +++ b/lib/alpha_simprini/client/binding.coffee @@ -1,64 +1,62 @@ AS = require("alpha_simprini") _ = require "underscore" -AS.Binding = AS.Object.extend - initialize: (@context, @model, @path, @options={}, @fn=undefined) -> - @path = [@path] unless _.isArray(@path) - @binding_path = AS.deepClone(@path) - @binding_path.splice @path.length - 1, 1, "change:#{_(@path).last()}" +AS.Binding = AS.Object.extend ({def}) -> + def initialize: (@context, @model, @field, @options={}, @fn=undefined) -> + @event = "change:#{field}" if _.isFunction(@options) [@fn, @options] = [@options, {}] - @container = @context.$ @context.current_node - @binding_group = @context.binding_group + @container = @context.$ @context.currentNode + @bindingGroup = @context.bindingGroup @content = @context.$ [] - if @will_group_bindings() - @context.group_bindings (binding_group) => - @binding_group = binding_group - @initialize() + if @willGroupBindings() + @context.groupBindings (bindingGroup) -> + @bindingGroup = bindingGroup + @setup() else - @initialize() + @setup() - will_group_bindings: -> - @constructor.will_group_bindings or _.isFunction(@fn) + def willGroupBindings: -> + @constructor.willGroupBindings or _.isFunction(@fn) - path_value: -> @model.readPath @path + def fieldValue: -> @field.get() - require_option: (name) -> + def require_option: (name) -> return unless @options[name] is undefined throw new AS.Binding.MissingOption("You must specify the #{name} option for #{@constructor.name} bindings.") - initialize: -> + def setup: -> class AS.Binding.MissingOption extends Error -class AS.Binding.Model - constructor: (@context, @model, @content=$([])) -> +AS.Binding.Model = AS.Object.extend ({def}) -> + def initialize: (@context, @model, @content=$([])) -> @styles = {} @attrs = {} - css: (properties) -> + def css: (properties) -> for property, options of properties do (property, options) => if _.isArray(options) @styles[property] = => @model.readPath(options) - painter = -> _.defer => + painter = => _.defer => value = @styles[property]() @content.css property, value - binding_path = AS.deepClone(options) - binding_path[options.length - 1] = "change:#{_(options).last()}" - @context.binds @model, binding_path, painter, this + bindingPath = AS.deepClone(options) + bindingPath[options.length - 1] = "change:#{_(options).last()}" + @context.binds @model, bindingPath, painter, this else @styles[property] = => options.fn(@model) - painter = -> _.defer => @content.css property, @styles[property]() + painter = => _.defer => @content.css property, @styles[property]() for field in options.field.split(" ") @context.binds @model, "change:#{field}", painter, this - attr: (attrs) -> + def attr: (attrs) -> for property, options of attrs do (property, options) => if _.isArray(options) @@ -71,12 +69,12 @@ class AS.Binding.Model else value - painter = -> _.defer => + painter = => _.defer => @content.attr property, @attrs[property]() - binding_path = AS.deepClone(options) - binding_path[options.length - 1] = "change:#{_(options).last()}" - @context.binds @model, binding_path, painter, this + bindingPath = AS.deepClone(options) + bindingPath[options.length - 1] = "change:#{_(options).last()}" + @context.binds @model, bindingPath, painter, this else @attrs[property] = => if options.fn @@ -84,13 +82,13 @@ class AS.Binding.Model else if @model[options.field]() then "yes" else "no" - painter = -> _.defer => + painter = => _.defer => @content.attr property, @attrs[property]() for field in options.field.split(" ") @context.binds @model, "change:#{field}", painter, this - paint: => + def paint: -> attrs = {} attrs[key] = fn() for key, fn of @attrs @@ -102,55 +100,56 @@ class AS.Binding.Model @content.width @width_fn() if @width_fn @content.height @height_fn() if @height_fn -class AS.Binding.Field extends AS.Binding +AS.Binding.Field = AS.Binding.extend ({def}) -> - initialize: -> - @content = @make_content() - @bind_content() - @set_content() + def initialize: -> + @_super.apply this, arguments + @content = @makeContent() + @bindContent() + @setContent() - bind_content: -> - @context.binds @model, @binding_path, @set_content, this + def bindContent: -> + @context.binds @field, "change", @setContent, this - set_content: => + def setContent: -> if @fn @container.empty() - @binding_group.unbind() - @context.within_binding_group @binding_group, => - @context.within_node @container, => + @bindingGroup.unbind() + @context.withinBindingGroup @bindingGroup, => + @context.withinNode @container, => @fn.call(@context) else - @content.text @path_value() + @content.text @fieldValue() - make_content: -> + def makeContent: -> if @fn @context.$ [] else @context.$ @context.span() -class AS.Binding.Input extends AS.Binding.Field - initialize: -> - super - @context.binds @model, @binding_path, @set_content, this +AS.Binding.Input = AS.Binding.Field.extend ({def}) -> + def initialize: -> + @_super.apply(this, arguments) + @context.binds @field, "change", @setContent, this - make_content: -> + def makeContent: -> @context.$ @context.input(@options) - bind_content: -> - @context.binds @content, "change", @set_field, this + def bindContent: -> + @context.binds @content, "change", _.bind(@setField, this) - set_content: () => - @content.val @path_value() + def setContent: () -> + @content.val @fieldValue() - set_field: () => - @model.write_path @path, @content.val() + def setField: () -> + @field.set @content.val() -class AS.Binding.Select extends AS.Binding.Input - constructor: -> - super +AS.Binding.Select = AS.Binding.Input.extend ({def}) -> + def initialize: -> + @_super.apply(this, arguments) @require_option "options" - make_content: -> + def makeContent: -> options = @options.options @select = @context.$ @context.select -> if _.isArray options @@ -160,35 +159,36 @@ class AS.Binding.Select extends AS.Binding.Input for key, value of options @option value: value, -> key - set_content: () => - path_value = @path_value() - path_value = path_value.id if path_value?.id - @content.val path_value + def setContent: () -> + fieldValue = @fieldValue() + fieldValue = fieldValue.id if fieldValue?.id + @content.val fieldValue - set_field: => + def setField: -> value = @select.val() if _.isArray value - @model.write_path @path, value[0] + @field.set value[0] else - @model.write_path @path, value + @field.set value + +AS.Binding.CheckBox = AS.Binding.Input.extend ({def}) -> + def initialize: (context, model, field, options={}, fn=undefined) -> + options.type = "checkbox" + @_super.apply(this, arguments) -class AS.Binding.CheckBox extends AS.Binding.Input - set_content: -> - @content.attr "checked", @path_value() + def setContent: -> + @content.attr "checked", @fieldValue() - bind_content: -> - @context.binds @content, "change", @set_field, this + def bindContent: -> + @context.binds @content, "change", _.bind(@setField, this) - set_field: => + def setField: -> if @content.is ":checked" - @model.write_path @path, true + @field.set true else - @model.write_path @path, false + @field.set false - initialize: -> - @options.type = "checkbox" - super class AS.Binding.EditLine extends AS.Binding rangy: require("rangy-core") @@ -205,13 +205,13 @@ class AS.Binding.EditLine extends AS.Binding doc.del commonStart, oldval.length - commonStart - commonEnd unless oldval.length == commonStart + commonEnd doc.insert commonStart, newval[commonStart ... newval.length - commonEnd] unless newval.length == commonStart + commonEnd - transform_insert_cursor = (text, position, cursor) -> + transformInsertCursor = (text, position, cursor) -> if position < cursor cursor + text.length else cursor - transform_delete_cursor = (text, position, cursor) -> + transformDeleteCursor = (text, position, cursor) -> if position < cursor cursor - Math.min(text.length, cursor - position) else @@ -219,27 +219,27 @@ class AS.Binding.EditLine extends AS.Binding initialize: -> @options.contentEditable = true - @content = @make_content() + @content = @makeContent() @elem = @content[0] - @elem.innerHTML = @path_value() - @previous_value = @path_value() + @elem.innerHTML = @fieldValue() + @previous_value = @fieldValue() @selection = start: 0, end: 0 - @context.binds @model, "share:insert:#{_(@path).last()}", @insert, this - @context.binds @model, "share:delete:#{_(@path).last()}", @delete, this + @context.binds @model, "share:insert:#{_(@field).last()}", @insert, this + @context.binds @model, "share:delete:#{_(@field).last()}", @delete, this - @context.binds @model, "change:#{_(@path).last()}", @updateUnlessFocused, this + @context.binds @model, "change:#{_(@field).last()}", @updateUnlessFocused, this for event in ['textInput', 'keydown', 'keyup', 'select', 'cut', 'paste', 'click', 'focus'] - @context.binds @content, event, @generate_operation, this + @context.binds @content, event, @generateOperation, this updateUnlessFocused: (event) -> # Defer this because we want text input to feel fluid! - _.defer => + _.defer -> return if @context.$(this.elem).closest(":focus")[0] - @elem.innerHTML = @path_value() + @elem.innerHTML = @fieldValue() - make_content: -> + makeContent: -> @context.$ @context.span(@options) replace_text: (new_text="") -> @@ -256,18 +256,18 @@ class AS.Binding.EditLine extends AS.Binding selection.setSingleRange(range) insert: (model, position, text) -> - @selection.start = transform_insert_cursor(text, position, @selection.start) - @selection.end = transform_insert_cursor(text, position, @selection.end) + @selection.start = transformInsertCursor(text, position, @selection.start) + @selection.end = transformInsertCursor(text, position, @selection.end) @replace_text @elem.innerHTML[...position] + text + @elem.innerHTML[position..] delete: (model, position, text) -> - @selection.start = transform_delete_cursor(text, position, @selection.start) - @selection.end = transform_delete_cursor(text, position, @selection.end) + @selection.start = transformDeleteCursor(text, position, @selection.start) + @selection.end = transformDeleteCursor(text, position, @selection.end) @replace_text @elem.innerHTML[...position] + @elem.innerHTML[position + text.length..] - generate_operation: => + generateOperation: -> selection = @rangy.getSelection() if selection.rangeCount range = @rangy.getSelection().getRangeAt(0) @@ -279,49 +279,49 @@ class AS.Binding.EditLine extends AS.Binding @previous_value = @elem.innerHTML # IE constantly replaces unix newlines with \r\n. ShareJS docs # should only have unix newlines. - @applyChange @model.share.at(@path), @model.share.at(@path).getText(), @elem.innerHTML.replace(/\r\n/g, '\n') - @model[@path] @model.share.at(@path).getText(), remote: true + @applyChange @model.share.at(@field), @model.share.at(@field).getText(), @elem.innerHTML.replace(/\r\n/g, '\n') + @model[@field] @model.share.at(@field).getText(), remote: true -class AS.Binding.HasMany extends AS.Binding - @will_group_bindings = true +AS.Binding.Many = AS.Binding.extend ({def}) -> + @willGroupBindings = true - initialize: -> - @collection = @path_value() + def initialize: -> + @_super.apply(this, arguments) + @collection = @field @contents = {} @bindings = {} - @sorting = @sorted_models() + @sorting = @sortedModels() - @initial_content() + @makeAll() - @context.binds @collection, "add", @insert_item, this - @context.binds @collection, "remove", @remove_item, this - @context.binds @collection, "change", @change_item, this + @context.binds @collection, "add", @insertItem, this + @context.binds @collection, "remove", @removeItem, this + @context.binds @collection, "change", @changeItem, this - initial_content: -> - @sorted_models().each @make_content + def makeAll: -> + @sortedModels().each _.bind @makeContent, this - sorted_models: -> - if sort_field = @options.order_by - @collection.models.sortBy((item) -> item[sort_field]()) + def sortedModels: -> + if sortField = @options.order_by + @collection.sortBy((item) -> item[sortField]()) else - @collection.models + @collection - skip_item: (item) -> + def skipItem: (item) -> return false unless @options.filter for key, value of @options.filter - expected_value = _([value]).flatten() - value_on_item = item[key]?() - - return true unless _(expected_value).include(value_on_item) + expectedValue = _([value]).flatten() + valueOnItem = item[key]?.get() + return true unless _(expectedValue).include(valueOnItem) false - insert_item: (item) => - return if @skip_item(item) - content = @context.dangling_content => @make_content(item) - index = @sorted_models().indexOf(item).value?() + def insertItem: (item) -> + return if @skipItem(item) + content = @context.danglingContent => @makeContent(item) + index = @sortedModels().indexOf(item).value?() index ?= 0 siblings = @container.children() if siblings.get(0) is undefined or siblings.get(index) is undefined @@ -329,9 +329,9 @@ class AS.Binding.HasMany extends AS.Binding else @context.$(siblings.get(index)).before(content) - @sorting = @sorted_models() + @sorting = @sortedModels() - remove_item: (item) => + def removeItem: (item) -> if @contents[item.cid] @contents[item.cid].remove() delete @contents[item.cid] @@ -339,35 +339,35 @@ class AS.Binding.HasMany extends AS.Binding @bindings[item.cid].unbind() delete @bindings[item.cid] - @sorting = @sorted_models() + @sorting = @sortedModels() - move_item: (item) -> + def moveItem: (item) -> content = @contents[item.cid] - current_index = content.index() - new_index = @sorted_models().indexOf(item).value() + currentIndex = content.index() + newIndex = @sortedModels().indexOf(item).value() siblings = content.parent().children() - if current_index < new_index - @context.$(siblings[new_index]).after(content) - else if new_index < current_index - @context.$(siblings[new_index]).before(content) + if currentIndex < newIndex + @context.$(siblings[newIndex]).after(content) + else if newIndex < currentIndex + @context.$(siblings[newIndex]).before(content) - change_item: (item) => - if @options.order_by and @sorting.indexOf(item).value() isnt @sorted_models().indexOf(item).value() - @move_item(item) - @sorting = @sorted_models() + def changeItem: (item) -> + if @options.order_by and @sorting.indexOf(item).value() isnt @sortedModels().indexOf(item).value() + @moveItem(item) + @sorting = @sortedModels() - if @skip_item(item) - @remove_item(item) + if @skipItem(item) + @removeItem(item) else if @contents[item.cid] is undefined - @insert_item(item) + @insertItem(item) - make_content: (item) => - return if @skip_item(item) + def makeContent: (item) -> + return if @skipItem(item) content = @context.$ [] - @context.within_binding_group @binding_group, => - @context.group_bindings => - @bindings[item.cid] = @context.binding_group + @context.withinBindingGroup @bindingGroup, => + @context.groupBindings => + @bindings[item.cid] = @context.bindingGroup binding = new AS.Binding.Model(@context, item, content) made = @fn.call(@context, AS.ViewModel.build(@context, item), binding) if made?.jquery @@ -375,55 +375,56 @@ class AS.Binding.HasMany extends AS.Binding else content.push made - binding.paint() + # FIXME: paint! + # binding.paint() @contents[item.cid] = content return content -class AS.Binding.EmbedsMany extends AS.Binding.HasMany -class AS.Binding.EmbedsOne extends AS.Binding.Field - @will_group_bindings = true - -class AS.Binding.HasOne extends AS.Binding.Field - @will_group_bindings = true - -class AS.Binding.Collection extends AS.Binding.HasMany - path_value: -> @model - -# use case: RadioSelectionModel -# ala-BAM-a -# @element_focus.binding "selected", (element) -> -# new Author.Views.ElementBoxAS.Binding(this, @div class:"Focus", element) -# -# @element_selection.binding "selected", (element) -> -# new Author.Views.ElementBoxBinding(this, @div class:"Selection", element) - -class AS.Binding.BelongsTo extends AS.Binding - @will_group_bindings = true - - initialize: -> - @make_content() - @context.within_binding_group @binding_group, => - @context.binds @model, @binding_path, @changed, this - - changed: => - @content.remove() - @binding_group.unbind() - @initialize() - - make_content: -> - item = @path_value() - if item - @context.within_binding_group @binding_group, => - @context.within_node @container, => - @content = @context.$ [] - binding = new AS.Binding.Model(@context, item, @content) - made = @fn.call(@context, AS.ViewModel.build(@context, item), binding) - if made?.jquery - @content.push made[0] - else - @content.push made - binding.paint() - @content - else - @content = @context.$ [] +# class AS.Binding.EmbedsMany extends AS.Binding.HasMany +# class AS.Binding.EmbedsOne extends AS.Binding.Field +# @willGroupBindings = true + +# class AS.Binding.HasOne extends AS.Binding.Field +# @willGroupBindings = true + +# class AS.Binding.Collection extends AS.Binding.HasMany +# fieldValue: -> @model + +# # use case: RadioSelectionModel +# # ala-BAM-a +# # @element_focus.binding "selected", (element) -> +# # new Author.Views.ElementBoxAS.Binding(this, @div class:"Focus", element) +# # +# # @element_selection.binding "selected", (element) -> +# # new Author.Views.ElementBoxBinding(this, @div class:"Selection", element) + +# class AS.Binding.BelongsTo extends AS.Binding +# @willGroupBindings = true + +# initialize: -> +# @makeContent() +# @context.withinBindingGroup @bindingGroup, -> +# @context.binds @model, @event, @changed, this + +# changed: -> +# @content.remove() +# @bindingGroup.unbind() +# @initialize() + +# makeContent: -> +# item = @fieldValue() +# if item +# @context.withinBindingGroup @bindingGroup, -> +# @context.withinNode @container, -> +# @content = @context.$ [] +# binding = new AS.Binding.Model(@context, item, @content) +# made = @fn.call(@context, AS.ViewModel.build(@context, item), binding) +# if made?.jquery +# @content.push made[0] +# else +# @content.push made +# binding.paint() +# @content +# else +# @content = @context.$ [] diff --git a/lib/alpha_simprini/client/binding_group.coffee b/lib/alpha_simprini/client/binding_group.coffee index 0518a8b..82fb06a 100644 --- a/lib/alpha_simprini/client/binding_group.coffee +++ b/lib/alpha_simprini/client/binding_group.coffee @@ -1,33 +1,33 @@ AS = require("alpha_simprini") _ = require "underscore" -class AS.BindingGroup +AS.BindingGroup = AS.Object.extend ({def}) -> - constructor: -> - @namespace = _.uniqueId(".bg") - @initialize() - - initialize: -> + def initialize: -> + @namespace = _.uniqueId("bg") @children = [] - @bound_objects = [] + @boundObjects = [] # Unbind all bindings, and then unbind all children binding groups - unbind: -> - object.unbind(@namespace) for object in @bound_objects + def unbind: -> + object.unbind(@namespace) for object in @boundObjects child.unbind() for child in @children @initialize() - binds: (object, event, handler, context) -> - @bound_objects.push object + def binds: (object, event, handler, context) -> + @boundObjects.push object if object.jquery - object.bind "#{event}#{@namespace}", handler + object.bind "#{event}.#{@namespace}", handler else - event = [event] unless _.isArray(event) - object.bind {path: event, namespace: @namespace}, handler, context + object.bind + event: event + namespace: @namespace + handler: handler + context: context - add_child: -> - child = new AS.BindingGroup + def addChild: -> + child = AS.BindingGroup.new() @children.push child return child - remove_child: (binding_group) -> @children = _(@children).without(binding_group) + def remove_child: (bindingGroup) -> @children = _(@children).without(bindingGroup) diff --git a/lib/alpha_simprini/client/dom.coffee b/lib/alpha_simprini/client/dom.coffee index 75928c7..727280a 100644 --- a/lib/alpha_simprini/client/dom.coffee +++ b/lib/alpha_simprini/client/dom.coffee @@ -27,37 +27,38 @@ SVG_ELEMENTS = _(' glyph missing-glyph hkern vkern font-face-src font-face-uri font-face-format font-face-name definition-src foreignObject '.split(" ")).chain().compact() -AS.DOM = AS.Object.extend - constructor: (args) -> - # body... +AS.DOM = AS.Object.extend ({def}) -> - $: $ + # def constructor: (args) -> + # # body... - text: (text_content) -> + def $: $ + + def text: (textContent) -> # createTextNode creates a text node, no DOM injection here # TODO: DOUBLE EXPRESS VERIFY THIS ASSUMPTION AND PASTE # LINKS TO SUPPORTING EVIDENCE IN THE CODE. - @current_node.appendChild document.createTextNode(text_content) + @currentNode.appendChild document.createTextNode(textContent) - raw: (html) -> + def raw: (html) -> @$(@span()).html(html) - tag: (name, attrs, content) -> + def tag: (name, attrs, content) -> node = document.createElement(name) return @_tag node, attrs, content - svg_tag: (name, attrs, content) -> + def svgTag: (name, attrs, content) -> node = document.createElementNS(SVG.ns, name) return @_tag node, attrs, content - _tag: (node, attrs, content) -> - @current_node ?= document.createDocumentFragment() + def _tag: (node, attrs, content) -> + @currentNode ?= document.createDocumentFragment() if _.isFunction(attrs) content = attrs attrs = undefined if _.isString(attrs) - text_content = attrs + textContent = attrs attrs = undefined # TODO: use jQuery for better compatibility / less performance @@ -67,37 +68,37 @@ AS.DOM = AS.Object.extend else node.setAttribute(key, value) - @current_node.appendChild node + @currentNode.appendChild node - if text_content - @$(node).text text_content + if textContent + @$(node).text textContent else if content - @within_node node, -> + @withinNode node, -> last = content.call(this) if _.isString(last) @text(last) return node - within_node: (node, fn) -> + def withinNode: (node, fn) -> node = node[0] if node?.jquery - prior_node = @current_node - @current_node = node + priorNode = @currentNode + @currentNode = node content = fn.call(this) - @current_node = prior_node + @currentNode = priorNode content - dangling_content: (fn) -> @within_node(null, fn) + def danglingContent: (fn) -> @withinNode(null, fn) DOM_ELEMENTS.each (element) -> AS.DOM::[element] = -> @tag.apply this, _(arguments).unshift(element) SVG_ELEMENTS.each (element) -> # Be wary of conflicts with regular HTML elements - html_svg_conflict = ~DOM_ELEMENTS.value().indexOf(element) - method_conflict = AS.DOM::[element]? - if html_svg_conflict or method_conflict + htmlSvgConflict = ~DOM_ELEMENTS.value().indexOf(element) + methodConflict = AS.DOM::[element]? + if htmlSvgConflict or methodConflict element = "svg_#{element}" - AS.DOM::[element] = -> @svg_tag.apply this, _(arguments).unshift(element) + AS.DOM::[element] = -> @svgTag.apply this, _(arguments).unshift(element) diff --git a/lib/alpha_simprini/client/models/targets.coffee b/lib/alpha_simprini/client/models/targets.coffee index e710eb3..1968d98 100644 --- a/lib/alpha_simprini/client/models/targets.coffee +++ b/lib/alpha_simprini/client/models/targets.coffee @@ -1,5 +1,6 @@ AS = require("alpha_simprini") $ = require("jquery") +Taxi = require "taxi" TOP = name:"TOP" MIDDLE = name:"MIDDLE" @@ -7,48 +8,49 @@ BOTTOM = name:"BOTTOM" LEFT = name: "LEFT" RIGHT = name: "RIGHT" -AS.Models.Targets = AS.Object.extend - TOP: TOP - MIDDLE: MIDDLE - BOTTOM: BOTTOM - LEFT: LEFT - RIGHT: RIGHT +AS.Models.Targets = AS.Object.extend ({def, defs, include}) -> + include Taxi.Mixin + def TOP: TOP + def MIDDLE: MIDDLE + def BOTTOM: BOTTOM + def LEFT: LEFT + def RIGHT: RIGHT - constructor: -> + def initialize: -> @gather() - gather: -> + def gather: -> @targets = $(@selector).map (i, el) -> return el: $(el), rect: el.getBoundingClientRect() - validate: () -> true + def validate: () -> true # validate: (data) -> true # return @element().can_be_parent_for(data.source) - dropstart: () -> + def dropstart: () -> return unless @current_hit?.rect @trigger("dropstart", @current_hit) - dropend: () -> + def dropend: () -> @trigger("dropend") - drop: (event) -> + def drop: (event) -> - dragend: (event) -> + def dragend: (event) -> return unless @current_hit?.rect @drop(event) @trigger("drop", @current_hit) - transition_hit: (hit) -> + def transition_hit: (hit) -> return @dropend() if hit is null - @current_hit ?= new AS.Models.Targets.Hit + @current_hit ?= AS.Models.Targets.Hit.new() # Nothin' changed, eh? return if @current_hit.equals(hit) or hit.rect is undefined @dropend() @current_hit = hit @dropstart() - drag: (event) -> + def drag: (event) -> throw "Drag unimplimented in base class!" AS.Models.Targets.TOP = TOP @@ -57,12 +59,12 @@ AS.Models.Targets.BOTTOM = BOTTOM AS.Models.Targets.LEFT = LEFT AS.Models.Targets.RIGHT = RIGHT -class AS.Models.Targets.Edge extends AS.Models.Targets - constructor: (options={}) -> - super +AS.Models.Targets.Edge = AS.Models.Targets.extend ({def}) -> + def initialize: (options={}) -> + @_super() @edge = options.edge or 30 - horizontal_target: (event) -> + def horizontal_target: (event) -> {clientX, clientY} = event["jquery/event"].originalEvent for target in @targets rect = target.rect @@ -77,10 +79,10 @@ class AS.Models.Targets.Edge extends AS.Models.Targets break return null unless edge - return new AS.Models.Targets.Hit target.rect, target.el, edge + return AS.Models.Targets.Hit.new target.rect, target.el, edge - vertical_target: (event) -> + def vertical_target: (event) -> {clientX, clientY} = event["jquery/event"].originalEvent for target in @targets @@ -96,15 +98,15 @@ class AS.Models.Targets.Edge extends AS.Models.Targets break return null unless edge - return new AS.Models.Targets.Hit target.rect, target.el, edge + return AS.Models.Targets.Hit.new target.rect, target.el, edge -class AS.Models.Targets.Thirds extends AS.Models.Targets +AS.Models.Targets.Thirds = AS.Models.Targets.extend ({def}) -> - within_vertically: (y, rect) -> + def within_vertically: (y, rect) -> rect.top <= y <= rect.bottom - which_third: (y, rect) -> + def which_third: (y, rect) -> # pre-supposes within_vertically is true one_third = rect.height / 3 offset = y - rect.top @@ -116,24 +118,24 @@ class AS.Models.Targets.Thirds extends AS.Models.Targets else @BOTTOM - target: (event) -> + def target: (event) -> {clientY} = event["jquery/event"].originalEvent for target in @targets if @within_vertically(clientY, target.rect) - hit = new AS.Models.Targets.Hit(target.rect, target.el, @which_third(clientY, target.rect), event) + hit = AS.Models.Targets.Hit.new(target.rect, target.el, @which_third(clientY, target.rect), event) return hit if @validate(hit) return null - drag: (event) -> + def drag: (event) -> @transition_hit @target(event) -class AS.Models.Targets.Hit - TOP: TOP - MIDDLE: MIDDLE - BOTTOM: BOTTOM - LEFT: LEFT - RIGHT: RIGHT - constructor: (@rect=null, @el=null, @section=null, @event) -> - equals: (other=new AS.Models.Targets.Hit) -> +AS.Models.Targets.Hit = AS.Object.extend ({def}) -> + def TOP: TOP + def MIDDLE: MIDDLE + def BOTTOM: BOTTOM + def LEFT: LEFT + def RIGHT: RIGHT + def initialize: (@rect=null, @el=null, @section=null, @event) -> + def equals: (other=AS.Models.Targets.Hit.new()) -> other.el is @el and other.section is @section diff --git a/lib/alpha_simprini/client/view.coffee b/lib/alpha_simprini/client/view.coffee index 94593a8..f0ec423 100644 --- a/lib/alpha_simprini/client/view.coffee +++ b/lib/alpha_simprini/client/view.coffee @@ -2,12 +2,12 @@ AS = require("alpha_simprini") _ = require("underscore") fleck = require("fleck") -AS.View = AS.DOM.extend - tag_name: "div" +AS.View = AS.DOM.extend ({def}) -> + def tagName: "div" - _ensure_element: -> @el ?= @$(@build_element()) + def _ensureElement: -> @el ?= @$(@build_element()) - constructor: (config={}) -> + def initialize: (config={}) -> @cid = _.uniqueId("c") for key, value of config @@ -16,55 +16,46 @@ AS.View = AS.DOM.extend else @[key] = value - @binding_group = new AS.BindingGroup - @_ensure_element() + @bindingGroup = AS.BindingGroup.new() + @_ensureElement() @delegateEvents() - @initialize() - initialize: -> - - append: (view) -> @el.append view.el - - process_attr: (node, key, value) -> - if value instanceof Function - # switch value - # when AS.Binding.Field - # false - # else - # false - else - node.setAttribute(key, value) - - group_bindings: (fn) -> - @within_binding_group @binding_group.add_child(), fn - - within_binding_group: (binding_group, fn) -> - current_group = @binding_group - @binding_group = binding_group - content = fn.call(this, binding_group) - @binding_group = current_group + def append: (view) -> @el.append view.el + + def process_attr: (node, key, value) -> + # if value instanceof Function + # # switch value + # # when AS.Binding.Field + # # false + # # else + # # false + # else + node.setAttribute(key, value) + + def groupBindings: (fn) -> + @withinBindingGroup @bindingGroup.addChild(), fn + + def withinBindingGroup: (bindingGroup, fn) -> + current_group = @bindingGroup + @bindingGroup = bindingGroup + content = fn.call(this, bindingGroup) + @bindingGroup = current_group content - binds: -> @binding_group.binds.apply(@binding_group, arguments) + def binds: -> @bindingGroup.binds.apply(@bindingGroup, arguments) - klass_string: (parts=[]) -> - if @constructor is AS.View - # parts.push "ASView" - parts.reverse().join " " - else - parts.push @constructor.name - @constructor.__super__.klass_string.call @constructor.__super__, parts + def klassString: -> @constructor.path().replace /\./g, " " - base_attributes: -> + def baseAttributes: -> attrs = - class: @klass_string() + class: @klassString() - build_element: -> - @current_node = @[@tag_name](@base_attributes()) + def build_element: -> + @currentNode = @[@tagName](@baseAttributes()) - delegateEvents: () -> + def delegateEvents: () -> if @events - @standard_events = new AS.ViewEvents(this, @events) + @standard_events = AS.ViewEvents.new(this, @events) @standard_events.apply_bindings() state_events = _(@constructor::).chain().keys().filter (key) -> @@ -73,7 +64,7 @@ AS.View = AS.DOM.extend for key in state_events.value() state = key.replace(/_events$/, '') do (key, state) => - @state_events[state] = new AS.ViewEvents(this, @[key]) + @state_events[state] = AS.ViewEvents.new(this, @[key]) @["exit_#{state}"] = -> @trigger("exitstate:#{state}") @@ -83,26 +74,26 @@ AS.View = AS.DOM.extend @trigger("enterstate:#{state}") @state_events[state].apply_bindings() - pluralize: (thing, count) -> + def pluralize: (thing, count) -> if count in [-1, 1] fleck.singularize(thing) else fleck.pluralize(thing) - reset_cycle: (args...) -> + def reset_cycle: (args...) -> delete @_cycles[args.join()] if @_cycles - cycle: (args...) -> + def cycle: (args...) -> @_cycles ?= {} @_cycles[args.join()] ?= 0 count = @_cycles[args.join()] += 1 args[count % args.length] - toggle: -> + def toggle: -> @button class:"toggle expand" @button class:"toggle collapse" - field: (_label, options = {}, fn = ->) -> + def field: (_label, options = {}, fn = ->) -> if _.isFunction options fn = options options = {} @@ -112,7 +103,7 @@ AS.View = AS.DOM.extend @input(options) fn?.call(this) - choice: (_label, options = {}, fn = ->) -> + def choice: (_label, options = {}, fn = ->) -> if _.isFunction options fn = options options = {} diff --git a/lib/alpha_simprini/client/view_events.coffee b/lib/alpha_simprini/client/view_events.coffee index d4c4a7a..ea72444 100644 --- a/lib/alpha_simprini/client/view_events.coffee +++ b/lib/alpha_simprini/client/view_events.coffee @@ -1,35 +1,30 @@ AS = require("alpha_simprini") _ = require "underscore" -class AS.ViewEvents - EVENT_SPLITTER = /^(@?[\w:]+)(\{.*\})?\s*(.*)$/ +AS.ViewEvents = AS.Object.extend ({def}) -> + EVENT_SPLITTER = /^(@?[\w:]+)\s*(.*)$/ - PARSE_GUARD = (guard="{}") -> - guard = guard.replace(/(\w+):/g, (__, match) -> "\"#{match}\":") - guard = JSON.parse(guard) - - constructor: (@view, events) -> + def initialize: (@view, events) -> @namespace = _.uniqueId ".ve" @events = @unify_options(events) @validate_options() @cache_handlers() - unify_options: (events) -> + def unify_options: (events) -> for key, options of events if _.isString options options = events[key] = method_name: options - [__, event_name, guard, selector] = key.match EVENT_SPLITTER + [__, event_name, selector] = key.match EVENT_SPLITTER options.event_name = event_name + @namespace - options.guard = PARSE_GUARD(guard) options.selector = selector options.method = @view[options.method_name] return events - validate_options: -> + def validate_options: -> for key, options of @events if options.method and options.transition throw new Error """ @@ -54,22 +49,20 @@ class AS.ViewEvents Specify only a function as a method for an event handler. """ - cache_handlers: -> + def cache_handlers: -> for key, options of @events do (key, options) => - options.handler = (event) => - for key, value of options.guard - return unless event[key] is value + options.handler = (_, event) => if options.method options.method.apply(@view, arguments) else if options.transition @view.transition_state options.transition - revoke_bindings: -> + def revoke_bindings: -> @revoke_binding(options) for key, options of @events - revoke_binding: (options) -> + def revoke_binding: (options) -> [selector, event_name] = [options.selector, options.event_name] if selector is '' @view.el.unbind @namespace @@ -82,10 +75,10 @@ class AS.ViewEvents target.die @namespace target.click() # bug with drag/drop allows for one last drag after revoking bindings :( - apply_bindings: -> + def apply_bindings: -> @apply_binding(options) for key, options of @events - apply_binding: (options) -> + def apply_binding: (options) -> [selector, event_name, handler] = [options.selector, options.event_name, options.handler] if selector is '' @view.el.bind event_name, handler diff --git a/lib/alpha_simprini/client/view_model.coffee b/lib/alpha_simprini/client/view_model.coffee index 01bccc0..fa13855 100644 --- a/lib/alpha_simprini/client/view_model.coffee +++ b/lib/alpha_simprini/client/view_model.coffee @@ -1,90 +1,69 @@ -AS = require("alpha_simprini") +AS = require "alpha_simprini" _ = require "underscore" jQuery = require "jQuery" +Pathology = require "pathology" -AS.ViewModel = AS.Object.extend() +AS.ViewModel = AS.Object.extend ({def, defs}) -> - # @build: (view, model) -> - # constructor = AS.ViewModel.constructor_for_model(model.constructor) - # new constructor(view, model) + defs build: (view, model) -> + constructor = AS.ViewModel.constructorForModel(model.constructor) + constructor.new(view, model) - # @constructor_for_model: (model) -> - # # Setting a cid on the constructor prevents name collisions - # model.cid ?= _.uniqueId("ctor") - # key = "#{model.name}-#{model.cid}" - # return AS.ViewModel[key] if AS.ViewModel[key] + defs constructorForModel: (model) -> + return AS.ViewModel[model.path()] if AS.ViewModel[model.path()] - # klass = class AS.ViewModel[key] extends AS.ViewModel - # klass.name = model.name - # klass::type = model.name + klass = AS.ViewModel[model.path()] = AS.ViewModel.extend() + klass.name = model.name + klass::type = model.name - # klass.bindables = {} - # klass.extended_by = model.extended_by + klass.bindables = {} + klass.extended_by = model.extended_by - # klass.field(field) for field, __ of model.fields if model.fields - # klass.field(virtual) for virtual, __ of model.virtuals if model.virtuals - # klass.embeds_many(embed_many) for embed_many, __ of model.embeds_manys if model.embeds_manys - # klass.embeds_one(embed_one) for embed_one, __ of model.embeds_ones if model.embeds_ones - # klass.has_many(has_many) for has_many, __ of model.has_manys if model.has_manys - # klass.has_one(has_one) for has_one, __ of model.has_ones if model.has_ones - # klass.belongs_to(belongs_to) for belongs_to, __ of model.belongs_tos if model.belongs_tos + for name, property of model.properties + klass.bindables[name] = switch property.constructor + when AS.Model.Field + AS.Binding.Field + when AS.Model.HasMany + AS.Binding.Many + when AS.Model.HasOne + AS.Binding.HasOne - # klass.delegations(model) + for method in AS.instanceMethods(model) + continue if _.include _.keys(Pathology.Object::), method + do (method) => + klass::[method] ?= -> @model[method].apply(@model, arguments) - # klass + return klass - # @field: (name) -> - # @bindables[name] = AS.Binding.Field + def initialize: (@view, @model) -> + @cid = @model.cid - # @embeds_many: (name) -> - # @bindables[name] = AS.Binding.EmbedsMany + def binding: (field, options, fn) -> + if _.isFunction(options) + [fn, options] = [options, {}] - # @embeds_one: (name) -> - # @bindables[name] = AS.Binding.EmbedsOne + new @constructor.bindables[field](@view, @model, field, options, fn) - # @has_many: (name) -> - # @bindables[name] = AS.Binding.HasMany + def input: (path, options) -> + new AS.Binding.Input(@view, @model, path, options) - # @has_one: (name) -> - # @bindables[name] = AS.Binding.HasOne + def checkbox: (path, options) -> + new AS.Binding.CheckBox(@view, @model, path, options) - # @belongs_to: (name) -> - # @bindables[name] = AS.Binding.BelongsTo + def select: (path, options) -> + new AS.Binding.Select(@view, @model, path, options) - # @delegations: (model) -> - # for method in AS.instance_methods(model) - # do (method) => - # @::[method] = -> @model[method].apply(@model, arguments) + def editline: (path, options) -> + new AS.Binding.EditLine(@view, @model, path, options) - # constructor: (@view, @model) -> - # @cid = @model.cid + def element: (tagname, fn) -> + element = @context[tagname] class: @model.constructor.name, fn + @view.$(element).data().model = @model + element - # binding: (field, options, fn) -> - # if _.isFunction(options) - # [fn, options] = [options, {}] - - # new @constructor.bindables[field](@view, @model, field, options, fn) - - # input: (path, options) -> - # new AS.Binding.Input(@view, @model, path, options) - - # checkbox: (path, options) -> - # new AS.Binding.CheckBox(@view, @model, path, options) - - # select: (path, options) -> - # new AS.Binding.Select(@view, @model, path, options) - - # editline: (path, options) -> - # new AS.Binding.EditLine(@view, @model, path, options) - - # element: (tagname, fn) -> - # element = @context[tagname] class: @model.constructor.name, fn - # @view.$(element).data().model = @model - # element - - # component: (ctor) -> - # if component = @model.component(ctor) - # AS.ViewModel.build(@view, component) - # else - # null + def component: (ctor) -> + if component = @model.component(ctor) + AS.ViewModel.build(@view, component) + else + null diff --git a/lib/alpha_simprini/client/views/panel.coffee b/lib/alpha_simprini/client/views/panel.coffee index b6b0ab9..1a24ed8 100644 --- a/lib/alpha_simprini/client/views/panel.coffee +++ b/lib/alpha_simprini/client/views/panel.coffee @@ -1,2 +1,2 @@ AS = require "alpha_simprini" -class AS.Views.Panel extends AS.View +AS.Views.Panel = AS.View.extend() diff --git a/lib/alpha_simprini/client/views/region.coffee b/lib/alpha_simprini/client/views/region.coffee index 1142e82..85f7fd2 100644 --- a/lib/alpha_simprini/client/views/region.coffee +++ b/lib/alpha_simprini/client/views/region.coffee @@ -3,26 +3,27 @@ _ = require "underscore" sum = (array) -> _.reduce(array, ((memo, num) -> memo + num), 0) -class AS.Views.Region extends AS.View - initialize: -> +AS.Views.Region = AS.View.extend ({def}) -> + def initialize: -> + @_super.apply this, arguments @application?.bind "resize", => @layout() - layout: -> -class AS.Views.North extends AS.Views.Region -class AS.Views.East extends AS.Views.Region - layout: -> + def layout: -> +AS.Views.North = AS.Views.Region.extend ({def}) -> +AS.Views.East = AS.Views.Region.extend ({def}) -> + def layout: -> @el.css top: @el.siblings(".North").outerHeight() or 0 bottom: @el.siblings(".South").outerHeight() or 0 -class AS.Views.South extends AS.Views.Region -class AS.Views.West extends AS.Views.Region - layout: -> +AS.Views.South = AS.Views.Region.extend ({def}) -> +AS.Views.West = AS.Views.Region.extend ({def}) -> + def layout: -> @el.css top: @el.siblings(".North").outerHeight() or 0 bottom: @el.siblings(".South").outerHeight() or 0 -class AS.Views.Center extends AS.Views.Region - layout: -> +AS.Views.Center = AS.Views.Region.extend ({def}) -> + def layout: -> @el.css top: @el.siblings(".North").outerHeight() or 0 bottom: @el.siblings(".South").outerHeight() or 0 diff --git a/lib/alpha_simprini/core/callbacks.coffee b/lib/alpha_simprini/core/callbacks.coffee index f147248..7f23ef1 100644 --- a/lib/alpha_simprini/core/callbacks.coffee +++ b/lib/alpha_simprini/core/callbacks.coffee @@ -1,16 +1,13 @@ -# AS = require("alpha_simprini") -# AS.Callbacks = new AS.Mixin -# depends_on: [AS.InheritableAttrs] -# class_methods: -# define_callbacks: (all) -> -# for key, callbacks of all -# do (key, callbacks) => -# for callback in callbacks or [] -# do (callback) => -# @["#{key}_#{callback}"] = (fn) -> -# @push_inheritable_item("#{key}_#{callback}_callbacks", fn) - -# instance_methods: -# run_callbacks: (name) -> -# for callback in @constructor["#{name}_callbacks"] || [] -# callback.call(null, this) \ No newline at end of file +AS = require("alpha_simprini") +AS.Callbacks = AS.Module.extend ({def, defs}) -> + defs define_callbacks: (all) -> + for key, callbacks of all + do (key, callbacks) => + for callback in callbacks or [] + do (callback) => + @["#{key}_#{callback}"] = (fn) -> + @pushInheritableItem("#{key}_#{callback}_callbacks", fn) + + def run_callbacks: (name) -> + for callback in @constructor["#{name}_callbacks"] || [] + callback.call(null, this) \ No newline at end of file diff --git a/lib/alpha_simprini/core/collection.coffee b/lib/alpha_simprini/core/collection.coffee index a81a425..c9ad81c 100644 --- a/lib/alpha_simprini/core/collection.coffee +++ b/lib/alpha_simprini/core/collection.coffee @@ -2,8 +2,11 @@ AS = require("alpha_simprini") Taxi = require("taxi") {extend, chain, isString} = require("underscore") -AS.Collection = AS.Object.extend - initialize: (@models=[], options = {}) -> +AS.Collection = AS.Object.extend ({def, include, delegate}) -> + include Taxi.Mixin + delegate AS.COLLECTION_DELEGATES, to: "models" + + def initialize: (@models=[], options = {}) -> extend this, options @length = 0 @byId = {} @@ -11,9 +14,9 @@ AS.Collection = AS.Object.extend @models = chain([]) @add(model) for model in @models - model: -> AS.Model + def model: -> AS.Model - add: (model={}, options={}) -> + def add: (model={}, options={}) -> # Allow for passing both Model and ViewModels in model = model.model if model.model and model.model.id @@ -27,7 +30,7 @@ AS.Collection = AS.Object.extend model - build: (model) -> + def build: (model) -> if isString(model) AS.All.byId[model] else @@ -37,9 +40,10 @@ AS.Collection = AS.Object.extend ctor = AS.module(model._type) else ctor = @model() - ctor.create(model) + + ctor.new(model) - _add: (model, options={}) -> + def _add: (model, options={}) -> options.at ?= this.length index = options.at @byCid[model.cid] = @byId[model.id] = model @@ -48,15 +52,15 @@ AS.Collection = AS.Object.extend model.bind event: "all" namespace: @objectId() - handler: @_on_model_event + handler: @_onModelEvent context: this model.trigger "add", this, options - at: (index) -> + def at: (index) -> @models.value()[index] - remove: (model, options={}) -> + def remove: (model, options={}) -> # Allow for passing both Model and ViewModels in model = model.model result = @_remove(model, options) @@ -65,7 +69,7 @@ AS.Collection = AS.Object.extend result - _remove: (model, options={}) -> + def _remove: (model, options={}) -> options.at = @models.indexOf(model).value() @length-- delete @byId[model.id] @@ -77,39 +81,10 @@ AS.Collection = AS.Object.extend namespace: @objectId() # # When an event is triggered from a model, it is bubbled up through the collection. - _on_model_event: (event, model, collection, options) -> + def _onModelEvent: (event, model, collection, options) -> return unless isString(event) - return if (event is "add" or event is "remove") and (this isnt collection[0]) + return if (event is "add" or event is "remove") and (this isnt collection) @_remove(model, options) if event is "destroy" @trigger.apply(this, arguments) -# pluck: (name) -> @map (item) -> item[name]() - -AS.Collection.delegate AS.COLLECTION_DELEGATES, to: "models" - -Taxi.Mixin.extends(AS.Collection) -# class AS.Collection -# AS.Delegate.extends(this) -# AS.Event.extends(this) - - -# @model: -> AS.Model - -# constructor: (@models=[]) -> -# @initialize() - -# initialize: () -> -# given_models = @models - - - -# # filter: (options) -> -# # @filter ?= new AS.Collection.Filter(this) -# # @filter.reset() -# # @filter.on(options) -# # @filter - - - - -# class AS.EmbeddedCollection extends AS.Collection +# def pluck: (name) -> @map (item) -> item[name]() diff --git a/lib/alpha_simprini/core/instance_methods.coffee b/lib/alpha_simprini/core/instance_methods.coffee index 627be86..d57d5b4 100644 --- a/lib/alpha_simprini/core/instance_methods.coffee +++ b/lib/alpha_simprini/core/instance_methods.coffee @@ -1,8 +1,8 @@ AS = require("alpha_simprini") _ = require "underscore" -AS.instance_methods = (klass) -> +AS.instanceMethods = (klass) -> methods = _(klass.prototype).chain().keys() if klass.__super__ - methods = methods.concat AS.instance_methods(klass.__super__.constructor) + methods = methods.concat AS.instanceMethods(klass.__super__.constructor) return methods.without("constructor", "initialize").value() \ No newline at end of file diff --git a/lib/alpha_simprini/core/model.coffee b/lib/alpha_simprini/core/model.coffee index 18cbdf1..ed096e7 100644 --- a/lib/alpha_simprini/core/model.coffee +++ b/lib/alpha_simprini/core/model.coffee @@ -1,9 +1,11 @@ AS = require("alpha_simprini") -{uniqueId} = require("underscore") +{uniqueId, toArray} = _ = require("underscore") Taxi = require("taxi") -AS.Model = AS.Object.extend - initialize: (attributes={}) -> +AS.Model = AS.Object.extend ({def, include}) -> + include Taxi.Mixin + + def initialize: (attributes={}) -> @model = this @id = attributes.id ? AS.uniq() @cid = @id or uniqueId("c") @@ -13,310 +15,9 @@ AS.Model = AS.Object.extend @[key].set(value) for key, value of attributes - -Taxi.Mixin.extends AS.Model - -# _ = require("underscore") -# AS.All = -# byId: {} -# byCid: {} - -# require_config = (config, key, message) -> -# return if key in config -# throw new Error message - -# FieldTypes = -# "Boolean": -# read: (value) -> -# return value if _.isBoolean(value) -# return true if value is "true" -# return false if value is "false" -# return false - -# write: (value) -> -# return "true" if value is "true" or value is true -# return "false" if value is "false" or value is false -# return "false" - -# "String": -# read: (value) -> value -# write: (value) -> value - -# "Number": -# read: (value) -> value -# write: (value) -> value - -# class AS.Model -# AS.Event.extends(this) -# AS.InheritableAttrs.extends(this) -# AS.Callbacks.extends(this) - -# @define_callbacks(after: ["initialize"], before: ["initialize"]) - -# @embeds_many: (name, config={}) -> -# config.relation = true -# @relation(name) -# @attribute(name) -# @write_inheritable_value("embeds_manys", name, config) - -# @has_many: (name, config={}) -> -# config.relation = true -# @relation(name) -# @attribute(name) -# @write_inheritable_value("has_manys", name, config) - -# @EmbedsOneMethod = (name) -> -# return (value) -> -# unless value is undefined -# if value is null -# @set_attribute(name, undefined) -# else if value.cid -# @set_attribute(name, value.cid) -# else if _.isString(value) -# @set_attribute(name, value) -# else -# if value._type -# model = AS.module(value._type) -# else -# model = AS.Model -# @set_attribute name, (new model value).cid - -# # attach our self to the embedded model for reflection, k? -# # Laffo, this could get ugly, except, we'll never be embedded in more than one -# # place at the same time, so I think we'll survive. -# # still, a half-baked idea. -# embedded = AS.All.byCid[@get_attribute(name)] -# embedded?.embedded_in ?= this -# # We always want to return the embedded object -# embedded - -# @embeds_one: (name, config={}) -> -# # require_config config, 'model', "for @embeds_one '#{name}, must specify the 'model' option. (Provide a function that returns a model constructor.)" - -# config.relation = true -# @relation(name) -# @write_inheritable_value("embeds_ones", name, config) - -# @::[name] = @EmbedsOneMethod(name) - -# @has_one: (name, config={}) -> -# config.relation = true -# @relation(name) -# @write_inheritable_value("has_ones", name, config) - -# @::[name] = (value) -> -# if value is undefined -# AS.All.byCid[@get_attribute(name)] -# else -# if value is null -# @set_attribute(name, undefined) -# else if value.cid -# @set_attribute(name, value.cid) -# else if _.isString(value) -# @set_attribute(name, value) -# else -# if value._type -# model = AS.module(value._type) -# else -# model = AS.Model -# @set_attribute name, (new model value).cid - -# @belongs_to: (name, config={}) -> -# config.relation = true -# @relation(name) -# @write_inheritable_value("belongs_tos", name, config) - -# @::[name] = (value) -> -# if value is undefined -# AS.All.byCid[@get_attribute(name)] -# else -# if value is null -# @set_attribute(name, undefined) -# else if value.cid -# @set_attribute(name, value.cid) -# else if _.isString(value) -# @set_attribute(name, value) -# else -# throw new Error(["Cannot set #{name} to unexpected value. Try passing a cid, or an object with a cid. Value was: ", value]) - -# @relation: (name) -> -# @push_inheritable_item("relations", name) - -# @field: (name, config={}) -> -# if config.type?.name -# config.type = FieldTypes[config.type.name] - -# config.type ?= FieldTypes.String -# @write_inheritable_value("fields", name, config) -# @attribute(name, config) - -# @virtual_properties: (fields..., defs) -> -# virtual_cache = {} -# for name, fn of defs -# @write_inheritable_value("virtuals", name, fields) - -# # bind to all events for fields -# @after_initialize (model) -> -# for field in fields -# if model.constructor.fields?[field] or model.constructor.embeds_ones?[field] -# model.bind "change:#{field}", (name, value, options) -> -# for name, fn of defs -# _value = model[name]() -# continue if _value is virtual_cache[name] -# virtual_cache[field] = _value -# model.trigger("change", name, _value, options) -# model.trigger("change:#{name}", name, _value, options) - -# else if model.constructor.has_manys?[field] or model.constructor.embeds_manys?[field] -# relation = model[field]() - -# callback = (collection, item, options) -> -# for name, fn of defs -# _value = model[name]() -# continue if _value is virtual_cache[name] -# virtual_cache[name] = _value -# model.trigger("change", name, _value, options) -# model.trigger("change:#{name}", name, _value, options) - -# relation.bind "add", callback -# relation.bind "remove", callback -# relation.bind "change", callback - -# # set up functions to reat virtual properties -# for name, fn of defs -# @::[name] = fn - -# @attribute: (name, config={}) -> -# if config.type -# @::[name] = (value, options) -> -# if value is undefined -# config.type.read @get_attribute(name) -# else -# @set_attribute name, config.type.write(value), options -# else -# @::[name] = (value, options) -> -# if value is undefined -# @get_attribute(name) -# else -# @set_attribute(name, value, options) - -# @initialize_relations: (model) -> - -# constructor: (@attributes = {}, options={}) -> -# # @model is @, used for compatibility with wrappers like ViewModel -# @model = this -# @run_callbacks "before_initialize" -# @set_defaults() if @new() -# @initialize(options) -# @run_callbacks "after_initialize" - -# initialize: (options={}) -> -# @attributes.id ?= AS.uniq() - -# @id = @attributes.id -# @cid = @id or _.uniqueId("c") - -# AS.All.byCid[@cid] = AS.All.byId[@id] = this - -# @initialize_embeds_many(name, config) for name, config of @constructor.embeds_manys || {} -# @initialize_has_many(name, config) for name, config of @constructor.has_manys || {} -# @initialize_embeds_one(name, config) for name, config of @constructor.embeds_ones || {} -# @initialize_has_one(name, config) for name, config of @constructor.has_ones || {} -# @initialize_belongs_to(name, config) for name, config of @constructor.belongs_tos || {} - -# # @persisted() - -# new: -> @attributes.id is undefined - -# set_defaults: () -> -# for name, config of @constructor.fields || {} -# @[name]() or @[name](config.default) - -# read_path: (path) -> -# target = this -# for piece in path -# target = target[piece]() -# target - -# write_path: (path, value) -> -# target = this -# for piece in path[..-2] -# target = target[piece]() -# target[path[path.length - 1]](value) - -# last: (attr) -> -# [@attributes, @previous_attributes] = [@previous_attributes, @attributes] -# last = @[attr]() -# [@attributes, @previous_attributes] = [@previous_attributes, @attributes] -# last - -# initialize_embeds_many: (name, config) -> -# data = {} -# klass = class this["#{name}_collection_klass"] extends AS.EmbeddedCollection -# _.extend klass::, config -# klass.model = -> config.model() if config.model -# collection = data[name] = new klass(@[name]?()) -# collection.source = this -# @set data - -# initialize_has_many: (name, config) -> -# @has_manys ?= {} -# data = {} -# klass = class this["#{name}_collection_klass"] extends AS.Collection -# _.extend klass::, config -# klass.model = -> config.model?() or AS.Model -# @has_manys[name] = collection = data[name] = new klass() -# collection.source = this -# @set data - -# initialize_embeds_one: (name, config) -> -# unless @[name](@attributes[name]) -# @[name]( new (config.model?() || AS.Model) ) unless config.prefill is false - -# initialize_has_one: (name, config) -> -# @[name](@attributes[name]) - -# initialize_belongs_to: (name, config) -> -# # pass; not sure you have to do anything, this should be properly set already. - -# save: () -> -# return false unless @changed() -# @persisted() -# true - -# # Persisted is a callback here. -# # Actual persistance will be handled by an observer. DEAL WITH IT IF YOU WANT IT. -# persisted: -> -# @previous_attributes = AS.deepClone(@attributes) - -# changes: () -> -# changed = {} -# for key, value of @attributes -# changed[key] = value unless @previous_attributes[value] is value -# changed - -# changed: () -> _(@changes()).chain().keys().any().value() - -# get: (attr) -> @[attr]() - -# set: (attrs) -> -# @[key](value) for key, value of attrs - -# set_attribute: (name, value, options={}) -> -# @attributes[name] = value -# @trigger("change:#{name}", name, value, options) -# @trigger("change", name, value, options) -# value - -# get_attribute: (name) -> -# @attributes?[name] - -# destroy: () -> -# @trigger("destroy") - -# trigger: () -> -# args = [].concat.apply [], arguments -# args.splice 1, 0, this -# AS.Event.instance_methods.trigger.apply this, args + def trigger: -> + args = toArray(arguments) + args.splice(1, 0, this) + @_super.apply this, args diff --git a/lib/alpha_simprini/core/model/share.coffee b/lib/alpha_simprini/core/model/share.coffee index 421a63d..b732b63 100644 --- a/lib/alpha_simprini/core/model/share.coffee +++ b/lib/alpha_simprini/core/model/share.coffee @@ -50,7 +50,7 @@ # model.did_load_embedded(share) # model -# instance_methods: +# instanceMethods: # did_open: (@share) -> # @ensure_defaults() # @bind_share_events() diff --git a/lib/alpha_simprini/core/models/multiple_selection_model.coffee b/lib/alpha_simprini/core/models/multiple_selection_model.coffee index 4eaa7f7..c442952 100644 --- a/lib/alpha_simprini/core/models/multiple_selection_model.coffee +++ b/lib/alpha_simprini/core/models/multiple_selection_model.coffee @@ -1,20 +1,19 @@ # AS = require "alpha_simprini" -# class AS.Models.MultipleSelectionModel extends AS.Model -# @has_many 'selected' +# AS.Models.MultipleSelectionModel = AS.Model.extend ({def}) -> +# @hasMany "items" -# initialize: -> -# super +# def initialize: -> +# @_super() # @items = @selected() # @items.bind "add", (item) => @trigger("add", item) # @items.bind "remove", (item) => @trigger("remove", item) -# select: (item) -> +# def select: (item) -> # @items.add(item) -# deselect: (item) -> +# def deselect: (item) -> # @items.remove(item) -# clear: -> +# def clear: -> # @items.each @items.remove, @items - diff --git a/lib/alpha_simprini/core/properties/field.coffee b/lib/alpha_simprini/core/properties/field.coffee index b082024..d73c96d 100644 --- a/lib/alpha_simprini/core/properties/field.coffee +++ b/lib/alpha_simprini/core/properties/field.coffee @@ -21,32 +21,31 @@ casters = return "false" # TODO: Field is generic. reuse it. -AS.Model.Field = AS.Property.extend - initialize: (@name, @_constructor, @options={}) -> +AS.Model.Field = AS.Property.extend ({def}) -> + def initialize: (@name, @_constructor, @options={}) -> @options.name = @name @_constructor.writeInheritableValue 'properties', @name, this - instance: (object) -> @constructor.Instance.create(object, @options) + def instance: (object) -> @constructor.Instance.new(object, @options) -# TODO: Instance is specific -AS.Model.Field.Instance = AS.Model.Field.Instance.extend - initialize: (@object, @options={}) -> - @options.type ?= String - @set(@options.default) if @options.default + @Instance = @Instance.extend ({def}) -> + def initialize: (@object, @options={}) -> + @options.type ?= String + @set(@options.default) if @options.default - get: -> - casters[@options.type.name].read(@value) + def get: -> + casters[@options.type.name].read(@value) - set: (value) -> - writeValue = casters[@options.type.name].write(value) - return if writeValue is @value - @value = writeValue - @object.trigger("change") - @object.trigger("change:#{@options.name}") - @trigger("change") - value + def set: (value) -> + writeValue = casters[@options.type.name].write(value) + return if writeValue is @value + @value = writeValue + @object.trigger("change") + @object.trigger("change:#{@options.name}") + @trigger("change") + value -AS.Model.field = (name, options) -> - AS.Model.Field.create(name, this, options) +AS.Model.defs field: (name, options) -> + AS.Model.Field.new(name, this, options) diff --git a/lib/alpha_simprini/core/properties/has_many.coffee b/lib/alpha_simprini/core/properties/has_many.coffee index ad56920..0c62068 100644 --- a/lib/alpha_simprini/core/properties/has_many.coffee +++ b/lib/alpha_simprini/core/properties/has_many.coffee @@ -1,27 +1,29 @@ AS = require("alpha_simprini") AS.Model.HasMany = AS.Model.Field.extend() -AS.Model.HasMany.Instance = AS.Model.HasMany.Instance.extend +AS.Model.HasMany.Instance = AS.Model.HasMany.Instance.extend ({def, delegate}) -> + delegate AS.COLLECTION_DELEGATES, to: "backingCollection" - initialize: (@object, @options={}) -> - @backingCollection = AS.Collection.create(undefined, @options) + def initialize: (@object, @options={}) -> + @backingCollection = AS.Collection.new(undefined, @options) - set: (models) -> + def set: (models) -> @backingCollection.add models - add: (models) -> @backingCollection.add(models) + def add: (models) -> @backingCollection.add.apply(@backingCollection, arguments) - remove: (models) -> @backingCollection.remove(models) + def at: (models) -> @backingCollection.at.apply(@backingCollection, arguments) - bind: -> @backingCollection.bind.apply(@backingCollection, arguments) + def remove: (models) -> @backingCollection.remove.apply(@backingCollection, arguments) - trigger: -> @backingCollection.trigger.apply(@backingCollection, arguments) + def bind: -> @backingCollection.bind.apply(@backingCollection, arguments) - unbind: -> @backingCollection.unbind.apply(@backingCollection, arguments) + def trigger: -> @backingCollection.trigger.apply(@backingCollection, arguments) + + def unbind: -> @backingCollection.unbind.apply(@backingCollection, arguments) -AS.Model.HasMany.Instance.delegate AS.COLLECTION_DELEGATES, to: "backingCollection" #FIXME: this should have worked # AS.Model.HasMany.Instance.delegate "add", "remove", "bind", "unbind", "trigger", to: "backingCollection" -AS.Model.hasMany = (name, options) -> - AS.Model.HasMany.create(name, this, options) +AS.Model.defs hasMany: (name, options) -> + AS.Model.HasMany.new(name, this, options) diff --git a/lib/alpha_simprini/core/properties/has_one.coffee b/lib/alpha_simprini/core/properties/has_one.coffee index a0125e6..9d88efe 100644 --- a/lib/alpha_simprini/core/properties/has_one.coffee +++ b/lib/alpha_simprini/core/properties/has_one.coffee @@ -1,31 +1,31 @@ AS = require("alpha_simprini") AS.Model.HasOne = AS.Model.Field.extend() -AS.Model.HasOne.Instance = AS.Model.HasOne.Instance.extend - initialize: (@object, @options) -> +AS.Model.HasOne.Instance = AS.Model.HasOne.Instance.extend ({def}) -> + def initialize: (@object, @options) -> @options.model ?= -> AS.Model - get: -> + def get: -> @value - set: (object) -> + def set: (object) -> return if object is @value object = object.model if object.model if object instanceof AS.Model @value = object else - @value = @options.model().create(object) + @value = @options.model().new(object) @object.trigger("change") @object.trigger("change:#{@options.name}") # @trigger("change") - bind: -> @value.bind.apply(@value, arguments) + def bind: -> @value.bind.apply(@value, arguments) - trigger: -> @value.trigger.apply(@value, arguments) + def trigger: -> @value.trigger.apply(@value, arguments) - unbind: -> @value.unbind.apply(@value, arguments) + def unbind: -> @value.unbind.apply(@value, arguments) -AS.Model.hasOne = (name, options) -> - AS.Model.HasOne.create(name, this, options) +AS.Model.defs hasOne: (name, options) -> + AS.Model.HasOne.new(name, this, options) diff --git a/lib/alpha_simprini/core/state_machine.coffee b/lib/alpha_simprini/core/state_machine.coffee index f2cd427..e5adb62 100644 --- a/lib/alpha_simprini/core/state_machine.coffee +++ b/lib/alpha_simprini/core/state_machine.coffee @@ -9,7 +9,7 @@ # # @event "stop_now" # # @event "" # AS.StateMachine = new AS.Mixin -# instance_methods: +# instanceMethods: # transition_state: (options) -> # if @state is options.from # @["exit_#{@state}"]?(options) if @state # default state comes from nowhere diff --git a/test/client/application.coffee b/test/client/application.coffee index 2e659b9..f03870d 100644 --- a/test/client/application.coffee +++ b/test/client/application.coffee @@ -1,7 +1,7 @@ {AS, $, _, sinon, jwerty} = require require("path").resolve("./test/client_helper") exports.Application = setUp: (callback) -> - @app = AS.Application.create() + @app = AS.Application.new() callback() "attaches global key handlers w/jwerty": (test) -> @@ -14,14 +14,14 @@ exports.Application = jwerty.fire "backspace" test.done() - # "initializes views into the application context": (test) -> - # app_panel = @app.view AS.Views.Panel, key: "value" - # test.equal app_panel.application, @app - # test.equal app_panel.key, "value" - # test.done() + "initializes views into the application context": (test) -> + app_panel = @app.view AS.Views.Panel, key: "value" + test.equal app_panel.application, @app + test.equal app_panel.key, "value" + test.done() - # "appends views into the app dom element": (test) -> - # app_panel = @app.view AS.Views.Panel, key: "value" - # @app.append app_panel - # test.equal @app.el.children()[0], app_panel.el[0] - # test.done() + "appends views into the app dom element": (test) -> + app_panel = @app.view AS.Views.Panel, key: "value" + @app.append app_panel + test.equal @app.el.children()[0], app_panel.el[0] + test.done() diff --git a/test/client/binding.coffee b/test/client/binding.coffee index c220ebc..18421d4 100644 --- a/test/client/binding.coffee +++ b/test/client/binding.coffee @@ -4,6 +4,7 @@ exports.setUp = coreSetUp BoundModel = NS.BoundModel = AS.Model.extend() BoundModel.field "field" +BoundModel.field "maybe", type: Boolean BoundModel.hasMany "items", model: -> SimpleModel BoundModel.hasOne "owner" @@ -14,13 +15,13 @@ SimpleModel = NS.SimpleModel = AS.Model.extend() SimpleModel.field "field" mock_binding = (binding_class, _options={}) -> - context = _options.context or AS.View.create - model = _options.model or BoundModel.create field: "value" - field = _options.field or "field" + context = _options.context or AS.View.new() + model = _options.model or BoundModel.new field: "value" + field = _options.field or model["field"] options = _options.options or {} fn = _options.fn or undefined - binding = binding_class.create context, model, field, options, fn + binding = binding_class.new context, model, field, options, fn mocks = binding: sinon.mock binding @@ -42,363 +43,390 @@ mock_binding = (binding_class, _options={}) -> exports.Binding = "stashes the binding container": (test) -> [mocks, binding] = mock_binding(AS.Binding) - test.equal binding.container[0], binding.context.current_node - test.done() - - # "stashes the binding group": (test) -> - # [mocks, binding] = mock_binding(AS.Binding) - # test.equal binding.binding_group, binding.context.binding_group - - # test.done() - - # "gets the field value": (test) -> - # [mocks, binding] = mock_binding(AS.Binding) - # test.equal binding.path_value(), "value" - - # test.done() - - # Model: - - # "paints styles": (test) -> - # context = new AS.View - # context_mock = sinon.mock context - # content = $("
") - # content_mock = sinon.mock content - # model = new AS.Model - # binding = new AS.Binding.Model context, model, content - - # context_mock.expects('binds').withArgs(model, "change:field1") - # context_mock.expects('binds').withArgs(model, "change:field2") - - # binding.css - # "background-color": - # fn: (model) -> model.bgcolor or "mock-color" - # field: "field1 field2" - - # content_mock.expects("css").withExactArgs - # "background-color": "mock-color" - - # binding.paint() - - # model.bgcolor = "bgcolor" - - # content_mock.expects("css").withExactArgs - # "background-color": "bgcolor" - - # model.trigger("change:field1") - - # test.done() - - # "paints attributes": (test) -> - # context = new AS.View - # context_mock = sinon.mock context - # content = $("
") - # content_mock = sinon.mock content - # model = new AS.Model - # binding = new AS.Binding.Model context, model, content - - # context_mock.expects('binds').withArgs(model, "change:field1") - # context_mock.expects('binds').withArgs(model, "change:field2") - - # binding.attr - # "data-property": - # fn: (model) -> model.property or "mock-value" - # field: "field1 field2" - - # content_mock.expects("attr").withExactArgs - # "data-property": "mock-value" - - # binding.paint() - - # model.property = "value2" - - # content_mock.expects("attr").withExactArgs - # "data-property": "value2" - - # model.trigger("change:field2") - - # test.done() - - # Field: - # "sets appropriate initial content": (test) -> - # [mocks, binding] = mock_binding(AS.Binding.Field) - # test.equal binding.container.find("span").text(), "value" - # test.done() - - # "updates content when model changes": (test) -> - # [mocks, binding] = mock_binding(AS.Binding.Field) - # binding.model.field("new value") - # test.equal binding.container.find("span").text(), "new value" - # test.done() - - # "uses given fn to generate content": (test) -> - # [mocks, binding] = mock_binding AS.Binding.Field, - # fn: -> - # @h1 -> @span "fn value" - - # test.equal binding.container.find("h1 > span").text(), "fn value" - # test.done() - - # "updates fn content when value changes": (test) -> - # model = new BoundModel field: "value" - # [mocks, binding] = mock_binding AS.Binding.Field, - # model: model - # fn: -> - # @h1 -> @span model.field() - - # test.equal binding.container.find("h1 > span").text(), "value" - # binding.model.field("changed value") - # test.equal binding.container.find("h1 > span").text(), "changed value" - # test.done() - - - # Input: - # "sets input value on initialization": (test) -> - # [mocks, binding] = mock_binding(AS.Binding.Input) - # test.equal binding.container.find("input").val(), "value" - # test.done() - - # "updates input value when model changes": (test) -> - # [mocks, binding] = mock_binding(AS.Binding.Input) - # binding.model.field("changed value") - # test.equal binding.container.find("input").val(), "changed value" - # test.done() - - # "updates model value when input changes": (test) -> - # [mocks, binding] = mock_binding(AS.Binding.Input) - # binding.model.field("changed value") - # binding.container.find("input").val("user value").trigger("change") - # test.equal binding.model.field(), "user value" - # test.done() - - # "inherits from Field": (test) -> - # test.equal AS.Binding.Input.__super__.constructor, AS.Binding.Field - # test.done() - - # Select: - # "must provide options option": (test) -> - # test.throws (-> mock_binding(AS.Binding.Select)), AS.Binding.MissingOption - # test.done() - - # "uses provided Array for select options": (test) -> - # options = [1..3] - # [mocks, binding] = mock_binding(AS.Binding.Select, options: options: options) - - # test.equal binding.container.find("option").length, 3 - # test.equal binding.container.find("select").text(), "123" - - # test.done() - - # "uses provided Object for select options": (test) -> - # options = - # "one": 1 - # "two": 2 - # "three": 3 - # [mocks, binding] = mock_binding(AS.Binding.Select, options: options: options) - - # test.equal binding.container.find("option").length, 3 + test.equal binding.container[0], binding.context.currentNode - # for key, value of options - # test.equal $(binding.container.find("option[value='#{value}']")).text(), key - - # test.done() + test.done() - # "sets select value on initialization": (test) -> - # model = new BoundModel field: "value" - # options = ["notvalue", "value"] - # [mocks, binding] = mock_binding(AS.Binding.Select, options: (options: options), model: model) + "stashes the binding group": (test) -> + [mocks, binding] = mock_binding(AS.Binding) + test.equal binding.bindingGroup, binding.context.bindingGroup - # test.equal binding.container.find("select").val(), "value" + test.done() - # test.done() + "gets the field value": (test) -> + [mocks, binding] = mock_binding(AS.Binding) + test.equal binding.fieldValue(), "value" - # "sets value of dom when model value changes": (test) -> - # model = new BoundModel field: "value" - # options = ["notvalue", "value"] - # [mocks, binding] = mock_binding(AS.Binding.Select, options: (options: options), model: model) + test.done() - # model.field("notvalue") + Model: - # test.equal binding.container.find("select").val()[0], "notvalue" + "paints styles": (test) -> + context = AS.View.new() + context_mock = sinon.mock context + content = $("
") + content_mock = sinon.mock content + model = AS.Model.new() + binding = AS.Binding.Model.new context, model, content - # test.done() + context_mock.expects('binds').withArgs(model, "change:field1") + context_mock.expects('binds').withArgs(model, "change:field2") - # "sets value on object when dom changes": (test) -> - # model = new BoundModel field: "value" - # options = ["notvalue", "value"] - # [mocks, binding] = mock_binding(AS.Binding.Select, options: (options: options), model: model) + binding.css + "background-color": + fn: (model) -> model.bgcolor or "mock-color" + field: "field1 field2" - # binding.container.find("select").val("notvalue") - # binding.container.find("select").trigger("change") + content_mock.expects("css").withExactArgs + "background-color": "mock-color" - # test.equal model.field(), "notvalue" + binding.paint() - # test.done() + model.bgcolor = "bgcolor" + content_mock.expects("css").withExactArgs + "background-color": "bgcolor" - # EditLine: - # setUp: (callback) -> - # @rangy_api = - # getSelection: -> { - # rangeCount: 0 - # createRange: -> { - # startOffset: 0 - # endOffset: 0 - # } - # } - # createRange: -> { - # startOffset: 0 - # endOffset: 0 - # } - - # @real_open = AS.open_shared_object - # AS.open_shared_object = (id, did_open) -> - # did_open makeDoc(id) - - # @remote = (operation, model = @model) -> - # if model.share.emit - # model.share.emit "remoteop", operation - # else - # model.share.doc.emit "remoteop", operation - - # AS.Binding.EditLine::rangy = @rangy_api - # callback() + model.trigger("change:field1") - # tearDown: (callback) -> - # AS.open_shared_object = @real_open - # callback() + test.done() - # "contenteditable area responds to all edit events": (test) -> - # test.expect 8 - # class EditLine extends AS.Binding.EditLine - # generate_operation: -> test.ok true - # [mocks, binding] = mock_binding(EditLine) - # mocks.binding.expects("applyChange").exactly(0) - # for event in ['textInput', 'keydown', 'keyup', 'select', 'cut', 'paste', 'click', 'focus'] - # binding.content.trigger(event) - # mocks.verify() - # test.done() + "paints attributes": (test) -> + context = AS.View.new() + context_mock = sinon.mock context + content = $("
") + content_mock = sinon.mock content + model = AS.Model.new() + binding = AS.Binding.Model.new context, model, content - # "applies change if content has changed on edit event": (test) -> - # model = SharedBoundModel.open() - # model.field("value") - # model.when_indexed => - # [mocks, binding] = mock_binding(AS.Binding.EditLine, model: model) - # binding.content[0].innerHTML += " change" - # binding.generate_operation() - # test.deepEqual model.share.get(), model.attributes_for_sharing() - # test.done() - - # "applies change from remote operation": (test) -> - # model = SharedBoundModel.open() - # model.field("value") - # model.when_indexed => - # [mocks, binding] = mock_binding(AS.Binding.EditLine, model: model) - # @remote model.share.at("field").insert(0, "remote "), model - # test.equal binding.content[0].innerHTML, "remote value" - # test.equal model.share.at("field").get(), "remote value" - # test.equal model.field(), "remote value" - # test.done() - - # HasMany: - # setUp: (callback) -> - # model = new BoundModel - # items = model.items() - # items.add() - # items.add() - # items.add() + context_mock.expects('binds').withArgs(model, "change:field1") + context_mock.expects('binds').withArgs(model, "change:field2") + binding.attr + "data-property": + fn: (model) -> model.property or "mock-value" + field: "field1 field2" - # content_fn = (thing) -> @div id: thing.cid + content_mock.expects("attr").withExactArgs + "data-property": "mock-value" - # [mocks, binding] = mock_binding(AS.Binding.HasMany, field: 'items', model: model, fn: content_fn) + binding.paint() - # @items = items - # @binding = binding - # callback() + model.property = "value2" - # "creates initial collection dom": (test) -> - # test.expect 3 - # @items.each (item) => - # test.ok @binding.container.find("##{item.cid}").is("div") + content_mock.expects("attr").withExactArgs + "data-property": "value2" - # test.done() + model.trigger("change:field2") - # "adds additional dom elements when items added to collection": (test) -> - # test.expect 1 - # item = @items.add() + test.done() - # test.ok @binding.container.find("##{item.cid}").is("div") + Field: + "sets appropriate initial content": (test) -> + [mocks, binding] = mock_binding(AS.Binding.Field) + test.equal binding.container.find("span").text(), "value" + test.done() - # test.done() + "updates content when model changes": (test) -> + [mocks, binding] = mock_binding(AS.Binding.Field) + binding.model.field.set("new value") + test.equal binding.container.find("span").text(), "new value" + test.done() - # "adds new dom elements at correct index": (test) -> - # test.expect 1 - # item = @items.add({}, at: 0) + "uses given fn to generate content": (test) -> + [mocks, binding] = mock_binding AS.Binding.Field, + fn: -> + @h1 -> @span "fn value" - # test.ok @binding.container.children(":first").is("##{item.cid}") + test.equal binding.container.find("h1 > span").text(), "fn value" + test.done() - # test.done() + "updates fn content when value changes": (test) -> + model = BoundModel.new field: "value" + [mocks, binding] = mock_binding AS.Binding.Field, + model: model + fn: -> + @h1 -> @span model.field.get() - # "removes dom elements when item removed from collection": (test) -> - # item = @items.at(0) - # @items.remove item - # test.ok @binding.container.find("##{item.cid}")[0] is undefined - # test.done() + test.equal binding.container.find("h1 > span").text(), "value" + binding.model.field.set("changed value") + test.equal binding.container.find("h1 > span").text(), "changed value" + test.done() - # HasManyWithFilter: - # setUp: (callback) -> - # model = new BoundModel - # items = model.items() - # content_fn = (thing) -> @div id: thing.cid + Input: + "sets input value on initialization": (test) -> + [mocks, binding] = mock_binding(AS.Binding.Input) + test.equal binding.container.find("input").val(), "value" + test.done() - # [mocks, binding] = mock_binding( - # AS.Binding.HasMany, - # field: 'items', - # model: model, - # fn: content_fn - # options: filter: (field: [true, "43"]) - # ) + "updates input value when model changes": (test) -> + [mocks, binding] = mock_binding(AS.Binding.Input) + binding.model.field.set("changed value") + test.equal binding.container.find("input").val(), "changed value" + test.done() - # @items = items - # @binding = binding - # callback() + "updates model value when input changes": (test) -> + [mocks, binding] = mock_binding(AS.Binding.Input) + binding.model.field.set("changed value") + binding.container.find("input").val("user value").trigger("change") + test.equal binding.model.field.get(), "user value" + test.done() - # "filters items in the collection": (test) -> - # one = @items.add field: true - # two = @items.add field: false - # three = @items.add field: "43" + "inherits from Field": (test) -> + test.equal AS.Binding.Input.__super__.constructor, AS.Binding.Field + test.done() - # test.equal @binding.container.find("##{one.cid}")[0].id, one.cid - # test.equal @binding.container.find("##{two.cid}")[0], undefined - # test.equal @binding.container.find("##{three.cid}")[0].id, three.cid - # test.done() + Select: + "must provide options option": (test) -> + test.throws (-> mock_binding(AS.Binding.Select)), AS.Binding.MissingOption + test.done() - # "moves items into place in the collection when their values change": (test) -> - # one = @items.add field: true - # two = @items.add field: false - # three = @items.add field: true + "uses provided Array for select options": (test) -> + options = [1..3] + [mocks, binding] = mock_binding(AS.Binding.Select, options: options: options) + + test.equal binding.container.find("option").length, 3 + test.equal binding.container.find("select").text(), "123" + + test.done() + + "uses provided Object for select options": (test) -> + options = + "one": 1 + "two": 2 + "three": 3 + [mocks, binding] = mock_binding(AS.Binding.Select, options: options: options) + + test.equal binding.container.find("option").length, 3 + + for key, value of options + test.equal $(binding.container.find("option[value='#{value}']")).text(), key + + test.done() + + "sets select value on initialization": (test) -> + model = BoundModel.new field: "value" + options = ["notvalue", "value"] + [mocks, binding] = mock_binding(AS.Binding.Select, options: (options: options), model: model) + + test.equal binding.container.find("select").val(), "value" + + test.done() + + "sets value of dom when model value changes": (test) -> + model = BoundModel.new field: "value" + options = ["notvalue", "value"] + [mocks, binding] = mock_binding(AS.Binding.Select, options: (options: options), model: model) + + model.field.set("notvalue") + + test.equal binding.container.find("select").val()[0], "notvalue" + + test.done() + + "sets value on object when dom changes": (test) -> + model = BoundModel.new field: "value" + options = ["notvalue", "value"] + [mocks, binding] = mock_binding(AS.Binding.Select, options: (options: options), model: model) + + binding.container.find("select").val("notvalue") + binding.container.find("select").trigger("change") + + test.equal model.field.get(), "notvalue" + + test.done() + + CheckBox: + "the checkbox is checked if the starting value is true": (test) -> + model = BoundModel.new maybe: true + [mocks, binding] = mock_binding(AS.Binding.CheckBox, model: model, field: model.maybe) + test.ok binding.container.find("input").is(":checked") + test.done() + + "the checkbox is unchecked if the starting value is false": (test) -> + model = BoundModel.new maybe: false + [mocks, binding] = mock_binding(AS.Binding.CheckBox, model: model, field: model.maybe) + test.ok binding.container.find("input").is(":not(:checked)") + test.done() + + "checking the box sets the field to true": (test) -> + model = BoundModel.new maybe: false + [mocks, binding] = mock_binding(AS.Binding.CheckBox, model: model, field: model.maybe) + binding.container.find("input").click().trigger("change") + test.equal model.maybe.get(), true + test.done() + + "unchecking the box sets the field to false": (test) -> + model = BoundModel.new maybe: true + [mocks, binding] = mock_binding(AS.Binding.CheckBox, model: model, field: model.maybe) + binding.container.find("input").click().trigger("change") + test.equal model.maybe.get(), false + test.done() + + + EditLine: + setUp: (callback) -> + @rangy_api = + getSelection: -> { + rangeCount: 0 + createRange: -> { + startOffset: 0 + endOffset: 0 + } + } + createRange: -> { + startOffset: 0 + endOffset: 0 + } + + @real_open = AS.open_shared_object + AS.open_shared_object = (id, did_open) -> + did_open makeDoc(id) + + @remote = (operation, model = @model) -> + if model.share.emit + model.share.emit "remoteop", operation + else + model.share.doc.emit "remoteop", operation + + AS.Binding.EditLine::rangy = @rangy_api + callback() + + tearDown: (callback) -> + AS.open_shared_object = @real_open + callback() + + # TODO: implement sharing things + # "contenteditable area responds to all edit events": (test) -> + # test.expect 8 + # EditLine = AS.Binding.EditLine.extend ({def}) -> + # def generate_operation: -> test.ok true + # [mocks, binding] = mock_binding(EditLine) + # mocks.binding.expects("applyChange").exactly(0) + # for event in ['textInput', 'keydown', 'keyup', 'select', 'cut', 'paste', 'click', 'focus'] + # binding.content.trigger(event) + # mocks.verify() + # test.done() + + # "applies change if content has changed on edit event": (test) -> + # model = SharedBoundModel.open() + # model.field("value") + # model.when_indexed => + # [mocks, binding] = mock_binding(AS.Binding.EditLine, model: model) + # binding.content[0].innerHTML += " change" + # binding.generate_operation() + # test.deepEqual model.share.get(), model.attributes_for_sharing() + # test.done() + + # "applies change from remote operation": (test) -> + # model = SharedBoundModel.open() + # model.field("value") + # model.when_indexed => + # [mocks, binding] = mock_binding(AS.Binding.EditLine, model: model) + # @remote model.share.at("field").insert(0, "remote "), model + # test.equal binding.content[0].innerHTML, "remote value" + # test.equal model.share.at("field").get(), "remote value" + # test.equal model.field(), "remote value" + # test.done() + + Many: + setUp: (callback) -> + model = BoundModel.new() + items = model.items + items.add() + items.add() + items.add() + + + content_fn = (thing) -> @div id: thing.cid + + [mocks, binding] = mock_binding(AS.Binding.Many, field: model.items, model: model, fn: content_fn) + + @items = items + @binding = binding + callback() + + "creates initial collection dom": (test) -> + test.expect 3 + @items.each (item) => + test.ok @binding.container.find("##{item.cid}").is("div") + + test.done() + + "adds additional dom elements when items added to collection": (test) -> + test.expect 1 + item = @items.add() + test.ok @binding.container.find("##{item.cid}").is("div") + + test.done() + + "adds new dom elements at correct index": (test) -> + test.expect 1 + item = @items.add({}, at: 0) + + test.ok @binding.container.children(":first").is("##{item.cid}") + + test.done() + + "removes dom elements when item removed from collection": (test) -> + item = @items.at(0) + @items.remove item + test.ok @binding.container.find("##{item.cid}")[0] is undefined + test.done() + + HasManyWithFilter: + setUp: (callback) -> + model = BoundModel.new() + items = model.items + + content_fn = (thing) -> @div id: thing.cid + + [mocks, binding] = mock_binding(AS.Binding.Many, + field: items, + model: model, + fn: content_fn + options: filter: (field: ["true", "43"]) + ) + + @items = items + @binding = binding + callback() + + "filters items in the collection": (test) -> + one = @items.add field: "true" + two = @items.add field: "false" + three = @items.add field: "43" + + test.equal @binding.container.find("##{one.cid}")[0].id, one.cid + test.equal @binding.container.find("##{two.cid}")[0], undefined + test.equal @binding.container.find("##{three.cid}")[0].id, three.cid + test.done() + + "moves items into place in the collection when their values change": (test) -> + one = @items.add field: true + two = @items.add field: false + three = @items.add field: true - # two.field("43") + two.field.set("43") - # test.equal @binding.container.children()[1].id, two.cid + test.equal @binding.container.children()[1].id, two.cid - # test.done() + test.done() - # "removes items when their values change": (test) -> - # one = @items.add field: true + "removes items when their values change": (test) -> + one = @items.add field: true - # one.field(false) + one.field.set(false) - # test.equal @binding.container.children().length, 0 - # test.done() + test.equal @binding.container.children().length, 0 + test.done() # Collection: # "field_value is the model": (test) -> # [mocks, binding] = mock_binding(AS.Binding.Collection, model: new AS.Collection) - # test.equal binding.path_value(), binding.model + # test.equal binding.pathValue(), binding.model # test.done() # EmbedsMany: diff --git a/test/client/binding_group.coffee b/test/client/binding_group.coffee index da3911d..34b2d9e 100644 --- a/test/client/binding_group.coffee +++ b/test/client/binding_group.coffee @@ -1,22 +1,22 @@ {AS, $, _, sinon} = require require("path").resolve("./test/client_helper") exports.BindingGroup = "has a unique namespace": (test) -> - bg1 = new AS.BindingGroup - bg2 = new AS.BindingGroup + bg1 = AS.BindingGroup.new() + bg2 = AS.BindingGroup.new() test.notEqual bg1.namespace, bg2.namespace - test.equal bg1.namespace[0], "." + test.equal bg1.namespace[0], "b" test.done() "binds to jquery objects": (test) -> - bg = new AS.BindingGroup + bg = AS.BindingGroup.new() object = jquery: true, bind: -> mock = sinon.mock(object) handler = -> - mock.expects("bind").withExactArgs("event#{bg.namespace}", handler) + mock.expects("bind").withExactArgs("event.#{bg.namespace}", handler) bg.binds object, "event", handler mock.verify() @@ -24,19 +24,23 @@ exports.BindingGroup = test.done() "binds to AS.Event event model": (test) -> - bg = new AS.BindingGroup + bg = AS.BindingGroup.new() object = bind: -> mock = sinon.mock(object) handler = -> - mock.expects("bind").withExactArgs({path: ["event"], namespace: bg.namespace}, handler, object) + mock.expects("bind").withExactArgs + event: "event" + namespace: bg.namespace + handler: handler + context: object bg.binds object, "event", handler, object mock.verify() test.done() "unbinds bound objects": (test) -> - bg = new AS.BindingGroup + bg = AS.BindingGroup.new() object = bind: -> @@ -53,8 +57,8 @@ exports.BindingGroup = "unbinds bound objects in nested binding groups": (test) -> - parent = new AS.BindingGroup() - child = parent.add_child() + parent = AS.BindingGroup.new() + child = parent.addChild() object = bind: -> diff --git a/test/client/dom.coffee b/test/client/dom.coffee index 0ba0f29..acaff2f 100644 --- a/test/client/dom.coffee +++ b/test/client/dom.coffee @@ -1,7 +1,7 @@ {AS, $, _, sinon} = require require("path").resolve("./test/client_helper") exports.DOM = "creates document fragments": (test) -> - html = (new AS.DOM).html -> + html = AS.DOM.new().html -> @head -> @title "This is the Title" @body -> @@ -18,11 +18,11 @@ exports.DOM = test.done() "appends raw (scary html) content": (test) -> - raw = (new AS.DOM).raw("") + raw = AS.DOM.new().raw("") test.ok $(raw).find("html").is("html") test.done() "appends escaped (non-scary html) content": (test)-> - raw = (new AS.DOM).span -> @text("") + raw = AS.DOM.new().span -> @text("") test.equal $(raw).find("html")[0], undefined test.done() diff --git a/test/client/models/targets.coffee b/test/client/models/targets.coffee index 1b6e8a1..faf5a3d 100644 --- a/test/client/models/targets.coffee +++ b/test/client/models/targets.coffee @@ -1,7 +1,7 @@ -{AS, $, _, sinon} = require require("path").resolve("./test/client_helper") +{AS, NS, $, _, sinon} = require require("path").resolve("./test/client_helper") -class SomeTargets extends AS.Models.Targets - selector: "target" +NS.SomeTargets = AS.Models.Targets.extend ({def}) -> + def selector: "target" class ClientRect top: 0 @@ -39,7 +39,7 @@ exports.Targets = callback() "gathers targets": (test) -> - targets = (new SomeTargets).targets + targets = NS.SomeTargets.new().targets test.equal targets.length, 3 test.equal targets[1].el[0], @t2 test.equal targets[1].rect.top, 50, 'top' @@ -51,14 +51,14 @@ exports.Targets = test.done() "dropend triggers dropend event": (test) -> - targets = new SomeTargets + targets = NS.SomeTargets.new() test.expect 1 targets.bind "dropend", -> test.ok true targets.dropend() test.done() "dropstart triggers dropstart event if current hit has a rect": (test) -> - targets = new SomeTargets + targets = NS.SomeTargets.new() hit = rect: true targets.current_hit = hit test.expect 1 @@ -67,14 +67,14 @@ exports.Targets = test.done() "dropstart is a noop if current hit lacks a rect": (test) -> - targets = new SomeTargets + targets = NS.SomeTargets.new() test.expect 0 targets.bind "dropstart", -> test.ok true targets.dropstart() test.done() "dragend calls drop and triggers drop if current hit has a rect": (test) -> - targets = new SomeTargets + targets = NS.SomeTargets.new() hit = rect: true data = new Object targets.current_hit = hit @@ -85,7 +85,7 @@ exports.Targets = test.done() "dragend is a noop if current hit lacks a rect": (test) -> - targets = new SomeTargets + targets = NS.SomeTargets.new() data = new Object test.expect 0 targets.bind "drop", (thehit) -> test.equal hit, thehit @@ -95,14 +95,14 @@ exports.Targets = "transition_hit()": "noop if hit has no rect": (test) -> - targets = new SomeTargets + targets = NS.SomeTargets.new() targets.dropend = -> test.ok true test.expect 0 targets.transition_hit {} test.done() "noop if currenth hit equals hit": (test) -> - targets = new SomeTargets + targets = NS.SomeTargets.new() targets.current_hit = equals: -> true targets.dropend = -> test.ok true test.expect 0 @@ -110,7 +110,7 @@ exports.Targets = test.done() "transitions if current hit does not equal hit": (test) -> - targets = new SomeTargets + targets = NS.SomeTargets.new() targets.current_hit = equals: -> false hit = rect: true test.expect 2 @@ -130,7 +130,7 @@ target_event = (x, y) -> exports.Targets.Edge = setUp: (callback) -> - @targets = new AS.Models.Targets.Edge + @targets = AS.Models.Targets.Edge.new() @el = {} @rect = new ClientRect width: 100, height: 50 @targets.targets = [ @@ -194,7 +194,7 @@ exports.Targets.Edge = exports.Targets.Thirds = setUp: (callback) -> - @targets = new AS.Models.Targets.Thirds + @targets = AS.Models.Targets.Thirds.new() @el = {} @rect = new ClientRect width: 100, height: 50 @targets.targets = [ diff --git a/test/client/view.coffee b/test/client/view.coffee index 499a78a..cfcef33 100644 --- a/test/client/view.coffee +++ b/test/client/view.coffee @@ -1,35 +1,36 @@ -{AS, $, _, sinon} = require require("path").resolve("./test/client_helper") +{AS, $, _, sinon, NS} = require require("path").resolve("./test/client_helper") exports.View = "generates klass strings": (test) -> - test.equal new AS.View().klass_string(), "", "basic klass_string is ASView" + test.equal AS.View.new().klassString(), "AlphaSimprini View", "basic klassString is ASView" - class SomeView extends AS.View + NS.SomeView = AS.View.extend() - test.equal new SomeView().klass_string(), "SomeView", "subclasses include parent class string" + test.equal NS.SomeView.new().klassString(), "NS SomeView", "subclasses include parent class string" test.done() "builds an element": (test) -> - test.ok (new AS.View).el.is("div") - class ListView extends AS.View - tag_name: "ol" - test.ok (new ListView).el.is("ol") + test.ok AS.View.new().el.is("div") + NS.ListView = AS.View.extend ({def}) -> + def tagName: "ol" + + test.ok NS.ListView.new().el.is("ol.NS.ListView") test.done() "sets options from constructor": (test) -> - test.equal (new AS.View this: "that").this, "that" + test.equal AS.View.new(this: "that").this, "that" test.done() "turns Model options into ASViewModels": (test) -> - test.ok (new AS.View it: new AS.Model).it instanceof AS.ViewModel + test.ok AS.View.new(it: new AS.Model).it instanceof AS.ViewModel test.done() "has a root binding group": (test) -> - test.ok (new AS.View).binding_group instanceof AS.BindingGroup + test.ok AS.View.new().bindingGroup instanceof AS.BindingGroup test.done() "pluralizes text": (test) -> - view = new AS.View + view = AS.View.new() test.equal view.pluralize("cat", 4), "cats" test.equal view.pluralize("person", 0), "people" test.equal view.pluralize("duck", 1), "duck" diff --git a/test/client/view_events.coffee b/test/client/view_events.coffee index e879b71..f80248f 100644 --- a/test/client/view_events.coffee +++ b/test/client/view_events.coffee @@ -1,112 +1,106 @@ -{AS, $, _, sinon} = require require("path").resolve("./test/client_helper") +{AS, $, _, sinon, coreSetUp} = require require("path").resolve("./test/client_helper") +exports.setUp = coreSetUp exports.ViewEvents = "delegates events": (test) -> - test.expect 4 + test.expect 3 - class BoundView extends AS.View - events: + BoundView = AS.View.extend ({def}) -> + def events: "click": "click_handler" "click button": "button_handler" "event @member": "member_handler" - "pass{pass:true} @member": "guard_pass_handler" - "fail{pass:false} @member": "guard_fail_handler" - constructor: -> - @member = new AS.Model - super - - initialize: -> + def initialize: -> + @member = AS.Model.new() + @_super.apply(this, arguments) @_button = @$ @button() - click_handler: -> test.ok true - member_handler: -> test.ok true - button_handler: -> test.ok true - guard_fail_handler: -> test.ok true - guard_pass_handler: -> test.ok true + def click_handler: -> test.ok true + def member_handler: -> test.ok true + def button_handler: -> test.ok true + def guard_fail_handler: -> test.ok true + def guard_pass_handler: -> test.ok true - view = new BoundView + view = BoundView.new() - view.el.trigger("click") view.member.trigger("event") view._button.trigger("click") - view.member.trigger("pass", pass: true) - view.member.trigger("fail", pass: true) test.done() - "registers state event": (test) -> - class StatelyView extends AS.View - left_events: - "event": "event_handler" + # rethinkign stately and other types of event guarding + # "registers state event": (test) -> + # StatelyView = AS.View.extend ({def}) -> + # def left_events: + # "event": "event_handler" - right_events: - "other_event": "other_event_handler" + # def right_events: + # "other_event": "other_event_handler" - event_handler: -> - other_event_handler: -> + # def event_handler: -> + # def other_event_handler: -> - view = new StatelyView + # view = StatelyView.new() - test.ok view.state_events.left instanceof AS.ViewEvents - test.ok view.state_events.right instanceof AS.ViewEvents + # test.ok view.state_events.left instanceof AS.ViewEvents + # test.ok view.state_events.right instanceof AS.ViewEvents - test.done() + # test.done() - "bind and unbinds state events on state changes": (test) -> - test.expect 5 + # "bind and unbinds state events on state changes": (test) -> + # test.expect 5 - class StatelyView extends AS.View + # StatelyView = AS.View.extend ({def}) -> - left_events: - "click": "event_handler" + # def left_events: + # "click": "event_handler" - right_events: - "click": "other_event_handler" + # def right_events: + # "click": "other_event_handler" - event_handler: -> test.equal "left", @state - other_event_handler: -> test.ok "right", @state + # def event_handler: -> test.equal "left", @state + # def other_event_handler: -> test.ok "right", @state - view = new StatelyView + # view = StatelyView.new() - view.bind "exitstate:left", -> test.ok true - view.bind "enterstate:left", -> test.ok true - view.bind "exitstate:right", -> test.ok true - view.bind "enterstate:right", -> test.ok true + # view.bind "exitstate:left", -> test.ok true + # view.bind "enterstate:left", -> test.ok true + # view.bind "exitstate:right", -> test.ok true + # view.bind "enterstate:right", -> test.ok true - view.transition_state from: undefined, to: "left" - view.el.trigger "click" + # view.transition_state from: undefined, to: "left" + # view.el.trigger "click" - view.transition_state from: "left", to: "right" - view.el.trigger "click" + # view.transition_state from: "left", to: "right" + # view.el.trigger "click" - test.done() + # test.done() - "bind state transition events": (test) -> - class StatelyView extends AS.View + # "bind state transition events": (test) -> + # StatelyView = AS.View.extend ({def}) -> + # def left_events: + # "click": "event_handler" + # "crank @": transition: + # from: "left", to: "right" - left_events: - "click": "event_handler" - "crank @": transition: - from: "left", to: "right" + # def right_events: + # "click": "other_event_handler" + # "crank @": transition: + # from: "right", to: "left" - right_events: - "click": "other_event_handler" - "crank @": transition: - from: "right", to: "left" + # def event_handler: -> test.equal "left", @state + # def other_event_handler: -> test.ok "right", @state - event_handler: -> test.equal "left", @state - other_event_handler: -> test.ok "right", @state + # def initialize: -> + # @_super() + # @default_state("left") - initialize: -> - super - @default_state("left") + # view = StatelyView.new() + # view.trigger 'crank' + # test.equal view.state, "right" + # view.trigger 'crank' + # test.equal view.state, "left" - view = new StatelyView - view.trigger 'crank' - test.equal view.state, "right" - view.trigger 'crank' - test.equal view.state, "left" - - test.done() + # test.done() diff --git a/test/client/view_model.coffee b/test/client/view_model.coffee index 74dac6c..400a1cf 100644 --- a/test/client/view_model.coffee +++ b/test/client/view_model.coffee @@ -1,23 +1,27 @@ -{AS, $, _, sinon} = require require("path").resolve("./test/client_helper") +{AS, NS, $, _, sinon, coreSetUp} = require require("path").resolve("./test/client_helper") -class Viewed extends AS.Model +exports.setUp = coreSetUp + +NS.Viewed = AS.Model.extend ({def}) -> @field "field" - @embeds_many "embeds" - @embeds_one "embed" - @has_many "relations" - @has_one "relation" - @belongs_to "owner" + @hasMany "many" + @hasOne "one" + # @embeds_many "embeds" + # @embeds_one "embed" + # @has_many "relations" + # @has_one "relation" + # @belongs_to "owner" - @virtual_properties "field" - one: -> - two: -> + # @virtual_properties "field" + # one: -> + # two: -> - other: -> + def other: -> exports.ViewModel = "builds viewmodels": (test) -> - view = new AS.View - model = new AS.Model + view = AS.View.new() + model = AS.Model.new() vm = AS.ViewModel.build view, model test.equal vm.view, view @@ -26,34 +30,19 @@ exports.ViewModel = test.done() "caches constructors": (test) -> - vm1 = AS.ViewModel.build new AS.View, new AS.Model - vm2 = AS.ViewModel.build new AS.View, new AS.Model + vm1 = AS.ViewModel.build AS.View.new(), AS.Model.new() + vm2 = AS.ViewModel.build AS.View.new(), AS.Model.new() test.equal vm1.constructor, vm2.constructor test.done() "configures constructor": (test) -> - vm = AS.ViewModel.build new AS.View, new Viewed + vm = AS.ViewModel.build AS.View.new(), NS.Viewed.new() bindables = vm.constructor.bindables test.equal bindables.field, AS.Binding.Field - test.equal bindables.embeds, AS.Binding.EmbedsMany - test.equal bindables.embed, AS.Binding.EmbedsOne - test.equal bindables.relations, AS.Binding.HasMany - test.equal bindables.relation, AS.Binding.HasOne - test.equal bindables.owner, AS.Binding.BelongsTo - test.equal bindables.one, AS.Binding.Field - test.equal bindables.one, AS.Binding.Field - - test.done() - - "delegates all model methods to model": (test) -> - vm = AS.ViewModel.build new AS.View, new Viewed - - delegate = new RegExp - - for method in "field embeds embed relations relation owner other".split(" ") - test.ok vm[method].toString().indexOf("return this.model[method].apply(this.model, arguments);") + test.equal bindables.many, AS.Binding.Many + test.equal bindables.one, AS.Binding.One test.done() diff --git a/test/client/views/region.coffee b/test/client/views/region.coffee index 6585130..c9bee4b 100644 --- a/test/client/views/region.coffee +++ b/test/client/views/region.coffee @@ -1,10 +1,10 @@ {AS, $, _, sinon} = require require("path").resolve("./test/client_helper") exports["Views Regions"] = "regions for cardinal directions/center extend Region": (test) -> - test.ok new AS.Views.Region instanceof AS.View - test.ok new AS.Views.North instanceof AS.Views.Region - test.ok new AS.Views.East instanceof AS.Views.Region - test.ok new AS.Views.South instanceof AS.Views.Region - test.ok new AS.Views.West instanceof AS.Views.Region - test.ok new AS.Views.Center instanceof AS.Views.Region + test.ok AS.Views.Region.new() instanceof AS.View + test.ok AS.Views.North.new() instanceof AS.Views.Region + test.ok AS.Views.East.new() instanceof AS.Views.Region + test.ok AS.Views.South.new() instanceof AS.Views.Region + test.ok AS.Views.West.new() instanceof AS.Views.Region + test.ok AS.Views.Center.new() instanceof AS.Views.Region test.done() diff --git a/test/core.coffee b/test/core.coffee index b271c81..30c926a 100644 --- a/test/core.coffee +++ b/test/core.coffee @@ -36,7 +36,7 @@ exports.utilities = test.done() humanSize: (test) -> - sz = AS.human_size + sz = AS.humanSize test.equal sz(100), "100.0 B" diff --git a/test/core/callbacks.coffee b/test/core/callbacks.coffee index 46d8b8d..8f5a97f 100644 --- a/test/core/callbacks.coffee +++ b/test/core/callbacks.coffee @@ -1,27 +1,8 @@ {AS, _, sinon, coreSetUp} = require require("path").resolve("./test/helper") exports.setUp = coreSetUp -exports.InstanceMethods = - discoversInstanceMethods: (test) -> - class HasMethods - a: 1 - b: 2 - - test.deepEqual AS.instance_methods(HasMethods), ["a", "b"] - test.done() - - traversesClasses: (test) -> - class A - a: 1 - - class B extends A - b: 2 - - test.deepEqual AS.instance_methods(B), ["b", "a"] - test.done() - -class WithCallbacks - AS.Callbacks.extends(this) +WithCallbacks = AS.Object.extend ({include}) -> + include AS.Callbacks @define_callbacks before: "this that".split(" ") @@ -40,7 +21,7 @@ exports.Callbacks = it.before_this cb it.before_that cb - one = new WithCallbacks + one = WithCallbacks.new() one.run_callbacks "before_this" one.run_callbacks "before_that" diff --git a/test/core/collection.coffee b/test/core/collection.coffee index fd915e2..413c24d 100644 --- a/test/core/collection.coffee +++ b/test/core/collection.coffee @@ -1,21 +1,21 @@ {AS, _, sinon, coreSetUp} = require require("path").resolve("./test/helper") exports.setUp = coreSetUp -C = AS.Namespace.create("Collections") +C = AS.Namespace.new("Collections") exports.Collection = "inserts item of specified type": (test) -> C.Thing = AS.Model.extend() - C.ThingCollection = AS.Collection.extend model: -> C.Thing + C.ThingCollection = AS.Collection.extend -> @def model: -> C.Thing - things = C.ThingCollection.create() + things = C.ThingCollection.new() things.add() test.ok things.first().value() instanceof C.Thing test.done() "inserts item at a specified index": (test)-> - things = AS.Collection.create() + things = AS.Collection.new() things.add() things.add() @@ -28,7 +28,7 @@ exports.Collection = test.done() "remove item from collection": (test) -> - things = AS.Collection.create() + things = AS.Collection.new() thing = things.add() things.remove(thing) test.equal things.length, 0 @@ -37,14 +37,14 @@ exports.Collection = Events: "add event": (test) -> test.expect 1 - collection = AS.Collection.create() + collection = AS.Collection.new() collection.bind "add", -> test.ok true collection.add() test.done() "remove event": (test) -> test.expect 1 - collection = AS.Collection.create() + collection = AS.Collection.new() thing = collection.add() collection.bind "remove", -> test.ok true collection.remove(thing) @@ -52,7 +52,7 @@ exports.Collection = "model change events bubble through collection": (test) -> test.expect 2 - collection = AS.Collection.create() + collection = AS.Collection.new() thing = collection.add() collection.bind "all", -> test.ok true collection.bind "modelevent", -> test.ok true @@ -63,8 +63,8 @@ exports.Collection = "add/remove events capture on collection": (test) -> test.expect 2 - thing = AS.Model.create() - collection = AS.Collection.create() + thing = AS.Model.new() + collection = AS.Collection.new() thing.bind "add", -> test.ok true thing.bind "remove", -> test.ok true diff --git a/test/core/instance_methods.coffee b/test/core/instance_methods.coffee index e69de29..65a4a6b 100644 --- a/test/core/instance_methods.coffee +++ b/test/core/instance_methods.coffee @@ -0,0 +1,21 @@ +{AS, _, sinon, coreSetUp} = require require("path").resolve("./test/helper") +exports.setUp = coreSetUp + +exports.InstanceMethods = + discoversInstanceMethods: (test) -> + HasMethods = AS.Object.extend ({def}) -> + def a: 1 + def b: 2 + + test.deepEqual AS.instanceMethods(HasMethods), ["a", "b"] + test.done() + + traversesClasses: (test) -> + A = AS.Object.extend ({def}) -> + def a: 1 + + B = A.extend ({def}) -> + def b: 2 + + test.deepEqual AS.instanceMethods(B), ["b", "a"] + test.done() diff --git a/test/core/model.coffee b/test/core/model.coffee index 4c8edbc..52ba32e 100644 --- a/test/core/model.coffee +++ b/test/core/model.coffee @@ -8,7 +8,7 @@ exports.Model = test.done() "puts new models in that place": (test) -> - model = AS.Model.create() + model = AS.Model.new() test.equal AS.All.byCid[model.cid], model, "puts model in AS.All.byCid" test.equal AS.All.byId[model.id], model, "puts model in AS.All.byId" test.done() diff --git a/test/core/model/share.coffee b/test/core/model/share.coffee index b031f11..3e53c56 100644 --- a/test/core/model/share.coffee +++ b/test/core/model/share.coffee @@ -1,293 +1,293 @@ -{AS, _, sinon, coreSetUp, makeDoc} = require require("path").resolve("./test/helper") -exports.setUp = coreSetUp - -class Shared extends AS.Model - AS.Model.Share.extends(this, "Shared") - @field "field" - @embeds_many "embeds", model: -> SimpleShare - @embeds_one "embedded", model: -> SimpleShare - @has_many "relations", model: -> SimpleShare - @has_one "relation" - @belongs_to "owner" - -class SimpleShare extends AS.Model - AS.Model.Share.extends(this, "SimpleShare") - @field "field" - @embeds_many "embeds", model: -> SimplerShare - @embeds_one "embedded", model: -> SimplerShare - @has_many "relations", model: -> SimplerShare - @has_one "relation" - @belongs_to "owner" - -class SimplerShare extends AS.Model - AS.Model.Share.extends(this, "SimplerShare") - @field "field" - -class IndexShare extends AS.Model - AS.Model.Share.extends(this, "IndexShare") - @index "docs" - @belongs_to "owner" - -exports["Model.Share"] = - setUp: (callback) -> - @real_open = AS.open_shared_object - @real_module = AS.module - AS.module = (name) -> - return { - "SimpleShare": SimpleShare, - "SimplerShare": SimplerShare, - "Shared": Shared, - "IndexShare": IndexShare - }[name] - AS.open_shared_object = (id, did_open) -> - did_open makeDoc(id) - - @remote = (operation, model = @model) -> - if model.share.emit - model.share.emit "remoteop", operation - else - model.share.doc.emit "remoteop", operation +# {AS, _, sinon, coreSetUp, makeDoc} = require require("path").resolve("./test/helper") +# exports.setUp = coreSetUp + +# class Shared extends AS.Model +# AS.Model.Share.extends(this, "Shared") +# @field "field" +# @embeds_many "embeds", model: -> SimpleShare +# @embeds_one "embedded", model: -> SimpleShare +# @has_many "relations", model: -> SimpleShare +# @has_one "relation" +# @belongs_to "owner" + +# class SimpleShare extends AS.Model +# AS.Model.Share.extends(this, "SimpleShare") +# @field "field" +# @embeds_many "embeds", model: -> SimplerShare +# @embeds_one "embedded", model: -> SimplerShare +# @has_many "relations", model: -> SimplerShare +# @has_one "relation" +# @belongs_to "owner" + +# class SimplerShare extends AS.Model +# AS.Model.Share.extends(this, "SimplerShare") +# @field "field" + +# class IndexShare extends AS.Model +# AS.Model.Share.extends(this, "IndexShare") +# @index "docs" +# @belongs_to "owner" + +# exports["Model.Share"] = +# setUp: (callback) -> +# @real_open = AS.open_shared_object +# @real_module = AS.module +# AS.module = (name) -> +# return { +# "SimpleShare": SimpleShare, +# "SimplerShare": SimplerShare, +# "Shared": Shared, +# "IndexShare": IndexShare +# }[name] +# AS.open_shared_object = (id, did_open) -> +# did_open makeDoc(id) + +# @remote = (operation, model = @model) -> +# if model.share.emit +# model.share.emit "remoteop", operation +# else +# model.share.doc.emit "remoteop", operation - @model_bindings = (model, test) -> - model.field("value") - test.equal model.share.at("field").get(), "value", "field model->share" +# @model_bindings = (model, test) -> +# model.field("value") +# test.equal model.share.at("field").get(), "value", "field model->share" - added_relation = SimpleShare.open() - model.relations().add added_relation - expected_has_many_value = {id: added_relation.id, _type: added_relation.constructor._type} - test.deepEqual model.share.at("relations", 0).get(), expected_has_many_value, "has_many model->share" +# added_relation = SimpleShare.open() +# model.relations().add added_relation +# expected_has_many_value = {id: added_relation.id, _type: added_relation.constructor._type} +# test.deepEqual model.share.at("relations", 0).get(), expected_has_many_value, "has_many model->share" - model.embeds().add added_embed = new SimpleShare - test.deepEqual model.share.at("embeds", 0).get(), added_embed.attributes_for_sharing(), "embeds_many model->share" +# model.embeds().add added_embed = new SimpleShare +# test.deepEqual model.share.at("embeds", 0).get(), added_embed.attributes_for_sharing(), "embeds_many model->share" - model.embeds().remove added_embed - test.deepEqual model.share.at("embeds").get(), [], "embeds_many remove->share" +# model.embeds().remove added_embed +# test.deepEqual model.share.at("embeds").get(), [], "embeds_many remove->share" - model.embedded set_embedded = new SimpleShare - test.deepEqual model.share.at("embedded").get(), set_embedded.attributes_for_sharing(), "embeds_one model->share" +# model.embedded set_embedded = new SimpleShare +# test.deepEqual model.share.at("embedded").get(), set_embedded.attributes_for_sharing(), "embeds_one model->share" - model.owner set_owner = SimpleShare.open() - test.deepEqual model.share.at("owner").get(), set_owner.id, "belongs_to model->share" +# model.owner set_owner = SimpleShare.open() +# test.deepEqual model.share.at("owner").get(), set_owner.id, "belongs_to model->share" - share = model.share - # test share -> attribute +# share = model.share +# # test share -> attribute - @remote share.at("field").insert(0, "!"), model - test.equal model.field(), "!value", "field share->model" +# @remote share.at("field").insert(0, "!"), model +# test.equal model.field(), "!value", "field share->model" - @remote share.at("field").insert(0, "OBOY "), model - test.equal model.field(), "OBOY !value", "field share->model; insert" +# @remote share.at("field").insert(0, "OBOY "), model +# test.equal model.field(), "OBOY !value", "field share->model; insert" - remote_relation = SimpleShare.open() - @remote share.at("relations", model.relations().length).set(remote_relation.attributes_for_sharing()), model - test.deepEqual model.relations().last().value().attributes_for_sharing(), remote_relation.attributes_for_sharing(), "has_many share->model" +# remote_relation = SimpleShare.open() +# @remote share.at("relations", model.relations().length).set(remote_relation.attributes_for_sharing()), model +# test.deepEqual model.relations().last().value().attributes_for_sharing(), remote_relation.attributes_for_sharing(), "has_many share->model" - remote_embed = SimpleShare.open() - @remote share.at("embeds", model.relations().length).set(remote_embed.attributes_for_sharing()), model - test.deepEqual model.embeds().last().value().attributes_for_sharing(), remote_embed.attributes_for_sharing(), "embeds_many share->model" +# remote_embed = SimpleShare.open() +# @remote share.at("embeds", model.relations().length).set(remote_embed.attributes_for_sharing()), model +# test.deepEqual model.embeds().last().value().attributes_for_sharing(), remote_embed.attributes_for_sharing(), "embeds_many share->model" - remote_embedded = SimpleShare.open() - @remote share.at("embedded").set(remote_embedded.attributes_for_sharing()), model - test.deepEqual model.embedded().attributes_for_sharing(), remote_embedded.attributes_for_sharing(), "embeds_one share->model" +# remote_embedded = SimpleShare.open() +# @remote share.at("embedded").set(remote_embedded.attributes_for_sharing()), model +# test.deepEqual model.embedded().attributes_for_sharing(), remote_embedded.attributes_for_sharing(), "embeds_one share->model" - remote_owner = SimpleShare.open() - @remote share.at("owner").set(remote_owner.id), model - test.equal model.owner().id, remote_owner.id, "belongs_to share->model" - - (@model = Shared.open()).when_indexed callback +# remote_owner = SimpleShare.open() +# @remote share.at("owner").set(remote_owner.id), model +# test.equal model.owner().id, remote_owner.id, "belongs_to share->model" + +# (@model = Shared.open()).when_indexed callback - tearDown: (callback) -> - AS.open_shared_object = @real_open - AS.module = @real_module - callback() - - "Lifecycle State Machine": - "share models have a Lifecycle SM": (test) -> - test.ok @model.lifecycle instanceof AS.Models.Share.Lifecycle +# tearDown: (callback) -> +# AS.open_shared_object = @real_open +# AS.module = @real_module +# callback() + +# "Lifecycle State Machine": +# "share models have a Lifecycle SM": (test) -> +# test.ok @model.lifecycle instanceof AS.Models.Share.Lifecycle - "#open": +# "#open": - "#load": - "#embedded" +# "#load": +# "#embedded" - "is new if share is undefined": (test) -> - delete @model.share - test.ok @model.new() - test.done() +# "is new if share is undefined": (test) -> +# delete @model.share +# test.ok @model.new() +# test.done() - "is new if constructed with new": (test) -> - test.ok (new Shared id:"an id").new() - test.done() +# "is new if constructed with new": (test) -> +# test.ok (new Shared id:"an id").new() +# test.done() - "sets defaults when opening a new model": (test) -> - class DefaultShared extends AS.Model - AS.Model.Share.extends(this, "DefaultShared") - @field "defaulted", default: "value" +# "sets defaults when opening a new model": (test) -> +# class DefaultShared extends AS.Model +# AS.Model.Share.extends(this, "DefaultShared") +# @field "defaulted", default: "value" - model = DefaultShared.open("someid") - test.equal model.defaulted(), "value" +# model = DefaultShared.open("someid") +# test.equal model.defaulted(), "value" - test.done() +# test.done() - "overrides defaults when loading remotely": (test) -> - AS.open_shared_object = (id, did_open) -> - did_open makeDoc(id, defaulted: "REMOTE VALUE") - class DefaultShared extends AS.Model - AS.Model.Share.extends(this, "DefaultShared") - @field "defaulted", default: "value" +# "overrides defaults when loading remotely": (test) -> +# AS.open_shared_object = (id, did_open) -> +# did_open makeDoc(id, defaulted: "REMOTE VALUE") +# class DefaultShared extends AS.Model +# AS.Model.Share.extends(this, "DefaultShared") +# @field "defaulted", default: "value" - model = DefaultShared.open("some other id") - test.equal model.defaulted(), "REMOTE VALUE" +# model = DefaultShared.open("some other id") +# test.equal model.defaulted(), "REMOTE VALUE" - test.done() +# test.done() - "sets initial attributes when opening an object": (test) -> - test.deepEqual @model.share.get(), @model.attributes_for_sharing() - test.done() +# "sets initial attributes when opening an object": (test) -> +# test.deepEqual @model.share.get(), @model.attributes_for_sharing() +# test.done() - "updates shared object when model attributes change": (test) -> - @model.field("VALUE") - test.equal @model.share.at("field").get(), "VALUE" +# "updates shared object when model attributes change": (test) -> +# @model.field("VALUE") +# test.equal @model.share.at("field").get(), "VALUE" - test.done() +# test.done() - "adds/removes items to relations in share": (test) -> - @model_bindings(@model, test) - test.done() +# "adds/removes items to relations in share": (test) -> +# @model_bindings(@model, test) +# test.done() - "adds items to shared collection at specified index": (test) -> - @model.relations().add SimpleShare.open() - @model.embeds().add SimpleShare.open() +# "adds items to shared collection at specified index": (test) -> +# @model.relations().add SimpleShare.open() +# @model.embeds().add SimpleShare.open() - @model.relations().add first_relation = SimpleShare.open(), at: 0 - @model.embeds().add first_embed = SimpleShare.open(), at: 0 +# @model.relations().add first_relation = SimpleShare.open(), at: 0 +# @model.embeds().add first_embed = SimpleShare.open(), at: 0 - relation_attrs = - id: first_relation.id - _type: first_relation.constructor._type +# relation_attrs = +# id: first_relation.id +# _type: first_relation.constructor._type - test.deepEqual relation_attrs, @model.share.at("relations", 0).get() - test.deepEqual first_embed.attributes_for_sharing(), @model.share.at("embeds", 0).get() +# test.deepEqual relation_attrs, @model.share.at("relations", 0).get() +# test.deepEqual first_embed.attributes_for_sharing(), @model.share.at("embeds", 0).get() - test.done() +# test.done() - "updates fields when fields change on share": (test) -> - test.expect 2 - @model.bind "change:field", -> test.ok true - @remote @model.share.at("field").set("value") - test.equal @model.field(), "value" - test.done() +# "updates fields when fields change on share": (test) -> +# test.expect 2 +# @model.bind "change:field", -> test.ok true +# @remote @model.share.at("field").set("value") +# test.equal @model.field(), "value" +# test.done() - "updates fields in embeds_one models when change occurs on share": (test) -> - test.expect 5 +# "updates fields in embeds_one models when change occurs on share": (test) -> +# test.expect 5 - @model.embedded first = SimpleShare.open() - @model.embedded().bind "change:field", -> test.ok true - @remote @model.share.at("embedded", "field").set("value") - test.equal first.field(), "value" +# @model.embedded first = SimpleShare.open() +# @model.embedded().bind "change:field", -> test.ok true +# @remote @model.share.at("embedded", "field").set("value") +# test.equal first.field(), "value" - # make sure when we swap out embeds the only the newer one is changed - @model.embedded second = SimpleShare.open() - @model.embedded().bind "change:field", -> test.ok true - @remote @model.share.at("embedded", "field").set("value2") - test.notEqual first.field(), "value2" - test.equal second.field(), "value2" +# # make sure when we swap out embeds the only the newer one is changed +# @model.embedded second = SimpleShare.open() +# @model.embedded().bind "change:field", -> test.ok true +# @remote @model.share.at("embedded", "field").set("value2") +# test.notEqual first.field(), "value2" +# test.equal second.field(), "value2" - test.done() +# test.done() - "updates fields on embedded models created in this client": (test)-> - model = Shared.open() - attrs = SimpleShare.open().attributes_for_sharing() - attrs.id = "embeddedsharedid" - @remote model.share.at("embeds").insert(0, attrs), model +# "updates fields on embedded models created in this client": (test)-> +# model = Shared.open() +# attrs = SimpleShare.open().attributes_for_sharing() +# attrs.id = "embeddedsharedid" +# @remote model.share.at("embeds").insert(0, attrs), model - test.equal model.embeds().first().value().id, attrs.id +# test.equal model.embeds().first().value().id, attrs.id - embed = model.embeds().first().value() - embed.field("!") - test.equal embed.share.at("field").get(), "!" +# embed = model.embeds().first().value() +# embed.field("!") +# test.equal embed.share.at("field").get(), "!" - @remote embed.share.at("field").insert(0, "BOO"), embed +# @remote embed.share.at("field").insert(0, "BOO"), embed - test.equal embed.share.at("field").get(), "BOO!" - - test.equal embed.field(), "BOO!" - - test.done() +# test.equal embed.share.at("field").get(), "BOO!" + +# test.equal embed.field(), "BOO!" + +# test.done() - "updates fields on models that have been received over the wire": (test) -> - - attrs = SimpleShare.open().attributes_for_sharing() - attrs.id = "someid" - - @remote @model.share.at("embeds", 0).set attrs - @model_bindings @model.embeds().first().value(), test +# "updates fields on models that have been received over the wire": (test) -> + +# attrs = SimpleShare.open().attributes_for_sharing() +# attrs.id = "someid" + +# @remote @model.share.at("embeds", 0).set attrs +# @model_bindings @model.embeds().first().value(), test - test.done() - - "updates belongs_to in has_many models when change occurs on share": (test) -> - test.expect 2 - owner = SimpleShare.open() - @model.bind "change:owner", -> test.ok true - @remote @model.share.at("owner").set(owner.id) - test.equal @model.owner(), owner - - test.done() +# test.done() + +# "updates belongs_to in has_many models when change occurs on share": (test) -> +# test.expect 2 +# owner = SimpleShare.open() +# @model.bind "change:owner", -> test.ok true +# @remote @model.share.at("owner").set(owner.id) +# test.equal @model.owner(), owner + +# test.done() - "loads models when indexes update": (test) -> - (@model = IndexShare.open()).when_indexed => - (other = SimpleShare.open()).when_indexed => - AS.open_shared_object = (id, did_open) -> did_open other.share - @model.bind "indexload", (loaded) => - loaded.when_indexed -> - test.done() - @remote @model.share.at("index:docs", other.id).set("SimpleShare") - - "loads models in indexes when opened": (test) -> - indexed = new SimpleShare - index = {} - index[indexed.id] = "SimpleShare" - delete AS.All.byId[indexed.id] - delete AS.All.byCid[indexed.cid] - snap = {} - snap["index:docs"] = index - snap["owner"] = indexed.id - doc = makeDoc(AS.uniq(), snap) - - @model = new IndexShare - - AS.open_shared_object = (id, did_open) -> - did_open makeDoc(id, indexed.attributes_for_sharing()) - - @model.did_open(doc) - @model.when_indexed => - test.notEqual AS.All.byId[indexed.id], undefined - test.equal @model.owner(), AS.All.byId[indexed.id] - test.done() - - "removes indexed models from the index when they are destroy()ed": (test) -> - indexed = new SimpleShare - index = {} - index[indexed.id] = "SimpleShare" - delete AS.All.byId[indexed.id] - delete AS.All.byCid[indexed.cid] - snap = {} - snap["index:docs"] = index - snap["owner"] = indexed.id - doc = makeDoc(AS.uniq(), snap) - - @model = new IndexShare - - AS.open_shared_object = (id, did_open) -> - did_open makeDoc(id, indexed.attributes_for_sharing()) - - test.expect 2 - @model.did_open(doc) - @model.when_indexed => - test.ok @model.index("docs").at(indexed.id).get() - indexed.destroy() - test.equal @model.index("docs").at(indexed.id).get(), undefined - test.done() +# "loads models when indexes update": (test) -> +# (@model = IndexShare.open()).when_indexed => +# (other = SimpleShare.open()).when_indexed => +# AS.open_shared_object = (id, did_open) -> did_open other.share +# @model.bind "indexload", (loaded) => +# loaded.when_indexed -> +# test.done() +# @remote @model.share.at("index:docs", other.id).set("SimpleShare") + +# "loads models in indexes when opened": (test) -> +# indexed = new SimpleShare +# index = {} +# index[indexed.id] = "SimpleShare" +# delete AS.All.byId[indexed.id] +# delete AS.All.byCid[indexed.cid] +# snap = {} +# snap["index:docs"] = index +# snap["owner"] = indexed.id +# doc = makeDoc(AS.uniq(), snap) + +# @model = new IndexShare + +# AS.open_shared_object = (id, did_open) -> +# did_open makeDoc(id, indexed.attributes_for_sharing()) + +# @model.did_open(doc) +# @model.when_indexed => +# test.notEqual AS.All.byId[indexed.id], undefined +# test.equal @model.owner(), AS.All.byId[indexed.id] +# test.done() + +# "removes indexed models from the index when they are destroy()ed": (test) -> +# indexed = new SimpleShare +# index = {} +# index[indexed.id] = "SimpleShare" +# delete AS.All.byId[indexed.id] +# delete AS.All.byCid[indexed.cid] +# snap = {} +# snap["index:docs"] = index +# snap["owner"] = indexed.id +# doc = makeDoc(AS.uniq(), snap) + +# @model = new IndexShare + +# AS.open_shared_object = (id, did_open) -> +# did_open makeDoc(id, indexed.attributes_for_sharing()) + +# test.expect 2 +# @model.did_open(doc) +# @model.when_indexed => +# test.ok @model.index("docs").at(indexed.id).get() +# indexed.destroy() +# test.equal @model.index("docs").at(indexed.id).get(), undefined +# test.done() diff --git a/test/core/properties/field.coffee b/test/core/properties/field.coffee index 7ba9bc9..d6ae9c9 100644 --- a/test/core/properties/field.coffee +++ b/test/core/properties/field.coffee @@ -10,17 +10,17 @@ Model.field "boolean", type: Boolean exports.Field = "is a property": (test) -> - o = Model.create() + o = Model.new() test.equal "AlphaSimprini.Model.Field.Instance", o.name.constructor.path() test.done() "is set when constructing a model": (test) -> - o = Model.create name: "Herb Alpert" + o = Model.new name: "Herb Alpert" test.equal "Herb Alpert", o.name.get() test.done() "may specify a default value for a field": (test) -> - o = Model.create() + o = Model.new() test.equal "the Tijuana Brass", o.band.get() test.done() @@ -29,14 +29,14 @@ exports.Field = test.done() "number fields are cast as numbers": (test) -> - o = Model.create( number: "44.89" ) + o = Model.new( number: "44.89" ) test.equal 44.89, o.number.get() o.number.set "44" test.equal 44, o.number.get() test.done() "boolean fields are cast as booleans": (test) -> - o = Model.create( boolean: "true" ) + o = Model.new( boolean: "true" ) test.equal true, o.boolean.get() o.boolean.set "false" test.equal false, o.boolean.get() @@ -44,7 +44,7 @@ exports.Field = "change event triggers on model and field": (test) -> test.expect 4 - o = Model.create() + o = Model.new() o.bind "change", -> test.ok true o.bind "change:boolean", -> test.ok true o.boolean.bind "change", -> test.ok true diff --git a/test/core/properties/has_many.coffee b/test/core/properties/has_many.coffee index f526787..0b97a0f 100644 --- a/test/core/properties/has_many.coffee +++ b/test/core/properties/has_many.coffee @@ -10,24 +10,24 @@ NS.Child.hasMany "children", model: -> NS.Child exports.HasMany = "property is a HasMany": (test) -> - o = NS.Parent.create() + o = NS.Parent.new() test.ok o.children instanceof AS.Model.HasMany.Instance test.done() "is set when constructing the model": (test) -> - o = NS.Parent.create children: {} + o = NS.Parent.new children: {} test.ok o.children.first().value() instanceof AS.Model test.done() "collection events trigger on property": (test) -> test.expect 1 - o = NS.Parent.create() + o = NS.Parent.new() o.children.bind "add", -> test.ok true o.children.add() test.done() "creates models of type speficied in options": (test) -> - o = NS.Child.create() + o = NS.Child.new() test.ok o.children.add() instanceof NS.Child test.done() \ No newline at end of file diff --git a/test/core/properties/has_one.coffee b/test/core/properties/has_one.coffee index 3b3fbd7..b30df0d 100644 --- a/test/core/properties/has_one.coffee +++ b/test/core/properties/has_one.coffee @@ -9,31 +9,31 @@ NS.Other.field "name" exports.HasOne = "property is a HasOne": (test) -> - o = NS.Parent.create() + o = NS.Parent.new() test.ok o.other instanceof AS.Model.HasOne.Instance test.done() "is set when constructing the model": "with a model": (test) -> - o = NS.Parent.create other: other = AS.Model.create() + o = NS.Parent.new other: other = AS.Model.new() test.equal other, o.other.get() test.done() "with a raw abject": (test) -> - o = NS.Parent.create other: name: "Linus" + o = NS.Parent.new other: name: "Linus" test.equal "Linus", o.other.get().name.get() test.done() "collection events trigger on property": (test) -> test.expect 1 - o = NS.Parent.create other: name: "Juliet" + o = NS.Parent.new other: name: "Juliet" o.other.get().name.bind "change", -> test.ok true o.other.get().name.set "Julio" test.done() "change event triggers when model is set": (test) -> test.expect 3, "fix field pass-through binding" - o = NS.Parent.create() + o = NS.Parent.new() o.bind "change", -> test.ok true o.bind "change:other", -> test.ok true console.warn "FIXME: WE EXPECT TO PROPERLY BIND TO FIELD EVENTS!" diff --git a/test/core/state_machine.coffee b/test/core/state_machine.coffee index 0688de2..e92b646 100644 --- a/test/core/state_machine.coffee +++ b/test/core/state_machine.coffee @@ -1,33 +1,33 @@ -{AS, _, sinon, coreSetUp} = require require("path").resolve("./test/helper") -exports.setUp = coreSetUp +# {AS, _, sinon, coreSetUp} = require require("path").resolve("./test/helper") +# exports.setUp = coreSetUp -class Car - AS.StateMachine.extends(this) +# class Car +# AS.StateMachine.extends(this) - constructor: -> @default_state "off" +# constructor: -> @default_state "off" -exports.StateMachine = - hasDefaultState: (test) -> - test.equal (new Car).state, "off" - test.done() +# exports.StateMachine = +# hasDefaultState: (test) -> +# test.equal (new Car).state, "off" +# test.done() - "will not transition from the wrong state": (test) -> - car = new Car - car.transition_state from: "wrongstate", to: "on" - test.equal car.state, "off" - test.done() +# "will not transition from the wrong state": (test) -> +# car = new Car +# car.transition_state from: "wrongstate", to: "on" +# test.equal car.state, "off" +# test.done() - "calls transition method with options for a valid transition": (test) -> - test.expect 2 - car = new Car - car.exit_off = (options) -> - test.deepEqual from: "off", to: "on", options +# "calls transition method with options for a valid transition": (test) -> +# test.expect 2 +# car = new Car +# car.exit_off = (options) -> +# test.deepEqual from: "off", to: "on", options - car.enter_on = (options) -> - test.deepEqual from: "off", to: "on", options +# car.enter_on = (options) -> +# test.deepEqual from: "off", to: "on", options - car.transition_state from: "off", to: "on" +# car.transition_state from: "off", to: "on" - test.done() +# test.done() diff --git a/test/helper.coffee b/test/helper.coffee index 6ba2046..ae53dcb 100644 --- a/test/helper.coffee +++ b/test/helper.coffee @@ -1,6 +1,6 @@ AS = exports.AS = require "alpha_simprini" -exports.NS = AS.Namespace.create("NS") +exports.NS = AS.Namespace.new("NS") _ = exports._ = require "underscore" sinon = exports.sinon = require "sinon" $ = exports.$ = require "jquery"