نظرات مطالب
معرفی فریم ورک Blueprint CSS
بسته به نیاز و کاربرد باید ابزار مناسبی رو انتخاب کرد. آیا شما نیاز به تمام عناصر موجود در فریم ورک توئیتر bootstrap دارید؟ من نیازی نداشتم به همین جهت انتخاب انجام شده هم بسیار سبک، کم حجم و متناسب بوده. از توئیتر bootstrap هم فقط دکمههای css ایی آن برای من جالب بود. نیازی به مابقی آن نداشتم.
در مقالهی قبلی ما بخشی از BootstrapDialog را با استفاده از Reflection پیاده سازی کردیم. دلیل اینکه پیاده سازی کاملی از آن نداشتیم، متغیر بودن مقادیر و پیچیدهتر شدن و طولانی تر شدن کد نویسی آن بود که برای آن کد ارزش زیادی نداشت تا وقت بیشتری صرف شود. ولی در اینجا بخاطر پیچیدگی کمتر، به طور کامل از Reflection استفاده شده است.
شیء BootstrapSwitch یک چک باکس است که با استفاده از جی کوئری و استایلها به یک سوئیچ انیمیشنی زیبا تبدیل شده است که خودم به شخصه علاقه زیادی به استفادهی از آن در پروژههای شخصی پیدا کردهام. غیر از زیبایی، حس خوبی از کارکرد برنامه میدهد.
فایلهای موردنیاز را دانلود کرده و آنها را در ابتدای صفحه و با رعایت ترتیب صدا بزنید:
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> <link href="~/content/css/bootstrap-switch.min.css" rel=stylesheet"></link> <script src="~/Scripts/bootstrap-switch.min.js"></script>
نکته مهم: فایل css شامل دو نسخه هست که یکی از آن برای Bootstrap2 و دیگری برای نسخه 3 آن است که نسبت به آن نسخه، استایل مناسب را انتخاب کنید.
پروژهی اصلی را دریافت کنید و آن را به solution خود اضافه کنید. پروژه به دو بخش اصلی Controls و Models تقسیم میشود که بخش مدل آن، برای ایجاد ساختارهای آن و در بخش کنترل، برای ترسیم آن به صورت HtmlHelper به کار میرود.
ابتدا قبل از هر چیزی یک شیء از کلاس BootstrapSwitchModel ایجاد کنید و مقادیر دلخواه خود را به خصوصیتهای آن نسبت دهید:
var model=BootstrapSwitchModel(); //وضعیت فعال بودن و غیرفعال بودن سوئیچ model.Checked=true; //اندازه آن model.Size=BootstrapSize..normal; //یک انیمیشن ساده موقع سوئیچ کردن دارد model.Animate=true; //به چک باکس عادی تبدیل میشود model.Disabled=true; //غیرفعال شده و به صورت فقط خواندنی قابل دسترس است model.Readonly=true; //رنگ قعال بودن model.OnColor=BootstrapColor.Success; //رنگ غیرفعال بودن model.OffColor=BootstrapColor.Danger; //متن نمایشی در هنگام فعال بودن model.OnText="On"; //متن نمایشی در حالت عدم انتخاب model.OffText="Off"; //بین دو حالت روشن و خاموش نمایش داده میشود model.label="Public Display"; //تعیین میزان اندازه برچسب بالا model.LabelWidth=100; //سوئیچ به صورت آینه ای معکوس میشود model.Inverse=false; //کلاسی جهت تغییر استایل سوئیچ model.BaseClass="myclass"; //تعیین کلاس برای تگ اصلی پدر model.WrapperClass="wclass"; //فقط یکی از چند سوئیچ میتواند فعال باشد model.RadioAllOff=false; //یک سوئیچ در حالت عادی فقط یکی از //وضعیتها را نمایش میده ولی در این حالت //سوئیچ در ابتدا بین این دو وضعیت گیر کرده است model.Indeterminate=true; //اندازه سمت چپ و راست سوئیچ model.HandleWidth=25;
@{ var model=BootstrapSwitchModel(); ....} @HTML.BootstrapSwitch("id",model);
در پستهای قبلی با مفهوم ng-app آشنا شدید. دایرکتیو ng-app برای استفاده از راه انداز خودکار فریم ورک Angular (معروف به auto-bootstrap) استفاده میشود. در حالت پیش فرض، به ازای هر سند Html فقط میتوان یک ماژول در Angular تعریف کرد. در سند مربوطه اولین المانی که دارای دایرکتیو ng-app باشد به عنوان عنصر ریشه در نظر گرفته میشود و تمام عناصر تعریف شده در محدوده این دایرکتیو قایل استفاده برای ماژول مورد نظر خواهد بود. سایر عناصر حتی اگر ng-app یکسان داشته باشند نادیده گرفته میشوند.
ابتدا یک مثال زیر را به روش auto-bootstrap بررسی میکنیم:
ابتدا یک مثال زیر را به روش auto-bootstrap بررسی میکنیم:
<div ng-app="myApp"> <div ng-controller="myController as ctrl"> <span>ng-app #1</span> {{ctrl.firstName}} {{ctrl.lastName}} </div> </div> <div ng-app="myApp"> <div ng-controller="myController as ctrl"> <span>ng-app #2</span> {{ctrl.firstName}} {{ctrl.lastName}} </div> </div> @section scripts { <script type="text/javascript" src="~/scripts/Modules/module8.js"></script> }
در کنترلر مورد نظر نیز تعاریف به صورت زیر خواهد بود:
var app = angular.module('myApp', []); app.controller('myController', function () { this.firstName = "Masoud"; this.lastName = "Pakdel"; });
در مثال بالا دو تگ div وجود دارد که به صورت مشترک با استفاده از دایرکتیو ng-app به یک ماژول اشاره میکنند. طبق گفتهها بالا در روش auto-bootstrap اولین عنصری که دارای دایرکتیو ng-app باشد به عنوان محدوده ماژول مورد استفاده قرار خواهد گرفت در نتیجه سایر المانها (در اینجا منظور تگ div دوم است)نادیده گرفته خواهند شد. پس خروجی به صورت زیر میشود:
اما اگر قصد داشته باشیم که در یک سند html دو نقطه شروع تعریف کنیم در حالی که هر کدام از یک منبع داده استفاده نمایند باید bootstrap برنامه را به صورت دستی تعیین کرد. برای این کار کافیست از دستور angular.bootstrap به صورت زیر استفاده نماییم:
پیاده سازی مثال بالا
پیاده سازی مثال بالا
<div id="myAppContainer1"> <div ng-controller="myController as ctrl"> <span>ng-app #1</span> {{ctrl.firstName}} {{ctrl.lastName}} </div> </div> <div id="myAppContainer2"> <div ng-controller="myController as ctrl"> <span>ng-app #2</span> {{ctrl.firstName}} {{ctrl.lastName}} </div> </div> @section scripts { <script type="text/javascript" src="~/scripts/Modules/module8.js"></script> }
اولین تغییر مورد نظر این است که، دایرکتیو ng-app حذف شد و به جای آن id برای تگ div تعیین کردیم. در فایل کنترلر مورد نظر نیز تغییر زیر را اعمال میکنیم:
var app = angular.module('myApp', []); app.controller('myController', function () { this.firstName = "Masoud"; this.lastName = "Pakdel"; }); angular.bootstrap(document.getElementById("myAppContainer1"), ["myApp"]); angular.bootstrap(document.getElementById("myAppContainer2"), ["myApp"]);
با استفاده از دستور angular.bootstrap میتوان بر اساس id تعیین شده تگ مورد نظر در سند را به دست آورد و ماژول مورد نظر را به آن نسبت داد.
خروجی مثال بالا:
خروجی مثال بالا:
برخلاف حالت قبل هر دو نقطه شروع به یک منبع داده اشاره میکنند و محدودیت حالت قبل برطرف میشود.
تبدیل بی عیب و نقص یک فایل PDF (انواع و اقسام آنها) به متن قابل درک بسیار مشکل است. در ادامه بررسی خواهیم کرد که چرا.
برخلاف تصور عموم، ساختار یک صفحه PDF شبیه به یک صفحه فایل Word نیست. این صفحات درحقیقت نوعی Canvas برای نقاشی هستند. در این بوم نقاشی، شکل، تصویر، متن و غیره در مختصات خاصی قرار خواهند گرفت. حتی کلمه «متن» میتواند به صورت سه حرف در سه مختصات خاص یک صفحه PDF نقاشی شود. برای درک بهتر این مورد نیاز است سورس یک صفحه PDF را بررسی کرد.
نحوه استخراج سورس یک صفحه PDF
فایل PDF تولیدی حاوی سه عبارت کامل و مفهوم میباشد:
اگر علاقمند باشید که سورس واقعی صفحات یک فایل PDF را مشاهده کنید، نحوه انجام آن توسط کتابخانه iTextSharp به صورت فوق است.
هرچند متد GetPageContent آرایهای از بایتها را بر میگرداند، اما اگر حاصل نهایی را در یک ادیتور متنی باز کنیم، قابل مطالعه و خواندن است. برای مثال، سورس مثال فوق (محتوای فایل page-1.txt تولید شده) به نحو زیر است:
و تفسیر این عملگرها به این ترتیب است:
همانطور که ملاحظه میکنید کلمه Test به مختصات خاصی انتقال داده شده و سپس به کمک اطلاعات فونت F1، ترسیم میشود.
تا اینجا استخراج متن از فایلهای PDF ساده به نظر میرسد. باید به دنبال Tj گشت و حروف مرتبط با آنرا ذخیره کرد. اما در مورد «ترسیم» عبارات hello world و hello people اینطور نیست. عبارت hello world به حروف متفاوتی تقسیم شده و سپس در مختصات مشخصی ترسیم میگردد. عبارت hello people به صورت یک شیء ذخیره شده در قسمت منابع فایل PDF، بازیابی و نمایش داده میشود و اصلا در سورس صفحه جاری وجود ندارد.
این تازه قسمتی از نحوه عملکرد فایلهای PDF است. در فایلهای PDF میتوان قلمها را مدفون ساخت. همچنین این قلمها نیز تنها زیر مجموعهای از قلم اصلی مورد استفاده هستند. برای مثال اگر عبارت Test قرار است نمایش داده شود، فقط اطلاعات T، e و s در فایل نهایی PDF قرار میگیرند. به علاوه امکان تغییر کلی شماره Glyph متناظر با هر حرف نیز توسط PDF writer وجود دارد. به عبارتی الزامی نیست که مشخصات اصلی فونت حتما حفظ شود.
شاید بعضی از PDFهای فارسی را دیده باشید که پس از کپی متن آنها در برنامه Adobe reader و سپس paste آن در جایی دیگر، متن حاصل قابل خواندن نیست. علت این است که نحوه ذخیره سازی قلم مورد استفاده کاملا تغییر کرده است و برای بازیابی متن اینگونه فایلها، استفاده از OCR سادهترین روش است. برای نمونه در این قلم جدید مدفون شده، دیگر شماره کاراکتر 0x41 مساوی A نیست. بنابر سلیقه PDF writer این شماره به Glyph دیگری انتساب داده شده و چون قلم و مشخصات هندسی Glyph مورد استفاده در فایل PDF ذخیره میشود، برای نمایش این نوع فایلها هیچگونه مشکلی وجود ندارد. اما متن آنها به سادگی قابل بازیابی نیست.
برخلاف تصور عموم، ساختار یک صفحه PDF شبیه به یک صفحه فایل Word نیست. این صفحات درحقیقت نوعی Canvas برای نقاشی هستند. در این بوم نقاشی، شکل، تصویر، متن و غیره در مختصات خاصی قرار خواهند گرفت. حتی کلمه «متن» میتواند به صورت سه حرف در سه مختصات خاص یک صفحه PDF نقاشی شود. برای درک بهتر این مورد نیاز است سورس یک صفحه PDF را بررسی کرد.
نحوه استخراج سورس یک صفحه PDF
using System.Diagnostics; using System.IO; using iTextSharp.text; using iTextSharp.text.pdf; namespace TestReaders { class Program { static void writePdf() { using (var document = new Document(PageSize.A4)) { var writer = PdfWriter.GetInstance(document, new FileStream("test.pdf", FileMode.Create)); document.Open(); document.Add(new Paragraph("Test")); PdfContentByte cb = writer.DirectContent; BaseFont bf = BaseFont.CreateFont(); cb.BeginText(); cb.SetFontAndSize(bf, 12); cb.MoveText(88.66f, 367); cb.ShowText("ld"); cb.MoveText(-22f, 0); cb.ShowText("Wor"); cb.MoveText(-15.33f, 0); cb.ShowText("llo"); cb.MoveText(-15.33f, 0); cb.ShowText("He"); cb.EndText(); PdfTemplate tmp = cb.CreateTemplate(250, 25); tmp.BeginText(); tmp.SetFontAndSize(bf, 12); tmp.MoveText(0, 7); tmp.ShowText("Hello People"); tmp.EndText(); cb.AddTemplate(tmp, 36, 343); } Process.Start("test.pdf"); } private static void readPdf() { var reader = new PdfReader("test.pdf"); int intPageNum = reader.NumberOfPages; for (int i = 1; i <= intPageNum; i++) { byte[] contentBytes = reader.GetPageContent(i); File.WriteAllBytes("page-" + i + ".txt", contentBytes); } reader.Close(); } static void Main(string[] args) { writePdf(); readPdf(); } } }
اگر علاقمند باشید که سورس واقعی صفحات یک فایل PDF را مشاهده کنید، نحوه انجام آن توسط کتابخانه iTextSharp به صورت فوق است.
هرچند متد GetPageContent آرایهای از بایتها را بر میگرداند، اما اگر حاصل نهایی را در یک ادیتور متنی باز کنیم، قابل مطالعه و خواندن است. برای مثال، سورس مثال فوق (محتوای فایل page-1.txt تولید شده) به نحو زیر است:
q BT 36 806 Td 0 -18 Td /F1 12 Tf (Test)Tj 0 0 Td ET Q BT /F1 12 Tf 88.66 367 Td (ld)Tj -22 0 Td (Wor)Tj -15.33 0 Td (llo)Tj -15.33 0 Td (He)Tj ET q 1 0 0 1 36 343 cm /Xf1 Do Q
SaveGraphicsState(); // q BeginText(); // BT MoveTextPos(36, 806); // Td MoveTextPos(0, -18); // Td SelectFontAndSize("/F1", 12); // Tf ShowText("(Test)"); // Tj MoveTextPos(0, 0); // Td EndTextObject(); // ET RestoreGraphicsState(); // Q BeginText(); // BT SelectFontAndSize("/F1", 12); // Tf MoveTextPos(88.66, 367); // Td ShowText("(ld)"); // Tj MoveTextPos(-22, 0); // Td ShowText("(Wor)"); // Tj MoveTextPos(-15.33, 0); // Td ShowText("(llo)"); // Tj MoveTextPos(-15.33, 0); // Td ShowText("(He)"); // Tj EndTextObject(); // ET SaveGraphicsState(); // q TransMatrix(1, 0, 0, 1, 36, 343); // cm XObject("/Xf1"); // Do RestoreGraphicsState(); // Q
تا اینجا استخراج متن از فایلهای PDF ساده به نظر میرسد. باید به دنبال Tj گشت و حروف مرتبط با آنرا ذخیره کرد. اما در مورد «ترسیم» عبارات hello world و hello people اینطور نیست. عبارت hello world به حروف متفاوتی تقسیم شده و سپس در مختصات مشخصی ترسیم میگردد. عبارت hello people به صورت یک شیء ذخیره شده در قسمت منابع فایل PDF، بازیابی و نمایش داده میشود و اصلا در سورس صفحه جاری وجود ندارد.
این تازه قسمتی از نحوه عملکرد فایلهای PDF است. در فایلهای PDF میتوان قلمها را مدفون ساخت. همچنین این قلمها نیز تنها زیر مجموعهای از قلم اصلی مورد استفاده هستند. برای مثال اگر عبارت Test قرار است نمایش داده شود، فقط اطلاعات T، e و s در فایل نهایی PDF قرار میگیرند. به علاوه امکان تغییر کلی شماره Glyph متناظر با هر حرف نیز توسط PDF writer وجود دارد. به عبارتی الزامی نیست که مشخصات اصلی فونت حتما حفظ شود.
شاید بعضی از PDFهای فارسی را دیده باشید که پس از کپی متن آنها در برنامه Adobe reader و سپس paste آن در جایی دیگر، متن حاصل قابل خواندن نیست. علت این است که نحوه ذخیره سازی قلم مورد استفاده کاملا تغییر کرده است و برای بازیابی متن اینگونه فایلها، استفاده از OCR سادهترین روش است. برای نمونه در این قلم جدید مدفون شده، دیگر شماره کاراکتر 0x41 مساوی A نیست. بنابر سلیقه PDF writer این شماره به Glyph دیگری انتساب داده شده و چون قلم و مشخصات هندسی Glyph مورد استفاده در فایل PDF ذخیره میشود، برای نمایش این نوع فایلها هیچگونه مشکلی وجود ندارد. اما متن آنها به سادگی قابل بازیابی نیست.
نظرات مطالب
چک لیست تهیه یک برنامه ASP.NET MVC
اگر امکان دارد طبق توصیه ای که شما گفتین « - از هشهای ترکیبی استفاده شود. مستقیما از MD5 یا SHA1 استفاده نشود. » لینک منابعی رو معرفی میکنین که بشه طریقه استفاده از بهترین الگوریتمهای هش و ترکیب آنها با هم را با سمپل بررسی کرد و در کارهای امن بکار برد ؟ متشکرم
این سری مطالب بسیار خوب و مفید است .از نویسنده محترم خواهش میکنم نگارش این مجموعه را متوقف نکند .
در صورتی که برای ایشون امکان پذیر نیست خواهش میکنم منبع یا منابعی که از آنها در مورد این سری مقالات به آن رجوع کرده اند را معرفی کنند.
با تشکر از زحماتشان
در صورتی که برای ایشون امکان پذیر نیست خواهش میکنم منبع یا منابعی که از آنها در مورد این سری مقالات به آن رجوع کرده اند را معرفی کنند.
با تشکر از زحماتشان
کار آقای عرب عامری فراتر است از 150 کلمه ذکر شده. آنالیز فتحه، کسره، ی فارسی و عربی و غیره هم در آن لحاظ شده.