* Ambiguous wording "Add next action to this context" and "Completed actions in this context" was fixed on home page. Fixes #71

* Replaced the built-in Effect.Squish() effect on deleted and completed actions with Effect2.Fade() by [http://mir.aculo.us/effects/index.html Thomas Fuchs]. This looks much nicer, and doesn't generate the visual oddities that Kris noted. I've also added an Effect.Highlight for when new actions are added to help inform the user that something has happened.


git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@109 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
bsag 2005-06-15 17:32:50 +00:00
parent f5053d60c2
commit bc978622e7
10 changed files with 370 additions and 20 deletions

View file

@ -31,7 +31,7 @@
<%= link_to_remote( image_tag("blank", :title =>"Delete context", :class=>"delete_item"),
:update => "context-#{context.id}-container",
:loading => "new Effect.Squish('context-#{context.id}-container')",
:loading => "new Effect2.Fade('context-#{context.id}-container', true)",
:url => { :controller => "context", :action => "destroy", :id => context.id }, :confirm => "Are you sure that you want to delete the context \'#{context.name}\'?" ) + " " +
link_to_function( image_tag( "blank", :title => "Edit context", :class=>"edit_item"), "Element.toggle('context-#{context.id}','context-#{context.id}-edit-form'); new Effect.Appear('context-#{context.id}-edit-form'); Form.focus_first('form-context-#{context.id}');" ) %>
</div>

View file

@ -6,7 +6,7 @@
:update => "completed",
:position => "top",
:loading => "Form.disable('checkbox-notdone-#{item.id}');",
:complete => "new Effect.Squish('item-#{item.id}-container', true);"
:complete => "new Effect2.Fade('item-#{item.id}-container', true);"
) %>
<div id="item-<%= item.id %>">
@ -14,7 +14,7 @@
<%=
link_to_remote( image_tag("blank", :title =>"Delete this action", :class=>"delete_item"),
:update => "item-#{item.id}-container",
:loading => "new Effect.Squish('item-#{item.id}-container')",
:loading => "new Effect2.Fade('item-#{item.id}-container', true)",
:url => { :controller => "context", :action => "destroy_action", :id => item.id }, :confirm => "Are you sure that you want to delete the action \'#{item.description}\'?" ) + " " +
link_to_function(image_tag( "blank", :title => "Edit item", :class=>"edit_item"), "Element.toggle('item-#{item.id}','action-#{item.id}-edit-form'); new Effect.Appear('action-#{item.id}-edit-form'); Form.focusFirstElement('form-action-#{item.id}');" ) + " "
%>
@ -61,7 +61,7 @@
:update => "next_actions",
:position => "bottom",
:loading => "Form.disable('checkbox-done-#{item.id}');",
:complete => "new Effect.Squish('done-item-#{item.id}-container', true);"
:complete => "new Effect2.Fade('done-item-#{item.id}-container', true);"
) %>
<div id="done-item-<%= item.id %>">
@ -69,7 +69,7 @@
<%=
link_to_remote( image_tag("blank", :title =>"Delete this action", :class=>"delete_item"),
:update => "done-item-#{item.id}-container",
:loading => "new Effect.Squish('done-item-#{item.id}-container')",
:loading => "new Effect2.Fade('done-item-#{item.id}-container', true)",
:url => { :controller => "context", :action => "destroy_action", :id => item.id }, :confirm => "Are you sure that you want to delete the action \'#{item.description}\'?" ) + " "
%>
<%= image_tag("blank") %>

View file

@ -40,7 +40,7 @@
:update=> "next_actions",
:position=> "bottom",
:loading => "context.reset()",
:complete => "Form.focusFirstElement('context-form-new-action');",
:complete => "Form.focusFirstElement('context-form-new-action'); new Effect.Highlight('next_actions');",
:html=> { :id=>'context-form-new-action', :name=>'context', :class => 'inline-form' } %>
<%= hidden_field( "new_item", "context_id", "value" => "#{@context.id}") %>
<label for="new_item_description">Description</label><br />

View file

@ -5,6 +5,7 @@
<%= javascript_include_tag "toggle_notes" %>
<%= javascript_include_tag "prototype" %>
<%= javascript_include_tag "prototype-ex" %>
<%= javascript_include_tag "effects2" %>
<%= stylesheet_link_tag 'calendar-system.css' %>
<%= javascript_include_tag 'calendar', 'calendar-en', 'calendar-setup' %>

View file

@ -29,7 +29,7 @@
<%= link_to_remote( image_tag("blank", :title =>"Delete project", :class=>"delete_item"),
:update => "project-#{project.id}-container",
:loading => "new Effect.Squish('project-#{project.id}-container')",
:loading => "new Effect2.Fade('project-#{project.id}-container', true)",
:url => { :controller => "project", :action => "destroy", :id => project.id }, :confirm => "Are you sure that you want to delete the project \'#{project.name}\'?" ) + " " +
link_to_function(image_tag( "blank", :title => "Edit item", :class=>"edit_item"), "Element.toggle('project-#{project.id}','project-#{project.id}-edit-form'); new Effect.Appear('project-#{project.id}-edit-form'); Form.focus_first('form-project-#{project.id}');" ) %>
</div>

View file

@ -6,7 +6,7 @@
:update => "completed",
:position => "top",
:loading => "Form.disable('checkbox-notdone-#{item.id}');",
:complete => "new Effect.Squish('item-#{item.id}-container', true);"
:complete => "new Effect2.Fade('item-#{item.id}-container', true);"
) %>
<div id="item-<%= item.id %>">
@ -14,7 +14,7 @@
<%=
link_to_remote( image_tag("blank", :title =>"Delete action", :class=>"delete_item"),
:update => "item-#{item.id}-container",
:loading => "new Effect.Squish('item-#{item.id}-container')",
:loading => "new Effect2.Fade('item-#{item.id}-container', true)",
:url => { :controller => "project", :action => "destroy_action", :id => item.id }, :confirm => "Are you sure that you want to delete the action \'#{item.description}\'?" ) + " " +
link_to_function(image_tag( "blank", :title => "Edit action", :class=>"edit_item"), "Element.toggle('item-#{item.id}','action-#{item.id}-edit-form'); new Effect.Appear('action-#{item.id}-edit-form'); Form.focusFirstElement('form-action-#{item.id}');" ) + " "
%>
@ -49,7 +49,7 @@
<%= form_remote_tag :url => { :controller => 'project', :action => 'update_action', :id => item.id },
:html => { :id => "form-action-#{item.id}", :class => "inline-form" },
:update => "item-#{item.id}-container",
:complete => "new Effect.Appear('item-#{item.id}-container');" %>
:complete => "new Effect.Appear('item-#{item.id}-container', true);" %>
<%= render_partial 'todo/action_edit_form', item %>
<%= end_form_tag %>
</div><!-- [end:action-item.id-edit-form] -->
@ -62,7 +62,7 @@
:update => "next_actions",
:position => "bottom",
:loading => "Form.disable('checkbox-done-#{item.id}');",
:complete => "new Effect.Squish('done-item-#{item.id}-container', true);"
:complete => "new Effect2.Fade('done-item-#{item.id}-container', true);"
) %>
<div id="done-item-<%= item.id %>">
@ -70,7 +70,7 @@
<%=
link_to_remote( image_tag("blank", :title =>"Delete action", :class=>"delete_item"),
:update => "done-item-#{item.id}-container",
:loading => "new Effect.Squish('done-item-#{item.id}-container')",
:loading => "new Effect2.Fade('done-item-#{item.id}-container', true)",
:url => { :controller => "project", :action => "destroy_action", :id => item.id }, :confirm => "Are you sure that you want to delete the action \'#{item.description}\'?" ) + " "
%>
</div><!-- [end:big-box] -->

View file

@ -45,7 +45,7 @@
:update=> "next_actions",
:position=> "bottom",
:loading => "project.reset()",
:complete => "Form.focusFirstElement('project-form-new-action');",
:complete => "Form.focusFirstElement('project-form-new-action'); new Effect.Highlight('next_actions');",
:html=> { :id=>'project-form-new-action', :name=>'project', :class => 'inline-form' } %>
<%= hidden_field( "new_item", "project_id", "value" => "#{@project.id}") %>
<label for="new_item_description">Description</label><br />

View file

@ -6,7 +6,7 @@
:update => "completed",
:position => "top",
:loading => "Form.disable('checkbox-notdone-#{item.id}');",
:complete => "new Effect.Squish('item-#{item.id}-container', true);"
:complete => "new Effect2.Fade('item-#{item.id}-container', true);"
) %>
<div id="item-<%= item.id %>">
@ -14,7 +14,7 @@
<%=
link_to_remote( image_tag("blank", :title =>"Delete action", :class=>"delete_item"),
:update => "item-#{item.id}-container",
:loading => "new Effect.Squish('item-#{item.id}-container')",
:loading => "new Effect2.Fade('item-#{item.id}-container', true)",
:url => { :controller => "todo", :action => "destroy_action", :id => item.id },
:confirm => "Are you sure that you want to delete the action, \'#{item.description}\'?") + " " +
link_to_function(image_tag( "blank", :title => "Edit action", :class => "edit_item"),
@ -61,7 +61,7 @@
:update => "new_actions",
:position => "bottom",
:loading => "Form.disable('checkbox-done-#{item.id}');",
:complete => "Element.toggle('new_actions');new Effect.Squish('done-item-#{item.id}-container', true);"
:complete => "Element.toggle('new_actions');new Effect2.Fade('done-item-#{item.id}-container', true);"
) %>
<div id="done-item-<%= item.id %>">
@ -69,7 +69,7 @@
<%=
link_to_remote( image_tag("blank", :title =>"Delete action", :class=>"delete_item"),
:update => "done-item-#{item.id}-container",
:loading => "new Effect.Squish('done-item-#{item.id}-container')",
:loading => "new Effect2.Fade('done-item-#{item.id}-container', true)",
:url => { :controller => "todo", :action => "destroy_action", :id => item.id }, :confirm => "Are you sure that you want to delete the action \'#{item.description}\'?" ) + " "
%>
<%= image_tag("blank") %>

View file

@ -27,7 +27,7 @@
<% end -%>
<div class="contexts">
<h2>Completed actions in this context</h2>
<h2>Completed actions</h2>
<div id="completed">
<% if @done.empty? -%>
@ -49,7 +49,7 @@
<div class="warning"><%= @flash["warning"] %></div>
<% end -%>
<%= link_to_function( "Add the next action in this context &#187;", "Element.toggle('todo_new_action');Element.toggle('new_actions');Form.focusFirstElement('todo-form-new-action');", {:title => "Add the next action [Alt+n]", :accesskey => "n"}) %>
<%= link_to_function( "Add a next action &#187;", "Element.toggle('todo_new_action');Element.toggle('new_actions');Form.focusFirstElement('todo-form-new-action');", {:title => "Add the next action [Alt+n]", :accesskey => "n"}) %>
<div id="todo_new_action" class="context_new" style="display:none">
<!--[form:todo]-->
@ -57,7 +57,7 @@
:update => "new_actions",
:position=> "bottom",
:loading => "context.reset()",
:complete => "Form.focusFirstElement('todo-form-new-action');",
:complete => "Form.focusFirstElement('todo-form-new-action');new Effect.Highlight('new_actions');",
:html=> { :id=>'todo-form-new-action', :name=>'todo', :class => 'inline-form' } %>
<label for="new_item_description">Description</label><br />
<%= text_field( "new_item", "description", "size" => 25, "tabindex" => 1 ) %><br />

View file

@ -0,0 +1,349 @@
// Copyright (c) 2005 Thomas Fuchs (http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Effect2 = {}
/* ------------- transitions ------------- */
Effect2.Transitions = {}
Effect2.Transitions.linear = function(pos) {
return pos;
}
Effect2.Transitions.sinoidal = function(pos) {
return (-Math.cos(pos*Math.PI)/2) + 0.5;
}
Effect2.Transitions.reverse = function(pos) {
return 1-pos;
}
Effect2.Transitions.flicker = function(pos) {
return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random(0.25);
}
Effect2.Transitions.wobble = function(pos) {
return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
}
/* ------------- core effects ------------- */
Effect2.Base = function() {};
Effect2.Base.prototype = {
setOptions: function(options) {
this.options = {
transition: Effect2.Transitions.sinoidal,
duration: 1.0, // seconds
fps: 25.0, // max. 100fps
sync: false, // true for combining
from: 0.0,
to: 1.0
}.extend(options || {});
},
start: function(options) {
this.setOptions(options || {});
this.currentFrame = 0;
this.startOn = new Date().getTime();
this.finishOn = this.startOn + (this.options.duration*1000);
if(this.options.beforeStart) this.options.beforeStart(this);
if(!this.options.sync) this.loop();
},
loop: function() {
timePos = new Date().getTime();
if(timePos >= this.finishOn) {
this.render(this.options.to);
if(this.finish) this.finish();
if(this.options.afterFinish) this.options.afterFinish(this);
return;
}
pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
frame = Math.round(pos * this.options.fps * this.options.duration);
if(frame > this.currentFrame) {
this.render(pos);
this.currentFrame = frame;
}
this.timeout = setTimeout(this.loop.bind(this), 10);
},
render: function(pos) {
if(this.options.transition) pos = this.options.transition(pos);
pos = pos * (this.options.to-this.options.from);
pos += this.options.from;
if(this.options.beforeUpdate) this.options.beforeUpdate(this);
if(this.update) this.update(pos);
if(this.options.afterUpdate) this.options.afterUpdate(this);
},
cancel: function() {
if(this.timeout) clearTimeout(this.timeout);
}
}
Effect2.Parallel = Class.create();
Effect2.Parallel.prototype = (new Effect2.Base()).extend({
initialize: function(effects) {
this.effects = effects || [];
this.start(arguments[1]);
},
update: function(position) {
for (var i = 0; i < this.effects.length; i++)
this.effects[i].render(position);
},
finish: function(position) {
for (var i = 0; i < this.effects.length; i++)
if(this.effects[i].finish) this.effects[i].finish(position);
}
});
Effect2.Opacity = Class.create();
Effect2.Opacity.prototype = (new Effect2.Base()).extend({
initialize: function() {
this.element = $(arguments[0] || document.rootElement);
options = {
from: 0.0,
to: 1.0
}.extend(arguments[1] || {});
this.start(options);
},
update: function(position) {
this.setOpacity(position);
},
setOpacity: function(opacity) {
opacity = (opacity == 1) ? 0.99999 : opacity;
this.element.style.opacity = opacity;
this.element.style.filter = "alpha(opacity:"+opacity*100+")";
}
});
Effect2.MoveBy = Class.create();
Effect2.MoveBy.prototype = (new Effect2.Base()).extend({
initialize: function(element, toTop, toLeft) {
this.element = $(element);
this.originalTop =
this.element.style.top ? parseFloat(this.element.style.top) : 0;
this.originalLeft =
this.element.style.left ? parseFloat(this.element.style.left) : 0;
this.toTop = toTop;
this.toLeft = toLeft;
if(this.element.style.position == "")
this.element.style.position = "relative";
this.start(arguments[3]);
},
update: function(position) {
topd = this.toTop * position + this.originalTop;
leftd = this.toLeft * position + this.originalLeft;
this.setPosition(topd, leftd);
},
setPosition: function(topd, leftd) {
this.element.style.top = topd + "px";
this.element.style.left = leftd + "px";
}
});
Effect2.Scale = Class.create();
Effect2.Scale.prototype = (new Effect2.Base()).extend({
initialize: function(element, percent) {
this.element = $(element)
options = {
scaleX: true,
scaleY: true,
scaleContent: true,
scaleFromCenter: false,
scaleMode: 'box', // 'box' or 'contents'
scaleFrom: 100.0
}.extend(arguments[2] || {});
this.originalTop = this.element.offsetTop;
this.originalLeft = this.element.offsetLeft;
if (this.element.style.fontSize=="") this.sizeEm = 1.0;
if (this.element.style.fontSize && this.element.style.fontSize.indexOf("em")>0)
this.sizeEm = parseFloat(this.element.style.fontSize);
this.factor = (percent/100.0) - (options.scaleFrom/100.0);
if(options.scaleMode=='box') {
this.originalHeight = this.element.clientHeight;
this.originalWidth = this.element.clientWidth;
} else
if(options.scaleMode=='contents') {
this.originalHeight = this.element.scrollHeight;
this.originalWidth = this.element.scrollWidth;
}
this.start(options);
},
update: function(position) {
currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
if(this.options.scaleContent && this.sizeEm)
this.element.style.fontSize = this.sizeEm*currentScale + "em";
this.setDimensions(
this.originalWidth * currentScale,
this.originalHeight * currentScale);
},
setDimensions: function(width, height) {
if(this.options.scaleX) this.element.style.width = width + 'px';
if(this.options.scaleY) this.element.style.height = height + 'px';
if(this.options.scaleFromCenter) {
topd = (height - this.originalHeight)/2;
leftd = (width - this.originalWidth)/2;
if(this.element.style.position=='absolute') {
if(this.options.scaleY) this.element.style.top = this.originalTop-topd + "px";
if(this.options.scaleX) this.element.style.left = this.originalLeft-leftd + "px";
} else {
if(this.options.scaleY) this.element.style.top = -topd + "px";
if(this.options.scaleX) this.element.style.left = -leftd + "px";
}
}
}
});
/* ------------- prepackaged effects ------------- */
Effect2.Fade = function(element) {
options = {
from: 1.0,
to: 0.0,
afterFinish: function(effect)
{ Element.hide(effect.element);
effect.setOpacity(1); }
}.extend(arguments[1] || {});
new Effect2.Opacity(element,options);
}
Effect2.Appear = function(element) {
options = {
from: 0.0,
to: 1.0,
beforeStart: function(effect)
{ effect.setOpacity(0);
Element.show(effect.element); },
afterUpdate: function(effect)
{ Element.show(effect.element); }
}.extend(arguments[1] || {});
new Effect2.Opacity(element,options);
}
Effect2.Puff = function(element) {
new Effect2.Parallel(
[ new Effect2.Scale(element, 200, { sync: true, scaleFromCenter: true }),
new Effect2.Opacity(element, { sync: true, to: 0.0, from: 1.0 } ) ],
{ duration: 1.0,
afterUpdate: function(effect)
{ effect.effects[0].element.style.position = 'absolute'; },
afterFinish: function(effect)
{ Element.hide(effect.effects[0].element); }
}
);
}
Effect2.BlindUp = function(element) {
$(element).style.overflow = 'hidden';
new Effect2.Scale(element, 0,
{ scaleContent: false,
scaleX: false,
afterFinish: function(effect)
{ Element.hide(effect.element) }
}.extend(arguments[1] || {})
);
}
Effect2.BlindDown = function(element) {
$(element).style.height = '0px';
$(element).style.overflow = 'hidden';
Element.show(element);
new Effect2.Scale(element, 100,
{ scaleContent: false,
scaleX: false,
scaleMode: 'contents',
scaleFrom: 0
}.extend(arguments[1] || {})
);
}
Effect2.SwitchOff = function(element) {
new Effect2.Appear(element,
{ duration: 0.4,
transition: Effect2.Transitions.flicker,
afterFinish: function(effect)
{ effect.element.style.overflow = 'hidden';
new Effect2.Scale(effect.element, 1,
{ duration: 0.3, scaleFromCenter: true,
scaleX: false, scaleContent: false,
afterUpdate: function(effect) {
if(effect.element.style.position=="")
effect.element.style.position = 'relative'; },
afterFinish: function(effect) { Element.hide(effect.element); }
} )
}
} )
}
Effect2.DropOut = function(element) {
new Effect2.Parallel(
[ new Effect2.MoveBy(element, 100, 0, { sync: true }),
new Effect2.Opacity(element, { sync: true, to: 0.0, from: 1.0 } ) ],
{ duration: 0.5,
afterFinish: function(effect)
{ Element.hide(effect.effects[0].element); }
});
}
Effect2.Shake = function(element) {
new Effect2.MoveBy(element, 0, 20,
{ duration: 0.05, afterFinish: function(effect) {
new Effect2.MoveBy(effect.element, 0, -40,
{ duration: 0.1, afterFinish: function(effect) {
new Effect2.MoveBy(effect.element, 0, 40,
{ duration: 0.1, afterFinish: function(effect) {
new Effect2.MoveBy(effect.element, 0, -40,
{ duration: 0.1, afterFinish: function(effect) {
new Effect2.MoveBy(effect.element, 0, 40,
{ duration: 0.1, afterFinish: function(effect) {
new Effect2.MoveBy(effect.element, 0, -20,
{ duration: 0.05, afterFinish: function(effect) {
}}) }}) }}) }}) }}) }});
}
Effect2.SlideDown = function(element) {
$(element).style.height = '0px';
$(element).style.overflow = 'hidden';
$(element).childNodes[0].style.position = 'relative';
Element.show(element);
new Effect2.Scale(element, 100,
{ scaleContent: false,
scaleX: false,
scaleMode: 'contents',
scaleFrom: 0,
afterUpdate: function(effect)
{ effect.element.firstChild.style.bottom =
(effect.originalHeight - effect.element.clientHeight) + 'px'; }
}.extend(arguments[1] || {})
);
}
Effect2.SlideUp = function(element) {
$(element).style.overflow = 'hidden';
$(element).childNodes[0].style.position = 'relative';
Element.show(element);
new Effect2.Scale(element, 0,
{ scaleContent: false,
scaleX: false,
afterUpdate: function(effect)
{ effect.element.firstChild.style.bottom =
(effect.originalHeight - effect.element.clientHeight) + 'px'; },
afterFinish: function(effect)
{ Element.hide(effect.element); }
}.extend(arguments[1] || {})
);
}