简体   繁体   English

从脚本标记中排除HTML

[英]Exclude HTML from script tag

I'm trying to learn Handlebars.js and thought of a way to get use of it in a site im making. 我正在尝试学习Handlebars.js,想到了一种在网站中使用它的方法。 It's a one page site which will have two containers with three divs in each which will contain embedded Soundcloud players through their API. 这是一个单页网站,它将有两个容器,每个容器有三个div,它们将通过API包含嵌入式Soundcloud播放器。

When including the divs which contain the API requests in the script tag handled by Handlebars, the site behave very unreliable and shows only some of the six players. 当在Handlebars处理的脚本标记中包含包含API请求的div时,该站点表现得非常不可靠并且仅显示六个玩家中的一些。 It's not really consistent but can show different players all the time. 这不是真的一致,但可以一直展示不同的球员。 The problem seems to be in the Soundcloud javascript SDK but I don't feel to familiar to dig around in there too much. 问题似乎是在Soundcloud javascript SDK中,但我觉得不太熟悉在那里挖掘太多。

Therefore I thought of some way to exclude the player divs (see code) so that they're loading instantly and not being Handled as javascript, but still show up beneath the artist - title in the placeholder div (which is set to contain the result of the Handlebar script). 因此我想到了一些方法来排除玩家div(见代码),以便他们立即加载而不是作为javascript处理,但仍然显示在艺术家的下方 - 占位符div中的标题(设置为包含结果Handlebar脚本)。

The problem is that I can't come up with a nice way of doing this, are there any easy function (with Handlebars helpers maybe) that will help me do what I want? 问题是我无法想出一个很好的方法,有没有任何简单的功能(可能有Handlebars助手),这将帮助我做我想要的?

<div id="placeholder"></div>
<script id="player-template" type="text/x-handlebars-template">
            <div id="container1">
                    Artist1 - {{title1}}
                    <div id="player1"></div>
                    Artist2 - {{title2}}
                    <div id="player2"></div>
                    Artist3 - {{title3}}
                    <div id="player3"></div>
           </div>
           <div id="container2">
                    Artist4 - {{title4}}
                    <div id="player4"></div>
                    Artist5 - {{title5}}
                    <div id="player5"></div>
                    Artist6 - {{title6}}
                    <div id="player6"></div>
            </div>
    </script>
    <script src="js/handlebars_title_script.js"></script>

One solution is of course to make one Handlebar template for each Artist - Title div and set the placeholder of each template to a div containing only Artist1 - {{title1}} but that really destroys the point of using Handlebars to minimize my HTML coding. 一个解决方案当然是为每个Artist - Title div制作一个Handlebar模板,并将每个模板的占位符设置为仅包含Artist1 - {{title1}}的div,但这实际上破坏了使用Handlebars来最小化HTML编码的重点。

Anyone got any tip for me how to solve this? 有人给我任何提示如何解决这个问题?

Edit 1: 编辑1:

I found another solution by changing in my javascript (which I didn't post at first so obviously you couldn't help me with that). 我通过更改我的javascript找到了另一种解决方案(我最初没有发帖,所以很明显你无法帮助我)。

$(document).ready(function() {
    var hey = "heya";
    SC.get("/users/artist/tracks", {limit: 1}, function(tracks){
    var title_data1 = tracks[0].title;
    hey = tracks[0].title;
    alert(title_data1);
    alert(hey)
    });


//Data that will replace the handlebars expressions in our template
var playerData = {
    title1 : hey,
};

document.getElementById( 'player-placeholder' ).innerHTML = playerTemplate( playerData );

});

Sorry for bad intendetion. 抱歉不好意思。 The only problem with this code is that title1 (in the variable playerData which is the Handlebars context) gets the first value of the variable hey ("heya"). 这段代码唯一的问题是title1(在变量playerData中是Handlebars上下文)得到变量的第一个值hey(“heya”)。 When it's alerted it pops up the real title, how can I make title1 use this value instead without nesting the variable in more javascript (since that's what causes the before mentioned error with players showing up weird)? 当它被警告它会弹出真实的标题时,如何让title1使用这个值而不将变量嵌入更多的javascript中(因为这是导致前面提到的错误,玩家出现奇怪的原因)?

Note: throughout the comments this answer has changed drastically. 注意:在整个评论中,这个答案已经发生了巨大的变化。 Please view the earlier revisions if you would like to see the evolution of this answer. 如果您希望看到此答案的演变,请查看早期版本。

After getting a hold of your JsFiddle example I was able to get it working in a way I think you wanted. 在掌握了JsFiddle示例后,我能够以我认为您想要的方式工作。

Working Demo 工作演示

HTML: HTML:

<body>
    <div id="wrapper">
        <div id="player-placeholder"><!-- rendered template goes here --></div>

        <!-- handlebars template: -->
        <script id="player-template" type="text/x-handlebars-template">
            {{#each tracks}}
                <div class="track">
                    <header class="header">
                        <span class="artist">{{user.username}}</span> - <span class="title">{{title}}</span>
                    </header>
                    <section class="player" data-uri="{{permalink_url}}">
                    </section>
                </div>
            {{/each}}
        </script>
    </div>
</body>

JavaScript: JavaScript的:

$(document).ready(function() {

  /*
    get your template string See:

    http://api.jquery.com/id-selector/
    http://api.jquery.com/html/
  */
  var source = $('#player-template').html();

  // compile the template into a handlebars function
  var template = Handlebars.compile(source);

  // initialize sound cloud api
  SC.initialize({
    client_id: '90fb9e15c1e26f39b63f57015ab8da0d'
  });

  /*
    This function will be called once the HTTP transaction
    started by SC.get(...) completes. Note, there's nothing
    wrong with doing this as an anonymous function, I'm
    simply assigning it to a variable to show that this
    is a distinct function that's called later
  */
  var callback = function(tracksResponse){
    /*
       once a response has been received, we'll use the response
       to generate a new context to pass to the template function.
       Note, you can use the template function in here because its
       within a closure. See:
       https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
    */
    var context = { tracks: tracksResponse };
    var html = template(context);

    /*
      assign the rendered html to your placeholder on the page
      see: http://api.jquery.com/html/
    */
    $('#player-placeholder').html(html);

    /*
      Now that the html is rendered and on the page, its time to
      setup the sound cloud players. Note the css classes I assigned
      to the track/player. This line selects all of the player's and
      runs the function over each. See:

      http://api.jquery.com/class-selector/
      http://api.jquery.com/each/
    */
    $('.track .player').each(function(index, e){
      var $this = $(this); // jQuery reference to the current object in 'each loop'

      /*
        I assigned the permalink_url of each track to an attribute called 'data-uri'
        This line gets the value of that attribute. See:

        http://api.jquery.com/data/#data2
      */
      var permalink = $this.data('uri'); 
      var urlParameters = '/&maxheight=100&maxwidth=300&format=json&sharing=false';

      /*
        finally we call the sound cloud oEmbed function feeding it the url
        stored in the element, as well as the actual element.

        (see the second argument of the each function: http://api.jquery.com/each/)
      */
      SC.oEmbed(permalink + urlParameters, e);
    });
  };

  // get tracks for your artist
  // Note the "limit" in the object controls the number of items returned
  // by sound cloud
  SC.get("/users/theshins/tracks", {limit: 5}, callback);
});

What went wrong? 什么地方出了错?

JavaScript is a single-threaded, asynchronous, event-driven language. JavaScript是一种单线程,异步,事件驱动的语言。 That giant mouth-full means JavaScript doesn't really have a notion of threading (I'm intentionally ignoring WebWorkers). 那个巨大的口碑意味着JavaScript并没有真正的线程概念(我故意无视WebWorkers)。 To work around that limitation, almost all IO in JavaScript is non-blocking (asynchronous). 要解决这个限制,JavaScript中的几乎所有IO都是非阻塞的(异步)。

Whenever an asynchronous IO transaction begins it immediately returns to the caller and code execution continues. 每当异步IO事务开始时,它立即返回调用者并继续执行代码。 Almost all IO transactions take a 'callback' or have an event that will be called when the IO transaction completes. 几乎所有IO事务都采用“回调”或具有在IO事务完成时将调用的事件。 That means the basic pattern for all IO operations follows something like this: 这意味着所有IO操作的基本模式遵循以下内容:

  • Create a callback function 创建一个回调函数
  • Call IO operation, passing it the arguments it requires to complete, plus the callback 调用IO操作,传递它需要完成的参数,以及回调
  • Execution returns immediately 执行立即返回
  • Sometime in the future, the callback function is called 将来的某个时候,会调用回调函数

In your original example $(document).ready(function() { ... }) queues an anonymous function to fire when the document.onReady event is raised. 在原始示例中, $(document).ready(function() { ... })一个匿名函数$(document).ready(function() { ... })队列,以便在引发document.onReady事件时触发。 Your original example, however, had two callbacks assigned. 但是,您的原始示例分配了两个回调。 This isn't a problem, an in fact .ready(...) is designed to accept and queue many callbacks. 这不是问题,事实上.ready(...)旨在接受并排队许多回调。 However, where you went wrong is you had two separate blocks of code that called SC.get(...) . 但是,如果你出错了,你有两个独立的代码块,它们调用了SC.get(...)

Technically if done right this wouldn't be a problem, but your first on ready callback's purpose was tasked to setup the page's HTML while your second callback tried to initialize the player controls based on html on the page. 从技术上讲,如果做得对,这不会是一个问题,但你的第一个准备回调的目的是设置页面的HTML,而你的第二个回调试图根据页面上的html初始化播放器控件。 Remember these events and IO operations are asynchronous, they'll fire in whatever order. 请记住,这些事件和IO操作是异步的,它们将以任何顺序触发。 Essentially this became a timing issue, you were attempting to initialize controls on the page, and generate HTML to display on the page at the same time. 基本上这成了一个计时问题,你试图初始化页面上的控件,并生成HTML以同时显示在页面上。

How it was fixed 它是如何修复的

To fix the timing issue you need to synchronize when you get your info, when you build your template HTML, and when you initialize your controls. 要解决时间问题,您需要在获取信息,构建模板HTML以及初始化控件时进行同步。 There's a lot of ways to do this and many frameworks support the idea of promises to help gain control over the order that asynchronous events are fired, and their callbacks called. 有很多方法可以做到这一点,许多框架支持promises的想法,以帮助控制异步事件被触发的顺序,并调用它们的回调。

I took the simple route and combined all of your SC.get calls in to one, then within it's callback I render the handlebars template and initialize the SoundCloud players. 我采用了简单的路线并将所有SC.get调用合并为一个,然后在其回调中我渲染了把手模板并初始化了SoundCloud播放器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM