1

This is first time I am using a framework for development and stuck with the very first step.

I am converting a Flex application to Javascript application and using backbone as framework.

I have to load a text file which is in name value format.

<!doctype html>
<html>
<head>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js'></script>
<script>
var ResourceBundleCollection = Backbone.Collection.extend({
url:'ResourceBundle.txt',
});
var resourceBundleCollection = new ResourceBundleCollection();
resourceBundleCollection.fetch();
</script>
</head>
<body>
</body>
</html>

The ResourceBundle.txt includes the content in following format

location_icon=../../abc/test.png
right_nav_arrow_image=assets/images/arrow.png
right_nav_arrow_image_visible=true

It is throwing following error not well-formed

I could load the text file easily using JQuery and parse it

$.ajax({
type : "GET",
url : "ResourceBundle.txt",
datatype : "script",
success : resourceXMLLoaded
});

and parse it using the following code

var lines = txt.split("\n");
for(var i=0;i<lines.length;i++) {
if(lines[i].length > 5) {
var _arr = lines[i].split("=");
resourceBundleObj[$.trim(_arr[0])] = $.trim(_arr[1]);
}
}

Please advice how to achieve the same results in backbone.js

Nitin Mukesh
  • 4,266
  • 6
  • 22
  • 26

2 Answers2

5

If you MUST use plain text to support this, you can override Backbone.Collection.parse to achieve what you need.

In addition to that, you may also want to create a ResourceBundleModel to host each item in the ResourceBundleCollection.

You can see a demo here: http://jsfiddle.net/dashk/66nkF/

Code for Model & Collection is here:

// Define a Backbone.Model that host each ResourceBundle
var ResourceBundleModel = Backbone.Model.extend({
    defaults: function() {
        return {
            name: null,
            value: null
        };
    }
});

// Define a collection of ResourceBundleModels.
var ResourceBundleCollection = Backbone.Collection.extend({
    // Each collection should know what Model it works with, though
    // not mandated, I guess this is best practice.
    model: ResourceBundleModel,

    // Replace this with your URL - This is just so we can demo
    // this in JSFiddle.
    url: '/echo/html/',

    parse: function(resp) {
        // Once AJAX is completed, Backbone will call this function
        // as a part of 'reset' to get a list of models based on
        // XHR response.
        var data = [];
        var lines = resp.split("\n");

        // I am just reusing your parsing logic here. :)
        for (var i=0; i<lines.length; i++) {
            if (lines[i].length > 5) {
                var _arr = lines[i].split("=");

                // Instead of putting this into collection directly,
                // we will create new ResourceBundleModel to contain
                // the data.
                data.push(new ResourceBundleModel({
                    name: $.trim(_arr[0]),
                    value: $.trim(_arr[1])
                }));
            }    
        }

        // Now, you've an array of ResourceBundleModel. This set of
        // data will be used to construct ResourceBundleCollection.
        return data;
    },

    // Override .sync so we can demo the feature on JSFiddle
    sync: function(method, model, options) {
        // When you do a .fetch, method is 'read'
        if (method === 'read') {
            var me = this;

            // Make an XHR request to get data
            // Replace this code with your own code
            Backbone.ajax({
                url: this.url,
                method: 'POST',
                data: {
                    // Feed mock data into JSFiddle's mock XHR response
                    html: $('#mockData').text()
                },
                success: function(resp) {
                    options.success(me, resp, options);
                },
                error: function() {
                    if (options.error) {
                        options.error();
                    }
                }
            });
        }
        else {
            // Call the default sync method for other sync method
            Backbone.Collection.prototype.sync.apply(this, arguments);
        }
    }
});

Backbone is designed to work with a RESTful API through JSON natively. It however is a library that is flexible enough to fit your need, given enough customization.

DashK
  • 2,640
  • 1
  • 22
  • 28
  • Dashk I can't thank you enough for the detailed explanation and creating the sample. This helped me understand the basics of collection. I am now reading the following documentation to understand backbone addyosmani.github.com/backbone-fundamentals I need one more help related to this. I want to access the values based on names so I added the getItem method jsfiddle.net/wBkVh Is this the correct implementation or is there any other way to get the value without adding loop. I tried using getter method but it is not working possible due to data is an array. – Nitin Mukesh Feb 14 '13 at 03:33
  • Thanks a lot Dashk. Yours look like a better solution. I was using this. var pattern = new RegExp(searchtext, "im"); return (this.filter(function(data) { return pattern.test(data.get('name')); }))[0].get('value'); – Nitin Mukesh Feb 15 '13 at 09:26
2

By default a collection in Backbone will only accept a JSON formatted collection. So you need to convert your input to JSON format:

[{"name": "name", "value": "value},
 {"name": "name", "value": "value}, ...
]

Of course you can override the default behaviour: Overriding backbone's parse function

Community
  • 1
  • 1
Drejc
  • 14,196
  • 16
  • 71
  • 106
  • Many thanks Drejc. Dashk I can't thank you enough for the detailed explanation and creating the sample. This helped me understand the basics of collection. I am now reading the following documentation to understand backbone http://addyosmani.github.com/backbone-fundamentals/ I need one more help related to this. I want to access the values based on names so I added the getItem method http://jsfiddle.net/wBkVh/ Is this the correct implementation or is there any other way to get the value without adding loop. I tried using getter method but it is not working possible due to data is an array. – Nitin Mukesh Feb 13 '13 at 04:13
  • No problem. It took me a while to wrap my head around the "Backbone" way of doing things. But once you master the basics it is a really nice framework to work with. – Drejc Feb 13 '13 at 07:53