scheduled_resource 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +136 -0
- data/Rakefile +2 -0
- data/bin/schedulize +173 -0
- data/lib/assets/javascripts/blank.jpg +0 -0
- data/lib/assets/javascripts/justify_tweaks.js +186 -0
- data/lib/assets/javascripts/time_pix.js.coffee +103 -0
- data/lib/assets/javascripts/use_block.js.coffee +131 -0
- data/lib/assets/stylesheets/scheduled_resource.css.scss +250 -0
- data/lib/scheduled_resource.rb +262 -0
- data/lib/scheduled_resource/helper.rb +65 -0
- data/lib/scheduled_resource/resource_use_block.rb +33 -0
- data/lib/scheduled_resource/version.rb +3 -0
- data/lib/z_time_header.rb +20 -0
- data/lib/z_time_header_day.rb +16 -0
- data/lib/z_time_header_hour.rb +15 -0
- data/lib/z_time_label.rb +88 -0
- data/lib/z_time_label_day.rb +23 -0
- data/lib/z_time_label_hour.rb +26 -0
- data/scheduled_resource.gemspec +25 -0
- metadata +178 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
class @TimePix # Ultimately, an angular $service
|
2
|
+
constructor: -> null
|
3
|
+
|
4
|
+
@scroll_container: -> $('#scrolling-container')
|
5
|
+
|
6
|
+
@set_display_parms: => # bound
|
7
|
+
@pixWindow = parseInt(window.innerWidth) - 110
|
8
|
+
@scroll_container().css( 'width', @pixWindow + 'px' )
|
9
|
+
$('#scrollbar-hider').css('width', @pixWindow + 61 + 'px' )
|
10
|
+
|
11
|
+
|
12
|
+
@baseTime: 0
|
13
|
+
@timeWindow: (3 * 3600)
|
14
|
+
@pixWindow: 750 # Matching width of #scrolling-container
|
15
|
+
|
16
|
+
# Time range [@tlo..@thi] is where the DOM has data.
|
17
|
+
@tlo: null
|
18
|
+
@thi: null
|
19
|
+
|
20
|
+
# Meta-data about most recent request
|
21
|
+
@meta: {}
|
22
|
+
|
23
|
+
@merge_metadata: (data) ->
|
24
|
+
@meta = data.meta
|
25
|
+
@baseTime ||= @meta['min_time']
|
26
|
+
@tlo = @tlo && Math.min( @tlo, @meta.t1 ) || @meta.t1
|
27
|
+
@thi = @thi && Math.max( @thi, @meta.t2 ) || @meta.t2
|
28
|
+
@inc = @meta.inc
|
29
|
+
@timeWindow = @meta.visible_time if @meta.visible_time
|
30
|
+
|
31
|
+
@next_hi: -> @thi + @timeWindow
|
32
|
+
@next_lo: -> @tlo - @timeWindow
|
33
|
+
|
34
|
+
# Ignoring @baseTime offset
|
35
|
+
@secs_to_pix_scale: (seconds) ->
|
36
|
+
pix = seconds * @pixWindow / @timeWindow
|
37
|
+
# Math.round(pix * 100) / 100
|
38
|
+
|
39
|
+
@pix_to_secs: (pix) ->
|
40
|
+
@baseTime + Math.round(pix * @timeWindow / @pixWindow)
|
41
|
+
|
42
|
+
@style_geo: (block) ->
|
43
|
+
[s, e] = [block.starttime, block.endtime] # per margins V
|
44
|
+
"left: #{@secs_to_pix_scale(s - @baseTime)}px; " +
|
45
|
+
"width: #{@secs_to_pix_scale(e-s)-4}px;"
|
46
|
+
|
47
|
+
@row_kind: (tag) -> # may/may not belong here.
|
48
|
+
tag.split('_')[0]
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
@ux_time_now: ->
|
54
|
+
new Date().valueOf() / 1000
|
55
|
+
|
56
|
+
@ux_time_offset: (uxt) ->
|
57
|
+
uxt - @baseTime
|
58
|
+
|
59
|
+
@ux_time_offset_pix: (uxt) ->
|
60
|
+
@secs_to_pix_scale @ux_time_offset(uxt)
|
61
|
+
|
62
|
+
@scroll_to_ux_time: (uxt) ->
|
63
|
+
sc = @scroll_container()
|
64
|
+
sc.scrollLeft( @ux_time_offset_pix(uxt) )
|
65
|
+
|
66
|
+
@scroll_to_thi: ->
|
67
|
+
@scroll_to_ux_time( @thi - @timeWindow )
|
68
|
+
|
69
|
+
@ux_time_of_pix: (x) ->
|
70
|
+
@pix_to_secs(x)
|
71
|
+
|
72
|
+
@scroll_to_tlo: => # bound
|
73
|
+
@scroll_to_ux_time @tlo
|
74
|
+
|
75
|
+
@set_time_cursor: => # bound
|
76
|
+
cursor = $('#current-time-cursor')
|
77
|
+
now_offset = @ux_time_offset_pix( @ux_time_now() );
|
78
|
+
cursor.css( 'left', now_offset + 'px' )
|
79
|
+
setTimeout( @set_time_cursor, 15 * 1000 )
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
@scroll_monitor: =>
|
84
|
+
sc = @scroll_container()
|
85
|
+
if @scroll_monitor.old_scroll != sc.scrollLeft()
|
86
|
+
@scroll_monitor.old_scroll = sc.scrollLeft()
|
87
|
+
@scroll_monitor.scroll_timestamp = new Date()
|
88
|
+
|
89
|
+
# Fetch more data if needed
|
90
|
+
l_vis_time = @pix_to_secs sc.scrollLeft()
|
91
|
+
r_vis_time = l_vis_time + @timeWindow
|
92
|
+
|
93
|
+
if r_vis_time > @thi
|
94
|
+
RsrcListCtrlScope.$apply RsrcListCtrlScope.more_data
|
95
|
+
else if l_vis_time < @tlo
|
96
|
+
RsrcListCtrlScope.$apply RsrcListCtrlScope.less_data
|
97
|
+
else
|
98
|
+
if new Date() - @scroll_monitor.scroll_timestamp > 1000
|
99
|
+
filter_justify_tweaks( sc ) # Try to make scrolled-off content visible
|
100
|
+
@scroll_monitor.scroll_timestamp = new Date()
|
101
|
+
|
102
|
+
setTimeout @scroll_monitor, 100
|
103
|
+
|
@@ -0,0 +1,131 @@
|
|
1
|
+
class @UseBlock
|
2
|
+
constructor: -> nil
|
3
|
+
|
4
|
+
|
5
|
+
class @ZTimeHeaderDayUseBlock extends UseBlock
|
6
|
+
constructor: -> nil
|
7
|
+
|
8
|
+
@process: (block) ->
|
9
|
+
@label block
|
10
|
+
@css_classes block
|
11
|
+
block
|
12
|
+
|
13
|
+
@label: (block) ->
|
14
|
+
block.label = block.title
|
15
|
+
|
16
|
+
@css_classes: (block) ->
|
17
|
+
# Could just as well come from server.
|
18
|
+
classes = 'ZTimeHeaderDayRow '
|
19
|
+
block.css_classes = classes
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
class @ZTimeHeaderHourUseBlock extends UseBlock
|
24
|
+
constructor: -> nil
|
25
|
+
|
26
|
+
@process: (block) ->
|
27
|
+
@label block
|
28
|
+
@css_classes block
|
29
|
+
block
|
30
|
+
|
31
|
+
@label: (block) ->
|
32
|
+
block.label = block.title
|
33
|
+
|
34
|
+
@css_classes: (block) ->
|
35
|
+
# Could just as well come from server.
|
36
|
+
# classes = 'ZTimeHeaderHourRow '
|
37
|
+
# block.css_classes = classes
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
# Uses these fields of block: title, subtitle, category, category_type,
|
46
|
+
# Sets these fields of block: label, css_classes
|
47
|
+
class @StationUseBlock extends UseBlock
|
48
|
+
constructor: -> nil
|
49
|
+
|
50
|
+
@process: (block) ->
|
51
|
+
@css_classes block
|
52
|
+
@label block
|
53
|
+
block
|
54
|
+
|
55
|
+
@label: (block) ->
|
56
|
+
block.label = block.title
|
57
|
+
block.label += ":<br> #{block.subtitle}" if block.subtitle
|
58
|
+
block.label += "<span class='flags'>#{@flags(block)}</span>"
|
59
|
+
|
60
|
+
@flags: (block) ->
|
61
|
+
flags = ''
|
62
|
+
flags += ' hd' if block.hdtv
|
63
|
+
flags += ' new' unless block.previouslyshown
|
64
|
+
flags
|
65
|
+
|
66
|
+
@css_classes: (block) ->
|
67
|
+
block.css_classes = @ct_name(block) + " " + @to_css_class(block.category)
|
68
|
+
|
69
|
+
|
70
|
+
@ct_name: (block) ->
|
71
|
+
ct = block.category_type || ''
|
72
|
+
return '' if /unknown/i.test ct
|
73
|
+
"type_#{ct.replace /[^a-z0-9\-_]+/gi, '_'}"
|
74
|
+
|
75
|
+
@to_css_class: (category, clss = null) ->
|
76
|
+
return clss if (clss = @memo[ category ])
|
77
|
+
@memo[ category ] = @css_class_search category
|
78
|
+
|
79
|
+
@css_class_search: (category) ->
|
80
|
+
for key, regex of @categories
|
81
|
+
return ('cat_' + key) if regex.test category
|
82
|
+
'cat_Unknown'
|
83
|
+
|
84
|
+
|
85
|
+
@memo: {}
|
86
|
+
|
87
|
+
@categories:
|
88
|
+
Action: /\b(action|adven)/i
|
89
|
+
Adult: /\b(adult|erot)/i
|
90
|
+
Animals: /\b(animal|tiere)/i
|
91
|
+
Art_Music: /\b(art|dance|music|cultur)/i
|
92
|
+
Business: /\b(biz|busine)/i
|
93
|
+
Children: /\b(child|infan|animation)/i
|
94
|
+
Comedy: /\b(comed|entertain|sitcom)/i
|
95
|
+
Crime_Mystery: /\b(crim|myster)/i
|
96
|
+
Documentary: /\b(doc)/i
|
97
|
+
Drama: /\b(drama)/i
|
98
|
+
Educational: /\b(edu|interests)/i
|
99
|
+
Food: /\b(food|cook|drink)/i
|
100
|
+
Game: /\b(game)/i
|
101
|
+
Health_Medical: /\b(health|medic)/i
|
102
|
+
History: /\b(hist)/i
|
103
|
+
Horror: /\b(horror)/i
|
104
|
+
HowTo: /\b(how|home|house|garden)/i
|
105
|
+
Misc: /\b(special|variety|info|collect)/i
|
106
|
+
News: /\b(news|current)/i
|
107
|
+
Reality: /\b(reality)/i
|
108
|
+
Romance: /\b(romance)/i
|
109
|
+
SciFi_Fantasy: /\b(fantasy|sci\\w*\\W*fi)/i
|
110
|
+
Science_Nature: /\b(science|nature|environm)/i
|
111
|
+
Shopping: /\b(shop)/i
|
112
|
+
Soaps: /\b(soaps)/i
|
113
|
+
Spiritual: /\b(spirit|relig)/i
|
114
|
+
Sports: /\b(sport)/i
|
115
|
+
Talk: /\b(talk)/i
|
116
|
+
Travel: /\b(travel)/i
|
117
|
+
War: /\b(war)/i
|
118
|
+
Western: /\b(west)/i
|
119
|
+
|
120
|
+
|
121
|
+
# console.log ChannelUseBlock.css_class_search('action')
|
122
|
+
# console.log ChannelUseBlock.to_css_class('action')
|
123
|
+
|
124
|
+
# block =
|
125
|
+
# category_type: 'series'
|
126
|
+
# category: 'adventure'
|
127
|
+
|
128
|
+
# block = {"airdate":0,"category":"Reality","category_type":"series","chanid":1791,"description":"Alexia enlists Troy's help to find her father.","endtime":"2013-03-04T12:00:00-08:00","first":true,"generic":false,"hdtv":false,"last":true,"listingsource":0,"manualid":0,"originalairdate":"2009-03-28","partnumber":0,"parttotal":0,"pid":"","previouslyshown":1,"programid":"EP010679340014","seriesid":"EP01067934","showtype":"Series","stars":0.0,"starttime":"2013-03-04T11:30:00-08:00","stereo":false,"subtitle":"A Daughter's Mission","subtitled":false,"syndicatedepisodenumber":"204","title":"The Locator"}
|
129
|
+
|
130
|
+
# console.log ChannelUseBlock.ct_name block
|
131
|
+
# console.log ChannelUseBlock.css_classes block
|
@@ -0,0 +1,250 @@
|
|
1
|
+
/* schedule.css.scss
|
2
|
+
Classes for scheduled_resource gem
|
3
|
+
- Mike Cannon (Mon Mar 4 '13)
|
4
|
+
(http://github.com/emeyekayee/tv4)
|
5
|
+
(michael.j.cannon@gmail.com)
|
6
|
+
*/
|
7
|
+
|
8
|
+
$bg-color: #1B3B5F;
|
9
|
+
/* #21456F; */
|
10
|
+
/* #002650; */
|
11
|
+
$daytime-bg: #33669E;
|
12
|
+
$nitetime-bg: #102441;
|
13
|
+
|
14
|
+
|
15
|
+
body {
|
16
|
+
border: 0;
|
17
|
+
margin: 10px;
|
18
|
+
padding: 0;
|
19
|
+
font-size: 11pt;
|
20
|
+
font-family: Arial, Helvetica, sans-serif;
|
21
|
+
background: $bg-color;
|
22
|
+
}
|
23
|
+
|
24
|
+
h2 { color: #204882 }
|
25
|
+
|
26
|
+
a:link { color: white; text-decoration: none;}
|
27
|
+
a:visited { color: white; text-decoration: none;}
|
28
|
+
|
29
|
+
|
30
|
+
.timespan {
|
31
|
+
position: absolute;
|
32
|
+
left: 0px;
|
33
|
+
}
|
34
|
+
|
35
|
+
.flags {
|
36
|
+
color: #ffff9b;
|
37
|
+
}
|
38
|
+
|
39
|
+
.blockdiv {
|
40
|
+
position: absolute;
|
41
|
+
border: 1px solid $bg-color;
|
42
|
+
font-size: 11px;
|
43
|
+
line-height: 1.2;
|
44
|
+
white-space: nowrap;
|
45
|
+
overflow: hidden;
|
46
|
+
}
|
47
|
+
|
48
|
+
#current-time-cursor {
|
49
|
+
border-left: 1px solid rgba(255,0,0,.65);
|
50
|
+
z-index: 1;
|
51
|
+
width: 1px;
|
52
|
+
height: 4000px;
|
53
|
+
position: absolute;
|
54
|
+
}
|
55
|
+
|
56
|
+
.text_locator {
|
57
|
+
position: absolute;
|
58
|
+
left: 2px;
|
59
|
+
right: 4px;
|
60
|
+
overflow: hidden;
|
61
|
+
}
|
62
|
+
|
63
|
+
#schedule-container{
|
64
|
+
position: relative;
|
65
|
+
}
|
66
|
+
|
67
|
+
#scrolling-container {
|
68
|
+
overflow-x: scroll;
|
69
|
+
padding-bottom: 1px;
|
70
|
+
vertical-align: top;
|
71
|
+
width: 750px;
|
72
|
+
border: 1px solid red;
|
73
|
+
}
|
74
|
+
|
75
|
+
#positioned-container {
|
76
|
+
overflow: hidden;
|
77
|
+
margin: 1px;
|
78
|
+
margin-top: 0px;
|
79
|
+
width: 140000px;
|
80
|
+
position: relative;
|
81
|
+
}
|
82
|
+
|
83
|
+
#labels-container {
|
84
|
+
width: 60px;
|
85
|
+
vertical-align: top;
|
86
|
+
position: absolute;
|
87
|
+
}
|
88
|
+
|
89
|
+
#timespans-container {
|
90
|
+
vertical-align: top;
|
91
|
+
position: absolute;
|
92
|
+
left: 65px;
|
93
|
+
}
|
94
|
+
|
95
|
+
#resource-labels {
|
96
|
+
position: relative;
|
97
|
+
padding-bottom: 2px;
|
98
|
+
left: 5px;
|
99
|
+
background: $bg-color;
|
100
|
+
border: 1px solid red;
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
#scrollbar-hider {
|
105
|
+
width: 811px; /* per #resource-labels + */
|
106
|
+
height: 20px; /* #scrolling-container */
|
107
|
+
background: $bg-color;
|
108
|
+
position: relative;
|
109
|
+
top: -20px;
|
110
|
+
left: 5px;
|
111
|
+
border-top: 1px solid red;
|
112
|
+
}
|
113
|
+
|
114
|
+
.rsrcRow {
|
115
|
+
display: block;
|
116
|
+
margin: 1px;
|
117
|
+
margin-left: 0px;
|
118
|
+
}
|
119
|
+
|
120
|
+
.rsrclabel {
|
121
|
+
position: absolute;
|
122
|
+
width: 56px;
|
123
|
+
border: 1px solid $bg-color;
|
124
|
+
background: transparent; /* #265990 */
|
125
|
+
font-weight: bold;
|
126
|
+
text-align: center;
|
127
|
+
color: white;
|
128
|
+
|
129
|
+
img {
|
130
|
+
position: absolute;
|
131
|
+
left: 0;
|
132
|
+
z-index: 0;
|
133
|
+
background: $bg-color;
|
134
|
+
}
|
135
|
+
|
136
|
+
> .label-text {
|
137
|
+
position: absolute;
|
138
|
+
z-index: 2;
|
139
|
+
color: rgba(255,255,255,.65); /* #fff */
|
140
|
+
text-align: center;
|
141
|
+
width: 56px;
|
142
|
+
}
|
143
|
+
|
144
|
+
// This is used to shelve a background image (if any) vs foreground label text.
|
145
|
+
> div.filter {
|
146
|
+
position: absolute;
|
147
|
+
background: $bg-color;
|
148
|
+
width: 56px;
|
149
|
+
z-index: 1;
|
150
|
+
opacity: 0.5;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
.ZTimeHeaderHourrow,
|
157
|
+
.ZTimeHeaderHourRow,
|
158
|
+
.ZTimeHeaderDayrow,
|
159
|
+
.ZTimeHeaderDayRow {
|
160
|
+
height: 22px;
|
161
|
+
|
162
|
+
.rsrclabel {
|
163
|
+
height: 22px;
|
164
|
+
width: 56px;
|
165
|
+
div {
|
166
|
+
font-size: 19px;
|
167
|
+
white-space: nowrap;
|
168
|
+
overflow: hidden;
|
169
|
+
text-align: center;
|
170
|
+
color: rgba(204, 204, 255, 0.5);
|
171
|
+
}
|
172
|
+
|
173
|
+
img {
|
174
|
+
height: 22px; /* Is "inherit" still a no go for IE ? */
|
175
|
+
width: 56px;
|
176
|
+
}
|
177
|
+
|
178
|
+
> div.filter {
|
179
|
+
height: 22px;
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
.text_locator {
|
184
|
+
text-align: center;
|
185
|
+
}
|
186
|
+
|
187
|
+
.blockdiv {
|
188
|
+
height: 18px;
|
189
|
+
padding: 2px;
|
190
|
+
background: #265990;
|
191
|
+
font-size: 14px;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
|
196
|
+
.ZTimeHeaderHourrow,
|
197
|
+
.ZTimeHeaderHourRow {
|
198
|
+
.blockdiv {
|
199
|
+
font-size: 12px;
|
200
|
+
padding-top: 4px;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
|
205
|
+
.ZTimeHeaderDayrow,
|
206
|
+
.ZTimeHeaderDayRow {
|
207
|
+
.blockdiv {
|
208
|
+
font-size: 16px;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
|
213
|
+
.blockdiv.ZTimeHeaderDayRow { /* background: $daytime-bg; */
|
214
|
+
background: -webkit-linear-gradient(left,
|
215
|
+
$nitetime-bg, $nitetime-bg 24%, $daytime-bg 26%,
|
216
|
+
$daytime-bg 74%, $nitetime-bg 76%, $nitetime-bg );
|
217
|
+
}
|
218
|
+
|
219
|
+
.blockdiv.dayTimeblock { background: $daytime-bg }
|
220
|
+
.blockdiv.niteTimeblock { background: $nitetime-bg }
|
221
|
+
|
222
|
+
|
223
|
+
// This is included as a model for adding a new scheduled resource type.
|
224
|
+
// In fact is it what is used for the tv4 example.
|
225
|
+
// .Stationrow {
|
226
|
+
// height: 36px;
|
227
|
+
|
228
|
+
// .rsrclabel {
|
229
|
+
// div {
|
230
|
+
// font-size: 16pt;
|
231
|
+
// }
|
232
|
+
|
233
|
+
// img {
|
234
|
+
// height: 36px; /* Is "inherit" still a no go for IE? */
|
235
|
+
// width: 56px;
|
236
|
+
// }
|
237
|
+
|
238
|
+
// > div.filter {
|
239
|
+
// height: 36px;
|
240
|
+
// }
|
241
|
+
|
242
|
+
// }
|
243
|
+
|
244
|
+
// .blockdiv {
|
245
|
+
// height: 32px;
|
246
|
+
// padding: 2px;
|
247
|
+
// }
|
248
|
+
// }
|
249
|
+
|
250
|
+
|