htaccess.js
8.87 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/**
* Htaccess editor manager, manage adding directives, correct paths, local and
* session storage for htaccess restoring
*
* @package JMAP::HTACCESS::administrator::components::com_jmap
* @subpackage js
* @author Joomla! Extensions Store
* @copyright (C) 2015 Joomla! Extensions Store
* @license GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html
*/
//'use strict';
(function($) {
var Htaccess = function() {
/**
* Store locally the original htaccess contents to restore it later
*
* @access private
* @var String
*/
var originalHtaccess = null;
/**
* Store the session versioning of htaccess to serve the UNDO/REDO function
*
* @access private
* @var Array
*/
var versioningHtaccess = new Array();
/**
* Validation snippet
*
* @access private
* @var Object
*/
var validationSnippet = '<ul class="errorlist"><li class="validation label label-danger">' + COM_JMAP_HTACCESS_REQUIRED + '</li></ul>';
/**
* Directive adding message snippet
*
* @access private
* @var Object
*/
var messageSnippet = '<div class="htaccess_messages alert alert-success">' +
'<h4 class="alert-heading">Message</h4>' +
'<p>' + COM_JMAP_HTACCESS_DIRECTIVE_ADDED + '</p>' +
'</div>';
/**
* Directive dropdown jQobject
*
* @access private
* @var Object
*/
var directiveDropdown = $('#htaccess_directive');
/**
* Validate inputs required based on directive type
*
* @access private
* @return Boolean
*/
var validateInputs = function() {
for(var i=0; i < arguments.length; i++) {
var values = arguments[i];
if(!values) {
$('ul.errorlist').remove();
$('div.paths').append(validationSnippet);
$('div.paths input').filter(function() {
return !this.value;
}).addClass('error');
return false;
}
}
return true;
};
/**
* Logic for the directive adder, based on the type of directive the
* path is safely corrected and appended to the htaccess
*
* @access private
* @return Void
*/
var addHtaccessDirective = function() {
// Retrieve the type of directive to add
var directive = parseInt($('option:selected', directiveDropdown).data('directive'));
var directiveType = $('option:selected', directiveDropdown).data('type');
var directiveName = null;
// Populate the array of values
var directiveValues = new Array();
switch (directive) {
case 404:
var path1 = $('#path1').val();
// Validating values
if(!validateInputs(path1)) {
return;
}
directiveValues.push(path1);
directiveName = 'Redirect 404 ';
break;
case 301:
// Retrieve values
var path1 = $('#path1').val();
var path2 = $('#path2').val();
// Validating values
if(!validateInputs(path1, path2)) {
return;
}
directiveValues.push(path1);
directiveValues.push(path2);
directiveName = 'Redirect 301 ';
break;
}
// Act accordingly
var endSlash = '';
if(directiveType == 'folder') {
endSlash = '/';
}
$.each(directiveValues, function(index, value){
// Sanitize values as folder directive, trailing and ending slashes
directiveValues[index] = '/' + value.characterTrim('/', '\\') + endSlash;
});
// Everything is in place, now append the directive and show success message
// Append text to the text area
$('#htaccess_contents').val(function(_, val){
return val + '\n' + directiveName + directiveValues.join(' ');
});
// Scroll to bottom the textarea
$("#htaccess_contents").scrollTop($("#htaccess_contents")[0].scrollHeight);
// Reset value
$('div.paths input').val('');
// Show user message
$('#system-message-container').html(messageSnippet);
setTimeout(function(){
$('.htaccess_messages').fadeOut(500, function(){
$(this).remove();
});
},1000);
};
/**
* Function dummy constructor
*
* @access private
* @param String
* contextSelector
* @method <<IIFE>>
* @return Void
*/
(function __construct() {
// Popover trigger
$('label.hasHtaccessPopover').popover({trigger:'hover', placement:'bottom', html:1});
// Extend String Object prototype
String.prototype.characterTrim = function(character, escape) {
var trimRegexp = new RegExp('^' + escape + character + '+', 'i');
return this.replace(trimRegexp, "");
}
// Bind the main save event
$('#htaccess_save').on('click', function(){
// Store the current history version of the htaccess
var currentHtaccess = $('#htaccess_contents').val();
versioningHtaccess.push(currentHtaccess);
// Now serialize in the sessionStorage
sessionStorage.setItem('htaccess_history', JSON.stringify(versioningHtaccess));
});
// Manage dropdown
directiveDropdown.on('change', function(jqEvent) {
// Hide/Show fields and change label caption based on the
// directive type
var directive = $('option:selected', this).data('directive');
// Single field input
if (directive == '404') {
$('*[data-role=extended]').hide();
$('label[data-role=basic]').text(COM_JMAP_HTACCESS_PATH);
} else {
// Redirect with double fields
$('*[data-role=extended]').show();
$('label[data-role=basic]').text(COM_JMAP_HTACCESS_OLD_PATH);
}
// By default reset always validation
$('div.paths input.error').removeClass('error');
$('div.paths ul.errorlist').remove();
});
// Directive adder event
$('#htaccess_adder').on('click', {
bind : this
}, function(jqEvent) {
jqEvent.preventDefault();
addHtaccessDirective.call(jqEvent.data.bind);
});
// Step before, restore the previous history version of the htaccess
$('#htaccess_prev_versioning').on('click', function(jqEvent){
if( window.sessionStorage !== null ) {
// Discard the latest versioning, equal to the current file version
if(versioningHtaccess.length) {
versioningHtaccess.pop();
// Reassign/Refresh the session storage history array of versioning
sessionStorage.setItem('htaccess_history', JSON.stringify(versioningHtaccess));
}
var previousVersion = versioningHtaccess.pop();
// If not null restore the original version
if(previousVersion) {
$('#htaccess_contents').val(previousVersion);
$('input[name=restored]').val(1);
$('#htaccess_save').trigger('click');
} else {
// We reached the bottom of the stack AKA the stack is empty, restore the original version
$('#htaccess_restore').trigger('click');
}
}
});
// Restoration of the original session htaccess file
$('#htaccess_restore').on('click', function(jqEvent){
if( window.sessionStorage !== null ) {
originalHtaccess = sessionStorage.getItem('htaccess');
// If not null restore the original version
if(originalHtaccess) {
$('#htaccess_contents').val(originalHtaccess);
$('input[name=restored]').val(1);
$('#htaccess_save').trigger('click');
}
// Reset the history
sessionStorage.removeItem('htaccess_history');
}
});
// Activation of the .htaccess file
$('#htaccess_activate').on('click', function(jqEvent){
$('input[name=task]').val('htaccess.activateEntity');
$('#adminForm').submit();
});
// Bind validation reset
$('div.paths input').on('keyup', function(jqEvent){
$(this).removeClass('error');
// Everything correct?
if(!$('div.paths input').hasClass('error')) {
$('div.paths ul.errorlist').remove();
}
});
// Store the sessionStorage value of the original htaccess file before editing
if( window.sessionStorage !== null ) {
// Grab the current value of the htaccess textarea file, initialize it only if not available
if(!sessionStorage.getItem('htaccess')) {
originalHtaccess = $('#htaccess_contents').val();
sessionStorage.setItem('htaccess', originalHtaccess);
}
// Initialize the versioning counter
if(sessionStorage.getItem('htaccess_history')) {
versioningHtaccess = JSON.parse(sessionStorage.getItem('htaccess_history'));
// Is there some history versions?
if(!versioningHtaccess.length) {
$('#htaccess_prev_versioning').attr('disabled', 'disabled');
}
// Counter databind
$('*[data-bind=versions_counter]').text(versioningHtaccess.length);
} else {
$('#htaccess_prev_versioning').attr('disabled', 'disabled');
}
}
// Scroll to bottom the textarea
$("#htaccess_contents").scrollTop($("#htaccess_contents")[0].scrollHeight);
$('#fancy_closer').on('click', function(){
parent.jQuery.fancybox.close();
return false;
});
// Add desc popover
$('label.hasrightPopover').popover({trigger:'hover', placement:'bottom', html:1});
}).call(this);
}
// On DOM Ready
$(function() {
window.JMapHtaccess = new Htaccess();
});
})(jQuery);