31 марта 2010 г.

Отслеживание сторонних изменений через JavaScript

Что делать, если нужно отследить изменения, совершаемые через JavaScript?

Такие изменения нельзя отловить обработчиками событий к элементам. Следовательно ответ напрашивается сам собой - изменить js код!

А что если мы не имеем права его изменять? Что если наша необходимость локальна и не требует "таких глобальных" решений?

Допустим, что у нас есть некоторое текстовое поле, значение которого изменяется какой-либо сторонней библиотекой...Тогда существуют следующие варианты:

1. Использование таймера для постоянного опроса.
В этом случае необходимо создать с помощью интервала циклический вызов функции, которая будет постоянно вытаскивать значение из текстового поля и сравнивать его с предыдущим:
setInterval(function () {if (input.value!=oldValue){...})}, 1000); 
+ простота
- задержка реакции на изменение значения поля
- иногда может повисать страница из-за зацикливания

2. Внедрение заготовленной функции в библиотечную.
Процесс внедрения происходит не в самом коде библиотеки, а динамически на самой странице). Это решает проблемы, например, с лицензией и тому подобным, что может мешать редактировать саму библиотеку, но несколько сложнее чем в предыдущем случае)

В основе такого внедрения лежит факт объектной природы функции в JS и специфика конвертации типов.

Приведу пример...)
Допустим у нас есть некоторая функция:
function firstButtonClick () {
     alert('Calling function')
} 
И к ней необходимо добавить вызов includedFunction() следующей функции:
function includedFunction () {
     alert('Other function');
}
То мы можем провести следующие действия:
var funcString = firstButtonClick.toString();
 // Вытащить тело изначальной функции 
var reg = /\{([\S\s]*)\}$/i;
var regArr = reg.exec(funcString);
 // Получить новую функцию
eval("firstButtonClick = function (){"+regArr[1]+" includedFunction()}");
Таким образов при вызове firstButtonClick будет вызываться и includedFunction, а сама firstButtonClick будет выглядеть следующим образом:
function firstButtonClick () {
    alert('Calling function');
    includedFunction();
}
Вот рабочий пример:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="Description" content="" />
    <meta name="Keywords" content="" />
        <title>Function include exemple</title>
 
        <style type="text/css">
           .input_div {
                margin:0 auto;
                width:370px;
           }

        </style>
 
        <script type="text/javascript">
function firstButtonClick () {
    alert('Calling function')
}
 
function secondButtonClick() {
    var funcString = firstButtonClick.toString();
    var reg = /\{([\S\s]*)\}$/i;
    var regArr = reg.exec(funcString);
    if (regArr[1]) {
        eval("firstButtonClick = function (){"+regArr[1]+" includedFunction()}");
        // Обнавляем ссылку
        document.getElementById('firstButton').onclick = firstButtonClick;
    }
}
 
function includedFunction () {
    alert('Other function');
}
 
window.onload = function () {
    document.getElementById('firstButton').onclick = firstButtonClick;
    document.getElementById('secondButton').onclick = secondButtonClick;
}
        </script>
    </head>
    <body>
        <div class="input_div">
            <input value="Text" id="inputField"/>
            <button id="firstButton">Call function</button>
            <button id="secondButton">Include function</button>
        </div>
    </body>
</html>
+ отсутствие задержек
+ в целом получается, будто была дописана функция из библиотеки
- в зависимости от ситуации требует достаточно сложных манипуляций

Комментариев нет:

Отправить комментарий