scheduled_resource 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|