Глобальные объекты, функции и переменные
Любому скрипту, кроме набора средств языка JavaScript, доступен набор объектов, функций и переменных, используемых для работы с SURVEYSTUDIO. Например, для доступа к вопросам, созданным в редакторе анкеты, можно использовать глобальные переменные вида Q1, Q5, Q34 и т.д. Также для доступа к любому вопросу, можно использовать объект questions, и, например, вопрос Q34 можно так же получить вызовом questions[34].
Объект questions
Используется для доступа к любому вопросу анкеты по его номеру, а также для добавления, удаления и изменения порядка вопросов (рандомизация, ротация). Например, для получения доступа к вопросу по номеру можно написать так:
var q = questions[34];
Также объект questions содержит различные методы и свойства:
count
Возвращает количество вопросов. Например:
var x = questions.count;
getNumbers()
getNumbers(qnFrom, qnTo)
Возвращает массив номеров вопросов. Может принимать параметры начала и конца диапазона.
Получить номера всех вопросов:
var numbers = questions.getNumbers();
Получить номера вопросов, которые находятся между 23 и 115 включительно:
var numbers = questions.getNumbers(23, 115);
getAll()
Возвращает все вопросы в виде массива. Например:
questions.getAll().forEach(function (q) {
q.comment = 'Тут комментарий для вопроса Q' + q.number;
});
Важно! При работе анкеты вопросы подгружаются постепенно при первом к ним обращении, а проход в цикле по всем вопросам вынуждает систему загрузить все вопросы сразу, что может замедлить, например, запуск анкеты, если такой скрипт будет в Подготовке.
randomize()
randomize([numbers])
randomizeFromTo(qnFrom, qnTo)
Перемешивает случайным образом либо все вопросы, либо указанные, если в качестве параметра передан массив номеров вопросов, либо все вопросы в указанном диапазоне.
questions.randomize();
questions.randomize([1,3,5,7]);
questions.randomizeFromTo(10, 20);
randomizeGroups(groups)
randomizeGroups(groupSize, firstNumbers)
Перемешивает случайным образом группы вопросов.
В параметре groups передаётся массив с массивами номеров первого и последнего вопроса в группе. Если группы вопросов одинакового размера, то в первом параметре (groupSize) можно указать количество вопросов в группе, а во втором — массив номеров первых вопросов в каждой группе.
Порядок вопросов внутри группы не изменяется.
Примеры.
- Есть вопросы: Q1,Q2, Q3,Q4,Q5,Q6,Q7,Q8, Q9. Необходимо перемешать между собой группы вопросов 1-2, 3-8, и 9. Сделать это можно так:
questions.randomizeGroups([[1,2], [3,8], [9,9]]);
- Есть вопросы: Q1,Q2,Q3, Q4,Q5,Q6, Q7,Q8,Q9. Необходимо перемешать между собой группы вопросов 1-3, 4-6, 7-9. Сделать это можно так:
questions.randomizeGroups(3, [1,4,7]);
// или
questions.randomizeGroups([[1,3], [4,6], [7,9]]);
rotate()
rotate([numbers [, shift]])
rotateFromTo(qnFrom, qnTo [, shift])
Производит ротацию вопросов (циклический сдвиг на определенный шаг). Если не переданы никакие параметры - ротируются все вопросы. Также можно передать шаг сдвига в параметре shift, при этом если шаг не передается - используется внутренний шаг, который автоматически увеличивается на 1 для каждого следующего интервью, что дает правильное равномерное распределение. Для ротации определённых вопросов нужно передать массив numbers с номерами этих вопросов. Также в параметрах qnFrom и qnTo можно указать диапазон вопросов, подлежащих ротации. Примеры:
questions.rotate();
questions.rotate(5);
questions.rotate([1,2,3,4,5,6]);
questions.rotate([1,2,3,4,5,6], 5);
questions.rotateFromTo(1, 6);
questions.rotateFromTo(1, 6, 5);
rotateGroups(groups [, shift])
rotateGroups(groupSize, firstNumbers [, shift])
Ротация групп вопросов. Работает по аналогии с функцией randomizeGroups. Примеры:
questions.rotateGroups([[1,3], [4,6], [7,9]]);
questions.rotateGroups([[1,3], [4,6], [7,9]], 2);
questions.rotateGroups(3, [1,4,7]);
questions.rotateGroups(3, [1,4,7], 2);
setOrder(orderedCodes)
Устанавливает необходимый порядок следования вопросов. В параметре orderedCodes передается массив номеров в необходимом порядке.
Например, есть вопросы Q1,Q2,Q3,Q4,Q5.
- Задать вопросы в обратном порядке можно так:
questions.setOrder([5,4,3,2,1]);
- Поменять местами Q2 и Q4 можно так:
questions.setOrder([4,2]);
setOrderGroups(groups)
setOrderGroups(groupSize, firstNumbers)
Устанавливает порядок для групп вопросов. Синтаксис аналогичен randomizeGroups.
add(number, text, comment, type)
Функция добавляет новый вопрос в конец анкеты и возвращает его в качестве результата. В параметрах функции передаются номер вопроса, текст, комментарий (может быть пустым) и тип вопроса. Для указания типа вопроса можно использовать одно из значений:
- welcomescreen,
- info,
- text,
- numeric,
- singlechoice,
- multiplechoice,
- table_text,
- table_numeric,
- table_singlechoice,
- table_multiplechoice,
- dropdown_singlechoice,
- dropdown_multiplechoice.
Пример:
// создаем новый текстовый вопрос Q56 и добавляем его в конец анкеты
var q = questions.add(56, 'Как Вас зовут?', 'Записать', 'text');
// включаем в созданном вопросе флаг "Исключить вопрос при выгрузке"
q.flags |= 0x00008;
insert(refNumber, number, text, comment, type)
Так же, как и функция add(), создает новый вопрос и вставляет его перед вопросом, номер которого указан в параметре refNumber. Пример:
// создаем новый текстовый вопрос Q56 и вставляем его перед вопросом Q57
var q = questions.insert(57, 56, 'Как Вас зовут?', 'Записать', 'text');
insertAfter(refNumber, number, text, comment, type)
Аналогично функции insert() создает новый вопрос, только вставляет его после вопроса, номер которого указан в параметре refNumber. Пример:
// создаем новый текстовый вопрос Q56 и вставляем его после вопроса Q55
var q = questions.insertAfter(55, 56, 'Как Вас зовут?', 'Записать', 'text');
remove(number)
Удаляет вопрос с указанным номером. Пример:
// удаляем вопрос Q56 из анкеты
questions.remove(56);
repeat(qnFrom, qnTo, qnSrc [, codes])
Создание цикла по вопросу, т.е. один блок существующих вопросов (с номерами от qnFrom до qnTo) будет задан для каждого выбранного ответа в вопросе с номером qnSrc в том же порядке, в котором эти ответы расположены во время запуска анкеты. Ответ не используется в цикле, если у него установлен флаг Запрещено использовать в циклах. Также коды вариантов ответа, которые необходимо проверять в вопросе qnSrc, можно задать в необязательном параметре codes (массив номеров). Если он не задан - используются все варианты ответа qnSrc.
Существующее условие показа в вопросах, если оно было прописано, не замещается, а дополняется через and (Q… = …).
В тексте вопроса, комментарии или ответе внутри цикла можно использовать макросы {answerText} и {answerCode}, которые при запуске анкеты заменятся на соответствующие значения ответов qnSrc. {answerText} - текст ответа, {answerCode} - код ответа.
Примеры использования:
// повтор вопросов с Q4 по Q6 для каждого выбранного в Q1 ответа
questions.repeat(4, 6, 1);
// повтор вопросов с Q4 по Q6 для ответов 1,3,5, если они выбраны в Q1
questions.repeat(4, 6, 1, [1,3,5]);
О создании циклов и работе с ними читайте здесь.
repeatIfNot(qnFrom, qnTo, qnSrc [, codes])
Этот метод работает аналогично предыдущему (см. описание выше), но наоборот: вопросы в цикле будут задаваться для невыбранных в qnSrc ответов. Примеры использования:
// повтор вопросов с Q4 по Q6 для каждого невыбранного в Q1 ответа
questions.repeatIfNot(4, 6, 1);
// повтор вопросов с Q4 по Q6 для ответов 1,3,5, если они не выбраны в Q1
questions.repeatIfNot(4, 6, 1, [1,3,5]);
Объект parameters
Используется для доступа к параметрам, переданным в ссылке (url) для запуска проекта. Например, если ссылка для запуска проекта была:
https://do
.survey-studio.com/s/ef87c2da?phone=78121234567&code=678
то получить значения параметров phone и code можно следующим образом:
var phone = parameters['phone'];
var code = parameters['code'];
// или можно проще
var phone = parameters.phone;
var code = parameters.code;
Параметры extId и extPhone, передаваемые в ссылке, являются системными и недоступны через объект parameters. Для получения значений этих параметров воспользуйтесь объектами respondent и contact соответственно.
Объект variables
Используется как хранилище глобальных переменных, значения которых будут сохраняться на протяжении всей анкеты. Обычно используется для автоматической подстановки необходимого значения в текст вопроса (а также комментарий или текст варианта ответа) с помощью макросов. Например, если в тексте вопроса написать Здравствуйте, {ФИО}!, то макрос {ФИО} будет заменен на значение переменной ФИО в объекте variables
. Также этот объект можно использовать для передачи значений из скрипта одного вопроса в скрипт другого. Для удобства у объекта variables
есть псевдоним V
.
Важные замечания:
- объект может хранить значения только простого типа (строка, число, true/false),
- не стоит использовать глобальные переменные в скрипте Подготовка, если от них зависит логика анкеты, так как при пост-обработке глобальные переменные из этого скрипта всегда пусты.
Примеры:
variables['ФИО'] = 'Иванов И.И.';
variables.name = 'Пётр';
V['age'] = 21;
V.title = 'Hello, World!';
if (V.age < 18) {
// Что-то сделать
}
Объект project
Используется для доступа к информации о проекте. У этого объекта есть следующие свойства:
- id - идентификатор проекта (доступен в ссылке на проект: …/project?pId=1962),
- name - наименование проекта.
Пример:
if (project.name.indexOf('Москва') > -1) Q.show(77);
Объект interview
Используется для доступа к информации о текущей версии интервью. У этого объекта есть следующие свойства:
- id - идентификатор версии интервью,
- result - результат интервью,
- resultDetails - наименование счётчика, если сработала квота,
- ipAddress - IP-адрес устройства респондента/интервьюера,
- userAgent - User Agent на устройстве респондента/интервьюера,
- referer - источник перехода по ссылке на анкету,
- clientLoginName - идентификатор клиента в SURVEYSTUDIO,
- clientName - имя клиента,
- contractor - информация о подрядчике:
- clientLoginName - идентификатор клиента в SURVEYSTUDIO,
- clientName - имя клиента,
- contractorName - название подрядчика,
- contractorCode - код (если указан),
- contractorRegionName - название региона (если указан).
Примеры:
informationTextAdd(interview.userAgent);
informationTextAdd(interview.contractor.clientLoginName);
Объект respondent
Используется для доступа к данным респондента.
extId
Идентификатор респондента из внешней системы (из параметра extid рабочей ссылки).
let url = 'http://example.com/?rid=' + respondent.extId;
return exitAndRedirect(url);
getLastInterviewAnswers([qn])
Возвращает массив ответов из предыдущей версии интервью. Обычно этот метод используется в телефонных опросах, когда у одного респондента может быть несколько версий интервью: интервьюер начал опрашивать респондента, но тот попросил перезвонить позже - сохранится первая версия. После перезвона начнётся вторая версия, во время которой можно получить предыдущие ответы.
Каждый элемент массива содержит следующие свойства:
- questionNumber - номер вопроса,
- rowCode - код строки,
- answerCode - код ответа,
- openValueNum - числовое значение,
- openValueTxt - текстовое значение.
Если в параметре передать номер вопроса, то метод вернёт ответ на этот вопрос, а не на все. Примеры:
// Получить ответ на вопрос Q5 из предыдущей версии интервью
var q5answers = respondent.getLastInterviewAnswers(5);
// Если в полученном массиве есть элементы, то вывести
// на экран содержимое текстового поля нулевого элемента массива
if (q5answers.length) informationText(q5answers[0].openValueTxt);
Объект contact
Используется для доступа к базе контактов. У этого объекта есть следующие свойства и объект:
- id - id контакта,
- tag - метка базы контактов,
- phone - номер телефона контакта,
- email - электронная почта контакта (может быть в рассылочной базе),
- data[name] - содержит данные из дополнительных полей контакта,
- contactPoolName - название базы контактов,
- contactPoolTimeZoneId - часовой пояс базы контактов.
- validUntilDate - дата указанна в поле Срок действия контакта
- validUntilTime - время указанное в поле Срок действия контакта (в часовом поясе базы контактов)
Примеры:
var phone = contact.phone;
V.fio = contact.data['ФИО'];
Объект user
Используется для доступа к данным пользователя SURVEYSTUDIO. У этого объекта есть следующие свойства:
- id - числовой идентификатор пользователя,
- loginName - логин пользователя,
- name - имя пользователя.
Пример:
// Поместить в глобальную переменную interviewer имя пользователя
V.interviewer = user.name;
Объект webClient
Позволяет взаимодействовать с внешними сервисами по URL. У этого объекта есть два метода:
- downloadString(url [, timeout, {headers}]) — выполняет GET-запрос,
- uploadString(url, string [, timeout, {headers}]) — POST-запрос.
После завершения работы оба метода возвращают содержимое ответа сервера. Если сервер не ответил статусом 200 OK — будет выброшено исключение, которое прервёт интервью, поэтому такую ситуацию необходимо предусмотреть в скрипте.
Запрос с одним и тем же URL будет выполнен только один раз за интервью. Это ограничение необходимо для защиты от повторного выполнения из-за ошибки в логике анкеты или при постобработке перед сохранением интервью.
Время работы любого скрипта анкеты ограничено 30-ю секундами, поэтому внешний сервер должен ответить как можно быстрее. Если он будет долго думать — интервью может прерваться с ошибкой в скрипте The operation has timed out
или Превышено максимально допустимое время выполнения скрипта 30 сек
. Многократное завершение с такой ошибкой может привести к блокировке анкеты на несколько минут. Поэтому, если время работы скрипта превышается, то можно попробовать уменьшить время ожидания ответа сервера, указав необходимое значение (в миллисекундах) в необязательном аргументе timeout. По умолчанию оно равно 25000 (25 секунд). Если указать null
, будет использоваться значение по умолчанию.
Пример:
// GET
let url = 'https://example.com/get.php';
try {
var result = webClient.downloadString(url, null, {"String-Header": "value", "Int-Header": 11});
} catch (e) {
informationText('Не удалось выполнить запрос к внешнему серверу: {0}', e.message);
return ok;
}
informationText('Ответ сервера: {0}', result);
// POST
let url = 'https://example.com/post.php';
let data = 'some data';
let headers = {
"String-Header": "value",
"Int-Header": 11
}
try {
var result = webClient.uploadString(url, data, null, headers);
} catch (e) {
informationText('Не удалось выполнить запрос к внешнему серверу: {0}', e.message);
return ok;
}
informationText('Ответ сервера: {0}', result);
Объект images
Позволяет получить изображение, загруженное через редактор вопросов анкеты, по его названию:
Q.image = images['Название изображения'];
Объект InterviewResult
Содержит результаты интервью:
- Completed - Полное
- Screening - Скрининг
- Overquoting - Квота
- Defect - Брак
- Interrupted - Прервано
- Postponed - Перенесено
- Exited - Завершено
- Unknown - Неизвестно
Примеры:
if (interview.result == InterviewResult.Overquoting) {
// …
}
return exitWithResult(InterviewResult.Completed);
Функции и переменные
rotationCounter
Возвращает текущее значение счетчика ротации для анкеты, который будет использоваться в функциях questions.rotate() и questions.rotateGroups(), если не задано явно значение сдвига (в параметре shift).
informationText(string)
Выводит на экран переданный в первом параметре текст, который будет отображаться в нижней левой части экрана на протяжении всего интервью. Поддерживается HTML. При повторном вызове этой функции существующий текст заменяется новым. В тексте можно использовать подстановки {0}, {1}, {2}…, которые будут заменяться значениями из остальных параметров функции. Примеры:
informationText('Имя респондента: ' + Q.openValueTxt);
informationText('Цена была {0} руб., а стала <font color="red">{1} руб.</font>', oldPrice, newPrice);
informationTextAdd(string)
Делает то же самое, что и предыдущая функция, но при повторном вызове этой функции к существующему тексту добавляется новая строка. Пример:
informationTextAdd('В траве');
informationTextAdd('сидел <b>кузнечик</b>.');
informationTextClear()
Удаляет весь текст, добавленный функциями informationText()
и informationTextAdd()
.
isTesting()
Возвращает значение true, если анкета работает в режиме тестирования (без проекта, т.е. без сохранения интервью в базу).
isPreProcessing()
Возвращает значение true, если анкета работает в режиме подготовки запуска (исполняется глобальный скрипт Подготовка).
isPostProcessing()
Возвращает значение true, если исполняется глобальный скрипт Обработка или производится повторный проход анкеты для нормализации ответов - очистка интервью от ответов, не соответствующих заданным в анкете условиям и переходам.
isQuotaReached()
Возвращает значение true, если сработала квота.
isRedial()
Возвращает значение true, если анкета запущена повторно для продолжения ввода с места, на котором остановились, например при перезвоне в телефонном опросе или возобновлении отложенного на планшете интервью.
isValidation()
Возвращает значение true, если анкета работает в режиме контроля (сохранённое интервью открыто повторно для контроля работы интервьюера).
isExport()
Возвращает значение true, если производится выгрузка массива.
disableQuotaChecking()
Отключает автоматическую проверку квот.
enableQuotaChecking()
Включает автоматическую проверку квот.
enableSaveWhenQuotaReached()
Включает запись интервью в базу, даже если сработала квота. По умолчанию если квота сработала - интервью завершается и в базу не записывается.
disableSaveWhenQuotaReached()
Отключает запись интервью в базу, когда сработала квота, т.е. включает поведение по умолчанию.
getCounter(name)
Производит поиск в проекте счётчика с указанным именем, и если он будет найден - возвращает объект со следующими свойствами:
- name - имя счётчика,
- quota - значение квоты (или undefined, если квота не задана),
- value - текущее значение счётчика,
- tag - метка счётчика.
Примеры использования:
var counter = getCounter('Москва: М 18-24');
if (counter) {
Q.comment = 'Значение счетчика = ' + counter.value;
}
var counter = getCounter('Полные интервью');
if (counter && counter.quota >= 0 && counter.value + 1 > counter.quota) {
return exit('Спасибо, больше не надо.');
}
getCounterByTag(tag)
Производит поиск в проекте счётчика с указанной меткой, и если он будет найден - возвращает объект с такими же свойствами, как у getCounter(). Если в нескольких счётчиках прописана одна и та же метка, то функция возвратит первый найденный.
Пример:
var counter = getCounterByTag('51');
if (counter && counter.quota >= 0 && counter.value + 1 > counter.quota) {
return exit('Спасибо, больше не надо.');
}
getCountersByTag(tag)
Как и предыдущая, эта функция так же производит поиск счётчика с указанной меткой, но если он будет найден - возвращает массив объектов с такими же свойствами, как у getCounter(). То есть если в нескольких счётчиках прописана одна и та же метка, то функция возвратит их все в виде массива.
Пример:
for (let counter of getCountersByTag('51')) {
if (counter.quota >= 0 && counter.value + 1 > counter.quota) {
return exit('Спасибо, больше не надо.');
}
}
lockKey(string)
Помещает переданную в параметре строку в хранилище проекта. Обычно используется совместно с функцией isKeyLocked(). Пример:
lockKey(interview.ipAddress + interview.userAgent);
isKeyLocked(string)
Возвращает true, если переданная в параметре строка содержится в хранилище проекта. Обычно используется для запрета повторного заполнения анкеты в веб-опросе. Пример:
var id = interview.ipAddress + interview.userAgent;
if (isKeyLocked(id)) return exit();
calc(expression)
Возвращает true, если переданное в параметре выражение выполняется. В выражении нельзя использовать Q
без номера вопроса. Пример:
Q[2].checked = calc('Q1(code = 1 or code = 3 or code = 5)');
randomizeArray(array)
Перемешивает случайным образом элементы массива. Пример:
informationText(randomizeArray([1,2,3,4,5,6,7,8,9,10]));
setCurrentLanguage(lang)
Принудительное изменение языка интерфейса опроса на указанный. Возможные варианты:
- en — английский
- az — азербайджанский
- de — немецкий
- es — испанский
- fr — французский
- id — индонезийский
- it — итальянский
- kk — казахский
- hu — венгерский
- ms — малайзийский
- nl — нидерландский
- uz — узбекский
- pt — португальский
- ru — русский
- sv — шведский
- tr — турецкий
- vi — вьетнамский
- ar — арабский
- fa — персидский (фарси)
- th — тайский
- zh — китайский
- ja — японский
Пример переключения на арабский:
setCurrentLanguage('ar');
getCurrentLanguage()
Возвращает текущий язык интерфейса опроса.