## jQuery Core
![tools](images/icon_tool.png)
### getElementsByClassName
```html contenteditable data-show-source="examples/01_getElementsByClassName.html"
loading source...
```
[» Demo](examples/01_getElementsByClassName.html)
```html contenteditable data-show-source="examples/02_getElementsByClassName2.html"
loading source...
```
[» Demo](examples/02_getElementsByClassName2.html)
### jQuery!
```html contenteditable data-show-source="examples/03_getElementsByClassName3.html"
loading source...
```
[» Demo](examples/03_getElementsByClassName3.html)
## The jQuery way
1. **Select** some HTML (Sizzle Selector Engine)
2. Do something with it
## jQuery core
DOM manipulation✓
event handling✓
animations
AJAX✓
plugins✓(next webinar)
```js fragment
$("#myId") // selects (one) element with the id "myId"
$(".myClass") // selects all elements with the class name "myClass"
$("div") // selects all elements of type "div"
$("div:first") // selects the first element of type "div"
$("div:odd") // selects odd "div" elements, zero-indexed
$("input:not(:checked)") // equals to
$("input").not(":checked")
```
### Selector Performance
### Example
```html contenteditable data-show-source="examples/04_jQuery_object.html"
loading source...
```
[» Demo](examples/04_jQuery_object.html)
## Event Model
![tools](images/icon_flash.png)
DOM Level 3 Event Model
![W3C: level 3 event](images/events_dom.png)
DOM Level 3 Event Model
```js contenteditable
document.getElementsByTagName('a')[0]
.addEventListener("click", function() {
alert(this.text);
});
```
jQuery Event Model
![jQuery Event Model](images/events_jquery.png)
jQuery Event Model
Demo Link
```js fragment contenteditable
$('a').on('click', function() {
alert(this.text);
});
```
```js fragment
$('a').click(function() {
alert(this.text);
});
```
### Some Ajax
```js contenteditable
$(function() {
$('#example').dataTable({
sAjaxSource: "/api/Note/"
});
});
```
### First try
```js contenteditable
$(function() {
$('td').click(function() {
alert($(this).text());
});
});
```
### Delegated events
```js contenteditable
$(function() {
$('table').on('click', 'td', function() {
alert($(this).text());
});
});
```
### API changes!
```js fragment contenteditable
$(selector).live(events, data, handler); // jQuery 1.3+
$(document).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(document).on(events, selector, data, handler); // jQuery 1.7+
```
## Asynchronous Communication
![tools](images/icon_communication.png)
### before jQuery 1.5
```js fragment contenteditable
$.ajax({
url: "/examples/webinar.json",
success: function(result) {
$.each(result, function(index, value) {
console.log(value.Title);
});
}
});
```
### Deferred object
```js fragment contenteditable
$.ajax("/examples/webinar.json")
.done(function(result) {
$.each(result, function(i, value) {
console.log(value.Title);
});
});
```
### Deferred object - Promisses
```js fragment contenteditable
$.when(
$.ajax("/examples/webinar.json"),
$.ajax("/examples/webinar.json"))
.done(function(result1, result2) {
var bothResults = result1[0].concat(result2[0]);
$.each(bothResults, function(i, value) {
console.log(value.Title);
});
});
```
## Best Practices
![tools](images/icon_mustache.png)
## Modul loaders
use AMD (require.js)
```js contenteditable fragment
define('myFirstModule', ['jquery'], function() {
return {
saySomething : function() { alert("hello!"); }
}
});
require(['myFirstModule'], function(t) {
t.saySomething();
});
```
## Own Events
Publish/Subscribe Pattern
```js contenteditable fragment
var $events = $({});
$events.bind('somethingHappens', function() {
alert("Something happened!");
});
$events.trigger('somethingHappens');
```
## ASP.NET MVC
#### Bundling and Minification
## Plugins
![tools](images/icon_tool.png)
## 1. Utility functions
similar to global functions
```js contenteditable fragment
(function($) {
$.say = function(what) {
alert('I say ' + what);
};
})(window.jQuery);
```
## 2. Wrapper methods
operate on a jQuery wrapped set
```js contenteditable fragment
(function($){
$.fn.changeColor = function() {
return this.css('color', 'green');
};
})(window.jQuery);
```
## Default options
```js contenteditable fragment
(function($){
$.fn.changeColor = function(options) {
var settings = $.extend({
color: "green"
}, options );
return this.css('color', settings.color);
};
})(window.jQuery);
```
## Chaining!
Always return this
```js contenteditable fragment
(function($){
$.fn.someNewMethod = function() {
return this.each(function(){
});
};
})(jQuery);
```
![Jasmine](images/jasmine_logo.png")
_TDD with [Jasmine](http://pivotal.github.com/jasmine/)_
## Why Jasmine?
BDD-style
similar to JSpec or RSpec, created by authors of jsUnit and Screw.Unit
independent
from any browser, DOM, framework or host language
integrates
into continuous build systems
## Jasmine Bootstrap
```html contenteditable small
_LT_!DOCTYPE html_GT_
_LT_html_GT_
_LT_head_GT_
_LT_title_GT_Jasmine Spec Runner_LT_/title_GT_
_LT_link rel=_QUOT_stylesheet_QUOT_ href=_QUOT_lib/jasmine-1.3.1/jasmine.css_QUOT_ /_GT_
_LT_script src=_QUOT_lib/jasmine-1.3.1/jasmine.js_QUOT__GT__LT_/script_GT_
_LT_script src=_QUOT_lib/jasmine-1.3.1/jasmine-html.js_QUOT__GT__LT_/script_GT_
_LT_!-- include source files here... --_GT_
_LT_script src=_QUOT_src/Player.js_QUOT__GT__LT_/script_GT_
_LT_script src=_QUOT_src/Song.js_QUOT__GT__LT_/script_GT_
_LT_!-- include spec files here... --_GT_
_LT_script src=_QUOT_spec/SpecHelper.js_QUOT__GT__LT_/script_GT_
_LT_script src=_QUOT_spec/PlayerSpec.js_QUOT__GT__LT_/script_GT_
_LT_script_GT_
(function () {
var htmlReporter = new jasmine.HtmlReporter();
var jasmineEnv = jasmine.getEnv();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function (spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function () {
if (currentWindowOnload) { currentWindowOnload(); }
jasmineEnv.execute();
};
})();
_LT_/script_GT_
_LT_/head_GT_
_LT_body_GT_
_LT_/body_GT_
_LT_/html_GT_
```
## Output
## Hello World
```javascript contenteditable
var helloWorld = function() {
return "Hello World!";
};
describe('helloWorld', function() {
it('says hello', function() {
expect(helloWorld()).toEqual("Hello World!");
});
});
jasmine.getEnv().execute();
```
hint: press F12 and paste this code!
## Test-Driven Development
1. Write your tests
1. Watch them fail
1. Make them pass
1. Refactor
1. Repeat
see [Growing Object-Oriented Software, Guided by Tests](http://www.amazon.de/dp/0321503627), page 6
see [Working Effectively with Legacy Code](http://www.amazon.de/dp/0131177052), page 62 or many other
## 1. Write your tests
```javascript contenteditable data-show-source="js/1_jasmine-demo_fail/saveFormat.spec.js"
loading source...
```
## 2. Watch them fail
```javascript contenteditable data-show-source="js/1_jasmine-demo_fail/saveFormat.js"
loading source...
```
jasmine.getEnv().execute(); Demo
## 3. Make them pass
```javascript contenteditable data-show-source="js/2_jasmine-demo_pass/saveFormat.js"
loading source...
```
jasmine.getEnv().execute(); Demo
## 4. Refactor
```javascript contenteditable data-show-source="js/3_jasmine-demo_refactor/saveFormat.js"
loading source...
```
Demo
## 5. Repeat
```javascript contenteditable data-show-source="js/4_jasmine-demo_repeat/saveFormat.js"
loading source...
```
Demo
## Testing HTML
Jasmine is DOM agnostic
comes without tools to set up HTML fixtures
Definition:
A test fixture is a fixed state of a set of
objects used as a baseline for running tests.
## First Solution
in memory fixture with jQuery
```javascript contenteditable
describe('trivial jQuery plugin', function () {
var fixture;
beforeEach(function () {
fixture = $('_LT_div_GT_some HTML code here_LT_/div_GT_');
});
it('should do something', function () {
fixture.myPlugin();
expect(fixture).toHaveClass("newClass");
});
});
jasmine.getEnv().execute();
```
... only works for trivial plugins!
## Clumsy Solution
directly append to/remove from DOM
```javascript contenteditable
describe('my jQuery plugin', function () {
beforeEach(function () {
$('#fixture').remove();
$('body').append('_LT_div id=_QUOT_fixture_QUOT__GT_HTML_LT_/div_GT_');
});
it('should do something', function () {
$('#fixture').myPlugin();
expect($('#fixture')).toHaveClass("newClass");
});
});
jasmine.getEnv().execute();
```
## jasmine-jquery
[custom matchers](https://github.com/velesin/jasmine-jquery#jquery-matchers), HTML/style/JSON fixtures, event spies
```javascript contenteditable
describe('my jQuery plugin', function () {
beforeEach(function() {
jasmine.getFixtures().fixturesPath='js/5_jasmine-demo_jquery';
jasmine.getFixtures().load('jquery.myPlugin.spec.html');
});
it('should do something', function() {
var $div = $('#helloWorld').myPlugin();
expect($div).toHaveClass("newClass");
});
});
jasmine.getEnv().execute();
```
Demo
## Mobile Apps
![tools](images/icon_apps.png)
## Mobile Apps
1. Native apps
2. Mobile optimized Websites
3. Hybrid apps
![Screenshot](images/cordova_bootstrap_knockout.png)
![Screenshot](images/cordova_jQueryMobile.png)
![Screenshot](images/cordova_KendoUiMobile.png)
## Downloads
![tools](images/icon_file.png)
### [bit.ly/devMedia](http://bit.ly/devMedia)
### [bit.ly/devMediaCode](http://bit.ly/devMediaCode)
## 02.10.
[Webinar: require.js & modulares JS - Teil 2](http://developer-media.de/portfolioentry/require-js-prinzipien-fur-modulares-javascript-2/)
50% Wiesn-Rabatt!
Code: Requirejs_JohannesHoppe
# Danke!