2012-11-19 157 views
0

我想創建我自己的jQuery小部件。我有我所有的HTML和jQuery寫的,和我想要動態地將其添加到使用頁面:Not loading Knockout.js

<div class='searchbar'></div> 

的Widget使用Knockout.js和代碼一個很好的協議,我寫我自己。我遇到的問題(我懷疑)處理腳本的加載順序。

這是我得到的錯誤:

Timestamp: 11/20/2012 9:26:13 AM 
Error: Error: Unable to parse binding attribute. 
Message: SyntaxError: syntax error; 
Attribute value: value: query, valueUpdate: 
Source File: http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-1.2.1.js 
Line: 44 

如果我註釋掉淘汰賽結合塊,一切正常(減去具有下拉菜單中的值)。不知道爲什麼它不通過這個代碼。

我的jQuery如下,但它現在正在做什麼的現場版本可用HERETHIS是一個工作版本,沒有嘗試加載所有動態,只是讓你知道它應該看起來像什麼。

(function() { 

    var jQuery; 

    /******** Load jQuery if not present *********/ 
    if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.8.0') { 
     var script_tag = document.createElement('script'); 
     script_tag.setAttribute("type","text/javascript"); 
     script_tag.setAttribute("src", 
      "http://code.jquery.com/jquery-1.8.0.min.js"); 
     if (script_tag.readyState) { 
      script_tag.onreadystatechange = function() { // For old versions of IE 
       if (this.readyState == 'complete' || this.readyState == 'loaded') { 
        scriptLoadHandler(); 
       } 
      }; 
     } else { 
      script_tag.onload = scriptLoadHandler; 
     } 
     (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag); 
    } else { 
     jQuery = window.jQuery; 
     main(); 
    } 

    /******** Called once jQuery has loaded ******/ 
    function scriptLoadHandler() { 
     jQuery = window.jQuery.noConflict(true); 
     main(); 
    } 

    /******** Our main function ********/ 
    function main() { 
     jQuery(document).ready(function($) { 

      $("head").append("<link href='style.css' rel='stylesheet' type='text/css' />");   
      $.getScript("http://knockoutjs.com/js/jquery.tmpl.js", function(){}); 
      $.getScript("http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-1.2.1.js", function(){}); 

      $(".searchBox").append("<div id='refine'>Creator</div>"); 
      $(".searchBox").append("<input class='inline' placeholder='Search...' size='30' type='text' id='search' data-bind='value: query, valueUpdate: 'keyup'' autocomplete='off' />"); 
      $(".searchBox").append("<div id='submit'>Search</div>"); 
      $(".searchBox").append("<div id='refineDropdown'><ul id='refineList'></ul></div>"); 
      $(".searchBox").append("<div id='dropdown'><ul data-bind=\"template: { name:'obj', foreach:objects }, click: function(){ $('.listObjItem').on('click', function(){ $('#search').val($(this).text()); $('#dropdown').hide(); $('#search').focus();});}\"></ul></div>"); 
      $(".searchBox").append("<script type='text/html' id='obj'><li class='listObjItem'><span data-bind='text: name'></span>&nbsp;in&nbsp;<strong data-bind='text: type'></strong></li></script>"); 

      /* Begin Knockout Bindings */ 

      var objects = [ 
       {name:"Pacers Game",    type:"Activities"}, 
       {name:"Colts Game",    type:"Activities"}, 
       {name:"Ice Game",     type:"Activities"}, 
       {name:"Indians Game",    type:"Activities"}, 
       {name:"Fever Game",    type:"Activities"}, 
       {name:"Purdue Game",    type:"Activities"}, 
       {name:"Campaign Posters",   type:"Projects"}, 
       {name:"Campaign Media",   type:"Projects"}, 
       {name:"Event Booking",   type:"Projects"}, 
       {name:"New Product Seminar",  type:"Projects"}, 
       {name:"State Fair",    type:"Projects"}, 
       {name:"Draft Designs",   type:"Tasks"}, 
       {name:"Design Posters",   type:"Tasks"}, 
       {name:"Review Designs",   type:"Tasks"}, 
       {name:"Book Venue",    type:"Tasks"}, 
       {name:"Decorate ICC",    type:"Tasks"}, 
       {name:"Book Live Music",   type:"Tasks"}, 
       {name:"Arrange for DJ Payment", type:"Tasks"}, 
       {name:"Event Cleanup",   type:"Tasks"} 
      ]; 

      var viewModel = { query: ko.observable('') }; 

      viewModel.objects = ko.dependentObservable(function() { 
       var search = this.query().toLowerCase(); 
       return ko.utils.arrayFilter(objects, function(obj) { 
        return obj.name.toLowerCase().indexOf(search) >= 0; 
       }); 
      }, viewModel); 

      ko.applyBindings(viewModel); 

      /* End Knockout Bindings */ 

      var refine = ["All", "ID", "Creator", "Name", "Description", "Last Modified"]; 

      refine = refine.sort(); 
      for (var i = 0; i < refine.length; i++) 
       $('#refineList').append('<li>' + refine[i] + '</li>'); 

      testLength(); 
      $("#dropdown").hide(); 
      $("#refineDropdown").hide(); 

      if($.browser.chrome) { 
       $('#search').css('height','26px'); 
       $('#search').css('padding','0px 5px 0px 5px'); 
       $('#refine').css('margin-right','-3px'); 
      } 
      else if($.browser.mozilla) { 
       $('#search').css('height','25px'); 
       $('#search').css('padding','0px 5px 0px 5px'); 
       $('#search').css('margin-top','-6px'); 
       $('#refine').css('margin-right','-1px'); 
      } 
      else if($.browser.msie) { 
       $('#search').css('height','22px'); 
       $('#search').css('padding','4px 5px 0px 5px'); 
      } 

      var $hidden = $('#hidden'); 
      $("input").keyup(function(e) { 
       testLength(); 
       $('#refine').removeClass('refineClicked'); 
       $('#refineDropdown').hide(); 
       if (this.value.length) { 
        var that = this; 
        $("#dropdown li").each(function() { 
         if ($(this).html().toLowerCase().indexOf(that.value.toLowerCase()) == -1) $(this).appendTo($hidden); 
        }); 
        $('#hidden li').each(function() { 
         if ($(this).html().toLowerCase().indexOf(that.value.toLowerCase()) !== -1) $(this).appendTo('#list'); 
        }); 
        $("#search").css('border-bottom-right-radius', '0px'); 
        $("#dropdown").show(); 
       } 
       else { 
        $("#dropdown").hide(); 
       } 
       if (e.which !== 40 && e.which !== 38) { 
        $('#dropdown li,#hidden li').each(function() { 
         $(this).removeClass('selected'); 
        }); 
        liSelected = null; 
       } 
      }); 

      $('#dropdown li').click(function() { 
       $('#search').val($(this).text()); 
       $('#search').focus(); 
       $("#dropdown").hide(); 
      }); 

      var li = $('li'); 
      var liSelected; 

      $('input').keydown(function(e) { 
       liSelected = $('#dropdown .selected'); 

       if (e.which === 40) { // down-arrow 
        if (liSelected.length) { 
         var next = liSelected.next(); 

         if (next.length) { 
          liSelected.removeClass('selected'); 
          liSelected = next.addClass('selected'); 
         } 
        } 
        else { 
         liSelected = $('#dropdown li').eq(0).addClass('selected'); 
        } 
       } 
       else if (e.which === 38) { // up-arrow 
        if (liSelected.length) { 
         var prev = liSelected.prev(); 

         if (prev.length) { 
          liSelected.removeClass('selected'); 
          liSelected = prev.addClass('selected'); 
         } 
         else { 
          liSelected = $('#dropdown li').eq(-1).addClass('selected'); 
         } 
        } 
        else { 
         liSelected = li.last().addClass('selected'); 
        } 
       } 
       else if (e.which === 13) { 
        $('#search').val(liSelected.text()); 
        $("#dropdown").hide() 
        $('#search').blur(); 
       } 
      }); 

      $('#refine').click(function() { 
       $("#dropdown").hide(); 
       if (!$('#refine').hasClass('refineClicked')) { 
        $('#refine').addClass('refineClicked'); 
        $('#refineDropdown').show(); 
       } 
       else { 
        $('#refine').removeClass('refineClicked'); 
        $('#refineDropdown').hide(); 
       } 
      }); 

      $('#refineDropdown li').click(function() { 
       var tmp = $('#refine').width(); 
       $('#refine').html($(this).text()); 
       $('#refine').removeClass('refineClicked'); 
       $("#refineDropdown").hide(); 
       testLength(); 
       $('#search').css('width', $('#search').width() + (tmp - $('#refine').width())); 
      }); 

      $('#submit').click(function() { 
       alert('Searching for ' + $('#search').val() + '...'); 
      }); 

      function testLength() { 
       if ($('#refine').text().length > 7) { 
        $('#refine').html($('#refine').text().substring(0, 6) + "..."); 
       } 
       $('#dropdown').css('width', $('#search').width() + 4); 

       if($.browser.chrome) 
        $('#dropdown').css('margin-left', $('#refine').width() + 11); 
       else 
        $('#dropdown').css('margin-left', $('#refine').width() + 13); 
      } 
     }); 
    } 
}()); 

回答

0

我想出了一個解決方案。不是在腳本中動態加載,而是直接將它們放入HTML頁面的頭部。我可能會添加到我的腳本文件中檢查是否加載了外部庫,但是我認爲這會導致大量額外的不必要的工作。

對於未來這個問題的訪問者,下面的腳本的順序是絕對必要的,以便使Knockout的任何工作都能正常工作。另外,值得注意的是jQuery tmpl的加載速度比Knockout.js慢。當我試圖動態加載它們時,我有外部庫加載完成時會觸發的函數。儘管tmpl首先被列出,但Knockout總是首先加載(除非瀏覽器處理最後一次警報FIRST,然後回滾到之前的警報......如果這是錯誤,請糾正我)。

<head> 
     <title>Search Prototype</title> 
     <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script> 
     <script type="text/javascript" src="https://raw.github.com/jquery/jquery-tmpl/master/jquery.tmpl.js"></script> 
     <script type="text/javascript" src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.2.0.js"></script> 
     <script type="text/javascript" src="search.js"></script> 
    </head> 
+0

你確定你還需要jquery-tmpl嗎?您問題中的代碼不會在任何地方使用。另外,你指向'https:// raw.github.com/jquery/jquery-tmpl/master/jquery.tmpl.js',因爲github將它作爲'text/plain'服務,所以不會被解析。如果你真的想使用jquery-tmpl(請注意,該庫已被棄用!!),請改用此URL:'https:// rawgithub.com/jquery/jquery-tmpl/master/jquery.tmpl.js'。不能在生產中使用,我強烈建議您不要使用該庫,並簡單地使用Knockout的內部模板引擎,您已經在使用該模板引擎。 –

0

您應該嘗試使用AMD(如require.js)來按順序加載腳本。