2015-12-26 22 views
17

के साथ डोम सामग्री बदलें मैं क्रोम एक्सटेंशन बना रहा हूं। मैं अपने ऐप को एक्सटेंशन में प्रत्येक पृष्ठ और ब्राउजर में देख रहे पेज के साथ संवाद करने की कोशिश कर रहा हूं। मुझे एक्सटेंशन से डोम तक पहुंचने की आवश्यकता है और फिर इसे अपडेट करें।क्रोम एक्सटेंशन

manifest.json 
popup.html 
popup.js 
background.js 
content.js 

और वर्तमान पृष्ठ जो उपयोगकर्ता देख रहा है।

मेरा लक्ष्य पृष्ठ लोड पर है डोम को संशोधित करें और उपयोगकर्ता को इसे देखने से पहले पृष्ठ का नया संस्करण दिखाएं। popup.js उपयोगकर्ताओं को पॉपअप में कीवर्ड दर्ज करने की अनुमति है। कीवर्ड localStorage पर सहेजे जाते हैं और जब वे वेब देखते हैं तो खोजशब्दों के मूल div को बनाकर कीवर्ड को उनके दृश्य से सेंसर किया जाता है, यदि वे किसी भी पेज पर देखे जाते हैं।

मुझे प्रत्येक पृष्ठ को संवाद करने में सहायता चाहिए और मुझे लगता है कि जिस तरह से मैं popup.js में पैरेंट divs छुपा रहा हूं, काम नहीं करेगा। मैं उलझन में हूँ कि सामने से डोम पर कार्रवाई कैसे करें।

पृष्ठभूमि को जेड भेजें .js पृष्ठ पर कीवर्ड खोजें और अपने मूल divs को छिपाएं में बदलें। डोम को वापस देखने वाले पृष्ठ पर दबाएं।

मुझे लगता है कि यह लाइन कह रही है कि अगर मैं किसी यूआरएल से मेल खाता हूं तो मेरा ऐप चलाएं लेकिन मुझे यकीन नहीं है।

"matches": ["*://*/*"], 

मेरे manifest.json

{ 
"name": "Wuno Zensoring", 
    "version" : "1.0", 
    "permissions": [ 
    "activeTab", 
    "tabs", 
    "storage" 
    ], 
    "description": "This extension will search the document file for keywords and hide their parent div.", 
    "icons": {     
    "19": "icon19.png", 
    "38": "icon38.png", 
    "48": "icon48.png", 
    "128": "icon128.png" 
    },  
    "background": { 
    "persistent": false, 
    "scripts": ["jquery-1.11.3.min.js","background.js"] 
    }, 
    "content_scripts": [{ 
     "matches": ["*://*/*"], 
     "js":   ["content.js"], 
     "run_at": "document_end", 
     "all_frames": true 
    }], 
    "web_accessible_resources": [ 
     "popup.js", "content.js" 
     ], 
    "browser_action": { 
    "default_icon": "icon.png128", 
    "default_popup": "popup.html", 
    "default_icon": {     
     "19": "icon19.png", 
     "38": "icon38.png", 
     "48": "icon48.png", 
     "128": "icon128.png"   
    } 
    }, 
    "manifest_version": 2 
} 

popup.html

<!doctype html> 
<html> 
    <head> 
    <title>Wuno Zensorship</title> 
    <script src="jquery-1.11.3.min.js"></script> 
     <script src="popup.js"></script> 
    <link rel="stylesheet" type="text/css" href="styles.css"> 
    </head> 
    <body> 
    <img src="icon48.png"> 

<section> 
<form id="form" action="#" method="POST"> 
<input id="description" name="description" type="text" /> 
<input id="add" type="submit" value="Add" /> 
<button id="clearChecked">Clear Checked Items</button> 
<button id="clear">Clear All</button> 
</form> 
<div id="alert"></div> 
<ul id="keyWords"></ul> 
</body> 
</html> 

popup.js

$(document).ready(function() { 
localArray = []; 

if (!localStorage.keyWords) { 
    localStorage.setItem('keyWords', JSON.stringify(localArray)); 
} 

loadKeyWords(); 

function loadKeyWords() { 
    $('#keyWords').html(''); 
    localArray = JSON.parse(localStorage.getItem('keyWords')); 
    for(var i = 0; i < localArray.length; i++) { 
     $('#keyWords').prepend('<li><input class="check" name="check" type="checkbox">'+localArray[i]+'</li>'); 
     } 
    } 

$('#add').click(function() { 
    var Description = $('#description').val(); 
    if($("#description").val() === '') { 
    $('#alert').html("<strong>Warning!</strong> You left the to-do empty"); 
    $('#alert').fadeIn().delay(1000).fadeOut(); 
    return false; 
    } 
    $('#form')[0].reset(); 
    var keyWords = $('#keyWords').html(); 
    localArray.push(Description); 
    localStorage.setItem('keyWords', JSON.stringify(localArray)); 
    loadKeyWords(); 
    return false; 
}); 

$('#clear').click(function() { 
window.localStorage.clear(); 
location.reload(); 
return false; 
}); 

$('#clearChecked').click(function() { 
    currentArray = []; 
    $('.check').each(function() { 
    var $curr = $(this); 
    if (!$curr.is(':checked')) { 
     var value = $curr.parent().text(); 
     currentArray.push(value); 
     localStorage.setItem('keyWords', JSON.stringify(currentArray)); 
     loadKeyWords(); 
    } else { 
     $curr.parent().remove(); 
    } 
    }); 
}); 


// Update the relevant fields with the new data 
function setDOMInfo(info) { 
    $("div p:contains(localStorage.getItem('keyWords')).parent('div').hide()"); 
} 

// Once the DOM is ready... 
window.addEventListener('DOMContentLoaded', function() { 
    // ...query for the active tab... 
    chrome.tabs.query({ 
    active: true, 
    currentWindow: true 
    }, function (tabs) { 
    // ...and send a request for the DOM info... 
    chrome.tabs.sendMessage(
     tabs[0].id, 
     {from: 'popup', subject: 'DOMInfo'}, 
     // ...also specifying a callback to be called 
     // from the receiving end (content script) 
     setDOMInfo); 
    }); 
}); 


}); // End of document ready function 

background.js

chrome.runtime.onMessage.addListener(function (msg, sender) { 
    // First, validate the message's structure 
    if ((msg.from === 'content') && (msg.subject === 'showPageAction')) { 
    // Enable the page-action for the requesting tab 
    chrome.pageAction.show(sender.tab.id); 
    } 
}); 

content.js

// Inform the background page that 
// this tab should have a page-action 
chrome.runtime.sendMessage({ 
    from: 'content', 
    subject: 'showPageAction' 
}); 

// Listen for messages from the popup 
chrome.runtime.onMessage.addListener(function (msg, sender, response) { 
    // First, validate the message's structure 
    if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) { 
    // Collect the necessary data 
    // (For your specific requirements `document.querySelectorAll(...)` 
    // should be equivalent to jquery's `$(...)`) 
    var domInfo = { 
     total: document.querySelectorAll('*').length, 
     inputs: document.querySelectorAll('input').length, 
     buttons: document.querySelectorAll('button').length 
    }; 

    // Directly respond to the sender (popup), 
    // through the specified callback */ 
    response(domInfo); 
    } 
}); 
+2

पूरे कोड को देखे बिना, पृष्ठभूमि पृष्ठ में एक नया डोम बनाकर और सामग्री स्क्रिप्ट पर भेजना ** ** ** लगता है कि एक अच्छी योजना नहीं है :) यह अधिकांश पृष्ठों को तोड़ देगा। डीओएम हेरफेर जगह में होना चाहिए (उदाहरण के लिए पृष्ठ में आवश्यक तर्क के साथ एक स्क्रिप्ट इंजेक्शन द्वारा)। – gkalpak

+1

बस एक सामग्री स्क्रिप्ट में डोम-मैनिपुलेशन तर्क डालें और इसे कीवर्ड भेजें (HTML भेजने के बजाय, इसे पृष्ठभूमि या पॉपअप पृष्ठ में फ़िल्टर करना और इसे सामग्री स्क्रिप्ट पर वापस भेजना)। – gkalpak

+0

आपकी समस्या को पूरी तरह से हल नहीं करते हैं, लेकिन मेरा सुझाव है कि आप इस समाधान को टेक्स्ट कंटेनर http://stackoverflow.com/a/18089011/1705006 पर खोजने के लिए देखें। प्रत्यक्ष पैरेंट नोड्स के लिए खोज करना अधिक कुशल और div नोड्स से अधिक तार्किक है। – karmiphuc

उत्तर

11

आपने इस क्वेरी का उपयोग करने से वर्तमान टैब में देखा जा रहा डोम को डेटा भेजने की जरूरत है।

chrome.tabs.executeScript(null, { 
     code: 'var config = ' + JSON.stringify(getKeywords) 
    }, function() { 
     chrome.tabs.executeScript(null, {file: 'custom.js'}); 
    }); 

और custom.js फ़ाइल आप लिख सकते हैं आप कार्य करते हैं कि आप DOM तत्व पर लागू करना चाहते हैं। जैसे कि आप custom.js में उस क्वेरी की आवश्यकता के मुकाबले कुछ छिपाना चाहते हैं। तो यदि आप उस उदाहरण का उपयोग करना चाहते हैं तो आपको इसे अपनी आवश्यकताओं के अनुसार संशोधित करने की आवश्यकता होगी।

var all = document.getElementsByTagName("div"); 
var searchValue=config.toString().split(','); 
alert('Example:' + searchValue[0]); 
for(j=0; j < searchValue.length; j++) { 
for(i=0; i < all.length; i++) { 
    if(all[i].innerHTML.indexOf(searchValue[j]) > -1){ 
    all[i].innerHTML = "" 
    } 
} 
} 
1

आप background.js या popup.js, कि प्राप्त करने से कमांड भेजने और content.js में डोम बदलना चाहिए। निम्न कोड एक साधारण परिदृश्य प्रदर्शित करता है: ब्राउज़र क्रिया पर क्लिक करें और वर्तमान पृष्ठ पर एक div संलग्न करें। आप किसी भी तत्व को दिखाने/छिपाने के लिए एक ही तर्क का उपयोग कर सकते हैं।

manifest.json

{ 
    "name": "Test", 
    "version": "1.0", 
    "permissions": [ 
    "tabs" 
    ], 
    "description": "Test", 
    "background": { 
    "persistent": false, 
    "scripts": [ 
     "background.js" 
    ] 
    }, 
    "content_scripts": [ 
    { 
     "matches": [ 
     "*://*/*" 
     ], 
     "js": [ 
     "content.js" 
     ], 
     "run_at": "document_end", 
     "all_frames": true 
    } 
    ], 
    "browser_action": { 
    "title": "Test" 
    }, 
    "manifest_version": 2 
} 

background.js

chrome.browserAction.onClicked.addListener(function() { 
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { 
     chrome.tabs.sendMessage(tabs[0].id, {command: "append"}, function(response) { 
      console.log(response.result); 
     }); 
    }); 
}); 

content.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { 
    console.log(request.command); 

    var div = document.createElement('div'); 
    var label = document.createElement('span'); 
    label.textContent = "Hello, world"; 
    div.appendChild(label); 
    document.body.appendChild(div); 

    sendResponse({result: "success"}); 
}); 
+0

क्या आप मेरी स्थिति का उपयोग करने के लिए दिखाए गए उदाहरण को बदलने में सक्षम हैं? – wuno

3

मैं, कभी के रूप में सरल इस सवाल का जवाब देने की कोशिश है क्योंकि कम परिवर्तन करने अपने कोड में आप तेजी से अनुसरण करने के लिए पथ सीखेंगे।

आम तौर पर जब मैं अंतिम उपयोगकर्ता पॉपअप पर स्टार्ट बटन दबाता हूं तो कोड की निम्न पंक्तियां लिखता हूं (अपने पॉपअप का संदर्भ लें।जे एस):

 
chrome.runtime.sendMessage({key: 'popupInit'}, function (response) { 
; 
}); 
window.close(); // this line closes the popup 

क्या बहुत महत्वपूर्ण है समझने के लिए प्रतिक्रिया गैर है एक संचार प्रणाली, लेकिन बस मक्खी इसी श्रोता से आ रही पर एक जवाब है। मेरे लिए श्रोता पृष्ठभूमि.जेएस है। इस फाइल को आप localStorage के बारे में लाभ उठा सकते हैं, ताकि आप जैसे कुछ है सकते हैं:

chrome.tabs.onUpdated.addListener(function(tabid, changeInfo, tab) { 
    if (typeof changeInfo.status == 'string' && changeInfo.status == 'complete') { 
    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) { 
     var keyString = JSON.parse(localStorage.getItem('keyWords')); 
     chrome.tabs.sendMessage(tabs[0].id, {key: 'init', wordToHide: keyString}, function (response) { 
     ; 
     }); 
    }); 
    } 
}); 

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { 
    var rq = request.key; 
    if (rq != undefined && typeof rq == 'string') { 
    switch (rq) { 
     case 'popupInit': 
     chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { 
      var keyString = JSON.parse(localStorage.getItem('keyWords')); 
      chrome.tabs.sendMessage(tabs[0].id, msgToSend, function(response) { 
      ; 
      }); 
     }); 
     break; 
    } 
    } 
}); 

chrome.tabs.onUpdated.addListener महत्वपूर्ण है क्योंकि हर बार सक्रिय वर्तमान पृष्ठ आप अद्यतन किया जाता है है LocalStorage से मान रही सामग्री स्क्रिप्ट के लिए संदेश भेज सकते हैं, एक ही होता है जब पॉपअप बंद हो और आप संकेत के लिए सुनने के लिए chrome.runtime.onMessage.addListener उपयोग कर सकते हैं, अगर वहाँ LocalStorage में शब्द हैं: पॉपअप इसलिए बंद कर दिया कंटेंट स्क्रिप्ट में काम शुरू करें जो इसे शब्दों की सरणी के साथ एक संदेश भेज रहा है।

अब आइए अपनी content.js फ़ाइल पर नज़र डालें।

// Listen for messages from the backgound.js 
chrome.runtime.onMessage.addListener(function (msg, sender, response) { 
    // First, validate the message's structure 
    if ((msg.key === 'init') && (Object.prototype.toString.call(msg.wordToHide) === '[object Array]')) { 

    var elements = document.querySelectorAll("body, body *"); 
    var results = []; 
    var child; 
    var regwordToHide = []; 
    if (msg.wordToHide.length > 0) { 
     msg.wordToHide.forEach(function(element, index, array) { 
     regwordToHide.push(new RegExp('\\b' + element + '\\b', 'g')); 
     }); 
    } 
    for(var i = 0; i < elements.length; i++) { 
     child = elements[i].childNodes[0]; 
     if (elements[i].hasChildNodes() && child.nodeType == 3) { 
     var nodeStr = child.textContent; 
     if (nodeStr.trim().replace(/\n\r\t/g, '').length > 0 && nodeStr.trim().charAt(0) != '<') { 
      regwordToHide.forEach(function(element, index, array) { 
      nodeStr = nodeStr.replace(element, ''); 
      }); 
      child.textContent = nodeStr; 
     } 
     } 
    } 
    document.getElementsByTagName("html")[0].style.visibility = "visible"; 
    } 
}); 
document.getElementsByTagName("html")[0].style.visibility = "hidden"; 

मैं पूरे पृष्ठ छिपाने की कोशिश: इस पर ध्यान देना है क्योंकि यह जटिल हो सकता है (अंत उपयोगकर्ता याद हमेशा कुछ देखना होगा, जबकि पेज लोड कर रहा है ....)।

बाद में, content.js पृष्ठभूमि से आने वाले संदेश की प्रतीक्षा करें और जब ऐसा होता है तो सामग्री स्क्रिप्ट अपना काम शुरू करती है! यह सब कुछ है।

मेरे लेखन में भ्रम के लिए खेद है। अगर आपको किसी अन्य मदद की ज़रूरत है तो मुझे बताएं। मैंने आपके एक्सटी का परीक्षण किया और उन स्थानों पर इसे सही किया जिन्हें आप देख सकते हैं।

एक क्रोम एक्सटेंशन में घटकों के बीच संचार के लिए आपको याद करने की जरूरत है:

  • पृष्ठभूमि बड़ा श्रोता
  • पॉपअप पृष्ठभूमि
  • पृष्ठभूमि सामग्री के साथ संवाद के साथ comunicate है

भेजने के लिए/संदेश प्राप्त आप Chrome messaging

करने के लिए एक बार देख ले सकता है
  1. समारोह chrome.runtime.sendMessage ({अभिवादन: "हैलो"}, समारोह (प्रतिक्रिया) { console.log (response.farewell); }); की तरह कुछ:
  2. chrome.runtime.onMessage.addListener भेजने के लिए usend सर्वर (रिसीवर)

sendResponse और प्रतिक्रिया संचार के बारे में मक्खी पर एक जाँच के लिए सिर्फ इस्तेमाल किया जाता है है हैलो -> ठीक है मैं समझ गया, अब मैं खुद से जारी है।

मैंने आपके शब्द को प्रतिस्थापित करने के लिए भी पूरा किया!