$("#uploader").pluploadQueue({ // Post init events, bound after the internal events init: { FileUploaded: function(up, file, info) { // Called when a file has finished uploading } } });
نحوه استفاده
نحوه استفاده از آن بسیار راحت است و در دموی 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 قرار بگیرند.
<div id="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' });
فایل 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);
متدها
//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(); } };
تابع 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); }
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" });
در خط بعدی محتویات نمونه را داخل تگ sectiondiv قرار میدهیم:
//create new form sectionDiv.html(sample);
بعد از آن برای رویداد کلیک لینک حذف، کد زیر را وارد میکنیم:
link.on('click', function (e) { e.preventDefault(); var $this = $(this); $this.closest(".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);
در ادامه نحوه سازگار سازی این مجموعه را با ASP.NET MVC مرور خواهیم کرد:
الف) سورسهای اصلی Flash کنترل ارسال فایلها
اگر علاقمند به تغییر اطلاعاتی در فایل فلش نهایی هستید به پوشه OriginalFlashSource پروژه پیوست شده مراجعه کنید. در اینجا برای مثال یک سری از برچسبهای آن فارسی شدهاند و کامپایل مجدد.
ب) مزیت استفاده از Flash uploader
با استفاده از Flash uploader امکان انتخاب چندین فایل با هم وجود دارد. همچنین در صفحه دیالوگ انتخاب فایلها دقیقا میتوان پسوند فایلهای مورد نظر را نیز تعیین کرد. این دو مورد در حالت ارسال معمولی فایلها به سرور و استفاده از امکانات معمولی HTML وجود ندارند. به علاوه امکان نمایش درصد پیشرفت آپلود فایلها و همچنین حذف کلی لیست و حذف یک آیتم از لیست را هم درنظر بگیرید.
ج) معادل کنترل Web forms را در ASP.NET MVC به شکل زیر میتوان تهیه کرد:
@helper AddFlashUploader( string uploadUrl, string queryParameters, string flashUrl, int totalUploadSizeLimit = 0, int uploadFileSizeLimit = 0, string fileTypes = "", string fileTypeDescription = "", string onUploadComplete = "") { onUploadComplete = string.IsNullOrEmpty(onUploadComplete) ? "" : "completeFunction=" + onUploadComplete; queryParameters = Server.UrlEncode(queryParameters); fileTypes = string.IsNullOrEmpty(fileTypes) ? "" : "&fileTypes=" + Server.UrlEncode(fileTypes); fileTypeDescription = string.IsNullOrEmpty(fileTypeDescription) ? "" : "&fileTypeDescription=" + Server.UrlEncode(fileTypeDescription); var totalUploadSizeLimitData = totalUploadSizeLimit > 0 ? "&totalUploadSize=" + totalUploadSizeLimit : ""; var uploadFileSizeLimitData = uploadFileSizeLimit > 0 ? "&fileSizeLimit=" + uploadFileSizeLimit : ""; var flashVars = onUploadComplete + fileTypes + fileTypeDescription + totalUploadSizeLimitData + uploadFileSizeLimitData + "&uploadPage=" + uploadUrl + "?" + queryParameters; <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="575" height="375" id="fileUpload" align="middle"> <param name="allowScriptAccess" value="sameDomain" /> <param name="movie" value="@flashUrl" /> <param name="quality" value="high" /> <param name="wmode" value="transparent"> <param name=FlashVars value="@flashVars"> <embed src="@flashUrl" FlashVars="@flashVars" quality="high" wmode="transparent" width="575" height="375" name="fileUpload" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /> </object> }
د) نحوه استفاده از HTML helper فوق:
@{ ViewBag.Title = "Index"; var uploadUrl = Url.Action("Uploader", "Home"); var flashUrl = Url.Content("~/Content/FlashUpload/FlashFileUpload.swf"); } <h2> Flash Uploader</h2> <div style="background: #E0EBEF;"> @FlashUploadHelper.AddFlashUploader( uploadUrl: uploadUrl, queryParameters: "User=Vahid&Id=تست", flashUrl: flashUrl, fileTypeDescription: "Images", fileTypes: "*.gif; *.png; *.jpg; *.jpeg", uploadFileSizeLimit: 0, totalUploadSizeLimit: 0, onUploadComplete: "alert('انجام شد');") </div>
using System.Collections.Generic; using System.IO; using System.Web; using System.Web.Mvc; namespace MvcFlashUpload.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } public ActionResult Uploader(string User, string Id, IEnumerable<HttpPostedFileBase> FileData) { var queryParameter1 = User; var queryParameter2 = Id; // ... foreach (var file in FileData) { if (file.ContentLength > 0) { var fileName = Path.GetFileName(file.FileName); var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"), fileName); file.SaveAs(path); } } return Content(" "); } } }
توضیحات:
در اینجا uploadUrl، مسیر اکشن متدی است که قرار است اطلاعات فایلها را دریافت کند. queryParameters اختیاری است. اگر تعریف شود تعدادی کوئری استرینگ دلخواه را میتواند به متد Uploader ارسال کند. برای نمونه در اینجا User و Id ارسال شدهاند یا هر نوع کوئری استرینگ دیگری که مدنظر است.
flashUrl مسیر فایل SWF را مشخص میکند. در اینجا فایل FlashFileUpload.swfدر پوشه Content/FlashUpload قرار گرفته است.
fileTypeDescription برچسبی است که نوع فایلهای قابل انتخاب را به کاربر نمایش میدهد و fileTypes نوعهای مجاز قابل ارسال را دقیقا مشخص میکند.
پارامترهای uploadFileSizeLimit و totalUploadSizeLimit در صورتیکه مساوی صفر وارد شوند، به معنای عدم محدودیت اندازه در فایلها و جمع حجم ارسالی در هر بار است.
استفاده از پارامتر onUploadComplete اختیاری است. در اینجا میتوان پس از پایان عملیات از طریق جاوا اسکریپت عملیاتی را انجام داد. برای مثال اگر خواستید کاربر را به صفحه خاصی هدایت کنید، window.locationرا مقدار دهی نمائید.
در متد Uploader کنترلر فوق، پارامترهای User و id اختیاری بوده و بر اساس queryParameters متد FlashUploadHelper.AddFlashUploader مشخص میشوند. اما نام FileData نباید تغییری کند؛ از این لحاظ که دقیقا همین نام در فایل فلش، مورد استفاده قرار گرفته است.
در اکشن متد دریافت فایلها، لیستی از فایلهای ارسالی به سرور دریافت شده و سپس بر این اساس میتوان آنها را در مکانی مشخص ذخیره نمود.
دریافت پروژه
MvcFlashUploader.zip
در مطلب آشنایی با Directiveها در AngularJS با نحوهی ایجاد Directive آشنا شدیم. هدف از این مطلب، آشنایی بیشتر با Directive در AngularJS است؛ یکی از بهترین فریم ورکهای جاوااسکریپتی، با قابلیت ایجاد کتابخانههایی از کامپوننتها که میتوانند به HTML اضافه شوند .
کتابخانههای جاوااسکریپتی زیادی وجود دارند. به عنوان مثال Bootstrap یکی از محبوبترین "front-end
framework" ها است که امکان تغییر در ظاهر المنتها را فراهم میکند و شامل
تعدادی کامپوننت جاوااسکریپتی نیز میباشد. مشکل کار، در هنگام استفاده از کامپوننت ها است. شخصی که در حال توسعهی HTML است
باید در کد جاوااسکریپتی خود از jQuery استفاده کند و بعنوان مثال یک Popover را فعال یا غیر فعال کند و این، یک فرآیند خسته کننده و مستعد خطا
است.
یک مثال ساده از Directives AngularJS و بررسی آن
var m = angular.module("myApp"); myApp.directive("myDir", function() { return { restrict: "E", scope: { name: "@", amount: "=", save: "&" }, template: "<div>" + " {{name}}: <input ng-model='amount' />" + " <button ng-click='save()'>Save</button>" + "</div>", replace: true, transclude: false, controller: [ "$scope", function ($scope) { … }], link: function (scope, element, attrs, controller) {…} } });
به الگوی نامگذاری directive دقت کنید. پیشوند my شبیه به یک namespace است. بنابراین اگر یک Application از دایرکتیوهای قرار گرفته در Module های متفاوت استفاده کند، به راحتی میتوان محل تعریف یک directive را تشخیص داد. این نام میتواند نشان دهندهی این باشد که این directive را خودتان توسعه دادهاید یا از یک directive توسعه داده شده توسط شخص دیگری در حال استفاده هستید. به هر حال این نحوهی نام گذاری یک اجبار نیست و به عنوان یک پیشنهاد است.
سازنده directive یک شیء را با تعدادی خاصیت باز میگرداند که تمامی آنها در سایت AngularJS توضیح داده شدهاند. در اینجا قصد داریم تا توضیحی مختصر در مورد کاری که این خصوصیات انجام میدهند داشته باشیم.
· restrict : تشخیص میدهد که آیا directive در HTML استفاده خواهد شد. گزینههای قابل استفاده ‘A’ ، ‘E’ ، ‘C’ برای attribute ، element ، class و یا comment است . پیش فرض ‘A’ برای attribute است. اما ما بیشتر علاقه به استفاده از ویژگی element برای ایجاد المنتهای UI داریم.
· scope : ایجاد یک scope ایزوله که متعلق به directive است و موجب ایزوله شدن آن از scope صدا زننده directive میشود. متغیرهای scope پدر از طریق خصوصیات تگ directive ارسال میشوند. این ایزوله کردن زمانی کاربردی است که در حال ایجاد کامپوننت هایی با قابلیت استفاده مجدد هستیم، که نباید متکی به scope پدر باشند. شیء scope در directive نام و نوع متغیرهای scope را تعیین میکنند. در مثال بالا سه متغیر برای scope تعریف شده است:
- name: "@" (by value, one-way) : علامت @ مشخص میکند که مقدار متغیر ارسال میشود. Directive یک رشته را دریافت میکند که شامل مقدار ارسال شده از scope پدر میباشد. Directive میتواند از آن استفاده کند، اما نمیتواند مقدار آن را در scope پدر تغییر دهد.
- amount: "=" (by reference, two-way) : علامت = مشخص میکند این متغیر با ارجاع ارسال میشود. Directive یک ارجاع به مقدار متغیر در scope اصلی دریافت میکند. مقدار میتواند هر نوع داده ای، شامل یک شیء complex یا یک آرایه باشد. Directive میتواند مقدار را در scope پدر تغییر دهد. این نوع متغیر، زمانیکه نیاز باشد directive مقدار را در scope پدر تغییر دهد، استفاده میشود.
- save: "&" (expression) : علامت & مشخص میکند این متغیر یک expression را که در scope پدر اجرا میشود، نگهداری میکند. اکنون directive قابلیت انجام کارهایی فراتر از تغییر یک مقدار را دارد. به عنوان مثال میتوان یک تابع را از scope پدر فراخوانی و نتیجهی اجرا را دریافت کرد.
· template : الگوی رشته ای که جایگزین المنت تعریف شده میشود. فرآیند جایگزینی تمامی خصوصیات را از المنت قدیمی به المنت جدید انتقال میدهد. به نحوه استفاده از متغیرهای تعریف شده در scope ایزوله دقت کنید. این مورد به شما امکان تعریف directive های macro-style را میدهد که نیاز به کد اضافهای، ندارند. اگرچه در بیشتر موارد الگو یک تگ ساده <div> است که از کدهای link که در زیر توضیح داده شده است استفاده میکند.
· replace : تعیین میکند که آیا الگوی directive باید جایگزین المنت شود. مقدار پیش فرض false است.
· transclude : تعیین کننده این است که محتوای directive باید در المنت کپی شود یا خیر. در مثال زیر المنت tab شامل المنتهای HTML دیگر است پس transclude برابر true است.
<body ng-app="components"> <h3>BootStrap Tab Component</h3> <tabs> <pane title="First Tab"> <div>This is the content of the first tab.</div> </pane> <pane title="Second Tab"> <div>This is the content of the second tab.</div> </pane> </tabs> </body>
· link : این تابع بیشتر منطق directive را شامل میشود. Link وظیفه دستکاری DOM ، ایجاد event listener ها و... را دارد. تابع Link پارامترهای زیر را دریافت میکند:
- scope : ارجاع به scope ایزوله شده directive دارد.
- element : ارجاع به المنتهای DOM که directive را تعریف کرده اند. تابع link معمولا برای دستکاری المنت از jQuery استفاده میکند. (یا از Angular's jqLite در صورتی که jQuery بارگذاری نشده باشد)
- controller : در مواقعی که از دایرکتیوهای تو در تو استفاده میشود کاربرد دارد. این پارامتر یک directive فرزند با ارجاعی به پدر را فراهم میکند، بنابراین موجب ارتباط directive ها میشود.
به عنوان مثال، این directive که پیاده سازی bootstrap tab را انجام داده است، میتوانید مشاهده نمایید.
موفق باشید
متدهای کمکی مفید در پروژه های asp.net mvc
"این یک متن ت..."
"این یک متن تست ..."
که این تابع میتونه به جای SubString مفید باشه :
public static string TruncateAtWord(this string input, int length) { if (input == null || input.Length < length) return input; int iNextSpace = input.LastIndexOf(" ", length); return string.Format("{0}...", input.Substring(0, (iNextSpace > 0) ? iNextSpace : length).Trim()); }
<input type="file" multiple="multiple" name="FileUpload1" id="FileUpload1" />
<asp:FileUpload runat="server" ID="FileUploadMultiple" AllowMultiple="true" />
در صورتیکه از این روش در پروژههایتان استفاده کنید فقط کافیست با یک حلقه تمامی کنترلهای مورد نظر را پیمایش و هر کدام از فایلها را آپلود و ذخیره نمایید.
<asp:FileUpload runat="server" ID="FileUploadMultiple" AllowMultiple="true" /> <asp:Button runat="server" ID="btnUlpad" Text="Upload" OnClick="btnUlpad_Click" /> <asp:Label runat="server" ID="lblMessage"></asp:Label>
int Count = 0; foreach (var item in FileUploadMultiple.PostedFiles) { string Extension = Path.GetExtension(item.FileName); string FileName = new Random().Next(1, 50).ToString()+Extension; item.SaveAs(Server.MapPath("~")+"//File//"+FileName); Count++; } if (Count == FileUploadMultiple.PostedFiles.Count) lblMessage.Text = string.Format("فایلهای انتخابی با موفقیت آپلود شدند"); else lblMessage.Text = string.Format("{0} از {1} فایل با موفقیت آپلود شد", Count, FileUploadMultiple.PostedFiles.Count);
Bootstrap 4 در واقع یک اقدام بزرگ بود که پس از یک سال توسعه، بزرگی این اقدام در خط به خط کدها احساس میگردد. تصمیم گرفتیم تا نسخهی اولیهی آن را به اشتراک بگذاریم و انتقادات و پیشنهادات شما را بشنویم. برای بهبود و پیشرفت در این زمینه، بسیاری از اخبار مرتبط را در اختیار شما قرار میدهیم. امیدواریم که ما را در بهتر شدن یاری کنید.
امکانات جدید Bootstrap
انتقال از Less به Sass
بهبود grid system مبتنی بر "rems"
h1 { /* 16 * 2.5 = 40px */ }
تغییر panel و wells به cards
Reset Component جایگزینی برای normalize.css
- نحوه ارسال فایل به سرور توسط ASP.NET MVC
- نحوه اعتبار سنجی سمت سرور ارسال فایلها
در ASP.NET MVC برای آپلود فایلها عموما عنوان میشود که از تگ input به نحو زیر استفاده شود:
<input type="file" name="file" />
<input type="file" data-val="true" data-val-required="لطفا فایلی را انتخاب کنید" name="file" /> @Html.ValidationMessage("file")
از این نکته خصوصا در طراحی html helperهای سفارشی نیز میتوان استفاده کرد.
برای مثال فرض کنید مشغول طراحی یک کنترل captcha هستید. قسمتی از آن مربوط به دریافت ورودی از کاربر است. به علاوه، پیغام خطایی هم که باید نمایش داده شود نیز باید توسط کاربر قابلیت سفارشی شدن را داشته باشد (و نمیتوان آنرا توسط یک attribute به سادگی به یک مدل خاص انتساب داد).
در این حالت تنظیم data-val و data-val-required به کمک anonymously typed objects پارامتر htmlAttributes میسر نیست (چون بین حروف آن dash وجود دارد) و باید از overload و نوع dictionary دار آن به نحو زیر استفاده کرد:
htmlHelper.TextBox("CaptchaInputText", string.Empty, new Dictionary<string, object> { { "data-val", "true"}, { "data-val-required", validationErrorMessage}, })