2013-10-05 1 views
2

Я просто хочу вставить jQuery на веб-страницу из расширения сафари. Но только на некоторые страницы, потому что добавление jQuery в качестве начального/endcript будет вводить его на все страницы, и это замедляет работу браузера. Я попробовал его, создав тег сценария, используя свою функцию OnLoad:Ввод jQuery на веб-страницу с расширением Safari

var node = document.createElement('script');  
node.onload = function(){ 
    initjquerycheck(function($) { 
     dosomethingusingjQuery($); 
    }); 
}; 
node.async = "async"; 
node.type = "text/javascript"; 
node.src = "https://code.jquery.com/jquery-2.0.3.min.js"; 
document.getElementsByTagName('head')[0].appendChild(node); 

, чтобы проверить, если загружен JQuery я использую:

initjquerycheck: function(callback) { 
    if(typeof(jQuery) != 'undefined'){ 
     callback(jQuery); 
    }else { 
     window.setTimeout(function() { initjquerycheck(callback); }, 100); 
    } 
} 

Но TypeOf (JQuery) остается неопределенной. (проверили, что с помощью console.log()). Только если я вызываю console.log (typeof (jQuery)) из консоли отладки, он возвращает 'function'. Любые идеи, как это исправить? Заранее спасибо!

ответ

4

Внутренние сценарии с расширением расширения не могут получить доступ к пространству имен JavaScript веб-страницы. Сгенерированный скрипт создает элемент <script> и добавляет его в DOM страницы, но тогда объект jQuery, созданный сценарием, принадлежит пространству имен страницы, а не к введенному сценарию.

Существует по меньшей мере два потенциальных решения. Во-первых, добавьте jQuery на страницу обычным способом, используя API расширений. Этот метод является только жизнеспособным, если веб-страницы, на которые вы нацеливаетесь, можно классифицировать с использованием шаблонов URL.

Два, используйте Window.postMessage для связи между введенным скриптом и пространством имен веб-страницы. Вам нужно будет добавить еще одну <script> на страницу, и в этом скрипте есть слушатель для события message. Слушатель сможет использовать jQuery, как если бы он был «родным» для самой страницы.

Вот, пожалуйста, код, который поможет вам приступить к работе.

В расширения впрыскивается скрипт:

var s0 = document.createElement('script'); 
s0.type = 'text/javascript'; 
s0.src = 'https://code.jquery.com/jquery-2.0.3.min.js'; 
document.head.appendChild(s0); 

var s1 = document.createElement('script'); 
s1.type = 'text/javascript'; 
s1.src = safari.extension.baseURI + 'bridge.js'; 
document.head.appendChild(s1); 

window.addEventListener('message', function (e) { 
    if (e.origin != window.location.origin) 
     return; 
    console.log(e.data); 
}, false); 

window.postMessage('What jQuery version?', window.location.origin); 

В bridge.js:

window.addEventListener('message', function (e) { 
    if (e.origin != window.location.origin) 
     return; 
    if (e.data == 'What jQuery version?') { 
     e.source.postMessage('Version ' + $.fn.jquery, window.location.origin); 
    } 
}, false); 
+0

Не могли бы вы расширить на первый вариант ("впрыснуть Jquery на страницу нормальный путь"), да означает через 'addContentScriptFromURL'? – meleyal

+0

Кроме того, если введенный сценарий имеет другое пространство имен, как он обращается к объекту 'window' (т. Е. Как он может обращаться к« окну », но не' $ ')? Похоже, что он по существу публикует сообщения для себя. – meleyal

+1

@meleyal, да, я имею в виду 'addContentScript' и' addContentScriptFromURL'. Что касается того, как инъекционный скрипт обращается к объекту окна, мне кажется, что введенный скрипт и собственный скрипт страницы действуют так, как будто они обитают в двух разных окнах; можно подумать о них как о виртуальных окнах, которые занимают одно и то же место в браузере. Но эти виртуальные окна имеют одинаковое расположение и происхождение, поэтому один сценарий позволяет отправлять сообщения другому виртуальному окну. (Они также используют один и тот же DOM, но это не относится к цели передачи сообщений.) – canisbos