From 3a2f2947460a5cc9d5cb2b6f6047179d253e7500 Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Thu, 23 Dec 2010 16:02:17 -0500 Subject: [PATCH] Adding autocomplete to add feed. Includes feed title, address, and link. --- apps/rss_feeds/urls.py | 1 + apps/rss_feeds/views.py | 20 ++++++++++- media/css/reader.css | 53 ++++++++++++++++++++++++++++ media/js/jquery.newsblur.js | 46 +++++++++++------------- media/js/newsblur/reader_add_feed.js | 43 ++++++++++++++++++---- settings.py | 1 + 6 files changed, 131 insertions(+), 33 deletions(-) diff --git a/apps/rss_feeds/urls.py b/apps/rss_feeds/urls.py index 3a53a90a3..9f82c1448 100644 --- a/apps/rss_feeds/urls.py +++ b/apps/rss_feeds/urls.py @@ -2,6 +2,7 @@ from django.conf.urls.defaults import * from apps.rss_feeds import views urlpatterns = patterns('', + url(r'^feed_autocomplete', views.feed_autocomplete, name='feed-autocomplete'), url(r'^statistics', views.load_feed_statistics, name='statistics'), url(r'^exception_retry', views.exception_retry, name='exception-retry'), url(r'^exception_change_feed_address', views.exception_change_feed_address, name='exception-change-feed-address'), diff --git a/apps/rss_feeds/views.py b/apps/rss_feeds/views.py index e1fdcfbab..358dae577 100644 --- a/apps/rss_feeds/views.py +++ b/apps/rss_feeds/views.py @@ -2,13 +2,31 @@ import datetime from utils import log as logging from django.shortcuts import get_object_or_404 from django.http import HttpResponseForbidden -from django.db import IntegrityError +# from django.db import IntegrityError from apps.rss_feeds.models import Feed, merge_feeds from apps.reader.models import UserSubscription from utils.user_functions import ajax_login_required from utils import json_functions as json, feedfinder from utils.feed_functions import relative_timeuntil, relative_timesince +@json.json_view +def feed_autocomplete(request): + query = request.GET['term'] + feeds = Feed.objects.filter(feed_address__icontains=query) + if not feeds: + feeds = Feed.objects.filter(feed_link__icontains=query) + if not feeds: + feeds = Feed.objects.filter(feed_title__icontains=query) + + feeds = feeds.order_by('-num_subscribers').only('feed_address', 'feed_title', 'num_subscribers')[:5] + feeds = [{ + 'value': feed.feed_address, + 'label': feed.feed_title, + 'num_subscribers': feed.num_subscribers, + } for feed in feeds] + + return feeds + @json.json_view def load_feed_statistics(request): stats = dict() diff --git a/media/css/reader.css b/media/css/reader.css index 2825f517b..9b91e2587 100644 --- a/media/css/reader.css +++ b/media/css/reader.css @@ -2594,6 +2594,59 @@ a.NB-splash-link:hover { display: block; } +.ui-autocomplete { + width: 344px; + padding: 0; + margin: 0; +} +.ui-autocomplete li { + padding: 0; + list-style: none; + margin: 0; + border-bottom: 1px solid #B0B0B0; +} +.ui-autocomplete li:last-child { + border-bottom: none; +} +.ui-autocomplete li a { + padding: 2px; + display: block; + cursor: pointer; +} +.ui-autocomplete li a.ui-state-hover { + border: none; + font-weight: normal; +} + +.ui-autocomplete li a .NB-add-autocomplete-subscribers { + float: right; + font-size: 10px; + color: #909090; + font-weight: bold; + text-transform: uppercase; + line-height: 16px; + padding: 2px 4px 0 0; +} +.ui-autocomplete li a .NB-add-autocomplete-title { + line-height: 16px; + color: #202020; + font-weight: bold; + font-size: 13px; + height: 16px; + overflow: hidden; + padding: 2px 0 0 4px; +} +.ui-autocomplete li a .NB-add-autocomplete-address { + display: block; + clear: both; + color: #3F3D6E; + font-size: 10px; + font-weight: normal; + height: 12px; + padding: 4px 0 4px 4px; + overflow: hidden; +} + /* ================ */ /* = Manage Feeds = */ /* ================ */ diff --git a/media/js/jquery.newsblur.js b/media/js/jquery.newsblur.js index 13c3765b1..bc1ade662 100644 --- a/media/js/jquery.newsblur.js +++ b/media/js/jquery.newsblur.js @@ -229,7 +229,7 @@ NEWSBLUR.log = function(msg) { // Second argument can be TextNode or Attributes // $.make('div', 'inner text') || $.make('div', { className: 'etc' }) if (args[1]) { - if (typeof args[1] == 'string') { + if (typeof args[1] == 'string' || typeof args[1] == 'number') { text = args[1]; } else if (typeof args[1] == 'object' && args[1].push) { children = args[1]; @@ -240,40 +240,36 @@ NEWSBLUR.log = function(msg) { // Third argument can be TextNode or an array of additional $.make if (args[2]) { - if (typeof args[2] == 'string') { + if (typeof args[2] == 'string' || typeof args[2] == 'number') { text = args[2]; } else if (typeof args[1] == 'object' && args[2].push) { children = args[2]; } } - if (tagname == 'text' && text) { - return document.createTextNode(text); - } else { - $elem = $(document.createElement(tagname)); - if (props) { - for (var propname in props) { - if (props.hasOwnProperty(propname)) { - if ($elem.is(':input') && propname == 'value') { - $elem.val(props[propname]); - } else { - $elem.attr(propname, props[propname]); - } + $elem = $(document.createElement(tagname)); + if (props) { + for (var propname in props) { + if (props.hasOwnProperty(propname)) { + if ($elem.is(':input') && propname == 'value') { + $elem.val(props[propname]); + } else { + $elem.attr(propname, props[propname]); } } } - if (children) { - for (var i = 0; i < children.length; i++) { - if (children[i]) { - $elem.append(children[i]); - } - } - } - if (text) { - $elem.html(text); - } - return $elem; } + if (children) { + for (var i = 0; i < children.length; i++) { + if (children[i]) { + $elem.append(children[i]); + } + } + } + if (text) { + $elem.html(text); + } + return $elem; }, rescope: function(func, thisArg){ diff --git a/media/js/newsblur/reader_add_feed.js b/media/js/newsblur/reader_add_feed.js index 11ae8e6d6..d742fa00d 100644 --- a/media/js/newsblur/reader_add_feed.js +++ b/media/js/newsblur/reader_add_feed.js @@ -13,14 +13,15 @@ NEWSBLUR.ReaderAddFeed.prototype = { this.handle_cancel(); this.open_modal(); this.handle_keystrokes(); + this.setup_autocomplete(); - this.$add.bind('click', $.rescope(this.handle_click, this)); + this.$modal.bind('click', $.rescope(this.handle_click, this)); }, make_modal: function() { var self = this; - this.$add = $.make('div', { className: 'NB-add NB-modal' }, [ + this.$modal = $.make('div', { className: 'NB-add NB-modal' }, [ $.make('h2', { className: 'NB-modal-title' }, 'Add feeds and folders'), $.make('div', { className: 'NB-add-form' }, [ $.make('div', { className: 'NB-fieldset NB-add-add-url NB-modal-submit' }, [ @@ -93,7 +94,7 @@ NEWSBLUR.ReaderAddFeed.prototype = { ]); if (NEWSBLUR.Globals.is_anonymous) { - this.$add.addClass('NB-signed-out'); + this.$modal.addClass('NB-signed-out'); } }, @@ -128,7 +129,7 @@ NEWSBLUR.ReaderAddFeed.prototype = { open_modal: function() { var self = this; - this.$add.modal({ + this.$modal.modal({ 'minWidth': 600, 'maxWidth': 600, 'overlayClose': true, @@ -155,7 +156,7 @@ NEWSBLUR.ReaderAddFeed.prototype = { }, handle_cancel: function() { - var $cancel = $('.NB-modal-cancel', this.$add); + var $cancel = $('.NB-modal-cancel', this.$modal); $cancel.click(function(e) { e.preventDefault(); @@ -163,15 +164,43 @@ NEWSBLUR.ReaderAddFeed.prototype = { }); }, + setup_autocomplete: function() { + var self = this; + var $add = $('.NB-add-url', this.$modal); + + $add.autocomplete({ + minLength: 0, + source: '/rss_feeds/feed_autocomplete', + focus: function(e, ui) { + $add.val(ui.item.value); + return false; + }, + select: function(e, ui) { + $add.val(ui.item.value); + NEWSBLUR.log(['select', e, ui, ui.item, ui.item.value]); + self.save_add_url(); + return false; + } + }).data("autocomplete")._renderItem = function(ul, item) { + return $.make('li', [ + $.make('a', [ + $.make('div', { className: 'NB-add-autocomplete-subscribers'}, item.num_subscribers + Inflector.pluralize(' subscriber', item.num_subscribers)), + $.make('div', { className: 'NB-add-autocomplete-title'}, item.label), + $.make('div', { className: 'NB-add-autocomplete-address'}, item.value) + ]) + ]).data("item.autocomplete", item).appendTo(ul); + }; + }, + handle_keystrokes: function() { var self = this; - $('.NB-add-url', this.$add).bind('keyup', 'return', function(e) { + $('.NB-add-url', this.$modal).bind('keyup', 'return', function(e) { e.preventDefault(); self.save_add_url(); }); - $('.NB-add-folder', this.$add).bind('keyup', 'return', function(e) { + $('.NB-add-folder', this.$modal).bind('keyup', 'return', function(e) { e.preventDefault(); self.save_add_folder(); }); diff --git a/settings.py b/settings.py index a0c679fad..967c38898 100644 --- a/settings.py +++ b/settings.py @@ -105,6 +105,7 @@ COMPRESS_JS = { 'js/jquery.ui.draggable.js', 'js/jquery.ui.sortable.js', 'js/jquery.ui.slider.js', + 'js/jquery.ui.autocomplete.js', 'js/jquery.ui.progressbar.js', 'js/jquery.layout.js', 'js/jquery.tinysort.js',