Заказы на доработку 1С (сервис удаленной работы)

Хранилище

База знаний
Бесплатные отчеты, обработки, конфигурации, внешние компоненты для 1С Статьи, описание работы, методики по работе с 1С

Здравствуйте, гость ( Вход | Зарегистрироваться )



> Javascript и 1С. Кросс-платформенное взаимодействие          
Vofka Подменю пользователя
сообщение 21.09.16, 12:06
Сообщение #1

У нас здесь своя атмосфера...
***********
Группа: Основатель
Сообщений: 13948
Из: Киев
Спасибо сказали: 4514 раз
Рейтинг: 3635.6

Что делать, если необходим богатый интерфейс, а управляемые формы нам его не могут обеспечить? Использовать HTML и JavaScript. В статье рассмотрено взаимодействие кода 1С и JavaScript, работающее на любой платформе: толстый, тонкий и веб-клиент, под Windows и Linux.



На текущий момент штатные средства 1С в управляемых формах не могут в полной мере удовлетворить потребность в богатом и отзывчивом интерфейсе. Ведь, по словам разработчиков платформы, управляемые формы призваны обеспечить быструю и эффективную разработку бизнес-логики приложения, с некоторым ущербом интерфейсу. Для абсолютного большинства ситуаций это верный подход, но есть случаи, когда необходимо и то, и другое.
Решением является использование HTML и JavaScript.

Прелагается решение, которое работает как в тонком, так и в веб-клиенте. Под Windows и Linux.

Примечание: при упоминании работоспособности в тонком клиенте, также подразумевается работоспособность и в толстом клиенте (управляемое приложение).

Вызов методов языка JavaScript из кода 1С.

Методы JavaScript могут быть вызваны из 1C так:

<Окно документа>.funcName(funcArgs);


Глобальные переменные доступны следующим образом:

<Окно документа>.varName;


Для браузера Internet Explorer окно документа доступно через

Элементы.ПолеHTMLДокумента.Документ.parentWindow


Для остальных браузеров через

Элементы.ПолеHTMLДокумента.Документ.defaultView


Подготовка переменных модуля для взаимодействия с JavaScript и вызов функции:

&НаКлиенте
Перем ДокументПервогоБраузера;

&НаКлиенте
Перем ОкноПервогоБраузера;

&НаКлиенте
Процедура ПервыйБраузерДокументСформирован(Элемент)
        
    // Сохранение элементов document и window в переменные модуля формы,
    // для последующего быстрого доступа к элементам и функциям.
    ДокументПервогоБраузера = Элемент.Документ;
    ОкноПервогоБраузера     = ДокументПервогоБраузера.parentWindow; // IE
    Если ОкноПервогоБраузера = Неопределено Тогда
        ОкноПервогоБраузера = ДокументПервогоБраузера.defaultView; // Прочие браузеры
    КонецЕсли;

    ОкноПервогоБраузера.createButtons(МассивКнопокПервогоБраузера);

КонецПроцедуры


Подробнее остановимся на передаваемых агрументах.

В тонком клиенте под Windows, помимо примитивных типов Строка, Число, Булево.., в функцию JavaScript можно передавать и нативные объекты 1С, такие как Структура, Массив, Соответствие, УправляемаяФорма, и др. Затем, в теле javascript функции доступны свойства и методы этих объектов.

Пример:

&НаКлиенте
Процедура СоздатьКнопки(Команда)
    
    МассивКнопок = Новый Массив;    
    ...
    Для Сч = 1 По КоличествоКнопок Цикл
        ...
        СтруктураКнопки = Новый Структура;
        СтруктураКнопки.Вставить("Заголовок",         ЗаголовокКнопки);
        СтруктураКнопки.Вставить("ИмяКоманды",         ИмяКоманды);
        СтруктураКнопки.Вставить("РазмерТекста",     РазмерТекста);
        СтруктураКнопки.Вставить("ЦветТекста",         ЦветТекста);
                
        МассивКнопок.Добавить(СтруктураКнопки);
    КонецЦикла;        
    
    ОкноПервогоБраузера.createButtons(МассивКнопок);
    
КонецПроцедуры

function createButtons(buttonsArray)
{
    var buttonsCount = buttonsArray.Количество(); // Доступны методы и свойства массива 1С
    for(var i = 0; i < buttonsCount; i++)
    {
        ПараметрыКнопки = buttonsArray.Получить(i);

        var btn = document.createElement('div');
        btn.id             = ПараметрыКнопки.ИмяКоманды;
        btn.innerText         = ПараметрыКнопки.Заголовок;    
        btn.style.fontSize     = ПараметрыКнопки.РазмерТекста;            
        btn.style.color     = ПараметрыКнопки.ЦветТекста;    
                        
        container.appendChild(btn);                        
    }  
}


Данный метод очень удобен, и он подходит, если хватает возможности работы в тонком клиенте в ОС Windows.

В тонком клиенте под Linux, а также в веб-клиенте метод не работает. При передаче структур, массивов, соответствий в аргумент функции, в её теле эти агрументы равны undefined. Работает передача строк, чисел, булев.

Решением возникшей проблемы является использование формата обмена данными JSON. Что это такое - см. [необходимо зарегистрироваться для просмотра ссылки]

Массивы, Структуры и Соответствия преобразуются в их строковое представление, и передаются в функцию. Затем, в теле функции они преобразовываются в объекты языка javascript, такие как Array и Object.

Функции сериализации и десериализации в/из JSON:

&НаКлиенте
Функция СериализоватьВJSON(СериализуемыйОбъект)
    
    #Если ВебКлиент Тогда    
        СтрокаJSON = СериализоватьВJSONНаСервере(СериализуемыйОбъект);
    #Иначе
        ЗаписьJSON = Новый ЗаписьJSON;
        ЗаписьJSON.УстановитьСтроку();
        НастройкиСериализации = Новый НастройкиСериализацииJSON();
        НастройкиСериализации.СериализовыватьМассивыКакОбъекты = Ложь;
        ЗаписатьJSON(ЗаписьJSON, СериализуемыйОбъект, НастройкиСериализации, "ПреобразованиеВJSON", ЭтотОбъект);
        СтрокаJSON = ЗаписьJSON.Закрыть();
    #КонецЕсли
    
    Возврат СтрокаJSON;

КонецФункции

&НаСервереБезКонтекста
Функция СериализоватьВJSONНаСервере(СериализуемыйОбъект)
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    НастройкиСериализации = Новый НастройкиСериализацииJSON();
    НастройкиСериализации.СериализовыватьМассивыКакОбъекты = Ложь;
    ЗаписатьJSON(ЗаписьJSON, СериализуемыйОбъект);
    // ЗаписатьJSON(ЗаписьJSON, СериализуемыйОбъект, НастройкиСериализации, "ПреобразованиеВJSON", ЭтотОбъект);
    //
    // ЭтотОбъект недоступнен в безконтекстном вызове, поэтому нужно либо поместтить эту функцию в общий модуль,
    // либо изменить директиву компиляции в &НаСервере
    СтрокаJSON = ЗаписьJSON.Закрыть();
        
    Возврат СтрокаJSON;

КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция ПреобразованиеВJSON(Свойство, Значение, ДополнительныеПараметры, Отказ) Экспорт
    
    // Данная функция вызывается для всех свойств, тип которых не поддерживает преобразование в формат JSON напрямую.
    // Они нам не нужны, поэтому всегда отказ от их записи.
    Отказ = Истина;    
    
    // Можно сделать преобразование в строку.
    // Значение = Строка(Значение);
    // Возврат Значение;
    
КонецФункции

&НаКлиенте
Функция ДесериализоватьИзJSON(СтрокаJSON)
    
    #Если ВебКлиент Тогда
        ДесериализованныйОбъект = ДесериализоватьИзJSONНаСервере(СтрокаJSON);
    #Иначе
        ЧтениеJSON = Новый ЧтениеJSON();
        ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
        ДесериализованныйОбъект = ПрочитатьJSON(ЧтениеJSON);
        ЧтениеJSON.Закрыть();
    #КонецЕсли    
    
    Возврат ДесериализованныйОбъект;
    
КонецФункции

&НаСервереБезКонтекста
Функция ДесериализоватьИзJSONНаСервере(СтрокаJSON)
    
    ЧтениеJSON = Новый ЧтениеJSON();
    ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
    ДесериализованныйОбъект = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    
    Возврат ДесериализованныйОбъект;
    
КонецФункции


Используются механизмы работы с JSON, реализованные в платформе 8.3.6.1977.

Для платформы 8.3.5 и ранее, можно использовать разработку господина Александра Переверзева, доступную по адресу http://pro1c.org.ua/index.php?showtopic=15065

Теперь, прежде чем передавать структуру в функцию JavaScript, преобразуем её в строку:

JSONМассивКнопокПервогоБраузера = СериализоватьВJSON(МассивКнопокПервогоБраузера);
ОкноПервогоБраузера.createButtons(JSONМассивКнопокПервогоБраузера);


Изменится и код функции Javascript, так как строку нужно преобразовать обратно в объект, пусть и не 1С-овский, но удобный для обработки:

function createButtonsWithJSON(buttonsData)
{
    buttonsData = JSON.parse(buttonsData);
    
    for(var i in buttonsData)
    {
        ПараметрыКнопки = buttonsData[i];

        var btn = document.createElement('li');
        btn.id = ПараметрыКнопки.ИмяКоманды;
        ...                                    
    }
}


Глобальный объект JSON, используемый для сериализации и парсинга (десериализации) в javascript, доступен начиная с Internet Explorer 8.

HTML документ в тонком клиенте, по умолчанию, даже при наличии установленного IE11, отображается в режиме совместимости с IE 5 (Quirks mode), поэтому необходимо его перевести в Standarts mode установной тега <meta http-equiv="X-UA-Compatible" content="IE=EDGE" /> в теле тега head.

Если на компьютере установлен IE7 (когда переход в режим IE8 невозможен), то нужно использовать следующий скрипт: [необходимо зарегистрироваться для просмотра ссылки]

который реализует функционал работы с JSON в IE < 8 (по аналогии с работой с JSON в платформе начиная с версии 8.3.6.1977, и до неё).

В функции javascript можно создавать массивы или объекты javascript, заполнять их, и возвращать в 1C.

&НаКлиенте
Процедура ПолучитьОбъектИзJavaScript(Команда)
    
    JSONСтруктураОтвета = ОкноПервогоБраузера.getDataFromJavaScript("");
    // Нужно передать любой параметр, например пустую строку, иначе функция не выполняется,
    // а переменной принимающей результат присваивается ссылка на эту функцию (COMОбъект).    
    СтруктураОтвета = ДесериализоватьИзJSON(JSONСтруктураОтвета);
    
    Для Каждого КлючИЗначение Из СтруктураОтвета Цикл
        Сообщить("Ключ: " + КлючИЗначение.Ключ + " Значение: " + КлючИЗначение.Значение);    
    КонецЦикла;
    
КонецПроцедуры

function getDataFromJavaScript()
{
    var arr = []; // Массив
    arr.push(555);
    arr.push("Строка в массиве");
    
     var obj = {}; // Объект (структура)
     obj["Ключ1"] = "Пробная строка";
     obj["Ключ2"] = 7777;
     obj["Ключ3"] = true;
     obj["Ключ4"] = arr;
    
     return JSON.stringify(obj);
}


Вызов методов 1С из JavaScript

В тонком клиенте под Windows доступен очень удобный метод:

В HTML документе создается глобальная переменная, например externalForm. При загрузке документа, переменной externalForm присваивается ссылка на текущую упрваляемую форму, доступную через ЭтотОбъект или ЭтаФорма.

Затем, в коде JavaScript становятся доступны любые клиентские экспортные методы и переменные модуля данной управляемой формы.

Пример:

// В документе html, в теге script объявляем глобальную переменную.
var externalForm = null;
var timer = null;
var counter = 0;

function startTimer()
{        
    alert(externalForm.ПеременнаяМодуля);
            
    timer = setInterval(function()
    {
        externalForm.МетодВызываемыйИзJavaScript("Значение переменной conunter: " + counter++);
    }, 1000);
}

function stopTimer()
{
    clearInterval(timer);
}
&НаКлиенте
Перем ПеременнаяМодуля Экспорт;

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    ...
    ПеременнаяМодуля = "Значение переменной модуля";
    
КонецПроцедуры

&НаКлиенте
Процедура ПервыйБраузерДокументСформирован(Элемент)
    
    ...        
    ОкноПервогоБраузера.externalForm = ЭтаФорма;
    
КонецПроцедуры

&НаКлиенте
Процедура ЗапуститьТаймер(Команда)
    
    ОкноПервогоБраузера.startTimer();
    
КонецПроцедуры

&НаКлиенте
Процедура ОстановитьТаймер(Команда)
    
    ОкноПервогоБраузера.stopTimer();
    
КонецПроцедуры

&НаКлиенте
Процедура МетодВызываемыйИзJavaScript(Данные) Экспорт
    
    Сообщить(Данные);
    
КонецПроцедуры


В тонком клиенте на Linux и в веб-клиенте методы и свойства переменной externalForm не доступны в javascript, их значение - undefined, поэтому используется следующая методика:

Объявляем глобальную переменную javascript, в которую будет помещать передаваемое значение.

var interactionVariable = null;


В документ добавляем невидимую кнопку

<button id="interactionButton" style="display: none">Кнопка взаимодействия</button>


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

interactionVariable = "МетодВызываемыйИзJavaScript через interactionButton. Значение переменной conunter: " + counter;
interactionButton.click();


И обрабатываем событие ПриНажатии у поля HTML документа.

&НаКлиенте
Процедура ПервыйБраузерПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
    
    НажатыйЭлемент = ДанныеСобытия.Element;
    Если НажатыйЭлемент.id = "interactionButton" Тогда
        МетодВызываемыйИзJavaScript(ОкноПервогоБраузера.interactionVariable);
        
        // Или Заглушка = Вычислить(ОкноПервогоБраузера.interactionVariable + "()");
        // Поле для фантазии большое    
    КонецЕсли;
    
КонецПроцедуры


Благодарю за внимание, не претендую на уникальность и надеюсь, что и данная информация будет полезна многим.

[необходимо зарегистрироваться для просмотра ссылки]

Сообщение отредактировал Vofka - 20.01.17, 15:14

Спасибо сказали: Acid, alider, logist, Petre,

Не нашли ответа на свой вопрос?
Зарегистрируйтесь и задайте новый вопрос.


Ответить Новая тема
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

RSS Текстовая версия Сейчас: 28.03.24, 16:12
1С Предприятие 8.3, 1С Предприятие 8.2, 1С Предприятие 8.1, 1С Предприятие 8.0, 1С Предприятие 7.7, Литература 1С, Общие вопросы по администрированию 1С, Методическая поддержка 1С - всё в одном месте: на Украинском 1С форуме!