2009-08-15 3 views
3

загружает этот JS кода из букмарклета:Попадая функцию из другого сценария в JS

function in_array(a, b) 
{ 
    for (i in b) 
    if (b[i] == a) 
     return true; 
    return false; 
} 

function include_dom(script_filename) { 
    var html_doc = document.getElementsByTagName('head').item(0); 
    var js = document.createElement('script'); 
    js.setAttribute('language', 'javascript'); 
    js.setAttribute('type', 'text/javascript'); 
    js.setAttribute('src', script_filename); 
    html_doc.appendChild(js); 
    return false; 
} 

var itemname = ''; 
var currency = ''; 
var price = ''; 

var supported = new Array('www.amazon.com'); 
var domain = document.domain; 

if (in_array(domain, supported)) 
{ 
    include_dom('http://localhost/bklts/parse/'+domain+'.js'); 
    alert(getName()); 
} 
[...] 

Обратите внимание, что «GetName()» функция находится в http://localhost/bklts/parse/www.amazon.com/js. Этот код работает только -второй раз, когда я нажимаю букмарклет (функция, похоже, не загружается до появления предупреждения()).

Как ни странно, если изменить код:

if (in_array(domain, supported)) 
{ 
    include_dom('http://localhost/bklts/parse/'+domain+'.js'); 
    alert('hello there'); 
    alert(getName()); 
} 

я получаю оба оповещения на первом щелчке, а остальные функции сценария. Как заставить скрипт работать с первым щелчком букмарклета без ложных предупреждений?

Спасибо! -Mala

+1

Мне кажется, что единственным способом, с которым новое предупреждение будет меняться, является время, поэтому, возможно, проблема заключается в том, что браузер не загружает лишний javascript достаточно быстро. –

ответ

2

Добавление сценария < > через DHTML делает скрипт загружен неслучайно, а это значит, что браузер начнет его загружать, но не ждет, пока он запустит остальную часть скрипта.

Вы можете обрабатывать события на объекте тега, чтобы узнать, когда загружен сценарий. Вот пример кода, который я использую, который, кажется, отлично работает во всех браузерах, хотя я уверен, что лучший способ добиться этого, я надеюсь, что это должно указывать на вас в правильном направлении:

Не забывайте для изменения тега на ваш объект, содержащего сценарий < >, fnLoader для функции для вызова при загрузке скрипта и fnError для функции, вызываемой при сбое сценария.

Имейте в виду, что эти функции будут вызываться позднее, поэтому они (например, тег) должны быть доступны тогда (закрытие позаботится об этом обычно).

 tag.onload = fnLoader; 
    tag.onerror = fnError; 
    tag.onreadystatechange = function() { 
     if (!window.opera && typeof tag.readyState == "string"){ 
      /* Disgusting IE fix */ 
      if (tag.readyState == "complete" || tag.readyState == "loaded") { 
       fnLoader(); 
      } else if (tag.readyState != "loading") { 
       fnError(); 
      }; 
     } else if (tag.readyState == 4) { 
      if (tag.status != 200) { 
       fnLoader(); 
      } 
      else { 
       fnError(); 
      }; 
     }; 
    }); 
+0

спасибо, это похоже на то, как я хотел! – Mala

0

Похоже, что загрузка внешнего скрипта (http://localhost/bklts/parse/www.amazon.com/js) не блокирует выполнение до его загрузки. Простой тайм-аут может быть достаточно, чтобы дать браузеру возможность обновить DOM, а затем сразу же очередь выполнения следующего блока логики:

//... 
if (in_array(domain, supported)) 
{ 
    include_dom('http://localhost/bklts/parse/'+domain+'.js'); 
    setTimeout(function() { 
     alert(getName()); 
    }, 0); 
} 
//... 

По моему опыту, если ноль не работает на тайм-аут количество, то у вас есть реальное состояние гонки. Увеличение времени ожидания (например, 10-100) может исправить его для некоторых ситуаций, но вы попадаете в опасную ситуацию, если вам это нужно, чтобы всегда работать. Если нуль работает для вас, тогда он должен быть довольно прочным. Если нет, вам может потребоваться больше (всего?) Вашего оставшегося кода, который будет выполнен во внешний скрипт.

+0

Я не javascript-гуру, но, возможно, вы можете установить 'loaded = false' перед' include_dom (...) ', а затем в конце внешнего набора' loaded = true', после чего 'while', который ждет для этого? –

+0

Тайм-аут 100 по-прежнему не работает, несмотря на то, что в настоящее время локатор размещается локально - поэтому, когда он подключен к сети, разумное количество времени, вероятно, тоже не будет работать. Использование функции load = false могло бы работать, пытаясь это сделать ... – Mala

+0

Остин - попробовал вашу идею, но это бросает меня в бесконечный цикл, который заставляет браузер зависать, пока firefox не решит прекратить выполнение ... Полагаю, пришло время попробуйте нажать весь оставшийся код во внешнюю функцию: - \ Gh! – Mala

0

Лучший способ получить работу: не надо.

Поскольку я вызывал JS из заготовки с маленьким загрузчиком в любом случае (который просто накладывает скрипт на страницу, на которую вы смотрите), я изменил букмарклет, чтобы указать src на php-скрипт, который выводит код JS, взяв document.domain в качестве параметра. Таким образом, я просто использовал php для включения внешнего кода.

Надежды, которые помогают кому-то. Поскольку это не совсем ответ на мой вопрос, я не буду отмечать это как принятый ответ. Если кто-то есть лучший путь, я хотел бы знать это, но я буду оставить свой код как:

букмарклет:

javascript:(function(){document.body.appendChild(document.createElement('script')).src='http://localhost/bklts/div.php?d='+escape(document.domain);})(); 

локальных/bklts/div.php:

<?php 

print(" 
// JS code 
"); 

$supported = array("www.amazon.com", "www.amazon.co.uk"); 
$domain = @$_GET['d'] 
if (in_array($domain, $supported)) 
    include("parse/$domain.js"); 

print(" 
// more JS code 
"); 

?> 
Смежные вопросы