استفاده از منابع داده محلی
در ادامه مثالی را از نحوهی استفاده از یک منبع داده محلی جاوا اسکریپتی، مشاهده میکنید:
<script type="text/javascript"> $(function () { var cars = [ { "Year": 2000, "Make": "Hyundai", "Model": "Elantra" }, { "Year": 2001, "Make": "Hyundai", "Model": "Sonata" }, { "Year": 2002, "Make": "Toyota", "Model": "Corolla" }, { "Year": 2003, "Make": "Toyota", "Model": "Yaris" }, { "Year": 2004, "Make": "Honda", "Model": "CRV" }, { "Year": 2005, "Make": "Honda", "Model": "Accord" }, { "Year": 2000, "Make": "Honda", "Model": "Accord" }, { "Year": 2002, "Make": "Kia", "Model": "Sedona" }, { "Year": 2004, "Make": "Fiat", "Model": "One" }, { "Year": 2005, "Make": "BMW", "Model": "M3" }, { "Year": 2008, "Make": "BMW", "Model": "X5" } ]; var carsDataSource = new kendo.data.DataSource({ data: cars }); carsDataSource.read(); alert(carsDataSource.total()); }); </script>
ذکر new kendo.data.DataSource به تنهایی به معنای مقدار دهی اولیه است و در این حالت منبع داده مورد نظر، استفاده نخواهد شد. برای مثال اگر متد total آنرا جهت یافتن تعداد عناصر موجود در آن فراخوانی کنید، صفر را بازگشت میدهد. برای شروع به کار با آن، نیاز است ابتدا متد read را بر روی این منبع داده مقدار دهی شده، فراخوانی کرد.
استفاده از منابع داده راه دور
در برنامههای کاربردی، عموما نیاز است تا منبع داده را از یک وب سرور تامین کرد. در اینجا نحوهی خواندن اطلاعات JSON بازگشت داده شده از جستجوی توئیتر را مشاهده میکنید:
<script type="text/javascript"> $(function () { var twitterDataSource = new kendo.data.DataSource({ transport: { read: { url: "http://search.twitter.com/search.json", dataType: "jsonp", contentType: 'application/json; charset=utf-8', type: 'GET', data: { q: "#kendoui" } }, schema: { data: "results" } }, error: function (e) { alert(e.errorThrown.stack); } }); }); </script>
در قسمت schema مشخص میکنیم که اطلاعات JSON بازگشت داده شده توسط توئیتر، در فیلد results آن قرار دارد.
کار با منابع داده OData
علاوه بر فرمتهای یاد شده، Kendo UI DataSource امکان کار با اطلاعاتی از نوع OData را نیز دارا است که تنظیمات ابتدایی آن به صورت ذیل است:
<script type="text/javascript"> var moviesDataSource = new kendo.data.DataSource({ type: "odata", transport: { read: "http://demos.kendoui.com/service/Northwind.svc/Orders" }, error: function (e) { alert(e.errorThrown.stack); } }); }); </script>
یک مثال: دریافت اطلاعات از ASP.NET Web API
یک پروژهی جدید ASP.NET را آغاز کنید. تفاوتی نمیکند که Web forms باشد یا MVC؛ از این جهت که مباحث Web API در هر دو یکسان است.
سپس یک کنترلر جدید Web API را به نام ProductsController با محتوای زیر ایجاد کنید:
using System.Collections.Generic; using System.Web.Http; namespace KendoUI02 { public class Product { public int Id { set; get; } public string Name { set; get; } } public class ProductsController : ApiController { public IEnumerable<Product> Get() { var products = new List<Product>(); for (var i = 1; i <= 100; i++) { products.Add(new Product { Id = i, Name = "Product " + i }); } return products; } } }
در ادامه نیاز است تعریف مسیریابی ذیل نیز به فایل Global.asax.cs برنامه اضافه شود تا بتوان به آدرس api/products در سایت، دسترسی یافت:
using System; using System.Web.Http; using System.Web.Routing; namespace KendoUI02 { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }
در ادامه فایلی را به نام Index.html (یا در یک View و یا یک فایل aspx دلخواه)، محتوای ذیل را اضافه کنید:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title>Kendo UI: Implemeting the Grid</title> <link href="styles/kendo.common.min.css" rel="stylesheet" type="text/css" /> <link href="styles/kendo.default.min.css" rel="stylesheet" type="text/css" /> <script src="js/jquery.min.js" type="text/javascript"></script> <script src="js/kendo.all.min.js" type="text/javascript"></script> </head> <body> <div id="report-grid"></div> <script type="text/javascript"> $(function () { var productsDataSource = new kendo.data.DataSource({ transport: { read: { url: "api/products", dataType: "json", contentType: 'application/json; charset=utf-8', type: 'GET' } }, error: function (e) { alert(e.errorThrown.stack); }, pageSize: 5, sort: { field: "Id", dir: "desc" } }); $("#report-grid").kendoGrid({ dataSource: productsDataSource, autoBind: true, scrollable: false, pageable: true, sortable: true, columns: [ { field: "Id", title: "#" }, { field: "Name", title: "Product" } ] }); }); </script> </body> </html>
- گرید صفحه، در محل div ایی با id مساوی report-grid تشکیل خواهد شد.
- سپس DataSource ایی که به آدرس api/products اشاره میکند، تعریف شده و در آخر productsDataSource را توسط یک kendoGrid نمایش دادهایم.
- نحوهی تعریف productsDataSource، در قسمت استفاده از منابع داده راه دور ابتدای بحث توضیح داده شد. در اینجا فقط دو خاصیت pageSize و sort نیز به آن اضافه شدهاند. این دو خاصیت بر روی نحوهی نمایش گرید نهایی تاثیر گذار هستند. pageSize تعداد رکورد هر صفحه را مشخص میکند و sort نحوهی مرتب سازی را بر اساس فیلد Id و در حالت نزولی قرار میدهد.
- در ادامه، ابتداییترین حالت کار با kendoGrid را ملاحظه میکنید.
- تنظیم dataSource و autoBind: true (حالت پیش فرض)، سبب خواهند شد تا به صورت خودکار، اطلاعات JSON از مسیر api/products خوانده شوند.
- سه خاصیت بعدی صفحه بندی و مرتب سازی خودکار ستونها را فعال میکنند.
- در آخر هم دو ستون گرید، بر اساس نامهای خواص کلاس Product تعریف شدهاند.
سورس کامل این قسمت را از اینجا میتوانید دریافت کنید:
KendoUI02.zip
معرفی Kendo UI
Kendo UI یک فریم ورک جاوا اسکریپتی ساخت برنامههای مدرن و تعاملی وب است و برای رسیدن به این مقصود، از JavaScript، CSS 3، HTML 5 و jQuery کمک میگیرد.
امکانات فراهم شده توسط Kendo UI
1) انواع و اقسام ویجتها: کنترلهای وب تهیه شده برفراز jQuery
ویجتهای آن در سه گروه کلی قرار میگیرند:
- گروه وب، مانند گرید، tree-view و غیره.
- گروه DataViz که جهت نمایش بصری اطلاعات و ترسیم انواع و اقسام نمودارها کاربرد دارد.
- گروه موبایل که با استفاده از فناوری adaptive rendering، در سیستم عاملهای مختلف موبایل، مانند اندروید و آی او اس، ظاهری بومی و هماهنگ با آنها را ارائه میدهد.
2) منبع داده سمت کاربر (Client side data source)
منبع داده سمت کاربر Kendo UI، از انواع و اقسام منابع داده محلی مانند آرایههای جاوا اسکریپتی تا منابع داده راه دور، مانند JSON، XML و JSONP، جهت نمایش اطلاعات و data binding پشتیبانی میکند. این منبع داده، مواردی مانند صفحه بندی، مرتب سازی اطلاعات و گروه بندی آنها را نیز فراهم میکند. به علاوه با عملیات ثبت، ویرایش و حذف اطلاعات نیز هماهنگی کاملی را دارد.
3) به همراه یک فریم ورک MVVM توکار است
این فریم ورک MVVM مواردی مانند two way data binding و همچنین declarative binding را نیز پشتیبانی میکند.
4) امکان تعویض قالب
5) پویا نمایی، کشیدن و رها کردن
6) فریم ورک اعتبارسنجی
چرا Kendo UI؟
- مهمترین مزیت کار با Kendo UI، فراهم آوردن تمام نیازهای توسعهی یک برنامهی مدرن وب، تنها در یک بسته است. به این ترتیب دیگر نیازی نیست تا گرید را از یکجا، tree-view را از جایی دیگر و کتابخانههای رسم نمودار را از منبعی ناهمگون با سایر عناصر برنامه دریافت و استفاده کنید؛ در اینجا تمام اینها در قالب یک بستهی آماده برای شما فراهم شدهاست و همچنین با یکدیگر سازگاری کاملی دارند.
- تمام ویجتهای آن برای نمایش سریع با کارآیی بالا طراحی شدهاند.
- پشتیبانی خوب آن. این فریم ورک محصول شرکتی است که به صورت تخصصی کار تهیه کامپوننتهای وب و دسکتاپ را انجام میدهد.
مرورگرهای پشتیبانی شده
یکی دیگر از مزایای مهم کار با Kendo UI پشتیبانی گستردهی آن از اکثر مرورگرهای موجود است. این فریم ورک با مرورگرهای زیر سازگار است:
- IE 7 به بعد
- فایرفاکس 10 به بعد
- تمام نگارشهای کروم
- اپرا 10 به بعد
- سفاری 4 به بعد
مجوز استفاده از Kendo UI
Kendo UI با سه مجوز ذیل ارائه میشود:
- 30 روزه آزمایشی رایگان
- تجاری
- سورس باز با مجوز Apache
پیشتر نسخهی تجاری آن تحت مجوز GPL نیز در دسترس بود. اما اخیرا مجوز GPL آن حذف شده و به Apache تغییر یافته است. اما باید در نظر داشت که نسخهی سورس باز آن شامل کنترلهای مهمی مانند «گرید» نیست و این موارد تنها در نسخهی تجاری آن لحاظ شدهاند.
مثالهای Kendo UI
پس از دریافت بستهی کامل آن، پوشههایی مانند js، styles و امثال آن قابل مشاهده هستند؛ به همراه پوشهی examples آن که حداقل 86 پوشهی دیگر در آن جهت ارائه مثالهایی از نحوهی کاربرد المانهای مختلف آن تدارک دیده شدهاند.
نحوهی افزودن Kendo UI به صفحه
از آنجائیکه Kendo UI یک فریم ورک جاوا اسکریپتی است، همانند سایر برنامههای وب، افزودن تعاریف فایلهای js، css و تصاویر مرتبط با آن، برای شروع به کار کفایت میکند. برای این منظور ابتدا پوشههای js و styles بستهی دریافتی آنرا به برنامهی خود اضافه کنید (این پوشهها در فایل پیوست انتهای بحث موجود هستند).
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <!--KendoUI: Web--> <link href="styles/kendo.common.min.css" rel="stylesheet" type="text/css" /> <link href="styles/kendo.default.min.css" rel="stylesheet" type="text/css" /> <script src="js/jquery.min.js" type="text/javascript"></script> <script src="js/kendo.web.min.js" type="text/javascript"></script> <!--KendoUI: DataViz--> <link href="styles/kendo.dataviz.min.css" rel="stylesheet" type="text/css" /> <script src="js/kendo.dataviz.min.js" type="text/javascript"></script> <!--KendoUI: Mobile--> <link href="styles/kendo.mobile.all.min.css" rel="stylesheet" type="text/css" /> <script src="js/kendo.mobile.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { $("#pickDate").kendoDatePicker(); }); </script> </head> <body> <span> Pick a date: <input id="pickDate" type="text"/> </span> </body> </html>
دریافت سورس کامل این قسمت که حاوی فایلهای اصلی kendoui.professional.2014.2.1008 نیز میباشد:
KendoUI01.7z
Webgrid گرید توکار asp.net
mvc 3 است که در سری آموزشهای mvc جناب نصیری به خوبی بررسی شده است . WebGrid از طریق مجموعه ای از خواص امکان استایل دهی
به ستونها و ردیفها را به توسعه دهنده میدهد . اما در این بخش مشکلی وجود دارد که
در ادامه به آن خواهم پرداخت . کدهای زیر را در نظر بگیرید
مدلها :
public class Customer { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public string Website { get; set; } public string Phone { get; set; } } public class Customers { public IList<Customer> GetList() { return new List<Customer>() { new Customer() { Id=1, Name="mohsen.d", Email="email@domain.com", Website="domain.com", Phone="213214321" } }; } public IList<Customer> GetEmptyList() { return new List<Customer>(); } }
public class HomeController : Controller { public ActionResult List() { var model = new Customers().GetList(); return View(model); } public ActionResult EmptyList() { var model = new Customers().GetEmptyList(); return View("list", model); } }
تابع کمکی برای ایجاد گرید :
@helper GenerateList(IEnumerable<object> items, List<WebGridColumn> columns) { var grid = new WebGrid(items); <div> @grid.GetHtml( tableStyle: "list", headerStyle: "list-header", footerStyle: "list-footer", alternatingRowStyle: "list-alt", selectedRowStyle: "list-selected", rowStyle: "list-row", htmlAttributes: new { id = "listItems" }, mode: WebGridPagerModes.All, columns: columns ) </div> }
@model IEnumerable<WebGridHeaderStyle.Models.Customer> @{ ViewBag.Title = "List"; } <h2>List</h2> @_List.GenerateList( Model, new List<WebGridColumn>() { new WebGridColumn(){ ColumnName="Id", Header="Id", Style="list-small-field" }, new WebGridColumn(){ ColumnName="Name", Header="Name", Style="list-long-field" }, new WebGridColumn(){ ColumnName="Email", Header="Email", Style="list-mid-field" }, new WebGridColumn(){ ColumnName="Website", Header="Website", Style="list-mid-field" }, new WebGridColumn(){ ColumnName="Phone", Header="Phone", Style="list-mid-field" } } )
خوب چندان بد نیست . با استفاده از استایلهای تعریف شده برای فیلدها و ردیفها ، لیست ساختار مناسبی دارد . اما حالا به Home/EmptyList می رویم :
همانطور که میبینید استایل هایی که برای هر ستون تعریف کرده بودیم اعمال نشده اند. مشکل هم همین
جاست . WebGrid استایل تعریف شده را تنها به ستونهای درون tbody
اعمال میکند و thead از این تنظیمات بی نصیب میماند ( WebGrid از table برای ساختن لیست استفاده میکند ) و در زمانی که رکوردی وجود نداشته باشد فرمت طراحی شده اعمال نمیشود .
در وب ترفندهایی را برای این مشکل پیدا
کردم که اصلا جالب نبودند . در نهایت راه حل زیر به نظرم رسید :
در زمان ساختن
گرید ، استایلهای تعریف شده را در یک فیلد hidden ذخیره و سپس با
استفاده از jquery این استایلها را به ستونهای header اعمال میکنیم .
تابع ساختن فیلد hidden :
@helper SetHeaderColumnsStyle(IEnumerable<WebGridColumn> columns) { var styles = new List<string>(); foreach(var col in columns) { styles.Add(col.Style); } <input id="styles" type="hidden" value="@string.Join("#",styles)" /> }
@SetHeaderColumnsStyle(columns)
<script> $(document).ready(function () { var styles = $("#styles").attr("value").split('#'); var $cols = $("#listItems th"); $cols.each(function (i) { $(this).addClass(styles[i]); }); }); </script>
تعریف مدل برنامه
در همان پروژهی خالی Blazor Server که در قسمت دوم با دستور dotnet new blazorserver ایجاد کردیم، پوشهی Models را افزوده و کلاس BlazorRoom را در آن تعریف میکنیم:
namespace BlazorServerSample.Models { public class BlazorRoom { public int Id { set; get; } public string Name { set; get; } public decimal Price { set; get; } public bool IsActive { set; get; } } }
@using BlazorServerSample.Models
Data binding یک طرفه
در ادامه به فایل Pages\Index.razor مراجعه کرده و منهای سطر اول مسیریابی آن، مابقی محتوای آنرا حذف میکنیم. در اینجا میخواهیم مقادیر نمونهای از شیء BlazorRoom را نمایش دهیم. به همین جهت این شیء را در قسمت code@ فایل razor جاری (همانند نکات قسمت قبل)، ایجاد میکنیم:
@page "/" <h2 class="bg-light border p-2"> First Room </h2> Room: @Room.Name <br/> Price: @Room.Price @code { BlazorRoom Room = new BlazorRoom { Id = 1, Name = "Room 1", IsActive = true, Price = 499 }; }
به این روش نمایش اطلاعات، one-way data-binding نیز گفته میشود. اما چطور میتوان یک طرفه بودن آنرا متوجه شد؟ برای این منظور یک text-box را نیز در ذیل تعاریف فوق، به صورت زیر اضافه میکنیم که مقدارش را از Room.Price دریافت میکند:
<input type="number" value="@Room.Price" />
Data binding دو طرفه
اکنون میخواهیم اگر مقدار ورودی Room.Price توسط text-box فوق تغییر کرد، نتیجهی نهایی، به خاصیت متناظر با آن نیز اعمال شود و تغییر کند. برای این منظور فقط کافی است ویژگی value را به bind-value@ تغییر دهیم:
<input type="number" @bind-value="@Room.Price" />
البته اگر برنامه را اجرا کنیم، با تغییر مقدار text-box، بلافاصله تغییری را مشاهده نخواهیم کرد. برای اعمال تغییرات نیاز خواهد بود تا در جائی خارج از text-box کلیک و focus را به المانی دیگر منتقل کنیم. اگر میخواهیم همراه با تایپ اطلاعات درون text-box، رابط کاربری نیز به روز شود، میتوان bind-value را به یک رخداد خاص، مانند oninput متصل کرد. حالت پیشفرض آن onchange است:
<input type="number" @bind-value="@Room.Price" @bind-value:event="oninput" />
لیست کامل رخدادها را در اینجا میتوانید مشاهده کنید. برای مثال برای یک المان input، دو رخداد onchange و oninput قابل تعریف هستند.
یک نکته: در حین کار با bind-value@، نیازی نیست مقدار آن با @ شروع شود. یعنی ذکر "bind-value="Room.Price@ نیز کافی است.
تمرین 1 - خاصیت IsActive یک اتاق را به یک checkbox متصل کرده و همچنین وضعیت جاری آنرا نیز در یک برچسب نمایش دهید.
در اینجا میخواهیم مقدار خاصیت Room.IsActive را توسط یک اتصال دو طرفه، به یک checkbox متصل کنیم:
<input type="checkbox" @bind-value="Room.IsActive" /> <br/> This room is @(Room.IsActive? "Active" : "Inactive").
بار اولی که برنامه نمایش داده میشود، هر چند مقدار IsActive بر اساس مقدار دهی آن در شیء Room، مساوی true است، اما chekbox، علامت نخورده باقی میماند. برای رفع این مشکل نیاز است ویژگی checked این المان را نیز به صورت زیر مقدار دهی کرد:
<input type="checkbox" @bind-value="Room.IsActive" checked="@(Room.IsActive? "cheked" : null)" />
اتصال خواص مدلها به dropdownها
اکنون میخواهیم مدل این مثال را کمی توسعه داده و خواص تو در تویی را به آن اضافه کنیم:
using System.Collections.Generic; namespace BlazorServerSample.Models { public class BlazorRoom { // ... public List<BlazorRoomProp> RoomProps { set; get; } } public class BlazorRoomProp { public int Id { set; get; } public string Name { set; get; } public string Value { set; get; } } }
پس از این تعاریف، فیلد Room را به صورت زیر به روز رسانی میکنیم تا تعدادی از خواص اتاق را به همراه داشته باشد:
@code { BlazorRoom Room = new BlazorRoom { Id = 1, Name = "Room 1", IsActive = true, Price = 499, RoomProps = new List<BlazorRoomProp> { new BlazorRoomProp { Id = 1, Name = "Sq Ft", Value = "100" }, new BlazorRoomProp { Id = 2, Name = "Occupancy", Value = "3" } } }; }
<select @bind="SelectedRoomPropValue"> @foreach (var prop in Room.RoomProps) { <option value="@prop.Value">@prop.Name</option> } </select> <span>The value of the selected room prop is: @SelectedRoomPropValue</span> @code { string SelectedRoomPropValue = ""; // ...
در اینجا یک فیلد را در قطعه کد برنامه تعریف کرده و به المان select متصل کردهایم. هرگاه آیتمی در این دراپ داون انتخاب شود، این فیلد، مقدار آن آیتم انتخابی را خواهد داشت. در ادامه توسط یک حلقهی foreach، تمام خواص یک اتاق را دریافت کرده و به صورت optionsهای یک select استاندارد، نمایش میدهیم. در آخر نیز مقدار SelectedRoomPropValue را نمایش دادهایم که این مقدار به صورت پویا تغییر میکند:
تعریف لیستی از اتاقها
عموما در یک برنامهی واقعی، با یک تک اتاق کار نمیکنیم. به همین جهت در ادامه لیستی از اتاقها را تعریف و مقدار دهی اولیه خواهیم کرد:
@code { string SelectedRoomPropValue = ""; List<BlazorRoom> Rooms = new List<BlazorRoom>(); protected override void OnInitialized() { base.OnInitialized(); Rooms.Add(new BlazorRoom { Id = 1, Name = "Room 1", IsActive = true, Price = 499, RoomProps = new List<BlazorRoomProp> { new BlazorRoomProp { Id = 1, Name = "Sq Ft", Value = "100" }, new BlazorRoomProp { Id = 2, Name = "Occupancy", Value = "3" } } }); Rooms.Add(new BlazorRoom { Id = 2, Name = "Room 2", IsActive = true, Price = 399, RoomProps = new List<BlazorRoomProp> { new BlazorRoomProp { Id = 1, Name = "Sq Ft", Value = "250" }, new BlazorRoomProp { Id = 2, Name = "Occupancy", Value = "4" } } }); } }
نمایش لیست قابل ویرایش اتاقها
اکنون میخواهیم به عنوان تمرین 2، لیست جزئیات اتاقهای تعریف شده را نمایش دهیم؛ با این شرط که نام و قیمت هر اتاق، قابل ویرایش باشد. همچنین خواص تعریف شده نیز به صورت ستونهایی مجزا، نمایش داده شوند. برای مثال اگر دو خاصیت در اینجا تعریف شده، 2 ستون اضافهتر نیز برای نمایش آنها وجود داشته باشد. به علاوه از آنجائیکه میخواهیم اتصال دوطرفه را نیز آزمایش کنیم، نام و قیمت هر اتاق را نیز در پایین جدول، مجددا به صورت برچسبهایی نمایش خواهیم داد.
برای رسیدن به تصویر فوق میتوان به صورت زیر عمل کرد:
<div class="border p-2 mt-3"> <h2 class="text-info">Rooms List</h2> <table class="table table-dark"> @foreach(var room in Rooms) { <tr> <td> <input type="text" @bind-value="room.Name" @bind-value:event="oninput"/> </td> <td> <input type="text" @bind-value="room.Price" @bind-value:event="oninput"/> </td> @foreach (var roomProp in room.RoomProps) { <td> @roomProp.Name, @roomProp.Value </td> } </tr> } </table> @foreach(var room in Rooms) { <p>@room.Name's price is @room.Price.</p> } </div>
هدف از foreach پس از جدول، نمایش تغییرات انجام شدهی در input-boxها است. برای مثال اگر نام یک ردیف را تغییر دادیم، چون یک اتصال دو طرفه برقرار است، خاصیت متناظر با آن به روز رسانی شده و بلافاصله در برچسبهای ذیل جدول، منعکس میشود.
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: Blazor-5x-Part-04.zip
String.format = function () { var s = arguments[0]; for (var i = 0; i < arguments.length - 1; i++) { s = s.replace("{" + i + "}", arguments[i + 1]); } return s; };
String.format = function () { var s = arguments[0]; for (var arg in arguments) { var i = parseInt(arg); s = s.replace("{" + i + "}", arguments[i + 1]); } return s; };
console.log(String.format("{0} is nice!", "donettips.info"));
donettips.info is nice!
console.log(String.format("{0} is {1} nice! {0} is {1} nice!", "donettips.info", "very"));
donettips.info is very nice! {0} is {1} nice!
String.format = function () { var original = arguments[0], replaced; for (var i = 0; i < arguments.length - 1; i++) { replaced = ''; while (replaced != original) { original = replaced || original; replaced = original.replace("{" + i + "}", arguments[i + 1]); } } return replaced; };
donettips.info is very nice! donettips.info is very nice!
String.format = function () { var s = arguments[0]; for (var i = 0; i < arguments.length - 1; i++) { s = s.replace(new RegExp("\\{" + i + "\\}", "g"), arguments[i + 1]); } return s; };
String.format = function () { var s = arguments[0], i = arguments.length - 1; while (i--) { s = s.replace(new RegExp('\\{' + i + '\\}', 'g'), arguments[i + 1]); } return s; };
console.log(String.format("{0}:0 {1}:1 {2}:2", "zero", "{2}", "two"));
zero:0 {2}:1 two:2
zero:0 two:1 two:2
console.log(String.format("{0}:0 {1}:1 {2}:2", "zero", "one", "{1}"));
zero:0 one:1 one:2
zero:0 one:1 {1}:2
String.format = function () { var args = arguments; return args[0].replace(/{(\d+)}/g, function (match, number) { return args[parseInt(number) + 1]; }); };
console.log(String.format("{0} is {1} nice!", "donettips.info"));
donettips.info is undefined nice!
String.format = function () { var s = arguments[0], args = arguments; return s.replace(/{(\d+)}/g, function (match, number) { var i = parseInt(number); return typeof args[i + 1] != 'undefined' ? args[i + 1] : match; }); };
console.log(String.format("{0}:0 {1}:1 {2}:2, {{0}} {{{1}}} {{{{2}}}} {2}", "zero", "{2}", "two"));
zero:0 {2}:1 two:2, {zero} {{{2}}} {{{two}}} two
String.format = function () { var s = arguments[0], args = arguments; return s.replace(/\{\{|\}\}|\{(\d+)\}/g, function (match, number) { if (match == "{{") { return "{"; } if (match == "}}") { return "}"; } var i = parseInt(number); return typeof args[i + 1] != 'undefined' ? args[i + 1] : match; }); };
zero:0 {2}:1 two:2, {0} {{2}} {{2}} two
String.prototype.format = function () { ... }
String.prototype.format = function () { var s = this.toString(), args = arguments; return s.replace(/\{\{|\}\}|\{(\d+)\}/g, function (match, number) { if (match == "{{") { return "{"; } if (match == "}}") { return "}"; } return typeof args[number] != 'undefined' ? args[number] : match; }); };
console.log("{0}:0 {1}:1 {2}:2, {{0}} {{{1}}} {{{{2}}}} {2}".format("zero", "{2}", "two"));
String.format = function () { var s = arguments[0], args = arguments[1]; for (var arg in args) { s = s.replace(new RegExp("{" + arg + "}", "g"), args[arg]); } return s; };
String.prototype.format = function () { var s = this.toString(), args = arguments[0]; for (var arg in args) { s = s.replace(new RegExp("{" + arg + "}", "g"), args[arg]); } return s; };
console.log(String.format("{site} is {adj}! {site} is {adj}!", { site: "donettips.info", adj: "nice" })); console.log("{site} is {adj}! {site} is {adj}!".format({ site: "donettips.info", adj: "nice" }));
String.format = function String$format(format, args) { /// <summary locid="M:J#String.format" /> /// <param name="format" type="String"></param> /// <param name="args" parameterArray="true" mayBeNull="true"></param> /// <returns type="String"></returns> // var e = Function._validateParams(arguments, [ // { name: "format", type: String }, // { name: "args", mayBeNull: true, parameterArray: true } // ]); // if (e) throw e; return String._toFormattedString(false, arguments); }; String._toFormattedString = function String$_toFormattedString(useLocale, args) { var result = ''; var format = args[0]; for (var i = 0; ; ) { var open = format.indexOf('{', i); var close = format.indexOf('}', i); if ((open < 0) && (close < 0)) { result += format.slice(i); break; } if ((close > 0) && ((close < open) || (open < 0))) { if (format.charAt(close + 1) !== '}') { throw Error.argument('format', Sys.Res.stringFormatBraceMismatch); } result += format.slice(i, close + 1); i = close + 2; continue; } result += format.slice(i, open); i = open + 1; if (format.charAt(i) === '{') { result += '{'; i++; continue; } if (close < 0) throw Error.argument('format', Sys.Res.stringFormatBraceMismatch); var brace = format.substring(i, close); var colonIndex = brace.indexOf(':'); var argNumber = parseInt((colonIndex < 0) ? brace : brace.substring(0, colonIndex), 10) + 1; if (isNaN(argNumber)) throw Error.argument('format', Sys.Res.stringFormatInvalid); var argFormat = (colonIndex < 0) ? '' : brace.substring(colonIndex + 1); var arg = args[argNumber]; if (typeof (arg) === "undefined" || arg === null) { arg = ''; } if (arg.toFormattedString) { result += arg.toFormattedString(argFormat); } else if (useLocale && arg.localeFormat) { result += arg.localeFormat(argFormat); } else if (arg.format) { result += arg.format(argFormat); } else result += arg.toString(); i = close + 1; } return result; }
console.log(String.format("{0:n}, {0:c}, {0:p}, {0:d}", 100.0001)); // result: 100.00, ¤100.00, 10,000.01 %, 100.0001 console.log(String.format("{0:d}, {0:t}", new Date(2015, 1, 1, 10, 45))); // result: 02/01/2015, 10:45
var template = jQuery.validator.format("{0} is not a valid value"); console.log(template("abc")); // result: 'abc is not a valid value'
String.format([full format string], [arguments...]); // or: [date|number].format([partial format string]);
// Object path String.format("Welcome back, {username}!", { id: 3, username: "JohnDoe" }); // Result: "Welcome back, JohnDoe!" // Date/time formatting String.format("The time is now {0:t}.", new Date(2009, 5, 1, 13, 22)); // Result: "The time is now 01:22 PM." // Date/time formatting (without using a full format string) var d = new Date(); d.format("hh:mm:ss tt"); // Result: "02:28:06 PM" // Custom number format string String.format("Please call me at {0:+##0 (0) 000-00 00}.", 4601111111); // Result: "Please call me at +46 (0) 111-11 11." // Another custom number format string String.format("The last year result was {0:+$#,0.00;-$#,0.00;0}.", -5543.346); // Result: "The last year result was -$5,543.35." // Alignment String.format("|{0,10:PI=0.00}|", Math.PI); // Result: "| PI=3.14|" // Rounding String.format("1/3 ~ {0:0.00}", 1/3); // Result: "1/3 ~ 0.33" // Boolean values String.format("{0:true;;false}", 0); // Result: "false" // Explicitly specified localization // (note that you have to include the .js file for used cultures) msf.setCulture("en-US"); String.format("{0:#,0.0}", 3641.667); // Result: "3,641.7" msf.setCulture("sv-SE"); String.format("{0:#,0.0}", 3641.667); // Result: "3 641,7"
//inline arguments String.format("some string with {0} and {1} injected using argument {{number}}", 'first value', 'second value'); //returns: 'some string with first value and second value injected argument {number}' //single array String.format("some string with {0} and {1} injected using array {{number}}", [ 'first value', 'second value' ]); //returns: 'some string with first value and second value injected using array {number}' //single object String.format("some string with {first} and {second} value injected using {{propertyName}}",{first:'first value',second:'second value'}); //returns: 'some string with first value and second value injected using {propertyName}'
Public Class User { public string Id { get; set; } public string PhoneNumber { get; set; } public Dictionary<string, App> Apps { get; set; } } public class App { public string FirstName { get; set; } public string LastName { get; set; } public string UserName { get; set; } public List<string> Roles { get; set; } public List<String> Messages { get; set; } public String AdressId { get; set; } public bool IsActive { get; set; } = true; [JsonIgnore] public string DisplayName => $"{FirstName} {LastName}"; }
services.AddSingleton<IDocumentStore>(serviceProvider => { var store = new DocumentStore() { Urls = new[] { "http://192.168.1.10:8080" }, Database = "AccountingSystem", }.Initialize(); return store; }); services.AddScoped<IAsyncDocumentSession>(serviceProvider => { var store = serviceProvider.GetRequiredService<IDocumentStore>(); return store.OpenAsyncSession(); });
var user = new User { PhoneNumber = user.PhoneNumber }; user.Apps.Add(appCode, new ActiveApp { FirstName = "عبدالصالح", LastName = "کاشانی", UserName = abdossaleh, IsActive = true, RolesId = new List<string>{"Admin"} }); await _documentSession.StoreAsync(user); await _documentSession.SaveChangesAsync()
var user = await _documentSession.LoadAsync<User>("Users/131-A");
_documentSession.Advanced.Patch<User, string>("Users/131-A", u => u.PhoneNumber , "09131110000");
_documentSession.Advanced.Patch<User, string>("Users/131-A", u => u.Apps["59"].RolesId , r => r.Add("Admin"));
_documentSession.Advanced.Increment<User, int>("Users/131-A", x => x.TestProp, 10);
_documentSession.Advanced.Defer(new PatchCommandData("Users/131-A", null, new PatchRequest() { Script = $@"this.Apps[args.appCode] = args.app", Values = { {"appCode", appCode}, {"app", new ActiveApp { FirstName = "عبدالصالح", LastName = "کاشانی", UserName = abdossaleh, RolesId = new List<string>{"Admin"} } } } }, null));
Script = "this.Apps[args.app].Roles.splice(args.index,0,args.role)", Values = { { "index": 1 // مکانی که میخواهیم عملیات انجام شود "app", 59 "role", "User" } }
splice(args.index,1,args.role)
Script = @"this.Roles= this.Apps[args.app].Roles.filter(role=> role != args.role);", Values = { {"app", 59} {"role", "User"} }
AngularJS #1
, What Every JavaScript Developer Should Know About ECMAScript 2015 is the book I'd like to read about the new features in the JavaScript language. The book isn't a reference manual or an exhaustive list of everything in the ES2015 specification. Instead, I purposefully selected what I think are the important features we will use in everyday programming.
کتابخانهی تاریخ شمسی برای پروژههای وب و مورد استفاده در جاوا اسکریپت به NuGet اضافه شد
این کتابخانه کاملترین کتابخانهی تاریخ شمسی در جاوا اسکریپت میباشد که از تاریخ 1/1/1 تا 30/12/9377 را پشتیبانی میکند
جهت نصب این دستور را در Package Manager Console تایپ کنید
Install-Package anyresolver.persiandate