0

I'm trying to create a simple web system that loads an arbitrary number of items (each which defines its own HTML rendering and dynamic behavior) in a container. The container will determine which items to load, load their HTML from the server, then initialize them with parameters. Here's a simplified example:

<!-- container.xhtml -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"/>
    <script>
        var params = {};
        $(document).ready(function() {
            params = {'text': 'Text A'};
            resp = $.get('item.xhtml', function(data) {
                $('.container').append(data);
                // want to initialize the new node
                data.init(params);
            });
            params = {'text': 'Text B'};
            resp = $.get('item.xhtml', function(data) {
                $('.container').append(data);
                // want to initialize the new node
                data.init(params);
            });
        });
    </script>
    <div class="container">
    </div>
</body>
</html>

And an example of an item:

<?xml version="1.0" encoding="UTF-8"?>
<!-- item.xhtml -->
<div class="item" xmlns="http://www.w3.org/1999/xhtml">
    <script>
        <!-- want this function to be called for each "item" node created -->
        function initialize(item, params) {
            item.find('.dynamic').text(params['text']);
        }
    </script>
    <div class="some_class">
        Some Content
    </div>
    <div class="dynamic">
        Replace me
    </div>
</div>

The challenge I face is I'm unable to assign the on_load function with its item. I can't give div[@class='item'] an ID because it may be loaded multiple times.

I want to maintain a simple container that needs only load a file and call some prescribed function to initialize the item. If it's absolutely necessary to modify the container to enable this model, it's important to minimize the interface between the container and item.

Is it possible to change only the code for item.xhtml such that when it is loaded by container.xhtml, the calls to data.init() will call the initialize() function with the appropriate item node and params? If not, how can one achieve this model by other means? Is there a better approach for this problem?

Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
  • All script in the loaded content is disabled, so you may want to find another way to get your script.. check out this old question I had so you can see that the entire script tag is remove (http://stackoverflow.com/questions/1821047/very-interesting-jquery-load-behavior-a-bug-or-solution) – Mottie Mar 01 '11 at 00:21

2 Answers2

1

Simple example to point in a direction:

What about attaching your code to the element, using a custom event, and then call that event when its loaded. Something like...

    <script>
          $('.item').bind("init",function(params){
            this.text(params['text']);
         });
    </script>

and calls it

EDIT : Correct my stupid calling snytax

$('.item:last').trigger('init',[{'text': 'Text B']);
macarthy
  • 3,074
  • 2
  • 23
  • 24
  • That's close to what I need - except I want to be careful that one item loading doesn't affect others. In the example, I think `$('.item').bind` could affect other nodes. While that may work, it seems messy. Is there no way to reference "the element in which this script resides"? – Jason R. Coombs Mar 01 '11 at 04:49
  • I tried this with http://paste.polimetrix.com/fvJpj and http://paste.polimetrix.com/xQ8a4, but it doesn't work. No errors are emitted, the init functions just don't run. If I change 'init' to 'foo', I get an error, `$(".item:last").foo is not a function`. – Jason R. Coombs Mar 01 '11 at 17:24
  • 1
    +1 The .bind was the right thing to do. To call it, use .trigger('init'). – Jason R. Coombs Mar 02 '11 at 17:00
0

After several hours of flailing, I managed to get pretty close.

Container:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"/>
    <script>
        var params = {};
        $(document).ready(function() {
            param_list = [
                {'text': 'Text A'},
                {'text': 'Text B'},
                {'text': 'Text C'}];
            for(param_index in param_list) {
                var params = param_list[param_index];
                init_func = function(params) {
                    return function(data) {
                        var node = $(data.documentElement)
                        $('.container').append(node);
                        // want to initialize the new node
                        node.trigger("initialize", [params]);
                    };
                }
                resp = $.get('item.xhtml', init_func(param_list[param_index]));
            }
        });
    </script>
    <div class="container">
    </div>
</body>
</html>

Item:

<?xml version="1.0" encoding="UTF-8"?>
<div id="item" xmlns="http://www.w3.org/1999/xhtml">
    <script>
        <!-- want this function to be called for each "item" node created -->
        $('#item').bind("initialize", function(event, params) {
            $(this).find('.dynamic').text(params['text']);
        }).removeAttr('id');
    </script>
    <div class="dynamic">
        Other content
    </div>
</div>

Note there are two limitations:

  1. The item designer must assign an ID to the node and remove it during construction. This appears to be the only way for his own javascript to bind to his own node. The ID has to be removed so it doesn't conflict with subsequently-added items.
  2. This fails in Chrome (with WRONG_DOCUMENT_ERR) because Chrome honors the W3C standard that says a DOM node can't be added from one document to another. It works in Firefox, however. Next step is to figure out how to load a node dynamically without the WRONG_DOCUMENT_ERR.
Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93