Completed
Pull Request — master (#51)
by Bui Quang
02:21
created

section.js ➔ ... ➔ element.slideUp(ꞌ300ꞌ)   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 1
nc 1
nop 0
1
import ImageUpload from './imageupload.js';
2
import Taxonomy from './taxonomy.js';
3
import PostType from './posttype.js';
4
import Layout from './layout.js';
5
6
var Section = function(sectionIndex, parentForm) {
7
8
    /**
9
     * section variable is created to represent Section instance.
10
     */
11
    var section = this;
12
13
    /**
14
     * index variable is created to represent Section index.
15
     */
16
    var index = sectionIndex;
17
18
    /**
19
     * id variable is create to represent id of the Section
20
     */
21
    var id = '#item-option-origin-' + index;
22
23
    /**
24
     * element variable is created to be a master element of the Section, all the variable will be found via element variable.
25
     */
26
    var element = $(id);
27
28
    /**
29
     * postType variable is created to represent Post Type part of the Section.
30
     */
31
    var postType;
32
33
    /**
34
     * taxonomies variable is created to represent all Taxonomy parts of the Section.
35
     */
36
    var taxonomies;
37
38
    /**
39
     * imageUpload variable is created to represent ImageUpload part of the Section.
40
     */
41
    var imageUpload;
42
43
    /**
44
     * deleteButton variable is created to represent Delete Buton of the Section.
45
     */
46
    var deleteButton;
47
48
    /**
49
     * errors variable is temporary variable to store all errors of the Section.
50
     */ 
51
    var errors = [];
52
53
    /** 
54
     * layout variable is created to handle all rendering layout stuff for the Section.
55
     */
56
    var layout = new Layout();
57
58
    /**
59
     * Initialize actions when create a instance of the Section.
60
     */
61
    this.init = function() {
62
        /* Assign all exist layout to corresponding variable. */
63
        section._checkLayoutAndAssignVariable();
64
        /**
65
         * Check if the Section has a Post Type part.
66
         *    If yes, Bind on selected feature when user changed the value of the post type.
67
         */
68
        if(typeof postType !== 'undefined') section._onSelectedPostType();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
69
        /* 
70
         * Check if the Section has a Delete Button.
71
         *    If yes, Bind delete feature when user click on Delete Button.
72
         */
73
        if(typeof deleteButton !== 'undefined') section.onDelete();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
74
    }
75
76
    /**
77
     * Check all exist parts and assign it to corresponding variable.
78
     */
79
    this._checkLayoutAndAssignVariable = function() {
80
        /* First: Check if PostType part exist.
81
         *    If yes, assign PostType part to postType variable.
82
         */
83
        if(section._checkLayoutExist('.post-type-row')) {
84
            postType = new PostType(id+' > .post-type-row');
85
        }
86
87
        /* Second: Check if Taxonomy parts exist.
88
         *    If yes, assign Taxonomy part to taxonomies variable.
89
         */
90
        if(section._checkLayoutExist('.taxonomy-row')) {
91
            var _taxonomies = [];
92
            $(id+' > .taxonomy-row').each(function(index, value){
93
                _taxonomies.push(new Taxonomy(value));
94
            });      
95
            taxonomies = _taxonomies;
96
        }
97
            
98
99
        /* Third: Check if ImageUpload part exist.
100
         *    If yes, assign ImageUpload part to imageUpload variable.
101
         */
102
        if(section._checkLayoutExist('.image-upload-row')) {
103
            imageUpload = new ImageUpload(id+' > .image-upload-row');
104
        }
105
106
        /* Fourth: Check if Delete Button exist.
107
         *    If yes, assign deleteButton variable to Delete Button.
108
         */
109
        if(section._checkLayoutExist('.btn-remove')) {
110
            deleteButton = $(id+' > .btn-remove');
111
        }
112
    }
113
114
    /**
115
     * Validate input data of the Section.
116
     */
117
    this.validate = function() {
118
        /**
119
         * Check if PostType value is exist.
120
         *    If PostType value is exist, check if ImageUpload value is exist.
121
         *       If ImageUpload value is not exist, store an error in errors variable, then return false.
122
         *    If PostType value is not exist, store an error in errors variable, then return false.
123
         */
124
        if(!postType.getValue()) {
125
            section._storeError('Post Type value on Section ' + index + ' must be not empty');
126
            return false;
127
        } else {
128
            if(!imageUpload.getId() || !imageUpload.getSource()) {
129
                section._storeError('Uploaded image value on Section ' + index + ' must be not empty');
130
                return false;
131
            }
132
        }
133
        return true;
134
    }
135
136
    /**
137
     * Store error in errors variable.
138
     */
139
    this._storeError = function(error) {
140
141
        errors.push(error);
142
    
143
    }
144
145
    /**
146
     * Truncate errors variable to store new errors of the Section.
147
     */
148
    this.truncateErrors = function() {
149
    
150
        errors = [];
151
    
152
    }
153
154
    /**
155
     * Return the errors of the Section.
156
     */
157
    this.getErrors = function() {
158
        /* Return the errors variable. */
159
        return errors;
160
    }
161
162
163
    /**
164
     * Bind delete feature when click on Delete Button.
165
     */
166
    this.onDelete = function() {
167
        deleteButton.click(function(event){
168
            /* Delete the section element. */
169
            event.preventDefault();
170
            element.slideUp( '300', function() {
171
                element.remove();
172
                /** 
173
                 * Remove section from parent form.
174
                 * Note that javascript array index start from 0, so we need to minus 1
175
                 */
176
                parentForm.removeSection(index - 1);
177
            });
178
        });
179
    }
180
181
    /**
182
     * Actions when user select a post type.
183
     */
184
    this._onSelectedPostType = function() {
185
        /* Bind actions when user select a post type. */
186
        postType.selectElement.change(function(e) { 
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
187
            /* First: Delete related layout. */
188
            section._deleteLayouts([taxonomies, imageUpload]);
189
            /* Second: Truncate related variables. */
190
            section._truncateVariables(['taxonomies', 'imageUpload']);
191
            /**
192
             * Third: 
193
             *    Check if selected value is not the blank value
194
             *    If yes:
195
             *        Get related layout.
196
             *        Add layout just received to the bottom of the section.
197
             *        Redo checkLayoutAndAssignVariable.
198
             */
199
            if(postType.getValue()) {
200
                layout.getRelatedSectionLayout(index, postType.getValue())
201
                      .done(section._addLayout)
202
                      .then(section._checkLayoutAndAssignVariable);
203
            }
204
        });
205
    }
206
207
    /**
208
     * Get Related Layout, related layout include taxonomies, image upload and image size.
209
     */
210
    this._getRelatedLayout = function() {
211
        return $.ajax({
212
            url: '/wp-admin/admin-ajax.php?action=wpdfi_get_related_layout',
213
            method: 'POST',
214
            data: {
215
                post_type: postType.getValue()
216
            },
217
        })
218
    }
219
220
    /**
221
     * Add new layout to the bottom of the Section.
222
     */
223
    this._addLayout = function(layout) {
224
        element.append(JSON.parse(layout));
225
    }
226
227
    /**
228
     * Truncate Section Variables.
229
     */
230
    this._truncateVariables = function(variables) {
231
        /**
232
         * We will need to modify the variable of the object, so we need to do something like pointer in this situation.
233
         * Unfortunately, there is no pointer in javascript. So I will use eval() function in this situation.
234
         */
235
236
        /* Loop through each element of variables array. */
237
        variables.forEach(function(_var) {
238
            /* Check if the variable is not undefined. */
239
            if(eval("typeof " + _var + " != 'undefined'")) {
0 ignored issues
show
Security Performance introduced by
Calls to eval are slow and potentially dangerous, especially on untrusted code. Please consider whether there is another way to achieve your goal.
Loading history...
240
                eval(_var + ' = null');
0 ignored issues
show
Security Performance introduced by
Calls to eval are slow and potentially dangerous, especially on untrusted code. Please consider whether there is another way to achieve your goal.
Loading history...
241
            }
242
            
243
        });
244
    } 
245
246
    /**
247
     * Delete Section Layouts.
248
     */
249
    this._deleteLayouts = function(variables) {
250
251
        /* Loop through each element of variables array. */
252
        variables.forEach(function(_var) {
253
            /* Check if the variable is not undefined. */
254
            if(typeof _var !== 'undefined' && _var) {
255
                /* Delete part */
256
                /* Check if variable can be looped or not. */
257
                if(typeof _var.length !== 'undefined') {
258
                    /* If yes, loop through each element and call to delete function. */
259
                    _var.forEach(function(objectElement) {
260
                        objectElement.delete();
261
                    })
262
                /* If variable can not be looped, call to delete function. */
263
                } else {
264
                    _var.delete();
265
                }   
266
            }
267
        });
268
    }
269
270
    /**
271
     * Check if layout exist or not via class name.
272
     */
273
    this._checkLayoutExist = function(className) {
274
        if(element.find(className).length > 0) return true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
275
        return false;
276
    } 
277
278
    /**
279
     * Get ID of the section.
280
     */
281
    this.getId = function() {
282
283
        return id;
284
285
    }
286
287
    /**
288
     * Get data index of the section.
289
     */
290
    this.getIndex = function() {
291
292
        return index;
293
294
    }
295
296
    /**
297
     * Remove delete button.
298
     */ 
299
    this.removeDeleteButton = function() {
300
301
        section._removeDeleteButtonEl();
302
303
    }
304
305
    /** 
306
     * Remove delete button element.
307
     */
308
    this._removeDeleteButtonEl = function() {
309
310
        deleteButton.remove();
311
        section._truncateVariables(['deleteButton']);
312
313
    }
314
315
    /**
316
     * Add new delete button.
317
     */
318
    this.addDeleteButton = function() {
319
320
        section._addDeleteButtonEl();
321
        section._updateDeleteButtonVar();
322
323
    }
324
325
    /**
326
     * Add new delete button element to the section.
327
     */
328
    this._addDeleteButtonEl = function() {
329
330
        var newDeleteButton = layout.getDeleteButtonLayout();
331
        element.append(newDeleteButton);
332
333
    }
334
335
    /**
336
     * Update delete button variable.
337
     */
338
    this._updateDeleteButtonVar = function() {
339
340
        deleteButton = element.find('.btn-remove');
341
    
342
    }
343
344
    this.reindex = function(newIndex) {
345
        var oldIndex = index;
346
        index = newIndex;
347
        section._updateID();
348
        section._updateElement();
349
        section._updateDataIndex();
350
        section._updateInput(oldIndex, newIndex);
351
        section._updateSelect(oldIndex, newIndex);
352
        section._updateLabel();
353
        section._truncateVariables(['postType', 'taxonomies', 'imageUpload', 'deleteButton']);
354
        section._checkLayoutAndAssignVariable();
355
356
    }
357
358
    /**
359
     * Update ID of the section.
360
     */
361
    this._updateID = function() {
362
363
        id = '#item-option-origin-' + index;
364
365
    }
366
367
    /**
368
     * Update Element of the section.
369
     */
370
    this._updateElement = function() {
371
        var idVal = id.replace('#', '');
372
        element.attr('id', idVal);
373
        element = $(id);
374
375
    }
376
377
    /**
378
     * Update attribute data-index of the section.
379
     */
380
    this._updateDataIndex = function() {
381
382
        element.attr('data-index', index);
383
384
    }
385
386
    /**
387
     * Reindex input of the section. 
388
     */
389
    this._updateInput = function(oldIndex, newIndex) {
390
391
        element.find('input').each(function(){
392
            var oldName = $(this).attr('name');
393
            var validName = (typeof oldName != 'undefined');
394
            /* Need to check name is valid or not before update the new name for the input. */
395
            if(validName) {
396
                /* Get the new name of the input by replace old index with new index. */
397
                var newName = oldName.replace(oldIndex, newIndex);
398
                /* Update new name for the input. */
399
                $(this).attr('name', newName);
400
            }
401
402
        });
403
404
    }
405
406
    /**
407
     * Reindex select input of the section. 
408
     */
409
    this._updateSelect = function(oldIndex, newIndex) {
410
411
        element.find('select').each(function(){
412
413
            var oldName = $(this).attr('name');
414
            var validName = (typeof oldName != 'undefined');
415
            /* Need to check name is valid or not before update the new name for the select input. */
416
            if(validName) {
417
                /* Get the new name of the select input by replace old index with new index. */
418
                var newName = oldName.replace(oldIndex, newIndex);
419
                /* Update new name for the select input. */
420
                $(this).attr('name', newName);
421
            }
422
        });
423
424
    };
425
426
    /**
427
     * Update section label with new index.
428
     */
429
    this._updateLabel = function() {
430
        var labelClass = '.section-label';
431
        var label = element.find(labelClass);
432
        /* Remove current label. */
433
        label.empty();
434
        /* Update new label. */ 
435
        label.text('Section ' + index);
436
437
    }
438
}
439
440
export default Section;
441
442