Skip to content

Commit

Permalink
Merge pull request #86 from it3s/layers
Browse files Browse the repository at this point in the history
Layers
  • Loading branch information
andersoncardoso committed Oct 28, 2014
2 parents 1d17582 + 826d44a commit d865389
Show file tree
Hide file tree
Showing 51 changed files with 1,937 additions and 138 deletions.
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
GIT
remote: git://github.com/it3s/meppit-map-rails.git
revision: e7b81c9ab6f4cdb03da8d8eff680b8dbb3dc2645
revision: e91cb7605515395ab692b5cf6bdbfd95f65719d6
specs:
meppit-map-rails (0.1.5)
meppit-map-rails (0.2.0)
coffee-rails
rails (~> 4.1.1)

Expand Down Expand Up @@ -213,7 +213,7 @@ GEM
rails (>= 3.2.13)
rest-client (>= 1.6.7)
method_source (0.8.2)
mime-types (2.4.2)
mime-types (2.4.3)
mini_magick (3.8.1)
subexec (~> 0.2.1)
mini_portile (0.6.0)
Expand Down
45 changes: 35 additions & 10 deletions app/assets/javascripts/base.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,35 @@ asyncFn = (fn) ->
, 0)
deferred

randomId = ->
Math.random().toString(36).substring(7)

getRef = (container) ->
href = container.attr('href')
if href?.length > 0 && href isnt "#" then href else undefined

compId = (name, container) ->
_id = container.attr('id') || getRef(container) || randomId(container)
"#{name}:#{_id}"

# components namespaces
components = { _instances: {} }
components =
_instances: {}

_getInstanceFor: (name, container) ->
components._instances[compId(name, container)]

_getInstancesFor: (container) ->
comps = container.data('components')?.split ' '
_.without (_.map comps, (name) -> components._getInstanceFor name, container)
, undefined

componentBuilder = (name, container) ->
options: ->
container.data("#{name.toLowerCase()}-options")

randomId: ->
Math.random().toString(36).substring(7)

getRef: ->
href = container.attr('href')
if href?.length > 0 && href isnt "#" then href else undefined

compId: ->
_id = container.attr('id') || @getRef() || @randomId()
"#{name}:#{_id}"
compId name, container

start: ->
if not components[name]?
Expand All @@ -52,6 +64,7 @@ componentBuilder = (name, container) ->
target.on evt, fn.bind(_comp)

_comp.initialize()
components._instances[_comp.identifier] = _comp
_comp

componentsManager = (container) ->
Expand Down Expand Up @@ -93,6 +106,18 @@ spinner = {
hide: -> @spinner?.remove()
}

# declare jQuery functions
(($) ->
$.fn.setComponentValue = (name, value) ->
if value is undefined
value = name
_.each components._getInstancesFor(this), (instance) ->
instance.setValue? value
else
components._getInstanceFor(name, this)?.setValue? value
this
)(jQuery)

# setup global App namesmpace
window.App =
mediator : mediator
Expand Down
60 changes: 60 additions & 0 deletions app/assets/javascripts/components/colorPicker.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#= require colpick
#
App.components.colorPicker = ->
attributes: ->
defaultColor: @attr.color || @container.val?() || '#0000ff'

initialize: ->
@findElements()
@bindEvents()
@initializePicker()
@setValue @attr.defaultColor

initializePicker: ->
@pickerEl.addClass 'color-picker'
@previewEl = $ '<div class="color-picker-preview"></div>'
@previewEl.css 'background-color', @getValue()
@fieldEl?.val @getValue()
@pickerEl.append @previewEl
@fieldEl?.hide()
@pickerEl.colpick
layout: 'hex'
color: @getValue()
submit: false
onChange: @onPickerChange.bind(this)

findElements: ->
if @container.is 'input'
@fieldEl = @container
@pickerEl = $('<div>').attr('title', @fieldEl.attr('title'))
@fieldEl.before @pickerEl
else
@pickerEl = @container

bindEvents: ->
@fieldEl?.change @onFieldChange.bind(this)

setValue: (value) ->
@color = value
@update()

getValue: -> @color

onPickerChange: (hsb, hex, rgb, el, bySetColor) ->
color = '#' + hex
@onChange color if @getValue() isnt color

onFieldChange: ->
@onChange @fieldEl.val() if @getValue() isnt @fieldEl.val()

onChange: (color) ->
@setValue color
@fieldEl?.val @getValue()
@fieldEl?.trigger 'change'
App.mediator.publish 'colorpicker:changed', color

update: ->
@previewEl.css 'background-color', @getValue()
@container.data 'colorPicker-color', @getValue()
@pickerEl.colpickSetColor @getValue(), true
@fieldEl?.val @getValue()
216 changes: 216 additions & 0 deletions app/assets/javascripts/components/editLayers.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
DataForm = ->
template: JST['templates/layerData']
_params: ['name', 'visible', 'fill_color', 'stroke_color', 'rule']

init: (opts) ->
@index = opts.index
@el = $ @template(opts)
@findFields()
@bindEvents()
@status = "active"
this

show: ->
@el.slideDown('fast')
@status = "active"

hide: ->
@el.slideUp('fast')
@status = "hidden"

toggle: ->
if @status is 'hidden' then @show() else @hide()

findFields: ->
@fields = {}
_.each ['name', 'visible', 'fill_color', 'stroke_color', 'tags'], (key) =>
@fields[key] = @el.find(".data_#{key}")

onChange: ->
App.mediator.publish 'layerData:changed', @index

getValue: ->
vals = {}
_.each @_params, (key) =>
if key == 'rule'
vals['rule'] = @_getRule()
else if @fields[key].attr('type') is 'checkbox'
vals[key] = @fields[key].prop('checked')
else
vals[key] = @fields[key].val()
vals

setValue: (entry) ->
_.each @_params, (key) =>
if key == 'rule'
return @_setRule(entry[key])
else if @fields[key].attr('type') is 'checkbox'
@fields[key].prop('checked', entry[key])
else
@fields[key].val(entry[key])
@fields[key].setComponentValue(entry[key])

bindEvents: ->
_.each @fields, (el, key) =>
el.change _.debounce(@onChange.bind(this), 100)

_getRule: ->
tags = @fields['tags'].val()
if tags.length > 0
{
operator: 'has'
property: 'tags'
value: tags.split(',')
}
else
null

_setRule: (rule) ->
if rule? and rule.operator == 'has' and rule.property == 'tags' and rule.value?
value = JSON.parse(rule.value).join(',')
@fields['tags'].setComponentValue('tags', value)


LayerItem = ->
template: JST['templates/layerItem']

init: (@opts) ->
@index = @opts.index
@el = $ @template(@opts)
@addDataForm(@opts)
@findElements()
@bindEvents()
@update()
this

addDataForm: (opts) ->
@data = DataForm().init(opts)
@el.find('.data-container').append @data.el

findElements: ->
@namePreviewEl = @el.find('.layer-name-preview')
@idEl = @el.find('.layer_id')
@colorPreviewEl = @el.find('.layer-color-preview')

onRemove: (evt) ->
evt.preventDefault()

@el.fadeOut 200, =>
App.mediator.publish 'layerItem:removed', @index
@el.remove()

getId: ->
if @idEl.val().length > 0 then @idEl.val() else null

getPosition: ->
@el.index()

getValue: ->
dataValue = @data.getValue()
_.extend {id: @getId(), position: @getPosition()}, dataValue

validateValue: ->
value = @getValue()
value.name.length > 0 && value.rule?

setValue: (entry)->
@idEl.val(entry.id)
@data.setValue(
name: _.result entry, 'name'
visible: _.result entry, 'visible'
fill_color: _.result entry, 'fill_color'
stroke_color: _.result entry, 'stroke_color'
rule: _.result entry, 'rule'
)
@update()

update: ->
value = @getValue()
@namePreviewEl.text(value.name || @opts.unnamed_layer)
@colorPreviewEl.css
'background-color': value.fill_color
'border-color': value.stroke_color
this

onChange: ->
@update()
App.mediator.publish 'layerItem:changed' if @getValue()

dataChanged: (evt, index) ->
@onChange() if index is @index

toggleData: (evt)->
evt.preventDefault()
@data.toggle()
this

showData: ->
@data.show()
this

hideData: ->
@data.hide()
this

bindEvents: ->
@el.find('.list-item-remove-btn').click @onRemove.bind(this)
@el.find('.list-item-metadata-btn').click @toggleData.bind(this)

App.mediator.subscribe 'layerData:changed', @dataChanged.bind(this)


App.components.editLayers = ->
itemDefaultValue:
visible: true
fill_color: () -> '#'+Math.floor(Math.random()*16777215).toString(16)
stroke_color: () -> '#'+Math.floor(Math.random()*16777215).toString(16)

attributes: ->
itemsContainer: @container.find('.layers-list')
addButton : @container.find('.add-new-btn')
layersInput : @container.find('.layers-value')
items : []
counter : 0

initialize: ->
layers = @attr.layersInput.val()
if layers.length > 0 && layers isnt '[]'
@loadData()
else
@addItem() # show an empty new entry
@listen()

loadData: ->
entries = _.sortBy JSON.parse(@attr.layersInput.val()), 'position'
_.each entries, (entry) =>
item = @addItem(entry)

addItem: (entry) ->
item = LayerItem().init _.extend({}, @attr.data, {index: @attr.counter++})
item.setValue @itemDefaultValue
@attr.items.push item
@attr.itemsContainer.append(item.el)
App.mediator.publish 'components:start', item.el
if entry?
item.setValue(entry).hideData()
item

listen: ->
@on @attr.addButton, 'click', @onAdd
@on @attr.itemsContainer, 'sortupdate', @onChange.bind(this)
App.mediator.subscribe 'layerItem:removed', @onRemove.bind(this)
App.mediator.subscribe 'layerItem:changed', @onChange.bind(this)

onAdd: (evt) ->
evt.preventDefault()
@addItem()

onRemove: (evt, index) ->
@attr.items[index] = null
@onChange()

onChange: ->
vals = []
_.each @attr.items, (item) ->
vals.push item.getValue() if item && item.validateValue()
@attr.layersInput.val JSON.stringify(vals)
6 changes: 3 additions & 3 deletions app/assets/javascripts/components/editRelations.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ relationItem = ->
if @metadata.status is 'hidden' then @metadata.show() else @metadata.hide()

bindEvents: ->
@el.find('.relation-remove-btn').click @onRemove.bind(this)
@el.find('.relation-metadata-btn').click @toggleMetadata.bind(this)
@el.find('.list-item-remove-btn').click @onRemove.bind(this)
@el.find('.list-item-metadata-btn').click @toggleMetadata.bind(this)

@targetEl.change @onChange.bind(this)
@typeEl.change @onChange.bind(this)
Expand All @@ -117,7 +117,7 @@ relationItem = ->
App.components.editRelations = ->
attributes: ->
itemsContainer: @container.find('.relations-list')
addButton : @container.find('.add-new-relation')
addButton : @container.find('.add-new-btn')
relationsInput: @container.find('.relations-value')
items : []
counter : 0
Expand Down
Loading

0 comments on commit d865389

Please sign in to comment.