دیروز در یک برنامه میخواستم کاربر بتواند لیست مواد مصرفی یک کارخانه را ایجاد کند که نیاز بود کاربر بتواند از هر سطر به تعداد نامحدود ایجاد کند و برای انتخاب هر یک از مواد به همراه جزئیات آن یک سطر به لیست اضافه شود. برای اینکار میتوانیم با استفاده از فناوری جی کوئری اینکار را انجام دهیم ولی بهتر بود که این مورد به یک افزونه تبدیل میشد تا در دفعات بعدی بسیار راحتتر باشیم. جهت آشنایی با پلاگین نویسی بهتر هست این
مقالات (
+) را مطالعه فرمایید.
نحوه استفاده
نحوه استفاده از آن بسیار راحت است و در دموی html همراه آن به طور ساده در سه مثال توضیح داده شده است. ابتدا از
این آدرس کتابخانه آن را دریافت کنید. این کتابخانه شامل یک فایل js که شامل کدهای پلاگین است، یک فایل css جهت تغییر استایل کدهایی است که پلاگین تولید میکند که اسامی آن دقیقا مشخص میکند که هر کلاس متعلق به چه بخشی است.
گام اول:
فایلهای مورد نظر را بعد از صدا زدن کتابخانهی جی کوئری صدا بزنید.
<link type="text/css" href="css/RowAdder.css" rel="stylesheet" />
<script src="js/RowAdder.js" type="text/javascript"></script>
گام دوم :
در تکه کدهای html، کدی را که قرار است در هر سطر تکرار شود، داخل یک div قرار داده و نامی مثل row-sample را برای آن قرار دهید (فعلا حتما این نام باشد)، بعدها پلاگین، کدهای داخل این تگ div را به عنوان هر سطر خواهد شناخت:
<div id="row-sample">
<form style="margin: 0; padding: 0;">
Name:<input type="text"/>
<input type="radio" name="Gender" value="male" checked="checked">Male
<input type="radio" name="Gender" value="female">Female
</form>
</div>
گام سوم:
سپس یک div دیگر ایجاد کنید و نامی مثل mypanel را به آن بدهید تا سطرهایی که ایجاد میشوند داخل این div قرار بگیرند.
گام چهارم:
در بخش head یک تگ اسکریپت باز کرده و کدهای زیر را به آن اضافه میکنیم. این کد باعث میشود که پلاگین فعال شود.
<script>
$(document).ready(function() {
$("#mypanel").RowAdder();
});
</script>
گام پنجم:
یک دکمه جهت افزودن سطر به صفحه اضافه میکنیم
<button id="addanotherform">Add New Form</button>
و در قسمت تگ اسکریپت هم کد زیر را اضافه میکنیم:
$("#addanotherform").on('click', function() {
$("#mypanel").RowAdder('add');
});
حال از صفحه تست میگیریم: با هر بار کلیک بر روی دکمهی Add New Form یک سطر جدید ایجاد میگردد.
در تصویر بالا دکمههای دیگر هم دیده میشوند که به دیگر متدهای آن اشاره دارد:
جهت مخفی سازی:
$("#mypanel").RowAdder('hide');
چهت نمایش:
$("#mypanel").RowAdder('show');
جهت افزودن سطر با کد:
$("#mypanel").RowAdder('add');
جهت دریافت تعداد سطرهای ایجاد شده:
$("#mypanel").RowAdder('count')
جهت دریافت کدهای یک سطر در اندیس x
$("#mypanel").RowAdder('content', 3)
جهت حذف یک سطر با اندیس x $("#mypanel").RowAdder('remove', 3);
همانطور که با صدا زدن اولین متد پلاگین متوجه شدید و نتیجهی آن را در دمو دیدید، این پلاگین از پیش فرضهایی جهت راه اندازی اولیه استفاده میکند که این پیش فرضها عبارتند از تگ row-sample که بدون معرفی رسمی، آن را شناسایی کرد. همچنین ممکن است بخواهید عبارت
Remove را با کلمهی فارسی «
حذف» جایگزین نمایید. برای اینکار میتوانید پلاگین را به شکل زیر به کار ببرید:
$("#mypanel").RowAdder({
sample: '#my-custom-sample',
type: 'text',
value:'حذف'
});
تغییر اولین پیش فرض، تغییر نام تگ row-sample به my-custom-sample بود و در مرحلهی بعد هم نام فارسی حذف را جایگزین remove کردیم. عبارت type به طور پیش فرض بر روی text قرار دارد که اجباری به ذکر آن در کد بالا نبود. ولی اگر دوست دارید که به جای نمایش عبارت حذف، از یک آیکن یا تصویر استفاده کنید، کد را به شکل زیر تغییر دهید:
$("#mypanel").RowAdder({
type: 'image',
value: 'images/remove.png'
});
در خطوط بالا عبارت type با image مقدار دهی شد و به پلاگین میگوید که به جای متن، از تصویر استفاده کن. همچنین value را به جای متن با آدرس تصویر مقداردهی کردهایم و نتیجه را میتوانید در
دموی قرار گرفته در گیت هاب ببینید.
فایل RowAdder.css در بردارنده هر سطر
.each-section {
margin: 20px;
padding: 5px;
}
جهت استایل بندی لینک چه تصویر و چه متن
.remove-link {
color:#999;
text-decoration: none;
}
a:hover.remove-link {
color:#802727;
}
جهت تغییر استایل بر روی خود تصویر
.remove-image {
}
آشنایی با کد پلاگین
(function ($) {
var settings = null;
$.fn.RowAdder = function (method) {
// call methods
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.RowAdder');
}
};
})(jQuery);
در
قسمت دوم آموزش پلاگین نویسی برای جی کوئری، متدها به طور واضح توضیح داده شدهاند. این کدها وظیفه دارند متدهایی را که کاربر درخواست داده است، شناسایی و به همراه آرگومانهای آن به سمت توابعی که به هر نام متد اختصاص دادهایم، ارسال کنند. در صورتیکه متدی با آرگومانهای ناهماهنگی ارسال شوند، پیام خطایی ارسال میگردد و در صورتیکه تعریف نشود، به طور مستقیم init را صدا میزند. متغیر settings هم بعدا با تنظیمات پیش فرض پر میشود.
متدها
//methods
var methods = {
init: function (options) {
//default-settings
settings = $.extend({
'sample': '#row-sample',
'type': 'text',
'value': 'Remove'
}, options);
this.attr('data-sample', settings.sample);
this.attr('data-type', settings.type);
this.attr('data-value', settings.value);
Do(this);
},
show: function () {
this.css("display", "inline");
},
hide: function () {
this.css("display", "none");
},
add: function () {
Do(this);
},
remove: function (index) {
console.log(index);
this.find(".each-section")[index].remove();
},
content: function (index) {
return this.find(".each-section")[index];
},
count: function (index) {
return this.find(".each-section").size();
}
};
متد init تنظیمات پیش فرض را دریافت مینماید و سپس بر روی المانی که پلاگین روی آن واقع شدهاست، مقادیر را ذخیره میکند تا در آینده با صدا زدن متدهای دیگر آن را استفاده نماید. کلمهی this در واقع به تگی اشاره میکند که پلاگین روی آن اعمال شده است که در مثالهای بالا mypanel نام داشت. متد Do تابع اصلی ما را در بر دارد که کدهای اصلی پلاگین را شامل میشود. مابقی متدها در واقع جست و جویی بر المانها هستند.
تابع Do
function Do(panelDiv) {
settings.sample = panelDiv.data('sample');
settings.type = panelDiv.data('type');
settings.value = panelDiv.data('value');
//find sample code
var rowsample = $(settings.sample);
rowsample.css("display", "none");
var sample = rowsample.html();
var i = panelDiv.find(".each-section").size();
//add html details to create a correct template
var sectionDiv = $('<div />', { "class": 'each-section', 'id': 'section'+i });
var image = $("<img />", { "src": settings.value,"class":"remove-image" });
var link = $("<a />", { "text": settings.value,"class":"remove-link" });
//remove event for remove selected form
//create new form
sectionDiv.html(sample);
link.on('click', function (e) {
e.preventDefault();
var $this = $(this);
$this.closest(".each-section").remove();
});
if (i > 0) {
if (settings.type == 'image') {
link.text('');
link.append(image);
}
sectionDiv.append(link);
}
//add new created form on document
panelDiv.append(sectionDiv);
}
آرگومان داده شده، در واقع همان this هست که به این تابع ارسال شده است. در اولین گام تنظیمات ذخیره شده را که قبلا ذخیره کردهایم، واکشی میکنیم. سپس تگ row-sample یا هر نامی را که به آن اختصاص داده شده است، مییابیم و محتوای آن را به شکل html در قالب string بیرون میکشیم. این کد html در واقع نمونهای است که قرار است در سطر تکرار شود. البته تگ نمونه فقط برای نمونه به کار میرود و نیازی نیست روی صفحه نمایش داده شود؛ پس آن را مخفی میکنیم. از آنجا که ممکن است این سطری که ایجاد میشود، سطر اول نباشد و قبلا هم سطرهایی توسط همین متد ایجاد شدهاند، بررسی میکنیم چند تگ با کلاس each-section داریم. اگر بیشتر از صفر باشد یعنی قبلا سطرهایی ایجاد شده است. در غیر اینصورت این اولین سطر ماست. اولین سطر توسط init صدا زده میشود و مابقی توسط متد add انجام میگیرد.
settings.sample = panelDiv.data('sample');
settings.type = panelDiv.data('type');
settings.value = panelDiv.data('value');
//find sample code
var rowsample = $(settings.sample);
rowsample.css("display", "none");
var sample = rowsample.html();
var i = panelDiv.find(".each-section").size();
در خطوط بعدی یک سری متغیر داریم که برای هر کدام یک قالب تگ div با کلاسهای مختلف میسازیم. sectionDiv یک تگ div با کلاس each-section است که هر سطر را به طور کامل در خود قرار میدهد. link، جهت ساخت لینک حذف با کلاس remove-link به کار میرود. image هم یک تگ image میسازد تا اگر کاربر درخواست 'type:'image را داد، به جای لینک متنی حذف، از تصویر استفاده شود.
//add html details to create a correct template
var sectionDiv = $('<div />', { "class": 'each-section', 'id': 'section'+i });
var image = $("<img />", { "src": settings.value,"class":"remove-image" });
var link = $("<a />", { "text": settings.value,"class":"remove-link" });
در خط بعدی محتویات نمونه را داخل تگ sectiondiv قرار میدهیم:
//create new form
sectionDiv.html(sample);
بعد از آن برای رویداد کلیک لینک حذف، کد زیر را وارد میکنیم:
link.on('click', function (e) {
e.preventDefault();
var $this = $(this);
$this.closest(".each-section").remove();
});
متد closest در جی کوئری این وظیفه را دارد تا به سمت تگهای والد تگ this حرکت کند و با برخوردن با اولین تگ والد با کلاس each-section، آن تگ والد را بازگرداند و سپس متد remove را روی آن اجرا کند تا آن تگ به همراه تمام فرزندانش حذف شوند.
اولین شرط زیر بررسی میکند که آیا این سطری که ایجاد شده است سطر دوم به بعد است یا خیر؟ اگر آری پس باید دکمهی حذف را به همراه داشته باشد. در صورتیکه سطر دوم به بعد باشد، وارد آن میشود. حالا بررسی میکند که کاربر برای دکمهی حذف، درخواست لینک تصویری یا لینک متنی داده است و لینک مناسب را ساخته و آن را به انتهای sectionDiv اضافه میکند.
if (i > 0) {
if (settings.type == 'image') {
link.text('');
link.append(image);
}
sectionDiv.append(link);
}
در انتها کل تگ sectionDiv را به تگ داده شده اضافه میکنیم تا به کاربر نمایش داده شود.
//add new created form on document
panelDiv.append(sectionDiv);