راهنماهای پروژه‌ها
سؤالات متداول
  • می‌خواهم برنامه‌ام را بر روی کامپیوتر مشتری بدون دردسر نصب کنم؛ با حداقل حجم و دردسر توزیع. به علاوه بدون نیاز به وصله پینه کردن اسمبلی‌های تجاری دریافت شده.

پاسخ: PdfReport از چند اسمبلی دات نتی تشکیل شده است که نیاز به نصب خاصی ندارد. همچنین حجم فشرده شده آن نیز زیر 2 مگابایت است. بنابراین از جهت توزیع مشکل خاصی نخواهید داشت. همچنین کل این مجموعه سورس باز است و مشکلات متداول همراه با گزارش سازهای تجاری را به همراه ندارد.

  • می‌خواهم فایل گزارش، به همراه برنامه و فایل exe آن و نه جدای از آن توزیع شود.

پاسخ: روش کار با PdfReport اصطلاحا code-first است. یعنی یک یا چند کلاس تهیه شده توسط شما، کار تهیه گزارش را انجام می‌دهند و تمام این‌ها کامپایل شده و به همراه فایل اجرایی یا اسمبلی‌های خاصی که برای آن درنظر می‌گیرید، کامپایل و توزیع خواهند شد. همچنین با توجه به code-first بودن آن و عدم وابستگی به فناوری خاصی، این گزارشات در برنامه‌های وب و ویندوز نیز می‌توانند بدون نیاز به تغییری در کدهای شما مورد استفاده قرار گیرند.

  • برای کار با PdfReport از کجا باید شروع کرد؟

پاسخ: لطفا برچسب PdfReport را در سایت جاری دنبال نمائید. نحوه استفاده از قابلیت‌های آن قدم به قدم توضیح داده شده‌اند.

  • می‌خواهم برای صرفه جویی در کاغذ چاپی، گزارش چند ستونه‌ای را تهیه کنم.

پاسخ: لطفا مراجعه کنید به مثال ایجاد قالب‌های سفارشی ستون‌ها.

  • می‌خواهم گزارشی را تولید کنم که حجم متن فیلدهای آن مشخص نیست. یکی ممکن است نصف صفحه باشد دیگری دو صفحه و یا بعضی تنها یک سطر.

پاسخ: در PdfReport ارتفاع هر سطر به صورت خودکار بر مبنای حجم وارد شده محاسبه و تنظیم می‌گردد. به عبارتی این تنظیم ثابت نیست و سبب حذف محتوای ارائه شده در آن‌ها یا محو شدن ردیف‌های دیگر نمی‌گردد.

  • نیاز به گزارش سازی دارم که بدون مشکل با ORMها کار کند. برای مثال در حین کار با Entity framework مستقیما بتواند با اشیاء و لیست‌های حاصل از آن کار کند.

پاسخ: یکی از انواع منابع داده تعریف شده در PdfReport جهت کار با ORMها طراحی شده است که مثالی از نحوه استفاده از آن‌را در مثال EF Code first همراه با مجموعه مثال‌های این کتابخانه می‌توانید ملاحظه نمائید.

  • آیا این کتابخانه می‌تواند از فایل سیستم (و نه صرفا بانک اطلاعاتی) هم تصاویر را دریافت و در گزارشات قرار دهد؟

پاسخ: بلی. لطفا به مثال ImageFilePath مراجعه نمائید.

  • می‌خواهم یک گزارش ساز پویا در برنامه داشته باشم. فقط کوئری غیر مشخصی را به آن بدهم و حاصل آن یک گزارش باشد.

پاسخ: امکان تهیه گزارش‌های پویا نیز در PdfReport پیش بینی شده است. توضیحات بیشتر همچنین این امکان در حین کار با ORMها نیز وجود دارد.

  • می‌خواهم بدون استفاده از بانک اطلاعاتی نیز بتوانم گزارشی را تهیه کنم. برای مثال یک لیست جنریک تشکیل شده در حافظه دارم.

پاسخ: برای این منظور تنها کافی است از منبع داده صحیحی استفاده نمائید. برای اطلاعات بیشتر به مثال IList مراجعه کنید.

  • می‌خواهم از بانک‌های اطلاعاتی دیگری بجز SQL Server استفاده کنم.

پاسخ: می‌توانید یک نمونه مثال استفاده از PdfReport را با بانک اطلاعاتی SQLite، در اینجا مشاهده کنید.

اشتراک‌ها
Yahoo Mail و استفاده از ReactJS


1999 First gen C++, HTML Ajax for world peace
2004 Oddpost Java, Python, JS
2008 Classic PHP, JS
2010 The One PHP, YUI, JS
2015 Next gen NodeJS, React + Flux, MicroJS

Yahoo Mail و استفاده از ReactJS
مطالب
جایگزین کردن jQuery با JavaScript خالص - قسمت ششم - رخدادهای مرورگرها
واکنش نشان دادن به تغییرات صفحات وب، قسمت مهم و عمده‌ای از کار توسعه‌ی برنامه‌های وب را تشکیل می‌دهد. مفاهیم مرتبط با DOM events از زمان IE 4.0 و Netscape Navigator version 2 به مرورگرها اضافه شدند و به مرور تکامل یافتند. پیش از ظهور مرورگرهای مدرن (به IE 9.0 و مرورگرهای پیش از آن، مرورگرهای «باستانی» گفته می‌شود) به علت عدم هماهنگی آن‌ها با استانداردهای وب و تفاوت روش‌های رخدادگردانی، jQuery نقش مهمی را در زمینه‌ی یکدست سازی کدهای مدیریت رخدادها در بین مرورگرهای مختلف ارائه کرد. اما با پیش‌رفت‌های صورت گرفته و هماهنگی بیشتر مرورگرها با استانداردهای وب، دیگر نیازی به jQuery برای ارائه‌ی کدهای یکدست رخدادگردانی نیست و کار مستقیم با API وب مرورگرها برای این منظور کافی است.


انواع رخدادها: بومی و سفارشی

دو رده بندی عمومی رخدادها در مرورگرها وجود دارند: بومی و سفارشی.
بومی‌ها همان‌هایی هستند که در مستندات رسمی استانداردهای وب ذکر شده‌اند؛ مانند click که توسط ماوس و یا صفحه کلید فعال می‌شود و یا load که در زمان بارگذاری کامل صفحه، تصاویر و یا یک iframe رخ می‌دهد.
رخدادهای سفارشی مواردی هستند که توسط یک کتابخانه‌ی خاص و یا جهت یک برنامه‌ی خاص تهیه شده‌اند. مانند یک رخداد سفارشی که زمان شروع آپلود یک فایل را اعلام می‌کند.
رخدادهای سفارشی که بدون jQuery ایجاد و رخ‌می‌دهند، توسط jQuery نیز قابل بررسی و مدیریت هستند و نه برعکس. به عبارتی رخدادهای سفارشی ایجاد شده‌ی توسط jQuery غیراستاندارد بوده و صرفا مختص به API آن هستند.
در این بین، شیء استاندارد Event کار اتصال رخدادهای سفارشی و استاندارد را انجام می‌دهد. هر نوع رخداد DOM (سفارشی و یا بومی)، توسط یک شیء Event بیان می‌شود که آن نیز به همراه تعدادی خاصیت و متد، جهت مدیریت این رخداد است. برای مثال رخداد click دارای خاصیت type ایی به نام click است که در شیء Event متناظر با آن تعریف شده‌است.


انتشار رخدادها در صفحه

در روزهای آغازین وب، Netscape روش event capturing را برای انتشار رخدادها در صفحه ارائه داد و در مقابل آن IE روش event bubbling را معرفی کرد که متضاد یکدیگر بودند. در سال 2000 با ارائه استاندارد DOM Level 2 Events Specification، این وضعیت تغییر کرد و شامل هر دو مورد event capturing و event bubbling است و در حال حاضر تمام مرورگرهای مدرن این استاندارد را پیاده سازی کرده‌اند. بر اساس این استاندارد، زمانیکه رویدادی خلق می‌شود، فاز capturing آغاز می‌گردد که از شیء window شروع، سپس به شیء document منتشر می‌شود و این روند تا رسیدن به المانی که سبب بروز رخداد شده‌است ادامه پیدا می‌کند. پس از پایان فاز capturing، فاز جدید bubbling شروع می‌شود. در این فاز، رخداد از تمام والدین شیء هدف عبور می‌کند تا به شیء window برسد.
برای مثال اگر سند HTML ما چنین تعریفی را داشته باشد و بر روی المان «child of child of one» کلیک شده باشد:
   <!DOCTYPE html> 
   <html>
   <head>
     <title>event propagation demo</title>
   </head>
   <body>
     <section>
       <h1>nested divs</h1>
       <div>one
        <div>child of one
          <div>child of child of one</div>
        </div>
      </div>
    </section>
  </body>
  </html>
این رخداد در فاز capturing از این المان‌ها عبور می‌کند:
1.window
2.document
3.<html>
4.<body>
5.<section>
6.<div>one
7.<div>child of one
8.<div>child of child of one
و در فاز Bubbling از این المان‌ها:
9.<div>child of child of one
10.<div>child of one
11.<div>one
12.<section>
13.<body>
14.<html>
15.document
16.window
هرچند به دلایل تاریخی و همچنین عدم پشتیبانی jQuery از فاز capturing، بیشتر از فاز Bubbling به صورت پیش‌فرض در رخدادگردانی استفاده می‌شود. همچنین صدور رخداد از المانی که آن‌را ایجاد کرده‌است، بیشتر منطقی به نظر می‌رسد تا عکس آن.
البته باید درنظر داشت که jQuery از روش ارائه شده‌ی توسط مرورگر برای فاز Bubbling استفاده نمی‌کند و این مسیر را خودش مجددا محاسبه و رخدادگردان‌های این مسیر را به صورت دستی اجرا می‌کند. به همین جهت کارآیی آن نسبت به روش توکار و بومی مرورگرها کمتر است.


ایجاد رخدادهای DOM و صدور آن‌ها در jQuery

برای نمایش ایجاد و صدور رخدادهای DOM با و بدون jQuery، از قطعه کد HTML زیر استفاده می‌کنیم:
   <div>
     <button type="button">do something</button>
   </div>
 
  <form method="POST" action="/user">
     <label>Enter user name:
       <input name="user">
     </label>
     <button type="submit">submit</button>
  </form>
jQuery به همراه دو متد trigger و triggerHandler برای ایجاد و انتشار رخدادها در طول DOM است. متد trigger سبب ایجاد، صدور و انتشار یک رخداد به تمام والدهای شیء صادر کننده‌ی رخداد می‌شود. نوع این انتشار نیز bubbling است. متد triggerHandler، فقط بر روی المانی که فراخوانی می‌شود، عمل کرده و سبب انتشار این رخداد از طریق bubbling نمی‌شود:
   // submits the form 
   $('FORM').trigger('submit');
 
   // submits the form by clicking the button 
   $('BUTTON[type="submit"]').trigger('click');
 
   // focuses the text input 
   $('INPUT').trigger('focus');
 
  // removes focus from the text input 
  $('INPUT').trigger('blur');
در این مثال‌ها توسط متد trigger، به دو روش سبب submit یک فرم و همچنین در ابتدا سبب focus یک تکست باکس و سپس رفع آن شده‌ایم.
هرچند روش دومی نیز در jQuery API برای انجام همینکارها نیز پیش بینی شده‌است:
   // submits the form 
   $('FORM').submit();
 
   // submits the form by clicking the button 
   $('BUTTON[type="submit"]').click();
 
   // focuses the text input 
   $('INPUT').focus();
 
  // removes focus from the text input 
  $('INPUT').blur();
در اینجا به ازای هر رخداد، یک نام مستعار در jQuery API تدارک دیده شده‌است.

در ادامه فرض کنید یک دکمه داخل یک div قرار گرفته‌است و آن div نیز به همراه یک مدیریت کننده‌ی رخداد کلیک است. در این حالت اگر بخواهیم با کلیک بر روی دکمه سبب اجرای رویدادگردان div والد نشویم، می‌توان از متد triggerHandler استفاده کرد:
  // clicks the first button - the click event does not bubble 
  $('BUTTON[type="button"]').triggerHandler('click');


ایجاد رخدادهای DOM و صدور آن‌ها در جاوا اسکریپت (بدون استفاده از jQuery)

در web API مرورگرها، برای انجام بروز رخدادهای معادل مثالی که با jQuery مطرح شد، می‌توان متدهای بومی متناظر با این رخدادها را بر روی المان‌ها فراخوانی کرد:
   // submits the form 
   document.querySelector('FORM').submit();
 
   // submits the form by clicking the button 
   document.querySelector('BUTTON[type="submit"]').click();
 
   // focuses the text input 
   document.querySelector('INPUT').focus();
 
  // removes focus from the text input 
  document.querySelector('INPUT').blur();
قطعه کد فوق به علت استفاده‌ی از querySelector، با IE 8.0 و تمام مرورگرهای پس از آن سازگار است.
متدهای توکار و بومی click ،focus و blur بر روی تمام عناصر DOM که از اینترفیس HTMLElement مشتق شده باشند، وجود دارند. متد submit فقط بر روی المان‌هایی از نوع <form> وجود دارد و قابل فراخوانی است.
باید دقت داشت که فراخوانی متدهای click و submit از نوع bubbling است؛ اما متدهای focus و blur خیر. از این جهت که این دو رخداد فاز capturing را سبب می‌شوند.

متدهای یاد شده را توسط سازنده‌ی شیء Event و یا متد createEvent شیء document نیز می‌توان ایجاد کرد. یکی از کاربردهای آن، ارائه‌ی رفتاری سفارشی مانند triggerHandler جی‌کوئری است:
   var clickEvent;

   if (typeof Event === 'function') {
     clickEvent = new Event('click', {bubbles: false});
   }
   else {
       clickEvent = document.createEvent('Event');
      clickEvent.initEvent('click', false, true);
  }

  document.querySelector('BUTTON[type="button"]').dispatchEvent(clickEvent);
کار با سازنده‌ی شیء Event در تمام مرورگرهای جدید، منهای IE (تمام نگارش‌های آن) پشتیبانی می‌شود. در اینجا اگر این پشتیبانی وجود داشت، از خاصیت bubbles: false شیء Event استفاده می‌شود و اگر مرورگری قدیمی بود، از متد document.createEvent برای این منظور کمک گرفته می‌شود. در این حالت دومین پارامتر متد initEvent، همان bubbles است.


ایجاد و صدور رخدادهای سفارشی

فرض کنید در حال تهیه‌ی کتابخانه‌ای هستیم که افزودن و حذف آیتم‌ها را به یک گالری عکس ارائه می‌دهد. می‌خواهیم روشی را در اختیار مصرف کننده قرار دهیم تا بتواند به این رخدادهای سفارشی (غیر استانداردی که جزو W3C نیستند) گوش فرا دهد.
در جی‌کوئری برای ایجاد رخدادهای سفارشی به صورت زیر عمل می‌شود:
  // Triggers a custom "image-removed" element, 
  // which bubbles up to ancestor elements.
$libraryElement.trigger('image-removed', {id: 1});
در اینجا نیز صدور رخدادها همانند قبل و توسط همان متد trigger است. اما مشکلی که با آن وجود دارد این است که گوش فرا دهنده‌ی به این رخداد نیز باید توسط جی‌کوئری ارائه شود و خارج از این کتابخانه قابل دریافت و پیگیری نیست.
در خارج از جی‌کوئری و توسط web API استاندارد مرورگرها ایجاد و صدور رخدادهای سفارشی به همراه bubbling آن به صورت زیر است:
  var event = new CustomEvent('image-removed', {
    bubbles: true,
    detail: {id: 1}
  });
  libraryElement.dispatchEvent(event);
البته باید به‌خاطر داشته باشید این روش صرفا با مرورگرهای جدید (منهای تمام نگارش‌های IE) کار می‌کند. در اینجا اگر نیاز به ارائه‌ی راه حلی سازگار با IE نیز وجود داشت می‌توان از document.createEvent استفاده کرد:
  var event = document.createEvent('CustomEvent');
  event.initCustomEvent('image-removed', false, true, {id: 1});
  libraryElement.dispatchEvent(event);
و اگر بخواهیم بررسی وجود IE و یا پشتیبانی از CustomEvent را نیز قید کنیم، به قطعه کد زیر خواهیم رسید که با تمام مرورگرهای موجود کار می‌کند:
  var event;
 
   // If the `CustomEvent` constructor function is not supported, 
   // fall back to `createEvent` method. 
   if (typeof CustomEvent === 'function') {
     event = new CustomEvent('image-removed', {
       bubbles: true,
       detail: {id: 1}
     });
  }
  else {
      event = document.createEvent('CustomEvent');
      event.initCustomEvent('image-removed', false, true, {
        id: 1
      });
  }

  libraryElement.dispatchEvent(event);


گوش فرادادن به رخدادهای صادر شده، توسط jQuery

در جی‌کوئری با استفاده از متد on آن می‌توان به تمام رخدادهای استاندارد و همچنین سفارشی گوش فرا داد:
  $(window).on('resize', function() {
     // react to new window size 
  });
در ادامه برای حذف تمام گوش فرا دهنده‌های به رخداد resize می‌توان از متد off آن استفاده کرد:
  // remove all resize listeners - usually a bad idea 
  $(window).off('resize');
اما مشکلی را که این روش به همراه دارد، از کار انداختن تمام قسمت‌های دیگری است که هم اکنون به صدور این رخداد گوش فرا می‌دهند.
روش بهتر انجام اینکار، ذخیره‌ی ارجاعی به متدی است که قرار است این رویداد گردانی را انجام دهد:
  var resizeHandler = function() {
      // react to new window size 
  };

  $(window).on('resize', resizeHandler);

  // ...later 
  // remove only our resize handler 
  $(window).off('resize', resizeHandler);
و در آخر تنها این گوش فرا دهنده‌ی خاص را در صورت نیاز غیرفعال می‌کنیم و نه تمام گوش فرادهنده‌های سراسر برنامه را.

همچنین اگر یک گوش فراهنده‌ی به رخدادی تنها قرار است یکبار در طول عمر برنامه اجرا شود، می‌توان از متد one استفاده کرد:
$(someElement).one('click', function() {
    // handle click event 
});
پس از یکبار اجرای رخدادگردان کلیک در اینجا، از کلیک‌های بعدی صرفنظر خواهد شد.


گوش فرادادن به رخدادهای صادر شده، توسط جاوا اسکریپت خالص (یا همان web API مرورگرها)

ابتدایی‌ترین روش گوش فرادادن به رخدادها که از زمان آغاز معرفی آن‌ها در دسترس بوده‌است، روش تعریف inline آن‌ها است:
  <button onclick="handleButtonClick()">click me</button>
در اینجا متد رویدادگردان به یکی از ویژگی المان انتساب داده می‌شود. مشکل این روش، نیاز به سراسری تعریف کردن متد handleButtonClick است و دیگر نمی‌توان آن‌را در فضای نامی خاص و یا سفارشی قرار داد.
روش دیگر ثبت رویدادگردان click، انتساب متد آن به خاصیت رخداد متناظری در آن المان ویژه است:
  buttonEl.onclick = function() {
    // handle button click 
  };
مزیت این روش، عدم نیاز به استفاده‌ی از متدهای سراسری است.
البته باید دقت داشت که یکی از دو روش یاد شده را می‌توانید استفاده کنید. در اینجا آخرین رویدادگردان متصل شده‌ی به المان، همواره تمام نمونه‌های موجود دیگر را بازنویسی می‌کند.
اگر نیاز به معرفی رویدادگردان‌های متعددی برای یک المان در ماژول‌های مختلف برنامه وجود داشت، از زمان IE 9.0 به بعد، متد addEventListener برای این منظور تدارک دیده شده‌است و syntax آن بسیار شبیه به متد on جی‌کوئری است:
  buttonEl.addEventListener('click', function() {
    // handle button click 
  });
در این حالت دیگر مشکل نیاز به متدهای سراسری و یا عدم امکان تعریف بیش از یک رویدادگردان خاص برای المانی مشخص، دیگر وجود ندارد.
برای نمونه معادل قطعه کد جی‌کوئری که پیشتر با متد on نوشتیم، با جاوا اسکریپت خالص به صورت زیر است:
  window.addEventListener('resize', function() {
    // react to new window size 
  });
در اینجا برای حذف یک رویدادگردان می‌توان از متد removeEventListener استفاده کرد. تفاوت مهم آن با متد off جی‌کوئری این است که در اینجا حتما باید مشخص باشد کدام رویدادگردان را می‌خواهید حذف کنید:
  var resizeHandler = function() {
      // react to new window size 
  };

  window.addEventListener('resize', resizeHandler);

  // ...later 
  // remove only our resize handler 
  window.removeEventListener('resize', resizeHandler);
یعنی روش حذف رویدادگردان‌ها در اینجا شبیه به مثال دومی است که برای متد off جی‌کوئری ارائه کردیم. ابتدا باید ارجاعی را به متد رویدادگردان تهیه کنیم و سپس بر اساس این ارجاع، امکان حذف آن وجود خواهد داشت.
در اینجا حتی امکان تعریف متد one جی‌کوئری نیز پیش بینی شده‌است (البته جزو استانداردهای جدید وب از سال 2016 است):
  someElement.addEventListener('click', function(event) {
     // handle click event 
  }, { once: true });
اگر بخواهیم متد one سازگار با مرورگرهای قدیمی‌تر را نیز ارائه کنیم، چنین شکلی را پیدا می‌کند:
  var clickHandler = function() {
    // handle click event 
    // ...then unregister handler 
    someElement.removeEventListener('click', clickHandler);
  };
  someElement.addEventListener('click', clickHandler);
در اینجا پس از بروز رخداد، کار removeEventListener آن به صورت خودکار صورت می‌گیرد.


کنترل انتشار رخدادها

فرض کنید می‌خواهیم جلوی انتخاب المان‌های صفحه مانند تصاویر و متن را توسط ماوس بگیریم. روش انجام اینکار با jQuery به صورت زیر است:
$(window).on('mousedown', function(event) {
    event.preventDefault();
});
و یا توسط web API مرورگرها به این صورت:
  window.addEventListener('mousedown', function(event) {
    event.preventDefault();
  });
مطابق «W3C DOM Level 3 Events specification» عملکرد پیش‌فرض رخداد mousedown با انتخاب متون و یا کشیدن و رها کردن المان‌ها آغاز می‌شود. متد preventDefault یکی از متدهای شیء event است که به رویدادگردان‌های تعریف شده ارسال می‌شود و توسط آن عملکرد پیش‌فرض آن رخداد لغو می‌شود.

برای جلوگیری کردن از انتشار رخدادی مانند click جهت رسیدن به سایر رویدادگردان‌های ثبت شده‌ی در بین راه فاز bubbling، می‌توان از متد stopPropagation استفاده کرد. روش انجام اینکار در جی‌کوئری:
  $someElement.on('click', function(event) {
      event.stopPropagation();
  });
البته jQuery صرفا فاز انتشار از نوع bubbling را پشتیبانی می‌کند.
و با web Api جهت جلوگیری از انتشار رخدادها در فاز capturing (این تنها راه مدیریت فاز capturing است):
  // stop propagation during capturing phase 
  someElement.addEventListener('click', function(event) {
      event.stopPropagation();
  }, true);
و یا استفاده از web API برای جلوگیری از انتشار رخدادها در فاز bubbling:
  // stop propagation during bubbling phase 
  someElement.addEventListener('click', function(event) {
      event.stopPropagation();
  });
البته باید درنظر داشت که متد stopPropagation از انتشار رخدادها به سایر گوش فرا دهنده‌های همان المان صادر کننده‌ی رخداد جلوگیری نمی‌کند. برای این منظور باید از متد stopImmediatePropagation استفاده کرد؛ در جی‌کوئری:
  $someElement.on('click', function(event) {
      event.stopImmediatePropagation();
  });
و توسط web API مرورگرها:
  someElement.addEventListener('click', function(event) {
      event.stopImmediatePropagation();
  });

یک نکته: در این حالت اگر متد رویدادگردانی مقدار false را برگرداند، به معنای فراخوانی هر دوی متد preventDefault و stopPropagation است.


ارسال اطلاعات به رویدادگردان‌ها

روش ارسال اطلاعات اضافی به رویداد گردان‌ها در جی‌کوئری به صورت زیر است:
  $uploaderElement.trigger('uploadError', {
    filename: 'picture.jpeg'
  });
و رویدادگردان گوش فرا دهنده‌ی به آن، به این نحو می‌تواند به filename دسترسی پیدا کند:
  $uploaderParent.on('uploadError', function(event, data) {
     showAlert('Failed to upload ' + data.filename);
  });
در اینجا دومین پارامتر تعریف شده، امکان دسترسی به تمام خواص سفارشی ارسالی را میسر می‌کند.

روش انجام اینکار با web API مرورگرها به صورت زیر است:
   // send the failed filename w/ an error event
  var event = new CustomEvent('uploadError', {
     bubbles: true,
     detail: {filename: 'picture.jpeg'}
   });
   uploaderElement.dispatchEvent(event);
 
   // ...and this is a listener for the event 
   uploaderParent.addEventListener('uploadError', function(event) {
      showAlert('Failed to upload ' + event.detail.filename);
  });
این روش با تمام مرورگرهای مدرن (منهای تمام نگارش‌های IE) کار می‌کند و روش دسترسی به خاصیت detail سفارشی تعریف و ارسال شده، از طریق همان خاصیت event ارسالی به رویدادگردان است.
و اگر می‌خواهید از IE هم پشتیبانی کنید، روش جایگزین کردن شیء CustomEvent با createEvent به صورت زیر است:
  // send the failed filename w/ an error event 
   var event = document.createEvent('CustomEvent');
   event.initCustomEvent('uploadError', true, true, {
     filename: 'picture.jpeg'
   });
   uploaderElement.dispatchEvent(event);
 
   // ...and this is a listener for the event 
   uploaderParent.addEventListener('uploadError', function(event) {
    showAlert('Failed to upload ' + event.detail.filename);
  });


متوجه شدن زمان بارگذاری یک شیء در صفحه

در حین توسعه‌ی برنامه‌های وب، با این نوع سؤالات زیاد مواجه خواهید شد: چه زمانی تمام و یا بعضی از المان‌های صفحه کاملا بارگذاری و رندر شده‌اند؟
پاسخ به این نوع سؤالات در W3C UI Events specification توسط رویداد استاندارد load داده شده‌است.

- چه زمانی تمام المان‌های موجود در صفحه کاملا بارگذاری و رندر شده و همچنین شیوه‌نامه‌های تعریف شده نیز به آن‌ها اعمال گردیده‌اند؟
روش انجام اینکار با jQuery:
  $(window).on('load', function() {
    // page is fully rendered 
  });
و توسط web API بومی مرورگرها که بسیار مشابه نمونه‌ی jQuery است:
  window.addEventListener('load', function() {
    // page is fully rendered 
  });

- چه زمانی markup استاتیک صفحه‌ی جاری در جای خود قرار گرفته‌اند؟
اهمیت این موضوع، به دسترسی به زمان مناسب و امن ایجاد تغییرات در DOM بر می‌گردد. برای این منظور رویداد استاندارد DOMContentLoaded پیش‌بینی شده‌است که زودتر از رویداد load، در دسترس برنامه نویس قرار می‌گیرد. در جی‌کوئری توسط یکی از دو روش معروف زیر به رویداد یاد شده دسترسی خواهید داشت:
  $(document).ready(function() {
    // markup is on the page 
  });

  //or
  $(function() {
    // markup is on the page 
  });
و معادل web API آن در تمام مرورگرهای جدید، همان تعریف رویدادگردانی برای DOMContentLoaded استاندارد است:
  document.addEventListener('DOMContentLoaded', function() {
    // markup is on the page 
  });

یک نکته: بهتر است این تعریف web API را پیش از تگ‌های <link> قرار دهید. زیرا بارگذاری آن‌ها، اجرای هر نوع اسکریپتی را تا زمان پایان عملیات، سد می‌کند.

- چه زمانی المانی خاص در صفحه بارگذاری شده‌است و چه زمانی بارگذاری یک المان با شکست مواجه شده‌است؟
در جی‌کوئری توسط بررسی رویدادهای load و error می‌توان به وضعیت نهایی بارگذاری المان‌هایی خاص دسترسی یافت:
   $('IMG').on('load', function() {
     // image has successfully loaded 
   });
 
   $('IMG').on('error', function() {
     // image has failed to load 
   });
روش انجام اینکار با web API مرورگرها نیز یکی است:
  document.querySelector('IMG').addEventListener('load', function() {
    // image has successfully loaded 
  });

  document.querySelector('IMG').addEventListener('error', function() {
    // image has failed to load 
  });

- جلوگیری از ترک اتفاقی صفحه‌ی جاری
گاهی از اوقات نیاز است برای از جلوگیری از تخریب صفحه‌ی جاری و از دست رفتن اطلاعات ذخیره نشده‌ی کاربر، اگر بر روی دکمه‌ی close بالای صفحه کلیک کرد و یا کاربر به اشتباه به صفحه‌ی دیگری هدایت شد، جلوی اینکار را بگیریم. برای این منظور رخداد استاندارد beforeunload درنظر گرفته شده‌است. روش استفاده‌ی از این رویداد در جی‌کوئری:
  $(window).on('beforeunload', function() {
    return 'Are you sure you want to unload the page?';
  });
و در web API مرورگرها:
  window.addEventListener('beforeunload', function(event) {
    var message = 'Are you sure you want to unload the page?';
    event.returnValue = message;
    return message;
  });
در حالت web API بعضی از مرورگرها از نتیجه‌ی متد استفاده می‌کنند و بعضی دیگر از مقدار خاصیت event.returnValue. به همین جهت هر دو مورد در اینجا مقدار دهی شده‌اند.
مطالب
اضافه کردن Net 4.5. و بالاتر به پروژه ستاپ ویژوال استودیو 2010
در این مطلب یک ترفند ساده و سریع برای دوستانی که می‌خواهند از ویژوال استودیو 2010 برای ساختن برنامه‌ی Setup  پروژه‌های خود استفاده کنند، آورده می‌شود.
اگر برای ساخت برنامه‌های نصب خود بخواهید از ویژوال استودیو 2010 استفاده کنید و ورژن دات نت برنامه شما بالا‌تر از 4 باشد، متوجه خواهید شد که در قسمت  prerequisites، ورژن دات نت مورد نظر شما وجود ندارد.
برای اضافه کردن net 4.5. و بالاتر به برنامه‌ی نصب خود باید یک Bootstrapper ایجاد کرده و به Bootstrapper Package  های موجود در ویندوز اضافه نمایید. 
در  اینجا نحوه ایجاد و استفاده از Bootstrapper  توضیح داده شده است. اما برای اینکه نخواهید درگیر ساخت XML manifests برای Net 4.5. شوید، یک راه حل ساده‌تر وجود دارد و آ ن استفاده از Bootstrapper های ساخته شده هنگام نصب ورژن‌های بالاتر ویژوال استودیو که شامل ورژن‌های مورد نیاز از دات نت نیز هستند می‌باشد.
برای این کار کافی است به مسیر زیر بر روی سیستم مراجعه نمایید:
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\Bootstrapper\Packages 
در مسیر فوق، فولدرهای DotNetFX451 ،DotNetFX45 و DotNetFX452 را مشاهده می‌کنید که شامل فایل‌های مورد نیاز برای اضافه کردن  Bootstrapper به ویژوال استادیو 2010 است.
برای اینکار فولدر مربوطه را کپی نمایید و در مسیر زیر قرار دهید:
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages 
فقط توجه داشته باشید که باید فایل نصب دات نت (مثلا برای دات نت 4.5 فایل dotNetFx45_Full_x86_x64.exe ) را به آن اضافه نمایید.
حال اگر ویژوال استادیو 2010 را باز کنید و یک پروژه ستاپ ایجاد نمایید می‌بینید که ورژن مورد نظر به قسمت prerequisites اضافه شده است.
 
نظرات مطالب
Identity و مباحث مربوطه (قسمت دوم) نحوه بدست آوردن مقادیر Identity
- خیر. چندین نوع استراتژی برای تعیین PK وجود دارند که یکی از آن‌ها فیلدهای Identity است و این تنها روش و الزاما بهترین روش نیست.
- مثلا زمانیکه با ORMها کار می‌کنید استفاده از فیلدهای Identity در حین ثبت تعداد بالایی از رکوردها مشکل ساز می‌شوند. چون این فیلدها تحت کنترل دیتابیس هستند و نه برنامه، ORM نیاز دارد پس از هربار Insert یکبار آخرین Id را از بانک اطلاعاتی واکشی کند. همین مساله یعنی افت سرعت در تعداد بالای Insertها (چون یکبار کوئری Insert باید ارسال شود و یکبار هم یک Select اضافی دوم برای دریافت Id تولیدی توسط دیتابیس).
- روش دوم تعیین PK استفاده از نوع Guid است. در این حالت، هم مشکل حذف رکوردها و خالی شدن یک شماره را در این بین ندارید و هم چون عموما تحت کنترل برنامه است، سرعت کار کردن با آن بالاتر است. فقط تنها مشکل آن زیبا نبودنش است در مقایسه با یک عدد ساده فیلدهای Identity.

در مورد فیلدهای Identity، تغییر شماره Id به صلاح نیست چون:
الف) همانطور که عنوان کردید روابط بین جداول را به هم خواهد ریخت.
ب) در یک وب سایت و یا هر برنامه‌ای، کلا آدرس‌ها و ارجاعات قدیمی را از بین می‌برد. مثلا فرض کنید شماره این مطلب 1381 است و شما آن‌را یادداشت کرده‌اید. در روزی بعد، برنامه نویس شماره Id‌ها را کلا ریست کرده. در نتیجه یک هفته بعد شما به شماره 1381 ایی خواهید رسید که تطابقی با مطلب مدنظر شما ندارد (حالا فرض کنید که این عدد شماره پرونده یک شخص بوده یا شماره کاربری او و نتایج و خسارات حاصل را درنظر بگیرید).
ج) این خوب است که در بین اطلاعات یک ردیف خالی وجود دارد. چون بر این اساس می‌توان بررسی کرد که آیا واقعا رکوردی حذف شده یا خیر. گاهی از اوقات کاربران ادعا می‌کنند که اطلاعات ارسالی آن‌ها نیست در حالیکه نبود این رکوردها به دلیل حذف بوده و نه عدم ثبت آن‌ها. با بررسی این Id‌ها می‌شود با کاربران در این مورد بحث کرد و پاسخ مناسبی را ارائه داد.

و اگر شماره‌ای که به کاربر نمایش می‌دهید فقط یک شماره ردیف است (و از این لحاظ می‌خواهید که حتما پشت سرهم باشد)، بهتر است یک View جدید ایجاد کنید تا این Id خود افزاینده را تولید کند (بدون استفاده از pk جدول).


پ.ن.
هدف من از این توضیحات صرفا عنوان این بود که به PK به شکل یک فیلد read only نگاه کنید. این دقیقا برخوردی است که Entity framework با این مفهوم دارد و صحیح است و اصولی. اگر در یک کشور هر روزه عده‌ای به رحمت ایزدی می‌روند به این معنا نیست که سازمان ثبت احوال باید شماره شناسنامه‌ها را هر ماه ریست کند!

مطالب
آموزش MDX Query - قسمت سوم - نصب Adventure Work DW و تهیه ی پایگاه داده ی Multidimensional Database توسط SSAS

برای ادامه دادن این سری از مقالات آموزش MDX Query نیاز می‌باشد که پایگاه داده‌ی Advwnture Work DW را نصب کرده و سپس توسط SSAS عمل Deploy را انجام دهیم تا پایگاه داده‌ی Multidimensional Database توسط SSAS ساخته شود .

در ابتدا می‌بایست فایل نصب پایگاه داده ی  Advwnture Work را دانلود نمایید برای این منظور به آدرس زیر رفته و فایل AdventureWorks2008R2_SR1.exe  را دانلود نمایید .

  http://www.general-files.biz/download/gs4ac37d18h17i0/AdventureWorks2008R2_SR1.exe.html

یا به آدرس زیر مراجعه کنید

https://msftdbprodsamples.codeplex.com/releases/view/59211 

نیاز می‌باشد قبل از شروع به نصب نرم افزار SQL Server Management Studio را ببندید.

سپس مراحل زیر را انجام دهید.

1. فایل AdventureWorks2008R2_SR1.exe را اجرا نمایید. 

2.  کمی صبر کنید تا صفحه‌ی زیر نمایش داده شود. و گزینه‌ی I Accept … را انتخاب نماید و دکمه‌ی Next را بزنید. 

3. در صورتی که از ویندوز 8 استفاده نماید احتمال دارد با خطای زیر مواجه شوید در این صورت به قسمت روش نصب در ویندوز 8 در ادامه‌ی این مقاله مراجعه کنید . 

4. در صورتی که از ویندوز‌های Server 2003, XP , Win7 استفاده کنید صفحه‌ی زیر را خواهید دید. در این صفحه ابتدا Instance مربوط به SQL سرور خود را انتخاب نماید (در صورت داشتن چندین Instance روی سرور پایگاه داده) سپس مسیر نصب فایل‌های Sample را مشخص نمایید (بعدا از همین مسیر اقدام به Deploy کردن پایگاه داده‌ی Multidimensional خواهیم کرد) و پیش فرض‌ها را بپذیرید و دکمه‌ی Install را بزنید. 

5. کمی صبر کنید تا نصب انجام گردد. و در انتها کلید Finish را بزنید. 

پس از مراحل بالا (به جز ویندوز 8) با باز کردن نرم افزار SQL Server Management Studio و اتصال به سرویس Database Engine در قسمت Database تصویر زیر را خواهید دید (البته امکان دارد شما از قبل دارای پایگاه داده‌های شخصی بوده باشید که بنابر این آنها نیز در لیست شما وجود خواهند داشت)  

همچنین شما می‌توانید از پنجره‌ی Object Explorer در قسمت Connect اقدام به اتصال به سرویس SSAS نموده . 

و در پنجره‌ی باز شده Server Name را انتخاب نمایید (با توجه به اینکه شما در حال حاضر می‌خواهید به SSAS موجود در سیستم Local متصل شوید ، بنابر این انتخاب سرور Local با وارد کردن کاراکتر (.) انجام می‌شود.) 

بعد از اتصال شکل زیر را خواهید داشت و در شاخه‌ی Database همچنان هیچ Multidimensional Database ی نخواهید داشت.(بعد از عمل Deploy که در ادامه آموزش داده خواهد شد پایگاه داده‌ی Multidimensional ساخته می‌شود.) 

 

تنها روشی که تاکنون برای  نصب پایگاه داده‌ی Adventure Work DW برروی ویندوز 8 یافته ام (البته کمی غیر حرفه ای می‌باشد.) به صورت زیر می‌باشد.

فایل بالا را ( AdventureWorks2008R2_SR1.exe ) روی سیستم عامل‌های ( Server 2003,XP,Win 7 ) نصب کرده (به عنوان یک سیستم عامل واسط) و سپس سرویس Database Engine را Stop کرده و فایل‌های پایگاه داده را به سیستم عامل ویندوز 8 انتقال داده و به صورت دستی Restore کنیم.

مراحل ایجاد پایگاه داده‌ی Multidimensional در ویندوز‌های مختلف ، یکسان می‌باشد.

 

بعد از نصب پایگاه داده‌ی Adventure Work DW باید به شاخه‌ی نصب Sample بروید (همان مسیری که در مراحل نصب وارد کردیم و البته آدرس پیش فرض آن C:\Program Files\Microsoft Sql Server\100\Tools\Sample می‌باشد.)

(در صورتی که در ویندوز 8 مراحل نصب را دنبال می‌کنید مسیر زیر را در سیستم خود درست نمایید و فایل‌ها و پوشه‌های موجود در مسیر فوق در سیستم عامل واسط (همان سیستم عاملی که فایل نصب بر روی آن نصب شده است) را به درون آن انتقال دهید.)

سپس به زیر شاخه‌ی \ AdventureWorks 2008R2 Analysis Services Project\enterprise بروید و فایل Adventure Works.sln را با Visual Studio 2010 باز کنید.

احتمال دارد که نیاز باشد روی کل شاخه‌ی enterprise در قسمت Security کاربر جاری را Add کنید و به آن دسترسی Full Control بدهید تا عملیات Convert این پروژه به درستی انجام شود.

پس از باز کردن پروژه در Visual Studio 2010 صفحه ای مطابق تصویر زیر در پنجره‌ی Solution Explorer خواهید دید. 

به هیچ عنوان نگران ساختار این پروژه نباشید ، زیرا در مقاله‌های آیند شرح کاملی در این خصوص کار با Business Intelligence Management Studio خواهم داد. فعلا هدف ما ایجاد پایگاه داده‌ی Multidimensional  می باشد.

 

برای ساخت پایگاه داده‌ی Multidimensional مراحل زیر را دنبال نمایید.

1. در ابتدا روی پروژه کلیک راست کرده و گزینه‌ی Properties را انتخاب نمایید. 

2. در قسمت Configuration Properties  منوی Deployment را انتخاب کرده و اطمینان حاصل کنید که سرور شما LocalHost و نام پایگاه داده شما Adventure Works DW 2008R2  باشد. 

3. سپس روی Adventure Works.ds کلیک راست کنید تا تنظیمات Connection String  به DW را انجام دهیم. مطابق شکل زیر 

4. سپس در پنجره‌ی باز شده دکمه‌ی Edit  را بزنید . 

5. و در صفحه باز شده تنظیمات زیر را مطابق تصویر زیر انجام دهید. دقت داشته باشید که تغییرات را از بالا به پایین باید انجام دهید و قبل از زدن دکمه‌ی OK حتما Test Connection را بزنید تا از صحت تنظیمات مطمعا شوید. 

6. سپس دو بار دکمه‌ی OK را در دوصفحه کلیک کنید. (بعد از این مراحل شما آماده‌ی Deploy کردن می‌باشد)

7. در ابتدا پروژه را Build نمایید ( CTRl + Shift + B )  و اطمینان حاصل کنید که Build  با موفقیت انجام می‌شود.

8. در انتها برروی نام پروژه کلیک راست نمایید و گزینه‌ی Deploy را انتخاب نمایید. فرایند Deploy کردن می‌تواند کمی زمان بر باشد بنابر این شکیبا باشید و در انتها پیام Deployment Completed Successfully را دریافت خواهید کرد. 

9. حال به SQL Server Management Studio بروید و به سرویس SSAS کانکت شوید . در قسمت DataBase یک پایگاه داده با نام Adventure Works DW 2008R2 مشاهده خواهید کرد . 

 

به شما تبریک می‌گویم اینک شما یک پایگاه داده‌ی Multidimensional را ساخته اید .

در مقاله‌ی بعدی توضیحاتی در خصوص BIMS (Business Intelligence Management Studio) خواهم داد و همچنین اولین MDX Query  را خواهیم نوشت.

 

اشتراک‌ها
دریافت Windows Server 2019

مایکروسافت امروز ویندوز سرور 2019 خودش رو در اختیار مشتریانش قرار داد...

دریافت  Windows Server 2019
اشتراک‌ها
ویندوز 10 ارائه شد

مایکروسافت امروز ویندوز ۱۰ خودش رو به صورت رسمی به مشتریانش ارائه کرد...

ویندوز 10 ارائه شد
نظرات مطالب
EF Code First #12
این مساله ارتباطی به الگوی واحد کار ندارد. شما به عنوان برنامه نویس باید پس از بررسی تشخیص دهید که آیا خطر mass assignment در حین کار با شیء در حال دریافت از کاربر (هر نامی که دارد)، برنامه را تهدید می‌کند یا خیر. همچنین آیا View در حال استفاده نیاز به چند Model برای کار کردن دارد یا خیر. در این حالات استفاده از ViewModel توصیه می‌شود. در غیراینصورت استفاده از Domain modelها نه مشکل امنیتی را به همراه خواهند داشت و نه برای صرفا گزارش گیری، کم و کسری دارند.