blob: 3040868bdad7bee6e0697bd69b915de3bfa9195c [file] [log] [blame]
/**
* RD Mail Form
* @version 1.1.0
* @author Evgeniy Gusarov (Stmechanus | Diversant)
* @license The MIT License (MIT)
* @todo Time Picker
* @todo Date Picker
* @todo Checboxes
* @todo Radio Buttons
* @todo TextArea
* @todo InputMasks
* @todo Input File
*/
;
(function ($, window, documen, undefined) {
var msg, e;
/**
* Template for some information status messages.
* @private
*/
msg = {
'MF000': 'Sent',
'MF001': 'Recipients are not set!',
'MF002': 'Form will not work locally!',
'MF003': 'Please, define email field in your form!',
'MF004': 'Please, define type of your form!',
'MF254': 'Something went wrong with PHPMailer!',
'MF255': 'Aw, snap! Something went wrong.'
};
/**
* Creates a form.
* @class The RD Mail Form.
* @public
* @param {HTMLElement|jQuery} element - The element to create the form for.
* @param {Object} [options] - The options
*/
function RDMailForm(element, options) {
/**
* Current options set by the caller including defaults.
* @public
*/
this.options = $.extend({}, RDMailForm.Defaults, options);
/**
* Plugin element.
* @public
*/
this.$element = $(element);
/**
* References to the running plugins of this Mail Form.
* @protected
*/
this._plugins = {};
/**
* All event handlers of Mail Form
* @protected
* @type {Object}
*/
this._handlers = {
'mf.success mf.fail': $.proxy(this.update, this),
'mf.process': $.proxy(this.process, this),
'reset': $.proxy(this.reset, this)
};
/**
* Creates the instances of all attached plugins
* @protected
*/
$.each(RDMailForm.Plugins, $.proxy(function (key, plugin) {
this._plugins[key[0].toLowerCase() + key.slice(1)]
= new plugin(this);
}, this));
this.initialize();
};
/**
* Default options for the Form.
* @public
*/
RDMailForm.Defaults = {
baseClass: 'rd-mailform'
};
/**
* Contains all registered plugins.
* @public
*/
RDMailForm.Plugins = {};
/**
* Initializes the Mail Form.
* @protected
*/
RDMailForm.prototype.initialize = function () {
this.$element.trigger('mf.initialize');
this.$element
.addClass(this.options.baseClass)
.trigger('reset');
this.create();
this.watch();
this.$element.trigger('mf.initialized');
};
/**
* Creates additional DOM of Mail Form
* @protected
*/
RDMailForm.prototype.create = function () {
var _self = this;
if (_self.$element.attr("data-type")) {
_self.$element
.prepend($("<input/>", {
"type": "hidden",
"name": "form-type",
"value": _self.$element.attr("data-type")
}));
}
};
/**
* Creates the events watchers of Mail Form
* @protected
*/
RDMailForm.prototype.watch = function () {
var _self = this;
_self.$element
.ajaxForm({
beforeSubmit: function (e) {
_self.$element.trigger('mf.process');
},
error: function (result) {
_self.$element.trigger('mf.fail', {code: result, message: msg[result]});
},
success: function (result) {
console.log(result);
if (result == 'MF000') {
_self.$element.trigger('mf.success', {code: result, message: msg[result]});
} else {
result = result.length == 5 ? result : 'MF255';
_self.$element.trigger('mf.fail', {code: result, message: msg[result]});
}
}
})
.on(this._handlers);
};
/**
* Changes form status to process
* @protected
*/
RDMailForm.prototype.process = function () {
this.$element.addClass('process');
};
/**
* Updates form status on sent
* @protected
*/
RDMailForm.prototype.update = function (e, data) {
this.$element.removeClass('process');
if (data.code === 'MF000') {
this.$element.addClass('success');
} else {
this.$element.addClass('fail');
}
setTimeout($.proxy(function () {
this.$element.trigger('reset');
}, this), 3000);
};
/**
* Resets form status
* @protected
*/
RDMailForm.prototype.reset = function () {
this.$element.removeClass('success');
this.$element.removeClass('fail');
this.$element.trigger('mf.reset');
};
/**
* The jQuery Plugin for the RD Mail Form
* @public
*/
$.fn.rdMailForm = function (options) {
return this.each(function () {
if (!$(this).data('rdMailForm')) {
$(this).data('rdMailForm', new RDMailForm(this, options));
}
});
};
/**
* The constructor for the jQuery Plugin
* @public
*/
$.fn.rdMailForm.Constructor = RDMailForm;
})(window.jQuery, window, document);
/**
* Validator Plugin
* @version 1.0.0
* @author Evgeniy Gusarov (Stmechanus | Diversant)
* @license The MIT License (MIT)
*/
;
(function ($, window, document, undefined) {
/**
* Creates the validator plugin.
* @class The Validator Plugin
* @param {RDMailForm} form - The Mail Form
*/
var Validator = $.fn.rdMailForm.Constructor.Plugins.Validator = function (form) {
/**
* Reference to the core.
* @protected
* @type {RDMailForm}
*/
this._core = form;
/**
* All event handlers.
* @protected
* @type {Object}
*/
this._handlers = {
'mfValidator.validate': this.validate,
'mfValidator.error': this.error,
'mfValidator.valid': this.valid,
'mfValidator.reset': this.reset,
'mfValidator.click': $.noop()
};
// set default options
this._core.options = $.extend({}, Validator.Defaults, this._core.options);
this.initialize();
};
/**
* Default options.
* @public
*/
Validator.Defaults = {
validator: {
'applyTo': '[data-constraints]',
'class': 'mfValidation',
'constraints': {
'@LettersOnly': {
rule: '^([a-zA-Zа-яА-ЯіїёІЇЁєЄҐґ\\s]{0,})$',
message: 'Please use letters only!'
},
'@NumbersOnly': {
rule: '^-?\\d*\\.?\\d*$',
message: 'Please use numbers only!'
},
'@NotEmpty': {
rule: '([^\\s])',
message: 'Field should not be empty!'
},
'@Email': {
rule: '^(([\\w-]+(?:\\.[\\w-]+)*)@((?:[\\w-]+\\.)*\\w[\\w-]{0,66})\\.([a-z]{2,6}(?:\\.[a-z]{2})?)){0,}$',
message: 'Enter valid e-mail address!'
},
'@Phone': {
rule: '^(\\+?\\d{0,3}\\s*\\(?\\d{1,3}\\)?\\s*\\d{3}\\s*\\d{4}){0,}$',
message: 'Enter valid phone number!'
},
'@Date': {
rule: function (o) {
if (!navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
return new RegExp('^($)|(((0[13578]|10|12)(-|\\/)((0[1-9])|([12])([0-9])|(3[01]?))(-|\\/)((19)([2-9])(\\d{1})|(20)([01])(\\d{1})|([8901])(\\d{1}))|(0?[2469]|11)(-|\/)(([1-9])|(0[1-9])|([12])([0-9]?)|(3[0]?))(-|\/)((19)([2-9])(\\d{1})|(20)([01])(\\d{1})|([8901])(\\d{1}))))$').test(o.val())
} else {
return true;
}
},
message: 'Use MM/DD/YYYY format!'
},
'@SelectRequired': {
rule: function (o) {
return o.find("option:selected").index() !== 0;
},
message: 'Please choose an option!'
}
}
}
};
/**
* Initializes validator for attached elements.
* @protected
*/
Validator.prototype.initialize = function () {
this._core.$element.trigger('mfValidator.initialize');
this.create();
this.watch();
this._core.$element.trigger('mfValidator.initialized');
};
/**
* Creates a necessary additional DOM for validating.
* @protected
*/
Validator.prototype.create = function () {
var self = this;
this._core.$element
.find(this._core.options.validator.applyTo)
.each(function () {
$(this)
.parent()
.append($('<span/>', {
'class': self._core.options.validator.class
}))
})
};
/**
* Creates all attached event handlers of validator.
* @protected
*/
Validator.prototype.watch = function () {
var self = this;
this._core.$element
.find(this._core.options.validator.applyTo)
.on('keyup', function (e) {
if ($(this).is('input') || $(this).is('textarea')) {
$(this).parent().trigger('mfValidator.validate', {
options: self._core.options.validator
});
}
})
.on('change', function (e) {
$(this).parent().trigger('mfValidator.validate', {
options: self._core.options.validator
});
})
.parent()
.on(this._handlers)
.find('.' + this._core.options.validator.class)
.on('click', function (e) {
$(this)
.removeClass("error").removeClass("show").addClass("hide")
.parent()
.trigger('mfValidator.click')
.find(self._core.options.validator.applyTo)
.focus();
});
this._core.$element
.on('submit', $.proxy(function (e) {
this._core.$element.find(this._core.options.validator.applyTo).each(function () {
$(this).parent().trigger('mfValidator.validate', {
options: self._core.options.validator
});
});
if (this._core.$element.find('.error').length) {
e.preventDefault();
return false;
}
}, this))
.on('mf.reset', $.proxy(function (e) {
this._core.$element.find(this._core.options.validator.applyTo).each(function () {
$(this).parent().trigger('mfValidator.reset', {options: self._core.options.validator});
});
}, this));
};
/**
* Validates all attached elements.
* @protected
*/
Validator.prototype.validate = function (e, data) {
var errors = [],
$this = $(this),
target = $this.find(data.options.applyTo),
ruleset = target.data('constraints').match(/\@\w+/g),
value = target.val();
for (var i in ruleset) {
if (data.options.constraints[ruleset[i]]) {
switch (typeof(data.options.constraints[ruleset[i]].rule)) {
case "function":
if (!data.options.constraints[ruleset[i]].rule(target)) {
errors.push(data.options.constraints[ruleset[i]].message);
}
break;
default :
if (!new RegExp(data.options.constraints[ruleset[i]].rule).test(value)) {
errors.push(data.options.constraints[ruleset[i]].message);
}
}
}
}
if (errors.length) {
$(this).trigger('mfValidator.error', {options: data.options, errors: errors});
} else {
$(this).trigger('mfValidator.valid', {options: data.options});
}
};
/**
* Notifies when element is not valid.
* @protected
*/
Validator.prototype.error = function (e, data) {
$(this).find('.' + data.options.class).removeClass('valid').removeClass('hide').addClass('show').addClass('error').text(data.errors);
};
/**
* Notifies when element is valid.
* @protected
*/
Validator.prototype.valid = function (e, data) {
var o = $(this).find('.' + data.options.class);
if (o.hasClass('error')) {
o.removeClass("error").addClass("hide");
}
o.find('.' + data.options.class).removeClass('show').addClass('valid').text(data.errors);
};
/**
* Resets the validation status
* @protected
*/
Validator.prototype.reset = function (e, data) {
var o = $(this).find('.' + data.options.class);
if (o.hasClass('error')) {
o.removeClass("error").addClass("hide");
}
$(this).find('.' + data.options.class).removeClass('show');
};
})(window.jQuery, window, document);
/**
* Input Plugin
* @version 1.0.0
* @author Evgeniy Gusarov (Stmechanus | Diversant)
* @license The MIT License (MIT)
*/
;
(function ($, window, document, undefined) {
/**
* Creates the input plugin.
* @class The Input Plugin
* @param {RDMailForm} form - The Mail Form
*/
var Input = $.fn.rdMailForm.Constructor.Plugins.Input = function (form) {
/**
* Reference to the core.
* @protected
* @type {RDMailForm}
*/
this._core = form;
/**
* All event handlers.
* @protected
* @type {Object}
*/
this._handlers = {
'mfInput.focus': this.focus,
'mfInput.blur': this.blur,
'mfInput.type': this.type,
'mfInput.delete': this.delete,
'mfInput.fill': this.fill,
'mfInput.empty': this.empty,
'mfInput.idle': this.idle,
'mfInput.reset': this.reset,
'click': function (e) {
e.preventDefault();
return false;
}
};
// set default options
this._core.options = $.extend({}, Input.Defaults, this._core.options);
this.initialize();
};
/**
* Default options.
* @public
*/
Input.Defaults = {
input: {
'applyto': 'input[type="text"], input[type="date"], textarea',
'class': 'mfInput'
}
};
/**
* Initializes all inputs in the Mail Form.
* @protected
*/
Input.prototype.initialize = function () {
this._core.$element.trigger('mfInput.initialize');
this.create();
this.watch();
this._core.$element.trigger('mfInput.initialized');
};
/**
* Creates a necessary additional DOM of input.
* @protected
*/
Input.prototype.create = function () {
this._core.$element
.find(this._core.options.input.applyto)
.parent()
.addClass(this._core.options.input.class);
};
/**
* Creates all attached event handlers of input.
* @protected
*/
Input.prototype.watch = function () {
this._core.$element
.find(this._core.options.input.applyto)
.on('focus', function () {
$(this).parent().trigger('mfInput.focus');
})
.on('blur', function () {
$(this).parent().trigger('mfInput.blur');
if ($(this).val() === '') {
$(this).parent().trigger('mfInput.void');
}
})
.on('keydown', this, function (e) {
if (e.data.ignore(e)) {
return;
}
if (e.keyCode === 8 || e.keyCode === 46) {
$(this).parent().trigger('mfInput.delete');
}
if (e.keyCode === 32 || e.keyCode > 46) {
$(this).parent().trigger('mfInput.type');
}
})
.on('keyup', this, function (e) {
var _this = $(this);
if (e.data.ignore(e)) {
return;
}
if (_this.val() === '') {
_this.parent().trigger('mfInput.empty');
}
if (e.keyCode === 8 || e.keyCode === 46) {
if (self.timer) {
clearTimeout(self.timer);
}
self.timer = setTimeout(function () {
_this.parent().trigger('mfInput.idle');
}, 1000);
}
else {
_this.parent().trigger('mfInput.fill');
_this.parent().trigger('mfInput.type');
if (self.timer) {
clearTimeout(self.timer);
}
self.timer = setTimeout(function () {
_this.parent().trigger('mfInput.idle');
}, 1000);
}
})
.on('keypress', this, function (e) {
if (e.data.ignore(e.keyCode)) {
return;
}
var _this = $(this);
if (self.timer) {
clearTimeout(self.timer);
}
self.timer = setTimeout(function () {
_this.parent().trigger('mfInput.idle');
}, 1000);
})
.parent()
.on(this._handlers);
this._core.$element.on('mf.reset', this, function (e) {
$(this).find('.' + e.data._core.options.input.class).each(function () {
$(this).trigger('mfInput.reset');
});
})
};
/**
* Notify when input is in focus.
* @protected
*/
Input.prototype.focus = function () {
$(this).addClass('focused');
};
/**
* Notify when input was blured.
* @protected
*/
Input.prototype.blur = function () {
$(this).removeClass('focused');
};
/**
* Notify when writing in input.
* @protected
*/
Input.prototype.type = function () {
$(this).removeClass('deleting');
$(this).addClass('typing');
};
/**
* Notify when deleting in input.
* @protected
*/
Input.prototype.delete = function () {
$(this).removeClass('typing');
$(this).addClass('deleting');
};
/**
* Notify when input is not empty.
* @protected
*/
Input.prototype.fill = function () {
$(this).addClass('filled');
};
/**
* Notify when input is empty.
* @protected
*/
Input.prototype.empty = function () {
$(this).removeClass('filled');
};
/**
* Notify when input is idling.
* @protected
*/
Input.prototype.idle = function () {
$(this).removeClass('typing');
$(this).removeClass('deleting');
};
/**
* Resets the input status.
* @protected
*/
Input.prototype.reset = function () {
$(this).removeClass('focused');
$(this).removeClass('deleting');
$(this).removeClass('filled');
$(this).removeClass('typing');
$(this).removeClass('error');
};
/**
* Checks the keycode for deprecated value.
* @protected
*/
Input.prototype.ignore = function (e) {
if (e.keyCode === 144 || e.keyCode === 20 || e.keyCode === 17 || e.keyCode === 37 || e.keyCode === 38 || e.keyCode === 39
|| e.keyCode === 40 || e.keyCode === 112 || e.keyCode === 113 || e.keyCode === 114 || e.keyCode === 115 || e.keyCode === 116
|| e.keyCode === 117 || e.keyCode === 118 || e.keyCode === 119 || e.keyCode === 120 || e.keyCode === 121 || e.keyCode === 122
|| e.keyCode === 123 || e.keyCode === 9 || e.ctrlKey) {
return true;
}
return false;
}
})(window.jQuery, window, document);
/**
* Select Plugin
* @version 1.0.0
* @author Evgeniy Gusarov (Stmechanus | Diversant)
* @license The MIT License (MIT)
*/
;
(function ($, window, document, undefined) {
/**
* Creates the select plugin.
* @class The Select Plugin
* @param {RDMailForm} form - The Mail Form
*/
var Select = $.fn.rdMailForm.Constructor.Plugins.Select = function (form) {
/**
* Reference to the core.
* @protected
* @type {RDMailForm}
*/
this._core = form;
/**
* Element event handlers.
* @protected
* @type {Object}
*/
this._handlers = {
"mfSelect.close": this.close,
"mfSelect.open": this.open,
"mfSelect.select": this.select,
"click": function (e) {
e.preventDefault();
e.stopPropagation();
}
};
// set default options
this._core.options = $.extend({}, Select.Defaults, this._core.options);
this.initialize();
};
/**
* Default options.
* @public
*/
Select.Defaults = {
select: {
'applyTo': 'select',
'class': 'mfSelect'
}
};
/**
* Initializes all selects in the Mail Form.
* @protected
*/
Select.prototype.initialize = function () {
this._core.$element.trigger('mfSelect.initialize');
this.create();
this.watch();
this._core.$element.trigger('mfSelect.initialized');
};
/**
* Creates a necessary pseudo DOM of select.
* @protected
*/
Select.prototype.create = function () {
this._core.$element
.find(this._core.options.select.applyTo)
.each(function () {
var $this = $(this);
$this
.css({
"position": "absolute",
"left": "50%",
"width": "0",
"height": "0",
"overflow": "hidden",
"opacity": "0"
})
.parent()
.append($('<div/>', {
'class': 'value',
'text': $this.find('option:selected').text()
}))
.append($('<ul/>', {'class': 'dropdown'}))
.end()
.find('option').each(function (i) {
if (i == 0) {
return;
}
var o = $(this);
o.parent().parent().find('.dropdown')
.append($('<li/>', {
'class': 'option',
'text': o.text()
}).addClass(o.is(':selected') ? 'selected' : ''));
})
})
.parent()
.addClass(this._core.options.select.class);
};
/**
* Creates all attached event handlers of select.
* @protected
*/
Select.prototype.watch = function () {
var self = this;
this._core.$element
.find(self._core.options.select.applyTo)
.on('focus', this.focus)
.on('blur', function (e) {
$(this).parent()
.trigger('mfSelect.close')
.removeClass('focus')
})
.on('keydown', function (e) {
if (e.keyCode == 38) {
$(this)
.val($(this).find('option').eq($(this).find('option:selected').index() > 0 ? $(this).find('option:selected').index() - 1 : 0).text())
.trigger('change');
}
if (e.keyCode == 40) {
$(this)
.val($(this).find('option').eq($(this).find('option:selected').index() < $(this).find('option').length - 1 ? $(this).find('option:selected').index() + 1 : $(this).find('option').length - 1).text())
.trigger('change');
}
if (e.keyCode == 13) {
if ($(this).parent().hasClass('show')) {
$(this).parent().trigger('mfSelect.close');
} else {
$(this).parent().trigger('mfSelect.open');
}
}
if (e.keyCode == 32 || e.keyCode == 37 || e.keyCode == 38 || e.keyCode == 39 || e.keyCode == 40 || e.keyCode == 13) {
e.preventDefault();
}
})
.on('change', function (e) {
$(this).parent()
.trigger('mfSelect.open')
.find('.value').text($(this).val());
var i = $(this).find('option:selected').index(),
$option = $(this).parent().find('.option').removeClass('selected');
if (i > 0) {
$option.eq(i - 1).addClass('selected');
}
})
.parent()
.on(this._handlers)
.find('.value')
.on('click', function (e) {
var $value = $(this),
$select = $value.parent().find('select'),
option = $select.find('option').eq(0).text();
$value.text(option);
$select
.trigger('focus')
.off('focus', self.focus);
if (!$(this).parent().hasClass('show')) {
$select.on('focus', self.focus);
var value = $(this).parent().find('.option.selected');
if (value.length) {
$value.text(value.text());
}
}
})
.parent()
.find('.option')
.on('click', function () {
$(this).parent().find('.option').removeClass('selected');
$(this).addClass('selected');
$(this).parent().parent()
.find('select')
.focus()
.on('focus', self.focus);
$(this).parent().parent()
.trigger('mfSelect.select', {
options: self._core.options.select,
value: $(this).text()
})
})
.parents('body')
.on('click', function (e) {
var o = self._core.$element.find('.' + self._core.options.select.class);
if (o.length) {
if (!o.is(e.target) && o.has(e.target).length === 0) {
o.find('select')
.each(function () {
var value = $(this).parent().find('.option.selected');
if (value.length) {
$(this).parent().find('.value').text(value.text());
}
})
.on('focus', self.focus);
}
}
});
this._core.$element
.on('mf.reset', function () {
$(this)
.find(self._core.options.select.applyTo).each(function () {
$(this).parent()
.find('.value').text($(this).prop('selectedIndex', 0).val());
$(this).parent().find('.option').removeClass('selected');
});
});
};
Select.prototype.focus = function () {
$(this).parent().trigger('mfSelect.open').addClass('focus');
};
Select.prototype.close = function () {
if (!navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
if ($(this).hasClass("show")) {
$(this).removeClass("show");
}
}
};
Select.prototype.open = function () {
if (!navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
if (!$(this).hasClass("show")) {
$(this).addClass("show");
}
}
};
Select.prototype.select = function (e, data) {
$(this)
.find(data.options.applyTo).val(data.value)
.trigger('change');
$(this)
.trigger('mfSelect.close');
};
})(window.jQuery, window, document);
/**
* DatePicker Plugin
* @version 1.0.0
* @author Evgeniy Gusarov (Stmechanus | Diversant)
* @license The MIT License (MIT)
*/
;
(function ($, window, document, undefined) {
/**
* Creates Icon plugin.
* @class The Icon Plugin
* @param {RDMailForm} form - The Mail Form
*/
var DatePicker = $.fn.rdMailForm.Constructor.Plugins.DatePicker = function (form) {
/**
* Reference to the core.
* @protected
* @type {RDMailForm}
*/
this._core = form;
this._handlers = {
'mfDatePicker.close': this.close,
'mfDatePicker.open': this.open,
'mfDatePicker.next': this.next,
'mfDatePicker.prev': this.prev,
'mfDatePicker.update': this.update,
'mfDatePicker.refresh': this.refresh,
'mfDatePicker.pick': this.pick
};
// set default options
this._core.options = $.extend({}, DatePicker.Defaults, this._core.options);
this.initialize();
};
/**
* Default options.
* @public
*/
DatePicker.Defaults = {
"datepicker": {
"applyTo": 'input[type="date"]',
"class": 'mfDatePicker',
"days": ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
"months": ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
"format": 'MM-DD-YYYY',
"prevMonth": '',
"nextMonth": ''
}
};
/**
* Initializes the Datepicker plugin.
* @protected
*/
DatePicker.prototype.initialize = function () {
this._core.$element.trigger('mfDatePicker.initialize');
this.create();
this.watch();
this._core.$element.trigger('mfDatePicker.initialized');
};
/**
* Creates a necessary DOM for datepicker plugin.
* @protected
*/
DatePicker.prototype.create = function () {
var self = this;
self._core.$element
.find(self._core.options.datepicker.applyTo)
.each(function () {
$(this)
.attr({
'type': !navigator.userAgent.match(/(iPod|iPhone|iPad)/) ? 'text' : 'date',
'data-type': 'date'
})
.after($('<div/>', {
'class': self._core.options.datepicker.class
})
.data('date', new Date())
);
})
.parent()
.find('.' + self._core.options.datepicker.class)
.each(function () {
$.proxy(self.update, this, {}, self._core.options.datepicker).call();
$.proxy(self.refresh, this, {}, self._core.options.datepicker).call();
});
};
/**
* Creates all attached event handlers of datepicker plugin.
* @protected
*/
DatePicker.prototype.watch = function () {
var self = this;
self._core.$element
.find('.' + self._core.options.datepicker.class)
.on('click', '.' + self._core.options.datepicker.class + '_next', function () {
var $this = $(this).parents('.' + self._core.options.datepicker.class);
$this.trigger('mfDatePicker.next');
$this.trigger('mfDatePicker.update', self._core.options.datepicker);
$this.trigger('mfDatePicker.refresh', self._core.options.datepicker);
})
.on('click', '.' + self._core.options.datepicker.class + '_prev', function () {
var $this = $(this).parents('.' + self._core.options.datepicker.class);
$this.trigger('mfDatePicker.prev');
$this.trigger('mfDatePicker.update', self._core.options.datepicker);
$this.trigger('mfDatePicker.refresh', self._core.options.datepicker);
})
.on('click', '.dp-day', function () {
var $this = $(this).parents('.' + self._core.options.datepicker.class);
$this.trigger('mfDatePicker.pick', {opt: self._core.options.datepicker, day: $(this)});
$this.parent()
.find('input')
.on('blur', self.blur)
.trigger('blur')
.trigger('keyup');
})
.on('click', function () {
})
.on(this._handlers)
.parent()
.on('click', function (e) {
e.preventDefault();
return false;
})
.find('input')
.on('focus', function () {
$(this).parent().find('.' + self._core.options.datepicker.class)
.trigger('mfDatePicker.open');
})
.on('blur', this.blur)
.on('keydown', function (e) {
if (e.keyCode == 9 || (e.shiftKey && e.keyCode == 9)) {
$(this)
.on('blur', self.blur);
}
})
.parents('body')
.on('mousedown', function (e) {
var o = self._core.$element.find('.' + self._core.options.datepicker.class).parent();
if (o.length) {
if (!o.is(e.target) && o.has(e.target).length === 0) {
o.find('input')
.on('blur', self.blur)
.trigger('blur');
} else {
o.find('input')
.off('blur', self.blur)
}
}
});
self._core.$element
.on('mf.reset', function () {
$(this)
.find('.' + self._core.options.datepicker.class).each(function () {
$(this).trigger("mfDatePicker.close")
});
});
};
/**
* Blur the datepickers input
* @protected
*/
DatePicker.prototype.blur = function () {
$(this).parent().find('.mfDatePicker')
.trigger('mfDatePicker.close');
};
/**
* Closes the datepicker
* @protected
*/
DatePicker.prototype.close = function () {
if (!navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
if ($(this).hasClass("open")) {
$(this).removeClass("open");
}
}
};
/**
* Opens the datepicker
* @protected
*/
DatePicker.prototype.open = function () {
if (!navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
if (!$(this).hasClass("open")) {
$(this).addClass("open");
}
}
};
/**
* Goto next month of picker
* @protected
*/
DatePicker.prototype.next = function (e) {
var $this = $(this),
date = $this.data('date');
if (date.getMonth() == 11) {
date = new Date(date.getFullYear() + 1, 0, 1);
} else {
date = new Date(date.getFullYear(), date.getMonth() + 1, 1);
}
$this.data('date', date);
};
/**
* Goto previous month of picker
* @protected
*/
DatePicker.prototype.prev = function (e) {
var $this = $(this),
date = $this.data('date');
if (date.getMonth() == 0) {
date = new Date(date.getFullYear() - 1, 11, 1);
} else {
date = new Date(date.getFullYear(), date.getMonth() - 1, 1);
}
$this.data('date', date);
};
/**
* Goto target date
* @protected
*/
DatePicker.prototype.pick = function (e, o) {
var $this = $(this);
$this.data('pickedDate', o.day.addClass("dp-selected").data('date'));
$this
.find('.dp-day')
.not(o.day)
.removeClass('dp-selected');
$this
.parent()
.find('input')
.val(
($this.data('pickedDate').getMonth() + 1 < 10 ? "0" + ($this.data('pickedDate').getMonth() + 1) : $this.data('pickedDate').getMonth() + 1 ) + '/' +
($this.data('pickedDate').getDate() < 10 ? "0" + ($this.data('pickedDate').getDate()) : $this.data('pickedDate').getDate()) + '/' +
$this.data('pickedDate').getFullYear()
)
};
/**
* Refreshes the DOM of picker according to current picked date.
* @protected
*/
DatePicker.prototype.update = function (e, opt) {
var $this = $(this),
$panel = $('<div/>', {"class": opt.class + '_panel'});
$panel.append($('<a/>', {
'class': opt.class + '_prev',
'text': opt.prevMonth
}));
$panel.append($('<a/>', {
'class': opt.class + '_next',
'text': opt.nextMonth
}));
$panel.append($('<div/>', {
'class': opt.class + '_title',
'text': opt.months[$this.data("date").getMonth()] + " " + $this.data("date").getFullYear()
}));
var $target = $this.find('.' + opt.class + '_panel');
if ($target.length) {
$target.replaceWith($panel);
} else {
$panel.appendTo($this);
}
};
/**
* Refreshes the DOM of picker according to current picked date.
* @protected
*/
DatePicker.prototype.refresh = function (e, opt) {
var $this = $(this),
$calendar = $('<table/>');
var $week = $('<tr/>');
for (var i = 0; i < opt.days.length; i++) {
$week.append($('<th/>', {
'class': 'dp-weekday',
'text': opt.days[i]
}));
}
$calendar.append($week);
var date = $this.data("date"),
pickedDate = $this.data("pickedDate"),
monthLength = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(),
prevMonthLength = new Date(date.getFullYear(), date.getMonth(), 0).getDate(),
firstDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay(),
counter = 1;
for (var i = 0; i < 7; i++) {
$week = $('<tr/>');
for (var j = 0; j < 7; j++) {
var day = 7 * i + j + 1,
currentDate,
currentDay = $('<td/>', {'class': 'dp-day'}),
today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setSeconds(0);
today.setMilliseconds(0);
// If Month had ended and new week started
if (j == 0 && day > monthLength + firstDay) {
break;
}
// If the day belongs to previous month
if (day - firstDay < 1) {
currentDay.text(prevMonthLength + (day - firstDay)).addClass("dp-offset");
currentDate = new Date(date.getFullYear(), date.getMonth() - 1, prevMonthLength + (day - firstDay));
}
// If the day belongs to current month
else if (day <= monthLength + firstDay) {
currentDay.text(day - firstDay);
currentDate = new Date(date.getFullYear(), date.getMonth(), day - firstDay);
}
// If the day belongs to next month
else {
currentDay.text(counter).addClass("dp-offset");
currentDate = new Date(date.getFullYear(), date.getMonth() + 1, counter++);
}
// If current day is today
if (currentDate.valueOf() == today.valueOf()) {
currentDay.addClass('dp-today');
}
// If current day was selected
if (pickedDate) {
if (currentDate.valueOf() == pickedDate.valueOf()) {
currentDay.addClass('dp-selected');
}
}
$week.append(currentDay.data('date', currentDate));
}
if ($week.html() != '') {
$calendar.append($week);
}
}
var $target = $this.find('table');
if ($target.length) {
$target.replaceWith($calendar);
} else {
$calendar.appendTo($this);
}
};
})(window.jQuery, window, document);
/**
* Icon Plugin
* @version 1.0.0
* @author Evgeniy Gusarov (Stmechanus | Diversant)
* @license The MIT License (MIT)
*/
;
(function ($, window, document, undefined) {
/**
* Creates Icon plugin.
* @class The Icon Plugin
* @param {RDMailForm} form - The Mail Form
*/
var Icon = $.fn.rdMailForm.Constructor.Plugins.Icon = function (form) {
/**
* Reference to the core.
* @protected
* @type {RDMailForm}
*/
this._core = form;
// set default options
this._core.options = $.extend({}, Icon.Defaults, this._core.options);
this.initialize();
};
/**
* Element event handlers.
* @protected
* @type {Object}
*/
this._handlers = {
"mfIcon.change": this.change
};
/**
* Default options.
* @public
*/
Icon.Defaults = {
"icon": {
"applyTo": "[data-add-icon]",
"class": "mfIcon",
"states": {
'.mfInput': {
'mfIcon.default': ['mfInput.blur', 'mfInput.idle', 'mfInput.reset'],
'mfIcon.state-1': ['mfInput.type'],
'mfIcon.state-2': ['mfInput.delete']
}
}
}
};
/**
* Initializes the Icon plugin.
* @protected
*/
Icon.prototype.initialize = function () {
this._core.$element.trigger('mfIcon.initialize');
this.create();
this.watch();
this._core.$element.trigger('mfIcon.initialized');
};
/**
* Creates a necessary DOM for Icon plugin.
* @protected
*/
Icon.prototype.create = function () {
var self = this;
self._core.$element
.find(self._core.options.icon.applyTo)
.each(function () {
var o = $(this);
o.append(
$('<span/>', {
'class': self._core.options.icon.class
}).append($("<span/>"))
);
});
};
/**
* Creates all attached event handlers of Icon plugin.
* @protected
*/
Icon.prototype.watch = function () {
var self = this;
self._core.$element
.find('.' + self._core.options.icon.class)
.on(self._handlers);
for (var component in self._core.options.icon.states) {
var $target = self._core.$element.find(component);
for (var state in self._core.options.icon.states[component]) {
for (var event in self._core.options.icon.states[component][state]) {
$target.on(self._core.options.icon.states[component][state][event], {state: state}, function (e) {
$(this).find('.' + self._core.options.icon.class)
.attr('class', e.data.state.replace('.', ' '));
})
}
}
}
};
})(window.jQuery, window, document);
/**
* PlaceHolder Plugin
* @version 1.0.0
* @author Evgeniy Gusarov (Stmechanus | Diversant)
* @license The MIT License (MIT)
*/
;
(function ($, window, document, undefined) {
/**
* Creates Placeholder plugin.
* @class The Placeholder Plugin
* @param {RDMailForm} form - The Mail Form
*/
var Placeholder = $.fn.rdMailForm.Constructor.Plugins.Placeholder = function (form) {
/**
* Reference to the core.
* @protected
* @type {RDMailForm}
*/
this._core = form;
// set default options
this._core.options = $.extend({}, Placeholder.Defaults, this._core.options);
this.initialize();
};
/**
* Element event handlers.
* @protected
* @type {Object}
*/
this._handlers = {
"mfIcon.change": this.change,
};
/**
* Default options.
* @public
*/
Placeholder.Defaults = {
"placeholder": {
"applyTo": "[data-add-placeholder]",
"class": "mfPlaceHolder",
"states": {
'.mfInput': {
'mfPlaceHolder.default': ['mfInput.void', 'mfInput.reset'],
'mfPlaceHolder.state-1': ['mfInput.fill', 'mfInput.focus']
}
}
}
};
/**
* Initializes the Placeholder plugin.
* @protected
*/
Placeholder.prototype.initialize = function () {
this._core.$element.trigger('mfPlaceHolder.initialize');
this.create();
this.watch();
this._core.$element.trigger('mfPlaceHolder.initialized');
};
/**
* Creates a necessary DOM for Placeholder plugin.
* @protected
*/
Placeholder.prototype.create = function () {
var self = this;
self._core.$element
.find(self._core.options.placeholder.applyTo)
.each(function () {
var o = $(this), inp, lab;
if (o.find('[placeholder]').length) {
o.append(
$('<span/>', {
'class': self._core.options.placeholder.class,
'text': o.find('[placeholder]').attr('placeholder') ? o.find('[placeholder]').attr('placeholder') : o.find('[data-placeholder]').attr('data-placeholder')
}))
.find('[placeholder]').removeAttr('placeholder').removeAttr('data-placeholder');
}
else if ((inp = o.find('input, textarea')).length) {
if (inp.attr("id")){
if ((lab = o.find('label[for="' + inp.attr("id") + '"]')).length){
lab.addClass(self._core.options.placeholder.class)
}
}
}
});
};
/**
* Creates all attached event handlers of Placeholder plugin.
* @protected
*/
Placeholder.prototype.watch = function () {
var self = this;
self._core.$element
.find('.' + self._core.options.placeholder.class)
.on('click', function (e) {
$(this).parent().find('input, textarea').trigger('focus');
})
.on(self._handlers);
for (var component in self._core.options.icon.states) {
var $target = self._core.$element.find(component);
for (var state in self._core.options.placeholder.states[component]) {
for (var event in self._core.options.placeholder.states[component][state]) {
$target.on(self._core.options.placeholder.states[component][state][event], {state: state}, function (e) {
$(this).find('.' + self._core.options.placeholder.class)
.attr('class', e.data.state.replace('.', ' '));
})
}
}
}
};
})(window.jQuery, window, document);
/**
* Progress Plugin
* @version 1.0.0
* @author Evgeniy Gusarov (Stmechanus | Diversant)
* @license The MIT License (MIT)
*/
;
(function ($, window, document, undefined) {
/**
* Creates Progress plugin.
* @class The Progress Plugin
* @param {RDMailForm} form - The Mail Form
*/
var Progress = $.fn.rdMailForm.Constructor.Plugins.Progress = function (form) {
/**
* Reference to the core.
* @protected
* @type {RDMailForm}
*/
this._core = form;
// set default options
this._core.options = $.extend({}, Progress.Defaults, this._core.options);
this.initialize();
};
/**
* Default options.
* @public
*/
Progress.Defaults = {
"progress": {
"applyTo": ".mfInfo",
"class": "mfProgress"
}
};
/**
* Initializes the Progress plugin.
* @protected
*/
Progress.prototype.initialize = function () {
this._core.$element.trigger('mfProgress.initialize');
this.create();
this.watch();
this._core.$element.trigger('mfProgress.initialized');
};
/**
* Creates a necessary DOM for Progress plugin.
* @protected
*/
Progress.prototype.create = function () {
var self = this;
self._core.$element
.append($("<div/>", {
"class": self._core.options.progress.applyTo.replace(/^\./i, "")
})
.each(function () {
var button = $(this);
button
.addClass(self._core.options.progress.class)
.wrapInner($('<span/>', {'class': 'cnt'}))
.append($('<span/>', {'class': 'loader'}))
.append($('<span/>', {'class': 'msg'}))
}));
};
/**
* Creates all attached event handlers of Progress plugin.
* @protected
*/
Progress.prototype.watch = function () {
var self = this;
self._core.$element
.on('mf.process', function () {
$(this).find('.' + self._core.options.progress.class).removeClass('hide').addClass('sending').find('.msg').text('Loading...');
})
.on('mf.fail', function (e, data) {
$(this).find('.' + self._core.options.progress.class)
.removeClass('sending')
.addClass('fail')
.find('.msg')
.text(data.message);
setTimeout($.proxy(function () {
$(this).find('.' + self._core.options.progress.class).removeClass('fail').addClass('hide').find('.msg');
}, this), 3000);
})
.on('mf.success', function (e, data) {
$(this).find('.' + self._core.options.progress.class)
.removeClass('sending')
.addClass('success')
.find('.msg')
.text(data.message);
setTimeout($.proxy(function () {
$(this).find('.' + self._core.options.progress.class).removeClass('success').addClass('hide').find('.msg');
}, this), 1500);
})
.on('mf.reset', function (e, data) {
$(this).find('.' + self._core.options.progress.class).removeClass('sending').removeClass('fail').removeClass('success').find('.msg');
});
};
})(window.jQuery, window, document);
/**
* Auto Initializer
* @version 1.0.0
* @author Evgeniy Gusarov (StMechanus | Diversant)
* @license The MIT License (MIT)
*/
;
(function ($, window, document) {
$(document).ready(function () {
var o = $('.mailform');
if (o.length) {
o.rdMailForm();
}
});
})(window.jQuery, window, document);