Tried out using a modal 'lightbox' style dialog for the new next action form on the home page (I'm using the scripts written by Bruno of [http://blog.feedmarker.com/2006/02/12/how-to-make-better-modal-windows-with-lightbox/ Feedmarker]).

Instead of opening up a form on the main page, clicking the 'Add new action' link (or hitting Alt/Ctrl N) opens up an overlay window, with a semi-transparent window underneath. You can add as many actions as you like by filling in the forms and hitting submit, then when you're done, click the close box or the shaded overlay area to dismiss the window.

It works very well on Safari, but for some reason, on my copy of Firefox, the cursor is invisible.

My plan is to also allow deferred actions to be added using this form, and eventually set up editing of existing actions to use the same format.



git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@250 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
bsag 2006-05-29 11:02:28 +00:00
parent f10e5b102e
commit 3da6fe2525
11 changed files with 239 additions and 11 deletions

View file

@ -61,7 +61,8 @@ class TodoController < ApplicationController
@on_page = "home"
if @saved
@up_count = @todos.collect { |x| ( !x.done? and !x.context.hide? ) ? x:nil }.compact.size.to_s
self.init # we have to do this again to update @todos
@up_count = @todos.reject { |x| x.done? or x.context.hide? }.size.to_s
end
return if request.xhr?
@ -202,7 +203,8 @@ class TodoController < ApplicationController
@saved = @item.destroy
@on_page = "home"
if @saved
@down_count = @todos.collect { |x| ( !x.done? and !x.context.hide? ) ? x:nil }.compact.size.to_s
self.init
@down_count = @todos.reject { |x| x.done? or x.context.hide? }.size.to_s
end
return if request.xhr?

View file

@ -10,6 +10,8 @@
<%= javascript_include_tag 'calendar', 'calendar-en', 'calendar-setup' %>
<%= javascript_include_tag "accesskey-hints" %>
<%= javascript_include_tag "todo-items" %>
<%= javascript_include_tag "lightbox" %>
<%= stylesheet_link_tag "lightbox" %>
<link rel="shortcut icon" href="<%= url_for(:controller => 'favicon.ico') %>" />
<%= auto_discovery_link_tag(:rss,{:controller => "feed", :action => "na_feed", :name => "#{@user.login}", :token => "#{@user.word}"}, {:title => "RSS feed of next actions"}) %>

View file

@ -0,0 +1,48 @@
<div id="mybox" style="display:none">
<div id="todo_new_action" class="context_new">
<%= form_remote_tag(
:url => { :controller => controller.controller_name, :action => "add_item" },
:html=> { :id=>'todo-form-new-action', :name=>'todo', :class => 'inline-form' }) %>
<h2>Add a new next action:</h2>
<div id="status">
</div>
<table>
<tr>
<td><label for="todo_description">Description</label></td>
<td><%= text_field( "todo", "description", "size" => 30, "tabindex" => 1) %></td>
</tr>
<tr>
<td><label for="todo_notes">Notes</label></td>
<td><%= text_area( "todo", "notes", "cols" => 25, "rows" => 10, "tabindex" => 2) %></td>
</tr>
<tr>
<td><label for="todo_context_id">Context</label></td>
<td><%= collection_select( "todo", "context_id", @contexts, "id", "name",
{}, {"tabindex" => 3}) %></td>
</tr>
<tr>
<td><label for="todo_project_id">Project</label></td>
<td><%= collection_select( "todo", "project_id", @projects.reject{|p| p.done?}, "id", "name",
{ :include_blank => true }, {"tabindex" => 4}) %></td>
</tr>
<tr>
<td><label for="todo_due">Due</label></td>
<td><%= text_field("todo", "due", "size" => 10, "class" => "Date", "onFocus" => "Calendar.setup", "tabindex" => 5, "autocomplete" => "off") %></td>
</tr>
<% if controller.controller_name == "project" -%>
<%= hidden_field( "todo", "project_id", "value" => "#{@project.id}") %>
<% elsif controller.controller_name == "context" -%>
<%= hidden_field( "todo", "context_id", "value" => "#{@context.id}") %>
<% end -%>
<tr>
<td></td>
<td><input type="submit" value="Add item" tabindex="6"></td>
</tr>
</table>
<%= end_form_tag %><!--[eoform:todo]-->
<%= calendar_setup( "todo_due" ) %>
</div><!-- [end:todo-new-action] -->
</div>

View file

@ -1,6 +1,6 @@
<h3>Active Projects:</h3>
<ul>
<% for project in @projects.reject{|p| p.done } -%>
<% for project in @projects.reject{|p| p.done? } -%>
<li><%= link_to( sanitize(project.name), { :controller => "project", :action => "show",
:name => urlize(project.name) } ) + " (" + project.count_undone_todos("actions") + ")" %></li>
<% end -%>
@ -8,7 +8,7 @@
<h3>Completed Projects:</h3>
<ul>
<% for project in @projects.reject{|p| !p.done } -%>
<% for project in @projects.reject{|p| !p.done? } -%>
<li><%= link_to( sanitize(project.name), { :controller => "project", :action => "show",
:name => urlize(project.name) } ) + " (" + project.count_undone_todos("actions") + ")" %></li>
<% end -%>
@ -16,7 +16,7 @@
<h3>Active Contexts:</h3>
<ul>
<% for context in @contexts.reject{|c| c.hide } -%>
<% for context in @contexts.reject{|c| c.hide? } -%>
<li><%= link_to( sanitize(context.name), { :controller => "context", :action => "show",
:name => urlize(context.name) } ) + " (" + context.count_undone_todos("actions") + ")" %></li>
<% end -%>
@ -24,7 +24,7 @@
<h3>Hidden Contexts:</h3>
<ul>
<% for context in @contexts.reject{|c| !c.hide } -%>
<% for context in @contexts.reject{|c| !c.hide? } -%>
<li><%= link_to( sanitize(context.name), { :controller => "context", :action => "show",
:name => urlize(context.name) } ) + " (" + context.count_undone_todos("actions") + ")" %></li>
<% end -%>

View file

@ -1,8 +1,8 @@
if @saved
page.hide "status"
page.show "status"
page.replace_html "status", content_tag("div", "Added new next action", "class" => "confirmation")
page.visual_effect :appear, 'status', :duration => 0.5
page.replace_html "badge_count", @up_count
page.visual_effect :fade, 'status', :duration => 2
page['badge_count'].replace_html @up_count
page.send :record, "Form.reset('todo-form-new-action');Form.focusFirstElement('todo-form-new-action')"
page.insert_html :bottom, "c#{@item.context_id}items", :partial => 'todo/item'
page.visual_effect :highlight, "item-#{@item.id}-container", :duration => 3

View file

@ -15,6 +15,7 @@
</div><!-- End of display_box -->
<div id="input_box">
<%= render :partial => "shared/add_new_item_form", :locals => {:hide_link => false, :msg => ""} %>
<a href="#" onclick="new Lightbox.base('mybox', { closeOnOverlayClick : true });Form.focusFirstElement('todo-form-new-action'); return false" accesskey="n">Add new action &raquo;</a>
<%= render :partial => "shared/new_action_form" %>
<%= render "shared/sidebar" %>
</div><!-- End of input box -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

View file

@ -0,0 +1,130 @@
/*--------------------------------------------------------------------------*/
/* Lightbox
* This is a script for creating modal dialog windows (like the ones your operating
* system uses)
*
*/
var Lightbox = {
/* hideAll - closes all open lightbox windows */
hideAll: function(){
lboxes = document.getElementsByClassName('lbox')
lboxes.each(function(box){
Element.hide(box)
}
)
if ($('overlay')){
Element.remove('overlay');
}
}
}
Lightbox.base = Class.create();
Lightbox.base.prototype = {
initialize: function(element, options){
//start by hiding all lightboxes
Lightbox.hideAll();
this.element = $(element);
this.options = Object.extend({
lightboxClassName : 'lightbox',
closeOnOverlayClick : false,
externalControl : false
}, options || {} )
//create the overlay
new Insertion.Before(this.element, "<div id='overlay' style='display:none;'></div>");
Element.addClassName(this.element, this.options.lightboxClassName)
//also add a default lbox class to the lightbox div so we can find and close all lightboxes if we need to
Element.addClassName(this.element, 'lbox')
//Tip: make sure the path to the close.gif image below is correct for your setup
closer = '<img id="close" src="/images/close.gif" alt="Close" title="Close this window" />'
//insert the closer image into the div
new Insertion.Top(this.element, closer);
Event.observe($('close'), 'click', this.hideBox.bindAsEventListener(this) );
if (this.options.closeOnOverlayClick){
Event.observe($('overlay'), 'click', this.hideBox.bindAsEventListener(this) );
}
if (this.options.externalControl){
Event.observe($(this.options.externalControl), 'click', this.hideBox.bindAsEventListener(this) );
}
this.showBox();
},
showBox : function(){
//show the overlay
Element.show('overlay');
//center the lightbox
this.center();
//show the lightbox
Element.show(this.element);
return false;
},
hideBox : function(evt){
Element.removeClassName(this.element, this.options.lightboxClassName)
Element.hide(this.element);
//remove the overlay element from the DOM completely
Element.remove('overlay');
return false;
},
center : function(){
var my_width = 0;
var my_height = 0;
if ( typeof( window.innerWidth ) == 'number' ){
my_width = window.innerWidth;
my_height = window.innerHeight;
}else if ( document.documentElement &&
( document.documentElement.clientWidth ||
document.documentElement.clientHeight ) ){
my_width = document.documentElement.clientWidth;
my_height = document.documentElement.clientHeight;
}
else if ( document.body &&
( document.body.clientWidth || document.body.clientHeight ) ){
my_width = document.body.clientWidth;
my_height = document.body.clientHeight;
}
this.element.style.position = 'absolute';
this.element.style.zIndex = 99;
var scrollY = 0;
if ( document.documentElement && document.documentElement.scrollTop ){
scrollY = document.documentElement.scrollTop;
}else if ( document.body && document.body.scrollTop ){
scrollY = document.body.scrollTop;
}else if ( window.pageYOffset ){
scrollY = window.pageYOffset;
}else if ( window.scrollY ){
scrollY = window.scrollY;
}
var elementDimensions = Element.getDimensions(this.element);
var setX = ( my_width - elementDimensions.width ) / 2;
var setY = ( my_height - elementDimensions.height ) / 2 + scrollY;
setX = ( setX < 0 ) ? 0 : setX;
setY = ( setY < 0 ) ? 0 : setY;
this.element.style.left = setX + "px";
this.element.style.top = setY + "px";
}
}

View file

@ -8,6 +8,7 @@ div.calendar { position: relative; }
color: #000;
cursor: default;
background: #eef;
z-index: 110;
font-family: tahoma,verdana,sans-serif;
}

View file

@ -0,0 +1,44 @@
/*body {
font-family:arial, helvetica, sans-serif;
}
*/
#overlay{
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
z-index:80;
background-color:#000;
-moz-opacity: 0.8;
opacity:.80;
filter: alpha(opacity=80);
}
#overlay[id]{ /* IE6 and below Can't See This */
position:fixed;
}
.lightbox{
width:350px;
background:#eee;
padding:10px;
border:2px solid #666;
}
.lightbox h2 {
background-color: #666;
color: #fff !important;
margin-left: -10px;
margin-right: -5px;
margin-top: -10px;
padding: 5px;
}
#close{
position:absolute;
top:-5px;
right:-5px;
cursor:pointer;
}

View file

@ -308,7 +308,7 @@ a.footer_link:hover {color: #fff; background-color: #cc3334 !important;}
}
#status .confirmation {
width: 220px;
margin: 2px 5px;
}
#warning, .warning {
padding: 2px;