开发者

Elegant clean way to include HTML in JavaScript files?

I'm building a small app with a few modal dialog windows. The windows require a tiny bit of HTML. I've hard coded the window HTML in the javascript library but am not thrilled with this solution. Is there a more elegant way to do this? It seems that JavaScript doesn't have multi line strings/heredoc syntax.

var html = "<div id='email_window'><h2>Email Share</h2><div>";
html = html + "<form action='javascript:emailDone();' method='post'>";
html = html + "<div><label for='to'>To</label><input id='to' type='text'></div>";
html = html + "<div><label for='from'>From</label><input id='from' type='text' value='" + email + "'></div>";
html = html + "<div><label for='subject'>Subject</label><input id='subject' type='text' disabled='disabled' value='" + subject + "'></div>";
html = html + "<div><label for='body'>Body</label><input id='body' type='text' disabled='disabled' value='" + body + "'></div>";
html = html + "<div><input type='submit' value='Send'&g开发者_Go百科t;<input type='button' value='Cancel' onClick='javascript:$.fancybox.close();'></div>";
html = html + "</form></div>";

$("#data").html(html);

Added to clarify the original message-

Any solution can't use Ajax/XHR to pull in the template file because the javascript library will be on a different domain that the html file it's included in It's a little like ShareThis. The library will be included on a number of different sites and attached to the onClick event of any anchor tag inside divs with attribute sharetool="true".

For example:

http://www.bar.com - index.html
<html>
...
<script type="text/javascript" src="http://www.foo.com/sharetool.js"></script>
...
<body>
<div sharetool="true">
</div>
...
</html>


You can include the HTML as regular markup at the end of the page, inside an invisible div. Then you're able to reference it with jQuery.

You then need to programmatically set your variable fields (email, subject, body)

<div id='container' style='display: none;'>
  <div id='your-dialog-box-contents'>
    ...
    ...
  </div>
</div>

<script type='text/javascript'>
  $("#from").val(from);
  $("#subject").val(subject);
  $("#body").val(body);
  $("#data").html($("#your-dialog-box-contents"));
</script>


Templates. Pick your poison

  • EJS
  • jQuery templates (nb: development discontinued)
  • underscore templates
  • mustache
  • jResig micro templates

Either inline them as script blocks or load them using ajax as external resources.

I personally use EJS as external template files and just get EJS to load them and inject them into a container with json data bound to the template.

new EJS({ 
    url: "url/to/view"
}).update('html_container_name', {
    "foobar": "Suprise"
});

And then view files use generic view logic.

// url/to/view
<p> <%=foobar %></p>


For multiline strings (no frameworks, just javascript) there are several solutions. See my answer to this SO Question. You could combine that with some simple templating:

String.prototype.template = String.prototype.template ||
        function (){
            var  args = Array.prototype.slice.call(arguments)
                ,str = this
                ,i=0
                ;
            function replacer(a){
                var aa = parseInt(a.substr(1),10)-1;
                return args[aa];
            }
            return  str.replace(/(\$\d+)/gm,replacer)
};
//basic usage:
'some #1'.template('string'); //=> some string
//your 'html' could look like:
var html =
  [ '<form action="javascript:emailDone();" method="post">',
    ' <div><label for="to">To</label>',
    '       <input id="to" type="text"></div>',
    ' <div><label for="from">From</label>',
    '       <input id="from" type="text" ',
    '         value="$0"></div>',
    ' <div><label for="subject">Subject</label>',
    '      <input id="subject" type="text" disabled="disabled" ',
    '        value="$1"></div>',
    ' <div><label for="body">Body</label>',
    '      <input id="body" type="text" disabled="disabled" ',
    '        value="$2"></div>',
    ' <div><input type="submit" value="Send"><input type="button" ',
    '        value="Cancel" ',
    '        onClick="javascript:$.fancybox.close();"></div>',
    '</form>'
  ] .join('').template(email, subject, body);


Personally I like building DOM trees like this:

$('#data').html(
    $('<div/>', {
        id: 'email_window',
        html: $('<h2/>', {
            html: 'Email Share'
        })
    }).after(
        $('<form/>', {
            action: 'javascript:emailDone();',
            method: 'post',
            html: $('<div/>', {
                html: $('<label/>', {
                    for: 'to',
                    html: 'To'
                }).after($('<input/>', {
                    id: 'to',
                    type: 'text'
                }))
            }).after(
                ... etc
            )
        })
    )
);


There is 2 solutions tto your problem: - An alternative to the heredoc Syntax in javascript is to escape the newline char with \ :

var tpl = "hello\
stackoverflow\
World !";

The char is escaped so ignored, and it wont take place in the resulting string.

You can also create a plain html file with your template, and in your js script you create a hidden iframe and load the crossdomain html template. You can now access the document object of the iframe and retreive body.innerHTML. In theory! I Didn't tested this solution yet....


You're right, JS doesn't have heredocs or multi-line strings. That said, the usual approach to this is to have the HTML in...the HTML, and show or hide it as appropriate. You're already using jQuery, so you're most of the way there:

<div style="display:none;">
    <form method='post' class="email">
         <input id='from' type='text'> <!-- other form fields omitted for brevity -->
    </form>
    <form method='post' class="facebook"></form> <!-- again, omitted for brevity -->
</div>

Then, you can populate the form and toss it in the right spot:

$('#data').html($('form.email').find('input#from').val(email).end().html());


Cook.js

div([
  button({click:[firstEvent, secondEvent]},
         'You can bind (attach) events on the fly.'),
  p('Here are some popular search engines'),
  ul([
    li([
      a('Google', {href:'http://www.google.com'})
    ]),
    li([
      a('Bing', {href:'http://www.bing.com'})
    ]),
    li([
      a('Yahoo', {href:'http://www.yahoo.com'})
    ])
  ])
]);

how it works

Objects = Attribute & Events
    -> {href:'facebook.com', src:'static/cat.gif', ng-bind:'blah'}
String  = Text or Html
    -> 'hello world'
Array   = Elements
    -> [a('hello world', {href:'facebook.com'}), img({src:'static/cat.gif'})] 

more on cook.js!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜