// Vimperator plugin: "Update Wassr" // Last Change: 19-Jan-2009. Jan 2008 // License: Creative Commons // Maintainer: mattn - http://mattn.kaoriya.net/ // Based On: twitter.js by Trapezoid // // The script allows you to update Wassr status from Vimperator 0.6.*. // // Commands: // :wassr some thing text // post "some thing text" to wassr. // :wassr! someone // show someone's statuses. // :wassr!? someword // show search result of 'someword' from "http://labs.ceek.jp/wassr/". // :wassr!@ // show replies. // :wassr!+ someone // fav someone's last status.. mean put iine. // :wassr!- someone // un-fav someone's last status.. mean remove iine. // :wassr -footmark // show footmarks. // :wassr -todo // show your todos. // :wassr -todo+ some thing text // add 'some thing text' to your todo. // :wassr -todo- todo-id // remove todo which id is todo-id. // :wassr -todo* todo-id // start todo which id is todo-id. // :wassr -todo/ todo-id // stop todo which id is todo-id. // :wassr -todo! todo-id // done todo which id is todo-id. (function(){ var passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); var evalFunc = window.eval; try { var sandbox = new Components.utils.Sandbox("about:blank"); if (Components.utils.evalInSandbox("true", sandbox) === true) { evalFunc = function(text) { return Components.utils.evalInSandbox(text, sandbox); } } } catch(e) { liberator.log('warning: wassr.js is working with unsafe sandbox.'); } function sprintf(format){ var i = 1, re = /%s/, result = "" + format; while (re.test(result) && i < arguments.length) result = result.replace(re, arguments[i++]); return result; } function emojiConv(str){ return str.replace(/[^*+.-9A-Z_a-z-]/g,function(s){ var c = s.charCodeAt(0); return (0xE001 <= c && c <= 0xF0FC) ? '' : s; }) } function sayWassr(username, password, stat){ var xhr = new XMLHttpRequest(); xhr.open("POST", "http://api.wassr.jp/statuses/update.json", false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send("status=" + encodeURIComponent(stat) + "&source=" + encodeURIComponent("vimperator/wassr.js")); } function showFollowersStatus(username, password, target){ var xhr = new XMLHttpRequest(); var endPoint = target ? "http://api.wassr.jp/user_timeline.json?id=" + target : "http://api.wassr.jp/statuses/friends_timeline.json?id=" + username; xhr.open("GET", endPoint, false, username, password); xhr.setRequestHeader("User-Agent", "XMLHttpRequest"); // for debug //xhr.open("GET", "http://api.wassr.jp/statuses/user_timeline/otsune.json", false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); var statuses = evalFunc(xhr.responseText) || []; var html = .toSource() .replace(/(?:\r?\n|\r)[ \t]*/g, " ") + statuses.map(function(status) <> {status.user.screen_name} {status.user_login_id}‬ .toSource() .replace(/(?:\r?\n|\r)[ \t]*/g, " ") + sprintf(': %s‬', status.html)) .join("
"); liberator.echo(html, true); } function favWassr(username, password, user){ var xhr = new XMLHttpRequest(); xhr.open("POST", "http://api.wassr.jp/user_timeline.json?id=" + user, false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); xhr.open("POST", "http://api.wassr.jp/favorites/create/" + evalFunc(xhr.responseText)[0].rid + ".json", false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); } function unfavWassr(username, password, user){ var xhr = new XMLHttpRequest(); xhr.open("POST", "http://api.wassr.jp/user_timeline.json?id=" + user, false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); xhr.open("POST", "http://api.wassr.jp/favorites/destroy/" + evalFunc(xhr.responseText)[0].rid + ".json", false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); } function showWassrReply(username, password){ var xhr = new XMLHttpRequest(); xhr.open("POST", "http://api.wassr.jp/statuses/replies.json", false, username, password); xhr.setRequestHeader("User-Agent", "XMLHttpRequest"); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); var statuses = evalFunc(xhr.responseText); var html = .toSource() .replace(/(?:\r?\n|\r)[ \t]*/g, " ") + statuses.map(function(status) <> {status.user.screen_name} {status.user_login_id}‬ .toSource() .replace(/(?:\r?\n|\r)[ \t]*/g, " ") + sprintf(': %s‬', status.html)) .join("
"); //liberator.log(html); liberator.echo(html, true); } function showWassrSearchResult(word){ var xhr = new XMLHttpRequest(); xhr.open("GET", "http://labs.ceek.jp/wassr/rss?k=" + encodeURIComponent(word), false); xhr.send(null); var items = xhr.responseXML.getElementsByTagName('item'); var html = .toSource() .replace(/(?:\r?\n|\r)[ \t]*/g, " ");
// ==VimperatorPlugin==
// @name           Div Scroller
// @description-ja スクロールができる div 要素などでスクロールする
// @license        Creative Commons 2.1 (Attribution + Share Alike)
// @version        0.1
// ==/VimperatorPlugin==
//
//  Mappings:
//    ]d [d
//      スクロール対象を変更
//      ]f [f のようなもの
//    <Leader>j <Leader>k
//      スクロールする
//
//  TODO:
//    フレーム対応

(function () {

  // スクロール可能か?
  function isScrollable (elem) {
    const re = /auto|scroll/i;
    let s = elem.ownerDocument.defaultView.getComputedStyle(elem, '');
    if (elem.scrollHeight <= elem.clientHeight)
      return false;
    return ['overflow', 'overflowY', 'overflowX'].some(function (n)
      s[n] && re.test(s[n]));
  }

  // 光らせる
  function flashElement (elem) {
    let indicator = elem.ownerDocument.createElement('div');
    let rect = elem.getBoundingClientRect();
    indicator.id = 'nyantoro-element-indicator';
    let style = 'background-color: blue; opacity: 0.5; z-index: 999;' +
                'position: fixed; ' +
                'top: ' + rect.top + 'px;' +
                'height:' + elem.clientHeight + 'px;'+
                'left: ' + rect.left + 'px;' +
                'width: ' + elem.clientWidth + 'px';
    indicator.setAttribute('style', style);
    elem.appendChild(indicator);
    setTimeout(function () elem.removeChild(indicator), 500);
  }

  // スクロール可能な要素のリストを返す
  function scrollableElements () {
    let result = [];
    let doc = content.document;
    let r = doc.evaluate('//div|//ul', doc, null, 7, null)
    for (let i = 0, l = r.snapshotLength; i < l; i++) {
      let elem = r.snapshotItem(i);
      if (isScrollable(elem))
        result.push(elem);
    }
    return result;
  }

  // スクロール対象を変更
  function shiftScrollElement (n) {
    let doc = content.document;
    let idx = doc.__div_scroller_index || 0;
    let es = scrollableElements();
    if (es.length <= 0)
      liberator.echoerr('scrollable element not found');
    idx += (n || 1);
    if (idx < 0)
      idx = es.length - 1;
    if (idx >= es.length)
      idx = 0;
    content.document.__div_scroller_index = idx;
    flashElement(es[idx]);
  }

  // 現在のスクロール対象を返す
  function currentElement () {
    let es = scrollableElements();
    let idx = content.document.__div_scroller_index || 0;
    return es[idx];
  }

  // スクロールする
  function scroll (down) {
    let elem = currentElement();
    if (elem)
      elem.scrollTop += Math.max(30, elem.clientHeight - 20) * (down ? 1 : -1);
  }


  mappings.addUserMap(
    [modes.NORMAL],
    ['<Leader>j'],
    'Scroll down',
    function () scroll(true)
  );

  mappings.addUserMap(
    [modes.NORMAL],
    ['<Leader>k'],
    'Scroll up',
    function () scroll(false)
  );

  mappings.addUserMap(
    [modes.NORMAL],
    [']d'],
    'Shift Scroll Element',
    function () shiftScrollElement(1)
  );

  mappings.addUserMap(
    [modes.NORMAL],
    ['[d'],
    'Shift Scroll Element',
    function () shiftScrollElement(-1)
  );


})();