2012年10月6日 星期六

[網站日誌~JavaScript]樹狀選單

為了日後方便導覽,在正式開始寫文章之前,想要先有個選單,想說三層選單應該很夠用了,所以就開始策劃,因為要上班上課,再加上對JavaScript不熟,弄了一個禮拜才好,由於文章量不多,現在也無法看出什麼問題來,如果有問題日後再做修改,對樹狀選單有興趣的話,請按下面的繼續閱讀!

找了許多地方,看了許多部落格,發現用YUI (Yahoo! User Interface)的函式庫居多,尤其是這個網站講解的最多,原先想說複製貼上就好,但是卻不行,也懶得去了解為什麼不行,搞了幾天就放棄用複製貼上的方法,覺得自己全部從寫還來的快和方便,不過那個網站卻給我很好的出發點,YUI、JavaScript、JSON。

首先,我先去YUI的網站了解它的樹狀選單,然後小學一下JavaScript,要學寫網頁的話,w3schools是一個很好的網站,最後則是了解JSON的架構,還有Google Blogger的JSON Feed API,把下面的YourDomainName改成網域名稱就可以看到JSON Feed的資料了,點這裡看看本站的JSON Feed吧。

http://YourDomainName/feeds/posts/default?alt=json-in-script

等功課做夠了,就可以開始動工啦!先把需要的css和js準備好。
<link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.9.0/build/treeview/assets/skins/sam/treeview.css">
<script src="http://yui.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js" ></script>
<script src="http://yui.yahooapis.com/2.9.0/build/treeview/treeview-min.js" ></script>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
接著就開始獻醜啦,把想要的標籤加進去,順便也弄個中文的,這樣也方便閱讀,注意第二層標籤(level2Categories),我是用第一層標籤來做index。
  var level1Categories = new Array("Tech", "Life", "Invest");
  var level1CategoriesChinese = new Array("科技(Tech)", "生活(Life)", "投資(Invest)");

  var level2Categories = new Array();
  var level2CategoriesChinese = new Array();

  level2Categories[level1Categories[0]] = new Array("JavaScript");
  level2CategoriesChinese[level1Categories[0]] = new Array("JavaScript");

  level2Categories[level1Categories[1]] = new Array("Music");
  level2CategoriesChinese[level1Categories[1]] = new Array("音樂(Music)");

  level2Categories[level1Categories[2]] = new Array();
  level2CategoriesChinese[level1Categories[2]] = new Array();
標籤都有啦,再來就是建立樹狀選單啦,JaySLabelTree這個名稱後來會在div用到,otherNodes則是以防找不到選單的時候用的,第11行的level1CategoriesChinese[i]是顯示出來的選單,第12行的連結就只是搜尋那個標籤,第13行則是用那個標籤寫到title裡面,因為後來我用到其他(Others)title,所以為了一致,這裡也加上去。
  var tree = new YAHOO.widget.TreeView("JaySLabelTree");
  var root = tree.getRoot();

  var level1Nodes = new Array();
  var level2Nodes = new Array();

  var otherNodes = new Array();
  
  for (var i = 0; i < level1Categories.length; i++)
  {
    level1Nodes[i] = new YAHOO.widget.TextNode(level1CategoriesChinese[i], root, false);
    level1Nodes[i].href = "http://jays-nest.blogspot.com/search/label/" + level1Categories[i];
    level1Nodes[i].title = level1Categories[i];

    level2Nodes[i] = new Array();
    for (var j = 0; j < level2Categories[level1Categories[i]].length; j++)
    {
      level2Nodes[i][j] = new YAHOO.widget.TextNode(level2CategoriesChinese[level1Categories[i]][j], level1Nodes[i], false);
      level2Nodes[i][j].href = "http://jays-nest.blogspot.com/search/label/" + level2Categories[level1Categories[i]][j];
      level2Nodes[i][j].title = level2Categories[level1Categories[i]][j];
    }
  }
接著是最難最常最臭的一部分了,我會盡可能的切成好幾小段來講,先用json.feed.entry拿到所有的文章,然後對每個文章做循環,這樣才可以放到正確的目錄下。
  var posts = json.feed.entry;
  for (var i = 0; i < posts.length; i++)
  {
    // 接後面;
  }
然後存取現在這個文章節點的網址、標題、和所有標籤,
    var postURL;
    var postTitle;
    for (var j=0; j < posts[i].link.length; j++)
    {
      if (posts[i].link[j].rel == "alternate")
      {
        postURL = posts[i].link[j].href;
        postTitle = posts[i].link[j].title;
        break;
      }
    }

    var postLabels = new Array();
    for (var j = 0; j < posts[i].category.length; j++)
    {
      postLabels[j] = posts[i].category[j].term;
    }
有了文章的所有標籤,就可以找到第一層和第二層的標籤選單,當然這個前期是文章有第一層和第二層的標籤囉,我的JavaScript最起碼要有第一層標籤在文章裡,沒有的話,就當然不會出現在選單裡囉!

有了所有的標籤,當然要確認有沒有在選單裡啦,所以下面的函式可以幫我們找到那個選單,值得注意的是,我是用jQuery來找出是否有那個標籤,categories是選單,labels是標籤囉!
function GetLabel(categories, labels)
{
  for (var i = 0; i < categories.length; i++)
  {
    if ($.inArray(categories[i], labels) != -1)
    {
      return categories[i];
    }
  }
  return null;
}
重頭戲來啦,下面這部份就是真的把文章放到選單底下啦,一開始先確認網頁標題是否有包含文章標題,如果有的話,那就要展開選單,然後找第一層選單,找到的話就繼續,再來找第二層,找到就放到那層選單底下,找不到就增加其他(Others)選單來放,這時候要注意的是不能一直加入其他(Others)選單,所以這時候就要用title來做確認啦,新增之後也不要忘了放到之前的otherNodes,這樣其他未歸類的文章也可以找得到其他(Others)選單。
    var expandPost = false;
    if (document.title.indexOf(postTitle) != -1)
    {
      expandPost = true;
    }

    var level1Category = GetLabel(level1Categories, postLabels);
    var indexOflevel1Category = $.inArray(level1Category, level1Categories);
    if (indexOflevel1Category != -1)
    {
      var level2Category = GetLabel(level2Categories[level1Categories[indexOflevel1Category]], postLabels);

      var indexOfLavel2Category = $.inArray(level2Category, level2Categories[level1Categories[indexOflevel1Category]]);

      if (indexOfLavel2Category != -1)
      {
        var newPost = new YAHOO.widget.TextNode(postTitle, level2Nodes[indexOflevel1Category][indexOfLavel2Category], expandPost);
        newPost.href = postURL;

        if (expandPost)
        {
          newPost.parent.expand();
          newPost.parent.parent.expand();
        }
      }
      else
      {
        var currentChildrenTitles = new Array();
        for (var j = 0; j < level1Nodes[indexOflevel1Category].children.length; j++)
        {
          currentChildrenTitles[j] = level1Nodes[indexOflevel1Category].children[j].title;
        }

        if ($.inArray("Others", currentChildrenTitles) == -1)
        {
          var othersNode = new YAHOO.widget.TextNode("其他(Others)", level1Nodes[indexOflevel1Category], false);
          othersNode.title = "Others";
          otherNodes[indexOflevel1Category] = othersNode;
        }


        var newPost = new YAHOO.widget.TextNode(postTitle, otherNodes[indexOflevel1Category], false);
        newPost.href = postURL;

        if (expandPost)
        {
          newPost.parent.expand();
          newPost.parent.parent.expand();
        }
      }
    }
當然最重要的就是render出來,還有把render出來的東西放上來,注意class是yui-skin-sam,id是JaySLabelTree,src用之前的JSON連結,這樣就大功告成啦!
tree.render();
<div class="yui-skin-sam" id="JaySLabelTree">

  <script type="text/javascript" src="http://jays-nest.blogspot.com/feeds/posts/default?alt=json-in-script&callback=CreateTreeviewLabels"></script>

</div>
下面是完整的JavaScript,有興趣人的可以複製拿去用,Happy Blogging!

<!--
// Copyright (c) 2012, JayS NesT All rights reserved.
// http://jays-nest.blogspot.com/
-->
<script type="text/javascript">
function GetLabel(categories, labels)
{
  for (var i = 0; i < categories.length; i++)
  {
    if ($.inArray(categories[i], labels) != -1)
    {
      return categories[i];
    }
  }
  return null;
}

function CreateTreeviewLabels(json) 
{  
  var level1Categories = new Array("Tech", "Life", "Invest");
  var level1CategoriesChinese = new Array("科技(Tech)", "生活(Life)", "投資(Invest)");

  var level2Categories = new Array();
  var level2CategoriesChinese = new Array();

  level2Categories[level1Categories[0]] = new Array("JavaScript", "Network");
  level2CategoriesChinese[level1Categories[0]] = new Array("JavaScript", "網路(Network)");

  level2Categories[level1Categories[1]] = new Array("Music");
  level2CategoriesChinese[level1Categories[1]] = new Array("音樂(Music)");

  level2Categories[level1Categories[2]] = new Array();
  level2CategoriesChinese[level1Categories[2]] = new Array();



  var tree = new YAHOO.widget.TreeView("JaySLabelTree");
  var root = tree.getRoot();

  var level1Nodes = new Array();
  var level2Nodes = new Array();

  var otherNodes = new Array();
  
  for (var i = 0; i < level1Categories.length; i++)
  {
    level1Nodes[i] = new YAHOO.widget.TextNode(level1CategoriesChinese[i], root, false);
    level1Nodes[i].href = "http://jays-nest.blogspot.com/search/label/" + level1Categories[i];
    level1Nodes[i].title = level1Categories[i];

    level2Nodes[i] = new Array();
    for (var j = 0; j < level2Categories[level1Categories[i]].length; j++)
    {
      level2Nodes[i][j] = new YAHOO.widget.TextNode(level2CategoriesChinese[level1Categories[i]][j], level1Nodes[i], false);
      level2Nodes[i][j].href = "http://jays-nest.blogspot.com/search/label/" + level2Categories[level1Categories[i]][j];
      level2Nodes[i][j].title = level2Categories[level1Categories[i]][j];
    }
  }



  var posts = json.feed.entry;
  for (var i = 0; i < posts.length; i++)
  {
    var postURL;
    var postTitle;
    for (var j=0; j < posts[i].link.length; j++)
    {
      if (posts[i].link[j].rel == "alternate")
      {
        postURL = posts[i].link[j].href;
        postTitle = posts[i].link[j].title;
        break;
      }
    }

    var postLabels = new Array();
    for (var j = 0; j < posts[i].category.length; j++)
    {
      postLabels[j] = posts[i].category[j].term;
    }

    

    var expandPost = false;
    if (document.title.indexOf(postTitle) != -1)
    {
      expandPost = true;
    }

    var level1Category = GetLabel(level1Categories, postLabels);
    var indexOflevel1Category = $.inArray(level1Category, level1Categories);
    if (indexOflevel1Category != -1)
    {
      var level2Category = GetLabel(level2Categories[level1Categories[indexOflevel1Category]], postLabels);

      var indexOfLavel2Category = $.inArray(level2Category, level2Categories[level1Categories[indexOflevel1Category]]);

      if (indexOfLavel2Category != -1)
      {
        var newPost = new YAHOO.widget.TextNode(postTitle, level2Nodes[indexOflevel1Category][indexOfLavel2Category], expandPost);
        newPost.href = postURL;

        if (expandPost)
        {
          newPost.parent.expand();
          newPost.parent.parent.expand();
        }
      }
      else
      {
        var currentChildrenTitles = new Array();
        for (var j = 0; j < level1Nodes[indexOflevel1Category].children.length; j++)
        {
          currentChildrenTitles[j] = level1Nodes[indexOflevel1Category].children[j].title;
        }

        if ($.inArray("Others", currentChildrenTitles) == -1)
        {
          var othersNode = new YAHOO.widget.TextNode("其他(Others)", level1Nodes[indexOflevel1Category], false);
          othersNode.title = "Others";
          otherNodes[indexOflevel1Category] = othersNode;
        }


        var newPost = new YAHOO.widget.TextNode(postTitle, otherNodes[indexOflevel1Category], false);
        newPost.href = postURL;

        if (expandPost)
        {
          newPost.parent.expand();
          newPost.parent.parent.expand();
        }
      }
    }
  }

  tree.render();
}    
</script>






<div class="yui-skin-sam" id="JaySLabelTree">

<script type="text/javascript" src="http://jays-nest.blogspot.com/feeds/posts/default?alt=json-in-script&callback=CreateTreeviewLabels"></script>

</div>

6 則留言:

  1. 作者已經移除這則留言。

    回覆刪除
  2. 這麼一大堆,看不太懂意思!
    對我初學者太難了。
    不過,還是很感謝你的提供囉~。謝謝。

    回覆刪除
    回覆
    1. 基本上只有從"Copyright (c) 2012, JayS NesT All rights reserved."這裡開始才是我寫的,在最下面,其他的就只是函式庫而已,不用看

      刪除
  3. 耶~有了,沒想到全部複製、貼上,然後儲存成test.heml
    就看到跟你一樣,只差別中文亂碼而已。
    謝謝你。
    不好意思喔,再請問,要怎麼把這檔案,弄到google 的 blog
    就跟你這部落格一樣,只是我想要放在左邊。
    謝謝你囉~~

    回覆刪除
    回覆
    1. 基本上就把最後幾行的JSON改成你自己的網站http://YourDomainName/feeds/posts/default?alt=json-in-script

      然後在版面配置放JavaScript就好了
      http://imgur.com/a/RxF7W

      刪除
  4. 作者已經移除這則留言。

    回覆刪除