PageSourceSearch

https://www.archives.gov/includes/javascript/sortable/customsort.js

js archives.gov collected 2026-09-25 06:10:48 UTC 13,917 bytes, 365 lines download raw bytes

1/*
2    sortEnglishDateTime
3    -------------------
4
5    This function sorts English dateTime vaues such as:
6
7    1st January 2003, 23:32:01
8    23/03/1972 à 10:22:22
9    1970/13/03 at 23:22:01
10    
11    The function is "safe" i.e. non-dateTime data (like the word "Unknown") can be passed in and is sorted properly.
12    
13    UPDATE 08/01/2009: 1. Full or Short-hand english month names (e.g. "March" or "Mar") now require a space
14                       or a comma after them to be properly parsed.
15                       2. If no timestamp is given, a fake timestamp "00:00:00" is added to the string this enables
16                       the function to parse both date and datetime data.
17*/
18var sortEnglishDateTime = fdTableSort.sortNumeric;
19
20function sortEnglishDateTimePrepareData(tdNode, innerText) {
21        // You can localise the function here
22        var months = ['january','february','march','april','may','june','july','august','september','october','november','december','jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'];
23
24        // Lowercase the text
25        var aa = innerText.toLowerCase();         
26        
27        // Replace the longhand and shorthand months with an integer equivalent
28        for(var i = 0; i < months.length; i++) {                 
29                aa = aa.replace(new RegExp(months[i] + '([\\s|,]{1})'), (i+13)%12 + " ");
30        };
31
32        // Replace multiple spaces and anything that is not valid in the parsing of the date, then trim
33        aa = aa.replace(/\s+/g, " ").replace(/([^\d\s\/-:.])/g, "").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
34        
35        // REMOVED: No timestamp at the end, then return -1
36        //if(aa.search(/(\d){2}:(\d){2}(:(\d){2})?$/) == -1) { return -1; };
37
38        // No timestamp at the end, then create a false one         
39        if(aa.search(/(\d){2}:(\d){2}(:(\d){2})?$/) == -1) { aa += " 00:00:00"; };
40        
41        
42        // Grab the timestamp
43        var timestamp = aa.match(/(\d){2}:(\d){2}(:(\d){2})?$/)[0].replace(/:/g, "");
44
45        // Make the timestamp 6 characters by default
46        if(timestamp.length == 4) { timestamp += "00"; };
47
48        // Remove it from the string to assist the date parser, then trim
49        aa = aa.replace(/(\d){2}:(\d){2}(:(\d){2})?$/, "").replace(/\s\s*$/, '');
50
51        // If you want the parser to favour the parsing of European dd/mm/yyyy dates then leave this set to "true"
52        // If you want the parser to favour the parsing of American mm/dd/yyyy dates then set to "false"
53        var favourDMY = true;
54
55        // If you have a regular expression you wish to add, add the Object to the end of the array
56        var dateTest = [
57                       { regExp:/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/, d:3, m:1, y:5 },  // mdy
58                       { regExp:/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/, d:1, m:3, y:5 },  // dmy
59                       { regExp:/^(\d\d\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/, d:5, m:3, y:1 }      // ymd
60                       ];
61
62        var start,y,m,d;
63        var cnt = 0;
64        var numFormats = dateTest.length;
65        while(cnt < numFormats) {
66               start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats;
67               if(aa.match(dateTest[start].regExp)) {
68                       res = aa.match(dateTest[start].regExp);
69                       y = res[dateTest[start].y];
70                       m = res[dateTest[start].m];
71                       d = res[dateTest[start].d];
72                       if(m.length == 1) m = "0" + String(m);
73                       if(d.length == 1) d = "0" + String(d);
74                       if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y);
75
76                       return y+String(m)+d+String(timestamp);
77               };
78               cnt++;
79        };
80        return -1;
81};
82
83/*
84    sortAlphaNumeric
85    ----------------
86
87    This function sorts alphaNumeric values e.g. 1, e, 1a, -23c, 54z
88    
89    Notice how the prepareData function actually returns an Array i.e. you are not limited
90    in the type of data you return to the tableSort script.
91*/
92function sortAlphaNumericPrepareData(tdNode, innerText){
93        var aa = innerText.toLowerCase().replace(" ", "");
94        var reg = /((\-|\+)?(\s+)?[0-9]+\.([0-9]+)?|(\-|\+)?(\s+)?(\.)?[0-9]+)([a-z]+)/;
95
96        if(reg.test(aa)) {
97                var aaP = aa.match(reg);
98                return [aaP[1], aaP[8]];
99        };
100
101        // Return an array
102        return isNaN(aa) ? ["",aa] : [aa,""];
103}
104
105function sortAlphaNumeric(a, b){
106        // Get the previously prepared array
107        var aa = a[fdTableSort.pos];
108        var bb = b[fdTableSort.pos];
109
110        // If they are equal then return 0
111        if(aa[0] == bb[0] && aa[1] == bb[1]) { return 0; };
112
113        // Check numeric parts if not equal
114        if(aa[0] != bb[0]) {
115                if(aa[0] != "" && bb[0] != "") { return aa[0] - bb[0]; };
116                if(aa[0] == "" && bb[0] != "") { return -1; };
117                return 1;
118        };
119        
120        // Check alpha parts if numeric parts equal
121        if(aa[1] == bb[1]) return 0;
122        if(aa[1] < bb[1])  return -1;
123        return 1;
124}
125
126/*
127    sortDutchCurrencyValues
128    -----------------------
129
130    This function sorts Dutch currency values (of the type 100.000,00)
131    The function is "safe" i.e. non-currency data (like the word "Unknown") can be passed in and is sorted properly.
132*/
133var sortDutchCurrencyValues = fdTableSort.sortNumeric;
134
135function sortDutchCurrencyValuesPrepareData(tdNode, innerText) {
136        innerText = parseInt(innerText.replace(/[^0-9\.,]+/g, "").replace(/\./g,"").replace(",","."));
137        return isNaN(innerText) ? "" : innerText;
138}
139
140/*
141   sortByTwelveHourTimestamp
142   -------------------------
143
144   This custom sort function sorts 12 hour timestamps of an hour/minute nature.
145   The hour/minute dividor can be a full-stop or a colon and it correctly calculates that 12.30am is before 1am etc
146   The am/pm part can be written in lower or uppercase and can optionally contain full-stops e.g.
147
148   am, a.m, a.m., AM, A.M etc
149
150   Additionally, the values "12 midnight" and "12 noon" are also handled correctly.
151
152   The question remains... does "12p.m." mean "midnight" or "12 noon"? I've decided here that it's 12 noon.
153
154   The function is "safe" i.e. non-timestamp data (like the word "Unknown") can be passed in and is sorted properly.
155*/
156var sortByTwelveHourTimestamp = fdTableSort.sortNumeric;
157
158function sortByTwelveHourTimestampPrepareData(tdNode, innerText) {
159        tmp = innerText
160        innerText = innerText.replace(":",".");
161
162        // Check for the special cases of "12 noon" or "12 midnight"
163        if(innerText.search(/12([\s]*)?noon/i) != -1) return "12.00";
164        if(innerText.search(/12([\s]*)?midnight/i) != -1) return "24.00";
165
166        var regExpPM = /^([0-9]{1,2}).([0-9]{2})([\s]*)?(p[\.]?m)/i;
167        var regExpAM = /^([0-9]{1,2}).([0-9]{2})([\s]*)?(a[\.]?m)/i;
168
169        if(innerText.search(regExpPM) != -1) {
170                var bits = innerText.match(regExpPM);
171                if(parseInt(bits[1]) < 12) { bits[1] = parseInt(bits[1]) + 12; }
172        } else if(innerText.search(regExpAM) != -1) {
173                var bits = innerText.match(regExpAM);
174                if(bits[1] == "12") { bits[1] = "00"; }
175        } else return "";
176
177        if(bits[2].length < 2) { bits[2] = "0" + String(bits[2]); }
178
179        innerText = bits[1] + "." + String(bits[2]);
180
181        return isNaN(innerText) ? "" : innerText;
182}
183/*
184   sortEnglishLonghandDateFormat
185   -----------------------------
186
187   This custom sort function sorts dates of the format:
188
189   "12th April, 2006" or "12 April 2006" or "12-4-2006" or "12 April" or "12 4" or "12 Apr 2006" etc
190
191   The function expects dates to be in the format day/month/year. Should no year be stipulated,
192   the function treats the year as being the current year.
193
194   The function is "safe" i.e. non-date data (like the word "Unknown") can be passed in and is sorted properly.
195*/
196var sortEnglishLonghandDateFormat = fdTableSort.sortNumeric;
197
198function sortEnglishLonghandDateFormatPrepareData(tdNode, innerText) {
199        var months = ['january','february','march','april','may','june','july','august','september','october','november','december'];
200
201        var aa = innerText.toLowerCase();
202
203        // Replace the longhand months with an integer equivalent
204        for(var i = 0; i < 12; i++) {
205                aa = aa.replace(months[i], i+1).replace(months[i].substring(0,3), i+1);
206        }
207
208        // If there are still alpha characters then return -1
209        if(aa.search(/a-z/) != -1) return -1;
210
211        // Replace multiple spaces and anything that is not numeric
212        aa = aa.replace(/\s+/g, " ").replace(/[^\d\s]/g, "");
213
214        // If were left with nothing then return -1
215        if(aa.replace(" ", "") == "") return -1;
216
217        // Split on the (now) single spaces
218        aa = aa.split(" ");
219
220        // If something has gone terribly wrong then return -1
221        if(aa.length < 2) return -1;
222
223        // If no year stipulated, then add this year as default
224        if(aa.length == 2) {
225                aa[2] = String(new Date().getFullYear());
226        }
227
228        // Equalise the day and month
229        if(aa[0].length < 2) aa[0] = "0" + String(aa[0]);
230        if(aa[1].length < 2) aa[1] = "0" + String(aa[1]);
231
232        // Deal with Y2K issues
233        if(aa[2].length != 4) {
234                aa[2] = (parseInt(aa[2]) < 50) ? '20' + aa[2] : '19' + aa[2];
235        }
236
237        // YMD (can be used as integer during comparison)
238        return aa[2] + String(aa[1]) + aa[0];
239}
240/*
241   sortIPAddress
242   -------------
243
244   This custom sort function correctly sorts IP addresses i.e. it checks all of the address parts and not just the first.
245
246   The function is "safe" i.e. non-IP address data (like the word "Unknown") can be passed in and is sorted properly.
247*/
248var sortIPAddress = fdTableSort.sortNumeric;
249
250function sortIPAddressPrepareData(tdNode, innerText) {
251        // Get the innerText of the TR nodes
252        var aa = innerText;
253
254        // Remove spaces
255        aa = aa.replace(" ","");
256
257        // If not an IP address then return -1
258        if(aa.search(/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/) == -1) return -1;
259
260        // Split on the "."
261        aa = aa.split(".");
262
263        // If we don't have 4 parts then return -1
264        if(aa.length != 4) return -1;
265
266        var retVal = "";
267
268        // Make all the parts an equal length and create a master integer
269        for(var i = 0; i < 4; i++) {
270                retVal += (String(aa[i]).length < 3) ? "0000".substr(0, 3 - String(aa[i]).length) + String(aa[i]) : aa[i];
271        }
272
273        return retVal;
274}
275/*
276   sortScientificNotation
277   ----------------------
278
279   This custom sort function sorts numbers stipulated in scientific notation
280
281   The function is "safe" i.e. data like the word "Unknown" can be passed in and is sorted properly.
282
283   N.B. The only way I can think to really sort scientific notation is to convert
284        it to a floating point number and then perform the sort on that. If you can think of
285        an easier/better way then please let me know.
286*/
287var sortScientificNotation = fdTableSort.sortNumeric;
288
289function sortScientificNotationPrepareData(tdNode, innerText) {
290        var aa = innerText;
291
292        var floatRegExp = /((\-|\+)?(\s+)?[0-9]+\.([0-9]+)?|(\-|\+)?(\s+)?(\.)?[0-9]+)/g;
293
294        aa = aa.match(floatRegExp);
295
296        if(!aa || aa.length != 2) return "";
297
298        var f1 = parseFloat(aa[0].replace(" ",""))*Math.pow(10,parseFloat(aa[1].replace(" ","")));
299        return isNaN(f1) ? "" : f1;
300}
301
302/*
303        sortImage
304        ---------
305
306        This is the function called in order to sort the data previously prepared by the function
307        "sortImagePrepareData". It does a basic case sensitive comparison on the data using the
308        tableSort's in-built sortText method.
309*/
310var sortImage = fdTableSort.sortText;
311
312/*
313        This is the function used to prepare i.e. parse data, to be used during the sort
314        of the images within the last table.
315
316        In this case, we are checking to see if the TD node has any child nodes that are
317        images and, if an image exists, return it's "src" attribute.
318        If no image exists, then we return an empty string.
319
320        The "prepareData" functions are passed the actual TD node and also the TD node inner text
321        which means you are free to check for child nodes etc and are not just limited to
322        sorting on the TD node's inner text.
323
324        The prepareData functions are not required (only your bespoke sort function is required)
325        and only called by the script should they exist.
326*/
327function sortImagePrepareData(td, innerText) {
328        var img = td.getElementsByTagName('img');
329        return img.length ? img[0].src: "";
330}
331
332/*
333        sortFileSize
334        ------------
335
336        1 Byte = 8 Bit
337        1 Kilobyte = 1024 Bytes
338        1 Megabyte = 1048576 Bytes
339        1 Gigabyte = 1073741824 Bytes
340*/
341var sortFileSize = fdTableSort.sortNumeric;
342
343function sortFileSizePrepareData(td, innerText) {
344        var regExp = /(kb|mb|gb)/i;
345
346        var type = innerText.search(regExp) != -1 ? innerText.match(regExp)[0] : "";
347
348        switch (type.toLowerCase()) {
349                case "kb" :
350                        mult = 1024;
351                        break;
352                case "mb" :
353                        mult = 1048576;
354                        break;
355                case "gb" :
356                        mult = 1073741824;
357                        break;
358                default :
359                        mult = 1;
360        };
361
362        innerText = parseFloat(innerText.replace(/[^0-9\.\-]/g,''));
363
364        return isNaN(innerText) ? "" : innerText * mult;
365};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.