/**
Widget to display live editor of label / input
Will fire LIVE_INPUT_CHANGED on data changed and also will fire a custom event
if one was give via options.customEvent
Powered by the awesome validator: https://github.com/chriso/validator.js
@class LiveInput
@constructor
@return {object} instantiated LiveInput
**/
define(['jquery', 'backbone', 'validator'], function ($, Backbone, validator) {
var LiveInput = Backbone.View.extend({
/**
Constructor
@method initialize
**/
initialize: function (options) {
var self = this;
self.m_validator = validator;
self.m_validationRules = {};
self.LIVE_INPUT_CHANGED = 'LIVE_INPUT_CHANGED';
self.LIVE_INPUT_VALID_ERROR = 'LIVE_INPUT_VALID_ERROR';
self.m_options = options;
self.m_prevValue = self.m_options.value;
var snippet = '<div>';
snippet += ' <h5 class="liveInput" data-toggle="popover" data-placement="auto right" data-trigger="manual" data-content="">' + self.m_options.value + '</h5>';
snippet += ' <a class="liveInputLink"><i style="color: gray" class="fa fa-pencil"></i></a>';
snippet += ' <input class="liveInputRename" type="text" data-localize="' + self.m_options.dataLocalize + '" placeholder="' + self.m_options.placeHolder + '" value="">';
snippet += ' </div>';
self.$el.append(snippet);
self.m_value = 0;
self.m_liveRename = self.$('.liveInput');
self.m_liveRenameInput = self.$('.liveInputRename');
self._listenRename();
self._extendValidator();
},
/**
Adding our own validation rules
@method _extendValidator
@return {Boolean} pass or fail
**/
_extendValidator: function () {
var self = this;
validator.extend('noEmpty', function (str) {
return !(_.isUndefined(str) || _.isNull(str) || str.trim().length === 0)
});
validator.extend('isNumberInRange', function (str, opts) {
str = Number(str);
if (_.isNaN(str))
return false;
if (str < opts.min || str > opts.max)
return false;
return true;
});
},
/**
Listen to up button increasing meters
@method _listenUp
**/
_listenRename: function () {
var self = this;
self.m_faIcon = self.$el.find('i');
self.$el.on('mousedown mouseup', function (e) {
// if mouse up, just give focus to control
if (e.type == "mouseup") {
self.m_liveRenameInput.focus();
return;
}
// already in edit mode, return since blur will kick next
if (!self.m_faIcon.hasClass('fa-pencil'))
return;
// on entering edit mode
self.m_liveRenameInput.show();
self.m_liveRename.hide();
self.m_faIcon.removeClass('fa-pencil').addClass('fa-check');
var value = self.m_liveRename.text();
self.m_liveRenameInput.prop('value', value);
// on entering view mode
self.m_liveRenameInput.one('blur', function (e) {
var value = self.m_liveRenameInput.prop('value');
self.m_faIcon.removeClass('fa-check').addClass('fa-pencil');
self.m_liveRename.text(value);
self.m_liveRenameInput.toggle();
self.m_liveRename.toggle();
self.setValue(value, true, true);
});
});
},
/**
Validate against all the given rules per instance
@method _validated
@param {Number} i_value
@return {Array} status of array of error messages
**/
_validated: function (i_value) {
var self = this;
var errors = [];
_.forEach(self.m_validationRules, function (rule, v) {
var func = rule[0];
var err = rule[1];
var opts = rule[2];
var value = i_value;
if (func)
if (func(value, opts) == false)
errors.push(err);
});
if (errors.length > 0) {
self.trigger(self.LIVE_INPUT_VALID_ERROR, errors);
self.m_liveRename.attr('data-content', errors[0]);
//self.m_liveRename.attr('data-content', 'hello world');
self.m_liveRename.popover('show');
setTimeout(function () {
self.m_liveRename.popover('hide');
}, 3000);
}
return errors;
},
/**
Return the validator object so caller can reference the isXXX functions as validation rules
@method getValidator
@return {Object} validator object
**/
getValidator: function () {
var self = this;
return self.m_validator;
},
/**
Enable validation via config object
@method rules
@param {Object} the config objects uses a AND rule and so ALL rules must match for no error message to display.
if any error we return it in the array of errors.
**/
rules: function (i_validationRules) {
var self = this;
self.m_validationRules = i_validationRules;
},
/**
Get current input value
@method getValue
@return {String} value
**/
getValue: function () {
return self.m_prevValue;
},
/**
Set value and announce the change
only announce if set to true
@method _listenUp
@params {String} i_value
@params {Boolean} i_announce
@params {Boolean} i_ignoreValidation
**/
setValue: function (i_value, i_announce, i_validate) {
var self = this;
if (i_value == self.m_prevValue)
return;
var edata = {
value: i_value,
preValue: self.m_prevValue,
el: self.m_options.el
};
// check for validation errors
if (i_validate) {
var errors = self._validated(i_value);
if (errors.length > 0) {
self.m_liveRename.text(self.m_prevValue);
return errors;
}
}
self.m_prevValue = i_value;
self.m_liveRename.text(i_value);
if (!i_announce)
return;
self.trigger(self.LIVE_INPUT_CHANGED, edata);
if (self.m_options.customEvent)
BB.comBroker.fire(self.m_options.customEvent, self, self, edata);
}
});
return LiveInput;
});