اضافه کردن یک ستون در آوت لوک کار سادهای است. برای مثال زمانیکه inbox باز است ، بر روی قسمت نمایش ایمیلها کلیک راست کرده و مسیر زیر را طی کنید:
در اینجا فرض بر این است که از منوی اصلی view->reading pane->bottom انتخاب شده است.
Customize current view -> fields -> new field
اما مقدار دهی ردیفهای این ستون ایجاد شده کار سادهای نیست و نیاز است تا با نکته زیر آشنا بود:
<view type="table">
<viewname>Messages</viewname>
<column>
<heading>تاریخ دریافت</heading>
<prop>http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/تاریخ%20دریافت</prop>
<type>string</type>
<width>150</width>
<style>padding-left:3px;;text-align:left</style>
<editable>1</editable>
</column>
</view>
اگر علاقمند بودید که مقدار کامل این ساختار را مشاهده نمائید در تابع addNewCol ، پس از تعریف curView سطر زیر را اضافه کنید:
MessageBox.Show(curView.XML);
var image = document.createElement("img"); image.setAttribute("src", "logo.png"); React.createElement("img", { src : "logo.png" });
Virtual DOM
تفاوت در ساخت تگهای HTML به صورت مجازی بین JavaScript و React این است که React وضعیت تگهایی را که میسازد دنبال میکند. برای مثال فرض کنید نام سه محصول را در یک تگ < ul > نشان دادهایم. React وضعیت اصلی این تگ را که به مرورگر فرستاده، در حافظه دارد و همچنین در اثر تغییر منبع دادهای که برای < ul > مشخص کردهایم (که میتواند ورود اطلاعات به صورت Ajax باشد (مثلا اضافه شدن یک محصول جدید)) وضعیت جدیدی را برای تگ < ul > در حافظه ایجاد میکند. با وجود دو وضعیت برای یک تگ در حافظه، React میتواند تفاوت بین آنها را تشخیص داده و تگ را به روز کند. به این حالت عملکرد React ، اصطلاحا Virtual DOM میگویند.
React رابط کاربری را به صورت یک مدل میبیند و این مدل را با توجه به وضعیت اصلی آن در حافظه دوباره میسازد. برای React مهم نیست که ماهیت تغییر چیست. فقط وضعیتها را مثل دو عکس میبیند و میفهمد که آیا چیزی عوض شدهاست یا نه. دیالوگ React با مرورگر اینطور است: ای تگ < ul > این لیست را نشان بده (لیستی با سه محصول)، و بعد میگوید: ای تگ < ul > این لیست را نشان بده (لیستی با چهار محصول)!
کامپوننتهای React
<a href = “http://google.com”> <img src=”google.png”/> </a> // Components <clickableimage/> <linkimage/>
در کد بالا، بخش اول واضح است. عکسی که قابلیت کلیک شدن را دارد. حال فرض کنید یکی از کامپوننتهای <clickableimage/> یا <linkimage/>، همان تصویر قابل کلیک را ایجاد کنند. با نام گذاری واضح کامپوننتها، خوانایی برنامه بهتر میشود. یعنی میدانیم هر کامپوننت چه کاری را برای ما انجام میدهد. با این تصور که اگر تگهای زیاد و طولانی را در بخش رابط کاربری داریم، ارزش استفاده از کامپوننتهای React مشخص میشود.
قابلیت استفاده مجدد
در React کامپوننتها برای اساس توابع ساخته میشوند. یعنی وقتی یک کامپوننت را صدا بزنیم، در واقع یک تابع را اجرا میکنیم. در نتیجه کامپوننتها رفتار توابع را دارند؛ ورودی میگیرند و خروجی که یک DOM مجازی است را تحویل میدهند. اگر تابعی که مسئول ساخت کامپوننت است وابستگی به توابع یا متغیرهای بیرونی نداشته باشد، میتواند در جای دیگری از برنامه یا برنامهای دیگر مجددا استفاده شود. کد زیر نشان میدهد که چطور کامپوننتهای React ساخته میشوند.var ClickableImage = function(props) { return ( <a href={props.href}> <img src={props.src} /> </a> ); }; ReactDOM.render( <ClickableImage href="http://google.com" src="logo.png" />, document.getElementById("targetDivId"));
- polyfills.js : برای ساختن برنامههای سازگار با انواع مرورگرها میباشد. به دلیل اینکه وقتی کدها را با جدیدترین ویژگیها مینویسیم، ممکن است که همهی مرورگرها توانایی پشتیبانی از آن ویژگیها را نداشته باشند.
- scripts.js : شامل اسکریپتهایی میباشد که در بخش scripts، در فایل angular.json تعریف کردهایم.
- webpack loader : runtime.js میباشد. این فایل شامل webpack utilitiesهایی میباشد که برای بارگذاری دیگر فایلها مورد نیاز است.
- styles.css : شامل style هایی است که در بخش styles، در فایل angular.json تعریف کردهایم.
- main.js : شامل تمامی کدها از قبیل کامپوننتها ( کدهای مربوط به css ، html ، ts) ، دایرکتیوها، pipes و سرویسها و ماژولهای ایمپورت شده از جمله third partyهای میباشد.
npm install --save-dev webpack-bundle-analyzer
"bundle-report": "ng build --prod --stats-json && webpack-bundle-analyzer dist/stats.json"
"bundle-report": "ng build --prod --stats-json && webpack-bundle-analyzer dist/YourApplicationName/stats.json"
npm run bundle-report
- در این حالت مرورگر منتظر میماند تا فونت دانلود شود و آن را parse کند و تنها بعد از آن متن را بر روی صفحه نمایش میدهد. متن روی صفحه تا زمانیکه فونت دانلود و parse نشده باشد، قابل مشاهده نیست؛ این FOIT است (Flash of invisible text) .
- مرورگر در ابتدا متن را با استفاده از فونت معمول نمایش میدهد و بعد از آن سعی میکند که ساختارهای فونت خارجی را دریافت کند. وقتی که دانلود انجام شد و سپس آن را parse کرد، فونت سفارشی دانلود شده، با فونت معمول جایگزین خواهد شد؛ این FOUT است ( Flash of unstyled text ).
چرا از آنگولار به ری اکت + ری داکس سوئیچ کردم!
در حین توسعه نکات زیادی باید مورد توجه قرار بگیرد اول اینکه ری اکت نیازمند و محتاج کتابخانههای متفرقه ای هست که باید با انتخاب خودتان استفادده شوند حال اگر در نظر بگیریم در یکی از آپدیتها ناسازگاری صورت بگیرد میتواند کل پروژه را تحت تاثیر قرار بدهد ولی در انگیولار از آنجا یک دستی کار توسط انگیولار تامین میشود کمتر این مشکلات دیده میشود ، همین الانش هم گاها مشکلاتی در این حالت رخ میدهد وای به حال اینکه توسط هیچ منبعی این یک دستی صورت نگیرد. حال تصور کنید در آپدیت عظیم یک پروژه چگونه یک مشکل کوچک میتواند کل کار را برای مدتی بر زمین بزند با این ادعا که کتابخانههای متن باز و رایگان تحت لایسنسهای مختلف داریم.
در لینکی که قرار دادید نوشته است که کامپوننتهای خود را کوچک نگه دارید یعنی اینکه توسعه دهنده میداند که اگر یک کامپوننت بخواهد بزرگ شود به چه دردسر زیادی میرسد و چه مخلوطی از کدها را خواهد داشت.
استفاده از تایپ اسکریپت برای انگیولار یک نقطه ضعف نیست بلکه یک مزیت محسوب میشود. استفاده از تایپ اسکریپ باعث میشود نگهداری کد سادهتر باشد و کدها را در قالب سادهتر و با سرعت بیشتری میتوان نوشت. هر روز نسخه جدید از مرورگها با پشتیبانی از فناوریهای جدید میآیند ولی بنا به مسائلی چون عدم پشتیبانی مرورگرها و یا قدیمی بودن مرورگر کاربر مجبور هستیم کدها را به شکل قدیمی بنویسیم و شاید این کدهای جدید باعث سرعت و کارایی بهتر باشند ولی با تایپ اسکریپت میتوان در آینده تنها یا یک ترانسپایل ساده به هر ورژن از ES تبدیل کنیم بدون اینکه نیاز به بازنویسی کد داشته باشیم که مستلزم وقت و هزینه خواهد بود. پس کدی که الان نوشته میشود در واقع کد به روز برای آینده هم محسوب میشود.
از نظر جنبه مالی همه پروژها به همین صورت هستند و ری اکت هم مستثنی نیست. همه کتابخانه هایی که متن باز هستند اگر به سود دهی نرسند و یا دیگر راضیشان نکند ان را رها میکنند. ابزرهای متن باز هم بدین صورت هستند هیچ شرکتی نمیآید پول و زمانش را صرف چیزی کند که برایش هیچ منفعتی به دنبال نداشته باشد و این قانون اول تجارت است. آیا فیس بوک همانند مایکروسافت یا گوگل نیست؟
ولی در نهایت هر دو ابزار و دیگر ابزارها هستند و تیم سازنده با توجه به نیازها باید ابزار خود را انتخاب کند.
//ViewModels public class CustomListItem { public int Id { get; set; } public string Text { get; set; } } public class ProductAddGetViewModel { public IEnumerable<CustomListItem> Categories { get; set; } public IEnumerable<CustomListItem> Groups { get; set; } } public class ProductAddViewModel { public string Name { get; set; } public bool IsActive { get; set; } public int CategoryId { get; set; } public int GroupId { get; set; } } public class ProductEditGetViewModel { public int Id { get; set; } public string Name { get; set; } public IEnumerable<CustomListItem> Categories { get; set; } public IEnumerable<CustomListItem> Groups { get; set; } } public class ProductEditViewModel { public int Id { get; set; } public string Name { get; set; } public int CategoryId { get; set; } public int GroupId { get; set; } }
// ProductsController - ApiControler // GET: api/products/views/add [HttpGet("views/add")] public async Task<IActionResult> GetAdd() { ProductAddGetViewModel model = await _productService.GetAddModelAsync(); return Ok(model) } // POST: api/products [HttpPost] public async Task<IActionResult> Add(ProductAddViewModel model) { ... } // GET: api/products/5/views/edit [HttpGet("{id}/views/edit")] public async Task<IActionResult> GetEdit(int id) { ProductEditGetViewModel model = await _productService.GetEditModelAsync(id); return Ok(model) } // PUT: api/products/5 [HttpPut("{id}")] public async Task<IActionResult> Edit(int id, ProductEditViewModel model) { ... }
Install-Package Breeze.WebApi2.EF6
var instance = breeze.config.initializeAdapterInstance("ajax", "angular"); instance.setHttp($http);
Install-Package Breeze.Angular
var manager = new breeze.EntityManager({ dataService: dataService, metadataStore: metadataStore, saveOptions: new breeze.SaveOptions({ allowConcurrentSaves: true, tag: [{}] }) });
var dataService = new breeze.DataService({ serviceName: "/breeze/"+ "Automobile", hasServerMetadata: false, namingConvention: breeze.NamingConvention.camelCase }); var metadataStore = new breeze.MetadataStore({});
var myMetadataStore = new breeze.MetadataStore(); myMetadataStore.addEntityType({...});
var customer = function () { this.City = ""; }; myMetadataStore.registerEntityTypeCtor("Customer", customer);
[BreezeController] public class AutomobileController : ApiController { readonly EFContextProvider<ApplicationDbContext> _contextProvider = new EFContextProvider<ApplicationDbContext>(); [HttpGet] public string Metadata() { return _contextProvider.Metadata(); } [HttpGet] public IQueryable<Customer> Customers() { return _contextProvider.Context.Customers; } [System.Web.Http.HttpPost] public SaveResult SaveChanges(JObject saveBundle) { _contextProvider.BeforeSaveEntitiesDelegate = BeforeSaveEntities; _contextProvider.AfterSaveEntitiesDelegate = afterSaveEntities; return _contextProvider.SaveChanges(saveBundle); } protected Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) { } private void afterSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap, List<KeyMapping> keyMappings) { } }
manger.saveChanges().then(function success() { }, function failer(e) { });
manger.rejectChanges()
کوئری:بعد از تعریف Entity Manger میتوانیم کوئری خود را اجرا نماییم. کوئری ما شامل گرفتن اطلاعات از جدول Customer، با مرتب سازی بر روی فیلد آیدی میباشد و با اجرا کردن کوئری میتوانیم موفقیت یا عدم موفقیت آنرا بررسی نماییم.
var query = breeze.EntityQuery .from("Customer") .orderBy("Id"); var result= manager.executeQuery(query); result.then(querySucceeded) .fail(queryFailed); query = query.where("Id", "==", 1)
var predicate = new breeze.Predicate("Id", "==", false); query = query.where(predicate) var p1 = new breeze.Predicate("IsArchived", "==", false); var p2 = breeze.Predicate("IsDone", "==", false); var predicate = p1.and(p2); query = query.where(predicate).orderBy("Id")
?$filter=IsArchived eq false&IsDone eq false &$orderby=Id
اعتبارسنجی :اعتبارسنجی در breeze، هم در سمت کلاینت و هم در سمت سرور امکان پذیر میباشد که در مثالی، در قسمت بعدی، validator سفارشی خودمان را خواهیم ساخت و به entity مورد نظر اعمال خواهیم کرد.
breeze.Validator.required({ allowEmptyStrings: true });
ردیابی تغییرات: هر آیتم Entity دارای EntityAspect است که وضعیت آنرا مشخص میکند و میتواند یکی از وضعیتهای Added،Modified،Deleted،Detached،Unchanged باشد. با مشخص کردن حالت هر آیتم، با فراخوانی SaveChanges تغییرات بر روی دیتابیس اعمال میگردد.
manager.createEntity('Customer', jsonValue);
manager.createEntity("Customer", jsonValue, breeze.EntityState.Modified, breeze.MergeStrategy.OverwriteChanges)
manager.createEntity("Customer", item, breeze.EntityState.Deleted)
برای اشنایی بیشتر با امکانات Breeze، قصد داریم یک سایت ایجاد آگهی را راه اندازی کنیم. پیش نیازهای ضروری این بخش typescript ،angularjs ،requirejs هستند. قصد داریم سایتی را برای آگهیهای خرید و فروش خودرو، مشابه با سایت باما ایجاد نماییم:
امکانات این سایت:
Install-Package angularjs Install-Package angularjs.TypeScript.DefinitelyTyped Install-Package bootstrap Install-Package bootstrap.TypeScript.DefinitelyTyped Install-Package jQuery Install-Package jquery.TypeScript.DefinitelyTyped Install-Package RequireJS Install-Package requirejs.TypeScript.DefinitelyTyped bower install angularAMD
مدلهای برنامه:
public class BaseEntity { public int Id { get; set; } public bool Status { get; set; } public DateTime CreatedDateTime { get; set; } }
public class Ad : BaseEntity { public string Title { get; set; } public float Price { get; set; } public double Rating { get; set; } public int? RatingNumber { get; set; } public string UserId { get; set; } public DateTime ModifieDateTime { get; set; } public string Description { get; set; } public virtual ICollection<Comment> Comments { get; set; } public virtual IdentityUser User { get; set; } public virtual ICollection<AdLabel> Labels { get; set; } public virtual ICollection<AdMedia> Medias { get; set; } }
public class Label { public int Id { get; set; } public string Title { get; set; } public int? ParentId { get; set; } public virtual Label Parent { get; set; } public virtual ICollection<Label> Items { get; set; } }
public class Media { public int Id { get; set; } public string Name { get; set; } public string MimeType { get; set; } }
public class AdLabel { public int Id { get; set; } public virtual Ad Ad { get; set; } public virtual Label Label { get; set; } [Index("IX_AdLabel", 1, IsUnique = true)] public int AdId { get; set; } [Index("IX_AdLabel", 2, IsUnique = true)] public int LabelId { get; set; } public string Value { get; set; } }
public class AdMedia { public int Id { get; set; } public virtual Ad Ad { get; set; } public virtual Media Media { get; set; } [Index("IX_AdMedia", 1, IsUnique = true)] public int AdId { get; set; } [Index("IX_AdMedia", 2, IsUnique = true)] public int MediaId { get; set; } }
public class Comment : BaseEntity { public string Body { get; set; } public double Rating { get; set; } public int? RatingNumber { get; set; } public string EntityName { get; set; } public string UserId { get; set; } public int? ParentId { get; set; } public int? AdId { get; set; } public virtual Comment Parent { get; set; } public virtual Ad Ad { get; set; } public virtual ICollection<Comment> Items { get; set; } public virtual IdentityUser User { get; set; } }
public class Customer:BaseEntity { public string UserId { get; set; } public virtual string DisplayName { get; set; } public virtual string BirthDay { get; set; } public string City { get; set; } public string Address { get; set; } public int? MediaId { get; set; } public bool? NewsLetterSubscription { get; set; } public string PhoneNumber { get; set; } public virtual IdentityUser User { get; set; } public virtual Media Media { get; set; } }
public class Rating { public int Id { get; set; } public string UserId { get; set; } public Double Rate { get; set; } public string EntityName { get; set; } public int DestinationId { get; set; } }
اضافه کردن مدلهای برنامه به ApplicationDbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { } public DbSet<Ad> Ads { get; set; } public DbSet<AdLabel> AdLabels { get; set; } public DbSet<AdMedia> AdMedias { get; set; } public DbSet<Comment> Comments { get; set; } public DbSet<Label> Labels { get; set; } public DbSet<Media> Medias { get; set; } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } }
لود کردن فایل main.js در فایل layout.cshtml ترجیحا در انتهای body
<script src="~/Scripts/require.js" data-main="/app/main"></script>
ایجاد فایل main.ts
requirejs.config({ paths: { "app": "app", "angularAmd":"/Scripts/angularAmd", "angular": "/Scripts/angular", "bootstrap": "/Scripts/bootstrap", "angularRoute": "/Scripts/angular-route", "jquery": "/Scripts/jquery-2.2.2", }, waitSeconds: 0, shim: { "angular": { exports: "angular" }, "angularRoute": { deps: ["angular"] }, "bootstrap": { deps: ["jquery"] }, "app": { deps: ["bootstrap","angularRoute"] } } }); require(["app"]);
ایجاد فایل app.ts: کارهایی که در فایل app انجام دادهایم:
<body ng-controller="SecurityCtrl"> ... </body>
"use strict"; module AdApps { class SecurityCtrl { private $scope: Interfaces.IAdvertismentScope; constructor($scope: Interfaces.IAdvertismentScope) { // security check this.$scope = $scope; } } define(["angularAmd", "angular"], (angularAmd, ng) => { angularAmd = angularAmd.__proto__; var app = ng.module("AngularTypeScript", ['ngRoute']); var viewPath = "app/views/"; var controllerPath = "app/controller/"; app.config(['$routeProvider', $routeProvider => { $routeProvider .when("/", angularAmd.route({ templateUrl: viewPath + "home.html", controllerUrl: controllerPath + "home .js" })) .otherwise({ redirectTo: '/' }); } ]); app.controller('SecurityCtrl', ['$scope', SecurityCtrl]); return angularAmd.bootstrap(app); })}
حال مواقعی پیش میآید که نیاز داریم پیغام هایی با گرافیک و عبارات متفاوت نمایش دهیم . برای رفع این نیاز میتوانیم از پلاگین jQuery Impromptu استفاده کنیم . البته این پلاگین قابلیتهای دیگری هم دارد که در این مقاله با آنها آشنا میشویم .
از ویژگیهای این پلاگین میتوان حجم کم (حدود 11 کیلوبایت) و قدرت شخصی سازی بالا اشاره کرد .
طرز استفاده به این شکل است :
$.prompt( msg , options )
msg میتواند یک string یا یک شئ از states باشد . string ارسال شده میتواند شامل کدهای html باشد .
یک شئ states هم شامل مجموعه ای از وضعیتهای prompt است . برای مثال میتوان یک prompt ایجاد کرد که مثل یک Wizard شامل چند مرحله باشد .
options هم تنظیماتی است که میتوان مشخص کرد . تنظیماتی مثل : prefix,classes,persistent,timeout,...
msg :
گفتیم شئ states شامل وضعیتهای مختلف prompt است . هر وضعیت ( state ) میتواند شامل بخشهای زیر باشد :
- html : مقدار Html وضعیت
- buttons : یک شئ شامل متن و مقدار دکمه هایی که کاربر میتواند کلیک کند
- focus : ایندکس دکمهی focus شده در وضعیت
- submit : تابعی که زمانی که یکی از دکمههای وضعیت انتخاب شود فراخوانی میشود .
اگر در این تابع false بازگشت داده شود یا متد preventDefault از event فراخوانی شود ، prompt باز میماند . ( روشی برای جلوگیری از بسته شدن prompt هنگام تغییر state یا اعتبار سنجی فرم )
همچنین شئ event شامل state ( المنت state ) و stateName ( نام state ) میباشد .
پیشفرض :
function(event, value, message, formVals){}
- position : مشخص کنندهی موقعیت state که شامل موارد زیر است :
position: { container: '#container', x: 0, y: 0, width: 0, arrow: 'lm' }
container : selector المنتی است که state باید در آن مکان قرار بگیرد .
x/y : موقعیت نسبی prompt نسبت به container
arrow : جهت نمایش فلش prompt است که میتواند یکی از این مقادیر باشد : tl, tc, tr, rt, tm, tb, br, bc, bl, lb, lm, lt.
var tourSubmitFunc = function (e, v, m, f) { if (v === -1) { $.prompt.prevState(); return false; } else if (v === 1) { $.prompt.nextState(); return false; } }; var states = { state0: { html: "State1", buttons: { Next: 1 }, //position: { container: '#container', x: 10, y: 0, width: 350, arrow: 'lm' }, submit: tourSubmitFunc }, state1: { html: "State2", buttons: { Prev: -1, Next: 1 }, submit: tourSubmitFunc }, state2: { html: "State3", buttons: { Prev: -1, Done: 0 }, submit: tourSubmitFunc } }; $.prompt(states);
تا به اینجا با پارامتر اول prompt آشنا شدیم و فهمیدیم که میتوانیم یک رشته یا یک شئ states به عنوان message به prompt ارسال کنیم .
options :
اکنون با optionهای prompt ( پارامتر دوم ) آشنا خواهیم شد .
توجه کنید که زمانی که یک رشته به prompt ارسال کنید ، مقادیر buttons,focus,submit از این تنظیمات دریافت میشود .
به عبارت دیگر ، زمانی که یک شئ states به prompt ارسال کنید ، از مقادیر فوق که در تنظیمات است ، استفاده نمیشود .
- loaded
یک تابع که زمانی که prompt کامل بارگزاری شده فراخوانی میشود .
$.prompt("Message", { loaded: function() { alert("Prompt Loaded !"); } });
- submit
یک تابع که زمانی که یکی از دکمههای state کلیک شود ، فراخوانی میشود .
( زمانی اتفاق میوفتد که یک رشته به عنوان متن به prompt ارسال کرده باشید و زمانی که یک شئ از states ارسال میکنید ، هنگام کلیک دکمههای آنها ، این تابع فراخوانی نمیشود . )
پیشفرض :
function(event){}
- statechanging
یک تابع که زمانی که یک state در حال تعویض شدن هست فراخوانی میشود .
پیشفرض :
function(event, fromStateName, toStateName){}
- statechanged
یک تابع که زمانی که یک state در حال تعویض شدن هست فراخوانی میشود .
پیشفرض :
function(event, toStateName){}
- callback
یک تابع که زمانی که ( یکی از دکمههای prompt کلیک شود و ) prompt بسته شود ، فراخوانی میشود .
پیشفرض :
function(event[, value, message, formVals]){}
- buttons
یک شئ شامل مجموعه ای از دکمهها .
پیشفرض :
{ Ok : true }
[ {title: 'Hello World',value:true}, {title: 'Good Bye',value:false} ]
- prefix
یک پیشوند برای همه css classها و idهای المنتهای html که توسط prompt ایجاد میشود .
پیشفرض : jqi
- classes
یک css class که به بالاترین سطح prompt داده میشود .
در حالت پیشفرض مقداری ندارد .
- focus
ایندکس دکمهی focus شده
پیشفرض : 0
- zIndex
zIndex اعمال شده بروی prompt .
پیشفرض : 999
- useiframe
استفاده از یک iframe برای overlay در IE6
پیشفرض : false
- top
فاصلهی prompt از بالای صفحه
پیشفرض : 15%
- opacity
میزان شفافیت لایهی ای که صفحه را پوشانده است .
پیشفرض : 0.6
- overlayspeed
سرعت نمایش افکت fadeIn , fadeOut لایهی پوشاننده .
مقادیر قابل قبول : "slow", "fast", number(milliseconds)
پیشفرض : "slow"
- promptspeed
سرعت نمایش prompt .
مقادیر قابل قبول : "slow", "fast", number(milliseconds)
پیشفرض : "fast"
- show
نام یک متد jQuery برای animate کردن نمایش prompt .
مقادیر قابل قبول : "show","fadeIn","slideDown", ...
پیشفرض : "promptDropIn"
- persistent
بسته شدن prompt زمانی که بروی لایهی fade کلیک شود .
false : بسته شدن
پیشفرض : true
- timeout
مدت زمانی که پس از آن ، prompt بصورت خودکار بسته میشود . ( milliseconds )
پیشفرض : 0
returns :
مقدار بازگشتی متد prompt ، یک شئ jQuery ، شامل همهی محتویات تولید شده توسط prompt است .
Events using Bind :
- promptloaded
معادل loaded در optionها .
- promptsubmit
هنگام submit شدن ( کلیک شدن یکی از دکمههای ) state فعال میشود .
- promptclose
معادل callback در optionها .
- promptstatechanging
معادل statechanging در optionها .
- promptstatechanged
معادل statechanged در optionها .
ظرز بایند کردن یک event به شئ prompt :
var myPrompt = $.prompt( msg , options ); myPrompt.bind('promptloaded', function(e){});
- jQuery.prompt.setDefaults(options)
تعیین مقادیر پیشفرض برای همهی promptها .
jQuery.prompt.setDefaults({ prefix: 'myPrompt', show: 'slideDown' });
- jQuery.prompt.setStateDefaults(options)
تعیین مقادیر پیشفرض برای stateها .
jQuery.prompt.setStateDefaults({ buttons: { Ok:true, Cancel:false }, focus: 1 });
- jQuery.prompt.getCurrentState()
یک شئ jQuery از state جاری برمیگرداند .
- jQuery.prompt.getCurrentStateName()
نام state جاری را برمیگرداند .
- jQuery.prompt.getStateContent(stateName)
یک شئ jQuery از state مشخص شده برمیگرداند .
- jQuery.prompt.goToState(stateName, callback)
state مشخص شده را در prompt نمایش میدهد .
callback تابعی است که بعد از تغییر state فراخوانی میشود .
- jQuery.prompt.nextState(callback)
prompt را به state بعدی منتقل میکند .
- jQuery.prompt.prevState(callback)
prompt را به state قبلی منتقل میکند .
- jQuery.prompt.close()
prompt را میبندد .
حال که با این پلاگین آشنا شدیم ، سه دستور جاوا اسکریپتی که در ابتدای مقاله ذکر کردیم را با این پلاگین پیاده سازی میکنیم .
- alert
$.prompt("یک پیام تستی", { prefix: 'dnt', buttons: { 'تایید': true } });
نتیجه :
- confirm
$.prompt("درخواست تایید - موافقید ؟", { prefix: 'dnt', buttons: { 'تایید': true, 'انصراف': false } });
نتیجه :
- prompt
یک فرم html مخفی برای نمایش در prompt :
<div class="prompt-content" style="display: none;"> <span>نام خود را وارد نمایید : </span> <span> <input type="text" name="name" /> </span> </div>
نمایش prompt :
$.prompt( $(".prompt-content").html(), { prefix: 'dnt', buttons: { 'تایید': true, 'انصراف': false } });
نتیجه :
در این سه مثال آخر ، از یک css متفاوت استفاده کردیم . این پلاگین یک سری کلاس دارد که نام این کلاسها از ترکیب مقدار prefix که در option مشخص کردیم حاصل میشود .
div.dnt .dntmessage { color: #444444; line-height: 20px; padding: 10px; /* Edited */ direction:rtl; text-align:right; }
البته راه بهتری هم هست که نیاز به آشنایی با فایرباگ دارد . در این روش ابتدا کل قالب jqi ( موجود در قالب پیشفرض ) را در برنامه خود کپی میکنیم ، مقادیر jqi را با نام قالب جایگزین میکنیم ، مقدار prefix را در prompt برابر با نام قالب قرار میهیم .
اکنون در FireFox یک prompt ایجاد میکنیم و توسط فایرباگ استایل هایی که با نام قالب بروی prompt اعمال شدهاند را مطابق سلیقه تغییر میدهیم . در مرحله آخر به تب CSS در فایرباگ میرویم و کل استایلهای مربوط به قالب را کپی و جایگزین استایل قبلی در برنامه میکنیم .
/* Start : DotNetTips Theme */ .dntfade { background-color: #AAAAAA; position: absolute; } div.dnt { background-color: #FFFFFF; border-radius: 10px 10px 10px 10px; border: 1px solid #FFFFFF; box-shadow: 0px 0px 10px 1px #6D6D6C; font-family: tahoma; font-size: 11px; padding: 7px; position: absolute; text-align: left; width: 400px; } div.dnt .dntcontainer { font-size: small; } div.dnt .dntclose { color: #BBBBBB; cursor: pointer; font-weight: bold; position: absolute; top: 4px; width: 18px; } div.dnt .dntmessage { color: #444444; line-height: 20px; padding: 10px; } div.dnt .dntbuttons { background-color: #F4F4F4; border: 1px solid #EEEEEE; padding: 5px 0px; text-align: right; } div.dnt button { background-color: #2F6073; border: 1px solid #F4F4F4; color: #FFFFFF; font-size: 12px; font-weight: bold; margin: 0px 10px; padding: 3px 10px; } div.dnt button:hover { background-color: #728A8C; } div.dnt button.dntdefaultbutton { background-color: #0099CC; } .dnt_state { direction: rtl; text-align: right; } .dnt_state button { font-family: tahoma; } .dntwarning .dnt .dntbuttons { background-color: #CCDDFF; } .dnt .dntarrow { border: 10px solid transparent; font-size: 0px; height: 0px; line-height: 0; position: absolute; width: 0px; } .dnt .dntarrowtl { border-bottom-color: #FFFFFF; left: 10px; top: -20px; } .dnt .dntarrowtc { border-bottom-color: #FFFFFF; left: 50%; margin-left: -10px; top: -20px; } .dnt .dntarrowtr { border-bottom-color: #FFFFFF; right: 10px; top: -20px; } .dnt .dntarrowbl { border-top-color: #FFFFFF; bottom: -20px; left: 10px; } .dnt .dntarrowbc { border-top-color: #FFFFFF; bottom: -20px; left: 50%; margin-left: -10px; } .dnt .dntarrowbr { border-top-color: #FFFFFF; bottom: -20px; right: 10px; } .dnt .dntarrowlt { border-right-color: #FFFFFF; left: -20px; top: 10px; } .dnt .dntarrowlm { border-right-color: #FFFFFF; left: -20px; margin-top: -10px; top: 50%; } .dnt .dntarrowlb { border-right-color: #FFFFFF; bottom: 10px; left: -20px; } .dnt .dntarrowrt { border-left-color: #FFFFFF; right: -20px; top: 10px; } .dnt .dntarrowrm { border-left-color: #FFFFFF; margin-top: -10px; right: -20px; top: 50%; } .dnt .dntarrowrb { border-left-color: #FFFFFF; bottom: 10px; right: -20px; } /* End : DotNetTips Theme */