Remove Config panel class and update Settings Panel spec

This commit is contained in:
probablycorey
2013-06-27 14:51:52 -07:00
parent 789b8a2987
commit 063078cd34
6 changed files with 171 additions and 239 deletions

View File

@@ -1,58 +0,0 @@
$ = require 'jquery'
{View} = require 'space-pen'
###
# Internal #
###
module.exports =
class ConfigPanel extends View
initialize: ->
@bindFormFields()
@bindEditors()
bindFormFields: ->
for input in @find('input[id]').toArray()
do (input) =>
input = $(input)
name = input.attr('id')
type = input.attr('type')
@observeConfig name, (value) ->
if type is 'checkbox'
input.attr('checked', value)
else
input.val(value) if value
input.on 'change', =>
value = input.val()
if type == 'checkbox'
value = !!input.attr('checked')
else
value = @parseValue(type, value)
config.set(name, value)
bindEditors: ->
for editor in @find('.editor[id]').views()
do (editor) =>
name = editor.attr('id')
type = editor.attr('type')
@observeConfig name, (value) ->
return if value?.toString() == editor.getText()
value ?= ""
editor.setText(value.toString())
editor.getBuffer().on 'contents-modified', =>
config.set(name, @parseValue(type, editor.getText()))
parseValue: (type, value) ->
switch type
when 'int'
intValue = parseInt(value)
value = intValue unless isNaN(intValue)
when 'float'
floatValue = parseFloat(value)
value = floatValue unless isNaN(floatValue)
value = undefined if value == ''
value

View File

@@ -1,7 +1,6 @@
$ = require 'jquery'
_ = require 'underscore'
{$$} = require 'space-pen'
ConfigPanel = require './config-panel'
{View, $$} = require 'space-pen'
EventEmitter = require 'event-emitter'
Editor = require 'editor'
PackageView = require './package-view'
@@ -14,7 +13,7 @@ class PackageEventEmitter
_.extend PackageEventEmitter.prototype, EventEmitter
module.exports =
class PackagePanel extends ConfigPanel
class PackagePanel extends View
@content: ->
@div class: 'package-panel', =>
@legend 'Packages'

View File

@@ -1,5 +1,4 @@
ConfigPanel = require './config-panel'
{$$} = require 'space-pen'
{$$, View} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'
@@ -10,7 +9,7 @@ _ = require 'underscore'
Editor = require 'editor'
module.exports =
class SettingsPanel extends ConfigPanel
class SettingsPanel extends View
@content: ->
@form id: 'settings-panel', class: 'form-horizontal', =>
@@ -18,46 +17,102 @@ class SettingsPanel extends ConfigPanel
initialize: ->
for namespace, settings of config.getSettings()
continue unless namespace is 'editor' or namespace is 'core'
@appendSettings(namespace, settings)
super
@bindFormFields()
@bindEditors()
appendSettings: (namespace, settings) ->
return if _.isEmpty(settings)
appendSetting = (namespace, name, value) ->
@div class: 'control-group', =>
@div class: 'controls', =>
if _.isBoolean(value)
appendCheckbox.call(this, namespace, name, value)
else if _.isArray(value)
appendArray.call(this, namespace, name, value)
else
appendEditor.call(this, namespace, name, value)
appendCheckbox = (namespace, name, value) ->
englishName = _.uncamelcase(name)
keyPath = "#{namespace}.#{name}"
@div class: 'checkbox', =>
@label for: keyPath, =>
@input id: keyPath, type: 'checkbox'
@text englishName
appendEditor = (namespace, name, value) ->
englishName = _.uncamelcase(name)
keyPath = "#{namespace}.#{name}"
type = if _.isNumber(value) then 'number' else 'string'
@label class: 'control-label', englishName
@div class: 'controls', =>
@subview keyPath.replace('.', ''), new Editor(mini: true, attributes: {id: keyPath, type: type})
appendArray = (namespace, name, value) ->
englishName = _.uncamelcase(name)
@label class: 'control-label', englishName
@div class: 'controls', =>
@text "readOnly: " + value.join(", ")
@append $$ ->
@fieldset =>
@legend "#{_.uncamelcase(namespace)} settings"
appendSetting.call(this, namespace, name, value) for name, value of settings
bindFormFields: ->
for input in @find('input[id]').toArray()
do (input) =>
input = $(input)
name = input.attr('id')
type = input.attr('type')
@observeConfig name, (value) ->
if type is 'checkbox'
input.attr('checked', value)
else
input.val(value) if value
input.on 'change', =>
value = input.val()
if type == 'checkbox'
value = !!input.attr('checked')
else
value = @parseValue(type, value)
config.set(name, value)
bindEditors: ->
for editor in @find('.editor[id]').views()
do (editor) =>
name = editor.attr('id')
type = editor.attr('type')
@observeConfig name, (value) ->
return if value?.toString() == editor.getText()
value ?= ""
editor.setText(value.toString())
editor.getBuffer().on 'contents-modified', =>
config.set(name, @parseValue(type, editor.getText()))
parseValue: (type, value) ->
if value == ''
value = undefined
else if type == 'int'
intValue = parseInt(value)
value = intValue unless isNaN(intValue)
else if type == 'float'
floatValue = parseFloat(value)
value = floatValue unless isNaN(floatValue)
value
###
# Space Pen Helpers
###
appendSetting = (namespace, name, value) ->
@div class: 'control-group', =>
@div class: 'controls', =>
if _.isBoolean(value)
appendCheckbox.call(this, namespace, name, value)
else if _.isArray(value)
appendArray.call(this, namespace, name, value)
else
appendEditor.call(this, namespace, name, value)
appendCheckbox = (namespace, name, value) ->
englishName = _.uncamelcase(name)
keyPath = "#{namespace}.#{name}"
@div class: 'checkbox', =>
@label for: keyPath, =>
@input id: keyPath, type: 'checkbox'
@text englishName
appendEditor = (namespace, name, value) ->
englishName = _.uncamelcase(name)
keyPath = "#{namespace}.#{name}"
if _.isNumber(value)
type = if value % 1 == 0 then 'int' else 'float'
else
type = 'string'
@label class: 'control-label', englishName
@div class: 'controls', =>
@subview keyPath.replace('.', ''), new Editor(mini: true, attributes: {id: keyPath, type: type})
appendArray = (namespace, name, value) ->
englishName = _.uncamelcase(name)
@label class: 'control-label', englishName
@div class: 'controls', =>
@text "readOnly: " + value.join(", ")

View File

@@ -1,5 +1,4 @@
ConfigPanel = require './config-panel'
{$$} = require 'space-pen'
{View, $$} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'
@@ -16,7 +15,7 @@ require 'jqueryui-browser/ui/jquery.ui.draggable'
delete window.jQuery
module.exports =
class ThemeConfigPanel extends ConfigPanel
class ThemeConfigPanel extends View
@content: ->
@div id: 'themes-config', =>
@legend "Themes"

View File

@@ -1,138 +0,0 @@
ConfigPanel = require '../lib/config-panel'
Editor = require 'editor'
describe "ConfigPanel", ->
it "automatically binds named input fields to their corresponding config keys", ->
class TestPanel extends ConfigPanel
@content: ->
@div =>
@input outlet: 'intInput', id: 'foo.int', type: 'int'
@input outlet: 'floatInput', id: 'foo.float', type: 'float'
@input outlet: 'stringInput', id: 'foo.string', type: 'string'
@input outlet: 'booleanInput', id: 'foo.boolean', type: 'checkbox'
config.set('foo.int', 22)
config.set('foo.boolean', true)
panel = new TestPanel
expect(panel.intInput.val()).toBe '22'
expect(panel.floatInput.val()).toBe ''
expect(panel.stringInput.val()).toBe ''
expect(panel.booleanInput.attr('checked')).toBeTruthy()
config.set('foo.int', 10)
expect(panel.intInput.val()).toBe '10'
expect(panel.floatInput.val()).toBe ''
expect(panel.stringInput.val()).toBe ''
config.set('foo.string', 'hey')
expect(panel.intInput.val()).toBe '10'
expect(panel.floatInput.val()).toBe ''
expect(panel.stringInput.val()).toBe 'hey'
config.set('foo.boolean', false)
expect(panel.booleanInput.attr('checked')).toBeFalsy()
panel.intInput.val('90.2').change()
expect(config.get('foo.int')).toBe 90
panel.floatInput.val('90.2').change()
expect(config.get('foo.float')).toBe 90.2
panel.intInput.val('0').change()
expect(config.get('foo.int')).toBe 0
panel.floatInput.val('0').change()
expect(config.get('foo.float')).toBe 0
panel.stringInput.val('moo').change()
expect(config.get('foo.string')).toBe 'moo'
panel.intInput.val('abcd').change()
expect(config.get('foo.int')).toBe 'abcd'
panel.floatInput.val('defg').change()
expect(config.get('foo.float')).toBe 'defg'
panel.intInput.val('').change()
expect(config.get('foo.int')).toBe undefined
panel.floatInput.val('').change()
expect(config.get('foo.float')).toBe undefined
panel.stringInput.val('').change()
expect(config.get('foo.string')).toBe undefined
it "automatically binds named editors to their corresponding config keys", ->
class TestPanel extends ConfigPanel
@content: ->
@div =>
@subview 'intEditor', new Editor(mini: true, attributes: { id: 'foo.int', type: 'int' })
@subview 'floatEditor', new Editor(mini: true, attributes: { id: 'foo.float', type: 'float' })
@subview 'stringEditor', new Editor(mini: true, attributes: { id: 'foo.string', type: 'string' })
config.set('foo.int', 1)
config.set('foo.float', 1.1)
config.set('foo.string', 'I think therefore I am.')
panel = new TestPanel
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(panel.intEditor.getText()).toBe '1'
expect(panel.floatEditor.getText()).toBe '1.1'
expect(panel.stringEditor.getText()).toBe 'I think therefore I am.'
config.set('foo.int', 2)
config.set('foo.float', 2.2)
config.set('foo.string', 'We are what we think.')
expect(panel.intEditor.getText()).toBe '2'
expect(panel.floatEditor.getText()).toBe '2.2'
expect(panel.stringEditor.getText()).toBe 'We are what we think.'
panel.intEditor.setText('3')
panel.floatEditor.setText('3.3')
panel.stringEditor.setText('All limitations are self imposed.')
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(config.get('foo.int')).toBe 3
expect(config.get('foo.float')).toBe 3.3
expect(config.get('foo.string')).toBe 'All limitations are self imposed.'
panel.intEditor.setText('not an int')
panel.floatEditor.setText('not a float')
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(config.get('foo.int')).toBe 'not an int'
expect(config.get('foo.float')).toBe 'not a float'
panel.intEditor.setText('')
panel.floatEditor.setText('')
panel.stringEditor.setText('')
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(config.get('foo.int')).toBe undefined
expect(config.get('foo.float')).toBe undefined
expect(config.get('foo.string')).toBe undefined
panel.intEditor.setText('0')
panel.floatEditor.setText('0')
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(config.get('foo.int')).toBe 0
expect(config.get('foo.float')).toBe 0
it "does not save the config value until it has been changed to a new value", ->
class TestPanel extends ConfigPanel
@content: ->
@div =>
@subview "fooInt", new Editor(mini: true, attributes: {id: 'foo.int', type: 'int'})
config.set('foo.int', 1)
observeHandler = jasmine.createSpy("observeHandler")
config.observe "foo.int", observeHandler
observeHandler.reset()
testPanel = new TestPanel
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(observeHandler).not.toHaveBeenCalled()
testPanel.fooInt.setText("1")
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(observeHandler).not.toHaveBeenCalled()
testPanel.fooInt.setText("2")
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(observeHandler).toHaveBeenCalled()

View File

@@ -0,0 +1,75 @@
SettingsPanel = require '../lib/settings-panel'
Editor = require 'editor'
getValueForId = (panel, id) ->
element = panel.find("##{id.replace('.', '\\.')}")
if element.is("input")
element.attr('checked')?
else
element.view().getText()
setValueForId = (panel, id, value) ->
element = panel.find("##{id.replace('.', '\\.')}")
if element.is("input")
element.attr('checked', if value then 'checked' else '')
element.change()
else
element.view().setText(value?.toString())
window.advanceClock(10000) # wait for contents-modified to be triggered
describe "SettingsPanel", ->
it "automatically binds named fields to their corresponding config keys", ->
config.set('foo.int', 22)
config.set('foo.float', 0.1)
config.set('foo.boolean', true)
config.set('foo.string', 'hey')
panel = new SettingsPanel()
expect(getValueForId(panel, 'foo.int')).toBe '22'
expect(getValueForId(panel, 'foo.float')).toBe '0.1'
expect(getValueForId(panel, 'foo.boolean')).toBeTruthy()
expect(getValueForId(panel, 'foo.string')).toBe 'hey'
config.set('foo.int', 222)
config.set('foo.float', 0.11)
config.set('foo.boolean', false)
config.set('foo.string', 'hey again')
expect(getValueForId(panel, 'foo.int')).toBe '222'
expect(getValueForId(panel, 'foo.float')).toBe '0.11'
expect(getValueForId(panel, 'foo.boolean')).toBeFalsy()
expect(getValueForId(panel, 'foo.string')).toBe 'hey again'
setValueForId(panel, 'foo.int', 90)
setValueForId(panel, 'foo.float', 89.2)
setValueForId(panel, 'foo.string', "oh hi")
setValueForId(panel, 'foo.boolean', true)
expect(config.get('foo.int')).toBe 90
expect(config.get('foo.float')).toBe 89.2
expect(config.get('foo.boolean')).toBe true
expect(config.get('foo.string')).toBe 'oh hi'
setValueForId(panel, 'foo.int', '')
setValueForId(panel, 'foo.float', '')
setValueForId(panel, 'foo.string', '')
expect(config.get('foo.int')).toBeUndefined()
expect(config.get('foo.float')).toBeUndefined()
expect(config.get('foo.string')).toBeUndefined()
it "does not save the config value until it has been changed to a new value", ->
config.set('foo.int', 1)
observeHandler = jasmine.createSpy("observeHandler")
config.observe "foo.int", observeHandler
observeHandler.reset()
testPanel = new SettingsPanel
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(observeHandler).not.toHaveBeenCalled()
setValueForId(testPanel, 'foo.int', 2)
expect(observeHandler).toHaveBeenCalled()
observeHandler.reset()
setValueForId(testPanel, 'foo.int', 2)
expect(observeHandler).not.toHaveBeenCalled()