Skip to content
This repository
Browse code

Initial menu items commit

  • Loading branch information...
commit c1229048514323b69a7e64fff11455d310be582d 1 parent b0f7211
Russell Branca authored November 21, 2011
10  app/controllers/admin/menu_items_controller.rb
... ...
@@ -0,0 +1,10 @@
  1
+class Admin::MenuItemsController < AdminController
  2
+
  3
+  def index
  4
+  end
  5
+
  6
+  def save
  7
+    raise params.inspect
  8
+  end
  9
+
  10
+end
2  app/models/menu_item.rb
... ...
@@ -0,0 +1,2 @@
  1
+class MenuItem < ActiveRecord::Base
  2
+end
12  app/views/admin/menu_items/index.html.haml
... ...
@@ -0,0 +1,12 @@
  1
+.main-content
  2
+  %h1 Choose your menu items
  3
+
  4
+  %ol.menu-items
  5
+    - MenuItem.all.each do |menu_item|
  6
+      %li
  7
+        .menu-item{"data-id" => menu_item.id}
  8
+          = check_box_tag menu_item.name_slug, nil, menu_item.enabled
  9
+          = menu_item.name
  10
+
  11
+  %a#toArray To Array
  12
+  %pre#toArrayOutput
1  app/views/layouts/new_admin.html.haml
@@ -12,6 +12,7 @@
12 12
     = javascript_include_tag 'hoverIntent'
13 13
     = javascript_include_tag 'superfish'
14 14
     = javascript_include_tag 'jquery.tablesorter.min'
  15
+    = javascript_include_tag 'jquery.ui.nestedSortable'
15 16
     = javascript_include_tag 'admin.js'
16 17
 
17 18
     -# IE Debugging 
1  config/routes.rb
@@ -168,6 +168,7 @@
168 168
     admin.resources :activity_scores
169 169
     admin.resources :ad_layouts
170 170
     admin.resources :ads
  171
+    admin.resources :menu_items, :collection => { :save => :post }
171 172
     admin.resources :announcements
172 173
     admin.resources :answers    
173 174
     admin.resources :cards
27  db/migrate/20111116005258_create_menu_items.rb
... ...
@@ -0,0 +1,27 @@
  1
+class CreateMenuItems < ActiveRecord::Migration
  2
+  def self.up
  3
+    create_table :menu_items do |t|
  4
+      t.string :menuitemable_type
  5
+      t.integer :menuitemable_id
  6
+      t.integer :parent_id, :default => nil
  7
+      t.boolean :enabled, :default => true
  8
+      t.integer :position, :default => 0
  9
+      t.string :resource_path, :default => nil
  10
+      t.string :url, :default => nil
  11
+      t.string :name
  12
+      t.string :name_slug
  13
+      t.string :locale_string
  14
+
  15
+      t.timestamps
  16
+    end
  17
+
  18
+    add_index :menu_items, :parent_id
  19
+    add_index :menu_items, :enabled
  20
+    add_index :menu_items, :name_slug
  21
+    add_index :menu_items, [:menuitemable_type, :menuitemable_id]
  22
+  end
  23
+
  24
+  def self.down
  25
+    drop_table :menu_items
  26
+  end
  27
+end
62  db/schema.rb
@@ -9,7 +9,7 @@
9 9
 #
10 10
 # It's strongly recommended to check this file into your version control system.
11 11
 
12  
-ActiveRecord::Schema.define(:version => 20111026003847) do
  12
+ActiveRecord::Schema.define(:version => 20111116005258) do
13 13
 
14 14
   create_table "announcements", :force => true do |t|
15 15
     t.string   "prefix"
@@ -523,6 +523,26 @@
523 523
 
524 524
   add_index "locales", ["code"], :name => "index_locales_on_code"
525 525
 
  526
+  create_table "menu_items", :force => true do |t|
  527
+    t.string   "menuitemable_type"
  528
+    t.integer  "menuitemable_id"
  529
+    t.integer  "parent_id"
  530
+    t.boolean  "enabled",           :default => true
  531
+    t.integer  "position",          :default => 0
  532
+    t.string   "resource_path"
  533
+    t.string   "url"
  534
+    t.string   "name"
  535
+    t.string   "name_slug"
  536
+    t.string   "locale_string"
  537
+    t.datetime "created_at"
  538
+    t.datetime "updated_at"
  539
+  end
  540
+
  541
+  add_index "menu_items", ["enabled"], :name => "index_menu_items_on_enabled"
  542
+  add_index "menu_items", ["menuitemable_type", "menuitemable_id"], :name => "index_menu_items_on_menuitemable_type_and_menuitemable_id"
  543
+  add_index "menu_items", ["name_slug"], :name => "index_menu_items_on_name_slug"
  544
+  add_index "menu_items", ["parent_id"], :name => "index_menu_items_on_parent_id"
  545
+
526 546
   create_table "messages", :force => true do |t|
527 547
     t.string   "subject"
528 548
     t.string   "email"
@@ -602,7 +622,6 @@
602 622
     t.boolean  "is_approved",                :default => true
603 623
     t.integer  "votes_tally",                :default => 0
604 624
     t.integer  "comments_count",             :default => 0
605  
-    t.integer  "questions_count",            :default => 0
606 625
     t.boolean  "is_blocked",                 :default => false
607 626
     t.boolean  "is_featured",                :default => false
608 627
     t.datetime "featured_at"
@@ -635,7 +654,6 @@
635 654
     t.boolean  "is_approved",              :default => true
636 655
     t.integer  "votes_tally",              :default => 0
637 656
     t.integer  "comments_count",           :default => 0
638  
-    t.integer  "guesses_count",            :default => 0
639 657
     t.boolean  "is_blocked",               :default => false
640 658
     t.boolean  "is_featured",              :default => false
641 659
     t.datetime "featured_at"
@@ -953,25 +971,25 @@
953 971
   add_index "urls", ["url"], :name => "index_urls_on_url"
954 972
 
955 973
   create_table "user_profiles", :force => true do |t|
956  
-    t.integer  "user_id",                     :limit => 8,                    :null => false
957  
-    t.integer  "facebook_user_id",            :limit => 8, :default => 0
958  
-    t.boolean  "isAppAuthorized",                          :default => false
959  
-    t.datetime "born_at"
960  
-    t.datetime "created_at",                                                  :null => false
961  
-    t.datetime "updated_at"
962  
-    t.text     "bio"
963  
-    t.integer  "referred_by_user_id",         :limit => 8, :default => 0
964  
-    t.boolean  "comment_notifications",                    :default => false
965  
-    t.boolean  "receive_email_notifications",              :default => true
966  
-    t.boolean  "dont_ask_me_for_email",                    :default => false
967  
-    t.datetime "email_last_ask"
968  
-    t.boolean  "dont_ask_me_invite_friends",               :default => false
969  
-    t.datetime "invite_last_ask"
970  
-    t.boolean  "post_comments",                            :default => true
971  
-    t.boolean  "post_likes",                               :default => true
972  
-    t.boolean  "post_items",                               :default => true
973  
-    t.boolean  "is_blocked",                               :default => false
974  
-    t.string   "profile_image"
  974
+    t.integer   "user_id",                     :limit => 8,                    :null => false
  975
+    t.integer   "facebook_user_id",            :limit => 8, :default => 0
  976
+    t.boolean   "isAppAuthorized",                          :default => false
  977
+    t.datetime  "born_at"
  978
+    t.timestamp "created_at",                                                  :null => false
  979
+    t.datetime  "updated_at"
  980
+    t.text      "bio"
  981
+    t.integer   "referred_by_user_id",         :limit => 8, :default => 0
  982
+    t.boolean   "comment_notifications",                    :default => false
  983
+    t.boolean   "receive_email_notifications",              :default => true
  984
+    t.boolean   "dont_ask_me_for_email",                    :default => false
  985
+    t.datetime  "email_last_ask"
  986
+    t.boolean   "dont_ask_me_invite_friends",               :default => false
  987
+    t.datetime  "invite_last_ask"
  988
+    t.boolean   "post_comments",                            :default => true
  989
+    t.boolean   "post_likes",                               :default => true
  990
+    t.boolean   "post_items",                               :default => true
  991
+    t.boolean   "is_blocked",                               :default => false
  992
+    t.string    "profile_image"
975 993
   end
976 994
 
977 995
   add_index "user_profiles", ["user_id"], :name => "index_user_infos_on_user_id", :unique => true
314  db/seeds.rb
@@ -1294,3 +1294,317 @@
1294 1294
     home_view_object.add_child! ViewObject.find_by_name(name)
1295 1295
   end
1296 1296
 end
  1297
+
  1298
+
  1299
+#######################################################################
  1300
+# Menu Items
  1301
+#######################################################################
  1302
+menu_items = {
  1303
+  :home => {
  1304
+    :data => {
  1305
+      :name          => "Home Page",
  1306
+      :position      => 0,
  1307
+      :resource_path => "home_index_path",
  1308
+      :locale_string => "shared.page_tabs.home"
  1309
+    }
  1310
+  },
  1311
+  :stories => {
  1312
+    :data => {
  1313
+      :name          => "Stories Page",
  1314
+      :position      => 1,
  1315
+      :resource_path => "stories_path",
  1316
+      :locale_string => "shared.page_tabs.stories"
  1317
+    },
  1318
+    :children => {
  1319
+      :stories_list => {
  1320
+        :data => {
  1321
+          :name          => "Stories Page",
  1322
+          :position      => 1,
  1323
+          :resource_path => "stories_path",
  1324
+          :locale_string => "shared.page_tabs.stories_list"
  1325
+        }
  1326
+      },
  1327
+      :newswires => {
  1328
+        :data => {
  1329
+          :name          => "Newswires Page",
  1330
+          :position      => 2,
  1331
+          :resource_path => "newswires_path",
  1332
+          :locale_string => "shared.page_tabs.newswire"
  1333
+        }
  1334
+      },
  1335
+      :new_story => {
  1336
+        :data => {
  1337
+          :name          => "New Story Page",
  1338
+          :position      => 3,
  1339
+          :resource_path => "new_story_path",
  1340
+          :locale_string => "shared.page_tabs.new_story"
  1341
+        }
  1342
+      },
  1343
+      :new_article => {
  1344
+        :data => {
  1345
+          :name          => "New Article Page",
  1346
+          :position      => 4,
  1347
+          :resource_path => "new_article_path",
  1348
+          :locale_string => "shared.page_tabs.newswire",
  1349
+          :enabled       => false
  1350
+        }
  1351
+      }
  1352
+    }
  1353
+  },
  1354
+  :articles => {
  1355
+    :data => {
  1356
+      :name          => "Articles Page",
  1357
+      :position      => 2,
  1358
+      :resource_path => "articles_path",
  1359
+      :locale_string => "shared.page_tabs.articles"
  1360
+    },
  1361
+    :children => {
  1362
+      :articles_list => {
  1363
+        :data => {
  1364
+          :name          => "Articles Page",
  1365
+          :position      => 1,
  1366
+          :resource_path => "articles_path",
  1367
+          :locale_string => "shared.page_tabs.articles_list"
  1368
+        }
  1369
+      },
  1370
+      :users_list => {
  1371
+        :data => {
  1372
+          :name          => "Users Page",
  1373
+          :position      => 2,
  1374
+          :resource_path => "users_path",
  1375
+          :locale_string => "shared.page_tabs.users_list"
  1376
+        }
  1377
+      },
  1378
+      :new_article => {
  1379
+        :data => {
  1380
+          :name          => "New Article Page",
  1381
+          :position      => 3,
  1382
+          :resource_path => "new_article_path",
  1383
+          :locale_string => "shared.page_tabs.new_article"
  1384
+        }
  1385
+      }
  1386
+    }
  1387
+  },
  1388
+  :forums => {
  1389
+    :data => {
  1390
+      :name          => "Forums Page",
  1391
+      :position      => 3,
  1392
+      :resource_path => "forums_path",
  1393
+      :locale_string => "shared.page_tabs.forums"
  1394
+    }
  1395
+  },
  1396
+  :classifieds => {
  1397
+    :data => {
  1398
+      :name          => "Classifieds Page",
  1399
+      :position      => 4,
  1400
+      :resource_path => "classifieds_path",
  1401
+      :locale_string => "shared.page_tabs.classifieds"
  1402
+    },
  1403
+    :children => {
  1404
+      :classifieds_list => {
  1405
+        :data => {
  1406
+          :name          => "Classifieds Page",
  1407
+          :position      => 1,
  1408
+          :resource_path => "classifieds_path",
  1409
+          :locale_string => "shared.page_tabs.classifieds_list"
  1410
+        }
  1411
+      },
  1412
+      :new_classified => {
  1413
+        :data => {
  1414
+          :name          => "New Classified Page",
  1415
+          :position      => 2,
  1416
+          :resource_path => "new_classified_path",
  1417
+          :locale_string => "shared.page_tabs.new_classified"
  1418
+        }
  1419
+      }
  1420
+    }
  1421
+  },
  1422
+  :questions => {
  1423
+    :data => {
  1424
+      :name          => "Questions Page",
  1425
+      :position      => 5,
  1426
+      :resource_path => "questions_path",
  1427
+      :locale_string => "shared.page_tabs.questions"
  1428
+    },
  1429
+    :children => {
  1430
+      :questions_list => {
  1431
+        :data => {
  1432
+          :name          => "Questions Page",
  1433
+          :position      => 1,
  1434
+          :resource_path => "questions_path",
  1435
+          :locale_string => "shared.page_tabs.questions_list"
  1436
+        }
  1437
+      },
  1438
+      :my_questions_list => {
  1439
+        :data => {
  1440
+          :name          => "My Questions Page",
  1441
+          :position      => 2,
  1442
+          :resource_path => "my_questions_question_path",
  1443
+          :locale_string => "questions.my_questions",
  1444
+          :enabled       => false
  1445
+        }
  1446
+      },
  1447
+      :new_question => {
  1448
+        :data => {
  1449
+          :name          => "New Question Page",
  1450
+          :position      => 3,
  1451
+          :resource_path => "new_question_path",
  1452
+          :locale_string => "shared.page_tabs.new_question"
  1453
+        }
  1454
+      }
  1455
+    }
  1456
+  },
  1457
+  :resources => {
  1458
+    :data => {
  1459
+      :name          => "Resources Page",
  1460
+      :position      => 6,
  1461
+      :resource_path => "resources_path",
  1462
+      :locale_string => "shared.page_tabs.resources"
  1463
+    },
  1464
+    :children => {
  1465
+      :resources_list => {
  1466
+        :data => {
  1467
+          :name          => "Resources Page",
  1468
+          :position      => 1,
  1469
+          :resource_path => "resources_path",
  1470
+          :locale_string => "shared.page_tabs.resources_list"
  1471
+        }
  1472
+      },
  1473
+      :new_resource => {
  1474
+        :data => {
  1475
+          :name          => "New Resource Page",
  1476
+          :position      => 2,
  1477
+          :resource_path => "new_resource_path",
  1478
+          :locale_string => "shared.page_tabs.new_resource"
  1479
+        }
  1480
+      }
  1481
+    }
  1482
+  },
  1483
+  :events => {
  1484
+    :data => {
  1485
+      :name          => "Events Page",
  1486
+      :position      => 7,
  1487
+      :resource_path => "events_path",
  1488
+      :locale_string => "shared.page_tabs.events"
  1489
+    },
  1490
+    :children => {
  1491
+      :events_list => {
  1492
+        :data => {
  1493
+          :name          => "Events Page",
  1494
+          :position      => 1,
  1495
+          :resource_path => "events_path",
  1496
+          :locale_string => "shared.page_tabs.events_list"
  1497
+        }
  1498
+      },
  1499
+      :my_events_list => {
  1500
+        :data => {
  1501
+          :name          => "My Events Page",
  1502
+          :position      => 2,
  1503
+          :resource_path => "my_events_event_path",
  1504
+          :locale_string => "share.subnav.events_subnav.my_events",
  1505
+          :enabled       => false
  1506
+        }
  1507
+      },
  1508
+      :new_event => {
  1509
+        :data => {
  1510
+          :name          => "New Event Page",
  1511
+          :position      => 3,
  1512
+          :resource_path => "new_event_path",
  1513
+          :locale_string => "shared.page_tabs.new_event"
  1514
+        }
  1515
+      }
  1516
+    }
  1517
+  },
  1518
+  :galleries => {
  1519
+    :data => {
  1520
+      :name          => "Galleries Page",
  1521
+      :position      => 8,
  1522
+      :resource_path => "galleries_path",
  1523
+      :locale_string => "shared.page_tabs.galleries"
  1524
+    },
  1525
+    :children => {
  1526
+      :galleries_list => {
  1527
+        :data => {
  1528
+          :name          => "Galleries Page",
  1529
+          :position      => 1,
  1530
+          :resource_path => "galleries_path",
  1531
+          :locale_string => "shared.page_tabs.galleries_list"
  1532
+        }
  1533
+      },
  1534
+      :new_gallery => {
  1535
+        :data => {
  1536
+          :name          => "New Gallery Page",
  1537
+          :position      => 2,
  1538
+          :resource_path => "new_gallery_path",
  1539
+          :locale_string => "shared.page_tabs.new_gallery"
  1540
+        }
  1541
+      }
  1542
+    }
  1543
+  },
  1544
+  :ideas => {
  1545
+    :data => {
  1546
+      :name          => "Ideas Page",
  1547
+      :position      => 9,
  1548
+      :resource_path => "ideas_path",
  1549
+      :locale_string => "shared.page_tabs.ideas"
  1550
+    },
  1551
+    :children => {
  1552
+      :ideas_list => {
  1553
+        :data => {
  1554
+          :name          => "Ideas Page",
  1555
+          :position      => 1,
  1556
+          :resource_path => "ideas_path",
  1557
+          :locale_string => "shared.page_tabs.ideas_list"
  1558
+        }
  1559
+      },
  1560
+      :my_ideas_list => {
  1561
+        :data => {
  1562
+          :name          => "My Ideas Page",
  1563
+          :position      => 2,
  1564
+          :resource_path => "my_ideas_idea_path",
  1565
+          :locale_string => "share.subnav.ideas_subnav.my_ideas",
  1566
+          :enabled       => false
  1567
+        }
  1568
+      },
  1569
+      :new_idea => {
  1570
+        :data => {
  1571
+          :name          => "New Idea Page",
  1572
+          :position      => 3,
  1573
+          :resource_path => "new_idea_path",
  1574
+          :locale_string => "shared.page_tabs.new_idea"
  1575
+        }
  1576
+      }
  1577
+    }
  1578
+  },
  1579
+  :predictions => {
  1580
+    :data => {
  1581
+      :name          => "Predictions Page",
  1582
+      :position      => 10,
  1583
+      :resource_path => "predictions_path",
  1584
+      :locale_string => "shared.page_tabs.predictions"
  1585
+    }
  1586
+  },
  1587
+  :cards => {
  1588
+    :data => {
  1589
+      :name          => "Cards Page",
  1590
+      :position      => 11,
  1591
+      :resource_path => "cards_path",
  1592
+      :locale_string => "cards.menu_title"
  1593
+    }
  1594
+  }
  1595
+}
  1596
+
  1597
+menu_items.each do |name, menu_item_data|
  1598
+  data = menu_item_data[:data]
  1599
+  data[:name_slug] = name.to_s
  1600
+  menu_item = MenuItem.find_or_create_by_name_slug(data)
  1601
+
  1602
+  if menu_item_data[:children].present?
  1603
+    menu_item_data[:children].each do |child_name, child_menu_item_data|
  1604
+      child_data = child_menu_item_data[:data]
  1605
+      child_data[:name_slug] = child_name.to_s
  1606
+      child_data[:parent_id] = menu_item.id
  1607
+      child_menu_item = MenuItem.find_or_create_by_name_slug(child_data)
  1608
+    end
  1609
+  end
  1610
+end
31  public/javascripts/admin.js
@@ -33,3 +33,34 @@ $(function() {
33 33
 
34 34
   }, 3500);
35 35
 });
  36
+
  37
+(function($) {
  38
+  setTimeout(function() {
  39
+    $('ol.menu-items').nestedSortable({
  40
+      disableNesting: 'no-nest',
  41
+      forcePlaceholderSize: true,
  42
+      handle: 'div.menu-item',
  43
+      helper:	'clone',
  44
+      items: 'li',
  45
+      maxLevels: 2,
  46
+      opacity: .6,
  47
+      placeholder: 'placeholder',
  48
+      revert: 250,
  49
+      tabSize: 25,
  50
+      tolerance: 'pointer',
  51
+      toleranceElement: '> div'
  52
+    });
  53
+		$('#toArray').click(function(e){
  54
+                  console.log("Dumping data");
  55
+			arraied = $('ol.menu-items').nestedSortable('toArray', {startDepthCount: 0});
  56
+                  console.log(arraied);
  57
+			//arraied = dump(arraied);
  58
+			//(typeof($('#toArrayOutput')[0].textContent) != 'undefined') ?
  59
+			//$('#toArrayOutput')[0].textContent = arraied : $('#toArrayOutput')[0].innerText = arraied;
  60
+		});
  61
+  }, 1000);
  62
+  
  63
+
  64
+
  65
+})(jQuery);
  66
+
356  public/javascripts/jquery.ui.nestedSortable.js
... ...
@@ -0,0 +1,356 @@
  1
+/*
  2
+ * jQuery UI Nested Sortable
  3
+ * v 1.3.4 / 28 apr 2011
  4
+ * http://mjsarfatti.com/sandbox/nestedSortable
  5
+ *
  6
+ * Depends:
  7
+ *	 jquery.ui.sortable.js 1.8+
  8
+ *
  9
+ * License CC BY-SA 3.0
  10
+ * Copyright 2010-2011, Manuele J Sarfatti
  11
+ */
  12
+
  13
+(function($) {
  14
+
  15
+	$.widget("ui.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
  16
+
  17
+		options: {
  18
+			tabSize: 20,
  19
+			disableNesting: 'ui-nestedSortable-no-nesting',
  20
+			errorClass: 'ui-nestedSortable-error',
  21
+			listType: 'ol',
  22
+			maxLevels: 0,
  23
+			noJumpFix: 0
  24
+		},
  25
+
  26
+		_create: function(){
  27
+			if (this.noJumpFix == false)
  28
+				this.element.height(this.element.height());
  29
+			this.element.data('sortable', this.element.data('nestedSortable'));
  30
+			return $.ui.sortable.prototype._create.apply(this, arguments);
  31
+		},
  32
+
  33
+
  34
+
  35
+		_mouseDrag: function(event) {
  36
+
  37
+			//Compute the helpers position
  38
+			this.position = this._generatePosition(event);
  39
+			this.positionAbs = this._convertPositionTo("absolute");
  40
+
  41
+			if (!this.lastPositionAbs) {
  42
+				this.lastPositionAbs = this.positionAbs;
  43
+			}
  44
+
  45
+			//Do scrolling
  46
+			if(this.options.scroll) {
  47
+				var o = this.options, scrolled = false;
  48
+				if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
  49
+
  50
+					if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
  51
+						this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
  52
+					else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
  53
+						this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
  54
+
  55
+					if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
  56
+						this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
  57
+					else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
  58
+						this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
  59
+
  60
+				} else {
  61
+
  62
+					if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
  63
+						scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
  64
+					else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
  65
+						scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
  66
+
  67
+					if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
  68
+						scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
  69
+					else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
  70
+						scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
  71
+
  72
+				}
  73
+
  74
+				if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
  75
+					$.ui.ddmanager.prepareOffsets(this, event);
  76
+			}
  77
+
  78
+			//Regenerate the absolute position used for position checks
  79
+			this.positionAbs = this._convertPositionTo("absolute");
  80
+
  81
+			//Set the helper position
  82
+			if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
  83
+			if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
  84
+
  85
+			//Rearrange
  86
+			for (var i = this.items.length - 1; i >= 0; i--) {
  87
+
  88
+				//Cache variables and intersection, continue if no intersection
  89
+				var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
  90
+				if (!intersection) continue;
  91
+
  92
+				if(itemElement != this.currentItem[0] //cannot intersect with itself
  93
+					&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
  94
+					&&	!$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
  95
+					&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
  96
+					//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
  97
+				) {
  98
+
  99
+					this.direction = intersection == 1 ? "down" : "up";
  100
+
  101
+					if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
  102
+						this._rearrange(event, item);
  103
+					} else {
  104
+						break;
  105
+					}
  106
+
  107
+					// Clear emtpy ul's/ol's
  108
+					this._clearEmpty(itemElement);
  109
+
  110
+					this._trigger("change", event, this._uiHash());
  111
+					break;
  112
+				}
  113
+			}
  114
+
  115
+			var parentItem = (this.placeholder[0].parentNode.parentNode && $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length) ? $(this.placeholder[0].parentNode.parentNode) : null;
  116
+			var level = this._getLevel(this.placeholder);
  117
+			var childLevels = this._getChildLevels(this.helper);
  118
+			var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
  119
+			if (previousItem != null) {
  120
+				while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0]) {
  121
+					if (previousItem[0].previousSibling) {
  122
+						previousItem = $(previousItem[0].previousSibling);
  123
+					} else {
  124
+						previousItem = null;
  125
+						break;
  126
+					}
  127
+				}
  128
+			}
  129
+
  130
+			newList = document.createElement(o.listType);
  131
+
  132
+			this.beyondMaxLevels = 0;
  133
+
  134
+			// If the item is moved to the left, send it to its parent level
  135
+			if (parentItem != null && this.positionAbs.left < parentItem.offset().left) {
  136
+				parentItem.after(this.placeholder[0]);
  137
+				this._clearEmpty(parentItem[0]);
  138
+				this._trigger("change", event, this._uiHash());
  139
+			}
  140
+			// If the item is below another one and is moved to the right, make it a children of it
  141
+			else if (previousItem != null && this.positionAbs.left > previousItem.offset().left + o.tabSize) {
  142
+				this._isAllowed(previousItem, level+childLevels+1);
  143
+				if (!previousItem.children(o.listType).length) {
  144
+					previousItem[0].appendChild(newList);
  145
+				}
  146
+				previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
  147
+				this._trigger("change", event, this._uiHash());
  148
+			}
  149
+			else {
  150
+				this._isAllowed(parentItem, level+childLevels);
  151
+			}
  152
+
  153
+			//Post events to containers
  154
+			this._contactContainers(event);
  155
+
  156
+			//Interconnect with droppables
  157
+			if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
  158
+
  159
+			//Call callbacks
  160
+			this._trigger('sort', event, this._uiHash());
  161
+
  162
+			this.lastPositionAbs = this.positionAbs;
  163
+			return false;
  164
+
  165
+		},
  166
+
  167
+		_mouseStop: function(event, noPropagation) {
  168
+
  169
+			// If the item is in a position not allowed, send it back
  170
+			if (this.beyondMaxLevels) {
  171
+				var parent = this.placeholder.parent().closest(this.options.items);
  172
+				
  173
+				for (var i = this.beyondMaxLevels - 1; i > 0; i--) {
  174
+					parent = parent.parent().closest(this.options.items);
  175
+				}
  176
+
  177
+				this.placeholder.removeClass(this.options.errorClass);
  178
+				parent.after(this.placeholder);
  179
+				this._trigger("change", event, this._uiHash());
  180
+			}
  181
+
  182
+			$.ui.sortable.prototype._mouseStop.apply(this, arguments);
  183
+
  184
+		},
  185
+
  186
+		serialize: function(o) {
  187
+
  188
+			var items = this._getItemsAsjQuery(o && o.connected);
  189
+			var str = []; o = o || {};
  190
+
  191
+			$(items).each(function() {
  192
+				var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
  193
+				var pid = ($(o.item || this).parent(o.listType).parent('li').attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
  194
+				if(res) str.push((o.key || res[1]+'['+(o.key && o.expression ? res[1] : res[2])+']')+'='+(pid ? (o.key && o.expression ? pid[1] : pid[2]) : 'root'));
  195
+			});
  196
+
  197
+			if(!str.length && o.key) {
  198
+				str.push(o.key + '=');
  199
+			}
  200
+
  201
+			return str.join('&');
  202
+
  203
+		},
  204
+
  205
+		toHierarchy: function(o) {
  206
+
  207
+			o = o || {};
  208
+			var sDepth = o.startDepthCount || 0;
  209
+			var ret = [];
  210
+
  211
+			$(this.element).children('li').each(function() {
  212
+				var level = _recursiveItems($(this));
  213
+				ret.push(level);
  214
+			});
  215
+
  216
+			return ret;
  217
+
  218
+			function _recursiveItems(li) {
  219
+				var id = ($(li).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
  220
+				if (id != null) {
  221
+					var item = {"id" : id[2]};
  222
+					if ($(li).children(o.listType).children('li').length > 0) {
  223
+						item.children = [];
  224
+						$(li).children(o.listType).children('li').each(function () {
  225
+							var level = _recursiveItems($(this));
  226
+							item.children.push(level);
  227
+						});
  228
+					}
  229
+					return item;
  230
+				}
  231
+			}
  232
+        },
  233
+
  234
+		toArray: function(o) {
  235
+
  236
+			o = o || {};
  237
+			var sDepth = o.startDepthCount || 0;
  238
+			var ret = [];
  239
+			var left = 2;
  240
+
  241
+			ret.push({"item_id": 'root', "parent_id": 'none', "depth": sDepth, "left": '1', "right": ($('li', this.element).length + 1) * 2});
  242
+
  243
+			$(this.element).children('li').each(function () {
  244
+				left = _recursiveArray(this, sDepth + 1, left);
  245
+			});
  246
+
  247
+			function _sortByLeft(a,b) {
  248
+				return a['left'] - b['left'];
  249
+			}
  250
+			ret = ret.sort(_sortByLeft);
  251
+
  252
+			return ret;
  253
+
  254
+			function _recursiveArray(item, depth, left) {
  255
+
  256
+				right = left + 1;
  257
+
  258
+				if ($(item).children(o.listType).children('li').length > 0) {
  259
+					depth ++;
  260
+					$(item).children(o.listType).children('li').each(function () {
  261
+						right = _recursiveArray($(this), depth, right);
  262
+					});
  263
+					depth --;
  264
+				}
  265
+
  266
+				id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
  267
+
  268
+				if (depth === sDepth + 1) pid = 'root';
  269
+				else {
  270
+					parentItem = ($(item).parent(o.listType).parent('li').attr('id')).match(o.expression || (/(.+)[-=_](.+)/));
  271
+					pid = parentItem[2];
  272
+				}
  273
+
  274
+				if (id != null) {
  275
+						ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
  276
+				}
  277
+
  278
+				return left = right + 1;
  279
+			}
  280
+
  281
+		},
  282
+
  283
+		_clear: function(event, noPropagation) {
  284
+
  285
+			$.ui.sortable.prototype._clear.apply(this, arguments);
  286
+
  287
+			// Clean last empty ul/ol
  288
+			for (var i = this.items.length - 1; i >= 0; i--) {
  289
+				var item = this.items[i].item[0];
  290
+				this._clearEmpty(item);
  291
+			}
  292
+			return true;
  293
+
  294
+		},
  295
+
  296
+		_clearEmpty: function(item) {
  297
+
  298
+			if (item.children[1] && item.children[1].children.length == 0) {
  299
+				item.removeChild(item.children[1]);
  300
+			}
  301
+
  302
+		},
  303
+
  304
+		_getLevel: function(item) {
  305
+
  306
+			var level = 1;
  307
+
  308
+			if (this.options.listType) {
  309
+					var list = item.closest(this.options.listType);
  310
+					while (!list.is('.ui-sortable')/* && level < this.options.maxLevels*/) {
  311
+							level++;
  312
+							list = list.parent().closest(this.options.listType);
  313
+					}
  314
+			}
  315
+
  316
+			return level;
  317
+		},
  318
+
  319
+		_getChildLevels: function(parent, depth) {
  320
+			var self = this,
  321
+			    o = this.options,
  322
+			    result = 0;
  323
+			depth = depth || 0;
  324
+
  325
+			$(parent).children(o.listType).children(o.items).each(function (index, child) {
  326
+					result = Math.max(self._getChildLevels(child, depth + 1), result);
  327
+			});
  328
+
  329
+			return depth ? result + 1 : result;
  330
+		},
  331
+
  332
+		_isAllowed: function(parentItem, levels) {
  333
+			var o = this.options
  334
+			// Are we trying to nest under a no-nest or are we nesting too deep?
  335
+			if (parentItem == null || !(parentItem.hasClass(o.disableNesting))) {
  336
+				if (o.maxLevels < levels && o.maxLevels != 0) {
  337
+					this.placeholder.addClass(o.errorClass);
  338
+					this.beyondMaxLevels = levels - o.maxLevels;
  339
+				} else {
  340
+					this.placeholder.removeClass(o.errorClass);
  341
+					this.beyondMaxLevels = 0;
  342
+				}
  343
+			} else {
  344
+				this.placeholder.addClass(o.errorClass);
  345
+				if (o.maxLevels < levels && o.maxLevels != 0) {
  346
+					this.beyondMaxLevels = levels - o.maxLevels;
  347
+				} else {
  348
+					this.beyondMaxLevels = 1;
  349
+				}
  350
+			}
  351
+		}
  352
+
  353
+	}));
  354
+
  355
+	$.ui.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.ui.nestedSortable.prototype.options);
  356
+})(jQuery);
11  test/fixtures/menu_items.yml
... ...
@@ -0,0 +1,11 @@
  1
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
  2
+
  3
+# This model initially had no columns defined.  If you add columns to the
  4
+# model remove the '{}' from the fixture names and add the columns immediately
  5
+# below each fixture, per the syntax in the comments below
  6
+#
  7
+one: {}
  8
+# column: value
  9
+#
  10
+two: {}
  11
+#  column: value
8  test/unit/menu_item_test.rb
... ...
@@ -0,0 +1,8 @@
  1
+require 'test_helper'
  2
+
  3
+class MenuItemTest < ActiveSupport::TestCase
  4
+  # Replace this with your real tests.
  5
+  test "the truth" do
  6
+    assert true
  7
+  end
  8
+end

0 notes on commit c122904

Please sign in to comment.
Something went wrong with that request. Please try again.