The tool library has been used in recent effects:
JavaScript multi-stage linkage floating menu (second edition)
JavaScript floating positioning prompt effect
JavaScript Table line positioning effect
JavaScript Table Sort
The main features of this tool library are:
【Cross-browser】
Can be used in the following browsers: IE6, IE7, IE8, Firefox 3.5.3, Chrome 3.0, Safari 4.0.3, Opera 10.10
The ie series is a must, and other versions can be supported.
【Using namespace】
Of course it is not a real "namespace", it is just some global variables with similar uses.
There is the following namespace:
$$: represents Object, saves object-related methods, and also replaces the most commonly used getElementById method;
$$B: represents Browser, saves browser information;
$$A: represents Array, related methods for saving arrays and class arrays;
$$F: represents Function, a related method for saving functions;
$$D: represents Dom, related operations and methods of document objects;
$$E: represents Event, related operations and compatible processing of events;
$$S: represents String, a related method for saving strings.
Although I don't object to restrained expansion of native objects, if possible, avoid naming pollution.
Use multiple namespaces (rather than single ones) just because management is easy and easy to use.
Using two $ is not about more US dollars (although I really want), but avoid conflicts with popular frameworks.
I don't use the form when using all variables, because that will cause some problems,Refer to here。
【Use anonymous functions】
It seems that jquery is developed, which is to embed the code in a function.
In fact, it is to use closures, which can use local variables and prevent naming conflicts.
【Using object detection】
"Object detection is inherently superior to browser detection", from the truth of "ppk talks about JavaScript".
Try to use any object detection as much as possible. Of course, don’t be too obsessed with some things that are too difficult to deal with.
jQuery's support is very good in object detection, so it is recommended to take a look.
The pursuit of goals is:
【Small size】
The volume here does not mean the number of characters, but the number of attributes and methods.
The properties and methods of the tool library must be very useful, preferably "must be added".
Of course, as the use increases, the tool library will gradually expand, but this principle must be adhered to.
【High efficiency】
Efficiency is an unchanging pursuit, of course, after weighing the pros and cons.
When it comes to efficiency, I have to admire Google. Not only does its code pursue efficiency, but the downloaded code has been detected by the browser.
You can download it yourself using each browser to try it out.
The purpose of establishment is:
【Common methods for integration】
Integrating commonly used methods is not only conducive to code reuse and maintenance.
But it is inevitable that some irrelevant methods will be added, which will increase the amount of code and reduce efficiency.
【Solve compatibility issues】
Solve some common compatibility issues and reduce coding burden.
Description of each part
【Object】
The namespace is: $$
$$ itself is the most commonly used method:
It also includes two methods: extend and deepextend.
Among them, extend is the same as that, and is used to extend objects, and is one of the longest used methods.
deepextend is a depth extension. The depth here is similar to the meaning of depth copying. The reference is jQuery's extension.
【Browser】
The namespace is: $$B
Get browser information through userAgent, mainly obtaining the type and version of the browser.
Here is a reference to the Browser. To understand this part, you must first know the userAgent of each browser.
Below are the userAgents of each browser (except for ie, the latest version is currently):
ie6
Mozilla/4.0 (compatible; MSIE 6.0; ...)
ie7
Mozilla/4.0 (compatible; MSIE 7.0; ...)
ie8
Mozilla/4.0 (compatible; MSIE 8.0; ...)
ff
Mozilla/5.0 (...) Gecko/20090824 Firefox/3.5.3
chrome
Mozilla/5.0 (...) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.195.27 Safari/532.0
safari
Mozilla/5.0 (...) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9.1
opera
Opera/9.80 (...) Presto/2.2.15 Version/10.10
First, judge the browser type by judging unique characters:
msie: /msie/.test(ua) && !/opera/.test(ua),
opera: /opera/.test(ua),
safari: /webkit/.test(ua) && !/chrome/.test(ua),
firefox: /firefox/.test(ua),
chrome: /chrome/.test(ua)
};
Getting version information is more troublesome, and Browser's method is more clever (with modifications):
for (var i in b) {
if (b[i]) {
vMark = i;
}
}
if () {
vMark = "version";
}
= RegExp("(?:" + vMark + ")[\\/: ]([\\d.]+)").test(ua) ? RegExp.$1 : "0";
But referring to the userAgent above, you will find that the operator's acquisition should also use "version". The problem is that its userAgent before 10 is as follows:
Opera/9.99 (...) Presto/9.9.9
"version" is not used. In order to apply it in most cases, it is better not to use "version" and this judgment is not used much.
【Array】
The namespace is: $$A
The following methods are included:
isArray: determines whether an object is an array
forEach: executes a specified function (callback) once on each element in the array. (Reference address)
filter: executes the specified function (callback) once on each element in the array, and creates a new array, which is the original array element with the return value true when all callback functions are executed. (Reference address)
every: Execute the specified function (callback) once on each element in the array until this function returns false. If this element is found, every will return false. If the callback function returns true after executing each element, every will return true. (Reference address)
some: Execute the specified function (callback) once on each element in the array until this function returns true. If this element is found, some will return true. If the callback function returns false after executing each element, some will return false. (Reference address)
map: executes a specified function (callback) once on each element in the array, and creates a new array for the elements with the result returned each time. (Reference address)
indexOf: Compare whether searchElement and each element of the array are absolutely consistent (===). When an element meets the condition, return the index of the current element. If no discovery is found, return -1 directly. (Reference address)
lastIndexOf: Compare whether searchElement and each element of the array are absolutely consistent (===). When an element meets the condition, it returns the index of the current element. If no discovery is found, return -1 directly. (Reference address)
In addition to isArray, the above methods are all methods of adding arrays in JavaScript 1.6. You can go to the specific ones.mozillaCheck.
Not only arrays can use these methods, but as long as the objects can be traversed like arrays, such as NodeList objects and arguments objects.
【Function】
The namespace is: $$F
There are only two methods in it: bind and bindAsEventListener.
These two are the classic methods in it, and are used to bind this to the function.
The principle is to use call/apply to change the object that calls the method.
It uses converting arguments objects into arrays. I don’t know who discovered them, just know the usage.
ps: Not only slice, but other things like concat, join, etc. can also be used in this way.
The difference between bindAsEventListener and bind is that it sets the first parameter as an event object, which is specifically used in event callback functions.
The compatibility of fixEvent is used to handle event, and the event section will be explained in detail later.
【Dom】
The namespace is: $$D
This part is the largest, most complex and most important part of the tool library.
Mainly, some Dom operations are stored and general compatibility issues are solved.
where getScrollTop and getScrollLeft are scrollTop and scrollLeft that get document scrolling, respectively.
Generally speaking, if you are in standard mode, you should use documentElement to get it, otherwise use body to get it.
But Chrome and safari (both using WebKit rendering engine) must be obtained using body even in standard mode.
The method used here is:
return || ;
Prioritize the access to documentElement and then choose the body, so that it can basically solve the problem.
But this is actually incomplete. If you add the following style to the document:
In ie6/7, you will find that in standard mode the body will be presented at the specified height and width, and can be equipped with scroll bars.
That is to say, documentElement and body can set scrollTops respectively.
Then it’s hard to tell which one to get at this time. Fortunately, this is not required to be set in this way (at least I haven’t touched it).
For such special cases, it is enough to know that this situation is present, and there is no need to add too much code for it.
ps: The scrollLeft/scrollLeft obtained will not have negative values.
The contains method is to determine whether the parameter 1 element object contains the parameter 2 element object.
It mainly uses ie's contains and w3c's compareDocumentPosition to judge.
For details, please refer to theCompare document location section。
There are two methods related to the coordinates of the element: rect and clientRect.
where rect is relative to the browser document, clientRect is relative to the browser window.
When gettingBoundingClientRect is supported, use it to work with getScrollLeft/getScrollTop to get document location.
Otherwise, use the offsetLeft/offsetTop of offsetParent to loop.
For details, please refer to theCompare element position parts。
There are three style-related methods: curStyle, getStyle, and setStyle
curStyle is used to get the final style sheet of the element, and returns getComputedStyle(w3c) or currentStyle(ie) according to the support situation.
ps: Here we should give priority to gettingComputedStyle, because operator also supports currentStyle.
getStyle is used to get the final style value of the specified style attribute of the element.
If you support getComputedStyle, just use it to get the style computed value, and you can do it with computed value.Refer to here。
Although currentStyle is a bit like getComputedStyle and both getComputedStyle, the values obtained by the two are different in form.
It does not return the exact specification uniform value after rendering is completed like getComputedStyle, but is just a set value.
And this value is not necessarily the accurate value after rendering.
The main thing the program does is to get the value close to getComputedStyle in ie.
First of all, it is to deal with transparency. Although ie uses filters, its value divided by 100 is the same as the value of "opacity" in w3c:
var opacity = parseFloat(RegExp.$1);
return opacity ? opacity / 100 : 0;
}
return 1;
There is also "float", which is easier to change to "styleFloat".
Another job after getting the style is to convert units. If the value obtained is determined to be a numeric value and the unit is not px, the conversion will be performed.
The method is to refer to jQuery's curCSS. Before understanding, we first understand two less used properties: runtimeStyle and pixelLeft.
runtimeStyle is a unique property of ie. Its usage is similar to style, but it has the highest priority.
That is to say, if the style is set in runtimeStyle, the same style in style will be ignored.
For details, please refer to birdshome's "About the difference between three Style instances in HTML Object"and"Discussion on using runtimeStyle attribute”
The function of pixelLeft is to return the left-style value of the element in pixels px, which is supported by ie (can also be used in runtimeStyle) and opera.
After knowing these two things, you can understand its principles:
1. First back up the original value:
2. Set the left of runtimeStyle to the left of currentStyle:
The purpose is to use the priority of runtimeStyle to ensure that the style can be displayed in the original style after modifying it;
3. Set the left of style to the value to be converted, and cleverly use pixelLeft to get the px unit form of this value:
ret = + "px";
4. Finally restore the original left value:
= rsLeft;
This allows you to convert pixel values without changing the rendering style.
ps: jQuery explains that this method was also proposed by Dean Edwards, God.
Finally, there is a setStyle for setting styles, which are mainly used to set styles in batches and solve some compatibility problems.
You can call it in the following two ways:
$$(element or element collection, { style attribute name: attribute value, ... })
$$(element or element collection, style attribute name, attribute value)
The first parameter is the element or element collection to set styles. If it is a single element, it will automatically be converted into a single element collection:
The second parameter is a set of key-value pairs, the key is the style attribute name, and the value is the corresponding attribute value.
If you only set one style, you can set the second parameter to the style attribute name and the third parameter to the attribute value. The program creates a new key-value pair collection:
Then use forEach to go through the element collection, and set all the styles listed in the bound function to the element in the for in.
ps: A single style should be set directly for a single element unless there is a compatibility issue.
The rest is to solve the compatibility problem.
First of all, transparency. I use filters. If you set filters directly, you will replace all other filters.
Refer to the jQuery method, first get the original filter, replace the transparent filter part, and add the transparent filter to be set:
"alpha(opacity=" + value * 100 + ")";
A very clever method, remember to multiply the value by 100 corresponding to the "opacity" of w3c.
As for "float", it is relatively simple. I just use "styleFloat" and others to use "cssFloat".
【Event】
The namespace is: $$E
This is an old problem of compatibility. There are three methods here: addEvent, removeEvent, and fixEvent.
addEvent and removeEvent are the addition and removal events respectively. In the past, I used ie's attachEvent to be compatible with w3c's addEventListener.
But after seeing Dean Edwards' method, I switched to his. In addition to better compatibility, it can also solve some bugs (see detailsThe bug part of cloneNode here)。
The addEvent/removeEvent in the code has been modified based on the Dean code as needed, but the principle is still the same.
The fixEvent is used to correct the compatibility of event objects. It mainly adds some w3c properties and methods. The bindAsEventListener uses it above.
Here I only made ie compatibility, and the others were directly used to use event, so that I could not achieve detailed compatibility, but it would be enough.
jQuery's fix is relatively complete and worth studying.
【String】
The namespace is: $$S
I rarely do advanced applications of String, so there is no way to put it in for the time being.
There is a camelize method in it to convert strings in the form of horizontal bars (such as "border-top") into camel form (such as "borderTop").
The principle is to use the trick when the second parameter of replace is function:
This can be used in the conversion of style attribute names, and it is used in getStyle/setStyle.
Call method
Finally, let’s talk about the calling method, which is the same as calling a general function method, except that you need to include a namespace before.
For example: $$.extend(...)
For example, $$ is a function itself, you can use it directly like this: $$(...)
Chained calls may be cool, but they are not suitable for use on such a tool library unless they extend native objects (not used here either).
Complete code
/*!
* Cloudgamer JavaScript Library v0.1
* Copyright (c) 2009 cloudgamer
* Blog: /
* Date: 2009-10-29
*/
var $$, $$B, $$A, $$F, $$D, $$E, $$S;
(function(){
var O, B, A, F, D, E, S;
/*Object*/
O = function (id) { return "string" == typeof id ? (id) : id; };
= function (destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
};
= function (destination, source) {
for (var property in source) {
var copy = source[property];
if ( destination === copy ) continue;
if ( typeof copy === "object" ){
destination[property] = ( destination[property] || {}, copy );
}else{
destination[property] = copy;
}
}
return destination;
};
/*Browser*/
/*from youa*/
B = (function(ua){
var b = {
msie: /msie/.test(ua) && !/opera/.test(ua),
opera: /opera/.test(ua),
safari: /webkit/.test(ua) && !/chrome/.test(ua),
firefox: /firefox/.test(ua),
chrome: /chrome/.test(ua)
};
var vMark = "";
for (var i in b) {
if (b[i]) {
vMark = i;
}
}
if () {
vMark = "version";
}
= RegExp("(?:" + vMark + ")[\\/: ]([\\d.]+)").test(ua) ? RegExp.$1 : "0";
= ;
b.ie6 = && parseInt() == 6;
b.ie7 = && parseInt() == 7;
b.ie8 = && parseInt() == 8;
return b;
})(());
/*Array*/
A = {
isArray: function( obj ) {
return (obj) === "[object Array]";
},
forEach: function( array, callback, thisp ){
if () {
(callback, thisp);
} else {
for ( var i = 0, len = ; i < len; i++ ) {
( thisp, array[i], i, array );
}
}
},
filter: function( array, callback, thisp ){
if () {
return (callback, thisp);
} else {
var res = [];
for ( var i = 0, len = ; i < len; i++ ) {
( thisp, array[i], i, array ) && (array[i]);
};
return res;
}
},
every: function( array, callback, thisp ){
if () {
return (callback, thisp);
} else {
for ( var i = 0, len = ; i < len; i++ ) {
if ( !( thisp, array[i], i, array ) ) return false;
};
return true;
}
},
some: function( array, callback, thisp ){
if () {
return (callback, thisp);
} else {
for ( var i = 0, len = ; i < len; i++ ) {
if ( ( thisp, array[i], i, array ) ) return true;
};
return false;
}
},
map: function( array, callback, thisp ){
if () {
return (callback, thisp);
} else {
var res = [];
for ( var i = 0, len = ; i < len; i++ ) {
( ( thisp, array[i], i, array ) );
};
return res;
}
},
indexOf: function( array, elt ){
if () {
return (elt);
} else {
for ( var i = 0, len = ; i < len; i++ ) {
if ( array[i] === elt ) return i;
};
return -1;
}
},
lastIndexOf: function( array, elt, from ){
if () {
return (elt);
} else {
var len = ;
if ( isNaN(from) || from >= len - 1 ) {
from = len - 1;
} else {
from = from < 0 ? (from) + len : (from);
}
for ( ; from > -1; from-- ) { if ( array[i] === elt ) return i; };
return -1;
}
}
};
/*Function*/
F = (function(){
var slice = ;
return {
bind: function( fun, thisp ) {
var args = (arguments, 2);
return function() {
return (thisp, ((arguments)));
}
},
bindAsEventListener: function( fun, thisp ) {
var args = (arguments, 2);
return function(event) {
return (thisp, [(event)].concat(args));
}
}
};
})();
/*Dom*/
D = {
getScrollTop: function(node){
var doc = node ? : document;
return || ;
},
getScrollLeft: function(node){
var doc = node ? : document;
return || ;
},
contains: function(a, b){
return ( =
? function(a, b){ return !!((b) & 16); }
: function(a, b){ return a != b && (b); }
)(a, b);
},
rect: function(node){
var left = 0, top = 0, right = 0, bottom = 0;
//IE8's getBoundingClientRect is inaccurate
if ( ! || B.ie8 ) {
var n = node;
while (n) { left += , top += ; n = ; };
right = left + ; bottom = top + ;
} else {
var rect = ();
left = right = (node); top = bottom = (node);
left += ; right += ;
top += ; bottom += ;
};
return { "left": left, "top": top, "right": right, "bottom": bottom };
},
clientRect: function(node){
var rect = (node), sLeft = (node), sTop = (node);
-= sLeft; -= sLeft;
-= sTop; -= sTop;
return rect;
},
curStyle: function(elem){
return ( =
? function(elem){ return (elem, null); }
: function(elem){ return ; }
)(elem);
},
getStyle: function(elem, name){
return ( =
? function(elem, name){
var style = (elem, null);
return name in style ? style[ name ] : ( name );
}
: function(elem, name){
var style = ;
//Transparency from youa
if (name == "opacity") {
if (/alpha\(opacity=(.*)\)/()) {
var opacity = parseFloat(RegExp.$1);
return opacity ? opacity / 100 : 0;
}
return 1;
};
if (name == "float") { name = "styleFloat"; }
var ret = style[ name ] || style[ ( name ) ];
//Unit conversion from jquery
if ( !/^\-?\d+(px)?$/( ret ) && /^\-?\d/.test( ret ) ) {
style = , left = , rsLeft = ;
= ;
= ret || 0;
ret = + "px";
= left;
= rsLeft;
}
return ret;
}
)(elem, name);
},
setStyle: function(elems, style, value) {
if (!) { elems = [ elems ]; }
if (typeof style == "string") { var s = style; style = {}; style[s] = value; }
(elems, function(elem){
for (var name in style) {
var value = style[name];
if (name == "opacity" && ) {
//ae transparency settings from jquery
= ( || "").replace( /alpha\([^)]*\)/, "" ) +
"alpha(opacity=" + value * 100 + ")";
} else if (name == "float") {
[ ? "styleFloat" : "cssFloat" ] = value;
} else {
[ ( name ) ] = value;
}
};
});
}
};
/*Event*/
E = (function(){
/*from dean edwards*/
var addEvent, removeEvent, guid = 1;
if ( ) {
addEvent = function(element, type, handler){
(type, handler, false);
};
removeEvent = function(element, type, handler){
(type, handler, false);
};
} else {
addEvent = function(element, type, handler){
if (!handler.$$guid) handler.$$guid = guid++;
if (!) = {};
var handlers = [type];
if (!handlers) {
handlers = [type] = {};
if (element["on" + type]) {
handlers[0] = element["on" + type];
}
}
handlers[handler.$$guid] = handler;
element["on" + type] = handleEvent;
};
removeEvent = function(element, type, handler){
if ( && [type]) {
delete [type][handler.$$guid];
}
};
function handleEvent() {
var returnValue = true, event = fixEvent();
var handlers = [];
for (var i in handlers) {
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false) {
returnValue = false;
}
}
return returnValue;
};
}
function fixEvent(event) {
if (event) return event;
event = ;
= + ();
= + ();
= ;
= stopPropagation;
= preventDefault;
if( == "mouseout") {
= ;
}else if( == "mouseover") {
= ;
}
return event;
};
function stopPropagation() { = true; };
function preventDefault() { = false; };
return {
"addEvent": addEvent,
"removeEvent": removeEvent,
"fixEvent": fixEvent
};
})();
/*String*/
S = {
camelize: function(s){
return (/-([a-z])/ig, function(all, letter) { return (); });
}
};
/*System*/
// remove css image flicker
if (B.ie6) {
try {
("BackgroundImageCache", false, true);
} catch(e) {}
};
/**/
$$ = O; $$B = B; $$A = A; $$F = F; $$D = D; $$E = E; $$S = S;
})();
Package and download