پاورفرم: 5 قدم برای ساختن قالب پرینت فرم در شیرپوینت

توی یه پروژه از من خواسته شد برای فرم‌هایی که با پاورفرم توی شیرپوینت ساخته شده قالبی برای نمای پرینت فرم طراحی کنم. یه سر به سایت رسمی سازنده پاورفرم زدم، اما نتیجه‌ای نگرفتم و بعد از یک روز سروکله زدن، متوجه شدم پرینت کردن توی پاورفرم چطوری کار می‌کنه.

توی این پست بررسی می‌کنیم که چطوری می‌شه با استفاده از یه فایل XSLT، نمای مخصوصی برای پرینت فرم پاورفرم طراحی کرد و گام به گام نحوه پیاده‌سازی این قابلیت رو بررسی می‌کنیم؛ برای ایجاد این نمای مخصوص چاپ در فرم‌های پاورفرم، مراحل زیر رو باید طی کنیم:

1. تنظیماتِ فرمِ پاورفرم

فرض من اینه که شما به طراحی فرم با پاورفرم مسلط هستید، یه خُرده HTML و CSS می‌دونید و قبلاً فرم مد نظرتونو توی پاورفرم طراحی کردید. بعد از تکمیل طراحی فرم، باید توی محیط ویرایشگر فرم پاورفرم، وارد بخش Options بشید و توی بخش General Settings، تیک Show Print Button رو فعال کنید:

تنظیمات در پاورفرم

برای این که پاورفرم، فرم رو برای پرینت آماده‌سازی کنه، نیاز به یه فایل با فرمت XSLT داره. فایل‌های XSLT فایل‌هایی هستن که به عنوان قالب (template) برای نمایش اطلاعات XML استفاده می‌شن؛ بنابراین لازمه که یه فایل با فرمت XSLT بسازید، با هر ویرایشگری که راحت هستید بازش کنید و این محتوا رو داخلش قرار بدید:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     <xsl:output method="xml" encoding="utf-8" indent="no"/>
     <xsl:template match="/">
          <table style="border: 2px das">
                <xsl:for-each select="ListItem/Control">
                     <tr>
                          <td>
                              <xsl:value-of select="@ControlName"/>
                         </td>
                         <td>
                              <xsl:value-of select="@ControlType"/>
                         </td>
                         <td>
                              <xsl:value-of select="."/>
                         </td>
                    </tr>
               </xsl:for-each>
          </table>
     </xsl:template>
</xsl:stylesheet>

این فایل XSLT رو ذخیره کنید و یه جایی توی یکی از مخزن‌های شیرپوینت قرار بدید، به محیط طراحی پاورفرم برگردید و آدرس فایل آپلود شده رو توی تنظیمات فرم، توی بخش Printing و داخل فیلد XSLT file url وارد کنید:

تنظیمات فرم پاورفرم رو ذخیره کنید و صفحه‌ای که فرم توش نمایش داده می‌شه رو رفرش کنید. می‌بینید که اکشن‌های مرتبط با پرینت کردن فرم، بالای صفحه ظاهر می‌شن.

با کلیک روی دکمه پرینت صفحه جدیدی باز می‌شه که همه فیلدهای فرم توش نمایش داده می‌شه (اگه با کلیک کردن روی دکمه پرینت صفحه جدید باز نشد کنسول مرورگرو باز کنید و سعی کنید خطایی که موقع کلیک روی دکمه پرینت به وجود میادو برطرف کنید).

کدی که توی فایل XSLT نوشتید، در واقع یه لوپه که همه فیلدهای فرم رو توی نمای پرینت نمایش می‌ده، اما در عمل احتمالاً موقع پرینت کردن فرم، نیاز به نمایش همه فیلدهای فرم ندارید یا فقط نیاز دارید تعداد کمی از فیدها رو نمایش بدید. در ادامه می‌بینیم که چطور می‌شه به صورت مشخص، فقط فیلدهایی که لازم داریمو توی نمای پرینت نمایش بدیم.

2. مشخص کردن فیلدها در فایل XSLT

مهم‌ترین چیزی که توی فایل XSLT هست، بخش مربوط به نمایش داده‌های فرمه. با استفاده از تگ‌های <xsl:value-of> می‌تونید داده‌هایی که توی فرم دخیره شدن دریافت کنید و هر جایی که لازم هست نمایش بدید. مثلاً برای نمایش مقدار هر کدوم از فیلدها، می‌تونید از این سینتکس توی فایل XSLT استفاده کنید:

<tr>
     <td colspan="1" class='heading'>عنوان فیلد</td>
     <td colspan="3">
          <xsl:value-of select="ListItem/Control[@ControlName='c_FieldName']"/>
     </td>
</tr>

توی کد بالا باید نام فیلد موجود در فرم رو به جای c_FieldName قرار بدید. نام فیلد رو باید از تنظیمات فیلد توی محیط ویرایش فرم پیدا کنید:

تنظیمات در پاورفرم

توی کد پایین چند تا فیلدی که برای نمایش توی نمای پرینت این فرم نیاز بوده را گذاشتم؛ دقت کنید که این مقادیر توی فرم‌های مختلف متفاوتن و برای همین، برای هر فرم، نیاز به درست کردن یه فایل XSLT مخصوص نمای پرینت همون فرم هست (توی این مثال اسم فیلدها الکی هستن و شما باید اسم فیلدهای فرم خودتونو از توی محیط طراحی فرم پاورفرم پیدا کنید):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     <xsl:output method="xml" encoding="utf-8" indent="no"/>
     <xsl:template match="/">
          <table>
               <tr>
                    <td colspan="1" class='heading'>فیلد اول</td>
                         <td colspan="3">
                              <xsl:value-of select="ListItem/Control[@ControlName='c_FormField1']"/>
                         </td>     
               </tr>
               <tr>
                    <td colspan="1" class='heading'>فیلد دوم</td>
                    <td colspan="3">
                         <xsl:value-of select="ListItem/Control[@ControlName='c_FormField2']"/>
                    </td>
               </tr>
          </table>
     </xsl:template>
</xsl:stylesheet>

3. مقدار دادن به سلول‌های خالی

از جاوااسکریپت برای قرار دادن یه عبارت به جای فیلدهایی که توی فرم پُر نشده‌ن استفاده می‌کنیم؛ این کد چک می‌کنه که محتوای تگ td در html خالی هست یا نه و اگه خالی بود، عبارت «ثبت نشده» رو اون جا نمایش می‌ده و کلس dataNotEntered را به td اضافه می‌کنه؛ بعداً برای تغییر نمایش فیلدهای خالی، می‌تونیم از این کلس استفاده کنیم:

const tdElements = document.querySelectorAll("table td")
tdElements.forEach(function(td) {
     if (!td.innerHTML.trim()) {
          td.innerHTML = "ثبت نشده"
          td.classList.add('dataNotEntered')
     }
})

4. ایجاد تغییرات در ظاهر فرم

با استفاده از تگ style در فایل XSLT می‌تونید مثل هر فایل HTML دیگه‌ای، با استفاده از CSS، استایل‌های اختصاصی برای جدول و فونت و اندازه‌ها و خلاصه هر چیز دیگه‌ای اضافه کنید:

<style>
table {
     direction: rtl;
     width: 100%;
     padding: 1em;
}
td {
     direction: rtl;
     text-align: right;
     font-family: b mitra;
     border: 1px solid;
     padding: .25em;
     min-width: 25%;
     width: 25%;
}
td:not(.heading) {
     font-weight: bold;
}
.heading {
     width: 20%;
     background: #e3efff;
     border: 1px solid #6eacff;
}
.title {
     text-align: center;
     border: none;
     padding-top: 1em;
}
.dataNotEntered {
     color: #5b5b5b;
     border: 1px dashed;
     font-weight: 100 !important;
}
</style>

با اضافه کردن این استایل‌ها می‌تونید نمای چاپی رو دقیقاً مطابق با نیاز خودتون و سازمانتون تنظیم کنید و به راحتی از طریق کد XSLT، نمای پرینت فرم رو به‌صورت حرفه‌ای نمایش بدید.

5. افزودن دکمه چاپ در نمای پرینت

خب، حالا فرم آماده شده. الان می‌تونیم با جاوااسکریپت یه دکمه برای چاپ به فرم اضافه کنیم تا هر کاربری بتون به راحتی وارد پنجره پرینت بشه و فرم رو به صورت مستقیم چاپ کنه. می‌تونید هر جایی از قالب HTML موجود توی فایل XSLT از این دکمه استفاده کنید:

<button onclick="window.print();" class="print">چاپ</button>

اما بعد از کلیک کردن روی این دکمه، توی پنجره‌ای که برای چاپ فرم ظاهر می‌شه، این دکمه لازم نیست که دیده بشه؛ برای همین باید از استایل زیر توی تگ style استفاده کنیم تا موقع چاپ، دکمه مخفی بشه:

@media print {
     .print{
          display:none;
     }
}


تموم شد! با دنبال کردن این مراحل، می‌تونید یه نمای چاپی زیبا و حرفه‌ای برای فرم‌های پاورفرمی شیرپوینت بسازید. قالب‌بندی نهایی کدتون توی فایل XSLT باید این شکلی باشه:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     <xsl:output method="xml" encoding="utf-8" indent="no"/>
     <xsl:template match="/">
          <style>
          table {
               direction: rtl;
               width: 100%;
               padding: 1em;
          }
          td {
               direction: rtl;
               text-align: right;
               font-family: b mitra;
               border: 1px solid;
               padding: .25em;
               min-width: 25%;
               width: 25%;
          }
          td:not(.heading) {
               font-weight: bold;
          }
          .heading{
               width: 20%;
               background: #e3efff;
               border: 1px solid #6eacff;
          }
          .title {
               text-align: center;
               border: none;
               padding-top: 1em;
          }
          .dataNotEntered {
               color: #5b5b5b;
               border: 1px dashed;
               font-weight: 100 !important;
          }
          .print {
               font-family: b mitra;
               border: none;
               color: white;
               font-weight: bolder;
               padding-left: 1em;
               padding-right: 1em;
               border-radius: 3em;
               cursor: pointer;
               background: linear-gradient(90deg, #093e71, #0c95ae, #6ec9ca);
          }
          @media print {
               .print{
                    display:none;
               }
          }
          </style>

          <table style="border: 2px das">
               <tr>
                    <td colspan="1" class='heading'>فیلد اول</td>
                         <td colspan="3">
                              <xsl:value-of select="ListItem/Control[@ControlName='c_FormField1']"/>
                         </td>     
               </tr>
               <tr>
                    <td colspan="1" class='heading'>فیلد دوم</td>
                    <td colspan="3">
                         <xsl:value-of select="ListItem/Control[@ControlName='c_FormField2']"/>
                    </td>
               </tr>
          </table>

          <script>
          const tdElements = document.querySelectorAll("table td")
          tdElements.forEach(function(td) {
               if (!td.innerHTML.trim()) {
                    td.innerHTML = "ثبت نشده"
                    td.classList.add('dataNotEntered')
               }
          })
           </script>
     </xsl:template>
</xsl:stylesheet>

ساختن پورتال سازمانی فارسی شیرپوینت در 5 قدم

توی این پست قراره کامل و قدم‌به‌قدم توضیح بدم که چطوری می‌شه یه پورتال سازمانی فارسی شیرپوینت طراحی و پیاده سازی کرد.

داشتن یه پورتال متمرکز و کارآمد برای ارتباطات داخلی سازمان و اطلاع‌رسانی به اعضای سازمان درباره مسائل مختلف، همیشه یه موضوع مهم برای هر سازمانی به حساب میاد. با شیرپوینت می‌تونید یه پورتال شخصی‌سازی شده برای سازمانتون طراحی کنید و کار کردن با شیرپوینت رو برای همکاراتون راحت‌تر و بهینه‌تر کنید.

قبل از هر چیزی مطمئن بشید که قالب سایت شیرپوینتی که در اختیارتون قرار دادن از نوع publishing site هست؛ اگر این طور نبود، از ادمین شیرپوینت سازمانتون در خواست کنید براتون یه سایت کالکشن با آدرس دلخواهتون بسازه و تأکید کنید که قالب سایت کالکشنی که ساخته می‌شه، حتماً از نوع publishing site باشه. وقتی سایت رو تحویل گرفتید می‌تونید شروع کنید به ساختن پورتال سازمانی فارسی شیرپوینت!

1. ساختن مسترپیجِ پورتال سازمانی فارسی شیرپوینت

مسترپیج (Masterpage) در شیرپوینت در واقع قالبیه که شامل طرح‌بندی کلی همه صفحات یک سایته. بخش‌هایی از صفحه که توی همه صفحات مشترک هستن داخل قالب مسترپیج قرار می‌گیرن؛ مثلاً:

  • هدر
  • فوتر
  • لوگو

محتوا و بدنه هر صفحه که ممکنه شامل متن و عکس و وب‌پارت‌های مختلف باشه، داخل قالب صفحه قرار می‌گیره و قالب صفحه داخل مسترپیج قرار می‌گیره. برای این که این موضوع قابل فهم‌تر بشه، به این دیاگرام که از داکیومنت‌های سایت مایکروسافت پیدا کردم دقت کنید:

قدم اول ما هم اینه که مسترپیجی که قراره پورتال از اون استفاده کنه رو بسازیم. برای این کار روی آیکون چرخ‌دنده بالای صفحه کلیک می‌کنیم و از اون جا وارد بخش Design Manager می‌شیم. از منوی موجود توی این صفحه استفاده می‌کنیم و روی گزینه شماره سه، یعنی Upload Design Files کلیک می‌کنیم می‌کنیم تا بتونم فایل‌های مرتبط به طراحی رو روی سیستم خودمون مَپ کنیم؛ این طوری به فایل‌ها خیلی راحت‌تر دسترسی خواهیم داشت و فرایند توسعه و پیاده‌سازی پورتال سازمانی خیلی سریع‌تر انجام می‌شه. پس:

  • روی گزینه Upload Design Files کلیک کنید.
  • آدرسی که توی صفحه میاد رو کپی کنید (معمولاً توش کلمه masterpage هست).
  • روی سیستم خودتون This PC (یا همون my computer) رو باز کنید.
  • از منوی سمت چپ روی Network، کلیک راست کنید و Map network drive رو بزنید.
  • آدرس کپی شده رو اون جا وارد کنید و Finish رو بزنید.
  • مشخصات اکانت ادمین رو وارد کنید و دکمه ثبت رو بزنید.
برای ساختن پورتال فارسی در شیرپوینت باید اول از همه فولد مرتبط با مسترپیج رو روی سیستم خودتون مپ کنید

از این فولدری که این جا براتون باز می‌شه می‌تونید استفاده کنید تا به راحتی به فایل‌ها و فولدرهای مرتبط با طراحی سایت دسترسی داشته باشید؛ حتماً می‌دونید که از طریق تنظیمات شیرپوینت هم می‌تونید به این فایل‌ها دسترسی داشته باشید، اما بر اساس تجربه من، این روش راحت‌ترین و سریع‌ترین راه برای دسترسی به فایل‌های مرتبط با مسترپیج و ویرایش کردن بخشای مختلف مسترپیجه.

حالا برمی‌گردیم به بخش Design Manager و روی لینک چهارم فهرست، یعنی Edit Master Pages، کلیک می‌کنیم. توی این صفحه روی لینک Create a minimal master page کلیک می‌کنیم تا سیستم برای ما یک مسترپیج ساده درست کنه؛ اسمش رو انتخاب کنید و اوکی رو بزنید.

بعد از چند ثانیه، می‌بینید که مسترپیجی که درست کردید به فهرست مسترپیج‌ها اضافه شده و مهم‌تر از همه، یک فایل HTML هم‌نام با این مسترپیج، توی فولدری که روی سیستم خودتون مپ کردید نمایش داده می‌شه؛ این فایل HTML مسترپیج، فایلیه که توی همه صفحات سایت فراخوانی می‌شه و بنابراین جای مناسبیه برای فراخونی منابع و فایل‌های دیگه‌ای که نیاز دارید توی همه صفحات سایت استفاده کنید؛ مثلاً فایل‌ها و کتابخونه‌های مرتبط با رابط کاربری.

داخل فولدری که مَپ کردیم یک فولدر به نام Theme Files درست کنید، فایل‌های مورد نیازتون رو توی این فولدر قرار بدید و بعد فایل‌هایی که نیاز دارید توی همه صفحات سایت لود بشن رو توی فایل مسترپیج زیر کامنت CE: End Head Snippet فراخونی کنید:

<!--CE: End Head Snippet-->
<link href="./Theme Files/css/icon.css" rel="stylesheet" />
<link type="text/css" rel="stylesheet" href="./Theme Files/css/materialize-rtl.min.css" media="screen,projection" />
<link type="text/css" rel="stylesheet" href="./Theme Files/css/style.css" media="screen,projection" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="text/javascript" src="./Theme Files/js/jquery-3.5.0.min.js">//<![CDATA[//]]></script>
<script type="text/javascript" src="./Theme Files/js/materialize.min.js">//<![CDATA[//]]></script>
<script type="text/javascript" src="./Theme Files/js/footer.js">//<![CDATA[//]]></script>
<!--[if gte mso 9]><xml>

توی این مسترپیج، من به چند تا فایل جاوااسکریپت نیاز داشتم: جی‌کوئری و متریالایز رو اضافه کردم و یک فایل به نام footer.js هم فراخونی کردم (چون فوتر توی همه صفحات باید وجود داشته باشه).

یادآوری می‌کنم که باید هر چیزی که نیاز دارید توی همه صفحات تکرار بشه، مثلاً لوگو، منو یا هر چیزی که به هدر و فوتر سایت مرتبط هست رو توی این صفحه مسترپیج که در واقع یک صفحه HTML هست، توسعه بدید و پیاده‌سازی کنید؛ این طوری دیگه لازم نیست مثلاً لوگوی سایت رو توی همه صفحات به صورت جداگونه فراخونی کنید؛ همچنین اگه بعداً لازم شد مثلاً فوترو تغییر بدید، فقط یک جا لازمه تغییر بدید و تغییر شما توی همه صفحات اعمال می‌شه.

برای این که تست کنید و ببینید که فایل‌هاتون درست لود می‌شن یا طرح مسترپیجتون درست پیاده‌سازی شده یا نه، باید دوباره وارد صفحه Design Manager بشید و اول از قسمت چهارم مسترپیجتون رو منتشر کنید (Approved) و بعد از قسمت هفتم (Publish and apply design) روی لینک Assign master page to your site کلیک کنید مسترپیج جدیدتون رو به سایت اعمال کنید.

نکته مهم اینه که همیشه مسترپیج رو فقط روی سایت اعمال کنید و بهتره که هرگز روی صفحات سیستمی سایت اعمال نکنید و از مسترپیج‌های پیشفرض شیرپوینت برای صفحات سیستمی استفاده کنید.

مسترپیج رو به پورتال سازمانی فارسی شیرپوینت اعمال کنید

توی تصویر بالا می‌بینید که من از مسترپیج پیش‌فرض seattle برای صفحات سیستمی استفاده کردم و فقط مسترپیج صفحات سایتی رو تغییر دادم؛ بعد از انجام دادن این مراحل می‌تونید به صفحه خانه سایت برید و تغییراتی که روی مسترپیج اعمال کردید رو مشاهده کنید.

2. اضافه کردن لوگو، هدر و فوتر

قدم دوم: چطور باید لوگو، هدر و فوتر رو به پورتال سازمانی فارسی شیرپوینت اضافه کنیم؟ اشتراکی که بین این سه عنصر وجود داره اینه که قراره توی همه صفحه‌های سایت نمایش داده بشن، برای همین باید توی مسترپیج اضافه بشن.

بریم سراغ لوگو. برای اضافه کردن لوگو باید:

  • از Design Manager روی لینک چهارم، یعنی Edit Master Pages کلیک کنید.
  • روی اسم مسترپیجی که روی صفحات سایت اعمال کردید کلیک کنید.
  • توی صفحه جدیدی که باز می‌شه از منوی بالا روی لینک Snippets کلیک کنید.
  • از منوی Design روی گزینه Site Logo کلیک کنید.
  • اسنیپتی که توی صفحه ظاهر می‌شه رو کپی کنید.
  • این اسنیپت رو توی صفحه HTML مسترپیج بذارید و صفحه رو ذخیره کنید.

سعی کنید خطوط و تگ‌های پیشفرض رو از صفحه HTML مسترپیج پاک نکنید (مخصوصاً چیزایی که نمی‌دونید چی هستن). بعد از ذخیره کردن مسترپیج به صفحه اصلی سایت برید و ببینید که لوگو چطوری توی پورتال قرار گرفته.

از الان به بعد می‌تونید لوگوی سایت رو از تنظیماتش عوض کنید؛ برای این کار کافیه به قسمت تنظیمات سایت برید و روی Title description and logo کلیک کنید؛ توی این صفحه هر لوگویی که برای سایتتون انتخاب کنید، توسط اسنیپتی که داخل مسترپیج قرار دادید، به شکل خودکار توی همه صفحات سایت قرار می‌گیره؛ اگر لازم داشتید از همین اسنیپت توی فوتر سایت یا هر جای دیگه هم می‌تونید استفاده کنید و اگر حوصله داشته باشید با CSS می‌تونید هر استایلی که دوست دارید بهش اعمال کنید.

هر چقدر حجم تصویری که به عنوان لوگو انتخاب می‌کنید کم‌تر باشه بهتره (مثلاً حداکثر صد کیلوبایت باشه).

هدر و فوتر هم توی فایل HTML مسترپیج بنویسید. من معمولاً از JSOM برای اضافه کردن آیتم‌هایی توی هدر و فوتر استفاده می‌کنم، برای همین هم فایل footer.js رو توی مسترپیج فراخونی کردم. توی بخش سوم توضیح می‌دم که چطوری می‌تونید از JSOM برای اضافه کردن بخش‌های مختلف به پورتال استفاده کنید.

3. اضافه کردن بخش‌های مختلف پورتال با فناوری JSOM

با اضافه کردن بخش‌های مختلف به پورتال و شخصی‌سازی صفحه اصلی پورتال سازمانی فارسی شیرپوینت، تجربه کاربری استفاده‌کننده‌ها و ادمین‌های پورتال ارتقا پیدا می‌کنه. JSOM فناوری خوبیه که من همیشه برای شخصی‌سازی صفحات شیرپوینت استفاده می‌کنم. با JSOM می‌تونید با داده‌های موجود در لیست‌ها و سایت‌های مختلف شیرپوینتتون تعامل داشته باشید؛ الان قراره از این فناوری استفاده کنیم و بخش «لینک‌های سامانه‌ها» رو توی پورتال اضافه کنیم.

دقت کنید که موضوع این آموزش JSOM نیست ولی من قبلاً یه مطلب دیگه درباره JSOM نوشتم که می‌تونید از این لینک مطالعه‌ش کنید و درباره‌ش اطلاعات بیشتری به دست بیارید.

بخش لینک‌های سامانه‌ها که معمولاً توی همه پورتال‌های سازمانی هست، مثل لوگو یا هدر یا فوتر نیست که توی همه صفحات تکرار بشه و فقط قراره توی صفحه اول نمایش داده بشه؛ برای همین قراره یه قالب صفحه درست کنیم و قالب رو روی صفحه اول اعمال کنیم؛ برای این کار برمی‌گردیم توی صفحه Design Manager و لینک شماره شش فهرست یعنی Edit Page Layouts رو می‌زنیم؛ توی این صفحه روی لینک Create page layout کلیک می‌کنیم، اسم قالب رو می‌نویسیم و همچنین مسترپیجی که خودمون ساختیمو انتخاب می‌کنیم. اگه به فولدری که روی سیستم مَپ کردید نگاه کنید می‌بینید که به همین سادگی فایل HTML قالب جدیدی که ساختید ایجاد شده (دقیقاً مثل ساخته شدن مسترپیج).

توی قالب صفحه‌ای که الان ساختید، قراره با استفاده از فناوری JSOM بخش لینک‌های سامانه‌ها رو درست کنیم. اگر بخوایم JSOM بنویسیم باید جاوااسکریپت بنویسیم، بنابراین نیاز داریم که یه فایل جاوااسکریپت بسازیم و توی این صفحه فراخونیش کنیم. من داخل فولدر js که قبلاً ساختم، یه فایل جدید می‌سازم به نام home.js و توی صفحه قالبم که اسمش رو گذاشتم home.html در انتهای فایل، قبل از بسته شدن تگ body فراخونیش می‌کنم:

          <script type="text/javascript" src="./Theme Files/js/home.js">//<![CDATA[//]]></script>
     <!--ME:</asp:ContentPlaceHolder>-->
     <!--MS:<asp:ContentPlaceHolder id="PlaceHolderLeftNavBar" runat="server">-->
     <!--ME:</asp:ContentPlaceHolder>-->
</body>

توی همین صفحه، جایی که قراره لینک‌ها قرار بگیرن هم باید با یه آی‌دی مشخص بشه که بعداً بتونیم از این آی‌دی توی کُد جاوااسکریپت استفاده کنیم:

<div class="row mb0">
     <div class="col s12">
          <div class="row">
               <div class="col s10 offset-s1">
                    <div class="row" id="homeMainLinks"></div>
               </div>
          </div>
     </div>
</div>

بعد از ذخیره کردن این فایل، به صفحه Design Manager برمی‌گردم و قالب اضافه شده رو منتشر می‌کنم. بعد به صفحه اصلی سایت می‌رم و وارد حالت ویرایش صفحه می‌شم و با استفاده از تنظیمات Page Layout، قالب جدیدی که ساختمو روی صفحه اعمال می‌کنم.

دقت کنید قبلاً توی یه سایت دیگه یه لیست شیرپوینتی ساخته شده که اطلاعات لینک‌هایی که قراره توی بخش لینک‌های مفید پورتال قرار بدم قراره از اون جا خونده بشه؛ فرقی نداره این لیست کجا و به چه شکلی ساخته بشه، مهم اینه که این قابلیت وجود داشته باشه که اطلاعات لینک‌ها به صورت داینامیک توسط ادمین شیرپوینت تغییر کنه و در صورت نیاز بروزرسانی بشه.

حالا توی فایل home.js یه کد JSOM می‌نویسم تا از لیستی که قبلاً ساخته شده، اطلاعات لینک‌ها رو فراخونی کنه و نمایش بده؛ برای این کار توی فایل home.js از jQuery و JSOM استفاده می‌کنم:

$(document).ready(function() {
     SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
          function getMainLinks() {

               // context
               var targetSiteUrl = 'آدرس سایت رو این جا وارد کنید'
               var context = new SP.ClientContext(targetSiteUrl)
               var web = context.get_web()

               // home main links
               var listMainLinks = web.get_lists().getByTitle('اسم لیست رو این جا وارد کنید')
               var camlMainLinks = new SP.CamlQuery()
               var camlStringMainLinks = 
               '<View>' +
                    '<Query>' +
                         '<OrderBy>' +
                              '<FieldRef Name="SPSArrangement" Ascending="TRUE" />' +
                         '</OrderBy>' +
                    '</Query>' +
               '</View>'
               camlMainLinks.set_viewXml(camlStringMainLinks)
               var itemMainLinks = listMainLinks.getItems(camlMainLinks)
               context.load(itemMainLinks)

               context.executeQueryAsync(
                    function() {

                         // home main links
                         var listItemsMainLinks = itemMainLinks.getEnumerator()                
                         while (listItemsMainLinks.moveNext()) {
                              var listItem = listItemsMainLinks.get_current()
                              var itemTitle = listItem.get_fieldValues().Title
                              var itemImage = listItem.get_fieldValues().SPSImage
                              var itemLinks = listItem.get_fieldValues().SPSLinkAddress

                              $('#homeMainLinks').append(
                                   '<div class="eachMainLink mb3">' +
                                        '<a href="' + itemLinks + '" target="_blank">' +
                                        itemImage +
                                        '<p class="center-align mt0">' + itemTitle + '</p>' +
                                   '</a>' +
                                   '</div>'
                              )
                         }
                    },
                    function(sender, args) { // On failure
                         console.log('Request failed: ' + args.get_message())
                    }
               );
          }
        
          // Call the function when the page is ready
          getMainLinks()

     })
})

به صورت خیلی خلاصه کاری که این کد انجام می‌ده اینه که:

  • منتظر می‌مونه تا صفحه کامل لود بشه.
  • منتظر می‌مونه تا فایل sp.js کامل لود بشه.
  • به سایتی که اطلاعات لینک‌ها داخلش هستن وصل می‌شه.
  • اطلاعات رو از لیستی که عنوانش رو مشخص کردیم دریافت می‌کنه.
  • از یک کوئری CAML استفاده می‌کنه تا ترتیب مواردو مشخص کنه.
  • موارد دریافت شده رو با استفاده از آی‌دی داخل HTML قرار می‌ده.

دیدید؟ به همین راحتی تونستید لینک‌ها رو توی پورتال سازمانی فارسی شیرپوینت قرار بدید!

حالا فرض کنید که قراره یه بخش دیگه هم توی پورتال داشته باشیم: مثلاً بخش آخرین اخبار؛ برای اضافه کردن آخرین اخبار هم باید یک لیست اخبار توی شیرپوینت داشته باشیم که ادمین شیرپوینت بتونه اخبارو اون جا وارد کنه و به محض وارد کردن اطلاعات توسط ادمین، بخش اخبار پورتال بروزرسانی بشه؛ برای این کار باید یه چیزایی رو به کد HTML موجود توی صفحه home.html و همچنین کد JSOM موجود در صفحه home.js اضافه کنیم.

<!-- home main links -->
<div class="row mb0">
     <div class="col s12">
          <div class="row pt5 mb0">
               <div class="col s10 offset-s1">
                    <div class="row" id="homeMainLinks"></div>
               </div>
          </div>
     </div>
</div>
<!-- home main links -->

<!-- news -->
<div class="row mb0">
     <div class="col s12">
          <div class="row pt5 pb5 px5 mb0" id="homeNewsContainer">
               <div class="mt3 mb3">
                    <h3 class="pr1">آخرین اخبار</h3>
               </div>
          </div>
     </div>
</div>
<!-- news -->
$(document).ready(function() {
     SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
          function getMainLinks() {

               // context
               var targetSiteUrl = 'آدرس سایت رو این جا وارد کنید'
               var context = new SP.ClientContext(targetSiteUrl)
               var web = context.get_web()

               // home main links
               var listMainLinks = web.get_lists().getByTitle('اسم لیست رو این جا وارد کنید')
               var camlMainLinks = new SP.CamlQuery()
               var camlStringMainLinks = 
               '<View>' +
                    '<Query>' +
                         '<OrderBy>' +
                              '<FieldRef Name="SPSArrangement" Ascending="TRUE" />' +
                         '</OrderBy>' +
                    '</Query>' +
               '</View>'
               camlMainLinks.set_viewXml(camlStringMainLinks)
               var itemMainLinks = listMainLinks.getItems(camlMainLinks)
               context.load(itemMainLinks)

               // news
               var listNews = web.get_lists().getByTitle('اخبار')
               var camlNews = new SP.CamlQuery()
               var camlStringNews = 
               '<View>' +
                    '<Query>' +
                         '<OrderBy>' +
                              '<FieldRef Name="Created" Ascending="FALSE" />' +
                    '</OrderBy>' +
                    '</Query>' +
                    '<RowLimit>4</RowLimit>' +
               '</View>'
               camlNews.set_viewXml(camlStringNews)
               var itemNews = listNews.getItems(camlNews)
               context.load(itemNews)

               context.executeQueryAsync(
                    function() {

                         // home main links
                         var listItemsMainLinks = itemMainLinks.getEnumerator()                
                         while (listItemsMainLinks.moveNext()) {
                              var listItem = listItemsMainLinks.get_current()
                              var itemTitle = listItem.get_fieldValues().Title
                              var itemImage = listItem.get_fieldValues().SPSImage
                              var itemLinks = listItem.get_fieldValues().SPSLinkAddress

                              $('#homeMainLinks').append(
                                   '<div class="eachMainLink mb3">' +
                                        '<a href="' + itemLinks + '" target="_blank">' +
                                        itemImage +
                                        '<p class="center-align mt0">' + itemTitle + '</p>' +
                                   '</a>' +
                                   '</div>'
                              )
                         }

                         // news
                         var listItemsNews = itemNews.getEnumerator()                
                         while (listItemsNews.moveNext()) {
                              var listItem = listItemsNews.get_current()
                              var itemIdddd = listItem.get_fieldValues().ID
                              var itemTitle = listItem.get_fieldValues().Title
                              var itemDescr = listItem.get_fieldValues().SPSDescription
                              var itemDates = listItem.get_fieldValues().Created
                              var itemImage = listItem.get_fieldValues().SPSImage
                              var persianTi = new Date(itemDates).toLocaleDateString('fa-IR')

                              $('#homeNewsContainer').append(
                                   '<div class="col s3">' +
                                        '<a href="#" target="_blank">' +
                                             itemImage +
                                             '<h5>' + itemTitle + '</h5>' +
                                             '<p>' + itemDescr + '</p>' +
                                             '<p class="homeNewsDate">' + persianTi + '</p>' +
                                        '</a>' +
                                   '</div>'
                              )
                         }

                    },
                    function(sender, args) { // On failure
                         console.log('Request failed: ' + args.get_message())
                    }
               );
          }
        
          // Call the function when the page is ready
          getMainLinks()

     })
})

توی این کد جاوااسکریپت می‌بینید که علاوه بر لینک‌ها، موارد موجود در لیست اخبار هم دریافت می‌کنیم. اگه داخل کوئری CAML رو با دقت نگاه کنید متوجه می‌شید که این بار با استفاده از تگ OrderBy موارد دریافت شده رو بر اساس زمان ایجاد مرتب کردیم و نتایج رو محدود به فقط چهار مورد کردیم.

این دو بخش رو به عنوان نمونه‌ای برای فهمیدن ساختار درست استفاده از JSOM این جا آوردم؛ شما به همین ترتیب می‌تونید بخش‌های مختلف دیگه‌ای مثل سخن روز، تصویر روز، پیام‌های مرتبط با تبریک تولد همکاران یا تسلیت به همکاران و هر ماژول مفید دیگه‌ای که فکرشو بکنید، به صفحه پورتال فارسی شیرپوینت اضافه کنید.

4. اضافه کردن فونت دلخواه به پورتال سازمانی فارسی شیرپوینت

نظر شخصی من اینه که تا وقتی فونت به پورتال اضافه نشه، فارسی بودن پورتال خوب به چشم نمیاد و اضافه کردن فونت متناسب با حال‌وهوای سازمانتون می‌تونه تجربه بصری و کاربری استفاده کننده‌های پورتال سازمانی‌تونو به شدت ارتقا بده. اما چطور می شه فونتی که انتخاب کردیدو به پورتال سازمانی فارسی شیرپوینت اضافه کنیم؟

من معمولاً از فونت‌هایی با فرمت ttf یا woff یا woff2 استفاده می‌کنم؛ این‌ فرمت‌ها فرمت‌های بهینه‌سازی شده برای وب هستن.

اول از همه فونت‌ها رو توی یکی از فولدرها، توی فولدری که قبلاً مپ کردیم اضافه می‌کنم. اگر دوست داشته باشید می‌تونید از یه مخزن اسناد برای آپلود کردن فایل فونت‌ها استفاده کنید و از آدرس اون مخزن اسناد برای رفرنس دادن استفاده کنید. مهم اینه که فایل‌ها جایی آپلود شده باشن که کاربری که به سایت مراجعه می‌کنه بهش دسترسی داشته باشه.

بعد با استفاده از CSS فایل‌هایی که اضافه کردمو توی صفحه فراخونی می‌کنم. قبلاً فایل CSS رو به نام style.css ساختم و همون طور که توی مرحله اول دیدید، اون رو توی فایل مسترپیج فراخونی کردم؛ بنابراین داخل فایل style.css می‌تونم فونت‌ها رو ثبت کنم و بعد هر جایی که می‌خوام ازشون استفاده کنم:

/*fonts*/
@font-face {
     font-family: 'peyda';
     src: url('fonts/peydaa/peydaWeb-light.eot');
     src:
          url('fonts/peydaa/peydaWeb-light.woff2') format('woff2'),
          url('fonts/peydaa/peydaWeb-light.woff') format('woff');
     font-weight: 100;
}
@font-face {
     font-family: 'peyda';
     src: url('fonts/peydaa/PeydaWeb-Medium.eot');
     src:
          url('fonts/peydaa/PeydaWeb-Medium.woff2') format('woff2'),
          url('fonts/peydaa/PeydaWeb-Medium.woff') format('woff');
     font-weight: 500;
}
@font-face {
     font-family: 'peyda';
     src: url('fonts/peydaa/PeydaWeb-Bold.eot');
     src:
          url('fonts/peydaa/PeydaWeb-Bold.woff2') format('woff2'),
          url('fonts/peydaa/PeydaWeb-Bold.woff') format('woff');
     font-weight: 900;
}
body, h1, h2, h3, h4, h5, h6, a, .s4-workspace * {
     font-family: 'peyda', serif;
}
/*fonts*/

شما باید اون جایی که url ثبت می‌شه، آدرس فایل‌هایی که آپلود کردید رو بذارید.

5. منتشر کردن فایل‌های مرتبط با پورتال سازمانی فارسی شیرپوینت

بعد از این که کار ساختن پورتال سازمانی تموم شد، از طراحی راضی بودید و تأیید مدیرای سازمانتونم گرفتید و کارای اداریشو انجام دادید، همه چی آماده‌س و می‌تونید فایل‌های مرتبط با پورتال رو منتشر کنید تا برای همه کاربرای شیرپوینت قابل مشاهده باشه.

همه فایل‌ها باید منتشر بشن و هیچ چیزی نباید از قلم بیفته؛ دقت کنید که به صورت پیشفرض در شیرپوینت، همه صفحات، وب‌پارت‌ها، فایل‌های CSS و JS، تصاویر، قالب‌های صفحات و در نهایت مسترپیج، قبل از این که برای عموم کاربران در دسترس و قابل مشاهده باشن، باید منتشر بشن. برای انجام عملیات انتشار باید به ترتیب این مواردو انجام بدید:

  • صفحه‌ای که درست کردید رو چند بار چک کنید که مشکلی نداشته باشه.
  • به صفحه Design Manager برید.
  • از طریق فهرست، روی Edit Master Pages کلیک کنید.
  • مسترپیجی که ساختید رو منتشر کنید.
  • از طریق فهرست، روی Edit Page Layouts کلیک کنید.
  • قالب یا قالب‌هایی که ساختید رو منتشر کنید.
  • از طریق فهرست، روی Publish and Apply Design کلیک کنید.
  • روی لینکی که انتهای پاراگراف اول کلیک کنید.
  • فولدر به فولدر همه فایل‌هایی که اضافه کردیدو منتشر کنید.
  • به صفحه Design Manager برگردید.
  • برای آخرین بار، مسترپیج رو به صفحات سایت اعمال کنید.
  • به مخزن اسنادی که صفحات سایت داخلش هست برید.
  • اون جا همه صفحاتی که جدید ساختید رو منتشر کنید.

اگر دقیقاً این مراحلو برای انتشار انجام دادید، بهتون تبریک می‌گم چون الان یه صفحه پورتال شخصی‌سازی شده برای سازمانتون ساختید و در دسترس همه همکاراتون قرار دادید! امیدوارم این آموزش به دردتون خورده باشه و همچنین پورتالی که می‌سازید به همکاراتون کمک کنه که کارشونو توی سازمان بهتر انجام بدن.

خلاصه کارهایی که انجام دادیم

توی این پست نکات مهم زیادی مطرح شد ولی از همه مهم‌تر یاد گرفتیم که چطوری:

  • قالب مسترپیج و قالب صفحه بسازیم
  • فایل‌هایی مورد نیازمونو داخل مسترپیج قرار بدیم
  • اسنیپت لوگو رو به مسترپیج اضافه کنیم
  • مسترپیج رو به صفحات سایتی اعمال کنیم
  • موارد لیست شیرپوینت رو با JSOM فراخونی کنیم
  • فونت فارسی دلخواهمون رو به پورتال اضافه کنیم
  • فایل‌ها رو منتشر کنیم

در نظر داشته باشید که شیرپوینت سیستم خیلی انعطاف‌پذیریه و همیشه می‌تونید هر طوری که مد نظرتون باشه ازش استفاده کنید، توسعه‌ش بدید و قابلیت‌های جدید بهش اضافه کنید.

اگر درباره شیرپوینت سازمانتون نیاز به مشورت دارید، از لینک‌های پایین صفحه استفاده کنید و باهام تماس بگیرید. اگر درباره این مطلب هم سؤال دارید می‌تونید همین زیر کامنت بذارید و سؤالتونو بپرسید. خوشحال می‌شم بتونم کمک کنم!

مصورسازی معماری دیدار

شینا صنعت پارس

رومی آنلاین

استفاده از JSOM در شیرپوینت

JSOM چیه؟

یکی از راه‌های مدیریت دیتا توی شیرپوینت، استفاده کردن از JSOM در شیرپوینت برای خوندن، ویرایش، حذف و اضافه کردن دیتاس؛ این کتابخونه به توسعه‌دهنده‌ها اجازه می‌ده کارای دیگه‌ای مثل تغییر دسترسی‌ها کاربرای مختلف هم انجام بدن.

برای استفاده کردن از JSOM در شیرپوینت فقط نیاز دارید که فایل sp.js رو توی صفحه فراخونی کنید و شروع کنید به کد زدن. برای فراخونی فایل sp.js راه‌های مختلفی وجود داره؛ مثلاً می‌شه از وب پارت content editor یا content search استفاده کرد. فرض من اینه که شما توسعه‌دهنده شیرپوینت هستید و با نحوه کار کردن display templateها توی شیرپوینت آشنایی دارید؛ همچنین به راحتی با HTML و CSS و jQuery کار می‌کنید.

توی این مقاله من از یه وب پارت content search استفاده کردم؛ البته راه‌های سرراست‌تری هم برای استفاده از JSOM در شیرپوینت وجود داره؛ مثلاً توی پست ساختن پورتال سازمانی فارسی از JSOM توی قالب صفحه استفاده کردیم؛ توی display templateهای پیش‌فرض شیرپوینت هم روش‌هایی برای فراخونی فایل‌های CSS و JS وجود داره که جلوتر می‌بینید.

هر وب پارت content search از دو تا فایل HTML ساخته شده: فایل کنترل و فایل آیتم (این فایل‌ها display template نامیده می‌شن). فایل کنترل فقط یک بار توی مارک‌آپ صفحه تکرار می‌شه و ساختار کلی نتایج سرچ رو مشخص می‌کنه. فایل آیتم، به ازای هر آیتمی که سرچ برگردونه تکرار می‌شه. کدی که من می‌خوام بنویسم لازمه که فقط یک بار در صفحه اجرا بشه، بنابراین یه فایل جاوااسکریپت می‌سازم و توی فایل کنترلم، اون رو فراخونی می‌کنم:

<script>
     $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js");
     $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Theme Files/css/select2.min.css");
     $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Theme Files/css/persian-datepicker.min.css");
     $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Theme Files/js/select2.min.js");
     $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Theme Files/js/persian-date.min.js");
     $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Theme Files/js/persian-datepicker.min.js");
     $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Theme Files/js/selectTheDate.js");
</script>

هر چیزی رو می‌تونید با تابع includeLanguageScript فراخونی کنید. توی کد بالا من غیر از چیزایی که توی این پروژه نیاز داشتم، فایل جاوااسکریپتی به اسم selectTheDate فراخونی کردم که قراره توش به روش JSOM کد بنویسم؛ پایین‌تر توی همین فایل کنترل، داخل تگ ul کد HTML پاپ‌آپی رو نوشتم که با فشار دادن یه دکمه قراره باز بشه و اطلاعاتی رو از کاربر دریافت کنه؛ چون از این پاپ‌آپ هم فقط یه دونه توی صفحه نیاز داشتم، این کد رو هم توی فایل کنترل می‌نویسم:

<ul class="cbs-List">

     <!-- pop -->
     <div id="popUpTerms" class="popUpKDM">
          <div class="white popUpContent pa1">

               <!-- date -->
               <div id="dateSelection" class="mt1">
                    <label for="date">انتخاب تاریخ</label>
                    <input type="text" class="date" placeholder="لطفاً انتخاب کنید" />
               </div>
               <!-- date -->

               <!-- actions -->
               <div class="popUpClosed">لغو</div>
               <div class="popUpAccept">ثبت</div>
               <!-- actions -->

          </div>
     </div>
     <!-- pop -->

توی سناریویی که برای نوشتن این مقاله انتخاب کردم، کاربر قراره با فشار دادن یه دکمه، یه پاپ‌آپی رو باز کنه و یه تاریخی رو انتخاب کنه، بعد ما انتخاب اون کاربر رو توی یه لیستِ شیرپوینتی که قبلاً ساختیم ذخیره کنیم؛ برای همین توی کد بالا توی پاپ‌آپ، یه فیلد گذاشتم برای انتخاب تاریخ شمسی.

همون طور که گفتم برای باز شدن پاپ‌آپ کاربر باید یه دکمه‌ای رو فشار بده، اگه فقط یک دکمه برای باز کردن پاپ‌آپ نیاز داشتیم می‌تونستیم همین جا توی همین فایل مارک‌آپ دکمه رو هم بنویسیم، اما من می‌خوام این دکمه به ازای هر آیتمی که سرچ برمی‌گردونه تکرار بشه، برای همینم مارک‌آپِ دکمه رو توی فایل آیتم می‌نویسم:

<a class="btn numGenerator" href="">انتخاب یک تاریخ</a>

خب حالا که خیالم از بابت مارک‌آپ این پاپ‌آپ راحت شد، می‌تونم برم سراغ فایل selectTheDate.js که قراره کار اصلی توش انجام بشه؛ اما قبل از اون باید یاد بگیریم اصلاً JSOM نوشتن چطوریه؟

JSOM در فایل جاوااسکریپت

اولین مرحله اینه که مطمئن بشیم فایل sp.js بارگذاری شده و آماده‌س که ازش استفاده بشه. شیرپوینت یه تابع داره به نام ExecuteOrDelayUntilScriptLoaded که قراره الان ازش استفاده کنیم؛ این تابع چک می‌کنه که اگه یه فایل به خصوص توی صفحه بارگذاری شده باشه، یه تابع دیگه رو اجرا کنه و اگه اون فایل به خصوص بارگذاری نشده باشه، صبر می‌کنه تا اون فایل بارگذاری و آماده بشه:

$(document).ready(function() {
     function stuffToRunAfterSP_JS() {
          console.log('sp.js is loaded now!')
     }
     ExecuteOrDelayUntilScriptLoaded(stuffToRunAfterSP_JS, "sp.js")
})

کاری که این کد انجام می‌ده اینه که صبر می‌کنه تا فایل sp.js توی صفحه کاملاً بارگذاری بشه و بعد تابع stuffToRunAfterSP_JS رو اجرا می‌کنه. حالا همه چی آماده‌س و می‌تونیم شروع کنیم به نوشتن JSOM.

ساختار توابع JSOM در شیرپوینت

اساساً هر تکه مجزا از کد JSOM که توی هر پروژه نوشته می‌شه و عملیات خاصی رو انجام می‌ده شامل این پنج تا بخش اصلیه:

  • کانتکست ـ آدرس سایت هدف
  • لیست ـ عنوان یا شناسه لیست، در صورت نیاز
  • کوئری ـ کمل کوئری برای دریافت آیتم‌ها، در صورت نیاز
  • عملیات ـ مثلاً حذف یا اضافه یا ویرایش کردن یک آیتم
  • توابع ـ شامل دو تابع که بعد از موفقیت یا شکست عملیات، مراحل بعدی رو مشخص می‌کنن

دریافت اطلاعات با JSOM در شیرپوینت

با یه مثال خیلی ساده همه چی خیلی واضح‌تر می‌شه: فرض کنیم قراره عنوان همه آیتم‌هایی از یه لیست رو که توشون کلمه «فروش» هست فراخونی کنیم و توی کنسول لاگ کنیم؛ برای این کار باید یه تابع بنویسیم:

$(document).ready(function() {
     function stuffToRunAfterSP_JS() {
          getSaleItems()
     }
     ExecuteOrDelayUntilScriptLoaded(stuffToRunAfterSP_JS, "sp.js")
})

var codingListItems
function getSaleItems() {

        // 1 - ctx
        var clientContext = new SP.ClientContext('https://portal.yourwebsite.com/subsite')

        // 2 - list
        var codingList = clientContext.get_web().get_lists().getByTitle('CodingUnits')

        // 3 - query
        var queryCodingList = new SP.CamlQuery()
        queryCodingList.set_viewXml("<View><Query><Where><Contains><FieldRef Name='Title'/><Value Type='Text'>فروش</Value></Contains></Where></Query></View>")
        codingListItems = codingList.getItems(queryCodingList)
        clientContext.load(codingListItems)

        // 4 - functions
        clientContext.executeQueryAsync(Function.createDelegate(this, onQueryOneSucceededs), Function.createDelegate(this, onQueryOneFaileds))

}
function onQueryOneSucceededs() {
     var codingListEnumerator = codingListItems.getEnumerator()
     var resultCount = codingListItems.get_count()
     if(resultCount > 0) {
          while (codingListEnumerator.moveNext()) {
               var theTitle = codingListEnumerator.get_current().get_item("Title")
               console.log(theTitle)
          }
     } else {
          alert('موردی که شامل کلمه فروش باشد وجود ندارد!')
     }
}
function onQueryOneFaileds(sender, args) {
     alert('Request failed. \nError: ' + args.get_message() + '\nStackTrace: ' + args.get_stackTrace())
}

همون طور که توی کد بالا می‌بینید، تابع اصلی getSaleItems شامل چهار بخشه که من شماره‌گذاری کردم.

بخش اول، کانتکست، در واقع آدرس سایتیه که دارید اطلاعات رو ازش می‌گیرید. اگه سایت مورد نظرتون همون سایتیه که کدتون داره توش اجرا می‌شه، دیگه لازم نیست آدرس سایت رو به عنوان پارامتر توی متد ClientContext وارد کنید.

بخش دوم اسم لیست مورد نظرتونه. من توی این مثال از عنوان لیست استفاده کردم، اما JSOM توابع دیگه‌ای هم برای مشخص کردن لیست هدف داره که مثلاً از شناسه لیست استفاده می‌کنن.

بخش سوم کمل‌کوئریه که روی لیست اعمال شده تا فقط آیتم‌هایی از لیست که توی عنوانشون کلمه «فروش» هست به ما نمایش داده بشه. دقت کنید که توی کمل‌کوئری وقتی داریم از یه ستون شیرپوینتی استفاده می‌کنیم، باید از internal name اون ستون استفاده کنیم. internal name اون اسمیه که اولین بار موقع ساختن یه ستون وارد کردید و هرگز قابل تغییر نیست (اون اسمی که قابل تغییره display name اون ستونه).

بخش چهارم شامل دو تا تابعه که به ترتیب در صورت موفقیت و شکست عملیات، مشخص می‌کنن که قدم‌های بعدی چی قراره باشه.

ساختن آیتم با JSOM در شیرپوینت

برگردیم به مأموریت اصلی‌مون. قراره کاربر یه تاریخ وارد کنه و ما اون رو توی یه لیست شیرپوینتی ذخیره کنیم. اول باید یه کاری کنیم که فقط وقتی کاربر روی دکمه کلیک کرد پاپ‌آپ باز بشه و همچنین فیلد تاریخ شمسی رو فعال کنیم.

var enDate

$(document).ready(function() {
     function stuffToRunAfterSP_JS() {

          // jalali date field
          $("#popUpTerms input.date").pDatepicker({

               // date format
               format: 'YYYY/MM/DD',
               initialValue: false,

               // set year
               onSelect: function(unix){

                    // the selected date
                    var date = new Date(unix).toLocaleDateString('fa-IR')

                    // the english date
                    enDate = new Date(unix)

            }

        })
          
          // show pop up
          $('a.numGenerator').on('click', function(event) {

               //show pop up
               $('#popUpTerms').show()
            
               // actions
               $('#popUpTerms .popUpAccept').show();
               $('#popUpTerms .popUpAccept').on('click', function(){
                    // create the item
               })
               $('.popUpClosed').show();
               $('.popUpClosed').on('click', function(){
                    $('#popUpTerms').hide();
               })

        })

     }
     ExecuteOrDelayUntilScriptLoaded(stuffToRunAfterSP_JS, "sp.js")
})

توی کد بالا وقتی کاربر پاپ‌آپ رو باز کنه و تاریخ رو انتخاب کنه، تاریخ انتخاب‌شده توی متغیر enDate قرار می‌گیره؛ جلوتر می‌بینید که برای مشخص کردن تاریخی که قراره توی آیتم جدید ذخیره کنیم از همین متغیر استفاده می‌کنیم. یه خرده استایل هم اضافه کردم که پاپ‌آپ از نظر ظاهری قابل‌قبول باشه:

/* popup */
.popUpKDM {
     display: none;
     background: #00000070;
     position: fixed;
     width: 100vw;
     height: 100vh;
     right: 0;
     top: 0;
     z-index: 999;
}
.popUpContent {
     overflow: hidden;
     width: max-content;
     min-width: 25%;
     left: 0;
     right: 0;
     top: 50%;
     transform: translate(0px, -50%);
     margin: auto;
     position: absolute;
     height: max-content;
     font-size: 1.25em;
     border-radius: .5em;
}
.popUpAccept, .popUpCancel, .popUpClosed {    
     background: #a2ffa2;
     padding-left: 1em;
     padding-right: 1em;
     width: max-content;
     float: left;
     margin-top: 1em;
     border-radius: .25em;
     height: 2.5em;
     line-height: 2.5em;
     cursor: pointer;
} 
.popUpClosed {    
     background: #ffdda8;
}
.popUpCancel {
     background: #ffcaca;
     margin-left: .5em;
}
/* popup */
JSOM در شیرپوینت

بعد از انتخاب تاریخ و فشار دادن دکمه ثبت، باید تابع JSOM فراخونی بشه و یه آیتم توی لیستی که ما بهش می‌گیم ثبت کنه. تابع JSOM رو بر اساس ساختاری که بالاتر توضیح دادم می‌نویسیم:

function createItem() {

     // 1 - ctx
     var clientContext = new SP.ClientContext('https://portal.yourwebsite.com/subsite')

     // 2 - list
     var oList = clientContext.get_web().get_lists().getByTitle("The List Name")

     // 3 - create
     var oListItemCreationInformation = new SP.ListItemCreationInformation()
     var oListItem = oList.addItem(oListItemCreationInformation)
     oListItem.set_item('Title', 'تست ثبت تاریخ')
     oListItem.set_item('SPSDate', enDate)
     oListItem.update()
     clientContext.load(oListItem)
        
     // 4 - functions
     clientContext.executeQueryAsync(andicatorOnSuccess, andicatorOnFail)

}
function andicatorOnSuccess() {
     alert('یک آیتم جدید ساخته شد')
}
function andicatorOnFail(sender, args) {
     alert('خطا در مرحله ساختن مورد در اندیکاتور')
     alert('Failed' + args.get_message() + '\n' + args.get_stackTrace());
}

این تابع هم مثل تابع قبلی شامل چهار بخشه که شماره‌گذاری کردم.

بخش اول که آدرس سایته. بخش دوم اسم لیستیه که آیتم قراره توش ساخته بشه. توی این تابع کمل‌کوئری نداریم و بخش سوم شامل متدهای مربوط به ساختن آیتم جدیده؛ مثل کمل‌کوئری، این جا هم وقتی قراره از یه ستون شیرپوینتی نام ببریم، باید از internal name اون ستون استفاده کنیم. بخش چهارم هم شامل دو تا تابعه که به ترتیب در صورت موفقیت و شکست عملیات، مشخص می‌کنن که قدم‌های بعدی چی قراره باشه.

این دو تا مثال ساده از نحوه کار کردن JSOM توی شیرپوینت بود. در نهایت کدی که برای اضافه کردن یه آیتم به لیست استفاده می‌شه اینه:

var enDate

$(document).ready(function() {
     function stuffToRunAfterSP_JS() {

          // jalali date field
          $("#popUpTerms input.date").pDatepicker({

               // date format
               format: 'YYYY/MM/DD',
               initialValue: false,

               // set year
               onSelect: function(unix){

                    // the selected date
                    var date = new Date(unix).toLocaleDateString('fa-IR')

                    // the english date
                    enDate = new Date(unix)

            }

        })
          
          // show pop up
          $('a.numGenerator').on('click', function(event) {

               //show pop up
               $('#popUpTerms').show()
            
               // actions
               $('#popUpTerms .popUpAccept').show();
               $('#popUpTerms .popUpAccept').on('click', function(){
                    createItem()
               })
               $('.popUpClosed').show();
               $('.popUpClosed').on('click', function(){
                    $('#popUpTerms').hide();
               })

        })

     }
     ExecuteOrDelayUntilScriptLoaded(stuffToRunAfterSP_JS, "sp.js")
})

function createItem() {

     // 1 - ctx
     var clientContext = new SP.ClientContext('https://portal.yourwebsite.com/subsite')

     // 2 - list
     var oList = clientContext.get_web().get_lists().getByTitle("RecAndicator")

     // 3 - create
     var oListItemCreationInformation = new SP.ListItemCreationInformation()
     var oListItem = oList.addItem(oListItemCreationInformation)
     oListItem.set_item('Title', 'تست ثبت تاریخ')
     oListItem.set_item('SPSDate', enDate)
     oListItem.update()
     clientContext.load(oListItem)
        
     // 4 - functions
     clientContext.executeQueryAsync(andicatorOnSuccess, andicatorOnFail)

}
function andicatorOnSuccess() {
     alert('یک آیتم جدید ساخته شد')
}
function andicatorOnFail(sender, args) {
     alert('خطا در مرحله ساختن مورد در اندیکاتور')
     alert('Failed' + args.get_message() + '\n' + args.get_stackTrace());
}

فونت در p5.js

p5.js می‌تونه هر فونتی رو لود کنه و توی متن‌ها ازش استفاده کنه، حتی فونت‌های فارسی. می‌تونید از فونت‌هایی که از قبل روی سیستمتون نصب شده استفاده کنید، یا توی برنامه‌تون فونت‌های دیگه‌ای رو لود کنید. برای اعمال فونت روی متن‌ها، توی برنامه‌های p5.j می‌تونیم از تابع textFont استفاده کنیم و برای نوشتن خود متن‌ها، می‌شه از تابع text استفاده کرد. همچنین برای تغییر سایز متن از تابع textSize استفاده می‌شه:

const myString = 'یک قدم کوچک برای انسان'

function setup() {
     createCanvas(windowWidth, windowHeight);
     textFont('B Mitra')
}
function draw() {
     textSize(30)
     text(myString, 25, 60)
     textSize(22)
     text(myString, 25, 100)
}
یک نمونه از تایپوگرافی در p5.js

توی تابع text اولین پارامتر، همون متنیه که قراره نمایش بده و پارامترهای بعدی مختصات نمایش متن روی بومه. توی مثال بالا، فونتی که فراخونی کردید باید روی سیستمی که برنامه شما رو اجرا می‌کنه نصب باشه؛ اگه بخواید این طوری نباشه، یعنی نیازی نباشه که سیستم شما فونت رو داشته باشه، باید فونت همراه با برنامه شما لود بشه.

لود کردن فونت در p5.js

p5.js می‌تونه فونت‌هایی با پس‌وند ttf یا otf رو لود کنه؛ برای این کار باید این مراحل طی بشه:

  • فونت توی همون فولدر کنار فایل sketch.js قرار بگیره
  • CSS مرتبط با لود فونت توی فایل HTML قرار بگیره
  • فونت جدید به عنوان فونت برنامه معرفی بشه
  • حتماً از تابع background در draw استفاده بشه

من از فونت ایران‌سنس استفاده کردم و فایل فونت رو کنار فایل sketch.js قرار دادم؛ بعد باید این کُدِ CSS رو به فایل HTML اضافه کنیم؛ این کد شامل آدرس فایلِ فونته؛ همچنین یه اسم برای فونتی که داریم به برنامه معرفی می‌کنیم انتخاب می‌کنیم:

@font-face {
     font-family: 'iranSans';
     src: url(IRANSansX-Regular.ttf);
}

فایل index.html الان باید این شکلی شده باشه:

<!DOCTYPE html>
<html lang="">

<head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>p5.js example</title>
     <style>
          @font-face {
               font-family: 'iranSans';
               src: url(IRANSansX-Regular.ttf);
          }
          body {
               padding: 0;
               margin: 0;
          }
     </style>
     <script src="../p5.js"></script>
     <script src="sketch.js"></script>
</head>

<body>
     <main>
     </main>
</body>

</html>

و فایل sketch.js این شکلی:

const myString = 'یک قدم کوچک برای انسان'

function setup() {
     createCanvas(windowWidth, windowHeight);
     textFont('iranSans')
}
function draw() {
     background(255)
     textSize(30)
     text(myString, 25, 60)
     textSize(22)
     text(myString, 25, 100)
}

یک نمونه از تایپوگرافی در p5.js که فونت دلخواه به این برنامه اضافه شده است

دقیقاً مثل شکل‌ها، برای مشخص کردن رنگ متن‌ها هم می‌شه از تابع‌های fill و stroke استفاده کرد.

const myString = 'یک قدم کوچک برای انسان'

function setup() {
     createCanvas(windowWidth, windowHeight);
     textFont('iranSans')
}
function draw() {
     background(200)
     fill(255)
     stroke(225, 0, 0)
     strokeWeight(5)
     textSize(45)
     text(myString, 25, 100)
     strokeWeight(3)
     textSize(30)
     text(myString, 25, 160)
}
یک نمونه از تایپوگرافی در p5.js که ظاهر متن ها تغییر داده شده است

حالا که یاد گرفتیم چطوری می‌شه فونت فارسی به برنامه اضافه کرد و چطوری می‌شه متن تایپ کرد، می‌تونیم اسکیس بزنیم. می‌خوام یه حرف انتخاب کنم و با حرکت ماوس کوچیک و بزرگ و جابجاش کنم. دقت کنید این دفعه دیگه از تابع draw استفاده نمی‌کنم، بلکه از یه تابع دیگه استفاده می‌کنم به نام mouseMoved که همون طوری که از اسمش پیداس، بر اساس حرکت ماوس کُدی که داخلش نوشته شده رو اجرا می‌کنه (اگه با متغیر mouseX و mouseY آشنا نیستید باید «ورودی» رو بخونید):

const letter = 'ق'

function setup() {
     createCanvas(windowWidth, windowHeight);
     textFont('iranSans')
     textAlign(CENTER, CENTER)
     background(255)
}
function mouseMoved() {
     background(200)
     textSize((mouseX - width / 2) * 5 + 1)
     text(letter, width / 2, mouseY)
}

نادین سافت

آموزش p5.js و فراتر از آن!

چرا آموزش p5.js؟

چند سالی هست که دارم با جاوااسکریپت و p5.js سر و کله می‌زنم و اخیراً این ایده به ذهنم رسید که چیزایی که تا الان یاد گرفتمو در قالب مجموعه‌ای از نوشته‌ها تحت عنوان «آموزش p5.js» توی سایتم منتشر کنم. البته من واقعاً هنوز در حال یادگیری هستم، اما فک می‌کنم چیزایی که تا الان یاد گرفتم هم ارزش دارن که با کسایی که اول این مسیر هستن به اشتراک گذاشته بشن. ضمن این که هیچ آموزش p5.js خوبی به زبون فارسی توی اینترنت پیدا نکردم.

یادداشت‌هایی که این جا می‌نویسم موضوعشون فقط آموزش p5.js نیست: قراره درباره مبانی برنامه‌نویسی، مقدار زیادی جاوااسکریپت، الگوریتم‌های مختلف و در نهایت ـ موضوع مورد علاقه خودم ـ ینی هنر مولد یا Generative Art کلی چیزمیز بخونید.

با یاد گرفتن یه زبان برنامه‌نویسی جدید، دنیایی از موقعیت‌های جدید روبروی شما قرار می‌گیره، چون می‌تونید با کامپیوتر صحبت کنید و ازش بخواید کارهایی رو براتون انجام بده.

جاوااسکریپت چیه؟

بعضیا ممکنه جاوااسکریپت رو با جاوا اشتباه بگیرن؛ این دو تا، چیزهای متفاوتی هستن و به غیر از تشابه اسمی هیچ ارتباطی به همدیگه ندارن. جاوااسکریپت زبونیه که برای برنامه‌نویسی صفحات وب استفاده می‌شه، با این که کاربرد اصلیش همین برنامه‌نویسیِ وب و فرانت‌انده و بیشتر افراد هم برای همین جاوااسکریپت یاد می‌گیرن، اما محیط‌های زیادی هستن که از این زبون پشتیبانی می‌کنن و همین باعث شده تا بشه کارای زیادی باهاش انجام داد: وقتی جاوااسکریپت یاد بگیرید، می‌تونید برنامه‌نویسی سرور انجام بدید، اپلیکیشن موبایل و دسکتاپ بنویسید و حتی بازی بسازید یا هوش مصنوعی کار کنید؛ همه این کارها رو می‌تونید با یاد گرفتن فقط یک زبون برنامه‌نویسی انجام بدید و برای همینه که جاوااسکریپت این قدر جذابه.

دوره‌های برنامه‌نویسی معمولاً تمرکزشون روی سینتکس و روش‌های حل مسئله‌س؛ خیلیا رو دیدم که حتی قبل از به پایان رسوندن این دوره‌ها کلاً بی‌خیال برنامه‌نویسی می‌شن؛ برای همین توی این یادداشت‌ها سعی می‌کنم تجربه‌هامو به اشتراک بذارم و با استفاده از کتابخونه p5.js، برنامه‌نویسی جاوااسکریپت رو با ایجاد تصاویر آموزش بدم؛ یعنی شما که در حال یادگیری جاوااسکریپت هستید، بیشتر مفاهیم رو با ساختن شکل و انیمیشن و سایر عناصر گرافیکی یاد می‌گیرید؛ امیدوارم این بازخورد گرافیکی باعث افزایش انگیزه برای یادگیری بشه؛ اگه اولین باره که دارید چیزی درباره برنامه‌نویسی یاد می‌گیرید، این طوری از نقطه خیلی خوبی وارد دنیای برنامه‌نویسی می‌شید.

p5.js چیه؟

p5.js کتابخونه‌ایه که با استفاده جاوااسکریپت نوشته شده و می‌شه باهاش برنامه‌هایی نوشت که تصویر و انیمیشن تولید می‌کنن؛ من چند سالیه که دارم ازش استفاده می‌کنم و هنوز برام جذابه. قدیما که دانشکده معماری درس می‌خوندم، وقتی یه ایده‌ای برای طراحی داشتم سریع یه کاغذ و قلم برمی‌داشتم و خیلی ساده روی کاغذ می‌کشیدمش؛ این کار بهم کمک می‌کرد که جنبه‌های مختلف اون ایده رو بررسی کنم و توسعه بدم؛ به این کار می‌گفتیم «اسکیس» زدن؛ ایده اصلی p5.js هم همینه که یه برنامه‌نویس با نوشتن حداقل کد، خیلی سریع به اون تصویری که توی ذهنشه برسه و بعد روی اون ایده کار کنه؛ مثلاً چند خط کد بنویسه و دایره روی مانیتور، دنبال ماوس حرکت کنه؛ به این کار اصطلاحاً می‌گیم «اسکیس زدن با کد».

p5.js چه کاربردهایی دارده؟

  • داده‌نمایی یا Data Visualization
  • تولید تصاویر مولد یا Generative Art
  • ساختن انیمیشن در صفحات وب
  • ساختن وبسایت
  • ساختن بازی

من شخصاً چون به موضوع Generative Art علاقه داشتم رفتم سراغ یادگیری p5.js و بعد که یاد گرفتم، شروع کردم به تصویر ساختن و پروژه‌های شخصی انجام دادن؛ اما یادگیری p5.js به درد همه کسایی می‌خوره که به گرافیک و برنامه‌نویسی علاقه دارن و مشتاقن ببینن که چطوری می‌شه اینارو با هم ترکیب کرد و چیزایی مثل تصویر، نمودار و انیمیشن درست کرد. اگه شما هم مثل من فکر می‌کنید که ساختن یه اثر هنری با کد، کار جذاب و هیجان‌انگیزیه توصیه من اینه که مبانی برنامه‌نویسی رو توی p5.js یاد بگیرید و بعد بر اساس اهدافتون، مسیرتون رو انتخاب کنید و پیش‌رفت کنید. اگه موافق هستید، شروع کنیم.

چه چیزهایی لازم داریم؟

خوبی یاد گرفتن یه زبون برنامه‌نویسی اینه که واقعاً به چیزای خیلی خفنی نیاز ندارید تا یادگیری رو شروع کنید. توی این دوره فرض من اینه که شما پای یه کامپیوتر دسکتاپ نشستید، به اینترنت دسترسی دارید و مثل من دوست دارید موقع کار یه لیوان قهوه داغ دم دستتون باشه. ضمناً اگه هیچ پیش‌زمینه‌ای از برنامه‌نویسی ندارید نگران نباشید، قرار نیست درباره چیزهای خیلی پیچیده و سخت صحبت کنیم و بیشتر، موضوعاتِ اساسی مورد بحث قرار می‌گیرن. خیلی‌ها اعتقاد دارن یاد گرفتن زبان برنامه‌نویسی از یاد گرفتن زبان خارجی راحت‌تره، پس اصلاً نگران نباشید.

برای شروع باید یه ویرایشگر کد نصب کنیم. برنامه‌های ویرایشگر کد مثل برنامه‌های ویرایشگر متن هستن (مثلاً نوت‌پد)، با این تفاوت که قابلیت‌های ویژه‌ای برای نوشتن و ویرایش کد دارن که جلوتر می‌بینیم؛ می‌تونید با هر برنامه‌ای که راحت‌تر هستید کار کنید چون تعدادشون خیلی زیاده. من از VS Code استفاده می‌کنم که متن‌باز و سبُکه. توی گوگل سرچ کنید VS Code، آخرین نسخه برنامه رو از سایتش دانلود کنید و با تنظیمات پیش‌فرض نصب کنید. بعد باید یه سر به این لینک بزنید: https://p5js.org/download و بسته p5.js complete رو دانلود کنید.

فایل زیپی که دانلود کردید رو توی یه فولدر دیگه آن‌زیپ کنید؛ مهم نیست اسم فولدر جدید چی باشه و فولدرو کجا درست می‌کنید؛ می‌تونید توی دسکتاپ درستش کنید و هر اسمی که دوست دارید براش بذارید. بعد به ترتیب این کارا رو انجام بدید:

  • برنامه VS Code رو باز کنید
  • از منوی File گزینه Open Folder رو انتخاب کنید
  • فولدری که ساختید رو پیدا کنید
  • فولدر empty-example رو توی VS Code باز کنید

تا این جای کار فولدر پروژه رو توی VS Code باز کردیم و آماده‌ایم تا اولین برنامه‌مونو بنویسیم.

توی p5.js، یه اسکیس شامل فایل‌های مختلفی می‌شه. اول از همه یه فایل HTML می‌بینید به نام index.html که همه اجزای برنامه رو توی یک صفحه به همدیگه متصل می‌کنه و فایلیه که در نهایت توسط مرورگر باز می‌شه و پروژه رو نمایش می‌ده. اگه فایل index.html رو داخل VS Code باز کنید می‌بینید که یه جایی از فایل، کتابخونه p5.js فراخونده شده. همچنین یه فایل دیگه فراخونده شده به نام sketch.js.

<!DOCTYPE html>
<html lang="">

<head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>p5.js example</title>
     <style>
          body {
               padding: 0;
               margin: 0;
          }
     </style>
     <script src="../p5.js"></script>
     <!-- <script src="../addons/p5.sound.js"></script> -->
     <script src="sketch.js"></script>
</head>

<body>
     <main>
     </main>
</body>

</html>

پس‌وند js مرتبط با زبان جاوااسکریپته. فایل p5.js شامل کدهای مرتبط با کتابخونه‌ایه که قراره باهاش کار کنیم و اصلاً نباید کاری با این فایل داشته باشید و قراره فقط توی اون فایل sketch.js کد جاوااسکریپت مرتبط با برنامه‌تونو بنویسید. فعلاً با فایل HTML هم هیچ کاری ندارید و نباید بهش دست بزنید.

فایل sketch.js رو باز کنید و یه نگاهی به کدی که توش نوشته شده بندازید:

function setup() {
     // put setup code here
}
function draw() {
     // put drawing code here
}

بعداً که درباره تابع‌ها صحبت کنیم، درباره این که تابع‌ها چی هستن و چطوری کار می‌کنن مفصل یاد می‌گیریم، اما فعلاً بدونید این دو تابعِ اصلیِ setup و draw توی همه برنامه‌هایی که با p5.js نوشته می‌شه وجود داره و یه تفاوتی بین اجراشون هست: هر کدی که مرتبط با وضعیت ابتدایی برنامه شما باشه، داخل تابع setup قرار می‌گیره و فقط یک بار اجرا می‌شه؛ هر کدی که مرتبط با کشیدن یه چیزی روی صفحه باشه توی تابع draw قرار می‌گیره و دائماً تکرار می‌شه.

توی کد بالا خطوطی وجود دارن که با علامت // مشخص شدن، به اینا می‌گیم کامنت. توی برنامه‌نویسی، کامنت‌ها خطوطی هستن که به زبان آدمیزاد نوشته می‌شن، یعنی موقعی که مرورگر داره برنامه رو اجرا می‌کنه، اون خطوط رو نادیده می‌گیره. کامنت‌ها برای این نوشته می‌شن که یه پیامی رو به آدمی که داره کد رو می‌خونه منتقل کنن و معمولاً برای توضیح دادن یه بخشی از کد استفاده می‌شن.

فعلاً چیزی توی تابع setup نمی‌نویسیم و می‌ذاریم خالی باشه. قراره اولین خطوط کدی که می‌نویسیم رو توی تابع draw قرار بدیم. داخل تابع draw کامنت put drawing code here رو پاک کنید و به جاش اینارو تایپ کنید:

background(204)
ellipse(50, 50, 80, 80)

کل فایل باید این شکلی باشه الان:

function setup() {
     // put setup code here
}
function draw() {
     background(204)
     ellipse(50, 50, 80, 80)
}

با فشار دادن دکمه‌های Ctrl + S فایل رو ذخیره کنید و بعد فایل index.html رو با هر مرورگری که دوست دارید باز کنید. اگه همه چی رو درست تایپ کرده باشید، باید یه دایره توی مرورگر ببینید.

توی p5.js دستورهایی وجود دارن که کارشون رسم شکله. مثلاْ همین ellipse که دایره یا بیضی می‌کشه یا دستور rect که مربع یا مستطیل می‌کشه. بیشتر دستورهایی که برای کشیدن اشکال استفاده می‌شن، چند تا پارامتر ضروری دارن که مشخص می‌کنه شکل کجا باید کشیده بشه و اندازه‌ش چقدر باشه (چند پیکسل باشه). دستورهایی هم وجود دارن که مشخص می‌کنن شکل‌هایی که بعد از اون‌ها ظاهر می‌شن، چه مشخصاتی قراره داشته باشن. مثلاً دستور noStroke که یعنی شکل، دورخط یا استروک نداره یا دستور fill که مشخص می‌کنه شکل قراره چه رنگی باشه.

توی مرحله بعد می‌ریم سراغ یه اسکیس جذاب‌تر. محتویات فایل script.js رو پاک کنید و کد پایین رو توش کپی کنید. فایل رو ذخیره کنید و پنجره مرورگرو با فشار دادن کلید F5 رفرش کنید.

function setup() {
     createCanvas(windowWidth, windowHeight)
}
function draw() {
     if(mouseIsPressed) {
          fill(0)
     } else {
          fill(255)
     }
     ellipse(mouseX, mouseY, 80, 80)
}
اولین چیزی که با خوندن مطلب آموزش p5.js درست کردید باید یه همچین شکلی باشه؛ کلی دایره روی مانیتور داریم!

این کد چه کاری انجام می‌ده؟

مرورگر، کدهایی که نوشتیمو به ترتیب از بالا به پایین اجرا می‌کنه. اگه دقت کنید می‌بینید که تابع setup شامل تابع createCanvas هست؛ این تابع چی کار می‌کنه؟ به صورت پیش‌فرض، بومی که اسکیس ما توش کشیده می‌شه، یه بوم صد پیکسل در صد پیکسله؛ اگه بخوایم یه بوم نقاشی با اندازه‌ی دلخواه خودمون داشته باشیم باید از تابع createCanvas استفاده کنیم. تابع createCanvas برای ما یه بوم نقاشی درست می‌کنه که توی مثال ما، عرضش هم‌عرض صفحه و ارتفاعش هم‌ارتفاع صفحه نمایشه.

کدی که توی تابع draw نوشته شده ـ همون طور که قبلاً گفتم ـ مکرراً اجرا می‌شه و با حرکت ماوس شروع می‌کنه به کشیدن دایره‌های سفید. اگر دکمه ماوس فشار داده بشه، رنگ دایره‌ای که داره کشیده می‌شه به سیاه تغییر پیدا می‌کنه.

اگه الان بخش‌هایی از کد هست که درست متوجه نمی‌شید؛ کاملاً طبیعیه و اصلاً لازم نیست نگران باشید؛ بعداً درباره جزییات هر بخش از این کد بیشتر صحبت می‌کنیم. مثلاً توی یاددشت مربوط به متغیرها می‌بینید که mouseIsPressed یه متغیر ازپیش‌تعریف‌شده‌س که هر وقت دکمه ماوس فشار داده می‌شه مقدارش true می‌شه. فعلاً لازم نیست نگرانش باشید و فقط فایل رو اجرا کنید و ببینید نتیجه‌ش چه شکلیه.

کنسول

مرورگرها یه ابزار خیلی مفیدی برای برنامه‌نویس‌ها دارن به نام کنسول. مهم‌ترین کار کنسول برای برنامه‌نویس‌ها اینه که برنامه نوشته شده رو عیب‌یابی می‌کنه. توی کروم برای این که کنسول رو باز کنید می‌تونید از کلیدهای میان‌بر Ctrl + Shift + J استفاده کنید؛ مثلاً اگه یه غلط دیکته‌ای توی برنامه شما باشه، اون جا ممکنه یه متن قرمز ببینید که خطا رو توضیح داده؛ البته توضیحاتی که می‌نویسه ممکنه یه خرده عجیب‌غریب به نظر برسه، اما اگه سمت راست همون خطا رو نگاه کنید نوشته که این خطا مربوط به کدوم فایل و کدوم خط از اون فایله؛ این آدرسی که می‌ده به شما کمک می‌کنه به اون جا مراجعه کنید و ببینید کجا مرتکب خطا شدید. دقت کنید که جاوااسکریپت نسبت به بزرگی و کوچکی حروف حساسیت داره. مثلاً توی حروف دستور noStroke فقط حرف S بزرگ نوشته شده و اگه به شکل nostroke یا NoStroke نوشته بشه، قطعاً با خطا مواجه می‌شید.

از کنسول می‌شه برای انجام تست‌های مختلف هم استفاده کرد. مثلاً می‌شه از دستور console.log جاهای مختلف کدی که می‌نویسیم استفاده کنیم تا ببینیم هر بخش از کد چطوری کار می‌کنه. الان من console.log رو داخل تابع setup و تابع draw قرار می‌دم تا ببینم چه اتفاقی می‌افته:

function setup() {
     console.log('setup')
}
function draw() {
     console.log('draw')
}

اگه شما هم کد بالا رو اجرا کنید و کنسول رو نگاه کنید، می‌بینید که اول از همه کد داخل تابع setup یک بار اجرا می‌شه و بعد از اون، کد داخل تابع draw پشت سر هم و خیلی سریع در حال اجرا شدنه و متوقف هم نمی‌شه و البته این همون چیزیه که ما توقع داریم p5.js برامون انجام بده.

چطوری یه پروژه جدید بسازیم؟

آسون‌ترین راه ساختن یه پروژه جدید اینه که از فولدر empty-example یه کپی بگیرید و همون جا پیست کنید؛ حالا می‌تونید اسم فولدر جدیدو عوض کنید و مثل فولدر قبلی توی برنامه VS Code بازش کنید. این خیلی مهمه که هر وقت خواستید برنامه‌تونو تست کنید، فایل index.html مرتبط با همون پروژه رو باز کنید.

افزونه Live Server روی VS Code

اگر شما هم مثل من از VS Code استفاده می‌کنید می‌تونید از افزونه Live Server برای دیدن تغییرات به صورت همزمان استفاده کنید؛ این طوری دیگه نیاز نیست هر موقع تغییری توی پروژه ایجاد می‌کنید صفحه مرورگرو رفرش کنید تا تغییرات رو ببینید؛ فقط تغییرات رو ذخیره کنید تا مرورگر خودبه‌خود رفرش بشه و تغییراتتون اعمال بشه.

برای نصب کردن افزونه Live Server:

  • از منوی سمت چپ وارد بخش Extensions بشید
  • عبارت Live Server رو سرچ کنید و افزونه رو نصب کنید
  • توی برنامه VS Code صفحه HTML پروژه رو باز کنید
  • از نوار آبی پایین روی Go Live کلیک کنید
  • شروع کنید به کد زدن

سر زدن به رفرنس‌ها

می‌دونم که خیلی طولانی شد ولی این مقدمات برای شروع آموزش p5.js لازم بود. توی یادداشت بعدی درباره متغیرها یاد می‌گیریم که برای یاد گرفتن جاوااسکریپت و همچنین ادامه آموزش p5.js خیلی اساسی و مهمه. امیدوارم حوصله‌تون سر نرفته باشه.

یه نکته نهایی هم بگم و برای یادداشت اول دیگه کافیه. وقتی دارید با p5.js برنامه‌نویسی می‌کنید خیلی وقتا لازمه که به وبسایت p5.js سر بزنید و یه نگاهی به رفرنس‌هایی که توی این لینک هستن بندازید: https://p5js.org/reference. من دائماً این کارو انجام می‌دم چون چیزای به‌دردبخور و مهم زیادی توش پیدا می‌شه. به نظر من هر وقت حس کردید که نسبت به یه چیزی توی برنامه‌تون آشنایی کامل ندارید، باید یه سر به رفرنس بزنید، ازش سر دربیارید و بفهمید دقیقاً چطوری کار می‌کنه و غافل‌گیر نشید. رفرنس p5.js خیلی کامله و همه توابع رو با مثال توضیح داده. بعداً که بیشتر با جاوااسکریپت و p5.js آشنا شدید، می‌تونید توی رفرنس بگردید و چیزای جدید کشف کنید.

سیکاس سپنتا