Giter Site home page Giter Site logo

cell's People

Contributors

peterwmwong avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

gerryster emidln

cell's Issues

Bindings returning empty arrays lose their position

beforeRender: ->
  @collection = new Collection()

render: (_)-> [
  'Before'
  -> @collection.map (item)-> item.get 'name'
]

afterRender: ->
  @collection.add name: 'YOLO'

Unfortunately, this'll end up rendering 'YOLOBefore' instead 'BeforeYOLO'. :(

I think the condition on...

renderValue = [d.createTextNode ''] unless renderValue?

... needs to include an empty array check.

Look at HTML5 IFrame's @Seamless/@Sandbox or Style's @Scoped

Currently, Cell's are loaded and added in the same context as the rest of the page.

  1. JS loaded using requirejs implementation of script async
  2. Templates loaded through XHR and added to the DOM as div element
  3. Style loaded through XHR and added to the DOM as head/style element

Although most cases won't, there is the opportunity for Cell's to break encapsulation and cause some head scratching problems (why didn't my Cell render/behave the same way):

  1. JS can access/modify global context and document DOM
  2. Style can accidentally create CSS rules that affect elements outside a Cell Rendering.

These problems could be remedied by using...

HTML5 IFrame's @Seamless/@sandbox
http://www.w3.org/TR/2010/WD-html5-20100624/author/the-iframe-element.html#attr-iframe-seamless

http://www.w3.org/TR/2010/WD-html5-20100624/author/the-iframe-element.html#attr-iframe-sandbox

HTML5 Style's @Scoped
http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#attr-style-scoped

View inheritance

Problem

We need some easy way of declaring a View that is based on another.

Solution 1: Composition (No change to cell)

define (require)->
  BaseView = require 'BaseView'
  require('cell/defineView!')
    renderEl: (_)->
      _ BaseView # Pass transformed options

Solution 2: passing extends to cell/defineView!

cell/defineView! is modified to handle a new extends property that allows the following:

define (require)->
  require('cell/defineView!')
    extends: require 'BaseView'
    beforeRender: ->
      # Mutate @options, which will be passed to BaseView when rendering
    # DO NOT specify a renderEl() or render()...

Initially, this seemed like a nice solution, BUT...

  1. passing options to the base view seems introduces a weird mutate-options-in-beforeRender pattern
  2. new funky one-off-ish rule that in this case, you can NOT specifiy renderEl() or render()

Now what?

Solution 1 seems to be the way to go as you can do this now and it doesn't add weirdness that Solution 2 adds. I'm leaving issue open and unworked on if anyone else has any better ideas.

EachBind returned from a Bind

render: (_)->
  ->if @get 'condition'
      _.map [1,2,3], (item)=>
        _ '.item', "item #{item}"

Result HTML

<div class='item'>1</div>
<div class='item'>2</div>
<div class='item'>3</div>

... later on view model changes

@set 'condition', 'another truthy value'

Result HTML

<div class='item'>1</div>
<div class='item'>2</div>
<div class='item'>3</div>
<div class='item'>1</div> <!-- :((( -->
<div class='item'>2</div> <!-- :((( -->
<div class='item'>3</div> <!-- :((( -->

When @get 'condition' changes, all the times in @collection get re-rendered WITHOUT the previous items being removed.

spy.watch() needs to handle Model/Collection access changing

Problem

render: -> [
  ->
    if @get 'switch' then @get 'one'
    else @get 'two'
]

Unfortunately, other than the 'switch' property, ONLY 'one' or 'two' will be watched to trigger an expression.

Proposed Solution

spy.watch() should monitor access patterns every evaluation of the watched expression, not just the first time.

Revisit spy.watch() API

Problem

Common code flows (from View and Ext) have come up when using spy.watch...

  • Is the value a function?
    • if so...
      • call spy.watch with...
        • use the hash of the context as the key
        • bound value to a context
        • bound callback to the same context
    • otherwise
      • call callback with a context passing value as the only argument

This causes the client code of spy.watch to declare dependencies on 'cell/util/fn' and 'cell/util/hash'.

Proposed Solution

The above should come for free and API should be:

spy.watch( context:any, watchFnOrValue:any, callbackFn:function )

Pipes API for Collection

Input and Output.
Takes a Collection input and outputs another Collection. Can be used for any type of transformation like, but not limited to: filtering, sorting, mapping, and reducing.
It allows for *nix style pipeing of data:

# *nix piping
> collection | Filter | Sort | Page
# cell/Collection piping
collection.pipe Filter(), Sort(), Page()

A Pipe can either be simple or incremental.

Simple Pipe

Just a function.

# Simple passthrough pipe
passthrough = (input)-> input.toArray()

Incremental Pipe

For large, high performance, and active collections.
A pipeline of simple pipes can be very costly calculate. And when a collection changes (add, remove), starting from scratch and executing each pipe could make it piping impractical if changes occur frequently and/or the collection is large.

Incremental pipes to the rescue.

If the input collection changes (add,remove), the first pipe is notified and can choose to operate on just the small subset that has changed. This may or may not effect it's output. If no changes are made to first pipe's output, then no other downstream pipe's are notified. If there changes are made, the next pipe is notified of only the changes. Thus only the minimal amount processing is done.

# Passthrough Incremental Pipe
Passthrough = Pipe.extend

  constructor: (options)->
    # You can listen to changes to option values using spy.watch() and change the output as necessary
    # Ex. Filtering of list changes based on user input
    spy.watch @, options.option1, -> # Do stuff

  onReset: -> @output.reset @input

  onAdd: (item, index)-> @output.add item, index

  onRemove: (item, index)-> @output.remove index

# Used in a view...
require('cell/defineView!')
  render: (_)-> [
    # User input can change options watched by an Incremental Pipe
    _ 'textarea', (x_model prop:'filterOption1', model:@)

    # Smart Pipes can be passed an options hash
    _.each (inputCollection.pipe Passthrough option1:-> @get 'filterOption1'), (item)->
      # Render item
  ]

Cell's as a superset of Backbone.View

Problem

Currently Cell has alot in common with Backbone.Views. In fact, aside from a differences in name (initialize/init) and small functionality (tag) there equal in functionality. Cell should not try to duplicate what already has alot of mindshare and buy-in from the community.

Proposed Solution

Cell should be:

  1. a plugin that wraps and extends Backbone.View
  2. Cell render helper (cell::_) should split off on its own as a "template renderer"

Nested spy.watch calls cause errors

spy.watch obj,
  ->
    a = model.get 'a'
    spy.watch obj,
      -> model.get 'b'
    a

Outer watch doesn't trigger when 'a' changes on model.
Inner watch clobbers spy log. :(

Remove __.if() and __.each()

__.if() and __.each() are unnecessary API's adding bloat that can easily be expressed as general binds.

__.each equivalence

_.each aCollection, (item)->
-> aCollection.map (item)->

__.if equivalence

_.if (-> @model.get 'condition'),
  then: -> 'yes'
  else: -> 'no'
-> if @model.get 'condition' 'yes'
    else 'no'

spy.watch is watching individual Models of a Collection

spy.watch obj, (-> collection.at(0).get 'property'), ->

Only collection should be watched for the following events:

  • 'change:property' (model events bubble up to their collection)
  • 'add'
  • 'remove'

Instead, currently, the first model in the collection is being watched for 'change:property'

This will be a problem for large Collections.

Redo test infrastructure

Tests need to be able to simulate various server behavior:

  • different http response codes (see 1312d88)
  • variability of load order (see 3bbb058)
    Tests need to also be automatable.

Right now tests rely on browser hack to allow loading local files (--allow-file-access-from-files), not good.

The model observed by x_model should be configurable

Problem

There are cases the View doesn't have a @model and instead you'd like x_model to use the View itself as the model.

This causes some weird patterns that don't feel right...

define (require)->
  x_model = require 'cell/exts/x_model'

  require('defineView!')
    beforeRender: ->
      @model = @  # !!! Whoa... wah? /upchuck
      @set 'text', ''

    render: (_)-> [
      _ 'textarea', (x_model 'text')
    ]

Proposed Solution

Add new method signature to x_model

x_model( {propName:string, model:Model} ) 

An example of usage:

define (require)->
  x_model = require 'cell/exts/x_model'

  require('defineView!')
    beforeRender: ->
      @set 'text', ''

    render: (_)-> [
      _ 'textarea', (x_model prop:'text', model:@)
    ]

Plugin-ize styling and template rendering

Why?

  1. Make it easier to use other template languages or handle precompiled templates
  2. ...it feels weird that mustache.js and less.js are part of the source and are default

So...

  1. Define the API (asynchronous, handles nested, requirejs build optimization etc.)
  2. Add data-cell-template-renderer, data-cell-style-renderer attributes to specify plugin
  3. Rip out mustache.js and less.js integration into their own projects and use API

Resurrect _.each()... and call it _.map()

render: (_)-> [
  -> @collection.map (item)-> ...
]
render: (_)-> [
  _.each @collection, (item)-> ...
]

_.each has the significant benefit of rerendering ONLY items added, when items are added to the collection. With a simple binding all items are rerendered upon collection changes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.