2011-07-28 75 views
1

我是新來的JavaScript所以maby這是衆所周知的/愚蠢的/無用的,但我想讓事情發生與DOM元素一旦加載(什麼都沒發現搜索本網站或谷歌,但很難用幾句話來解釋這一點)。例如,當一個大頁面加載時,我想隱藏/添加onlick事件/等。元素一旦出現在用戶的屏幕上,不在$(document).ready()上。我寫了一個簡單的類(僅用於培訓,閉包對我來說是新的,所以可能會有很多錯誤),但我希望使用更好的商業用途(在我正在幫助開發的站點上)。下面是我的源代碼 - 莫比它會解釋什麼,我想要更好的,然後這個帖子:我是新來的英語水平(:一旦元素被加載,Javascript綁定元素事件

function MY_loader() { 
    function container() { 
     this.add_event = function(new_event,obj_selector,settings) { 
      if(typeof(settings)!='object') { 
       settings={}; 
      } 
      if(typeof(settings.event_id)!='string') { 
       settings.event_id=gen_new_event_id(); 
      } 
      settings=$.extend({},default_settings,settings); 
      settings.obj_selector=obj_selector; 
      settings.event=new_event; 
      events[settings.event_id]=settings; 
     } 

     this.execute_events = function(if_force) { 
      if(typeof(if_force)=='undefined') { 
       if_force=false; 
      } 
      if(html_is_loaded&&!if_force) { 
       return; 
      } 
      var temp_obj; 
      for(var event_name in events) { 
       temp_obj=$(events[event_name].obj_selector); 
       if(temp_obj.length || (html_is_loaded && events[event_name].if_force)) { 
        temp_obj.each(function() { 
         if(events[event_name].expect_multiple) { 
          if($(this).data('my_loader_'+events[event_name].event_id+'_executed')) { 

           return; 
          } 
         } 
         if(events[event_name].event_type!='func') { 
          $(this).bind(events[event_name].event_type+'.'+events[event_name].event_id,events[event_name].event); 
         } 
         else { 
          events[event_name].event($(this)); 
         } 
         if(events[event_name].expect_multiple) { 
          alert('here'); 
          $(this).data('my_loader_'+events[event_name].event_id+'_executed',1); 
         } 
        }); 
         //alert(events[event_name].obj_selector+' '+events[event_name].event_type); 
        if(!events[event_name].expect_multiple) { 
         delete events[event_name]; 
        } 
       } 
      } 
      if(!html_is_loaded) { 
       var cur_time=new Date().getTime(); 
       setTimeout('MY_loader().execute_events();',Math.max(Math.min(tick_time-(cur_time-last_tick_time),tick_time),0,min_tick_diff)); 
       last_tick_time=cur_time; 
      } 
     } 

     this.html_is_loaded_set=function(if_html_is_loaded) { 
      html_is_loaded=if_html_is_loaded?true:false; 
     }; 

     this.html_is_loaded_get=function() { 
      return html_is_loaded?true:false; 
     }; 

     return this; 
    } 
    function instance(if_strat) { 
     if(typeof(class_is_loaded)=='undefined'||!class_is_loaded) { 
      load_class(); 
     } 
     return container(if_strat); 
    } 

    var load_class=function() { 
     this.class_is_loaded=true; 
     this.events = {}; 
     this.allowed_event_id_chars='abcdefghijklmnopqrstuvwxyz'; 
     this.default_settings={ 
      'event_type':'click', 
      'if_force':false, 
      'expect_multiple':false 
     }; 
     this.tick_time=500; 
     this.min_tick_diff=100; 
     this.last_tick_time=0; 
     this.html_is_loaded=false; 
     MY_loader().execute_events(); 
     $(document).ready(function(){ 
      MY_loader().html_is_loaded_set(true); 
      MY_loader().execute_events(true); 
     }); 
    } 

    var gen_new_event_id=function() { 
     for(var new_id=gen_random_id();typeof(events[new_id])!='undefined';new_id=gen_random_id()); 
     return new_id; 
    } 

    var gen_random_id=function() { 
     var allowed_event_id_chars_size=allowed_event_id_chars.length; 
     var new_id=''; 
     for(var i=0;i<10;i++) { 
      new_id+=allowed_event_id_chars[get_random_int(0,allowed_event_id_chars_size-1)]; 
     } 
     return new_id; 
    } 

    function get_random_int(min, max) 
    { 
     return Math.floor(Math.random() * (max - min + 1)) + min; 
    } 

    return new instance(); 
} 
//Add click event to #some_selector (once and dont check after it) 
MY_loader().add_event(function() { 
    alert($(this).val()); 
}, '#some_selector'); 
//Hide elements as soon as they are loaded. 
//We expect multiple elements with this selector, so it will 
//check for this elements untill document is loaded, but this function 
//will be applied only one time for each element. 
MY_loader().add_event(function(obj) { 
    obj.hide(); 
    alert('This should happen before DOM is completely loaded!'); 
}, '.some_other_selector',{'event_type':'func','expect_multiple':true}); 
//This alert should be outputted the last 
$(document).ready(function(){ 
    alert('Document is fully loaded!'); 
}); 

謝謝大家提前

UPD:爲了使這個問題!更有趣一點,因爲它看起來太具體了,我必須補充一點:大多數瀏覽器在完全加載之前就開始頁面渲染(這似乎因爲某些原因而不是衆所周知的),下面是幾個鏈接:

  1. http://en.wikipedia.org/wiki/Incremental_rendering
  2. When do browsers start to render partially transmitted HTML?
  3. http://www.vbulletin.org/forum/showthread.php?t=161099

所以,我的問題應該得到更廣泛的,因爲這增加的頁面加載增加了許多針對開發商的問題:用戶可以點擊非工作按鈕之前加載頁面時,有些事情是隱藏的JavaScript負載可能會顯示,他們可以是醜陋的,等等(這是我的問題的例子)。其他開發者是否忽略了這個問題?請糾正我,如果我錯了。

+0

你是否正在使用一些在構建DOM之前實際呈現頁面的瀏覽器?我不知道有這樣的瀏覽器。 – kinakuta

+0

@kinakuta:幾乎所有的瀏覽器都是這樣:例如firefox(100%測試)。閱讀評論:http://php.net/manual/ru/function.flush.php,但這不是唯一的情況下(甚至啓用gzip)。 – XzKto

+1

您可能已經知道這一點,但document.ready()與body onload不同。 onload等待加載所有資源(images/css/etc),但document.ready()不加載。除非你有一個巨大的DOM結構,否則用戶在.ready()觸發之前可以選擇任何東西似乎不太可能。 –

回答

0

如果您關注的是,你不希望用戶看到的網頁之前,它是最終的,你也許可以逃脫做DOM修改通俗易懂,如:

<a href="#" id="test">Test</a> 
<script type="text/javascript" src="enhancePage.js"></script> 

因爲有問題的節點在解析腳本之前存在於DOM中,您可以使用它。

+0

我也想過,但我不想混合HTML與JavaScript - 這是很難維護(完整的JavaScript文件更容易閱讀),我當然希望我所有的JavaScript緩存。 – XzKto

+0

然後,只要確保在所有節點寫完腳本後都要包含腳本,腳本可能會關心。 – Tom

+0

它將與$(document).ready()相同,因爲一些節點在頁面的末尾。 – XzKto