در گیت هاب میتونید تعداد زیادی پروژه پیدا کنید که لیستی از منابع و لینکهای مفید رو برای یه زبون با یک فریم ورک خاص جمع کرده. مثلا awesome-javascript رو مشاهده کنید: https://github.com/sorrycc/awesome-javascript
حالا یک پروژه به نام awesome درست شده که لیستی از تمام این awesomeها رو تو خودش جمع کرده! و این واقعا عالیه
معرفی کتابخانه Postal برای ASP.NET MVC
A from address must be specified
توسعه سیستم مدیریت محتوای DNTCms - قسمت دوم
No Authentication
اگر گزینه No Authentication را انتخاب کنید، پروژه ایجاد شده صفحاتی را برای ورود به سایت نخواهد ساخت. همچنین رابط کاربری ای برای نمایش کاربر فعلی، کلاسهای موجودیتها برای یک دیتابیس عضویت و رشتههای اتصالی نیز وجود نخواهند داشت.
- سیستم عضویت جدید بجای استفاده از ماژول ASP.NET Forms Authentication بر پایه OWIN نوشته شده است. این بدین معنا است که از یک مکانیزم احراز هویت واحد میتوانید در اپلیکیشنهای ASP.NET Web Forms, MVC, Web API و SignalR استفاده کنید.
- سیستم عضویت جدید توسط Entity Framework Code First مدیریت میشود و شامل تمامی کلاسهایی است که نماینده جداول و موجودیتها هستند. این بدین معنا است که روی الگوی دیتابیس کنترل کامل دارید. سفارشی سازی و تغییر اطلاعات کاربران و پروفایل هایشان بسیار سادهتر است، تنها لازم است برای اعمال تغییرات از Code First Migrations استفاده کنید.
- asp.net/identity
- Create an ASP.NET MVC 5 App with Facebook and Google OAuth2 and OpenID Sign-on
- Web API - External Authentication Services
- Adding External Logins to your ASP.NET application in Visual Studio 2013
اگر گزینه Organizational Accounts را انتخاب کنید پروژه ایجاد شده برای استفاده از (Windows Identity Foundation (WIF پیکربندی خواهد شد. این فریم ورک برای احراز هویت کاربران از (Windows Azure Active Directory (WAAD استفاده میکند که شامل Office 365 نیز میشود.
از این گزینه برای احراز هویت کاربرانی استفاده کنید که در قالب یک OWIN Tenant تعریف میشوند. برای مثال سایتی با نام Company.com داریم که برای کارمندان این سازمان از طریق company.onmicrosoft.com قابل دسترسی خواهد بود. نمیتوانید WAAD را طوری پیکربندی کنید که کاربران tenantهای دیگر نیز به اپلیکیشن شما دسترسی داشته باشند.
Domain
نام دامنهای در WAAD که میخواهید اپلیکیشن را برای آن پیکربندی کنید، مثلا company.onmicrosoft.com. اگر از custom domain ها استفاده میکنید مانند company.com بجای company.onmicrosoft.com میتوانید این اطلاعات را اینجا وارد کنید.
سطح دسترسی
اگر اپلیکیشن نیاز به کوئری گرفتن یا بروز رسانی اطلاعات پوشهها (directory information) را توسط Graph API دارد، از گزینههای Single Sign-On, Read Directory Data و یا Single Sign-On, Read and Write Directory Data استفاده کنید. در غیر اینصورت گزینه Single Sign-On را رها کنید. برای اطلاعات بیشتر به Application Access Levels و Using the Graph API to Query Windows Azure AD مراجعه کنید.
Application ID URI
بصورت پیش فرض، قالب پروژه یک شناسه application ID URI برای شما تولید میکند، که این کار با الحاق نام پروژه شما به نام دامنه WAAD صورت میگیرد. برای مثال، اگر نام پروژه Example باشد و نام دامنه contoso.onmicrosoft.com، شناسه خروجی https://contoso.onmicrosoft.com/Example میشود. اگر میخواهید بصورت دستی این فیلد را مقدار دهی کنید، گزینه More Options را انتخاب کنید. این شناسه باید با //:https شروع شود.
بصورت پیش فرض، اگر اپلیکیشنی که در WAAD تهیه و تدارک دیده شده است، شناسهای یکسان با شناسه موجود در پروژه Visual Studio داشته باشد، پروژه شما به اپلیکیشن موجود در WAAD متصل خواهد شد. اگر میخواهید تدارکات جدیدی ببینید تیک گزینه Overwrite the application entry if one with the same ID already exists را حذف کنید.
اگر تیک این گزینه حذف شده باشد، و ویژوال استودیو اپلیکیشنی با شناسهای یکسان را پیدا کند، عددی به آخر URI اضافه خواهد شد. مثلا فرض کنید نام پروژه Example است و اپلیکیشنی نیز با شناسه https://contoso.onmicrosoft.com/Example در WAAD وجود دارد. در این صورت اپلیکیشن جدیدی با شناسه ای مانند https://contoso.onmicrosoft.com/Example_ 20130619330903 ایجاد میشود.
تهیه و تدارک اپلیکیشن در WAAD
برای آنکه یک اپلیکیشن WAAD ایجاد کنید و یا پروژه را به یک اپلیکیشن موجود متصل کنید، ویژوال استودیو به اطلاعات ورود یک مدیر کل برای دامنه مورد نظر، نیاز دارد. هنگامی که در دیالوگ Configure Authentication روی OK کلیک میکنید، اطلاعات ورود یک مدیر کل از شما درخواست میشود و نهایتا هنگامیکه روی Create Project کلیک میکنید، ویژوال استودیو اپلیکیشن شما را در WAAD پیکربندی میکند.
برای اطلاعات بیشتر درباره نحوه استفاده از مدل احراز هویت Cloud - Single Organization به لینکهای زیر مراجعه فرمایید:
- Windows Azure Authentication
- Adding Sign-On to Your Web Application Using Windows Azure AD
- Developing ASP.NET Apps with Windows Azure Active Directory
از این گزینه برای احراز هویت کاربرانی استفاده کنید که در WAAD tenantهای متعددی تعریف شدهاند. برای مثال، نام سایت contoso.com است و برای کارمندان دو سازمان از طریق آدرسهای contoso.onmicrosoft.com و fabrikam.onmicrosoft.com قابل دسترسی خواهد بود. نحوه پیکربندی این مدل نیز مانند قسمت قبلی است.
برای اطلاعات بیشتر درباره احراز هویت Cloud - Multi Organization به لینکهای زیر مراجعه کنید:
- Easy Web App Integration with Windows Azure Active Directory, ASP.NET & Visual Studio
- Developing Multi-Tenant Web Applications with Windows Azure AD
این گزینه را هنگامی انتخاب کنید که کاربران در (Windows Server Active Directory (AD تعریف شده اند و نمیخواهید از WAAD استفاده کنید. از این مدل برای ایجاد وب سایتهای اینترنت و اینترانت میتوانید استفاده کنید. برای یک وب سایت اینترنتی از (Active Directory Federation Services (ADFS استفاده کنید.
برای یک وب سایت اینترانتی، میتوانید کلا این گزینه را رها کنید و از Windows Authentication استفاده کنید. در صورت استفاده از گزینه Windows Authentication لازم نیست تا آدرس سند متادیتا (metadata document URL) را فراهم کنید، همچنین توجه داشته باشید که Windows Authentication امکان کوئری گرفتن از پوشهها و کنترل سطوح دسترسی در Active Directory را ندارد.
On-Premises Authority
آدرس سند متادیتا. این سند اطلاعاتی درباره مختصات Authority دارد که اپلیکیشن از آنها برای به پیش بردن روند احراز هویت و ورود به سایت استفاده میکند.
Application ID URI
یک شناسه منحصر به فرد که AD از آن برای شناسایی اپلیکیشن استفاده میکند. میتوانید این فیلد را خالی رها کنید تا ویژوال استودیو بصورت خودکار اپلیکیشنی بدین منظور بسازد.
قدمهای بعدی
در این مقاله با مدلهای مختلف احراز هویت در اپلیکیشنهای Visual Studio 2013 آشنا شدید و برخی تغییرات و امکانات جدید نیز بررسی شدند. برای اطلاعات تکمیلی به ASP.NET and Web Tools for Visual Studio 2013 Release Notes مراجعه کنید.
برای ساخت یک extender کافیست تابع مورد نظر را به عنوان آرگومان به شی ko.extenders پاس دهیم. پارامتر اول این تابع، شیء observable شده مورد نظر و پارامتر دوم آن، شیء option برای انجام یک سری تنظیمات یا فرستادن مقادیر مورد نظر به تابع است. خروجی این تابع نیز میتواند یک شی observable یا حتی یک شی computed/observable نیز باشد.
یک مثال ساده برای extenderها به صورت زیر است:
ko.extenders.logOpt = function(target, option) { target.subscribe(function(newValue) { console.log(option + ": " + newValue); }); return target; };
برای استفاده از این extender کافیست آن را در هنگام تعریف تابع observable برای خواص، به صورت زیر فراخوانی نمایید:
this.firstName = ko.observable("Masoud").extend({logOpt: "my first name"});
my first name : Masoud
پیاده سازی یک extender جهت اعلام هشدار برای مقادیر منفی
برای اینکه هنگام ورود دادهها توسط کاربر، بتوانیم با ورود مقادیر منفی یک هشدار (تغییر رنگ ورودی) اعلام کنیم، میتوان به صورت زیر عمل نمود:
ko.extenders.negativeValueWarn = function (target, option) { target.hasWarning = ko.observable(); function warn(newValue) { if(newValue && newValue.substring) { newValue = parseFloat(newValue); } target.hasWarning(newValue < 0 ? true : false); } warn(target()); target.subscribe(warn); return target; };
یاد آوری : در KO برای انتساب مقدار جدید به خواصی که به صورت observable تعریف شده اند به صورت زیر:
target(NewValue) => فراخوانی به صورت تابع و پاس دادن مقدار جدید به آن
target() => فراخوانی به صورت تابع بدون آرگومان
پیاده سازی یک extender برای انتساب مقادیر Boolean به Radio Button ها
برای اینکه radio buttonها نیز بتوانند فقط با مقادیر Boolean مقدار دهی شوند و از طرفی در هنگام عملیات مقید سازی و ارسال نتایج در قالب شی Json به سرور، بدون هیچ گونه تغییر و محاسبات مقادیر مورد نظر به صورت true/false (از نوع Boolean) باشند میتوان به صورت زیر عمل نمود:
ko.extenders["booleanValue"] = function (target) { target.formattedValue = ko.computed({ read: function () { if (target() === true) return "True"; else if (target() === false) return "False"; }, write: function (newValue) { if (newValue) { if (newValue === "False") target(false); else if (newValue === "True") target(true); } } }); target.formattedValue(target()); return target; };
با فرض اینکه کدهای Html صفحه به صورت زیر است:
<span>Do you want fries with that?</span> <label> <input type="radio" name="question" value="True" data-bind="value: myValue.formattedValue" /> Yes </label> <label> <input type="radio" name="question" value="False" data-bind="value: myValue.formattedValue" /> No </label>
برای استفاده از آن کافیست به صورت زیر عمل نمایید:
this.myValue= ko.observable(false).extend({ booleanValue: null });
برش تصاویر قبل از آپلود (Crop)
<div style="overflow: auto"> <img id="preview" /> </div>
در این بین من با استفاده از فریمورک بوت استراپ کلاس img-responsive را به تگ image میدهم تا تصویر در هر صفحه نمایشی متناسب با اندازه آن نمایش داده شود. مشکل زیبایی تصویر در صفحه و نحوه کراپ کردن آن حل میشود ولی مشکل جدیدتر این است که تصویری که کراپ میشود آن ناحیه ای نیست که شما قبلا انتخاب کرده بودید؛ دلیل آن هم این است که تصویری که responsive شده است اندازه جدیدی برای خود دارد و برش ناحیه در سمت کلاینت و مختصاتی که به شما داده میشود بر اساس اندازه تغییر یافته است ولی در سمت سرور شما با اندازه واقعی تصویر سر و کار دارید و به همین دلیل مختصات ناحیه برش داده شده اشتباه بوده و قسمتهای دیگری از تصویر برش میخورند.
برای حل این مشکل ابتدا دو المان مخفی زیر را به صفحه اضافه میکنیم:
<input type="hidden" id="RealW" name="RealW" /> <input type="hidden" id="RealH" name="RealH" />
سپس کدهای زیر را به فایل js به شکل زیر ویرایش میکنیم:
$('#preview').Jcrop({ aspectRatio: 2, bgFade: true, bgOpacity: .3, onChange: updateInfo, onSelect: updateInfo }, function () { // use the Jcrop API to get the real image size //============== خطوط جدید $("#RealW").val($('#preview').css("width").replace("px", "")); $("#RealH").val($('#preview').css("height").replace("px", "")); //============== jcrop_api = this; });
سپس در سمت کلاینت با محاسبه فرمولهای تناسب این مشکل را رفع میکنیم تا مختصاتهای دریافت شده را به مختصاتهای واقعی تبدیل کنیم:
public static byte[] Resize(this byte[] byteImageIn, int x1,int y1,int x2,int y2,int realW,int realH) { //convert to full size image ImageConverter ic = new ImageConverter(); Image src = (Image)(ic.ConvertFrom(byteImageIn)); //original size if (src == null) return null; // چهار خط زیر فرمول تناسب را اجرا میکند x1 = src.Width * x1 / realW; x2 = src.Width * x2 / realW; y1 = src.Height * y1 / realH; y2 = src.Height * y2 / realH; Bitmap target = new Bitmap(x2 - x1, y2 - y1); using (Graphics graphics = Graphics.FromImage(target)) graphics.DrawImage(src, new Rectangle(0, 0, target.Width, target.Height), new Rectangle(x1,y1,x2-x1,y2-y1), GraphicsUnit.Pixel); src = target; using (var ms = new MemoryStream()) { src.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); return ms.ToArray(); } }
BulkInsert در EF CodeFirst
علت اصلی هم به اینجا بر میگردد که فایل pdb، به همراه کتابخانهی مورد نظر توزیع شده و این فایل حاوی محل قرارگیری سورس کتابخانه و همچنین شماره سطر مرتبط با استثناء است. چون این سورس بر روی سیستم شما موجود نیست و فایل pdb نیز پیوست شده، صفحهی باز کردن فایل یافت نشده، نمایش داده میشود.
نوشتن یک Tag Helper سفارشی، برای رندر کردن لیستهای بوت استرپی
فرض کنید میخواهیم یک tag helper جدید را جهت رندر کردن لیست بوت استرپی ذیل تهیه کنیم:
<ul class="list-group"> <li class="list-group-item">Item 1</li> <li class="list-group-item">Item 2</li> <li class="list-group-item">Item 3</li> </ul>
{ "version": "1.0.0-*", "dependencies": { "NETStandard.Library": "1.6.0", "Microsoft.AspNetCore.Http.Extensions": "1.0.0", "Microsoft.AspNetCore.Mvc.Abstractions": "1.0.1", "Microsoft.AspNetCore.Mvc.Core": "1.0.1", "Microsoft.AspNetCore.Mvc.ViewFeatures": "1.0.1", "Microsoft.AspNetCore.Razor.Runtime": "1.0.0" }, "frameworks": { "netstandard1.6": { "imports": "dnxcore50" } } }
بررسی آناتومی یک کلاس TagHelper
یک کلاس Tag Helper سفارشی، در حالت کلی میتواند شکل زیر را داشته باشد:
namespace Core1RtmEmptyTest.TagHelpers { [HtmlTargetElement("list-group")] public class ListGroupTagHelper : TagHelper { [HtmlAttributeName("asp-items")] public List<string> Items { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { } } }
توسط HtmlTargetElement نام نهایی تگ مرتبط با TagHelper سفارشی را تعریف و سفارشی سازی کردهایم. در این حالت این TagHelper جدید در Viewهای برنامه، توسط تگ ذیل شنایی میشود (بجای نام پیش فرض کلاس):
<list-group></list-group>
<list-group asp-items="Model.Items"></list-group>
برای اینکه نام این ویژگی را نیز بتوانیم سفارشی سازی کنیم، میتوان از ویژگی HtmlAttributeName استفاده کرد. در صورت عدم ذکر آن، از نام پیش فرض این خاصیت عمومی جهت تعریف ویژگیهای تگ نهایی استفاده میگردد.
عملیات نهایی افزودن تگهای HTML، به View برنامه، در متد Process انجام میشود. در اینجا توسط متدهایی مانند output.Content.AppendHtml میتوان خروجی دلخواهی را به صفحه اضافه کرد.
تکمیل کدهای Tag Helper سفارشی رندر کردن لیستهای بوت استرپی
پس از آشنایی با ساختار کلی یک کلاس TagHelper، اکنون میتوان کدهای آن را به نحو ذیل تکمیل کرد:
using System; using System.Collections.Generic; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; namespace Core1RtmEmptyTest.TagHelpers { [HtmlTargetElement("list-group")] public class ListGroupTagHelper : TagHelper { [HtmlAttributeName("asp-items")] public List<string> Items { get; set; } protected HttpRequest Request => ViewContext.HttpContext.Request; [ViewContext, HtmlAttributeNotBound] public ViewContext ViewContext { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (output == null) { throw new ArgumentNullException(nameof(output)); } if (Items == null) { throw new InvalidOperationException($"{nameof(Items)} must be provided"); } output.TagName = "ul"; output.TagMode = TagMode.StartTagAndEndTag; output.Attributes.Add("class", "list-group"); foreach (var item in Items) { TagBuilder itemBuilder = new TagBuilder("li"); itemBuilder.AddCssClass("list-group-item"); itemBuilder.InnerHtml.Append(item); output.Content.AppendHtml(itemBuilder); } } } }
- چون میخواهیم تگ نهایی آن، list-group نام داشته باشد، آنرا توسط ویژگی HtmlTargetElement به صورت صریحی مشخص کردهایم.
- همچنین علاقمندیم تا ویژگی دریافت لیست آیتمها، نامی معادل asp-items داشته باشد. بنابراین آنرا نیز توسط ویژگی HtmlAttributeName، دقیقا مشخص کردهایم.
- در این کلاس، یک خاصیت اضافهی ViewContext را نیز مشاهده میکنید. ویژگی ViewContext اعمالی به آن، سبب خواهد شد تا اطلاعات درخواست جاری، به این خاصیت عمومی، به صورت خودکار تزریق شود. بنابراین اگر نیاز به اطلاعاتی مانند Request جاری دارید، شیء ViewContext.HttpContext.Request، این مقادیر را در اختیار شما قرار میدهد. به علاوه اگر دقت کرده باشید، این خاصیت با ویژگی HtmlAttributeNotBound مزین شدهاست. از این جهت که نمیخواهیم این خاصیت عمومی، در لیست ویژگیهای تگ نهایی TagHelper در حال تهیه، ظاهر شود.
- پس از آن کاری که انجام شده، تکمیل متد Process است. در اینجا توسط output.TagName مشخص میکنیم که TagHelper جاری، در بین تگهای ul قرار گیرد (مفهوم TagMode.StartTagAndEndTag ذکر شده) و همچنین این تگ محصور کننده دارای کلاس list-group بوت استرپ نیز خواهد بود.
- سپس بر روی لیست آیتمهای دریافت شده، یک حلقه را تشکیل داده و به کمک TagBuilder، تگهای li داخل ul برونی را تکمیل میکنیم. این TagBuilder در نهایت توسط متد output.Content.AppendHtml به View برنامه اضافه خواهد شد. در اینجا، متد Append هم وجود دارد. اگر از آن استفاده شود، خروجی نهایی HTML Encoded خواهد بود.
ثبت و استفادهی از TagHelper سفارشی تهیه شده
پس از تعریف TagHelper سفارشی فوق، ابتدا ارجاعی از اسمبلی آنرا به پروژهی جاری اضافه میکنیم و سپس به فایل ViewImports.cshtml_ برنامه مراجعه و یک سطر ذیل را به آن اضافه میکنیم:
@addTagHelper *,Core1RtmEmptyTest.TagHelpers
اکنون که این TagHelper در Viewهای برنامه قابل شناسایی است، روش افزودن آن، بر اساس همان سفارشی سازیهایی است که انجام دادیم:
PDFKit
A JavaScript PDF generation library for Node and the browser
نمونه مثال ایجاد شده
وارد کردن کتابخانه ها
این کتابخانه شامل دو فایل css و JS میباشد که بسته به محیطی که در آن کار میکنید متفاوت هستند. در این صفحه شما میتوانید برای 4 محیط Jquery ,JqueryUI , Bootstrap2 و Bootsrap3 بستهی مخصوصش را یا به صورت دانلود فایلها یا از طریق CDN دریافت نمایید. در اینجا هم یک دمو از قابلیتهای آن قابل مشاهده است.
برای شروع، کتابخانهی مورد نظر خود را دریافت و آنها را به صفحهی خود اضافه نمایید. در صورتیکه از Bootstrap استفاده میکنید، ابتدا فایلهای زیر را اضافه کنید:
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"> <script src="http://code.jquery.com/jquery-2.0.3.min.js"></script> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
اولین حالتیکه میتوانید با این کتابخانه کار کنید، استفاده از خاصیت *-data است. نمونه زیر را در نظر بگیرید:
<a href="#" id="favsite" data-type="text" data-pk="1" data-url="@Url.Action(MVC.Categories.EditCategory())" data-title="Enter your favorite site">dotnettips.info</a>
$(document).ready(function () { $('#favsite').editable(); });
$(document).ready(function () { $.fn.editable.defaults.mode = 'inline'; $('#favsite').editable(); });
حالت بعدی که میتوان استفاده کرد به شکل زیر است:
<a href="#" id="favsite" >dotnettips.info</a>
$.fn.editable.defaults.mode = 'inline'; $(document).ready(function () { $('#favsite').editable({ type: 'text', pk: 1, url: '@Url.Action(MVC.Categories.EditCategory())', title: 'Enter your favorite site' }); });
خوبی این روش این است که میتوان اطلاعات بیشتری چون رویدادها را به آن پاس داد. تا الان با نحوهی انتساب آن به اشیاء آشنا شدیم. اجازه دهید تا با خصوصیات آن آشنا شویم.
AjaxOptions | همانطور
که متوجه شدید به طور خودکار اطلاعات ویرایش شده، به سمت آدرس داده شده،
به شیوه Post ارسال میگردند. در صورتیکه قصد دست بردن
در نوع درخواست را دارید، میتوانید از این ویژگی استفاده کنید: ajaxOptions: { type: 'put', dataType: 'json' } |
Anim | این
ویژگی که تنها در حالت inline پاسخ میدهد، میتواند زمان بسته شدن
x-editable را تغییر دهد که به طور پیش فرض با false مقداردهی شده است. جهت
تغییر زمان بسته شدن، کد زیر را وارد نمایید: anim:'false' //or anim: { duration: 2000 } |
autotext | در انتهای جدول آمده است. |
defaultValue | در
صورتیکه عنصر مورد نظر محتوایی نداشته باشد و این خصوصیت را
مقداردهی کنید، موقع ویرایش، این عبارت تعیین شده نمایش مییابد. در مثال
بالا باید متن تگ a را حذف کرده تا نتیجه را ببینید: (البته فیلد value نباید مقداری داشته باشد) defaultValue: 'default val' //or defaultValue: undefined //or defaultValue: null |
disabled | false کردن این ویژگی باعث غیرفعال شدن x-editable بر روی کنترل جاری میگردد. |
display | خاصیت
display یا مقدار بولین false را دریافت میکند، یا نال، یا یک تابع
callback را میتوان به آن پاس داد. این خصوصت زمانی صدا زده میشود که
اطلاعات به سمت آدرس سرور رفته و با موفقیت بازگشت داده میشوند (در صورتی
که این ویژگی غیرفعال باشد، بلافاصه بعد از تایید کاربر، از اطلاعات وارد شده
صدا زده میشود) و سپس متن جدید عنصر تغییر مییابد. حال اگر این خاصیت نال
که مقدار پیش فرض آن است باشد، متن تغییر مییابد. ولی اگر false باشد، متن سابق
باقی خواهد ماند و در صورتیکه تابعی به آن پاس داده باشید، طبق تابع شما
عمل خواهد کرد. پارامترهایی که تابع شما میتواند داشته باشد به شرح زیر است: value : مقدار جدید response : پاسخ سرور ( در صورتی که ارسال از طریق Ajax صورت گرفته باشد) و در صورتیکه عنصر شما checlklist یا select باشد که حاوی منبعی از مقادیر هست، مقادیرشان در قالب یک آرایه با نام sourceData بازگشت خواهد خورد. برای دسترسی به آیتمهای انتخابی هم از کد زیر استفاده میکنیم: $.fn.editableutils.itemsByValue(value, sourceData) |
emptyclass | معرفی یک کلاس css برای موقعیکه عنصر خالی است. |
emptytext | در صورتی خالی بودن عنصر، این متن را برای عنصر نمایش بده. |
highlight | بعد از به روز رسانی متن عنصر، آن را با این رنگ highlight خواهد کرد و کد رنگی باید در مبنای هگز باشد. مقدار پیش فرض آن false است. |
mode | دو
حالت نمایشی دارد که پیش فرض آن popup است و با باز کردن یک پنجره، مقدار
جدید را دریافت میکند. مورد بعدی inline است که به جای باز کردن پنجره،
متن عنصر را به حالت ویرایش تغییر میدهد. |
name | نام فیلدی که مقدارش تغییر میکند. |
onblur | زمانی که کاربر فوکوس را از ویرایشگر میگیرد، ویرایشگر چه پاسخی باید به آن بدهد، باز بماند؟ ignore ، بسته شود؟ cancel و یا مقدار داده شده را تایید کند؟submit |
params | پارامترهای درخواست ایجکسی که کنترل در حالت پیش فرض ارسال میکند؛ شامل Pk که آن را با id
رکورد پر میکنیم. name نام فیلدی که تغییر یافته است و value که مقدار جدید
است. در صورتیکه دوست دارید اطلاعات اضافیتری نیز ارسال شوند،
میتوانید از این خاصیت استفاده کنید و پارامترها را در قالب Object به آن
پاس کنید. ولی اگر بخواهید در کل همهی پارامترها را رونویسی کنید باید یک
تابع را به آن پاس کنید: params: function(params) { //در این حالت پارامترهای پیش فرض ارسال نشده و تنها پارامترهای معرفی شده در این تابع ارسال میشوند params.a = 1; return params; } |
pk | کلید
اصلی رکورد شما در دیتابیس یا هان id است. در صورتی که از کلیدهای ترکیبی
استفاده میکنید، نگران نباشید فکر آن را هم کرده اند.//کلید عدد pk:1, //کلید رشته ای pk:'dp123' //کلید ترکیبی pk:{id: 1, lang: 'en'} //معرفی یک تابع به آن و بازگشت |
Placement | این ویژگی فقط به درد حالت Popup میخورد که پنجره را کجای عنصر نمایش دهد و شامل چهار مقدار left,right,top,bottom میشود. |
saveonchange | زمانی
که مقدار جدید، برابر مقدار فعلی باشد و این خاصیت false باشد، هیچ تغییری رخ
نخواهد داد. ولی اگر برابر true باشد ،مقدار جدید اسال و جایگزین مقدار فعلی
خواهد شد. مقدار پیش فرض آن false است. |
selector |
با استفاده از این خصوصیت در عنصر انتخابی به دنبال عناصری که در selector
تعیین شده میگردد و حالت ویرایش را روی آنها فعال میکند. در این حالت استفاده از خصوصیات emptytext و autotext در ابتدای امر ممکن نیست و بعد از اولین کلیک قابل استفاده هستند. نکته بعدی اینکه شما باید کلاسهای زیر را دستی اضافه کنید. کلاس editable-click برای همه کنترلها وکلاس editable-empty به کنترلهای بدون مقدار و برای مقداردهی کنترلهای بدون مقدار میتوان از خاصیت ''=data-value استفاده کرد. <div id="user"> <!-- empty --> <a href="#" data-name="username" data-type="text" data-value="" title="Username">Empty</a> <!-- non-empty --> <a href="#" data-name="group" data-type="select" data-source="/groups" data-value="1" title="Group">Operator</a> </div> <script> $('#user').editable({ selector: 'a', url: '/post', pk: 1 }); </script> |
send | سه
مقدار auto,always و never را دریافت میکند. موقعی که شما آن را روی auto
تنظیم کنید؛ در صورتی مقادیر به سمت سرور ارسال میشوند که دو خاصیت url و
pk تعریف شده باشند. در غیر این صورت ویرایش فقط در حالت محلی و روی سیستم
کاربر رخ خواهد داد. |
showbuttons | در
صورتیکه با false مقداردهی شود، تایید فرم به طور خودکار انجام میگیرد و
اگر با یکی از مقادیر left یا Bottom پر شود، دکمهها را در آن قسمت نشان
میدهد. |
success | اطلاعات به سمت سرور
رفته و با موفقیت با کد 200 بازگشت داده شدهاند. در مستندات نوشته است، هر
کد وضعیتی غیر از 200 بازگشت داده شود، به سمت خاصیت error هدایت میشو.د ولی
آن طور که من با httpresponsemessage
تست کردم، چنین چیزی را مشاهده نکردم و مجددا success صدا زده شد. پس بهتر
هست دادهای را که به سمت کنترل برگشت میدهید، خودتان کنترل کنید. به خصوص
اگر انتقال اطلاعات صحیح باشد. ولی اگر در دیتابیس، تغییر با خطا روبرو گردد
بهتر است نتیجهی آن ارسال شده و از تغییر مقدار فعلی ممانعت به عمل آورید. success: function(response, newValue) { if(!response.success) return response.msg; } |
toggle | اگر قصد دارید که باز و بسته کردن ویرایشگر را بر عهدهی مثلا یک دکمهی روی صفحه بگذارید، این خصوصیت به شما کمک میکند:$('#edit-button').click(function(e) { e.stopPropagation(); $('#favsite').editable('toggle'); }); |
type | نوع
ویرایشی را که قرار است انجام گیرد، مشخص میکند. text برای متن، date برای
تاریخ، textarea جهت متون طولانیتر نسبت به text و بسیاری از موارد دیگر |
unsavedclass | این
کلاس موقعی اعمال میگردد که اطلاعاتی را ویرایش کردهاید، ولی اطلاعاتی
به سمت سرور ارسال نشده است. مثلا pk مقداردهی نشده یا send=never قرار
داید و یا اینکه به صورت محلی ذخیره میکنید و میخواهید در آخر همهی اطلاعات را
ارسال کنید. این خاصیت به طور پیش فرض با کلاس editable-unsaved مقداردهی شده که میتوانید با نال کردن، از شرش خلاص شوید. |
url | این
خاصیت با آدرس سمت سرور پر میشود. ولی میتوان به آن یک تابع هم پاس کرد که
این تابع جایگزین درخواست ایجکسی خودش خواهد شد و برای بازگشت دادن نتیجهی این درخواست به سمت تابعهای callback خودش میتوانید یک deferred object را برگشت دهید: url: function(params) { var d = new $.Deferred; if(params.value === 'abc') { //returning error via deferred object return d.reject('error message'); } else { //async saving data in js model someModel.asyncSaveMethod({ ..., success: function(){ d.resolve(); } }); return d.promise(); } } |
validate | مقدار
پیش فرض آن نال است و میتوان به آن یک تابع را جهت اعتبارسنجی سمت کلاینت پاس
داد. به عنوان آرگومان، مقدار جدیدی را ارسال کرده و در آن به اعتبارسنجی
میپردازید. در صورتی که مقدار، نامعتبر باشد، میتوانید یک پیام خطا از نوع
رشتهای را برگردانید. در صورتی که از نسخهی 1.5.1 به بعد استفاده میکنید، دریافت یک object با مقادیر زیر نیز ممکن شده است: newValue: مقدار جدید و جایگزین مقدار غیر معتبر. msg : پیام خطا. به کدهای زیر در سه حالت نگاه کنید: validate: function (value) { if ($.trim(value) == '') { //در تمامی نسخههای یک پیام متنی باز میگردد return 'This field is required'; //1.5.1 //یک مقدار جدید برگشت میدهد که بلافاصله آن را // تایید میکند و متن عنصر به روز میشود return { newValue: 'validated' }; //متن جدید ار ارسال کرده و پیام هشدار را نشان میدهد //ولی تایید نمیکند و منتظر تایید کاربر است return { newValue: 'validated', |
value | مقدار پیش فرضی که در ویرایشگر نشان میدهد و اگر مقداردهی نشود، از متن عنصر استفاده میکند. |
autotext | سه مقدار دارد auto (پیش فرض)،always و never. موقعیکه عنصر شما متنی نداشته باشد و روی auto تنظیم شده باشد، مقدار value را به عنوان متن عنصر نمایش میدهد. always کاری ندارد که عنصر شما متن دارد یا خالی است؛ مقدار value به آن انتساب داده خواهد شد. never هیچگاه. |
در قسمت بعدی که قسمت پایانی است مطالب را ادامه میدهیم.