config_parser.js 9.35 KB
Newer Older
1
(function (requirejs, require, define) {
2
define([], function () {
3 4
    return configParser;

5
    function configParser(state, config) {
6
        state.config = {
7
            'draggables': [],
8
            'baseImage': '',
9
            'targets': [],
10
            'onePerTarget': null, // Specified by user. No default.
11 12
            'targetOutline': true,
            'labelBgColor': '#d6d6d6',
13
            'individualTargets': null, // Depends on 'targets'.
14
            'foundErrors': false // Whether or not we find errors while processing the config.
15 16
        };

17 18 19 20 21 22 23 24 25
        getDraggables(state, config);
        getBaseImage(state, config);
        getTargets(state, config);
        getOnePerTarget(state, config);
        getTargetOutline(state, config);
        getLabelBgColor(state, config);

        setIndividualTargets(state);

26
        if (state.config.foundErrors !== false) {
27 28 29 30 31 32 33 34
            return false;
        }

        return true;
    }

    function getDraggables(state, config) {
        if (config.hasOwnProperty('draggables') === false) {
35
            console.log('ERROR: "config" does not have a property "draggables".');
36
            state.config.foundErrors = true;
37
        } else if ($.isArray(config.draggables) === true) {
38 39 40 41 42 43
            config.draggables.every(function (draggable) {
                if (processDraggable(state, draggable) !== true) {
                    state.config.foundErrors = true;

                    // Exit immediately from .every() call.
                    return false;
44
                }
45 46 47 48

                // Continue to next .every() call.
                return true;
            });
49
        } else {
50
            console.log('ERROR: The type of config.draggables is no supported.');
51
            state.config.foundErrors = true;
52
        }
53
    }
54

55 56
    function getBaseImage(state, config) {
        if (config.hasOwnProperty('base_image') === false) {
57
            console.log('ERROR: "config" does not have a property "base_image".');
58
            state.config.foundErrors = true;
59 60
        } else if (typeof config.base_image === 'string') {
            state.config.baseImage = config.base_image;
61
        } else {
62
            console.log('ERROR: Property config.base_image is not of type "string".');
63
            state.config.foundErrors = true;
64
        }
65
    }
66

67 68 69 70 71 72 73
    function getTargets(state, config) {
        if (config.hasOwnProperty('targets') === false) {
            // It is possible that no "targets" were specified. This is not an error.
            // In this case the default value of "[]" (empty array) will be used.
            // Draggables can be positioned anywhere on the image, and the server will
            // get an answer in the form of (x, y) coordinates for each draggable.
        } else if ($.isArray(config.targets) === true) {
74 75 76 77 78 79
            config.targets.every(function (target) {
                if (processTarget(state, target) !== true) {
                    state.config.foundErrors = true;

                    // Exit immediately from .every() call.
                    return false;
80
                }
81 82 83 84

                // Continue to next .every() call.
                return true;
            });
85
        } else {
86
            console.log('ERROR: Property config.targets is not of a supported type.');
87
            state.config.foundErrors = true;
88
        }
89
    }
90

91 92
    function getOnePerTarget(state, config) {
        if (config.hasOwnProperty('one_per_target') === false) {
93
            console.log('ERROR: "config" does not have a property "one_per_target".');
94
            state.config.foundErrors = true;
95
        } else if (typeof config.one_per_target === 'string') {
96
            if (config.one_per_target.toLowerCase() === 'true') {
97
                state.config.onePerTarget = true;
98
            } else if (config.one_per_target.toLowerCase() === 'false') {
99
                state.config.onePerTarget = false;
100
            } else {
101
                console.log('ERROR: Property config.one_per_target can either be "true", or "false".');
102
                state.config.foundErrors = true;
103
            }
104
        } else {
105
            console.log('ERROR: Property config.one_per_target is not of a supported type.');
106
            state.config.foundErrors = true;
107
        }
108
    }
109

110
    function getTargetOutline(state, config) {
111 112 113 114 115 116 117 118 119 120
        // It is possible that no "target_outline" was specified. This is not an error.
        // In this case the default value of 'true' (boolean) will be used.

        if (config.hasOwnProperty('target_outline') === true) {
            if (typeof config.target_outline === 'string') {
                if (config.target_outline.toLowerCase() === 'true') {
                    state.config.targetOutline = true;
                } else if (config.target_outline.toLowerCase() === 'false') {
                    state.config.targetOutline = false;
                } else {
121
                    console.log('ERROR: Property config.target_outline can either be "true", or "false".');
122 123
                    state.config.foundErrors = true;
                }
124
            } else {
125
                console.log('ERROR: Property config.target_outline is not of a supported type.');
126
                state.config.foundErrors = true;
127
            }
128
        }
129
    }
130

131
    function getLabelBgColor(state, config) {
132 133 134 135 136 137 138
        // It is possible that no "label_bg_color" was specified. This is not an error.
        // In this case the default value of '#d6d6d6' (string) will be used.

        if (config.hasOwnProperty('label_bg_color') === true) {
            if (typeof config.label_bg_color === 'string') {
                state.config.labelBgColor = config.label_bg_color;
            } else {
139
                console.log('ERROR: Property config.label_bg_color is not of a supported type.');
140
            }
141
        }
142
    }
143

144
    function setIndividualTargets(state) {
145
        if (state.config.targets.length === 0) {
146
            state.config.individualTargets = false;
147
        } else {
148
            state.config.individualTargets = true;
149
        }
150
    }
151

152
    function processDraggable(state, obj) {
153 154 155 156
        if (
            (attrIsString(obj, 'id') === false) ||
            (attrIsString(obj, 'icon') === false) ||
            (attrIsString(obj, 'label') === false) ||
157

158 159 160
            (attrIsBoolean(obj, 'can_reuse', false) === false) ||

            (obj.hasOwnProperty('target_fields') === false)
161
        ) {
Valera Rozuvan committed
162 163 164
            return false;
        }

165 166 167 168 169 170 171 172 173 174
        // Check that all targets in the 'target_fields' property are proper target objects.
        // We will be testing the return value from .every() call (it can be 'true' or 'false').
        if (obj.target_fields.every(
            function (targetObj) {
                return processTarget(state, targetObj, false);
            }
        ) === false) {
            return false;
        }

175
        state.config.draggables.push(obj);
176

177 178
        return true;
    }
179

180 181 182 183 184 185 186 187
    // We need 'pushToState' parameter in order to simply test an object for the fact that it is a
    // proper target (without pushing it to the 'state' object). When
    //
    //     pushToState === false
    //
    // the object being tested is not going to be pushed to 'state'. The function will onyl return
    // 'true' or 'false.
    function processTarget(state, obj, pushToState) {
188 189
        if (
            (attrIsString(obj, 'id') === false) ||
190

191 192
            (attrIsInteger(obj, 'w') === false) ||
            (attrIsInteger(obj, 'h') === false) ||
193

194 195 196
            (attrIsInteger(obj, 'x') === false) ||
            (attrIsInteger(obj, 'y') === false)
        ) {
197 198
            return false;
        }
199

200 201 202
        if (pushToState !== false) {
            state.config.targets.push(obj);
        }
203

204 205
        return true;
    }
206

207
    function attrIsString(obj, attr) {
Valera Rozuvan committed
208
        if (obj.hasOwnProperty(attr) === false) {
209
            console.log('ERROR: Attribute "obj.' + attr + '" is not present.');
Valera Rozuvan committed
210 211 212

            return false;
        } else if (typeof obj[attr] !== 'string') {
213
            console.log('ERROR: Attribute "obj.' + attr + '" is not a string.');
214

215
            return false;
216 217
        }

218 219
        return true;
    }
220

221 222
    function attrIsInteger(obj, attr) {
        var tempInt;
223

Valera Rozuvan committed
224
        if (obj.hasOwnProperty(attr) === false) {
225
            console.log('ERROR: Attribute "obj.' + attr + '" is not present.');
Valera Rozuvan committed
226 227 228 229

            return false;
        }

230
        tempInt = parseInt(obj[attr], 10);
231

232
        if (isFinite(tempInt) === false) {
233
            console.log('ERROR: Attribute "obj.' + attr + '" is not an integer.');
234

235 236
            return false;
        }
237

238
        obj[attr] = tempInt;
239

240
        return true;
241
    }
Valera Rozuvan committed
242 243 244 245

    function attrIsBoolean(obj, attr, defaultVal) {
        if (obj.hasOwnProperty(attr) === false) {
            if (defaultVal === undefined) {
246
                console.log('ERROR: Attribute "obj.' + attr + '" is not present.');
Valera Rozuvan committed
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

                return false;
            } else {
                obj[attr] = defaultVal;

                return true;
            }
        }

        if (obj[attr] === '') {
            obj[attr] = defaultVal;
        } else if ((obj[attr] === 'false') || (obj[attr] === false)) {
            obj[attr] = false;
        } else if ((obj[attr] === 'true') || (obj[attr] === true)) {
            obj[attr] = true;
        } else {
263
            console.log('ERROR: Attribute "obj.' + attr + '" is not a boolean.');
Valera Rozuvan committed
264 265 266 267 268 269

            return false;
        }

        return true;
    }
270
}); // End-of: define([], function () {
271
}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); // End-of: (function (requirejs, require, define) {