-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdistributeLayers.coffee
127 lines (100 loc) · 3.79 KB
/
distributeLayers.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
module.exports.distributeLayers =
# Defaults used by every public method
globalDefaults:
direction: "vertical"
startOffset: 0
# All layers have the same distance from eachother. 50, 100, 150, 200 etc.
sameDistance: (options) ->
# Arguments that are unique to this method
defaults =
distance: 500
# Set up options and validate properties
options = Object.assign({}, this.globalDefaults, defaults, options)
this._validateOptions(options)
# Loop through all layers and position them
offset = options.startOffset
for index, layer of options.layers
if options.direction == "vertical"
layer.y = offset
else
layer.x = offset
offset += options.distance
# Remember which method was used
this._setLayerMetadata(layer, 'methodUsed', 'sameDistance')
# Layers follow one another. They are spaced with the same margin.
sameMargin: (options) ->
# Arguments that are unique to this method
defaults =
margin: 10
# Set up options and validate properties
options = Object.assign({}, this.globalDefaults, defaults, options)
this._validateOptions(options)
# Loop through all layers and position them
offset = options.startOffset
for index, layer of options.layers
if options.direction == "vertical"
layer.y = offset
offset += layer.height + options.margin if layer.height > 0
else
layer.x = offset
offset += layer.width + options.margin if layer.width > 0
# Remember which method was used
this._setLayerMetadata(layer, 'methodUsed', 'sameMargin')
# Layers fill up the space between 0 and 'max'. The space
# between the layers is automatically calculated.
spaced: (options) ->
# Arguments that are unique to this method
defaults =
max: 1000
# Set up options and validate properties
options = Object.assign({}, this.globalDefaults, defaults, options)
this._validateOptions(options)
# Calculate the height/width of all layers combined
totalArea = 0
for index, layer of options.layers
if options.direction == "vertical"
totalArea += layer.height
else
totalArea += layer.width
# Calculate the spacing between each layer
spacing = (options.max - totalArea) / (options.layers.length - 1)
# Loop through all layers and position them
offset = options.startOffset
for index, layer of options.layers
if options.direction == "vertical"
layer.y = offset
offset += layer.height + spacing if layer.height > 0
else
layer.x = offset
offset += layer.width + spacing if layer.width > 0
# Remember which method was used
this._setLayerMetadata(layer, 'methodUsed', 'spaced')
# Simple validation for options objects. Designed to be beginner-friendly.
_validateOptions: (options) ->
if !options.layers
throw this._error('noLayers')
if !_.isArray(options.layers)
throw this._error('layersNotArray')
if options.layers.length == 0
throw this._error('layersArrayEmpty')
if typeof options.margin == "string"
throw this._error('numberAsString', options.margin)
if typeof options.startOffset == "string"
throw this._error('numberAsString', options.startOffset)
# Throws different errors for different error codes
_error: (id, value) ->
err = null
if id == "numberAsString"
err = new Error "Don't put quotation marks around numbers. " + "\"" + value + "\" should be written as " + value + "."
if id == "noLayers"
err = new Error "You didn't give distributeLayers.layers any value"
if id == "layersNotArray"
err = new Error "distributeLayers.layers expects an array"
if id == "layersArrayEmpty"
err = new Error "The array that you passed to distributeLayers.layers was empty"
return err
# Attaches custom metadata to layers
_setLayerMetadata: (layer, key, value) ->
if !layer.custom then layer.custom = {}
layer.custom.distributeLayers = {}
layer.custom.distributeLayers[key] = value