• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

allura


Commit MetaInfo

修订版d36ab9df031b17fe7532862928fd05daede96419 (tree)
时间2010-07-07 06:36:23
作者Jenny Steele <jsteele@geek...>
CommiterJenny Steele

Log Message

[#677] Added reusable tooltips for field labels and used them on project admin overview and download admin options.

更改概述

差异

--- /dev/null
+++ b/ForgeDownloads/forgedownloads/templates/admin_options.html
@@ -0,0 +1,45 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3+<html xmlns="http://www.w3.org/1999/xhtml"
4+ xmlns:py="http://genshi.edgewall.org/"
5+ xmlns:xi="http://www.w3.org/2001/XInclude">
6+ <xi:include href="master.html" />
7+ <head>
8+ <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
9+ <title>$app.config.options.mount_point Admin Options</title>
10+ </head>
11+
12+ <body>
13+ <h1 class="title">$app.config.options.mount_point Admin Options</h1>
14+ <div class="content">
15+ <div class="row">
16+ <div class="column grid_12">
17+ <form method="POST" action="update_options">
18+ <ol>
19+ <li>
20+ <div class="row dual">
21+ <div class="column" style="margin-right:0">
22+ <label for="show_download_button"
23+ title="Select this if you want a download button on the project's home page to give users an easy path to download the latest release.
24+ The download button will appear in the upper left corner of your projects home page.">Show Download:</label>
25+ </div>
26+ <div class="column grid_10" style="margin-left:0">
27+ <div class="editable viewing">
28+ <div class="viewer">$c.project.show_download_button</div>
29+ <div class="editor"><input name="show_download_button" type="checkbox" checked="${c.project.show_download_button or None}"/></div>
30+ </div>
31+ </div>
32+ </div>
33+ </li>
34+ <hr class="clear clearfix" />
35+ <li>
36+ <label>&nbsp;</label>
37+ <input type="submit" value="Save"/>
38+ </li>
39+ </ol>
40+ </form>
41+ </div>
42+ </div>
43+ </div>
44+ </body>
45+</html>
--- a/pyforge/pyforge/ext/admin/templates/project_overview.html
+++ b/pyforge/pyforge/ext/admin/templates/project_overview.html
@@ -66,11 +66,19 @@
6666 <form py:if="has_project_access('update')()" method="POST" action="update" enctype="multipart/form-data">
6767 <ol>
6868 <li>
69- <label for="name">Name:</label>
70- <div class="editable viewing">
71- <div class="viewer">$c.project.name</div>
72- <div class="editor"><input type="text" name="name" value="$c.project.name"/></div>
69+ <div class="row dual">
70+ <div class="column" style="margin-right:0">
71+ <label for="name"
72+ title="This is the publicly viewable name of the project, and will appear on project listings.
73+ It should be what you want to see as the project title in search listing.">Name:</label>
74+ </div>
75+ <div class="column grid_10" style="margin-left:0">
76+ <div class="editable viewing">
77+ <div class="viewer">$c.project.name</div>
78+ <div class="editor"><input type="text" name="name" value="$c.project.name"/></div>
79+ </div>
7380 </div>
81+ </div>
7482 </li>
7583 <hr class="clear clearfix" />
7684 <li>
@@ -79,29 +87,37 @@
7987 </li>
8088 <hr class="clear clearfix" />
8189 <li>
82- <label for="category">Category:</label>
83- <div class="editable viewing">
84- <div class="viewer">${c.project.category and c.project.category.label or 'Uncategorized'}</div>
85- <div class="editor">
86- <select name="category">
87- <option value="">Uncategorized</option>
88- <py:for each="cat in categories">
89- <option value="$cat._id" py:if="c.project.category and c.project.category._id == cat._id" selected="selected">$cat.label</option>
90- <option value="$cat._id" py:if="not c.project.category or (c.project.category and c.project.category._id != cat._id)">$cat.label</option>
91- <py:for each="subcat in cat.subcategories">
92- <option value="$subcat._id" py:if="c.project.category and c.project.category._id == subcat._id" selected="selected">-- $subcat.label</option>
93- <option value="$subcat._id" py:if="not c.project.category or (c.project.category and c.project.category._id != subcat._id)">-- $subcat.label</option>
94- </py:for>
95- </py:for>
96- </select>
97- </div>
90+ <div class="row dual">
91+ <div class="column" style="margin-right:0">
92+ <label for="category" title="This will determine which pages you appear under in the SourceForge Directory.">Category:</label>
9893 </div>
94+ <div class="column grid_10" style="margin-left:0">
95+ <div class="editable viewing">
96+ <div class="viewer">${c.project.category and c.project.category.label or 'Uncategorized'}</div>
97+ <div class="editor">
98+ <select name="category">
99+ <option value="">Uncategorized</option>
100+ <py:for each="cat in categories">
101+ <option value="$cat._id" py:if="c.project.category and c.project.category._id == cat._id" selected="selected">$cat.label</option>
102+ <option value="$cat._id" py:if="not c.project.category or (c.project.category and c.project.category._id != cat._id)">$cat.label</option>
103+ <py:for each="subcat in cat.subcategories">
104+ <option value="$subcat._id" py:if="c.project.category and c.project.category._id == subcat._id" selected="selected">-- $subcat.label</option>
105+ <option value="$subcat._id" py:if="not c.project.category or (c.project.category and c.project.category._id != subcat._id)">-- $subcat.label</option>
106+ </py:for>
107+ </py:for>
108+ </select>
109+ </div>
110+ </div>
111+ </div>
112+ </div>
99113 </li>
100114 <hr class="clear clearfix" />
101115 <li>
102116 <div class="row dual">
103117 <div class="column" style="margin-right:0">
104- <label for="icon">Icon:</label>
118+ <label for="icon"
119+ title="This is the icon that will appear on your project header and search results.
120+ For best appearance, use a square image with a transparent background.">Icon:</label>
105121 </div>
106122 <div class="column grid_10" style="margin-left:0">
107123 <div class="editable viewing">
@@ -118,17 +134,27 @@
118134 </li>
119135 <hr class="clear clearfix" />
120136 <li>
121- <label for="short_description">Summary:</label>
122- <div class="editable viewing">
123- <div class="viewer"><pre data-prompt="Write a brief summary of your project">$c.project.short_description</pre></div>
124- <div class="editor multiline"><textarea name="short_description">$c.project.short_description</textarea></div>
137+ <div class="row dual">
138+ <div class="column" style="margin-right:0">
139+ <label for="short_description"
140+ title="This is a text only project summary which will be included on search results and project listings.
141+ Typically this is one or two sentences describing the project, and is plain text.">Summary:</label>
125142 </div>
143+ <div class="column grid_10" style="margin-left:0">
144+ <div class="editable viewing">
145+ <div class="viewer"><pre data-prompt="Write a brief summary of your project">$c.project.short_description</pre></div>
146+ <div class="editor multiline"><textarea name="short_description">$c.project.short_description</textarea></div>
147+ </div>
148+ </div>
149+ </div>
126150 </li>
127151 <hr class="clear clearfix" />
128152 <li>
129153 <div class="row dual">
130154 <div class="column" style="margin-right:0">
131- <label for="description">Home Page:</label>
155+ <label for="description"
156+ title='This is the contents of the front page, and uses the markdown/HTML syntax similar to the wiki.
157+ This can be as long as you need it to be.'>Home Page:</label>
132158 </div>
133159 <div class="column grid_10" style="margin-left:0">
134160 ${c.markdown_editor.display(name='description',value=c.project.description)}
@@ -137,11 +163,19 @@
137163 </li>
138164 <hr class="clear clearfix" />
139165 <li>
140- <label for="labels">Tags:</label>
141- <div class="editable viewing">
142- <div class="viewer">${len(c.project.labels) and ', '.join(c.project.labels) or "No Tags"}</div>
143- <div class="editor">${c.label_edit.display(name='labels',value=c.project.labels)}</div>
166+ <div class="row dual">
167+ <div class="column" style="margin-right:0">
168+ <label for="labels"
169+ title="Free-form tags to describe your project.
170+ These can be used to search for similar projects.">Tags:</label>
144171 </div>
172+ <div class="column grid_10" style="margin-left:0">
173+ <div class="editable viewing">
174+ <div class="viewer">${len(c.project.labels) and ', '.join(c.project.labels) or "No Tags"}</div>
175+ <div class="editor">${c.label_edit.display(name='labels',value=c.project.labels)}</div>
176+ </div>
177+ </div>
178+ </div>
145179 </li>
146180 <hr class="clear clearfix" />
147181 <!-- <li>
--- /dev/null
+++ b/pyforge/pyforge/public/nf/css/forge/jquery.tooltip.css
@@ -0,0 +1,9 @@
1+#tooltip {
2+ position: absolute;
3+ z-index: 3000;
4+ border: 1px solid #111;
5+ background-color: #eee;
6+ padding: 5px;
7+ opacity: 0.85;
8+}
9+#tooltip h3, #tooltip div { margin: 0; }
--- /dev/null
+++ b/pyforge/pyforge/public/nf/js/jquery.tooltip.js
@@ -0,0 +1,294 @@
1+/*
2+ * jQuery Tooltip plugin 1.3
3+ *
4+ * http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
5+ * http://docs.jquery.com/Plugins/Tooltip
6+ *
7+ * Copyright (c) 2006 - 2008 Jörn Zaefferer
8+ *
9+ * $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
10+ *
11+ * Dual licensed under the MIT and GPL licenses:
12+ * http://www.opensource.org/licenses/mit-license.php
13+ * http://www.gnu.org/licenses/gpl.html
14+ */
15+
16+;(function($) {
17+
18+ // the tooltip element
19+ var helper = {},
20+ // the current tooltipped element
21+ current,
22+ // the title of the current element, used for restoring
23+ title,
24+ // timeout id for delayed tooltips
25+ tID,
26+ // IE 5.5 or 6
27+ IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
28+ // flag for mouse tracking
29+ track = false;
30+
31+ $.tooltip = {
32+ blocked: false,
33+ defaults: {
34+ delay: 200,
35+ fade: false,
36+ showURL: true,
37+ extraClass: "",
38+ top: 15,
39+ left: 15,
40+ id: "tooltip"
41+ },
42+ block: function() {
43+ $.tooltip.blocked = !$.tooltip.blocked;
44+ }
45+ };
46+
47+ $.fn.extend({
48+ tooltip: function(settings) {
49+ settings = $.extend({}, $.tooltip.defaults, settings);
50+ createHelper(settings);
51+ return this.each(function() {
52+ $.data(this, "tooltip", settings);
53+ this.tOpacity = helper.parent.css("opacity");
54+ // copy tooltip into its own expando and remove the title
55+ this.tooltipText = this.title;
56+ $(this).removeAttr("title");
57+ // also remove alt attribute to prevent default tooltip in IE
58+ this.alt = "";
59+ })
60+ .mouseover(save)
61+ .mouseout(hide)
62+ .click(hide);
63+ },
64+ fixPNG: IE ? function() {
65+ return this.each(function () {
66+ var image = $(this).css('backgroundImage');
67+ if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
68+ image = RegExp.$1;
69+ $(this).css({
70+ 'backgroundImage': 'none',
71+ 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
72+ }).each(function () {
73+ var position = $(this).css('position');
74+ if (position != 'absolute' && position != 'relative')
75+ $(this).css('position', 'relative');
76+ });
77+ }
78+ });
79+ } : function() { return this; },
80+ unfixPNG: IE ? function() {
81+ return this.each(function () {
82+ $(this).css({'filter': '', backgroundImage: ''});
83+ });
84+ } : function() { return this; },
85+ hideWhenEmpty: function() {
86+ return this.each(function() {
87+ $(this)[ $(this).html() ? "show" : "hide" ]();
88+ });
89+ },
90+ url: function() {
91+ return this.attr('href') || this.attr('src');
92+ }
93+ });
94+
95+ function createHelper(settings) {
96+ // there can be only one tooltip helper
97+ if( helper.parent )
98+ return;
99+ // create the helper, h3 for title, div for url
100+ helper.parent = $('<div id="' + settings.id + '"><h3></h3><div class="body"></div><div class="url"></div></div>')
101+ // add to document
102+ .appendTo(document.body)
103+ // hide it at first
104+ .hide();
105+
106+ // apply bgiframe if available
107+ if ( $.fn.bgiframe )
108+ helper.parent.bgiframe();
109+
110+ // save references to title and url elements
111+ helper.title = $('h3', helper.parent);
112+ helper.body = $('div.body', helper.parent);
113+ helper.url = $('div.url', helper.parent);
114+ }
115+
116+ function settings(element) {
117+ return $.data(element, "tooltip");
118+ }
119+
120+ // main event handler to start showing tooltips
121+ function handle(event) {
122+ // show helper, either with timeout or on instant
123+ if( settings(this).delay )
124+ tID = setTimeout(show, settings(this).delay);
125+ else
126+ show();
127+
128+ // if selected, update the helper position when the mouse moves
129+ track = !!settings(this).track;
130+ $(document.body).bind('mousemove', update);
131+
132+ // update at least once
133+ update(event);
134+ }
135+
136+ // save elements title before the tooltip is displayed
137+ function save() {
138+ // if this is the current source, or it has no title (occurs with click event), stop
139+ if ( $.tooltip.blocked || this == current || (!this.tooltipText && !settings(this).bodyHandler) )
140+ return;
141+
142+ // save current
143+ current = this;
144+ title = this.tooltipText;
145+
146+ if ( settings(this).bodyHandler ) {
147+ helper.title.hide();
148+ var bodyContent = settings(this).bodyHandler.call(this);
149+ if (bodyContent.nodeType || bodyContent.jquery) {
150+ helper.body.empty().append(bodyContent)
151+ } else {
152+ helper.body.html( bodyContent );
153+ }
154+ helper.body.show();
155+ } else if ( settings(this).showBody ) {
156+ var parts = title.split(settings(this).showBody);
157+ helper.title.html(parts.shift()).show();
158+ helper.body.empty();
159+ for(var i = 0, part; (part = parts[i]); i++) {
160+ if(i > 0)
161+ helper.body.append("<br/>");
162+ helper.body.append(part);
163+ }
164+ helper.body.hideWhenEmpty();
165+ } else {
166+ helper.title.html(title).show();
167+ helper.body.hide();
168+ }
169+
170+ // if element has href or src, add and show it, otherwise hide it
171+ if( settings(this).showURL && $(this).url() )
172+ helper.url.html( $(this).url().replace('http://', '') ).show();
173+ else
174+ helper.url.hide();
175+
176+ // add an optional class for this tip
177+ helper.parent.addClass(settings(this).extraClass);
178+
179+ // fix PNG background for IE
180+ if (settings(this).fixPNG )
181+ helper.parent.fixPNG();
182+
183+ handle.apply(this, arguments);
184+ }
185+
186+ // delete timeout and show helper
187+ function show() {
188+ tID = null;
189+ if ((!IE || !$.fn.bgiframe) && settings(current).fade) {
190+ if (helper.parent.is(":animated"))
191+ helper.parent.stop().show().fadeTo(settings(current).fade, current.tOpacity);
192+ else
193+ helper.parent.is(':visible') ? helper.parent.fadeTo(settings(current).fade, current.tOpacity) : helper.parent.fadeIn(settings(current).fade);
194+ } else {
195+ helper.parent.show();
196+ }
197+ update();
198+ }
199+
200+ /**
201+ * callback for mousemove
202+ * updates the helper position
203+ * removes itself when no current element
204+ */
205+ function update(event) {
206+ if($.tooltip.blocked)
207+ return;
208+
209+ if (event && event.target.tagName == "OPTION") {
210+ return;
211+ }
212+
213+ // stop updating when tracking is disabled and the tooltip is visible
214+ if ( !track && helper.parent.is(":visible")) {
215+ $(document.body).unbind('mousemove', update)
216+ }
217+
218+ // if no current element is available, remove this listener
219+ if( current == null ) {
220+ $(document.body).unbind('mousemove', update);
221+ return;
222+ }
223+
224+ // remove position helper classes
225+ helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");
226+
227+ var left = helper.parent[0].offsetLeft;
228+ var top = helper.parent[0].offsetTop;
229+ if (event) {
230+ // position the helper 15 pixel to bottom right, starting from mouse position
231+ left = event.pageX + settings(current).left;
232+ top = event.pageY + settings(current).top;
233+ var right='auto';
234+ if (settings(current).positionLeft) {
235+ right = $(window).width() - left;
236+ left = 'auto';
237+ }
238+ helper.parent.css({
239+ left: left,
240+ right: right,
241+ top: top
242+ });
243+ }
244+
245+ var v = viewport(),
246+ h = helper.parent[0];
247+ // check horizontal position
248+ if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
249+ left -= h.offsetWidth + 20 + settings(current).left;
250+ helper.parent.css({left: left + 'px'}).addClass("viewport-right");
251+ }
252+ // check vertical position
253+ if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
254+ top -= h.offsetHeight + 20 + settings(current).top;
255+ helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
256+ }
257+ }
258+
259+ function viewport() {
260+ return {
261+ x: $(window).scrollLeft(),
262+ y: $(window).scrollTop(),
263+ cx: $(window).width(),
264+ cy: $(window).height()
265+ };
266+ }
267+
268+ // hide helper and restore added classes and the title
269+ function hide(event) {
270+ if($.tooltip.blocked)
271+ return;
272+ // clear timeout if possible
273+ if(tID)
274+ clearTimeout(tID);
275+ // no more current element
276+ current = null;
277+
278+ var tsettings = settings(this);
279+ function complete() {
280+ helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", "");
281+ }
282+ if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
283+ if (helper.parent.is(':animated'))
284+ helper.parent.stop().fadeTo(tsettings.fade, 0, complete);
285+ else
286+ helper.parent.stop().fadeOut(tsettings.fade, complete);
287+ } else
288+ complete();
289+
290+ if( settings(this).fixPNG )
291+ helper.parent.unfixPNG();
292+ }
293+
294+})(jQuery);
--- a/pyforge/pyforge/public/nf/js/pyforge-base.js
+++ b/pyforge/pyforge/public/nf/js/pyforge-base.js
@@ -1,4 +1,10 @@
11 (function($) {
2+ // Setup label help text
3+ $('label[title]').each(function(){
4+ var $this = $(this);
5+ $this.append('<a href="#" class="help_icon ico"><b class="ui-icon ui-icon-help"></b></a>');
6+ $this.tooltip({showURL: false});
7+ });
28 // Setup title-pane widgets
39 $('.title-pane .title').click(function(e) {
410 e.preventDefault();
--- a/pyforge/pyforge/templates/master.html
+++ b/pyforge/pyforge/templates/master.html
@@ -18,6 +18,7 @@
1818 <py:for each="blob in g.resource_manager.emit('head_js')">$blob</py:for>
1919 <?python neighborhood = 'neighborhood' in locals() and neighborhood or None ?>
2020 <link rel="stylesheet" type="text/css" href="${g.forge_static('css/forge/jquery-ui-1.8rc3.custom.css')}" />
21+ <link rel="stylesheet" type="text/css" href="${g.forge_static('css/forge/jquery.tooltip.css')}" />
2122 <link py:if="not c.project and not neighborhood" rel="stylesheet" type="text/css" media="screen" href="${tg.url('/nf/site_style.css')}" />
2223 <link py:if="c.project" rel="stylesheet" type="text/css" media="screen" href="${c.project.neighborhood.url()+'site_style.css'}" />
2324 <link py:if="neighborhood" rel="stylesheet" type="text/css" media="screen" href="${neighborhood.url()+'site_style.css'}" />
@@ -62,6 +63,7 @@
6263 <script type="text/javascript" src="${g.forge_static('js/jquery-1.4.2.min.js')}"/>
6364 <script type="text/javascript" src="${g.forge_static('js/jquery-ui-1.8rc3.custom.min.js')}"></script>
6465 <script type="text/javascript" src="${g.forge_static('js/jquery.cookie.js')}"></script>
66+ <script type="text/javascript" src="${g.forge_static('js/jquery.tooltip.js')}"></script>
6567 <script type="text/javascript" src="${g.forge_static('js/pyforge-base.js')}"/>
6668 <py:for each="blob in g.resource_manager.emit('body_js')">$blob</py:for>
6769 </body>
--- a/pyforge/pyforge/templates/master_one_col.html
+++ b/pyforge/pyforge/templates/master_one_col.html
@@ -17,6 +17,7 @@
1717 <py:for each="blob in g.resource_manager.emit('head_css')">$blob</py:for>
1818 <py:for each="blob in g.resource_manager.emit('head_js')">$blob</py:for>
1919 <?python neighborhood = 'neighborhood' in locals() and neighborhood or None ?>
20+ <link rel="stylesheet" type="text/css" href="${g.forge_static('css/forge/jquery.tooltip.css')}" />
2021 <link py:if="not c.project and not neighborhood" rel="stylesheet" type="text/css" media="screen" href="${tg.url('/nf/site_style.css')}" />
2122 <link py:if="c.project" rel="stylesheet" type="text/css" media="screen" href="${c.project.neighborhood.url()+'site_style.css'}" />
2223 <link py:if="neighborhood" rel="stylesheet" type="text/css" media="screen" href="${neighborhood.url()+'site_style.css'}" />
@@ -50,6 +51,7 @@
5051 <script type="text/javascript" src="${g.forge_static('js/jquery-1.4.2.min.js')}"/>
5152 <script type="text/javascript" src="${g.forge_static('js/jquery-ui-1.8rc3.custom.min.js')}"></script>
5253 <script type="text/javascript" src="${g.forge_static('js/jquery.cookie.js')}"></script>
54+ <script type="text/javascript" src="${g.forge_static('js/jquery.tooltip.js')}"></script>
5355 <script type="text/javascript" src="${g.forge_static('js/pyforge-base.js')}"/>
5456 <py:for each="blob in g.resource_manager.emit('body_js')">$blob</py:for>
5557 </body>