GithubHelp home page GithubHelp logo

end-dash's Introduction

Getting Started

EndDash is a two-way binding javascript templating framework built on top of semantic HTML

In its current release, EndDash relies on Backbone objects. See the dependency section for further details.

(Documentation is below)

Setting up

Install EndDash and install grunt helper

npm install

# We use grunt for running tasks.
npm install -g grunt-cli

# Build end-dash in build/ directory
grunt build # also aliased as `grunt`

Include the library and dependencies.

<!-- Make sure you include these libraries before EndDash -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://backbonejs.org/backbone.js"></script>

<script src="/end-dash/build/end-dash.js"></script>

Define your templates.

<script type="text/enddash" name="character">
  <div class="user">
    <p>
      Hello, my name is <span class="firstName-"></span>
      <span class="lastName-"></span>...
    </p>

    <strong class="quip-"></strong>
  </div>
</script>

WARNING: A template can only have one root element. In the above case, it is the div with class 'user'.

Load your templates into EndDash.

$.ready(function() {
  // Load all the templates on the page.
  EndDash.bootstrap();
)};

Bind your templates to models in your application code.

  var tony = new Backbone.Model({
    firstName: 'Tony',
    lastName: 'Stark',
    quip: "You know, the question I get asked most often is, 'Tony, how do you go to the bathroom in your suit?'"
  });

  var template = EndDash.getTemplate('character', tony);

  $('#content').html(template.el);
});

If your models changes, the DOM will update to reflect the changes.

Ready Made Examples

If you clone this repo and install grunt as described above you can play with some end-dash examples in your browser. Just type grunt in the root directory to build the current version of end-dash into the build directory, and then open up any of the example html files in the examples directory in your browser (open examples/looping.html for example works on OS X), and you can edit the templates or models directly in the html file if you want to experiment.

Documentation

Using Model Attributes

Inputs

Looping

Conditionals

Scoping

View Integration

Templates

Partials

Debugging

Dependencies

Contributing and Future Improvements

Using Model Attributes

Variables

EndDash variables are rendered into the body of HTML elements, displaying their values as ordinary text:

<div class="user-">
  My name is <span class="firstName-"></span> <span class="lastName-"></span>.
</div>

Attribute Interpolation

Model properties can also be interpolated into any html tag attribute.

<a href="/person/#{firstName}"> Home Page </a>
template.bind(new Backbone.Model({firstName: 'Derrick'}));

Resulting Tag:

<a href="/person/Derrick"> Home Page </a>

Inputs

EndDash does two-way binding between model attributes and input elements.

Text Inputs

Text inputs are bound to a referenced attribute on the model in scope. To create this binding, add the attribute name with a dash at the end as a classname in the template.

<p>
  What is your name?
  <input  type="text" class="name-">
</p>

Radio buttons

Radio buttons bind the selected button's value to the model's referenced attribute.

<div>
  <p>Who is your favorite character?</p>
  <input type="radio" class="name-" name="name-" value="tony" id="tony"/>
  <label for="tony">Tony</label>
  <input type="radio" class="name-" name="name-" value="pepper" id="pepper"/>
  <label for="pepper">Pepper</label>
  <input type="radio" class="name-" name="name-" value="james" id="james"/>
  <label for="james">James</label>
</div>

Checkboxes

Checkboxes are trickier. When unchecked, the referenced attribute on the model will be 'false'. When checked, the referenced model's attribute will be set to the attribute value on the input element (or 'true' if no value is defined).

<p>Do you want to receive notifications about Iron Man?</p>
<input type="checkbox" name="notifyList" class="notify-" />

Looping

Simple Looping

To reuse a set of DOM elements for each child model in a collection, add the data-each attribute to the parent of this set.

  <div data-each>
    <div class="firstName-"></div>
  </div>

The object in scope at these elements, will be iterated through (using .each). Each child of this collection will be bound to the nested elements.

Given the above template and the collection:

var characters = new Backbone.Collection([
  new Backbone.Model({firstName: 'Tony'}),
  new Backbone.Model({firstName: 'Pepper'}),
  new Backbone.Model({firstName: 'Iron'}),
  new Backbone.Model({firstName: 'James'})
]);

the output will be:

  <div data-each>
    <div class="firstName-">Tony</div>
    <div class="firstName-">Pepper</div>
    <div class="firstName-">Iron</div>
    <div class="firstName-">James</div>
  </div>

Note that the elements iterated over must have one root. (Here <div class="firstName-"></div>).

Polymorphic attributes

If your objects have an enum field, you can branch based on its value.

For example, role behaves as a polymorphic attribute:

<div class="rolePolymorphic-" data-each>
  <div class="whenHero-">
    <span class="firstName-"></span> says:
    Don't worry. I'll probably save you.
  </div>

  <div class="whenVillain-">
    <span class="firstName-"></span> says:
    Worry.
  </div>

  <div class="whenCivilian-">
    <span class="firstName-"></span> says:
    Get me outta here!
  </div>
</div>

Given the following objects:

new Backbone.Collection([
  new Backbone.Model({firstName: 'Tony', role: 'hero'}),
  new Backbone.Model({firstName: 'Pepper', role: 'civilian'}),
  new Backbone.Model({firstName: 'Aldrich', role: 'villain'}),
  new Backbone.Model({firstName: 'James', role: 'hero'})
]);

The template would produce the following HTML:

<div class="rolePolymorphic-" data-each>
  <div class="whenHero-">
    <span class="firstName-">Tony</span> says:
    Don't worry.  I'll probably save you.
  </div>

  <div class="whenCivilian-">
    <span class="firstName-">Pepper</span> says:
    Get me outta here!
  </div>

  <div class="whenVillain-">
    <span class="firstName-">Aldrich</span> says:
    The whole world's gonna be watching.
  </div>

  <div class="whenHero-">
    <span class="firstName-">James</span> says:
    Don't worry.  I'll save you!
  </div>
</div>

To add a default case, include a non-EndDash child div:

<div class="rolePolymorphic-">
  <div class="whenHero-">
    <span class="firstName-"></span> says:
    Don't worry.  I'll probably save you.
  </div>

  <!-- Default case! The following gets rendered unless
       model.get('role') === 'hero'. -->
  <div>
    <span class="firstName-"></span> says:
    I've lost my memory.  I don't know who I am!
  </div>
</div>

Collection Attributes

Please note: Backbone.Collection does not support attributes natively for its collections, but there are a number of options for extending collections to do so. EndDash supports collection attributes as long as they are implemented according to Backbone.Model API, via the get method (which Backbone.Collection natively uses only for getting a model by id, not an attribute by name). Typically collection attributes are used for metadata about the collection, such as total size (if the collection is paginated and this is different than length), as in the example below:

<div class="authorizedPeople-" >
  <p>
    There are <span class="totalCount-"></span> people allowed in Tony's basement.
  </p>
</div>

Conditionals

A ternary operator is available for presence handling via 'truthiness' for attributes that may be present, with or without a false condition:

<div class="user- #{availability ? available : unavailable}">
  <p>
    My schedule is very full. <span class="isAvailable-">I just have a few openings</span>
  </p>
</div>

The same truthiness controls conditional visibility EndDash class elements that start with is or has, and their boolean opposites isNot and hasNo, as above with isAvailable-. EndDash will hide (via a display:none style attribute) any such element when its named attribute is falsy (or hide when truthy in the case of isNot and hasNo.)

template.bind({
  user: new Backbone.Model({
    firstName: 'Tony',
    lastName: 'Stark',
    alias: 'IronMan'
    availability: ['10am', '2pm']
  });
});

Scoping

What is Scoping?

Scope in EndDash refers to the model on the top of the EndDash stack. Each template and partial is given its own scope. The 'root' scope is always the object passed to EndDash's 'bind' or 'getTemplate' function.

template.bind({
  user: new Backbone.Model({
    firstName: 'Tony',
    lastName: 'Stark',
    hobby: {
      description: 'Building all the cool technology'
    }
  })
});

The root object is the object literal with the property 'user'.

Scope can change in two ways:

Scoping Down With A Dash

<div class="user-">
  //Internal HTML
</div>

Scopes into the Backbone Model with properties: 'firstName', 'lastName', and 'hobby'. This syntax only allows scopping down.

Scoping With Paths

(UNIX style)

<div class="user-">
  <div data-scope="/">
    //Iternal HTML
  </div>
</div>

Scopes down into the user object and then, via the data-scope property, scopes back to the root object (the object literal with propery 'user').

Normal UNIX path shorthands apply: .. to move back up a scope level, / to seperate scope levels, . for the current scope.

<div class="user-">
  //User scope
  <div class="hobby-">
  //Hobby scope
    <div data-scope="../">
    //Back in User Scope
      <div data-scope="/user/hobby">
      //Back in Hobby scope
      </div>
    </div>
  </div>
</div>

class="user-" is actually syntactic sugar for data-scope="./user". Using data-scope like this, at the current scope, is mainly useful for accessing a property of a nested model in the same DOM element that you change the scope.

View Integration

EndDash provides dynamic behavior often otherwise handled by views in Backbone. If more specific dynamic behavior is required, take advantadge of EndDash's hooks to Backbone Views. Simply add the html attribute data-view with the value of your viewName, to the template.

<div>
  <h2>
    Configure Iron Man's suit below:
  </h2>
  <div class="suit-" data-view="iron_man_suit_view">
    <div id="suitConfig">
  </div>
</div>

When EndDash runs into a data-view, it will lookup the view and initialize it with the model in scope at the DOM element where the view is initialized.

To lookup the view, EndDash uses a simple view store. You can register views by calling EndDash.registerView with the view name and the view class object. You can also define your own function and pass it into EndDash.setCustomGetView

EndDash.registerView('myViewName', viewObj);
var views = {},
    getViews = function(name) {
      return views[name];
};
EndDash.setCustomGetView(getViews);

Templates

Registering a Template

This can be done manually.

EndDash.registerTemplate('greetings','<div>Hello Citizens, I am <span class="name-"></span></div>');

Or, via EndDash.bootstrap.

To bootstrap, have your templates loaded as scripts of type 'enddash' on the page.

<script type="text/enddash" name="greetings">
  <div>
    Hello Citizens, I am <span class="name-"></span>
  </div>
</script>

Then call EndDash.bootstrap.

$.ready(function() {
  // Load all the templates on the page.
  EndDash.bootstrap();
)};

Binding to a Template

First, get the EndDash-parsed version of your template.

var template = EndDash.getTemplate('greetings');

Then bind it to a model.

var hero = new Backbone.Model({name: 'Superman'}),
    boundTemplate = template.bind(hero);

This can be done in a single step, by passing a model as a second argument to EndDash.getTemplate.

var hero = new Backbone.Model({name: 'Superman'}),
    boundTemplate = EndDash.getTemplate('greetings', hero);

Displaying HTML of a bound Template

Show the el property of the template.

$('.content').html(boundTemplate.el);

Partials

Small, reusable, components of HTML can be templated in EndDash as partials. To use a partial, add src="templateName" as an attribute to an element with no children.

<script type="text/enddash" name="superheroes">
  <img src="#{logo}" />
  <div class="heroes-">
    <div src="superhero-navigation" data-replace></div>
  </div>
</script>

The partial will be passed the model in scope as its root element.

The data-replace attribute tells EndDash to substitute the partial's root element for its partial. Without data-replace, EndDash will embed the root element beneath the partial's element and leave it.

If elsewhere you define this partial as:

<script type="text/enddash" name="superhero-navigation">
  <ul data-each>
    <li>
      <a href="#{url}"><span class="name-"></span></a>
    </li>
  </ul>
</script>

And bind to the top level template with:

template.bind({
    heroes: new Backbone.Collection([
      new Backbone.Model({name: 'Iron Man', url: '/superheroes/techGenius'}),
      new Backbone.Model({name: 'Spiderman', url: '/superheroes/webMaster'}),
      new Backbone.Model({name: 'Superwoman', url: '/superheroes/strong'})
    ]),
    logo: '/public/emblems/protectTheWorld'
});

This will result in:

<img class="/public/emblems/protectTheWorld">
<div class="heroes-">
  <ul>
    <li><a href="/superheroes/techGenius">Iron Man</a></li>
    <li><a href="/superheroes/webMaster">Spiderman</a></li>
    <li><a href="/superheroes/strong">Superwoman</a></li>
  </ul>
</div>

Debugging

Open up a debugger in development mode to inspect the context of the template.

Open a context in the highest template scope:

<body>
  <div debugger />
</body>

In a child model scope:

<body>
  <div class="questions-">
    <!-- Open a debugger in the scope of get('questions') -->
    <div debugger />
  </div>
</body>

Dependencies

In its current release, EndDash relies on Backbone style events to update the DOM when a bound object changes. This means only objects which define an interface with Backbone's "on, once, set, get" will interpolate model attributes into the DOM and update the DOM on model changes.

EndDash used without Backbone style getting & setting will still interpolate a bound object's attributes into the DOM but will not update the DOM on model changes.

Contributing and Future Improvements

There are a number of future improvements planned for EndDash and we'd love for you to be involved in them. Please Fork the EndDash repo and open pull requests or get involved in discussing features or improving documentation via GitHub issues or a PR on the README.md file. Our homepage at enddash.com is hosted on GitHub pages via the gh-pages branch, so feel free to improve and make PR's to the home page and live examples there as well.

Building and testing

To develop EndDash locally, you must have NPM and Grunt installed. From the directory of your local clone of the EndDash repository:

npm install

# We use grunt for running tasks.
npm install -g grunt-cli

# Build end-dash in build/ directory
grunt build # also aliased as `grunt`

# Run tests
grunt test

# Watch for changes and run tests
grunt watch

Future Improvements

Right now EndDash only supports browser side rendering, but we have plans to support Node.js server-side rendering as well, and hybrid rendering where templates are pre-processed server side and served as static compiled assets for the client. We also have a branch with a new interpolation syntax support to avoid requiring the use of span elements for dynamic text, and a few other ideas open or coming soon to GitHub issues and pull-requests on the github repo.

end-dash's People

Contributors

chrisvoxland avatar fredericoandrade avatar jameselkins avatar pbadger avatar tobowers avatar xcoderzach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

end-dash's Issues

Attribute Conditional Interpolation is odd behavior

a)
#{sentPercentage} does not interpolate anything when model.get('sentPercentage') === 0

b)

"#{sentPercentage ? : 0}"
## ^ if sentPercentage is 0 returns 0 else returns model.get('sentPercentage)

"#{sentPercentage ? sentPercentage  : 0}"
## ^ if sentPercentage is 0 returns 0 else returns "sentPercentage"

"#{sentPercentage ? sentPercentage  :  .1}"
## ^ Fails to interpolate

"#{sentPercentage ? sentPercentage  : width:0%}"
## ^ Fails to interpolate

๐Ÿ˜ธ

Disabled attribute not controllable with EndDash

If you have a template like:

Save

The template will look on the user's presenter for the disabled attribute and add the class. However, this won't affect the html 'disabled' attribute. Thus, it would be awesome if we could do

Save

or even just have the disabled class turn the disabled attribute on and off, since we never want something that looks disabled that isn't. This would be a bit more magic however. Probably disabled='disabled-' is the way to go.

What happens if a polymorphicKey changes?

When polymorphic keys change, does the div update?

For example, given:

<div class="rolePolymorphic-" data-each>
  <p><span class="firstName-"></span> says:</p>

  <div class="whenHero-">Don't worry. I'll probably save you.</div>
  <div class="whenVillain-">Worry.</div>
  <div class="whenCivilian-">Get me outta here!</div>
</div>
var characters = new Backbone.Collection([
  new Backbone.Model({
    firstName: 'Anna',
    lastName: 'Marie',
    role: 'villain'
  }),

  new Backbone.Model({
    firstName: 'James',
    lastName: 'Rhodes',
    role: 'hero'
  }),

  new Backbone.Model({
    firstName: 'Pepper',
    lastName: 'Potts',
    role: 'civilian'
  })
]);

what happens if it changes?
I mean if you have {firstName: 'Anna', lastName: 'Marie', role: 'villain'} in the collection, you render it, and then do rogue.set('role', 'hero')

Reaction classes are gross

Inheritance?!? Static methods?!? ๐Ÿ’ฉ

Reaction.register("selector", {
  reactIf: function() {},
  init: function() {},
  observe: function() {}
})

//or shorthand

Reaction.register("selector", function() {
  //just the init.
})

Batch updates

Updates should be batched together, so you don't repaint/reflow the brower a bajillion times.

if you buffer all changes and then do a requestAnimationFrame, I think everything would be a lot faster

xss

Variable reaction is xss-able. Should probably replace the call to
this.el.html with this.el.text, unless something like, data-htmlenable exists.
I don't remember why we didn't fix this before, I think it had something to do with the call page, and maybe being lazy.

Try it for yourself

  1. go to http://www.enddash.com/
  2. <script>alert('xss')</script> in the box
  3. lulz

support non template id based binding

Alternate interface for attaching models directly to dom where html has been written directly in end dash syntax (gh-pages branch has basic implementation idea)

Handle multiple Backbones more gracefully

Instead of trying to be clever about resolving Backbone dependencies, we should do some combination of:

  • explicitly require backbone.js as a dependency, at least until it isn't a dependency any longer.
  • default to window.Backbone if it's defined.
  • use require('backbone').noConflict()
  • allow the user to override EndDash.Backbone. (Backbone itself follows this pattern... it has a jQuery dependency and allows you to override Backbone.$ if you want to use a custom jQuery).

@bglusman
@devmanhinton

Add logger and configuration for logging (only in development).

For rails, detecting development isn't too hard, maybe for all platforms detecting localhost or 127.0.0.1 in window.location is good enough. Want an integrated logger like EndDash.logger that will ignore calls in production or if logging is disabled, probably use console.log internally when active, possibly multiple logging levels like EndDash.error and EndDash.info, or EndDash.logger.error/info

License?

I can't seem to find what license this is? Typically projects mention this in a LICENSE.md file in the root directory, at the bottom of their readmes under a ## License header, or in their package.json files under the "license": "MIT" property.

This error needs to be better.

Tried to bind template to a undefined, but templates can only be bound to objects.

It needs to at least tell you what is undefined, like

Tried to bind this templates user to undefined.

Same Template, two iterations, both polymorphic with same key === overwrite

(Writing iteration because we are changing EndDash's iteration mechanism)

(If all below in same template)

<div "iteration typePolymorphic">
   <div class='whenUser'>
   //HTML1
   </div>
</div>

//Other HTML

<div "iteration typePolymorphic">
   <div class='whenUser'>
   //HTML2
   </div>
</div>

In both will be HTML2

Backbone View .onClean function

That when a template was being cleaned up (template.cleanup()), it ran a user defined cleanup function for view reactions if the function exist on the view

class coolDomView
#...
  cleanup: ()->

If you unbind the el of an EndDash template with a looping reaction and then you trigger a remove on the collection, it errors

<div class='replace'>
</div>

mytemplate.js

<div class='people-' data-each>
   <div class='name-'></div>
</div>
template = EndDash.getTemplate('mytemplate.js', {people: collection})
$('.replace').html(template.template)
$('.replace').html(template.template)
people.remove(0)

Did not try this exact case (real case is in private code base), this is ~ repro steps.

If we get around to do this, will test again

animations

animating between states would be coolio.

syntax change of data-each and polymorphic

I propose that

  • data-each be on the element being repeated.
  • polymorphic be removed from looping and made its own thing

a complex example:

<div class="chats-">
  <p class="totalCount-"></p>
  <ul>

      <li>Nothing to see here</li>

      <li data-each>
        Said the user:
        <div data-case="userName">
          <div data-when="currentUser">
            <p>you</p>
            <p class="content-"></p>
          </div>

          <div data-when="bob">
            <p class="userName-"></p>
            <p class="content-"></p>
          </div>
        </div>
      </li>
  </ul>
</div>

In this case:

  • the li is looped for every chat
  • the data-case div looks at its contents and displays one or the other div based on the data-when
  • if no data-when matches the data-case is display: none;

If I did not want a li to show up for non-matching cases I would do the following:

     <li data-case="userName" data-each>
          <div data-when="currentUser">
            <p>you</p>
            <p class="content-"></p>
          </div>

          <div data-when="bob">
            <p class="userName-"></p>
            <p class="content-"></p>
          </div>
      </li>

in this case the li would be inserted by the looping but display: none by the data-case when neither of then when's match

@yaymukund @devmanhinton @bglusman @xcoderzach : thoughts?

Simplify collection syntax

collections are the ickiest part of the code. since they require the inflection library
and all kinds of hacks. Instead use a syntax like:

<ul class="things-" data-col>
  <li></li>
</ul>

or

<ul>
  <li class="things-"></li>
</ul>

and always repeat elements in place when the data is a collection.

cannot run tests following instructions on enddash.com

npm install

npm install -g grunt-cli

grunt build
Loading "watch.js" tasks...ERROR
>> Error: Cannot find module 'minimatch'
>> Local Npm module "grunt-contrib-jshint" not found. Is it installed?
Loading "simple-mocha.js" tasks...ERROR
>> Error: Cannot find module 'debug'
Loading "browserify.js" tasks...ERROR
>> Error: Cannot find module 'through'
Warning: Task "browserify" not found. Use --force to continue.

Aborted due to warnings.

Allow for context driven state in partials, like rails local variables are passed in

For example, in our stateful_button partial, the text is fixed as 'Save', 'Saving...' and 'Saved' for the various button states, but in some contexts other text is more appropriate for similar AJAX transactions, e.g. 'Send', 'Sending'

Having a mechanism for templates to pass state to their partials would DRY up template code and encourage reusable, modular partials. One possibility is a data-inherit attribute in a partial, along with some conventions for how to parse and interpret the value from the context of the containing tree above it in the DOM, such as data-inherit-button-text in the partial and data-inherit-button-text="Send" in a containing partial, but there might be uses beyond just static text such as an optional second model the partial might use for children of the data-inherit element.

Removing awesome-docs documentation

@bglusman

cc suspenders.js compadre @devmanhinton

This came up in #24 :

Also, the two .markdown tests look to be the old AwesomeDocs tests, I think Topper replaced/converted all of those to mocha, are they still needed?

I started looking at this. The tests are within the documentation, so it's tricky to decouple them in such a way that the documentation still makes any sense.

We have "clean up documentation" as part of this sprint, so we'll address it in more detail later this week. I'll leave this issue open as a reminderโ€” does that sound reasonable, @bglusman ?

EndDash does not work as expected with trigger

This is an issue @jameselkins and myself found and then diagnosed

Calling model.trigger('change:batchSize') fires only a 'change:batchSize' which attribute reactions will not catch. We have the code written to catch it but we are not using it for attributes.

Code that handles listening, notice the first granular listen

//Reaction.js
Reaction.prototype.change = function(property, callback, context) {
  if(typeof property === "string") {
    if(this._presenter.on) {
      var events = property.replace(/(^| )/g, " change:").slice(1);
      this.listenTo(this._presenter, events, callback, context);
    }
  } else {
    callback = property;
    if(this._presenter.on) {
      this.listenTo(this._presenter, "change", callback, context);
    }
  }
};

How we are listening now:

//Attribute.js
  observe: function() {
    this.change(function() {
      this.updateAttributes(this.attributes);
    }, this);
  }

This normally actually works fin since backbone fires but a granular and non-granular event on set

//From Backbone.js, specifically the set function
if (!silent) {
        if (changes.length) this._pending = true;
        for (var i = 0, l = changes.length; i < l; i++) {
          this.trigger('change:' + changes[i], this, current[changes[i]], options);
        }
      }

      if (changing) return this;
      if (!silent) {
        while (this._pending) {
          this._pending = false;
          this.trigger('change', this, options);
        }
      }

It looks like an easy fix, just a change in Attribute.js to listen to the granular events ๐Ÿ‘

Bind object to template and add markup to page in one line?

We have a lot of code internally like:

var userMarkup = new UserTemplate({user: user}).template;
$('.user').html(userMarkup);

Maybe we should just be doing:

new UserTemplate({user: user}).bindTo('.user');

or maybe:

new UserTemplate({user: user, bindTo: '.user'});

Not sure what's the right solution, but it would cut down on a lot of similar boilerplate.

Interpolated Variables & Brief

https://github.com/amicus/end-dash/tree/interpolated-variables

Allows for

<div>#{firstName}</div>

Instead of

<div class='firstName-'></div>

Issue: Make this work with brief.

A solution:

a) Use a regexp in templates/ ~= 'If a dom element has a class ending in a '-' and no children elements. Add a '#{name}' child text node. Where name is the name of the class ending in a dash.'

b) This leaves affected dom elements with an extra scope reaction (class ending in a dash). You can remove this class but it will break shit tons of css. Solutions:
I) Add _noOpt as a reserved class name that prevents EndDash scoping reactions
II) Person up, and break all the css, then fix all the css

Thoughts? @yaymukund @bglusman

EndDash overbinds when > 1 root

    <h1> The User's name is </h1>
    <div class="firstName-"> </div>

As an EndDash template will bind the model's firstName to both the div and the h1.

   <div>
      <h1> The User's name is </h1>
      <div class="firstName-"> </div>
   </div>

Will be fine however.

This is due to the selector generation in util.js. It relies on only one root to a template. I believe this is the line https://github.com/Amicus/end-dash/blob/master/lib/util.js#L16. But more investigation is necessary

Partials are inlined, making relative paths to sub-partials problematic

Partials are regular end-dash templates able to include other partials/templates, but because partials are inlined to their parent before being evaluated, any relative path may be incorrect unless the parent is in the same folder.

Probably the easiest fix is for partials to be recursively parsed to inline their child partials before being inlined to their parent, but other possibilities might be easier... workaround is to only use absolute paths in src attributes if the template has any chance of being included in another template as a partial.

template.template

uhhhg I hate this so much, it should be template.el but I'll leave in template.template for backwards compat.

DISCUSSION: tag line on docs is confusing to many.

"EndDash is a bindings-aware client-side templating framework built on top of valid HTML."

Many don't immediately know what "bindings-aware" means. Advanced users will still take a sec to figure it out.

My suggestion:

EndDash is a javascript templating framework built on top of valid HTML that allows bidirectional binding of Backbone objects to the DOM.

Recognition of Collections is inconvenient

In order for templates to properly function three main requirements must be satisfied:

  1. Template must have a div that is scoped to a name "y" with a child that is scoped to the singular of y

ex.

     <div class="users-">
        <div class="user-">
          <h1> The User's name is </h1>
          <div class="firstName-"> </div>
        </div>
     </div>
  1. The collection must be in an anonymous model

More investigation needed here. In brief this might not come up since we always access collections through other objections (for instance questions from the script model).

To work out of the box, one need do something akin to

    var userCollection = new Backbone.Collection
    var user1 = new User({firstName: "Brian"})
    var user2 = new User({firstName: "Sam"})
    var user3 = new User({firstName: "Justin"})
    userCollection.add([user1, user2, user3])
    var template = EndDash.getTemplate('simpleCollectionBind', {users: userCollection})

Note the parameter in the last line where the collection is passed in an object literal. In this case, the name
"users" in both the object literal and template are irrelevant. The same model attribute interpolation can be achieved
using

     <div class="xboxs-">
        <div class="xbox-">
          <h1> The name of the User is </h1>
          <div class="firstName-"> </div>
        </div>
     </div>


    var userCollection = new Backbone.Collection
    var user1 = new User({firstName: "Brian"})
    var user2 = new User({firstName: "Sam"})
    var user3 = new User({firstName: "Justin"})
    userCollection.add([user1, user2, user3])
    var template = EndDash.getTemplate('simpleCollectionBind', {xboxs: userCollection})

Relevant End-Dash code:
https://github.com/Amicus/end-dash/blob/master/lib/rules.js#L67
https://github.com/Amicus/end-dash/blob/master/lib/rules.js#L13
https://github.com/Amicus/end-dash/blob/master/lib/rules.js#L62

partials are also shitty

Straight up inlining code isn't cool :-( ๐Ÿ‘Ž

I think that a partial should just do:

var Partial = require(<valueof data-partial>)
var p = new Partial(stack.last())
partialEl.html(p.el)

That way, anything that has a .el property can be a partial. And it works really well with my new component architecture that I use. Since I can just plug in a component and it just works. BOOM YEAH.

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.