masum diary

<< February 2020 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 >>

スポンサーサイト

一定期間更新がないため広告を表示しています

- | permalink | - | -
<< auの機種変更をした。 | main | リストアップしてみる >>

Trac用Greasemonkey スクリプト

Tracの機能を少しだけ拡張するためのgreasemonkeyスクリプトを作った。

Trac.user.js


  • レポート画面にて、1ページに複数のテーブルがある場合でも、列のソートをできるようにした。
  • wiki エリアにて、alt + enter で [[BR]]入力
  • チケットページにて、ログが多くなると見づらくなるので、いろいろと色別けをした。


適用させるページは、「*trac*」としてある。つまり、URL中に trac という文字列がある場合は全て拾ってしまうので、適宜、適用条件の変更を。

少し多いけど、記録に残す意味で、ソースも載せておく。

詳細ページにて…


// ==UserScript==

// @name       trac

// @namespace    masum

// @include    *trac*

// ==/UserScript==

(function () {

  var BR         = "[[BR]]";   // 改行文字列

  var COLOR_PREVIEW  = "#ffe3e3";  // preview 背景色

  var COLOR_TICKETWIKI = "#e3e3ff";  // wiki 背景色

  var COLOR_TICKETLOG1 = "#fff";   // チケットチェンジログ背景色1

  var COLOR_TICKETLOG2 = "#e3ffe3";  // チケットチェンジログ背景色2



  // XPath によるタグ検出

  function $2(xpath){

    var nodes = document.evaluate(xpath, document, null,

            XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

    var data = [];

    for (var i = 0; i&lt;nodes.snapshotLength; i++) {

      data.push(nodes.snapshotItem(i));

    }

    return (data.length &gt;= 1) ? data : null;

  }



  // チケットの Description Preview と、Comment Preview の背景色変更

  path = '//*[@class="ticket"]//*[@id="preview"]';

  if ( (nodes = $2(path) ) != null) {

    nodes[0].style.backgroundColor = COLOR_PREVIEW;

  }



  // チケットの wiki の背景色変更

  path = '//*[@class="ticket"]//*[@class="wikitext"]';

  if ( (nodes = $2(path) ) != null) {

    while(node = nodes.pop()) {

      node.style.backgroundColor = COLOR_TICKETWIKI;

    }

  }



  // チケットのチェンジログの背景色を交互に変更

  path = '//*[@class="ticket"]//*[@class="change"]';

  if ( (nodes = $2(path) ) != null) {

    for (var i=0;i&lt;nodes.length;i++) {

      nodes[i].style.backgroundColor = 

        (i%2)? COLOR_TICKETLOG1:COLOR_TICKETLOG2;

    }

  }



  // 各wiki にて、機能追加

  path = '//textarea[@class="wikitext"]';

  if (( nodes = $2(path) ) != null) {

    while(node = nodes.pop()) {

      node.addEventListener('keypress', 

          function(e){

            var elm = e.target;

            if (e.altKey && e.keyCode == 13) {

              appendBR(elm);

            }

          }, false);



    }

  }



  // textarea にて、現在の位置に改行コードを挿入

  function appendBR(elm) {

    var end = elm.selectionEnd;

    elm.value = elm.value.substr(0, end) + BR + elm.value.substr(end);

    end = end + BR.length;

    elm.setSelectionRange(end, end);

  }



  // レポートのテーブルにソート機能を追加する

  path = '//*[@class="report"]//*[@class="listing tickets"]';

  if ( (nodes = $2(path) ) != null) {

    while(node = nodes.pop()) {

      registSortable(node);

    }

  }

  

  // 1つのテーブル毎の処理。th に clickイベントを登録。

  function registSortable(t) {

    var hs = t.getElementsByTagName("th");

    for (var i=0;i&lt;hs.length;i++) {

      var as = hs[i].getElementsByTagName("a");

      if ((as!=null)&&(as.length&gt;0)) {

        break;

      }

      hs[i].style.cursor = "pointer";

      hs[i].addEventListener('click',

          function(e) {

            var ths = this.parentNode.getElementsByTagName("th");

            for (var n=0;n&lt;ths.length;n++) {

               if (ths[n]==this) {break;}

            }

            var table = reverseSearch(this,"TABLE");

            tablesort(table,n);

          },false);

    }

  }



  // th から table を遡って検索

  function reverseSearch(e,tag) {

    var node = e.parentNode;

    while((node!=null)&&(node.tagName!=tag)) {

      node = node.parentNode;

    }

    return node;

  }



  // th をクリックした時のソート実処理

  function tablesort(t,c) {

    var tbs = t.getElementsByTagName("TBODY");

    if (tbs==null) return;

    var tb = tbs[0];

    for (var i=0;i&lt;tb.rows.length-1;i++) {

      var p = i;

      var v1 = getCellValue(tb,i,c);

      for (var j=i+1;j&lt;tb.rows.length;j++) {

        var v2 = getCellValue(tb,j,c);

        if (v1 &lt; v2) {

          p = j;

          v1 = v2;

        }

      }

      if (p != i) {

        tb.insertBefore(tb.rows[p],tb.rows[i]);

      }

    }

  }



  // セル内の値を取得する

  function getCellValue(tb,r,c) {

    td = tb.rows[r].cells[c];

    if (td == null) return "";

    ch = td.firstChild;

    if (ch == null) return "";

    if (ch.tagName == "A") {

      va = ch.firstChild.nodeValue;

    } else {

      va = ch.nodeValue;

    }

    if (va == null) return "";

    if (va.match(/^#(¥d+)/)) {

      va = RegExp.$1 - 0;

    }

    return va;

  }

})();


Trac | permalink | comments(0) | -

スポンサーサイト

- | permalink | - | -

この記事に対するコメント

コメントする