summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--css/news.css357
-rw-r--r--index.php2
-rw-r--r--js/main.js96
-rw-r--r--js/menu.js683
-rw-r--r--js/news.js50
-rw-r--r--templates/main.php12
-rw-r--r--templates/part.feeds.php47
-rw-r--r--templates/part.listfeed.php17
-rw-r--r--templates/part.listfolder.php23
9 files changed, 515 insertions, 772 deletions
diff --git a/css/news.css b/css/news.css
index 595d13fdf..730fa6039 100644
--- a/css/news.css
+++ b/css/news.css
@@ -59,286 +59,222 @@ div.add_parentfolder {
}
/* feed/folder list */
-#leftcontent {
+#leftcontent_news {
width: 20em;
margin: 0;
- z-index: 0;
+ height: 100%;
position: relative;
overflow: hidden;
- top: 0;
- bottom: 0;
+ border-right: 1px solid #ccc;
+ background-color: #f8f8f8;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
}
-#feeds {
+#feed_wrapper {
background-color: #f8f8f8;
- position: absolute;
+ position: relative;
top: 0;
- bottom: 2.8em;
- left: 0;
- right: 0;
+ height: 100%;
+ padding-bottom: 2.8em;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
+#feeds {
+ height: 100%;
+ overflow: auto;
+}
+
#feeds > ul {
height: 100%;
- overflow: auto;
+ overflow-x: hidden;
}
-
+
.dnd_over {
- -moz-transition: background-color 200ms ease 0s;
- transition: background-color 200ms ease 0s;
- background-color: #d0d0d0! important;
+ -moz-transition: padding-bottom 500ms ease 0s;
+ transition: padding-bottom 500ms ease 0s;
+ }
+
+ #feeds > ul.dnd_over {
+
}
.dnd_over > ul {
- padding-bottom: 2.5em;
- -moz-transition: padding-bottom 500ms ease 0s;
- transition: padding-bottom 500ms ease 0s;
+ padding-bottom: 2.5em! important;
+
}
+ #feeds > ul ul.dnd_over {
+ padding-bottom: 2.5em !important;
+ }
- #feeds .folder {
- box-sizing: border-box;
- -moz-box-sizing: border-box;
- padding: .5em 0 .5em 2.5em !important;
- background-color: #dfdfdf !important;
- font-weight: bold ;
- border-bottom: 1px solid #bbb !important;
- position: relative;
- z-index: 1;
+ .all_read {
+ font-weight: normal;
}
- #feeds .folder a {
- float: none;
- display: inline-block;
- position: relative;
+
+ #feeds .buttons {
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ display: none;
+ }
+
+ #feeds .buttons button {
+ margin: .65em .3em 0 0;
+ background-position: center;
+ background-repeat: no-repeat;
}
- #feeds .folder:hover {
- background-color: #d0d0d0 !important;
- -moz-transition: background-color 200ms ease 0s;
- transition: background-color 200ms ease 0s;
+ #feeds li:hover > .buttons {
+ display: block;
}
- #feeds .subscriptions, #feeds .subscriptions:hover {
- background-image: url('%appswebroot%/news/img/rss.svg');
- background-repeat: no-repeat;
- background-size: 16px 16px;
- background-position: .8em center;
+ #feeds .buttons button.feeds_delete {
+ background-image: url('%webroot%/core/img/actions/delete.svg');
+ }
+
+ #feeds .buttons button.feeds_edit {
+ background-image: url('%webroot%/core/img/actions/rename.svg');
+ }
+
+ #feeds .buttons button.feeds_markread {
+ background-image: url('%appswebroot%/news/img/mark_read.svg');
+ }
+
+ #feeds button.collapsable_trigger {
+ position: absolute;
+ left: .5em;
+ top: .4em;
+ background: none;
+ background-image: url('%webroot%/core/img/actions/triangle-s.svg');
+ border: none;
+ border-radius: 0;
+ outline: none !important;
+ box-shadow: none;
+ -moz-box-shadow: none;
+ display: none;
}
- #feeds .starred, #feeds .starred:hover {
- background-image: url('%appswebroot%/news/img/starred.svg');
- background-repeat: no-repeat;
- background-size: 16px 16px;
- background-position: .8em center;
-
+ #feeds button.collapsable_trigger.triggered {
+ -moz-transform: rotate(-90deg);
+ transform: rotate(-90deg);
}
- #feeds .subscriptions a, #feeds .starred a {
- display: inline-block;
- width: 75%;
+ #feeds .folder.collapsable:hover button.collapsable_trigger {
+ display: block;
}
- #feeds li.feed {
- position: relative;
+ #feeds li {
+ border-bottom: 1px solid #bbb;
+ padding: 0 .5em;
+ background-color: #dfdfdf;
+ font-weight: bold ;
box-sizing: border-box;
-moz-box-sizing: border-box;
- border-bottom: 1px solid #ccc;
- padding-left: 2.5em;
- -moz-transition: background-color 200ms ease 0s;
- transition: background-color 200ms ease 0s;
- background-color: #f1f1f1;
- z-index: 1;
- background-size:16px 16px;
- background-repeat: no-repeat;
- background-position: .8em center;
+ width: 100%;
+ position: relative;
}
-
- #feeds li.feed a {
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- text-align: left;
- width: 85%;
- font-weight: bold;
- }
-
- #feeds li.feed a.all_read, #feeds .all_read {
- font-weight: normal;
- }
- #feeds li#selected_feed {
- background-color: #ffffff !important;
- font-style: oblique;
- }
+ #feeds li#selected_feed {
+ background-color: #ffffff !important;
+ font-style: oblique;
+ }
- #feeds li.feed.updating {
- padding-right: 21px;
- background-image: url('%webroot%/core/img/loader.gif');
+ #feeds li a.title {
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ width: 100%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ display: block;
+ padding-left: 2em;
background-size: 16px 16px;
background-repeat: no-repeat;
- background-position: right center;
+ background-position: .2em center;
+ line-height: 2.5em;
}
-
- #feeds li.feed:hover {
- background-color: #ddd;
- }
-
- #feeds li.feed .feeds_delete,
- #feeds li.feed .feeds_edit {
- display: none;
- border: none;
- }
-
- #feeds li.feed:hover .unreaditemcounter {
- display: none;
- }
- #feeds li.feed:hover .feeds_delete,
- #feeds li.feed:hover .feeds_edit,
- #feeds .collapsable:hover .feeds_delete,
- #feeds .collapsable:hover .feeds_edit {
- display: inline-block;
+ #feeds li:hover > a.title {
+ width: 75%;
}
- #feeds .feeds_delete {
- position: absolute;
- right: 0.2em;
- background: url('%webroot%/core/img/actions/delete.svg') no-repeat center;
- display: none;
- padding: 0;
- margin: -8px 0 0 0;
- top: 50%;
- }
-
- #feeds .feeds_edit {
- position: absolute;
- right: 1.6em;
- background: url('%webroot%/core/img/actions/rename.svg') no-repeat center;
- display: none;
- padding: 0;
- margin: -8px 0 0 0;
- top: 50%;
- }
-
- #feeds .unreaditemcounter {
- position: relative;
- top: .3em;
- right: .3em;
- background: #5E5E5E;
- border-radius: 5px;
- padding: 2px 5px;
- color: white;
- text-align: center;
- font-weight: normal;
- margin: 0;
- display: none;
+ #feeds .starred a.title {
+ background-image: url('%appswebroot%/news/img/starred.svg');
}
-
- #feeds .unreaditemcounter.all_read {
- display: none !important;
- }
- #feeds li.collapsable_container {
- background-color: #dfdfdf;
- font-weight: bold;
- padding: 0;
- border: 0;
- border-bottom: 1px solid #bbb;
- position: relative;
- z-index: 1;
+ #feeds .subscriptions a.title {
+ background-image: url('%appswebroot%/news/img/rss.svg');
}
- #feeds li.collapsable_container.open {
- background-image: linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%);
- background-image: -o-linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%);
- background-image: -moz-linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%);
- background-image: -webkit-linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%);
- background-image: -ms-linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%);
- font-weight: bold;
- padding: 0;
- border: 0;
- border-bottom: 1px solid #bbb;
- border-top: 1px solid #bbb;
- -webkit-box-shadow: inset 0 0 5px -1px #bbb;
- box-shadow: inset 0 0 5px -1px #bbb;
- }
+ #feeds .feed {
+ border-bottom: 1px solid #ccc;
+ background-color: #f1f1f1;
+ }
- #feeds li.collapsable_container:hover {
- background-color: #d0d0d0;
- -moz-transition: background-color 200ms ease 0s;
- transition: background-color 200ms ease 0s;
- }
-
+ #feeds .feed:hover {
+ background-color: #ddd;
+ }
+ #feeds .folder {
+ padding: 0 .5em;
+ }
- #feeds li.collapsable_container.open > ul {
- margin: 0 8px 8px 8px;
- position: relative;
- z-index: 1;
+ #feeds .folder:hover, #feeds .starred:hover, #feeds .subscriptions:hover {
+ background-color: #d0d0d0;
}
- #feeds li.collapsable_container > ul > li {
- border: 1px solid #ccc;
- border-bottom: 0;
- }
-
- #feeds li.collapsable_container > ul > li:last-child {
- border: 1px solid #ccc;
- }
-
- #feeds div.collapsable {
- position: relative;
- z-index: 1;
- border-radius: 5px;
+ #feeds .folder a.title {
+ background-image: url('%webroot%/core/img/places/folder.svg');
}
-
- #feeds .collapsable_trigger {
- border: none ;
- margin: 0 0 0 .8em;
- padding: 0;
- border-radius: 0;
- box-shadow: none;
- vertical-align: middle !important;
- background: url('%webroot%/core/img/places/folder.svg') no-repeat;
- outline: none;
- opacity: 1;
+ #feeds .folder.collapsable:hover a {
+ background-image: none;
}
- #feeds .collapsable_container:hover .collapsable_trigger.triggerable {
- background-image: url('%webroot%/core/img/actions/triangle-s.svg');
- -moz-transform: none;
- transform: none;
- }
+ #feeds .folder.collapsable.open {
+ background-image: linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%),
+ background-image: url('%webroot%/core/img/places/folder.svg');
+ background-image: -o-linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%),
+ background-image: url('%webroot%/core/img/places/folder.svg');
+ background-image: -moz-linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%),
+ background-image: url('%webroot%/core/img/places/folder.svg');
+ background-image: -webkit-linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%),
+ background-image: url('%webroot%/core/img/places/folder.svg');
+ background-image: -ms-linear-gradient(bottom, rgb(208,208,208) 0%, rgb(222,222,222) 100%),
+ background-image: url('%webroot%/core/img/places/folder.svg');
+ border-bottom: 1px solid #bbb;
+ border-top: 1px solid #bbb;
+ -webkit-box-shadow: inset 0 0 5px -1px #bbb;
+ box-shadow: inset 0 0 5px -1px #bbb;
+ padding-bottom: .5em;
+ }
- #feeds .collapsable_container:hover .collapsable_trigger.triggered {
- background-image: url('%webroot%/core/img/actions/triangle-s.svg');
- -moz-transform: rotate(-90deg);
- transform: rotate(-90deg);
+ #feeds .folder.collapsable.open ul {
+ border: 1px solid #ccc;
}
-
- #feeds .collapsable_title {
- padding: .5em 0 .5em .5em;
- line-height: 1.5em;
- float: none;
- display: inline-block;
- position: relative;
+
+ #feeds .folder.open ul li:last-child {
+ border-bottom: 0;
}
/* feed settings */
#feed_settings {
padding: 0;
- bottom: 0px;
+ bottom: 0;
overflow:visible;
height:2.8em;
width: 20em;
margin:0;
+ z-index: 2;
background:#eee;
- border-top:1px
- solid #ccc;
+ border-top: 1px solid #ccc;
+ border-right: 1px solid #ccc;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
position:fixed;
}
@@ -410,6 +346,7 @@ div.add_parentfolder {
background:-o-linear-gradient(#DCDCDC, #EEEEEE);
background:linear-gradient(#DCDCDC, #EEEEEE);
position:fixed;
+ z-index: 6;
margin-left: 0;
bottom: 2.8em;
border-left:1px solid #ccc;
diff --git a/index.php b/index.php
index 3a42ff5ac..fccc2b1c8 100644
--- a/index.php
+++ b/index.php
@@ -17,7 +17,9 @@ OCP\User::checkLoggedIn();
OCP\App::checkAppEnabled('news');
OCP\App::setActiveNavigationEntry('news');
+OCP\Util::addScript('news','main');
OCP\Util::addScript('news','news');
+OCP\Util::addScript('news','menu');
OCP\Util::addScript('news','jquery.timeago');
OCP\Util::addScript('news','jquery.onscreen');
diff --git a/js/main.js b/js/main.js
new file mode 100644
index 000000000..b6d21a5b2
--- /dev/null
+++ b/js/main.js
@@ -0,0 +1,96 @@
+/**
+* ownCloud - News app
+*
+* @author Bernhard Posselt
+* Copyright (c) 2012 - Bernhard Posselt <nukeawhale@gmail.com>
+*
+* This file is licensed under the Affero General Public License version 3 or later.
+* See the COPYING-README file
+*
+*/
+
+
+var News = News || {};
+
+$(document).ready(function(){
+
+ // basic setup
+ News.Feed.updateAll();
+ var updateInterval = 200000; //how often the feeds should update (in msec)
+ setInterval('News.Feed.updateAll()', updateInterval);
+
+ // bind listeners on the menu
+ var menu = new News.Menu(false);
+ menu.bindOn('#feeds ul');
+
+
+ /* first run script begins */
+ $('#browsebtn_firstrun, #cloudbtn_firstrun, #importbtn_firstrun').hide();
+
+ /* first run script ends */
+
+ $('#addfeed').click(function() {
+ News.UI.overview('#addfeed_dialog','feeddialog.php');
+ });
+
+ $('#addfeedbtn').click(function() {
+ $(this).hide();
+ $('#addfeed_dialog_firstrun').show();
+ });
+
+ $('#addfolder').click(function() {
+ News.UI.overview('#addfolder_dialog','folderdialog.php');
+ });
+
+ $('#addfeedfolder').click(function(event) {
+ News.DropDownMenu.fade($(this).children('ul'));
+ event.stopPropagation();
+ });
+
+ $('#settingsbtn').on('click keydown', function() {
+ try {
+ OC.appSettings({appid:'news', loadJS:true, cache:false});
+ } catch(e) {
+ alert(e);
+ }
+ });
+
+ $('#view').click(function(){
+ var term;
+ if($(this).hasClass('show_all')){
+ term = 'unread';
+ $(this).addClass('show_unread').removeClass('show_all');
+ } else {
+ term = 'all';
+ $(this).addClass('show_all').removeClass('show_unread');
+ }
+ News.Feed.filter(term);
+ });
+
+ // mark items whose title was hid under the top edge as read
+ // when the bottom is reached, mark all items as read
+ $('#feed_items').scroll(function(){
+ var boxHeight = $(this).height();
+ var scrollHeight = $(this).prop('scrollHeight');
+ var scrolled = $(this).scrollTop() + boxHeight;
+ var scrollArea = this;
+ $(this).children('ul').children('.feed_item:not(.read)').each(function(){
+ var item = this;
+ var itemOffset = $(this).position().top;
+ if(itemOffset <= 0 || scrolled >= scrollHeight){
+ // wait and check if the item is still under the top edge
+ setTimeout(function(){ markItemAsRead(scrollArea, item);}, 1000);
+ }
+ })
+
+ });
+
+ $('#feed_items').scrollTop(0);
+
+ $(document).keydown(function(e) {
+ if ((e.keyCode || e.which) == 74) { // 'j' key shortcut
+
+ }
+ });
+
+});
diff --git a/js/menu.js b/js/menu.js
index 32d528156..19a869e35 100644
--- a/js/menu.js
+++ b/js/menu.js
@@ -18,79 +18,11 @@
* HOWTO
*
-We create a new instance of the menu. The first argument is its class.
-
- var menu = new News.Menu('feedlist');
-
-
-To fill it with items we use JSON. Hint: If no icons are given, default icons
-are being used. A typical JSON array would look like this:
-
- var menuStructure = [
- {
- id: 1,
- title: 'New Articles',
- type: News.MenuNodeType.New,
- children: [],
- unreadCount: 4,
- },
- {
- id: 1,
- title: 'Starred',
- type: News.MenuNodeType.Starred,
- children: [],
- unreadCount: 1,
- },
- {
- id: 1,
- title: 'hi',
- type: News.MenuNodeType.Folder,
- unreadCount: 7,
- children: [
- {
- id: 2,
- title: 'hi too',
- type: News.MenuNodeType.Feed,
- unreadCount: 4,
- children: [],
- icon: '/test/test.png'
- },
- {
- id: 2,
- title: 'hi 3',
- type: News.MenuNodeType.Feed,
- children: [],
- unreadCount: 3,
- },
- ]
- },
- {
- id: 4,
- title: 'hi 4',
- type: News.MenuNodeType.Feed,
- children: [],
- unreadCount: 1,
- },
- {
- id: 114,
- title: 'hi 3',
- type: News.MenuNodeType.Folder,
- children: [],
- unreadCount: 1,
- },
- ];
-
- menu.populateFromJSON(menuStructure, menu);
-
-
-Now that the menu is populated, we can render, append it into the place we'd
-like to and select the current selected item
-
- $('#leftcontent').append(menu.render());
- var selectedType = News.MenuNodeType.Feed;
- var selectedId = 3;
- menu.setSelected(selectedType, selectedId);
+We create a new instance of the menu. Then we need to bind it on an ul which contains
+all the items:
+ var menu = new News.Menu();
+ menu.bindOn('#feeds ul');
Updating nodes (you dont have to set all values in data):
@@ -164,16 +96,15 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
'Feed': 0,
'Folder': 1,
'Starred': 2,
- 'New': 3
+ 'Subscriptions': 3
}
- // TODO: set paths for icons
- MenuNodeTypeDefaultIcon = {
- 'Feed': '',
- 'Folder': '',
- 'Starred': '',
- 'New': ''
- }
+ // map css classes to MenuNodeTypes
+ MenuNodeTypeClass = {};
+ MenuNodeTypeClass[MenuNodeType.Feed] = 'feed';
+ MenuNodeTypeClass[MenuNodeType.Folder] = 'folder';
+ MenuNodeTypeClass[MenuNodeType.Starred] = 'starred';
+ MenuNodeTypeClass[MenuNodeType.Subscriptions] = 'subscriptions';
News.MenuNodeType = MenuNodeType;
@@ -183,255 +114,248 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
*#########################################################################/
/**
* This is the basic menu used to construct and maintain the menu
- * @param cls the css class of the element
+ * @param showAll if all items should be shown by default
*/
- Menu = function(cls){
- this._class = cls;
- this._children = [];
- this._parent = false;
- this._id = 0;
- this._$htmlElement = $('<ul>');
- this._$htmlElement.attr('data-id', this._id);
- this._bindDroppable(this._$htmlElement);
- this._selectedNode = undefined;
- this._showAll = false;
+ Menu = function(showAll){
+ this._showAll = showAll;
+ this._unreadCount = {
+ Feed: {},
+ Folder: {},
+ Starred: 0,
+ Subscriptions: 0
+ };
}
News.Menu = Menu;
/**
- * Attaches a MenuNode to a node and renders it in the dom
- * @param parentType the type of the parent node
- * @param parentId the id of the parent node, if 0 the top menu is used
- * @param node the MenuNode that should be created
+ *
*/
- Menu.prototype.createNode = function(parentType, parentId, node){
- var parentNode = this._findNode(parentType, parentId);
- parentNode._addChildNode(node);
- parentNode._$htmlElement.append(node.render());
+ Menu.prototype.removeNode = function(type, id){
+
}
/**
- * Recursively remove all occurences of the node from the dom and
- * from the datastructure
- * @param type the type of the node (MenuNodeType)
- * @param id the id of the node
- * @param removeDom if true, also remove the dom
- * @return the childelemnt or undefined if not found
+ * A node can only be added to a folder or to the root
*/
- Menu.prototype.removeNode = function(type, id, removeDom){
- for(var i=0; i<this._children.length; i++){
- var child = this._children[i];
- if(child._type === type && child._id === id){
- var nodeIndex = i;
- // if we have children, we need to remove their
- // html from the dom first then we need to
- if(removeDom){
- child._$htmlElement.remove();
- }
- this._children.splice(nodeIndex, 1);
- return child;
- } else {
- var child = child.removeNode(type, id);
- if(child !== undefined){
- return child;
- }
- }
- }
- return undefined;
+ Menu.prototype.addNode = function(parentId, type, id, data){
+
}
/**
- * Updates a node in the menu
- * @param type the type of the node (MenuNodeType)
- * @param id the id of the node
- * @param data the data array like {title: 'title', unreadCount: 1, icon: 'path/icon.png'}
+ *
*/
Menu.prototype.updateNode = function(type, id, data){
- var node = this._findNode(type, id);
- node.update(data);
+
}
/**
- * Creates the menu from a json structure
- * @param json the json looks like this
- [
- {
- id: 1,,
- title: 'hi',
- type: MenuNodeType.Folder,
- icon: 'url/to/jpg.png',
- children: [
- {
- id: 1,
- title: 'hi too',
- type: MenuNodeType.Feed,
- children: []
- },
- {
- ...
- }
- ]
- },
- {
- ...
- }
- ]
- * @param attachToNode used for recursion. to set the current
- * element to the node, pass the current structure
+ * Binds the menu on an existing menu
+ * @param css Selector the selector to get the element with jquery
*/
- Menu.prototype.populateFromJSON = function(json, attachToNode){
- for(var i=0; i<json.length; i++){
- var nodeInfo = json[i];
- var nodeData = {
- title: nodeInfo.title,
- icon: nodeInfo.icon,
- unreadCount: nodeInfo.unreadCount
- };
- var node = new MenuNode(nodeInfo.type, nodeInfo.id, nodeData);
- attachToNode._addChildNode(node);
- this.populateFromJSON(nodeInfo.children, node);
- }
+ Menu.prototype.bindOn = function(cssSelector){
+ var self = this;
+ this._$root = $(cssSelector);
+ this._id = this._$root.data('id');
+ this._$root.children('li').each(function(){
+ self._bindMenuItem($(this));
+ });
+ this._bindDroppable(this._$root);
}
/**
- * This function creates the html of the menu and its children
- * @return the menu of the node and its children
+ * Binds the according handlers and reads in the meta data for each node
+ * @param $listItem the jquery list element
*/
- Menu.prototype.render = function(){
- var $html = this._$htmlElement.addClass(this._class).data('id', this._id);
- for(var i=0; i<this._children.length; i++){
- var child = this._children[i];
- var childHTML = child.render();
- $html.append(childHTML);
+ Menu.prototype._bindMenuItem = function($listItem){
+ switch(this._listItemToMenuNodeType($listItem)){
+ case MenuNodeType.Feed:
+ this._bindFeed($listItem);
+ break;
+ case MenuNodeType.Folder:
+ this._bindFolder($listItem);
+ break;
+ case MenuNodeType.Starred:
+ this._bindStarred($listItem);
+ break;
+ case MenuNodeType.Subscriptions:
+ this._bindSubscriptions($listItem);
+ break;
+ default:
+ console.log('Found unknown MenuNodeType');
+ console.log($listItem);
+ break;
}
- this._rendered = true;
-
- return $html;
}
/**
- * Returns the number of elements in the menu
- * @return the number of all children
+ * Returns the MenuNodeType of a list item
+ * @param $listItem the jquery list element
+ * @return the MenuNodeType of the jquery element
*/
- Menu.prototype.getSize = function(){
- var size = this._children.length;
- for(var i=0; i<this._children.length; i++){
- size += this._children[i].getSize();
+ Menu.prototype._listItemToMenuNodeType = function($listItem){
+ if($listItem.hasClass(this._menuNodeTypeToClass(MenuNodeType.Feed))){
+ return MenuNodeType.Feed;
+ } else if($listItem.hasClass(this._menuNodeTypeToClass(MenuNodeType.Folder))){
+ return MenuNodeType.Folder;
+ } else if($listItem.hasClass(this._menuNodeTypeToClass(MenuNodeType.Starred))){
+ return MenuNodeType.Starred;
+ } else if($listItem.hasClass(this._menuNodeTypeToClass(MenuNodeType.Subscriptions))){
+ return MenuNodeType.Subscriptions;
}
- return size;
}
/**
- * Shortcut for intially setting the selected node
- * @param type the type of the node (MenuNodeType)
- * @param id the id of the node
+ * Returns the classname of the MenuNodeType
+ * @param menuNodeType the type of the menu node
+ * @return the class of the MenuNodeType
*/
- Menu.prototype.setSelected = function(type, id){
- this._setSelected(this._findNode(type, id));
+ Menu.prototype._menuNodeTypeToClass = function(menuNodeType){
+ return MenuNodeTypeClass[menuNodeType];
}
/**
- * Elements should only be set as hidden if the user clicked on a new entry
- * Then all all_read entries should be marked as hidden
- * This function is used to hide all the read ones if showAll is false,
- * otherwise shows all
+ * Binds event listeners to the folder and its subcontents
+ * @param $listItem the jquery list element
*/
- Menu.prototype.triggerHideRead = function(){
- // only trigger in the root menu
- if(this._parent === false){
- if(this._showAll){
- $(this._$htmlElement).find('.hidden').each(function(){
- $(this).removeClass('hidden');
- });
- } else {
- $(this._$htmlElement).find('.all_read').each(function(){
- if(!$(this).hasClass('hidden')){
- $(this).addClass('hidden');
- }
- });
- }
-
- }
- }
+ Menu.prototype._bindFolder = function($listItem){
+ var self = this;
+ var id = $listItem.data('id');
+ this._setUnreadCount(MenuNodeType.Folder, id,
+ this._getAndRemoveUnreadCount($listItem));
- /**
- * Sets the showAll value
- * @param showAll if true, all read folders and feeds are being shown
- * if false only unread ones are shown
- */
- Menu.prototype.setShowAll = function(showAll){
- this._showAll = showAll;
- this.triggerHideRead();
+ this._resetOpenFolders();
+
+ // bind subitems
+ $children.each(function(){
+ self._bindMenuItem($(this));
+ });
+
+ // bind click listeners
+ this._bindDroppable($listItem);
+ this._bindDroppable($listItem.children('ul'));
+
+ $listItem.children('.title').click(function(){
+ self._load(MenuNodeType.Folder, id);
+ return false;
+ });
+
+ $listItem.children('.collapsable_trigger').click(function(){
+ self._toggleCollapse($listItem);
+ });
+
+ $listItem.children('.feeds_delete').click(function(){
+ self._delete(MenuNodeType.Folder, id);
+ });
+
+ $listItem.children('.feeds_edit').click(function(){
+ self._edit(MenuNodeType.Folder, id);
+ });
+
+ $listItem.children('.feeds_markread').click(function(){
+ self._markRead(MenuNodeType.Folder, id);
+ });
}
- /**
- * Shortcut for toggling show all
- */
- Menu.prototype.toggleShowAll = function(){
- this.setShowAll(!this._showAll);
+ Menu.prototype._bindFeed = function($listItem){
+ var self = this;
+ var id = $listItem.data('id');
+ this._setUnreadCount(MenuNodeType.Feed, id,
+ this._getAndRemoveUnreadCount($listItem));
+
+ // bind click listeners
+ $listItem.children('.title').click(function(){
+ self._load(MenuNodeType.Folder, id);
+ return false;
+ });
+
+ $