event_cal 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/Rakefile +21 -0
  3. data/app/views/event_calendar/_calendar.html.haml +9 -0
  4. data/app/views/event_calendar/_date.html.haml +10 -0
  5. data/app/views/event_calendar/_event_details.html.haml +4 -0
  6. data/lib/event_calendar/calendar.rb +50 -0
  7. data/lib/event_calendar/calendar_helper.rb +45 -0
  8. data/lib/event_calendar/engine.rb +15 -0
  9. data/lib/event_calendar/event.rb +16 -0
  10. data/lib/event_calendar/version.rb +3 -0
  11. data/lib/event_calendar.rb +4 -0
  12. data/lib/tasks/event_calendar_tasks.rake +4 -0
  13. data/vendor/assets/images/calendar_next.png +0 -0
  14. data/vendor/assets/images/calendar_prev.png +0 -0
  15. data/vendor/assets/images/icon_config.png +0 -0
  16. data/vendor/assets/javascripts/calendarApplication.js.coffee +11 -0
  17. data/vendor/assets/javascripts/controllers/calendarDatesController.js.coffee +32 -0
  18. data/vendor/assets/javascripts/controllers/calendarEventsController.js.coffee +19 -0
  19. data/vendor/assets/javascripts/event_calendar.js +1117 -0
  20. data/vendor/assets/javascripts/event_calendar_no_libs.js +191 -0
  21. data/vendor/assets/javascripts/lib/moment.js +1 -0
  22. data/vendor/assets/javascripts/lib/spine.js.coffee +535 -0
  23. data/vendor/assets/javascripts/lib/spinelib/ajax.js.coffee +223 -0
  24. data/vendor/assets/javascripts/lib/spinelib/list.js.coffee +43 -0
  25. data/vendor/assets/javascripts/lib/spinelib/local.js.coffee +16 -0
  26. data/vendor/assets/javascripts/lib/spinelib/manager.js.coffee +83 -0
  27. data/vendor/assets/javascripts/lib/spinelib/relation.js.coffee +144 -0
  28. data/vendor/assets/javascripts/lib/spinelib/route.js.coffee +151 -0
  29. data/vendor/assets/javascripts/models/calendarDate.js.coffee +7 -0
  30. data/vendor/assets/javascripts/models/calendarEvent.js.coffee +11 -0
  31. data/vendor/assets/stylesheets/event_calendar.css.scss +251 -0
  32. metadata +274 -0
@@ -0,0 +1,535 @@
1
+ Events =
2
+ bind: (ev, callback) ->
3
+ evs = ev.split(' ')
4
+ calls = @hasOwnProperty('_callbacks') and @_callbacks or= {}
5
+
6
+ for name in evs
7
+ calls[name] or= []
8
+ calls[name].push(callback)
9
+ this
10
+
11
+ one: (ev, callback) ->
12
+ @bind ev, ->
13
+ @unbind(ev, arguments.callee)
14
+ callback.apply(this, arguments)
15
+
16
+ trigger: (args...) ->
17
+ ev = args.shift()
18
+
19
+ list = @hasOwnProperty('_callbacks') and @_callbacks?[ev]
20
+ return unless list
21
+
22
+ for callback in list
23
+ if callback.apply(this, args) is false
24
+ break
25
+ true
26
+
27
+ unbind: (ev, callback) ->
28
+ unless ev
29
+ @_callbacks = {}
30
+ return this
31
+
32
+ list = @_callbacks?[ev]
33
+ return this unless list
34
+
35
+ unless callback
36
+ delete @_callbacks[ev]
37
+ return this
38
+
39
+ for cb, i in list when cb is callback
40
+ list = list.slice()
41
+ list.splice(i, 1)
42
+ @_callbacks[ev] = list
43
+ break
44
+ this
45
+
46
+ Log =
47
+ trace: true
48
+
49
+ logPrefix: '(App)'
50
+
51
+ log: (args...) ->
52
+ return unless @trace
53
+ if @logPrefix then args.unshift(@logPrefix)
54
+ console?.log?(args...)
55
+ this
56
+
57
+ moduleKeywords = ['included', 'extended']
58
+
59
+ class Module
60
+ @include: (obj) ->
61
+ throw new Error('include(obj) requires obj') unless obj
62
+ for key, value of obj when key not in moduleKeywords
63
+ @::[key] = value
64
+ obj.included?.apply(this)
65
+ this
66
+
67
+ @extend: (obj) ->
68
+ throw new Error('extend(obj) requires obj') unless obj
69
+ for key, value of obj when key not in moduleKeywords
70
+ @[key] = value
71
+ obj.extended?.apply(this)
72
+ this
73
+
74
+ @proxy: (func) ->
75
+ => func.apply(this, arguments)
76
+
77
+ proxy: (func) ->
78
+ => func.apply(this, arguments)
79
+
80
+ constructor: ->
81
+ @init?(arguments...)
82
+
83
+ class Model extends Module
84
+ @extend Events
85
+
86
+ @records: {}
87
+ @crecords: {}
88
+ @attributes: []
89
+
90
+ @configure: (name, attributes...) ->
91
+ @className = name
92
+ @records = {}
93
+ @crecords = {}
94
+ @attributes = attributes if attributes.length
95
+ @attributes and= makeArray(@attributes)
96
+ @attributes or= []
97
+ @unbind()
98
+ this
99
+
100
+ @toString: -> "#{@className}(#{@attributes.join(", ")})"
101
+
102
+ @find: (id) ->
103
+ record = @records[id]
104
+ if !record and ("#{id}").match(/c-\d+/)
105
+ return @findCID(id)
106
+ throw new Error('Unknown record') unless record
107
+ record.clone()
108
+
109
+ @findCID: (cid) ->
110
+ record = @crecords[cid]
111
+ throw new Error('Unknown record') unless record
112
+ record.clone()
113
+
114
+ @exists: (id) ->
115
+ try
116
+ return @find(id)
117
+ catch e
118
+ return false
119
+
120
+ @refresh: (values, options = {}) ->
121
+ if options.clear
122
+ @records = {}
123
+ @crecords = {}
124
+
125
+ records = @fromJSON(values)
126
+ records = [records] unless isArray(records)
127
+
128
+ for record in records
129
+ record.id or= record.cid
130
+ @records[record.id] = record
131
+ @crecords[record.cid] = record
132
+
133
+ @trigger('refresh', @cloneArray(records))
134
+ this
135
+
136
+ @select: (callback) ->
137
+ result = (record for id, record of @records when callback(record))
138
+ @cloneArray(result)
139
+
140
+ @findByAttribute: (name, value) ->
141
+ for id, record of @records
142
+ if record[name] is value
143
+ return record.clone()
144
+ null
145
+
146
+ @findAllByAttribute: (name, value) ->
147
+ @select (item) ->
148
+ item[name] is value
149
+
150
+ @each: (callback) ->
151
+ for key, value of @records
152
+ callback(value.clone())
153
+
154
+ @all: ->
155
+ @cloneArray(@recordsValues())
156
+
157
+ @first: ->
158
+ record = @recordsValues()[0]
159
+ record?.clone()
160
+
161
+ @last: ->
162
+ values = @recordsValues()
163
+ record = values[values.length - 1]
164
+ record?.clone()
165
+
166
+ @count: ->
167
+ @recordsValues().length
168
+
169
+ @deleteAll: ->
170
+ for key, value of @records
171
+ delete @records[key]
172
+
173
+ @destroyAll: ->
174
+ for key, value of @records
175
+ @records[key].destroy()
176
+
177
+ @update: (id, atts, options) ->
178
+ @find(id).updateAttributes(atts, options)
179
+
180
+ @create: (atts, options) ->
181
+ record = new @(atts)
182
+ record.save(options)
183
+
184
+ @destroy: (id, options) ->
185
+ @find(id).destroy(options)
186
+
187
+ @change: (callbackOrParams) ->
188
+ if typeof callbackOrParams is 'function'
189
+ @bind('change', callbackOrParams)
190
+ else
191
+ @trigger('change', callbackOrParams)
192
+
193
+ @fetch: (callbackOrParams) ->
194
+ if typeof callbackOrParams is 'function'
195
+ @bind('fetch', callbackOrParams)
196
+ else
197
+ @trigger('fetch', callbackOrParams)
198
+
199
+ @toJSON: ->
200
+ @recordsValues()
201
+
202
+ @fromJSON: (objects) ->
203
+ return unless objects
204
+ if typeof objects is 'string'
205
+ objects = JSON.parse(objects)
206
+ if isArray(objects)
207
+ (new @(value) for value in objects)
208
+ else
209
+ new @(objects)
210
+
211
+ @fromForm: ->
212
+ (new this).fromForm(arguments...)
213
+
214
+ # Private
215
+
216
+ @recordsValues: ->
217
+ result = []
218
+ for key, value of @records
219
+ result.push(value)
220
+ result
221
+
222
+ @cloneArray: (array) ->
223
+ (value.clone() for value in array)
224
+
225
+ @idCounter: 0
226
+
227
+ @uid: (prefix = '') ->
228
+ uid = prefix + @idCounter++
229
+ uid = @uid(prefix) if @exists(uid)
230
+ uid
231
+
232
+ # Instance
233
+
234
+ constructor: (atts) ->
235
+ super
236
+ @load atts if atts
237
+ @cid = @constructor.uid('c-')
238
+
239
+ isNew: ->
240
+ not @exists()
241
+
242
+ isValid: ->
243
+ not @validate()
244
+
245
+ validate: ->
246
+
247
+ load: (atts) ->
248
+ for key, value of atts
249
+ if typeof @[key] is 'function'
250
+ @[key](value)
251
+ else
252
+ @[key] = value
253
+ this
254
+
255
+ attributes: ->
256
+ result = {}
257
+ for key in @constructor.attributes when key of this
258
+ if typeof @[key] is 'function'
259
+ result[key] = @[key]()
260
+ else
261
+ result[key] = @[key]
262
+ result.id = @id if @id
263
+ result
264
+
265
+ eql: (rec) ->
266
+ !!(rec and rec.constructor is @constructor and
267
+ (rec.cid is @cid) or (rec.id and rec.id is @id))
268
+
269
+ save: (options = {}) ->
270
+ unless options.validate is false
271
+ error = @validate()
272
+ if error
273
+ @trigger('error', error)
274
+ return false
275
+
276
+ @trigger('beforeSave', options)
277
+ record = if @isNew() then @create(options) else @update(options)
278
+ @trigger('save', options)
279
+ record
280
+
281
+ updateAttribute: (name, value, options) ->
282
+ @[name] = value
283
+ @save(options)
284
+
285
+ updateAttributes: (atts, options) ->
286
+ @load(atts)
287
+ @save(options)
288
+
289
+ changeID: (id) ->
290
+ records = @constructor.records
291
+ records[id] = records[@id]
292
+ delete records[@id]
293
+ @id = id
294
+ @save()
295
+
296
+ destroy: (options = {}) ->
297
+ @trigger('beforeDestroy', options)
298
+ delete @constructor.records[@id]
299
+ delete @constructor.crecords[@cid]
300
+ @destroyed = true
301
+ @trigger('destroy', options)
302
+ @trigger('change', 'destroy', options)
303
+ @unbind()
304
+ this
305
+
306
+ dup: (newRecord) ->
307
+ result = new @constructor(@attributes())
308
+ if newRecord is false
309
+ result.cid = @cid
310
+ else
311
+ delete result.id
312
+ result
313
+
314
+ clone: ->
315
+ createObject(this)
316
+
317
+ reload: ->
318
+ return this if @isNew()
319
+ original = @constructor.find(@id)
320
+ @load(original.attributes())
321
+ original
322
+
323
+ toJSON: ->
324
+ @attributes()
325
+
326
+ toString: ->
327
+ "<#{@constructor.className} (#{JSON.stringify(this)})>"
328
+
329
+ fromForm: (form) ->
330
+ result = {}
331
+ for key in $(form).serializeArray()
332
+ result[key.name] = key.value
333
+ @load(result)
334
+
335
+ exists: ->
336
+ @id && @id of @constructor.records
337
+
338
+ # Private
339
+
340
+ update: (options) ->
341
+ @trigger('beforeUpdate', options)
342
+ records = @constructor.records
343
+ records[@id].load @attributes()
344
+ clone = records[@id].clone()
345
+ clone.trigger('update', options)
346
+ clone.trigger('change', 'update', options)
347
+ clone
348
+
349
+ create: (options) ->
350
+ @trigger('beforeCreate', options)
351
+ @id = @cid unless @id
352
+
353
+ record = @dup(false)
354
+ @constructor.records[@id] = record
355
+ @constructor.crecords[@cid] = record
356
+
357
+ clone = record.clone()
358
+ clone.trigger('create', options)
359
+ clone.trigger('change', 'create', options)
360
+ clone
361
+
362
+ bind: (events, callback) ->
363
+ @constructor.bind events, binder = (record) =>
364
+ if record && @eql(record)
365
+ callback.apply(this, arguments)
366
+ @constructor.bind 'unbind', unbinder = (record) =>
367
+ if record && @eql(record)
368
+ @constructor.unbind(events, binder)
369
+ @constructor.unbind('unbind', unbinder)
370
+ binder
371
+
372
+ one: (events, callback) ->
373
+ binder = @bind events, =>
374
+ @constructor.unbind(events, binder)
375
+ callback.apply(this, arguments)
376
+
377
+ trigger: (args...) ->
378
+ args.splice(1, 0, this)
379
+ @constructor.trigger(args...)
380
+
381
+ unbind: ->
382
+ @trigger('unbind')
383
+
384
+ class Controller extends Module
385
+ @include Events
386
+ @include Log
387
+
388
+ eventSplitter: /^(\S+)\s*(.*)$/
389
+ tag: 'div'
390
+
391
+ constructor: (options) ->
392
+ @options = options
393
+
394
+ for key, value of @options
395
+ @[key] = value
396
+
397
+ @el = document.createElement(@tag) unless @el
398
+ @el = $(@el)
399
+ @$el = @el
400
+
401
+ @el.addClass(@className) if @className
402
+ @el.attr(@attributes) if @attributes
403
+
404
+ @events = @constructor.events unless @events
405
+ @elements = @constructor.elements unless @elements
406
+
407
+ @delegateEvents(@events) if @events
408
+ @refreshElements() if @elements
409
+
410
+ super
411
+
412
+ release: =>
413
+ @trigger 'release'
414
+ @el.remove()
415
+ @unbind()
416
+
417
+ $: (selector) -> $(selector, @el)
418
+
419
+ delegateEvents: (events) ->
420
+ for key, method of events
421
+
422
+ if typeof(method) is 'function'
423
+ # Always return true from event handlers
424
+ method = do (method) => =>
425
+ method.apply(this, arguments)
426
+ true
427
+ else
428
+ unless @[method]
429
+ throw new Error("#{method} doesn't exist")
430
+
431
+ method = do (method) => =>
432
+ @[method].apply(this, arguments)
433
+ true
434
+
435
+ match = key.match(@eventSplitter)
436
+ eventName = match[1]
437
+ selector = match[2]
438
+
439
+ if selector is ''
440
+ @el.bind(eventName, method)
441
+ else
442
+ @el.delegate(selector, eventName, method)
443
+
444
+ refreshElements: ->
445
+ for key, value of @elements
446
+ @[value] = @$(key)
447
+
448
+ delay: (func, timeout) ->
449
+ setTimeout(@proxy(func), timeout || 0)
450
+
451
+ html: (element) ->
452
+ @el.html(element.el or element)
453
+ @refreshElements()
454
+ @el
455
+
456
+ append: (elements...) ->
457
+ elements = (e.el or e for e in elements)
458
+ @el.append(elements...)
459
+ @refreshElements()
460
+ @el
461
+
462
+ appendTo: (element) ->
463
+ @el.appendTo(element.el or element)
464
+ @refreshElements()
465
+ @el
466
+
467
+ prepend: (elements...) ->
468
+ elements = (e.el or e for e in elements)
469
+ @el.prepend(elements...)
470
+ @refreshElements()
471
+ @el
472
+
473
+ replace: (element) ->
474
+ [previous, @el] = [@el, $(element.el or element)]
475
+ previous.replaceWith(@el)
476
+ @delegateEvents(@events)
477
+ @refreshElements()
478
+ @el
479
+
480
+ # Utilities & Shims
481
+
482
+ $ = window?.jQuery or window?.Zepto or (element) -> element
483
+
484
+ createObject = Object.create or (o) ->
485
+ Func = ->
486
+ Func.prototype = o
487
+ new Func()
488
+
489
+ isArray = (value) ->
490
+ Object::toString.call(value) is '[object Array]'
491
+
492
+ isBlank = (value) ->
493
+ return true unless value
494
+ return false for key of value
495
+ true
496
+
497
+ makeArray = (args) ->
498
+ Array::slice.call(args, 0)
499
+
500
+ # Globals
501
+
502
+ Spine = @Spine = {}
503
+ module?.exports = Spine
504
+
505
+ Spine.version = '1.0.8'
506
+ Spine.isArray = isArray
507
+ Spine.isBlank = isBlank
508
+ Spine.$ = $
509
+ Spine.Events = Events
510
+ Spine.Log = Log
511
+ Spine.Module = Module
512
+ Spine.Controller = Controller
513
+ Spine.Model = Model
514
+
515
+ # Global events
516
+
517
+ Module.extend.call(Spine, Events)
518
+
519
+ # JavaScript compatability
520
+
521
+ Module.create = Module.sub =
522
+ Controller.create = Controller.sub =
523
+ Model.sub = (instances, statics) ->
524
+ class Result extends this
525
+ Result.include(instances) if instances
526
+ Result.extend(statics) if statics
527
+ Result.unbind?()
528
+ Result
529
+
530
+ Model.setup = (name, attributes = []) ->
531
+ class Instance extends this
532
+ Instance.configure(name, attributes...)
533
+ Instance
534
+
535
+ Spine.Class = Module