Created
March 17, 2014 02:37
-
-
Save junyper/9593039 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
App = Ember.Application.create() | |
App.Router.map -> | |
@route 'standards-list', | |
path: '/' | |
###### Routes ######### | |
App.StandardsListRoute = Ember.Route.extend | |
model: -> | |
window.ENV.map (item) -> | |
standard = item.grading_standard | |
App.Standard.create | |
title: standard.title | |
grades: standard.data.map (data) -> | |
App.Grade.create | |
label: data[0] | |
value: data[1] | |
####### Models ###### | |
App.Standard = Ember.Object.extend | |
title: null | |
ranges: null | |
selected: false #TODO: this seems like it belongs in the controller, but the ArrayController doesn't seem to be able to set controller properties. | |
App.Grade = Ember.Object.extend | |
label: null | |
value: 0 | |
#TODO: these seem like they belong in the controller, but the ArrayController doesn't seem to be able to set controller properties. | |
min: -1 | |
max: 1 | |
color: 'transparent' | |
editable: false | |
####### Controllers ####### | |
App.StandardsListController = Ember.ArrayController.extend | |
actions: | |
remove: (standard) -> | |
# TODO: ic-ajax | |
@removeObject(standard) | |
edit: (standard) -> | |
editable = @findBy 'editable', true | |
if editable? then editable.set 'editable', false | |
standard.set 'editable', true | |
add: -> | |
newStandard = App.Standard.create | |
title: 'New Standard' | |
grades: Ember.A [ | |
App.Grade.create | |
selected: true | |
editable: true | |
value: .5 | |
label: 'Pass' | |
App.Grade.create | |
editable: true | |
value: 0 | |
label: 'Fail' | |
] | |
@addObject newStandard | |
@send 'edit', newStandard | |
App.StandardController = Ember.ObjectController.extend | |
setEditable: (-> | |
@get('grades').setEach 'editable', @get('editable') | |
).observes('editable') | |
actions: | |
save: -> | |
# TODO: ic-ajax then: | |
@set('editable', false) | |
App.GradesListController = Ember.ArrayController.extend | |
updateGrades: ( -> | |
grades = @get('content') | |
@forEach (grade, index) -> | |
grade.setProperties | |
max: if grades[index-1]? then grades[index-1].get('value') else 1 | |
min: if grades[index+1]? then grades[index+1].get('value') else -1 | |
).on('init').observes('content', '@each.value') | |
updateColors: ( -> | |
length = @get('length') | |
@forEach (grade, i) -> | |
grade.set 'color', $.Color( | |
hue: 120 - (i/(length-1) * 120) | |
saturation: .7 | |
lightness: .8 | |
).toRgbaString() | |
).on('init').observes('length') | |
actions: | |
remove: (grade) -> | |
@removeObject(grade) | |
add: -> | |
newGrade = App.Grade.create | |
label: 'New' | |
value: .01 | |
editable: true | |
@replaceContent @get('length')-1, 0, [newGrade] | |
@send 'select', newGrade | |
select: (grade) -> | |
selected = @findBy 'selected', true | |
if selected? then selected.set 'selected', false | |
grade.set 'selected', true | |
App.GradeController = Ember.ObjectController.extend | |
setSelected: (-> | |
if not @get('editable') then @set 'selected', false | |
).observes('editable') | |
colorStyle: (-> | |
"background-color: #{@get('color')}" | |
).property('color').readOnly() | |
readOnlyValue: (-> | |
@get('min') == -1 or !@get('selected') | |
).property('min', 'selected').readOnly() | |
deleteable: (-> | |
@get('min') > -1 | |
).property('min').readOnly() | |
isValid: (-> # TODO: validate label | |
value = @get('value') | |
min = @get('min') | |
max = @get('max') | |
(min < value < max) or @get('min') == -1 | |
).property('value', 'min', 'max').readOnly() | |
maxPercentage: (-> | |
@get('max') * 100 | |
).property('max').readOnly() | |
minPercentage: (-> | |
@get('min') * 100 | |
).property('min').readOnly() | |
percentage: ((key, value) -> | |
if arguments.length > 1 | |
@set 'value', value/100 | |
@get('value') * 100 | |
).property('value') | |
######## Views ####### | |
App.GradeView = Ember.View.extend | |
classNames: ['gs-grade'] | |
tagName: 'tr' | |
classNameBindings: ['controller.isValid::error'] | |
attributeBindings: ['tabindex'] | |
tabindex: (-> | |
-1 if @get('controller').get('editable') | |
).property('controller.editable') | |
focusIn: (evt) -> | |
controller = @get('controller') | |
controller.send 'select', controller | |
######## Components ####### | |
App.FocusedInputComponent = Ember.TextField.extend | |
initFocus: (-> | |
Ember.run.scheduleOnce 'afterRender', => | |
@$()?.focus() | |
).on('didInsertElement') | |
Ember.Handlebars.helper 'focused-input', App.FocusedInputComponent | |
App.SpinnerInputComponent = Ember.TextField.extend | |
classNames: ['spinner-input'] | |
initSpinner: (-> | |
Ember.run.scheduleOnce 'afterRender', => | |
@$()?.spinner @get('spinnerOptions') | |
).on('didInsertElement').observes('spinnerOptions') | |
spinnerOptions: (-> | |
max: @get('max') | |
min: @get('min') | |
mouseWheel: false | |
).property('max', 'min') | |
Ember.Handlebars.helper 'spinner-input', App.SpinnerInputComponent | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
padding: 20px; | |
} | |
.gs-btns { | |
float: right; | |
} | |
.gs-label { | |
min-width: 60px; | |
padding: 5px; | |
display: inline-block; | |
border-radius: 3px; | |
font-weight: bold; | |
text-align: center; | |
} | |
.gs-standard { | |
max-width: 400px; | |
border-top: 1px solid #eee; | |
margin: 40px 0; | |
padding: 10px; | |
} | |
.gs-standard-title { | |
font-weight: bold; | |
} | |
.gs-standard-editable { | |
background-color: #f4f8fa; | |
border-radius: 3px; | |
border-top: 0; | |
} | |
.gs-standard-editable .gs-grade:hover { | |
cursor: pointer; | |
} | |
.gs-standard input { | |
margin: 0; | |
} | |
.gs-value input { | |
width: 50px; | |
font-size: 1em; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Grading Standards</title> | |
<link href="http://getbootstrap.com/2.3.2/assets/css/bootstrap.css" rel="stylesheet" type="text/css" /> | |
<link href="http://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.min.css" rel="stylesheet" type="text/css" /> | |
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script> | |
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script> | |
<script src="http://code.jquery.com/color/jquery.color-2.1.0.min.js"></script> | |
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.2.1.js"></script> | |
<script src="http://builds.emberjs.com/tags/v1.4.0/ember.js"></script> | |
</head> | |
<body> | |
<script type="text/x-handlebars" data-template-name="standards-list"> | |
<h2>Grading Standards</h2> | |
{{#each standard in model}} | |
{{ render "standard" standard }} | |
{{/each}} | |
<button {{ action "add" }} class="btn btn-default"> | |
Add a Standard | |
</button> | |
</script> | |
<script type="text/x-handlebars" data-template-name="standard"> | |
<section {{ bind-attr class=":gs-standard editable:gs-standard-editable:" }}> | |
<header> | |
{{#if editable}} | |
{{ focused-input value=title class="gs-standard-title"}} | |
{{else}} | |
<div class="gs-btns"> | |
<button {{ action "edit" this }} class="btn btn-sm"> | |
<i class="icon-edit"></i> | |
</button> | |
<button {{ action "remove" this }} class="btn btn-sm"> | |
<i class="icon-trash"></i> | |
</button> | |
</div> | |
<h3>{{title}}</h3> | |
{{/if}} | |
</header> | |
<table {{ bind-attr class=":table :table-striped editable:table-hover:" }}> | |
<thead> | |
<tr> | |
<th>Grade</th> | |
<th>Minimum %</th> | |
{{#if editable}} | |
<th></th> | |
{{/if}} | |
</tr> | |
</thead> | |
{{ render "grades-list" grades }} | |
</table> | |
<footer> | |
{{#if editable}} | |
<button {{ action "save" }} class="btn btn-primary btn-large"> | |
Save Standard | |
</button> | |
{{/if}} | |
</footer> | |
</section> | |
</script> | |
<script type="text/x-handlebars" data-template-name="grades-list"> | |
{{#each grade in model}} | |
{{ render "grade" grade }} | |
{{/each}} | |
</script> | |
<script type="text/x-handlebars" data-template-name="grade"> | |
<td> | |
<span class="gs-label" {{ bind-attr style=colorStyle }}> | |
{{#if selected}} | |
{{ focused-input value=label }} | |
{{else}} | |
{{label}} | |
{{/if}} | |
</span> | |
</td> | |
<td class="gs-value"> | |
{{#unless readOnlyValue}} | |
{{spinner-input value=percentage min=minPercentage max=maxPercentage}} | |
{{else}} | |
{{percentage}} | |
{{/unless}} | |
</td> | |
{{#if editable}} | |
<td class="gs-grade-btns"> | |
{{#if deleteable}} | |
<button {{ action "remove" this }} class="btn btn-sm" title="Remove this grade"> | |
<i class="icon-trash"></i> | |
</button> | |
{{else}} | |
<button {{ action "add" bubbles=false }} class="btn btn-sm" title="Add a grade"> | |
<i class="icon-plus"></i> | |
</button> | |
{{/if}} | |
</td> | |
{{/if}} | |
</script> | |
<script>ENV = [ | |
{ | |
"grading_standard": { | |
"data": [ | |
[ | |
"A", | |
0.925 | |
], | |
[ | |
"A-", | |
0.91 | |
], | |
[ | |
"B+", | |
0.875 | |
], | |
[ | |
"B", | |
0.823 | |
], | |
[ | |
"B-", | |
0.8 | |
], | |
[ | |
"C+", | |
0.778 | |
], | |
[ | |
"C", | |
0.74 | |
], | |
[ | |
"C-", | |
0.7 | |
], | |
[ | |
"D+", | |
0.67 | |
], | |
[ | |
"D", | |
0.64 | |
], | |
[ | |
"D-", | |
0.61 | |
], | |
[ | |
"F", | |
0 | |
] | |
], | |
"title": "Lorem Ipsum Standard" | |
} | |
}, | |
{ | |
"grading_standard": { | |
"data": [ | |
[ | |
"4.0", | |
0.75 | |
], | |
[ | |
"3.0", | |
0.01 | |
], | |
[ | |
"M", | |
0 | |
] | |
], | |
"title": "GPA 2" | |
} | |
} | |
];</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment