x

Основні розділи

  1. LimeSurvey Cloud проти LimeSurvey CE
  2. Короткий посібник із початку роботи - LimeSurvey 3.0+
  3. Встановлення - LimeSurvey CE
  4. Як створити хороше опитування (посібник)
  5. Початок роботи
  6. Адміністрування LimeSurvey
  7. Опитування - вступ
  8. Налаштування опитування
  9. Меню опитування
  10. Структура опитування
  11. Питання - вступ
  12. Групи питань - вступ
  13. Опитування - керування
  14. Параметри панелі інструментів опитування
  15. Багатомовне опитування
  16. ExpressionScript Engine - Короткий посібник
  17. Некатегоризовані та розширені функції
  18. Загальні поширені запитання
  19. Усунення несправностей
  20. Обхідні рішення
  21. Ліцензія
  22. Журнал змін версій
  23. Плагіни
 Actions

ExpressionScript - Презентація

From LimeSurvey Manual

Ця сторінка, можливо, перекладена машинним способом і може містити помилки. Показати англійський оригінал · Покращити цей переклад
This page is a translated version of the page ExpressionScript - Presentation and the translation is 100% complete.


Вступ

LimeSurvey використовує Expression Script (Скрипт виразів), який дає змогу LimeSurvey підтримувати складніше розгалуження, оцінювання, перевірку та адаптацію тексту. Він замінює спосіб, у який LimeSurvey керує замінами, умовами та оцінюванням на серверній частині. Він також значно прискорює обробку, оскільки усуває більшість зчитувань з бази даних під час виконання. Expression Script розробив д-р Томас Вайт (TMSWhite).


Ключові визначення

  1. Вираз: усе, що взято у фігурні дужки:
    • Якщо одразу після відкривної дужки або перед закривною фігурною дужкою немає пробілів.
    • Вміст виразу обчислюється EM, тому він може містити математичні формули, функції, а також складну обробку рядків і дат.
  2. Адаптація тексту (Tailoring): іноді її називають «piping». Це процес умовної зміни тексту:
    • Ви маєте доступ до всіх «полів заміни», даних учасника та даних відповідей.
    • Ви також маєте простіший доступ до питань, відповідей та їхніх властивостей.
  3. Рівняння релевантності: новий атрибут питання, що керує видимістю питання:
    • Якщо існує рівняння релевантності, питання показується лише тоді, коли релевантність має значення «істина».
    • Внутрішньо всі команди array_filter та array_filter_exclude стають релевантністю на рівні підпитань.
  4. SGQA (як змінні називали раніше):
    • Означає Survey-Group-Question-Answer (опитування-група-питання-відповідь)
    • Імена змінних SGQA виглядають як 123X5X382X971 і можуть мати суфікси підпитань.
    • Ці імена змінних прив'язані до кодів S/Q/G/A у базі даних, тому їх часто потрібно змінювати
  5. Рівняння (тип питання): новий тип питання, який зберігає обчислення або звіти в базі даних:
    • Він подібний до питання типу «Текстовий блок», але його вміст зберігається в базі даних, навіть якщо вибрано «Завжди ховати це запитання».
  6. Код запитання: це бажане ім'я змінної для EM:
    • Це може бути описова назва, що вказує на призначення питання, що полегшує читання складної логіки.
    • Дійсні коди питань НЕ повинні починатися з цифри, тому для нумерації питань за допомогою коду просто використовуйте «q1», «q1a» або «g1q2».
    • Саме це стає іменем змінної під час експорту даних до SPSS або R. Тому, якщо ви проводите статистичний аналіз, потрібно створювати лише унікальні коди питань.


Чи обов'язково мені використовувати Expression Script?

Коротка відповідь: «ні». Проте це значною мірою залежить від складності опитування, яке ви хочете створити.

Наприклад, редактор умов охоплює деякі базові вирази, які можна застосувати до питань вашого опитування. Однак редактор умов обмежений. Саме тому використовується Expression Script - він розширює сферу можливостей налаштування.


Чи можна поєднувати умови та рівняння релевантності?

Так. Ви можете використовувати редактор умов для одних питань і рівняння релевантності для інших.

Ви не можете одночасно налаштувати умови та вирази в одному питанні! Щойно умову налаштовано, вона замінює будь-який вираз, записаний у полі рівняння релевантності. Крім того, поле рівняння релевантності більше не можна редагувати вручну.

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


Як вибрати між умовами та релевантністю?

Нижче наведено переваги та недоліки кожного підходу:

Підхід Переваги Недоліки
Умови 1. Зручний графічний інтерфейс для створення простих умов.
2. Графічний інтерфейс добре задокументований і зрозумілий службі підтримки
1. Підтримує лише прості порівняння і погано працює з умовами «І» та «АБО».
2. Каскадні умови працюють непередбачувано
3. Повільно - інтенсивне використання бази даних - може уповільнювати довгі опитування.
4. Є повідомлення про проблеми з перезавантаженням умов.
5. Графічний інтерфейс погано масштабується, коли є десятки, сотні чи тисячі питань.
6. Перенесення паперових опитувань може бути повільним, оскільки потрібно використовувати імена SGQA.
7. Часто потрібен програміст, щоб написати код для складного розгалуження.
Релевантність 1. Підтримує дуже складну логіку, зокрема понад 80 функцій та математичних/рядкових операторів.
2. Чудова підтримка каскадної логіки.
3. Швидко - без додаткових звернень до бази даних, підтримує опитування з понад 1000 питань.
4. Немає проблем із перезавантаженням логіки, оскільки коди SGQA не потрібні.
5. Підсвічування синтаксису масштабується на опитування з понад 1000 питань.
6. Простий і швидкий у використанні для груп, які хочуть автоматизувати наявні паперові опитування.
7. Легко підтримує напівструктуровані інтерв'ю та епідеміологічні опитування без залучення програміста.
1. Немає графічного інтерфейсу для простих умов - натомість використовується підсвічування синтаксису.


Примітка:
  • Рекомендуємо використовувати те, що краще відповідає вашим потребам.
  • Докладніше про можливості EM читайте за цим посиланням.

Початок роботи

Найкращий спосіб розпочати роботу з EM:

Термінологія

Ці терміни зазвичай використовують для опису можливостей EM:

  • Розгалуження на основі релевантності - якщо питання релевантне, його ставлять, інакше ні (наприклад, роблять невидимим і позначають як NULL у базі даних). Поля релевантності можна знайти на панелі редагування питання, а також на панелі редагування групи питань. Останнє використовується, щоб застосувати набір умов до цілої групи без копіювання тієї самої умови до кожного питання та/або поєднати логіку умов на рівні групи та питання).
  • Адаптація тексту (Tailoring) - коли ви знаєте, які питання потрібно ставити, адаптація (іноді її називають piping) визначає, як саме питання має бути поставлене. Це дає змогу підтримувати не лише просту підстановку (як-от {TOKEN:FIRSTNAME}), а й відмінювання дієслів та іменників залежно від статі чи числа ваших респондентів. Вона також дає змогу змінювати повідомлення для респондента залежно від того, чи відповів він (або як відповів) на інші питання.
  • Рівняння - EM додає новий тип питання під назвою Рівняння, який зберігає результат виразу. Результати рівнянь обчислюються й записуються в базу даних, навіть якщо ви приховуєте їх на сторінці. Тому їх використовують для прихованих обчислень балів, навігації на основі складних рівнянь, оцінювання та звітів, які будуть створені й збережені в базі даних.


Релевантність і каскадна релевантність

Кожен тип питання тепер має параметр релевантності, який визначає, чи відображається питання. EM обробляє кожне рівняння релевантності в тому порядку, в якому вони з'являються в опитуванні. Якщо вираз істинний (або відсутній - для підтримки застарілих опитувань), питання буде відображено. Якщо воно не релевантне, питання буде приховано, а значення в базі даних буде встановлено в NULL. Якщо в групі немає релевантних питань, вся група буде пропущена.

Крім того, якщо будь-яка зі змінних у виразі нерелевантна, вираз завжди повертає «хибність». Це забезпечує каскадну релевантність, тож вам не потрібно писати дуже довгі рівняння релевантності для кожного питання.

Припустімо, у вас є п'ять питань Q1-Q5, і ви хочете показувати Q2 лише якщо відповіли на Q1, Q3 - якщо відповіли на Q2 тощо. Рівняння релевантності можуть бути такими:

Код питання Релевантність Питання
Q1 1 Як вас звати?
Q2 Q1 {Q1}, скільки вам років?
Q3 Q2 Отже, вам {Q2} років. Ви одружені?
Q4 Q3 == "Y" {Q1}, як довго ви одружені?
Q5 Q4 Скільки у вас дітей, {Q1}?


Релевантність на рівні групи

ExpressionScript також підтримує релевантність на рівні групи. Це полегшує реалізацію циклів. Припустімо, ви хочете зібрати інформацію щодо до 10 об'єктів (наприклад, продуктів або членів домогосподарства), де спочатку визначаєте, скількох об'єктів потрібно стосуватися уточнювальні питання (наприклад, запитавши, скільки людей живе в домогосподарстві, або попросивши відзначити, які продукти їм подобаються, з довгого списку). Дізнавшись, скількох об'єктів стосуватимуться уточнювальні питання, ви можете використати релевантність на рівні групи, як-от {count >= 1}, {count >=2}, ... {count >= 10} для кожної з 10 груп уточнювальних питань. У кожній групі можна мати умовну логіку на рівні питання (наприклад, уточнювальні питання залежно від статі чи віку для кожного об'єкта). Рівняння релевантності на рівні питання та групи поєднуються через «І», щоб визначити, що слід показати.

Щоб переглянути такий приклад, імпортуйте таке опитування: приклад опитування для перепису.

На знімку екрана нижче видно, що група Person 1 відображається (або є релевантною), якщо респондент проживає принаймні з ще одним співмешканцем:



Адаптація тексту/Piping

Усе, що знаходиться у фігурних дужках, тепер розглядається як вираз (за одним винятком, описаним нижче). Вирази мають доступ до всіх LimeReplacementFields і змінних (через кілька псевдонімів), до всіх типових операторів рівнянь (математичних, логічних і порівняння), а також до десятків функцій (які навіть працюють динамічно на стороні клієнта).

Використовуючи ці рівняння, ви можете, наприклад:

  1. Умовно показувати респондентам адаптовані повідомлення на основі попередніх відповідей;
  2. Створювати оцінювання та показувати його результати (або умовно розгалужувати опитування чи показувати повідомлення на основі цих результатів), не використовуючи сам модуль оцінювання;
  3. Відмінювати дієслова та іменники у питаннях, відповідях і звітах;
  4. Показувати підсумки відповідей перед сторінкою «Показати ваші відповіді» в кінці опитування.


Рівняння

Існує новий тип питання під назвою Рівняння. Розглядайте його як тип питання «Відображення тексту», з тією різницею, що він зберігає в базі даних значення того, що відображається. Тож якщо текст питання типу «Рівняння» містить обчислення оцінювання, це значення буде збережено в базі даних у змінній, яку можна відобразити в публічній або приватній статистиці.


Синтаксис

Усе, що міститься у фігурних дужках, тепер вважається виразом (за одним винятком: не повинно бути пробілів на початку та в кінці — це потрібно, щоб ExpressionScript не намагався обробляти вбудований JavaScript).

Зверніть увагу, що вирази можуть займати кілька рядків, якщо після відкривної фігурної дужки або перед закривною немає пробілів. Це особливо корисно для вкладених операторів «if()», як у цьому прикладі:

{if(is_empty(PFTotals),
 '',
 if(PFTotals >= -5 && PFTotals <= -4,
   'Very Soft',
   if(PFTotals >= -3 && PFTotals <= -2,
     'Soft',
     if(PFTotals == -1,
       'Somewhat Soft',
       if(PFTotals == 0,
         'Moderate',
         if(PFTotals == 1,
           'Somewhat Hard',
           if(PFTotals >= 2 && PFTotals <= 3,
             'Hard',
             if(PFTotals >= 4 && PFTotals <= 5,
               'Very Hard',
               ''
             )
           )
         )
       )
     )
   )
 )
)}

ExpressionScript підтримує такий синтаксис:

  • Усі стандартні математичні оператори (напр. +,-,*,/,!);
  • Усі стандартні оператори порівняння (напр. <,<=,==,!=,>,>=, а також їхні еквіваленти: lt, le, eq, ne, gt, ge);
  • Круглі дужки (щоб групувати підвирази);
  • Умовні оператори (напр. &&,| | та їхні еквіваленти: and, or);
  • Рядки в одинарних і подвійних лапках (кожен з яких може містити вбудовані рядки з лапками іншого типу);
  • Оператор «кома» (дозволяє мати список виразів і повертати лише фінальний результат);
  • Оператор присвоєння (=);
  • Попередньо визначені змінні (для посилання на питання, атрибути питань і відповіді) — напр. коди SGQA;
  • Попередньо визначені функції (їх уже понад 80, і легко додати нові).


Оператори

Синтаксис EM дотримується звичайного пріоритету операторів:

Рівень Оператор(и) Опис
1 () круглі дужки для групування або виклику функцій
2 ! - + унарні оператори: НЕ, заперечення, унарний плюс
3 * / множення, ділення
4 + - додавання, віднімання
5 < <= > >= lt le gt ge порівняння «більше/менше»
6 == != eq ne порівняння на рівність
7 and логічне І
8 or логічне АБО
9 = оператор присвоєння
10 , оператор «кома»
Для узгодженості між JavaScript і PHP оператор плюс (+) виконує додавання, якщо обидва операнди числові, але виконує конкатенацію, якщо обидві частини є нечисловими рядками. Проте для конкатенації ми радимо використовувати функцію «join()», адже вона чіткіше передає ваш намір. Це також допомагає уникнути неочікуваних результатів, якщо ви очікували рядки, а отримали числа (або навпаки).

Застереження щодо невідповідності числа й рядка та алфавітного/числового порівняння

Коли ви порівнюєте значення за допомогою операторів «більше/менше» або рівності, звертайте увагу на невідповідності типів. Значення, введене користувачем (або надане через код відповіді), можна використовувати як число, якщо це явно число. Якщо взяти одне зі значень у ", відбудеться текстове/рядкове порівняння. Якщо ви хочете порівнювати як числа, ніколи не беріть число в ".

Наприклад, Q0.NAOK > "50" істинне, якщо Q0.NAOK — числове питання зі значенням 9. Це тому, що оператор > вважатиме порівняння алфавітним, а не числовим.

Щоб гарантувати порівняння цілих чисел, можна використати intval(Q0.NAOK) > 50. Пам’ятайте: якщо Q0.NAOK не є числом (порожнє значення або рядок), то intval(Q0.NAOK) === 0. Для порівняння рядків ("A" < "B") використовуйте безпосередньо strcmp: strcmp(Q0.NAOK,"B") або strcmp(Q0.NAOK,"A5").

Застереження щодо використання оператора присвоєння (=)

Уникайте використання операторів присвоєння, окрім випадків крайньої потреби, оскільки вони можуть спричинити неочікувані побічні ефекти. Наприклад, якщо змінити значення попередньої відповіді, каскадна релевантність і логіка перевірки між цим питанням і поточним не перераховуються, тож ви можете отримати внутрішньо суперечливі дані (наприклад, питання, які залишаються з відповіддю, але мали б бути обнулені, або питання, які пропущені, але мали б отримати відповідь). Загалом, якщо ви хочете присвоїти значення змінній, слід створити питання типу «Рівняння» і використати вираз для встановлення його значення. Однак іноді цей оператор справді потрібен, тому ми зробили його доступним.

Щоб застерегти вас щодо цього оператора, у рівняннях синтаксису він показаний червоним шрифтом (щоб ви не плутали його з «==»).



Використання оператора присвоєння

Основні причини, з яких вам може знадобитися оператор присвоєння:

  • Потрібно встановити значення за умовчанням через рівняння для питання, яке не приймає значень за умовчанням (наприклад, список із перемикачами, де інтерфейс дозволяє вибрати один із варіантів відповіді, але не дозволяє ввести рівняння). Однак будьте обережні, адже LimeSurvey не зможе перевірити, чи ваше рівняння генерує одну з допустимих відповідей для цього питання;
  • Потрібно примусово змінити відповідь на попереднє питання на основі пізнішої відповіді;
  • тощо...


  Увага : Присвоєння виконується лише в PHP. Це означає, що значення не оновлюється на тій самій сторінці, а лише тоді, коли користувач переходить на наступну сторінку. Тому будьте уважні, коли оператор присвоєння використовується на одній сторінці з іншими виразами.



Для цієї мети можна використовувати всю систему Expression Manager. Краще використовувати для цього Рівняння.

Деякі приклади:

  • Встановити відповідь на питання типу «Короткий текст» малими літерами : {QCODE=strtolower(QCODE.NAOK)};
  • Встановити відповідь за умовчанням для питання типу «масив» на початку опитування : {Q1_SQ1=(is_empty(Q1_SQ1.NAOK),"A99",Q1_SQ1.NAOK)};
  • Встановити відповідь за умовчанням для питання типу «масив текстів» на початку опитування : {Q1_SQY1_SQX1 = (is_empty(Q1_SQY1_SQX1.NAOK),"Inserted answer", Q1_SQY1_SQX1.NAOK)};
  • Встановити відповідь за умовою : {QCODE=if(YesNo="Y","A1","")}.

Безпека XSS

Коли XSS увімкнено, деякі частини системи Expression Manager використовувати не можна:

  • початок HTML-тегу у виразі, а його завершення в іншому виразі;
  • використання складного виразу в URL.


Зверніть увагу, що XSS-захист увімкнено за замовчуванням у будь-якій інсталяції LimeSurvey.


Приклади та способи обходу:

  • {if( 1 ,"<strong>","")}information{if( 1 ,"</strong>","")} не працює при увімкненому XSS-захисті, тут можна використати {if(1,"<strong>information</strong>","information")};
  • <a href="/script.php?value={if(QCODE == "Y","yes","no")}">next</a>, тут можна використати питання типу «Рівняння», оскільки використання повного коду питання допускається: <a href="/script.php?value={EQUATION.NAOK}">next</a>.


Доступ до змінних

ExpressionScript надає доступ лише для читання до будь-яких змінних, які вам можуть знадобитися. Для зворотної сумісності доступні такі змінні:

Крім того, ExpressionScript дозволяє посилатися на змінні за кодом запитання (стовпець 'title' у таблиці питань у базі даних). Це також мітка змінної, яка використовується під час експорту даних до SPSS, R або SAS. Наприклад, якщо у вас є питання про ім'я, вік і стать, ви можете назвати ці змінні name, age і gender замість 12345X13X22, 12345X13X23 і 12345X13X24. Це полегшує читання рівнянь і перевірку логіки для кожного, а також дає змогу переставляти питання місцями без необхідності стежити за номерами груп чи питань.

Важливо: безпечніше посилатися на змінні, що містяться на попередніх сторінках або в попередніх питаннях.

Крім того, ExpressionScript дозволяє отримати доступ до багатьох властивостей питання:


Синтаксис Значення Приклад Результат прикладу
Qcode псевдонім для Qcode.code {implode(',',name,gender)} 'Tom','M'
Qcode.code вибраний код відповіді на питання, якщо воно релевантне (інакше порожньо), або текстове значення, якщо питання не має кодованих відповідей {implode(',',name.code,gender.code)} 'Tom','M'
Qcode.NAOK те саме, що й Qcode - див. обговорення NAOK {gender.NAOK} 'M'
Qcode.value значення оцінки для питання, якщо воно релевантне (інакше порожньо), або текстове значення, якщо питання не має кодованих відповідей {gender.value} '1'
Qcode.valueNAOK те саме, що й Qcode.value - див. обговорення NAOK {gender.valueNAOK} '1'
Qcode.shown відображуване значення для питання {implode(',',name.shown,gender.shown)} 'Tom','Male'
Qcode.question текст питання {gender.question} 'What is your gender?'
Qcode.mandatory чи є питання обов'язковим (Y/N) {gender.mandatory} 'N'
Qcode.qid внутрішній номер питання (не порядковий номер) {gender.qid} 337
Qcode.type тип питання {gender.type} 'G'
Qcode.jsName правильна назва питання в javascript, незалежно від того, оголошене воно на цій сторінці чи ні {gender.jsName} 'java1827X3X337'
Qcode.gid внутрішній номер групи (не порядковий номер) {gender.gid} 3
Qcode.qseq порядковий номер питання, починаючи з 0 {gender.qseq} 5
Qcode.gseq порядковий номер групи, починаючи з 0 {gender.gseq} 1
Qcode.relevanceStatus чи є питання наразі релевантним (0 або 1) {gender.relevanceStatus} 1
Qcode.relevance рівняння релевантності на рівні питання {gender.relevance} '!is_empty(name)'
Qcode.grelevance рівняння релевантності на рівні групи {gender.grelevance} 'num_children >= 5'
Qcode.sgqa значення SGQA для цього питання {gender.sgqa} '1827X3X337'


Проблема з HTML редактором

Якщо ви використовуєте HTML редактор, деякі символи замінюються на HTML-сутності.

  • & на &amp;
  • < на &lt;
  • > на &gt;

Якщо ви використовуєте HTML редактор, потрібно використовувати:

  • and замість &
  • lt замість <
  • le замість <=
  • gt замість >
  • ge замість >=


Рекомендується очищати вираз від HTML-коду, що з'являється всередині виразу. Якщо ви використовуєте HTML редактор LimeSurvey, натисніть кнопку «Джерело» (у верхній лівій частині редактора) та видаліть усі символи, не пов'язані з вашим виразом (наприклад,

,
тощо).

Іменування змінних Qcode

Нижче наведено подробиці того, як формувати Qcode (і отримувати доступ до деяких властивостей) залежно від типу питання. Загалом Qcode формуються так:

 QuestionCode . '_' . SubQuestionID . '_' . ScaleId

Для коментаря та іншого відповідні коди питань мають вигляд QuestionCode_comment та QuestionCode_other.

Тип Опис Код Підпитання Варіанти відповідей Шкали Код відповіді Показана відповідь Релевантність
5 Вибір із 5 варіантів, радіокнопки Q1 1-5 {Q1} {Q1.shown} {Q1==3}
B Масив (вибір із 10 пунктів), радіокнопки Q2 L1-L6 1-10 {Q2_L2} {Q2_L2.shown} {Q2_L2==7}
A Масив (вибір із 5 пунктів), радіокнопки Q3 1-5 1-5 {Q3_1} {Q3_1.shown} {Q3_1>=3}
1 Масив (гнучкі мітки), подвійна шкала Q4 sq1-sq5 0:a1-a3 1:b1-b3 {Q4_sq1_0} {Q4_sq1_1.shown} {Q4_sq1_1=='b2'}
H Масив (гнучкий) - формат стовпців Q5 1-5 s,m,t {Q5_1} {Q5_1.shown} {Q5_1=='s'}
F Масив (гнучкий) - формат рядків Q6 F1-F5 1-5 {Q6_F3} {Q6_F3.shown} {Q6_F3==4}
E Табличне запитання (Підвищення/Той самий рівень/Зниження), радіокнопки Q7 1-7 I,S,D {Q7_4} {Q7_4.shown} {Q7_4=='D'}
: Масив (множинні гнучкі) від 1 до 10 Q8 ls1,todo,ls2 min,max,avg {Q8_ls1_max} {Q8_ls2_avg.shown} {Q8_ls2_min==7}
; Масив (множинні гнучкі) текст Q9 hp,st,sw 1st,2nd,3rd {Q9_hp_3rd} {Q9_hp_3rd.shown} {Q9_hp_3rd=='Peter'}
C Масив (Так/Невизначено/Ні), радіокнопки Q10 1-5 Y,N,U {Q10_1} {Q10_1.shown} {Q10_3=='Y'}
X Питання-заготовка (Boilerplate) Q11 {Q11.shown}
D Дата Q12 {Q12} {Q12.shown}
* Рівняння Q13 {Q13} {Q13.shown} {Q13>5}
~124~ Завантаження файлу (записує кількість завантажених файлів) Q14 {Q14} {Q14>0}
G Список «Стать», що розкривається Q15 M,F {Q15} {Q15.shown} {Q15=='M'}
U Величезний довільний текст Q16 {Q16} {Q16.shown} {strlen(Q16)>100}
I Питання «Мова» Q17 {Q17} {Q17.shown} {Q17=='en'}
! Список - випадаючий Q18 1-5 {Q18} {Q18.shown} {Q18==3}
L Список, що розкривається/радіокнопки Q19 A-Z {Q19} {Q19.shown} {Q19=='X'}
O Список з коментарями, що розкривається/радіокнопки + текстова область Q20 A-F {Q20},{Q20comment} {Q20.shown} {Q20=='B'}
T Довгий довільний текст Q21 {Q21} {Q21.shown} {strstr(Q21,'hello')>0}
M Множинний вибір, прапорці Q22 A-F, other {Q22_E}, {Q22_other} {Q22_E.shown}, {Q22_other.shown} {Q22_E=='Y'}
P Множинний вибір з коментарями, прапорець + текст Q23 A-F {Q23_D}, {Q23_Dcomment} {Q23_D.shown} {!is_empty(Q23)}
K Множинне числове питання Q24 self,mom,dad {Q24_self} {Q24_self.shown} {Q24_self>30}
Q Кілька коротких текстів Q25 A-F {Q25_B} {Q25_B.shown} {substr(Q25_B,1,1)=='Q'}
N Числове питання Q26 {Q26} {Q26.shown} {Q26 > 30}
R Рейтинг Q27 1-4 {Q27_1} {Q27_1.shown} {Q27_1==3}
S Короткий довільний текст Q28 {Q28} {Q28.shown} {Q28=='mine'}
Y Так/Ні, радіокнопки Q29 {Q29} {Q29.shown} {Q29=='Y'}


Використання NAOK

NAOK --> «Не застосовується» (NA) допустимо (OK)


Використання NAOK означає, що всі або деякі змінні нерелевантні (тобто «Не застосовується» (NA) допустимо (OK)).

Наприклад: count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) завжди повертає порожній рядок, якщо одне з підпитань Q1 відфільтроване. Щоб підрахувати кількість позначених підпитань у такому питанні, можна використати count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK). Якщо підпитання приховане, EM повертає порожній рядок.

Без NAOK, якщо одне питання або одне підпитання приховане, EM завжди повертає порожній рядок (що рівнозначно поверненню false).

Суфікс .shown завжди використовує систему NAOK (порожній рядок, якщо приховано), але якщо вам потрібен код відповіді, завжди варто додавати .NAOK після коду питання (за винятком випадків, коли він вам потрібен і ви розумієте, що робите).

Додаткову інформацію наведено в підрозділі «Перевизначення каскадних умов».


Зарезервовані змінні «this», «self» та «that»

Досить часто потрібно оцінити всі частини питання, наприклад, підрахувати, скільки підпитань отримали відповідь, або підсумувати бали. В інших випадках потрібно обробити лише певні рядки чи стовпці питання (наприклад, отримати суми по рядках чи стовпцях і зберегти їх у базі даних). Ці зарезервовані змінні роблять цей процес відносно простим.


Змінна «this»

Змінна «this» використовується виключно в опціях «Рівняння перевірки питання» та «Рівняння для перевірки додаткового запитання» (остання недоступна з графічного інтерфейсу). Вона розгортається в імена змінних кожної з комірок цих питань. Отже, якщо ви хочете переконатися, що кожне значення більше трьох, слід встановити для «Рівняння для перевірки додаткового запитання» значення (this > 3).


Змінна «self»

Змінні «self» та «that» є потужнішими й слугують макросами, які розгортаються перед обробкою рівнянь. Варіанти синтаксису для змінної «self»:

  • self
  • self.суфікс
  • self.підселектор
  • self.підселектор.суфікс
  1. suffix — це будь-який зі звичайних суфіксів qcode (наприклад, NAOK, value, shown)
  1. sub-selector може бути одним із таких:
  • comments - лише підпитання, які є коментарями (наприклад, множинний вибір з коментарями та список з коментарями);
  • nocomments - лише підпитання, які не є коментарями;
  • sq_X - де X — ідентифікатор рядка або стовпця. Вибираються лише підпитання, що відповідають шаблону X. Зверніть увагу: пошук виконується за повним ідентифікатором коду, тому sq_X збігається з підпитаннями nX, X, Xn і включає їх (наприклад, якщо ви використовуєте sq_1, будуть включені підпитання a1, 1a, 1, 11 або 001). Будьте уважні з типом питання з подвійною шкалою, де коди підпитань мають вигляд QCODE_SQCODE_1 і QCODE_SQCODE_1, та з типом питання «рейтинг», де коди підпитань мають вигляд QCODE_1, QCODE_2 ....

Приклади:

  • Чи була дана відповідь на якусь частину питання? -> {count(self.NAOK)>0}
  • Яка оцінка за це питання? -> {sum(self.value)}

Ви також можете використовувати їх для отримання підсумків за рядками та стовпцями. Припустімо, у вас є масив чисел із рядками A-E і стовпцями 1-5.

  • Який загальний підсумок? -> {sum(self.NAOK)}
  • Яка сума в рядку B? -> {sum(self.sq_B.NAOK)}
  • Яка сума в стовпці 3? -> {sum(self.sq_3.NAOK)}


Змінна "that"

Змінна "that" подібна до змінної "self", але дає змогу посилатися на інші питання. Її синтаксис:

  • that.qname
  • that.qname.suffix
  • that.qname.sub-selector
  • that.qname.sub-selector.suffix

qname — це назва питання без жодних розширень підпитань. Отже, створімо питання 'q1', де 'q' також представляє його qname.

Приклади:

  • Чи була дана відповідь на якусь частину питання q1? -> {count(that.q1.NAOK)>0}
  • Яка оцінка за питання q2? -> {sum(that.q2.NAOK)}
  • Який загальний підсумок для q3? -> {sum(that.q3.NAOK)}
  • Яка сума в рядку C питання q4? -> {sum(that.q4.sq_C.NAOK)}
  • Яка сума в стовпці 2 питання q4? -> {sum(that.q4.sq_2.NAOK)}

Змінні "self" і "that" можна використовувати в будь-якій релевантності, перевірці або персоналізації.

Єдине застереження: коли ви використовуєте функцію Show logic file, вона показуватиме розгорнуте значення "self" і "that". Це дає змогу побачити фактичне рівняння, яке буде згенеровано, щоб ви (і EM) могли перевірити, чи існують змінні. Це може збивати з пантелику, оскільки ви можете побачити досить довгі рівняння. Проте, якщо ви відредагуєте питання, то побачите початкове рівняння з використанням "self" та/або "that".

Не слід використовувати ці змінні, якщо ви
  • хочете явно називати кожну змінну, використану в рівнянні, або
  • використовуєте змінні, які не мають підпитань (наприклад, питання з однією відповіддю). У таких випадках додавати до змінної префікс "that" надмірно, і ви ризикуєте отримати неочікувані результати.

Доступ до функцій

ExpressionScript надає доступ до математичних, рядкових і користувацьких функцій, як показано нижче. Для цих функцій є еквіваленти в PHP та JavaScript, тому вони працюють однаково на стороні сервера (PHP) і на стороні клієнта (JavaScript). Додавати нові функції легко.


Реалізовані функції

Наразі доступні такі функції:

Функція Значення Синтаксис
abs Абсолютна величина number abs(number)
acos Арккосинус number acos(number)
addslashes Екранувати рядок за допомогою зворотних скісних рисок string addslashes(string)
asin Арксинус number asin(number)
atan Арктангенс number atan(number)
atan2 Арктангенс двох змінних number atan2(number, number)
ceil Округлити дроби вгору number ceil(number)
checkdate Повертає true(1), якщо це допустима дата за григоріанським календарем bool checkdate(month,day,year)
convert_value Перетворити числове значення за допомогою вхідної та вихідної таблиць числових значень number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList)
cos Косинус number cos(number)
count Підрахувати кількість питань у списку, на які є відповідь (непорожніх) number count(arg1, arg12, ..., argN)
countif Підрахувати кількість питань у списку з відповідями, що дорівнюють першому аргументу number countif(matches, arg1, arg2, ... argN)
countifop Підрахувати кількість питань у списку з відповідями, які відповідають критерію (arg op value) number countifop(op, value, arg1, arg2, ... argN)
date Форматувати місцеву дату / час string date(format [, timestamp=time()])
exp Розрахувати експоненту e number exp(number)
fixnum Відображати числа з комою як роздільником дробової частини, якщо потрібно string fixnum(number)
floor Округлити дроби вниз number floor(number)
gmdate Форматувати дату / час GMT string gmdate(format [, timestamp=time()])
html_entity_decode Перетворити всі HTML-сутності на відповідні символи (завжди використовує ENT_QUOTES та UTF-8) string html_entity_decode(string)
htmlentities Перетворити всі відповідні символи на HTML-сутності (завжди використовує ENT_QUOTES та UTF-8) string htmlentities(string)
expr_mgr_htmlspecialchars Перетворити спеціальні символи на HTML-сутності (завжди використовує ENT_QUOTES та UTF-8) string htmlspecialchars(string)
expr_mgr_htmlspecialchars_decode Перетворити спеціальні HTML-сутності назад на символи (завжди використовує ENT_QUOTES та UTF-8) string htmlspecialchars_decode(string)
idate Форматувати місцевий час / дату як ціле число string idate(string [, timestamp=time()])
if if у стилі Excel: if(test,result_if_true,result_if_false) if(test,result_if_true,result_if_false)
implode З'єднати елементи масиву в рядок string implode(glue,arg1,arg2,...,argN)
intval Отримати значення ціллого числа змінної int intval(number [, base=10])
is_empty Визначити, чи вважається змінна порожньою bool is_empty(var)
is_float Дізнатися чи тип змінної є числом з плаваючою комою bool is_float(var)
is_int Дізнатися чи тип змінної є цілим числом bool is_int(var)
is_nan Дізнатися чи значення не є числом bool is_nan(var)
is_null Дізнатися чи змінна є порожньою (нульовою) bool is_null(var)
is_numeric Дізнатися чи змінна є числом або числовим рядком bool is_numeric(var)
is_string Дізнатися чи тип змінної є рядком bool is_string(var)
join (New in 2.0 build 130129) З'єднати елементи в новий рядок join(arg1, arg2, ... argN)
list Повернути список непорожніх значень, розділених комами string list(arg1, arg2, ... argN)
listifop (New in 3.16.1 ) Повернути список вказаної властивості питання (retProp), розділений роздільником 'glue', для питань зі списку, які відповідають критерію (cmpProp op value) string listifop(cmpProp, op, value, retProp, glue, sgqa1, sgqa2, ... sgqaN)
ltrim Видалити пропуски (або інші символи) на початку рядка string ltrim(string [, charlist])
max Знайти найбільше значення number max(arg1, arg2, ... argN)
min Знайти найменше значення number min(arg1, arg2, ... argN)
mktime Отримати штамп часу UNIX для дати (кожен із 6 аргументів необов'язковий) number mktime([hour [, minute [, second [, month [, day [, year ]]]]]])
modulo-function Функція модуля ще не підтримується. Натомість можна використати функцію floor() floor(x/y)==(x/y)
nl2br Вставляє HTML-розриви рядків перед усіма символами нового рядка в рядку string nl2br(string)
number_format Форматувати число до тисячних string number_format(number)
pi Отримати значення числа Пі number pi()
pow Експоненціальний вираз number pow(base, exp)
quoted_printable_decode Перетворити рядок quoted-printable на 8-бітний рядок string quoted_printable_decode(string)
quoted_printable_encode Перетворити 8-бітний рядок на рядок quoted-printable string quoted_printable_encode(string)
quotemeta Поставити лапки для метасимволів string quotemeta(string)
rand Згенерувати випадкове ціле число, див. цей приклад int rand() OR int rand(min, max)
regexMatch порівняти рядок із регулярним виразом bool regexMatch(pattern,input)
round Округлення числа до додаткової точності number round(val [, precision])
rtrim Видалити пропуски (або інші символи) в кінці рядка string rtrim(string [, charlist])
sin Синус number sin(arg)
sprintf Повернути відформатований рядок string sprintf(format, arg1, arg2, ... argN)
sqrt Квадратний корінь number sqrt(arg)
stddev Обчислити вибіркове стандартне відхилення для списку чисел number stddev(arg1, arg2, ... argN)
str_pad Доповнити рядок іншим рядком до заданої довжини string str_pad(input, pad_length [, pad_string])
str_repeat Повторити рядок string str_repeat(input, multiplier)
str_replace Замінити всі входження шуканого рядка рядком заміни string str_replace(search, replace, subject)
strcasecmp Бінарне безпечне порівняння рядків без урахування регістру int strcasecmp(str1, str2)
strcmp Бінарне безпечне порівняння рядків int strcmp(str1, str2)
strip_tags Зняти HTML та PHP теги з рядка string strip_tags(str, allowable_tags)
stripos Знайти позицію першого входження рядка Unicode без урахування регістру (відлік починається з 0, повертає false, якщо не знайдено) int stripos(haystack, needle [, offset=0])
stripslashes Зняти лапки рядка з лапками string stripslashes(string)
stristr Без урахування регістру strstr (Case-insensitive strstr) string stristr(haystack, needle [, before_needle=false])
strlen Отримати довжину рядка int strlen(string)
strpos Знайти позицію першого входження рядка Unicode (відлік починається з 0, повертає false, якщо не знайдено) int strpos(haystack, needle [ offset=0])
strrev Перевернути рядок string strrev(string)
strstr Знайти перший випадок рядка string strstr(haystack, needle[, before_needle=false])
strtolower Перетворити рядок на нижній регістр string strtolower(string)
strtotime Перетворити майже будь-який англійський текстовий опис дати й часу на штамп часу Unix int strtotime(string)
strtoupper Перетворити рядок на верхній регістр string strtoupper(string)
substr Повернути частину рядка Unicode string substr(string, start [, length])
sum Обчислити суму значень масиву number sum(arg1, arg2, ... argN)
sumifop Підсумувати значення питань у списку з відповідями, які відповідають критерію (arg op value) number sumifop(op, value, arg1, arg2, ... argN)
tan Тангенс number tan(arg)
time Повертати поточний штамп дати/часу UNIX number time()
trim Видалити пропуски (або інші символи) на початку й в кінці рядка string trim(string [, charlist])
ucwords Перетворити перший символ кожного слова в рядку на верхній регістр string ucwords(string)
unique Повертати істину, якщо усі непорожні відповіді є унікальними boolean unique(arg1, ..., argN)
Натисніть тут, щоб дізнатися більше про заплановані (або розглядувані) функції.

<span id="Create_new_expression_functions_with_plugin_ (New in 4.0.0 )">

Створення нових функцій виразів за допомогою плагіна (New in 4.0.0 )

Якщо вам потрібна нова функція, якої немає в ядрі, ви можете створити її за допомогою плагіна. Така нова функція створюється за допомогою події expressionManagerStart.

ExpressionScript знає, які змінні є локальними

Щоб правильно сформувати JavaScript для сторінки, EM має знати, які змінні задано на цій сторінці та який у них JavaScript ID (наприклад, для document.getElementById(x)). Він також має знати, які змінні задано на інших сторінках (щоб гарантувати, що потрібні поля <input type='hidden' value='x'> присутні та заповнені).


Каскадні умови

Якщо будь-яка зі змінних нерелевантна, усе рівняння буде нерелевантним (false). Наприклад, у наведеній нижче таблиці N/A означає, що одна зі змінних не була релевантною:


Оператор Приклад a b Результат
+ (unary) +a N/A false
! !a N/A false
== (or eq) a == b N/A 5 false
== (or eq) a == b N/A 0 false
== (or eq) a == b N/A N/A false
!= (or ne) a != b N/A 5 false
!= (or ne) a != b N/A N/A false
!= (or ne) a != b N/A 0 false
> (or gt) a > b N/A 5 false
>= (or ge) a >= b N/A 5 false
< (or lt) a < b N/A 5 false
<= (or le) a <= b N/A 5 false
and a and b N/A 5 false
and a and b N/A N/A false
or a or b N/A N/A false
or a or b N/A 5 false
+ a + b N/A 5 false
* a * b N/A 5 false
/ a / b 5 N/A false
() (a) N/A false
(exp) (a && b) N/A 5 false
(exp) op (exp) (b + b) > (a && b) N/A 5 false
function sum(a,b,b) N/A 5 false
function max(a,b) N/A 5 false
function min(a,b) N/A 5 false
function implode(', ',a,b,a,b) N/A 5 false
function if(a,a,b) N/A 5 false
function is_empty(a) N/A false
function is_empty(a) 0 (or blank) true
function !is_empty(a) N/A false


Перевизначення каскадних умов

Припустімо, ви хочете показати поточну суму всіх релевантних відповідей. Ви можете спробувати використати рівняння {sum(q1,q2,q3,...,qN)}. Однак внутрішньо воно перетворюється на LEMif(LEManyNA("q1","q2","q3",...,"qN"),"",sum(LEMval("q1"),LEMval("q2"),LEMval("q3"),...,LEMval("qN"))). Тож якщо будь-яке зі значень q1-qN нерелевантне, рівняння завжди повертатиме false. У цьому випадку sum() показуватиме "0", доки не буде надано відповіді на всі питання.

Щоб цього уникнути, до кожної змінної можна додати суфікс ".NAOK" (означає, що «Not Applicable» — це нормально). У такому разі спрацьовує така поведінка. Припустімо, у вас є змінна q1.NAOK:

  1. q1 не додається до виразу LEManyNA()
  2. LEMval('q1') і далі перевірятиме, чи відповідь релевантна, і повертатиме "", якщо ні (тобто окремі нерелевантні відповіді буде проігноровано, але вони не зроблять недійсним увесь вираз).

Отже, розв’язком проблеми поточної суми є використання рівняння sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).

Використання суфікса .NAOK також дає змогу авторам створювати опитування з кількома можливими шляхами, які згодом сходяться на спільних шляхах. Наприклад, респонденти відповідають на опитування так, що їхні відповіді виходять за межі звичайного діапазону. Автор може попередити їх, що результати можуть бути недійсними, і запитати, чи вони справді хочуть продовжити опитування. Якщо вони відповідають «Так», решту питань буде показано. Умова для «решти питань» перевірятиме, чи початкові відповіді були в межах звичайного діапазону, АБО чи респондент відповів «Так» на питання, яке релевантне лише тоді, коли відповіді були поза звичайним діапазоном.

Як ExpressionScript підтримує умовне мікротейлорінг?

Ось приклад мікротейлорінгу (де Question Type=='expr' означає рівняння):


Код питання Релевантність Тип питання Питання
name 1 text Як вас звати?
age 1 text Скільки вам років?
badage !is_empty(age) expr {(age<16) or (age>80)}
agestop badage message Вибачте, {name}, ви надто {if( (age<16),'young',if( (age>80),'old','middle-aged') ) } для цього тесту.
kids !badage yesno Чи є у вас діти?
parents 1 expr {!badage && kids=='Y'}
numKids parents text Скільки у вас дітей?
kid1 parents && numKids >= 1 text Скільки років вашій першій дитині?
kid2 parents && numKids >= 2 text Скільки років вашій другій дитині?
kid3 parents && numKids >= 3 text Скільки років вашій третій дитині?
kid4 parents && numKids >= 4 text Скільки років вашій четвертій дитині?
kid5 parents && numKids >= 5 text Скільки років вашій п’ятій дитині?
sumage 1 expr {sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)}
report parents text {name}, ви вказали, що вам {age} і що у вас {numKids} дітей. Сума віку ваших перших {min(numKids,5)} дітей становить {sumage}


Щоб завантажити наведений вище приклад опитування, натисніть на таке посилання: Приклад опитування про кількість дітей.

Усі ці питання можуть бути на одній сторінці (наприклад, в одній групі), і буде показано лише релевантні питання. Крім того, під час введення віку дітей вираз sum() в останньому питанні динамічно оновлюватиметься.

ExpressionScript забезпечує цю функціональність, обгортаючи кожен вираз в іменований елемент <span>. Щоразу, коли значення змінюється, він повторно обчислює вираз, який має відображатися в цьому елементі <span>, і оновлює відображення. На одній сторінці може бути десятки або навіть сотні таких виразів.


Підсвічування синтаксису

Щоб допомогти під час введення та перевірки виразів, EM пропонує підсвічування синтаксису з такими можливостями:

Типи та значення підсвічування синтаксису

Колір Зразок Значення Підказка Коментарі
бежевий фон Sample усе рівняння немає Усе у фігурних дужках, що розпізнається як рівняння (тобто немає пробілів на початку чи в кінці), буде виділено бежевим фоном, щоб відрізняти його від навколишнього тексту
жирний червоний текст Sample Помилка Пояснення помилки Може бути невідома змінна або помилка у функції. Опитування не працює, а питання, що залежать від відповідного виразу, не буде показано респондентам.
синій текст Sample назва функції значення та допустимий синтаксис Позначає назви функцій або те, що має бути функціями, оскільки далі йде відкрита дужка. Вони відображаються жирним синім текстом. Підказки показують значення та допустимий синтаксис функції.
сірий текст Sample рядок немає Рядки в одинарних і подвійних лапках відображаються сірим текстом.
блакитний текст Sample змінна, задана на цій самій сторінці, [name]: питання; значення; answerList із кодами для кожного значення Будь-яка змінна, задана на тій самій сторінці, що й питання, яке ви зараз редагуєте, відображається блакитним текстом (її можна оновлювати в JavaScript). Підказка показує її назву, саме питання та поточне значення (або порожнє, якщо не задано). Якщо тип питання передбачає відповіді з переліченого набору значень, показується відповідність кодів значенням, що відображаються.
зелений текст Sample змінна, задана на попередній сторінці [name]: питання; значення; answerList із кодами для кожного значення Будь-яка змінна, задана на попередній сторінці, відображається жирним зеленим текстом. Підказка показує її назву, саме питання та поточне значення (або порожнє, якщо не задано). Якщо тип питання передбачає відповіді з переліченого набору значень, показується відповідність кодів значенням, що відображаються.
жирний рожевий текст Sample змінна, задана на наступній сторінці загалом: порожня на початку опитування, але може бути заповнена за допомогою індексу або кнопки «Назад» [name або код SGQA]: питання; значення; answerList із кодами для кожного значення Будь-яка змінна, задана на наступній сторінці, відображається жирним рожевим текстом. Підказка показує її назву, саме питання та поточне значення (або порожнє, якщо не задано). Якщо тип питання передбачає відповіді з переліченого набору значень, показується відповідність кодів значенням, що відображаються.
жирний бежевий текст Sample значення заміни Lime значення Рядки заміни Lime (як-от {TOKEN:xxx}, {PRIVACY_MESSAGE}) відображаються жирним бежевим текстом.
червоний текст Sample оператор присвоєння (=) попередження Якщо ви використовуєте оператор присвоєння (=), його буде показано червоним текстом. Це допомагає запобігти випадковому перевизначенню значень, коли ви насправді хотіли перевірити, чи a == b, а не задати значення a = b.
звичайний чорний текст Sample розділові знаки немає Усі інші розділові знаки у виразі відображаються звичайним чорним текстом.
текст у червоній рамці жирна червона лінія оточує помилку синтаксична помилка опис помилки Будь-які виявлені синтаксичні помилки показуються в червоних рамках. Підказка показує помилку. Приклади: незакриті дужки, використання невизначених функцій, передавання функціям неправильної кількості аргументів, погано структуровані вирази (наприклад, відсутні оператори між змінними), спроба присвоїти нове значення змінній лише для читання, спроба присвоїти значення не змінним або використання синтаксису, що не підтримується. Зауважте, що система виявлення синтаксичних помилок може повідомити лише про одну помилку у виразі, навіть якщо їх кілька; проте якщо виявлено будь-які помилки, буде показано принаймні одну.


Під підказками ми маємо на увазі спливне повідомлення, яке з’являється, коли ви наводите курсор на певні функції та змінні.


Додаткові матеріали

Приклади опитувань ExpressionScript

Сценарії використання та інструкції

Покрокові приклади

Довідник для розробників

Дорожня карта, стан, список завдань