config_parser.js 10.1 KB
Newer Older
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
(function(requirejs, require, define) {
    define([], function() {
        return configParser;

        function configParser(state, config) {
            state.config = {
                'draggables': [],
                'baseImage': '',
                'targets': [],
                'onePerTarget': null, // Specified by user. No default.
                'targetOutline': true,
                'labelBgColor': '#d6d6d6',
                'individualTargets': null, // Depends on 'targets'.
                'foundErrors': false // Whether or not we find errors while processing the config.
            };

            getDraggables(state, config);
            getBaseImage(state, config);
            getTargets(state, config);
            getOnePerTarget(state, config);
            getTargetOutline(state, config);
            getLabelBgColor(state, config);

            setIndividualTargets(state);

            if (state.config.foundErrors !== false) {
                return false;
            }
29

30 31
            return true;
        }
32

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

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

                // Continue to next .every() call.
47 48 49 50 51 52
                    return true;
                });
            } else {
                console.log('ERROR: The type of config.draggables is no supported.');
                state.config.foundErrors = true;
            }
53
        }
54 55 56 57 58 59 60 61 62 63 64

        function getBaseImage(state, config) {
            if (config.hasOwnProperty('base_image') === false) {
                console.log('ERROR: "config" does not have a property "base_image".');
                state.config.foundErrors = true;
            } else if (typeof config.base_image === 'string') {
                state.config.baseImage = config.base_image;
            } else {
                console.log('ERROR: Property config.base_image is not of type "string".');
                state.config.foundErrors = true;
            }
65 66
        }

67 68
        function getTargets(state, config) {
            if (config.hasOwnProperty('targets') === false) {
69 70 71 72
            // 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.
73 74 75 76
            } else if ($.isArray(config.targets) === true) {
                config.targets.every(function(target) {
                    if (processTarget(state, target) !== true) {
                        state.config.foundErrors = true;
77 78

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

                // Continue to next .every() call.
83 84 85 86 87 88
                    return true;
                });
            } else {
                console.log('ERROR: Property config.targets is not of a supported type.');
                state.config.foundErrors = true;
            }
89
        }
90 91 92 93 94 95 96 97 98 99 100 101 102 103

        function getOnePerTarget(state, config) {
            if (config.hasOwnProperty('one_per_target') === false) {
                console.log('ERROR: "config" does not have a property "one_per_target".');
                state.config.foundErrors = true;
            } else if (typeof config.one_per_target === 'string') {
                if (config.one_per_target.toLowerCase() === 'true') {
                    state.config.onePerTarget = true;
                } else if (config.one_per_target.toLowerCase() === 'false') {
                    state.config.onePerTarget = false;
                } else {
                    console.log('ERROR: Property config.one_per_target can either be "true", or "false".');
                    state.config.foundErrors = true;
                }
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
        // 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.

114 115 116 117 118 119 120 121 122 123
            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 {
                        console.log('ERROR: Property config.target_outline can either be "true", or "false".');
                        state.config.foundErrors = true;
                    }
124
                } else {
125
                    console.log('ERROR: Property config.target_outline is not of a supported type.');
126 127
                    state.config.foundErrors = true;
                }
128
            }
129 130
        }

131
        function getLabelBgColor(state, config) {
132 133 134
        // 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.

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

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

152 153
        function processDraggable(state, obj) {
            if (
154 155 156
            (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
        ) {
162 163
                return false;
            }
Valera Rozuvan committed
164

165 166
        // 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').
167 168
            if (obj.target_fields.every(
            function(targetObj) {
169 170 171
                return processTarget(state, targetObj, false);
            }
        ) === false) {
172 173
                return false;
            }
174

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

177 178
            return true;
        }
179

180 181 182 183 184 185 186
    // 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.
187 188
        function processTarget(state, obj, pushToState) {
            if (
189
            (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 203 204
            if (pushToState !== false) {
                state.config.targets.push(obj);
            }

            return true;
205
        }
206

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

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

215 216
                return false;
            }
217

218
            return true;
219 220
        }

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

            if (obj.hasOwnProperty(attr) === false) {
                console.log('ERROR: Attribute "obj.' + attr + '" is not present.');
226

227 228
                return false;
            }
229

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

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

235 236
                return false;
            }
237

238
            obj[attr] = tempInt;
239

240
            return true;
241
        }
242

243 244 245 246
        function attrIsBoolean(obj, attr, defaultVal) {
            if (obj.hasOwnProperty(attr) === false) {
                if (defaultVal === undefined) {
                    console.log('ERROR: Attribute "obj.' + attr + '" is not present.');
247

248 249 250
                    return false;
                } else {
                    obj[attr] = defaultVal;
Valera Rozuvan committed
251

252 253 254
                    return true;
                }
            }
Valera Rozuvan committed
255

256
            if (obj[attr] === '') {
Valera Rozuvan committed
257
                obj[attr] = defaultVal;
258 259 260 261 262 263
            } else if ((obj[attr] === 'false') || (obj[attr] === false)) {
                obj[attr] = false;
            } else if ((obj[attr] === 'true') || (obj[attr] === true)) {
                obj[attr] = true;
            } else {
                console.log('ERROR: Attribute "obj.' + attr + '" is not a boolean.');
Valera Rozuvan committed
264

265
                return false;
Valera Rozuvan committed
266 267
            }

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