2013-07-13 24 views
6

Tôi cần được thông báo khi một phần tử có nav 'lớp' được tạo khi tài liệu đang tải. Googling tôi tìm thấy MutationObservers và nghĩ rằng họ sẽ hoàn hảo, nhưng tôi dường như không thể làm cho nó hoạt động được.Xem để tạo yếu tố trong tập lệnh viết bằng mỡ?

// ==UserScript== 
// @name  ii-shortcuts 
// @namespace https://github.com/RedHatter 
// @include  * 
// @version  1 
// @run-at document-start 
// ==/UserScript== 

var observer = new MutationObserver(function(mutations) 
{ 
    mutations.forEach(function(mutation) 
    { 
     if (mutation.target.getAttribute('class') == 'nav') 
      GM_log('nav creation'); 
    });  
}); 
observer.observe(document, {subtree: true, attributes: true, attributeFilter: ['class']});  

Tôi cũng đã thử.

// ==UserScript== 
// @name  ii-shortcuts 
// @namespace https://github.com/RedHatter 
// @include  * 
// @version  1 
// @run-at document-start 
// ==/UserScript== 

var observer = new MutationObserver(function(mutations) 
{ 
    mutations.forEach(function(mutation) 
    { 
     if (mutation.addedNodes[0].getAttribute('class') == 'nav') 
      GM_log('nav creation'); 
    });  
}); 
observer.observe(document, {subtree: true, childList: true}); 

Nhưng trong trường hợp thứ hai là nhật ký 'nav creation' khi tải trang. Tôi đang thiếu gì?

+0

@CrazyTrain Không accouding đến [số kỹ thuật] (http://www.w3.org/html/wg/drafts /html/master/syntax.html#syntax) "Sự kiện đột biến DOM không được kích hoạt cho các thay đổi do UA phân tích cú pháp tài liệu ... Tuy nhiên, các nhà quan sát đột biến làm cháy, theo yêu cầu của đặc tả DOM." – RedHatter

+0

bạn có thể sử dụng [đến.js] (https://github.com/uzairfarooq/arrive), nó cung cấp api đơn giản để nghe các yếu tố sáng tạo (sử dụng MutationObserver nội bộ) –

+0

Hmm ... trông rất đẹp. Cảm ơn bạn @UzairFarooq – RedHatter

Trả lời

6

Một số vấn đề (lớn đến nhỏ):

  1. Khi tài liệu là đầu tiên, tĩnh nạp; các sự kiện là childList sự kiện, chứ không phải sự kiện attributes.

    Ví dụ,

    $("body").append ('<p id="foo" class="bar">Hiya!</p><p>blah</p>'); 
    

    tạo mộtchildList sự kiện, trong khi một tiếp theo

    $("#foo").attr ("class", "bar2"); 
    

    tạo ra một sự kiện attributes.

  2. Các tỷ lệ cược rằng mutation.addedNodes[0] chứa một phần tử với lớp nav là thực tế không. Đây gần như luôn là một nút văn bản.
    Bạn cần phải kiểm tra toàn bộ mảng, PLUS target.

  3. Không sử dụng getAttribute('class') == 'nav' để kiểm tra các lớp học. Điều này sẽ ném ngoại lệ cho các nút không có hàm getAttribute và nó sẽ bỏ qua các phần tử có nhiều hơn một lớp. EG: <p class="foo nav bar">...

    Sử dụng classList.contains() trên các loại nút thích hợp.

  4. Sử dụng chỉ thị @grant nếu bạn sử dụng bất kỳ chức năng GM_ nào như GM_log(). Sử dụng trợ cấp, để đảm bảo rằng hộp cát vẫn bật.

  5. Tránh sử dụng // @include *. Đặc biệt với bộ đếm thời gian và máy quan sát, điều này có thể làm hỏng trình duyệt và máy của bạn.

  6. Thông tin này dành cho Firefox. Chrome có sự khác biệt lớn về cách nó triển khai các nhà quan sát đột biến. Loại mã này sẽ không hoạt động trong Chrome trước khi tải trang.


Đưa nó tất cả cùng nhau, kịch bản trở thành:

// ==UserScript== 
// @name  _ii-shortcuts 
// @namespace https://github.com/RedHatter 
// @include  http://YOUR_SERVER.COM/YOUR_PATH/* 
// @run-at  document-start 
// @version  1 
// @grant  GM_log 
// ==/UserScript== 
/*- The @grant directive is needed to work around a design change 
    introduced in GM 1.0. It restores the sandbox. 
*/ 
var MutationObserver = window.MutationObserver; 
var myObserver  = new MutationObserver (mutationHandler); 
var obsConfig  = { 
    childList: true, attributes: true, 
    subtree: true, attributeFilter: ['class'] 
}; 

myObserver.observe (document, obsConfig); 

function mutationHandler (mutationRecords) { 

    mutationRecords.forEach (function (mutation) { 

     if ( mutation.type    == "childList" 
      && typeof mutation.addedNodes == "object" 
      && mutation.addedNodes.length 
     ) { 
      for (var J = 0, L = mutation.addedNodes.length; J < L; ++J) { 
       checkForCSS_Class (mutation.addedNodes[J], "nav"); 
      } 
     } 
     else if (mutation.type == "attributes") { 
      checkForCSS_Class (mutation.target, "nav"); 
     } 
    }); 
} 

function checkForCSS_Class (node, className) { 
    //-- Only process element nodes 
    if (node.nodeType === 1) { 
     if (node.classList.contains (className)) { 
      console.log (
       'New node with class "' + className + '" = ', node 
      ); 
      // YOUR CODE HERE 
      //GM_log ('nav creation'); 
     } 
    } 
} 
+0

Cảm ơn lời khuyên! mặc dù tôi sẽ thêm '@ grant' khi kịch bản được thực hiện (bạn nhận được pop phiền toái đó), và tôi chỉ đặt' @include * ''vì tôi không muốn hiển thị trang web nào tôi đang sử dụng tập lệnh trên. – RedHatter

0

MutationObservers được gọi cho nhiều thứ hơn là chỉ thêm nút, bao gồm các thay đổi đối với thuộc tính và xóa nút.

Vì vậy, hãy chú ý đến số mutation.addedNodes trả về giá trị NULL - trong trường hợp này mã này sẽ không thành công. Hãy thử:

if (mutation.addedNodes && mutation.addedNodes[0].getAttribute('class') === 'nav') { 
    ... 

Đối tượng đột biến cũng có thuộc tính 'loại' bạn có thể sử dụng để biết thêm thông tin; bạn đã đọc tài liệu API trên MDN chưa? Có một số ví dụ tốt ở đó.

+0

Tôi đã thử mã, không thay đổi bất cứ điều gì. Vấn đề không phải là kịch bản thất bại, đó là một phần tử với nav class không bao giờ được chuyển tới MutationObserver. Và vâng tôi đã đọc tài liệu. – RedHatter

+0

Bạn có trang thử nghiệm với HTML mà bạn đang xem bằng mã này không? – Wheeyls