mizugumo 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +16 -13
- data/lib/generators/mizugumo/install/templates/javascripts/jquery.ninja_script.js +157 -21
- data/lib/generators/mizugumo/install/templates/stylesheets/mizugumo.css +9 -1
- data/lib/generators/mizugumo/install/templates/stylesheets/sass/mizugumo.sass +9 -1
- metadata +5 -8
- data/doc/NAME.haml +0 -14
- data/doc/PURPOSE.haml +0 -71
- data/doc/making_generators.txt +0 -45
data/README.rdoc
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
Mizugumo is a gem designed to provide Rails with JavaScript and AJAX behavior that is:
|
4
4
|
* absolutely seamless
|
5
5
|
* completely unobtrusive - no markup whatsoever in your HTML and
|
6
|
-
* gracefully-degrading: defaults to fully functional and
|
7
|
-
sensible page-reload behavior when javascript is not available.
|
6
|
+
* gracefully-degrading: defaults to fully functional and sensible page-reload behavior when JavaScript is not available.
|
8
7
|
|
9
8
|
See a demo running at:
|
10
9
|
http://mizugumo-demo.lrdesign.com
|
@@ -16,18 +15,21 @@ Mizugumo uses NinjaScript by Judson Lester to provide unobtrusive JS behaviors.
|
|
16
15
|
|
17
16
|
== WARNINGS
|
18
17
|
|
19
|
-
In the current (early release) version, Mizugumo and NinjaScript have some limitations.
|
18
|
+
In the current (early release) version, Mizugumo and NinjaScript have some limitations.
|
19
|
+
Notably, in this version they will clobber the normal rails.js and prevent its behaviors from
|
20
20
|
working. The installer will copy a jQuery-compatible version of rails.js that you should
|
21
|
-
use instead if you depend on Rails' default (semi-obtrusive) approaches to AJAX,
|
21
|
+
use instead if you depend on Rails' default (semi-obtrusive) approaches to AJAX,
|
22
|
+
link_to with :confirm =>'Are you sure?' and similar things working.
|
22
23
|
|
23
|
-
In addition, NinjaScript currently requires jQuery 1.4.2. It is NOT compatible with the current version of jQuery, 1.
|
24
|
+
In addition, NinjaScript currently requires jQuery 1.4.2. It is NOT compatible with the current version of jQuery, 1.5.
|
25
|
+
We are eagerly working on a fix.
|
24
26
|
|
25
27
|
== Features
|
26
28
|
|
27
29
|
Mizugumo's main features are:
|
28
30
|
* Easy tools for installing NinjaScript
|
29
|
-
* A
|
30
|
-
* A default NinjaScript behavior (in your application.js) that automatically converts those forms back into the expected links when
|
31
|
+
* A Rails helper to automatically output <form>s instead of <a> tags when link_to is called with a :method other than GET. This allows these links to function as intended for users who lack JavaScript.
|
32
|
+
* A default NinjaScript behavior (in your application.js) that automatically converts those forms back into the expected links when JavaScript is available, resulting in transparent usability for JS users.
|
31
33
|
* A scaffold generator that builds both both AJAX behavior and standard "page-reload" behavior in the controller and view and adds NinjaScript behaviors to application.js to activate AJAX. Out of the box, your scaffolded controller will function as an AJAX controller when JS is available but will degrade properly when JS is not available.
|
32
34
|
|
33
35
|
== Installing
|
@@ -41,7 +43,7 @@ First, add Mizugumo to your gemfile:
|
|
41
43
|
|
42
44
|
Second, install Mizugumo files:
|
43
45
|
|
44
|
-
|
46
|
+
rails generate mizugumo:install
|
45
47
|
|
46
48
|
Third, link to jQuery and NinjaScript in your application layout, plus the optional ninjascript.css. If using ERB, add these lines:
|
47
49
|
|
@@ -66,7 +68,8 @@ side-by-side with Prototype.
|
|
66
68
|
Rails' concept of REST runs headlong into the desire to make a site degrade
|
67
69
|
gracefully. Specifically, the link_to() helper, when passed a method other
|
68
70
|
than 'get', outputs a link with a data-method attribute that won't work
|
69
|
-
when JS is absent. To wit: link_to('Delete Item', @item, :method => 'delete')
|
71
|
+
when JS is absent. To wit: link_to('Delete Item', @item, :method => 'delete')
|
72
|
+
in Rails outputs this:
|
70
73
|
|
71
74
|
<a href='/items/1' data-method='delete'>Delete Item</a>
|
72
75
|
|
@@ -110,7 +113,8 @@ complex GET links.
|
|
110
113
|
|
111
114
|
== Scaffold generator
|
112
115
|
|
113
|
-
Mizugumo ships with a scaffold generator that builds out-of-the-box AJAX/UJS scaffolds that degrade
|
116
|
+
Mizugumo ships with a scaffold generator that builds out-of-the-box AJAX/UJS scaffolds that degrade
|
117
|
+
gracefully in the absence of JavaScript. To use it, add this to config/application.rb:
|
114
118
|
|
115
119
|
For ERB views:
|
116
120
|
|
@@ -119,7 +123,7 @@ For ERB views:
|
|
119
123
|
g.template_engine 'mizugumo:erb'
|
120
124
|
end
|
121
125
|
|
122
|
-
For
|
126
|
+
For Haml views:
|
123
127
|
|
124
128
|
config.generators do |g|
|
125
129
|
g.scaffold_controller 'mizugumo:scaffold_controller'
|
@@ -130,7 +134,6 @@ For HAML views:
|
|
130
134
|
== Contributing to Mizugumo
|
131
135
|
|
132
136
|
* Install MizugumoDemo and make sure that its tests still pass with your version of Mizugumo!
|
133
|
-
|
134
137
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
135
138
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
136
139
|
* Fork the project
|
@@ -145,7 +148,7 @@ Use the GitHub issue tracker.
|
|
145
148
|
|
146
149
|
== Copyright
|
147
150
|
|
148
|
-
Copyright (c) 2011 Evan Dorn and Logical Reality
|
151
|
+
Copyright (c) 2011 Evan Dorn and Logical Reality Design. See LICENSE.txt for
|
149
152
|
further details.
|
150
153
|
|
151
154
|
Web Development by Logical Reality Design: http://LRDesign.com
|
@@ -1,7 +1,10 @@
|
|
1
1
|
/*
|
2
|
-
* NinjaScript - 0.8.
|
3
|
-
* written and copyright 2010-2011 Judson Lester and Logical Reality Design
|
2
|
+
* NinjaScript - 0.8.2
|
3
|
+
* written by and copyright 2010-2011 Judson Lester and Logical Reality Design
|
4
4
|
* Licensed under the MIT license
|
5
|
+
* 2011-02-04
|
6
|
+
*
|
7
|
+
* Those new to this source should skim down to standardBehaviors
|
5
8
|
*/
|
6
9
|
Ninja = (function() {
|
7
10
|
function log(message) {
|
@@ -108,6 +111,9 @@ Ninja = (function() {
|
|
108
111
|
return jQuery.extend(left, right)
|
109
112
|
},
|
110
113
|
ensureDefaults: function(config, defaults) {
|
114
|
+
if(!config instanceof Object) {
|
115
|
+
config = {}
|
116
|
+
}
|
111
117
|
return this.enrich(defaults, config)
|
112
118
|
},
|
113
119
|
//DOM and Events
|
@@ -191,6 +197,9 @@ Ninja = (function() {
|
|
191
197
|
return "GET"
|
192
198
|
},
|
193
199
|
//Ninjascript utils
|
200
|
+
cantTransform: function() {
|
201
|
+
throw new TransformFailedException
|
202
|
+
},
|
194
203
|
applyBehaviors: function(element, behaviors) {
|
195
204
|
this.getRootCollection().apply(element, behaviors)
|
196
205
|
},
|
@@ -221,7 +230,7 @@ Ninja = (function() {
|
|
221
230
|
},
|
222
231
|
busyOverlay: function(elem) {
|
223
232
|
var overlay = this.overlay(elem)
|
224
|
-
overlay.set.addClass("
|
233
|
+
overlay.set.addClass("ninja_busy")
|
225
234
|
overlay.laziness = this.ninja.config.busyLaziness
|
226
235
|
return overlay
|
227
236
|
},
|
@@ -390,7 +399,7 @@ Ninja = (function() {
|
|
390
399
|
for(var eventName in behavior.eventHandlers) {
|
391
400
|
var oldHandler = this.handlers[eventName]
|
392
401
|
if(typeof oldHandler == "undefined") {
|
393
|
-
oldHandler = function(){}
|
402
|
+
oldHandler = function(){return true}
|
394
403
|
}
|
395
404
|
this.handlers[eventName] = behavior.buildHandler(context, eventName, oldHandler)
|
396
405
|
}
|
@@ -407,6 +416,7 @@ Ninja = (function() {
|
|
407
416
|
|
408
417
|
function RootContext() {
|
409
418
|
this.stashedElements = []
|
419
|
+
this.eventHandlerSet = {}
|
410
420
|
}
|
411
421
|
|
412
422
|
RootContext.prototype = Ninja.tools.enrich(
|
@@ -424,10 +434,16 @@ Ninja = (function() {
|
|
424
434
|
var formDiv = Ninja.tools.hiddenDiv()
|
425
435
|
forEach(this.stashedElements, function(element) {
|
426
436
|
var elem = jQuery(element)
|
427
|
-
elem.data("ninja-visited",
|
437
|
+
elem.data("ninja-visited", this)
|
428
438
|
jQuery(formDiv).append(elem)
|
429
439
|
elem.trigger(event)
|
430
440
|
})
|
441
|
+
},
|
442
|
+
unbindHandlers: function() {
|
443
|
+
var el = jQuery(this.element)
|
444
|
+
for(eventName in this.eventHandlerSet) {
|
445
|
+
el.unbind(eventName, this.eventHandlerSet[eventName])
|
446
|
+
}
|
431
447
|
}
|
432
448
|
})
|
433
449
|
|
@@ -524,10 +540,13 @@ Ninja = (function() {
|
|
524
540
|
}
|
525
541
|
},
|
526
542
|
applyBehaviorsTo: function(element, behaviors) {
|
543
|
+
return this.applyBehaviorsInContext(new RootContext, element, behaviors)
|
544
|
+
},
|
545
|
+
applyBehaviorsInContext: function(context, element, behaviors) {
|
527
546
|
var curContext,
|
528
|
-
context = new RootContext,
|
529
547
|
applyList = [],
|
530
548
|
scribe = new EventScribe
|
549
|
+
Ninja.tools.enrich(scribe.handlers, context.eventHandlerSet)
|
531
550
|
|
532
551
|
behaviors = behaviors.sort(function(left, right) {
|
533
552
|
if(left.priority != right.priority) {
|
@@ -570,9 +589,10 @@ Ninja = (function() {
|
|
570
589
|
}
|
571
590
|
}
|
572
591
|
)
|
573
|
-
jQuery(element).data("ninja-visited",
|
592
|
+
jQuery(element).data("ninja-visited", context)
|
574
593
|
|
575
594
|
scribe.applyEventHandlers(element)
|
595
|
+
Ninja.tools.enrich(context.eventHandlerSet, scribe.handlers)
|
576
596
|
|
577
597
|
this.fireMutationEvent()
|
578
598
|
|
@@ -598,7 +618,8 @@ Ninja = (function() {
|
|
598
618
|
apply: function(element, startBehaviors, selectorIndex) {
|
599
619
|
var applicableBehaviors = [], len = this.selectors.length
|
600
620
|
this.collectBehaviors(element, applicableBehaviors, startBehaviors)
|
601
|
-
|
621
|
+
var context = jQuery(element).data('ninja-visited')
|
622
|
+
if (!context) {
|
602
623
|
if(typeof selectorIndex == "undefined") {
|
603
624
|
selectorIndex = 0
|
604
625
|
}
|
@@ -607,8 +628,12 @@ Ninja = (function() {
|
|
607
628
|
this.collectBehaviors(element, applicableBehaviors, this.behaviors[this.selectors[j]])
|
608
629
|
}
|
609
630
|
}
|
610
|
-
}
|
611
631
|
this.applyBehaviorsTo(element, applicableBehaviors)
|
632
|
+
}
|
633
|
+
else {
|
634
|
+
context.unbindHandlers()
|
635
|
+
this.applyBehaviorsInContext(context, element, applicableBehaviors)
|
636
|
+
}
|
612
637
|
},
|
613
638
|
applyAll: function(root){
|
614
639
|
var len = this.selectors.length
|
@@ -694,7 +719,7 @@ Ninja = (function() {
|
|
694
719
|
var context = this.inContext({})
|
695
720
|
|
696
721
|
elem = this.applyTransform(context, elem)
|
697
|
-
jQuery(elem).data("ninja-visited",
|
722
|
+
jQuery(elem).data("ninja-visited", context)
|
698
723
|
|
699
724
|
this.applyEventHandlers(context, elem)
|
700
725
|
|
@@ -851,9 +876,11 @@ Ninja = (function() {
|
|
851
876
|
//})
|
852
877
|
//
|
853
878
|
submitsAsAjaxLink: function(configs) {
|
854
|
-
|
855
|
-
|
856
|
-
|
879
|
+
configs = Ninja.tools.ensureDefaults(configs,
|
880
|
+
{ busyElement: function(elem) {
|
881
|
+
return $(elem).parents('address,blockquote,body,dd,div,p,dl,dt,table,form,ol,ul,tr')[0]
|
882
|
+
}})
|
883
|
+
|
857
884
|
return new ninja.does({
|
858
885
|
priority: 10,
|
859
886
|
helpers: {
|
@@ -890,9 +917,9 @@ Ninja = (function() {
|
|
890
917
|
//})
|
891
918
|
//
|
892
919
|
submitsAsAjaxForm: function(configs) {
|
893
|
-
|
894
|
-
|
895
|
-
|
920
|
+
configs = Ninja.tools.ensureDefaults(configs,
|
921
|
+
{ busyElement: undefined })
|
922
|
+
|
896
923
|
return new ninja.does({
|
897
924
|
priority: 20,
|
898
925
|
helpers: {
|
@@ -929,10 +956,6 @@ Ninja = (function() {
|
|
929
956
|
// busyElement: function(elem) { jQuery("#user-notification") }
|
930
957
|
//})
|
931
958
|
becomesAjaxLink: function(configs) {
|
932
|
-
if(!(configs instanceof Object)) {
|
933
|
-
configs = { busyElement: undefined }
|
934
|
-
}
|
935
|
-
|
936
959
|
configs = Ninja.tools.ensureDefaults(configs, {
|
937
960
|
busyElement: undefined,
|
938
961
|
retainAttributes: ["id", "class", "lang", "dir", "title", "data-.*"]
|
@@ -970,6 +993,7 @@ Ninja = (function() {
|
|
970
993
|
}
|
971
994
|
else {
|
972
995
|
log("Couldn't find a submit input in form");
|
996
|
+
this.cantTransform()
|
973
997
|
}
|
974
998
|
|
975
999
|
var link = jQuery("<a rel='nofollow' href='#'>" + linkText + "</a>")
|
@@ -988,7 +1012,7 @@ Ninja = (function() {
|
|
988
1012
|
|
989
1013
|
//Use for elements that should be transient. For instance, the default
|
990
1014
|
//behavior of failed AJAX calls is to insert a message into a
|
991
|
-
//div#messages with a "flash" class. You can use this behavior to
|
1015
|
+
//div#messages with a "flash" class. You can use this behavior to have
|
992
1016
|
//those disappear after a few seconds.
|
993
1017
|
//
|
994
1018
|
//Configs:
|
@@ -1021,6 +1045,118 @@ Ninja = (function() {
|
|
1021
1045
|
Ninja.packageBehaviors(standardBehaviors)
|
1022
1046
|
})();
|
1023
1047
|
|
1048
|
+
(function($){
|
1049
|
+
function uiBehaviors(ninja){
|
1050
|
+
function watermarkedSubmitter(inputBehavior) {
|
1051
|
+
return new ninja.does({
|
1052
|
+
priority: 1000,
|
1053
|
+
submit: [function(event, el, oldHandler) {
|
1054
|
+
inputBehavior.prepareForSubmit()
|
1055
|
+
oldHandler(event)
|
1056
|
+
}, "andDoDefault"]
|
1057
|
+
})
|
1058
|
+
}
|
1059
|
+
function isWatermarkedPassword(configs) {
|
1060
|
+
return new ninja.does({
|
1061
|
+
priority: 1000,
|
1062
|
+
helpers: {
|
1063
|
+
prepareForSubmit: function() {
|
1064
|
+
if($(this.element).hasClass('ninja_watermarked')) {
|
1065
|
+
$(this.element).val('')
|
1066
|
+
}
|
1067
|
+
},
|
1068
|
+
},
|
1069
|
+
transform: function(element) {
|
1070
|
+
var label = $('label[for=' + $(element)[0].id + ']')
|
1071
|
+
if(label.length == 0) {
|
1072
|
+
this.cantTransform()
|
1073
|
+
}
|
1074
|
+
label.addClass('ninja_watermarked')
|
1075
|
+
this.watermarkText = label.text()
|
1076
|
+
|
1077
|
+
var el = $(element)
|
1078
|
+
el.addClass('ninja_watermarked')
|
1079
|
+
el.val(this.watermarkText)
|
1080
|
+
el.attr("type", "text")
|
1081
|
+
|
1082
|
+
this.applyBehaviors(el.parents('form')[0], [watermarkedSubmitter(this)])
|
1083
|
+
|
1084
|
+
return element
|
1085
|
+
},
|
1086
|
+
events: {
|
1087
|
+
focus: function(event) {
|
1088
|
+
$(this.element).removeClass('ninja_watermarked').val('').attr("type", "password")
|
1089
|
+
},
|
1090
|
+
blur: function(event) {
|
1091
|
+
if($(this.element).val() == '') {
|
1092
|
+
$(this.element).addClass('ninja_watermarked').val(this.watermarkText).attr("type", "text")
|
1093
|
+
}
|
1094
|
+
}
|
1095
|
+
}
|
1096
|
+
})
|
1097
|
+
}
|
1098
|
+
|
1099
|
+
function isWatermarkedText(configs) {
|
1100
|
+
return new ninja.does({
|
1101
|
+
priority: 1000,
|
1102
|
+
helpers: {
|
1103
|
+
prepareForSubmit: function() {
|
1104
|
+
if($(this.element).hasClass('ninja_watermarked')) {
|
1105
|
+
$(this.element).val('')
|
1106
|
+
}
|
1107
|
+
},
|
1108
|
+
},
|
1109
|
+
transform: function(element) {
|
1110
|
+
var label = $('label[for=' + $(element)[0].id + ']')
|
1111
|
+
if(label.length == 0) {
|
1112
|
+
this.cantTransform()
|
1113
|
+
}
|
1114
|
+
label.addClass('ninja_watermarked')
|
1115
|
+
this.watermarkText = label.text()
|
1116
|
+
var el = $(element)
|
1117
|
+
el.addClass('ninja_watermarked')
|
1118
|
+
el.val(this.watermarkText)
|
1119
|
+
|
1120
|
+
this.applyBehaviors(el.parents('form')[0], [watermarkedSubmitter(this)])
|
1121
|
+
|
1122
|
+
return element
|
1123
|
+
},
|
1124
|
+
events: {
|
1125
|
+
focus: function(event) {
|
1126
|
+
$(this.element).removeClass('ninja_watermarked').val('')
|
1127
|
+
},
|
1128
|
+
blur: function(event) {
|
1129
|
+
if($(this.element).val() == '') {
|
1130
|
+
$(this.element).addClass('ninja_watermarked').val(this.watermarkText)
|
1131
|
+
}
|
1132
|
+
}
|
1133
|
+
}
|
1134
|
+
})
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
return {
|
1138
|
+
isWatermarked: function(configs) {
|
1139
|
+
return new ninja.chooses(function(meta) {
|
1140
|
+
meta.asText = isWatermarkedText(configs)
|
1141
|
+
meta.asPassword = isWatermarkedPassword(configs)
|
1142
|
+
},
|
1143
|
+
function(elem) {
|
1144
|
+
if($(elem).is("input[type=text],textarea")) {
|
1145
|
+
return this.asText
|
1146
|
+
}
|
1147
|
+
//Seems IE has a thing about changing input types...
|
1148
|
+
//We'll get back to this one
|
1149
|
+
// else if($(elem).is("input[type=password]")){
|
1150
|
+
// return this.asPassword
|
1151
|
+
// }
|
1152
|
+
})
|
1153
|
+
}
|
1154
|
+
}
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
Ninja.packageBehaviors(uiBehaviors)
|
1158
|
+
})(jQuery);
|
1159
|
+
|
1024
1160
|
|
1025
1161
|
//This exists to carry over interfaces from earlier versions of Ninjascript. Likely, it will be removed from future versions of NinjaScript
|
1026
1162
|
( function($) {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.
|
1
|
+
.ninja_busy {
|
2
2
|
background-color: white;
|
3
3
|
background-image: url("/images/ui/spinner.gif");
|
4
4
|
background-position: center center;
|
@@ -6,6 +6,14 @@
|
|
6
6
|
opacity: 0.75;
|
7
7
|
filter: "progid:DXImageTransform.Microsoft.Alpha(opacity=75)"; }
|
8
8
|
|
9
|
+
input.ninja_watermarked, textarea.ninja_watermarked {
|
10
|
+
color: #666688;
|
11
|
+
font-style: italic;
|
12
|
+
opacity: 0.75; }
|
13
|
+
|
14
|
+
label.ninja_watermarked {
|
15
|
+
display: none; }
|
16
|
+
|
9
17
|
form {
|
10
18
|
margin: 1em 0;
|
11
19
|
padding: 1em;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.
|
1
|
+
.ninja_busy
|
2
2
|
:background-color white
|
3
3
|
:background-image url("/images/ui/spinner.gif")
|
4
4
|
:background-position center center
|
@@ -6,6 +6,14 @@
|
|
6
6
|
:opacity 0.75
|
7
7
|
:filter 'progid:DXImageTransform.Microsoft.Alpha(opacity=75)'
|
8
8
|
|
9
|
+
input.ninja_watermarked, textarea.ninja_watermarked
|
10
|
+
:color #668
|
11
|
+
:font-style italic
|
12
|
+
:opacity 0.75
|
13
|
+
|
14
|
+
label.ninja_watermarked
|
15
|
+
:display none
|
16
|
+
|
9
17
|
form
|
10
18
|
:margin 1em 0
|
11
19
|
:padding 1em
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mizugumo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Evan Dorn
|
@@ -127,9 +127,6 @@ files:
|
|
127
127
|
- lib/generators/rails/mizugumo/view_generator.rb
|
128
128
|
- lib/mizugumo.rb
|
129
129
|
- lib/mizugumo_link_helper.rb
|
130
|
-
- doc/making_generators.txt
|
131
|
-
- doc/NAME.haml
|
132
|
-
- doc/PURPOSE.haml
|
133
130
|
- spec/spec_helper.rb
|
134
131
|
has_rdoc: true
|
135
132
|
homepage: http://github.com/LRDesign/mizugumo
|
@@ -161,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
158
|
requirements: []
|
162
159
|
|
163
160
|
rubyforge_project:
|
164
|
-
rubygems_version: 1.
|
161
|
+
rubygems_version: 1.3.7
|
165
162
|
signing_key:
|
166
163
|
specification_version: 3
|
167
164
|
summary: Seamless UJS for Rails using NinjaScript
|
data/doc/NAME.haml
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
%h1 Mizugumo Ᾱ Name
|
2
|
-
|
3
|
-
%p
|
4
|
-
'mizugumo' is Japanese for 'water-spider'. Mythologically, however, it is the
|
5
|
-
name for special wooden shoes that ninja used to walk on water and thereby approach
|
6
|
-
targets via unexpected routes.
|
7
|
-
|
8
|
-
%p
|
9
|
-
As much as the Mythbusters were not impressed (real mizugumo likely did not work
|
10
|
-
for actual water-walking, and probably only worked as snowshoes to cross marshy
|
11
|
-
terrain), we thought it an appropriate name for an unobtrusive JS behavior library.
|
12
|
-
|
13
|
-
|
14
|
-
|
data/doc/PURPOSE.haml
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
%h1 Mizugumo Ᾱ Purpose
|
2
|
-
|
3
|
-
%p
|
4
|
-
Mizugumo exists to help Rails developers quickly build apps that are both AJAXy and that degrade
|
5
|
-
gracefully when JavaScript is absent. It uses NinjaScript to provide unobtrusive javascript
|
6
|
-
behaviors.
|
7
|
-
|
8
|
-
%h2 Graceful Degradation
|
9
|
-
|
10
|
-
%h3 Why we care
|
11
|
-
|
12
|
-
%p
|
13
|
-
Rails developers are notorious for making apps that do not degrade well when JS is unavailable,
|
14
|
-
especially if the app uses AJAX for some actions. It's hard to blame anyone - generally, adding
|
15
|
-
AJAX is a bit of a pain, and adding degradation requires duplicating a lot of development.
|
16
|
-
|
17
|
-
%p
|
18
|
-
Ideally, we should put the effort into graceful degradation because we can't count on JavaScript
|
19
|
-
in real-world conditions. Some situations we care about in which JavaScript might not be
|
20
|
-
available:
|
21
|
-
|
22
|
-
%ul
|
23
|
-
%li NoScript users and other security-conscious folk
|
24
|
-
%li Screen readers for vision-impaired users
|
25
|
-
%li Search engines and spiders, which should see as accurate
|
26
|
-
%li Automation tools
|
27
|
-
|
28
|
-
%h3 How to solve the problem
|
29
|
-
|
30
|
-
%p
|
31
|
-
Because the client sees the normal, JS-enabled behavior, and because we are all busy people,
|
32
|
-
Rails developers usually won't make their sites degrade gracefully until it becomes no harder
|
33
|
-
to build in graceful degradation than not to. Mizugumo aspires to this goal.
|
34
|
-
|
35
|
-
%p
|
36
|
-
Mizugumo replaces some of rails' default behavior that depend on JS with ones that work
|
37
|
-
in the absence of JS. Specifically, link_to with a :method option other than GET actually
|
38
|
-
outputs a <form>, not an <a href='foo'>. It then provides a default javascript behavior,
|
39
|
-
written in NinjaScript, to implicitly convert those forms
|
40
|
-
|
41
|
-
%p
|
42
|
-
Mizugumo also provides a scaffold tool that gives you an out-of-the box AJAX controller
|
43
|
-
in which all actions degrade perfectly in the absence of JS. From that scaffold, it becomes
|
44
|
-
much easier to build rich behaviors into your sites while maintaining JS-less functionality.
|
45
|
-
|
46
|
-
%h2 The Philosophy of Ninja-like Unobtrusiveness
|
47
|
-
|
48
|
-
%p
|
49
|
-
The goal of Mizugumo's JS engine, NinjaScript, is to make javascript super easy to use, and
|
50
|
-
reliable for the developer &%8212; no surprises.
|
51
|
-
|
52
|
-
%3 CSS is Great, JS Sucks
|
53
|
-
|
54
|
-
%p
|
55
|
-
We take for granted CSS's super-easy behavior: specify a selector and add a style. That style
|
56
|
-
will always apply to anything that matches that selector, even if the DOM is restructured. JavaScript
|
57
|
-
is not like this, however: if we use a library (say jQuery) to bind events to a selector, event
|
58
|
-
handlers will get bound to the DOM nodes that match that selector *now*, but elements that get added
|
59
|
-
later are out of luck. We can fix event handlers with event delegation methods, but that still
|
60
|
-
doesn't help us if what we want to do is transform elements. If I write a javascript block to
|
61
|
-
add rounded corners to a bunch of elements, or to add tooltip elements to a bunch of <li> nodes,
|
62
|
-
it will only make those changes to the elements that match at the time it is run.
|
63
|
-
|
64
|
-
%p
|
65
|
-
NinjaScripts aims to make JS as much like CSS as possible: specify a behavior once - including
|
66
|
-
transformations of the elements themselves - and those behaviors will always apply to all elements
|
67
|
-
even if the elements are added to the DOM later. So you can say "all divs with class .foo
|
68
|
-
get rounded corners" or "all forms matching .mizugomo_graceful_form get replaced with
|
69
|
-
links with the text matching the submit button text" and likewise not worry about when
|
70
|
-
and how said forms get added to the DOM.
|
71
|
-
|
data/doc/making_generators.txt
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
These are notes to myself to hopefully avoid this kind of suffering again.
|
2
|
-
|
3
|
-
I ran into some troubles (a few hours worth) trying to get the generators
|
4
|
-
working.
|
5
|
-
|
6
|
-
Rails wants to load generators from specific "namespaces", but parts of those
|
7
|
-
namespaces are automatically generated. In particular, when a generator is
|
8
|
-
invoked, it will generally be looked for with both a "base" and a "context".
|
9
|
-
Rails will use *one* of these two when looking, for example, it will look for:
|
10
|
-
|
11
|
-
<base>/<your generator> and <your generator>/<context>.
|
12
|
-
|
13
|
-
These are interdependent; particularly, setting up a scaffold_controller
|
14
|
-
generator will cause part of it's namespace to be assumed when looking for
|
15
|
-
the other items, like template_engine and test_framework.
|
16
|
-
|
17
|
-
For example, setting scaffold_generator to "ninja_helper:scaffold_controller"
|
18
|
-
will cause it to assume a base of "ninja_helper" and a context of "scaffold"
|
19
|
-
when you run "rails generate scaffold", which will make it look for your view
|
20
|
-
generator in "ninja_helper:erb" and "erb:scaffold", even if you don't explicitly
|
21
|
-
set template_engine to anything.
|
22
|
-
|
23
|
-
The fix for this was to specify the hooks for template_engine etc. with an
|
24
|
-
:in => :rails parameter which causes it to look in the rails namespace
|
25
|
-
(and thus retrieve the defaults) unless configs in application.rb specifically
|
26
|
-
override those generators.
|
27
|
-
|
28
|
-
Ultimately, Rails will generate eight acceptable namespaces for the
|
29
|
-
generator based on the requested name in config in application.rb
|
30
|
-
***It must live in one of those paths on the filesystem.*** However, the
|
31
|
-
actual ruby module namespace does not need to match (seems to be irrelevant).
|
32
|
-
The Rails 'namespace' can be massaged just by setting self.namespace(blah)
|
33
|
-
in the class, for example:
|
34
|
-
|
35
|
-
self.namespace("rails:ninja_helper:erb")
|
36
|
-
|
37
|
-
This lives in generators/rails/ninja_helper/erb_generator.rb, which is
|
38
|
-
one of the acceptable namespaces/paths for a beast with this config:
|
39
|
-
|
40
|
-
config.generators do |g|
|
41
|
-
g.template_engine 'ninja_helper:erb'
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
|