experimenting with jQ.fn.transform(..) -- appears to do what I need but not yet fully featured + need to revise...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2015-12-21 03:49:39 +03:00
parent 62d5b45e7f
commit d0d2f108db

View File

@ -77,71 +77,67 @@ function(path){
/*********************************************************************/ /*********************************************************************/
// func -> [{attr|alt: unit, ..}, ..]
var _transform_parse = { var _transform_parse = {
// 2d transforms: // 2d transforms:
//martix: [], //martix: [],
translate: ['left|0', 'top|0'], translate: [{'left|0': 'px', 'top|0': 'px'}],
translateX: ['left'], translateX: [{'left|x': 'px'}],
translateY: ['top'], translateY: [{'top|y': 'px'}],
scale: [ scale: [
['scale'], {scale: null},
['scaleX|scale', 'scaleY|scale'], {'scaleX|scale': null, 'scaleY|scale': null},
], ],
scaleX: ['scaleX'], scaleX: [{'scaleX': null}],
scaleY: ['scaleY'], scaleY: [{'scaleY': null}],
rotate: ['rotate'], rotate: [{'rotate': 'deg'}],
skew: ['skewX', 'skewY'], skew: [{'skewX': 'px', 'skewY': 'px'}],
skewX: ['skewX'], skewX: [{'skewX': 'px'}],
skewY: ['skewY'], skewY: [{'skewY': 'px'}],
// 3d transforms: // 3d transforms:
//martix3d: [], //martix3d: [],
translate3d: ['x|0', 'y|0', 'z|0'], translate3d: [{'x|0': 'px', 'y|0': 'px', 'z|0': 'px'}],
translateZ: ['z'], translateZ: [{'z': 'px'}],
scale3d: ['scaleX', 'scaleY', 'scaleZ'], scale3d: [{'scaleX': null, 'scaleY': null, 'scaleZ': null}],
scaleZ: ['scaleZ'], scaleZ: [{'scaleZ': null}],
// XXX // XXX
//rotate3d: [x, y, z, angle], //rotate3d: [x, y, z, angle]],
// rotateX // rotateX
// rotateY // rotateY
// rotateZ // rotateZ
perspective: ['perspective'], perspective: [{'perspective': null}],
} }
var _transform_parse_rev = {}
// attr -> [alt, ..]
var _transform_parse_alt = {}
// attr -> [func, ..]
var _transform_parse_func = {}
Object.keys(_transform_parse).forEach(function(func){ Object.keys(_transform_parse).forEach(function(func){
var args = _transform_parse[func] _transform_parse[func].forEach(function(variant){
Object.keys(variant).forEach(function(arg){
var alt = arg.split(/\|/g)
var arg = alt.shift()
// we got multiple signatures == merge... _transform_parse_func[arg] = _transform_parse_func[arg] || []
if(!(args[0] instanceof Array)){ _transform_parse_func[arg].push(func)
args = [args] _transform_parse_alt[arg] = _transform_parse_alt[arg] || []
}
args if(alt.length > 0){
// merge lists of args... _transform_parse_alt[arg] = (_transform_parse_alt[alt] || [])
.reduce(function(a, b){ return [].concat.call(a, b) }) .concat(alt)
.unique() .unique()
// split alternatives... }
.map(function(a){ return a.split(/\|/g) }) })
.forEach(function(a){
var arg = a[0]
var alt = a.slice(1)
var e = _transform_parse_rev[arg] = _transform_parse_rev[arg] || {}
e.funcs = e.funcs || []
e.funcs.indexOf(func) < 0 && e.funcs.push(func)
e.alt = e.alt || []
// XXX we explicitly support only one alternative now...
e.alt = e.alt.concat(alt).unique()
}) })
}) })
@ -188,16 +184,19 @@ jQuery.fn.transform = function(){
var origin_str = elem.style[prefix + 'transformOrigin'] var origin_str = elem.style[prefix + 'transformOrigin']
var transform_str = elem.style[prefix + 'transform'] var transform_str = elem.style[prefix + 'transform']
// origin...
var origin = origin_str
.split(/\s+/)
// XXX add this to transform...
// build the current state... // build the current state...
// NOTE: we'll need this for both fetching (parsing) and writing // NOTE: we'll need this for both fetching (parsing) and writing
// (checking)... // (checking)...
var transform = {} var transform = {}
var functions = {} var functions = {}
var attrs = {}
// origin... //var implicit = {}
var origin = origin_str //var implicit_attrs = {}
.split(/\s+/)
// XXX add this to transform...
// transform... // transform...
transform_str transform_str
@ -223,20 +222,24 @@ jQuery.fn.transform = function(){
// we do not know this function... // we do not know this function...
if(spec == null){ if(spec == null){
transform[func] = args transform[func] = [args]
} else { } else {
spec = spec[0] instanceof Array ? spec : [spec] var seen = []
spec.forEach(function(s){ transform[func] = []
var proc = function(res, attrs, explicit){
return function(s){
var keys = Object.keys(s)
// skip non-matching signatures... // skip non-matching signatures...
// XXX is this correct??? // XXX is this correct???
if(s.length != args.length){ if(explicit && keys.length != args.length){
return return
} }
s.forEach(function(e, i){
// this is for things that have optional arguments var data = {}
// like scale(..) res.push(data)
// XXX should we treat this in some special way???
keys.forEach(function(e, i){
if(args[i] == null){ if(args[i] == null){
return return
} }
@ -244,121 +247,135 @@ jQuery.fn.transform = function(){
var alternatives = e.split(/\|/g) var alternatives = e.split(/\|/g)
var k = alternatives.shift().trim() var k = alternatives.shift().trim()
transform[k] = args[i].slice(-2) == 'px' var val = args[i].slice(-2) == 'px'
|| /[0-9\.]+/.test(args[i]) ? || /^[0-9\.]+$/.test(args[i]) ?
parseFloat(args[i]) parseFloat(args[i])
: args[i] : args[i]
var unit = args[i].split(val+'').pop()
attrs[k] = function(v, d){
v = v || val
d = d || data
// set attrs -- for getting data...
d[k] = v
// set funcs -- for setting data...
functions[func][i] = typeof(v) == typeof('str') ?
v
: v + unit
return v
}
attrs[k]()
}) })
}) }
}
spec.forEach(proc(transform[func], attrs, true))
} }
}) })
// handler origin...
if(origin_str != ''){
transform['origin'] = [origin_str.split(/\s+/g)
.map(function(e){
return e.slice(-2) == 'px'
|| /^[0-9\.]+$/.test(e) ?
parseFloat(e)
: e
})]
}
// get data... // get data...
// functions -> transform
if(args.constructor === Array){ if(args.constructor === Array){
var res = {} var res = {}
// return the full transform... // get everything set...
if(args.length == 0){ if(args.length == 0){
return transform Object.keys(attrs).forEach(function(k){ attrs[k](null, res) })
return res
} }
args.forEach(function(arg){ args.forEach(function(arg){
// direct match in shorthand data... do {
// we got an explicitly defined attr name...
if(arg in attrs){
res[arg] = attrs[arg]()
break
}
// we got a explicit function name...
if(arg in transform){ if(arg in transform){
res[arg] = transform[arg] res[arg] = transform[arg][0]
break
// try and find an alias...
} else if(arg in _transform_parse_rev){
var funcs = _transform_parse_rev[arg].funcs
var alt = _transform_parse_rev[arg].alt[0]
// no alternatives...
if(!alt){
res[arg] = ''
// explicit number value...
} else if(/^[0-9\.]+$/.test(alt)){
res[arg] = parseFloat(alt)
// explicit string value...
} else if(/^(['"]).*\1$/.test(alt)){
res[arg] = alt.slice(1, -1)
} else {
var v = $(that).transform(alt)
res[arg] = v == '' ? alt : v
} }
// we got an implicitly defined function...
// collect from function... if(arg in _transform_parse){
} else if(arg in _transform_parse){ // XXX
var v = res[arg] = {}
_transform_parse[arg].forEach(function(e){
var alternatives = e.split(/\|/g)
var k = alternatives.shift().trim()
v[k] = transform[k] != null ? transform[k] : ''
})
// don't know about this attr...
} else {
res[arg] = ''
} }
// search for aliases...
if(arg in _transform_parse_alt){
arg = _transform_parse_alt[arg][0]
}
break
} while(arg in _transform_parse_alt
|| arg in attrs
|| arg in transform)
}) })
// special case: we asked for a single value...
if(args.length == 1){ if(args.length == 1){
return res[args[0]] return res[Object.keys(res)[0]]
} }
return res return res
// set data... // set data...
// transform -> functions
} else { } else {
transform = Object.create(transform) Object.keys(args).forEach(function(arg){
Object.keys(args).forEach(function(key){ var val = args[arg]
// the changing value already exists...
if(key in transform // special case: origin...
// get one of the shorthand keys... if(arg == 'origin'){
// NOTE: we might need to pack or re-pack the date but we transform['origin'] = val
// can't decide here...
|| key in _transform_parse_rev // full function...
// got one of the standard keys... } else if(arg in _transform_parse){
|| key in _transform_parse){ if(val == ''){
transform[key] = args[key] delete functions[arg]
// key undefined...
} else { } else {
console.warn('Ignoring key "%s".', key) val = val instanceof Array ? val : [val]
transform[key] = args[key] var units = _transform_parse[arg]
.filter(function(s){
return Object.keys(s).length == val.length })[0]
functions[arg] = val.map(function(a, i){
var u = units[Object.keys(units)[i]] || ''
return typeof(a) != typeof('str') ? a + u : a })
}
// got an arg...
} else if(arg in attrs){
attrs[arg](val)
} }
}) })
elem.style.transform = Object.keys(functions)
.map(function(func){
return func +'('+ functions[func].join(', ') + ')'
})
.join(' ')
console.log('>>>>', transform) elem.style.transformOrigin = transform['origin'] != '' ?
transform['origin']
// XXX set new values and resolve new functions... .map(function(e){
// XXX return typeof(e) == typeof('str') ? e : e + 'px'
}).join(' ')
: ''
// build the value string...
var transform_str = ''
for(var f in functions){
transform_str += f +'('
+(functions[f]
// XXX test if px value...
.map(function(e){ return typeof(e) == typeof(123) ? e + 'px' : e })
.join(', '))+') '
}
console.log(transform_str)
// XXX STUB
return functions
// set the values...
elem.style.transform = transform_str
elem.style.transformOrigin = origin_str
} }
return $(this) return $(this)
@ -372,9 +389,11 @@ jQuery.fn.scale = function(value){
return $(this).transform('scale') return $(this).transform('scale')
} }
} }
jQuery.fn.origin = function(value){ jQuery.fn.origin = function(a, b, c){
if(value){ if(a && b && c){
return $(this).transform({origin: value}) return $(this).transform({origin: [a, b, c]})
} else if(a == '' || a instanceof Array){
return $(this).transform({origin: a})
} else { } else {
return $(this).transform('origin') return $(this).transform('origin')
} }