ExpressionScript - العرض
From LimeSurvey Manual
مقدمة
يستخدم LimeSurvey سكريبت التعبير (Expression Script) الذي يتيح لـ LimeSurvey دعم تفرعات أكثر تعقيدًا، والتقييمات، والتحقق من الصحة، والتخصيص. وهو يحل محل الطريقة التي يدير بها LimeSurvey الاستبدالات والشروط والتقييمات في الواجهة الخلفية. كما أنه يسرّع المعالجة بشكل كبير لأنه يلغي معظم عمليات القراءة من قاعدة البيانات أثناء التشغيل. تم تطوير سكريبت التعبير بواسطة الدكتور توماس وايت (TMSWhite).
التعريفات الرئيسية
- التعبير (Expression): أي شيء محاط بأقواس معقوفة:
- طالما لا توجد مسافة فارغة مباشرة بعد القوس الافتتاحي أو قبل القوس الختامي.
- يتم تقييم محتوى التعبير بواسطة EM، لذلك يمكن أن يحتوي على صيغ رياضية ودوال ومعالجة معقدة للنصوص والتواريخ.
- التخصيص (Tailoring): يسمى أحيانًا "piping". وهو عملية تعديل النص بشكل شرطي:
- لديك إمكانية الوصول إلى جميع "حقول الاستبدال" وبيانات المشارك وبيانات الردود.
- كما يمكنك الوصول بسهولة أكبر إلى الأسئلة والإجابات وخصائصها.
- معادلة الصلة (Relevance): سمة سؤال جديدة تتحكم في ظهور السؤال:
- إذا كانت هناك معادلة صلة، فلن يظهر السؤال إلا إذا كانت نتيجة تقييم الصلة صحيحة.
- داخليًا، تتحول جميع أوامر array_filter وarray_filter_exclude إلى صلة على مستوى السؤال الفرعي.
- SGQA (الطريقة التي كانت تُسمى بها المتغيرات في الماضي):
- ويعني Survey-Group-Question-Answer (الاستبيان - المجموعة - السؤال - الإجابة)
- تبدو أسماء متغيرات SGQA مثل 123X5X382X971، وقد تحتوي على لواحق للأسئلة الفرعية.
- هذه الأسماء خاصة برموز قاعدة البيانات الأساسية S/Q/G/A، لذلك غالبًا ما تحتاج إلى التغيير
- نوع السؤال معادلة (Equation): نوع سؤال جديد يحفظ الحسابات أو التقارير في قاعدة البيانات:
- وهو يشبه سؤال Boilerplate، لكن محتوياته تُحفظ في قاعدة البيانات حتى إذا قمت بتعيين "دائما اخف هذا السؤال".
- كود السؤال: هذا هو اسم المتغير المفضل لـ EM:
- يمكن أن يكون اسمًا وصفيًا يشير إلى غرض السؤال، مما يسهّل قراءة المنطق المعقد.
- يجب ألا تبدأ أكواد الأسئلة الصالحة برقم، لذلك عند استخدام كود السؤال لترقيم أسئلتك، استخدم ببساطة "q1" أو "q1a" أو "g1q2".
- هذا هو ما يصبح اسم المتغير إذا قمت بتصدير البيانات إلى SPSS أو R. لذا إذا كنت تجري تحليلًا إحصائيًا، فعليك إنشاء أكواد أسئلة فريدة فقط.
هل يجب أن أستخدم سكريبت التعبير؟
الإجابة المختصرة هي "لا". ومع ذلك، يعتمد ذلك إلى حد كبير على مدى تعقيد الاستبيان الذي تريد إنشاءه.
على سبيل المثال، يغطي محرر الشروط بعض التعبيرات الأساسية التي يمكن تطبيقها على أسئلة استبيانك. ومع ذلك، فإن محرر الشروط محدود. ولهذا السبب يُستخدم سكريبت التعبير - فهو يوسع نطاق إمكانيات التخصيص.
هل يمكنني الجمع بين الشروط ومعادلات الصلة؟
نعم. يمكنك استخدام محرر الشروط لبعض الأسئلة ومعادلات الصلة لأسئلة أخرى.
لا يمكنك إعداد الشروط والتعبيرات معًا في السؤال نفسه! بمجرد إعداد شرط، فإنه يحل محل أي تعبير مكتوب في حقل معادلة الصلة. علاوة على ذلك، لا يمكن بعد ذلك تحرير حقل معادلة الصلة يدويًا.
ومع ذلك، هناك طريقة لاستخدام التعبيرات والشروط معًا داخل السؤال. كما ذُكر أعلاه، يحل الشرط محل حقل معادلة الصلة. بعد ذلك، تحقق من المعادلة التي تم إنشاؤها حديثًا وانسخها في محرر نصوص. احذف الشرط الذي تم إنشاؤه من محرر الشروط ثم حرر السؤال بإضافة التعبيرات المبنية على الشرط من ملف محرر النصوص إلى جانب بقية التعبيرات التي ترغب في استخدامها.
كيف أختار بين الشروط والصلة؟
فيما يلي قائمة بمزايا وعيوب كل أسلوب:
| الأسلوب | المزايا | العيوب |
|---|---|---|
| الشروط | 1. واجهة رسومية لطيفة لإنشاء شروط بسيطة. 2. الواجهة الرسومية موثقة جيدًا ومفهومة لدى فريق الدعم |
1. تدعم المقارنات البسيطة فقط ولا تتعامل جيدًا مع شروط "AND" و"OR". 2. الشروط المتتالية تعمل بشكل غير منتظم 3. بطيئة - تعتمد بكثافة على قاعدة البيانات - وقد تبطئ الاستبيانات الطويلة. 4. تم الإبلاغ عن بعض المشكلات عند إعادة تحميل الشروط. 5. الواجهة الرسومية لا تتوسع جيدًا عند وجود عشرات أو مئات أو آلاف الأسئلة. 6. قد يكون تحويل الاستبيانات الورقية بطيئًا لأنه يجب استخدام أسماء SGQA. 7. غالبًا ما تحتاج إلى مبرمج لكتابة المنطق المخصص اللازم للتفرعات المعقدة. |
| الصلة | 1. تدعم منطقًا معقدًا جدًا، بما في ذلك أكثر من 80 دالة ومعاملات رياضية ونصية. 2. دعم مثالي لـالمنطق المتتالي. 3. سريعة - بدون استدعاءات إضافية لقاعدة البيانات، وتدعم استبيانات تضم أكثر من 1000 سؤال. 4. لا مشكلات في إعادة تحميل المنطق لأنها لا تتطلب رموز SGQA. 5. تمييز الصياغة يتوسع ليشمل استبيانات تضم أكثر من 1000 سؤال. 6. سهلة وسريعة الاستخدام للمجموعات التي ترغب في حوسبة الاستبيانات الورقية الحالية. 7. تدعم بسهولة المقابلات شبه المنظمة والاستبيانات الوبائية دون الحاجة إلى مبرمج. |
1. لا توجد واجهة رسومية للشروط البسيطة - بل تعتمد على تمييز الصياغة. |
- نوصيك باستخدام ما يناسب احتياجاتك بشكل أفضل.
- لمزيد من الشرح التفصيلي لميزات EM، انقر على الرابط التالي.
البدء
أفضل طريقة للبدء مع EM هي:
- تثبيت أحدث إصدار مستقر من https://www.limesurvey.org/en/download.
- استيراد واستكشاف بعض الاستبيانات النموذجية.
- استكشاف حالات الاستخدام والأدلة الإرشادية، والأمثلة خطوة بخطوة.
- استكشاف وثائق EM (هذه الصفحة)
- اختبارات الوحدة للتعبيرات المعزولة (متقدم)
- تعرض أمثلة على استخدام جميع دوال ومعاملات EM، ونتائج PHP وJavaScript؛
- لاحظ أن هناك بعض الدوال التي تعطي نتائج مختلفة في إصداري PHP وJavaScript، لذلك تتيح لك هذه الصفحة تخطيط منطق EM الخاص بك وفقًا لذلك.
- اختبارات الوحدة للتعبيرات المعزولة (متقدم)
المصطلحات
تُستخدم هذه الكلمات عادةً لوصف إمكانيات EM:
- التفرع المبني على الصلة - إذا كان السؤال ذا صلة، يُطرح، وإلا فلا (مثلًا، يُخفى ويُعلَّم بـ NULL في قاعدة البيانات). يمكنك العثور على حقول الصلة في لوحة محرر السؤال وكذلك في لوحة محرر مجموعة الأسئلة. وتُستخدم الأخيرة لتطبيق مجموعة من الشروط على مجموعة كاملة دون الحاجة إلى نسخ الشرط نفسه إلى كل سؤال، و/أو الجمع بين المنطق الشرطي على مستوى المجموعة والسؤال.
- التخصيص - بمجرد معرفة الأسئلة التي يجب طرحها، يحدد التخصيص (ويسمى أحيانًا piping) كيفية طرح السؤال. وهذا يتيح لك دعم الاستبدال البسيط (مثل {TOKEN:FIRSTNAME})، وكذلك تصريف الأفعال وإعراب الأسماء بناءً على جنس أو عدد الأشخاص المعنيين. كما يتيح لك تغيير الرسالة التي توجهها إلى المشارك في الاستبيان بناءً على ما إذا كان قد أجاب عن أسئلة أخرى (أو كيف أجاب عنها).
- المعادلات - يضيف EM نوع سؤال جديدًا يسمى معادلة يخزّن نتيجة التعبير. تُحتسب نتائج المعادلات وتُكتب في قاعدة البيانات، حتى لو أخفيتها في الصفحة. ولذلك تُستخدم في حسابات التقييم المخفية، والتنقل المبني على معادلات معقدة، والتقييمات، والتقارير التي سيتم إنشاؤها وتخزينها داخل قاعدة البيانات.
الصلة والصلة المتتالية
لكل نوع سؤال الآن خيار الصلة الذي يتحكم في ما إذا كان السؤال يُعرض أم لا. يعالج EM كل معادلة صلة بالترتيب الذي تظهر به في الاستبيان. إذا كان التعبير صحيحًا (أو مفقودًا - لدعم الاستبيانات القديمة)، فسيتم عرض السؤال. أما إذا لم يكن ذا صلة، فسيتم إخفاء السؤال، وتُعيَّن قيمته إلى NULL في قاعدة البيانات. وإذا لم تكن هناك أسئلة ذات صلة في مجموعة ما، فسيتم تخطي المجموعة بأكملها.
علاوة على ذلك، إذا كان أي من المتغيرات داخل التعبير غير ذي صلة، فإن التعبير يُقيَّم دائمًا بأنه خطأ (false). وهذا يتيح الصلة المتتالية بحيث لا تضطر إلى كتابة معادلات صلة طويلة جدًا لكل سؤال.
لنفترض أن لديك خمسة أسئلة 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} لكل مجموعة من مجموعات أسئلة المتابعة العشر. وداخل كل مجموعة، يمكن أن يكون لديك منطق شرطي على مستوى السؤال (مثل أسئلة متابعة خاصة بالجنس أو العمر لكل شخص). ويتم ربط معادلات الصلة على مستوى السؤال والمجموعة بعامل AND لتحديد ما يجب عرضه.
للاطلاع على مثال كهذا، قم باستيراد الاستبيان التالي: مثال استبيان التعداد.
يمكن ملاحظة في لقطة الشاشة أدناه أن مجموعة Person 1 تُعرض (أو تكون ذات صلة) إذا كان المجيب يعيش مع شخص آخر على الأقل:

التخصيص/التمرير
يُعامَل الآن أي شيء داخل الأقواس المعقوفة على أنه تعبير (باستثناء حالة واحدة موضحة أدناه). تتيح التعبيرات الوصول إلى جميع LimeReplacementFields والمتغيرات (عبر عدة أسماء بديلة)، وإلى جميع عوامل المعادلات المعتادة (الحسابية والمنطقية وعوامل المقارنة)، وإلى عشرات الدوال (التي تعمل ديناميكيًا حتى على جانب العميل).
باستخدام هذه المعادلات، يمكنك القيام بأمور مثل:
- عرض رسائل مخصصة للمشاركين بشكل مشروط بناءً على الردود السابقة؛
- إنشاء تقييمات وعرض نتائجها (أو التفرع المشروط أو عرض رسائل) بناءً على تلك النتائج، دون استخدام وحدة التقييمات نفسها؛
- تصريف الأفعال وتغيير صيغ الأسماء داخل الأسئلة والإجابات والتقارير؛
- عرض ملخصات للردود قبل صفحة "عرض إجاباتك" في نهاية الاستبيان.
المعادلات
هناك نوع سؤال جديد يسمى معادلة. يمكنك اعتباره نوع سؤال إظهار المعلومات المكتوبة (النصوص)، إلا أنه يخزّن في قاعدة البيانات قيمة ما يتم عرضه. لذلك، إذا كان نص سؤال المعادلة يحتوي على عملية حسابية للتقييم، فسيتم تخزين تلك القيمة في قاعدة البيانات في متغير يمكن عرضه في الإحصاءات العامة أو الخاصة.
الصيغة
يُعتبر الآن أي شيء موجود داخل الأقواس المعقوفة تعبيرًا (باستثناء حالة واحدة: يجب ألا تكون هناك مسافة بيضاء في البداية أو النهاية - وهذا ضروري لضمان عدم محاولة 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 | AND المنطقي |
| 8 | or | OR المنطقي |
| 9 | = | عامل الإسناد |
| 10 | , | عامل الفاصلة |
تحذير بشأن عدم تطابق الأرقام والسلاسل النصية والمقارنة الأبجدية/الرقمية
عند مقارنة القيم باستخدام المقارنات النسبية أو مقارنات المساواة، انتبه لحالات عدم التطابق. يمكن استخدام القيمة التي يدخلها المستخدم (أو التي يتم توفيرها عبر رمز الإجابة) كرقم إذا كانت رقمًا بوضوح.
إذا وضعت إحدى القيم بين "، فسيتم إجراء مقارنة نصية/سلسلة نصية. إذا أردت المقارنة كرقم، فلا تضع الرقم أبدًا بين ".
على سبيل المثال، 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").
تنبيه بشأن استخدام عامل الإسناد (=)
يجب تجنب استخدام عوامل الإسناد ما لم يكن ذلك ضروريًا للغاية، لأنها قد تتسبب في آثار جانبية غير متوقعة. على سبيل المثال، إذا غيّرت قيمة رد سابق، فلن تتم إعادة حساب منطق الصلة المتسلسلة والتحقق من الصحة بين ذلك السؤال والسؤال الحالي، وقد ينتهي بك الأمر ببيانات غير متسقة داخليًا (مثل أسئلة تظل مُجابة بينما كان ينبغي تفريغها NULL، أو أسئلة يتم تخطيها بينما كان ينبغي الإجابة عنها). بشكل عام، إذا أردت إسناد قيمة إلى متغير، فعليك إنشاء سؤال من نوع معادلة واستخدام تعبير لتعيين قيمته. ومع ذلك، هناك بعض الحالات النادرة التي يحتاج فيها المستخدمون فعلاً إلى هذا العامل، لذلك أتحناه.
للتنبيه إلى هذا العامل، يظهر بخط أحمر داخل معادلات الصيغة (حتى لا تخلط بينه وبين "==").
استخدام عامل الإسناد
الأسباب الرئيسية التي قد تدفعك لاستخدام عامل الإسناد هي:
- تحتاج إلى تعيين القيمة الافتراضية عبر معادلة لسؤال لا يقبل القيم الافتراضية (مثل قائمة الاختيار الإذاعي، حيث تتيح الواجهة اختيار أحد خيارات الإجابة لكنها لا تتيح إدخال معادلة). ومع ذلك، كن حذرًا، لأن LimeSurvey لن يتمكن من التحقق من أن معادلتك تنتج إحدى الإجابات المسموح بها لذلك السؤال؛
- تحتاج إلى تغيير الرد على سؤال سابق قسرًا بناءً على رد لاحق؛
- إلخ...
يمكنك استخدام نظام مدير التعبيرات بالكامل لهذا الغرض. ومن الأفضل استخدام معادلة لهذا الغرض.
بعض الأمثلة:
- تعيين الإجابة على سؤال نص قصير بأحرف صغيرة :
{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، لا يمكن استخدام بعض أجزاء نظام مدير التعبيرات:
- بدء وسم HTML في تعبير وإنهاؤه في تعبير آخر؛
- استخدام تعبير معقد داخل عنوان URL.
أمثلة وحلول بديلة:
{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 وصولًا للقراءة فقط إلى أي متغيرات قد تحتاجها. ولضمان التوافق مع الإصدارات السابقة، فإنه يتيح الوصول إلى ما يلي:
- TOKEN:xxx - قيمة الرمز المميز TOKEN (مثل TOKEN:FIRSTNAME وTOKEN:ATTRIBUTE_5) (فقط في الاستبيانات غير المجهولة).
- جميع قيم {XXX} المستخدمة بواسطة القوالب.
- في نص السؤال، يمكنك استخدام {QID} ليتم استبداله بمعرف السؤال، و{SGQ} ليتم استبداله بقيمة SGQA الخاصة بالسؤال.
- {SAVEDID} لمعرف الاستجابة الحالية
بالإضافة إلى ذلك، يتيح لك 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 | اسم جافاسكريبت الصحيح للسؤال، سواء تم تعريفه في هذه الصفحة أو خارجها | {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.
- يتم استبدال & بـ &
- يتم استبدال < بـ <
- يتم استبدال > بـ >
إذا كنت تستخدم محرر HTML، فعليك استخدام ما يلي:
- and بدلًا من &
- lt بدلًا من <
- le بدلًا من <=
- gt بدلًا من >
- ge بدلًا من >=
يُنصح بتنظيف تعبيرك من أي HTML يظهر داخله. إذا كنت تستخدم محرر HTML في LimeSurvey، فانقر على الزر "المصدر" (الموجود في الجزء العلوي الأيسر من المحرر) واحذف جميع الأحرف غير المرتبطة بتعبيرك (مثل
,
وما إلى ذلك).
تسمية متغيرات Qcode
فيما يلي تفاصيل كيفية إنشاء Qcode (والوصول إلى بعض الخصائص) بحسب نوع السؤال. بصفة عامة، يتم إنشاء Qcode على النحو التالي:
QuestionCode . '_' . SubQuestionID . '_' . ScaleId
بالنسبة لـ comment وother، تكون رموز الأسئلة المقابلة هي 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.suffix
- self.sub-selector
- self.sub-selector.suffix
- suffix هو أي من اللواحق العادية لرمز السؤال (qcode) (مثل: NAOK، value، shown)
- 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" في أي ارتباط (relevance) أو تحقق من الصحة أو تخصيص للنص.
التنبيه الوحيد هو أنه عند استخدام ميزة 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 | تُرجع صحيح (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 | إحسب الأس | number exp(number) |
| fixnum | عرض الأرقام مع الفاصلة كفاصل عشري، عند الحاجة | string fixnum(number) |
| floor | قرب الكسور إلى اعداد صحيحة | number floor(number) |
| gmdate | نسق توقيت/تاريخ جرينتش | 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 | جد ما إذا كان المتغير 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 ) | إرجاع قائمة مفصولة بـ 'glue' لخاصية السؤال المحددة (retProp) من الأسئلة في القائمة التي تستوفي المعيار (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 لتاريخ ما (جميع الوسائط الستة اختيارية) | 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 | إيجاد موضع أول ظهور لسلسلة يونيكود بدون حساسية لحالة الأحرف (يبدأ من 0، ويرجع false إذا لم يُعثر عليها) | int stripos(haystack, needle [, offset=0]) |
| stripslashes | لا إقتباس لسلسلة مقتبسة | string stripslashes(string) |
| stristr | strstr غير حساس لحالة الأحرف | string stristr(haystack, needle [, before_needle=false]) |
| strlen | هات طول سلسلة حرفية | int strlen(string) |
| strpos | إيجاد موضع أول ظهور لسلسلة يونيكود (يبدأ من 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 | إرجاع جزء من سلسلة يونيكود | 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 الخاص بكل منها (مثلاً لاستخدامه في 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 is OK). في هذه الحالة يحدث السلوك التالي. لنفترض أن لديك المتغير q1.NAOK:
- لا تتم إضافة q1 إلى عبارة LEManyNA()
- ستستمر LEMval('q1') في التحقق مما إذا كان الرد ذا صلة، وستُرجع "" إذا لم يكن كذلك (وبذلك يتم تجاهل الردود الفردية غير ذات الصلة، ولكنها لا تُبطل التعبير بأكمله).
إذن، حل مشكلة المجموع التراكمي هو استخدام المعادلة sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).
يتيح استخدام اللاحقة .NAOK أيضاً لمصممي الاستبيانات إنشاء استبيانات ذات مسارات متعددة محتملة تلتقي لاحقاً في مسارات مشتركة. على سبيل المثال، لنفترض أن المشاركين أجابوا عن الاستبيان بطريقة خارج النطاق الطبيعي للردود. يمكن لمصمم الاستبيان تنبيههم إلى أنهم قد لا يحصلون على نتائج صالحة، وسؤالهم عمّا إذا كانوا يرغبون فعلاً في متابعة الاستبيان. إذا أجابوا بـ "نعم"، فسيتم عرض بقية الأسئلة. وسيتحقق شرط "بقية الأسئلة" مما إذا كانت الردود الأولية ضمن النطاق الطبيعي أو ما إذا كان المشارك قد أجاب بـ "نعم" عن السؤال الذي لا يكون ذا صلة إلا إذا كانت إجاباته خارج النطاق الطبيعي.
كيف يدعم ExpressionScript التخصيص الجزئي الشرطي (micro-tailoring)؟
فيما يلي مثال على التخصيص الجزئي (حيث يعني نوع السؤال=='expr' معادلة):
| كود السؤال | الصلة | نوع السؤال | السؤال |
|---|---|---|---|
| name | 1 | text | ما اسمك؟ |
| age | 1 | text | كم عمرك؟ |
| badage | !is_empty(age) | expr | {(age<16) or (age>80)} |
| agestop | badage | message | عذراً {name}، أنت {if( (age<16),'صغير جداً',if( (age>80),'كبير جداً','في منتصف العمر') ) } على هذا الاختبار. |
| 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 تمييزاً لبناء الجملة بالميزات التالية:
أنواع تمييز بناء الجملة ومعانيها
| اللون | عينة | المعنى | تلميح الأداة | ملاحظات |
|---|---|---|---|---|
| خلفية بنية فاتحة | عينة | المعادلة بأكملها | لا يوجد | أي شيء داخل الأقواس المعقوفة يتم التعرف عليه كمعادلة (أي لا توجد مسافة بيضاء في بدايته أو نهايته) سيتم تلوينه بخلفية بنية فاتحة لتمييزه عن النص المحيط |
| نص أحمر غامق | عينة | خطأ | شرح مختصر للخطأ | قد يكون متغيراً غير معروف أو خطأ في دالة. الاستبيان معطّل ولن يتم عرض الأسئلة التي تعتمد على التعبير المعني للمشاركين. |
| نص أزرق | عينة | اسم دالة | المعنى وبناء الجملة المسموح به | يشير إلى أسماء الدوال أو إلى ما يفترض أن يكون دوالاً لأنه متبوع بقوس مفتوح. يتم عرضها بنص أزرق غامق. تعرض تلميحات الأداة المعنى وبناء الجملة المسموح به للدالة. |
| نص رمادي | عينة | سلسلة نصية | لا يوجد | يتم عرض السلاسل النصية المحاطة بعلامات اقتباس مفردة أو مزدوجة بنص رمادي. |
| نص سماوي | عينة | متغير معيّن في الصفحة نفسها | [الاسم]: السؤال؛ القيمة؛ قائمة الإجابات التي تعرض الرموز لكل قيمة | أي متغير معيّن في الصفحة نفسها التي تحتوي على السؤال الذي تقوم بتحريره حالياً يظهر بنص سماوي (يمكن تحديثه عبر javascript). يعرض تلميح الأداة اسمه والسؤال الفعلي وقيمته الحالية (أو فارغاً إذا لم تكن معيّنة). إذا كان نوع السؤال يتوقع ردوداً من مجموعة قيم محددة، فسيتم عرض ربط الرموز بقيم العرض. |
| نص أخضر | عينة | متغير معيّن في صفحة سابقة | [الاسم]: السؤال؛ القيمة؛ قائمة الإجابات التي تعرض الرموز لكل قيمة | أي متغير معيّن في صفحة سابقة يظهر بنص أخضر غامق. يعرض تلميح الأداة اسمه والسؤال الفعلي وقيمته الحالية (أو فارغاً إذا لم تكن معيّنة). إذا كان نوع السؤال يتوقع ردوداً من مجموعة قيم محددة، فسيتم عرض ربط الرموز بقيم العرض. |
| نص وردي غامق | عينة | متغير معيّن في صفحة لاحقة بشكل عام: فارغ عند بدء الاستبيان، ولكن يمكن ملؤه عبر الفهرس أو العودة إلى السابق | [الاسم أو رمز SGQA]: السؤال؛ القيمة؛ قائمة الإجابات التي تعرض الرموز لكل قيمة | أي متغير معيّن في صفحة لاحقة يظهر بنص وردي غامق. يعرض تلميح الأداة اسمه والسؤال الفعلي وقيمته الحالية (أو فارغاً إذا لم تكن معيّنة). إذا كان نوع السؤال يتوقع ردوداً من مجموعة قيم محددة، فسيتم عرض ربط الرموز بقيم العرض. |
| نص بني غامق | عينة | قيمة استبدال في Lime | القيمة | تظهر سلاسل الاستبدال في Lime (مثل {TOKEN:xxx} و{PRIVACY_MESSAGE}) بنص بني غامق. |
| نص أحمر | عينة | معامل الإسناد (=) | رسالة تحذير | إذا استخدمت أحد معاملات الإسناد (=)، فسيظهر هذا المعامل بنص أحمر. الهدف من ذلك المساعدة في منع إعادة إسناد القيم عن غير قصد عندما كنت تقصد التحقق مما إذا كان a == b بدلاً من تعيين قيمة a = b. |
| نص أسود عادي | عينة | علامات الترقيم | لا يوجد | تظهر جميع علامات الترقيم الأخرى داخل التعبير بنص أسود عادي. |
| نص داخل مربع أحمر | خط أحمر غامق يحيط بالخطأ | خطأ في بناء الجملة | وصف الخطأ | تظهر أي أخطاء مكتشفة في بناء الجملة داخل مربعات حمراء. يعرض تلميح الأداة الخطأ. ومن الأمثلة على ذلك الأقواس غير المتطابقة، واستخدام دوال غير معرّفة، وتمرير عدد خاطئ من الوسائط إلى الدوال، والتعبيرات سيئة البنية (مثل غياب المعاملات بين المتغيرات)، ومحاولة إسناد قيمة جديدة إلى متغير للقراءة فقط، ومحاولة إسناد قيم إلى عناصر ليست متغيرات، أو استخدام بناء جملة غير مدعوم. لاحظ أن نظام اكتشاف أخطاء بناء الجملة قد يبلغ عن خطأ واحد فقط في التعبير حتى لو كانت هناك عدة أخطاء؛ ومع ذلك، إذا تم اكتشاف أي أخطاء، فسيتم عرض خطأ واحد على الأقل. |
قراءات إضافية
عينات استبيانات ExpressionScript
حالات الاستخدام والأدلة الإرشادية
أمثلة خطوة بخطوة
مرجع للمطورين