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

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

رومی آنلاین

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

JSOM چیه؟

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

توی این مقاله من از یه وب پارت content search استفاده کردم؛ این کار خیلی منطقی‌ترین راه به نظر می‌رسه چون توی display templateهای پیش‌فرض شیرپوینت، روش‌هایی برای فراخونی فایل‌های CSS و JS وجود داره که جلوتر می‌بینید.

JSOM در content search

هر وب پارت 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 رو بر اساس ساختاری که بالاتر توضیح دادم می‌نویسیم:

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 آشنا شدید، می‌تونید توی رفرنس بگردید و چیزای جدید کشف کنید.

سیکاس سپنتا

راهکار خلاق

آرمان پرتو تصویر