Ustream.tvビューア

UTMCの後輩の間でUstream.tvという動画ストリーミング・サービスでWindowsデスクトップや現実のデスクトップを晒し合うのが流行ってたので,割り込んでjQueryというJavaScriptライブラリを使ったビューアを書いてみた... と言うか,先週末から1週間かけて書いてた.もちろん,平日はほとんど時間が取れなかったけど.

メモ:

以下,ソース.開発者キーがHTMLソース内に直書きされてるのでサンプルをthe Internetに公開する訳には行かない.開発者キーはhttp://developer.ustream.tv/ に登録すると貰える.jQuery UIではsortableのみを使っており,jQuery UIのダウンロード・ページが提供するカスタマイズ機能でsortable関連部分だけを含むソースを生成して使った.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
<!-- vim: set ts=2 sts=2 sw=2 tw=0 fdm=marker: -->
<!-- $Id: $ -->
<html lang="ja">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta name="author" content="flatline @ UTMC" />
    <title>Ustream Viewer</title>
    <meta name="keyword" lang="ja" content="ustream.tv jquery ajax" />
    <meta name="description" content="複数のUstream Showを一覧で見る" />
    <link href="ustream.css" rel="stylesheet" title="default" type="text/css" />
    <script type="text/javascript" src="jquery-1.2.6.js"></script>
    <script type="text/javascript" src="jquery.cookie.js"></script>
    <script type="text/javascript" src="jquery-ui-personalized-1.6rc2.packed.js"></script>
    <script type="text/javascript" src="jquery.timers-1.0.0.js"></script>
    <script type="text/javascript">
      <!--
    function a(v) {
      var c = $.cookie("a");
      if (c) {
        var a = unescape(c);
        if (! a.match(v)) {
          while (true) {
            var b = a + "," + v;
            var e = escape(b);
            if (e.length > 4094) {
              a = a.replace(/[^,]*,/, "");
            }
            else {
              $.cookie("a", b, {expires:365});
              break;
            }
          }
        }
      }
      else {
        $.cookie("a", v);
      }
    }
    function d(u) {
      var x = 0;
      $("ul#m li").each(function() {
          if ($(this).attr("id").replace(/_\d+_l$/, "") == u) x += 1;
        });
      if (x == 1) {
        var c = $.cookie("a");
        if (c) {
          var a = unescape(c).split(/,/);
          var b = new Array(a.length-1);
          for (var i=0,j=0; i<a.length; i+=1) {
            var x = a[i];
            if (x != u) {
              b[j] = x;
              j += 1;
            }
          }
          $.cookie("a", b.join(","), {expires:365});
        }
      }
    }
    function f(e) {
      e.preventDefault();
      var l = e.data;
      var u = l.attr("id").replace(/_\d+_l$/, "");
      d(u);
      l.fadeOut("slow", function() { l.remove(); });
    }
    function h(e) {
      e.preventDefault();
      var u = $(this).attr("id").replace(/_\d+_r/, "");
      var a = $.trim($("#d").html().replace(/<[^>]+>/g, "")).split(/\s+/);
      var b = false;
      jQuery.each(a, function(i, v) { b = b || (v == u); } );
      if (b) {
        $(this).remove();
      }
      else {
        a.push(u);
        var s = '<?xml version="1.0" encoding="utf-8"?>\n<ul>\n' +
          $.map(a, function(e) { return "<li>" + e + "</li>"; } ).join("\n") +
          "\n</ul>\n";
        (function(b) {
          $.ajax({ type:"PUT", url:"default.xml", data:s, dataType:"text",
                   success:function(x, r) {
                     if (r == "success") {
                       b.remove();
                       $("#d ul").append("<li>" + u + "</li>");
                     }
                   }
          });
        })($(this));
      }
    }
    function g(v, b) {
      var w = v + "_" + c;
      c += 1;
      $.getJSON("http://api.ustream.tv/json/user/" + v +
        "/listAllChannels?key=(開発者キー)&callback=?",
        function(j) {
          if (j == null) {
            alert("そのようなユーザは存在しません.");
            return;
          }
          var s = $.map(j, function(e) {
            var ed = e.description;
            return e.title.replace(/(.)/g, "$1&#x200B;") + // word-wrap:break-word; の代わり
            (ed != null && ed != "" ? " (" + ed + ")" : "") +
            (e.status == "live" ?
             "\n" + e.embedTag.replace(/width="320"/g, 'width="160"')
             .replace(/height="260"/g, 'height="130"')
             : " : オフライン") }).join("<br>\n");
          $("#m").append('<li id="' + w + '_l">' +
            s + ' <br><input type="submit" value="削除" id="' + w + '_d">' +
            (b ? '<input type="submit" value="ワンタッチに登録" id="' +
            w + '_r">' : "") + '</li>');
          var l = $("#" + w + "_l");
          $("#" + w + "_d").bind("click", l, f);
          $("#" + w + "_r").bind("click", h);
          l.fadeIn("slow");
          a(v);
        });
    }
    $(document).ready(function() {
      $("#m").sortable({});
      $("#a").click(function(e) {
        e.preventDefault();
        var u = $("#u");
        var v = u.val();
        u.val("");
        var b = true;
        $("#d ul li").each(function() { b = b && ($(this).text() != e); });
        g(v, b);
      });
      $("#c").click(function(e) {
        e.preventDefault();
        $.cookie("a", null);
      });
      $("#d").load("default.xml", function() {
          $("#d ul li").click(function() { g($(this).text()); });
          var c = $.cookie("a");
          if (c) {
            var a = unescape(c).split(/,/);
            var l = $("#d ul li");
            for (var i=0; i<a.length; i+=1) {
              var e = a[i], b = true;
              l.each(function() { b = b && ($(this).text() != e); });
              (function(i, e, b) {
                $(this).oneTime(100+i*1500, function() { g(e, b); });
              })(i, e, b);
            }
          }
        });
    });
    var c=0;
    // -->
    </script>
  </head>

  <body>
    <h1><a href="http://ustream.tv/">Ustream</a> Viewer</h1>

    <ul id="m"></ul>

    <hr>

    <p id="p">ワンタッチID(サイトグローバル)</p>
    <div id="d"></div>

    <form action= "#">
      <input type="text" id="u" size="15">
      <input type="submit" value="メンバーをIDで追加" id="a">
    </form>

    <input type="submit" value="デフォルト表示メンバー(Cookie)の消去" id="c">

    <address>
      flatline @ UTMC
    </address>
  </body>
</html>
ul {
    list-style:none;
    margin:0px;
    padding:0px;
}
ul#m li {
    display:none;
    float:left;
    width:160px;
    border:blue solid thin;
    padding:0px;
    word-wrap:break-word; /* IE,CSS3 */
}
p#p {
    display:inline;
}
div#d {
    display:inline;
}
div#d ul {
    display:inline;
}
div#d ul li {
    display:inline;
    text-decoration:underline;
    cursor:pointer;
    margin:0px 0.5ex;
}
hr {
    clear:both;
}
<?xml version="1.0" encoding="utf-8"?>
<ul>
<li>SFShiba</li>
<li>ObamaForAmerica</li>
</ul>