The prototype framework was first built to facilitate Ruby developers in Javascript development, and is fully embodied in this version.
Compared with version 1.3.1, the programming ideas and skills in version 1.4.0 are even more shocking and helpful for developing programming ideas.
This version mainly includes the iterator idea and is also a core concept in Ruby. Using this framework for Javascript development can almost avoid the use of for loops.
Below are someCode:
/* Prototype JavaScript framework, version 1.4.0
* (C) 2005 Sam Stevenson <sam@conio.net>
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the prototype web site: http://prototype.conio.net/
*
/*--------------------------------------------------------------------------*/
/*
Prototype-1.4.0 comment version by http://www.x2blog.cn/supnate //*
Define prototype object to inform version information, which is helpfulProgramAutomatic detection
Scriptfragment is a regular expression used to capture the <SCRIPT> tag and its content in a string.
Emptyfunction: Empty Function
K: return the function of the parameter, which will be applied later.
The syntax for directly defining objects is used here:
VaR OBJ = {
Property1: value1,
Property2: value2,
....
}
It will be frequently used later
*/
VaR prototype = {
Version: '1. 4.0 ',
Scriptfragment :'(? : <Script. *?>) (\ N | \ r | .)*?) (? : <\/SCRIPT> )',
Emptyfunction: function (){},
K: function (x) {return x}
}
/*
Defines the mode for creating classes. classes created in this mode can implement constructors.
Initialize is an abstract method. Apply allows you to keep parameters for it.
If you call this. initialize (arguments) directly, the entire parameter array is used as a parameter.
*/
VaR class = {
Create: function (){
Return function (){
This. Initialize. Apply (this, arguments );
}
}
}
// Indicates the namespace or abstract class to make the code logic clearer.
VaR abstract = new object ();
/*
copy all source attributes to destination.
example:
var A ={};
var B = {P: 1};
object. extent (a, B);
alert (. p);
we can see that a has the property P and the value is equal to 1.
If the attributes are the same, they are overwritten.
*/
object. extend = function (destination, source) {
for (property in source) {
destination [property] = source [property];
}< br> return destination;
}< br>/*
the following function is missing compared to prototype-1.3.1:
object. prototype. extend = function (object) {
return object. extend. apply (this, [This, object]);
}< br> therefore, compatibility issues may occur when the original JS script based on the 1.3.1 framework is upgraded to 1.4.0. You only need to add the above function in 1.4.0.
This is probably because it is a waste to add the extend method to each object. After all, 95% of objects are not used.
the extend method also brings some trouble to the reflection enumeration, which can be seen from the usage of the hash object.
*/
/*
converts an object to a string. Here, we can provide more details as long as the object customizes the inspect function. Instead of the tostring of the original object, it is always [object].
for example, if the inspect function is defined for the array,
var arr = [, 3];
-> arr. inspect () = "[1, 2, 3]";
*/
object. inspect = function (object) {
try {
If (Object = undefined) return 'undefined';
If (Object = NULL) return 'null';
return object. inspect? Object. inspect (): object. tostring ();
}catch (e) {
If (E instanceof rangeerror) return '... ';
throw E;
}< BR >}
/*
A very important method, which can bind a function to an object to run
compared with version 1.3.1, a parameter cannot be added during binding, but now we can.
example:
var obj1 = {P: "obj1" };< br> var obj2 ={< br> P: "obj2",
method: function (ARG) {
alert (Arg + this. p);
}< BR >}< br> obj2.method ("this is"); // displays "this is obj2";
obj2.method. BIND (obj1, "Now this is"); // display "Now this is obj1";
the last sentence must be written as follows in 1.3.1:
obj2.method. BIND (obj1) ("Now this is"); // displays "Now this is obj1";
*/
function. prototype. bind = function () {
VaR _ method = This, argS = $ A (arguments), object = args. shift ();
return function () {
return _ method. apply (object, argS. concat ($ A (arguments);
}< BR >}< br>/*
listens to events that use functions as objects, in this way, an independent and common event handler can be generated. For example, to process a click event:
function clickhandler (element) {
// process the Click Event of the element
}
assume that node node1 exists.
node1.onclick = function () {
clickhandler. bindaseventlistener (this) (event | window. event);
}< br> */
function. prototype. bindaseventlistener = function (object) {
VaR _ method = This;
return function (event) {
return _ method. call (object, event | window. event);
}< BR >}
/*
All numeric types are number instances. The following describes how to define the number class.
*/
object. extend (number. prototype, {
/*
convert a number to a color format
*/
tocolorpart: function () {
var digits = This. tostring (16);
If (this <16) return '0' + digits;
return digits;
},
// Add 1
succ: function () {
return this + 1;
},
/*
execute a specified number of cycles, for example, obtaining 10 random numbers
var ran = []
var c = 10;
C. times (function () {
Ran. Push (math. Random ();
});
$ R is a quick creation method for objectrange objects, which will be introduced later.
*/
times: function (iterator) {
$ R (0, this, true ). each (iterator);
return this;
}< BR >});
/*
Try object, only one method these
*/
VaR try = {
/*
Call a function based on the specified parameter. The first successful call value is returned.
It is used later when an XMLHTTPRequest object is created across browsers.
If none of them are successful, undefined is returned.
*/
These: function (){
VaR returnvalue;
For (VAR I = 0; I <arguments. length; I ++ ){
VaR Lambda = arguments [I];
Try {
Returnvalue = Lambda ();
Break;
} Catch (e ){}
}
Return returnvalue;
}
}
/*--------------------------------------------------------------------------*/
/*
The timer class, compared with the window. setinterval function, can make the callback function not to be concurrently called. For details, see the ontimerevent annotation.
*/
VaR periodicalexecuter = Class. Create ();
Periodicalexecuter. Prototype = {
/*
Constructor, which specifies the callback function and execution frequency, in seconds.
*/
Initialize: function (callback, frequency ){
This. Callback = callback;
This. frequency = frequency;
This. currentlyexecuting = false;
This. registercallback ();
},
/*
Start to execute the timer. Generally, do not display the call, which is called in the constructor.
Note:
This. ontimerevent. BIND (this)
If it is written as follows:
This. ontimerevent
The this pointer of the function in ontimerevent points to the window object, that is, the default object of setinterval.
*/
Registercallback: function (){
Setinterval (this. ontimerevent. BIND (this), this. Frequency * 1000 );
},
/*
It is equivalent to a callback function proxy.
In the traditional setinterval function, when the time reaches, the callback function is executed forcibly, And the currentlyexecuting attribute is added here to judge,
If the execution time of the callback function exceeds a time slice, it is prevented from being executed repeatedly.
*/
Ontimerevent: function (){
If (! This. currentlyexecuting ){
Try {
This. currentlyexecuting = true;
This. Callback ();
} Finally {
This. currentlyexecuting = false;
}
}
}
}
/*--------------------------------------------------------------------------*/
/*
A convenient quick link function can obtain the page node specified by the parameter. If there are multiple parameters, an array is returned.
The parameter format can be either the node id value or the node reference, that is, $ ("someid") and $ ("someid") are equivalent;
*/
Function $ (){
VaR elements = new array ();
For (VAR I = 0; I <arguments. length; I ++ ){
VaR element = arguments [I];
If (typeof element = 'string ')
Element = Document. getelementbyid (element );
If (arguments. Length = 1)
Return element;
Elements. Push (element );
}
Return elements;
}
/*
The method used to add a String object is the same as the method used to add a number.
*/
Object. Extend (string. prototype ,{
/*
Convert HTML to plain text, for example:
VaR S = "<font color = 'red'> Hello </font> ";
S. striptags () will get "hello ".
*/
Striptags: function (){
Return this. Replace (/<\/? [^>] +>/GI ,'');
},
/*
Delete the script code in the text (<script xxx>... </SCRIPT>)
*/
Stripscripts: function (){
Return this. Replace (New Regexp (prototype. scriptfragment, 'img '),'');
},
// Extract the script from the string and return an array consisting of all the script content
Extractscripts: function (){
VaR matchall = new Regexp (prototype. scriptfragment, 'img '); // first find all the code tags including <SCRIPT>
VaR matchone = new Regexp (prototype. scriptfragment, 'im '); // Delete each script <SCRIPT> flag
Return (this. Match (matchall) | []). Map (function (scripttag ){
Return (scripttag. Match (matchone) | ['','']) [1];
});
},
// Extract the script block from the string before executing the script
Evalscripts: function (){
Return this. extractscripts (). Map (eval );
},
/*
Use the browser's own mechanism to encode HTML strings, such as converting <to <;
*/
Escapehtml: function (){
VaR DIV = Document. createelement ('div ');
VaR text = Document. createtextnode (this );
Div. appendchild (text );
Return Div. innerhtml;
},
/*
Decoding html
*/
Unescapehtml: function (){
VaR DIV = Document. createelement ('div ');
Div. innerhtml = This. striptags ();
Return Div. childnodes [0]? Div. childnodes [0]. nodevalue :'';
},
// Obtain the query string array. For example, you can use document. Location. toqueryparams () to obtain a hash table consisting of keys and values (represented by objects ).
Toqueryparams: function (){
VaR pairs = This. Match (/^ \?? (. *) $/) [1]. Split ('&');
Return pairs. Inject ({}, function (Params, pairstring ){
VaR pair = pairstring. Split ('= ');
Params [pair [0] = pair [1];
Return Params;
});
},
// Convert a string to a character array
Toarray: function (){
Return this. Split ('');
},
/*
Camels the strings connected. For example:
VaR S = "background-color ";
Alert (S. camelize ());
"Backgroundcolor" is displayed ".
*/
Camelize: function (){
VaR ostringlist = This. Split ('-');
If (ostringlist. Length = 1) return ostringlist [0];
VaR camelizedstring = This. indexof ('-') = 0
? Ostringlist [0]. charat (0). touppercase () + ostringlist [0]. substring (1)
: Ostringlist [0];
For (VAR I = 1, Len = ostringlist. length; I <Len; I ++ ){
VaR S = ostringlist [I];
Camelizedstring + = S. charat (0). touppercase () + S. substring (1 );
}
Return camelizedstring;
},
/*
Inspect indicates observation. Here we will convert the string to an observed form. Here, the escape characters are written as strings before the escape,
For example:
VaR S = "ABC \ ndef ";
Alert (s );
The following two strings are obtained: the first line is ABC and the next line is def.
While
Alert (S. Inspect ());
ABC \ ndef
That is, the form used to assign a value to a string, which is similar to the inspect function of the array.
*/
Inspect: function (){
Return "'" + this. Replace (' \ ',' \ '). Replace ("'", '\') + "'";
}
});
// Create a name Link
String. Prototype. parsequery = string. Prototype. toqueryparams;
// Two exception objects are defined for iterative control.
VaR $ break = new object ();
VaR $ continue = new object ();
/*
This is a very Ruby mechanism. In fact, you can regard enumerable as an enumeration interface,
_ Each is a required method. Any class that implements this method can call other members of the interface class.
For example, the following array implements this interface, which is also the most typical application.
*/
VaR enumerable = {
/*
Call the iterator method for each member of an enumerated object,
If $ continue exception is thrown by the iterator method, the execution continues. If $ break exception is thrown, the iteration does not continue.
The abstract method _ each is called,
_ Each is implemented by a class that inherits from enumerable.
The index counter is used to indicate the elements currently executed by the iterator, which is optional by the iterator.
*/
Each: function (iterator ){
VaR Index = 0;
Try {
This. _ each (function (value ){
Try {
Iterator (value, index ++ );
} Catch (e ){
If (E! = $ Continue) Throw E;
}
});
} Catch (e ){
If (E! = $ Break) Throw E;
}
},
/*
Determines whether all elements in the enumerated object can make the iterator return true. If no iterator is specified, it determines whether all elements correspond to the true value of the boolean type.
True is returned if all conditions are met; otherwise, false is returned;
Note that $ break exception is used to implement short-circuit effect of "logical and" operations.
Another skill worth noting is the use !! Cast a variable to a boolean type, see: http://www.x2blog.cn/supNate? Tid = 4669
*/
ALL: function (iterator ){
VaR result = true;
This. Each (function (value, index ){
Result = Result &&!! (Iterator | prototype. K) (value, index );
If (! Result) throw $ break;
});
Return result;
},
/*
Determines whether all elements in the enumerated object meet the specified iterator (true is returned). If yes, true is returned. Otherwise, false is returned.
The principle is similar to that of the All method.
Returns true if the array is empty.
*/
Any: function (iterator ){
VaR result = true;
This. Each (function (value, index ){
If (result = !! (Iterator | prototype. K) (value, index ))
Throw $ break;
});
Return result;
},
/*
Returns the results of all enumeration elements executed by the iterator as an array.
*/
Collect: function (iterator ){
VaR Results = [];
This. Each (function (value, index ){
Results. Push (iterator (value, index ));
});
Return results;
},
/*
Returns the value of the first enumeration element that enables the iterator to return true. If no value is true, "undefined" is returned, that is, the result is not assigned a value.
This may be a small mistake for the author to consider. After all, returning "undefined" is not a good style (just speculation)
*/
Detect: function (iterator ){
VaR result;
This. Each (function (value, index ){
If (iterator (value, index )){
Result = value;
Throw $ break;
}
});
Return result;
},
/*
Returns all enumeration elements that enable the iterator to return true as an array.
*/
Findall: function (iterator ){
VaR Results = [];
This. Each (function (value, index ){
If (iterator (value, index ))
Results. Push (value );
});
Return results;
},
/*
Grep is a classic command in a UNIX operating system. Here it is a similar implementation of JavaScript.
Pattern is the regular mode. It performs iterator operations on all enumeration elements that conform to this mode, saves the operation results to the array, and returns the results.
Note that the iterator parameter is optional. In this case, only the enumerated elements are matched in the pattern and all matching results are returned.
*/
Grep: function (pattern, iterator ){
VaR Results = [];
This. Each (function (value, index ){
VaR stringvalue = value. tostring ();
If (stringvalue. Match (pattern ))
Results. Push (iterator | prototype. K) (value, index ));
})
Return results;
},
/*
The each method is used to determine whether the enumerated object contains enumeration elements of the specified value, instead of loops. prototype is designed to provide a ruby-based programming method,
If it is implemented in a loop, it is similar to the following code:
For (VAR I = 0; I <this. length; I ++ ){
If (this [I] = Object) return true;
}
In this function, the iterator is defined:
Function (value ){
If (value = Object ){
Found = true;
Throw $ break;
}
}
This iterator serves as a parameter for the each method.
*/
Include: function (object ){
VaR found = false;
This. Each (function (value ){
If (value = Object ){
Found = true;
Throw $ break;
}
});
Return found;
},
/*
The literal meaning is "injection". Its function is equivalent to using memo as the global variable associated with each iterator. Each iteration operates on it and returns the final result of the operation. For example, for Arrays:
VaR arr = [1, 2, 3];
Now you want to convert the string to: 123
If you do not call the join method, the traditional method is:
VaR S = "";
For (VAR I = 0; I <arr. length; I ++ ){
S + = arr [I];
}
Now, by calling the inject function, you can:
VaR S = arr. Inject ("", function (memo, value) {return memo + value });
The running results are identical.
*/
Inject: function (memo, iterator ){
This. Each (function (value, index ){
Memo = iterator (memo, value, index );
});
Return memo;
},
/*
Call the method on all enumeration elements and PASS Parameters to this method.
Returns the execution results of all methods as an array.
*/
Invoke: function (method ){
VaR ARGs = $ A (arguments). Slice (1 );
Return this. Collect (function (value ){
Return Value [Method]. Apply (value, argS );
});
},
/*
Returns the largest iterator returned value.
*/
MAX: function (iterator ){
VaR result;
This. Each (function (value, index ){
Value = (iterator | prototype. K) (value, index );
If (value> = (result | value ))
Result = value;
});
Return result;
},
/*
Returns the smallest iterator returned value.
*/
Min: function (iterator ){
VaR result;
This. Each (function (value, index ){
Value = (iterator | prototype. K) (value, index );
If (value <= (result | value ))
Result = value;
});
Return result;
},
/*
Based on the returned results of the iterator, enumeration elements are divided into two arrays Trues and falses. Trues includes enumeration elements that the iterator returns true, and falses is the opposite.
*/
Partition: function (iterator ){
VaR Trues = [], falses = [];
This. Each (function (value, index ){
(Iterator | prototype. K) (value, index )?
Trues: falses). Push (value );
});
Return [Trues, falses];
},
/*
Returns the property of all enumerated elements.
*/
Pluck: function (property ){
VaR Results = [];
This. Each (function (value, index ){
Results. Push (value [property]);
});
Return results;
},
/*
Returns the enumerated elements whose execution result of all iterators is false.
*/
Reject: function (iterator ){
VaR Results = [];
This. Each (function (value, index ){
If (! Iterator (value, index ))
Results. Push (value );
});
Return results;
},
/*
A complex function is used to sort enumeration elements based on the iterator results. The execution result of iterator is smaller than that of iterator.
It mainly includes three functions:
1. Collect method. Each returned array element includes the result of running the value and iterator, which is obtained by {value: value, criteria: iterator (value, index )}.
2. Execute the sort method on the array returned by collect. In this case, the object embedded in the array object is a delegate function that is used to specify the sorting rule. The standard is to sort the values returned by the iterator, smaller than the previous
3. Execute the pluck method on the sort result, that is, return the value of the value attribute, so the original values in the returned enumerated object are finally sorted based on the result of the iterator of the iterator.
*/
Sortby: function (iterator ){
Return this. Collect (function (value, index ){
Return {value: value, criteria: iterator (value, index )};
}). Sort (function (left, right ){
VaR A = left. Criteria, B = right. criteria;
Return a <B? -1: A> B? 1: 0;
}). Pluck ('value ');
},
/*
Converts enumeration objects to arrays and uses the collect method and prototype. K functions to reduce repeated code.
*/
Toarray: function (){
Return this. Collect (prototype. K );
},
/*
Compression functions are complex to implement and cannot be used -_-.
The received parameter must be an enumerated object and can have multiple parameters. The last parameter is the iterator (optional.
It is used to swap the rows and columns of a two-dimensional array composed of itself and parameters, remove unnecessary data, or supplement the missing data (with undefined ). The number of lines after switching is determined by the number of elements in the caller, while the number of columns is the number of array parameters plus 1.
The first element order of each array parameter is the first line, the second element order is the second line, and so on. Until the caller has used up the elements.
The iterator is used to perform an operation on each converted row.
For example:
VaR arr1 = [1, 2, 3];
VaR arr2 = [4, 5, 6];
VaR arr3 = [7, 8, 9];
VaR arr=arr1.zip (arr2, arr3 );
// Use the iterator to output the result. Inspect is used to output the array string represented by the array syntax.
Arr. Each (function (s ){
Document. Write (S. Inspect ());
Document. Write ("<br/> ");
}
);
The result is as follows:
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]
If arr1 = [1, 2] is left unchanged, the execution result is:
[1, 4, 7]
[2, 5, 8]
*/
ZIP: function () {
var iterator = prototype. k, argS = $ A (arguments);
If (typeof args. last () = 'function')
iterator = args. pop ();
// uses its own enumeration object as an element and an array of parameters (which can also be enumerated, and convert the enumerated object to an array (through the $ A iterator)
var collections = [this]. concat (ARGs ). map ($ A);
return this. map (function (value, index) {
iterator (value = collections. pluck (INDEX);
return value;
});
},
/*
This is actually an abstract method to be implemented, the array object has a redefinition
. Therefore, this is converted to an array (toarray () and inspect is called.
for non-array enumeration objects, '# 'format
*/
inspect: function () {
return' # ';
}< BR >}< br> // provides a quick link to some methods of the enumerable base class
object. extend (enumerable, {
map: enumerable. collect,
Find: enumerable. detect,
select: enumerable. findall,
Member: enumerable. include,
entries: enumerable. toarray
});
/*
Converts an object to an array.
For a string, it is directly converted into a character array. For example, $ A ("ABC") will obtain ["A", "B", "C"]
Otherwise, the set object becomes an array. Such objects include the arguments set of function parameters and the options set of <SELECT>,
The elements set of <form>, childnodes of all child nodes of a node, and so on.
*/
VaR $ A = array. From = function (iterable ){
If (! Iterable) return [];
If (iterable. toarray ){
Return iterable. toarray ();
} Else {
VaR Results = [];
For (VAR I = 0; I <iterable. length; I ++)
Results. Push (iterable [I]);
Return results;
}
}
/*
Let the array inherit from enumarable object (base class)
*/
Object. Extend (array. prototype, enumerable );
/*
Make a link. Generally, private or abstract members in prototype start with an underscore. Here _ reverse is generally used as an descriptive method.
*/
Array. Prototype. _ Reverse = array. Prototype. Reverse;
......