admin.js ➔ errorPlacement   F
last analyzed

Complexity

Conditions 36

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 36
eloc 6
c 0
b 0
f 0
dl 0
loc 8
rs 0

How to fix   Complexity   

Complexity

Complex classes like admin.js ➔ errorPlacement often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
//htmlEditor
2
$('.ams-htmleditor').trumbowyg();
3
var safeDecodeEntities = (function() {
4
    // this prevents any overhead from creating the object each time
5
    var element = document.createElement('div');
6
    function decodeHTMLEntities(str) {
7
        if (str && typeof str === 'string') {
8
            // strip script/html tags
9
            str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
10
            str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
11
            element.innerHTML = str;
12
            str = element.textContent;
13
            element.textContent = '';
14
        }
15
        return str;
16
    }
17
    return decodeHTMLEntities;
18
})();
19
// Autocomplete */
20
(function($) {
21
    function AutoInput(element, options) {
22
        this.element = element;
23
        this.options = options;
24
        this.timer = null;
25
        this.items = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
26
        $(element).attr('autocomplete', 'off');
27
        $(element).on('focus', $.proxy(this.focus, this));
28
        $(element).on('blur', $.proxy(this.blur, this));
29
        $(element).on('keydown', $.proxy(this.keydown, this));
30
        $(element).after('<ul class="dropdown-menu"></ul>');
31
        $(element).siblings('ul.dropdown-menu').delegate('li', 'click', $.proxy(this.click, this));
32
    }
33
    AutoInput.prototype = {
34
        getElement: function() {
35
            return $(this.element);
36
        },
37
        focus: function() {
38
            this.request();
39
        },
40
        blur: function() {
41
            setTimeout(function(object) {
42
                object.hide();
43
            }, 200, this);
44
        },
45
        click: function(event) {
46
            event.preventDefault();
47
            value = $(event.target).data('value');
0 ignored issues
show
Bug introduced by
The variable value seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.value.
Loading history...
48
            if (value && this.items[value]) {
49
                this.options.select(this.items[value]);
50
            }
51
        },
52
        keydown: function(event) {
53
            switch (event.keyCode) {
54
                case 27: // escape
55
                    this.hide();
56
                    break;
57
                default:
58
                    this.request();
59
                    break;
60
            }
61
        },
62
        show: function() {
63
            var pos = $(this.element).position();
64
            console.log(pos);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
65
            $(this.element).siblings('ul.dropdown-menu').css({
66
                left: pos.leftm,
67
                top: pos.top + $(this.element).outerHeight(),
68
                width: $(this.element).outerWidth()
69
            });
70
            $(this.element).siblings('ul.dropdown-menu').show();
71
        },
72
        hide: function() {
73
            $(this.element).siblings('ul.dropdown-menu').hide();
74
        },
75
        request: function() {
76
            clearTimeout(this.timer);
77
            this.timer = setTimeout(function(object) {
78
                object.options.source($(object.element).val(), $.proxy(object.response, object));
79
            }, 350, this);
80
        },
81
        response: function(json) {
82
            html = '';
0 ignored issues
show
Bug introduced by
The variable html seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.html.
Loading history...
83
            if (json.length) {
84
                for (i = 0; i < json.length; i++) {
0 ignored issues
show
Bug introduced by
The variable i seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.i.
Loading history...
85
                    this.items[json[i]['value']] = json[i];
86
                }
87
                for (i = 0; i < json.length; i++) {
88
                    html += '<li class="dropdown-item" data-value="' + json[i]['value'] + '">' + safeDecodeEntities(json[i]['label']) + '</li>';
89
                }
90
            }
91
            if (html) {
92
                this.show();
93
            } else {
94
                this.hide();
95
            }
96
            $(this.element).siblings('ul.dropdown-menu').html(html);
97
        }
98
    };
99
    $.fn.autoinput = function(option) {
100
        return this.each(function() {
101
            var data = $(this).data('autoinput');
102
            if (!data) {
103
                data = new AutoInput(this, option);
104
                $(this).data('autoinput', data);
105
            }
106
        });
107
    }
108
})(window.jQuery);
109
$('input.autoinput').each(function() {
110
    var $this = $(this);
111
    var url = $this.data('url')
112
    var method = $this.data('type') || 'get'
113
    //     console.log($(this).attr('data-url'));
114
    $(this).autoinput({
115
        'source': function(request, response) {
116
            $.ajax({
117
                url: url,
118
                method: method,
119
                data: {
120
                    q: encodeURIComponent(request)
121
                },
122
                dataType: 'json',
123
                success: function(json) {
124
                    response(json);
125
                }
126
            });
127
        },
128
        'select': function(item) {
129
            if ($this.attr("data-limit") == "1") {
130
                $this.val(safeDecodeEntities(item['label']));
131
                $('#' + $this.attr('data-target')).val(item['value']);
132
            } else {
133
                $this.val('');
134
                $('#' + $this.attr('data-target') + '-' + item['value']).remove();
135
                $('#' + $this.attr('data-target')).append('<div class="list-group-item" id="' + $this.attr('data-target') + '-' + item['value'] + '"><div class="input-group"><span class="input-group-btn"><button class="btn btn-default btn-minus-circle" type="button"><i class="fa fa-minus-circle text-danger"></i></button></span><span class="form-control">' + item['label'] + '</span><input type="hidden" name="' + $this.attr('data-key') + '[]" value="' + item['value'] + '" /></div></div>');
136
            }
137
        }
138
    });
139
});
140
    //Autocomplete Slug
141
var timedCall = false;
142
$(document).on('keyup', '#pageTitle', function() {
143
	if(amsSettings.editing === false) return;
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...
Bug introduced by
The variable amsSettings seems to be never declared. If this is a global, consider adding a /** global: amsSettings */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
144
	if (timedCall) clearTimeout(timedCall);
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...
145
	var pageTitle = $(this).val()
146
	timedCall = setTimeout(function() {
147
		$.get(amsSettings.routes.slug + '?generate=1&page_slug=' + pageTitle)
0 ignored issues
show
Bug introduced by
The variable amsSettings seems to be never declared. If this is a global, consider adding a /** global: amsSettings */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
148
			.then(function(response) {
149
				$('#pageSlug').val(response.slug);
150
				typeof validator !== 'undefined' && validator.element("#pageSlug");
151
			});
152
	}, 350);
153
});
154
//form Validation
155
if (typeof $.validator !== 'undefined') {
156
    var validator = $('#create-asset-form').validate({
157
        ignore: [
158
            '.no-validate'
159
        ],
160
        invalidHandler: function() {
161
            var submits = $(this).find('[type="submit"]');
162
            setTimeout(function() {
163
                submits.attr('disabled', false);
164
                $('.nav-tabs a strong.required').remove();
165
                var validatePane = $('.tab-content.tab-validate .tab-pane:has(input.is-invalid)').each(function() {
0 ignored issues
show
Unused Code introduced by
The variable validatePane seems to be never used. Consider removing it.
Loading history...
166
                    var id = $(this).attr('id');
167
                    $('.nav-tabs,.nav-pills').find('a[href^="#' + id + '"]').append(' <strong class="required text-danger">***</strong> ');
168
                });
169
            });
170
        },
171
        errorElement: "em",
172
        errorPlacement: function errorPlacement(error, element) {
173
            error.addClass("invalid-feedback");
174
            if (element.prop("type") === "checkbox") {
175
                error.insertAfter(element.parent("label"));
176
            } else {
177
                error.insertAfter(element);
178
            }
179
        },
180
        highlight: function highlight(element) {
181
            $(element)
182
                .addClass("is-invalid")
183
                .removeClass("is-valid");
184
        },
185
        unhighlight: function unhighlight(element) {
186
            $(element)
187
                .addClass("is-valid")
188
                .removeClass("is-invalid");
189
        },
190
        rules: {
191
            page_slug: {
192
                required: true,
193
                remote: {
194
                    url: amsSettings.routes.slug,
0 ignored issues
show
Bug introduced by
The variable amsSettings seems to be never declared. If this is a global, consider adding a /** global: amsSettings */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
195
                    data: {
196
                        id: function() {
197
                            return $('#asset_id').val()
198
                        }
199
                    }
200
                }
201
            }
202
        }
203
    });
204
}
205
$('#addChild').click(function() {
206
    var idx = Number($('a.child-tab:last').attr('data-count'));
207
    var counter = idx + 1;
208
    var label = $('a.child-tab:last').attr('data-label') + ' ' + counter;
209
    $('a.remove-child').show();
210
    $('#addChild').hide();
211
    var childPill = $('a.child-tab:last').clone();
212
    childPill.attr('data-count', counter)
213
        .attr('id', 'v-pills-' + counter + '-tab')
214
        .attr('aria-controls', 'v-pills-' + counter)
215
        .attr('href', '#v-pills-' + counter)
216
        .removeClass('active')
217
        .text(label);
218
    $('#child-pills').append(childPill);
219
    var childTab = $('.child-tab-pane:last').clone();
220
    childTab.attr('id', 'v-pills-' + counter)
221
        .attr('ria-labelledby', 'v-' + counter + '-home-tab')
222
        .removeClass('active');
223
    childTab.find('h6').find('span').text($('a.child-tab:last').attr('data-label') + ' ' + counter);
224
    childTab.find('h6').find('a')
225
        .attr('data-target', '#v-pills-' + counter)
226
        .attr('data-count', counter)
227
        .text('Remove ' + $('a.child-tab:last').attr('data-label') + ' ' + counter);
228
    childTab.find('.child-asset-form-container').empty()
229
    $('.child-tab-pane:last').after(childTab);
230
    childTab.find('.child-asset-form-container').load(amsSettings.routes.inject + '?asset=' + $('a.child-tab:last').attr('data-type') + '&idx=' + counter, function() {
0 ignored issues
show
Bug introduced by
The variable amsSettings seems to be never declared. If this is a global, consider adding a /** global: amsSettings */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
231
        childPill.trigger("click");
232
        childTab.find('.ams-htmleditor').trumbowyg();
233
        $('#addChild').show();
234
    });
235
    return false
236
});
237
$(document).on("click", 'a.remove-child', function() {
238
    var count = $(this).attr('data-count');
239
    var tab = $(this).attr('data-target');
240
    // if it is not green, do this
241
    if (!$(this).hasClass('btn-success')) {
242
        $(tab).find('div.child-mask').show();
243
        $(tab).find('.asset-injector-input').attr('name', $(tab).find('.asset-injector-input').attr('name').replace('assetInjectionform', 'assetRemove'));
244
        $('a.child-tab[data-count=' + count + ']').addClass('removed');
245
        $(this).addClass('btn-success').removeClass('btn-danger').text($(this).text().replace('Remove', 'Restore'));
246
        if ($('a.child-tab').not('.removed').length <= 1) {
247
            $('a.remove-child').not('.btn-success').hide();
248
        }
249
    } else {
250
        $(tab).find('div.child-mask').hide();
251
        $(tab).find('.asset-injector-input').attr('name', $(tab).find('.asset-injector-input').attr('name').replace('assetRemove', 'assetInjectionform'));
252
        $('a.child-tab[data-count=' + count + ']').removeClass('removed');
253
        $(this).removeClass('btn-success').addClass('btn-danger').text($(this).text().replace('Restore', 'Remove'));
254
        $('a.remove-child').show();
255
    }
256
    return false;
257
});
258
$(document).on("click", ".ams-upload-button, .ams-upload-filename", function() {
259
    var target = $(this).data('target');
260
    $('#' + target).trigger("click");
261
});
262
$(document).on('keydown', '.ams-upload-filename', function(e) {
263
    e.preventDefault();
264
    e.stopPropagation();
265
    return false;
266
})
267
$(document).on("click", ".ams-upload-clear-button", function(e) {
268
    e.preventDefault();
269
    var target = $(this).data('target') + '_file';
270
    $('#' + target).val('');
271
    $('img[data-rel="' + target + '"]').attr('src', $('img[data-rel="' + target + '"]').data('placeholder'));
272
})
273
$(document).on("change", ':file', function() {
274
    var file = this.files[0];
275
    var data = new FormData();
276
    var target = $(this).attr('id') + '_file';
277
    var url = $(this).hasClass('ams-image') ? amsSettings.routes.image : amsSettings.routes.file
0 ignored issues
show
Bug introduced by
The variable amsSettings seems to be never declared. If this is a global, consider adding a /** global: amsSettings */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
278
    data.append("file", file);
279
    data.append("_token", $('meta[name="csrf-token"]').attr('content'));
280
    $.ajax({
281
        url: url,
282
        type: 'POST',
283
        data: data,
284
        cache: false,
285
        contentType: false,
286
        processData: false,
287
        xhr: function() {
288
            $('progress[data-rel="' + target + '"').show();
289
            var myXhr = $.ajaxSettings.xhr();
290
            if (myXhr.upload) {
291
                // For handling the progress of the upload
292
                myXhr.upload.addEventListener('progress', function(e) {
293
                    if (e.lengthComputable) {
294
                        $('progress').attr({
295
                            value: e.loaded,
296
                            max: e.total,
297
                        });
298
                    }
299
                }, false);
300
            }
301
            return myXhr;
302
        },
303
        success: function(res) {
304
            //	$('progress[data-rel="' + target + '"').hide();
305
            $('#' + target).val(res.file);
306
            $('img[data-rel="' + target + '"]').attr('src', amsSettings.routes.thumbs + '/' + res.file)
0 ignored issues
show
Bug introduced by
The variable amsSettings seems to be never declared. If this is a global, consider adding a /** global: amsSettings */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
307
        }
308
    });
309
});
310
$(document).on('change', 'select.asset_callback_selector', function() {
311
    $(this).closest('.form-group').find('.asset_autocallback').val('');
312
});
313
$('.asset_autocallback').each(function() {
314
    var $this = $(this);
315
    var callback_selector = $(this).closest('.form-group').find('.asset_callback_selector');
316
    var url = $this.data('url');
317
    $this.autoinput({
318
        source: function(request, response) {
319
            var data = {
320
                q: encodeURIComponent(callback_selector.val()),
321
                term: request
322
            }
323
            $.getJSON(url, data, function(data, status, xhr) {
0 ignored issues
show
Unused Code introduced by
The parameter status 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...
Unused Code introduced by
The parameter xhr 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...
324
                response(data);
325
            });
326
        },
327
        select: function(item) {
328
            $this.val(item.label);
329
            $this.siblings('.asset_autocallback_id').val(item.value);
330
            $this.siblings('.asset_autocallback_meta').val(callback_selector.val() + '|' + item.label);
331
            return false;
332
        }
333
    });
334
});
335
336
var updateSortedList = function(){
337
338
339
	$('.awd_list_container').each(function() {
340
		var $this = $(this);
341
		var n = $this.find('.idx').length;
342
		var ids;
343
344
		if(n == 0) {
0 ignored issues
show
Best Practice introduced by
Comparing n to 0 using the == operator is not safe. Consider using === instead.
Loading history...
345
			$this.find(".frmmsg.information").show();
346
			$this.find(".frmmsg.note").hide();
347
		}else{
348
			$this.find(".frmmsg.information").hide();
349
			$this.find(".frmmsg.note").show();
350
		}
351
352
		$this.find('.idx').each(function(index){
353
			ids += (index === 0) ? $(this).val() : '|' + $(this).val()
354
		})
355
		$(this).find('.asset_autocallback_value').val(ids)
356
357
	})
358
};
359
360
updateSortedList()
361
362
$('.awd_list_container .sortableMenu').each(function() {
363
	var sortableList = $(this).sortable({
0 ignored issues
show
Unused Code introduced by
The variable sortableList seems to be never used. Consider removing it.
Loading history...
364
		handle: '.handle',
365
		sort: true,  // sorting inside list
366
		animation: 150,
367
		fallbackOnBody: true,
368
		swapThreshold: 0.65,
369
		draggable: "li",  // Specifies which items inside the element should be draggable
370
		onSort: updateSortedList,
371
		ghostClass: 'ghost'
372
373
	});
374
});
375
376
$(document).on("click",'.btn-clear-sorted', function() {
377
	$(this).closest('li').fadeOut(function() {
378
		$(this).remove();
379
		updateSortedList();
380
	});
381
});