Changeset 33940

Show
Ignore:
Timestamp:
06/13/09 21:20:51 (5 years ago)
Author:
sheile
Message:

内部関数をあまり使わない形に書き換え

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lang/javascript/userscripts/1movegooglecalendar.user.js

    r13292 r33940  
    11// ==UserScript== 
     2 
    23// @name           1 Move Google Calendar 
    34// @namespace      http://d.hatena.ne.jp/sheile/ 
    4 // @description    Google Calendarの表示範囲を1日単位で移動できるボタンを付与します 
     5// @description    Google Calendarの表示範囲を1日単位で移動できるボタンを追加します 
    56// @include        https://www.google.com/calendar/render* 
    67// @include        http://www.google.com/calendar/render* 
     
    89 
    910(function() { 
    10         var isComplete = false; 
    11         var innerNames = {}; 
    12         var available = {}; 
    13         var MODE_NAME = { 1: "DAY", 2: "WEEK", 3: "MONTH", 4: "CUSTOM", 5: "LIST" }; 
     11        var functionName = "void"; 
    1412 
    15         function observe(element, event, func) 
    16         { 
    17                 if(element.attachEvent) { element.attachEvent("on" + event, func); } 
    18                 if(element.addEventListener) { element.addEventListener(event, func, false); } 
     13        window.addEventListener("load", addSingleMoveButton, false); 
     14 
     15        function getXPathElement(parent, xpath) { 
     16                return document.evaluate(xpath, parent, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; 
    1917        } 
    20  
    21         function native(element) 
    22         { 
    23                 if(element.wrappedJSObject) return element.wrappedJSObject; 
    24                 return element; 
    25         } 
    26  
    27         observe(window, "load", addSingleMoveButton); 
    28  
     18         
    2919        //----------------------------------------------------------------- 
    3020        //      1日だけ表示期間を変更するボタンを追加する 
     
    3424                getInnerFunction(); 
    3525 
    36                 var parent = document.getElementById("t1").getElementsByTagName("TR")[0]; 
    37                 var target = parent.getElementsByTagName("TD")[1]; 
     26                var trElement = getXPathElement(document, "//table[@id='t1']/tbody/tr"); 
     27                var tdElement = getXPathElement(trElement, "td[2]"); 
    3828 
    3929                var m1button = document.createElement("TD"); 
    40                 m1button.setAttribute("className", "noprint"); 
    41                 m1button.innerHTML = '<IMG class=navbutton style="filter:alpha(opacity=60);opacity:.60;BACKGROUND-POSITION: -148px -17px; PADDING-LEFT: 2px; BACKGROUND-IMAGE: url(//calendar.google.com/googlecalendar/images/combined_2_0.gif);VERTICAL-ALIGN:middle; padding-right:2px;" height=17 src="//calendar.google.com/googlecalendar/images/blank.gif" width=29>'; 
    42                 parent.insertBefore(m1button, target); 
     30                m1button.setAttribute("class", "noprint"); 
     31                m1button.innerHTML = '<img class="navbutton navBack" style="opacity:.60;" height=17 width=29 src="//calendar.google.com/googlecalendar/images/blank.gif">'; 
     32                trElement.insertBefore(m1button, tdElement); 
    4333 
    4434                var p1button = document.createElement("TD"); 
    45                 p1button.setAttribute("className", "noprint"); 
    46                 p1button.innerHTML = '<IMG class=navbutton style="filter:alpha(opacity=60);opacity:.60;BACKGROUND-POSITION: -148px 0px; PADDING-LEFT: 2px; BACKGROUND-IMAGE: url(//calendar.google.com/googlecalendar/images/combined_2_0.gif);VERTICAL-ALIGN:middle;" height=17 src="//calendar.google.com/googlecalendar/images/blank.gif" width=29>'; 
    47                 parent.insertBefore(p1button, target); 
     35                p1button.setAttribute("class", "noprint"); 
     36                p1button.innerHTML = '<img class="navbutton navForward" style="opacity:.60;" height=17 width=29 src="//calendar.google.com/googlecalendar/images/blank.gif">'; 
     37                trElement.insertBefore(p1button, tdElement); 
    4838 
    49                 observe(parent.getElementsByTagName("TD")[1], "mousedown", function() { singleMove(-1); }); 
    50                 observe(parent.getElementsByTagName("TD")[1], "dblclick", function() { singleMove(-1); }); 
    51                 observe(parent.getElementsByTagName("TD")[2], "mousedown", function() { singleMove(+1); }); 
    52                 observe(parent.getElementsByTagName("TD")[2], "dblclick", function() { singleMove(+1); }); 
     39                getXPathElement(m1button, "img").addEventListener("mousedown", function() { singleMove(-1); }, false); 
     40                getXPathElement(p1button, "img").addEventListener("mousedown", function() { singleMove(+1); }, false); 
    5341        } 
    5442 
     
    5947        function singleMove(diffDay) 
    6048        { 
    61                 if(!available["ALL"]) { 
    62                         getInnerFunction(); 
    63                 } 
    64                 if(!currentModeAvailable()) return; 
     49                var currentMode = getXPathElement(document, "//table[@id='chrome_main1']//div[@class='modelinkOn']/nobr/@id").nodeValue; 
    6550 
    66                 //      週モードの場合には7日間選択モードに変更をかける 
    67                 if(document.getElementById("mode_link2").getElementsByTagName("DIV")[2].className == "modelinkOn") { 
    68                         eval(innerNames["currentDate"] + "=" + innerNames["innerDate"]); 
    69                         eval(innerNames["changeMode"])("compact,7", true); 
    70                 } 
    71  
    72                 //      月モードの場合には普通の< >と同じ動作をする 
    73                 if(document.getElementById("mode_link3").getElementsByTagName("DIV")[2].className == "modelinkOn") { 
    74                         eval(innerNames["moveFunc"] + "(diffDay)"); 
     51                //      日、月、予定モードの場合は通常通りの処理を行う 
     52                if(currentMode == "mode-day" || currentMode == "mode-month" || currentMode == "mode-list") { 
     53                        window.wrappedJSObject[functionName](diffDay); 
    7554                        return; 
    7655                } 
    7756 
    78                 //      予定リストモードで前の予定を表示する場合は1つ前の予定を検索する 
    79                 if(document.getElementById("mode_link5").getElementsByTagName("DIV")[2].className == "modelinkOn" && 
    80                    diffDay < 0) { 
    81                         var miniTd = document.getElementById("dp_0_tbl").getElementsByTagName("TD"); 
    82                         var startPos; 
    83                         var i; 
    84                         for(i = 10; i < miniTd.length; i++) { 
    85                                 if(miniTd[i].className.match("DP_onmonth")) { 
    86                                         startPos = i; 
    87                                         break; 
    88                                 } 
    89                         } 
    90  
    91                         var curPos = startPos + (eval(innerNames["currentDate"]).toString().substr(6) - 1); 
    92                         i = curPos; 
    93                         while(i --> 10) { 
    94                                 if(miniTd[i].style.fontWeight == "bold") { 
    95                                         diffDay = i - curPos; 
    96                                         break; 
    97                                 } 
    98                         } 
    99                 } 
    100  
    101                 var moveNativeClosure = createMoveNativeClosure(innerNames, diffDay); 
    102                 setTimeout(moveNativeClosure, 0); 
    103         } 
    104  
    105  
    106         function currentModeAvailable() 
    107         { 
    108                 var selected = false; 
    109                 for(var i = 1; i <= 5; i++) { 
    110                         if(document.getElementById("mode_link" + i).getElementsByTagName("DIV")[2].className == "modelinkOn") { 
    111                                 if(available[MODE_NAME[i]]) return true; 
    112                                 selected = true; 
    113                         } 
    114                 } 
    115  
    116                 //      モード未選択の場合はCUSTOMが可能かどうか 
    117                 if(!selected) return available["CUSTOM"]; 
    118  
    119                 return false; 
    120         } 
    121  
    122         //----------------------------------------------------------------- 
    123         //      Google Calendarの内部関数を呼び出して期間をdiffDay日動かす 
    124         //----------------------------------------------------------------- 
    125         function createMoveNativeClosure(innerNames, diffDay) 
    126         { 
    127                 return function() { 
    128                         eval(innerNames["preFunc1"])(); 
    129                         eval(innerNames["preFunc2"])(); 
    130  
    131                         var targetDate = eval(innerNames["str2Date"] + "(" + innerNames["currentDate"] + ")"); 
    132  
    133                         targetDate.c += diffDay; 
    134                         eval(innerNames["instanceName"] + "." + innerNames["applyFunc"] + "(targetDate." + innerNames["date2Str"] + "())"); 
    135  
    136                         eval(innerNames["postFunc"])(); 
     57                //      週、指定日モードの場合は1日分の移動を行う 
     58                if(currentMode == "customModeLabel" || currentMode == "mode-week") { 
     59                        var cols = document.evaluate("count(//table[@id='tgTable']//td[contains(@class, 'tg-col')])", document, null, XPathResult.NUMBER_TYPE, null).numberValue; 
     60                        window.wrappedJSObject[functionName](diffDay / cols); 
    13761                } 
    13862        } 
    139  
    14063 
    14164        //----------------------------------------------------------------- 
     
    14467        function getInnerFunction() 
    14568        { 
    146                 var target = native(document.getElementById("t1").getElementsByTagName("IMG")[0]); 
    147                 var matchResult = target.onmousedown.toString().match(/function\s+[^(]+\([^()]+\)\s*\{\s*([^(]+)\(-1\);\s*return\s+false;\s*\}/); 
    148                 if(matchResult == null) return; 
    149  
    150                 innerNames["moveFunc"] = "native(window)." + matchResult[1]; 
    151                 available["MONTH"] = true; 
    152  
    153                 matchResult = eval(innerNames["moveFunc"]).toString().match(/function\s+[^(]+\(([^()]+)\)\s*\{\s*([^(]+)\(\);\s*try\s*\{\s*([^(]+)\(\);\s*([^.]+)\.([^(]+)\(\1\);\s*([^(]+)\(\);?\s*\}\s*finally\s*\{\s*[^(]+\(\4\.toString\(\)\s*\+\s*"\.AlterPeriod\("\s*\+\s*\1\s*\+\s*"\)"\);?\s*\}\s*\}/); 
    154                 if(matchResult == null) return; 
    155  
    156                 innerNames["preFunc1"] = "native(window)." + matchResult[2]; 
    157                 innerNames["preFunc2"] = "native(window)." + matchResult[3]; 
    158                 innerNames["instanceName"] = "native(window)." + matchResult[4]; 
    159                 innerNames["postFunc"] = "native(window)." + matchResult[6]; 
    160  
    161                 var innerFunc = matchResult[5]; 
    162                 matchResult = eval(innerNames["instanceName"] + "." + innerFunc).toString().match(/function\s*\(([^()]+)\)\s*\{\s*var\s+([^;]+);\s*if\s*\(\1\s*===\s*0\)\s*\{\s*if\s*\([^.]+\.[^<]+\s*<\s*7\)\s*\{\s*this\.[^(]+\([^.]+\(\)\);\s*return;?\s*\}\s*\2\s*=\s*[^.]+\(\);\s*var\s+([^\s=]+)\s*=\s*\2\.[^(]+\(\),\s*([^\s=]+)\s*=\s*[^(]+\(\)\.[^(]+\([^,]+,\s*[^(]+\([^()]+\)\);\s*if\s*\(\3\s*!==\s*\4\)\s*\{\s*var\s+([^\s=]+)\s*=\s*([^(]+)\(\2\);\s*\5\.[^+]+\s*\+=\s*\4\s*-\s*\3;\s*if\s*\(\3\s*<\s*\4\)\s*\{?\s*\5\.[^-]+\s*-=\s*7;\s*\}?\s*\2\s*=\s*\5\.[^(]+\(\);?\s*\}\s*this\.([^(]+)\(\2\);?\s*\}\s*else\s*\{\s*\2\s*=\s*\6\(([^()]+)\);\s*\2\.[^+]+\s*\+=\s*this\.[^*]+\s*\*\s*\1;\s*this\.\7\(\2\.([^(]+)\(\)\);?\s*\}\s*\}/); 
    163                 if(matchResult != null) { 
    164                         innerNames["str2Date"] = "native(window)." + matchResult[6]; 
    165                         innerNames["applyFunc"] = matchResult[7]; 
    166                         innerNames["currentDate"] = "native(window)." + matchResult[8]; 
    167                         innerNames["originalCurrentDate"] = matchResult[8]; 
    168                         innerNames["date2Str"] = matchResult[9]; 
    169                 } else { 
    170                         matchResult = eval(innerNames["instanceName"] + "." + innerFunc).toString().match(/function\s*\(([^()]+)\)\s*\{\s*if\s*\(\1\s*===\s*0\)\s*\{?\s*this\.([^(]+)\([^()]+\(\)\);\s*\}?\s*else\s*\{\s*var\s+([^\s=]+)\s*=\s*([^(]+)\(([^()]+)\);\s*\3\.[^+]+\s*\+=\s*\1\s*\*\s*7;\s*this\.\2\(\3\.([^(]+)\(\)\);?\s*\}\s*\}/); 
    171                         if(matchResult == null) return; 
    172                         innerNames["str2Date"] = "native(window)." + matchResult[4]; 
    173                         innerNames["applyFunc"] = matchResult[2]; 
    174                         innerNames["currentDate"] = "native(window)." + matchResult[5]; 
    175                         innerNames["originalCurrentDate"] = matchResult[5]; 
    176                         innerNames["date2Str"] = matchResult[6]; 
    177                 } 
    178  
    179                 available["DAY"] = true; 
    180                 available["CUSTOM"] = true; 
    181                 available["LIST"] = true; 
    182                 //      右上の表示期間タブから切り替え用内部関数名を取得 
    183                 var functionText = native(document.getElementById("mode_link0")).onmousedown.toString(); 
    184                 matchResult = functionText.match(/function\s+[^(]+\([^()]*\)\s*\{\s*([^(]+)\((['"])search\2\);?\s*\}/); 
    185                 if(matchResult == null) return; 
    186  
    187                 innerNames["changeMode"] = "native(window)." + matchResult[1]; 
    188  
    189                 //      ▽から内部的な現在日を取得 
    190                 matchResult = native(document.getElementById("mode_link4")).onmousedown.toString().match(/function\s+[^(]+\([^()]*\)\s*\{\s*([^()]+)\(\);?\s*\}/); 
    191                 if(matchResult == null) return; 
    192  
    193                 matchResult = eval("native(window)." + matchResult[1]).toString().match("}\\s*([^\\s=]+)\\s*=\\s*\\(" + innerNames["originalCurrentDate"]); 
    194                 if(matchResult == null) return; 
    195  
    196                 innerNames["innerDate"] = "native(window)." + matchResult[1]; 
    197                 available["WEEK"] = true; 
    198  
    199                 available["ALL"] = true; 
     69                var script = getXPathElement(document, "//table[@id='t1']//img[@class='navbutton navBack']/@onmousedown").nodeValue; 
     70                functionName = script.match(/([^(]+)\(-1\);/)[1]; 
    20071        } 
    20172})();