Skip to content

Instantly share code, notes, and snippets.

@texastoland
Created July 1, 2018 05:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save texastoland/2d0c7d8147514604217cce24df8ff749 to your computer and use it in GitHub Desktop.
Save texastoland/2d0c7d8147514604217cce24df8ff749 to your computer and use it in GitHub Desktop.
My first OSS circa 2008
/**
* @author jtoland
*/
Ext.ux.extendMixin('Ext.ux.layout.AlignLayout', Ext.layout.ContainerLayout, function( $super ) { return {
monitorResize:true,
parseMargins : function( val ) {
if (typeof val == 'string') { return arguments.callee.call(null, val.split(' ')); }
if (typeof val == 'number') { return arguments.callee.call(null, [val]); }
if (Ext.isArray(val)) {
switch (val.length) {//intentional fall through
case 1: val[1] = val[0];
case 2: val[2] = val[0];
case 3: val[3] = val[1];
}
val = {top : val[0], right : val[1], bottom : val[2], left : val[3]};
}
return val;
},
parseAlign : function( place ) {
if (place == 'fill') { return 0; }
if (place.indexOf('-') >= 0) return place;
if (place.length == 2) { switch (place) {
case 'nw': return arguments.callee.call(null, 'tl');
case 'ne': return arguments.callee.call(null, 'tr');
case 'se': return arguments.callee.call(null, 'br');
case 'sw': return arguments.callee.call(null, 'bl');
} } else { switch (place.charAt(0)) {
case 'n': return arguments.callee.call(null, 't');
case 'e': return arguments.callee.call(null, 'r');
case 's': return arguments.callee.call(null, 'b');
case 'w': return arguments.callee.call(null, 'l');
case 'c': place = 'c';
} }
return place + '-' + place;
},
parseOffset : function( val, rel ) {
switch (typeof val) {
case 'number': return val;
case 'string': return val.indexOf('%') < 0 ? parseInt(val, 10) : Math.floor(parseFloat(val) / 100 * rel);
}//implicit default: return falsy;
},
parseSize : function( val, rel ) {
return typeof (val = Ext.ux.applyCb(this.parseOffset, null, arguments)) == 'number' && val <= 0 ?
val + rel : val;
},
onLayout : $super.onLayout.createSequence(function( ct, target ) {
var targetSize = target.getInnerSize();
ct.items.each(function( item ) {
var margins, sizer = item.alignEl && Ext.get(item.alignEl),
layoutEl = sizer && sizer.getWidth() && sizer.getHeight() ? sizer : target,
layoutSize = layoutEl == target ? targetSize : layoutEl.getInnerSize(),
initW = item.width, initH = item.height;
if (item.align) { switch (typeof item.align) {
case 'string':
if (item.align.search(/[a-z]/i) >= 0) {
item.align = this.parseAlign(item.align.toLowerCase());
if (typeof item.align == 'string') { break; }
}//intentional fall through for case 'fill' becomes 0
default:
item.align = this.parseMargins(item.align);
margins = {
top : item.align.top ? this.parseSize(item.align.top, layoutSize.height) : 0,
right : item.align.right ? this.parseSize(item.align.right, layoutSize.width) : 0,
bottom : item.align.bottom ? this.parseSize(item.align.bottom, layoutSize.height) : 0,
left : item.align.left ? this.parseSize(item.align.left, layoutSize.width) : 0
};
margins.width = Math.max(layoutSize.width - margins.right - margins.left, 0);
margins.height = Math.max(layoutSize.height - margins.bottom - margins.top, 0);
} }
if (margins) { item.setSize(margins); }
else if (initW || initW === 0 || initH || initH === 0) {
item.setSize(this.parseSize(initW, layoutSize.width), this.parseSize(initH, layoutSize.height));
}
var el = item.getPositionEl();
if (item.position !== false && ct.positioning !== false) {
el.position(item.position || ct.positioning || 'absolute');
}
var xy = margins ? [margins.left, margins.top] : [
this.parseOffset(item.x, layoutSize.width) || 0,
this.parseOffset(item.y, layoutSize.height) || 0
];
if (item.align && !margins) {
var righty = item.align.indexOf('r') > 0;
//tweak styles to prevent auto-width el from getting swallowed by parent hiding overflow
if (righty) { el.dom.style.right = 0; }
el.dom.style.left = '';
el.alignTo(layoutEl, item.align, xy);
if (righty) { el.dom.style.right = ''; }
}
else if (xy[0] || xy[1]) { item.setPosition(xy); }
}, this);
}),
//borrowed by CardFlipper to compensate for FillLayout bug
mixer : arguments.callee.createCallback($super)
}; }, function() {
Ext.Container.LAYOUTS.align = this;
this.getMixin = this.prototype.mixer;
delete this.prototype.mixer;
});
/**
* @author jtoland
* @version 0.6
*/
(function() {
function mixin( $super ) { return {
filterOptRe : (function() {
var regex = $super.filterOptRe.toString();
return new RegExp(Ext.escapeRe(regex.
slice(regex.indexOf('/') + 1, regex.lastIndexOf('/')).replace(/(\)\$)/, '|proxy$1')));
})(),
initAutoEl : function() {
this.autoEl = !this.autoEl ? {} : typeof this.autoEl == 'string' && this.autoEl.indexOf('<') < 0 ?
{html : this.autoEl} : this.autoEl;
},
onRender : function() {
this.initAutoEl();
$super.onRender.apply(this, arguments);
this.on();
},
proxyListener : function( evt, fn, scope ) {
var actionEl = this.getActionEl();
actionEl.on.apply(actionEl, arguments);
if (!this.proxiedListeners) { this.proxiedListeners = {}; }
this.proxiedListeners[evt.toLowerCase()] = {h : fn, s : scope};
},
routeListener : function( evt, fn, scope, cfg ) {
//no need to parse evt to Object b/c will recurse as String by design
if (typeof evt != 'string' || cfg && !cfg.proxy) { return $super.on.apply(this, arguments); }
var cache = Array.prototype.slice.call(arguments, 0);
if (!cache[2]) { cache[2] = cache[3] && cache[3].scope ? cache[3].scope : this; }
this.el ? this.proxyListener.apply(this, cache) : this.cachedListeners ?
this.cachedListeners.push(cache) : this.cachedListeners = [cache];
},
on : function() {
if (arguments.length) { return this.routeListener.apply(this, arguments); }
if (!this.cachedListeners) return;
Ext.each(this.cachedListeners, function( item ) { this.proxyListener.apply(this, item); }, this);
delete this.cachedListeners;
},
addListener : function() { this.on.apply(this, arguments); },
un : function( evt, fn, scope ) {
evt = evt.toLowerCase();
if (!this.proxiedListeners || !this.proxiedListeners[evt] || this.proxiedListeners[evt].h != fn ||
this.proxiedListeners[evt].s != scope && this.proxiedListeners[evt].s != this) {
return $super.un.apply(this, arguments);
}
var actionEl = this.getActionEl();
actionEl.un.apply(actionEl, arguments);
delete this.proxiedListeners[evt];
},
removeListener : function() { this.un.apply(this, arguments); }
}; }
Ext.ux.extendMixin('Ext.ux.DomComponent', Ext.BoxComponent, mixin, 'dom');
Ext.ux.extendMixin('Ext.ux.Canvas', Ext.Container, mixin, function() {
this.override({
initComponent : this.superclass.initComponent.createInterceptor(function() {
if (!this.layout && Ext.ux.layout && Ext.ux.layout.AlignLayout) { this.layout = 'align'; }
}),
initAutoEl : this.prototype.initAutoEl.createSequence(function() {
this.autoEl = typeof this.autoEl == 'string' ? {html : this.autoEl} : {cn : this.autoEl};
}),
onRender : this.prototype.onRender.createSequence(function() {
this.html = Ext.get(this.el.dom.firstChild);
}),
getResizeEl : function() { return this.html; },
getFirstChild : function() { return this.items.items[0]; },
getLastChild : function() { return this.items.items[this.items.items.length - 1]; }
});
}, 'canvas');
})();
/**
* @projectDescription generic utilities to supplement distributed versions
* @author jtoland
*//*global console*/
//TODO:port docs to JSDoc
if (typeof console != 'undefined' && console.firebug) {
/**
* self-explanatory extension to Firebug console api
* @param {Object} ...
* @return {Void}
* @see console.dir
* @see console.group
* @see console.groupEnd
*/
console.groupDir = function() {
for (var i = 0; i < arguments.length; i++) {
console.group(arguments[i]);
console.dir(arguments[i]);
console.groupEnd();
}
};
}
/**
* supplement broken Ext.Fx.shift if intend to shift exclusively x or y
*///TODO:report bug
Ext.lib.AnimBase.prototype.setAttribute = (function () {
var libXY = Ext.lib.AnimBase.prototype.setAttribute;
return function() { return isNaN(arguments[1]) || libXY.apply(this, arguments); };
})();
/**
* supplement broken Function#extend on Ext classes which fails to return subclass
* @param {Object,Function} mixin
* @param {Function} [callback]
* @param {Object} [scope]
* @param {String} [xtype]
* @return {Function}
* @see Ext.ux.extendMixin
*///TODO:report bug
Function.prototype.mixin = function( mixin, callback, scope ) {
return Ext.ux.extendMixin(null, this, mixin, callback, scope);
};
/**
* shortcut for converting arguments object to Array
* @param {Object,Array} a array-like
* @param {Number} [n=0] begin
* @param {Number} [m=length] end
* @return {Array}
* @see Array#slice
*/
Ext.ux.subArray = function( a, n, m ) { return Array.prototype.slice.call(a, n || 0, m || a.length); };
/**
* emulate Java Object#clone neither recurses nor makes provisions for prototype
* @param {Object,Array} o
* @return {Object}
*/
Ext.ux.clone = function( o ) {
return Ext.isArray(o) || o.length && o.callee ? Ext.ux.subArray(o) : Ext.apply({}, o);
};
/**
* supplement broken Ext.callback which fails to return result;
* syntax less prone to typographical error than Function#apply
* @param {Function} cb
* @param {Object} scope
* @param {Array} args
* @return {Variant}
*///TODO:report bug
Ext.ux.applyCb = function( cb, scope, args ) { return cb.apply(scope, args); };
Ext.ns('Ext.ux.util.CSS');
/** supplement Ext.util.CSS.createStyleSheet by concatenating rules array if provided */
Ext.ux.util.CSS.createStyleSheet = function() {
var args = Ext.ux.subArray(arguments);
if (Ext.isArray(args[0])) { args[0] = Ext.ux.applyCb(String.prototype.concat, '', args[0]); }
Ext.ux.applyCb(Ext.util.CSS.createStyleSheet, Ext.util.CSS, args);
};
/** supplement broken Ext.Element#setOpacity which pads filter string with left spaces *///TODO:report bug
Ext.Element.prototype.setOpacity = Ext.Element.prototype.setOpacity.createSequence(function() {
if (!Ext.isIE) { return; }
if (!(this.dom.style.filter = this.dom.style.filter.trim())) { this.dom.style.removeAttribute('filter'); }
});
/**
* normalize Element#getViewSize and Element#getStyleSize
* @return {Size}
*/
Ext.Element.prototype.getInnerSize = function() {
var view = this.getViewSize(), content = this.getStyleSize();
return {width : Math.min(view.width, content.width), height : Math.min(view.height, content.height)};
};
(function() {
function init( lender, asignee, donor ) {//private
if (donor && !asignee) { asignee = '({/*anonymous*/}).Class'; }
var courier = {self : asignee, config : lender}, autoConstructor;
if (typeof asignee == 'string') {
Ext.ns(asignee);
if (donor) { autoConstructor = donor; asignee += '=function(){autoConstructor.apply(this,arguments);}'; }
courier.self = eval(asignee);
}
if (typeof lender == 'function') { courier.config = donor ? lender(donor.prototype, courier.self) : lender(courier.self); }
if (autoConstructor && courier.config.Constructor) {
autoConstructor = courier.config.Constructor;
delete courier.config.Constructor;
}
if (courier.self.prototype && courier.self !== asignee && !courier.config.ctype) {
courier.config.ctype = autoConstructor ? asignee.substring(0, asignee.lastIndexOf('=')) : asignee;
}
return courier;
}
/**
* intended for wrapping module files to facilitate namespacing and to provide module alias within closures
* @param {String,Object} module automatically namespaced
* @param {Function,Object} mixin passed single argument of module expected to return Object
* @param {Function} [callback] after mixin has been applied to module
* @param {Object} [scope=module]
* @return {Object}
*/
Ext.ux.applyMixin = function( module, mixin, callback, scope ) {/*
* <code>
* Ext.ux.applyMixin('Company.project', function( $module ) { return {
* View : {
* css : [
* '.red{background-color:red}',
* '.green{background-color:green}',
* '.blue{background-color:blue}',
* ]
* },
* init : function() { Ext.ux.util.CSS.createStyleSheet($module.View.css); }
* }; }, function() { Ext.onReady(this.init); });
* </code>
*/
var args = init(mixin, module);
Ext.apply(module = args.self, args.config);
if (callback) { callback.call(scope || module); }
return module;
};
/**
* intended for wrapping class files to facilitate namespacing and to provide superclass alias to mixin
* @param {String,Function} subclass automatically namespaced
* @param {Function} superclass
* @param {Function,Object} mixin passed superclass prototype and subclass expected to return Object
* @param {Function} [callback] after class creation
* @param {Object} [scope=subclass]
* @param {String} [xtype] final String argument registers itself
* @return {Function}
*/
Ext.ux.extendMixin = function( subclass, superclass, mixin, callback, scope ) {/*
* <code>
* Ext.ux.extendMixin('Ext.ux.CustomCmp', Ext.Component, function( $super ) { return {
* Constructor : $super.constructor.createInterceptor(function() { this.id = this.xtype + new Date().getTime(); }),
* onRender : function() {
* this.autoEl = {html : 'instance:' + this.ctype};
* Ext.ux.applyCb($super.onRender, this, arguments);
* this.getEl().highlight();
* }
* }; }, 'mycmp');
* </code>
*/
var args = init(mixin, subclass, superclass);
Ext.extend(subclass = args.self, superclass, args.config);
if (typeof callback == 'function') { callback.call(typeof scope == 'object' ? scope : subclass); }
var xtype = arguments[arguments.length - 1];
if (arguments.length > 3 && typeof xtype == 'string') { Ext.reg(xtype, subclass); }
return subclass;
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment