Bundle, transpile, install and run JavaScript & TypeScript projects — all in Bun
source on github
<!DOCTYPE html> <html> <head> <link rel="stylesheet" media="all" type="text/css" href="http://trentrichardson.com/Impromptu/jquery-impromptu.css" /> <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.0.min.js"></script> <script type="text/javascript" src="http://trentrichardson.com/Impromptu/jquery-impromptu.js"></script> </head> <body> <button class="show">ShowPrompt</button> <script type="text/javascript"> $(function(){ $(".show").click(function(e){ $.prompt("Hello World!"); }); }); </script> </body> </html>
<!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>
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
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
<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>
// 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');
// 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();
// clicks the first button - the click event does not bubble $('BUTTON[type="button"]').triggerHandler('click');
// 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();
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);
// Triggers a custom "image-removed" element, // which bubbles up to ancestor elements. $libraryElement.trigger('image-removed', {id: 1});
var event = new CustomEvent('image-removed', { bubbles: true, detail: {id: 1} }); libraryElement.dispatchEvent(event);
var event = document.createEvent('CustomEvent'); event.initCustomEvent('image-removed', false, true, {id: 1}); libraryElement.dispatchEvent(event);
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);
$(window).on('resize', function() { // react to new window size });
// 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);
$(someElement).one('click', function() { // handle click event });
<button onclick="handleButtonClick()">click me</button>
buttonEl.onclick = function() { // handle button click };
buttonEl.addEventListener('click', function() { // handle button click });
window.addEventListener('resize', function() { // react to new window size });
var resizeHandler = function() { // react to new window size }; window.addEventListener('resize', resizeHandler); // ...later // remove only our resize handler window.removeEventListener('resize', resizeHandler);
someElement.addEventListener('click', function(event) { // handle click event }, { once: true });
var clickHandler = function() { // handle click event // ...then unregister handler someElement.removeEventListener('click', clickHandler); }; someElement.addEventListener('click', clickHandler);
$(window).on('mousedown', function(event) { event.preventDefault(); });
window.addEventListener('mousedown', function(event) { event.preventDefault(); });
$someElement.on('click', function(event) { event.stopPropagation(); });
// stop propagation during capturing phase someElement.addEventListener('click', function(event) { event.stopPropagation(); }, true);
// stop propagation during bubbling phase someElement.addEventListener('click', function(event) { event.stopPropagation(); });
$someElement.on('click', function(event) { event.stopImmediatePropagation(); });
someElement.addEventListener('click', function(event) { event.stopImmediatePropagation(); });
$uploaderElement.trigger('uploadError', { filename: 'picture.jpeg' });
$uploaderParent.on('uploadError', function(event, data) { showAlert('Failed to upload ' + data.filename); });
// 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); });
// 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); });
$(window).on('load', function() { // page is fully rendered });
window.addEventListener('load', function() { // page is fully rendered });
$(document).ready(function() { // markup is on the page }); //or $(function() { // markup is on the page });
document.addEventListener('DOMContentLoaded', function() { // markup is on the page });
$('IMG').on('load', function() { // image has successfully loaded }); $('IMG').on('error', function() { // image has failed to load });
document.querySelector('IMG').addEventListener('load', function() { // image has successfully loaded }); document.querySelector('IMG').addEventListener('error', function() { // image has failed to load });
$(window).on('beforeunload', function() { return 'Are you sure you want to unload the page?'; });
window.addEventListener('beforeunload', function(event) { var message = 'Are you sure you want to unload the page?'; event.returnValue = message; return message; });
نوع | دکمه | Shortcut | توضیحات |
اجرای مجدد | Shift + F18 | Stack فعلی را مجدد اجرا میکند. (Stack: لیستی از توابع به ترتیبی که با فراخوانی آنها تابع جاری فراخونی شده است. در مقاله بعدی توضیحات بیشتری ارائه خواهد شد.) | |
ادامه | F8 | اجرای برنامه را (تا Break Point بعدی) ادامه میدهد. | |
وارد شدن | F11 | در صورت رسیدن به یک تابع، با زدن این دکمه دیباگر وارد بندهی آن تابع میشود. | |
رد شدن | F10 | اجرای برنامه را در سطح (Scope) فعلی ادامه میدهد. مشابه قبلی وارد تابع نمیشود. | |
خارج شدن | Shift + F11 | کنترل به تابعی که تابع جاری را فراخوانی کرده است بازمیگردد. روشی سودمند زمانی که هنگام خطایابی وارد کدهای jQuery یا مثل آن میشوید :) |
using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace Mvc4TwitterBootStrapTest.Models { public class User { [DisplayName("نام")] [Required(ErrorMessage="لطفا نام را تکمیل کنید")] public string Name { set; get; } [DisplayName("نام خانوادگی")] [Required(ErrorMessage = "لطفا نام خانوادگی را تکمیل کنید")] public string LastName { set; get; } } }
using System.Web.Mvc; using Mvc4TwitterBootStrapTest.Models; namespace Mvc4TwitterBootStrapTest.Controllers { public class HomeController : Controller { [HttpGet] public ActionResult Index() { return View(); } [HttpPost] public ActionResult Index(User user) { if (this.ModelState.IsValid) { if (user.Name != "Vahid") { this.ModelState.AddModelError("", "لطفا مشکلات را برطرف کنید!"); this.ModelState.AddModelError("Name", "نام فقط باید وحید باشد!"); return View(user); } // todo: save ... return RedirectToAction("Index"); } return View(user); } } }
@model Mvc4TwitterBootStrapTest.Models.User @{ ViewBag.Title = "تعریف کاربر"; } @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { @class = "form-horizontal" })) { @Html.ValidationSummary(true, null, new { @class = "alert alert-error alert-block" }) <fieldset> <legend>تعریف کاربر</legend> <div class="control-group"> @Html.LabelFor(x => x.Name, new { @class = "control-label" }) <div class="controls"> @Html.TextBoxFor(x => x.Name) @Html.ValidationMessageFor(x => x.Name, null, new { @class = "help-inline" }) </div> </div> <div class="control-group"> @Html.LabelFor(x => x.LastName, new { @class = "control-label" }) <div class="controls"> @Html.TextBoxFor(x => x.LastName) @Html.ValidationMessageFor(x => x.LastName, null, new { @class = "help-inline" }) </div> </div> <div class="form-actions"> <button type="submit" class="btn btn-primary"> ارسال</button> </div> </fieldset> }
@section javaScript { <script type="text/javascript"> $.validator.setDefaults({ highlight: function (element, errorClass, validClass) { if (element.type === 'radio') { this.findByName(element.name).addClass(errorClass).removeClass(validClass); } else { $(element).addClass(errorClass).removeClass(validClass); $(element).closest('.control-group').removeClass('success').addClass('error'); } $(element).trigger('highlated'); }, unhighlight: function (element, errorClass, validClass) { if (element.type === 'radio') { this.findByName(element.name).removeClass(errorClass).addClass(validClass); } else { $(element).removeClass(errorClass).addClass(validClass); $(element).closest('.control-group').removeClass('error').addClass('success'); } $(element).trigger('unhighlated'); } }); $(function () { $('form').each(function () { $(this).find('div.control-group').each(function () { if ($(this).find('span.field-validation-error').length > 0) { $(this).addClass('error'); } }); }); }); </script> }
public override Task OnDisconnected(bool stopCalled) { if (stopCalled) { // We know that Stop() was called on the client, // and the connection shut down gracefully. } else { // This server hasn't heard from the client in the last ~35 seconds. // If SignalR is behind a load balancer with scaleout configured, // the client may still be connected to another SignalR server. } return base.OnDisconnected(stopCalled); }
window.setFocus = function (element) { element.focus(); };
<input @ref="@ReferenceToInputControl" />
<input _bl_bc0f34fa-16bd-4687-a8eb-9e3838b5170d="">
private ElementReference ReferenceToInputControl;
await JSRuntime.InvokeVoidAsync("setFocus", ReferenceToInputControl);
public class Category { public int CategoryId { set; get; } public string CategoryName { set; get; } [JsonIgnore] public IList<Product> Products { set; get; } } public class Product { public int ProductId { set; get; } public string ProductName { set; get; } }
using System.Linq; using System.Text; using System.Web.Mvc; using KendoUI12.Models; using Newtonsoft.Json; namespace KendoUI12.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); // shows the page. } [HttpGet] public ActionResult GetCategories() { return new ContentResult { Content = JsonConvert.SerializeObject(CategoriesDataSource.Items), ContentType = "application/json", ContentEncoding = Encoding.UTF8 }; } [HttpGet] public ActionResult GetProducts(int categoryId) { var products = CategoriesDataSource.Items .Where(category => category.CategoryId == categoryId) .SelectMany(category => category.Products) .ToList(); return new ContentResult { Content = JsonConvert.SerializeObject(products), ContentType = "application/json", ContentEncoding = Encoding.UTF8 }; } } }
<!--نحوهی راست به چپ سازی --> <div class="k-rtl k-header demo-section"> <label for="categories">گروهها: </label><input id="categories" style="width: 270px" /> <label for="products">محصولات: </label><input id="products" disabled="disabled" style="width: 270px" /> </div> @section JavaScript { <script type="text/javascript"> $(function () { $("#categories").kendoDropDownList({ optionLabel: "انتخاب گروه...", dataTextField: "CategoryName", dataValueField: "CategoryId", dataSource: { transport: { read: { url: "@Url.Action("GetCategories", "Home")", dataType: "json", contentType: 'application/json; charset=utf-8', type: 'GET' } } } }); $("#products").kendoDropDownList({ autoBind: false, // won’t try and read from the DataSource when it first loads cascadeFrom: "categories", // the id of the DropDown you want to cascade from optionLabel: "انتخاب محصول...", dataTextField: "ProductName", dataValueField: "ProductId", dataSource: { // When the serverFiltering is disabled, then the combobox will not make any additional requests to the server. serverFiltering: true, // the DataSource will send filter values to the server transport: { read: { url: "@Url.Action("GetProducts", "Home")", dataType: "json", contentType: 'application/json; charset=utf-8', type: 'GET', data: function () { return { categoryId: $("#categories").val() }; } } } } }); }); </script> <style scoped> .demo-section { width: 100%; height: 100px; } </style> }
//برای ذخیره مقادیر از ساختار نام و مقدار استفاده میکنیم که نامها را اینجا ثبت کرده ام var Variables={ posts:"posts", postsComments:"postsComments", shares:"shares", sharesComments:"sharesComments", } //برای ذخیره زمان آخرین تغییر سایت برای هر یک از مطالب به صورت جداگانه نیاز به یک ساختار نام و مقدار است که نامها را در اینجا ذخیره کرده ام var DateContainer={ posts:"dtposts", postsComments:"dtpostsComments", shares:"dtshares", sharesComments:"dtsharesComments", interval:"interval" } //برای نمایش پیامها به کاربر var Messages={ SettingsSaved:"تنظیمات ذخیره شد", SiteUpdated:"سایت به روز شد", PostsUpdated:"مطلب ارسالی جدید به سایت اضافه شد", CommentsUpdated:"نظری جدیدی در مورد مطالب سایت ارسال شد", SharesUpdated:"اشتراک جدید به سایت ارسال شد", SharesCommentsUpdated:"نظری برای اشتراکهای سایت اضافه شد" } //لینکهای فید سایت var Links={ postUrl:"https://www.dntips.ir/feeds/posts", posts_commentsUrl:"https://www.dntips.ir/feeds/comments", sharesUrl:"https://www.dntips.ir/feed/news", shares_CommentsUrl:"https://www.dntips.ir/feed/newscomments" } //لینک صفحات سایت var WebLinks={ Home:"https://www.dntips.ir", postUrl:"https://www.dntips.ir/postsarchive", posts_commentsUrl:"https://www.dntips.ir/commentsarchive", sharesUrl:"https://www.dntips.ir/newsarchive", shares_CommentsUrl:"https://www.dntips.ir/newsarchive/comments" }
chrome.runtime.onInstalled.addListener(function(details) { var now=String(new Date()); var params={}; params[Variables.posts]=true; params[Variables.postsComments]=false; params[Variables.shares]=false; params[Variables.sharesComments]=false; params[DateContainer.interval]=1; params[DateContainer.posts]=now; params[DateContainer.postsComments]=now; params[DateContainer.shares]=now; params[DateContainer.sharesComments]=now; chrome.storage.local.set(params, function() { if(chrome.runtime.lastError) { /* error */ console.log(chrome.runtime.lastError.message); return; } }); });
chrome.storage.local.set('mykey':myvalue,....
chrome.storage.local.set(mykey:myvalue,...
"background": { "scripts": ["const.js","init.js"] }
نکته:نمی توان در تعریف بک گراند هم فایل اسکریپت معرفی کرد و هم فایل html
"background": { "page": "background.htm" }
<html> <head> <script type="text/javascript" src="const.js"></script> <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript" src="init.js"></script> <script type="text/javascript" src="omnibox.js"></script> <script type="text/javascript" src="rssreader.js"></script> <script type="text/javascript" src="contextmenus.js"></script> </head> <body> </body> </html>
"content_security_policy": "script-src 'self' https://*.google.com; object-src 'self'"
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
google.load("feeds", "1"); google.setOnLoadCallback(alarmManager);
function alarmManager() { chrome.storage.local.get(DateContainer.interval,function ( items) { period_time==items[DateContainer.interval]; chrome.alarms.create('RssInterval', {periodInMinutes: period_time}); }); chrome.alarms.onAlarm.addListener(function (alarm) { console.log(alarm); if (alarm.name == 'RssInterval') { var boolposts,boolpostsComments,boolshares,boolsharesComments; chrome.storage.local.get([Variables.posts,Variables.postsComments,Variables.shares,Variables.sharesComments],function ( items) { boolposts=items[Variables.posts]; boolpostsComments=items[Variables.postsComments]; boolshares=items[Variables.shares]; boolsharesComments=items[Variables.sharesComments]; chrome.storage.local.get([DateContainer.posts,DateContainer.postsComments,DateContainer.shares,DateContainer.sharesComments],function ( items) { var Vposts=new Date(items[DateContainer.posts]); var VpostsComments=new Date(items[DateContainer.postsComments]); var Vshares=new Date(items[DateContainer.shares]); var VsharesComments=new Date(items[DateContainer.sharesComments]); if(boolposts){var result=RssReader(Links.postUrl,Vposts,DateContainer.posts,Messages.PostsUpdated);} if(boolpostsComments){var result=RssReader(Links.posts_commentsUrl,VpostsComments,DateContainer.postsComments,Messages.CommentsUpdated); } if(boolshares){var result=RssReader(Links.sharesUrl,Vshares,DateContainer.shares,Messages.SharesUpdated);} if(boolsharesComments){var result=RssReader(Links.shares_CommentsUrl,VsharesComments,DateContainer.sharesComments,Messages.SharesCommentsUpdated);} }); }); } }); }
function RssReader(URL,lastupdate,datecontainer,Message) { var feed = new google.feeds.Feed(URL); feed.setResultFormat(google.feeds.Feed.XML_FORMAT); feed.load(function (result) { if(result!=null) { var strRssUpdate = result.xmlDocument.firstChild.firstChild.childNodes[5].textContent; var RssUpdate=new Date(strRssUpdate); if(RssUpdate>lastupdate) { SaveDateAndShowMessage(datecontainer,strRssUpdate,Message) } } }); }
var strRssUpdate = result.xmlDocument.firstChild.firstChild.childNodes[5].textContent;
function SaveDateAndShowMessage(DateField,DateValue,Message) { var params={ } params[DateField]=DateValue; chrome.storage.local.set( params,function(){ var options={ type: "basic", title: Messages.SiteUpdated, message: Message, iconUrl: "icon.png" } chrome.notifications.create("",options,function(){ chrome.notifications.onClicked.addListener(function(){ chrome.tabs.create({'url': WebLinks.Home}, function(tab) { }); }); }); }); }
"permissions": [ "storage", "tabs", "alarms", "notifications" ]
chrome.notifications.create("",options,function(){ chrome.notifications.onClicked.addListener(function(){ chrome.tabs.create({'url': WebLinks.Home}, function(tab) { });}); });
"web_accessible_resources": [ "icon.png" ]
"options_page": "popup.html"
"chrome_url_overrides": { "newtab": "newtab.htm" }
"devtools_page": "devtools.htm"
<script src="devtools.js"></script>
chrome.devtools.panels.create( "Dotnettips Updater Tools", "icon.png", "devtoolsui.htm", function(panel) { } );
window.addEventListener("load", function() { chrome.extension.sendMessage({ type: "dom-loaded", data: { myProperty : "value" } }); }, true);
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { switch(request.type) { case "dom-loaded": alert(request.data.myProperty ); break; } return true; });
var port = chrome.runtime.connect({name: "my-channel"}); port.postMessage({myProperty: "value"}); port.onMessage.addListener(function(msg) { // do some stuff here });
chrome.runtime.onConnect.addListener(function(port) { if(port.name == "my-channel"){ port.onMessage.addListener(function(msg) { // do some stuff here }); } });
آپلود نهایی کار در Google web store
برای آپلود نهایی کار به google web store که در آن تمامی برنامهها و افزونههای کروم قرار دارند بروید. سمت راست آیکن تنظیمات را بزنید و گزینه developer dashboard را انتخاب کنید تا صفحهی آپلود کار برای شما باز شود. دایرکتوری محتویات اکستنشن را zip کرده و آپلود نمایید. توجه داشته باشید که محتویات و سورس خود را باید آپلود کنید نه فایل crx را. بعد از آپلود موفقیت آمیز، صفحهای ظاهر میشود که از شما آیکن افزونه را در اندازه 128 پیکسل میخواهد بعلاوه توضیحاتی در مورد افزونه، قیمت گذاری که به طور پیش فرض به صورت رایگان تنظیم شده است، لینک وب سایت مرتبط، لینک محل پرسش و پاسخ برای افزونه، اگر لینک یوتیوبی در مورد افزونه دارید، یک شات تصویری از افزونه و همینطور چند تصویر برای اسلایدشو سازی که در همان صفحه استاندارد آنها را توضیح میدهد و در نهایت گزینهی جالبتر هم اینکه اکستنشن شما برای چه مناطقی تهیه شده است که متاسفانه ایران را ندیدم که میتوان همه موارد را انتخاب کرد. به خصوص در مورد ایران که آی پیها هم صحیح نیست، انتخاب ایران چنان تاثیری ندارد و در نهایت گزینهی publish را میزنید که متاسفانه بعد از این صفحه درخواست میکند برای اولین بار باید 5 دلار آمریکا پرداخت شود که برای بسیاری از ما این گزینه ممکن نیست.
سورس پروژه را میتوانید از اینجا ببینید و خود افزونه را از اینجا دریافت کنید.