250 lines
8.4 KiB
JavaScript
250 lines
8.4 KiB
JavaScript
/**
|
|
* EditableForm utilites
|
|
*/
|
|
(function ($) {
|
|
"use strict";
|
|
|
|
//utils
|
|
$.fn.editableutils = {
|
|
/**
|
|
* classic JS inheritance function
|
|
*/
|
|
inherit: function (Child, Parent) {
|
|
var F = function() { };
|
|
F.prototype = Parent.prototype;
|
|
Child.prototype = new F();
|
|
Child.prototype.constructor = Child;
|
|
Child.superclass = Parent.prototype;
|
|
},
|
|
|
|
/**
|
|
* set caret position in input
|
|
* see http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
|
|
*/
|
|
setCursorPosition: function(elem, pos) {
|
|
if (elem.setSelectionRange) {
|
|
elem.setSelectionRange(pos, pos);
|
|
} else if (elem.createTextRange) {
|
|
var range = elem.createTextRange();
|
|
range.collapse(true);
|
|
range.moveEnd('character', pos);
|
|
range.moveStart('character', pos);
|
|
range.select();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* function to parse JSON in *single* quotes. (jquery automatically parse only double quotes)
|
|
* That allows such code as: <a data-source="{'a': 'b', 'c': 'd'}">
|
|
* safe = true --> means no exception will be thrown
|
|
* for details see http://stackoverflow.com/questions/7410348/how-to-set-json-format-to-html5-data-attributes-in-the-jquery
|
|
*/
|
|
tryParseJson: function(s, safe) {
|
|
if (typeof s === 'string' && s.length && s.match(/^[\{\[].*[\}\]]$/)) {
|
|
if (safe) {
|
|
try {
|
|
/*jslint evil: true*/
|
|
s = (new Function('return ' + s))();
|
|
/*jslint evil: false*/
|
|
} catch (e) {} finally {
|
|
return s;
|
|
}
|
|
} else {
|
|
/*jslint evil: true*/
|
|
s = (new Function('return ' + s))();
|
|
/*jslint evil: false*/
|
|
}
|
|
}
|
|
return s;
|
|
},
|
|
|
|
/**
|
|
* slice object by specified keys
|
|
*/
|
|
sliceObj: function(obj, keys, caseSensitive /* default: false */) {
|
|
var key, keyLower, newObj = {};
|
|
|
|
if (!$.isArray(keys) || !keys.length) {
|
|
return newObj;
|
|
}
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
key = keys[i];
|
|
if (obj.hasOwnProperty(key)) {
|
|
newObj[key] = obj[key];
|
|
}
|
|
|
|
if(caseSensitive === true) {
|
|
continue;
|
|
}
|
|
|
|
//when getting data-* attributes via $.data() it's converted to lowercase.
|
|
//details: http://stackoverflow.com/questions/7602565/using-data-attributes-with-jquery
|
|
//workaround is code below.
|
|
keyLower = key.toLowerCase();
|
|
if (obj.hasOwnProperty(keyLower)) {
|
|
newObj[key] = obj[keyLower];
|
|
}
|
|
}
|
|
|
|
return newObj;
|
|
},
|
|
|
|
/*
|
|
exclude complex objects from $.data() before pass to config
|
|
*/
|
|
getConfigData: function($element) {
|
|
var data = {};
|
|
$.each($element.data(), function(k, v) {
|
|
if(typeof v !== 'object' || (v && typeof v === 'object' && (v.constructor === Object || v.constructor === Array))) {
|
|
data[k] = v;
|
|
}
|
|
});
|
|
return data;
|
|
},
|
|
|
|
/*
|
|
returns keys of object
|
|
*/
|
|
objectKeys: function(o) {
|
|
if (Object.keys) {
|
|
return Object.keys(o);
|
|
} else {
|
|
if (o !== Object(o)) {
|
|
throw new TypeError('Object.keys called on a non-object');
|
|
}
|
|
var k=[], p;
|
|
for (p in o) {
|
|
if (Object.prototype.hasOwnProperty.call(o,p)) {
|
|
k.push(p);
|
|
}
|
|
}
|
|
return k;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
method to escape html.
|
|
**/
|
|
escape: function(str) {
|
|
return $('<div>').text(str).html();
|
|
},
|
|
|
|
/*
|
|
returns array items from sourceData having value property equal or inArray of 'value'
|
|
*/
|
|
itemsByValue: function(value, sourceData, valueProp) {
|
|
if(!sourceData || value === null) {
|
|
return [];
|
|
}
|
|
|
|
if (typeof(valueProp) !== "function") {
|
|
var idKey = valueProp || 'value';
|
|
valueProp = function (e) { return e[idKey]; };
|
|
}
|
|
|
|
var isValArray = $.isArray(value),
|
|
result = [],
|
|
that = this;
|
|
|
|
$.each(sourceData, function(i, o) {
|
|
if(o.children) {
|
|
result = result.concat(that.itemsByValue(value, o.children, valueProp));
|
|
} else {
|
|
/*jslint eqeq: true*/
|
|
if(isValArray) {
|
|
if($.grep(value, function(v){ return v == (o && typeof o === 'object' ? valueProp(o) : o); }).length) {
|
|
result.push(o);
|
|
}
|
|
} else {
|
|
var itemValue = (o && (typeof o === 'object')) ? valueProp(o) : o;
|
|
if(value == itemValue) {
|
|
result.push(o);
|
|
}
|
|
}
|
|
/*jslint eqeq: false*/
|
|
}
|
|
});
|
|
|
|
return result;
|
|
},
|
|
|
|
/*
|
|
Returns input by options: type, mode.
|
|
*/
|
|
createInput: function(options) {
|
|
var TypeConstructor, typeOptions, input,
|
|
type = options.type;
|
|
|
|
//`date` is some kind of virtual type that is transformed to one of exact types
|
|
//depending on mode and core lib
|
|
if(type === 'date') {
|
|
//inline
|
|
if(options.mode === 'inline') {
|
|
if($.fn.editabletypes.datefield) {
|
|
type = 'datefield';
|
|
} else if($.fn.editabletypes.dateuifield) {
|
|
type = 'dateuifield';
|
|
}
|
|
//popup
|
|
} else {
|
|
if($.fn.editabletypes.date) {
|
|
type = 'date';
|
|
} else if($.fn.editabletypes.dateui) {
|
|
type = 'dateui';
|
|
}
|
|
}
|
|
|
|
//if type still `date` and not exist in types, replace with `combodate` that is base input
|
|
if(type === 'date' && !$.fn.editabletypes.date) {
|
|
type = 'combodate';
|
|
}
|
|
}
|
|
|
|
//`datetime` should be datetimefield in 'inline' mode
|
|
if(type === 'datetime' && options.mode === 'inline') {
|
|
type = 'datetimefield';
|
|
}
|
|
|
|
//change wysihtml5 to textarea for jquery UI and plain versions
|
|
if(type === 'wysihtml5' && !$.fn.editabletypes[type]) {
|
|
type = 'textarea';
|
|
}
|
|
|
|
//create input of specified type. Input will be used for converting value, not in form
|
|
if(typeof $.fn.editabletypes[type] === 'function') {
|
|
TypeConstructor = $.fn.editabletypes[type];
|
|
typeOptions = this.sliceObj(options, this.objectKeys(TypeConstructor.defaults));
|
|
input = new TypeConstructor(typeOptions);
|
|
return input;
|
|
} else {
|
|
$.error('Unknown type: '+ type);
|
|
return false;
|
|
}
|
|
},
|
|
|
|
//see http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
|
|
supportsTransitions: function () {
|
|
var b = document.body || document.documentElement,
|
|
s = b.style,
|
|
p = 'transition',
|
|
v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms'];
|
|
|
|
if(typeof s[p] === 'string') {
|
|
return true;
|
|
}
|
|
|
|
// Tests for vendor specific prop
|
|
p = p.charAt(0).toUpperCase() + p.substr(1);
|
|
for(var i=0; i<v.length; i++) {
|
|
if(typeof s[v[i] + p] === 'string') {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
};
|
|
}(window.jQuery));
|