/*jslint eqeq: true, plusplus: true, undef: true, sloppy: true, vars: true, forin: true */
|
(function ($) {
|
var ms = $.mobiscroll,
|
defaults = {
|
invalid: [],
|
showInput: true,
|
inputClass: ''
|
},
|
preset = function (inst) {
|
var s = $.extend({}, defaults, inst.settings),
|
elm = $(this),
|
input,
|
prevent,
|
id = this.id + '_dummy',
|
lvl = 0,
|
ilvl = 0,
|
timer = {},
|
wa = s.wheelArray || createWheelArray(elm),
|
labels = generateLabels(lvl),
|
currWheelVector = [],
|
fwv = firstWheelVector(wa),
|
w = generateWheelsFromVector(fwv, lvl);
|
|
/**
|
* Disables the invalid items on the wheels
|
* @param {Object} dw - the jQuery mobiscroll object
|
* @param {Number} nrWheels - the number of the current wheels
|
* @param {Array} whArray - The wheel array objects containing the wheel tree
|
* @param {Array} whVector - the wheel vector containing the current keys
|
*/
|
function setDisabled(dw, nrWheels, whArray, whVector) {
|
var i = 0;
|
while (i < nrWheels) {
|
var currWh = $('.dwwl' + i, dw),
|
inv = getInvalidKeys(whVector, i, whArray);
|
$.each(inv, function (i, v) {
|
$('.dw-li[data-val="' + v + '"]', currWh).removeClass('dw-v');
|
});
|
i++;
|
}
|
}
|
|
/**
|
* Returns the invalid keys of one wheel as an array
|
* @param {Array} whVector - the wheel vector used to search for the wheel in the wheel array
|
* @param {Number} index - index of the wheel in the wheel vector, that we are interested in
|
* @param {Array} whArray - the wheel array we are searching in
|
* @return {Array} - list of invalid keys
|
*/
|
function getInvalidKeys(whVector, index, whArray) {
|
var i = 0,
|
n,
|
whObjA = whArray,
|
invalids = [];
|
|
while (i < index) {
|
var ii = whVector[i];
|
//whObjA = whObjA[ii].children;
|
for (n in whObjA) {
|
if (whObjA[n].key == ii) {
|
whObjA = whObjA[n].children;
|
break;
|
}
|
}
|
i++;
|
}
|
i = 0;
|
while (i < whObjA.length) {
|
if (whObjA[i].invalid) {
|
invalids.push(whObjA[i].key);
|
}
|
i++;
|
}
|
return invalids;
|
}
|
|
/**
|
* Creates a Boolean vector with true values (except one) that can be used as the readonly vector
|
* n - the length of the vector
|
* i - the index of the value that's going to be false
|
*/
|
function createROVector(n, i) {
|
var a = [];
|
while (n) {
|
a[--n] = true;
|
}
|
a[i] = false;
|
return a;
|
}
|
|
/**
|
* Creates a labels vector, from values if they are defined, otherwise from numbers
|
* l - the length of the vector
|
*/
|
function generateLabels(l) {
|
var a = [],
|
i;
|
for (i = 0; i < l; i++) {
|
a[i] = s.labels && s.labels[i] ? s.labels[i] : i;
|
}
|
return a;
|
}
|
|
/**
|
* Creates the wheel array from the vector provided
|
* wv - wheel vector containing the values that should be selected on the wheels
|
* l - the length of the wheel array
|
*/
|
function generateWheelsFromVector(wv, l, index) {
|
var i = 0, j, obj, chInd,
|
w = [{}],
|
wtObjA = wa;
|
|
if (l) { // if length is defined we need to generate that many wheels (even if they are empty)
|
for (j = 0; j < l; j++) {
|
w[j] = {};
|
w[j][labels[j]] = {}; // each wheel will have a label generated by the generateLabels method
|
}
|
}
|
while (i < wv.length) { // we generate the wheels until the length of the wheel vector
|
w[i] = {};
|
w[i][labels[i]] = getWheelFromObjA(wtObjA);
|
|
j = 0;
|
chInd = undefined;
|
|
while (j < wtObjA.length && chInd === undefined) {
|
if (wtObjA[j].key == wv[i] && ((index !== undefined && i <= index) || index === undefined)) {
|
chInd = j;
|
}
|
j++;
|
}
|
|
if (chInd !== undefined && wtObjA[chInd].children) {
|
i++;
|
wtObjA = wtObjA[chInd].children;
|
} else if ((obj = getFirstValidItemObjOrInd(wtObjA)) && obj.children) {
|
i++;
|
wtObjA = obj.children;
|
} else {
|
return w;
|
}
|
}
|
return w;
|
}
|
|
/**
|
* Returns the first valid Wheel Node Object or its index from a Wheel Node Object Array
|
* getInd - if it is true then the return value is going to be the index, otherwise the object itself
|
*/
|
function getFirstValidItemObjOrInd(wtObjA, getInd) {
|
if (!wtObjA) {
|
return false;
|
}
|
|
var i = 0,
|
obj;
|
|
while (i < wtObjA.length) {
|
if (!(obj = wtObjA[i++]).invalid) {
|
return getInd ? i - 1 : obj;
|
}
|
}
|
return false;
|
}
|
|
function getWheelFromObjA(objA) {
|
var wheel = {},
|
j = 0;
|
|
while (j < objA.length) {
|
wheel[objA[j].key] = objA[j++].value;
|
}
|
return wheel;
|
}
|
|
/**
|
* Hides the last i number of wheels
|
* i - the last number of wheels that has to be hidden
|
*/
|
function hideWheels(dw, i) {
|
$('.dwc', dw).css('display', '').slice(i).hide();
|
}
|
|
/**
|
* Generates the first wheel vector from the wheeltree
|
* wt - the wheel tree object
|
* uses the lvl global variable to determine the length of the vector
|
*/
|
function firstWheelVector(wa) {
|
var t = [],
|
ndObjA = wa,
|
obj,
|
ok = true,
|
i = 0;
|
|
while (ok) {
|
obj = getFirstValidItemObjOrInd(ndObjA);
|
t[i++] = obj.key;
|
if (ok = obj.children) {
|
ndObjA = obj.children;
|
}
|
}
|
return t;
|
}
|
|
/**
|
* Calculates the level of a wheel vector and the new wheel vector, depending on current wheel vector and the index of the changed wheel
|
* wv - current wheel vector
|
* index - index of the changed wheel
|
*/
|
function calcLevelOfVector2(wv, index) {
|
var t = [],
|
ndObjA = wa,
|
lvl = 0,
|
next = false,
|
i,
|
childName,
|
chInd;
|
|
if (wv[lvl] !== undefined && lvl <= index) {
|
i = 0;
|
|
childName = wv[lvl];
|
chInd = undefined;
|
|
while (i < ndObjA.length && chInd === undefined) {
|
if (ndObjA[i].key == wv[lvl] && !ndObjA[i].invalid) {
|
chInd = i;
|
}
|
i++;
|
}
|
} else {
|
chInd = getFirstValidItemObjOrInd(ndObjA, true);
|
childName = ndObjA[chInd].key;
|
}
|
|
next = chInd !== undefined ? ndObjA[chInd].children : false;
|
|
t[lvl] = childName;
|
|
while (next) {
|
ndObjA = ndObjA[chInd].children;
|
lvl++;
|
next = false;
|
chInd = undefined;
|
|
if (wv[lvl] !== undefined && lvl <= index) {
|
i = 0;
|
|
childName = wv[lvl];
|
chInd = undefined;
|
|
while (i < ndObjA.length && chInd === undefined) {
|
if (ndObjA[i].key == wv[lvl] && !ndObjA[i].invalid) {
|
chInd = i;
|
}
|
i++;
|
}
|
} else {
|
chInd = getFirstValidItemObjOrInd(ndObjA, true);
|
chInd = chInd === false ? undefined : chInd;
|
childName = ndObjA[chInd].key;
|
}
|
next = chInd !== undefined && getFirstValidItemObjOrInd(ndObjA[chInd].children) ? ndObjA[chInd].children : false;
|
t[lvl] = childName;
|
}
|
return {
|
lvl: lvl + 1,
|
nVector: t
|
}; // return the calculated level and the wheel vector as an object
|
}
|
|
function createWheelArray(ul) {
|
var wheelArray = [];
|
|
lvl = lvl > ilvl++ ? lvl : ilvl;
|
|
ul.children('li').each(function (index) {
|
var that = $(this),
|
c = that.clone();
|
|
c.children('ul,ol').remove();
|
|
var v = c.html().replace(/^\s\s*/, '').replace(/\s\s*$/, ''),
|
inv = that.data('invalid') ? true : false,
|
wheelObj = {
|
key: that.data('val') || index,
|
value: v,
|
invalid: inv,
|
children: null
|
},
|
nest = that.children('ul,ol');
|
|
if (nest.length) {
|
wheelObj.children = createWheelArray(nest);
|
}
|
|
wheelArray.push(wheelObj);
|
});
|
|
ilvl--;
|
return wheelArray;
|
}
|
|
$('#' + id).remove(); // Remove input if exists
|
|
if (s.showInput) {
|
input = $('<input type="text" id="' + id + '" value="" class="' + s.inputClass + '" readonly />').insertBefore(elm);
|
inst.settings.anchor = input; // give the core the input element for the bubble positioning
|
|
if (s.showOnFocus) {
|
input.focus(function () {
|
inst.show();
|
});
|
}
|
}
|
|
if (!s.wheelArray) {
|
elm.hide().closest('.ui-field-contain').trigger('create');
|
}
|
|
return {
|
width: 50,
|
wheels: w,
|
headerText: false,
|
onBeforeShow: function (dw) {
|
var t = inst.temp;
|
currWheelVector = t.slice(0);
|
inst.settings.wheels = generateWheelsFromVector(t, lvl, lvl);
|
prevent = true;
|
},
|
onSelect: function (v, inst) {
|
if (input) {
|
input.val(v);
|
}
|
},
|
onChange: function (v, inst) {
|
if (input && s.display == 'inline') {
|
input.val(v);
|
}
|
},
|
onClose: function () {
|
if (input) {
|
input.blur();
|
}
|
},
|
onShow: function (dw) {
|
$('.dwwl', dw).bind('mousedown touchstart', function () {
|
clearTimeout(timer[$('.dwwl', dw).index(this)]);
|
});
|
},
|
validate: function (dw, index, time) {
|
var t = inst.temp;
|
if ((index !== undefined && currWheelVector[index] != t[index]) || (index === undefined && !prevent)) {
|
inst.settings.wheels = generateWheelsFromVector(t, null, index);
|
var args = [],
|
i = (index || 0) + 1,
|
o = calcLevelOfVector2(t, index);
|
if (index !== undefined) {
|
inst.temp = o.nVector.slice(0);
|
}
|
while (i < o.lvl) {
|
args.push(i++);
|
}
|
hideWheels(dw, o.lvl);
|
currWheelVector = inst.temp.slice(0);
|
if (args.length) {
|
prevent = true;
|
inst.settings.readonly = createROVector(lvl, index);
|
clearTimeout(timer[index]);
|
timer[index] = setTimeout(function () {
|
inst.changeWheel(args);
|
inst.settings.readonly = false;
|
}, time * 1000);
|
return false;
|
}
|
setDisabled(dw, o.lvl, wa, inst.temp);
|
} else {
|
var o = calcLevelOfVector2(t, t.length);
|
setDisabled(dw, o.lvl, wa, t);
|
hideWheels(dw, o.lvl);
|
}
|
prevent = false;
|
}
|
};
|
};
|
|
$.each(['list', 'image', 'treelist'], function (i, v) {
|
ms.presets[v] = preset;
|
ms.presetShort(v);
|
});
|
|
})(jQuery);
|