Code Monkey home page Code Monkey logo

spine's Issues

proxy function called with undefined parameter

Hi,
on my project (https://github.com/loicginoux/spine-annotation-plugin) i encountered an error where the 'proxy' function was called without paramter.
I haven't tried to understand what was causing the issue inside spine but i managed to fix the issue by adding a condition on the parameter existence like that:

proxy: function(m) {
    var l = this;
    return (function() {
        if (m) return m.apply(l, arguments)
    })
}

instead of the current:

proxy: function(m) {
    var l = this;
    return (function() {
        return m.apply(l, arguments)
    })
}

You can test the issue by downloading the project and opening edit.html.
I have the master branch with the initial spine.js (originally it was the minified version, I de-obfuscated it for debugging purpose).
The error happens when you drag a note (after creating one)
The other branch 'spine-fix' has the change in the proxy function and when testing the dragging, it works.

I was wondering if this is an issue from spine or if I am misusing the framework.

let me know what you think.
cheers

Coffeescript Classes vs Spine Classes

How are you planning on making Coffeescript Classes vs Spine Classes work, since there's a fair bit of functionality crossover?

I'd really like to be able to use native CoffeeScript classes with Spine, but I'm not quite sure what the most sustainable approach is, or if there's a good way to get CoffeeScript classes working in harmony with Spine classes as-is. I am yet to try using the js branch of Spine with CoffeeScript classes, have you?

To utilize the class system, will CoffeeScript be required in the future? Will the existing extend/include system still work/be fallback for non-CoffeeScript users?

Spine.Ajax Delete with Rails

Perhaps I am wrong on this. This is related to Spine.Ajax when used with a Rails Backend, specifically when the destroy action is called on a Model , which in turns sends a Delete Request to the server trough Ajax.

The standard Rails Delete command returns: " " in its response. ( at least with a regular scaffold, don't know if it's Rest Standard )

So, Jquery Ajax tries to parse this and throws a Parse Error which instead of triggering the Success Event, triggers the Error Event; Even thou the response status is 200 and the instance was actually deleted on the server.

The quick solution is to change the Rails Delete Route, and make it return something that Jquery.Ajax can understand;

However, since that is the Rails Standard* way of doing things, I've been figuring out a solution so Spine works out of the box.

One of them involves checking the error function to see if the status is 200. This would mean that the error occurred on the client side, so the success function should be fired instead. However, if something actually went wrong , or the response being sent has a mistake, there would be no way of knowing. So I don't know if that will be a solution.

So this comment, is more an observation than anything to remind you that this issue should be documented so users of the Spine Framework know that they should change a bit the Delete Route on Rails when using Rest and make it response with something meaningful;.... or to start a discussion on how to handle it on Spine

Cannot send query parameters to a server when issuing a fetch

In Spine.Model.Ajax#send, it takes in parameters that can be passed into the fetch function. The problem is that when ensuring the parameters are set up any data values that could've been used for issuing a query are replaced with an empty object.

Instead it should do something like:

params = $.extend(params || {}, {
    type:                this.methodMap[method],
    contentType:    "application/json",
    dataType:         "json",
    data:                params.data || {}
});

Spine.Route add RegExp handling on Firefox

Spine.Route add method has the following code:
if (typeof path === "object")

Consider path to be of regex type: path = /mypath[=]/

Firefox: typeof (path) => 'object'
Chrome: typeof (path) => 'function'

Special case handling would be needed:
if (typeof path === "object" && !(path instanceof RegExp))...

Add separation note in Readme/docs

It looks like spine is in 2 branches now? One for coffee script one for js? I was originally using master and spent an hour trying to make it work before stumbling across a random issue mentioning the js branch :)

Could you add a quick note in the Readme on master about the separation? I grabbed the base js file from the github pages, but wanted to add ajax so grabbed that from master, and thats when the trouble started. Grabbing both from the js branch cleared it right up.

I hope you keep the js branch going, as spine is an awesome library and some of us don't like that coffeescript nonsense :)

Ajax Get Params Data Lost

When I try to pass parameters to fetch they are being overridden. It appears the the $.extend method is applying second object's (defaults) values over the top of the first's (params).

Perhaps I'm doing something wrong but I think this may be a bug. If I reverse the call to $.extend the params are passed.

From:

params = $.extend(params || {}, {
  type:          this.methodMap[method],
  contentType:  "application/json",
  dataType:     "json",
  data:         {}
});

To:

params = $.extend({
  type:          this.methodMap[method],
  contentType:  "application/json",
  dataType:     "json",
  data:         {}
}, params || {});

Class inheritance in Spine

Hi,

I'm trying to work out how to correctly work with inheritance in Spine Classes. However I think I am missing something and I couldn't find anything about it in the documentation or tutorials on the web.

As a basic example in pseudocode I want to do something like this:

class Base {
   constructor: function() {
      this.foo = 'bar';
      this.bar = 'woosh';
   },
   printContent: function() {
     console.log(this.foo, this.bar); 
   }
}   

class Extend extends Base {
   constructor: function() {
     parent:: constructor();
     this.bar = 'blablabla';
   }    
}           

i1 = Base();
i1.printContent(); // should print:  bar woosh
i2 = Extend();
i2.printContent(); // should print: bar bladiebla

~

I have played around with the spine classes and did something like:

var Base = Spine.Class.create({
 init: function() {
   console.log('base init');
   this.foo = 'bar';
   this.bar = 'woosh';
 },
 dump: function() {
  console.log('dump', this.foo, this.bar);
 }
});
var Extend = Base.create({
  init: function() {
    console.log('extend init');
    this.bar ='bladiebla';
  },
  dump2: function() {
    console.log('dump2', this.foo, this.bar);
  }
});
base = Base.init();
base.dump();
extend = Extend.init();
extend.dump2();

This results in:
base init
dump bar woosh
extend init
dump2 undefined bladiebla

Apparently this is not the approach to take in Spine. Although I think i'm pretty close (the functions seem to inherit correctly, but the proper tie settings are not.

Can you help out a bit?

Kind Regards,

Mark

ajaxPrefix taken literally

From spine.ajax.js:
if (record.parent.ajaxPrefix) {
data = {};
data[record.parent.ajaxPrefix] = record;
} else {
data = record;
}

Thus if we do:
Spine.Model.ajaxPrefix = true;
like the docs instruct, then the serialization will be:
"data":"{"true":{"name":"arst","id":"05831A06-3A42-46E6-8768-783A1DBF1037"}}"
on all models.

There's also a slight quirk in this implementation for an ajax extended model:
myModel.create(serializedData) will send the long spine guid which the server has no need for in all the cases i can think of.

setting id on refresh

When creating a new record spine checks if an attribute named "id" exists. If it does not it assigns an id. Shouldn't the same happen for refresh too? It seems that calling refresh should do the following:
if ( !record.id ) record.id = Spine.guid();

Validate() returns null when Model is valid

Hi, Spine is really great!
Just a quick contribution :

Model.validate() returns null when the model is valid and a string when it is not.
So validation may looks like this:

    if (!Model.validate()) {
        alert('Model is valid');
    } else {
        alert('Model is not valid');
    }

It looks weird to me. I expect (maybe I'm the only one) that Model.validate() returns true when the model is valid or false when it is not.
So why not add an extra method Model.isValid() with something like that:

     isValid: function(){
        if (typeof this.validate() == 'string') {
            return false;
        }
        return true;
     }

My two cents :)

Event callback cannot unbind itself

Hi there,

Currently Events.unbind() modifies the array in the _callbacks object. This causes issues when .unbind() is called on the same array being iterated over in the Events.trigger() method. Hopefully the following example demonstrates this.

eventInstance.bind('once', function a() {});
eventInstance.bind('once', function b() { eventInstance.unbind('once', b) });
eventInstance.bind('once', function c() {});

eventInstance.trigger('once'); // throws reference error.

Cheers,
Aron

Support for querying subsets?

There doesn't seem to be support for querying a subset of data from the backend (for example, by supplying a custom URL). Are there plans to support this? If not, would you consider patches?

Controller.elements key/value ordering

var Tasks = Spine.Controller.create({
    elements: {".mySelector": "controllerProperty"},
})

The ordering here seems a little unintuitive, it would make more sense to have the elements the other way around, looking more like an assignment:

var Tasks = Spine.Controller.create({
    elements: {"controllerProperty": ".mySelector"},
})

What do you think?

Why the move to CoffeeScript?

I was wondering why the move to CoffeeScript? Spine was a nice, zero-dependency alternative to Backbone with easy to understand Javascript... now I have to wade through CoffeeScript to see what's going on under the hood as the compiled version is full of CoffeeScript magic.

A real shame.

Model "inheritence"

Hello,

I'm really liking Spine.js, I make extensive use of it in my latest project. However the code base grew and grew and now I reached a point where I'd like to tidy things up a little.

One particular thing that I'm having trouble with is adding some more hierarchy to my models and controllers. I really like the Spine.Class design and the docs state that Models and Controllers are just a special type of Spine.Class, so this is all good. However I do not fully understand how I'm I supposed to make use of it.

What I'd like to achieve is to have some base model classes like so:

window.Base = Spine.Model.sub();

window.Base.include({
    some_base_property: 123,
    other_base_property: 234,
    some_function: function() {
         console.log("Base::some_function");
    },
    other_function: function() {
         console.log("Base::other_function");
         this.some_function();
    }
});

window.ConcreteModel = Base.setup("ConcreteModel", ["additional_property"]);

window.ConcreteModel.include({
    additional_property: 345,
    some_function: function() {
         console.log("ConcreteModel::some_function()");
    },
    other_function: function() {
         console.log("ConcreteModel::other_function()");
         // CALL SUPER.other_function() SOMEHOW, BUT IN THE PRESENT CONTEXT
    }
});
  1. The desired output for calling someConcreteModel.other_function() would read:
ConcreteModel::other_function()
Base::other_function()
ConcreteModel::some_function()

Just as it would in a regular OOP language. Is there a way to achieve this with Spine?
2) Is there a way to have Base attributes like base_property and other_base_property saved along with additional_property when playing with ConcreteModel instances without having to specify them over again inside the call to setup()?
3) Finally what is the proper way to structure model tree and to bring common functionality to models?

Thanks in advance.

Binding to event on model instance with server-side id change via AJAX should trigger callback

Found an interesting bug today.

My understanding is that binding to an event on a model model instance will add a callback to the Model callback list, capturing the instance in a closure so that only that instance will get event callbacks for this binding:

From Spine.Model:

bind: function(events, callback){
  return this.parent.bind(events, this.proxy(function(record){
    if ( record && this.eql(record) )
      callback.apply(this, arguments);
  }));
}

Also important: when saving via AJAX, the spine.ajax callbacks operate on a clone of the record:

create: function(){
  this.trigger("beforeCreate", this);
  if ( !this.id ) this.id = Spine.guid();
  this.newRecord   = false;
  var records      = this.parent.records;
  records[this.id] = this.dup();
  var clone        = records[this.id].clone();
  this.trigger("create", clone);
  this.trigger("change", clone, "create");
},

So, when trying to process ajaxSuccess from spine.ajax, the clone's id is updated (not the original record, and thus not the record captured in the closure). From Spine.ajax:

  // ID change, need to do some shifting
    if (data.id && record.id != data.id) {
      var records      = record.parent.records;
      records[data.id] = records[record.id];
      delete records[record.id];
      record.id        = data.id;
    }

    // Update with latest data
    Ajax.noSync(function(){ 
      record.updateAttributes(data); 
    });

    record.trigger("ajaxSuccess", record, status, xhr);

When we go to trigger ajaxSuccess here, because the clone has a different id than its original Model instance, there will be no matching callback found.

Works for me by not dup()-ing the record in create; however, I'm not sure if there are other rammifications caused by that.

Model ordering by attribute

Hi,

First of all, I'd like to say this is a great framework and the docs are great. I started to play around with this it saves a lot of frontend coding for me.

One thing I think is missing is Model ordering. For example, if I want to retrieve a model and order it by date, I'd have to retrieve everyone, parse out the date and then put it into a separate array ordered by date.

Thanks,
Ray

Inconsistent behavior between Asset.each and Asset.find

Why does Asset.each yield direct references to assets, but Asset.find yield clones?

It's confusing because if you set attributes (without saving) on assets from Asset.each, the attributes are set on the models directly and are accessible everywhere, but if you set them on assets from Asset.find, they get set on clones and are thus lost (unless you save()).

Related question: How do I set attributes on a model and make sure they're accessible everywhere else without having to save() the model?

update

Hi!

Model#update causes change/update event nomatter whether properties really change or not. Feature or just don't care?

TIA,
--Vladimir

Constructors being called twice

I'm using the CS version of Spine, and I just noticed that all my constructors are being called twice. What could be the reason for this?

Not a lot of comments

The spine code lacks comments. One might say it's self explanitory but any sane open source project should have some kind of doc-commenting-like comments. kthx.

Documentation typo

In: "Creating models is slightly different from creating classes, since the create() function is already reserved by models. Models are created with the setup() function, passing in the model name and an array of attributes."

I guess it should be "since the create() function is already reserved by classes."

Model: reuse at server-side

Hi!

Are there experiments/tutorials in reusing Models at server-side? Say, mongodb/redis-backed Models

TIA,
--Vladimir

Controller's delay function does not return the setTimeout() response

It might be outside the scope of the delay function, but I have a situation where I wanted to cancel certain set timeout events.

For example, I have a keyup event which can fire an Ajax event. However when (within a specified time) another keypress is done, the ajax event should not be fired but instead the most recent delayed event.

Currently I implemented this the following way:

            this.timeoutCalls = [];

            <snip>

            for( i=0; i<this.timeoutCalls.length; i++) {
                window.clearTimeout( this.timeoutCalls[i] );
            }
            wrapThis = this;
            this.timeoutCalls.push( window.setTimeout( function() { wrapThis.timeout(); }, 1000) );

This way I'm always sure only the last ajax call is fired.

However I can not use the delay() function of the controller as this does not return the setTimeout()'s return value.

Where did ajaxPrefix go? (CS Branch)

I'm trying to use the CS branch with the Ajax adapter and Rails.

In this branch the ajaxPrefix option seems to have been removed. Is there a reason for this? Will it be added in, or am I missing something obvious?

Spine.List

Spine.List.render() should skip destroyed: true records

Better code commenting

Hello, I am trying to learn spine.js reading docs and examples, but I've found that documentation is not full. There are many methods which are not covered in docs, something like refreshElements or delegateEvents in Controllers and so on. Even worse that code of the library has no comments. Backbone.js has good docs and good comments for all methods. I think that this is crucial for easy adaptation of your library. What do you think?

Dependency on external libraries

Spine still makes certain expectations of your DOM manipulation and event libraries, specifically Spine.Route and Spine.Manager, which use functions like $().bind and $().hasClass respectively.

I have built a compatibility layer to get Spine to work with Dojo specifically and you can see in these files how I have modified Route and Manager to use Dojo functions:

https://github.com/lyleunderwood/spine/tree/master/dojo

This is obviously not a solution, but it clearly illustrates the problem. I'm wondering if there is any intention to change this. I don't really expect Spine.Tabs to be completely agnostic, but probably the router, Spine.Model.Ajax, etc.. I just want to open this discussion.

You might also notice that I've ported everything in Spine to work with module loaders that use the AMD format. I'm using it with requireJS right now which is really nice alongside Dojo.

Default Array Attributes

While using Spine, we came across a situation where we wanted to initialize an attribute with an array. However, the attribute is a reference to the original array, rather than generating new arrays.
https://gist.github.com/1035948
Here is a test case for our desired behavior. Do you have any suggestions? We looked into modifying the setup to take an extra parameter init: Asset = Spine.Model.setup("AssetNew", ["name", "arrayTest"], function() {this.arrayTest = []});
However if we do this we don't want to break any other initialization behavior. Can you tell us where it is the best place to call this new init function?

Why does SomeModel.find(id) return non-identical instances?

I can see that by design every call to find(id) returns a distinct instance. I wonder what is the reason behind it.

This kind of behaviour causes problems at times, as it makes updating the same instance virtually impossible. This is very often inconvenient as different controllers might keep references to models and want respond to their changes. However the way it works now, references just become obsolete. It's very difficult to predict when exactly that happens.

Model ordering by attribute

Hi,

First of all, I'd like to say this is a great framework and the docs are great. I started to play around with this it saves a lot of frontend coding for me.

One thing I think is missing is Model ordering. For example, if I want to retrieve a model and order it by date, I'd have to retrieve everyone, parse out the date and then put it into a separate array ordered by date.

Thanks,
Ray

Optionally suppress event trigger on models

It would be nice if there was a way to call the various methods on a model without triggering events.
This could be an additional parameter:

var task = Task.init({name: 'abc'});
task.save(false);
Task.create({name: 'abc'}, false);

Or maybe an option, so it could deal with optional validations as well:

Task.create({name: 'abc'}, {validate: false, silent: true});

What do you think? Or is this already possible and I just didn't see it?

Docs don't properly specify character set.

Your code block that uses Unicode right-arrow characters looked mangled on my browser (Safari 5.0.4) and so I checked your markup. It contains a META element unlike any I've personally seen before. Below are two that will work:

<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta charset=utf-8>

Documentation issues

When going through the documentation at http://maccman.github.com/spine/ I came across certain oddities and wanted to check if this was due to mistypes, missing information or due to code imperfections.

In the validation topic it describes that you should extend your model with the validation function. However (after digging through spine.js) I found out that the validation function should be included instead of extended. This seems to be either an implementation issue or a documentation issue.

At certain times it is assumed that certain libraries are included, but this is not specified in the documentation. It took me some time to find out they were required. It would be helpful if this was named explicitly.

For example:

Under serialization it is said that Spine supports JSON natively. Although most browsers support natively include json functionality, it is not default behavior. Certain browsers do not include it and require you to include the json2.js library.

Under persistence it is not described that the external spine.model.local.js should be included. Althoug this is described at the end of the document, it would be nice if it was mentioned in the explanation of persistence.

Same goes for the spine.model.ajax.js.

Under the routing chapter it is described correctly :-)

Lastly, when you first come in contact with Spine it should be advised to go through the documentation first and then to the example's (instead of first referring to the exmaples). When you go to the examples cold-turkey, you end up flabbergasted. Once you read through the documentation first and then go to the examples, it is easier to understand.

instance vs. class properties

Hi,

Reading the Spine.js' doc and also your book, I can't really get the difference between instance and class properties...

Could you explain when to use include / when to use extend with the advantage of each?

Thanks in advance.

Splitting things up

Hi,

I'm really liking the look of spine and although it is already a tiny library, I'm wondering if it could be split into a few pieces. I love the prototypal inheritance stuff and have a use for it without controllers and models, I also see times where models could be used without necessarily needing controllers... how about going super-micro and having spine.class.js, spine.model.js and spine.controller.js?

Class.create is a confusing name

MyClass.create is a factory for subclasses, not a factory for instances of the class, but there's nothing in the name that suggests that's true. Might I suggest MyClass.beget instead?

Validation

Is there an example somewhere where this is working? Do you need to check what the Model's validation method returns somewhere in the Controller prior to creation? I've got my model alerting an error message when I've entered something not valid, but then the item is still created and placed into localstorage.

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.