Академический Документы
Профессиональный Документы
Культура Документы
OREILLY
^'
Alex MacCaw
JavaScript
Web Applications
OREILLY*
Beijing Cambridge Farnham Koln Sebastopol Tokyo
JavaScript
^'
- - -
-- - - -
- -
2012
32.988.02-018
004.738.5
15
15
32.988.02-018
004.738.5
OReilly. .
.
, , ,
. , ,
, .
ISBN 978-1449303518 .
ISBN 978-5-459-01504-1
..........................................................................................13
1. MVC ....................................................................... 21
2. ........................................................40
3. ................................................................ 53
4. .................................................. 73
5. ...................... 91
. ............................................... 100
7. ............................................................. 109
8. - ................................. 126
9. ...................................................137
........................................................................................13
?...............................................................................13
.............................................................................................................. 14
, ............................................................... 17
.............................................................................................18
, ............................................................18
j Query...............................................................................................................19
Holla................................................................................................................................19
......................................................................................................... 19
............................................................................................................... 20
1. MVC ................................................................. 21
................................................................................................................... 21
....................................................................................................22
MVC?.............................................................................................................. 23
.............................................................................................................................. 23
................................................................................................................. 24
...................................................................................................................... 25
, .................................................................. 26
................................................................................... 28
.................................................... 28
Prototype............................. 31
............................................ 32
............................................................................................................ 33
.................................35
................................................................................... 37
........................................................................................................ 38
2. .................................................40
............................................................................................... 40
..................................................................................... 41
...........................................................................................................42
................................................................................................................ 42
................................................................................................... 44
...................................................................................................45
.............................................................................................. 45
.........................................................................................46
j Q uery............................47
, DOM .................................................. 49
3. ............................................................. 53
MVC ......................................................................53
ORM .................................................................................................................55
.........................................................................................55
O RM .......................................................................................... 56
..................................................................................................58
ID ..........................................................................................59
........................................................................ ................................60
......................................................................................................... 61
........................................................................... 62
Ajax..............................................................................63
JSO N P.............................................................................................................................66
................................... 67
ORM ...................................................................................67
.......................................................................................68
ORM......................................70
............................................................................71
4. ...............................................73
............................................................................................................. 74
..................................................................................................... 74
..................................................................................................... 74
..................................................................................................75
.................................................................................. 76
................................................................. 78
........................................................................................... 79
.............................................................................................. 81
...................................................................................................... 83
........................................................................................................... 85
URL-..........................................................................85
.................................................................................. 86
Ajax Crawling.................................................................................................................87
History API HTML5.........................................................................88
5. ............... 91
.......................................................91
...........................................................................................................................93
.................................................................................................95
..................................................................................................... 95
....................................................................................................................97
........................................................................................................98
6. ....................................... 100
CommonJS....................................................................................................................... 101
....................................................................................................... 102
....................................................................................................... 102
...................................................................................................103
Yabble............................................................................................................................103
RequireJS...................................................................................................................... 104
.............................................................................................. 106
............................................................................. ................107
LABjs.............................................................................................................................107
FU B C............................................................................................................................108
7. ........................................................ 109
..................................................................................................109
............................................................................... 110
....................................................................................................................110
......................................................... .....................................................111
............................................................................................112
..................................................................... 114
......................................... 115
..................................................................................................115
................................................................................................................ 116
...................................................................................... 116
................................................................................................................ 117
.............................................................................................................. 119
..................................................................................120
.......................................................................:.................................. 120
Ajax.... ..............................................................122
j Query............ 124
............................ 124
...........................................................................................................125
8. - ........................ 126
.......................................................... 126
WebSockets..................................................................................................................... 127
Node.js Socket.IO...................................................................................................... 131
................................................................................. 133
.................................................................................................... 135
9. ................................................137
...................................................................................................139
............................................................................................................... 139
QUnit.............................................................................................................................140
Jasmine..........................................................................................................................144
.........................................................................................................................146
............................................................................................ 149
Zombie...........................................................................................................................149
Ichabod....................................................................................................... ...................151
..................................................................................... 152
..........................................................................................153
.................................................................................................................... 153
-............................................................................................................. 154
Firebug..........................................................................................................................155
............................................................................................................................156
....................................................!................ 157
............................................................................................ 158
.............................................................................................. 160
................................................................................ 161
10. ..........................................................164
..................................................................................................... 164
............................................................................................................... 165
............................................................................................................. 167
Gzip............................................................................................ 169
CDN...................................................................................................169
.........................................................................................................................170
............................................................................................................................171
11. Spine.......................................................172
........................................................................................................................ 172
......................... ....................................................................................................173
..................................................................................................173
10
..................................................................................................174
...................................................................................................................... 175
..........................................................................................................................176
............................................................................................. ;............................ 177
...................................................................................................178
....................................................................................................... 179
..................................................................................................................... 180
.............................................................................................. 180
..................................................................................................................183
..........................................................................184
.................................................................................................................... 184
............................................................................................185
............................................................................................... 185
..................................................................................................186
..................................................................................................186
...........................................................................................................187
.........................................................189
C ontact..........................................................................................................190
Sidebar....................................................................................................191
Contacts................................................................................................193
..........................................................................................................196
11
.................................................................................................... 222
.......................................................................................223
.......................................................................................................223
...........................................................................................................223
.............................................................................................................................224
.........................................................................224
................................................................................................227
-............................................................................................... 227
...................................................................................................................228
-..................................................................................................228
................................................................................................229
................................................................ ........................................230
...................................................................................................... 231
......................................................................................................... 231
.....................................................................................................231
.........................................................................................................232
.............................................................................................. 232
CRUD-..........................................................................................................233
........................... 233
............................................................................................... 234
j Query.............................................................................................. 234
script-............................................................................................... 235
S.View ................................................................................................235
Deferred-.......................................................................................................235
, .............................236
S.Controller:
j Query.................................................................................................... 237
................................................................................................239
........................................................................ 240
..................................................................................................... 241
................................................................................................ 241
: CRUD-.......................................243
. jQuery................................................... 245
DOM-................................................................................. 247
DOM................................................................................................................248
..........................................................................................................................250
Ajax............................................................................................................................... ...251
......................................................252
................................................................................................................... 253
jQuery Growl................................................... 254
12
. CSS-............................................... 257
.................................................................................................................... 257
......................................................................................................................... 258
.......................................................................................................258
.............................................................................. 259
................................................................................................................................259
Less?...............................................................................259
....................................................................... 260
Rack........................................................................................... 260
JavaScript................................................................................................260
Less.app.........................................................................................................................260
. CSS3......................................... 262
........................................................................................................................263
................................................................................................................................263
......................................................................................................... 264
.....................................................................................................265
..............................................................................................................266
........................................................................................................................267
................................................................................................................268
.......................................................................................................................268
N- ................................................................................................269
.............................................................'......................................... 269
..............................................................................................270
.........................................................................................................................270
................................................................271
...................................272
............................................................................................................. 272
......................................................................273
...........................................................................................................................274
...............................................................................................275
Modemizr..................................................................................................................... 276
Google Chrome Frame.......................................................................... 277
............................................................................................................. 278
1995 JavaScript
Netscape JIT -.
, Ajax
,
JavaScript- .
JavaScript-,
,
.
. JavaScript
,
,
.
JavaScript: CSS3
HTML5, ,
, Safari, Chrome, Firefox ,
, IE9.
,
,
. HTML5 CSS3
, , ,
.
.
. ,
, ,
.
. ,
JavaScript-.
?
JavaScript, ,
JavaScript: (,
2012).
14
JavaScript, , jQuery ,
JavaScript-.
, , ,
JavaScript-.
1
JavaScript
,
. MVC,
JavaScript -,
.
2
, , API
. jQuery,
.
, DOM-,
PubSub.
3
MVC- ,
.
MVC ,
ORM- .
JSONP Ajax. ,
HTML5 ,
RESTful.
4
.
,
, DOM. ,
,
URL, , API
HTML5. .
5
JavaScript.
,
( , s c r ip t-
15
).
.
6
JavaScript- CommonJS. ,
CommonJS, CommonJS
, Yabble RequireJS.
,
. ,
CommonJS, Sprockets LABjs.
7
, HTML5: API
. ,
, , ,
.
() .
XMLHttpRequest Level , ,
j Query Ajax API.
8
WebSockets.
.
WebSockets ,
API JavaScript. RPC-,
WebSockets .
Socket. I
.
9
,
- JavaScript.
, ,
,
, QUnit Jasmine.
, Selenium.
, - Firefox WebKit,
JavaScript.
16
10
,
- JavaScript: .
, , gzip- ,
.
(CDN)
,
.
11
JavaScript, . Spine
VC- ,
, .
: , , .
,
, , .
12
Backbone, JavaScript-.
Backbone, ,
, .
RESTful JSON Backbone
. ,
.
13
JavaScriptMVC,
, j Query
- JavaScript.
JavaScriptMVC, , ,
. , CRUD, ,
, JavaScriptMVC.
j Query,
,
. j Query
, .
API, DOM, DOM,
, .
17
,
,
:
URL, , ,
.
,
, , , , , , ,
, , , , , , ,
, , , , , , XML-,
HTML-, , .
, ,
, , .
18
GitHub ( https://github.com/
maccman/book-assets).
zip- ( https://glthub.com/maccman/book-assets/zipball/master)
.
. , ,
.
assets/_ /.
,
assert() assertEqual().
assert () () ,
true;
, .
assert () : .
true, :
var assert = function(value, msg) {
if ( lvalue )
throw(msg || (value + " true));
};
assertEqual() ,
.
, assert (), .
, :
var assertEqual = function(vall, val2, msg) {
if (vail !== val2)
throw(msg || (vail + " " + val2));
};
, ,
. ,
:
assert( true );
// assertEqual()
assert( false === false )j
assertEqual( 1, 1 );
assertEqual(), , ,
,
jQuery
19
. ,
assets/chOO/deep_equality.html.
jQuery
jQuery,
JavaScript-, ,
DOM-,
Ajax.
, , , jQuery
JavaScript,
.
jQuery,
. API,
DOM-. jQuery
.
Holla
, Holla ,
JavaScript. Holla ,
,
. , Holla , :
CSS3 HTML5 ;
;
Sprockets Less;
WebSockets ;
JavaScript-, .
, .
,
. ,
,
, .
.
(Stuart Eccles), (Tim Malbon),
20
Holla
|
*,
) (+
'
Coogle
# CD
H o lla
Share
. 0.1. Holla, -
, ,
comp@piter.com ( , ).
!
, , GitHub
(https://github.com/maccman/book-assets).
- http://www.piter.com
.
MVC
JavaScript
. ,
Netscape ,
Google V8. ,
ECMAScript.
.
JavaScript, -
. ,
- , ,
, ,
. JavaScript?
- , JavaScript,
, Java
Java,
. - , ,
. ,
Python Ruby,
, .
JavaScript .
JavaScript ,
, ,
, , -
. , ,
, ,
.
JavaScript .
JavaScript- ,
JavaScript
22
1. MVC
, . , Gmail
Google Maps,
, .
JavaScript . JavaScript
,
,
, ,
.
, JavaScript. , , -
. - ,
JavaScript, . ,
-- (Model View Controller, MVC),
HTML JavaScript.
JavaScript
, ,
(Douglas Crockford) JavaScript: The Good Parts (
OReilly). ,
JavaScript-,
-.
JavaScript-
, ,
. ,
, ,
JavaScript-, HTML-.
,
.
, .
JavaScript . ,
, ,
, Python Ruby.
, ,
?
, MVC,
,
. ,
JavaScript-.
MVC?
23
MVC?
MVC , :
(Model, ), (View, )
(Controller, ). ,
.
1.
2.
3.
4.
.
.
, .
.
, , . 1.1 ,
- Holla.
H olla
3 CD
Profile
Hello there!
Activity
Settings
V.
___________ J
Share
. 1.1. - Holla
1.
2.
3.
4.
5.
-.
.
Chat Model.
.
- ^-.
MVC
. MVC-
, .
, .
MVC .
, .
, User, ,
, .
.
, .
24
1. MVC
, ,
, .
, : MVC- .
.
,
. ,
-, ,
, .
, :
var user = users["foo"];
destroyUser(user);
:
var user = User.find("foo");
user.destroy();
.
destroyllser(),
.
. destroy()
User,
. ,
, .
, ,
destroy(), .
3,
, (object-relational mapper, ORM).
, , ,
, . JavaScript
HTML, CSS JavaScript.
, ,
.
, ,
.
.
.
, MVC ,
.
25
: ,
, .
, , ,
:
// template.html
<div>
<script>
function formatDate(date) {
/*...*/
};
</script>
${ formatDate(this.date) }
</div>
formatDate() ,
MVC, -
, .
, , , ,
MVC-.
// helper.js
var helper = {};
helper.formatDate = function(){ /* ... */ };
// template.html
<div>
${ helper.formatDate(this.date) }
</div>
helper,
.
,
5.
MVC.
.
, ,
(, )
.
. , ,
.
26
1. MVC
-
. , jQuery:
var Controller = {};
//
(Controller.users = function($){
var nameClick = function(){
/*...*/
>;
//
$(function(){
$("#view .name").click(nameClick);
>)(jQuery);
users,
Controller.
,
.
.
, .
MVC
.
4.
,
MVC,
, JavaScript.
.
JavaScript ,
,
. , JavaScript
, , .
.
JavaScript , , ,
JavaScript , , , .
jQuery,
, . JavaScript ,
, . . .
, , , ,
JavaScript , .
JavaScript
new. -
27
.
JavaScript.
- new.
new , return.
, new
:
var Person - function(name) {
this.name = name;
};
// Person
var alice =^new Person('alice');
//
assert( alice instanceof Person );
, -
, ,
. , new.
// !
Person('bob'); //=> undefined ( )
undefined,
( ), name.
- , new.
- new,
() ,
. , th is
. , ,
.
, -,
th is.
, , , ,
:
var Class = function(){
var klass = function(){
this.init.apply(this, arguments);
};
klass.prototype.init
return klass;
= function(){};
};
>;
// :
var person = new Person;
28
1. MVC
:
JavaScript 2, class .
class _class
klass.
JavaScript:
Person.find = function(id){ /*...*/ };
var person = Person.find(l);
prototype:
Person.prototype.breath = function(){ /*...*/ };
var person = new Person;
person.breath();
fn:
Person.fn = Person.prototype;
Person.fn.run = function(){ /*...*/ };
jQuery,
jQuery, jQuery .fn.
. ,
-.
, ,
- :
var Person = new Class;
// , .
Person.find = function(id){ /* ... *1 };
//
var person = Person.find(l);
29
, ,
:
var Person = new Class;
// ,
Person.prototype.save = function(){ /* ... */ };
//
var person = new Person;
person.save();
,
.
, .
: extend() include():
var Class = function(){
var klass = function(){
this.init.apply(this, arguments);
};
klass.prototype.init
= function(){};
//
klass.fn = klass.prototype;
//
klass.fn.parent = klass;
//
klass.extend = function(obj){
var extended = obj.extended;
for(var i in obj){
klassfi] = obj[i];
>
if (extended) extended(klass)
};
//
klass.include = function(obj){
var included = obj.included;
for(var i in obj){
klass.fn[i] = obj[i];
>
if (included) included(klass)
};
return klass;
>;
30
1. MVC
extend(), .
:
var Person = new Class;
Person.extend({
find:
function(id) { /* ... */ },
exists: functions(id) { /* ... */ }
});
include() , ,
, .
, ,
.
var Person = new Class;
Person.include({
save:
function(id) { /* ... */ },
destroy: functions(id) { /* ... */ }
});
(extended)
(included). ,
:
Person.extend({
extended: function(klass) {
console.log(klass, " !");
}
});
Ruby,
. ,
. ,
.
var ORMModule = {
save: function(){
//
}
};
31
Prototype
prototype,
. ,
.
JavaScript , ,
, . .
-: , ,
.
, .
.
JavaScript
. , JavaScript
,
Object .prototype. , , ,
undefined ( ).
, Array.prototype,
JavaScript.
,
-.
-.
:
var Animal = function(){};
Animal.prototype.breath = function(){
console.log('');
};
var Dog = function(){};
// Dog () Animal ()
Dog.prototype = new Animal;
Dog.prototype.wag = function(){
console.log(' ');
};
:
var dog = new Dog;
dog.wag();
dog.breath(); //
32
1. MVC
.
(parent):
var Class = function(parent){
var klass = function(){
this.init.apply(this, arguments);
};
// klass
if (parent) {
var subclass = function() { };
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
>;
klass.prototype.init = function(){};
//
klass.fn = klass.prototype;
klass.fn.parent = klass;
klass._super = klass._proto__;
/* (include) (extend)... */
return klass;
};
Class parent,
.
. ,
, .
_proto__;. , Super, js,
,
.
,
Class:
var Animal = new Class;
Animal.include({
breath: function(){
console.log('');
});
var Cat = new Class(Animal)
//
var tommy = new Cat;
tommy.breath();
JavaScript, . ,
, . , . .
th is, , .
, : apply()
11(). ,
.
apply () : .
, . :
function.apply(this, [1, 23 3])
call() , -.
,
. ,
, apply(), .
function.call(this, 1, 2, 3);
? ,
. JavaScript
,
. (
, .
- , , .)
j Query
apply() call () API,
each(). , ,
, :
$(*.clicky1).click(function(){
// 'this*
$(this).hide();
});
$(' ').each(function(){
// 'this'
$(this).remove();
34
1. MVC
th is . :
var clicky * {
wasClicked: function(){
/*...*/
addListeners: function(){
var self * this;
$('.clicky').click(function(){
self.wasClicked()
});
}
>;
clicky.addListeners();
, apply,
, :
var proxy = function(func, thisObject){
return(function(){
return func.apply(thisObject, arguments);
;
};
var clicky = {
wasClicked: function(){
/*...*/
b
addListeners: function(){
var self = this;
$('.clicky').click(proxy(this.wasClicked, this));
}
};
,
click; jQuery, , .
API jQuery -,
( , , , jQuery.proxy ()):
$('.clicky').click($.proxy(function(){ /* ... */ }, this));
1() 11()
.
:
var {
log: function(){
if (typeof console == "undefined") return;
35
//
console.log.apply(console, args);
>
};
,
, , , console.log().
arguments,
, ,
. ,
, j query.
makeArray().
-, ,
, .
- , ,
,
. .:
var Class = function(parent){
var klass = function(){
t h i s . i n i t . app ly (th is, arguments);
};
k la ss.p ro to ty p e .in it = function(){};
klass.fn = klass.prototype;
// -
klass.proxy = function(func){
var s e lf = th is ;
return(function(){
return fu n c.ap p ly (self, arguments);
});
}
//
klass.fn.proxy = klass.proxy;
return klass;
};
36
1. MVC
proxy () ,
:
var Button = new Class;
Button.include({
init: function(element){
this.element = jQuery(element);
// (click)
this.element.click(this.proxy(this.click));
h
click: function(){ / * . . . * / }
;
click() -,
this.element, Button,
. JavaScript ECMAScript,
(ES5)
bind().
,
this. :
Button.include({
init: function(element){
this.element = jQuery(element);
// click
this.element.click(this.click.bind(this));
L
click: function(){ / * . . . * / }
});
()
click() .
bind(),
.
,
ES5 ,
. , ,
bind (), :
if ( !Function.prototype.bind ) {
Function.prototype.bind = function( obj ) {
var slice = [].slice,
args = slice.call(argumentsi 1),
self = this,
nop = function () {},
37
bound function () {
return self.apply( this instanceof nop ? this : ( obj || {} ),
args.concat( slice.call(arguments) ) );
};
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
}
Function prototype ,
: -
. (shimming)
, ,
JavaScript. es5-shim,
, ES5.
, ,
.
.
(_).
, API.
, .
JavaScript ,
, ,
. ,
,
JavaScript:
var Person = function(){};
(function(){
};
})();
38
1. MVC
,
(findByld),
. Person
, .
var,
.
,
, :
(function(exports){
var foo = "bar";
//
exports.foo = foo;
})(window);
assertEqual(foo, "bar"); 7
,
, ,
. jQuery ,
HJS.
, $. Class.
create:
var Person = $.Class.create({
//
initialize: function(name) {
this.name = name;
}
});
:
var Student = $.Class.create(Personi {
price: function() { /* ... */ }
});
:
Person.find = function(id){ /* ... */ };
39
API HJS ,
clone() equal():
var alex = new Student("Alex");
var bill = alex.clone();
assert( alex.equal(bill) );
Ho HJS
Spine.
spine.js:
<script src="http://maccman.github.com/spine/spine.js"> </script>
<script>
var Person = Spine.Class.create();
Person.extend({
find: function() { /* ... */ }
});
Person.include({
init: function(atts){
this.attributes = atts || {};
}
});
Spine API, ,
.
extend(),
include().
,
Spine.Class.
jQuery,
Prototype. API ,
.
jQuery (John Resig)
(classical inheritance with
the library). , ,
JavaScript.
JavaScript-,
.
JavaScript.
Netscape Microsoft ,
.
W3C, Internet Explorer
IE9.
, , jQuery Prototype,
, API,
. ,
,
, W3C.
, addEventListener ()
: (, click), , . .
() , useCapture (
). ,
DOM- , ,
, :
var button = document.getElementById("createButton");
button.addEventListener("click", function(){ /* ... */ }, false);
, removeEventListener()
,
addEventListener(). -
, :
var div = document.getElementByld("div");
var listener = function(event) { /* ... */ };
div.addEventListener("click", listener, false);
div.removeEventListener("click", listener, false);
41
- (listener)
(event),
, , .
.
, ,
:
click ()
dblclick ( )
mousemove ( )
mouseover ( )
mouseout ( )
focus ( )
blur ( )
change (, )
submit ( )
- Quirksmode.
, .
,
? , , , Netscape Microsoft
.
Netscape 4 ,
, -
, . . .
Microsoft ,
, ,
. . .
, , ,
, . W3C
.
, W3C, ,
, .
, useCapture
addEventListener(). ,
addEventListener(), true,
42
2.
, false,
:
// false
button.addEventListener("click", function(){ / * . . . * / } , false);
, , .
, addEventListener()
false.
,
stopPropagation(), .
, :
button.addEventListener("click", function(e){
e .stopPropagation();
/*...*/
b fa ls e );
, , jQuery, stoplmmediatePropagation(),
, .
. ,
, ,
.
.
.
preventDefault(), .
false:
form.addEventListener("submit", function(e){
/*...*/
return confirm("Bbi ?");
b false);
confirm() false, . .
, ,
, false, .
stopPropagation() preventDefault(),
. ,
43
W3C, ,
.
:
bubbles
, DOM
( )
, :
button
, , ( )
( - )
ctrlKey
, , Ctrl
altKey
, , Alt
shiftKey
, , Shift
metaKey
, , Meta
, :
isChar
, ,
charCode
(
keypress)
keyCode
which
,
, :
pageXypageY
(. . )
screenXt screenY
44
2.
, :
currentTarget
DOM-
target, originalTarget
DOM-
relatedTarget
DOM-, ( )
, W3C,
. , , jQuery Prototype,
.
, ,
JavaScript,
. , API
jQuery,
, Prototype, MooTools YUI.
API, .
API jQuery
bind().
jQuery, :
jQuery("#element").bind(eventName, handler);
,
:
jQuery("#element").bind("click", function(event) {
//
});
...
jQuery , (click),
(submit) (mouseover).
:
$("#myDiv").click(function(){
//
});
...
,
, . . ,
.
(load) :
jQuery(window).bind("load", function() {
$("#signinForm").submit(checkForm);
});
45
,
DOM DOMContentLoaded.
DOM,
. , ,
.
DOMContent Loaded , jQuery
ready(),
:
jQuery.ready(function($){
$("#myForm").bind("submit", function(){ /* ... */ });
});
ready ()
jQuery:
jQuery(function($){
// ,
});
, ,
.
addEventListener()
::
new function(){
this.appName = "wem";
document.body.addEventListener("click", function(e){
// , appName
alert(this.appName);
}, false);
>;
, . 1,
- .
, jQuery proxy (),
,
:
$("signinForm").submit($.proxy(function(){ /* ... */ }, this));
, ,
.
46
2.
, SproutCore,
:
// ul
list.addEventListener("click", function(e){
if (e.currentTarget.tagName == "li") {
/*...*/
return false;
}
}, fa ls e );
jQuery :
delegate() , .
click
li. , delegate(), ,
:
// ! 'li' ( )
$("ul li").click(function(){ /* ... */ });
//
$("ul").delegate("li", "click", /* ... */);
,
,
, .
li, ,
click.
, ,
. ,
,
jQuery. W3C, ,
,
, jQuery
Prototype.
jQuery , t r i g
ger (). ,
. :
//
$(".class").bind("refresh.widget", function(){});
//
$(".lass").trigger("refresh,widget");
47
t rigger ().
:
$(".class").bind("frob.widget", function(event, dataNumber){
console.log(dataNumber);
});
$(".class").trigger("frob.widget", 5);
,
DOM.
jQuery
,
jQuery,
, DOM.
jQuery, ,
jQuery.
-
,
.
.
, jQuery
. u l-,
(click). ,
active, active
:
<ul id="tabs">
<li data-tab="users">Users</li>
<li data-tab="groups">Groups</li>
</ul>
<div id="tabsContent">
<div data-tab="users"> ... </div>
<div data-tab="groups"> ... </div>
</div>
, div- tabsContent,
.
active div-, ,
.
48
2.
CSS,
active:
jQuery.fn.tabs = function(control){
var element = $(this);
control = $(control);
element.find("li").bind("click", function(){
// active
element.find("li").removeClass("active");
$(this).addClass("active");
// active tabContent
var tabName = $(this).attr("data-tab");
control.find(">[data-tab]").removeClass("active");
control.find(">[data-tab='" + tabName + "']").addClass("active");
});
//
element.find("li:first").addClass("active");
// 'this'
return this;
>;
prototype jQuery,
jQuery:
$("ul#tabs").tabs("#tabContent");
?
,
.
delegate().
, , . ,
, , ,
.
, ,
. change.tabs
,
active :
jQuery.fn.tabs = function(control){
var element = $(this);
control = $(control);
element.delegate("li", "click", function(){
//
var tabName = $(this).attr("data-tab");
, DOM
49
//
element.trigger("change.tabs", tabName);
});
//
element.bind("change.tabs", function(e, tabName){
element.find("li").removeClass("active");
element.find(">[data-tab='" + tabName + "']").addClass("active");
});
element.bind("change.tabs", function(e, tabName){
control.find(">[data-tab]").removeClass("active");
control.find(">[data-tab=" + tabName + "']").addClass("active");
});
//
var firstName = element.find("li:first").attr("data-tab");
element.trigger("change.tabs", firstName);
return this;
>;
, ?
, ,
,
. ,
change.tabs :
$("#tabs").trigger("change.tabs", "users");
,
:
$("#tabs").bind("change.tabs", function(e, tabName){
window.location.hash = tabName;
});
$(window).bind("hashchange", function(){
var tabName = window.location.hash.slice(l);
$("#tabs").trigger("change.tabs", tabName);
});
.
,
DOM
, , ,
,
50
2.
.
(DOM),
.
-, .
- (Publish/Subscribe, Pub/Sub)
, : .
,
, .
,
, . ,
.
,
.
, Pub/Sub ?
, ,
. PubSub,
:
var PubSub = {
subscribe: function(ev; callback) {
// _callbacks,
var calls = this._callbacks || (this._callbacks = {});
// ,
// ,
(this._callbacks[ev] || (this._callbacks[ev] = [])).push(callback);
return this;
publish: function() {
//
var args = Array.prototype.slice.call(arguments, 0);
// ( )
var ev
= args.shift();
// , _callbacks
//
var list, calls, i, 1;
if (!(calls = this._callbacks)) return this;
if (!(list = this._callbacks[ev])) return this;
//
for (i * 0, 1 = list.length; i < 1; i++)
list[i].apply(this, args);
return this;
, DOM
51
>
>;
//
PubSub.subscribe("wem", function(){
alert("Wem!");
5
PubSub.publish("wem");
,
, (:).
PubSub.subscribe("user:create", function(){ /* ... */ });
jQuery, ,
(Ben Alman). ,
:
/*!
* jQuery Tiny Pub/Sub - V0.3 - 11/4/2010
* http://benalman.com/
*/
(function($){
var = $({});
$.subscribe = function() {
o.bind.apply( o, arguments );
};
$.unsubscribe = function() {
o.unbind.apply( o, arguments );
};
$.publish = function() {
o.trigger.apply( o, arguments );
>;
})(jQuery);
>);
$.publish( "/some/topic", "a", "b", "c" );
52
2.
Pub/Sub ,
. PubSub
:
var Asset = {};
// PubSub
jQuery.extend(Asset, PubSub);
// publish subscribe
Asset.subscribe("create", function(){
//
>);
...
Asset , PubSub,
extend(), jQuery.
publish() subscribe() Asset.
, -
(ORM), ()
Ajax-3anpoca.
.
,
.
JavaScript-
. -,
.
.
,
. ,
, .
,
.
,
. ,
,
.
.
MVC
,
. MVC,
( MVC).
. ,
,
.
54
3.
JavaScript ,
. :
var User = {
records: [ / * . . . * / ]
>;
User.records. , ,
User. ,
fetchRemote() :
var User = {
records: [],
fetchRemote: function(){ / * . . . * / }
>;
- MVC.
(
) .
, ,
. , destroy()
. , ,
User:
var user = new User;
user.destroy()
, User ,
:
var User = function(atts){
this.attributes = atts || {};
};
User.prototype.destroy = function(){
/*...*/
};
, ,
, User:
User.fetchRemote = function(){
/* . . . */
};
, (Peter Michaux),
.
ORM
55
ORM
- (ORM)
, JavaScript.
,
JavaScript-. ORM, , ,
,
, Ajax- .
HTML ,
, .
, ORM.
ORM ,
. ORM
SQL, ORM
JavaScript.
,
. ,
, ,
,
.
ORM Object.
create(), 1 ,
. -
new , .
Object.create() , -,
-. ,
, ,
.
Object.create() ECMAScript, ,
, IE, .
, :
if (typeof Object.create !== "function")
Object.create = function(o) {
function F() {>
F.prototype = o;
return new F();
};
(Douglas
Crockford) Prototypal Inheritance. ,
JavaScript.
56
3.
Model,
:
var Model = {
inherited: function(){}>
created: function(){},
prototype: {
init: function(){}
b
create: function(){
var object = Object.create(this);
object.parent = this;
object.prototype = object.fn = Object.create(this.prototype);
object.created();
this.inherited(object);
return object;
b
init: function(){
var instance = Object.create(this.prototype);
instance.parent = this;
instance.init.apply(instance, arguments);
return instance;
}
>;
Object.reate(),
, . create()
, Model,
. init() ,
Model.prototype, . . Model:
var Asset = Model.create();
var User = Model.create();
var user = User.initQ;
ORM
, Model, :
//
jQuery.extend(Model, {
find: function(){}
ORM
57
//
jQuery.extend(Model.prototype, {
init: function(atts) {
if (atts) this.load(atts);
b
load: function(attributes){
for(var name in attributes)
this[name] - attributes[name];
>
;
jQuery.extend()
for ,
, load().
:
assertEqual( typeof Asset.find, "function" );
,
extend() include() Model:
var Model = {
/* ... ... */
extend: function(o){
var extended = o.extended;
jQuery.extend(this, o);
if (extended) extended(this);
b
include: function(o){
var included = o.included;
jQuery.extend(this-prototype, o);
if (included) included(this);
>
};
//
Model.extend({
find: function(){}
;
//
Model.include({
init: function(atts) { /* ... */ },
load: function(attributes){ / * . . . * / }
;
(assets) :
var asset = Asset.init({name: "foo.png"});
58
3.
, . .
, .
records, Model.
,
:
//
Model.records - {};
Model.include({
newRecord: true,
create: function(){
this.newRecord = false;
this.parent.records[this.id] = this;
b
destroy: function(){
delete this.parent.records[this.id];
>
;
? ,
:
Model.include({
update: function(){
this.parent.records[this.id] = this;
>
>);
,
, :
//
Model.include({
save: function(){
this.newRecord ? this.create() : this.update();
}
;
fin d (), ID?
Model.extend({
// no ID
find: function(id){
return this.records[id] || throw(" ");
>
});
ORM
59
, ORM, :
var asset = Asset.init();
asset.name = "same, same";
asset.id
= 1
asset.save();
var asset2 = Asset.init();
asset2.name = "but different";
asset2.id
= 2;
asset2.save();
assertEqual( Asset.find(l).name, "same, same" );
asset2.destroy();
ID
ID .
, , , .
GUID- (Globally Unique Identifier
). , JavaScript
128- GUID-
API, .
- GUID-
, ,
-, BIOS,
,
,
! JavaScript
Math.random().
(Robert Kieffer) GUID, Math.random() GUID. ,
:
Math.guid = function(){
return '--4--'.replace(/[xy]/g,
function(c) {
var r = Math.random()*16|0, v = == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
}).toUpperCase();
>;
60
3.
, GUID-,
ORM .
create():
Model.extend({
create: function(){
if :( !this.id ) this.id = Math.guid();
this.newRecord = false;
this.parent.records[this.id] = this;
}
});
ID GUID-:
var asset = Asset.init();
asset.save();
asset.id //=> "54E52592-313E-4F8B-869B-58D61F00DC74"
ORM, ,
. ,
find () , ,
, .
,
update():
var asset = new Asset({name: "foo"});
asset.save();
//
assertEqual( Asset.find(asset.id).name, "foo" );
// , update()
asset.name = "wem";
// ! ,
// "wem"
assertEqual( Asset.find(asset.id).name, "foo" );
, fin d ().
:
Asset.extend({
find: function(id){
var record = this.records[id];
if ( !record ) throw("Hen3BecTHafl ");
return record.dup();
ORM
61
});
Asset.include({
create: function(){
this.newRecord = false;
this.parent.records[this.id] = this.dup();
b
update: function(){
this.parent.records[this.id] = this.dup();
dup: function(){
return jQuery.extend(true, {}, this);
}
;
: Model.records ,
:
assertEqual( Asset.records, Person.records );
:
var asset = Asset.init();
asset.save();
assert( asset in Person.records );
records
. Model.created()
, ,
:
Model.extend({
created: function(){
this.records = {};
}
});
- ,
.
,
.
,
. ,
.
,
.
62
3.
,
.
, .
, (
).
, ,
? , ,
( ).
, .
,
. - ,
. ,
,
.
HTTP- Ajax JSONP.
,
,
. AJAX
JSON HTML-,
.
,
, ,
.
.
JSON- .
, Ruby on Rails :
<script type="text/javascript">
var User = {};
User.records = <%= raw @users.to_json %>;
</script>
ERB- JSON- .
raw JSON.
HTML :
<script type="text/javascript">
var User = {};
User.records = [{"first_name": "Alex"}];
</script>
ORM
63
JavaScript JSON,
, JavaScript.
Ajax
, ,
, , :
, .
, Ajax
API ,
.
Ajax XMLHttpRequest,
Getting Started Mozilla. ,
, , , ,
jQuery, Ajax API, .
API jQuery,
XMLHttpRequest .
jQuery Ajax API jQuery.
ajax() , ,
. jQuery.ajax()
,
. ,
.
url
URL. ,
success
, .
, .
contentType
Content-Type.
, application/x-www-formurlencoded, .
data
, . , jQuery
URL.
type
HTTP-: GET, POST DELETE.
GET.
dataType
, . jQuery , ,
. dataType , jQuery
MIME- . :
64
3.
text
; ,
script
jQuery JavaScript,
json
jQuery JSON, ,
jsonp
JSONP-, .
, , Ajax-,
, :
jQuery.ajax({
url: "/ajax/endpoint",
type: "GET",
success: function(data) {
alert(data);
}
});
. , jQuery
. jQuery .get () URL,
:
jQuery.get("/ajax/endpoint", function(data){
$(".ajaxResult").text(data);
;
GET-:
jQuery.get("/ajax/endpoint", {foo: "bar"}, function(data){
/*...*/
;
JSON,
jQuery.getDSON(), data "json":
jQuery.getDSON("/json/endpoint", function(j son){
});
jQuery .post (), URL,
:
jQuery.post(H/usersH, {first_name: "Alex"}, function(result){
/* Ajax POST */
});
ORM
65
IE >= 8 ( )
Firefox >= 3
Safari:
Chrome:
Opera:
CORS .
, :
Access-Control-Allow-Origin: example.com
Access-Control-Request-Method: GET,POST
66
3.
,
Access-Control-Allow-Origin, .
,
(origin) (*).
, Safari, OPTIONS,
. Firefox , CORS , .
.
,
Access-Control-Request-Headers:
Access-Control-Request-Headers: Authorization
, Ajax-
,
OAuth:
var req = new XMLHttpRequest();
req.open("POST", "/endpoint", true);
req.setRequestHeader("Authorization", oauth_signature);
JSONP
JSONP, JSON (padding),
CORS
. script,
JSON,
. script -
, .
, scrip t, :
<script src="http://example.com/data.json"> </script>
, data.json, JSON-,
:
jsonCallback({"data": "foo"})
ORM
67
.
, :
window.jsonCallback = function(result){
//
>
. , jQuery API:
jQuery.getJSON("http://example.com/data.json?callback=?H, function(result)
//
;
jQuery URL
,
.
,
.
JSONP
, .
, , API
, CORS JSONP
. Ajax- cookie-
, , API .
, .
CORS/JSONP ,
API,
:
, ,
;
(, ).
,
,
Auth.
ORM
ORM
. ,
. Model populate(),
68
3.
,
records:
Model.extend({
populate: function(values){
// model records
this.records = {};
for (var i=0, il = values.length; i < il; i++) {
var record = this.init(values[i]);
record.newRecord = false;
this.records[record.id] = record;
}
}
});
Model.populate()
:
jQuery.getJSON("/assets", function(result){
Asset.populate(result);
});
ORM.
.
cookie-
Adobe Flash. Cookie- API
, ,
, .
Flash,
.
, HTML5,
. cookie-,
.
, ,
(, ,
), 5 :
IE > * 8
Firefox >* 3.5
Safari >= 4
Chrome > = 4
Opera >= 10.6
ORM
69
API - :
//
var itemsStored = localStorage.length;
// ( -)
localStorage.setltem("someData", "wem");
// , null,
,
, .
JSON,
JSON- ( ),
JSON- :
var object = {some: "object"};
//
localStorage.setItem("seriData", JSON.stringify(object));
//
var result = DSON.parse(loc^lStorage.getItem(MseriDataM));
/
( 5 ),
QUOTA_EXCEEDED_
ERR.
70
3.
ORM
ORM,
.
localStorage,
JSON-. ,
:
var json = JSON.stringify(Asset.init({name: "foo"}));
json //=> "{"parent":{"parent":{"prototype":{}},"records":[]},"name":"foo"}"
, JSON- .
,
. Model ,
:
Model.extend({
created: function(){
this.records = {};
this.attributes = [];
>
});
,
, attributes
Model.
, , records.
attributes(),
:
Model.include({
attributes: function(){
var result = {};
for(var i in this.parent.attributes) {
var attr = this.parent.attributes[i];
result[attr] = this[attr];
>
result.id = this.id;
return result;
}
});
:
Asset.attributes = ["name", "ext"];
attributes () :
var asset = Asset.init({name: "document", ext: ".txt"});
asset.attributesQ; //=> {name: "document", ext: ".txt"};
ORM
71
JSON.stringify(),
to3SON () . JSON
,
records :
Model.include({
toJSON: function(){
return(this.attributes());
>
;
.
JSON- :
var json = JSON.stringif(Asset.records);
json //= M{M7B2A9E8D...":"{"name":"document" ,"ext":".
txt","id":"7B2A9E8D..."}"}"
JSON-,
.
Model : savel_ocal()H loadLocalQ.
Model.records ,
localStorage:
var Model.LocalStorage = {
saveLocal: function(name){
//
var result = [];
for (var i in this.records)
result.push(this.records[i])
localStorage[name] = JSON.stringify(result);
loadLocal: function(name){
var result = DSON.parse(localStorage[name]);
this.populate(result);
>
>;
Asset.extend(Model.LocalStorage);
,
.
.
jQuery- post()
. : URL, :
jQuery.post("/users", {first_name: "Alex"}, function(result){
/* Ajax POST */
});
72
3.
, attributes(),
, POST- :
jQuery.post("/assets", asset.attributesQ, function(result){
/* Ajax POST */
;
REST-, HTTP POST-
PUT- .
Model : createRemoteQ updateRemoteQ,
HTTP- :
Model.include({
createRemote: function(url, callback){
$.post(url, this.attributesQ, callback);
;
>
;
createRemote() Asset,
POST- :
// :
Asset.init({name: "jason.txt"}).createRemote("/assets");
,
- .
,
cookie-. JavaScript-
, ,
.
.
,
.
, JavaScript-
.
.
? ? , DOM?
,
.
DOM.
, ! ,
MVC,
.
?
. ,
.
,
.
,
.
.
,
. .
74
4.
.
, , ,
JavaScript.
. ,
, ,
:
(function(){
/*...*/
>)();
() ,
. JavaScript ,
.
,
.
,
.
, ,
.
, ,
JavaScript
.
.
, .
, ,
, :
(function($){
/*...*/
})(jQuery);
jQuery
, $. ,
, , ,
. jQuery $
.
75
, - ,
. window
, ,
:
(function($, exports){
exports.Foo = "wem";
})(jQuery, window);
assertEqual( Foo, "wem" );
, exports,
, .
,
.
this window:
(function(){
assertEqual( this, window );
>)();
,
. :
(function(){
var mod = {};
mod.contextFunction = function(){
assertEqual( this, mod );
};
mod.contextFunction();
();
contextFunctionQ
mod. this,
. ,
,
:
(function($){
var mod = {};
mod.load = function(func){
$($.proxy(func, this));
&
76
4.
mod.load(function(){
this.view = $("#view");
>);
mod.assetsClick = function(e){
//
};
mod.load(function(){
this.view.find(".assets").click(
$.proxy(this.assetsClick, this)
);
});
})(jQuery);
load(), ,
. ,
jQuery.
proxy ().
, ,
assetsClick().
. ,
.
,
.
load() proxy() include():
(function($, exports){
var mod = function(includes){
if (includes) this.include(includes);
};
mod.fn = mod.prototype;
mod.fn.proxy = function(func){
return $.proxy(func, this);
>;
mod.fn.load = function(func){
$(this.proxy(func));
>;
mod.fn.include = function(ob){
$.extend(this, ob);
};
exports.Controller = mod;
})(jQuery, window);
77
proxy () ,
,
. includeQ
, .
exports,
Controller.
Controller, -.
, class-
:
(function($, Controller){
var mod = new Controller;
mod.toggleClass = function(e){
this.view.toggleClass("over", e .data);
};
mod.load(function(){
this.view = $("#view");
this.view.mouseover(this.proxy(this.toggleClass), true);
this.view.mouseout(this.proxy(this.toggleClass), false);
>);
})(jQuery, Controller);
, view
. , , toggleC lass(),
, c la ss- .
, ,
assets/ch04/modules.html.
, th is.
. ,
Controller, :
Controller.fn.unload = function(func){
jQuery(window).bind("unload", this.proxy(func));
};
includeQ , :
var mod = new Controller;
mod.include(StateMachine);
StateMachine
,
don't repeat yourself DRY ( ).
78
4.
,
DOM, ,
.
,
,
.
DOM. , ,
,
DOM .
,
. Controller -,
,
:
// window
//
var exports = this;
(function($){
var mod = {};
mod.create = function(includes){
var result = function(){
this.init.apply(this, arguments);
};
result.fn = result.prototype;
result.fn.init = function(){};
result.proxy = function(func){ return $.proxy(func, this); };
result.fn.proxy = result.proxy;
result.include = function(ob){ $.extend(this.fn, ob); };
result.extend = function(ob){ $.extend(this, ob); };
if (includes) result.include(includes)
return result;
>;
exports.Controller = modj
})(jQuery);
Controller.createQ
, .
, jQuery(function(){ /* ... * /}).
79
jQuery.ready (), ,
DOM :
jQuery(function($){
var ToggleView = Controller.create({
init: function(view){
this.view = $(view);
this.view.mouseover(this.proxy(this.toggleClass), true);
this.view.mouseout(this.proxy(this.toggleClass), false);
b
this.toggleClass: function(e){
this.view.toggleClass("over", e .data);
>
>);
// Instantiate controller, calling init()
new ToggleViewC'tview");
>);
.
, ,
, .
,
. (ID),
.
ID class,
.
, .
jQuery(),
.
,
:
//
...
init: function(view){
this.view = $(view);
this.form = this.view.find("form");
>
, ,
DOM. ,
80
4.
,
:
elements: {
"form.searchForm": "searchForm",
"form input[type=text]": "searchlnput"
}
, this.searchForm this.searchlnput
. jQuery,
,
.
,
. init(),
:
var exports = this;
jQuery(function($){
exports.SearchView = Controller.create({
//
elements: {
"input[type=search]": "searchlnput",
"form": "searchForm"
//
init: function(element){
this.el = $(element);
this.refreshElements();
this.searchForm.submit(this.proxy(this.search));
search: function(){
console.log("Searching:", this.searchlnput.val());
//
$: function(selector){
// 'el'
return $(selector, this.el);
//
refreshElements: function(){
for (var key in this.elements) {
this[this.elements[key]] = this.$(key);
}
}
});
new SearchView("#users");
});
81
refreshElements()
el, .
refreshElements()
this.searchForm this.searchlnput,
DOM.
, ,
assets/ch04/views.html.
(proxying) events,
.
elements, , :
events: {
"submit form": "submit"
}
SearchView.
refreshElements(), delegateEvents(),
.
,
. Search View search(),
<form /> :
var exports = this;
jQuery(function($){
exports.SearchView = Controller.create({
// ,
//
events: {
"submit form": "search"
init: function(){
/ / ...
this.delegateEvents();
b
search: function(e){ / * . . . * / } ,
//
//
eventSplitter: /A(\w+)\s*(.*)$/,
delegateEvents: function(){
&
82
4.
}
}
}
;
, delegate(),
bindQ delegateEvents().
, el.
, ,
, .
, . .
,
.
Controller,
.
( assets/ch04/finished_
controller.html):
var exports = this;
jQuery(function($){
exports.SearchView = Controller.create({
elements: {
"input[type=search]": "searchlnput",
"form": "searchForm"
events: {
"submit form": "search"
b
;
83
(State machines, , , Finite
State Machines (FSM))
(UI). ,
,
. ?
, : .
, .
.
? ,
, , ,
.
, .
,
.
, ,
,
.
,
, . ,
, . -,
Events, API ,
jQuery (. 2),
:
var Events = {
bind: function(){
if ( Ithis.o ) this. = $({});
this. .bind.apply(this.o, arguments);
b
trigger: function(){
if ( Ithis.o ) this. = $({});
this..trigger.apply(this., arguments);
}
};
Events, , jQuery
DOM,
. StateMachine,
add():
var StateMachine = function(){};
StateMachine.fn = StateMachine.prototype;
&
84
4.
//
$.extend(StateMachine.fn, Events);
StateMachine.fn.add = function(controller){
this.bind("change", function(e, current){
if (controller == current)
controller.activate();
else
controller.deactivate();
});
controller.active = $.proxy(function(){
this.trigger("change", controller);
b this);
};
add ()
active().
active(), .
activate() ,
deactivate() .
, , ,
, :
var conl = {
activate: function(){ /* ... */
deactivate: function(){ / * . . . * / }
};
var con2 = {
activate: function(){ /* ... */ },
deactivate: function(){ / * . . . * / }
};
// StateMachine
var sm = new StateMachine;
sm.add(conl);
sm.add(con2);
//
conl.active();
add(), ,
change, activate()
deactivate(), , .
active(), ,
change:
sm.trigger("change", con2);
85
a c tiv a te ()
, . ,
d eactiv ate() -, . CSS
.
, , . active, ,
:
var conl = {
activ ate: function(){
$( "#conl"). addClass ( "activ e");
b
deactivate: function(){
$("#conl").removeClass("active");
}
};
var con2 = {
activ ate: function(){
$("#con2").addClass("active");
b
deactivate: function(){
$ ("#con2") . removeClass( "activ e");
}
};
.activ e
, :
#1, #con2 { display: none; }
# conl.active, #con2.active { display: block; }
assets/ch04/state_machine.html.
,
URL . ,
URL
. ,
, .
, URL.
URL.
URL
.
URL .
URL-
URL
, - . ,
86
4.
. URL .
,
. , URL
#! /maccman:
http://twitter.com/#!/maccman
, location:
//
window.location.hash = "foo";
assertEqual( window.location.hash , "#foo" );
// "#"
var hashValue = window.location.hash.slice(l);
assertEqual( hashValue, "foo" );
URL , location.hash .
location.hash - URL
#.
, .
, , , ,
.
, .
, hashchange.
, ,
:
window.addEventListener("hashchange", function(){ /* ... */ }, false);
jQuery:
$(window).bind("hashchange", function(event){
// ,
});
hashchange
.
:
IE > - 8
Firefox >= 3.6
Chrome
Safari >= 5
Opera > - 10.6
87
,
jQuery, hashchange
.
,
.
,
:
jQuery(function(){
var hashValue = location.hash.slice(l);
if (hashValue)
$(window).trigger("hashchange");
Ajax Crawling
(search engine crawlers) JavaScript
, .
- :
URL , -
.
, JavaScript-
, Google,
.
.
HTML- ,
JavaScript- .
, . , Google
: Ajax Crawling.
(
):
http://twitter.com/#!/maccman
Google,
Ajax Crawling. URL
, , , , URL :
http://twitter./?_escaped_fragment_=/maccman
88
4.
URL ,
, HTML ,
.
, .
curl -v http://twitter.com/P_escaped_fragment_s/maccman
302 redirected to http://twitter.com/maccman
(302),
(301), URL, ,
-, . . JavaScript- (http://twitter.eom/#!/
maccman). ,
HTML , URL-
_escaped_f ragment_.
Ajax Crawling,
, Fetch as Googlebot.
,
- ,
. -
, Google, JavaScript
, .
API histo
ry .pushState(). : ,
URL-:
// ,
// popstate
var dataObject = {
createdAt: *2011-10-10*,
89
author: 'donnamoss'
};
, ,
.
data
. popstate (
).
title
, , ,
.
url
, URL
. , URL
, , .
URL,
, URL .
History API JavaScript-
, URL HTML-.
history.pushState()
URL, . ,
URL, API, ,
, .
HTML-, ,
, JavaScript.
, JavaScript-,
URL. ,
404 ( ), URL
.
, URL ,
.
History API . history.replaceState()
, history.pushState(),
. ,
history.back() history.forwardQ.
popstate
history.pushState(). event
90
4.
state, data,
history.pushState():
window.addEventListener("popstate", function(event){
if (event.state) {
// history.pushState()
}
>);
URL. jQuery ,
.
:
$(window).bind("popstate", function(event){
event = event.originalEvent;
if (event.state) {
// history.pushState()
>
});
,
.
HTML-,
,
. MVC,
.
! , .
, ,
,
.
HTML-, .
JavaScript- .
-, , ,
,
. Ajax-, JSON-,
.
HTML ,
. ,
,
.
DOM- JavaScript,
. .
JavaScript. DOM-,
document .createElement(), .
92
5.
,
:
var views = document.getElementById("views");
views.innerHTML =
//
var container = document.createElementC'div");
container.id = "user";
var name = document.createElement("span");
name.innerHTML = data.name;
container.appendChild(name);
views.appendChild(container);
API jQuery:
$("#views").empty();
var container = $("<div />").attr({id: "user"});
var name
= $("<span />").text(data.name);
$("#views").append(container.append(name));
, ,
, , , ,
.
MVC- .
HTML
, .
, ,
,
.
, , HTML-,
:
<div id="views">
<div class="groups"> ... </div>
<div class="user">
<spanx/span>
</div>
</div>
jQuery:
$("#views div").hide();
var container = $("#views .user");
container.find("span").text(data.name);
container.show();
,
.
93
HTML,
. ,
, , DOM-.
,
.
JavaScript- , HTML-
, ,
JavaScript, .
JavaScript
, , Smarty , ERB
Ruby, Python.
jQuery.tmpl. jQuery
,
,
, .
, Mustache,
, JavaScript.
Microsoft jQuery .tmpl
,
(Jhn Resig).
jQuery. jQuery.
tmpl(), .
, .
, ,
;
:
var object = {
u r l : "h ttp ://example. com",
getName: function(){ return "Trevor"; }
};
var template = '< l i x a href="${url}">${getName()}</a></li>, ;
var element = jQuery.tmpl(template, o b ject);
// :
94
5.
,
. , i f else,
, JavaScript. ,
,
:
{{if url
${url>
{{/if
if ,
false, 0, null,
Nan undefined. ,
{{/if}}, !
, , ,
, :
{{if messages.length}}
<!-- ... -->
{{else}}
<>, </>
{{/if}}
. JS,
JavaScript-THna Object Array,
{{each}}. Object {{each}},
.
.
,
, $value.
, ,
${$value}. :
var object = {
foo: "bar",
messages: ["Hi there", "Foo bar"]
};
, .
$index .
<ul>
{{each messages}}
<li>${$index + 1}: <em>${$value}</emx/li>.
{{/each}}
</ul>
, jQuery.tmpl API
. ,
95
API,
, lambda-, .
, .
MVC-
. , ,
</>. ,
:
<div>
${ this.data.replace(
/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"*-]*>))/g,
'<a target^Jjlank" href=,,$l,,>$l</a> *) >
</div>
,
, ^
.
helpers.js, -,
autoLink(). -
:
// helper.js
var helper = {};
helper.autoLink = function(data){
var re = /((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g;
return(data.replace(re, '<a target="_blank" href="$l">$l</a> ') );
};
// template.html
<div>
${ helper.autoLink(this.data) }
</div>
: autoLink()
.
JavaScript
s c rip t-
HTML
96
5.
MVC-.
s c rip t-,
.
JavaScript.
,
, MVC-.
Ajax-,
.
, ,
.
JavaScript-
,
.
HTML- .
,
.
, .
,
. ,
, .
s c rip t-,
JavaScript ID.
, .
s c rip t- ,
, .
,
jQuery.fn.tmpl(data) . . tmpl()
jQuery:
<script type="text/x-jquery-tmpl" id="someTemplate">
<span>${getName()}</span>
</script>
<script>
var data = {
getName: function(){ return "Bob" }
>;
, jQuery.tmpl
. ,
.
,
.
97
, ,
.
,
,
. ( ),
, , .
( RequireJS,
6) .
. ,
JavaScript ( ).
JavaScript ,
. ,
,
.
. ,
,
.
,
8.
JavaScript
,
. , JavaScript
.
, methodjnissing Ruby
Python, JavaScript
(getter) (setter).
JavaScript ,
change:
var addChange = function(ob){
ob.change = function(callback){
if (callback) {
if ( !this._change ) this._change = [];
this._change.push(callback);
} else {
if ( !this._change ) return;
for (var i=0; i < this._change.length; i++)
this._change[i].apply(this);
>
>;
>;
98
5.
addChange() change()
. change() , change jQuery.
, change() ,
, change() .
:
var object = {};
object.name = "Foo";
addChange(object);
object.change(function(){
console.log("M3MeHeHo!", this);
//
});
object.change();
object.name = "Bar";
object.change();
, change() ,
change.
.
,
change, .
User,
, change,
, :
<script>
var User = function(name){
this.name = name;
>;
User.records = []
User.bind = function(ev, callback) {
var calls = this._callbacks || (this._callbacks = {});
(this._callbacks[ev] || (this._callbacks[ev] = [])).push(callback);
>;
User.trigger = function(ev) {
var list, calls, i, 1;
if (!(calls = this._callbacks)) return this;
if (!(list = this._callbacks[ev])) return this;
jQuery.each(list, function(){ this() })
>;
User.create = function(name){
this.records.push(new this(name));
this.trigger("change")
};
jQuery(function($){
99
User.bind("change", function(){
var template = $("#userTmpl").tmpl(User.records);
$("#users").empty();
$("#users").append(template);
});
</script>
<script id="userTmpl" type="text/x-jquery-tmpl">
<li>${name}</li>
</script>
<ul id="users">
</ul>
, User,
change User, ,
.
, ,
,
. , , User:
User.create("Sam Seaborn");
change User,
,
. assets/
ch05/model.html.
, JavaScript ,
.
, JavaScript
. , jQuery,
- ,
.
JavaScript,
. ?
function() {
function() {
function() {
function() {
>
>
>
>
,
. ,
s c rip t-, JavaScript, ,
. JavaScript-
.
, s c r ip t- .
, :
<script src="jquery.js" type="text/javascript" charset="utf-8"x/script>
<script src="jquery.ui.js" type="text/javascript" charset="utf-8"x/script>
<script src="application.utils.js" type="text/javascript"
charset="utf-8"x/script>
<script src="application.js" type="text/javascript" charset="utf-8"x/script>
<script src="models/asset.js" type="text/javascript" charset="utf-8"x/script>
<script src="models/activity.js" type="text/javascript" charset="utf-8">
</script>
CommonJS
101
<! -- . . . -->
,
, .
HTTP- JavaScript-,
, ,
. , cookie-,
TCP. ,
SSL.
CommonJS
JavaScript ,
. SpiderMonkey
Rhino load(),
. Node.js require(),
,
. ,
, , Rhino Node.js?
,
, JavaScript,
.
(Kevin Dangoor) CommonJS.
JavaScript
,
:
JavaScript ,
.
',
( !).
[] . ,
- .
, CommonJS.
.
JavaScript
, -, - (Socket streams)
.
102
6.
CommonJS .
;
exports:
// maths.js
exports.per = function(value, total) {
return( (value / total) * 100 );
};
// application.js
var Maths = require("./maths");
assertEqual( Maths.per(50, 100), 50 );
, ,
require(),
. ,
maths.js, Maths.
,
CommonJS- JavaScript, Narwhal
Node.js.
JavaScript- ?
,
, , CommonJS
. JavaScript,
, ,
, (eval-based compilation),
. CommonJS
module transport formaty .
CommonJS- ,
.
.
,
:
// maths.js
require.define("maths", function(require, exports){
exports.per = function(value, total) {
return( (value / total) * 100 );
};
});
103
// application.js
require.define("application", function(require, exports){
var per = require("./maths").per;
assertEqual( per(50, 100), 50 );
} b ["./maths"]); // (maths.js)
. .
,
,
, .
, , ,
CommonJS- .
,
, !
CommonJS-
. ,
.
, ,
.
CommonJS- ,
. ,
, , ,
.
: Transport Transport D. -
, ,
,
.
,
.
Yabble
Yabble .
XHR,
s c rip t-. XHR
, , . . .
eval(), . , CDN.
104
6.
XHR
, :
<script src="https://github.com/jbrantly/yabble/raw/master/lib/yabble.js">
</script>
<script>
require.setModuleRoot("javascripts");
// ,
// script-
require.useScriptTags();
require.ensure(["application"], function(require) {
//
</script>
, , , .
, require():
<script>
require.ensure(["application", "utils"], function(require) {
var utils = require("utils");
assertEqual( utils.per( 50, 200 ), 25 );
</script>
utils , require.
ensure() ,
, .
.
RequireJS
Yabble RequireJS,
. RequireJS
,
Asynchronous Module Definition, AMD. ,
, , API
. RequireJS CommonJS, .
JavaScript require(),
, ,
:
<script>
require(["lib/application", "lib/utils"], function(application, utils) {
// !
;
</script>
105
, utils
require().
, RequireJS
JavaScript-, jQuery Dojo.
,
.
, , :
require(["lib/jquery.js"], function($) {
// jQuery
$("#el").show();
});
, require(),
, /. ,
RequireJS
. :
data-main:
<script data-main="lib/application" src="lib/require.js"x/script>
//...
;
, , ?
, RequireJS
. require.defineQ,
define(). ,
.
, ,
. RequireJS- require(),
:
define(["underscore", "./utils"], function(_, Utils) {
return({
size: 10
;
exports .
. RequireJS-
106
6.
, ,
. ,
API CommonJS, . .
Node.js . : RequireJS
, CommonJS-,
def in e ():
define(function(require, exports) {
var mod = require("./relative/name");
exports.value = "exposed";
});
, ,
, , . . require exports.
, - .
, - :
HTTP-. , ,
, ,
,
, .
, ,
, , .
,
. ,
,
. ,
,
.
, .
, . . .
, rack-modulr Transporter,
-,
.
, , Rack- CommonJS, rackmodulr:
require "rack/modulr"
use Rack:rModulr, :source => "lib", :hosted_at => "/lib"
run Rack::Directory.new("public")
rackup.
lib CommonJS-
107
.
,
:
>> curl "http://localhost:9292/lib/application.js"
require.define("maths"___
Ruby,
. Fly Script CommonJS-,
, Transporter , JSGI, a Stitch Node.js-.
,
,
, . ,
, Sprockets.
require() JavaScript.
, //=,
Sprockets. , //= require Sprockets
, :
//= require <jquery>
//= require "./states"
jquery.js , a states.js
. Sprockets
, , ,
. CommonJS-,
Sprockets .
. , JavaScript
,
.
Sprockets ,
Rack Rails, rack-sprockets. . Sprockets , ,
, JavaScript
, , .
LABjs
LABjs
. -
CommonJS-. LABjs
,
108
6.
. LABjs
. , :
<script>
$LAB
FUBC
:
, (flash of unbehaviored content,
FUBC) . e. ,
JavaScript. ,
JavaScript .
,
CSS, ,
.
-
, -
,
, Adobe Flash. HTML5,
,
-.
,
,
, ,
.
API, HTML5, ,
,
.
Firefox>=3.6
Safari >= 6.0
Chrome >= 7.0
IE:
Opera >= 11.1
IE ,
,
,
. ,
:
if (window.File && window.FileReader && window.FileList) {
// API
>
110
7.
, HTML5,
, ,
. ,
-.
JavaScript ,
. , JavaScript
.
HTML5 File,
,
name
,
size
,
type
MIME- , ,
(""),
.
FileList, , ,
File.
, -,
. HTML5 , .
.
Adobe Flash.
HTML5 multiple. m ultiple
, ,
. ,
HTML5, :
<input type="file" multiple>
; ,
Shift. ,
. Facebook , 85% ,
111
, . , ,
(. . 7.1),
85 40%.
, .
,
. HTML5
, f ile s .
files FileList,
, ,
:
var input = $("in p u t[ty p e= file]");
in p u t. change(function(){
var f il e s = t h i s .f i l e s ;
for (var i=0; i < file s .le n g th ; i++)
a ssert( files[i].ty p e.m atch (/im ag e.* /) )
});
Upload photos
fe cmyk_wallpaper.png
U p lo a d in g tip
You can select multiple photos in the dialogue by holding
the 'command' key down while clicking on the photos
Trouble uploading photos Try the Simple Upfoader
______________________________
- 1
(_ Cancel )
il
<
(3 * ^ 3
Select photos
Cancel
. 7.1. Facebook
. , ,
.
,
, Ajax
. - .
Microsoft 1999 Internet Explorer 5.0, IE
. HTML5 ,
, Safari, Firefox Chrome ,
Microsoft. , ,
112
7.
.
, : dragstart, drag, dragover, dragenter, dragleave, drop dragend.
.
API, HTML5,
, API .
:
Firefox>=3.5
Safari >=3.2
Chrome >=7.0
IE >= 6.0
Opera:
.
, draggable true.
<div id="dragme" draggable="true">nepeTauiH MeHfl!</div>
- .
, dragstart
setData():
var element = $("#dragme");
element.bind("dragstart", function(event){
// jQuery
event = event.originalEvent;
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData("text/plain", $(this).text());
event.dataTransfer.setData("text/html", $(this).html());
event.dataTransfer.setDragImage("/images/drag.png", -10, -10);
});
jQuery ,
dataTransfer.
originalEvent, API .
, dataTransfer,
. setData()
mimetype . drag
text text/html.
drop, . ,
,
,
.
113
text/plain.
, .
: text/plain text/uri-list.
:
//
event.dataTransf.setData("text/uri-list", "http://example.com");
event.dataT ransfer.setData("text/plain", "http://example.com");
//
event.dataTransfer.setData("text/uri-list",
"http://example.com\nhttp://google.com");
event.dataTransfer.setData("text/plain",
"http://example.com\nhttp://google.com");
setDraglmageQ ,
.
/ .
,
. setDraglmageQ
addElement (element, , ),
. ,
, .
, DownloadURL. URL
, . Gmail
,
.
,
Chrome .
, ,
. DownloadURL
: mime-, ,
(:).
$("#preview").bind("dragstart", function(e){
e .originalEvent.dataT ransfer.setData("DownloadURL", [
"application/octet-stream",
// MIME-
"File.exe",
//
"http://example.com/file.png" //
].join(":"));
});
API , HTML5,
assets/ch07/drag.html.
114
7.
API (drop)
.
API .
drop *
: dragover dragenter. , , :
var element = $("#dropzone");
element.bind("dragenter", function(e){
//
e .stopPropagation();
e .preventDefault();
});
element.bind("dragover", function(e){
//
e.originalEvent.dataTransfer.dropEffect = "copy";
//
e .stopPropagation();
e .preventDefault();
});
dropEffect, . e.
dragover, . dragenter dragleave
,
.
dragenter dragover,
drop. drop ,
. dataTransfer
drop files, FileList,
:
element.bind("drop", function(event){
//
event.stopPropagation();
event.preventDefault();
event = event.originalEvent;
//
var files = event.dataTransfer.files;
for (var i=0; i < files.length; i++)
alert("Dropped " + files[i].name);
});
, ,
dataTransfer.getData(), .
, undefined (),
var text = event.dataTransfer.getData("Text");
115
dataTransfer types,
, DOMStringList ( ) mime, dragstart. ,
- , "Files".
var dt = event.dataTransfer
for (var i=0; i < dt.types.length; i++)
console.log( dt.types[i], dt.getData(dt.types[i]) );
, drop, assets/ch07/drop.html.
-
. ,
, ,
,
. ,
(body) dragover.
$("body").bind("dragover", function(e){
e .stopPropagation();
e .preventDefault();
return false;
});
. API
HTML5,
, .
IE, , ,
, IE 5.0. WebKit API Microsoft
, API .
, :
dataTransfer clipboardData.
Firefox , API
, , . WebKit
(Safari Chrome) , , W3C
, API
. :
116
7.
, , , :
beforecopy
beforecut
cut
, beforecopy beforecut
, .
- , ,
clipboardData,
. dataTransfer,
clipboardData setData(), mime . ,
, .
IE clipboardData .
,
, .
Firefox , Data,
. Chrome ,
.
$("textarea").bind("copy", function(event){
event.stopPropagation();
event.preventDefault();
var cd = event.originalEvent.clipboardData;
// IE
if ( !cd ) cd = window.clipboardData;
// Firefox
if ( led ) return;
cd.setData("text/plain", $(this).text());
});
, ,
.
- ,
, .
: beforepaste paste. paste
, ,
117
- .
. Chrome ,
. A IE Safari ,
.
API API drop. clipboardData,
getData(),
mime-. , ,
types null, , mime-
. ,
,
, :
$("textarea").bind("paste", function(event){
event.stopPropagation();
event.preventDefault();
event = event.originalEvent;
var cd = event.clipboardData;
// IE
if ( !cd ) cd = window.clipboardData;
// Firefox
if ( !cd ) return;
$("#result").text(cd.getData("text/plain"));
// Safari
var files = cd.files;
});
WebKit files clip
boardData, . ,
, .
, - ? , , .
, Cappuccino ,
. Command/
Ctrl + v ,
. ,
, , .
File,
FileReader .
FileReader
, , .
FileReader .
, , .
118
7.
readAsBinaryString(Blob|File)
.
0 255.
readAsDataURL(Blob|File)
, URL .
,
src, .
readAsText(Blob|File, encodings'UTF-8')
.
UTF-8.
readAsArrayBuffer(Blob|File)
ArrayBuffer.
.
FileReader ,
. ,
, :
t
onerror
onprogress
onload
FileReader ,
. onload
result,
:
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
};
reader.readAsDataURL(file);
, data, ,
, ,
:
var preview = $("img#preview")
// , image
//
// -
119
if (file.type.match(/image.*/) &&
file.size < 50000000) {
var reader = new FileReader();
reader.onload = function(e) {
var data
= e.target.result;
preview.attr("src", data);
};
reader.readAsDataURL(file);
,
. API, HTML5,
slice(). ,
( ).
Blob, ,
File, FileReader. ,
, :
var bufferSize = 1024;
var pos = 0;
var onload = function(e){
console.log("npo4HTaHo: ", e.target.result);
};
var onerror = function(e){
console.log("0mn6Ka!", e);
};
while (pos < file.size) {
var blob = file.slice(pos, bufferSize);
var reader = new FileReader();
reader.onload = onload;
reader.onerror = onerror;
reader.readAsText(blob);
pos += bufferSize;
}
, FileReader
, .
assets/ch07/slices.html. ,
, .
, slices.html , ,
onerror.
120
7.
. ,
(Browse) (Attachment)
,
. ,
. ,
, Firefox,
.
,
.
, ,
, .
, .
assets/ch07 jquery.browse.js,
j Query,
.
jQuery browseElement ().
, change,
- .
var input = $("#attach"),browseElement();
input.change(function(){
var files = $(this).attr("files");
});
!
XMLHttpRequest
Level 2. .
,
, ,
, - , . .
. , XHR 2 .
,
, .
:
Safari >= 5.0
Firefox >= 4.0
Chrome >= 7.0
121
IE:
Opera:
XMLHttpRequest API send() , ,
FormData. FormData
.
FormData form
:
var formData = new FormData($("form")[0]);
//
formData.append("stringKey", "stringData");
// File
formData.append("fileKey", file);
FormData
POST , XMLHttpRequest. Ajax-
jQuery, processData
false, jQuery
. Content- ,
multipart/form-data,
:
jQuery.ajax({
data: formData,
processData: false,
url: "http://example.com",
type: "POST"
})
FormData
send () XHR-:
var req = new XMLHttpRequestQ;
req.open("POST", "http://example.com", true);
req.send(file);
});
122
7.
,
multipart/formdata. ,
, .
.
, X-File-Name.
:
$.ajax({
url: "http://example.com",
type: "POST",
success: function(){ /* ... */ },
processData: false,
contentType: "multipart/form-data",
beforeSend: function(xhr, settings){
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("X-File-Name", file.fileName);
xhr.setRequestHeader("X-File-Size", file.fileSize);
b
data: file
});
,
,
, multipart URL .
.
FormData ,
multipart/formdata. assets/ch07 jquery.upload.js,
jQuery,
$.upload(url, file).
Ajax
XHR Level 2
progress, , .
,
, ,
.
XHR-:
var req = new XMLHttpRequestQ;
req.addEventListener("progress", updateProgress, false);
req.addEventListener("load", transferComplete, false);
req.open();
123
progress ,
upload XHR-:
var req = new XMLHttpRequestQ;
req.upload.addEventListener("progress", updateProgress, false);
req.upload.addEventListener("load", transferComplete, false);
req.open();
load , ,
. jQuery, XHR beforeSend.
, , :
$.ajax({
url: "http://example.com",
type: "POST",
success: function(){ /* ... */ L
processData: false,
dataType: "multipart/form-data",
beforeSend: function(xhr, settings){
var upload = xhr.upload;
if (settings.progress)
upload.addEventListener("progress", settings.progress, false);
if (settings.load)
upload.addEventListener("load", settings.load, false);
var fd = new FormData;
for (var key in settings.data)
fd.append(key, settings.data[key]);
settings.data = fd;
data: file
});
progress (. .
) ( ).
:
var progress = function(event){
var percentage = Math.round((event.position / event.total) * 100);
//
}
,
,
estimated time of completion (ETA):
var startStamp
var progress =
var lapsed =
var eta
=
};
= new DateQ;
function(e){
startStamp - e.timestamp;
lapsed * e.total / e.position - lapsed;
124
7.
( ) .
, ,
. ,
,
.
jQuery
,
.
: jquery.js , jquery.ui.js , jquery.drop.js
API jquery. upload .js
Ajax. jQuery.ready(),
DOM-:
//=
//=
//=
//=
require
require
require
require
<jquery>
<jquery.ui>
<jquery.drop>
<jquery.upload>
jQuery.ready(function($){
});
, #drop,
.
drop, ,
uploadFile():
var view = $("#drop");
view.dropAreaQ;
view.bind("drop", function(e){
e .stopPropagation();
e .preventDefault();
var files = e.originalEvent.dataTransfer.files;
for ( var i = 0; i < files.length; i++)
uploadFile(files[i]);
return false;
});
jQuery
125
uploadFileQ, .
Ajax-
$ .upload() jquery.upload.js. progress
jQuery UI.
, :
var uploadFile = function(file){
var element = $("<div />");
element.text(file.fileName);
var bar = $("<div />");
element.append(bar);
$("#progress").append(element);
var onProgress = function(e){
var per = Math.round((e.position / e.total) * 100);
bar.progressbar({value: per});
};
var onSuccess = function(){
element.text(" ");
element.delay(1000).fade();
};
$.upload("/uploads", file, {upload: {progress: onProgress},
success: onSuccess});
};
! assets/ch07/
dragdropupload.html.
- ?
, , -
. ,
. ,
,
. , Google, Facebook Twitter,
. ,
.
- - : -, ,
, .
Ajax, -
.
,
,
.
. :
.
.
,
,
TCP-,
HTTP-. , .
Comet. (iframes),
, xhr-multipart, htmlfile
(long polling).
WebSockets
127
XMLHttpRequest- (XHR) ,
, . , ,
, , .
, .
Comet ,
. ,
. ,
. Comet ,
.
, Adobe Flash Java.
TCP- ,
.
,
,
, .
HTML5.
, , Internet
Explorer, . Comet
.
WebSockets
WebSockets HTML5,
TCP-. ,
,
, .
,
.
, . ,
WebSockets,
, Comet (polling).
WebSockets
,
,
HTTP- , , .
Comet HTTP,
HTTP-.
128
8. -
, TCP-,
.
WebSockets,
, . ,
. ,
,
( ). ,
,
, -.
WebSockets HTML5
Google (Ian Hickson):
2 ...
150 50 .
, WebSockets
Google .
, WebSocket :
Chrome > = 4
Safari >= 5
iOS >= 4.2
Firefox >= 4*
Opera >= 11*
API WebSocket .
, WebSocket,
, ws://example.com:
var socket = new WebSocket("ws://example.com");
:
//
socket.onopen = function(){ /* ... */ }
WebSockets
129
//
socket.onmessage = function(data){ /* ... */ }
//
socket.onclose = function(){ / * . . . * / }
, onmessage. ,
, send()
. , ,
:
socket.onmessage = function(msg){
console.log("New data - ", msg);
};
socket.onopen = function(){
socket.send(", - ").
};
.
JSON,
, ,
:
var = {
test: function(argl, arg2) { /* ... */ }
};
socket.onmessage = function(data){
// DSON
var msg = DSON.parse(data);
// RPC
rpc[msg.method].apply(rpc, msg.args);
};
(RPC). JSON,
, :
{"method": "test", "args": [1, 2]}
, .
,
JavaScript.
close():
var socket = new WebSocket("ws://localhost:8000/server");
130
8. -
, , , WebSocket
WebSocket, ws://, http://. WebSockets
TLS, wss://. WebSockets
80 443
. , URL ,
. , ,
.
: ,
, , IE
. , , , , ,
. Web-socket-js, WebSocket,
Adobe Flash.
WebSocket- Flash,
, .
API WebSocket, , WebSockets ,
, .
API,
. WebSocket
: (drafts) 75 76. ,
, .
WebSockets . WebSocket,
WebSocket- .
( ). WebSocket , . . , ,
, .
, WebSockets
-,
HTTP-.
. -
WebSockets, . -
,
.
( 76)
- . WebSockets
, .
WebSocket- (wss). -
,
.
WebSocket-cepeepaMH , HTTP-.
WebSockets
131
HTTP-
WebSocket.
, WebSocket,
.
, ,
, , Comet
.
, ? ,
, Ruby, Python Java. ,
, , 76
, .
Node.js:
node-Websocket-server;
Socket.IO.
Ruby:
EventMachine;
Cramp;
Sunshowers.
Python:
Twisted;
Apache module.
PHP:
php-Websocket.
Java:
Jetty.
Google Go:
Native.
Node.js Socket.IO
Node.js , ,
. Node.js JavaScript, Google- V8 JS. ,
,
, WebSocket-cepeepa.
Socket.IO Node.js WebSockets. , ,
. :
Socket.IO
,
.
132
8. -
WebSockets , Socket.IO
,
.
, :
WebSocket;
Adobe Flash Socket;
ActiveX HTMLFile (IE);
XHR multipart-;
XHR ;
JSONP- ( ).
Socket.IO .
,
Socket.IO ,
.
:
Safari >= 4
Chrome >= 5
IE > - 6
iOS
Firefox >= 3
Opera > - 10.61
Socket.IO Node.js,
, Ruby (Rack), Python (Tornado),
Java Google Go.
API .
API API, WebSocket:
var socket = new io.Socket();
socket.on("connect", function(){
socket.send('!');
});
socket.on("message", function(data){
alert(data);
});
socket.on("disconnect", function(){});
Socket.IO .
readme , Socket.IO ,
, .
133
, Socket.,
Juggernaut, .
Juggernaut : ,
, . .
PubSub (-).
, ,
TLS .
,
Pusher.
, :
-. ,
JavaScript- .
, HTTP-
REST API.
, JavaScript-?
, .
, ,
PubSub. , ,
.
.
:
, ,
, .
,
:
?
?
,
.
,
.
, .
.
.
1. .
2. Ajax-, Chat.
134
8. -
3. Chat
,
.
4. , ,
. . , .
5. , ( chat),
.
.
Rails, Holla.
Message, 3uggernaut0bserver
.
:
?
PubSub: ,
.
, ,
ID ,
,
.
, :
/observer/0765F0ED-96E6-476D-B82D-8EBDA33F4EC4
, .
.
, PubSub
, WebSockets Comet. ,
, Juggernaut Pusher. PubSub
WebSockets, API
, .
,
MVC-. .
:
{
"klass":
"type":
"id":
"record":
"Chat",
"create",
"3,
{"body": "New chat"}
}
, ,
. ,
Chat. UI,
135
.
,
Chat. ,
,
.
. ,
,
, .
. , ,
.
,
(user
experience, UX) ,
. :
Amazon
100 1%
(: (Greg Linden), Amazon).
Google
500 20%
(: (Marrissa Mayer), Google).
Yahoo!
400 5-9%
,
, (: (Nicole
Sullivan), Yahool).
, ,
.
, , ,
.
JavaScript ,
.
.
, Ajax- .
,
, .
136
8. -
.
, , , .
,
? ,
.
( ),
.
.
,
.
, ,
, .
, .
. ,
.
. ,
(
). (UX)
, .
, -
. ,
.
, .
.
.
JavaScript, . . ,
.
,
.
,
. , ,
JavaScript, .
JavaScript -
, JavaScript-
. , ,
JavaScript , .
, , jQuery.
10 ,
.
. , jQuery:
Safari: 3.2,4, 5
Chrome: 8,9,10,11
Internet Explorer: 6, 7, 8,9
Firefox: 2, 3, 3.5,3.6
Opera: 9.6,10,11
, ,
. ,
, ,
, !
.
, jQuery , ,
. ,
138
9.
, j Query,
. ,
,
.
,
, ,
-. ,
, , .
.
, .
- . , , ,
Statcounter.com 2011 :
Safari: 4%
Chrome: 15%
IE: 36%
Firefox: 37%
Opera: 2%
IE
Firefox Chrome. , IE6,
, .
,
.
, : ,
. . ,
, IE 5% ,
. ,
.
, ,
Firefox Chrome,
,
. ,
, ,
. , ,
:
IE 8,9
Firefox 3.6
Safari 5
Chrome 11
139
,
, ,
,
.
.
,
.
,
.
,
,
.
,
.
,
, .
,
, , , ,
- -
.
JavaScript, .
,
.
, ,
. ,
.
, , -
.
, assert(),
:
var asset = function(value, msg) {
if ( lvalue )
throw(msg || (value + " "));
};
140
9.
.
(true), :
//
assert( false );
assert( "" );
assert( 0 );
JavaScript
undefined, 0 null false. , a ssert
n u ll-:
// null,
assert( User.first() );
,
JavaScript,
.
.
,
, .
, assert Equal (),
:
var assertEqual = function(vall, val2, msg) {
if (vail !== val2)
throw(msg || (vail + " " + val2));
};
//
assertEqual("one", "one");
, ,
API
.
Q Unit
QUnit
, jQuery. ,
QUnit?
,
:
<!DOCTYPE html>
<html>
<head>
<title>QUnit Test Suite</title>
141
. ,
, -
(ORM), 3:
test("load()", function(){
var Asset = Model.setup();
var a = Asset.init();
a.load({
local: true,
name: "test.pdf"
});
ok(a.local, "Load sets properties");
equals(a.name, "test.pdf", "load() sets properties (2)");
var b = Asset.init({
name: "test2.pdf"
});
});
testQ
(
). :
() , true,
equals() .
, ,
, , .
, ,
. 9.1.
! ,
, , .
142
9.
,
,
.
. 9.1. QUnit
module(),
. ,
setup module(),
, , .
Asset,
setup:
module("Model test", {
setup: function(){
this.Asset = Model.setup();
}
test ("loadQ", function(){
var a = this.Asset.init();
a.load({
local: true,
name: "test.pdf"
});
ok(a.local, "Load sets properties");
equals(a.name, "test.pdf", "loadQ sets properties (2)");
var b = this.Asset.init({
name: "test2.pdf"
});
equals(b.name, "test2.pdf", "Calls loadQ on instantiation");
});
,
. module()
teardown (), ,
.
:
test("attributes()", function(){
143
toadQ (0. 3, $
. 9.2. QUnit
144
9.
Jasm ine
(
) Jasmine. Jasmine
, .
, .
Jasmine , ,
DOM. , JavaScript,
Node.js.
QUnit, HTML, ,
:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN
"http://www.w3 .org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Test Runner</title>
<link rel=,,stylesheet" type="text/css" href="lib/jasmine.css,,>
<script type="text/javascript" src="lib/jasmine.js"x/script>
<script type="text/javascript" src="lib/jasmine-html. js"x/script>
<!-- ... -->
<1-- ... -->
</head>
<body>
<script type="text/javascript">
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().execute();
</script>
</body>
</html>
, Jasmine. -
ORM 3:
describe("Model", function(){
var Asset;
beforeEach(function(){
Asset = Model.setup();
Asset.attributes = ["name"];
});
it("can create records", function(){
var asset = Asset.create({name: "test.pdf"});
expect(Asset.first()).toEqual(asset);
});
145
asset.save();
expect(Asset.first().name).toEqual("wem.pdf");
});
it("can destroy records", function(){
var asset = Asset.create({name: "test.pdf"});
expect(Asset.first()).toEqual(asset);
asset.destroy();
expect (Asset.first ().).toBeFalsy ();
});
});
describe(),
.
, ,
beforeEach(). Jasmine afterEach(),
. beforetach() Asset,
, .
it(),
, .
expect(),
, , :
expect(x).toEqual(y)
.
expect(x).toBe(y)
, ,
.
expect(x).toMatch(pattern)
, .
expect(x) .toBeNullQ
, null.
expect().toBeTruthy()
, true.
expect(x).toBeFalsy()
, false.
expect(x).toContain(y)
, .
expect(fn).toThrow(e)
, f
.
146
9.
Jasmine
. . 9.3
Jasmine Test Runner,
.
ia s m in e
S .s e e c s . 0 fa ilu r e s in .Q .Q 2 1 s
Show
passed
skipped
1 M
run
M a tte l
can cre e
re co rd s
run
c a a -M B d A te r e c o r d s
run
c a n .d e s ir o v .r e c Q r d s
run
. 9.3. , Jasmine
-
,
.
,
.
.
,
. JavaScript
.
,
,
JavaScript-,
.
W atir ( ) Ruby
, Chrome, Firefox, Safari Internet Explorer (
). W atir
Ruby- , ,
.
, :
# FireWatir Firefox
require "firewatir"
browser = Watir::Browser.new
browser.goto("http://bit.ly/watir-example")
browser.text_field(:name => "entry.0.single").set "Watir"
browser.button(:name => "logon").click
147
-
,
Internet Explorer,
Windows. Safari
, Mac OS X.
Selenium. (domain
scripting language, DSL)
, #, Java, Groovy, Perl, PHP, Python Ruby. Selenium
.
,
, . Selenium
, Selenium IDE,
Firefox, ,
.
. 9.4 Selenium IDE
, .
, .
,
.
Selenium IDE 1.0.10 *
Ease
URL
____
file.///Users/Alex/book/as sets/ch09/selenium/index.html
>1
H I
Test Case
Table
Source
Untitled 2
fCommand
Target
open
cHckAndWait
Runs:
Value
ffle7//Users/A!ex/book/as.
nk Login.htm
type
test@example.com
type
password
test
dickAndWait
//mput(@value'Contnue .
Command
open
Target
Value
Failures
opcmurl)
Arguments:
url the U R L to open; may be relative or absolute
Opens an U R L in the test frame. This accepts both relative and absolute URLs. The open" command waits
for the page to load before proceeding, ie the AndW t" suffix is implicit. Note: The U R L must be on the
. 9.4. Selenium
148
9.
, . 9.5,
(Test Case) .
F irefox
M31BI
Edit
Options
Window
Help
3SD
HTML
Ruby (Test::Unit)
RSpec
JUnit 3 (Remote Control)
Groovy (JUnit)
Perl
FHP
Python 2 (Remote Control)
C# (Remote Control)
Close
-----
W J
ckkAndWait
link Login.html
. 9.5. Selenium
,
Test: :Unit Ruby. , Selenium IDE
,
, :
class SeleniumTest < Test::Unit::TestCase
def setup
^selenium = Selenium:-.Client::Driver.new \
:host => "localhost",
:port => 4444,
:browser => "chrome",
:url => "http://example.com/index.html",
:timeout_in_second => 60
@selenium.start_new_browser_session
end
def test_selenium
gselenium.open "http://example.com/index.html"
gselenium.click "link=Login.html"
@selenium.wait_for_page_to_load "30000"
^selenium.type "email", "test@example.com"
@selenium.type "password", "test"
gselenium.click "//input[@value='Continue
@selenium.wait_for_page_to_load "30000"
end
149
@selenium,
:
def test_selenium
# ...
assert @selenium.is_text_present("elvis")
end
Selenium - selemiumhq.
org, screencast.
JavaScript-, Node.js Rhino,
.
,
.
.
, , .
, , JavaScript
. ,
, j Query, ,
DOM .
(
).
Envjs Qohn Resig),
JavaScript- j Query.
DOM API Rhino, JavaScript Java,
Mozilla. env.js Rhino
.
Zom bie
Zombie.js ,
Node.js.
:
,
.
, JavaScript ,
,
JavaScript. Google JavaScript- V8
.
150
9.
JavaScript
, Zombie V8 ,
,
. , Chrome
.
Browser. DOM,
,
. ,
, Vows.js, ,
,
.
Zombie.js Browser,
-: (cookie-,
, -) (
).
, ( ,
, . .) (
XPath CSS ).
, ,
:
// email, password ,
browser.
fill("email, "zombiegunderworld.dead").
fill("password", "eat-the-living").
pressButton("Sign Me Up!", function(err, browser) {
// , .
assert.equal<browser.text("title"), "Welcome to Brains Depot");
;
. ,
Zombie.js, Browser
. err.
-, Zombie.js :
,
.
, loaded error, .
, Zombie ,
. ,
null ,
Browser. ,
Error.
151
, -
.
Node.js ,
, Vows.js.
,
, error null.
null, .
, , , Zombie.js Vows.js.
- brains (,
):
var zombie = require("zombie");
vows.describe("Zombie lunch").addBatch({
"visiting home page": {
topic: functionQ {
var browser = new zombie.Browser;
browser.cookies("localhost").update("session_id=5678");
browser.visit("http://localhost:3003/", this.callback);
}
}
});
Zombie.js . ,
(cookie-, , - . .)
(
).
DOM ,
.
, Resources
Web Inspector WebKit. Zombie Node.js,
HTTP- -, , ,
Ruby- Python-.
Ichabod
Ichabod
,
.
Ichabod , DOM
WebKit ,
Safari Chrome. Ichabod OS X,
MacRuby OS X WebView API.
152
9.
. MacRuby,
, rvm. gem- Ichabod:
$ gem install ichabod
-,
:
$ ichabod --jasmine ./tests/index.html
Finished in 0.393 seconds
1 test, 5 assertions, 0 failures
Ichabod WebKit,
, .
.
TestSwarm:
TestSwarm
JavaScript
.
,
JavaScript.
TestSwarm .
TestSwarm
.
TestSwarm.
.
(swarm) . ,
, . 9.6,
, , ,
, .
&
S
Sr
&
153
. 9.6. TestSwarm
, Sauce Labs,
.
Selenium,
,
, .
,
- . , ,
.
,
.
JavaScript-
a le r t () .
, ,
-.
,
.
154
9.
_; .
General Appearance
Advanced
Bookmarks
Tabs
RSS
AutoFill
. 9.7. Safari
Chrome ,
.
.
-, . 9.8, ,
HTML-, ,
JavaScript . ,
JavaScript-.
Elements
Resources
Network
* Scripts
Tmnetine
Profiles
&
Audits
^Consote
! Computed Style
[ t Styles
<ht*l>
<head>_</head>
*<body>
<div id="container*>
header
<hl~/hl>
/header
Show
nherited
elem ent.style {
<div id post*'.</div>
<div id*4coeents*,..</div>
</div>
</body>
</htl>
li .
Matched CSS Rute>
screen.css:59
t ontent {
: isargin: 0 2 209px;
-width: 90;
i>
[div {
user agent stylesheet'
d isplay: block;
j
t
A
r
>3
Q,
html
body
divcontamer 2 2 1
91
155
,
-.
Elements
HTML-,
Resources
Network
HTTP-
Scripts
JavaScript-
Timeline
Audits
Console
JavaScript
Firebug
Firefox JavaScript-HHcneKTopa,
: Firebug (. . 9.9.)
*> J* }*
ii Edtl hl.ttle < dv*post
<!>
HTML
CSS
< divcontni
Script
DOM
< divfconumer
.......... .....
1
body
Styles
Computed
U your
DOM
^content {
screen css (line 59)
margin:
200px 200px,
mox width: 900px;
I* <htral>
<heod>
<body>
}
Inherited from body
?
^ <div id ^ c o o t o in c r V
<hecder>
body {
screen css (line 1)
font-fo m ily: Georg a ,s e r if ;
fonfc-sixe: 18px;
<div \d"post">
>
^ <dtv id*-"cowncnts*>
</div>
</div>
</body>
</ht*l>
___ ___
Firebug
-, ,
.
Console
JavaScript
156
9.
HTML
,
CSS
CSS
Script
JavaScript-
DOM
Net
HTTP-
Firebug Firefox- , Firebug Lite.
, Firebug,
,
. Firebug Lite Internet Explorer (,
, IE). Firebug Lite
, - s c rip t-:
<script type="text/javascript" src="https://getfirebug.com/firebug-lite.js">
</script>
,
- Firebug Lite.
JavaScript
, .
,
, console.log().
,
, :
console.log("test");
console.log(l, 2, {3: "three"});
.
, ,
console.warn() console.error(-):
console.(" ");
console.error("- !");
try {
// -
} catch(e) {
console.error(" !", );
157
, :
var = {trace: true};
App.log = function(){
if (!this.trace) return;
if (typeof console == "undefined") return;
var slice = Array.prototype.slice;
var args = slice.call(arguments, 0);
args.unshift("(App)");
console.log.apply(console, args);
};
App.log() "App" ,
console.log().
,
console . ,
, Internet Explorer Firefox Firebug, console
,
.
- App. lo g ().
console.traceQ ,
.
, ,
, ,
:
//
console. traceQ;
, , JIT -
,
.
. , $0
$4 -
Firebug. , ,
:
// $0
$0.style.color = "green";
// , jQuery
jQuery($0).css({background: "black"});
$() ID. ,
document.getElementBy!d(). ,
158
9.
jQuery, Prototype , $,
:
$("user").addEventListener("click", function(){ /* ... */});
$$() ,
CSS-. document.querySelectorAllQ.
, Prototype MooTools,
:
// class, .users
var users = $$(".users");
users.forEach(function(){ /* ... */ });
$x() ,
XPath:
//
var checkboxes = $x("/html/body//form");
clearQ :
clearQ;
dir() :
dir({one: 1});
inspect () ,
,
:
inspect($("user"));
keys () :
// ["two"]
keys({two: 2>);
values() ,
, . . keys():
// [2]
values({two: 2});
JavaScript JavaScript-.
,
, ,
, .
159
,
debugger - ,
:
var test = function(){
// ...
debugger
};
Scripts,
,
. . 9.10.
, , ,
, debugger.
JavaScript ,
, .
. 9.11.
<
73
Resources
Network 1
Jqu eryjs
i n i t : f u n c tio n ( s e le c t o r ,
v a r m a tc h , e le w , r e t ,
//
14
Profiles
Audits
'_j| Console
Not Paused
B r e a k p o in ts
C j q u f iy j s 5
C o p y r ig h t
86
87
80
09
90
) {
Scripts
Mj (1
f f f*
fat
W a tc h E x p r e s s io n s
^ C a ll S ta ck
v S c o p e V a r ia b le s
o r $ ( u n d e fm e d )
H a n d le $ (0 0 H E le e n t
( s e le c t o r . n o d e T y p e
th is .c o n te x t
t h i s 101
t h is .le n g t h
1;
re tu rn t h i s ;
if
-?
*(""). $ ( n u l l ) ,
) {
>
//
Tim eline
) {
c o n te x t
doc;
H a n d le
s e le c t o r
re tu rn t h i s :
if
80
81
?
83
84
Script*
J
75
76
77
78
Elements
20 10 ,
jqueryJs 85
th is .c o n te x t
s e le c t o r ;
Joh n R e s ig
t h i s [01
s e l.
D O M B r e a k p o in ts
>
/ / T he body e le m e n t o n ly e x i s t s
Q1
if 1 u lartn r
.
"hnHis" XX
'
-* * w
*
> >2
X H R B r e a k p o in ts
E v e n t lis t e n e r
v Workers
+
4
once,
o p t im i z e
t /
f in d in g
it
B r e a k p o in ts
_ Debuq
. 9.10. - Safari
<
sm
*, Elements
Resources
chO O htm l
*/coCe></pre>
( j ) Network
Sc'pxs
Profiles
y f Timebne
^ 4 Audits
Q Search Scripts
^ ^ C o n s o le
|
M
379
80 s c r ip t ty p e nt e x t / i a v a s c r i p t M c h a r s e t Mu t f - 8 >
381
war v a lu e * 'one*'
fu n c tio n
Mo n e H
____
>
Pained
S c o p e V a r ia b le s
Local
t e s t lH
l
bugger
38
>
307 < / s c r ip t >
C a ll S ta ck
383
384
W a tch E x p r e s s io n s
-------~----- ? 5 ~ v ~ rr
~ * rr~
G lo b a l
------
...
DOHWindow
B r e a k p o in ts
D O M B r e a k p o in ts
384 i
3*0 < poebugging
391 scre e n sh o ts< / p >
392
4
v
X H R B r e a k p o in ts
E v e n t L is te n e r B r e a k p o in ts
W o rk e rs
G D ebug
&
>3
01
. 9.11. - Safari
160
9.
Scripts
(call stack),
.
, .
,
.
,
,
.
, ,
, .
,
. ,
.
JavaScript console.log(),
, .
. 9.12, , , , ,
.
TQSearchRv^ovfc*s
^ Benvtms |
2
lC3
D o cu m e n ts
>Z
I-
S ty le sh e e ts
Im ages
S c rip ts
XHR
F o n ts
O th e r
Sort b y R e s p o n s e T im e
. 9.12. -
,
. , ,
. jQuery
, ,
, .
161
async defer
(. 10), , JavaScript
, . ,
.
.
.
DOMContentLoaded,
, DOM-. ,
load,
.
, , ,
(. 9.13).
Elements
I D o c u m e n ts
S ty le sh e e ts
lm * g e s
S c r ip ts
C 2 5 3 3 I
C o n te n t
XHR
F o n ts
O th e r
R e q u e st URL: h t t p : / / l o c a l h o s t : 9 2 9 2 / s t y l e s h e e t s / h i g h l i g h t . c s s
R e q u e st M e th o d : G ET
S ta tu s C o d e : 20 0 OK
v R e q u e st H e a d e rs
A cce p t: t e x t / c s s , / * ; q
0 .1
C a c h e - C o n t r o l: m a x -a g e * 0
R e fe r e r h t t p : / / l o c a I h o s t : 9 2 9 2 / p o s t s / c h 0 9 . h t I
U s e r A g e n t. H o z i l l a / 5 . 0 ( M a c in t o s h ; U ; I n t e l OS X 1 0 _ 6 _ 6 ;
KHTML, I x k e G e c k o ) V e r s i o n / 5 . 0 . 3 S a f a r i / 5 3 3 . 1 9 . 4
e n -u s )
A p p le W e b K a t / 5 3 3 .1 9 .4
R e s p o n s e H e a d e rs
C a c h e - C o m r o l: n a x - a g e 3 1 5 3 6 0 0 0 ,
p u b lic
C o n n e ctio n : K e e p - A l i v e
C o n te n t- L e n g th : 1 616
C o n te n t- T y p e : t e x t / c s s
D ate: T h u ,
10 H a r 20 1 1 1 9 : 0 9 : 3 7 GHT
E x p ire s: S a t ,
10 M a r 2012 0 7 : 4 2 : 4 2
S erver: W E B r ic k / 1 . 3 . 1
>a f
I?
S o n b y R e s p o n s e T im e
GHT
( R u b y / 1 .9 .2 / 2 0 1 1 - 0 2 - 1 0 )
02
. 9.13. ,
JavaScript-
, .
,
, -, Firebug.
,
co n so le.p ro file() console.
profileEnd():
console. p ro file ( );
II . . .
console. profileEnd();
162
9.
profileEnd(), ,
( , ),
(. 9.14).
Elements
Resources
Network
Scripts
( J
Tim eline I
ProTOes
Audits
fQ,'Search''proftSei
Console
Function
(program)
totiectedScript_popoUttPfop*rryN4m
injectedScript evaluateOn
IfOectedScript getProperties
(anonymous function)
InjectedScript evaluate
lr\jectedScnpt getCompiettons
injectedScript .eviluateAndWrap
. 9.14. -
record ()
,
.
, ,
.
, . 9.15.
, , , .
,
,
.
Dements
^ R eso u rces
(^ N e tw o rk
jp
Scripts
HEA P SNAPSHO TS
<S>
Profiles
4 ^ A u d ts
Console
18
IS
1127
>2
1 Count
3327
13300
2677
1547
295
352
1S17
Code
(Jf Timelirw
i Constructor
I(code)
IP String
I(closure)
iPOtyect
ay
RegExp
(global property)
DOMWinbow
Error
HTHLElemem
CPU PROFILES
C o m p a red to S napsh ot I J
Count
Objects
19874
Total
23^01
Code
1G3M!
Q, S*aich Proves
* Count ! Size jr
oj
" 08 IIT
08 1I
410.46KB
0
404.12KB
OB
16862KB
08
0
0
08
14.53KB
12.38KB
08
0
11.85KB
0
08
6.23KB
0
08
08 S'
504B
0
4208
08
*
Si/e
Objects
135MB
Tout
238M8
. 9.15. -
,
. API,
, console.
163
- ,
. Facebook,
.
, .
JavaScript HTML , ,
, , .
- .
, ,
JavaScript-
. , .
-.
: HTTP-.
HTTP- ,
TCP.
.
, ,
.
,
-.
CSS
HTTP-,
.
.
-.
CSS-
.
165
, -
.
,
, .
. , Chrome,
, .
166
10.
,
Expires, .
, ,
, ,
.
Expires: Thu, 20 March 2015 00:00:00 GMT
. ,
20 2015 . - Apache,
, ExpiresDefault:
ExpiresDefault "access plus 5 years"
, ?
( mtime)
URL-, . ,
Rails . , , URL
, .
<link rel="stylesheet" href="master.css1296085785" type="text/css">
- . ,
, , , .
max-age
,
. Expires,
,
.
public
. ,
SSL -,
.
no-store
,
.
must-revalidate
-, ,
.
HTTP -
167
. , , .
LastModif ied.
If-Modified-Since, .
, 304
( ). - ,
, :
#
GET /example.gif /1.1
Host:www.example.com
If-Modified-Since:Thu, 29 Apr 2010 12:09:05 GMT
#
HTTP/1.1 200 OK
Date: Thu, 20 March 2009 00:00:00 GMT
Server: Apache/1.3.3 (Unix)
Cache-Control: max-age=3600, must-revalidate
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Last-Modified: Mon, 17 March 2009 00:00:00 GMT
Content-Length: 1040
Content-Type: text/html
JavaScript ,
. ,
168
10.
.
JavaScript.
, .
, , .
JavaScript.
HTML.
. ,
, . ,
,
.
,
. ,
, , ,
.
, ,
, JavaScript,
. YUI Compressor,
. Yahoo!
(Julien Lecomte) JavaScript, JSMin,
. , :
function per(value, total) {
return( (value / total) * 100 );
}
YUI Compressor
, :
function per(b,a){return((/)*100)};
169
.
, Sprockets Less, .
YUI Compressor,
gem- (Sam Stephenson) Ruby-YUI-compressor
J ammit.
Gzip
Gzip ,
-. GNU-,
H T T P /1.1. - ,
Accept-Encoding:
Accept-Encoding: gzip, deflate
-
,
Content-Encoding:
Content-Encoding: gzip
. ,
,
. Gzip 70%,
.
,
gzip. gzip
, HTML, JSON, JavaScript .
, PDF-,
gzip, .
gzip , Apache 2.x
, m oddeflate. -
.
CDN
, CDN (content delivery network),
, .
- .
CDN-
, ,
( , ).
Yahoo! , CDN-
20% .
, ,
, CDN-,
170
10.
,
. YSlow Firebug,
, , Firefox.
, .
-.
, , , . gzip
CDN-. ,
,
.
Google Chrome Safari ,
. . 10.1, Chrome
171
^ 'E le m e n ts
Netwok
httpc//iocalhsuS2*>2/p.
Profiles
^ A u d it s
9 Console
'Q
>2
C ^t Timehnc
s e a rc h A ucflw
Enable
RtSUITS
j p Scripts
Audits
(g j
jW _ Resources
Page
Perform ance
lil
A
t f.
. 10.1. - -
Yahoo I, Google -. ,
,
. Google
Pagerank ,
. ,
.
Google Yahoo!.
Spine
Spine JavaScript, ,
, MVC, .
, 500
JavaScript, 2 .
- . Spine
JavaScript-,
.
Spine , MVC, ,
.
, , , , Holla,
, Spine.
, ,
Cappuccino SproutCore, Spine , .
. Spine ,
,
.
Spine Spine.
Class, Spine.Events, ORM Spine.Model
Spine.Controller. , ,
DOM-, ,
, . , Spine
j Query Zepto.js, .
Spine . ,
,
. ,
.
Spine .
Spine :
<script src="spine.js" type="text/javascript" charset="utf-8"x/script>
173
Spine,
, . ,
j Query, Zepto Prototype, .
Spine . Spine
Object.create() ,
3,
.
Spine.Class.create([instanceProperties, classProperties]),
(instanceProperties) (classProperties):
var User = Spine.Class.create({
name: "Caroline"
>);
User
name. createQ ,
Spine.Class, . . .
, createQ
:
var Friend = User.createQ;
Friend User,
:
assertEqual( Friend.prototype.name, "Caroline" );
-
,
new. Spine init():
var user = User.initQ;
assertEqual( user.name,
"Caroline" );
user.name "Irish";
assertEqual( user.name, "Irish" );
, initQ,
initQ:
var User - Spine.Class.create({
init: function(name){
this.name = name;
&
174
11. Spine
>
;
var user User.init(Martina");
assertEqual( user.name, "Martina" );
,
include() extend(), :
User.include({
//
});
User.extend({
//
});
includeQ extendQ ,
,
:
var ORM * {
extended: function(){
//
//
this ==* User
};
User.extend( ORM );
. extended
User.extend() User. ,
included, .
, ,
,
:
var Friend = User.createQ;
User.include({
email: "infogeribium.org
});
assertEqual( Friend.initQ.email, "infogeribium.org" );
.
, ,
. ,
175
,
. created(), Spine
:
// , records
var User = Spine.Class.create({
//
init: function(){
this.attributes = {};
}
b {
//
created: function(){
this.records = [];
}
;
JavaScript ,
Spine.Class
. :
var Controller Spine.Class.create({
init: function(){
//
$("#destroy").click(this.destroy);
L
destroy: function(){
// destroy ,
// 'this'
// :
assertEqual( this, Controller.fn );
}
}>;
destroy()
#destroy, Controller.
,
, , .
Spine ():
var Controller Spine.Class.create({
init: function(){
$("#destroy").click(this.proxy(this.destroy));
b
destroy: function(){ }
176
11. Spine
,
, ,
. Spine 11():
var Controller Spine.Class.create({
init: function(){
this.proxyAll("destroy", "render")
$("#destroy").click(this.destroy);
b
//
destroy: function(){ },
render: function(){ }
});
proxyAllQ ,
, .
destroy ()
render () .
Spine,
. Spine
Spine.Events, ,
. , ,
Spine:
var User Spine.Class.createQ;
User.extend(Spine.Events);
Spine. Events :
bind(eventName, callback)
trigger(eventName, [*data])
unbind(eventName, [callback])
API , jQuery,
. , , User
:
User.bind("create", function(){ /* ... */ });
User.trigger("create");
:
User.bind("create update", function(){ /* ... */ });
177
trigger() ,
, :
User.bind("countChange", function(count){
// 'count' trigger
assertEqual(count, 5);
;
User.trigger("countChange", 5);
Spine ,
.
.
Spine, ,
, ,
MVC-.
, a Spine ,
- (ORM).
createQ,
, Spine.Model.setup(name,
attrs), :
// Task.
var Task Spine.Model.setup("Task", ["name", "done"]);
include() extend():
Task.extend({
// ,
done: function(){ / * . . . * / }
});
Task.include({
//
name: "...
done: false,
toggle: function(){
this.done = !this.done;
>
;
178
11. Spine
,
:
var task = Task.init({name: " "});
assertEqual( task.name, " " );
,
. , a ttrib u te s Q
, :
var task = Task.initQ;
task.name = " ";
assertEqual( task.attributesQ, {name: " "});
saveQ. , ID , ,
:
var task = Task.init({name: " "});
task.saveQ;
task.id //=> "44E1DB33-2455-4728-AEA2-ECBD724B5E7B"
findQ ,
ID :
var task = Task.find("44ElDB33-2455-4728-AEA2-ECBD724B5E7B");
assertEqual( task.name, " ");
ID, .
, ,
e x is ts ():
var taskExists = Task.exists("44ElDB33-2455-4728-AEA2-ECBD724B5E7B");
assert( taskExists );
-,
destroyQ:
var task = Task.create({name: " "});
assert( task.existsQ );
task. destroyQ;
assertEqual( task.existsQ, false );
ID .
. Spine 11(),
selec tQ eachQ:
// (tasks)
Task.allQ; //=> []
179
// (done), false
var pending * Task.select(function(task){ return Itask.done });
//
Task.each(function(task){ /* ... */ });
, Spine
:
//
Task.findByAttribut(, );
//*>
//
Task.findAllByAttribut(, ); //=> []
,
:
Task.bind("save", function(record){
console.log(record.name, "!");
});
,
. ,
,
:
Task.first().bind("save", function(){
console.log(this.name, "!")
});
tr ig g e r () , ,
, .
save
( , )
update
create
destroy
change
, . . (, )
180
11. Spine
refresh
error
,
.
:
validate(), . validate()
. validate() - ,
.
, :
Task.include({
validate: function(){
if ( !this.name ) return " ";
}
});
, validate()
, .
:
Task.bindC'error", furtction(record; msg){
//
alert(" : " + msg);
});
error .
.
Spine ,
: , HTML5
(Local Storage) Ajax.
.
JavaScript- spine.model.local.js
Spine.Model.Local:
//
Task.extend(Spine.Model.Local);
Task.fetch();
181
,
fetch(),
.
.
, refresh:
Task.bind("refresh", function(){
// !
renderTemplate(Task.all());
;
Ajax
, spine.model.ajax.js
Spine.Model.Ajax:
//
Task.extend(Spine.Model.Ajax);
Spine
URL
. URL- Task ^
/tasks. ,
URL:
// URL
Task.extend({
url: "/tasks"
;
// (tasks)
Task.fetch();
/
/
//id
//id
182
11. Spine
. , ,
:
POST /tasks HTTP/1.0
Host: localhost:3000
Origin: http://localhost:3000
Content-Length: 66
Content-Type: application/json
{"id": "44E1DB33-2455-4728-AEA2-ECBD724B$E7B", "name": " ")
,
DELETE, PUT. PUT
DELETE URL ID :
PUT /tasks/44ElDB33-2455-4728-AEA2-ECBD724B5E7B HTTP/1.0
Host: localhost:3000
Origin: http://localhost:3000
Content-Length: 71
Content-Type: application/json
{"id": "44E1DB33-2455-4728-AEA2-ECBD724B5E7B", "name": " ")
Spine Ajax , .
,
, . ,
, . .
.
. -,
, ,
. -,
,
,
- . -,
,
.
? Spine ,
.
, ,
( ),
.
,
ajaxError, , XMLHttpRequest, Ajax-,
:
Task.bind("ajaxError", function(record, xhr, settings, error){
//
});
183
Spine,
. DOM-
,
. Spine-
Spine.Controller createQ:
jQuery(function(){
window.Tasks = Spine.Controller.create({
//
});
});
,
,
. Spine
, jQuery().
.
Spine
, ,
, .
,
.
init ():
var tasks = Tasks.init();
DOM-,
el. .
,
div-:
var tasks = Tasks.init({el: $("#tasks")});
assertEqual( tasks.el.attr("id"), "tasks" );
:
window.Tasks = Spine.Controller.create({
init: function(){
this.el.html(" ");
}
});
var tasks = Tasks.init();
$("body").append(tasks.el);
184
11. Spine
, , init (),
. :
var tasks = Tasks.init({item: Task.first()>);
assertEqual( Task.first(), tasks.item );
,
, , this.proxy(),
.
, Spine
proxied. proxied,
,
:
// proxyAll
var Tasks = Spine.Controller.create({
proxied: ["render, "addAll"],
render: function(){ /* ... */ },
addAll: function(){ / * . . . * / }
});
, render(),
, .
.
. Spine :
elements. elements,
.
this.input , form input [type=text].
, (el):
// 'input'
var Tasks = Spine.Controller.create({
elements: {
"form input[type=text]": "input"
b
init: function(){
// this.input
console.log( this.input.val() );
}
});
, HTML-
(el) refreshElements()
.
185
Spine events
. Spine
, (el)
. events,
el.
events {" ": "__6"}. , ,
el.
, ,
, .
, el
:
var Tasks = Spine.Controller.create({
events: {
"keydown form input[type=text]": "keydown"
, ,
keydown,
keydown.
.
,
, ,
. , , ,
target.
, Spine- ,
.
Spine. Events, ,
, bind() trigger().
,
:
var Sidebar = Spine.Controller.create({
events: {
"click [data-name]": this.click
b
init: function(){
this.bind("change", this.change);
186
11. Spine
>
n ...
});
var sidebar = Sidebar.init({el: $("#sidebar")});
sidebar.bind("change", function(name){
console.log("Sidebar changed:", name);
})
Sidebar . 2
. ,
,
.
Spine .
PubSub, ,
, .
Spine.,
:
var Sidebar = Spine.Controller.create({
proxied: ["change"],
init: function(){
this.App.bind("change", this.change);
change: function(name){ / * . . . * / }
;
Spine- Spine.App
this., .
, Sidebar
change.
:
Spine..trigger("change", "messages");
, ,
.
.
,
187
.
el, , :
var Tasks = Spine.Controller.create({
init: function(){
Task.bind("refresh change", this.proxy(this.render));
b
template: function(items){
return($("#tasksTemplate").tmpl(items));
b
render: function(){
this.el.html(this.template(Task.all()));
}
});
,
. ,
,
,
.
.
,
, .
: , , ,
.
, , :
var Tasksltem = Spine.Controller.create({
// click
events: {
"click": "click"
b
//
proxied: ["render", "remove"],
//
init: function(){
this.item.bind("update", this.render);
this.item.bind("destroy", this.remove);
b
//
render: function(item){
if (item) this.item = item;
&
188
11. Spine
this.el.html(this.template(this.item));
return this;
L
// , jQuery.tmpl.js
template: function(items){
return($("#tasksTemplate").tmpl(items));
b
//
remove: function(){
this.el.removeO;
b
// ,
//
click: function(){ / * . . . * / }
});
var Tasks = Spine.Controller.create({
proxied: ["addAll", "addOne"],
init: function(){
Task.bind("refresh", this.addAll);
Task.bind("create", this.addOne);
b
addOne: function(item){
var task = Tasksltem.init({item: item});
this.el.append(task.render().el);
b
addAll: function(){
Task.each(this.addOne);
}
});
Tasks
, Tasksltem
update () destroy (),
. ,
.
, : . ,
. ,
click,
.
189
API Spine
- , .
, , ,
.
. 11.1 , ,
.
& ^ >
1
index.html
1
-______ - ____
tml
LfEX* Google
Spine Contacts
Edit contact
Search
A le x M a c C a w
Email contact
Name
A le x M a c C a w
R ich a rd M a c C a w
L !
T rish Fogarty
M artina C u d d y
Email
info@eribiunn.org
Mobile number
000-000-000-00
Work number
000 0
Address
1 Infinity Lo o p
Blank
. 11.1. Spine-
Spine-,
.
.
. 11.1 ,
, .
Sidebar Contacts.
, : Contact.
190
11. Spine
^ ,
:
<div id"sidebar">
<ul class"items">
</ul>
<footer>
<button>New contact</button>
</footer>
</div>
<div class*"vdivide"x/div>
<div id"contacts">
<div class"show">
<ul class*"options">
<li class"optEdit">Edit contact</li>
<11 class*"optEmail>Email contact</li>
</ul>
<div class"content"x/div>
</div>
<div class"edit">
<ul class"options">
<11 class*"optSave default>Save contact</li>
<11 class"optDestroy">Delete contact</li>
</ul>
<div class"content"x/div>
</div>
</div>
, , div- #sidebar div #contacts.
. items, ,
#contacts. .optEmail .optSave,
.
, .optDestroy,
.
Contact
, .
: f irst_name, last_name email.
,
:
//
var Contact = Spine.Model.setup("Contact,
191
//
Contact.extend(Spine.Model.Local);
//
Contact.include({
fullName: function(){
if ( !this.first_name && !this.last_name ) return;
return(this.first_name + " " + this.last_name);
>
;
, Spine.Model.Local.
,
.
Sidebar
Sidebar,
.
Sidebar , .
, New contact ( ),
, .
.
,
Spine, ,
:
jQuery(function($){
window.Sidebar = Spine.Controller.create({
// :
// this.items //=> <ulx/ul>
elements: {
.items: "items
b
//
events: {
"click button": "create"
b
// ,
//
//
proxied: ["render"],
//
template: function(items){
return($("#contactsTemplate").tmpl(items));
}j
&
192
11. Spine
init: function(){
this.list = Spine.List.init({
el: this.items,
template: this.template
}>S
//
this.list.bind("change", this.proxy(function(item){
this.App.trigger("show:contact", item);
};
//
// , . .
this.App.bind("show:contact edit:contact", this.list.change);
//
Contact.bind("refresh change", this.render);
b
render: function(){
var items = Contact.all();
this.list.render(items);
b
// 'Create'
create: function(){
var item = Contact.create();
this.App.trigger("edit:contact", item);
}
});
});
, init ()
Spine.List, . Spine.List
, . Spine.
List ,
change, .
. , ,
, , ,
.
#contactsTemplate, template(), script,
:
<script type="text/x-jquery-tmpl" id="contactsTemplate">
<li class="item">
193
{{if fullName()}}
<span>${fullName()}</span>
{{else}}
<span>No Name</span>
{{/if}}
</li>
</script>
j Query.tmpl,
5. Spine.List
,
current class- <>,
.
Contacts
Sidebar ,
.
? Contacts:
jQuery(function($){
window.Contacts = Spine.Controller.create({
//
elements: {
".show": "showEl",
".show .content": "showContent",
".edit: "editEl"
b
proxied: ["render", "show"],
init: function(){
//
this.show();
//
Contact.bind("change", this.render);
//
this.App.bind("show:contact", this.show);
b
change: function(item){
this.current = item;
this.render();
re n d e r: fu n c tio n ( ) {
&
194
11. Spine
this.showContent.html($("#contactTemplate").tmpl(this.current));
b
show: function(item){
if (item && item.model) this.change(item);
this.showEl.show();
this.editEl.hide();
}
});
,
show: contact. Contacts,
show(), .
div- showContent,
.
#contactTemplate,
Contacts .
:
<script type"text/x-jquery-tmpl" id="contactTemplate">
<label>
<span>Name</span>
${first_name} ${last_name}
</label>
<label>
<span>Email</span>
{{if email}}
${email}
{{else}}
<div class="emptyH>Blank</div>
{{/if}}
</label>
</script>
, ?
Contacts, .
,
,
.optEdit .optSave. :
#editContactTemplate.
:
jQuery(function($){
window.Contacts = Spine.Controller.create({
//
elements: {
".show": "showEl",
".edit": "editEl",
".show .content": "showContent",
".edit .content": "editContent"
b
//
events: {
"click .optEdit": "edit",
"click .optDestroy": "destroy",
"click .optSave": "save"
b
proxied: ["render", "show", "edit"],
init: function(){
this.show();
Contact.bind("change", this.render);
this.App.bind("show:contact", this.show);
this.App.bind("edit:contact", this.edit);
b
change: function(item){
this.current * item;
this.render();
b
render: function(){
this.showContent.html($("#contactTemplate").tmpl(this.current));
this.editContent.html($("#editContactTemplate").tmpl(this.current));
b
show: function(item){
if (item && item.model) this.change(item);
this.showEl.show();
this.editEl.hide();
b
// 'edit'
edit: function(item){
if (item && item.model) this.change(item);
this.showEl.hide();
this.editEl.show();
b
// 'delete'
&
196
11. Spine
destroy: function(){
this.current.destroy();
b
// 'save'
save: function(){
var atts = this.editEl.serializeForm();
this.current.updateAttributes(atts);
this.show();
}
});
});
,
#editContactTemplate. ,
. , #editContactTemplate
#contactTemplate, ,
:
<script type="text/x-jquery-tmpl" id="editContactTemplate">
<label>
<span>First name</span>
<input type="text" name="first_name" value="${first_name}" autofocus>
</label>
<label>
<span>Last name</span>
cinput type="text" name="last_name" value="${last_name}">
</label>
<label>
<span>Email</span>
<input type="text" name=email value="${email}">
</label>
</script>
App
, Sidebar Contacts,
, Contact.
,
, :
jQuery(function($){
window.App = Spine.Controller.create({
el: $("body"),
elements: {
"#sidebar": "sidebarEl",
197
"#contacts": "contactsEl"
init: function(){
this.sidebar = Sidebar.init({el: this.sidebarEl});
this.contact = -Contacts.init({el: this.contactsEl});
//
Contact.fetch();
}
}).init();
});
, .init()
. fetch() Contact,
.
, , ! (Sidebar Contacts),
(Contact) . ,
. 11.2.
' 4 ,
mdex.html
I + I * file:///Users/Atex/sp<ne.comacts/index.htmt
C l
c v Coogle
<*Search
Alex M acCaw
Juiia
Martina C u d d y
Stina
1
1
Fir** name
R ichard]
Tim M acC aw
M acCaw
Email
Mobile number
Trish Fogarty
Work number
C"
Address
New contact
act
. 11.2. Spine-
Backbone
Backbone JavaScript-.
.
. , MVC,
Backbone.
, ,
.
Backbone , SproutCore
Cappuccino?
Backbone. SproutCore Cappuccino
,
HTML. gzip-
,
JavaScript, CSS , . ,
Backbone 4 ,
, , , ,
.
Backbone underscore.js,
, JavaScript
. Underscore 60 , ,
, , JavaScript
.
API, Underscore,
. Underscore , Backbone
, j Query
Zepto.js.
Backbone ,
.
,
.
199
Backbone, .
Backbone , .
, , MVC: .
.
. -
extend() Backbone.Model:
var User = Backbone.Model.extend({
initialize: function() {
/ / ...
}
});
, extend(), ,
.
. ,
, extend ()
:
var User = Backbone.Model.extend({
//
instanceProperty: "foo"
b {
//
classProperty: "bar"
}>;
assertEqual( User.instanceProperty, "foo" );
assertEqual( User.prototype.classProperty, "bar" );
initialize(), ,
. - ,
new:
var User = Backbone.Model.extend({
initialize: function(name) {
this.set({name: name});
}
});
var user = new User("Leo McGarry");
assertEqual( user.get("name"), "Leo McGarry");
200
12. Backbone
set() get():
var user = new User();
user.set({name: "Donna Moss"})
assertEqual( user.get("name"), "Donna Moss" );
assertEqual( user.attributes, {name: "Donna Moss"} );
}
}
});
, -
validate() , ,
, Error.
, set() save()
error.
error,
:
var user * new User;
user.bind("error", fundtion(model, error) {
//
});
user.set({email: "ga"});
//
user.set({"email": "ga"}, {error: function(model, error){
II...
}});
201
default.
:
var Chat = Backbone.Model.extend({
defaults: {
from: "anonymous"
}
});
assertEqual( (new Chat).get("from"), "anonymous" );
Backbone . ,
, ,
, , . , ,
Twitter, : Followers
Followees, User.
,
User,
.
, Back
bone. Collection:
var Users = Backbone.Collection.extend({
model: User
});
,
model, ,
User.
, ,
, - .
, .
. -,
, :
var users = new Users([{name: "Toby Ziegler"}, {name: "Josh Lyman"}]);
, add():
var users = new Users;
//
users.add({name: "Donna Moss"});
&
202
12. Backbone
//
users.add([{name: "Josiah Bartlet"}, {name: "Charlie Young"}]);
add:
users.bind("add", function(user) {
alert("Ahoy " + user.get("name") + "!");
;
, remove (),
remove:
users.bind("remove", function(user) {
alert(" " + user.get("name") + "!");
});
users.remove( users.models[0] );
. ID ,
get ():
var user = users.get("some-guid");
ID , cid
(client ID), Backbone :
var user = users.getByCid("HeKUU_cicT);
add remove ,
, change:
var user = new User({name: "Adam Buxton"});
var users = new Backbone.Collection;
users.bind("change", function(rec){
// !
});
users.add(user);
user.set({name: "Joe Cornish"});
comparator(), ,
,
:
var Users = Backbone.Collection.extend({
comparator: function(user){
return user.get("name");
}
});
203
, ,
( JavaScript).
Users
.
, -
, . sort().
- ,
, .
, MVC- ,
HTML ,
. , Backbone ,
,
DOM-.
,
Backbone , Backbone.
View:
var UserView = Backbone.View.extend({
initialize: function(){ /* ... */ },
render: function(){ / * . . . * / }
;
DOM-,
this.el, , .
el
tagName, className id. , el
div-:
var UserView = Backbone.View.extend({
tagName: "span",
className: "users"
;
assertEqual( (new UserView).el.className, "users" );
, el . , ,
,
:
var UserView = Backbone.View.extend({
el: $(".users")
});
204
12. Backbone
el
, tagName, className id:
new UserView({id: "followers"});
render(),
no-op ( ).
.
,
el HTML:
var TodoView = Backbone.View.extend({
template: template($("#todo-template").html()),
render: function() {
$(this.el).html(this.template(this.model.toJS0N()));
return this;
}
});
Backbone ,
.
. ,
HTML JavaScript-nporpaMM. Underscore.js,
, Backbone, ,
template (), .
, , ,
this.model.
:
new TodoView({model: new Todo});
toJS0N(), ,
, .
-
e l .
:
var TodoView = Backbone.View.extend({
events: {
"change input[type=checkbox]" : "toggleDone",
"click .destroy"
: "clear",
205
});
{" : "__"}. , ,
el. ,
, , ,
el , .
, , -
, el.
,
.
, ,
,
. ,
this.el this.model,
toggleDone() clear().
render()?
, ,
, change. ,
HTML ( )
:
var TodoView = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render', 'close');
this.model.bind('change', this.render);
b
close: function(){ / * . . . * / }
;
, ,
. Underscore
: _. bindAll(//, *).
( ). _.bindAll()
,
. ,
, .
render() close()
TodoView.
206
12. Backbone
. delete,
el :
var TodoView Backbone.View.extend({
initialize: function() {
bindAll(this, 'render', 'remove');
this.model.bind('change', this.render);
this.model.bind('delete', this.remove);
b
remove: function(){
$(this.el).remove();
>
, -
, .
render() initialize(),
.
,
, Backbone.
- URL,
, ,
. ,
, .
: , (splats), , :
routes: {
"help":
"help",
"search/:query":
"search",
"search/:query/p:page": "search"
"file/*path":
"file"
// :
// #help
// #search/kiwis
// #search/kiwis/p7
// #f ile//Ho66/e_cuAi6o/76//path.txt
}
,
:, . ,
, . ,
*, , -,
. ,
.
, ,
. , ,
, .
207
Backbone.Controllers,
, :
var PageController = Backbone.Controller.extend({
routes: {
I i i .
index,
"help":
help",
I I #help
"search/:query":
search", // #search/kiwis
"search/:query/p:page'
search"
// #search/kiwis/p7
b
index: function(){ /* ...'*// },
h
help: function() {
/ / ...
b
search: function(query, page) {
// ...
>
;
, http://example.
com#search/coconut, ,
, search() query,
"coconut".
Ajax Crawling
( 4),
!/, :
var PageController = Backbone.Controller.extend({
routes: {
"!/page/:title": "page", // #!/page/foo-title
>
// ...
}):
,
.
,
,
route () :
var PageController = Backbone.Controller.extend({
initialize: function(){
this.route(/pages\/(\d+)/, 'id', function(pageId){
II . . .
});
>
:
208
12. Backbone
, URL- ,
? window,
location.hash , Backbone
saveLocation(fragment):
Backbone.history.saveLocation("/page/" + this.model.id);
saveLocation() URL-
. ,
saveLocation() initialize() ,
, - .
Backbone
onhashchange , ,
, i f - .
Backbone:
Backbone.history.start();
Backbone ,
, . Backbone
API HTML5,
pushState() replaceState(). ,
,
Internet Explorer.
Backbone, .
- URL.
Backbone
Ajax-, : jQuery, Zepto.js. Backbone
Backbone.sync() ,
. Backbone RESTful JSON-
, , , .
,
url REST- .
Backbone:
var User = Backbone.Model.extend({
url: '/users'
});
url , , .
,
.
209
Backbone , , (CRUD)
:
create -> POST /
read
-> GET /[/11]
update -> PUT
//id
delete
DELETE
//id
}});
save() ,
Ajax-, success failure.
, Backbone j Query, ,
save(), $.ajax(). ,
Ajax- j Query,
timeout.
,
error. ,
:
var user = new User();
user.bind("error", function(e){
// !
});
user.save({email: " "});
, fetch(),
( GET-).
210
12. Backbone
,
change:
var user * Users.get(l);
user.fetch();
, ,
? Backbone,
.
,
url. , Backbone
url :
var Followers = Backbone.Collection.extend({
model: User,
url: "/followers"
;
Followers.fetch();
fetch() GET- ,
/followers, .
, , refresh.
refresh()
, .
. GET-
, ,
refresh () JSON-. , ,
Rails:
<script type="text/javascript">
Followers.refresh(<%= @users.to_json %>);
</script>
, Backbone
RESTful:
create
read
read
update
delete
POST
GET
GET
PUT
DELETE
/
/
//id
//id
//id
Backbone JSON.
User :
{"name": "Yasmine"}
211
, ,
, Rails-.
Rails Backbone, ,
, .
CRUD-
. , Rails- update,
:
def update
user ** User.find(params[:id])
user.update_attributesl(params)
render :json *> user
end
,
attr_accessible,
, .
, destroy, JSON- .
JSON ,
Rails ,
:
{"user: {"name": "Daniela"
, Backbone .
, Rails
JSON- , -:
# config/initializers/json.rb
ActiveRecord::Base.include_root_in_json * false
Backbone.sync() Backbone,
.
( Ajax-)
, WebSockets, XML-
. , , Backbone.sync() -, ,
:
Backbone.sync = function(method, model, options) {
console.log(method, model, options);
options.success(model);
};
, Backbone.sync()
(method), (model) (options),
:
212
12. Backbone
method
( )
options
, ,
, Backbone ,
: opt ions. success(), opt ions. error().
sync
:
Todo.prototype.sync = function(method, mod^l, options){ /* ... */ };
Backbone.sync()
.
localStorage
Backbone
HTML5 localStorage. , Backbone, sync()
CRUD- store, ,
options.success () :
// todo
// "todos" localStorage.
Todos.prototype.localStorage = new Store("todos");
// Backbone.sync()
// localStorage
// , Store.
Backbone.sync = function(method, model, options) {
var resp;
var store = model.localStorage || model.collection.localStorage;
switch (method) {
case "read":
resp =
break;
case "create": resp =
break;
case "update": resp =
break;
case "delete": resp =
break;
To-Do ( )
213
if (resp) {
options.success(resp);
} else {
options.error(" ");
>
};
To-Do ( )
, Backbone,
, . ,
CRUD-
. ,
,
assets/chl2/todos.
, CSS, JavaScript- -, todos.js,
:
<html>
<head>
<link href="todos.css" media="all" rel="stylesheet" type="text/css"/>
<script src="lib/json2. js"x/script>
<script src="lib/jquery. js"x/script>
<script src="lib/jquery.tmpl.js"x/script>
<script src="lib/underscore.js"x/script>
<script src="lib/backbone. js"x/script>
<script src="lib/backbone.localStorage.js"x/script>
<script src="todos.js"x/script>
</head>
<body>
<div id="todoapp,,>
<div class="title">
<hl>Todos</hl>
</div>
<div class="content">
<div id="create-todo">
<input id="new-todo" placeh0lder="4T0 ?"
type="text" />
</div>
<div id="todos">
<ul id="todo-list"x/ul>
</div>
</div>
</div>
</body>
</html>
214
12. Backbone
:
(#new-todo) ,
(#todo-list).
todos.js, Backbone. jQuery () , ,
:
// todos.js
jQuery(function($){
// ...
})
Todo content done.
done,
toggle ():
window.Todo = Backbone.Model.extend({
defaults: {
done: false
b
toggle: function() {
this.save({done: !this.get("done")});
}
});
, Todo
window. ,
, ,
window.
TodoList,
Todo:
window.TodoList = Backbone.Collection.extend({
model: Todo,
// to-do "todos".
localStorage: new Store("todos"),
//
// ,
done: function() {
return this.filter(function(todo){ return todo.get('done'); });
b
remaining: function() {
return this.without.apply(this, this.done());
}
});
To-Do ( )
215
// Todos.
window.Todos = new TodoList;
- (backbone.localStorage. js),
localStorage
, . TodoList, done()
remaining(), ,
, .
TodoList, :
window.Todos.
, , TodoView.
change Todo
:
window.TodoView = Backbone.View.extend({
// .
tagName: "",
// template ,
template: $("#item-template").template(),
//
events: {
"change
.check"
: "toggleDone",
"dblclick .todo-content" : "edit",
"click .todo-destroy" : "destroy",
"keypress .todo-input"
: "updateOnEnter",
"blur
.todo-input"
: "close"
b
initialize: function() {
//
_.bindAll(this, 'render', 'close', 'remove');
//
this.model.bind('change', this.render);
this.model.bind('destroy', this.remove);
b
render: function() {
// el
var element = jQuery.tmpl(this.template, this.model.toJSON());
$(this.el).html(element);
return this;
b
// done ()
toggleDone: function() {
&
216
12. Backbone
this.model.toggle();
b
// '"editing"' (),
// ,
edit: function() {
$(this.el).addClass("editing");
this.input.focus();
b
// '"editing"', .
close: function(e) {
this.model.save({content: this.input.val()});
$(this.el).removeClass("editing");
b
// '', .
// blur ,
// close()
updateOnEnter: function(e) {
if (e.keyCode == 13) e.target.blur();
b
//
remove: function() {
$(this.el).remove();
b
// .todo-destroy1
destroy: functionQ {
this.model.destroy();
>
;
, ,
, . ,
toggleDone(),
done. , , change,
.
HTML- jQuery.tmpl,
e l .
, ID, #item-template,
. , body-
index.html:
<script type="text/template" id="item-template">
<div class="todo {{if done}}done{{/if}}">
<div class="display" title=" ...">
To-Do ( )
217
5, j Query.tmpl . ,
#todo-content #todo-input.
, "checked".
TodoView
el
. AppView,
TodoView.
AppView Todo,
, #new-todo:
// AppView UI ,
window.AppView = Backbone.View.extend({
//
// , HTML,
el: $("#todoapp"),
events: {
"keypress #new-todo": "createOnEnter",
"click .todo-clear a": "clearCompleted"
b
//
// 'Todos', .
//
// ,
// *localStorage*.
initialize: function() {
_.bindAll(this, 'addOne', 'addAll', 'render');
this.input = this.$("#new-todo");
Todos.bind('add',
this.addOne);
Todos.bind('refresh', this.addAll);
Todos.fetch();
b
&
218
12. Backbone
11
// '<ul>'.
addOne: function(todo) {
var view * new TodoView({model: todo});
this.$("#todo-list").append(view.render().el);
// Todos.
addAll: function() {
Todos.each(this.addOne);
b
// ,
//
// Todo
createOnEnter: function(e) {
if (e.keyCode != 13) return;
var value = this.input.val();
if ( lvalue ) return;
Todos.create({content: value});
this.input.val(11);
clearCompleted: functionQ {
_.each(Todos.done(), function(todo){ todo.destroy(); });
return false;
>
});
// , .
window.App = new AppView;
Todos ,
refresh. addAll(),
Todo, TodoView
#todo-list. , Todo Todos,
Todos, addOne()
TodoView . ,
Todo AppView, TodoView
.
. ,
- . 12.1.
, ,
,
. - ,
.
219
To-Do ( )
Backbone, ,
.
assets/chl2/todos.
Backbone Demo: To do s
til 4 1* .'f
I http://example.com
Coogife
Todos
What needs to be done?
Have tea with the Queen
Circumnavigate the world
Race a cheetah
Clim b Mount Everest
3 items left.
//
. 12.1. - Todo
JavaScriptMVC
(Justin Meyer),
JavaScriptMVC
JavaScriptMVC (JMVC) JavaScript- ,
j Query. ()
, ,
,
j Query.
JavaScriptMVC
, . , ,
7 , .
JavaScriptMVC
,
.
JavaScriptMVC $. Class,
$ .Model, $.View $ .Controller. .
$ .Class
, JavaScript
$ .Model
$.View
$ .Controller
j Query
JavaScriptMVC
-- (MVC).
, $ .C ontroller
, ,
221
,
.
JavaScript MVC ,
.
MVC-, (download builder, http://
javascriptmvc.com/builder.html), Controller, Model View
EJS templates Download.
j Query
. s c rip t :
<script type='text/javascript' src='jquery-1.6.1.js'></script>
<script type='text/javascript' src='jquerymx-1.0.custom.js'></script>
J MVC-
$. Class. $. Class (, [, ] ]):
$.Class("Animal,{
breathe : function(){
console.log(breathe);
}
});
Animal breathe().
Animal
breathe():
var man = new Animal();
man.breathe();
,
:
Animal("Dog",{
wag : function(){
console.log('wag');
}
})
var dog = new Dog;
dog.wag();
dog.breathe();
222
13. JavaScriptMVC
init
, -:
$.Class('Person',{
init : function(name){
this.name * name;
b
speak : function(){
return "I am " + this.name +
>
;
var payal ^ new Person("Payal");
assertEqual( payal.speak() , 'I am Payal.' );
this ._super.
person, :
Person("ClassyPerson", {
speak : function(){
return "Salutations, " + this._super();
}
});
var fancypants * new ClassyPerson("Mr. Fancy");
assertEquals( fancypants.speak() , 'Salutations, I am Mr. Fancy.')
,
this, $.proxy.
Clicky, :
$.Class("Clicky",{
init : function(){
this.clickCount = 0;
b
clicked: function(){
this.clickCount++;
listen: function(el){
el.click( this.callback('clicked') );
>
})
223
.
person
Per son. findOne( ID, success(person) ).
Person, speak:
$.Class("Person",{
findOne : functioned, success){
$.get('/person/'+id, function(attrs){
success( new Person( attrs ) );
b json)
init : function(attrs){
$.extend(this, attrs)
b
speak : function(){
return "I am "+this.name+".
}
})
Person.findOne(5, function(person){
assertEqual( person.speak(), "I am Payal." );
:
$.Class("Jupiter.Person");
Jupiter.Person.shortName; //-> 'Person'
Jupiter.Person.fullName; //-> 'Jupiter.Person'
Jupiter.Person.namespace; //-> Jupiter
var person new Jupiter.Person();
person.Class.shortName; //-> 'Person'
,
ORM-. Model
224
13. JavaScriptMVC
REST-
Model:
$.Class("Model",{
findOne : functioned, success){
$.get('/' + this.fullName.toLowerCase() + '/' + id,
this.callback(function(attrs){
success( new this( attrs ) );
})
b'json')
>
}>{
init : function(attrs){
$.extend(this, attrs)
}
})
Model("Person",{
speak : function(){
return "I am "+this.name+".
>
;
Person.findOne(5, function(person){
alert( person.speak() );
;
Model("Task");
Task.find0ne(7,function(task){
alert(task.name);
;
, JavaScriptMVC.
JavaScriptMVC
, ,
, , .
,
.
, ,
. , MVC .
225
, JavaScript MVC
. .
. ,
Next () Previous (),
,
(, 1-20).
.
offset
limit
count
JavaScript MVC $. Model:
var paginate = new $.Model({
offset: 0,
limit: 20,
count: 200
;
paginate .
,
, .
model.attr(HAW):
assertEqual( paginate.offset, 0 );
assertEqual( paginate.attr('limit') , 20 );
,
(offset).
model.attr(HAftf, ).
offset :
paginate.attr('offset', 20);
, .
model, bind(ATTR, success( ev, newVal ) ):
paginate.bind('offset', function(ev, newVal){
$('#details').text( ' ' + (newVal + 1 ) +
'-' + this.count )
})
226
13. JavaScriptMVC
'updated.attr':
paginate.bind('updated.attr', function(ev, newVal){
$('tdetails').text( ' ' + (newVal+1 )+ '-' +
this.count )
})
j Query ,
:
J.fn.nextPrev = function(paginate){
this.delegate('.next','click', function(){
var nextOffset = paginate.offset + paginate.limit;
if( nextOffset < paginate.count){
paginate.attr('offset', nextOffset );
}
});
this.delegate('.prev','click', function(){
var nextOffset * paginate.offset-paginate.limit;
if( 0 < paginate.offset ){
paginate.attr('offset', Math.max(0, nextOffset) );
}
});
var self * this;
paginate.bind('updated.attr', function(){
var next = self.find('.next'),
prev = self.find('.prev');
if( this.offset == 0 ){
prev.removeClass('enabled');
} else {
prev.removeClass('disabled');
>
if( this.offset > this.count - this.limit ){
next.removeClass('enabled');
} else {
next.removeClass('disabled');
}
;
};
.
-, ,
paginate. ,
.
227
-,
(offset:) , ,
. .
,
,
limit, offset count.
JavaScriptMVC $ . Class.
$. Model (, [STATIC, ] ):
$.Model('Paginate', {
staticProperty: 'f'
prototypeProperty: 'bar'
Paginate.
-
,
.
-
- ,
set. val, model. attr(HAftf,
val), ,
. ,
, (error)
. (success)
-, .
Paginate -
(count)
(offset). ,
:
$.Model('Paginate', {
setCount : function(newCount, success, error){
return newCount < 0 ? 0 : newCount;
b
setOffset : function(newOffset, success, error){
return newOffset < 0 ? 0 :
Math.min(newOffset, !isNaN(this.count - 1) ?
this.count : Infinity )
}
});
228
13. JavaScriptMVC
nextPrev
(offset),
:
this.delegate('.next','click', function(){
paginate.attr('offset', paginate.offset+paginate.limit);
;
this.delegate('.prev','click', function(){
paginate.attr('offset', paginate.offset-paginate.limit );
});
Paginate defaults.
paginate ,
:
$.Model('Paginate',{
defaults : {
count: Infinity,
offset: 0,
limit: 100
;
var paginate = new Paginate({count: 500});
assertEqual(paginate.limit, 100);
assertEqual(paginate.count, 500);
Paginate
-.
-
,
, .
Paginate next prev,
, .
canNext canPrev,
:
$.Model('Paginate',{
defaults : {
count: Infinity,
229
offset: 0,
limit: 100
b
b
prev : function(){
this.attr('offset', this.offset - this.limit )
canNext : function(){
return this.offset > this.count - this.limit
canPrev : function(){
return this.offset > 0
}
})
, j Query- :
J.fn.nextPrev = function(paginate){
this.delegate('.next','click', function(){
paginate.attr('offset', paginate.offset+paginate.limit);
this.delegate('.prev','click', function(){
paginate.attr('offset', paginate.offset-paginate.limit );
});
})
, $ .Model
.
, . ,
, ( CRUD-) ,
.
, $ .Model .
230
13. JavaScriptMVC
$ .Model .
.
$ . Model
: Representational
State Transfer (REST) JSON.
REST URL- HTTP- POST, GET, PUT
DELETE , ,
. , , , ,
(tasks), :
create
POST /tasks
read all
GET /tasks
read
GET /tasks/2
update
PUT /tasks/2
delete - DELETE /tasks/2
,
, , , :
$.Model("Task,{
create : "POST /tasks.json",
findOne : "GET /tasks/{id}.json",
findAll : "GET /tasks.json",
update : "PUT /tasks/{id}.json",
destroy : "DELETE /tasks/{id}.json"
;
, Task
CRUD- .
new Task({ name: 'do the dishes'}).save(
success( task, data ),
error( jqXHR)
) //=> taskDeferred
new Model (attributes). save(). save()
, ID. ,
save() .
.
success
, , . success
, .
error
, ,
. XHR-, jQuery.
231
save() deferred- (
), .
Task.findOne(params, ~
success( task ),
error( jqXHR)
) //=> taskDeferred
. ,
params
; ID { id : 2}.
success
, , . success
.
error
, , .
findOneQ deferred-, .
Task.findAll(params,
success( tasks ),
error( jqXHR)
) //=> tasksDeferred
. ,
params
. ({})
{limit: 20, offset: 100}.
success
, , . success
.
error
, , .
findAll () deferred-, .
task.attr('name','take out recycling');
task.save(
success( task, data ),
error( jqXHR)
) //=> taskDeferred
232
13. JavaScriptMVC
attr
. save(). save()
,
.
task.destroy(
success( task, data ),
error( jqXHR)
) //=> taskDeferred
destroy() . ,
success
, , . success
, .
error
, , .
save(), destroy () deferred-,
. , Task !
,
(createdAt) , 1303173531164?
18 2011 .
task.createdAt ,
JavaScript, new Date(1303173531164).
- setCreatedAt,
(Date)
.
, $. Model ,
.
attributes,
convert:
$.Model('Task'/{
attributes : {
createdAt : 'date'
convert : {
date : function(date){
return typeof date == 'number' ? new Date(date) : date;
>
>
233
>);
CRU D-
, .
. ,
MOD L.bind (,
callback( ev, instance ) ).
,
. ,
.
:
Task.bind('created', function(ev, task){
var el = $('<li>').html(todo.name);
el.appendTo($('#todos'));
task.bind('updated', function(){
el.html(this.name);
}).bind('destroyed', function(){
el.remove();
>);
JavaScriptMVC-
, ,
. HTML,
DOM.
$.View ,
, . :
;
HTML- ;
;
;
234
13. JavaScriptMVC
;
;
$. Deferred.
JavaScriptMVC
:
EJS
JAML
Micro
Tmpl
EJS-,
(
).
. jQuery.View
j Query-,
:
$("#f" ).html('mytemplate.js ',{message: 'hello world'})
:
1. mytemplate.ejs. :
<h2><%= message %></h2>
3. foo, :
<div id='foo'><h2>hello world</h2x/div>
jQ uery
-
j Query:
$('#bar').after('temp.ejs',{});
$('#bar').append('temp.ejs',{});
$('#bar').before('temp.ejs',{});
$('#bar').html('temp.ejs',{});
$('#bar').prepend('temp.ejs',{});
$('#bar').replaceWith('temp.ejs',{});
$('#bar').text('temp.ejs',{});
235
script-
s c rip t- .
s c rip t- s c rip t- type,
(te x t/e js), id, :
<script type='text/ejs' id='recipesEDS'>
<% for(var i=0; i < recipes.length; i++){ %>
<lix%=recipes[i] .name %></li>
<%} %>
</script>
:
JC'tfoo").html('recipesEDS', recipeData)
, id ,
.
$.View
.
$. View ( , ) . $.View ,
, :
var html = J.ViewC'template/items.ejs", items );
.
(items.ejs).
template/items.ejs ,
template/item.ejs:
<% for( var i = 0; i < this.length; i++){ %>
<li>
<%= J.ViewC'template/item.ejs", this[i]);
</li>
< % } %>
th is , . template/
items.ejs th is . template/item.ejs th is
.
D eferred-
Ajax-
-. Task
, $ .Model,
:
Task.findAll({}, function(tasks){
$(,#tasks,).html(,,views/tasks.ejs" , tasks )
236
13. JavaScriptMVC
,
$. View , , :
s c rip t-;
JavaScript;
.
JavaScriptMVC s c rip t- .
s c rip t-:
JavaScript-.
,
.
JavaScriptMVC
JavaScript- ,
, .
JavaScriptMVC StealJS
, .
s te a l, views (PATH, . . . ) :
steal.v iew s( 't a s k s .e j s ', 't a s k . e j s ');
, $.View ,
, -, Ajax.
, ,
jQuery.get.
URL dataType 'view'
(.Controller: jQuery
237
(
):
$(window).load(function(){
setT imeout(function(){
$.get('users.ejs',function(){},'view');
$.get('user.ejs',function(){},'view');
>,500)
$.Controller:
jQuery
JavaScriptMVC- .
jQuery. ,
. ,
. ,
.
,
:
jQuery;
;
, ;
.
JavaScript.
, ,
, :
$.fn.tooltip = function(){
var el = this[0];
{(document).click(function(ev){
if (ev.target !== el)
$(el).remove();
>);
$(el).show();
return this;
>);
238
13. JavaScriptMVC
, ,
, tooltip:
$(H<div class='tooltip'> <^1>")
.appendTo(document.body)
.tooltip()
. , ?
: ,
?
, !
. ,
.
, j Query
, ,
.
, ,
.
, -- (MVC),
, .
. , nextPrev
$ .Model paginate:
paginate.bind('updated.attr', function(){
self.find('.prev')[this.canPrev() ? 'addClass1 :
'removeClass']('enabled')
self.find('.next')[this.canNext() ? 'addClass' :
'removeClass']('enabled');
paginate! , ,
, .
tooltip, nextPrev .
. , $. Controller
.
tooltip:
$.Controller('Tooltip',{
init: function(){
this.element.show()
>
>
(.Controller: jQuery
239
DOM, $. Control
ler .
$ . Controller nextPrev,
Paginate:
$.Controller('Nextprev',{
".next click" : function(){
var paginate = this.options.paginate;
paginate.attr('offset', paginate.offset+paginate.limit);
b
".prev click" : function(){
var paginate = this.options.paginate;
paginate.attr('offset', paginate.offset-paginate.limit );
b
"{paginate} updated.attr" : function(ev, paginate){
this.find('.prev')[paginate.canPrev() ? 'addClass' :
'removeClass']('enabled')
this.find('.next')[paginate.canNext() ? 'addClass' :
'removeClass']('enabled');
>
// nextprev
$('#pagebuttons').nextprev({ paginate: new Paginate() })
$ . Controller $ . Class.
$. Controller (, , )
, .
:
$.Controller("List", {
defaults : {}
init : function(){ },
"li click" : function(){ }
- jQuery,
. , ,
, .
240
13. JavaScriptMVC
, . ,
$. Controller ( 'App.FooBar') $(el) .app_foo_bar().
new t roller (, _), HTML-
, j Query, ,
. :
new List($('ul#tasks'), {model : Task});
List #tasks
- j Query:
$('ul#tasks').list({model : Task})
init
.
this.element
HTML-, jQuery.
this.options
, ,
defaults.
List
,
.
$.Controller("List", {
defaults : {
template: "items.ej s"
}
L {
init : function(){
this.element.html( this.options.template, this.options.model.findAll()
);
b
"li click" : function(){ }
;
List
. ,
!
$('#tasks').list({model: Task, template: "tasks.ejs"});
$('#users').list({model: User, template: "users.ejs"})
, List items.ejs.
$.Controller: jQuery
241
$. Controller,
.
.
, ,
"li click". jQuery.bind jQuery.
delegate.
,
, .
, .
"li click"
li
.
"mousemove"
.
"{window} click"
.
,
jQuery, , , .
:
"li click": function( el, ev ) {
assertEqual(el[0].nodeName, "li" )
assertEqual(ev.type, "click")
>
$. Controller .
,
.
, {}, ,
.
,
.
$.Controller("Menu",{
"li {openEvent}" : function(){
//
>
;
242
13. JavaScriptMVC
// , (click)
$("#clickMenu").menu({openEvent: 'click'});
// ,
// ( mouseenter)
>
;
$("#divMenu").menu({menuTag : "div"})
. , Task
$ . Model created Task.
,
:
$.Controller("List", {
defaults : {
template: "items.ejs"
>
init : function(){
this.element.html( this.options.template, this.options.model.findAll() );
"{Task} created" : function(Task, ev, newTask){
this.element.append(this.options.template, [newTask])
}
})
"{Task} created" Task,
Task.
( )
HTML .
List .
:
$.Controller("List", {
defaults : {
template: "items.ejs",
: CRUD-
243
model: null
>
init
: function(){
this.element.html( this.options.template, this.options.model.findAll()
>;
b
}
});
//
$('#tasks').list({model: Task, template: "tasks.ejs"});
:
CRUD-
,
, .
:
"{model} updated" : function(Model, ev, updatedltem){
// LI updatedltem
}
. -
, .
. ,
$ . Model $.View
.
EJS-,
. tasks.ejs:
<% for(var i =0 ; i < this.length; i++){ %>
<% var task = thisfi]; %>
<li <%= task %> > <%= task.name %> </li>
<% } %>
tasks.ejs .
(task) li . ,
<lix%=task %></li> jQuery- .
244
13. JavaScriptMVC
modelInstance.elements([CONTEXT]).
, jQuery, .
, :
$.Controller("List", {
defaults : {
template: "items.ejs",
model: null
>
init : function(){
this.element.html( this.options.template, this.options.model.findAll()
);
b
>
;
//
$('#tasks').list({model: Task, template: "tasks.ejs"});
, JavaScriptMVC
, .
jQuery
DOM ,
j Query.
: j Query API,
,
. , j Query
.
, JavaScript
.
j Query jQuery,
($). , Prototype,
j Query - JavaScript,
.
j Query .
CSS, .
j Query , ,
. ,
j Query,
.
,
selected foo.
JavaScript, j Query:
// JavaScript
var elements = document.getElementsByClassName("foo");
for (var i=0; i < elements.length; i++) {
elementsfi].className += " selected";
>
// jQuery
$(".foo").addClass("selected");
246
. jQuery
, , API jQuery
. .
ID CSS (#),
jQuery:
// ID (wem)
var element = document.getElementById("wem");
var element = $("#wem");
// (bar)
var elements = document.getElementsByClassName("bar");
var elements = $(".bar");
// ()
var elements = document.getElementsByTagName("p");
var elements = $("p");
CSS,
:
// , 'foo' 'bar'
var foo = $(".bar .foo");
:
var username = $("input[name='username']");
:
var example = $(".wemifirst");
,
:
// 'foo'
$(".foo").addClass("bar");
, jQuery
, DOM, :
// !
var element = document.getElementByld("wem");
element.addClass("bar");
, API jQuery,
jQuery:
var element = document.getElementById("wem");
{(element).addClass("bar");
DOM-
247
DOM-
j Query
, :
var wem = $("#wem"); '
//
wem.find(".test");
//
wem.parent();
//
//
wem.parents(".optionalSelector");
// ( )
wem.children();
:
var wem = $("#wem");
// (0)
wem.eq( 0 );
// ( $.fn.eq(0))
wem.first();
// ,
(".foo")
wem.filter(".foo");
// ,
//
wem.filter(function(){
// this
return $(this).hasClass(".foo");
});
// , ,
// (".selected")
wem.has(".selected");
248
. jQuery
j Query () each(),
:
var wem = $("#wem");
// ,
//
wem.map(function(element, index){
assertEqual(this, element);
return this.id;
}>;
// ,
// 'for'.
wem.each(function(index, element){
assertEqual(this, element);
/*...*/
;
:
//
var wem = $("#wem");
wem.add( $("p") );
DOM
Ho j Query , API
DOM. j Query
HTML-,
:
var element = $("");
element.addClass("bar")
element.text(" ");
DOM ,
: append() prepend().
,
DOM:
//
var newDiv = $("<div />");
$("body").append(newDiv);
//
$(".container").prepend($("<hr />"));
DOM
249
:
//
$(".container").after( $("< />") );
//
$(".container").before( $("< />") );
:
//
$("wem").remove();
? j Query
. , ,
addClass():
$("#f00 ").addClass("bar");
//
$("#f").removeClass("bar");
// ?
var hasBar = $("#foo").hasClass("bar");
CSS. css ()
, ,
:
var getColor = $(".foo").css("color");
//
$(".f").ss("lo", "#000");
//
$(".foo").css({color: "#000", backgroundColor: "#FFF"});
j Query
:
// display ,
$(".bar").hide();
// display block,
$(".bar").show();
, :
$(".foo").fadeOut();
$(".foo").fadeln();
250
. jQuery
j Query - - CSS
. , , ,
html():
// HTML
var getHTML = $(#bar).html();
// HTML
$(#bar").html("<p>Hi</p>");
text(), :
var getText = $("#bar").text();
$("#bar).text(", ");
, , empty ():
$("#bar").empty();
,
API. j Query ,
API.
j Query,
2 (http://api.jquery.com/category/events).
, bindQ,
:
$(".clicky").bind("click", function(event){
//
});
j Query ,
bind() , , :
$(".clicky").click(function(){ /* ... */ });
, , , , document.
ready. , DOM ,
, , . j Query
:
jQuery:
jQuery(function($){
// document.ready
});
j Query
. ,
Ajax
251
,
$(". clicky"):
$(".clicky").click(function(){
// 'this'
assert( $(this).hasGlass(".clicky") );
});
this
.
, self:
var self = this;
$(".clicky").click(function(){
self.clickedClick();
;
, -,
jQuery.proxy():
*(".clicky").click($.proxy(function(){
// Context isn't changed
L this));
2.
Ajax
Ajax, XMLHttpRequest ,
. jQuery
,
API. jQuery Ajax API 3,
.
jQuery ajax()
. ajax() ,
URL,
(success):
$.ajax({
url: "http://example.com",
type: "GET",
success: function(){ / * . . . * / }
});
jQuery API :
$.get("http://example.com", function(){ /* *./ })
$.post("http://example.com", {some: "data"});
252
. jQuery
;
j Query
, getDSONQ,
ajax():
$.get3S0N("http://example,com/endpoint.json", function(json){ / * . . * / });
j Query , -.
. j Query
$, ,
Prototype. , ,
jQuery noConflict
$:
var $3 = jQuery.noConflict();
assertEqual( $, undefined );
j Query- ,
j Query $ jQuery.
$ ,
:
(function($){
// $
$(".foo").addClass("wem");
})(jQuery);
253
, j Query
document.ready:
jQuery(function($){
//
assertEqual( $, jQuery );
});
j Query, , .
,
jQuery:
jQuery.myExt = function(argl){ /*...*/ };
// ,
$.myExt("anyArgs");
,
, jQuery.fn,
jQuery.prototype.
, (. . this),
:
jQuery.fn.wemExt = function(argl){
$(this).html("Bar");
return this;
};
$("#element").wemExt(1).addClass("foo");
,
. ,
:
(function($){
//
var replaceLinks = function(){
var re =
/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g;
$(this).html(
$(this).htmlQ.replace(re, '<a target="_blank" href="$l">$l</a> ')
)i
};
$.fn.autolink = function() {
return this.each(replaceLinks);
};
})(jQuery);
254
. jQuery
jQuery Growl
jQuery Growl.
, Growl, Mac OS X,
. OS X
JavaScript ,
. .1.
That s it
I m on strike!
. .1. Growl-
div- #container,
. ,
, jQuery, jQuery UI,
. ,
div-:
//= require <jquery>
//= require <jquery.ui>
(function($){
var container = $("<div />");
container.attr({id: "growl"});
$(function(){
// div
$("body").append(container);
});
/*...*/
}) (jQuery);
.
, div container.
jQuery Growl
255
(drop), , - ,
, Growl OS X:
$ .growl = function(body){
// div- Growl
var msg = $("<div />,").addClass("msg");
msg.html(body);
//
container.append(msg);
//
msg.show("drop", {
direction: "down",
distance: 50
300). .
delay(2000).
fadeOut(300, function(){
$(this).remove();
});
return msg;
>;
JavaScript.
, CSS3.
div- #container
:
#growl {
position: absolute;
bottom: 10px;
right: 20px;
overflow: hidden;
}
.
HUD Growl, .
, rgba, (inset
box-shadow), :
#growl .msg {
width: 200;
min-height: 30;
padding: 10;
margin-bottom: 10;
border: lpx solid #171717;
color: #E4E4E4;
text-shadow: 0 -lpx lpx #0A131A;
&
256
. jQuery
font-weight: bold;
font-size: 15px;
background: #141517;
background: -webkit-gradient(
linear, left top, left bottom,
from(rgba(255, 255, 255, 0.3)),
color-stop(0.8, rgba(255, 255, 255, 0))),
rgba(0, 0, 0, 0.8);
-webkit-box-shadow: inset 0 lpx lpx #8E8E8E;
-moz-box-shadow: inset 0 lpx lpx #8E8E8E;
box-shadow: inset 0 lpx lpx #8E8E8E;
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px;
}
. , j Query
. ,
assets/appA/growI.html.
CSS-
}
:
.panel {
.vbg-gradient(#FFF, #);
,
Less- ,
.
:
@panel-color: #;
:
header {
color: @panel-color;
258
. CSS-
Less- . ,
,
:
.vbg-gradient(@f : #FFF, @tc: #) {
background: @fc;
background: -webkit-gradient(linear, left top, left bottom, from(fc),
to(@tc));
background: -moz-linear-gradient(top, fc, @tc);
background: linear-gradient(top, fc, @tc);
>
: f tc,
#FFF # .
. ,
.
CSS3 ,
, , ,
-webkit -moz. , , ,
;
.
, , , Less
, ,
, .
, :
/* */
.border-radius(@r: ) {
-moz-border-radius: @;
-webkit-border-radius: @;
border-radius: @;
}
/* */
.box-shadow (@h: 0px, @v: 0px, @b: 4, @: #333) {
-moz-box-shadow: @h @v @b @c;
-webkit-box-shadow: @h @v @b @c;
box-shadow: @h @v @b @c;
259
,
:
button {
.border-radius();
.box-shadow(0, lpx,- lpx, #FFF);
.vbg-gradient(#F9F9F9, #E3E3E3);
:active {
.vbg-gradient(#E3E3E3, #F9F9F9);
}
}
:
,
, .
,
, ^import
. Less
, ,
-.
. ,
CSS3, :
^import "utils";
Less ,
, , . Less
, :
background:
background:
background:
background:
saturate(#319, 10%);
desaturate(#319, 10%);
darken(#319, 10%);
lighten(#319, 10%)
,
. ,
, .
Less?
Less CSS.
260
. CSS-
gem- Less, lessc:
gem install less
lessc sty^.less
Rack
Rack-, Rails 3,
: gem- rack-less.
gem- Gemfile:
gem "rack-less"
application.rb:
require "rack/less"
config.middleware.use "Rack::Less"
Less, //stylesheets,
. ,
rack-less production.rb:
Rack::Less.configure do |config|
config.cache * true
config.compress = :yui
end
JavaScript
, , Ruby-, , ,
: Xess.js, Less,
JavaScript. Less
JavaScript- less.js,
:
<link rel="stylesheet/less" href="main.less" type="text/css">
<script src="less.js" type="text/javascript"x/script>
Less.js 40 Ruby- .
Less,
. Node.js,
:
node bin/lessc style.less
Less.app
, Mac OS X,
Less. Less.js ,
Less?
261
, . . Less
CSS (. .1).
f i i 1
fiB MyWbrte
| Pul Thurro<
John Cnitar
* Zulu
A O utp u t
/Th* Yankces.lss
SuckJess
OwtjMft
/* Co*
CSS3
CSS2.1 ,
,
JavaScript-. CSS3
-
, .
- Photoshop
CSS3 HTML5. ,
, PSD- .
,
HTML- ,
.
: ?
, CSS3 ?
.
CSSS-, . , Chrome
,
, IE7 , ,
, .
Internet Explorer 6,
, Facebook, Amazon Google,
IE6
.
IE, Firefox, Chrome Safari. Chrome Safari
JavaScript,
WebKit.
, -
Chrome WebKit, .
Microsoft IE9. ,
,
, ,
CSS3.
263
,
.
CSS3
. , ,
CSS3-cm ra . ,
CSS3 Firefox Safari : Firefox
-moz-linear-gradient, a Safari (WebKit) -webkit-gradient;
, .
:
O
O
- ,
. ,
CSSS-,
, :
#prefix-example {
-moz-box-shadow: 0 5 #FFF;
-webkit-box-shadow: 0 5px #FFF;
box-shadow: 0 5px #FFF;
CSS3 ,
- (alpha transparency).
1 x 1 ,
.
Rgb- ,
, , .
- Safari
, Styles.
264
. CSS3
#FFF, :
#rgb-example {
//
(, , );
color: rgb(255, 255, 255);
>
h sl-, (hue),
(saturation) (lightness).
HSL :
Hue
; 0 ( 360) , 120 , 240
. .
Saturation
; 100% .
Lightness
; 0% () , 100% (
) , 50% .
rgb hsl - ,
, , rgba hsla. - 0 () 1 ().
#alpha-example {
background: hsla(324, 100%, 50%, .5);
border: lem solid rgba(0, 0, 0, .3);
color: rgba(255, 255, 255, .8);
>
:
Firefox:
Chrome:
Opera:
Safari:
IE:
Opera:
CSS2.1 ,
, JavaScript-.
borderradius. padding margin,
265
, , ,
,
. ,
:
border-radius: 20;
// ,
border-radius: 20 20;
// , , ,
border-radius: 20 20 20 20;
Firefox:
Chrome:
Safari: -webkitIE >= 9.0:
Opera:
CSS3 ,
. CSS3
box-shadow, .
, ,
.
box-shadow : ,
, ,
. inset
, ,
. ,
, :
// , , ,
box-shadow: 10 5 15 #000;
//
box-shadow: 10 5 15 #000 inset;
// , , ,
// ,
box-shadow: 10 5 15 15 #000;
//
box-shadow: 0 lpx lpx #FFF inset, 5px 5px 10px #000;
266
. CSS3
,
.
box-shadow
.
; :
#shadow-example {
-moz-box-shadow: 0 lpx lpx #FFF inset;
-webkit-box-shadow: 0 lpx lpx #FFF inset;
box-shadow: 0 lpx lpx #FFF inset;
}
:
Firefox:
Chrome: -webkitSafari: -webkitIE >= 9.0:
Opera:
CSS3
, . CSS3
text-shadow.
, ,
:
// , ,
text-shadow: lpx lpx #FFF;
// , , ,
text-shadow: lpx lpx . rgba(255, 255, 255, .8);
(box-shadow),
.
.
, . ,
, .
:
Firefox:
Chrome:
Safari:
IE:
Opera:
267
.
, ,
.
CSS3 ,
.
CSS-,
, .
lineargradient , :
linear-gradient(#CCC, #DDD, white)
,
, :
//
linear-gradient(left, #, #DDD, #FFF);
//
linear-gradient(-45deg , # , #FFF)
,
.
:
linear-gradient(white , #DDD 20% , black)
:
radial-gradient( rgba(255, 255, 255, .8) , transparent )
Safari .
,
:
// -webkit-gradient(<Twi>, <> [, <>]?, <> [, <>]?
// [, <>]*);
-webkit-gradient(linear, left top, left bottom,
from(#FFF), color-stop(10%, #DDD), to(#CCC));
CSS- ,
:
268
. CSS3
:
#gradient-example {
/* */
background: #FFF;
/* Chrome < 10, Safari < 5.1 */
background: -webkit-gradient(linear, left top, left bottom,
from(#FFF), to(#CCC));
/* Chrome >= 10, Safari >= 5.1 */
background: -webkit-linear-gradient(#FFF, #CCC);
/* Firefox >= 3.6 */
background: -moz-linear-gradient(#FFF, #CCC);
/* Opera >* 11.1 */
background: -o-linear-gradient(#FFF, #CCC);
/* IE >= 10 */
background: -ms-linear-gradient(#FFF, #CCC);
/* */
background: linear-gradient(#FFF, #CCC);
}
!
, Less Sass, .
CSS3 , . ,
, . .
. CSS3
, :
background: url(snowflakes.png) top repeat-x,
url(chimney.png) bottom no-repeat,
-moz-linear-gradient(white, #CCC),
#CCC;
Firefox:
Chrome:
Safari:
IE >* 9.0:
Opera:
CSS3 :
269
:first-child
:last-child
:only-child
.target
, URL
:checked
,
.
N-
: nth -child
n- . ,
:
#example:nth-child( ) { / * . . . * / }
:
/* */
#example:nth-child( 2 )
{/*...*/}
#example:nth-child( even ) { / * . . . * / }
/* */
#example:nth-child( 2n+l ) { / * . . . * / }
#example:nth-child( odd ) { / * . . . * / }
:
/* */
#example:nth-last-child( 1 )
:first-child :nth-child(l),
a :last-child :nth-last-child(l).
,
,
(>):
/* div-, */
#example > div { }
270
. CSS3
,
: not, .
, :not (hi + ), :
/* , , class
"current" */
#example > *:not(.current) {
display: none
>
:
Firefox:
Chrome:
Safari:
IE >= 9.0:
Opera:
CSS3 ,
. ,
.
(s) (ms):
/* , , () */
transition: 1.5s opacity ease-out
/* */
transition: 2s opacity , .5s height ease-in
transition: .5s height , .5s .5s width
(,
), .
(timing functions):
linear
ease-in
ease-out
ease-in-out
, ,
, , .
271
#transition-example {
position: absolute;
>
Safari Chrome, ,
WebKitTransitionEvent. Firefox
transitionend. , -
:
.
,
(, Safari) :
#transition-example {
width: 50;
height: 50;
background: red;
-webkit-transition: 2s background ease-in-out;
-moz-transition: 2s background ease-in-out;
-o-transition: 2s background ease-in-out;
transition: 2s background ease-in-out;
>
#transition-example:hover {
background: blue;
>
, - . ,
height:0 height:auto.
:
border-image
. URL ,
.
,
272
. CSS3
.
round ( ), repeat
() stretch ():
border-image: url(border.png) 14 14 14 14 round round;
border-image: url(border.png) 14 14 14 14 stretch stretch;
:
Firefox: -moz Chrome: -webkit Safari: -webkit IE:
Opera: --
- 100% ,
?
CSS ,
. ,
100%, , ,
.
box-sizing border-box
content-box,
, , , :
.border-box {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
>
,
, ,
, Internet Explorer 8.
CSS3, 2-,
, , .
, 30 :
transform: rotate( -30deg );
273
,
:
transform: skew( 30deg , -10deg );
translateX translated
translateX(30px);
translateY(50opx);
. 1:
transform: scale(1.2);
, :
trartsform: rotate(30deg) skewX(30deg);
CSS3 (flexible box model),
.
CSS ,
GUI-, Adobe Flex. ,
flo ats.
, .
:
.hbox {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
-webkit-box-pack: left;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
-moz-box-pack: left;
&
274
. CSS3
.vbox {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-align: stretch;
>
display -webkit-box -moz-box,
.
,
. ,
box-flex.
box-flex 0, ,
, 1 , ,
, . ,
flex 0,
flex 1:
#sidebar {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
width: 200px;
>
#content {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
>
:
@font-face
. ,
, .
275'
TrueType .
,
, .
@font-face , ,
font-family URL- :
@font-face {
font-family: "Bitstream Vera Serif Bold";
src: url("/fonts/VeraSeBd.ttf");
>
, :
#font-example {
font-family: "Bitstream Vera Serif Bold";
>
. , ,
, ,
. -
, .
:
Firefox:
Chrome:
Safari:
IE >= 9:
Opera:
CSS
. , CSS3,
.
,
, , CSS-,
. CSS- , -
, .
, CSS2.1,
, rgba:
#example-gd {
background: white;
background: rgba(255, 255, 255, .75);
276
. CSS3
? .
,
, .
, ,
CSS3 :
#example-gd {
background: #FFF;
background: -webkit-gradient(linear, left top, left bottom,
from(#FFF), to(#CCC));
background: -webkit-linear-gradient(#FFF, #CCC);
background: -moz-linear-gradient(#FFF, #CCC);
background: linear-gradient(#FFF, #CCC);
>
M odernizr
Modernizr (http://www.modemizr.com)
CSS3-CB0iicTB,
:
multiplebgs div {
/* ,
*/
.no-multiplebgs di vp {
/*
, */
Modernizr :
@font-face
rgba()
hsla()
border-image:
border-radius:
box-shadow:
text-shadow:
(Multiple backgrounds)
(Flexible box model)
CSS-
CSS-
CSS 2-
CSS-
Modernizr
(http://www.modemizr.com).
277
Modemizr , JavaScript
<html>-Tery c la ss- no-js:
<script src= "/jav ascrip ts/m o d ern izr.js"x /scrip t>
<html class="no-js">
Modernizr <html>-Tery,
:
/*
*/
.no-flexbox #content {
float: left;
>
- :
X-UA-Compatible: chrome=l
, GCF- -
. GCF ,
, IE (
).
GCF,
.
JavaScript- GCF:
<script src="http://jax.googleapis.com/ajax/libs/chrome-f/1/
CFInstall.min.js"
CFInstall:
<script>
jQuery(function(){
CFInstall.check({
mode: "overlay",
;
;
</script>
278
. CSS3
CFInstall :
mode
,
node
ID ,
GCF User-Agent
chromef rame. URL- GCF
Internet Explorer . ,
GCF cookie-, SSL-, ,
, .
(http://www.chromium.org/developers/how-tos/chrome-framegetting-started).
, Holla.
.
sidebar main:
<body>
<header id="title">
<hl>Holla</hl>
</header>
<div id="content">
<div class="sidebar"x/div>
<div class="main"x/div>
</div>
</body>
(body):
body, html {
margin: 0;
padding: 0;
>
body {
font-family: Helvetica, Arial, "MS Trebuchet", sans-serif;
font-size: 16px;
279
color: #363636;
background: #D2D2D2;
line-height: 1.2em;
>
h-:
hi, h2 {
font-weight: bold;
text-shadow: 0 lpx lpx #ffffff;
>
hi {
font-size: 21pt;
color: #404040;
>
h2 {
font-size: 24pt;
color: #404040;
margin: lem 0 0.7em 0;
}
h3 {
font-size: 15px;
color: #404040;
text-shadow: 0 lpx lpx #ffffff;
>
.
CSS3,
, :
#title {
border-bottom: lpx solid #535353;
overflow: hidden;
height: 50px;
line-height: 50px;
background: #575859;
background: -webkit-gradient(linear, left top, left bottom,
from(#575859), to(#272425));
background: -webkit-linear-gradient(top, #575859, #272425);
background: -moz-linear-gradient(top, #575859, #272425);
background: linear-gradient(top, #575859, #272425);
>
#title hi {
color: #ffffff;
text-shadow: 0 lpx lpx #000000;
margin: 0 10px;
>
280
. CSS3
, , . .1,
.
CSS3 Example
* J
J + l file:///Users/Alex/book/assets/css3 html
ifC fr Googte
li
H olla
I
|
. .1. CSS
div- #content,
. ,
, .
,
(flexible box):
#content {
overflow: hidden;
/*
div- ,
.
*/
position: absolute;
left: 0;
right: 0;
top: 50px;
bottom: 0;
/* */
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
-webkit-box-pack: left;
display: -moz-box;
281
-moz-box-orient: horizontal;
-moz-box-align: stretch;
-moz-box-pack: left;
>
.sidebar.
, box-flex 0:
#content .sidebar {
background: #EDEDED;
width: 200px;
/*
,
*/
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
>
.sidebar .
, h3. ,
CSS3, -
. ,
Less-:
#content .sidebar ul {
margin: 0;
padding: 0;
list-style: none;
}
#content .sidebar ul li {
display: block;
padding: 10px 10px 7px 20px;
border-bottom: lpx solid #cdcdcc;
cursor: pointer;
-moz-box-shadow: 0 lpx lpx #fcfcfc;
-webkit-box-shadow: 0 lpx lpx #fcfcfc;
box-shadow: 0 lpx lpx #fcfcfc;
>
#content .sidebar ul li.active {
color: #ffffff;
text-shadow: 0 lpx lpx #46677f;
-webkit-box-shadow: none;
-moz-box-shadow: none;
background: #7bb5db;
background: -webkit-gradient(linear, left top, left bottom,
from(#7bb5db), to(#4775b8));
282
. CSS3
>
HTML- :
<div class=,,sidebar,,>
<h3>Channels</h3>
<ul>
<li class="active">Developers</li>
<li>Sales</li>
<li>Marketing</li>
<li>Ops</li>
</ul>
</div>
>
. . .2,
, .
CSS3 Example
[ < j
j + J * file:///Users/A!ex/book/assets/css3.html
O r Coogle
H o lla
Channels
Sales
Marketing
Ops
. .2.
283
, CSS3
- .
Less-. :
#content .sidebar h3 {
.vbg-gradient(#FFF, #DEDFE0);
.box-shadow(0, -5px, 10px, #E4E4E4);
>
Holla.
- JavaScript
.
.
.
.
.
.
.