dolores-cml 0.4.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/cml.gemspec +5 -2
- data/lib/cml/converters/jsawesome.rb +2 -2
- data/lib/cml/parser.rb +21 -7
- data/lib/cml/tag.rb +10 -6
- data/spec/complex_spec.rb +13 -142
- data/spec/converters/jsawesome_spec.rb +5 -5
- data/spec/fixtures/html.cml +66 -140
- data/spec/fixtures/segfault.cml +1 -0
- data/spec/normalize_spec.rb +47 -0
- metadata +6 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.2
|
data/cml.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{cml}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.5.2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Chris Van Pelt"]
|
9
|
-
s.date = %q{2009-09-
|
9
|
+
s.date = %q{2009-09-07}
|
10
10
|
s.description = %q{CML let's you easily create form elements and custom interfaces for the CrowdFlower Croud Labor platform}
|
11
11
|
s.email = %q{vanpelt@doloreslabs.com}
|
12
12
|
s.extra_rdoc_files = [
|
@@ -44,7 +44,9 @@ Gem::Specification.new do |s|
|
|
44
44
|
"spec/fixtures/complex.cml",
|
45
45
|
"spec/fixtures/html.cml",
|
46
46
|
"spec/fixtures/invalid.cml",
|
47
|
+
"spec/fixtures/segfault.cml",
|
47
48
|
"spec/meta_spec.rb",
|
49
|
+
"spec/normalize_spec.rb",
|
48
50
|
"spec/sorta_match.rb",
|
49
51
|
"spec/spec_helper.rb",
|
50
52
|
"spec/tags/checkbox_spec.rb",
|
@@ -68,6 +70,7 @@ Gem::Specification.new do |s|
|
|
68
70
|
"spec/complex_spec.rb",
|
69
71
|
"spec/converters/jsawesome_spec.rb",
|
70
72
|
"spec/meta_spec.rb",
|
73
|
+
"spec/normalize_spec.rb",
|
71
74
|
"spec/sorta_match.rb",
|
72
75
|
"spec/spec_helper.rb",
|
73
76
|
"spec/tags/checkbox_spec.rb",
|
@@ -42,7 +42,7 @@ module CML
|
|
42
42
|
label = label(parts[0])
|
43
43
|
parts << key if label != key.capitalize.gsub(/_/,' ') || opts[:meta]
|
44
44
|
attrs = opts[:meta] ? [] : ["label=\"#{label}\""]
|
45
|
-
attrs << "name=\"#{parts[1]}\"" if parts[1]
|
45
|
+
attrs << "#{opts[:nested] ? "value" : "name"}=\"#{parts[1]}\"" if parts[1]
|
46
46
|
attrs << "checked=\"true\"" if val[1]
|
47
47
|
attrs << "validates=\"required\"" if @labels[key] && @labels[key]["required"]
|
48
48
|
opts.reject {|k,v| v.to_s.strip.length == 0 || k.is_a?(Symbol) }.each do |k,v|
|
@@ -81,7 +81,7 @@ module CML
|
|
81
81
|
parent = "select"
|
82
82
|
child = "option"
|
83
83
|
end
|
84
|
-
tag(parent, k, {:children => v.map { |c| [child, c]}, :parent =>
|
84
|
+
tag(parent, k, {:children => v.map { |c| [child, c, {:nested => child}]}, :parent => parent })
|
85
85
|
#Multiple hidden fields...
|
86
86
|
elsif(k =~ /^_/)
|
87
87
|
v.map { |c| tag("hidden", c, :parent => true)}.join("\n")
|
data/lib/cml/parser.rb
CHANGED
@@ -5,22 +5,24 @@ module CML
|
|
5
5
|
def initialize(content, opts = {})
|
6
6
|
@opts = opts
|
7
7
|
#Because nokogiri is munging my CDATA sections, we parse it out ahead of time
|
8
|
-
@cdata = content.scan(/(<(
|
8
|
+
@cdata = content.scan(/(<(script|style)[^>]*>)(.+?)(<\/\2)/m)
|
9
9
|
@doc = Parser.parse(content)
|
10
10
|
@cftags = @doc.xpath("//cml:*[not(ancestor::cml:*)]")
|
11
|
+
normalize if opts[:normalize]
|
11
12
|
@tags = @cftags.map do |t|
|
12
13
|
Parser.tag_class(t.name).new(t, @opts)
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.parse(content)
|
17
|
-
#This sucks, we remove scripts, styles, and close
|
18
|
-
|
18
|
+
#This sucks, we remove scripts, styles, and close non self closed tags
|
19
|
+
#We could potentially add CDATA clauses to them, but this is "easier"
|
20
|
+
xhtml = content.gsub(/(<(script|style)[^>]*>)(.+?)(<\/\2)/m, "\\1\\4").gsub(/(<(input|link|img|br|hr).*?)>/,'\1/>') #base, basefont, area, meta
|
19
21
|
Nokogiri::XML("<root xmlns:cml=\"http://crowdflower.com\">#{xhtml}</root>")
|
20
22
|
end
|
21
23
|
|
22
24
|
def convert(opts = nil)
|
23
|
-
@opts
|
25
|
+
@opts.merge!(opts) if opts
|
24
26
|
cloned = @doc.dup
|
25
27
|
cloned.xpath("//cml:*[not(ancestor::cml:*)]").each_with_index do |t,i|
|
26
28
|
t.replace(@tags[i].convert(opts))
|
@@ -28,6 +30,18 @@ module CML
|
|
28
30
|
cloned
|
29
31
|
end
|
30
32
|
|
33
|
+
def normalize
|
34
|
+
@cftags.each do |t|
|
35
|
+
if ["radios", "select"].include?(t.name)
|
36
|
+
child = t.name == "radios" ? "radio" : "option"
|
37
|
+
t.name = "checkboxes"
|
38
|
+
t.xpath("cml:#{child}").each { |c| c.name = "checkbox" }
|
39
|
+
elsif t.name == "meta"
|
40
|
+
t.name = "text"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
31
45
|
def fields
|
32
46
|
@fields = {}
|
33
47
|
@tags.each do |g|
|
@@ -83,7 +97,7 @@ module CML
|
|
83
97
|
|
84
98
|
def wrap(content)
|
85
99
|
#This has to happen if we are outputing html, can go away if we use xhtml
|
86
|
-
content = content.gsub(/%7B%7B/,'{{').gsub(/%7D%7D/,'}}')
|
100
|
+
#content = content.gsub(/%7B%7B/,'{{').gsub(/%7D%7D/,'}}')
|
87
101
|
@opts[:no_wrap] ? content : "<div class=\"cml#{" "+@opts[:class] if @opts[:class]}\" id=\"#{@opts[:prefix]}\">#{content}</div>"
|
88
102
|
end
|
89
103
|
|
@@ -93,9 +107,9 @@ module CML
|
|
93
107
|
|
94
108
|
def to_html(opts = nil)
|
95
109
|
#We are going to html because xhtml is crazy with the encoding
|
96
|
-
html = convert(opts).at("root").children.
|
110
|
+
html = convert(opts).at("root").children.to_xhtml
|
97
111
|
#Let's re-insert that CDATA
|
98
|
-
@cdata.each { |
|
112
|
+
@cdata.each { |matches| html.sub!(/(<(?:script|style)[^>]*>)</m, "\\1#{matches[2]}<") }
|
99
113
|
wrap(html)
|
100
114
|
end
|
101
115
|
|
data/lib/cml/tag.rb
CHANGED
@@ -80,14 +80,18 @@ module CML
|
|
80
80
|
@cml.to_s
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
83
|
+
def raw_label
|
84
|
+
label = @attrs["label"]
|
84
85
|
label ||= @attrs["name"].to_s.capitalize
|
86
|
+
end
|
87
|
+
|
88
|
+
def label(tag = "label")
|
85
89
|
required = " <span class=\"required\">(required)</span>" if validations.include?("required")
|
86
|
-
"<#{tag} class=\"legend\">#{
|
90
|
+
"<#{tag} class=\"legend\">#{raw_label}#{required}</#{tag.split(" ")[0]}>" if raw_label.to_s != ""
|
87
91
|
end
|
88
92
|
|
89
|
-
def legend
|
90
|
-
label(
|
93
|
+
def legend
|
94
|
+
label("h2")
|
91
95
|
end
|
92
96
|
|
93
97
|
def to_liquid
|
@@ -124,8 +128,8 @@ module CML
|
|
124
128
|
def data
|
125
129
|
(@opts[:data] || {}).merge({
|
126
130
|
"name" => prefix(name),
|
127
|
-
"label" => label
|
128
|
-
"legend" => legend
|
131
|
+
"label" => label,
|
132
|
+
"legend" => legend,
|
129
133
|
"classes" => classes,
|
130
134
|
"value" => value
|
131
135
|
})
|
data/spec/complex_spec.rb
CHANGED
@@ -59,11 +59,12 @@ describe "CML Complex" do
|
|
59
59
|
|
60
60
|
it "parses scripts and styles" do
|
61
61
|
@p = Parser.new(File.read(File.dirname(__FILE__) + "/fixtures/html.cml"), {:prefix => "u12345"})
|
62
|
-
@p.to_html.length.should >
|
62
|
+
@p.to_html.length.should > 900
|
63
|
+
#puts Parser.escape(@p.to_html).gsub(/\n/,"<br/>")
|
64
|
+
|
63
65
|
@p.to_html.should sorta_match(<<-HTML)
|
64
|
-
<div class="cml" id="u12345"
|
65
|
-
|
66
|
-
<a href="#" class="toggle" target="_blank">toggle series description</a>
|
66
|
+
<div class="cml" id="u12345"><hr />
|
67
|
+
<a target="_blank" class="toggle" href="#">toggle series description</a>
|
67
68
|
<div style="display:none">
|
68
69
|
{{seriesdescription | textilize}}
|
69
70
|
</div>
|
@@ -73,155 +74,25 @@ describe "CML Complex" do
|
|
73
74
|
<img src="{{url}}/{{image}}" style="width:110px" /></div>
|
74
75
|
{% endfor %}
|
75
76
|
<br style="clear:both" />
|
76
|
-
<div class="text">
|
77
|
-
<label class="legend">Cool dude</label>
|
77
|
+
<div class="text"><label class="legend">Cool dude</label>
|
78
78
|
<input name="u12345[cool_dude]" class="cool_dude" value="" type="text" />
|
79
79
|
</div>
|
80
|
-
<style type="text/css"
|
81
|
-
|
80
|
+
<style media="screen" type="text/css">
|
82
81
|
div.wrap {
|
83
82
|
position:relative;
|
84
83
|
float:left;
|
85
84
|
margin:5px 5px 0 0;
|
86
85
|
}
|
87
|
-
div.wrap span {
|
88
|
-
font-size:430%;
|
89
|
-
text-align:center;
|
90
|
-
color:#111;
|
91
|
-
background:#CCC;
|
92
|
-
opacity:0.65;
|
93
|
-
width:110px;
|
94
|
-
font-weight:bold;
|
95
|
-
position:absolute;
|
96
|
-
left:0;
|
97
|
-
z-index:1;
|
98
|
-
}
|
99
|
-
|
100
86
|
</style>
|
101
87
|
<script type="text/javascript" charset="utf-8">
|
102
88
|
var ranking = [null]
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
if(document.location.href.test(/ASSIGNMENT_ID_NOT_AVAILABLE/))
|
110
|
-
return alert('Please accept the hit before proceeding.')
|
111
|
-
var ul = this.getParent('ul')
|
112
|
-
var i = ul.retrieve('i')
|
113
|
-
var rank = this.get('class').replace(/\D/g,'')
|
114
|
-
var cur = i.getPrevious('span')
|
115
|
-
if(cur) {
|
116
|
-
var cur_rank = cur.get('class').replace(/\D/g,'')
|
117
|
-
ranking[cur_rank.toInt() - 1] = null
|
118
|
-
cur.destroy()
|
119
|
-
if(cur_rank == rank) {
|
120
|
-
i.retrieve('i').fireEvent('mouseleave')
|
121
|
-
return
|
122
|
-
}
|
123
|
-
}
|
124
|
-
var old = ranking[rank.toInt() - 1]
|
125
|
-
if(old)
|
126
|
-
old.getPrevious().destroy()
|
127
|
-
ranking[rank.toInt() - 1] = i
|
128
|
-
$$('input.ranking').destroy()
|
129
|
-
this.getParent('form').getElement('.jsawesome').adopt(ranking.map(function(r){
|
130
|
-
if(r) {
|
131
|
-
return new Element('input', {
|
132
|
-
type:'hidden',
|
133
|
-
name:'u{{_unit_id}}[ranking][]',
|
134
|
-
'class':'ranking',
|
135
|
-
value: r.get('src')
|
136
|
-
}).store('custom', function(right, inform){
|
137
|
-
right.each(function(url){
|
138
|
-
$$('img[src='+url+']').each(function(img){
|
139
|
-
img.getParent().setStyles({
|
140
|
-
background: 'green'
|
141
|
-
})
|
142
|
-
img.set('opacity', 0.7)
|
143
|
-
})
|
144
|
-
})
|
145
|
-
new Fx.Scroll(window, {onComplete:function(){
|
146
|
-
alert('The only acceptable images for this show are shown below in green. Please be more careful!')
|
147
|
-
inform()
|
148
|
-
}, offset:{x:0,y:-50}}).toElement($$('.wrap')[0])
|
149
|
-
})
|
150
|
-
}
|
151
|
-
}).clean())
|
152
|
-
new Element('span', {
|
153
|
-
html:this.get('html'),
|
154
|
-
styles: {
|
155
|
-
'line-height': i.getHeight()
|
156
|
-
},
|
157
|
-
'class':this.get('class'),
|
158
|
-
opacity: 0.65,
|
159
|
-
events: {
|
160
|
-
'mouseenter': function(e){
|
161
|
-
this.getNext().fireEvent('mouseenter', [e, rank])
|
162
|
-
},
|
163
|
-
'mouseleave': function(e){
|
164
|
-
this.getNext().fireEvent('mouseleave', [e, rank])
|
165
|
-
}
|
166
|
-
}
|
167
|
-
}).inject(i,'before')
|
168
|
-
i.retrieve('i').fireEvent('mouseleave')
|
169
|
-
}
|
170
|
-
}
|
171
|
-
}))
|
172
|
-
}))
|
173
|
-
window.addEvent('domready', function(){
|
174
|
-
$$('form').addEvent('submit', function(e){
|
175
|
-
if($$('input.any_problems').some(function(i){return i.checked}))
|
176
|
-
return true
|
177
|
-
var needed = ranking.indexOf(null)
|
178
|
-
if(needed > -1) {
|
179
|
-
var suf;
|
180
|
-
|
181
|
-
switch (needed){
|
182
|
-
case 0: suf = 'st'; break;
|
183
|
-
case 1: suf = 'nd'; break;
|
184
|
-
case 2: suf = 'rd'; break;
|
185
|
-
default: suf = 'th'
|
186
|
-
}
|
187
|
-
alert('You must choose '+ranking.length+' image or select no good images.')
|
188
|
-
e.stop()
|
189
|
-
}
|
190
|
-
})
|
191
|
-
$$('a.toggle').addEvent('click', function(e){
|
192
|
-
e.stop()
|
193
|
-
this.getNext().setStyle('display', (this.getNext().getStyle('display') == 'none' ? '' : 'none'))
|
194
|
-
})
|
195
|
-
$$('.wrap img').addEvent('mouseenter', function(e, cur){
|
196
|
-
this.store('cur', cur)
|
197
|
-
if(!this.retrieve('i')) {
|
198
|
-
var thumb = this
|
199
|
-
this.store('i', this.clone(true).setStyles({width:400}).addEvent('mouseenter', function(e){
|
200
|
-
rank.getElements('a').removeClass('cur')
|
201
|
-
var cur = thumb.retrieve('cur')
|
202
|
-
if(cur)
|
203
|
-
rank.getElement('a._'+cur).addClass('cur')
|
204
|
-
rank.store('i', thumb).setStyles({top:this.getTop() + 40, left:this.getLeft() + 160}).inject(this, 'after').fade('hide').fade(0.7)
|
205
|
-
}).addEvent('mouseleave', function(e){
|
206
|
-
//Don't know why the ul goes missing sometime..
|
207
|
-
if(this.getNext('ul') && (!e || !e.relatedTarget || !(e.relatedTarget.get('tag') == "ul" || e.relatedTarget.getParent('ul.rank')))) {
|
208
|
-
this.getNext('ul').dispose();
|
209
|
-
this.dispose()
|
210
|
-
}
|
211
|
-
}).addEvent('click', function(){this.fireEvent('mouseleave')}).addClass('zoomed'))
|
89
|
+
//Some really long comment that doesn't get borked by libxml... don't you dare insert a new line.
|
90
|
+
//Why are my && disapearing?
|
91
|
+
if(ranking && !false) {
|
92
|
+
//Preserve my curlies
|
93
|
+
var unit_id = {{_unit_id}};
|
94
|
+
var rad = "even inside strings {{awesome}}"
|
212
95
|
}
|
213
|
-
//Cleanup
|
214
|
-
$$('.zoomed').dispose()
|
215
|
-
var i = this.retrieve('i')
|
216
|
-
s = this.getParent('.wrap')
|
217
|
-
i.setStyles({position:'absolute',zIndex:2,top:s.getTop() + 40, left:s.getLeft() - 145})
|
218
|
-
i.inject(s,'after').fade('hide').fade('in')
|
219
|
-
}).addEvent('mouseleave', function(e){
|
220
|
-
var i = this.retrieve('i')
|
221
|
-
if(e.relatedTarget != i)
|
222
|
-
i.dispose()
|
223
|
-
})
|
224
|
-
})
|
225
96
|
</script></div>
|
226
97
|
HTML
|
227
98
|
end
|
@@ -6,9 +6,9 @@ describe "JSAwesome Converter" do
|
|
6
6
|
json = "[[
|
7
7
|
[\"text_field\", \"default value\"],
|
8
8
|
[\"#text_area\", \"\"],
|
9
|
-
[\"single_select\", [\"boo\", \"~yah\"]],
|
9
|
+
[\"single_select\", [\"boo|moo\", \"~yah\"]],
|
10
10
|
[\"^check\", [\"One|totally_rad\", [\"two\",true], \"three\"]],
|
11
|
-
[\"*radio\", [\"a\", \"b\", [\"c\", true]]],
|
11
|
+
[\"*radio\", [\"a\", \"b|D\", [\"c\", true]]],
|
12
12
|
[\"_hidden\",\"hot\"],
|
13
13
|
[[\"^single_check\"],[\"^Edge|edge_case\", false]]
|
14
14
|
],
|
@@ -35,17 +35,17 @@ describe "JSAwesome Converter" do
|
|
35
35
|
</cml:text>
|
36
36
|
<cml:textarea name="text_area" validates="required" label="Input some text with atleast one digit" />
|
37
37
|
<cml:select label="Single select" validates="required">
|
38
|
-
<cml:option label="Boo" />
|
38
|
+
<cml:option label="Boo" value="moo" />
|
39
39
|
<cml:option label="Yah" />
|
40
40
|
</cml:select>
|
41
41
|
<cml:checkboxes label="Check" gold="true">
|
42
|
-
<cml:checkbox label="One"
|
42
|
+
<cml:checkbox label="One" value="totally_rad" />
|
43
43
|
<cml:checkbox label="Two" checked="true" />
|
44
44
|
<cml:checkbox label="Three" />
|
45
45
|
</cml:checkboxes>
|
46
46
|
<cml:radios label="Radio">
|
47
47
|
<cml:radio label="A" />
|
48
|
-
<cml:radio label="B" />
|
48
|
+
<cml:radio label="B" value="D" />
|
49
49
|
<cml:radio label="C" checked="true" />
|
50
50
|
</cml:radios>
|
51
51
|
<cml:hidden label="Hidden" value="hot" />
|
data/spec/fixtures/html.cml
CHANGED
@@ -11,148 +11,74 @@
|
|
11
11
|
<br style="clear:both">
|
12
12
|
<cml:text label="Cool dude"/>
|
13
13
|
<style media="screen" type="text/css">
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
}
|
20
|
-
div.wrap span {
|
21
|
-
font-size:430%;
|
22
|
-
text-align:center;
|
23
|
-
color:#111;
|
24
|
-
background:#CCC;
|
25
|
-
opacity:0.65;
|
26
|
-
width:110px;
|
27
|
-
font-weight:bold;
|
28
|
-
position:absolute;
|
29
|
-
left:0;
|
30
|
-
z-index:1;
|
31
|
-
}
|
32
|
-
|
14
|
+
div.wrap {
|
15
|
+
position:relative;
|
16
|
+
float:left;
|
17
|
+
margin:5px 5px 0 0;
|
18
|
+
}
|
33
19
|
</style>
|
34
20
|
<script type="text/javascript" charset="utf-8">
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if(old)
|
59
|
-
old.getPrevious().destroy()
|
60
|
-
ranking[rank.toInt() - 1] = i
|
61
|
-
$$('input.ranking').destroy()
|
62
|
-
this.getParent('form').getElement('.jsawesome').adopt(ranking.map(function(r){
|
63
|
-
if(r) {
|
64
|
-
return new Element('input', {
|
65
|
-
type:'hidden',
|
66
|
-
name:'u{{_unit_id}}[ranking][]',
|
67
|
-
'class':'ranking',
|
68
|
-
value: r.get('src')
|
69
|
-
}).store('custom', function(right, inform){
|
70
|
-
right.each(function(url){
|
71
|
-
$$('img[src='+url+']').each(function(img){
|
72
|
-
img.getParent().setStyles({
|
73
|
-
background: 'green'
|
74
|
-
})
|
75
|
-
img.set('opacity', 0.7)
|
76
|
-
})
|
77
|
-
})
|
78
|
-
new Fx.Scroll(window, {onComplete:function(){
|
79
|
-
alert('The only acceptable images for this show are shown below in green. Please be more careful!')
|
80
|
-
inform()
|
81
|
-
}, offset:{x:0,y:-50}}).toElement($$('.wrap')[0])
|
82
|
-
})
|
83
|
-
}
|
84
|
-
}).clean())
|
85
|
-
new Element('span', {
|
86
|
-
html:this.get('html'),
|
87
|
-
styles: {
|
88
|
-
'line-height': i.getHeight()
|
89
|
-
},
|
90
|
-
'class':this.get('class'),
|
91
|
-
opacity: 0.65,
|
92
|
-
events: {
|
93
|
-
'mouseenter': function(e){
|
94
|
-
this.getNext().fireEvent('mouseenter', [e, rank])
|
95
|
-
},
|
96
|
-
'mouseleave': function(e){
|
97
|
-
this.getNext().fireEvent('mouseleave', [e, rank])
|
98
|
-
}
|
99
|
-
}
|
100
|
-
}).inject(i,'before')
|
101
|
-
i.retrieve('i').fireEvent('mouseleave')
|
102
|
-
}
|
103
|
-
}
|
104
|
-
}))
|
105
|
-
}))
|
106
|
-
window.addEvent('domready', function(){
|
107
|
-
$$('form').addEvent('submit', function(e){
|
108
|
-
if($$('input.any_problems').some(function(i){return i.checked}))
|
109
|
-
return true
|
110
|
-
var needed = ranking.indexOf(null)
|
111
|
-
if(needed > -1) {
|
112
|
-
var suf;
|
113
|
-
|
114
|
-
switch (needed){
|
115
|
-
case 0: suf = 'st'; break;
|
116
|
-
case 1: suf = 'nd'; break;
|
117
|
-
case 2: suf = 'rd'; break;
|
118
|
-
default: suf = 'th'
|
119
|
-
}
|
120
|
-
alert('You must choose '+ranking.length+' image or select no good images.')
|
121
|
-
e.stop()
|
21
|
+
// query1 = 'compare'
|
22
|
+
// query2 = 'base'
|
23
|
+
document.addEvent('domready', function() {
|
24
|
+
|
25
|
+
var inFrame = ($$('body.in_frame').length > 0);
|
26
|
+
var onWarningPage = ($$('div.missed', 'h3.tainted').length > 0);
|
27
|
+
|
28
|
+
var results = $('u{{_unit_id}}_div').getElements('.searchresult');
|
29
|
+
var rand = Math.floor(Math.random()*2);
|
30
|
+
var inputValues = ['compare_is_much_better', 'compare_is_a_little_better', 'base_is_a_little_better', 'base_is_much_better']
|
31
|
+
var htmlValues = [
|
32
|
+
'The <b>top</b> result is <b>much better</b> than the bottom one',
|
33
|
+
'The <b>top</b> result is <b>a little better</b> than the bottom one',
|
34
|
+
'The <b>bottom</b> result is <b>a little better</b> than the top one',
|
35
|
+
'The <b>bottom</b> result is <b>much better</b> than the top one',
|
36
|
+
'<b>Both</b> results are <b>not relevant</b> to the search terms <b>at all</b>'
|
37
|
+
];
|
38
|
+
|
39
|
+
if (inFrame && !onWarningPage) {
|
40
|
+
if (rand == 0) {
|
41
|
+
// Put base on top
|
42
|
+
results[0].inject(results[1], 'after');
|
43
|
+
inputValues.reverse();
|
122
44
|
}
|
123
|
-
}
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
45
|
+
} else {
|
46
|
+
// Fix the text a bit
|
47
|
+
$$('div.missed span').each(function(el) {
|
48
|
+
el.set('text', el.get('text').replace('Compare', 'The top result'));
|
49
|
+
el.set('text', el.get('text').replace('Base', 'The bottom result'));
|
50
|
+
el.set('text', el.get('text').replace(' compare', ' or the top result'));
|
51
|
+
el.set('text', el.get('text').replace(' base', ' or the bottom result'));
|
52
|
+
});
|
53
|
+
}
|
54
|
+
|
55
|
+
// Fix the input values and labels
|
56
|
+
if ($('u{{_unit_id}}')) {
|
57
|
+
$('u{{_unit_id}}').getElements('input.result_is_better').each(function(input, i) {
|
58
|
+
if (i < inputValues.length) input.set('value', inputValues[i]);
|
59
|
+
input.inject(input.getParent().set('html', htmlValues[i]), 'top');
|
60
|
+
});
|
61
|
+
}
|
62
|
+
|
63
|
+
$('u{{_unit_id}}_div').getElements('table.srchresult').each(function(el, i) {
|
64
|
+
// Fix a weird bug that got introduced in some circumstances way back in the scraping process
|
65
|
+
var bid_buy = el.getElement('td.bid_buy');
|
66
|
+
if (bid_buy.getChildren().length < 1) {
|
67
|
+
var numBids = Math.floor(Math.random()*15);
|
68
|
+
new Element('p', {'text': numBids+' bids'}).inject(bid_buy);
|
145
69
|
}
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
70
|
+
});
|
71
|
+
|
72
|
+
// Show the input form
|
73
|
+
$('u{{_unit_id}}_div').setStyle('display', 'block');
|
74
|
+
});
|
75
|
+
|
76
|
+
var ranking = [null]
|
77
|
+
//Some really long comment that doesn't get borked by libxml... don't you dare insert a new line.
|
78
|
+
//Why are my && disapearing?
|
79
|
+
if (ranking && !onSomeWarningpage) {
|
80
|
+
//Preserve my curlies
|
81
|
+
var unit_id = {{_unit_id}};
|
82
|
+
var rad = "even inside strings {{awesome}}"
|
83
|
+
}
|
158
84
|
</script>
|
@@ -0,0 +1 @@
|
|
1
|
+
<script type="text/javascript" src="http://api.maps.yahoo.com/ajaxymap?v=3.8&appid=Knx84fDV34H2VnhVU1DoD7chT1wjJ2r36uf4dZW7Vc5si9sqQRAYU_g8fo7zV.wF"></script><br><script src="/javascripts/upload.js" type="text/javascript" charset="utf-8"></script><br><script type="text/javascript"><br> mapInterface=new Object();//Wrapper for all info we will store;<br> mapInterface.baseCrowdflowerUrl='http://crowdflower.com';//'http://www.crowdflower.com';<br> mapInterface.debug=false;<br> mapInterface.jobId=1059;<br> mapInterface.accepted=new Object();<br> mapInterface.accepted.unit=null;<br> mapInterface.accepted.unitId=null;<br> mapInterface.accepted.cart=new Object();//Contains all units selected<br> //Consider using cookie for this<br> mapInterface.accepted.cond=false; //Bool thatrepresents whether the user has accepted a task yet<br> mapInterface.imageBaseUrl='http://a1.doloreslabs.com/q82/images/';<br> mapInterface.startingZoom=15;<br> mapInterface.addressZoom=10;<br> mapInterface.searchBox=new Object();<br> mapInterface.searchBox.lonRange=10;<br> mapInterface.searchBox.latRange=10;<br> mapInterface.maxDistance=160900;//100 miles in meters<br> mapInterface.maxPoints=300; //Max points to display on the screen<br> mapInterface.formAwesome=new Object(); <br> mapInterface.formAwesome.form = [["*the_specified_location",["yes","no"]],["#and_the_situation","For example, \"This is a new road and there is no paint.\""],["#specified_latitudelongitude_location",""],["*the_road_paved",["yes","no"]],["*road_private_access",["yes","no"]],["*road_one_way",["yes","no"]],["*on_the_road",["yes","no"]],["in_the_map",""],["in_the_map_2",""],["of_the_road",""],["the_new_road",""],["of_the_map",""],["#residential_development_etc","For example, \"This is a new road in a developing neighborhood.\""],["*in_the_future",["yes","no"]],["#please_elaborate",""],["#about_the_task",""]];<br> mapInterface.formAwesome.labels={"in_the_map_2":{"label":"What is the number of lanes in the south or west-ward direction of travel in the map? ","required":true},"of_the_road":{"label":"What is the speed limit on the initial section of the road? ","required":true},"the_road_paved":{"label":"Is the road paved? ","required":true},"road_one_way":{"label":"Is the road one way? ","required":true},"about_the_task":{"label":"Any comments about the task?"},"the_new_road":{"label":"Are there any turn restrictions turning on to the new road, or turning off the new road? ","required":true},"the_specified_location":{"label":"Does a road exist at the specified location? ","required":true},"on_the_road":{"label":"Is there a divider on the road? ","required":true},"and_the_situation":{"label":"Describe the road and the situation. ","required":true},"road_private_access":{"label":"Is the road private access? ","required":true},"in_the_map":{"label":"What is the number of lanes in the north or east-ward direction of travel in the map? ","required":true},"of_the_map":{"label":"What are the minimum and maximum address numbers on the road within the range of the map? ","required":true},"residential_development_etc":{"label":"Please provide a general description of the road and area. Note whether the road is still under construction, leads to hotels, if it is in the residential development, etc. ","required":true},"in_the_future":{"label":"Would you be willing to do this task again in the future?","required":true},"please_elaborate":{"label":"Please elaborate"},"specified_latitudelongitude_location":{"label":"If the road did not exist at the specified latitude/longitude location but was nearby, please describe its actual location. What was at the specified latitude/longitude location?"}};<br> <br> mapInterface.points=new Object();<br> //mapInterface.points.data=<?=file_get_contents('units.json')?>;<br> <br> //Returns an array of units that fit in the appropriate location<br> mapInterface.points.filterByLoc=function(userLoc){<br> var filtUnits=new Array();<br> var counter=0;<br> for(var unitId in mapInterface.points.data){<br> var unit=mapInterface.points.data[unitId];<br> //Check distance<br> if( great_circle_distance(userLoc,unit)>=mapInterface.maxDistance){<br> continue;<br> }<br> else if(counter >= mapInterface.maxPoints){<br> break;<br> }<br> else{<br> filtUnits[unitId]=unit;<br> counter++;<br> }<br> }<br> //*/<br> return filtUnits;<br> <br> //Calculates Euclidean distance between two points<br> function checkDistance(point1,point2){<br> return Math.pow (<br> Math.pow( (point2.Lat-point1.Lat), 2)+Math.pow( (point2.Lon-point1.Lon), 2)<br> , .5);<br> }<br> //Gabe smed's true distance calc<br> function great_circle_distance(point_a, point_b) {<br> var lat1 = point_a.Lat;<br> var lat2 = point_b.Lat;<br> var lon1 = point_a.Lon;<br> var lon2 = point_b.Lon;<br> <br> var R = 6378140; // meters<br> var dLat = deg_to_rad(lat2-lat1)<br> var dLon = deg_to_rad(lon2-lon1)<br> var a = Math.sin(dLat/2) * Math.sin(dLat/2) +<br> Math.cos(deg_to_rad(lat1)) * Math.cos(deg_to_rad(lat2)) *<br> Math.sin(dLon/2) * Math.sin(dLon/2);<br> var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));<br> var d = R * c;<br> <br> return d<br> <br> function deg_to_rad(deg) {<br> return deg * Math.PI / 180.0<br> }<br> }<br> <br> };<br> mapInterface.points.draw=function(userLoc, map){<br> //AJAX GET request to pull units in a large bounding box<br> //Then we use method .filterByLoc to reduce the search further<br> //(function(){<br> var dataRequest=new Request.JSON({<br> url: mapInterface.baseCrowdflowerUrl+'/jobs/'+mapInterface.jobId+'/units/custom.json',<br> onSuccess: function(responseJSON, responseText){<br> //console.log(responseJSON);<br> mapInterface.points.data=new Object();<br> for(var unitId in responseJSON){<br> mapInterface.points.data[unitId]= mapInterface.formatUnit(responseJSON[unitId], unitId);<br> }<br> afterDataUpdated();<br> $$('div.loading').setStyle('visibility','hidden');<br> },<br> onFailure: function(xhr){<br> alert('Error loading data. Please try refreshing the page or send an email to info@doloreslabs.com');<br> }<br> });<br> var searchBoxLonSize=mapInterface.searchBox.lonRange;<br> var searchBoxLatSize=mapInterface.searchBox.latRange;<br> var params={ c1_key:'long'<br> ,c1_val: (userLoc.Lon-searchBoxLonSize).toString()+','+(userLoc.Lon+searchBoxLonSize).toString()<br> ,c1_op: 'bt'<br> ,c2_key:'lat'<br> ,c2_val: (userLoc.Lat-searchBoxLatSize).toString()+','+(userLoc.Lat+searchBoxLatSize).toString()<br> ,c2_op: 'bt'<br> };<br> dataRequest.get(params);<br> //})();<br> function afterDataUpdated(){<br> map.removeMarkersAll();<br> if(typeof(userLoc)=='undefined'){<br> return false;<br> }<br> var units=mapInterface.points.filterByLoc(userLoc);<br> if ( units.length===0){<br> alert('Sorry, no results found! Try another address.');<br> return false;<br> }<br> for(var unitId in units){<br> unit=units[unitId];<br> if(typeof(unit['file1'])=='undefined'<br> || typeof(unit['file2'])=='undefined'){<br> //For some reason some of the unit objects are malformed<br> //console.log(unit);<br> continue;<br> }<br> <br> var sMarker=new YMarker(new YGeoPoint( unit.Lat,unit.Lon ));<br> sMarker.unitId=unitId;<br> sMarker.unit=unit;<br> //Add onclick event to the markers<br> YEvent.Capture(sMarker,EventsList.MouseClick,function(e){<br> if(mapInterface.accepted.cond===true){<br> mapInterface.popup.confirmReturnUnit.bind(this, [this.unit, this.unitId])();<br> }<br> else{<br> mapInterface.popup.simpleUnit.bind(this, [this.unit, this.unitId])();<br> }<br> });<br> map.addOverlay(sMarker);<br> }<br> }<br> };//*/<br> //Adds some custom properties to the unit<br> mapInterface.formatUnit=function(unit, unitId){<br> unit.Lat=unit.lat;<br> unit.Lon=unit.long;<br> unit.image1Url=mapInterface.imageBaseUrl+unit.file1.trim();<br> unit.image2Url=mapInterface.imageBaseUrl+unit.file2.trim();<br> unit.unitMapLink="<a href=\"http://maps.yahoo.com/#mvt=m&lat="+unit.Lat+"&lon="+unit.Lon+"&zoom=14&q1="+unit.Lat+"%252C%2520"+unit.Lon+"\" target=\"_blank\">Click here to get driving instructions</a>";<br> unit.img1html='<a target="_blank" href="'+unit.image1Url+'"><img src="'+unit.image1Url+'"/></a>';<br> unit.img2html='<a target="_blank" href="'+unit.image2Url+'"><img src="'+unit.image2Url+'"/></a>';<br> unit.unitId=unitId;<br> return unit;<br> }<br> <br> mapInterface.popup=new Object();<br> //Used for callback on click of a YAHOO map marker.<br> //Pops up a new window with a simple unit view <br> mapInterface.popup.simpleUnit=function(unit, unitId){<br> //Kill any existing window div<br> $$('div.popup').dispose();<br> //Create a new popup div window (popup) using template found in div.popupContent<br> var divText=$(document.body)<br> .getElement('div.popupContent div.simpleUnitView')<br> .get('html')<br> .substitute(unit);<br> <br> //Inject into DOM<br> var newDiv=new Element('div', {"class": "popup", "id":"popupU"})<br> .set('html',divText)<br> .inject( $(document.body) )<br> .store('unit',unit)<br> .store('unitId',unitId);<br> <br> //Wire up close button<br> newDiv.getElement('span.close').addEvent('click',function(e){<br> this.getParent().getParent().dispose();<br> });<br> <br> <br> //Wire up accept button<br> if(mapInterface.previewMode===true){<br> newDiv.getElement('div.viewMore').dispose();<br> $$('div.simpleUnitView div.previewInstructions').setStyle('display','block');<br> }<br> else{<br> //Wire up "View More Details" button<br> newDiv.getElement('div.viewMore').addEvent('click',mapInterface.popup.advUnit);<br> }<br> <br> //Make div popup and transparent while dragging<br> var movableDiv=new Drag.Move(newDiv,{<br> onStart:function(el){el.addClass('dragging').set('opacity','.5');},<br> onComplete: function(el){el.removeClass('dragging').set('opacity','1.0');} <br> });<br> };<br> //Used as callback for when someone clicks "View more info" on the unit popup div<br> //Fullscreens an existing unit<br> mapInterface.popup.advUnit=function(e){<br> //Move window to upper left, Add a class that will include styles to maximize div to full screen<br> var popupDiv=this.getParent().position({x:'left',y:'top'}).addClass('fullscreen');<br> var unitId=this.getParent().retrieve('unitId');<br> var unit=this.getParent().retrieve('unit');<br> <br> var divText=$(document.body)<br> .getElement('div.popupContent div.advUnitView')<br> .get('html')<br> .substitute(unit);<br> this.getParent().set('html',divText);<br> <br> popupDiv.getElement('div.accept').addEvent('click',function(e){<br> //Lock in unit through AJAX request<br> var acceptRequest=new Request.JSON({<br> url:'/jobs/'+mapInterface.jobId+'/units/'+unitId+'/custom',<br> method: 'put',<br> data: {unit:{state:'judging'}},<br> onSuccess: function(responseJSON, responseText){<br> mapInterface.accepted.unitId=unitId;<br> mapInterface.accepted.unit=unit;<br> mapInterface.accepted.cond=true;<br> mapInterface.popup.printableForm.bind( this )();<br> $$('div.acceptedTaskLink').setStyle('display','block');<br> }.bind(this.getParent().getParent()),<br> onFailure: function(){<br> alert('Sorry, it seems a network problem is preventing you from accepting the task. Please try again later or email admin@doloreslabs.com');<br> }<br> });<br> //Params<br> acceptRequest.send();<br> });<br> //Wire up close button<br> popupDiv.getElement('span.close').addEvent('click',function(e){<br> this.getParent().getParent().dispose();<br> });<br> };<br> //Pops up a new window at the beginning of task<br> mapInterface.popup.splash=function(){<br> var content=$(document.body).getElement('div.popupContent div.splash').get('html');<br> var newDiv=new Element('div', {"class": "splash popup fullscreen"})<br> .set('html',content)<br> .inject( $(document.body) );<br> //Wire up close button<br> newDiv.getElement('span.close').addEvent('click',function(e){<br> this.getParent().getParent().dispose();<br> });<br> //Wire up returning button<br> newDiv.getElement('div.returning').addEvent('click',function(e){<br> mapInterface.popup.checkUnitId(); <br> });<br> //Wire up new button<br> newDiv.getElement('div.new').addEvent('click',function(e){<br> this.getParent().getParent().dispose();<br> });<br> };<br> <br> //Pops up a new window at the beginning of task<br> mapInterface.popup.preview=function(){<br> var content=$(document.body).getElement('div.popupContent div.preview').get('html');<br> var newDiv=new Element('div', {"class": "preview popup"})<br> .set('html',content)<br> .inject( $(document.body) );<br> //Wire up close button<br> newDiv.getElement('span.close').addEvent('click',function(e){<br> newDiv.dispose();<br> });<br> //Wire up returning button<br> newDiv.getElement('div.preview.clickable').addEvent('click',function(e){<br> //Undisable search box (which is by default disabled in PREVIEW mode)<br> if(mapInterface.previewMode===true){<br> $('userAddress').set('disabled',false);<br> }<br> newDiv.dispose();<br> });<br> <br> //Make div popup and transparent while dragging<br> var movableDiv=new Drag.Move(newDiv,{<br> onStart:function(el){el.addClass('dragging').set('opacity','.5');},<br> onComplete: function(el){el.removeClass('dragging').set('opacity','1.0');} <br> });<br> };<br> <br> //Allow user to enter in existing unit id<br> mapInterface.popup.checkUnitId=function(){<br> var content=$(document.body).getElement('div.popupContent div.checkUnitId').get('html');<br> var popupDiv= new Element('div', {"class": "popup checkUnitId fullscreen"})<br> .set('html',content)<br> .inject( $(document.body) );<br> //So we can distinguish this div from the hidden one<br> popupDiv.getElement('input.unitId').addClass('real');<br> //Wire up close button<br> popupDiv.getElement('span.close').addEvent('click',function(e){<br> this.getParent().getParent().dispose();<br> });<br> //Wire up submit button <br> popupDiv.getElement('div.checkUnitId').addEvent('click',function(e){<br> //Grab unitId<br> var unitId=Number( $(document.body).getElement('input.unitId.real').value.trim() );<br> if(typeof(unitId)!='number' || !isFinite(unitId) || unitId<=0 ){<br> alert('The unit ID must be a number in the format 9999999');<br> return false;<br> }<br> var request=new Request.JSON({<br> url: mapInterface.baseCrowdflowerUrl+'/jobs/'+mapInterface.jobId+'/units/'+unitId+'/custom.json',<br> method: 'get',<br> onSuccess: function(responseText, responseXML){<br> mapInterface.accepted.unitId=unitId;<br> mapInterface.accepted.unit=mapInterface.formatUnit(responseText.data, unitId);<br> mapInterface.accepted.cond=true;<br> //console.log(responseText);<br> mapInterface.popup.submittableForm();<br> },<br> onFailure: function(xhr){<br> alert('The entered unit ID is not valid. Please ensure you entered it correctly and try again.');<br> }<br> });<br> request.send();<br> });<br> //Wire up cancel button<br> popupDiv.getElement('div.cancel').addEvent('click',function(e){<br> popupDiv.dispose(); <br> });<br> <br> //Wire up input box so that hitting enter submits form<br> popupDiv.getElement('input.unitId').addEvent('keypress',function(e){<br> if(e.key=='enter'){<br> e.stop(); //Prevent form from submitting<br> popupDiv.getElement('div.checkUnitId').fireEvent('click');<br> }<br> });<br> };<br> //Now actually display the form<br> mapInterface.popup.submittableForm=function(e){<br> //Kill existing popups<br> $$('div.popup').dispose();<br> //Grab HTML from hidden div on page<br> var html=$(document.body).getElement('div.popupContent div.submittableForm').get('html').substitute(mapInterface.accepted.unit);<br> //Create the windowed div<br> var newDiv=new Element('div', {"class": "submittableForm popup fullscreen"})<br> .set('html',html)<br> .inject( $(document.body) );<br> //Wire up close button<br> newDiv.getElement('span.close').addEvent('click',function(e){<br> this.getParent().getParent().dispose();<br> });<br> //Add form<br> var jsaDivId='u'+mapInterface.accepted.unitId;<br> var jsaDiv=new Element('div', {"class": "submittableForm", id: jsaDivId} )<br> .inject( newDiv.getElement('div.content form'), 'bottom' );<br> //JSawesome creates the form elements<br> var myJSAwesome=new JSAwesome(jsaDivId,mapInterface.formAwesome.form, mapInterface.formAwesome.labels);<br> myJSAwesome.to_html();<br> myJSAwesome.addValidation();<br> <br> //Submit button<br> var submitButton=new Element('input', {type: "submit", name: "submit", value: "Submit"}).inject(newDiv.getElement('div.content form'), 'bottom');<br> <br> //Add some validation when submitting<br> submitButton.addEvent('click',function(e){<br> if( $$('.files').length > 0 ){<br> var myCookie=Cookie.write('submittedForm','yes',{duration: 30}); //save for a month)<br> return true;<br> }<br> else{<br> e.stop();<br> alert('You didn\'t upload any files! You must upload an image of the street to submit this task. Make sure you click the "Upload Images" button to upload the files after you have selected them from your computer.');<br> }<br> });<br> <br> newDiv.getElement('input.upload').addClass('real');<br> newDiv.getElement('div.uploadStatus').addClass('real');<br> newDiv.getElement('ul.list').addClass('real');<br> newDiv.getElement('a.browse').addClass('real');<br> mapInterface.uploader.wireUp(newDiv);<br> };<br> <br> mapInterface.popup.printableForm=function(e){<br> //Kill existing popups<br> $$('div.popup').dispose();<br> //Grab HTML from hidden div on page<br> var html=$(document.body).getElement('div.popupContent div.printableForm').get('html').substitute(mapInterface.accepted.unit);<br> //Create the windowed div<br> var newDiv=new Element('div', {"class": "printableForm popup fullscreen"})<br> .set('html',html)<br> .inject( $(document.body) );<br> //Wire up close button<br> newDiv.getElement('span.close').addEvent('click',function(e){<br> this.getParent().getParent().dispose();<br> });<br> var form=new Element('form', {"class": "printableForm", id: "printableForm" } )<br> .inject( newDiv.getElement('div.content') );<br> new JSAwesome('printableForm',mapInterface.formAwesome.form, mapInterface.formAwesome.labels).to_html();<br> }<br> mapInterface.uploader=new Object();<br> mapInterface.uploader.wireUp=function(newDiv){<br> newDiv.getElement('input.upload').addEvent('click', function(){mapInterface.uploader.swiffy.upload()})<br> var unit_id = mapInterface.accepted.unitId;<br> var worker_id = "{{_worker_id}}"<br> mapInterface.uploader.swiffy = new FancyUpload2(newDiv.getElement('div.uploadStatus'), newDiv.getElement('ul.list'), {<br> url: 'http://crowdflower_upload.s3.amazonaws.com/',<br> typeFilter: {'Data (*.jpg, *.jpeg)': '*.jpg; *.jpeg'},<br> fieldName: 'file',<br> path: '/Swiff.Uploader.swf',<br> limitSize: 5 * 1024 * 1024, // 5Mb<br> multiple: true,<br> mergeData: true,<br> autoStart: false,<br> method: 'post',<br> passStatus:[201],<br> data: {<br> 'key': 'uploads/'+unit_id+'-'+worker_id+'_1.jpg',<br> 'AWSAccessKeyId': "00NZJT8HNJ5H6N5MGP02",<br> 'success_action_status' : 201,<br> 'acl': 'private',<br> 'policy': "eyJleHBpcmF0aW9uIjogIjIwMTAtMDEtMDFUMDA6MDA6MDBaIiwKICAiY29uZGl0aW9ucyI6IFsgCiAgICB7ImJ1Y2tldCI6ICJjcm93ZGZsb3dlcl91cGxvYWQifSwgCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXBsb2Fkcy8iXSwKICAgIFsic3RhcnRzLXdpdGgiLCAiJEZpbGVuYW1lIiwgIiJdLAogICAgeyJhY2wiOiAicHJpdmF0ZSJ9LAogICAgWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDAsIDEwNDg1NzZdLAogICAgWydlcScsICckc3VjY2Vzc19hY3Rpb25fc3RhdHVzJywgJzIwMSddCiAgXQp9Cg==",<br> 'signature': "RUrMBFa13RBYm4HQ5zGfE0BXFIY=" <br> },<br> fileInvalid: function(e) {<br> flash("File must be less than 10MB", "error")<br> },<br> onComplete: function(res){<br> $$('input.upload.real').set({'value': 'Upload complete!'})<br> this.fileList.each(function(file,i){<br> if(file.element.hasClass('completed'))<br> return<br> file.element.addClass('completed').getElement('.file-remove').dispose()<br> new Element('input', {type:'hidden', 'class':'files', name:'u'+unit_id+'[_files][]', value:unit_id+'-'+worker_id+'_'+(i+1)+'.'+file.extension}).inject(this.status)<br> }, this)<br> var later = function(){<br> this.size = this.uploading = this.bytesLoaded = this.percentLoaded = 0;<br> }<br> later.delay(500,this)<br> $$('input.upload.real').set({disabled:false, value:'Upload these images', style:'display:none'})<br> },<br> onFileRemove: function(w){<br> if(this.fileList.length == 0) {<br> $$('a.browse.real').set('html', 'Choose images of the road')<br> $$('input.upload.real').setStyle('display', 'none')<br> }<br> },<br> onBeforeStart: function(){<br> $$('input.upload.real').set({'disabled':true, 'value': 'Uploading...'})<br> },<br> onSelectSuccess: function(files){<br> this.overallProgress.set(0);<br> this.currentProgress.set(0);<br> var offset = this.fileList.length - files.length + 1<br> files.each(function(f,i){<br> var data = mapInterface.uploader.swiffy.options.data<br> data.key = data.key.replace(/_(\d+)\.jpg/,'_'+(offset + i)+'.'+f.extension)<br> f.setOptions({data:data})<br> })<br> $$('a.browse.real').set('html', 'Choose more images of the road')<br> $$('input.upload.real').setStyle('display','')<br> },<br> onFail: function(error) {<br> switch (error) {<br> case 'hidden': // works after enabling the movie and clicking refresh<br> alert('To enable the embedded uploader, unblock it in your browser and refresh (see Adblock).');<br> break;<br> case 'blocked': // This no *full* fail, it works after the user clicks the button<br> alert('To enable the embedded uploader, enable the blocked Flash movie (see Flashblock).');<br> break;<br> case 'empty': // Oh oh, wrong path<br> alert('A required file was not found, please be patient and we\'ll fix this.');<br> break;<br> case 'flash': // no flash 9+ :(<br> alert('To enable the embedded uploader, install the latest Adobe Flash plugin.')<br> }<br> },<br> target: ($$('a.browse.real')[0])<br> });<br> };<br> <br> <br> <br> mapInterface.popup.confirmReturnUnit=function(unit, unitId){<br> //Kill any existing window div<br> $$('div.popup').dispose();<br> //Create a new popup div window (popup) using template found in div.popupContent<br> var divText=$(document.body)<br> .getElement('div.popupContent div.confirmReturnUnit')<br> .get('html');<br> <br> //Inject into DOM<br> var newDiv=new Element('div', {"class": "popup confirmReturnUnit"})<br> .set('html',divText)<br> .inject( $(document.body) )<br> <br> //Wire up close button<br> newDiv.getElement('span.close').addEvent('click',function(e){<br> this.getParent().getParent().dispose();<br> });<br> <br> //Wire up "View More Details" button<br> newDiv.getElement('div.confirm').addEvent('click',function(unit, unitId){<br> mapInterface.popup.simpleUnit(unit, unitId);<br> /*<br> //If task is already accepted, we need to first revoke the original task<br> if(mapInterface.accepted.cond===true){<br> //AJAX call to set state of the unit back to unjudged<br> var returnRequest=new Request.JSON({<br> url:'/jobs/'+mapInterface.jobId+'/units/'+mapInterface.accepted.unitId+'/custom',<br> method: 'put',<br> data: {unit:{state:'judgable'}},<br> onSuccess: function(responseJSON, responseText){<br> mapInterface.accepted.unitId=null;<br> mapInterface.accepted.unit=null;<br> mapInterface.accepted.cond=false;<br> $$('div.acceptedTaskLink').setStyle('display','none');<br> $$('div.popup').dispose();<br> },<br> onFailure: function(){<br> alert('Error connecting to server: could not return task. If you continue to receive this error, please send an email to admin@doloreslabs.com');<br> }<br> });<br> //Params<br> returnRequest.send();<br> }<br> //*/<br> }.bind(this, [unit, unitId]) );<br> newDiv.getElement('div.cancel').addEvent('click',function(e){<br> mapInterface.popup.printableForm(); <br> });<br> <br> //Make div popup and transparent while dragging<br> var movableDiv=new Drag.Move(newDiv,{<br> onStart:function(el){el.addClass('dragging').set('opacity','.5');},<br> onComplete: function(el){el.removeClass('dragging').set('opacity','1.0');} <br> });<br> }<br> <br> // Create a Map that will be placed in the "map" div.<br> window.addEvent('domready',function(){<br> if( Cookie.read('submittedForm') === 'yes'){<br> Cookie.write('submittedForm','no');<br> alert('Thanks for submitting the task! Now you can select a new task or submit answers to another one.');<br> }<br> <br> //Hide existing submit button<br> $$('input[type=submit]').addClass('invisible');<br> <br> //Check if this is preview in AMT or not<br> if( $$('input[type=submit]')[0].get('disabled') ){<br> mapInterface.previewMode=true;<br> $$('div.linkToSubmitPage.clickable').setStyle('visibility','hidden');<br> mapInterface.popup.preview();<br> }<br> //Only display splash screen if we're not in preview mode<br> else{<br> mapInterface.previewMode=false;<br> mapInterface.popup.splash();<br> }<br> <br> var map = new YMap($('map')); <br> // Add the ability to change between Sat, Hybrid, and Regular Maps<br> map.addTypeControl(); <br> // Add the zoom control. Long specifies a Slider versus a "+" and "-" zoom control<br> map.addZoomLong(); <br> // Add the Pan control to have North, South, East and West directional control<br> map.addPanControl(); <br> // Specifying the Map starting location and zoom level<br> map.drawZoomAndCenter("San Francisco", mapInterface.startingZoom);<br> <br> $$('div.acceptedTaskLink').addEvent('click',function(){<br> mapInterface.popup.printableForm();<br> });<br> <br> //Wire up the user address submit button<br> $$('span#submitUserForm').addEvent('click',function(){<br> $$('div.loading').setStyle('visibility','visible');<br> var userAddress=$('userAddress').value;<br> map.geoCodeAddress(userAddress);<br> YEvent.Capture(map, EventsList.onEndGeoCode, function(geoCode) {<br> map.drawZoomAndCenter(geoCode.GeoPoint,mapInterface.addressZoom);<br> if (geoCode.success){<br> //Clear points<br> mapInterface.points.draw(geoCode.GeoPoint,map);<br> }<br> });<br> });<br> <br> //Wire up take me back to home page link<br> $$('div.linkToSubmitPage').addEvent('click',function(){<br> mapInterface.popup.checkUnitId();<br> });<br> <br> //Change default action of hitting enter on the input element<br> $$('input#userAddress').addEvent('keypress',function(e){<br> if(e.key=='enter'){<br> e.stop(); //Prevent form from submitting<br> $$('span#submitUserForm').fireEvent('click');<br> }<br> });<br> });<br></script><br><style type="text/css"><br>.invisible{<br> display:none;<br>}<br>input{<br> margin-right:15px;<br>}<br>div#map{<br> <br> height:400px;<br> width:700px;<br>}<br>div.loading{<br> background-color:yellow;<br> width:8em;<br> font-size:130%;<br> visibility:hidden;<br>}<br>div.loadingTop{<br> position:fixed;<br> left:0px;<br> top:0px;<br> z-index:1000;<br> background-color:yellow;<br> width:8em;<br> font-size:130%;<br> display:none;<br>}<br>div.acceptedTaskLink{<br> margin-top:5px;<br> display:none;<br> <br>}<br>div.userLocation{<br> padding-top:30px;<br>}<br>span#submitUserForm{<br> cursor:pointer;<br> background-color:#5D9732;<br> padding:4px;<br> color:white;<br>}<br>input#userAddress{<br> width:50em;<br>}<br>/*Styling for div/span buttons*/<br>div.clickable{<br> background-color:#27572A;<br> padding:5px;<br> cursor:pointer;<br> text-align:center;<br> font-size:120%;<br> color:white;<br>}<br>div.clickable.small{<br> width:10em;<br>}<br>div.popup{<br> background-color:white;<br> border-width:5px;<br> border-style:solid;<br> border-color:black;<br> width:400px;<br> z-index:255;<br> position:fixed;<br> top:10%;<br> left:10%;<br> cursor:-moz-grab;<br> cursor:grab;<br>}<br>div.popup.preview{<br> width:540px;<br>}<br>div.dragging{<br> cursor:-moz-grabbing;<br> cursor:grabbing;<br>}<br>div.popup.fullscreen{<br> width:96%;<br> height:96%;<br> position:absolute;<br> left:2px;<br> top:2px;<br>}<br>div.popup div.topBar{<br> width:100%;<br> text-align:right;<br> background-color:#5D9732;<br>}<br>div.popup.fullscreen{<br> cursor:default;<br>}<br>/*Close button*/<br>div.popup span.popupButton{<br> padding-left:5px;<br> padding-right:5px;<br> background-color:black;<br> color:white;<br> cursor:pointer;<br>}<br>div.popup span.popupButtonSpacer{<br> background-color:inherit;<br> padding:0px;<br> padding-left:3px;<br>}<br>div.popup div.content{<br> background-color:white;<br> padding:20px;<br>}<br>div.popup div.content div.image1{<br> width:300px;<br>}<br>div.popup div.content div.image2{<br> width:300px;<br>}<br>div.popup.fullscreen div.content div.imageHolder{<br> float:right;<br> width:60%;<br>}<br>div.popup.fullscreen div.content div.image1{<br> height:40%;<br> float:right;<br>}<br>div.popup.fullscreen div.content div.image2{<br> height:40%;<br> float:right;<br>}<br>div.popup.fullscreen div.text{<br> padding:40px;<br>}<br>div.popup div.content img{<br> width:100%;<br>}<br>div.popupContent{<br> display:none;<br>}<br>div.popup.splash{<br> cursor:default;<br> position:fixed;<br> top:2px;<br> left:2px;<br> bottom:2px;<br> right:2px;<br>}<br>div.popup.splash div.returning{<br> width:60%;<br> margin-top:20%;<br> margin-left:15%;<br>}<br>div.popup.splash div.new{<br> margin-top:1em;<br> margin-left:15%;<br> width:60%;<br>}<br>div.popup.checkUnitId input{<br> width:10em;<br> margin-top:5%;<br> margin-bottom:5px;<br>}<br>div#formAwesome{<br> width:95%;<br> height:95%;<br> margin-top:5%;<br>}<br>div.linkToSubmitPage{<br> margin-top:3px;<br> width:45em;<br> font-size:80%;<br>}<br>div.popup.fullscreen.printableForm{<br> height:auto;<br> cursor:default;<br>}<br>div.popup.fullscreen.submittableForm{<br> height:auto;<br> cursor:default;<br>}<br>div.popup div.previewInstructions{<br> display:none;<br> padding:10px;<br>}<br>div.vertPadding{<br> margin-top:5px;<br>}<br></style><br><style type="text/css" media="screen"><br>/*Uploader styles*/<br>div.uploader{<br> margin-left:10px;<br> width:auto;<br>}<br>div.uploader img{<br> width:auto !important;<br>}<br>div#status{<br> display:hidden;<br>}<br>.progress {<br> background: white url(/images/progress-bar/progress.gif) no-repeat +50% 0;<br> margin-right: 0.5em;<br>}<br>.progress-text{<br> font-size: 0.9em;<br> font-weight: bold;<br>}<br>.file-remove {<br> font-size:0.9em;<br> padding:5px;<br> color:#ad1a2c;<br>}<br>.file-info {<br> margin-left:8px;<br>}<br>.file-name {<br> margin-left:5px;<br>}<br>.completed {<br> color:#CCC;<br>}<br></style><br><div class="loadingTop">Loading</div><br><div class="linkToSubmitPage clickable"><br> I've already driven to a location and completed a task. Let me submit my answers!<br></div><br><div class="userLocation"><br> <form name="userLocationForm"><br> <h3>Enter your city to find nearby tasks (e.g. San Francisco, CA or Melbourne, Australia): </h3><br> <input type="text" name="address" id="userAddress"/><br> <span id="submitUserForm">Search</span><br> </form><br></div><br><div class="acceptedTaskLink clickable">You have already accepted a task! Click here to view instructions</div><br><div class="mapInstructions"><h3>Click on an orange flag to preview a task.</h3></div><br><div class="loading">Loading</div><br><div id="map"></div><br><!--Stores the actual content of the popup divs--><br><div class="popupContent"><br> <div class="splash"><br> <div class="topBar"><span class="close popupButton">x</span></div><br> <div class="content"><br> <p>In this task, you will drive to a given location and answer questions about the area. To perform this task, you must:<br> <ol><br> <li>Choose a location from the map interface</li><br> <li>Print out or write down a short form containing questions about the physical location</li><br> <li>Within 24 hours, <b>drive to the chosen location</b> and answer the questions about the location</li><br> <li>Take pictures of the area <b>using a digital camera</b></li><br> <li>Return to this task, enter in the information you collected, and upload your photos</li><br> <li>Submit the task</li><br> </ol><br> </p><br> <p>You've now accepted the Task through Mechanical Turk, but you now need to accept a particular location in our map interface.<br> To continue, please select one of the following:</p><br> <div class="buttons"><br> <div class="clickable returning">I previously accepted a task here and just need to submit my answer</div><br> <div class="clickable new">I need to browse through the available tasks</div><br> </div><br> </div><br> </div><br> <br> <div class="preview"><br> <div class="topBar"><span class="close popupButton">x</span></div><br> <div class="content"><br> <p><br> <h3>IMPORTANT: After accepting this task AND accepting a location, you will have 24 hours to drive to the location, take photos, and return to your computer to submit the answers.</h3><br> <h3>It may take up to 48 hours to approve your results.</h3><br> </p><br> <p>In this task, you will drive to a given location and answer questions about the area. To perform this task, you must:<br> <ol><br> <li>Choose a location from the map interface</li><br> <li>Print out or write down a short form containing questions about the physical location</li><br> <li>Within 24 hours, <b>drive to the chosen location</b> and answer the questions about the location</li><br> <li>Take pictures of the area <b>using a digital camera</b></li><br> <li>Return to this task, enter in the information you collected, and upload your photos</li><br> <li>Submit the task</li><br> </ol><br> </p><br> <p>Before you accept this task, you should see if any tasks are available in your location. Click the Preview button below to search for tasks in your area.<br> If you find a task that you want to accept, you need to then click the yellow Accept button in the Mechanical Turk inteface (above this frame).</p><br> <div class="clickable preview small">Preview</div><br> </div><br> </div> <br> <br> <div class="confirmReturnUnit"><br> <div class="topBar"><span class="close popupButton">x</span></div><br> <div class="content"><br> You've already accepted a task! Are you sure you want to also accept another one? Make sure you've printed out details of the first task before you accept the next one!<br> </div><br> <div class="buttons"><br> <div class="confirm clickable">I've already printed out details of my last task and want <b>also</b> to accept another one</div><br> <div class="vertPadding"></div><br> <div class="cancel clickable">Never mind, bring me back to the last task I accepted</div><br> </div><br> </div><br> <br> <div class="simpleUnitView"><br> <div class="topBar"><span class="close popupButton">x</span></div><br> <div class="content"><br> <div class="image1">{img1html}</div><br><br> <b>Address:</b> {address}<br><br> <b>City:</b> {city}<br><br> <b>State:</b> {state}<br><br> <b>Country:</b> {country}<br><br> {unitMapLink}<br> </div><br> <div class="previewInstructions"><br> You must accept the task by pressing the yellow "Accept" button above this frame (in the Amazon interface) before you can choose this location for your task.<br> </div><br> <div class="viewMore clickable small">Proceed</div><br> </div><br> <div class="advUnitView"><br> <div class="topBar"><span class="close popupButton">x</span></div><br> <div class="content"><br> <div class="imageHolder"><br> <div class="image1">{img1html}</div><br> <div class="image2">{img2html}</div><br> </div><br> <div class="text"><br> <b>Lat:</b> {Lat}<br><br> <b>Lon:</b> {Lon}<br><br> <b>Street Name:</b> {address}<br><br> <b>City:</b> {city}<br><br> <b>State:</b> {state}<br><br> <b>Country:</b> {country}<br><br> {unitMapLink}<br> </div><br> <div class="instructions"><br> <p>To complete this task, you will need to drive to the specified location with a digital camera and a printout of a short (one-page) questionnaire about the area.<br> To accept the task and display a printable questionnaire to answer about the location, click the button below.</p><br> <p><b>DISCLAIMER: You need to drive to the location and take and upload a JPEG digital photo of the specified location to complete this task.</b></p><br> </div><br> <div class="accept clickable small">Accept this task</div><br> </div><br> </div><br> <br> <div class="checkUnitId"><br> <div class="topBar"><span class="close popupButton">x</span></div><br> <div class="content"><br> <h1>Enter in the UNIT ID code given to you earlier. You must have the UNIT ID to continue with the task:</h1><br> Unit Id: <input type="text" name="unitId" class="unitId hidden"/><br> <table><br> <tr><br> <td> <div class="clickable small checkUnitId">Proceed</div> </td><br> <td> <div class="clickable small cancel">Cancel</div> </td><br> </tr><br> </table><br> </div><br> </div><br> <br> <div class="submittableForm"><br> <div class="topBar"><span class="close popupButton">x</span></div><br> <div class="instructions"><br> <h1>Before submitting the form, make sure that the below information is the correct location (the one that you drove to).</h1><br> <h2>Unit ID:{unitId}</h2><br> <b>Lat:</b> {Lat}<br><br> <b>Lon:</b> {Lon}<br><br> <b>Street Name:</b> {address}<br><br> <b>City:</b> {city}<br><br> <b>State:</b> {state}<br><br> <b>Country:</b> {country}<br><br> <p>Please be <b>as descriptive as possible</b> in your answers!</p><br> <p>Note that it may take up to 48 hours before your work is approved and you are paid. Your work will be manually verified.</p><br> </div><br> <div class="content"><br> <form method="POST"><br> <input type="hidden" name="started_at" class="started_at" value=""/><br> <div class="uploader"><br> <h3>File upload</h3><br> <div class="uploadStatus"><br> <a href="#" class="browse">Choose images of the road</a><br> <div><br> <div class="current-title"></div><br> <img src="/images/progress-bar/bar.gif" class="progress current-progress" /><br> </div><br> <div class="current-text" style="display:none"></div><br> <div><br> <div class="overall-title"></div><br> <img src="/images/progress-bar/bar.gif" class="progress overall-progress" /><br> <ul class="list"></ul><br> </div><br> <input type="button" class="upload" value="Upload these images" style="display:none"/><br> </div><br> </div><br> <div class="vertPadding"></div> <br> </form><br> </div><br> </div><br> <br> <div class="printableForm"><br> <div class="topBar"><span class="close popupButton">x</span></div><br> <div class="instructions"><br> <h1>Print out a copy of these questions. Make sure you write down the UNIT ID, or you will not be able to submit your answers and get paid. Read and follow the instructions carefully!</h1><br> <h2>Unit ID:{unitId}</h2><br> <h3><br> Instructions:<br> <ol><br> <li>Drive to the location shown in the map and specified in the below details.</li><br> <li>Bring a digital camera and a copy of these questions. A digital camera that geotags images (stores the location where they were taken) is preferred, if you have access to one (don't worry--you'll still get paid if you use a regular digital camera). Please use the highest resolution and quality possible on your camera.</li><br> <li>See if there is a street at the location shown in the map with the name given below.</li><br> <li>If so, take a picture of the street and the corresponding street sign containing the name of the street</li><br> <li>EITHER WAY, take <b>at least 4 pictures</b> of the area around the latitude/longtitude position given. Take one photo in each direction (North, East, South, West). <b>IMPORTANT:</b> When taking these four photos, please write on a piece of paper the direction (North, East, etc.) in which you are taking the given photo and then hold this label in the picture. For an example, <a href="http://a1.doloreslabs.com/q82/examples/ex_img_map.JPG">click here</a>.</li><br> <li>If the street mentioned in the task is nearby but not at the latitude/longitude specified, please take a picture of the street sign and make note of the location in as much detail as possible.</li><br> <li>Take as many other pictures as possible to fully provide an understanding of the location and the streets there.</li><br> <li>Answer the questions below for the street and the area around it (the area to consider for this task extends to the edges of the first map image given)</li><br> <li>After you have the answers and photos of the street, refresh the page and choose the option, "I previously accepted a task here and just need to submit my answer".<br> Then enter in the Unit ID ({unitId}).</li><br> <br> </ol><br> <p><br> After you've printed the instructions for the task, if you'd like to accept another location in addition to this one (and do both), click the black X on the right side of the green bar above. Then choose another location by clicking an orange marker.<br> </p><br> </h3><br> <b>Lat:</b> {Lat}<br><br> <b>Lon:</b> {Lon}<br><br> <b>Street Name:</b> {address}<br><br> <b>City:</b> {city}<br><br> <b>State:</b> {state}<br><br> <b>Country:</b> {country}<br><br> {unitMapLink}<br> <div class="imageHolder"><br> <div class="image1">{img1html}</div><br> <div class="image2">{img2html}</div><br> </div><br> </div><br> <div class="content"><br> </div><br> </div><br></div><cml:text label="Text"/>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
describe "CML Normalize" do
|
5
|
+
it "normalizes everything to checkboxes or text inputs" do
|
6
|
+
@p = Parser.new(<<-HTML, {:prefix => "u12345", :normalize => true})
|
7
|
+
<cml:select label="Awesome" validates="required" default="Choose an option" instructions="Just be cool about it">
|
8
|
+
<cml:gold src="awesome_gold" regex="\\.asdf\\." flags="i" strict="true" />
|
9
|
+
<cml:option label="Awesome" />
|
10
|
+
<cml:option label="Cool" />
|
11
|
+
<cml:option label="Rad" />
|
12
|
+
<cml:option label="Neat" />
|
13
|
+
</cml:select>
|
14
|
+
<cml:text label="Opinion" validates="minLength:30" class="large" />
|
15
|
+
<cml:radios label="Hot">
|
16
|
+
<cml:radio label="For sure"/>
|
17
|
+
<cml:radio label="Not" />
|
18
|
+
</cml:radios>
|
19
|
+
<cml:meta label="Neat" gold="true"/>
|
20
|
+
HTML
|
21
|
+
#puts Parser.escape(@p.to_html).gsub(/\n/,"<br/>")
|
22
|
+
@p.to_html.should sorta_match(<<-HTML)
|
23
|
+
<div class="cml" id="u12345">
|
24
|
+
<div class="checkboxes">
|
25
|
+
<h2 class="legend">Awesome</h2>
|
26
|
+
<label><input name="u12345[awesome][]" class="awesome validates-required" value="Awesome" type="checkbox" /> Awesome</label>
|
27
|
+
<label><input name="u12345[awesome][]" class="awesome validates-required" value="Cool" type="checkbox" /> Cool</label>
|
28
|
+
<label><input name="u12345[awesome][]" class="awesome validates-required" value="Rad" type="checkbox" /> Rad</label>
|
29
|
+
<label><input name="u12345[awesome][]" class="awesome validates-required" value="Neat" type="checkbox" /> Neat</label>
|
30
|
+
<p class="instructions">Just be cool about it</p>
|
31
|
+
</div>
|
32
|
+
<div class="text"><label class="legend">Opinion</label>
|
33
|
+
<input name="u12345[opinion]" class="opinion validates-minLength:30 large" value="" type="text" />
|
34
|
+
</div>
|
35
|
+
<div class="checkboxes">
|
36
|
+
<h2 class="legend">Hot</h2>
|
37
|
+
<label><input name="u12345[hot][]" class="hot" value="For sure" type="checkbox" /> For sure</label>
|
38
|
+
<label><input name="u12345[hot][]" class="hot" value="Not" type="checkbox" /> Not</label>
|
39
|
+
</div>
|
40
|
+
<div class="text">
|
41
|
+
<label class="legend">Neat</label>
|
42
|
+
<input name="u12345[neat]" class="neat" value="" type="text" />
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
HTML
|
46
|
+
end
|
47
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dolores-cml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Van Pelt
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09-
|
12
|
+
date: 2009-09-07 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -82,7 +82,9 @@ files:
|
|
82
82
|
- spec/fixtures/complex.cml
|
83
83
|
- spec/fixtures/html.cml
|
84
84
|
- spec/fixtures/invalid.cml
|
85
|
+
- spec/fixtures/segfault.cml
|
85
86
|
- spec/meta_spec.rb
|
87
|
+
- spec/normalize_spec.rb
|
86
88
|
- spec/sorta_match.rb
|
87
89
|
- spec/spec_helper.rb
|
88
90
|
- spec/tags/checkbox_spec.rb
|
@@ -98,7 +100,6 @@ files:
|
|
98
100
|
- spec/validation_spec.rb
|
99
101
|
has_rdoc: false
|
100
102
|
homepage: http://github.com/dolores/cml
|
101
|
-
licenses:
|
102
103
|
post_install_message:
|
103
104
|
rdoc_options:
|
104
105
|
- --charset=UTF-8
|
@@ -119,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
120
|
requirements: []
|
120
121
|
|
121
122
|
rubyforge_project:
|
122
|
-
rubygems_version: 1.
|
123
|
+
rubygems_version: 1.2.0
|
123
124
|
signing_key:
|
124
125
|
specification_version: 3
|
125
126
|
summary: CML is CrowdFlower Markup Language
|
@@ -127,6 +128,7 @@ test_files:
|
|
127
128
|
- spec/complex_spec.rb
|
128
129
|
- spec/converters/jsawesome_spec.rb
|
129
130
|
- spec/meta_spec.rb
|
131
|
+
- spec/normalize_spec.rb
|
130
132
|
- spec/sorta_match.rb
|
131
133
|
- spec/spec_helper.rb
|
132
134
|
- spec/tags/checkbox_spec.rb
|