Переменная вне области действия обработчика событий - PullRequest
1 голос
/ 21 декабря 2009

У меня сбои в Javascript, которые выходят за рамки моего знания языка.

Я создаю собственный плагин для CKEditor. Плагин - это IFrame, который открывается в DIV, сгенерированном CKEditor.

Внутри IFrame я показываю несколько изображений. Если пользователь выбирает одно из этих изображений, HTML-код, необходимый для отображения этого изображения, вставляется в CKEditor.

Динамически делая это, где я застрял. Я подключаюсь к экземпляру CKEditor из Iframe следующим образом:

var CKEDITOR = window.parent.CKEDITOR;    

CKEditor предлагает «прослушиватель OK», который срабатывает при нажатии кнопки OK (отображаемой CKEDitor). Этот хороший слушатель находится за пределами IFrame.

Определение прослушивателя OK, который работает со статическими значениями, работает:

var okListener = function(ev) {
   this._.editor.insertHtml('<img class="symbol" src="my_static_symbol.gif">');
   CKEDITOR.dialog.getCurrent().removeListener("ok", okListener);
};

// Assign OK listener
CKEDITOR.dialog.getCurrent().on("ok", okListener);

Но я еще не знаю свое возвращаемое значение, когда назначаю слушателя OK, поэтому мне нужно будет сделать что-то вроде этого:

var okListener = function(ev) {
   this._.editor.insertHtml('<img class="symbol" src="'+my_dynamic_value()+'">');
   CKEDITOR.dialog.getCurrent().removeListener("ok", okListener);
};

// Assign OK listener
CKEDITOR.dialog.getCurrent().on("ok", okListener);

Но это не работает, потому что my_dynamic_value находится вне области действия функции в тот момент, когда она запускается кнопкой «ОК» в CKEditor.

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

Есть ли какой-то трюк с областью действия, который я могу использовать, чтобы получить доступ к вещам из моего Iframe из okListener ()?

Надеюсь, это достаточно ясно. Если это не так, прокомментируйте, и я уточню.

Ответы [ 2 ]

5 голосов
/ 21 декабря 2009

Но это не работает, потому что my_dynamic_value находится вне область действия функции в то время как это запускается кнопкой «ОК» CKEditor.

OK. Может быть, это действительно не работает, но объяснение неверно. В JavaScript переменные имеют лексическую область видимости. Это означает, что если my_dynamic_value находится в области видимости, когда ваша функция (обработчик) объявлена, то она остается там навсегда. Какое сообщение об ошибке вы получаете?

1 голос
/ 21 декабря 2009

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

function createOKListener(imgURLFunc) {
   return function(ev) {
      this._.editor.insertHtml('<img class="symbol" src="'+imgURLFunc()+'">');
      CKEDITOR.dialog.getCurrent().removeListener("ok", okListener);
   };
};

// Assign OK listener
CKEDITOR.dialog.getCurrent().on("ok", createOKListener(function() {iframeRef.path.to.imageURL}));

Или:

function createOKListener(imgURL) {
   return function(ev) {
      this._.editor.insertHtml('<img class="symbol" src="'+imgURL+'">');
      CKEDITOR.dialog.getCurrent().removeListener("ok", okListener);
   };
};

// Assign OK listener
CKEDITOR.dialog.getCurrent().on("ok", createOKListener(path.to.imageURL));

Я подозреваю, что происходит то, что функция выполняется в контексте окна верхнего уровня; правда это или нет, зависит от реализации события CKEditor. Если это так, то вы можете попробовать получить доступ к глобальным переменным iframe через окно iframe (как описано в версии imgURLFunc) или связать значение с локальной переменной (как это было сделано с createOKListener).

Что происходит, так это то, что глобальные переменные (кроме window) разрешаются как свойства window (представьте, что вокруг блоков кода with (window) {...}). Когда CKEditor запускает событие, это происходит в контексте CKEDITOR, то есть window.parent (из iframe).

...