incorporated AMD into the main application
- added AMD support for Template, but it still exports to window.Template until we convert all recent stuff into modules - converted objectCollection, CustomList, and courseList to modules - added specs for objectCollection Change-Id: Ib4ca4e25374c656b7b583ec7284c37672c117d2a Reviewed-on: https://gerrit.instructure.com/6545 Reviewed-by: Ryan Florence <ryanf@instructure.com> Tested-by: Hudson <hudson@instructure.com>
This commit is contained in:
parent
8ec102aa0e
commit
cc4522fc04
|
@ -1,7 +1,7 @@
|
|||
# A client-side templating wrapper. Templates are compiled with the rake task
|
||||
# `$ rake jst:compile` or automatically using the guard gem `$ guard`.
|
||||
# Don't call the templating object directly (like Handlebars), use this class.
|
||||
class @Template
|
||||
class Template
|
||||
|
||||
# If called w/o `new`, it will return the HTML string immediately.
|
||||
# i.e. `Template(test, {foo: 'bar'})` => '<div>bar</div>'
|
||||
|
@ -44,3 +44,11 @@ class @Template
|
|||
toElement: (locals) ->
|
||||
html = @toHTML locals
|
||||
jQuery('<div/>').html(html)
|
||||
|
||||
# export to window until we convert new stuff to modules
|
||||
@Template = Template
|
||||
|
||||
# register as module (will eventually put this at the head of the file)
|
||||
define 'compiled/Template', ->
|
||||
Template
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
require [
|
||||
'compiled/widget/courseList'
|
||||
], (courseList) ->
|
||||
# eventually we'll be requiring packages, like "common" etc.
|
||||
# but this is a simple start
|
||||
courseList.init()
|
||||
|
|
@ -3,55 +3,56 @@
|
|||
# Returns an array with extra methods. It uses direct property injection so our
|
||||
# prototypes are still clean, but we get a nice OO syntax for these kinds
|
||||
# of arrays.
|
||||
define 'compiled/util/objectCollection', ->
|
||||
(array) ->
|
||||
|
||||
@objectCollection = (array) ->
|
||||
# The usual indexOf support if not present
|
||||
unless array.indexOf
|
||||
array.indexOf = (needle) ->
|
||||
for item, index in array
|
||||
index if item is needle
|
||||
-1
|
||||
|
||||
# The usual indexOf support if not present
|
||||
unless array.indexOf
|
||||
array.indexOf = (needle) ->
|
||||
# Can find a specific element by a property ie:
|
||||
# arr = arrayOfObjects([{id: 1}, {id: 2}])
|
||||
# arr.findBy('id', 1) //> {id: 1}
|
||||
array.findBy = (prop, value) ->
|
||||
for item, index in array
|
||||
index if item is needle
|
||||
-1
|
||||
return item if (item[prop] is value)
|
||||
false
|
||||
|
||||
# Can find a specific element by a property ie:
|
||||
# arr = arrayOfObjects([{id: 1}, {id: 2}])
|
||||
# arr.findBy('id', 1) //> {id: 1}
|
||||
array.findBy = (prop, value) ->
|
||||
for item, index in array
|
||||
return item if (item[prop] is value)
|
||||
false
|
||||
array.eraseBy = (prop, value) ->
|
||||
item = array.findBy(prop, value)
|
||||
array.erase(item)
|
||||
|
||||
array.eraseBy = (prop, value) ->
|
||||
item = array.findBy(prop, value)
|
||||
array.erase(item)
|
||||
# Inserts an item into an array at a specific index
|
||||
array.insert = (item, index = 0) ->
|
||||
array.splice(index, 0, item)
|
||||
|
||||
# Inserts an item into an array at a specific index
|
||||
array.insert = (item, index = 0) ->
|
||||
array.splice(index, 0, item)
|
||||
# erases an item from an array, if it exists
|
||||
array.erase = (victim) ->
|
||||
for prospect, index in array
|
||||
array.splice(index, 1) if prospect is victim
|
||||
|
||||
# erases an item from an array, if it exists
|
||||
array.erase = (victim) ->
|
||||
for prospect, index in array
|
||||
array.splice(index, 1) if prospect is victim
|
||||
# Sort an array of of objects by object property, Supports sorting by strings
|
||||
# and numbers
|
||||
array.sortBy = do ->
|
||||
sorters =
|
||||
string: (a, b) ->
|
||||
if a < b
|
||||
-1
|
||||
else if a > b
|
||||
1
|
||||
else
|
||||
0
|
||||
|
||||
# Sort an array of of objects by object property, Supports sorting by strings
|
||||
# and numbers
|
||||
array.sortBy = do ->
|
||||
sorters =
|
||||
string: (a, b) ->
|
||||
if a < b
|
||||
-1
|
||||
else if a > b
|
||||
1
|
||||
else
|
||||
0
|
||||
number: (a, b) ->
|
||||
a - b
|
||||
|
||||
number: (a, b) ->
|
||||
a - b
|
||||
(prop) ->
|
||||
type = typeof array[0][prop] or 'string'
|
||||
array.sort (a, b) ->
|
||||
return sorters[type](a[prop], b[prop])
|
||||
|
||||
(prop) ->
|
||||
type = typeof array[0][prop] or 'string'
|
||||
array.sort (a, b) ->
|
||||
return sorters[type](a[prop], b[prop])
|
||||
return array
|
||||
|
||||
return array
|
||||
|
|
|
@ -1,221 +1,221 @@
|
|||
###
|
||||
requires:
|
||||
js!requires:
|
||||
- vendor/jquery-1.6.4.js
|
||||
- compiled/util/objectCollection.js
|
||||
- vendor/publisher.js
|
||||
- compiled/Template.js
|
||||
- jst/CustomList/courseList/wrapper.js
|
||||
- jst/CustomList/courseList/content.js
|
||||
- jQuery.ajaxJSON
|
||||
###
|
||||
|
||||
class @CustomList
|
||||
define 'compiled/widget/CustomList', [
|
||||
'compiled/util/objectCollection'
|
||||
'compiled/Template'
|
||||
], (objectCollection, Template) ->
|
||||
|
||||
options:
|
||||
animationDuration: 200
|
||||
model: 'Course'
|
||||
dataAttribute: 'id'
|
||||
wrapper: 'courseList/wrapper'
|
||||
content: 'courseList/content'
|
||||
url: '/favorites'
|
||||
appendTarget: 'body',
|
||||
resetCount: 12
|
||||
class CustomList
|
||||
options:
|
||||
animationDuration: 200
|
||||
model: 'Course'
|
||||
dataAttribute: 'id'
|
||||
wrapper: 'courseList/wrapper'
|
||||
content: 'courseList/content'
|
||||
url: '/favorites'
|
||||
appendTarget: 'body',
|
||||
resetCount: 12
|
||||
|
||||
constructor: (selector, items, options) ->
|
||||
@options = jQuery.extend {}, @options, options
|
||||
@appendTarget = jQuery @options.appendTarget
|
||||
@element = jQuery selector
|
||||
@targetList = @element.find '> ul'
|
||||
@wrapper = jQuery Template @options.wrapper, {}
|
||||
@sourceList = @wrapper.find '> ul'
|
||||
@contentTemplate = new Template @options.content
|
||||
@ghost = jQuery('<ul/>').addClass('customListGhost')
|
||||
@requests = { add: {}, remove: {} }
|
||||
@doc = jQuery document.body
|
||||
@isOpen = false
|
||||
constructor: (selector, items, options) ->
|
||||
@options = jQuery.extend {}, @options, options
|
||||
@appendTarget = jQuery @options.appendTarget
|
||||
@element = jQuery selector
|
||||
@targetList = @element.find '> ul'
|
||||
@wrapper = jQuery Template @options.wrapper, {}
|
||||
@sourceList = @wrapper.find '> ul'
|
||||
@contentTemplate = new Template @options.content
|
||||
@ghost = jQuery('<ul/>').addClass('customListGhost')
|
||||
@requests = { add: {}, remove: {} }
|
||||
@doc = jQuery document.body
|
||||
@isOpen = false
|
||||
|
||||
@attach()
|
||||
@setItems items
|
||||
@attach()
|
||||
@setItems items
|
||||
|
||||
open: ->
|
||||
@wrapper.appendTo(@appendTarget).show()
|
||||
setTimeout => # css3 animation
|
||||
@element.addClass('customListEditing')
|
||||
, 1
|
||||
open: ->
|
||||
@wrapper.appendTo(@appendTarget).show()
|
||||
setTimeout => # css3 animation
|
||||
@element.addClass('customListEditing')
|
||||
, 1
|
||||
|
||||
close: ->
|
||||
@wrapper.hide 0, =>
|
||||
@teardown()
|
||||
@element.removeClass('customListEditing');
|
||||
@resetList() if @pinned.length is 0
|
||||
close: ->
|
||||
@wrapper.hide 0, =>
|
||||
@teardown()
|
||||
@element.removeClass('customListEditing');
|
||||
@resetList() if @pinned.length is 0
|
||||
|
||||
attach: ->
|
||||
@element.delegate '.customListOpen', 'click', jQuery.proxy(this, 'open')
|
||||
@wrapper.delegate '.customListClose', 'click', jQuery.proxy(this, 'close')
|
||||
@wrapper.delegate '.customListRestore', 'click', jQuery.proxy(this, 'reset')
|
||||
@wrapper.delegate 'a', 'click.customListTeardown', (event) ->
|
||||
event.preventDefault()
|
||||
@wrapper.delegate(
|
||||
'.customListItem',
|
||||
'click.customListTeardown',
|
||||
jQuery.proxy(this, 'sourceClickHandler')
|
||||
)
|
||||
attach: ->
|
||||
@element.delegate '.customListOpen', 'click', jQuery.proxy(this, 'open')
|
||||
@wrapper.delegate '.customListClose', 'click', jQuery.proxy(this, 'close')
|
||||
@wrapper.delegate '.customListRestore', 'click', jQuery.proxy(this, 'reset')
|
||||
@wrapper.delegate 'a', 'click.customListTeardown', (event) ->
|
||||
event.preventDefault()
|
||||
@wrapper.delegate(
|
||||
'.customListItem',
|
||||
'click.customListTeardown',
|
||||
jQuery.proxy(this, 'sourceClickHandler')
|
||||
)
|
||||
|
||||
teardown: ->
|
||||
@wrapper.detach()
|
||||
teardown: ->
|
||||
@wrapper.detach()
|
||||
|
||||
add: (id, element) ->
|
||||
item = @items.findBy('id', id)
|
||||
clone = element.clone().hide()
|
||||
item.element = clone
|
||||
add: (id, element) ->
|
||||
item = @items.findBy('id', id)
|
||||
clone = element.clone().hide()
|
||||
item.element = clone
|
||||
|
||||
element.addClass 'on'
|
||||
element.addClass 'on'
|
||||
|
||||
@pinned.push item
|
||||
@pinned.sortBy('shortName')
|
||||
|
||||
index = @pinned.indexOf(item) + 1
|
||||
target = @targetList.find("li:nth-child(#{index})")
|
||||
|
||||
if target.length isnt 0
|
||||
clone.insertBefore target
|
||||
else
|
||||
clone.appendTo @targetList
|
||||
|
||||
clone.slideDown @options.animationDuration
|
||||
@animateGhost element, clone
|
||||
@onAdd item
|
||||
|
||||
animateGhost: (fromElement, toElement) ->
|
||||
from = fromElement.offset()
|
||||
to = toElement.offset()
|
||||
clone = fromElement.clone()
|
||||
from.position = 'absolute'
|
||||
|
||||
@ghost.append(clone)
|
||||
@ghost.appendTo(@doc).css(from).animate to, @options.animationDuration, =>
|
||||
@ghost.detach().empty()
|
||||
|
||||
remove: (item, element) ->
|
||||
element.removeClass 'on'
|
||||
@animating = true
|
||||
@onRemove item
|
||||
item.element.slideUp @options.animationDuration, =>
|
||||
item.element.remove()
|
||||
@pinned.eraseBy 'id', item.id
|
||||
@animating = false
|
||||
|
||||
abortAll: ->
|
||||
req.abort() for id, req of @requests.add
|
||||
req.abort() for id, req of @requests.remove
|
||||
|
||||
reset: ->
|
||||
@abortAll()
|
||||
|
||||
callback = =>
|
||||
delete @requests.reset
|
||||
|
||||
@requests.reset = jQuery.ajaxJSON(@options.url + '/' + @options.model, 'DELETE', {}, callback, callback)
|
||||
@resetList()
|
||||
|
||||
resetList: ->
|
||||
defaultItems = @items.slice 0, @options.resetCount
|
||||
html = @contentTemplate.toHTML { items: defaultItems }
|
||||
@targetList.empty().html(html)
|
||||
@setPinned()
|
||||
|
||||
onAdd: (item) ->
|
||||
if @requests.remove[item.id]
|
||||
@requests.remove[item.id].abort()
|
||||
return
|
||||
|
||||
success = =>
|
||||
args = [].slice.call arguments
|
||||
args.unshift(item.id)
|
||||
@addSuccess.apply(this, args)
|
||||
|
||||
error = =>
|
||||
args = [].slice.call arguments
|
||||
args.unshift(item.id)
|
||||
@addError.apply(this, args)
|
||||
|
||||
data =
|
||||
favorite:
|
||||
context_type: @options.model,
|
||||
context_id: item.id
|
||||
|
||||
req = jQuery.ajaxJSON(@options.url, 'POST', data, success, error)
|
||||
|
||||
@requests.add[item.id] = req
|
||||
|
||||
onRemove: (item) ->
|
||||
if @requests.add[item.id]
|
||||
@requests.add[item.id].abort();
|
||||
return
|
||||
|
||||
success = =>
|
||||
args = [].slice.call arguments
|
||||
args.unshift(item.id)
|
||||
@removeSuccess.apply(this, args)
|
||||
|
||||
error = =>
|
||||
args = [].slice.call arguments
|
||||
args.unshift(item.id)
|
||||
@removeError.apply(this, args)
|
||||
|
||||
url = @options.url + '/' + item.id
|
||||
req = jQuery.ajaxJSON(url, 'DELETE', {context_type: @options.model}, success, error)
|
||||
|
||||
@requests.remove[item.id] = req
|
||||
|
||||
addSuccess: (id) ->
|
||||
delete @requests.add[id]
|
||||
|
||||
addError: (id) ->
|
||||
delete @requests.add[id]
|
||||
|
||||
removeSuccess: (id) ->
|
||||
delete @requests.remove[id]
|
||||
|
||||
removeError: (id) ->
|
||||
delete @requests.remove[id]
|
||||
|
||||
setItems: (items) ->
|
||||
@items = objectCollection items
|
||||
@items.sortBy 'shortName'
|
||||
html = @contentTemplate.toHTML items: @items
|
||||
@sourceList.html html
|
||||
@setPinned()
|
||||
|
||||
setPinned: ->
|
||||
@pinned = objectCollection []
|
||||
|
||||
@element.find('> ul > li').each (index, element) =>
|
||||
element = jQuery element
|
||||
id = element.data('id')
|
||||
item = @items.findBy('id', id)
|
||||
|
||||
return unless item
|
||||
item.element = element
|
||||
@pinned.push item
|
||||
@pinned.sortBy('shortName')
|
||||
|
||||
@wrapper.find('ul > li').removeClass('on')
|
||||
index = @pinned.indexOf(item) + 1
|
||||
target = @targetList.find("li:nth-child(#{index})")
|
||||
|
||||
for item in @pinned
|
||||
match = @wrapper.find("ul > li[data-id=#{item.id}]")
|
||||
match.addClass 'on'
|
||||
if target.length isnt 0
|
||||
clone.insertBefore target
|
||||
else
|
||||
clone.appendTo @targetList
|
||||
|
||||
sourceClickHandler: (event) ->
|
||||
@checkElement jQuery event.currentTarget
|
||||
clone.slideDown @options.animationDuration
|
||||
@animateGhost element, clone
|
||||
@onAdd item
|
||||
|
||||
checkElement: (element) ->
|
||||
# DOM and data get out of sync for atomic clicking, hence @animating
|
||||
return if @animating or @requests.reset
|
||||
id = element.data 'id'
|
||||
item = @pinned.findBy 'id', id
|
||||
animateGhost: (fromElement, toElement) ->
|
||||
from = fromElement.offset()
|
||||
to = toElement.offset()
|
||||
clone = fromElement.clone()
|
||||
from.position = 'absolute'
|
||||
|
||||
if item
|
||||
@remove item, element
|
||||
else
|
||||
@add id, element
|
||||
@ghost.append(clone)
|
||||
@ghost.appendTo(@doc).css(from).animate to, @options.animationDuration, =>
|
||||
@ghost.detach().empty()
|
||||
|
||||
remove: (item, element) ->
|
||||
element.removeClass 'on'
|
||||
@animating = true
|
||||
@onRemove item
|
||||
item.element.slideUp @options.animationDuration, =>
|
||||
item.element.remove()
|
||||
@pinned.eraseBy 'id', item.id
|
||||
@animating = false
|
||||
|
||||
abortAll: ->
|
||||
req.abort() for id, req of @requests.add
|
||||
req.abort() for id, req of @requests.remove
|
||||
|
||||
reset: ->
|
||||
@abortAll()
|
||||
|
||||
callback = =>
|
||||
delete @requests.reset
|
||||
|
||||
@requests.reset = jQuery.ajaxJSON(@options.url + '/' + @options.model, 'DELETE', {}, callback, callback)
|
||||
@resetList()
|
||||
|
||||
resetList: ->
|
||||
defaultItems = @items.slice 0, @options.resetCount
|
||||
html = @contentTemplate.toHTML { items: defaultItems }
|
||||
@targetList.empty().html(html)
|
||||
@setPinned()
|
||||
|
||||
onAdd: (item) ->
|
||||
if @requests.remove[item.id]
|
||||
@requests.remove[item.id].abort()
|
||||
return
|
||||
|
||||
success = =>
|
||||
args = [].slice.call arguments
|
||||
args.unshift(item.id)
|
||||
@addSuccess.apply(this, args)
|
||||
|
||||
error = =>
|
||||
args = [].slice.call arguments
|
||||
args.unshift(item.id)
|
||||
@addError.apply(this, args)
|
||||
|
||||
data =
|
||||
favorite:
|
||||
context_type: @options.model,
|
||||
context_id: item.id
|
||||
|
||||
req = jQuery.ajaxJSON(@options.url, 'POST', data, success, error)
|
||||
|
||||
@requests.add[item.id] = req
|
||||
|
||||
onRemove: (item) ->
|
||||
if @requests.add[item.id]
|
||||
@requests.add[item.id].abort();
|
||||
return
|
||||
|
||||
success = =>
|
||||
args = [].slice.call arguments
|
||||
args.unshift(item.id)
|
||||
@removeSuccess.apply(this, args)
|
||||
|
||||
error = =>
|
||||
args = [].slice.call arguments
|
||||
args.unshift(item.id)
|
||||
@removeError.apply(this, args)
|
||||
|
||||
url = @options.url + '/' + item.id
|
||||
req = jQuery.ajaxJSON(url, 'DELETE', {context_type: @options.model}, success, error)
|
||||
|
||||
@requests.remove[item.id] = req
|
||||
|
||||
addSuccess: (id) ->
|
||||
delete @requests.add[id]
|
||||
|
||||
addError: (id) ->
|
||||
delete @requests.add[id]
|
||||
|
||||
removeSuccess: (id) ->
|
||||
delete @requests.remove[id]
|
||||
|
||||
removeError: (id) ->
|
||||
delete @requests.remove[id]
|
||||
|
||||
setItems: (items) ->
|
||||
@items = objectCollection items
|
||||
@items.sortBy 'shortName'
|
||||
html = @contentTemplate.toHTML items: @items
|
||||
@sourceList.html html
|
||||
@setPinned()
|
||||
|
||||
setPinned: ->
|
||||
@pinned = objectCollection []
|
||||
|
||||
@element.find('> ul > li').each (index, element) =>
|
||||
element = jQuery element
|
||||
id = element.data('id')
|
||||
item = @items.findBy('id', id)
|
||||
|
||||
return unless item
|
||||
item.element = element
|
||||
@pinned.push item
|
||||
|
||||
@wrapper.find('ul > li').removeClass('on')
|
||||
|
||||
for item in @pinned
|
||||
match = @wrapper.find("ul > li[data-id=#{item.id}]")
|
||||
match.addClass 'on'
|
||||
|
||||
sourceClickHandler: (event) ->
|
||||
@checkElement jQuery event.currentTarget
|
||||
|
||||
checkElement: (element) ->
|
||||
# DOM and data get out of sync for atomic clicking, hence @animating
|
||||
return if @animating or @requests.reset
|
||||
id = element.data 'id'
|
||||
item = @pinned.findBy 'id', id
|
||||
|
||||
if item
|
||||
@remove item, element
|
||||
else
|
||||
@add id, element
|
||||
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
###
|
||||
requires:
|
||||
- CustomList => widget/CustomList.js
|
||||
- js!vendor/jquery-1.6.4.js
|
||||
###
|
||||
define 'compiled/widget/courseList', ['compiled/widget/CustomList'], (CustomList) ->
|
||||
|
||||
jQuery ->
|
||||
menu = jQuery '#menu_enrollments'
|
||||
init: ->
|
||||
jQuery ->
|
||||
menu = jQuery '#menu_enrollments'
|
||||
|
||||
return if menu.length is 0 # :(
|
||||
return if menu.length is 0 # :(
|
||||
|
||||
jQuery.getJSON '/all_menu_courses', (enrollments) ->
|
||||
window.courseList = new CustomList '#menu_enrollments', enrollments,
|
||||
appendTarget: '#menu_enrollments'
|
||||
|
||||
jQuery.getJSON '/all_menu_courses', (enrollments) ->
|
||||
window.courseList = new CustomList '#menu_enrollments', enrollments,
|
||||
appendTarget: '#menu_enrollments'
|
||||
|
|
|
@ -95,7 +95,7 @@ javascripts:
|
|||
- public/javascripts/jst/courseList/content.js
|
||||
- public/javascripts/compiled/widget/CustomList.js
|
||||
- public/javascripts/compiled/widget/courseList.js
|
||||
|
||||
- public/javascripts/compiled/main.js
|
||||
assignmentMuter:
|
||||
- public/javascripts/compiled/AssignmentMuter.js
|
||||
- public/javascripts/jst/mute_dialog.js
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(function() {
|
||||
this.Template = (function() {
|
||||
var Template;
|
||||
Template = (function() {
|
||||
function Template(name, locals) {
|
||||
this.name = name;
|
||||
this.locals = locals;
|
||||
|
@ -20,4 +21,8 @@
|
|||
};
|
||||
return Template;
|
||||
})();
|
||||
this.Template = Template;
|
||||
define('compiled/Template', function() {
|
||||
return Template;
|
||||
});
|
||||
}).call(this);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
(function() {
|
||||
require(['compiled/widget/courseList'], function(courseList) {
|
||||
return courseList.init();
|
||||
});
|
||||
}).call(this);
|
|
@ -1,71 +1,73 @@
|
|||
(function() {
|
||||
this.objectCollection = function(array) {
|
||||
if (!array.indexOf) {
|
||||
array.indexOf = function(needle) {
|
||||
var index, item, _len, _results;
|
||||
_results = [];
|
||||
define('compiled/util/objectCollection', function() {
|
||||
return function(array) {
|
||||
if (!array.indexOf) {
|
||||
array.indexOf = function(needle) {
|
||||
var index, item, _len, _results;
|
||||
_results = [];
|
||||
for (index = 0, _len = array.length; index < _len; index++) {
|
||||
item = array[index];
|
||||
_results.push(item === needle ? index : void 0);
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
-1;
|
||||
}
|
||||
array.findBy = function(prop, value) {
|
||||
var index, item, _len;
|
||||
for (index = 0, _len = array.length; index < _len; index++) {
|
||||
item = array[index];
|
||||
_results.push(item === needle ? index : void 0);
|
||||
if (item[prop] === value) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
array.eraseBy = function(prop, value) {
|
||||
var item;
|
||||
item = array.findBy(prop, value);
|
||||
return array.erase(item);
|
||||
};
|
||||
array.insert = function(item, index) {
|
||||
if (index == null) {
|
||||
index = 0;
|
||||
}
|
||||
return array.splice(index, 0, item);
|
||||
};
|
||||
array.erase = function(victim) {
|
||||
var index, prospect, _len, _results;
|
||||
_results = [];
|
||||
for (index = 0, _len = array.length; index < _len; index++) {
|
||||
prospect = array[index];
|
||||
_results.push(prospect === victim ? array.splice(index, 1) : void 0);
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
-1;
|
||||
}
|
||||
array.findBy = function(prop, value) {
|
||||
var index, item, _len;
|
||||
for (index = 0, _len = array.length; index < _len; index++) {
|
||||
item = array[index];
|
||||
if (item[prop] === value) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
array.eraseBy = function(prop, value) {
|
||||
var item;
|
||||
item = array.findBy(prop, value);
|
||||
return array.erase(item);
|
||||
};
|
||||
array.insert = function(item, index) {
|
||||
if (index == null) {
|
||||
index = 0;
|
||||
}
|
||||
return array.splice(index, 0, item);
|
||||
};
|
||||
array.erase = function(victim) {
|
||||
var index, prospect, _len, _results;
|
||||
_results = [];
|
||||
for (index = 0, _len = array.length; index < _len; index++) {
|
||||
prospect = array[index];
|
||||
_results.push(prospect === victim ? array.splice(index, 1) : void 0);
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
array.sortBy = (function() {
|
||||
var sorters;
|
||||
sorters = {
|
||||
string: function(a, b) {
|
||||
if (a < b) {
|
||||
return -1;
|
||||
} else if (a > b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
array.sortBy = (function() {
|
||||
var sorters;
|
||||
sorters = {
|
||||
string: function(a, b) {
|
||||
if (a < b) {
|
||||
return -1;
|
||||
} else if (a > b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
number: function(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
},
|
||||
number: function(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
};
|
||||
return function(prop) {
|
||||
var type;
|
||||
type = typeof array[0][prop] || 'string';
|
||||
return array.sort(function(a, b) {
|
||||
return sorters[type](a[prop], b[prop]);
|
||||
});
|
||||
};
|
||||
})();
|
||||
return array;
|
||||
};
|
||||
};
|
||||
return function(prop) {
|
||||
var type;
|
||||
type = typeof array[0][prop] || 'string';
|
||||
return array.sort(function(a, b) {
|
||||
return sorters[type](a[prop], b[prop]);
|
||||
});
|
||||
};
|
||||
})();
|
||||
return array;
|
||||
};
|
||||
});
|
||||
}).call(this);
|
||||
|
|
|
@ -1,257 +1,256 @@
|
|||
(function() {
|
||||
/*
|
||||
requires:
|
||||
js!requires:
|
||||
- vendor/jquery-1.6.4.js
|
||||
- compiled/util/objectCollection.js
|
||||
- vendor/publisher.js
|
||||
- compiled/Template.js
|
||||
- jst/CustomList/courseList/wrapper.js
|
||||
- jst/CustomList/courseList/content.js
|
||||
- jQuery.ajaxJSON
|
||||
*/
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
this.CustomList = (function() {
|
||||
CustomList.prototype.options = {
|
||||
animationDuration: 200,
|
||||
model: 'Course',
|
||||
dataAttribute: 'id',
|
||||
wrapper: 'courseList/wrapper',
|
||||
content: 'courseList/content',
|
||||
url: '/favorites',
|
||||
appendTarget: 'body',
|
||||
resetCount: 12
|
||||
};
|
||||
function CustomList(selector, items, options) {
|
||||
this.options = jQuery.extend({}, this.options, options);
|
||||
this.appendTarget = jQuery(this.options.appendTarget);
|
||||
this.element = jQuery(selector);
|
||||
this.targetList = this.element.find('> ul');
|
||||
this.wrapper = jQuery(Template(this.options.wrapper, {}));
|
||||
this.sourceList = this.wrapper.find('> ul');
|
||||
this.contentTemplate = new Template(this.options.content);
|
||||
this.ghost = jQuery('<ul/>').addClass('customListGhost');
|
||||
this.requests = {
|
||||
add: {},
|
||||
remove: {}
|
||||
define('compiled/widget/CustomList', ['compiled/util/objectCollection', 'compiled/Template'], function(objectCollection, Template) {
|
||||
var CustomList;
|
||||
return CustomList = (function() {
|
||||
CustomList.prototype.options = {
|
||||
animationDuration: 200,
|
||||
model: 'Course',
|
||||
dataAttribute: 'id',
|
||||
wrapper: 'courseList/wrapper',
|
||||
content: 'courseList/content',
|
||||
url: '/favorites',
|
||||
appendTarget: 'body',
|
||||
resetCount: 12
|
||||
};
|
||||
this.doc = jQuery(document.body);
|
||||
this.isOpen = false;
|
||||
this.attach();
|
||||
this.setItems(items);
|
||||
}
|
||||
CustomList.prototype.open = function() {
|
||||
this.wrapper.appendTo(this.appendTarget).show();
|
||||
return setTimeout(__bind(function() {
|
||||
return this.element.addClass('customListEditing');
|
||||
}, this), 1);
|
||||
};
|
||||
CustomList.prototype.close = function() {
|
||||
this.wrapper.hide(0, __bind(function() {
|
||||
return this.teardown();
|
||||
}, this));
|
||||
this.element.removeClass('customListEditing');
|
||||
if (this.pinned.length === 0) {
|
||||
return this.resetList();
|
||||
function CustomList(selector, items, options) {
|
||||
this.options = jQuery.extend({}, this.options, options);
|
||||
this.appendTarget = jQuery(this.options.appendTarget);
|
||||
this.element = jQuery(selector);
|
||||
this.targetList = this.element.find('> ul');
|
||||
this.wrapper = jQuery(Template(this.options.wrapper, {}));
|
||||
this.sourceList = this.wrapper.find('> ul');
|
||||
this.contentTemplate = new Template(this.options.content);
|
||||
this.ghost = jQuery('<ul/>').addClass('customListGhost');
|
||||
this.requests = {
|
||||
add: {},
|
||||
remove: {}
|
||||
};
|
||||
this.doc = jQuery(document.body);
|
||||
this.isOpen = false;
|
||||
this.attach();
|
||||
this.setItems(items);
|
||||
}
|
||||
};
|
||||
CustomList.prototype.attach = function() {
|
||||
this.element.delegate('.customListOpen', 'click', jQuery.proxy(this, 'open'));
|
||||
this.wrapper.delegate('.customListClose', 'click', jQuery.proxy(this, 'close'));
|
||||
this.wrapper.delegate('.customListRestore', 'click', jQuery.proxy(this, 'reset'));
|
||||
this.wrapper.delegate('a', 'click.customListTeardown', function(event) {
|
||||
return event.preventDefault();
|
||||
});
|
||||
return this.wrapper.delegate('.customListItem', 'click.customListTeardown', jQuery.proxy(this, 'sourceClickHandler'));
|
||||
};
|
||||
CustomList.prototype.teardown = function() {
|
||||
return this.wrapper.detach();
|
||||
};
|
||||
CustomList.prototype.add = function(id, element) {
|
||||
var clone, index, item, target;
|
||||
item = this.items.findBy('id', id);
|
||||
clone = element.clone().hide();
|
||||
item.element = clone;
|
||||
element.addClass('on');
|
||||
this.pinned.push(item);
|
||||
this.pinned.sortBy('shortName');
|
||||
index = this.pinned.indexOf(item) + 1;
|
||||
target = this.targetList.find("li:nth-child(" + index + ")");
|
||||
if (target.length !== 0) {
|
||||
clone.insertBefore(target);
|
||||
} else {
|
||||
clone.appendTo(this.targetList);
|
||||
}
|
||||
clone.slideDown(this.options.animationDuration);
|
||||
this.animateGhost(element, clone);
|
||||
return this.onAdd(item);
|
||||
};
|
||||
CustomList.prototype.animateGhost = function(fromElement, toElement) {
|
||||
var clone, from, to;
|
||||
from = fromElement.offset();
|
||||
to = toElement.offset();
|
||||
clone = fromElement.clone();
|
||||
from.position = 'absolute';
|
||||
this.ghost.append(clone);
|
||||
return this.ghost.appendTo(this.doc).css(from).animate(to, this.options.animationDuration, __bind(function() {
|
||||
return this.ghost.detach().empty();
|
||||
}, this));
|
||||
};
|
||||
CustomList.prototype.remove = function(item, element) {
|
||||
element.removeClass('on');
|
||||
this.animating = true;
|
||||
this.onRemove(item);
|
||||
return item.element.slideUp(this.options.animationDuration, __bind(function() {
|
||||
item.element.remove();
|
||||
this.pinned.eraseBy('id', item.id);
|
||||
return this.animating = false;
|
||||
}, this));
|
||||
};
|
||||
CustomList.prototype.abortAll = function() {
|
||||
var id, req, _ref, _ref2, _results;
|
||||
_ref = this.requests.add;
|
||||
for (id in _ref) {
|
||||
req = _ref[id];
|
||||
req.abort();
|
||||
}
|
||||
_ref2 = this.requests.remove;
|
||||
_results = [];
|
||||
for (id in _ref2) {
|
||||
req = _ref2[id];
|
||||
_results.push(req.abort());
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
CustomList.prototype.reset = function() {
|
||||
var callback;
|
||||
this.abortAll();
|
||||
callback = __bind(function() {
|
||||
return delete this.requests.reset;
|
||||
}, this);
|
||||
this.requests.reset = jQuery.ajaxJSON(this.options.url + '/' + this.options.model, 'DELETE', {}, callback, callback);
|
||||
return this.resetList();
|
||||
};
|
||||
CustomList.prototype.resetList = function() {
|
||||
var defaultItems, html;
|
||||
defaultItems = this.items.slice(0, this.options.resetCount);
|
||||
html = this.contentTemplate.toHTML({
|
||||
items: defaultItems
|
||||
});
|
||||
this.targetList.empty().html(html);
|
||||
return this.setPinned();
|
||||
};
|
||||
CustomList.prototype.onAdd = function(item) {
|
||||
var data, error, req, success;
|
||||
if (this.requests.remove[item.id]) {
|
||||
this.requests.remove[item.id].abort();
|
||||
return;
|
||||
}
|
||||
success = __bind(function() {
|
||||
var args;
|
||||
args = [].slice.call(arguments);
|
||||
args.unshift(item.id);
|
||||
return this.addSuccess.apply(this, args);
|
||||
}, this);
|
||||
error = __bind(function() {
|
||||
var args;
|
||||
args = [].slice.call(arguments);
|
||||
args.unshift(item.id);
|
||||
return this.addError.apply(this, args);
|
||||
}, this);
|
||||
data = {
|
||||
favorite: {
|
||||
context_type: this.options.model,
|
||||
context_id: item.id
|
||||
CustomList.prototype.open = function() {
|
||||
this.wrapper.appendTo(this.appendTarget).show();
|
||||
return setTimeout(__bind(function() {
|
||||
return this.element.addClass('customListEditing');
|
||||
}, this), 1);
|
||||
};
|
||||
CustomList.prototype.close = function() {
|
||||
this.wrapper.hide(0, __bind(function() {
|
||||
return this.teardown();
|
||||
}, this));
|
||||
this.element.removeClass('customListEditing');
|
||||
if (this.pinned.length === 0) {
|
||||
return this.resetList();
|
||||
}
|
||||
};
|
||||
req = jQuery.ajaxJSON(this.options.url, 'POST', data, success, error);
|
||||
return this.requests.add[item.id] = req;
|
||||
};
|
||||
CustomList.prototype.onRemove = function(item) {
|
||||
var error, req, success, url;
|
||||
if (this.requests.add[item.id]) {
|
||||
this.requests.add[item.id].abort();
|
||||
return;
|
||||
}
|
||||
success = __bind(function() {
|
||||
var args;
|
||||
args = [].slice.call(arguments);
|
||||
args.unshift(item.id);
|
||||
return this.removeSuccess.apply(this, args);
|
||||
}, this);
|
||||
error = __bind(function() {
|
||||
var args;
|
||||
args = [].slice.call(arguments);
|
||||
args.unshift(item.id);
|
||||
return this.removeError.apply(this, args);
|
||||
}, this);
|
||||
url = this.options.url + '/' + item.id;
|
||||
req = jQuery.ajaxJSON(url, 'DELETE', {
|
||||
context_type: this.options.model
|
||||
}, success, error);
|
||||
return this.requests.remove[item.id] = req;
|
||||
};
|
||||
CustomList.prototype.addSuccess = function(id) {
|
||||
return delete this.requests.add[id];
|
||||
};
|
||||
CustomList.prototype.addError = function(id) {
|
||||
return delete this.requests.add[id];
|
||||
};
|
||||
CustomList.prototype.removeSuccess = function(id) {
|
||||
return delete this.requests.remove[id];
|
||||
};
|
||||
CustomList.prototype.removeError = function(id) {
|
||||
return delete this.requests.remove[id];
|
||||
};
|
||||
CustomList.prototype.setItems = function(items) {
|
||||
var html;
|
||||
this.items = objectCollection(items);
|
||||
this.items.sortBy('shortName');
|
||||
html = this.contentTemplate.toHTML({
|
||||
items: this.items
|
||||
});
|
||||
this.sourceList.html(html);
|
||||
return this.setPinned();
|
||||
};
|
||||
CustomList.prototype.setPinned = function() {
|
||||
var item, match, _i, _len, _ref, _results;
|
||||
this.pinned = objectCollection([]);
|
||||
this.element.find('> ul > li').each(__bind(function(index, element) {
|
||||
var id, item;
|
||||
element = jQuery(element);
|
||||
id = element.data('id');
|
||||
CustomList.prototype.attach = function() {
|
||||
this.element.delegate('.customListOpen', 'click', jQuery.proxy(this, 'open'));
|
||||
this.wrapper.delegate('.customListClose', 'click', jQuery.proxy(this, 'close'));
|
||||
this.wrapper.delegate('.customListRestore', 'click', jQuery.proxy(this, 'reset'));
|
||||
this.wrapper.delegate('a', 'click.customListTeardown', function(event) {
|
||||
return event.preventDefault();
|
||||
});
|
||||
return this.wrapper.delegate('.customListItem', 'click.customListTeardown', jQuery.proxy(this, 'sourceClickHandler'));
|
||||
};
|
||||
CustomList.prototype.teardown = function() {
|
||||
return this.wrapper.detach();
|
||||
};
|
||||
CustomList.prototype.add = function(id, element) {
|
||||
var clone, index, item, target;
|
||||
item = this.items.findBy('id', id);
|
||||
if (!item) {
|
||||
clone = element.clone().hide();
|
||||
item.element = clone;
|
||||
element.addClass('on');
|
||||
this.pinned.push(item);
|
||||
this.pinned.sortBy('shortName');
|
||||
index = this.pinned.indexOf(item) + 1;
|
||||
target = this.targetList.find("li:nth-child(" + index + ")");
|
||||
if (target.length !== 0) {
|
||||
clone.insertBefore(target);
|
||||
} else {
|
||||
clone.appendTo(this.targetList);
|
||||
}
|
||||
clone.slideDown(this.options.animationDuration);
|
||||
this.animateGhost(element, clone);
|
||||
return this.onAdd(item);
|
||||
};
|
||||
CustomList.prototype.animateGhost = function(fromElement, toElement) {
|
||||
var clone, from, to;
|
||||
from = fromElement.offset();
|
||||
to = toElement.offset();
|
||||
clone = fromElement.clone();
|
||||
from.position = 'absolute';
|
||||
this.ghost.append(clone);
|
||||
return this.ghost.appendTo(this.doc).css(from).animate(to, this.options.animationDuration, __bind(function() {
|
||||
return this.ghost.detach().empty();
|
||||
}, this));
|
||||
};
|
||||
CustomList.prototype.remove = function(item, element) {
|
||||
element.removeClass('on');
|
||||
this.animating = true;
|
||||
this.onRemove(item);
|
||||
return item.element.slideUp(this.options.animationDuration, __bind(function() {
|
||||
item.element.remove();
|
||||
this.pinned.eraseBy('id', item.id);
|
||||
return this.animating = false;
|
||||
}, this));
|
||||
};
|
||||
CustomList.prototype.abortAll = function() {
|
||||
var id, req, _ref, _ref2, _results;
|
||||
_ref = this.requests.add;
|
||||
for (id in _ref) {
|
||||
req = _ref[id];
|
||||
req.abort();
|
||||
}
|
||||
_ref2 = this.requests.remove;
|
||||
_results = [];
|
||||
for (id in _ref2) {
|
||||
req = _ref2[id];
|
||||
_results.push(req.abort());
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
CustomList.prototype.reset = function() {
|
||||
var callback;
|
||||
this.abortAll();
|
||||
callback = __bind(function() {
|
||||
return delete this.requests.reset;
|
||||
}, this);
|
||||
this.requests.reset = jQuery.ajaxJSON(this.options.url + '/' + this.options.model, 'DELETE', {}, callback, callback);
|
||||
return this.resetList();
|
||||
};
|
||||
CustomList.prototype.resetList = function() {
|
||||
var defaultItems, html;
|
||||
defaultItems = this.items.slice(0, this.options.resetCount);
|
||||
html = this.contentTemplate.toHTML({
|
||||
items: defaultItems
|
||||
});
|
||||
this.targetList.empty().html(html);
|
||||
return this.setPinned();
|
||||
};
|
||||
CustomList.prototype.onAdd = function(item) {
|
||||
var data, error, req, success;
|
||||
if (this.requests.remove[item.id]) {
|
||||
this.requests.remove[item.id].abort();
|
||||
return;
|
||||
}
|
||||
item.element = element;
|
||||
return this.pinned.push(item);
|
||||
}, this));
|
||||
this.wrapper.find('ul > li').removeClass('on');
|
||||
_ref = this.pinned;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
item = _ref[_i];
|
||||
match = this.wrapper.find("ul > li[data-id=" + item.id + "]");
|
||||
_results.push(match.addClass('on'));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
CustomList.prototype.sourceClickHandler = function(event) {
|
||||
return this.checkElement(jQuery(event.currentTarget));
|
||||
};
|
||||
CustomList.prototype.checkElement = function(element) {
|
||||
var id, item;
|
||||
if (this.animating || this.requests.reset) {
|
||||
return;
|
||||
}
|
||||
id = element.data('id');
|
||||
item = this.pinned.findBy('id', id);
|
||||
if (item) {
|
||||
return this.remove(item, element);
|
||||
} else {
|
||||
return this.add(id, element);
|
||||
}
|
||||
};
|
||||
return CustomList;
|
||||
})();
|
||||
success = __bind(function() {
|
||||
var args;
|
||||
args = [].slice.call(arguments);
|
||||
args.unshift(item.id);
|
||||
return this.addSuccess.apply(this, args);
|
||||
}, this);
|
||||
error = __bind(function() {
|
||||
var args;
|
||||
args = [].slice.call(arguments);
|
||||
args.unshift(item.id);
|
||||
return this.addError.apply(this, args);
|
||||
}, this);
|
||||
data = {
|
||||
favorite: {
|
||||
context_type: this.options.model,
|
||||
context_id: item.id
|
||||
}
|
||||
};
|
||||
req = jQuery.ajaxJSON(this.options.url, 'POST', data, success, error);
|
||||
return this.requests.add[item.id] = req;
|
||||
};
|
||||
CustomList.prototype.onRemove = function(item) {
|
||||
var error, req, success, url;
|
||||
if (this.requests.add[item.id]) {
|
||||
this.requests.add[item.id].abort();
|
||||
return;
|
||||
}
|
||||
success = __bind(function() {
|
||||
var args;
|
||||
args = [].slice.call(arguments);
|
||||
args.unshift(item.id);
|
||||
return this.removeSuccess.apply(this, args);
|
||||
}, this);
|
||||
error = __bind(function() {
|
||||
var args;
|
||||
args = [].slice.call(arguments);
|
||||
args.unshift(item.id);
|
||||
return this.removeError.apply(this, args);
|
||||
}, this);
|
||||
url = this.options.url + '/' + item.id;
|
||||
req = jQuery.ajaxJSON(url, 'DELETE', {
|
||||
context_type: this.options.model
|
||||
}, success, error);
|
||||
return this.requests.remove[item.id] = req;
|
||||
};
|
||||
CustomList.prototype.addSuccess = function(id) {
|
||||
return delete this.requests.add[id];
|
||||
};
|
||||
CustomList.prototype.addError = function(id) {
|
||||
return delete this.requests.add[id];
|
||||
};
|
||||
CustomList.prototype.removeSuccess = function(id) {
|
||||
return delete this.requests.remove[id];
|
||||
};
|
||||
CustomList.prototype.removeError = function(id) {
|
||||
return delete this.requests.remove[id];
|
||||
};
|
||||
CustomList.prototype.setItems = function(items) {
|
||||
var html;
|
||||
this.items = objectCollection(items);
|
||||
this.items.sortBy('shortName');
|
||||
html = this.contentTemplate.toHTML({
|
||||
items: this.items
|
||||
});
|
||||
this.sourceList.html(html);
|
||||
return this.setPinned();
|
||||
};
|
||||
CustomList.prototype.setPinned = function() {
|
||||
var item, match, _i, _len, _ref, _results;
|
||||
this.pinned = objectCollection([]);
|
||||
this.element.find('> ul > li').each(__bind(function(index, element) {
|
||||
var id, item;
|
||||
element = jQuery(element);
|
||||
id = element.data('id');
|
||||
item = this.items.findBy('id', id);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
item.element = element;
|
||||
return this.pinned.push(item);
|
||||
}, this));
|
||||
this.wrapper.find('ul > li').removeClass('on');
|
||||
_ref = this.pinned;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
item = _ref[_i];
|
||||
match = this.wrapper.find("ul > li[data-id=" + item.id + "]");
|
||||
_results.push(match.addClass('on'));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
CustomList.prototype.sourceClickHandler = function(event) {
|
||||
return this.checkElement(jQuery(event.currentTarget));
|
||||
};
|
||||
CustomList.prototype.checkElement = function(element) {
|
||||
var id, item;
|
||||
if (this.animating || this.requests.reset) {
|
||||
return;
|
||||
}
|
||||
id = element.data('id');
|
||||
item = this.pinned.findBy('id', id);
|
||||
if (item) {
|
||||
return this.remove(item, element);
|
||||
} else {
|
||||
return this.add(id, element);
|
||||
}
|
||||
};
|
||||
return CustomList;
|
||||
})();
|
||||
});
|
||||
}).call(this);
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
(function() {
|
||||
/*
|
||||
requires:
|
||||
- CustomList => widget/CustomList.js
|
||||
*/ jQuery(function() {
|
||||
var menu;
|
||||
menu = jQuery('#menu_enrollments');
|
||||
if (menu.length === 0) {
|
||||
return;
|
||||
}
|
||||
return jQuery.getJSON('/all_menu_courses', function(enrollments) {
|
||||
return window.courseList = new CustomList('#menu_enrollments', enrollments, {
|
||||
appendTarget: '#menu_enrollments'
|
||||
});
|
||||
});
|
||||
- js!vendor/jquery-1.6.4.js
|
||||
*/ define('compiled/widget/courseList', ['compiled/widget/CustomList'], function(CustomList) {
|
||||
return {
|
||||
init: function() {
|
||||
return jQuery(function() {
|
||||
var menu;
|
||||
menu = jQuery('#menu_enrollments');
|
||||
if (menu.length === 0) {
|
||||
return;
|
||||
}
|
||||
return jQuery.getJSON('/all_menu_courses', function(enrollments) {
|
||||
return window.courseList = new CustomList('#menu_enrollments', enrollments, {
|
||||
appendTarget: '#menu_enrollments'
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}).call(this);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
curl = require = {
|
||||
baseUrl: '/public/javascripts/compiled',
|
||||
baseUrl: '/public/javascripts',
|
||||
apiName: 'require'
|
||||
};
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
define [
|
||||
'js!vendor/jquery-1.6.4.js!order'
|
||||
# non-amd dependencies, once everything is a module you'll rarely require
|
||||
# more than one thing in a spec
|
||||
'js!vendor/jquery-1.6.4.js'
|
||||
'js!jquery.ajaxJSON.js!order'
|
||||
|
||||
'js!i18n.js!order'
|
||||
'js!vendor/handlebars.vm.js!order'
|
||||
'js!compiled/handlebars_helpers.js!order'
|
||||
'js!compiled/Template.js!order'
|
||||
'js!jst/courseList/wrapper.js!order'
|
||||
'js!jst/courseList/content.js!order'
|
||||
|
||||
'js!compiled/util/objectCollection.js!order'
|
||||
'js!compiled/widget/CustomList.js!order'
|
||||
], ->
|
||||
|
||||
# module dependencies
|
||||
'compiled/widget/CustomList'
|
||||
], (a, b, c, d, e, f, g, CustomList)->
|
||||
|
||||
module 'CustomList',
|
||||
setup: ->
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
define ['compiled/util/objectCollection'], (objectCollection) ->
|
||||
|
||||
module 'objectCollection',
|
||||
setup: ->
|
||||
arrayOfObjects = [
|
||||
{id: 1, name: 'foo'}
|
||||
{id: 2, name: 'bar'}
|
||||
{id: 3, name: 'baz'}
|
||||
{id: 4, name: 'quux'}
|
||||
]
|
||||
@collection = objectCollection arrayOfObjects
|
||||
|
||||
test 'indexOf', ->
|
||||
needle = @collection[2]
|
||||
index = @collection.indexOf needle
|
||||
equal index, 2, 'should find the correct index'
|
||||
|
||||
test 'findBy', ->
|
||||
byId = @collection.findBy 'id', 1
|
||||
equal @collection[0], byId, 'should find the first item by id'
|
||||
|
||||
byName = @collection.findBy 'name', 'bar'
|
||||
equal @collection[1], byName, 'should find the second item by name'
|
||||
|
||||
test 'eraseBy', ->
|
||||
originalLength = @collection.length
|
||||
equal @collection[0].id, 1, 'first item id should be 1'
|
||||
|
||||
@collection.eraseBy 'id', 1
|
||||
|
||||
equal @collection.length, originalLength - 1, 'collection length should less by 1'
|
||||
equal @collection[0].id, 2, 'first item id should be 2, since first is erased'
|
||||
|
||||
test 'insert', ->
|
||||
corge = {id: 5, name: 'corge'}
|
||||
@collection.insert corge
|
||||
equal @collection[0], corge, 'should insert at index 0 by default'
|
||||
|
||||
grault = {id: 6, name: 'grault'}
|
||||
@collection.insert grault, 2
|
||||
equal @collection[2], grault, 'should insert at an arbitrary index'
|
||||
|
||||
|
||||
test 'erase', ->
|
||||
originalLength = @collection.length
|
||||
@collection.erase @collection[0]
|
||||
equal @collection[0].name, 'bar', 'should erase first item by reference, second item becomes first'
|
||||
equal @collection.length, originalLength - 1, 'should decrease length'
|
||||
|
||||
test 'sortBy', ->
|
||||
@collection.sortBy 'name'
|
||||
equal @collection[0].name, 'bar'
|
||||
equal @collection[1].name, 'baz'
|
||||
equal @collection[2].name, 'foo'
|
||||
equal @collection[3].name, 'quux'
|
||||
|
||||
@collection.sortBy 'id'
|
||||
equal @collection[0].id, 1
|
||||
equal @collection[1].id, 2
|
||||
equal @collection[2].id, 3
|
||||
equal @collection[3].id, 4
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
(function() {
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
define(['js!vendor/jquery-1.6.4.js!order', 'js!jquery.ajaxJSON.js!order', 'js!i18n.js!order', 'js!vendor/handlebars.vm.js!order', 'js!compiled/handlebars_helpers.js!order', 'js!compiled/Template.js!order', 'js!jst/courseList/wrapper.js!order', 'js!jst/courseList/content.js!order', 'js!compiled/util/objectCollection.js!order', 'js!compiled/widget/CustomList.js!order'], function() {
|
||||
define(['js!vendor/jquery-1.6.4.js', 'js!jquery.ajaxJSON.js!order', 'js!i18n.js!order', 'js!vendor/handlebars.vm.js!order', 'js!compiled/handlebars_helpers.js!order', 'js!jst/courseList/wrapper.js!order', 'js!jst/courseList/content.js!order', 'compiled/widget/CustomList'], function(a, b, c, d, e, f, g, CustomList) {
|
||||
module('CustomList', {
|
||||
setup: function() {
|
||||
var index, items;
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
(function() {
|
||||
define(['compiled/util/objectCollection'], function(objectCollection) {
|
||||
module('objectCollection', {
|
||||
setup: function() {
|
||||
var arrayOfObjects;
|
||||
arrayOfObjects = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'foo'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'bar'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'baz'
|
||||
}, {
|
||||
id: 4,
|
||||
name: 'quux'
|
||||
}
|
||||
];
|
||||
return this.collection = objectCollection(arrayOfObjects);
|
||||
}
|
||||
});
|
||||
test('indexOf', function() {
|
||||
var index, needle;
|
||||
needle = this.collection[2];
|
||||
index = this.collection.indexOf(needle);
|
||||
return equal(index, 2, 'should find the correct index');
|
||||
});
|
||||
test('findBy', function() {
|
||||
var byId, byName;
|
||||
byId = this.collection.findBy('id', 1);
|
||||
equal(this.collection[0], byId, 'should find the first item by id');
|
||||
byName = this.collection.findBy('name', 'bar');
|
||||
return equal(this.collection[1], byName, 'should find the second item by name');
|
||||
});
|
||||
test('eraseBy', function() {
|
||||
var originalLength;
|
||||
originalLength = this.collection.length;
|
||||
equal(this.collection[0].id, 1, 'first item id should be 1');
|
||||
this.collection.eraseBy('id', 1);
|
||||
equal(this.collection.length, originalLength - 1, 'collection length should less by 1');
|
||||
return equal(this.collection[0].id, 2, 'first item id should be 2, since first is erased');
|
||||
});
|
||||
test('insert', function() {
|
||||
var corge, grault;
|
||||
corge = {
|
||||
id: 5,
|
||||
name: 'corge'
|
||||
};
|
||||
this.collection.insert(corge);
|
||||
equal(this.collection[0], corge, 'should insert at index 0 by default');
|
||||
grault = {
|
||||
id: 6,
|
||||
name: 'grault'
|
||||
};
|
||||
this.collection.insert(grault, 2);
|
||||
return equal(this.collection[2], grault, 'should insert at an arbitrary index');
|
||||
});
|
||||
test('erase', function() {
|
||||
var originalLength;
|
||||
originalLength = this.collection.length;
|
||||
this.collection.erase(this.collection[0]);
|
||||
equal(this.collection[0].name, 'bar', 'should erase first item by reference, second item becomes first');
|
||||
return equal(this.collection.length, originalLength - 1, 'should decrease length');
|
||||
});
|
||||
return test('sortBy', function() {
|
||||
this.collection.sortBy('name');
|
||||
equal(this.collection[0].name, 'bar');
|
||||
equal(this.collection[1].name, 'baz');
|
||||
equal(this.collection[2].name, 'foo');
|
||||
equal(this.collection[3].name, 'quux');
|
||||
this.collection.sortBy('id');
|
||||
equal(this.collection[0].id, 1);
|
||||
equal(this.collection[1].id, 2);
|
||||
equal(this.collection[2].id, 3);
|
||||
return equal(this.collection[3].id, 4);
|
||||
});
|
||||
});
|
||||
}).call(this);
|
|
@ -3,6 +3,7 @@ require([
|
|||
'specs/CustomListSpec',
|
||||
'specs/invokerSpec',
|
||||
'specs/jQuery.instructureMiscPluginsSpec',
|
||||
'specs/userNamePartsSpec'
|
||||
'specs/userNamePartsSpec',
|
||||
'specs/objectCollectionSpec'
|
||||
]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue