cache.Add(hashValue, true, null, DateTime.Now.AddSeconds(DelayRequest), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
کار با Kendo UI DataSource
AngularJS #4
ASP.NET MVC #8
var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext); var url = urlHelper.Action("Home", "Index");
UrlHelper.GenerateUrl(null, actionName, controllerName, null, null, null, routeValues, htmlHelper.RouteCollection, htmlHelper.ViewContext.RequestContext, true);
کتابخانه mesing
meSing.js is a JavaScript singing synthesis library that uses the Web Audio API's DSP capabilities in conjunction with the meSpeak.js speech synthesis library to provide a vocal synthesizer for the web. First, the lyrics with corresponding MIDI notes are parsed and fed to meSpeak.js; the resulting text-to-speech output is then converted into a series of AudioBufferSourceNodes, which are subsequently processed and adjusted for pitch, rhythm, and expression. Demo
بروز خطا هنگام افزودن نقش جدید
Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values
- Success
- Error
- Warning
- Verbose
- Debug
- Information
cmdlet | Name | Id |
Write-Output | Success | 1 |
Write-Error | Error | 2 |
Write-Warning | Warning | 3 |
Write-Verbose | Verbose | 4 |
Write-Debug | Debug | 5 |
Write-Information | Information | 6 |
به جز دو مورد اول، بقیه cmdletها خروجی را به صورت پیشفرض درون کنسول نمایش نمیدهند. به عنوان مثال اسکریپت زیر را در نظر بگیرید:
Write-Output 'Output' Write-Error 'This is an error' Write-Warning 'This is a warning' Write-Verbose 'This is verbose' Write-Debug 'This is Debug' Write-Information 'This is information'
با اجرای اسکریپت فوق خروجی زیر را خواهیم داشت:
Output Write-Error: This is an error WARNING: This is a warning
همانطور که مشاهده میکنید سه cmdlet فوق، خروجی را درون کنسول نمایش ندادهاند. این رفتار توسط مفهومی تحت عنوان Action Preference قابل تنظیم است که در واقع یک Enum است با مقدار زیر:
6 | Break | |
رخداد به صورت عادی مدیریت شده و برنامه ادامه پیدا میکند | 2 | Continue |
به طور کلی از رخداد صرفنظر خواهد شد؛ بدون اینکه چیزی در استریم نمایش داده شود | 4 | Ignore |
سوال پرسیده خواهد شد که برنامه را ادامه دهد یا متوقف کند | 3 | Inquire |
به طور کلی از رخداد صرفنظر خواهد شد | 0 | SilentlyContinue |
دستور را متوقف خواهد کرد | 1 | Stop |
دستور به نوعی معلق خواهد شد | 5 | Suspend |
بنابراین با تغییر Action Preference برای هر کدام از cmdletها میتوانیم رفتار اسکریپت قبلی را تغییر دهیم:
Write-Output 'Output' Write-Error 'This is an error' Write-Warning 'This is a warning' $VerbosePreference = 'Continue' Write-Verbose 'This is verbose' $DebugPreference = 'Continue' Write-Debug 'This is Debug' $InformationPreference = 'Continue' Write-Information 'This is information'
اکنون اگر اسکریپت فوق را اجرا کنید، سه خروجی آخر را نیز مشاهده خواهید کرد:
Output Write-Error: This is an error WARNING: This is a warning VERBOSE: This is verbose DEBUG: This is Debug This is information
هر کدام از استریمهای فوق قابل redirect شدن نیز هستند؛ برای اینکار میتوانیم از redirect operatorهایی که در PowerShell پشتیبانی میشود استفاده کنیم:
> >> >&1
به عنوان مثال میتوانیم تمام خطاها یا هشدارهای درون یک اسکریپت را به یک فایل منتقل کنیم:
./script.ps1 2>&1 > .\logs.txt
یا میتوانیم تمام Success streamها را به یک فایل هدایت کنیم:
.\script.ps1 > script.log
ارسال تمام Success, Warning, Errorها به یک فایل:
&{ Write-Warning "hello" Write-Error "hello" Write-Output "hi" } 3>&1 2>&1 > C:\Temp\redirection.log
ارسال تمام استریمها به یک فایل:
.\script.ps1 *> script.log
همچنین میتوانیم استریمی را به اصطلاح suppress کنیم که در خروجی نمایش داده نشود:
./script.ps1 1> $null 2> $null ./script.ps1 *> $null
از تکنیک فوق برای drop کردن خروجیهایی که نمیخواهیم نمایش داده شوند، استفاده میشود. در کد فوق دو Idهای ۱ و ۲ را به متغیر ویژهی null هدایت کردهایم؛ همچنین میتوانستیم از یک رشتهی خالی نیز بجای null استفاده کنیم. در خط بعدی از * استفاده کردهایم که به معنای تمامی استریمهای موجود است؛ با اینکار چیزی در خروجی نمایش داده نخواهد شد. یک روش دیگر برای drop کردن، استفاده از دستور Out-Null است:
Get-ChildItem | Out-Null
لازم به ذکر است که این cmdlet تا قبل از نسخه ۶ خیلی کند بود؛ زیرا همانند دیگر cmdletهای درون pipeline میبایست یک ورودی (InputObject) را دریافت کند که باعث میشد هزینهی پردازشی بالایی داشته باشد. اما در نسخه ۶ به بعد این مشکل رفع شدهاست و پارزر به محض رسیدن به این keyword به صورت کلی خروجی را discard میکند بدون اینکه Out-Null را فراخوانی کند؛ در واقع این cmdlet یک hint برای پارزر است. روش دیگر برای drop کردن خروجی، انتساب نتیجه یک دستور به متغییر null است:
New-Item -Type Directory -Path $path | Out-Null $null = New-Item -Type Directory -Path $path
همچنین میتوانیم خروجی یک دستور را به void تبدیل کنیم؛ که نتیجه مشابه با تکنیکهای فوق دارد:
[void](New-Item -Name test -ItemType Directory)
یک نکته در مورد Out-Null
در loopهای بزرگ ممکن است Out-Null حتی در PowerShell 7.x هم کند عمل کند:
PS > Measure-Command { for($i=0; $i -lt 1mb; $i++) { $i | Out-Null } } | Select-Object TotalSeconds TotalSeconds ------------ 4.3056315 PS > Measure-Command { for($i=0; $i -lt 1mb; $i++) { $null = $i } } | Select-Object TotalSeconds TotalSeconds ------------ 1.1210884 PS > Measure-Command { for($i=0; $i -lt 1mb; $i++) { [void]$i } } | Select-Object TotalSeconds TotalSeconds ------------ 1.130507 PS > Measure-Command { for($i=0; $i -lt 1mb; $i++) { $i > $null } } | Select-Object TotalSeconds TotalSeconds ------------ 1.3832427
در یک طبقه بندی کلی، عملگرهای پرس و جو بر اساس ورودی و خروجی آنها به سه دسته تقسیم میشوند:
1- نتیجهی توالی ورودی، بصورت یک توالی، به خروجی ارسال میشود.
2- نتیجهی توالی ورودی، بصورت یک عنصر یکتا و واحد به خروجی ارسال میشود.
3- اثری از ورودی در توالی خروجی وجود ندارد (این عملگرها عناصر خودشان را تولید میکنند).
دستهی آخر شاید کمی عجیب به نطر برسد. این عملگرها هیچ توالی ورودی را دریافت نمیکنند. مثلا میتوان از طریق این عملگرها، یک توالی از اعداد صحیح را تولید کرد.
تقسیم بندی عملگرهای پرس و جو بر اساس عملکرد به صورت زیر میباشد :
- محدود کننده (Restriction)
where
- بازتابی (Projection)
Select,SelectMany
- جداکننده (Partitioning)
Take,Skip,TakeWhile,SkipWhile
- مرتب سازی (Ordering)
OrderBy,OrderByDescending,ThenBy,ThenByDescending,Reverse
- گروه بندی (Grouping)
GroupBy
- مجموعه (Set)
Concat,Union,Intersect,Except
- تبدیل (Conversion)
ToArray,ToList,ToDictionary,ToLookup,OfType,Cast
- عنصر(Element)
First,FirstOrDefault,Last,LastOrDefalt,Single,SingleOrDefault
- عنصر در (ElementAt)
ElementAtOrDefault,DefaultIfEmpty
- تولید (Generation)
Empty,Range,Report
- کمی (Quantifier)
Any,All,Contains,SequenceEqual
- مجموعه (Aggregate)
Count,LongCount,Sum,Min,Max,Average,Aggregate
- اتصال (Join)
Join,GroupJoin,Zip
در این مطلب عملگرهای محدود کننده، بازتابی و جداکننده، بررسی خواهند شد. بعد از معرفی هر عملگر، معادل عبارتهای پرس و جوی آنها نیز معرفی خواهند شد.
این عملگر، عناصری را به خروجی ارسال میکند که با گزارهی (Predicate) تعریف شده مطابقت داشته باشند.
نکته : گزاره (Predicate) تابعی است که اگر شرط آن تامین شود، مقدار true و در غیر اینصورت مقدار false را باز میگرداند.
مثال :
Ingredient[] ingredients = { new Ingredient{Name = "Sugar", Calories=500}, new Ingredient{Name = "Egg", Calories=100}, new Ingredient{Name = "Milk", Calories=150}, new Ingredient{Name = "Flour", Calories=50}, new Ingredient{Name = "Butter", Calories=200}, }; IEnumerable<Ingredient> query = ingredients.Where(x => x.Calories >= 200); foreach (var ingredient in query) { Console.WriteLine(ingredient.Name); }
خروجی کد بالا:
Sugar Butter
IEnumerable<Ingredient> query = ingredients.Where((ingredient, index) => ingredient.Name == "Sugar" || index == 4);
پیاده سازی توسط عبارتهای پرس و جو
در روش عبارتهای پرس و جو، کلمهی کلیدی where بههمراه یک عبارت منطقی در پرس و جو ظاهر میشود:
IEnumerable<Ingredient> gueryExpression = from i in ingredients where i.Calories >= 200 select i;
عملگرهای بازتاب (Projection Operators)
عملگرهای پرس و جوی بازتابی، یک توالی ورودی را دریافت و با تبدیل عناصر آنها، یک توالی خروجی را تولید میکنند.
Select
عملگر پرس و جوی select هر عنصر توالی ورودی را به یک عنصر در توالی خروجی تبدیل میکند. تعداد عناصر ورودی و خروجی در این حالت یکسان میباشند.
پرس و جوی زیر عناصر توالی ورودی Ingredient را به عناصر رشتهای در توالی خروجی بازتاب میکند. عبارت Lambda تعریف شده، نحوهی بازتاب عناصر را مشخص میکند (هر عنصر ingredient به یک عنصر رشتهای بازتاب میشود):
IEnumerable<string> query = ingredients.Select(x => x.Name);
IEnumerable<int> query = ingredients.Select(x => x.Name.Length);
در عملیات بازتاب میتوان یک شیء جدید را در توالی خروجی ایجاد کرد. در کد زیر عناصر Ingredient به یک عنصر جدید از نوع IngredientNameAndLenght بازتاب شده است.
class IngredientNameAndLength { public string Name { get; set; } public int Length { get; set; } public override string ToString() { return Name + " " + Length; } } IEnumerable<IngredientNameAndLength> query = ingredients.Select(x => new IngredientNameAndLength { Name = x.Name, Length = x.Name.Length });
var query = ingredients.Select(x => new { Name = x.Name, Length = x.Name.Length });
{ Name = Sugar, Length = 5 } { Name = Egg, Length = 3 } { Name = Milk, Length = 4 } { Name = Flour, Length = 5 } { Name = Butter, Length = 6 }
پیاده سازی توسط عبارتهای پرس و جو
کلمهی کلیدی select در عبارتهای پرس و جو، به شکل زیر استفاده میشود:
var query = from i in ingredients select new { Name=i.Name, Length=i.Name.Length };
برعکس دستور select که به ازای هر عنصر در توالی ورودی، یک عنصر را در توالی خروجی بازتاب میکرد، دستور SelectMany ممکن است تعداد عناصر کمتر و یا بیشتری را در توالی خروجی بازتاب کند (انتخاب مقادیر یک مجموعه از مجموعهی دیگر).
عبارت Lambda نوشته شده در عملگر Select، یک مقدار را باز میگرداند. اما عبارت Lambda نوشته شده در عملگر SelectMany، یک توالی فرزند (Child Sequence) را ایجاد میکند. توالی فرزند ممکن است حاوی تعداد مختلفی از عناصر به ازای هر عنصر در توالی ورودی باشد.
در مثال زیر عبارت Lambda یک توالی فرزند از کاراکترها ایجاد میکند (یک کاراکتر به ازای هر حرف از هر عنصر توالی ورودی). بهطور مثال عنصر ورودی Sugar، پس از پردازش توسط عبارت Lambda، یک توالی فرزند با 5 عنصر 's','u','g','e','r' فراهم میکند. هر رشتهی در توالی Ingredient میتواند تعداد حروف متفاوتی داشته باشد. در نتیجه عبارت Lambda، توالیهای فرزندی با طولهای مختلف ایجاد میکند.
مثال:
string[] ingredients = {"Sugar","Egg","Milk","Flour","Butter"}; IEnumerable<char> query = ingredients.SelectMany(x => x.ToCharArray()); foreach (var item in query) { Console.WriteLine(item); }
S u g a r E g g M i l k F l o u r B u t t e r
پیاده سازی توسط عبارتهای پرس و جو
در روش عبارتهای پرس و جو یک عبارت (clause) اضافی from برای تولید یک توالی فرزند به کار برده میشود. خروجی کد زیر مشابه کد قبلی است:
string[] ingredients = {"Sugar","Egg","Milk","Flour","Butter"}; IEnumerable<char> query2 = from i in ingredients from c in i.ToCharArray() select c; foreach (var item in query2) { Console.WriteLine(item); }
عملگرهای جداکننده، یک توالی ورودی را دریافت و آنها را از هم جدا میکنند.
Take
عملگر Takeیک توالی ورودی را دریافت کرده و تعداد مشخصی از توالی را باز میگرداند.
مثال: عملگر Take، سه عضو اول توالی Ingredient را باز میگرداند:
Ingredient[] ingredients = { new Ingredient{Name = "Sugar", Calories=500}, new Ingredient{Name = "Egg", Calories=100}, new Ingredient{Name = "Milk", Calories=150}, new Ingredient{Name = "Flour", Calories=50}, new Ingredient{Name = "Butter", Calories=200}, }; IEnumerable<Ingredient> query = ingredients.Take(3); foreach (var ingredient in query) { Console.WriteLine(ingredient.Name); }
Sugar Egg Milk
Ingredient[] ingredients = { new Ingredient{Name = "Sugar", Calories=500}, new Ingredient{Name = "Egg", Calories=100}, new Ingredient{Name = "Milk", Calories=150}, new Ingredient{Name = "Flour", Calories=50}, new Ingredient{Name = "Butter", Calories=200}, }; IEnumerable<Ingredient> query = ingredients.Where(x=>x.Calories>100).Take(2); foreach (var ingredient in query) { Console.WriteLine(ingredient.Name); }
Sugar Milk
پیاده سازی توسط عبارتهای پرس و جو
کلمهی کلیدی (Key word) جایگزینی برای عملگر Take وجود ندارد، ولی میتوان با ترکیب دو روش نوشتن پرس و جو، خروجی مورد نظر را تولید کرد:
IEnumerable<Ingredient> query = (from i in ingredients where i.Calories > 100 select i).Take(2); TakeWhile
کد زیر تا زمانی که خصوصیت Calorie توالی ورودی بزرگتر و مساوی 100 باشد، عناصر را جدا میکند.
Ingredient[] ingredients = { new Ingredient{Name = "Sugar", Calories=500}, new Ingredient{Name = "Egg", Calories=100}, new Ingredient{Name = "Milk", Calories=150}, new Ingredient{Name = "Flour", Calories=50}, new Ingredient{Name = "Butter", Calories=200}, }; IEnumerable<Ingredient> query = ingredients.TakeWhile(x => x.Calories >= 100); foreach (var ingredient in query) { Console.WriteLine(ingredient.Name); }
Sugar Egg Milk
پیاده سازی توسط عبارتهای پرس و جو
برای این عملگر هم کلمهی کلیدی (Key word) جایگزینی وجود ندارد و با ترکیب دو روش نوشتن پرس و جو نتیجهی دلخواه حاصل میشود.
Skip
این عملگر تعداد مشخصی از عناصر را از ابتدای توالی نادیده گرفته و باقی عناصر را باز میگرداند.
کد زیر سه عضو اول توالی را نادیده گرفته و مابقی را باز میگرداند:
Ingredient[] ingredients = { new Ingredient{Name = "Sugar", Calories=500}, new Ingredient{Name = "Egg", Calories=100}, new Ingredient{Name = "Milk", Calories=150}, new Ingredient{Name = "Flour", Calories=50}, new Ingredient{Name = "Butter", Calories=200}, }; IEnumerable<Ingredient> query = ingredients.Skip(3); foreach (var ingredient in query) { Console.WriteLine(ingredient.Name); }
Flour Butter
پیاده سازی توسط عبارتهای پرس و جو
برای این عملگر هم کلمهی کلیدی (Key word) جایگزینی وجود ندارد و با ترکیب دو روش نوشتن پرس و جو، نتیجهی دلخواه حاصل میشود.
با ترکیب عملگر Take و Skip میتوان اطلاعات را بهصورت صفحه بندی به کاربر ارائه کرد. مثال زیر این حالت را نشان میدهد.
IEnumerable<Ingredient> firstPage = ingredients.Take(2); IEnumerable<Ingredient> secondPage = ingredients.Skip(2).Take(2); IEnumerable<Ingredient> thirdPage = ingredients.Skip(4).Take(2); Console.WriteLine("First Page : "); foreach (var ingredient in firstPage) { Console.WriteLine(" - " + ingredient.Name); } Console.WriteLine("Second Page : "); foreach (var ingredient in secondPage) { Console.WriteLine(" - " + ingredient.Name); } Console.WriteLine("Third Page : "); foreach (var ingredient in thirdPage) { Console.WriteLine(" - " + ingredient.Name); }
First Page : - Sugar - Egg Second Page : - Milk - Flour Third Page : - Butter SkipWhile
مثال:
Ingredient[] ingredients = { new Ingredient{Name = "Sugar", Calories=500}, new Ingredient{Name = "Egg", Calories=100}, new Ingredient{Name = "Milk", Calories=150}, new Ingredient{Name = "Flour", Calories=50}, new Ingredient{Name = "Butter", Calories=200}, }; IEnumerable<Ingredient> query = ingredients.SkipWhile(x => x.Name != "Milk"); foreach (var ingredient in query) { Console.WriteLine(ingredient.Name); }
Milk Flour Butter
<html> <body> <div> Prevent default: <input type="checkbox" id="keydownStop" value="1" /> keydown <input type="checkbox" id="keypressStop" value="1" /> keypress <input type="checkbox" id="keyupStop" value="1" /> keyup </div> Ignore: <input type="checkbox" id="keydownIgnore" value="1" /> keydown <input type="checkbox" id="keypressIgnore" value="1" /> keypress <input type="checkbox" id="keyupIgnore" value="1" /> keyup <div> Focus on the input below and press any key. </div> <div> <input type="text" style=" width: 600px" id="keyInput" /> </div> Log: <div> <textarea id="keyLogger" rows="18" onfocus="this.blur()" style="width: 600px; border: 1px solid black"></textarea> </div> <input type="button" value="Clear" onclick="clearLog()" /> <script type="text/javascript"> document.getElementById('keyInput').onkeydown = keyHandler; document.getElementById('keyInput').onkeyup = keyHandler; document.getElementById('keyInput').onkeypress = keyHandler; document.getElementById('keyInput').focus(); function keyHandler(e) { e = e || window.event; if (document.getElementById(e.type + 'Ignore').checked) return; var evt = e.type; while (evt.length < 10) evt += ' ' + log(evt + ' keyCode=' + e.keyCode + ' which=' + e.which + ' charCode=' + e.charCode + ' char=' + String.fromCharCode(e.keyCode || e.charCode) + (e.shiftKey ? ' +shift' : '') + (e.ctrlKey ? ' +ctrl' : '') + (e.altKey ? ' +alt' : '') + (e.metaKey ? ' +meta' : '')); if (document.getElementById(e.type + 'Stop').checked) { e.preventDefault ? e.preventDefault() : (e.returnValue = false); } } function clearLog() { document.getElementById('keyLogger').value = ''; document.getElementById('keyInput').focus(); } function log(text) { var area = document.getElementById('keyLogger'); area.value += text + '\n'; area.scrollTop = area.scrollHeight; } </script> </body> </html>
<!doctype html>
document.onkeydown = function (e) { e = e || event; console.log(e); }
function getCharacter(event) { if (event.which == null) return String.fromCharCode(event.keyCode); // IE else if (event.which != 0 && event.charCode != 0) return String.fromCharCode(event.which); // All others return null; // special key }
<html> <body> <input id="inputText" type="text" /> <script> document.onkeydown = keyDown; document.onkeypress = keyPress; document.onkeyup = keyUp; function keyDown(e) { var input = document.getElementById('inputText'); input.value = 'keyDown started ...'; input.disabled = true; var j = 0; for (var i = 0; i < 999999999; i++) { j = i - j; } console.log(j); //alert('keyDown'); input.value = 'keyDown finished.'; input.disabled = false; } function keyPress(e) { alert('keyPress'); //console.log('keyPress'); } function keyUp(e) { alert('keyUp'); //console.log('keyUp'); } </script> </body> </html>
<html> <head> <script type="text/javascript"> function process() { var above = 0, below = 0; for (var i = 0; i < 200000; i++) { if (Math.random() * 2 > 1) { above++; } else { below++; } } } function test() { var result1 = document.getElementById('log'); var start = new Date().getTime(); console.log('start'); for (var i = 0; i < 200; i++) { result1.value = 'time=' + (new Date().getTime() - start) + ' [i=' + i + ']'; process(); } result1.value = 'time=' + (new Date().getTime() - start) + ' [done]'; console.log('end'); } window.onload = test; </script> </head> <body> <input id='log' /> </body> </html>
<input onkeydown="return false" /> <input onkeypress="return false" />
document.getElementById('myInputText').onkeypress = function (e) { var char = getCharacter(e || window.event); if (!char) return; // special key this.value += char.toUpperCase(); return false; // برای اینکه کاراکتر اضافی نمایش داده نشود }
e ? e : window.event;
document.getElementById('numberInputText').onkeypress = function (e) { e = e || window.event; var chr = getCharacter(e); if (!isNumeric(chr) && chr !== null) return false; } function isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } function isNumber(val) { return val !== "NaN" && (+val) + '' === val + '' }
0==false // true 0===false // false, because they are of a different type 1=="1" // true, auto type coercion 1==="1" // false, because they are of a different type
e.ctrlKey && e.keyCode == 'A'.charCodeAt(0)
<html> <body> <div id="dotnettips" style="width: 35px; height: 35px; background-image: url(https://www.dntips.ir/favicon.ico); position: absolute; left: 10px; top: 10px;" tabindex="0"> </div> <script> document.getElementById('dotnettips').onkeydown = function (e) { e = e || event; switch (e.keyCode) { case 37: // left this.style.left = parseInt(this.style.left) - this.offsetWidth + 'px'; return false; case 38: // up this.style.top = parseInt(this.style.top) - this.offsetHeight + 'px'; return false; case 39: // right this.style.left = parseInt(this.style.left) + this.offsetWidth + 'px'; return false; case 40: // down this.style.top = parseInt(this.style.top) + this.offsetHeight + 'px'; return false; } } </script> </body> </html>
<html> <body> <input id="inputText" type="text" /> <div id="divCapsLock" style="color: Red; display: none;">Caps Lock is ON!</div> <script> var capsLock = null; document.onkeypress = keyPress; document.onkeydown = keyDown; function keyDown(e) { e = e || event; capsLock = (e.keyCode == 20 && capsLock !== null) ? !capsLock : capsLock; document.getElementById('divCapsLock').style.display = capsLock ? 'block' : 'none'; } function keyPress(e) { if (capsLock != null) return; e = e || window.event; var charCode = e.charCode || e.keyCode; capsLock = (charCode >= 97 && charCode <= 122 && e.shiftKey) || (charCode >= 65 && charCode <= 90 && !e.shiftKey); document.getElementById('divCapsLock').style.display = capsLock ? 'block' : 'none'; } </script> </body> </html>
<html> <body> <div id='divInput'> <input id="inputText" type="text" /> </div> <script> document.getElementById('inputText').onkeydown = inputKeyDown; document.getElementById('divInput').onkeydown = divKeyDown; document.onkeydown = documentKeyDown; window.onkeydown = windowKeyDown; function divKeyDown(e) { console.log('divKeyDown'); } function inputKeyDown(e) { console.log('inputKeyDown'); } function documentKeyDown(e) { console.log('documentKeyDown'); } function windowKeyDown(e) { console.log('windowKeyDown'); } </script> </body> </html>
<html> <body> <input id="inputText" type="text" /> <div id="divCapsLock" style="color: Red; display: none;">Caps Lock is ON!</div> <script> var capsLock = null; var hasFocus = false; document.onkeyup = keyUp; document.onkeypress = keyPress; document.getElementById('inputText').onfocus = focus; document.getElementById('inputText').onblur = focus; function warnCapsLock() { document.getElementById('divCapsLock').style.display = (capsLock != null && capsLock && hasFocus) ? 'block' : 'none'; } function focus() { hasFocus = !hasFocus; warnCapsLock(); } function keyUp(e) { e = e || event; capsLock = (e.keyCode == 20 && capsLock !== null) ? !capsLock : capsLock; warnCapsLock(); } function keyPress(e) { if (capsLock != null) return; e = e || window.event; var charCode = e.charCode || e.keyCode; capsLock = (charCode >= 97 && charCode <= 122 && e.shiftKey) || (charCode >= 65 && charCode <= 90 && !e.shiftKey); warnCapsLock(); } </script> </body> </html>
window.onblur = function () { capsLock = null; }
var Client = {}; Client.Keyboard = {}; Client.Keyboard.EnableKeyDown = true; Client.Keyboard.EnableKeyUp = false; Client.Keyboard.CurrentKeyEvent = null; window.onkeydown = function (event) { if (!Client.Keyboard.EnableKeyDown) return true; return KeyboardEvents(event); }; window.onkeyup = function (event) { if (!Client.Keyboard.EnableKeyUp) return true; return KeyboardEvents(event); }; function Rise(event) { var e = Client.Keyboard.CurrentKeyEvent; if (event) { var data = { shift: e.shiftKey, ctrl: e.ctrlKey, alt: e.altKey }; if (!event(data)) return false; return event(data); } return true; } function KeyboardEvents(e) { e = e || window.event; Client.Keyboard.CurrentKeyEvent = e; switch (e.keyCode) { case 8: return Rise(Client.Keyboard.Backspace); case 9: return Rise(Client.Keyboard.Tab); case 13: return Rise(Client.Keyboard.Enter); case 16: return Rise(Client.Keyboard.Shift); case 17: return Rise(Client.Keyboard.Ctrl); case 18: return Rise(Client.Keyboard.Alt); case 19: return Rise(Client.Keyboard.Pause); case 20: return Rise(Client.Keyboard.CapsLock); case 27: return Rise(Client.Keyboard.Esc); case 33: return Rise(Client.Keyboard.PageUp); case 34: return Rise(Client.Keyboard.PageDown); case 35: return Rise(Client.Keyboard.End); case 36: return Rise(Client.Keyboard.Home); case 37: return Rise(Client.Keyboard.Left); case 38: return Rise(Client.Keyboard.Up); case 39: return Rise(Client.Keyboard.Right); case 40: return Rise(Client.Keyboard.Down); case 44: return Rise(Client.Keyboard.PrtScr); case 45: return Rise(Client.Keyboard.Insert); case 46: return Rise(Client.Keyboard.Delete); ////////////////////////////////////////////////////////////////////////////////////////////////// case 48: return Rise(Client.Keyboard.Num0); case 49: return Rise(Client.Keyboard.Num1); case 50: return Rise(Client.Keyboard.Num2); case 51: return Rise(Client.Keyboard.Num3); case 52: return Rise(Client.Keyboard.Num4); case 53: return Rise(Client.Keyboard.Num5); case 54: return Rise(Client.Keyboard.Num6); case 55: return Rise(Client.Keyboard.Num7); case 56: return Rise(Client.Keyboard.Num8); case 57: return Rise(Client.Keyboard.Num9); ////////////////////////////////////////////////////////////////////////////////////////////////// case 65: return Rise(Client.Keyboard.A); case 66: return Rise(Client.Keyboard.B); case 67: return Rise(Client.Keyboard.C); case 68: return Rise(Client.Keyboard.D); case 69: return Rise(Client.Keyboard.E); case 70: return Rise(Client.Keyboard.F); case 71: return Rise(Client.Keyboard.G); case 72: return Rise(Client.Keyboard.H); case 73: return Rise(Client.Keyboard.I); case 74: return Rise(Client.Keyboard.J); case 75: return Rise(Client.Keyboard.K); case 76: return Rise(Client.Keyboard.L); case 77: return Rise(Client.Keyboard.M); case 78: return Rise(Client.Keyboard.N); case 79: return Rise(Client.Keyboard.O); case 80: return Rise(Client.Keyboard.P); case 81: return Rise(Client.Keyboard.Q); case 82: return Rise(Client.Keyboard.R); case 83: return Rise(Client.Keyboard.S); case 84: return Rise(Client.Keyboard.T); case 85: return Rise(Client.Keyboard.U); case 86: return Rise(Client.Keyboard.V); case 87: return Rise(Client.Keyboard.W); case 88: return Rise(Client.Keyboard.X); case 89: return Rise(Client.Keyboard.Y); case 90: return Rise(Client.Keyboard.Z); //////////////////////////////////////////////////////////////////////////// case 91: //case 219: // opera return Rise(Client.Keyboard.LeftWindow); case 92: return Rise(Client.Keyboard.RightWindow); case 93: return Rise(Client.Keyboard.ContextMenu); //////////////////////////////////////////////////////////////////////////// case 96: return Rise(Client.Keyboard.NumPad0); case 97: return Rise(Client.Keyboard.NumPad1); case 98: return Rise(Client.Keyboard.NumPad2); case 99: return Rise(Client.Keyboard.NumPad3); case 100: return Rise(Client.Keyboard.NumPad4); case 101: return Rise(Client.Keyboard.NumPad5); case 102: return Rise(Client.Keyboard.NumPad6); case 103: return Rise(Client.Keyboard.NumPad7); case 104: return Rise(Client.Keyboard.NumPad8); case 105: return Rise(Client.Keyboard.NumPad9); //////////////////////////////////////////////////////////////////////////// case 106: return Rise(Client.Keyboard.Multiply); case 107: return Rise(Client.Keyboard.Add); case 109: return Rise(Client.Keyboard.Subtract); case 110: return Rise(Client.Keyboard.DecimalPoint); case 111: return Rise(Client.Keyboard.Divide); //////////////////////////////////////////////////////////////////////////// case 112: return Rise(Client.Keyboard.F1); case 113: return Rise(Client.Keyboard.F2); case 114: return Rise(Client.Keyboard.F3); case 115: return Rise(Client.Keyboard.F4); case 116: return Rise(Client.Keyboard.F5); case 117: return Rise(Client.Keyboard.F6); case 118: return Rise(Client.Keyboard.F7); case 119: return Rise(Client.Keyboard.F8); case 120: return Rise(Client.Keyboard.F9); case 121: return Rise(Client.Keyboard.F10); case 122: return Rise(Client.Keyboard.F11); case 123: return Rise(Client.Keyboard.F12); //////////////////////////////////////////////////////////////////////////// case 144: return Rise(Client.Keyboard.NumLock); case 145: return Rise(Client.Keyboard.ScrollLock); case 186: case 59: // opera & firefox return Rise(Client.Keyboard.SemiColon); case 187: case 61: // opera //case 107: //firefox return Rise(Client.Keyboard.Equal); case 188: return Rise(Client.Keyboard.Camma); case 189: return Rise(Client.Keyboard.Dash); case 190: return Rise(Client.Keyboard.Period); case 191: return Rise(Client.Keyboard.Slash); case 192: return Rise(Client.Keyboard.GraveAccent); case 219: return Rise(Client.Keyboard.OpenBracket); case 220: return Rise(Client.Keyboard.BackSlash); case 221: return Rise(Client.Keyboard.CloseBracket); case 222: return Rise(Client.Keyboard.SingleQuote); } };
// ctrl + s Client.Keyboard.S = function (e) { if (e.ctrl) { // انجام عملیات موردنظر } return true; }
انجام عملیات Pivot توسط MDX :
برای این منظور کافی است فقط جای سطر و ستون را با هم عوض کنیم.برای مثال، کوئریهای زیر را اجرا نمایید.
Select [Date].[Calendar].[Calendar Year] on columns, [Product].[Product Categories].[Category] on rows From [Adventure Works] GO Select [Product].[Product Categories].[Category] on columns, [Date].[Calendar].[Calendar Year] on rows From [Adventure Works]
خروجی به صورت زیر میباشد.
چگونگی استفاده از ساختارهای سلسله مراتبی در محورهای مختلف :
برای روشن شدن مطلب چندین نمونه کوئری زیر را باهم اجرا میکنیم.
در ابتدا به خاطر داشته باشید که امکان استفاده از یک ساختار سلسله مراتبی در دو محور (Axis ) مجزا وجود ندارد. برای روشنتر شدن این مطلب کوئری زیر را اجرا کنید:
Select [Date].[Calendar].[Calendar Year] on columns, [Date].[Calendar].[Month] on rows From [Adventure Works]
در توضیح مثال بالا دقت داشته باشید که واکشی [Calendar Year] و [Month] از یک ساختار سلسله مراتبی یکسان به نام [Date].[Calendar] انجام شده است و این کار در MDX ها غیر مجاز میباشد.
البته استفاده از دو ساختار سلسله مراتبی متفاوت از یک دایمنشن در دو محور مجزا امکان پذیر میباشد برای مثال :
Select [Date].[Calendar].[Calendar Year] on columns, [Date].[Month of Year].[Month of Year] on rows From [Adventure Works]
در مثال بالا واکشی از دو ساختار سلسله مراتبی مختلف اما از یک دایمنشن در دو محور مجزا صورت گرفته است.
امکان استفاده از دو ساختار سلسله مراتبی یکسان در یک محور مجاز میباشد.
Select [Measures].[Internet Sales Amount] on columns, {[Date].[Calendar].[Calendar Year],[Date].[Calendar].[Month]} on rows From [Adventure Works]
همچنین استفاده از دو ساختار سلسله مراتبی مختلف از یک دایمنشن در یک محور مجاز نمیباشد.
Select [Measures].[Internet Sales Amount] on columns, {[Date].[Calendar].[Calendar Year],[Date].[Month of Year].[Month of Year]} on rows From [Adventure Works]
در مثال بالا از دو ساختار سلسله مراتبی [Date].[Calendar] و [Date].[Month of Year] استفاده شده است.
در صورتی میتوانیم از دو ساختار سلسله مراتبی متفاوت از یک دایمنشن در یک محور استفاده کنیم که آنها را باهم Cross Join کنیم.
Select [Measures].[Internet Sales Amount]on columns, crossjoin( [Date].[Calendar].[Calendar Year], [Date].[Month of Year].[Month of Year] )on rows From [Adventure Works]
دقت داشته باشید که امکان استفاده از دو ساختار سلسله مراتبی یکسان از یک دایمنشن در Cross Join وجود ندارد همان گونه که در دو مثال قبل مشاهده نمودید. (و البته نیازی هم به استفاده از Cross Join وجود ندارد)
Select [Measures].[Internet Sales Amount] on columns, crossjoin( [Date].[Calendar].[Calendar Year], [Date].[Calendar].[Month] )on rows From [Adventure Works]
به طور کلی استفاده از Cross Join مانند استفاده از () می باشد . بنابر این می توان کلمه ی Cross Join را ننوشت .
Select {[Measures].[Internet Sales Amount],[Measures].[Reseller Sales Amount]} on columns, crossjoin( [Date].[Calendar].[Calendar Year], [Date].[Month of Year].[Month of Year] )on rows From [Adventure Works] GO Select {[Measures].[Internet Sales Amount],[Measures].[Reseller Sales Amount]} on columns, ( [Date].[Calendar].[Calendar Year], [Date].[Month of Year].[Month of Year] )on rows From [Adventure Works]
دو کوئری بالا مشابه هم میباشند.
می توان از دو Cross Join در دو محور مختلف نیز استفاده کرد.
Select crossjoin( [Product].[Product Categories].[Category], {[Measures].[Internet Sales Amount],[Measures].[Reseller Sales Amount]} )on columns, crossjoin( [Date].[Calendar].[Calendar Year], [Date].[Month of Year].[Month of Year] )on rows From [Adventure Works]
دقت داشته باشید نوع محصول در ستونها بالای سر ستون [ Internet Sales Amount] و [Reseller Sales Amount] قرار گرفته است.
استفاده از Cross Join های تودر تو نیز وجود دارد.
Select crossjoin( [Sales Territory].[Sales Territory].[Country], crossjoin( [Product].[Product Categories].[Category], { [Measures].[Internet Order Count], [Measures].[Reseller Order Count] } ) )on columns , crossjoin( [Date].[Calendar].[Calendar Year], [Date].[Month of Year].[Month of Year] ) on rows From [Adventure Works]
در کوئری زیر به جای Cross Join از () استفاده شده است
Select crossjoin( [Sales Territory].[Sales Territory].[Country], [Product].[Product Categories].[Category], { [Measures].[Internet Order Count], [Measures].[Reseller Order Count] } ) on columns, ([Date].[Calendar].[Calendar Year],[Date].[Month of Year].[Month of Year]) on rows From [Adventure Works]
استفاده از عملگر * مانند استفاده از Cross Join می باشد.
Select crossjoin( [Sales Territory].[Sales Territory].[Country], [Product].[Product Categories].[Category], { [Measures].[Internet Order Count], [Measures].[Reseller Order Count] } ) on columns, [Date].[Calendar].[Calendar Year] * [Date].[Month of Year].[Month of Year] on rows From [Adventure Works]
در مقالات بعدی آموزش MDX Query را ادامه خواهیم داد.