Tag Archives: javascript

KO Support für IE8

Leider ist der Internet Explorer 8, trotz des hohen Alters, noch immer nicht ausgestorben*. Deshalb sollte eine Website auch mit dem IE8 “zugänglich” sein.

Das MVVM Framework Knockout unterstütz offiziell den Internet Explorer v6 – v11.

Knockout is tested on the following browsers:
•Mozilla Firefox (versions 3.5 – current)
•Google Chrome (current)
•Microsoft Internet Explorer (versions 6 – 11)
•Apple Safari for Mac OS (current)
•Apple Safari for iOS (versions 6 – 8)
•Opera (current version)

It’s very likely that Knockout also works on older and newer versions of these browsers, but there’s only so many combinations we can check regularly! At the time of the last check, Knockout was also found to work on the following browsers (though we don’t recheck these for every release):
•Google Android OS browser
•Opera Mini
•Google Chrome 5+
•iOS Safari 5
•Mac OS X Safari 3.1.2+

To get a good idea of how Knockout will run on another browser or platform, simply run the test suite. This will validate hundreds of behavioral specifications and produce a report of any problems. The pass rate should be 100% on all the browsers listed above.

Quelle: Knockout: Browser Support

Als ich jedoch meine auf Knockout basierte Webapplikation auf IE8 ausprobiert habe, hat das Databinding nicht funktioniert. Der Grund ist realtiv simpel. Dennoch ist es verwunderlich, dass auf der Knockout Seite kein Wort darüber verloren wird.

Der Internet Explorer 8 interpretiert einige Keywords im “data-bind”-Attribut falsch und das Binding schlägt fehl. Das lässt sich verhindern in dem diese Keywords mit einfachen Anführungszeichen (‘) umschlossen werden. Das hat keine Auswirkung auf die Funktionalität und die Bindings funktionieren so auch in anderen Browsern.

Beispiel:

<!-- Funktioniert im IE8 nicht -->
<div data-bind="template: { if: myViewModel.templateName, name: myViewModel.templateName }"></div>
<div data-bind="with: myViewModel, css: { 'cssClassToApply': myViewModel.isXyAvailable }">

<!-- Funktioniert im IE8 -->
<div data-bind="template: { 'if': myViewModel.templateName, name: myViewModel.templateName }"></div>
<div data-bind="'with': myViewModel, 'css': { 'cssClassToApply': myViewModel.isXyAvailable }">

Meine Versuche haben ergeben, dass folgende Bindings nur mit einfachen Anführungszeichen verwendet werden können**:
– for
– foreach
– css
– with

* Gemäss statcounter kommt der IE8 immer noch auf einen Marktanteil von ~5% (27.06.2015).
Als der IE8 released wurde (19. März 2009) war Google Chrome in der Version 1 verfügbar. Die aktuellste Chrome Version ist v43.

** Nicht systematisch getestet. Ohne Gewähr.

jQuery UI und Knockout – “You cannot apply bindings multiple times to the same element”

Um jQuery UI zusammen mit Knockout zu verwenden habe ich ein eigenes Knockout Binding erstellt. In der Init Methode wird das jQuery Widget erstellt.
Beim folgenden Beispiel handelt es sich um TypeScript Code.

ko.bindingHandlers["dialogBox"] = {
	init(element: any, valueAccessor: any) {
		$(element).dialog({
			autoOpen: false,
			modal: true,
                        
			resizable: false,
			// More Code
		});
		return false;
	},
	update(element: any, valueAccessor: any) {
		// Update Code
	}
}

In diesem Beispiel verwende ich den jQuery UI Dialog. Der Content des Dialogs befindet sich in einem Div. Natürlich wurde der Inhalt dieses Divs über ein Knockout-Template erzeugt (“template”-Binding). Mit dieser Methode lässt sich der Code welcher das DOM kennt, auf die Bindings beschränken.

Bei einigen Widgets, darunter auch der Dialog, tritt jedoch der folgende Fehler auf:
“You cannot apply bindings multiple times to the same element.”

Um die Ursache zu verstehen, muss man wissen, dass jQuery UI beim initialisieren bzw. erstellen des Widgets das Div, welches den Content des Dialogs darstellt, ausschneidet, etwas verpackt und ganz unten in der Seite einfügt.

Vorher:

<html>
	<head>
		<!-- jQuery und jQuery UI includen -->
		<script>
			$(function() {
				$( "#dialog" ).dialog();
			});
		</script>
	</head>
	<body>
		<div id="insideMeIsTheDialog">
			<div id="dialog" title="Basic dialog">
				<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed
					with the 'x' icon.</p>
			</div>
		</div>
	</body>
</html>

Nachher:

<html>
	<head>
		<script>
			$(function() {
				$( "#dialog" ).dialog();
			});
		</script>
	</head>
	<body style="cursor: auto;">
		<div id="insideMeIsTheDialog"></div>
		<div aria-labelledby="ui-id-1" aria-describedby="dialog" role="dialog" tabindex="-1" style="position: absolute; height: 143.6px; width: 299.6px; top: 203px; left: 660px; display: block; right: auto; bottom: auto;" class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-front ui-draggable ui-resizable">
			<div class="ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix ui-draggable-handle">
				<span class="ui-dialog-title" id="ui-id-1">Basic dialog</span>
				<button title="Close" role="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only ui-dialog-titlebar-close"
				type="button">
					<span class="ui-button-icon-primary ui-icon ui-icon-closethick"></span>
					<span class="ui-button-text">Close</span>
				</button>
			</div>
			<div style="width: auto; min-height: 105px; max-height: none; height: auto;" class="ui-dialog-content ui-widget-content" id="dialog">
				<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
			</div>
			<div style="z-index: 90;" class="ui-resizable-handle ui-resizable-n"></div>
			<div style="z-index: 90;" class="ui-resizable-handle ui-resizable-e"></div>
			<div style="z-index: 90;" class="ui-resizable-handle ui-resizable-s"></div>
			<div style="z-index: 90;" class="ui-resizable-handle ui-resizable-w"></div>
			<div style="z-index: 90;" class="ui-resizable-handle ui-resizable-se ui-icon ui-icon-gripsmall-diagonal-se"></div>
			<div style="z-index: 90;" class="ui-resizable-handle ui-resizable-sw"></div>
			<div style="z-index: 90;" class="ui-resizable-handle ui-resizable-ne"></div>
			<div style="z-index: 90;" class="ui-resizable-handle ui-resizable-nw"></div>
		</div>
	</body>

</html>

Ist nun der Knockout Binding Scope der Body oder allgemeiner gesamt, der gemeinsame Parent des Dialog Divs und des “ausgeschnittenen” Dialog Divs, so probiert Knockout die Bindings mehrmals auszuführen.

Die Lösung:
1. Den Scope für das Knockout Binding einschränken
2. jQuery UI das Widget ausserhalb dieses Scopes platzieren lassen

<html>
	<head>
		<script>
			$(function() {
				$( "#dialog" ).dialog({
					appendTo: "#container"
				});
			});
		</script>
	</head>
	<body>
		<div id="container">
			<div id="bindingRoot">
				<div id="dialog" title="Basic dialog">
					<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed
						with the 'x' icon.</p>
				</div>
			</div>
		</div>
	</body>
</html>

TypeScript Greeter mit RequireJS und Knockout

Im Rahmen eines aktuellen Projektes beschäftige ich mich mit TypeScript und diversen JavaScript Frameworks, darunter RequireJS und KnockoutJS. Aus diesem Grund habe ich als kleines Beispiel den “Greeter” (Template wenn ein neues Visual Studio TypeScript Projekt angelegt wird) mittels eben diesen zwei Frameworks realisiert. Es ist alles andere als “Rocket Science”, kann jedoch für den Anfang ganz nützlich sein. Der Code ist auf GitHub verfügbar: https://github.com/msallin/TypeScript_RJS_Sample

Top 10 OWASP for .NET – Summary

OWASP

The Open Web Application Security Project (OWASP) is a 501(c)(3) worldwide not-for-profit charitable organization focused on improving the security of software. Our mission is to make software security visible, so that individuals and organizations worldwide can make informed decisions about true software security risks.

https://www.owasp.org/index.php/Main_Page

OWASP gibt jedes Jahr eine Liste mit den zehn kritischsten Lücken heraus.
Hier ist der Guide “OWASP Top 10 for .NET developers” zu finden. Dasselbe PDF hier auf meinem Blog, sollte er einmal nicht mehr Verfügbar sein.

Basierend auf diesem Guide habe ich eine kleine Zusammenfassung erstellt.
Sie dient als Nachschlagewerk oder als Auffrischung. Ich empfehle aber auf jeden Fall den gesamten Guide zu lesen.

Continue reading

Sdk.Soap.js – Mehr Power für JS?

Bis jetzt wurde es immer unbequem, wollte man mit JS den CRM SOAP Endpoint ansprechen. Anscheinend soll sich das ändern:

Sdk.Soap.js is a JavaScript library that helps you write JavaScript with web resources that use the CRM 2013 Modern App SOAP endpoint (formerly called the SOAP endpoint for web resources).

This library makes writing JavaScript code for data operations much like using C#. While the OData (REST) endpoint is good for many things and is relatively easy to use, it doesn’t provide a way to execute messages or access formatted values.

With Sdk.Soap.js you can be much more productive when you need to use the SOAP endpoint. Please look at the following samples:

Sdk.Soap.js
Contains the core library and supporting libraries to call 202 messages.

Sdk.Soap.js Entity Class Generator

Contains a sample to generate supporting libraries for entities in your organization. This allows for ‘early-binding’ style code with IntelliSense for your entities. This is essentially a CRMSvcUtil.exe code generation tool for JavaScript.

Sdk.Soap.js Action Message Generator
Contains a sample to generate support libraries for custom actions in your organization. Actions are like custom messages you define using the workflow editor.
Sdk.Soap.js Samples

Contains a variety of samples showing the use of the Sdk.Soap.js library.

Der originale Post:
http://blogs.msdn.com/b/crm/archive/2014/04/28/new-microsoft-crm-sdk-sample-sdk-soap-js.aspx

Ein erster Blick in den Code ist vielversprechend:

 var account = new Sdk.Account() 
 account.Name.setValue("Sample Account 001"); 
 account.CreditOnHold.setValue(false); 
 account.Address1_Latitude.setValue(47.638197); 
 account.Address1_Longitude.setValue(-122.131378); 
 account.NumberOfEmployees.setValue(500); 
 account.Description.setValue("This is a description."); 
 account.CreditLimit.setValue(200000.00); 
 account.AccountCategoryCode.setValue(1); 

Sdk.Async.create(
  account,
  function (id) { },
  new ErrorHandler("create account").getError);

Sdk.Soap.js:
http://code.msdn.microsoft.com/SdkSoapjs-9b51b99a