muck-contents 0.2.25 → 0.2.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. data/README.rdoc +10 -0
  2. data/VERSION +1 -1
  3. data/app/controllers/muck/contents_controller.rb +2 -1
  4. data/lib/active_record/acts/muck_content.rb +6 -0
  5. data/muck-contents.gemspec +21 -2
  6. data/test/rails_root/public/images/icon_no.gif +0 -0
  7. data/test/rails_root/public/images/icon_success.gif +0 -0
  8. data/test/rails_root/public/javascripts/jquery/fg.menu.js +517 -0
  9. data/test/rails_root/public/javascripts/muck_admin.js +13 -0
  10. data/test/rails_root/public/stylesheets/admin.css +22 -0
  11. data/test/rails_root/public/stylesheets/fgmenu/fg.menu.css +114 -0
  12. data/test/rails_root/public/stylesheets/flick/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  13. data/test/rails_root/public/stylesheets/flick/images/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  14. data/test/rails_root/public/stylesheets/flick/images/ui-bg_flat_55_ffffff_40x100.png +0 -0
  15. data/test/rails_root/public/stylesheets/flick/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  16. data/test/rails_root/public/stylesheets/flick/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  17. data/test/rails_root/public/stylesheets/flick/images/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
  18. data/test/rails_root/public/stylesheets/flick/images/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
  19. data/test/rails_root/public/stylesheets/flick/images/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
  20. data/test/rails_root/public/stylesheets/flick/images/ui-icons_0073ea_256x240.png +0 -0
  21. data/test/rails_root/public/stylesheets/flick/images/ui-icons_454545_256x240.png +0 -0
  22. data/test/rails_root/public/stylesheets/flick/images/ui-icons_666666_256x240.png +0 -0
  23. data/test/rails_root/public/stylesheets/flick/images/ui-icons_ff0084_256x240.png +0 -0
  24. data/test/rails_root/public/stylesheets/flick/images/ui-icons_ffffff_256x240.png +0 -0
  25. data/test/rails_root/public/stylesheets/flick/jquery-ui-1.8.1.custom.css +486 -0
  26. data/test/rails_root/test/functional/contents_controller_test.rb +59 -0
  27. data/test/rails_root/test/unit/content_test.rb +8 -0
  28. metadata +23 -4
data/README.rdoc CHANGED
@@ -227,6 +227,16 @@ NOTE: you must define icon, thumb, small, medium and large as styles. They can
227
227
 
228
228
  end
229
229
 
230
+ == Tips
231
+ If friendly_id starts producing errors like this then you need to redo your slugs:
232
+ ActiveRecord::StatementInvalid (Mysql::Error: Duplicate entry 'my-content-page-/-2' for key 2: UPDATE `slugs` SET `scope` = '/', `sequence` = 2 WHERE `id` = 189):
233
+
234
+ Run this and you should be good to go:
235
+ rake friendly_id:redo_slugs MODEL=Content
236
+
237
+ Cleanup old slugs with:
238
+ rake friendly_id:remove_old_slugs MODEL=Content
239
+
230
240
  == Testing
231
241
  This gem uses a full rails application in the test directory for testing and development. By default there isn't a global_config.yml setup.
232
242
  Use global_config.sample.yml to set one up.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.25
1
+ 0.2.26
@@ -106,6 +106,7 @@ class Muck::ContentsController < ApplicationController
106
106
  #
107
107
  def edit
108
108
  @page_title = @content.locale_title(I18n.locale)
109
+ @content.setup_uri_path # be sure to recover uri_path or scope will get messed up when the content is saved.
109
110
  respond_to do |format|
110
111
  format.html { render :template => @edit_template || 'contents/edit'}
111
112
  format.pjs { render :template => @edit_template || 'contents/edit', :layout => 'popup'}
@@ -214,7 +215,7 @@ class Muck::ContentsController < ApplicationController
214
215
  # Pass the numeric id to this method to ensure that the operations update and delete occur on the correct object
215
216
  def get_secure_content
216
217
  @content = Content.find(params[:id])
217
- unless @content.can_edit?(current_user)
218
+ if !@content.can_edit?(current_user)
218
219
  respond_to do |format|
219
220
  format.html do
220
221
  flash[:notice] = I18n.t('muck.contents.cant_delete_content')
@@ -141,6 +141,12 @@ module ActiveRecord
141
141
  File.join(self.scope, self.to_param)
142
142
  end
143
143
 
144
+ # uri_path is used to calculate scope on save and therefore must be recovered
145
+ # before a save is executed. Use this method to set it from the uri method.
146
+ def setup_uri_path
147
+ self.uri_path = self.class.scope_from_uri(self.uri)
148
+ end
149
+
144
150
  # get scope from the slug
145
151
  def scope
146
152
  self.slug.scope
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{muck-contents}
8
- s.version = "0.2.25"
8
+ s.version = "0.2.26"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Justin Ball", "Joel Duffin"]
12
- s.date = %q{2010-05-27}
12
+ s.date = %q{2010-07-14}
13
13
  s.email = %q{justin@tatemae.com}
14
14
  s.extra_rdoc_files = [
15
15
  "README.rdoc"
@@ -1626,6 +1626,8 @@ Gem::Specification.new do |s|
1626
1626
  "test/rails_root/public/images/file_icons/text.gif",
1627
1627
  "test/rails_root/public/images/file_icons/text.png",
1628
1628
  "test/rails_root/public/images/file_icons/word.gif",
1629
+ "test/rails_root/public/images/icon_no.gif",
1630
+ "test/rails_root/public/images/icon_success.gif",
1629
1631
  "test/rails_root/public/images/icons/accept.png",
1630
1632
  "test/rails_root/public/images/icons/add.png",
1631
1633
  "test/rails_root/public/images/icons/blue_guy.png",
@@ -2011,6 +2013,7 @@ Gem::Specification.new do |s|
2011
2013
  "test/rails_root/public/javascripts/effects.js",
2012
2014
  "test/rails_root/public/javascripts/fancyzoom.min.js",
2013
2015
  "test/rails_root/public/javascripts/jquery/colorpicker.js",
2016
+ "test/rails_root/public/javascripts/jquery/fg.menu.js",
2014
2017
  "test/rails_root/public/javascripts/jquery/jquery-ui.js",
2015
2018
  "test/rails_root/public/javascripts/jquery/jquery.autocomplete.js.readme",
2016
2019
  "test/rails_root/public/javascripts/jquery/jquery.autocomplete.min.js",
@@ -2033,6 +2036,7 @@ Gem::Specification.new do |s|
2033
2036
  "test/rails_root/public/javascripts/muck-users.js",
2034
2037
  "test/rails_root/public/javascripts/muck.js",
2035
2038
  "test/rails_root/public/javascripts/muck_activities.js",
2039
+ "test/rails_root/public/javascripts/muck_admin.js",
2036
2040
  "test/rails_root/public/javascripts/muck_time/en.js",
2037
2041
  "test/rails_root/public/javascripts/prototype.js",
2038
2042
  "test/rails_root/public/javascripts/scriptaculous.js",
@@ -3429,6 +3433,21 @@ Gem::Specification.new do |s|
3429
3433
  "test/rails_root/public/stylesheets/blueprint/src/print.css",
3430
3434
  "test/rails_root/public/stylesheets/blueprint/src/reset.css",
3431
3435
  "test/rails_root/public/stylesheets/blueprint/src/typography.css",
3436
+ "test/rails_root/public/stylesheets/fgmenu/fg.menu.css",
3437
+ "test/rails_root/public/stylesheets/flick/images/ui-bg_flat_0_aaaaaa_40x100.png",
3438
+ "test/rails_root/public/stylesheets/flick/images/ui-bg_flat_0_eeeeee_40x100.png",
3439
+ "test/rails_root/public/stylesheets/flick/images/ui-bg_flat_55_ffffff_40x100.png",
3440
+ "test/rails_root/public/stylesheets/flick/images/ui-bg_flat_75_ffffff_40x100.png",
3441
+ "test/rails_root/public/stylesheets/flick/images/ui-bg_glass_65_ffffff_1x400.png",
3442
+ "test/rails_root/public/stylesheets/flick/images/ui-bg_highlight-soft_100_f6f6f6_1x100.png",
3443
+ "test/rails_root/public/stylesheets/flick/images/ui-bg_highlight-soft_25_0073ea_1x100.png",
3444
+ "test/rails_root/public/stylesheets/flick/images/ui-bg_highlight-soft_50_dddddd_1x100.png",
3445
+ "test/rails_root/public/stylesheets/flick/images/ui-icons_0073ea_256x240.png",
3446
+ "test/rails_root/public/stylesheets/flick/images/ui-icons_454545_256x240.png",
3447
+ "test/rails_root/public/stylesheets/flick/images/ui-icons_666666_256x240.png",
3448
+ "test/rails_root/public/stylesheets/flick/images/ui-icons_ff0084_256x240.png",
3449
+ "test/rails_root/public/stylesheets/flick/images/ui-icons_ffffff_256x240.png",
3450
+ "test/rails_root/public/stylesheets/flick/jquery-ui-1.8.1.custom.css",
3432
3451
  "test/rails_root/public/stylesheets/jquery/cupertino/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png",
3433
3452
  "test/rails_root/public/stylesheets/jquery/cupertino/images/ui-bg_diagonals-thick_15_444444_40x40.png",
3434
3453
  "test/rails_root/public/stylesheets/jquery/cupertino/images/ui-bg_glass_100_f0f0f0_1x400.png",
@@ -0,0 +1,517 @@
1
+ /*--------------------------------------------------------------------
2
+ Scripts for creating and manipulating custom menus based on standard <ul> markup
3
+ Version: 3.0, 03.31.2009
4
+
5
+ By: Maggie Costello Wachs (maggie@filamentgroup.com) and Scott Jehl (scott@filamentgroup.com)
6
+ http://www.filamentgroup.com
7
+ * reference articles: http://www.filamentgroup.com/lab/jquery_ipod_style_drilldown_menu/
8
+
9
+ Copyright (c) 2009 Filament Group
10
+ Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
11
+ --------------------------------------------------------------------*/
12
+
13
+
14
+ var allUIMenus = [];
15
+
16
+ $.fn.menu = function(options){
17
+ var caller = this;
18
+ var options = options;
19
+ var m = new Menu(caller, options);
20
+ allUIMenus.push(m);
21
+
22
+ $(this)
23
+ .mousedown(function(){
24
+ if (!m.menuOpen) { m.showLoading(); };
25
+ })
26
+ .click(function(){
27
+ if (m.menuOpen == false) { m.showMenu(); }
28
+ else { m.kill(); };
29
+ return false;
30
+ });
31
+ };
32
+
33
+ function Menu(caller, options){
34
+ var menu = this;
35
+ var caller = $(caller);
36
+ var container = $('<div class="fg-menu-container ui-widget ui-widget-content ui-corner-all">'+options.content+'</div>');
37
+
38
+ this.menuOpen = false;
39
+ this.menuExists = false;
40
+
41
+ var options = jQuery.extend({
42
+ content: null,
43
+ width: 180, // width of menu container, must be set or passed in to calculate widths of child menus
44
+ maxHeight: 180, // max height of menu (if a drilldown: height does not include breadcrumb)
45
+ positionOpts: {
46
+ posX: 'left',
47
+ posY: 'bottom',
48
+ offsetX: 0,
49
+ offsetY: 0,
50
+ directionH: 'right',
51
+ directionV: 'down',
52
+ detectH: true, // do horizontal collision detection
53
+ detectV: true, // do vertical collision detection
54
+ linkToFront: false
55
+ },
56
+ showSpeed: 200, // show/hide speed in milliseconds
57
+ callerOnState: 'ui-state-active', // class to change the appearance of the link/button when the menu is showing
58
+ loadingState: 'ui-state-loading', // class added to the link/button while the menu is created
59
+ linkHover: 'ui-state-hover', // class for menu option hover state
60
+ linkHoverSecondary: 'li-hover', // alternate class, may be used for multi-level menus
61
+ // ----- multi-level menu defaults -----
62
+ crossSpeed: 200, // cross-fade speed for multi-level menus
63
+ crumbDefaultText: 'Choose an option:',
64
+ backLink: true, // in the ipod-style menu: instead of breadcrumbs, show only a 'back' link
65
+ backLinkText: 'Back',
66
+ flyOut: false, // multi-level menus are ipod-style by default; this parameter overrides to make a flyout instead
67
+ flyOutOnState: 'ui-state-default',
68
+ nextMenuLink: 'ui-icon-triangle-1-e', // class to style the link (specifically, a span within the link) used in the multi-level menu to show the next level
69
+ topLinkText: 'All',
70
+ nextCrumbLink: 'ui-icon-carat-1-e'
71
+ }, options);
72
+
73
+ var killAllMenus = function(){
74
+ $.each(allUIMenus, function(i){
75
+ if (allUIMenus[i].menuOpen) { allUIMenus[i].kill(); };
76
+ });
77
+ };
78
+
79
+ this.kill = function(){
80
+ caller
81
+ .removeClass(options.loadingState)
82
+ .removeClass('fg-menu-open')
83
+ .removeClass(options.callerOnState);
84
+ container.find('li').removeClass(options.linkHoverSecondary).find('a').removeClass(options.linkHover);
85
+ if (options.flyOutOnState) { container.find('li a').removeClass(options.flyOutOnState); };
86
+ if (options.callerOnState) { caller.removeClass(options.callerOnState); };
87
+ if (container.is('.fg-menu-ipod')) { menu.resetDrilldownMenu(); };
88
+ if (container.is('.fg-menu-flyout')) { menu.resetFlyoutMenu(); };
89
+ container.parent().hide();
90
+ menu.menuOpen = false;
91
+ $(document).unbind('click', killAllMenus);
92
+ $(document).unbind('keydown');
93
+ };
94
+
95
+ this.showLoading = function(){
96
+ caller.addClass(options.loadingState);
97
+ };
98
+
99
+ this.showMenu = function(){
100
+ killAllMenus();
101
+ if (!menu.menuExists) { menu.create() };
102
+ caller
103
+ .addClass('fg-menu-open')
104
+ .addClass(options.callerOnState);
105
+ container.parent().show().click(function(){ menu.kill(); return false; });
106
+ container.hide().slideDown(options.showSpeed).find('.fg-menu:eq(0)');
107
+ menu.menuOpen = true;
108
+ caller.removeClass(options.loadingState);
109
+ $(document).click(killAllMenus);
110
+
111
+ // assign key events
112
+ $(document).keydown(function(event){
113
+ var e;
114
+ if (event.which !="") { e = event.which; }
115
+ else if (event.charCode != "") { e = event.charCode; }
116
+ else if (event.keyCode != "") { e = event.keyCode; }
117
+
118
+ var menuType = ($(event.target).parents('div').is('.fg-menu-flyout')) ? 'flyout' : 'ipod' ;
119
+
120
+ switch(e) {
121
+ case 37: // left arrow
122
+ if (menuType == 'flyout') {
123
+ $(event.target).trigger('mouseout');
124
+ if ($('.'+options.flyOutOnState).size() > 0) { $('.'+options.flyOutOnState).trigger('mouseover'); };
125
+ };
126
+
127
+ if (menuType == 'ipod') {
128
+ $(event.target).trigger('mouseout');
129
+ if ($('.fg-menu-footer').find('a').size() > 0) { $('.fg-menu-footer').find('a').trigger('click'); };
130
+ if ($('.fg-menu-header').find('a').size() > 0) { $('.fg-menu-current-crumb').prev().find('a').trigger('click'); };
131
+ if ($('.fg-menu-current').prev().is('.fg-menu-indicator')) {
132
+ $('.fg-menu-current').prev().trigger('mouseover');
133
+ };
134
+ };
135
+ return false;
136
+ break;
137
+
138
+ case 38: // up arrow
139
+ if ($(event.target).is('.' + options.linkHover)) {
140
+ var prevLink = $(event.target).parent().prev().find('a:eq(0)');
141
+ if (prevLink.size() > 0) {
142
+ $(event.target).trigger('mouseout');
143
+ prevLink.trigger('mouseover');
144
+ };
145
+ }
146
+ else { container.find('a:eq(0)').trigger('mouseover'); }
147
+ return false;
148
+ break;
149
+
150
+ case 39: // right arrow
151
+ if ($(event.target).is('.fg-menu-indicator')) {
152
+ if (menuType == 'flyout') {
153
+ $(event.target).next().find('a:eq(0)').trigger('mouseover');
154
+ }
155
+ else if (menuType == 'ipod') {
156
+ $(event.target).trigger('click');
157
+ setTimeout(function(){
158
+ $(event.target).next().find('a:eq(0)').trigger('mouseover');
159
+ }, options.crossSpeed);
160
+ };
161
+ };
162
+ return false;
163
+ break;
164
+
165
+ case 40: // down arrow
166
+ if ($(event.target).is('.' + options.linkHover)) {
167
+ var nextLink = $(event.target).parent().next().find('a:eq(0)');
168
+ if (nextLink.size() > 0) {
169
+ $(event.target).trigger('mouseout');
170
+ nextLink.trigger('mouseover');
171
+ };
172
+ }
173
+ else { container.find('a:eq(0)').trigger('mouseover'); }
174
+ return false;
175
+ break;
176
+
177
+ case 27: // escape
178
+ killAllMenus();
179
+ break;
180
+
181
+ case 13: // enter
182
+ if ($(event.target).is('.fg-menu-indicator') && menuType == 'ipod') {
183
+ $(event.target).trigger('click');
184
+ setTimeout(function(){
185
+ $(event.target).next().find('a:eq(0)').trigger('mouseover');
186
+ }, options.crossSpeed);
187
+ };
188
+ break;
189
+ };
190
+ });
191
+ };
192
+
193
+ this.create = function(){
194
+ container.css({ width: options.width }).appendTo('body').find('ul:first').not('.fg-menu-breadcrumb').addClass('fg-menu');
195
+ container.find('ul, li a').addClass('ui-corner-all');
196
+
197
+ // aria roles & attributes
198
+ container.find('ul').attr('role', 'menu').eq(0).attr('aria-activedescendant','active-menuitem').attr('aria-labelledby', caller.attr('id'));
199
+ container.find('li').attr('role', 'menuitem');
200
+ container.find('li:has(ul)').attr('aria-haspopup', 'true').find('ul').attr('aria-expanded', 'false');
201
+ container.find('a').attr('tabindex', '-1');
202
+
203
+ // when there are multiple levels of hierarchy, create flyout or drilldown menu
204
+ if (container.find('ul').size() > 1) {
205
+ if (options.flyOut) { menu.flyout(container, options); }
206
+ else { menu.drilldown(container, options); }
207
+ }
208
+ else {
209
+ container.find('a').click(function(){
210
+ menu.chooseItem(this);
211
+ return false;
212
+ });
213
+ };
214
+
215
+ if (options.linkHover) {
216
+ var allLinks = container.find('.fg-menu li a');
217
+ allLinks.hover(
218
+ function(){
219
+ var menuitem = $(this);
220
+ $('.'+options.linkHover).removeClass(options.linkHover).blur().parent().removeAttr('id');
221
+ $(this).addClass(options.linkHover).focus().parent().attr('id','active-menuitem');
222
+ },
223
+ function(){
224
+ $(this).removeClass(options.linkHover).blur().parent().removeAttr('id');
225
+ }
226
+ );
227
+ };
228
+
229
+ if (options.linkHoverSecondary) {
230
+ container.find('.fg-menu li').hover(
231
+ function(){
232
+ $(this).siblings('li').removeClass(options.linkHoverSecondary);
233
+ if (options.flyOutOnState) { $(this).siblings('li').find('a').removeClass(options.flyOutOnState); }
234
+ $(this).addClass(options.linkHoverSecondary);
235
+ },
236
+ function(){ $(this).removeClass(options.linkHoverSecondary); }
237
+ );
238
+ };
239
+
240
+ menu.setPosition(container, caller, options);
241
+ menu.menuExists = true;
242
+ };
243
+
244
+ this.chooseItem = function(item){
245
+ // edit this for your own custom function/callback:
246
+ if ($(item).attr('alt') == "pop")
247
+ {
248
+ var d = jQuery('<div class="dialog"><div style="width:32px; margin:20px auto 0px auto"><img src="/images/loading-spinner.gif"/></div></div>').appendTo("body");
249
+ d.dialog({ modal: true, autoOpen: true, width: 'auto', title: $(item).attr('title') });
250
+ d.load($(item).attr('href'), '', function(){
251
+ d.dialog("open");
252
+ apply_ajax_forms();
253
+ });
254
+ }
255
+ else
256
+ {
257
+ location.href = $(item).attr('href');
258
+ }
259
+ menu.kill();
260
+ };
261
+ };
262
+
263
+ Menu.prototype.flyout = function(container, options) {
264
+ var menu = this;
265
+
266
+ this.resetFlyoutMenu = function(){
267
+ var allLists = container.find('ul ul');
268
+ allLists.removeClass('ui-widget-content').hide();
269
+ };
270
+
271
+ container.addClass('fg-menu-flyout').find('li:has(ul)').each(function(){
272
+ var linkWidth = container.width();
273
+ var showTimer, hideTimer;
274
+ var allSubLists = $(this).find('ul');
275
+
276
+ allSubLists.css({ left: linkWidth, width: linkWidth }).hide();
277
+
278
+ $(this).find('a:eq(0)').addClass('fg-menu-indicator').html('<span>' + $(this).find('a:eq(0)').text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>').hover(
279
+ function(){
280
+ clearTimeout(hideTimer);
281
+ var subList = $(this).next();
282
+ if (!fitVertical(subList, $(this).offset().top)) { subList.css({ top: 'auto', bottom: 0 }); };
283
+ if (!fitHorizontal(subList, $(this).offset().left + 100)) { subList.css({ left: 'auto', right: linkWidth, 'z-index': 999 }); };
284
+ showTimer = setTimeout(function(){
285
+ subList.addClass('ui-widget-content').show(options.showSpeed).attr('aria-expanded', 'true');
286
+ }, 300);
287
+ },
288
+ function(){
289
+ clearTimeout(showTimer);
290
+ var subList = $(this).next();
291
+ hideTimer = setTimeout(function(){
292
+ subList.removeClass('ui-widget-content').hide(options.showSpeed).attr('aria-expanded', 'false');
293
+ }, 400);
294
+ }
295
+ );
296
+
297
+ $(this).find('ul a').hover(
298
+ function(){
299
+ clearTimeout(hideTimer);
300
+ if ($(this).parents('ul').prev().is('a.fg-menu-indicator')) {
301
+ $(this).parents('ul').prev().addClass(options.flyOutOnState);
302
+ }
303
+ },
304
+ function(){
305
+ hideTimer = setTimeout(function(){
306
+ allSubLists.hide(options.showSpeed);
307
+ container.find(options.flyOutOnState).removeClass(options.flyOutOnState);
308
+ }, 500);
309
+ }
310
+ );
311
+ });
312
+
313
+ container.find('a').click(function(){
314
+ menu.chooseItem(this);
315
+ alert("FOO");
316
+ return false;
317
+ });
318
+ };
319
+
320
+
321
+ /* Menu.prototype.setPosition parameters (defaults noted with *):
322
+ referrer = the link (or other element) used to show the overlaid object
323
+ settings = can override the defaults:
324
+ - posX/Y: where the top left corner of the object should be positioned in relation to its referrer.
325
+ X: left*, center, right
326
+ Y: top, center, bottom*
327
+ - offsetX/Y: the number of pixels to be offset from the x or y position. Can be a positive or negative number.
328
+ - directionH/V: where the entire menu should appear in relation to its referrer.
329
+ Horizontal: left*, right
330
+ Vertical: up, down*
331
+ - detectH/V: detect the viewport horizontally / vertically
332
+ - linkToFront: copy the menu link and place it on top of the menu (visual effect to make it look like it overlaps the object) */
333
+
334
+ Menu.prototype.setPosition = function(widget, caller, options) {
335
+ var el = widget;
336
+ var referrer = caller;
337
+ var dims = {
338
+ refX: referrer.offset().left,
339
+ refY: referrer.offset().top,
340
+ refW: referrer.getTotalWidth(),
341
+ refH: referrer.getTotalHeight()
342
+ };
343
+ var options = options;
344
+ var xVal, yVal;
345
+
346
+ var helper = $('<div class="positionHelper"></div>');
347
+ helper.css({ position: 'absolute', left: dims.refX, top: dims.refY, width: dims.refW, height: dims.refH });
348
+ el.wrap(helper);
349
+
350
+ // get X pos
351
+ switch(options.positionOpts.posX) {
352
+ case 'left': xVal = 0;
353
+ break;
354
+ case 'center': xVal = dims.refW / 2;
355
+ break;
356
+ case 'right': xVal = dims.refW;
357
+ break;
358
+ };
359
+
360
+ // get Y pos
361
+ switch(options.positionOpts.posY) {
362
+ case 'top': yVal = 0;
363
+ break;
364
+ case 'center': yVal = dims.refH / 2;
365
+ break;
366
+ case 'bottom': yVal = dims.refH;
367
+ break;
368
+ };
369
+
370
+ // add the offsets (zero by default)
371
+ xVal += options.positionOpts.offsetX;
372
+ yVal += options.positionOpts.offsetY;
373
+
374
+ // position the object vertically
375
+ if (options.positionOpts.directionV == 'up') {
376
+ el.css({ top: 'auto', bottom: yVal });
377
+ if (options.positionOpts.detectV && !fitVertical(el)) {
378
+ el.css({ bottom: 'auto', top: yVal });
379
+ }
380
+ }
381
+ else {
382
+ el.css({ bottom: 'auto', top: yVal });
383
+ if (options.positionOpts.detectV && !fitVertical(el)) {
384
+ el.css({ top: 'auto', bottom: yVal });
385
+ }
386
+ };
387
+
388
+ // and horizontally
389
+ if (options.positionOpts.directionH == 'left') {
390
+ el.css({ left: 'auto', right: xVal });
391
+ if (options.positionOpts.detectH && !fitHorizontal(el)) {
392
+ el.css({ right: 'auto', left: xVal });
393
+ }
394
+ }
395
+ else {
396
+ el.css({ right: 'auto', left: xVal });
397
+ if (options.positionOpts.detectH && !fitHorizontal(el)) {
398
+ el.css({ left: 'auto', right: xVal });
399
+ }
400
+ };
401
+
402
+ // if specified, clone the referring element and position it so that it appears on top of the menu
403
+ if (options.positionOpts.linkToFront) {
404
+ referrer.clone().addClass('linkClone').css({
405
+ position: 'absolute',
406
+ top: 0,
407
+ right: 'auto',
408
+ bottom: 'auto',
409
+ left: 0,
410
+ width: referrer.width(),
411
+ height: referrer.height()
412
+ }).insertAfter(el);
413
+ };
414
+ };
415
+
416
+
417
+ /* Utilities to sort and find viewport dimensions */
418
+
419
+ function sortBigToSmall(a, b) { return b - a; };
420
+
421
+ jQuery.fn.getTotalWidth = function(){
422
+ return $(this).width() + parseInt($(this).css('paddingRight')) + parseInt($(this).css('paddingLeft')) + parseInt($(this).css('borderRightWidth')) + parseInt($(this).css('borderLeftWidth'));
423
+ };
424
+
425
+ jQuery.fn.getTotalHeight = function(){
426
+ return $(this).height() + parseInt($(this).css('paddingTop')) + parseInt($(this).css('paddingBottom')) + parseInt($(this).css('borderTopWidth')) + parseInt($(this).css('borderBottomWidth'));
427
+ };
428
+
429
+ function getScrollTop(){
430
+ return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
431
+ };
432
+
433
+ function getScrollLeft(){
434
+ return self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
435
+ };
436
+
437
+ function getWindowHeight(){
438
+ var de = document.documentElement;
439
+ return self.innerHeight || (de && de.clientHeight) || document.body.clientHeight;
440
+ };
441
+
442
+ function getWindowWidth(){
443
+ var de = document.documentElement;
444
+ return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
445
+ };
446
+
447
+ /* Utilities to test whether an element will fit in the viewport
448
+ Parameters:
449
+ el = element to position, required
450
+ leftOffset / topOffset = optional parameter if the offset cannot be calculated (i.e., if the object is in the DOM but is set to display: 'none') */
451
+
452
+ function fitHorizontal(el, leftOffset){
453
+ var leftVal = parseInt(leftOffset) || $(el).offset().left;
454
+ return (leftVal + $(el).width() <= getWindowWidth() + getScrollLeft() && leftVal - getScrollLeft() >= 0);
455
+ };
456
+
457
+ function fitVertical(el, topOffset){
458
+ var topVal = parseInt(topOffset) || $(el).offset().top;
459
+ return (topVal + $(el).height() <= getWindowHeight() + getScrollTop() && topVal - getScrollTop() >= 0);
460
+ };
461
+
462
+ /*--------------------------------------------------------------------
463
+ * javascript method: "pxToEm"
464
+ * by:
465
+ Scott Jehl (scott@filamentgroup.com)
466
+ Maggie Wachs (maggie@filamentgroup.com)
467
+ http://www.filamentgroup.com
468
+ *
469
+ * Copyright (c) 2008 Filament Group
470
+ * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
471
+ *
472
+ * Description: Extends the native Number and String objects with pxToEm method. pxToEm converts a pixel value to ems depending on inherited font size.
473
+ * Article: http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/
474
+ * Demo: http://www.filamentgroup.com/examples/pxToEm/
475
+ *
476
+ * Options:
477
+ scope: string or jQuery selector for font-size scoping
478
+ reverse: Boolean, true reverses the conversion to em-px
479
+ * Dependencies: jQuery library
480
+ * Usage Example: myPixelValue.pxToEm(); or myPixelValue.pxToEm({'scope':'#navigation', reverse: true});
481
+ *
482
+ * Version: 2.0, 08.01.2008
483
+ * Changelog:
484
+ * 08.02.2007 initial Version 1.0
485
+ * 08.01.2008 - fixed font-size calculation for IE
486
+ --------------------------------------------------------------------*/
487
+
488
+ Number.prototype.pxToEm = String.prototype.pxToEm = function(settings){
489
+ //set defaults
490
+ settings = jQuery.extend({
491
+ scope: 'body',
492
+ reverse: false
493
+ }, settings);
494
+
495
+ var pxVal = (this == '') ? 0 : parseFloat(this);
496
+ var scopeVal;
497
+ var getWindowWidth = function(){
498
+ var de = document.documentElement;
499
+ return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
500
+ };
501
+
502
+ /* When a percentage-based font-size is set on the body, IE returns that percent of the window width as the font-size.
503
+ For example, if the body font-size is 62.5% and the window width is 1000px, IE will return 625px as the font-size.
504
+ When this happens, we calculate the correct body font-size (%) and multiply it by 16 (the standard browser font size)
505
+ to get an accurate em value. */
506
+
507
+ if (settings.scope == 'body' && $.browser.msie && (parseFloat($('body').css('font-size')) / getWindowWidth()).toFixed(1) > 0.0) {
508
+ var calcFontSize = function(){
509
+ return (parseFloat($('body').css('font-size'))/getWindowWidth()).toFixed(3) * 16;
510
+ };
511
+ scopeVal = calcFontSize();
512
+ }
513
+ else { scopeVal = parseFloat(jQuery(settings.scope).css("font-size")); };
514
+
515
+ var result = (settings.reverse == true) ? (pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em';
516
+ return result;
517
+ };
@@ -0,0 +1,13 @@
1
+ jQuery(function(){
2
+ // BUTTONS
3
+ jQuery('.fg-button').hover(
4
+ function(){ jQuery(this).removeClass('ui-state-default').addClass('ui-state-focus'); },
5
+ function(){ jQuery(this).removeClass('ui-state-focus').addClass('ui-state-default'); }
6
+ );
7
+ jQuery('.flat').each(function() {
8
+ jQuery(this).menu({
9
+ content: jQuery(this).next().html(), // grab content from this page
10
+ showSpeed: 200
11
+ });
12
+ });
13
+ });
@@ -31,6 +31,8 @@ ul.admin-list li a{font-size:1.2em;}
31
31
  #admin-messages{display:none;}
32
32
  /* ui elements */
33
33
  #ui-datepicker-div{z-index:2005;}
34
+ /* jquery-ui theme overrides */
35
+ .ui-widget {font-size:.8em;}
34
36
  /* tables */
35
37
  .adminTable{margin:5px 0 0 0;padding:0 0 40px 0px;width:980px;}
36
38
  .adminTable a{color:#000;text-decoration:none;font-weight:bold;}
@@ -38,3 +40,23 @@ ul.admin-list li a{font-size:1.2em;}
38
40
  .adminTable tr{background-color:#fff;}
39
41
  .adminTable table{border:2px solid #c4ad63;}
40
42
  .adminTable tr td{font-size:1.1em;font-weight:bold;padding:5px;border-bottom:1px solid #eee;}
43
+ /* menu styles*/
44
+ .hidden { position:absolute; top:0; left:-9999px; width:1px; height:1px; overflow:hidden; }
45
+ .fg-button { font-size:11px; clear:left; padding: .4em 1em; text-decoration:none !important; cursor:pointer; position: relative; text-align: center; zoom: 1; }
46
+ .fg-button .ui-icon { position: absolute; top: 50%; margin-top: -8px; left: 50%; margin-left: -8px; }
47
+ a.fg-button { float:left; }
48
+ button.fg-button { width:auto; overflow:visible; } /* removes extra button width in IE */
49
+ .fg-button-icon-left { padding-left: 2.1em; }
50
+ .fg-button-icon-right { padding-right: 2.1em; }
51
+ .fg-button-icon-left .ui-icon { right: auto; left: .2em; margin-left: 0; }
52
+ .fg-button-icon-right .ui-icon { left: auto; right: .2em; margin-left: 0; }
53
+ .fg-button-icon-solo { display:block; width:8px; text-indent: -9999px; } /* solo icon buttons must have block properties for the text-indent to work */
54
+ .fg-button.ui-state-loading .ui-icon { background: url(spinner_bar.gif) no-repeat 0 0;}
55
+ /*tabs*/
56
+ .tabs{font-size:1.2em;border-bottom:solid 2px #000;position:relative;}
57
+ .tabs ul{list-style-type:none;}
58
+ .tabs ul li{float:left;display:inline;margin-right:20px;}
59
+ .tabs ul li a{color:#000;text-decoration:none;}
60
+ .tabs ul li a:hover{color:#333;}
61
+ .tabs ul li a.active{background-position:0 bottom;color:#fff;}
62
+ .tabs ul li a.active span{background-position:right bottom;}