From af87c9db473e8db354cb13b6b2c630d97514b827 Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Sun, 19 Oct 2014 17:15:22 +0100 Subject: [PATCH 001/143] Remove debugger gem It wouldn't install under Ruby 2.1.2, and we weren't using it anyway. --- Gemfile | 3 --- Gemfile.lock | 8 -------- 2 files changed, 11 deletions(-) diff --git a/Gemfile b/Gemfile index 2360041eb..124c1f4f9 100644 --- a/Gemfile +++ b/Gemfile @@ -80,9 +80,6 @@ gem 'flickraw' # To use debugger group :development do - # Installation of the debugger gem fails on Travis CI, - # so we don't use it in the test environment - gem 'debugger' # A debugger and irb alternative. Pry doesn't play nice # with unicorn, so start a Webrick server when debugging # with Pry diff --git a/Gemfile.lock b/Gemfile.lock index fae16d6ad..6f6b7d1a5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,7 +77,6 @@ GEM coffee-script-source execjs coffee-script-source (1.8.0) - columnize (0.8.9) commonjs (0.2.7) compass (0.12.7) chunky_png (~> 1.2) @@ -96,12 +95,6 @@ GEM dalli (2.7.2) database_cleaner (1.3.0) debug_inspector (0.0.2) - debugger (1.6.8) - columnize (>= 0.3.1) - debugger-linecache (~> 1.2.0) - debugger-ruby_core_source (~> 1.3.5) - debugger-linecache (1.2.0) - debugger-ruby_core_source (1.3.5) devise (3.2.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -336,7 +329,6 @@ DEPENDENCIES csv_shaper dalli database_cleaner (~> 1.3.0) - debugger devise (~> 3.2.0) factory_girl_rails (~> 4.0) figaro From 3d105533737306174fa2f1b8f2678ce402ded436 Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Sun, 19 Oct 2014 17:16:04 +0100 Subject: [PATCH 002/143] Add Rake task to load altnames. --- lib/tasks/growstuff.rake | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index f19bf1fed..0e0555949 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -270,6 +270,36 @@ namespace :growstuff do p.save end end + + desc "October 2014: add alternate names for crops" + task :add_alternate_names_for_crops => :environment do + require 'csv' + @file = ENV['file'] or raise "Usage: rake growstuff:oneoff:add_alternate_names_for_crops file=file.csv" + puts "Loading alternate names from #{@file}..." + cropbot = Member.find_by_login_name("cropbot") + CSV.foreach(@file) do |row| + crop_id, crop_name, alternate_names = row + if crop_name.blank? or alternate_names.blank? then + next + end + crop = Crop.find_by_name(crop_name) + if crop.nil? then + puts "Couldn't find crop #{crop_name}" + next + end + if crop.id.to_s != crop_id then + puts "crop #{crop} has ID #{crop.id}, expected #{crop_id}" + end + alternate_names.split(/,\s*/).each do |an| + puts "Adding alternate name '#{an}' to #{crop}" + AlternateName.create( + name: an, + crop_id: crop.id, + creator_id: cropbot.id + ) + end + end + end end # end oneoff section end From 0aea1721d82159bd76c4ec104bc911adbfbf443e Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Sun, 19 Oct 2014 17:22:34 +0100 Subject: [PATCH 003/143] Add altname data and include load in deploy-tasks. --- db/seeds/alternate_names_201410.csv | 383 ++++++++++++++++++++++++++++ lib/tasks/growstuff.rake | 4 +- script/deploy-tasks.sh | 3 + 3 files changed, 388 insertions(+), 2 deletions(-) create mode 100644 db/seeds/alternate_names_201410.csv diff --git a/db/seeds/alternate_names_201410.csv b/db/seeds/alternate_names_201410.csv new file mode 100644 index 000000000..0430b5c2d --- /dev/null +++ b/db/seeds/alternate_names_201410.csv @@ -0,0 +1,383 @@ +Id,Name,Alternate names (comma separated) +1,achiote,"aploppas, uruku" +2,ackee,"achee, ackee apple, akee" +267,acorn squash,"pepper squash, Des Moines squash" +3,acuyo,"yerba santa, hierba santa, Mexican pepperleaf, tlanepa, anisillo, root beer plant, sacred pepper" +345,adjuma pepper,"adjoema, ojemma, aji umba" +346,ají dulce pepper, +312,Aleppo pepper, +4,alexanders,"alisanders, horse parsley, smyrnium" +5,alfalfa,lucerne +6,allspice,"Jamaica pepper, pepper, myrtle pepper, pimenta, pimento, English pepper, newspice" +7,almond, +254,aloe vera, +8,amaranth, +313,Anaheim pepper,New Mexico pepper +9,anise,aniseed +10,apple, +11,apple mint, +12,apricot, +13,arrowroot,"maranta, West Indian arrowroot, obedience plant, Bermuda arrowroot, araru, ararao, hulankeeriya" +14,artichoke, +15,arugula,"salad rocket, rucola, rucoli, rugula, colewort, roquette" +16,asparagus, +17,avocado, +271,bamboo, +18,banana, +314,banana pepper,"yellow wax pepper, banana chili" +19,barley, +20,basil,sweet basil +21,bay,"bay laurel, sweet bay, bay, true laurel, Grecian laurel,[1] laurel tree, laurel" +22,bean, +23,beet,"beetroot, table beet, garden beet, red beet, golden beet" +24,bell pepper,"sweet pepper, pepper, capsicum" +353,bhut jolokia pepper,"ghost pepper, ghost chili pepper, red naga chilli, ghost chilli" +241,bilberry,"common bilberry, blue whortleberry, whortleberry, European blueberry, blaeberry, hurtleberry, huckleberry, winberry, fraughan" +315,bird's eye chili,"bird's chili, Thai chili" +340,bishop's crown pepper,"Christmas bell pepper, peri peri, joker's hat pepper" +25,bitter melon,"bitter gourd, bitter squash, goya, karela" +351,black habanero pepper, +248,black mint,"southern cone marigold, stinking roger" +371,black-eyed pea,black-eyed bean +26,blackberry, +27,blackcurrant, +240,blueberry, +236,bok choy,Chinese cabbage +28,borage,starflower +270,brassica, +343,Brazilian starfish, +29,breadfruit, +30,broccoli, +31,Brussels sprout, +32,buckwheat, +286,burdock,"greater burdock, gobō,edible burdock, lappa, beggar's buttons" +265,butternut squash,butternut pumpkin +33,cabbage, +355,cachucha pepper,"Boabs Bonnet, Scotty Bons, Bonney peppers, Caribbean red peppers" +273,cantaloupe,"cantelope, cantaloup, muskmelon, mushmelon, rockmelon, sweet melon, Persian melon, spanspek" +34,cape gooseberry,"Cape gooseberry, Inca berry, Aztec berry, golden berry, giant ground cherry, African ground cherry, Peruvian groundcherry, Peruvian cherry, love-in-a-cage, physalis" +35,caper,Flinders rose +306,Capsicum, +307,Capsicum annuum, +308,Capsicum baccatum, +309,Capsicum chinense,yellow lantern chili +311,Capsicum frutescens, +36,cardoon,"artichoke thistle, cardone, cardoni, carduni, cardi" +37,carrot, +316,cascabel chili,rattle chili +38,cassava,"manioc, yuca, mandioca, tapioca-root, kappa, manioc root" +39,catnip,"catswort, catmint" +40,cauliflower, +264,cavalo nero, borecole +41,cayenne pepper,"Guinea spice, cow-horn pepper, aleva, bird pepper, red pepper" +42,celeriac," turnip-rooted celery, knob celery, celery root" +43,celery, +374,celtuce,"stem lettuce, celery lettuce, asparagus lettuce, Chinese lettuce" +44,chamomile,"camomile, German chamomile, Hungarian chamomile, wild chamomile, scented mayweed" +244,chard,"Swiss chard, silverbeet, crab beet, bright lights, seakale beet, mangold" +45,chaya,tree spinach +46,chayote,"christophene, christophine, cho-cho, mirliton, merleton, chuchu, pear squash, vegetable pear, chouchoute, choko, ishkus, chowchow" +47,cherry, +48,chervil,"garden chervil, French parsley" +49,chestnut, +50,chickpeas,"garbanzo, garbanzo bean, ceci, cece, channa, Bengal gram" +51,chickweed,stitchwort +52,chicory, +321,chile de árbol pepper,"bird's beak chile, rat's tail chile" +318,chiltepin pepper,"chiltepin, chiltepe, chile tepin, turkey, bird’s eye, bird peppers" +53,chinese cabbage,"napa cabbage, bok choy" +54,chives, +237,choy sum,"choi sum, Chinese flowering cabbage" +319,Chungyang red pepper, +55,cicely,sweet cicely +56,citron, +57,coconut, +232,coffee, +58,collard greens,Dalmatian cabbage +59,comfrey,comphrey +304,common mushroom,"button mushroom, white mushroom, cultivated mushroom, table mushroom, champignon mushroom, Swiss brown mushroom, Roman brown mushroom, Italian brown, Italian mushroom, cremini mushroom, crimini mushroom, brown cap mushroom, chestnut mushroom, portobello mushroom" +60,coriander,"cilantro, Chinese parsley, dhania" +61,corn,maize +62,corn salad,"lamb's lettuce, fetticus, nut lettuce, field salad, rapunzel" +372,cowpea, +63,cress,"mustard and cress, garden pepper cress, pepperwort, pepper grass, poor man's pepper" +320,cubanelle pepper,Cuban pepper +261,cucamelon,"mouse melon, Mexican sour gherkin, cucamelon, Mexican miniature watermelon, Mexican sour cucumber" +64,cucumber, +65,cumin,jeera +66,cumquat,kumquat +67,curry leaf, +68,curry plant, +69,daikon,"daikon radish, mooli, white radish, winter radish, Oriental radish, long white radish, Japanese radish, Chinese white radish" +70,dandelion, +71,dates, +347,datil pepper, +72,desert lime, +73,dill, +74,dog rose, +322,dundicut, +75,durian, +76,eggplant,"aubergine, melongene, garden egg, guinea squash" +77,elderberry,"elder, black elder, European elder, European elderberry, European black elderberry" +249,elecampane,"horse-heal, elfdock" +78,endive, +79,epazote,"wormseed, Jesuit's tea, Mexican tea" +323,facing heaven pepper, +348,fatalii pepper, +80,fava bean,"broad bean, fava bean, field bean, bell bean, tic bean" +81,feijoa,"pineapple guava, guavasteen" +82,fennel, +83,fenugreek,methi +84,fiddlehead,fiddlehead greens +85,fig, +86,flax,linseed +324,Fresno pepper, +366,fuzzy kiwifruit, +87,garlic, +88,garlic chives,"Chinese chives, Oriental garlic, Chinese leek, kow choi, gau choy, nira" +89,ginger, +285,goji,wolfberry +367,golden kiwifruit, +364,Good King Henry,"poor-man's asparagus, perennial goosefoot, Lincolnshire spinach, markery" +90,gooseberry, +91,grapefruit, +92,grapes, +325,guajillo pepper, +93,guava, +326,Guntur Sannam chili, +94,habanero, +350,habanero pepper, +358,Hainan yellow lantern,yellow emperor chili +368,hardy kiwifruit,"kiwi berry, arctic kiwi, baby kiwi, dessert kiwi, grape kiwi, northern kiwi, cocktail kiwi" +369,hazelnut,"cobnut, filbert nut" +95,hibiscus,rose mallow +275,honeydew melon, +253,hops, +96,horseradish, +327,Hungarian wax pepper, +283,ice plant,"highway ice plant, pigface, Hottentot fig, sour fig" +328,Italian sweet pepper, +329,jalapeño pepper, +97,jasmine, +98,Jerusalem artichoke,"sunroot, sunchoke, earth apple, topinambour" +99,jicama,"Mexican yam, Mexican turnip" +100,juniper berry, +268,kabocha,"danhobak, fak thong, Japanese pumpkin, kabocha squash" +101,kaffir lime,makrut lime +102,kale, +363,kambuzi, +103,kava, +365,kiwifruit,"kiwi, Chinese gooseberry" +104,kohlrabi,"German turnip, turnip cabbage" +250,lady's bedstraw,yellow bedstraw +259,land cress,"American cress, bank cress, black wood cress, Belle Isle cress, Bermuda cress, early yellowrocket, early wintercress, scurvy cress, creasy greens, upland cress" +105,lavender, +106,leek, +107,lemon, +108,lemon balm,"balm, balm mint" +341,lemon drop pepper,hot lemon pepper +109,lemon myrtle,"lemon myrtle, lemon scented myrtle, lemon scented ironwood, sweet verbena tree, sweet verbena myrtle, lemon scented verbena, lemon scented backhousia" +110,lemon verbena,lemon beebrush +111,lemongrass,"barbed wire grass, silky heads, citronella grass, fever grass" +112,lentils, +113,lettuce, +114,licorice,liquorice +115,lillipilli,"riberry, small leaved lilly pilly, cherry satinash, cherry alder, clove lilli pilli" +116,lima bean,butter bean +117,lime, +238,loquat,"Japanese medlar, Japanese plum, Chinese plum" +118,lovage, +119,luffa,loofah +287,lupin,lupine +120,lupin bean,lupini bean +121,macadamia,"Queensland nut, bush nut, maroochi nut, bauple nut, Hawaii nut" +349,Madame Jeanette pepper,Suriname yellow pepper +122,Malabar spinach,"pui, vine spinach, red vine spinach, climbing spinach, creeping spinach, buffalo spinach, malabar spinach, ceylon spinach" +361,malagueta pepper,"malaguetinha pepper, piri piri pepper" +123,mandarin,"mandarin orange, mandarine" +124,mango, +125,maracuja,"passion fruit, passionfruit, purple granadilla" +126,marjoram,"sweet marjoram, knotted marjoram" +127,marshmallow,"marsh mallow, common marshmallow" +128,medlar,common medlar +331,medusa pepper, +129,melon, +252,Mexican tarragon,"yerbaniz, Mexican marigold, Mexican mint marigold, Mexican tarragon, Spanish tarragon, Texas tarragon" +257,Meyer lemon, +292,midgen berry,midyim +276,milkweed, +130,miner's lettuce,"spring beauty, winter purslane, Indian lettuce" +131,mint,"spearmint, spear mint" +235,mizuna,"shui cai, kyona, Japanese mustard, potherb mustard, Japanese greens, California peppergrass, spider mustard" +279,moringa, +332,mulato pepper, +234,mulberry, +132,mung bean,"moong bean, green gram, golden gram" +284,murnong,yam daisy +303,mushroom, +274,muskmelon, +133,mustard, +375,myoga ginger,Japanese ginger +298,naranjilla,lulo +134,nasturtium, +277,native ginger, +290,nectarine, +246,nettle, +135,New Zealand spinach, +136,nigella," fennel flower, nutmeg flower, black caraway, Roman coriander" +137,oats, +289,Okinawan spinach,edible gynura +138,okra,"ladies' fingers, bhindi, bamia, gumbo" +139,olive, +302,olive herb,holy flax +140,onion,"bulb onion, common onion" +141,orange,sweet orange +142,oregano,wild marjoram +297,pandan,pandan leaves +143,parsley, +144,parsnip, +317,pasilla pepper,"chile negro, chilaca" +145,passion fruit,"passionfruit, purple granadilla" +269,patty-pan squash,"scallop squash, sunburst squash, granny squash, custard marrow, custard squash, white squash, scallopini, schwoughksie squash" +146,pea, +147,peach, +149,peanut,groundnut +150,pear, +151,pearl millet,"cattail millet, candle millet, dark millet" +152,pecan, +334,peperoncini pepper, +342,peppadew pepper, +153,peppermint, +335,pequin pepper,piquin pepper +291,perilla, +263,perpetual spinach,spinach beet +154,Persian lime,"shiraz limoo,Tahiti lime, Bearss lime" +155,persimmon, +333,peter pepper, +156,pigeon pea,"kardis, gandule bean, tropical green pea, kadios, Congo pea, gungo pea, gunga pea, no-eye pea" +157,pigface,angular sea-fig +336,pimento pepper,"pimiento pepper, cherry pepper" +158,pineapple, +359,piri-piri pepper,"peri peri, pili pili, African bird's eye chili" +159,pistachio, +160,plantain,cooking plaintain +161,plum, +337,poblano pepper,"ancho pepper, ancho chile pepper" +162,pomegranate, +163,pomelo,"shaddock, pummelo, pommelo, lusho fruit" +247,pot marigold,"ruddles, common marigold, garden marigold, English marigold, Scottish marigold" +164,potato, +165,prickly pear, +166,pumpkin, +167,purslane,"common purslane, verdolaga, pigweed, little hogweed, red root, pursley, moss rose" +168,quandong,"desert quandong, native peach" +169,quince, +170,quinoa, +171,radicchio,Italian chicory +172,radish, +262,rainbow chard, +173,rapeseed,"rape, oilseed rape, rapa, rappi, rapaseed" +243,rapini,"broccoli raab, broccoli rabe" +174,raspberry,"red raspberry, European raspberry" +352,red savino pepper, +293,redcurrant,red currant +175,rhubarb, +176,rice, +177,rice bean,ricebean +310,rocoto,"rukutu, ruqutu, luqutu" +370,romaine lettuce,cos lettuce +178,rose, +255,rose geranium,"rose geranium, old fashioned rose geranium, rose-scent geranium" +179,roselle,"rosella, rosella fruit, carcade, " +180,rosemary,anthos +281,ruby saltbush,barrier saltbush +181,rue,"common rue, herb-of-grace" +182,runner bean,"scarlet runner bean, multiflora bean" +183,rutabaga,"swede, turnip, yellow turnip, neep" +184,rye, +185,safflower, +186,saffron, +187,sage,"garden sage, common sage" +188,salad burnet,"garden burnet, small burnet, burnet" +189,salsify, +190,samphire,"rock samphire, sea fennel" +338,Santa Fe Grande pepper,"yellow hot chili pepper, guero chili pepper" +191,sassafras,"white sassafras, red sassafras, silky sassafras" +295,scallion,"green onion, spring onion, salad onion, table onion, green shallot, onion stick, long onion, baby onion, precious onion, yard onion, gibbon, syboe, scally onion" +354,Scotch bonnet pepper,"Boabs bonnet, Scotty bons, bonney peppers, Caribbean red peppers" +339,serrano pepper, +192,sesame, +193,shallot, +305,shiitake,"Sawtooth oak mushroom, black forest mushroom, black mushroom, golden oak mushroom, oakwood mushroom" +330,shishito pepper, +362,siling labuyo pepper, +373,snap pea,"sugar snap peas, mangetout" +260,snow pea,mangetout +194,sorghum, +195,sorrel,"common sorrel, garden sorrel, spinach dock, narrow-leaved dock" +196,soursop,Brazilian pawpaw +197,soybean,soya bean +266,spaghetti squash,"vegetable spaghetti, noodle squash, vegetable marrow, spaghetti marrow, squaghetti" +198,spearmint,spear mint +199,spinach, +251,squash, +200,star anise,"star aniseed, Chinese star anise" +201,starfruit,carambola +202,stevia, +203,strawberry,garden strawberry +204,summer savory, +205,sunflower, +206,sweet potato,kumara +207,Swiss chard,chard +360,Tabasco pepper, +208,tamarillo,"tree tomato, tamamoro" +209,tamarind, +210,tangerine, +211,tansy,"common tansy, bitter buttons, cow bitter, mugwort, golden buttons" +212,taro, +213,tarragon, +242,tatsoi,"spinach mustard, spoon mustard, rosette bok choy" +233,tea, +214,thyme, +215,tomatillo,"husk tomato, mexican husk tomato" +216,tomato, +357,Trinidad Moruga scorpion pepper, +356,Trinidad scorpion butch T pepper, +217,turmeric, +218,turnip,white turnip +219,urad bean,"urad dal, black gram, black lentil, white lentil, black matpe bean" +220,valerian,"garden valerian, garden heliotrope, all-heal" +221,vanilla, +239,Vietnamese mint,"Vietnamese mint, Vietnamese cilantro, Cambodian mint, hot mint" +222,walnut, +223,wasabi,Japanese horseradish +301,water caltrop,"water caltrop, water chestnut, buffalo nut, bat nut, devil pod, ling nut" +300,water chestnut,Chinese water chestnut +299,watercress, +224,watermelon, +282,wattle,"acacia, thorntree, whistling thorn" +296,Welsh onion,"Welsh onion, Japanese bunching onion, green onion, spring onion, scallion, escallion, salad onion" +225,wheat, +294,white currant, +344,wild baccatum, +278,wild ginger,"British Columbia wild ginger, western wild ginger, long-tailed wild ginger" +376,wine cap mushroom,"burgundy mushroom, king stropharia, godzilla mushroom" +280,winged bean,"Goa bean, asparagus pea, four-angled bean, four-cornered bean, Manila bean, Mauritius bean, winged pea" +256,winter melon,"white gourd, winter gourd, tallow gourd, Chinese preserving melon, ash gourd" +226,winter savory, +258,wood sorrel,"yellow sorrel, pink sorrel" +227,wormwood,"absinthium, absinthe wormwood, common wormwood, green ginger, grand wormwood" +228,yam, +229,yardlong bean,"yardlong bean, bora, bodi, long-podded cowpea, asparagus bean, pea bean, snake bean, Chinese long bean" +230,yarrow,"common yarrow, gordaldo, nosebleed plant, old man's pepper, devil's nettle, sanguinary, milfoil, soldier's woundwort, thousand-leaf, thousand-seal" +231,zucchini,"courgette, baby marrow" +,Slender Amaranth,Green Amaranth +,Red Amaranth,"Huautli, Alegría, Blood amaranth, red amaranth, purple amaranth, prince's feather, Mexican grain amaranth, shravani maath, rajgira" +,Red Spinach,"Red spinach, Chinese spinach, Spleen Amaranth, Hon-toi-moi, Yin choy, Hsien tsai." +,Common bean,"common bean, string bean, field bean, flageolet bean, French bean, garden bean, haricot bean, pop bean, snap bean" +,Smooth Amaranth,"Smooth pigweed, red amaranth, slim amaranth" +,Prince of Wales," Prince-of-Wales feather, Prince's feather" +,Palmers Amaranth,"Palmer amaranth, Palmer's pigweed, carelessweed" +,Red-Root Amaranth,"redroot pigweed, red-rooted pigweed, common amaranth, pigweed amaranth, common tumbleweed" +,Spiny Amaranth,"prickly amaranth, thorny amaranth" +,Tandaljo,"Tandalja bhaji, callaloo, Joseph's coat " \ No newline at end of file diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 0e0555949..288c5ff62 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -272,9 +272,9 @@ namespace :growstuff do end desc "October 2014: add alternate names for crops" - task :add_alternate_names_for_crops => :environment do + task :add_alternate_names => :environment do require 'csv' - @file = ENV['file'] or raise "Usage: rake growstuff:oneoff:add_alternate_names_for_crops file=file.csv" + @file = ENV['file'] or raise "Usage: rake growstuff:oneoff:add_alternate_names file=file.csv" puts "Loading alternate names from #{@file}..." cropbot = Member.find_by_login_name("cropbot") CSV.foreach(@file) do |row| diff --git a/script/deploy-tasks.sh b/script/deploy-tasks.sh index 451fe0032..5b930b551 100755 --- a/script/deploy-tasks.sh +++ b/script/deploy-tasks.sh @@ -18,3 +18,6 @@ rake growstuff:oneoff:remove_unused_photos echo "2014-10-05 - generate crops_posts records for existing posts" rake growstuff:oneoff:generate_crops_posts_records + +echo "2014-10-19 - load alternate names for crops" +rake growstuff:oneoff:add_alternate_names file=db/seeds/alternate_names_201410.csv From 36be5e9533874e035c7e032581ee16df2d6dd3e8 Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Sun, 19 Oct 2014 21:54:46 +0100 Subject: [PATCH 004/143] Hardcode alternate-name CSV file path. --- lib/tasks/growstuff.rake | 6 +++--- script/deploy-tasks.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 288c5ff62..c702052c9 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -274,10 +274,10 @@ namespace :growstuff do desc "October 2014: add alternate names for crops" task :add_alternate_names => :environment do require 'csv' - @file = ENV['file'] or raise "Usage: rake growstuff:oneoff:add_alternate_names file=file.csv" - puts "Loading alternate names from #{@file}..." + file = "db/seeds/alternate_names_201410.csv" + puts "Loading alternate names from #{file}..." cropbot = Member.find_by_login_name("cropbot") - CSV.foreach(@file) do |row| + CSV.foreach(file) do |row| crop_id, crop_name, alternate_names = row if crop_name.blank? or alternate_names.blank? then next diff --git a/script/deploy-tasks.sh b/script/deploy-tasks.sh index 5b930b551..715e9dfb8 100755 --- a/script/deploy-tasks.sh +++ b/script/deploy-tasks.sh @@ -20,4 +20,4 @@ echo "2014-10-05 - generate crops_posts records for existing posts" rake growstuff:oneoff:generate_crops_posts_records echo "2014-10-19 - load alternate names for crops" -rake growstuff:oneoff:add_alternate_names file=db/seeds/alternate_names_201410.csv +rake growstuff:oneoff:add_alternate_names From 06a4fcab712072da3e42509752fe871ec0d32748 Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Sun, 19 Oct 2014 22:19:41 +0100 Subject: [PATCH 005/143] Remove superfluous* error-checks from load_altnames * /me crosses fingers... --- db/seeds/alternate_names_201410.csv | 3 +-- lib/tasks/growstuff.rake | 12 ++---------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/db/seeds/alternate_names_201410.csv b/db/seeds/alternate_names_201410.csv index 0430b5c2d..2a48911c1 100644 --- a/db/seeds/alternate_names_201410.csv +++ b/db/seeds/alternate_names_201410.csv @@ -1,4 +1,3 @@ -Id,Name,Alternate names (comma separated) 1,achiote,"aploppas, uruku" 2,ackee,"achee, ackee apple, akee" 267,acorn squash,"pepper squash, Des Moines squash" @@ -380,4 +379,4 @@ Id,Name,Alternate names (comma separated) ,Palmers Amaranth,"Palmer amaranth, Palmer's pigweed, carelessweed" ,Red-Root Amaranth,"redroot pigweed, red-rooted pigweed, common amaranth, pigweed amaranth, common tumbleweed" ,Spiny Amaranth,"prickly amaranth, thorny amaranth" -,Tandaljo,"Tandalja bhaji, callaloo, Joseph's coat " \ No newline at end of file +,Tandaljo,"Tandalja bhaji, callaloo, Joseph's coat " diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index c702052c9..479fd9f4e 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -279,22 +279,14 @@ namespace :growstuff do cropbot = Member.find_by_login_name("cropbot") CSV.foreach(file) do |row| crop_id, crop_name, alternate_names = row - if crop_name.blank? or alternate_names.blank? then + if alternate_names.blank? then next end - crop = Crop.find_by_name(crop_name) - if crop.nil? then - puts "Couldn't find crop #{crop_name}" - next - end - if crop.id.to_s != crop_id then - puts "crop #{crop} has ID #{crop.id}, expected #{crop_id}" - end alternate_names.split(/,\s*/).each do |an| puts "Adding alternate name '#{an}' to #{crop}" AlternateName.create( name: an, - crop_id: crop.id, + crop_id: crop_id, creator_id: cropbot.id ) end From 7c3059fcae6c492dd09658816fb8f318fafa6aed Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Sun, 19 Oct 2014 22:21:10 +0100 Subject: [PATCH 006/143] Fix typo in altname CSV --- db/seeds/alternate_names_201410.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seeds/alternate_names_201410.csv b/db/seeds/alternate_names_201410.csv index 2a48911c1..913f9124f 100644 --- a/db/seeds/alternate_names_201410.csv +++ b/db/seeds/alternate_names_201410.csv @@ -26,7 +26,7 @@ 314,banana pepper,"yellow wax pepper, banana chili" 19,barley, 20,basil,sweet basil -21,bay,"bay laurel, sweet bay, bay, true laurel, Grecian laurel,[1] laurel tree, laurel" +21,bay,"bay laurel, sweet bay, bay, true laurel, Grecian laurel, laurel tree, laurel" 22,bean, 23,beet,"beetroot, table beet, garden beet, red beet, golden beet" 24,bell pepper,"sweet pepper, pepper, capsicum" From badb0c4fe7fe60c1e975aac90508c19acf54bc14 Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Sun, 19 Oct 2014 22:21:29 +0100 Subject: [PATCH 007/143] Make load altnames task idempotent. --- lib/tasks/growstuff.rake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 479fd9f4e..11236be4b 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -283,8 +283,7 @@ namespace :growstuff do next end alternate_names.split(/,\s*/).each do |an| - puts "Adding alternate name '#{an}' to #{crop}" - AlternateName.create( + AlternateName.find_or_create( name: an, crop_id: crop_id, creator_id: cropbot.id From f795918e17fa0b8047d4f93c0a1d4d0da405ca5d Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Sun, 19 Oct 2014 22:49:18 +0100 Subject: [PATCH 008/143] Remove alternate names for crops without IDs. --- db/seeds/alternate_names_201410.csv | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/db/seeds/alternate_names_201410.csv b/db/seeds/alternate_names_201410.csv index 913f9124f..e606482ee 100644 --- a/db/seeds/alternate_names_201410.csv +++ b/db/seeds/alternate_names_201410.csv @@ -355,7 +355,7 @@ 299,watercress, 224,watermelon, 282,wattle,"acacia, thorntree, whistling thorn" -296,Welsh onion,"Welsh onion, Japanese bunching onion, green onion, spring onion, scallion, escallion, salad onion" +296,Welsh onion,"Japanese bunching onion, green onion, spring onion, scallion, escallion, salad onion" 225,wheat, 294,white currant, 344,wild baccatum, @@ -369,14 +369,4 @@ 228,yam, 229,yardlong bean,"yardlong bean, bora, bodi, long-podded cowpea, asparagus bean, pea bean, snake bean, Chinese long bean" 230,yarrow,"common yarrow, gordaldo, nosebleed plant, old man's pepper, devil's nettle, sanguinary, milfoil, soldier's woundwort, thousand-leaf, thousand-seal" -231,zucchini,"courgette, baby marrow" -,Slender Amaranth,Green Amaranth -,Red Amaranth,"Huautli, Alegría, Blood amaranth, red amaranth, purple amaranth, prince's feather, Mexican grain amaranth, shravani maath, rajgira" -,Red Spinach,"Red spinach, Chinese spinach, Spleen Amaranth, Hon-toi-moi, Yin choy, Hsien tsai." -,Common bean,"common bean, string bean, field bean, flageolet bean, French bean, garden bean, haricot bean, pop bean, snap bean" -,Smooth Amaranth,"Smooth pigweed, red amaranth, slim amaranth" -,Prince of Wales," Prince-of-Wales feather, Prince's feather" -,Palmers Amaranth,"Palmer amaranth, Palmer's pigweed, carelessweed" -,Red-Root Amaranth,"redroot pigweed, red-rooted pigweed, common amaranth, pigweed amaranth, common tumbleweed" -,Spiny Amaranth,"prickly amaranth, thorny amaranth" -,Tandaljo,"Tandalja bhaji, callaloo, Joseph's coat " +231,zucchini,"courgette, baby marrow" \ No newline at end of file From a9fdab5d7c931af5e9b5f8369fb8fea61cc7efc4 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Wed, 12 Nov 2014 00:23:01 +1100 Subject: [PATCH 009/143] Basic follower relationship --- app/controllers/follows_controller.rb | 27 ++++++++++++++++ app/models/follow.rb | 6 ++++ app/models/member.rb | 6 ++++ app/views/follows/_form.html.haml | 16 ++++++++++ app/views/follows/edit.html.haml | 7 +++++ app/views/follows/index.html.haml | 21 +++++++++++++ app/views/follows/new.html.haml | 5 +++ app/views/follows/show.html.haml | 12 +++++++ config/routes.rb | 2 ++ db/migrate/20141111130849_create_follows.rb | 10 ++++++ db/schema.rb | 9 +++++- spec/factories/follows.rb | 7 +++++ spec/models/follow_spec.rb | 5 +++ spec/requests/follows_spec.rb | 11 +++++++ spec/routing/follows_routing_spec.rb | 35 +++++++++++++++++++++ 15 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 app/controllers/follows_controller.rb create mode 100644 app/models/follow.rb create mode 100644 app/views/follows/_form.html.haml create mode 100644 app/views/follows/edit.html.haml create mode 100644 app/views/follows/index.html.haml create mode 100644 app/views/follows/new.html.haml create mode 100644 app/views/follows/show.html.haml create mode 100644 db/migrate/20141111130849_create_follows.rb create mode 100644 spec/factories/follows.rb create mode 100644 spec/models/follow_spec.rb create mode 100644 spec/requests/follows_spec.rb create mode 100644 spec/routing/follows_routing_spec.rb diff --git a/app/controllers/follows_controller.rb b/app/controllers/follows_controller.rb new file mode 100644 index 000000000..7cb078fd4 --- /dev/null +++ b/app/controllers/follows_controller.rb @@ -0,0 +1,27 @@ +class FollowsController < ApplicationController + + # POST /follows + def create + @follow = current_user.follows.build(followed_id: params[:followed_id]) + + if @follow.save + flash[:notice] = "Followed #{@follow.followed.name}." + redirect_to :back + else + flash[:error] = "Already following or error while following." + redirect_to :back + end + end + + + # DELETE /follows/1 + # DELETE /follows/1.json + def destroy + @follow = current_user.follows.find(params[:id]) + name = @follow.followed.name + @follow.destroy + + flash[:notice] = "Unfollowed #{name}" + redirect_to root_path + end +end diff --git a/app/models/follow.rb b/app/models/follow.rb new file mode 100644 index 000000000..cbac4948f --- /dev/null +++ b/app/models/follow.rb @@ -0,0 +1,6 @@ +class Follow < ActiveRecord::Base + attr_accessible :followed_id, :member_id + belongs_to :member_id + belongs_to :followed, class_name: "Member" + validates :member_id, uniqueness: { scope: :followed_id } +end diff --git a/app/models/member.rb b/app/models/member.rb index 14d16c175..4c1d209d2 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -27,6 +27,12 @@ class Member < ActiveRecord::Base has_many :photos + has_many :follows + has_many :followed, through: :follows + + has_many :inverse_follows, class_name: "Follow", foreign_key: "follower_id" + has_many :followers, through: :inverse_follows, source: :member + default_scope order("lower(login_name) asc") scope :confirmed, where('confirmed_at IS NOT NULL') scope :located, where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL") diff --git a/app/views/follows/_form.html.haml b/app/views/follows/_form.html.haml new file mode 100644 index 000000000..f11f553f6 --- /dev/null +++ b/app/views/follows/_form.html.haml @@ -0,0 +1,16 @@ += form_for @follow do |f| + - if @follow.errors.any? + #error_explanation + %h2= "#{pluralize(@follow.errors.count, "error")} prohibited this follow from being saved:" + %ul + - @follow.errors.full_messages.each do |msg| + %li= msg + + .field + = f.label :member_id + = f.number_field :member_id + .field + = f.label :followed_id + = f.number_field :followed_id + .actions + = f.submit 'Save' diff --git a/app/views/follows/edit.html.haml b/app/views/follows/edit.html.haml new file mode 100644 index 000000000..9ed5e22d5 --- /dev/null +++ b/app/views/follows/edit.html.haml @@ -0,0 +1,7 @@ +%h1 Editing follow + += render 'form' + += link_to 'Show', @follow +\| += link_to 'Back', follows_path diff --git a/app/views/follows/index.html.haml b/app/views/follows/index.html.haml new file mode 100644 index 000000000..75f9ab0e4 --- /dev/null +++ b/app/views/follows/index.html.haml @@ -0,0 +1,21 @@ +%h1 Listing follows + +%table + %tr + %th Member + %th Followed + %th + %th + %th + + - @follows.each do |follow| + %tr + %td= follow.member_id + %td= follow.followed_id + %td= link_to 'Show', follow + %td= link_to 'Edit', edit_follow_path(follow) + %td= link_to 'Destroy', follow, :method => :delete, :data => { :confirm => 'Are you sure?' } + +%br + += link_to 'New Follow', new_follow_path diff --git a/app/views/follows/new.html.haml b/app/views/follows/new.html.haml new file mode 100644 index 000000000..fce286b48 --- /dev/null +++ b/app/views/follows/new.html.haml @@ -0,0 +1,5 @@ +%h1 New follow + += render 'form' + += link_to 'Back', follows_path diff --git a/app/views/follows/show.html.haml b/app/views/follows/show.html.haml new file mode 100644 index 000000000..ea673e551 --- /dev/null +++ b/app/views/follows/show.html.haml @@ -0,0 +1,12 @@ +%p#notice= notice + +%p + %b Member: + = @follow.member_id +%p + %b Followed: + = @follow.followed_id + += link_to 'Edit', edit_follow_path(@follow) +\| += link_to 'Back', follows_path diff --git a/config/routes.rb b/config/routes.rb index d751647d5..8011d2fe6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,7 @@ Growstuff::Application.routes.draw do + resources :follows + resources :plant_parts devise_for :members, :controllers => { :registrations => "registrations", :passwords => "passwords" } diff --git a/db/migrate/20141111130849_create_follows.rb b/db/migrate/20141111130849_create_follows.rb new file mode 100644 index 000000000..2b9d7f8a9 --- /dev/null +++ b/db/migrate/20141111130849_create_follows.rb @@ -0,0 +1,10 @@ +class CreateFollows < ActiveRecord::Migration + def change + create_table :follows do |t| + t.integer :member_id + t.integer :followed_id + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 39a68cab2..e22a2289b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20141018111015) do +ActiveRecord::Schema.define(:version => 20141111130849) do create_table "account_types", :force => true do |t| t.string "name", :null => false @@ -80,6 +80,13 @@ ActiveRecord::Schema.define(:version => 20141018111015) do add_index "crops_posts", ["crop_id", "post_id"], :name => "index_crops_posts_on_crop_id_and_post_id" add_index "crops_posts", ["crop_id"], :name => "index_crops_posts_on_crop_id" + create_table "follows", :force => true do |t| + t.integer "member_id" + t.integer "followed_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "forums", :force => true do |t| t.string "name", :null => false t.text "description", :null => false diff --git a/spec/factories/follows.rb b/spec/factories/follows.rb new file mode 100644 index 000000000..756111732 --- /dev/null +++ b/spec/factories/follows.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :follow do + member_id 1 +followed_id 1 + end + +end diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb new file mode 100644 index 000000000..7a7eb0fa5 --- /dev/null +++ b/spec/models/follow_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Follow do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/requests/follows_spec.rb b/spec/requests/follows_spec.rb new file mode 100644 index 000000000..32a4c2e44 --- /dev/null +++ b/spec/requests/follows_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe "Follows" do + describe "GET /follows" do + it "works! (now write some real specs)" do + # Run the generator again with the --webrat flag if you want to use webrat methods/matchers + get follows_path + response.status.should be(200) + end + end +end diff --git a/spec/routing/follows_routing_spec.rb b/spec/routing/follows_routing_spec.rb new file mode 100644 index 000000000..82ddc7fda --- /dev/null +++ b/spec/routing/follows_routing_spec.rb @@ -0,0 +1,35 @@ +require "spec_helper" + +describe FollowsController do + describe "routing" do + + it "routes to #index" do + get("/follows").should route_to("follows#index") + end + + it "routes to #new" do + get("/follows/new").should route_to("follows#new") + end + + it "routes to #show" do + get("/follows/1").should route_to("follows#show", :id => "1") + end + + it "routes to #edit" do + get("/follows/1/edit").should route_to("follows#edit", :id => "1") + end + + it "routes to #create" do + post("/follows").should route_to("follows#create") + end + + it "routes to #update" do + put("/follows/1").should route_to("follows#update", :id => "1") + end + + it "routes to #destroy" do + delete("/follows/1").should route_to("follows#destroy", :id => "1") + end + + end +end From cacc002a012cfda0651da6ab4d07d6353deb0688 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Wed, 12 Nov 2014 01:47:26 +1100 Subject: [PATCH 010/143] Added follow/unfollow buttons --- app/controllers/follows_controller.rb | 9 ++++----- app/controllers/members_controller.rb | 2 +- app/models/follow.rb | 4 ++-- app/models/member.rb | 14 +++++++++++--- app/views/members/show.html.haml | 6 +++++- config/routes.rb | 2 ++ 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/app/controllers/follows_controller.rb b/app/controllers/follows_controller.rb index 7cb078fd4..b9e07f738 100644 --- a/app/controllers/follows_controller.rb +++ b/app/controllers/follows_controller.rb @@ -2,10 +2,10 @@ class FollowsController < ApplicationController # POST /follows def create - @follow = current_user.follows.build(followed_id: params[:followed_id]) + @follow = current_member.follows.build(:followed_id => params[:followed_id]) if @follow.save - flash[:notice] = "Followed #{@follow.followed.name}." + flash[:notice] = "Followed #{ @follow.followed.login_name }" redirect_to :back else flash[:error] = "Already following or error while following." @@ -17,11 +17,10 @@ class FollowsController < ApplicationController # DELETE /follows/1 # DELETE /follows/1.json def destroy - @follow = current_user.follows.find(params[:id]) - name = @follow.followed.name + @follow = current_member.follows.find(params[:id]) @follow.destroy - flash[:notice] = "Unfollowed #{name}" + flash[:notice] = "Unfollowed #{ @follow.followed.login_name }" redirect_to root_path end end diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 247ac1c8b..08c04a359 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -23,7 +23,7 @@ class MembersController < ApplicationController # it requires a garden to be passed in @garden. # The new garden is not persisted unless Garden#save is called. @garden = Garden.new - + respond_to do |format| format.html # show.html.haml format.json { render :json => @member.to_json(:only => [:id, :login_name, :bio, :created_at, :slug, :location, :latitude, :longitude]) } diff --git a/app/models/follow.rb b/app/models/follow.rb index cbac4948f..f57f1e76e 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -1,6 +1,6 @@ class Follow < ActiveRecord::Base attr_accessible :followed_id, :member_id - belongs_to :member_id + belongs_to :member belongs_to :followed, class_name: "Member" - validates :member_id, uniqueness: { scope: :followed_id } + validates :member_id, uniqueness: { :scope => :followed_id } end diff --git a/app/models/member.rb b/app/models/member.rb index 4c1d209d2..cb3e78fda 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -28,10 +28,10 @@ class Member < ActiveRecord::Base has_many :photos has_many :follows - has_many :followed, through: :follows + has_many :followed, :through => :follows - has_many :inverse_follows, class_name: "Follow", foreign_key: "follower_id" - has_many :followers, through: :inverse_follows, source: :member + has_many :inverse_follows, :class_name => "Follow", :foreign_key => "followed_id" + has_many :followers, :through => :inverse_follows, :source => :member default_scope order("lower(login_name) asc") scope :confirmed, where('confirmed_at IS NOT NULL') @@ -261,4 +261,12 @@ class Member < ActiveRecord::Base }) end + def already_following?(member) + self.follows.exists?(:followed_id => member.id) + end + + def follow_id(member) + self.follows.where(:followed_id => @member.id).first if already_following?(member) + end + end diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index edf4d0b68..bba4afab3 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -7,7 +7,11 @@ = link_to "Upgrade account", shop_path, :class => 'btn btn-default' -if can? :create, Notification and current_member != @member =link_to 'Send message', new_notification_path(:recipient_id => @member.id), :class => 'btn btn-default' - + - if current_member != @member && !current_member.already_following?(@member) + = link_to 'Follow', follows_path(:followed_id => @member.id), :method => :post, :class => 'btn btn-default' + - if current_member.already_following?(@member) + - follow = current_member.follows.where(:followed_id => @member.id).first + = link_to 'Unfollow', follow_path(follow), :method => :delete, :class => 'btn btn-default' - content_for :member_rss_login_name, @member.login_name - content_for :member_rss_slug, @member.slug diff --git a/config/routes.rb b/config/routes.rb index 8011d2fe6..a740857ce 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -81,4 +81,6 @@ Growstuff::Application.routes.draw do match '/admin/newsletter' => 'admin#newsletter', :as => :admin_newsletter match '/admin/:action' => 'admin#:action' + + end From 3c3eb1fd785143ee374eb89fddc046689ebaab74 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Wed, 12 Nov 2014 01:53:47 +1100 Subject: [PATCH 011/143] Fixed/improved method in member model --- app/models/member.rb | 2 +- app/views/members/show.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index cb3e78fda..a72dd15a6 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -266,7 +266,7 @@ class Member < ActiveRecord::Base end def follow_id(member) - self.follows.where(:followed_id => @member.id).first if already_following?(member) + self.follows.where(:followed_id => member.id).first if already_following?(member) end end diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index bba4afab3..63f4aa27e 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -10,7 +10,7 @@ - if current_member != @member && !current_member.already_following?(@member) = link_to 'Follow', follows_path(:followed_id => @member.id), :method => :post, :class => 'btn btn-default' - if current_member.already_following?(@member) - - follow = current_member.follows.where(:followed_id => @member.id).first + - follow = current_member.follow_id(@member) = link_to 'Unfollow', follow_path(follow), :method => :delete, :class => 'btn btn-default' - content_for :member_rss_login_name, @member.login_name - content_for :member_rss_slug, @member.slug From b5e1b6bc22e377c4c4d3c6256b50bf6e8aa248bb Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Thu, 13 Nov 2014 00:46:34 +1100 Subject: [PATCH 012/143] Delete unused views, add feature tests --- app/controllers/members_controller.rb | 10 ++++++++ app/models/ability.rb | 2 ++ app/models/follow.rb | 15 ++++++++++-- app/models/member.rb | 2 +- app/views/follows/_form.html.haml | 16 ------------- app/views/follows/edit.html.haml | 7 ------ app/views/follows/index.html.haml | 21 ----------------- app/views/follows/new.html.haml | 5 ---- app/views/follows/show.html.haml | 12 ---------- app/views/members/_account.html.haml | 6 +++++ app/views/members/show.html.haml | 6 ++--- app/views/members/view_followers.html.haml | 11 +++++++++ app/views/members/view_follows.html.haml | 10 ++++++++ config/routes.rb | 11 +++++---- spec/features/member_profile_spec.rb | 27 ++++++++++++++++++++++ spec/models/follow_spec.rb | 5 ---- spec/requests/follows_spec.rb | 11 --------- spec/routing/follows_routing_spec.rb | 20 ---------------- 18 files changed, 90 insertions(+), 107 deletions(-) delete mode 100644 app/views/follows/_form.html.haml delete mode 100644 app/views/follows/edit.html.haml delete mode 100644 app/views/follows/index.html.haml delete mode 100644 app/views/follows/new.html.haml delete mode 100644 app/views/follows/show.html.haml create mode 100644 app/views/members/view_followers.html.haml create mode 100644 app/views/members/view_follows.html.haml delete mode 100644 spec/models/follow_spec.rb delete mode 100644 spec/requests/follows_spec.rb diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 08c04a359..dbdaaf9ef 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -34,4 +34,14 @@ class MembersController < ApplicationController end end + def view_follows + @member = Member.confirmed.find(params[:login_name]) + @follows = @member.followed + end + + def view_followers + @member = Member.confirmed.find(params[:login_name]) + @followers = @member.followers + end + end diff --git a/app/models/ability.rb b/app/models/ability.rb index 3e76c6738..92bfce14e 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -6,6 +6,8 @@ class Ability # everyone can do these things, even non-logged in can :read, :all + can :view_follows, Member + can :view_followers, Member # except these, which don't make sense if you're not logged in cannot :read, Notification diff --git a/app/models/follow.rb b/app/models/follow.rb index f57f1e76e..42624bd4f 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -1,6 +1,17 @@ class Follow < ActiveRecord::Base attr_accessible :followed_id, :member_id - belongs_to :member - belongs_to :followed, class_name: "Member" + belongs_to :member, :dependent => :destroy + belongs_to :followed, class_name: "Member", :dependent => :destroy validates :member_id, uniqueness: { :scope => :followed_id } + + after_create do + Notification.create( + :recipient_id => self.followed_id, + :sender_id => self.member_id, + :subject => "#{self.member.login_name} has followed you", + :body => "#{self.member.login_name} has followed you" + ) + end + + end diff --git a/app/models/member.rb b/app/models/member.rb index a72dd15a6..22749491b 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -265,7 +265,7 @@ class Member < ActiveRecord::Base self.follows.exists?(:followed_id => member.id) end - def follow_id(member) + def get_follow_id(member) self.follows.where(:followed_id => member.id).first if already_following?(member) end diff --git a/app/views/follows/_form.html.haml b/app/views/follows/_form.html.haml deleted file mode 100644 index f11f553f6..000000000 --- a/app/views/follows/_form.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -= form_for @follow do |f| - - if @follow.errors.any? - #error_explanation - %h2= "#{pluralize(@follow.errors.count, "error")} prohibited this follow from being saved:" - %ul - - @follow.errors.full_messages.each do |msg| - %li= msg - - .field - = f.label :member_id - = f.number_field :member_id - .field - = f.label :followed_id - = f.number_field :followed_id - .actions - = f.submit 'Save' diff --git a/app/views/follows/edit.html.haml b/app/views/follows/edit.html.haml deleted file mode 100644 index 9ed5e22d5..000000000 --- a/app/views/follows/edit.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -%h1 Editing follow - -= render 'form' - -= link_to 'Show', @follow -\| -= link_to 'Back', follows_path diff --git a/app/views/follows/index.html.haml b/app/views/follows/index.html.haml deleted file mode 100644 index 75f9ab0e4..000000000 --- a/app/views/follows/index.html.haml +++ /dev/null @@ -1,21 +0,0 @@ -%h1 Listing follows - -%table - %tr - %th Member - %th Followed - %th - %th - %th - - - @follows.each do |follow| - %tr - %td= follow.member_id - %td= follow.followed_id - %td= link_to 'Show', follow - %td= link_to 'Edit', edit_follow_path(follow) - %td= link_to 'Destroy', follow, :method => :delete, :data => { :confirm => 'Are you sure?' } - -%br - -= link_to 'New Follow', new_follow_path diff --git a/app/views/follows/new.html.haml b/app/views/follows/new.html.haml deleted file mode 100644 index fce286b48..000000000 --- a/app/views/follows/new.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -%h1 New follow - -= render 'form' - -= link_to 'Back', follows_path diff --git a/app/views/follows/show.html.haml b/app/views/follows/show.html.haml deleted file mode 100644 index ea673e551..000000000 --- a/app/views/follows/show.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -%p#notice= notice - -%p - %b Member: - = @follow.member_id -%p - %b Followed: - = @follow.followed_id - -= link_to 'Edit', edit_follow_path(@follow) -\| -= link_to 'Back', follows_path diff --git a/app/views/members/_account.html.haml b/app/views/members/_account.html.haml index 37ff0c699..e44bae027 100644 --- a/app/views/members/_account.html.haml +++ b/app/views/members/_account.html.haml @@ -9,4 +9,10 @@ = member.account_type account +%p + %strong Following: + = link_to member.follows.count, member_follows_path(member) +%p + %strong Followed by: + = link_to member.followers.count, member_followers_path(member) diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index 63f4aa27e..71152ac52 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -7,10 +7,10 @@ = link_to "Upgrade account", shop_path, :class => 'btn btn-default' -if can? :create, Notification and current_member != @member =link_to 'Send message', new_notification_path(:recipient_id => @member.id), :class => 'btn btn-default' - - if current_member != @member && !current_member.already_following?(@member) + - if member_signed_in? && current_member != @member && !current_member.already_following?(@member) = link_to 'Follow', follows_path(:followed_id => @member.id), :method => :post, :class => 'btn btn-default' - - if current_member.already_following?(@member) - - follow = current_member.follow_id(@member) + - if member_signed_in? && current_member.already_following?(@member) + - follow = current_member.get_follow_id(@member) = link_to 'Unfollow', follow_path(follow), :method => :delete, :class => 'btn btn-default' - content_for :member_rss_login_name, @member.login_name - content_for :member_rss_slug, @member.slug diff --git a/app/views/members/view_followers.html.haml b/app/views/members/view_followers.html.haml new file mode 100644 index 000000000..e196a8130 --- /dev/null +++ b/app/views/members/view_followers.html.haml @@ -0,0 +1,11 @@ +- content_for :title, @member.login_name + +%p Followed by: + +.row + .col-md-12 + - @followers.each do |f| + .col-md-4.three-across + .thumbnail + = render :partial => "members/thumbnail", :locals => { :member => f } + \ No newline at end of file diff --git a/app/views/members/view_follows.html.haml b/app/views/members/view_follows.html.haml new file mode 100644 index 000000000..ee2248239 --- /dev/null +++ b/app/views/members/view_follows.html.haml @@ -0,0 +1,10 @@ +- content_for :title, @member.login_name + +%p Follows: + +.row + .col-md-12 + - @follows.each do |f| + .col-md-4.three-across + .thumbnail + = render :partial => "members/thumbnail", :locals => { :member => f } diff --git a/config/routes.rb b/config/routes.rb index a740857ce..1b9c30c05 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,12 +1,10 @@ Growstuff::Application.routes.draw do - resources :follows - resources :plant_parts devise_for :members, :controllers => { :registrations => "registrations", :passwords => "passwords" } - resources :members + resources :members resources :photos @@ -43,6 +41,11 @@ Growstuff::Application.routes.draw do resources :forums resources :notifications + resources :follows, :only => [:create, :destroy] + get '/members/:login_name/follows' => 'members#view_follows', :as => 'member_follows' + get '/members/:login_name/followers' => 'members#view_followers', :as => 'member_followers' + + get '/places' => 'places#index' get '/places/search' => 'places#search', :as => 'search_places' get '/places/:place' => 'places#show', :as => 'place' @@ -81,6 +84,6 @@ Growstuff::Application.routes.draw do match '/admin/newsletter' => 'admin#newsletter', :as => :admin_newsletter match '/admin/:action' => 'admin#:action' - + end diff --git a/spec/features/member_profile_spec.rb b/spec/features/member_profile_spec.rb index 809b052a8..1520b215e 100644 --- a/spec/features/member_profile_spec.rb +++ b/spec/features/member_profile_spec.rb @@ -143,6 +143,33 @@ feature "member profile" do scenario "has a private message button" do expect(page).to have_link "Send message", :href => new_notification_path(:recipient_id => other_member.id) end + + scenario "has a follow button" do + expect(page).to have_link "Follow", :href => follows_path(:followed_id => other_member.id) + end + + scenario "following and unfollowing" do + click_link 'Follow' + expect(page).to have_content "Followed #{other_member.login_name}" + expect(page).to have_link "Unfollow", :href => follow_path(member.get_follow_id(other_member)) + + visit member_follows_path(member) + expect(page).to have_content "#{other_member.login_name}" + + visit member_followers_path(other_member) + expect(page).to have_content "#{member.login_name}" + + visit member_path(other_member) + click_link 'Unfollow' + expect(page).to have_content "Unfollowed #{other_member.login_name}" + + visit member_follows_path(member) + expect(page).to_not have_content "#{other_member.login_name}" + + visit member_followers_path(other_member) + expect(page).to_not have_content "#{member.login_name}" + end + end end diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb deleted file mode 100644 index 7a7eb0fa5..000000000 --- a/spec/models/follow_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe Follow do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/requests/follows_spec.rb b/spec/requests/follows_spec.rb deleted file mode 100644 index 32a4c2e44..000000000 --- a/spec/requests/follows_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec_helper' - -describe "Follows" do - describe "GET /follows" do - it "works! (now write some real specs)" do - # Run the generator again with the --webrat flag if you want to use webrat methods/matchers - get follows_path - response.status.should be(200) - end - end -end diff --git a/spec/routing/follows_routing_spec.rb b/spec/routing/follows_routing_spec.rb index 82ddc7fda..d4259e024 100644 --- a/spec/routing/follows_routing_spec.rb +++ b/spec/routing/follows_routing_spec.rb @@ -3,30 +3,10 @@ require "spec_helper" describe FollowsController do describe "routing" do - it "routes to #index" do - get("/follows").should route_to("follows#index") - end - - it "routes to #new" do - get("/follows/new").should route_to("follows#new") - end - - it "routes to #show" do - get("/follows/1").should route_to("follows#show", :id => "1") - end - - it "routes to #edit" do - get("/follows/1/edit").should route_to("follows#edit", :id => "1") - end - it "routes to #create" do post("/follows").should route_to("follows#create") end - it "routes to #update" do - put("/follows/1").should route_to("follows#update", :id => "1") - end - it "routes to #destroy" do delete("/follows/1").should route_to("follows#destroy", :id => "1") end From e687bd43dc6bdd8c5052d95de01878673802416b Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Thu, 13 Nov 2014 01:22:28 +1100 Subject: [PATCH 013/143] Added model tests for follows --- spec/factories/follows.rb | 2 +- spec/models/follow_spec.rb | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 spec/models/follow_spec.rb diff --git a/spec/factories/follows.rb b/spec/factories/follows.rb index 756111732..711402374 100644 --- a/spec/factories/follows.rb +++ b/spec/factories/follows.rb @@ -1,7 +1,7 @@ FactoryGirl.define do factory :follow do member_id 1 -followed_id 1 + followed_id 2 end end diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb new file mode 100644 index 000000000..f9302c9d3 --- /dev/null +++ b/spec/models/follow_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe Follow do + + context "basic" do + before(:each) do + @member1 = FactoryGirl.create(:member) + @member2 = FactoryGirl.create(:member) + end + + it "sends a notification when a follow is created" do + expect { + Follow.create(:member_id => @member1.id, :followed_id => @member2.id) + }.to change(Notification, :count).by(1) + end + end + +end \ No newline at end of file From 03fea2a78513d26ca543d4241b2b89bfb8e036f4 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Thu, 13 Nov 2014 01:52:43 +1100 Subject: [PATCH 014/143] Remove dependent detroy as this wipes out both users. Woops. --- app/models/follow.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/follow.rb b/app/models/follow.rb index 42624bd4f..e312efc90 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -1,7 +1,7 @@ class Follow < ActiveRecord::Base attr_accessible :followed_id, :member_id - belongs_to :member, :dependent => :destroy - belongs_to :followed, class_name: "Member", :dependent => :destroy + belongs_to :member + belongs_to :followed, class_name: "Member" validates :member_id, uniqueness: { :scope => :followed_id } after_create do From 77f40a3dc227cb5779daa53092590bd653b8adf0 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Thu, 13 Nov 2014 02:10:54 +1100 Subject: [PATCH 015/143] Fixed comment + code style --- app/controllers/follows_controller.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/follows_controller.rb b/app/controllers/follows_controller.rb index b9e07f738..d6e38c81f 100644 --- a/app/controllers/follows_controller.rb +++ b/app/controllers/follows_controller.rb @@ -13,14 +13,13 @@ class FollowsController < ApplicationController end end - # DELETE /follows/1 - # DELETE /follows/1.json def destroy @follow = current_member.follows.find(params[:id]) + unfollowed_name = @follow.followed.login_name @follow.destroy - flash[:notice] = "Unfollowed #{ @follow.followed.login_name }" + flash[:notice] = "Unfollowed #{ unfollowed_name }" redirect_to root_path end end From 8d74fd52dbcbeea271e4d58c9090f01b27bc27ee Mon Sep 17 00:00:00 2001 From: Kevin Rio Date: Wed, 12 Nov 2014 13:54:01 -0500 Subject: [PATCH 016/143] Rearrange titles on RSS feeds https://www.pivotaltracker.com/n/projects/646869/stories/50492161 --- app/views/comments/index.rss.haml | 2 +- app/views/crops/index.rss.haml | 2 +- app/views/members/show.rss.haml | 2 +- app/views/plantings/index.rss.haml | 2 +- app/views/posts/index.rss.haml | 2 +- app/views/posts/show.rss.haml | 2 +- app/views/seeds/index.rss.haml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/views/comments/index.rss.haml b/app/views/comments/index.rss.haml index d04f5be76..5df3b3403 100644 --- a/app/views/comments/index.rss.haml +++ b/app/views/comments/index.rss.haml @@ -1,7 +1,7 @@ %rss{:version => 2.0} %channel - %title #{ENV['GROWSTUFF_SITE_NAME']} - Recent comments on all posts + %title Recent comments on all posts (#{ENV['GROWSTUFF_SITE_NAME']}) %link= comments_url - @comments.each do |comment| %item diff --git a/app/views/crops/index.rss.haml b/app/views/crops/index.rss.haml index 0766a5348..5714a594c 100644 --- a/app/views/crops/index.rss.haml +++ b/app/views/crops/index.rss.haml @@ -1,7 +1,7 @@ %rss{:version => 2.0} %channel - %title #{ENV['GROWSTUFF_SITE_NAME']} - Recently added crops + %title Recently added crops (#{ENV['GROWSTUFF_SITE_NAME']}) %link= crops_url - @crops.each do |crop| %item diff --git a/app/views/members/show.rss.haml b/app/views/members/show.rss.haml index 96c17f984..6d727fbbe 100644 --- a/app/views/members/show.rss.haml +++ b/app/views/members/show.rss.haml @@ -1,7 +1,7 @@ %rss{:version => 2.0} %channel - %title #{ENV['GROWSTUFF_SITE_NAME']} - #{@member.login_name}'s recent posts + %title #{@member.login_name}'s recent posts (#{ENV['GROWSTUFF_SITE_NAME']}) %link= member_url(@member) - @posts.each do |post| %item diff --git a/app/views/plantings/index.rss.haml b/app/views/plantings/index.rss.haml index 04304c635..623b3a93e 100644 --- a/app/views/plantings/index.rss.haml +++ b/app/views/plantings/index.rss.haml @@ -2,7 +2,7 @@ %rss{:version => 2.0} %channel %title - #{ENV['GROWSTUFF_SITE_NAME']} - Recent plantings from #{ @owner ? @owner : 'all members' } + Recent plantings from #{ @owner ? @owner : 'all members' } (#{ENV['GROWSTUFF_SITE_NAME']}) %link= plantings_url - @plantings.each do |planting| %item diff --git a/app/views/posts/index.rss.haml b/app/views/posts/index.rss.haml index 34c0d1153..19832b013 100644 --- a/app/views/posts/index.rss.haml +++ b/app/views/posts/index.rss.haml @@ -2,7 +2,7 @@ %rss{:version => 2.0} %channel %title - #{ENV['GROWSTUFF_SITE_NAME']} - Recent posts from #{ @author ? @author : 'all members' } + Recent posts from #{ @author ? @author : 'all members' } (#{ENV['GROWSTUFF_SITE_NAME']}) %link= posts_url - @posts.each do |post| %item diff --git a/app/views/posts/show.rss.haml b/app/views/posts/show.rss.haml index 0bc4e2348..ccec88cca 100644 --- a/app/views/posts/show.rss.haml +++ b/app/views/posts/show.rss.haml @@ -1,7 +1,7 @@ %rss{:version => 2.0} %channel - %title #{ENV['GROWSTUFF_SITE_NAME']} - Recent comments on #{@post.subject} + %title Recent comments on #{@post.subject} (#{ENV['GROWSTUFF_SITE_NAME']}) %link= post_url(@post) - @post.comments.each do |comment| %item diff --git a/app/views/seeds/index.rss.haml b/app/views/seeds/index.rss.haml index 570f35f2f..30cec02af 100644 --- a/app/views/seeds/index.rss.haml +++ b/app/views/seeds/index.rss.haml @@ -2,7 +2,7 @@ %rss{:version => 2.0} %channel %title - #{ENV['GROWSTUFF_SITE_NAME']} - Recent seeds from #{ @owner ? @owner : 'all members' } + Recent seeds from #{ @owner ? @owner : 'all members' } (#{ENV['GROWSTUFF_SITE_NAME']}) %link= seeds_url - @seeds.each do |seed| %item From c6f56a23d69eacebbf63aedca556cd1c4b1023bb Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Thu, 13 Nov 2014 07:26:10 +1100 Subject: [PATCH 017/143] Adds binstubs for rails and rake --- bin/bundle | 3 +++ bin/rails | 4 ++++ bin/rake | 4 ++++ 3 files changed, 11 insertions(+) create mode 100755 bin/bundle create mode 100755 bin/rails create mode 100755 bin/rake diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 000000000..66e9889e8 --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails new file mode 100755 index 000000000..728cd85aa --- /dev/null +++ b/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../../config/application', __FILE__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake new file mode 100755 index 000000000..17240489f --- /dev/null +++ b/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative '../config/boot' +require 'rake' +Rake.application.run From 40a88b5b09eede0c4c985d9e1fb02f28deedbe1d Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sat, 15 Nov 2014 21:44:55 +1100 Subject: [PATCH 018/143] tests run but fail like whoa --- Gemfile | 58 ++++---- Gemfile.lock | 230 +++++++++++++++-------------- app/models/comment.rb | 2 +- app/models/crop.rb | 6 +- app/models/garden.rb | 4 +- app/models/harvest.rb | 2 +- app/models/member.rb | 4 +- app/models/notification.rb | 2 +- app/models/order.rb | 2 +- app/models/photo.rb | 2 +- app/models/plant_part.rb | 2 +- app/models/planting.rb | 4 +- app/models/post.rb | 2 +- app/models/seed.rb | 2 +- config/environments/development.rb | 6 +- config/environments/production.rb | 6 +- config/environments/staging.rb | 6 +- config/environments/test.rb | 2 + config/routes.rb | 54 +++---- 19 files changed, 207 insertions(+), 189 deletions(-) diff --git a/Gemfile b/Gemfile index d034f2789..725100ff2 100644 --- a/Gemfile +++ b/Gemfile @@ -2,11 +2,23 @@ source 'https://rubygems.org' ruby "2.1.2" +# gems for Rails 4 upgrade +gem 'rails4_upgrade' +gem 'actionpack-action_caching', '~>1.0.0' +gem 'actionpack-page_caching', '~>1.0.0' +gem 'actionpack-xml_parser', '~>1.0.0' +gem 'actionview-encoded_mail_to', '~>1.0.4' +gem 'activerecord-session_store', '~>0.0.1' +gem 'activeresource', '~>4.0.0.beta1' +gem 'protected_attributes', '~>1.0.1' +gem 'rails-observers', '~>0.1.1' +gem 'rails-perftest', '~>0.0.2' + gem 'bundler', '>=1.1.5' -gem 'rails', '3.2.13' -gem 'rack', '~>1.4.5' -gem 'json', '~>1.7.7' +gem 'rails', '4.1.7' +# gem 'rack', '~>1.4.5' +# gem 'json', '~>1.7.7' gem 'haml' gem 'leaflet-rails' gem 'leaflet-markercluster-rails' @@ -37,32 +49,28 @@ group :production, :staging do gem 'rails_12factor' # supresses heroku plugin injection end -# Gems used only for assets and not required -# in production environments by default. -group :assets do - # CSS preprocessor, used for app/assets/stylesheets/application.css - gem 'sass-rails', '~> 3.2.3' - # CoffeeScript is a Python-like language that compiles to JavaScript - gem 'coffee-rails', '~> 3.2.1' +# CSS preprocessor, used for app/assets/stylesheets/application.css +gem 'sass-rails', '~> 4.0.4' +# CoffeeScript is a Python-like language that compiles to JavaScript +gem 'coffee-rails', '~> 4.1.0' - # less-rails depends on a JavaScript engine; we use therubyracer. - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - # long term, we'll probably want node.js for performance, but this will do - # for now as it's easier for new people to install - gem "therubyracer", "~> 0.12", :platforms => :ruby - # libv8 is needed by therubyracer and is a bit finicky - gem 'libv8', '3.16.14.3' +# less-rails depends on a JavaScript engine; we use therubyracer. +# See https://github.com/sstephenson/execjs#readme for more supported runtimes +# long term, we'll probably want node.js for performance, but this will do +# for now as it's easier for new people to install +gem "therubyracer", "~> 0.12", :platforms => :ruby +# libv8 is needed by therubyracer and is a bit finicky +gem 'libv8', '3.16.14.3' - # Another CSS preprocessor, used for Bootstrap overrides - gem "less", '~>2.5.0' - gem "less-rails", '~> 2.5.0' - # CSS framework - gem "less-rails-bootstrap", '~> 3.2.0' +# Another CSS preprocessor, used for Bootstrap overrides +gem "less", '~>2.5.0' +gem "less-rails", '~> 2.5.0' +# CSS framework +gem "less-rails-bootstrap", '~> 3.2.0' - gem 'uglifier', '>= 1.0.3' # JavaScript compressor +gem 'uglifier', '~> 2.5.3' # JavaScript compressor - gem 'compass-rails', '~> 1.0.3' # Yet Another CSS framework -end +# gem 'compass-rails', '~> 1.0.3' # Yet Another CSS framework gem 'jquery-rails' gem 'jquery-ui-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 34b5f136a..3a3c2ddda 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,36 +20,51 @@ PATH GEM remote: https://rubygems.org/ specs: - actionmailer (3.2.13) - actionpack (= 3.2.13) - mail (~> 2.5.3) - actionpack (3.2.13) - activemodel (= 3.2.13) - activesupport (= 3.2.13) - builder (~> 3.0.0) + actionmailer (4.1.7) + actionpack (= 4.1.7) + actionview (= 4.1.7) + mail (~> 2.5, >= 2.5.4) + actionpack (4.1.7) + actionview (= 4.1.7) + activesupport (= 4.1.7) + rack (~> 1.5.2) + rack-test (~> 0.6.2) + actionpack-action_caching (1.0.0) + actionpack (>= 4.0.0.beta, < 5.0) + actionpack-page_caching (1.0.2) + actionpack (>= 4.0.0, < 5) + actionpack-xml_parser (1.0.1) + actionpack (>= 4.0.0.rc1) + actionview (4.1.7) + activesupport (= 4.1.7) + builder (~> 3.1) erubis (~> 2.7.0) - journey (~> 1.0.4) - rack (~> 1.4.5) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.2.1) - activemodel (3.2.13) - activesupport (= 3.2.13) - builder (~> 3.0.0) - activerecord (3.2.13) - activemodel (= 3.2.13) - activesupport (= 3.2.13) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activeresource (3.2.13) - activemodel (= 3.2.13) - activesupport (= 3.2.13) - activesupport (3.2.13) - i18n (= 0.6.1) - multi_json (~> 1.0) + actionview-encoded_mail_to (1.0.5) + rails + activemodel (4.1.7) + activesupport (= 4.1.7) + builder (~> 3.1) + activerecord (4.1.7) + activemodel (= 4.1.7) + activesupport (= 4.1.7) + arel (~> 5.0.0) + activerecord-session_store (0.0.1) + actionpack (>= 4.0.0.beta, < 5) + activerecord (>= 4.0.0.beta, < 5) + railties (>= 4.0.0.beta, < 5) + activeresource (4.0.0.beta1) + activemodel (>= 4.0.0.beta1) + activesupport (>= 4.0.0.beta1) + rails-observers (~> 0.1.1) + activesupport (4.1.7) + i18n (~> 0.6, >= 0.6.9) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.1) + tzinfo (~> 1.1) addressable (2.3.6) - arel (3.0.3) - bcrypt (3.1.7) + arel (5.0.1.20140414130214) + bcrypt (3.1.9) better_errors (2.0.0) coderay (>= 1.0.0) erubis (>= 2.6.6) @@ -59,7 +74,7 @@ GEM bluecloth (2.2.0) bootstrap-datepicker-rails (1.3.0.2) railties (>= 3.0) - builder (3.0.4) + builder (3.2.2) cancan (1.6.10) capybara (2.4.4) mime-types (>= 1.16) @@ -70,30 +85,23 @@ GEM capybara-email (2.4.0) capybara (~> 2.4) mail - chunky_png (1.3.2) cliver (0.3.2) coderay (1.1.0) - coffee-rails (3.2.2) + coffee-rails (4.1.0) coffee-script (>= 2.2.0) - railties (~> 3.2.0) + railties (>= 4.0.0, < 5.0) coffee-script (2.3.0) coffee-script-source execjs coffee-script-source (1.8.0) commonjs (0.2.7) - compass (0.12.7) - chunky_png (~> 1.2) - fssm (>= 0.2.7) - sass (~> 3.2.19) - compass-rails (1.0.3) - compass (>= 0.12.2, < 0.14) coveralls (0.7.1) multi_json (~> 1.3) rest-client simplecov (>= 0.7) term-ansicolor thor - csv_shaper (1.0.0) + csv_shaper (1.1.1) activesupport (>= 3.0.0) dalli (2.7.2) database_cleaner (1.3.0) @@ -120,10 +128,8 @@ GEM figaro (1.0.0) thor (~> 0.14) flickraw (0.9.8) - friendly_id (4.0.10.1) - activerecord (>= 3.0, < 4.0) - fssm (0.2.10) - gibbon (1.1.3) + friendly_id (4.0.10) + gibbon (1.1.4) httparty multi_json (>= 1.3.4) gravatar-ultimate (2.0.0) @@ -131,19 +137,19 @@ GEM rack haml (4.0.5) tilt - haml-rails (0.4) - actionpack (>= 3.1, < 4.1) - activesupport (>= 3.1, < 4.1) - haml (>= 3.1, < 4.1) - railties (>= 3.1, < 4.1) + haml-rails (0.5.3) + actionpack (>= 4.0.1) + activesupport (>= 4.0.1) + haml (>= 3.1, < 5.0) + railties (>= 4.0.1) hashie (3.3.1) highline (1.6.21) hike (1.2.3) - httparty (0.11.0) - multi_json (~> 1.0) + httparty (0.13.3) + json (~> 1.8) multi_xml (>= 0.5.2) - i18n (0.6.1) - i18n-tasks (0.7.7) + i18n (0.6.11) + i18n-tasks (0.7.8) activesupport easy_translate (>= 0.5.0) erubis @@ -152,18 +158,17 @@ GEM slop (>= 3.5.0) term-ansicolor terminal-table - journey (1.0.4) jquery-rails (3.1.2) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) - jquery-ui-rails (4.1.2) - railties (>= 3.1.0) + jquery-ui-rails (5.0.2) + railties (>= 3.2.16) js-routes (0.9.9) railties (>= 3.2) sprockets-rails - json (1.7.7) + json (1.8.1) kgio (2.9.2) - launchy (2.4.2) + launchy (2.4.3) addressable (~> 2.3) leaflet-markercluster-rails (0.7.0) railties (>= 3.1) @@ -178,19 +183,19 @@ GEM letter_opener (1.2.0) launchy (~> 2.2) libv8 (3.16.14.3) - mail (2.5.4) - mime-types (~> 1.16) - treetop (~> 1.4.8) + mail (2.6.3) + mime-types (>= 1.16, < 3) memcachier (0.0.2) method_source (0.8.2) - mime-types (1.25.1) - mini_portile (0.6.0) + mime-types (2.4.3) + mini_portile (0.6.1) + minitest (5.4.3) multi_json (1.10.1) multi_xml (0.5.5) netrc (0.8.0) - newrelic_rpm (3.9.5.251) - nokogiri (1.6.3.1) - mini_portile (= 0.6.0) + newrelic_rpm (3.9.6.257) + nokogiri (1.6.4.1) + mini_portile (~> 0.6.0) oauth (0.4.7) omniauth (1.2.2) hashie (>= 1.2, < 4) @@ -210,42 +215,43 @@ GEM cliver (~> 0.3.1) multi_json (~> 1.0) websocket-driver (>= 0.2.0) - polyglot (0.3.5) + protected_attributes (1.0.8) + activemodel (>= 4.0.1, < 5.0) pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - rack (1.4.5) - rack-cache (1.2) - rack (>= 0.4) - rack-ssl (1.3.4) - rack + rack (1.5.2) rack-test (0.6.2) rack (>= 1.0) - rails (3.2.13) - actionmailer (= 3.2.13) - actionpack (= 3.2.13) - activerecord (= 3.2.13) - activeresource (= 3.2.13) - activesupport (= 3.2.13) - bundler (~> 1.0) - railties (= 3.2.13) + rails (4.1.7) + actionmailer (= 4.1.7) + actionpack (= 4.1.7) + actionview (= 4.1.7) + activemodel (= 4.1.7) + activerecord (= 4.1.7) + activesupport (= 4.1.7) + bundler (>= 1.3.0, < 2.0) + railties (= 4.1.7) + sprockets-rails (~> 2.0) + rails-observers (0.1.2) + activemodel (~> 4.0) + rails-perftest (0.0.5) + rails4_upgrade (0.5.0) + bundler (>= 1.2.2) + terminal-table (>= 1.4.5) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging rails_serve_static_assets (0.0.2) rails_stdout_logging (0.0.3) - railties (3.2.13) - actionpack (= 3.2.13) - activesupport (= 3.2.13) - rack-ssl (~> 1.3.2) + railties (4.1.7) + actionpack (= 4.1.7) + activesupport (= 4.1.7) rake (>= 0.8.7) - rdoc (~> 3.4) - thor (>= 0.14.6, < 2.0) + thor (>= 0.18.1, < 2.0) raindrops (0.13.0) rake (10.3.2) - rdoc (3.12.2) - json (~> 1.4) ref (1.0.5) rest-client (1.7.2) mime-types (>= 1.16, < 3.0) @@ -262,23 +268,26 @@ GEM rspec-expectations (~> 2.12.0) rspec-mocks (~> 2.12.0) sass (3.2.19) - sass-rails (3.2.6) - railties (~> 3.2.0) - sass (>= 3.1.10) - tilt (~> 1.3) + sass-rails (4.0.4) + railties (>= 4.0.0, < 5.0) + sass (~> 3.2.2) + sprockets (~> 2.8, < 2.12) + sprockets-rails (~> 2.0) simplecov (0.9.1) docile (~> 1.1.0) multi_json (~> 1.0) simplecov-html (~> 0.8.0) simplecov-html (0.8.0) slop (3.6.0) - sprockets (2.2.2) + sprockets (2.11.3) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sprockets-rails (0.0.1) - sprockets (>= 1.0.2) + sprockets-rails (2.2.0) + actionpack (>= 3.0) + activesupport (>= 3.0) + sprockets (>= 2.8, < 4.0) term-ansicolor (1.3.0) tins (~> 1.0) terminal-table (1.4.5) @@ -290,13 +299,11 @@ GEM thread_safe (0.3.4) tilt (1.4.1) tins (1.3.3) - treetop (1.4.15) - polyglot - polyglot (>= 0.3.1) - tzinfo (0.3.41) - uglifier (2.2.1) + tzinfo (1.2.2) + thread_safe (~> 0.1) + uglifier (2.5.3) execjs (>= 0.3.0) - multi_json (~> 1.0, >= 1.0.2) + json (>= 1.8.0) unicorn (4.8.3) kgio (~> 2.6) rack @@ -307,7 +314,7 @@ GEM nokogiri (>= 1.2.0) rack (>= 1.0) rack-test (>= 0.5.3) - websocket-driver (0.3.5) + websocket-driver (0.4.0) will_paginate (3.0.7) xpath (2.0.0) nokogiri (~> 1.3) @@ -316,8 +323,14 @@ PLATFORMS ruby DEPENDENCIES + actionpack-action_caching (~> 1.0.0) + actionpack-page_caching (~> 1.0.0) + actionpack-xml_parser (~> 1.0.0) + actionview-encoded_mail_to (~> 1.0.4) active_utils (= 1.0.5)! activemerchant (= 1.33.0)! + activerecord-session_store (~> 0.0.1) + activeresource (~> 4.0.0.beta1) better_errors binding_of_caller bluecloth @@ -326,8 +339,7 @@ DEPENDENCIES cancan capybara capybara-email - coffee-rails (~> 3.2.1) - compass-rails (~> 1.0.3) + coffee-rails (~> 4.1.0) coveralls csv_shaper dalli @@ -346,7 +358,6 @@ DEPENDENCIES jquery-rails jquery-ui-rails js-routes - json (~> 1.7.7) leaflet-markercluster-rails leaflet-rails less (~> 2.5.0) @@ -361,15 +372,18 @@ DEPENDENCIES omniauth-twitter pg poltergeist (~> 1.5.1) + protected_attributes (~> 1.0.1) pry - rack (~> 1.4.5) - rails (= 3.2.13) + rails (= 4.1.7) + rails-observers (~> 0.1.1) + rails-perftest (~> 0.0.2) + rails4_upgrade rails_12factor rake (>= 10.0.0) rspec-rails (~> 2.12.1) - sass-rails (~> 3.2.3) + sass-rails (~> 4.0.4) therubyracer (~> 0.12) - uglifier (>= 1.0.3) + uglifier (~> 2.5.3) unicorn webrat will_paginate (~> 3.0) diff --git a/app/models/comment.rb b/app/models/comment.rb index f797848e0..91d163f98 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -3,7 +3,7 @@ class Comment < ActiveRecord::Base belongs_to :author, :class_name => 'Member' belongs_to :post - default_scope order("created_at DESC") + default_scope { order("created_at DESC") } scope :post_order, reorder("created_at ASC") # for display on post page after_create do diff --git a/app/models/crop.rb b/app/models/crop.rb index 9777d8fd4..c8025a270 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -13,7 +13,7 @@ class Crop < ActiveRecord::Base has_many :photos, :through => :plantings has_many :seeds has_many :harvests - has_many :plant_parts, :through => :harvests, :uniq => :true + has_many :plant_parts, -> { uniq }, :through => :harvests belongs_to :creator, :class_name => 'Member' belongs_to :parent, :class_name => 'Crop' @@ -22,7 +22,7 @@ class Crop < ActiveRecord::Base before_destroy {|crop| crop.posts.clear} - default_scope order("lower(name) asc") + default_scope { order("lower(name) asc") } scope :recent, reorder("created_at desc") scope :toplevel, where(:parent_id => nil) scope :popular, reorder("plantings_count desc, lower(name) asc") @@ -30,7 +30,7 @@ class Crop < ActiveRecord::Base validates :en_wikipedia_url, :format => { - :with => /^https?:\/\/en\.wikipedia\.org\/wiki/, + :with => /\Ahttps?:\/\/en\.wikipedia\.org\/wiki/, :message => 'is not a valid English Wikipedia URL' } diff --git a/app/models/garden.rb b/app/models/garden.rb index 7f64994cc..cc5492906 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -7,7 +7,7 @@ class Garden < ActiveRecord::Base :location, :latitude, :longitude, :area, :area_unit belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id' - has_many :plantings, :order => 'created_at DESC', :dependent => :destroy + has_many :plantings, -> { order(created_at: :desc) }, :dependent => :destroy has_many :crops, :through => :plantings # set up geocoding @@ -16,7 +16,7 @@ class Garden < ActiveRecord::Base after_validation :empty_unwanted_geocodes after_save :mark_inactive_garden_plantings_as_finished - default_scope order("lower(name) asc") + default_scope { order("lower(name) asc") } scope :active, where(:active => true) scope :inactive, where(:active => false) diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 48e9eac19..184ae595d 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -21,7 +21,7 @@ class Harvest < ActiveRecord::Base end end - default_scope order('created_at DESC') + default_scope { order('created_at DESC') } validates :crop, :presence => {:message => "must be present and exist in our database"} diff --git a/app/models/member.rb b/app/models/member.rb index 14d16c175..d75b39001 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -27,7 +27,7 @@ class Member < ActiveRecord::Base has_many :photos - default_scope order("lower(login_name) asc") + default_scope { order("lower(login_name) asc") } scope :confirmed, where('confirmed_at IS NOT NULL') scope :located, where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL") scope :recently_signed_in, reorder('updated_at DESC') @@ -74,7 +74,7 @@ class Member < ActiveRecord::Base :message => "name is reserved" }, :format => { - :with => /^\w+$/, + :with => /\A\w+\z/, :message => "may only include letters, numbers, or underscores" }, :uniqueness => { diff --git a/app/models/notification.rb b/app/models/notification.rb index 3fc48a0c7..9ab2d183b 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -6,7 +6,7 @@ class Notification < ActiveRecord::Base belongs_to :recipient, :class_name => 'Member' belongs_to :post - default_scope order('created_at DESC') + default_scope { order('created_at DESC') } scope :unread, where(:read => false) before_create :replace_blank_subject diff --git a/app/models/order.rb b/app/models/order.rb index 122d83700..68fcd80ac 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,7 +4,7 @@ class Order < ActiveRecord::Base has_many :order_items, :dependent => :destroy - default_scope order('created_at DESC') + default_scope { order('created_at DESC') } validates :referral_code, :format => { :with => /\A[a-zA-Z0-9 ]*\z/, diff --git a/app/models/photo.rb b/app/models/photo.rb index 862b9d28b..995fecc71 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -10,7 +10,7 @@ class Photo < ActiveRecord::Base photo.harvests.clear end - default_scope order("created_at desc") + default_scope { order("created_at desc") } # remove photos that aren't used by anything def destroy_if_unused diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index 41e8d26ea..16241372a 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -3,7 +3,7 @@ class PlantPart < ActiveRecord::Base friendly_id :name, :use => :slugged has_many :harvests - has_many :crops, :through => :harvests, :uniq => true + has_many :crops, -> { uniq }, :through => :harvests attr_accessible :name, :slug diff --git a/app/models/planting.rb b/app/models/planting.rb index 889fb2d80..132bed8ed 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -21,7 +21,7 @@ class Planting < ActiveRecord::Base end end - default_scope order("created_at desc") + default_scope { order("created_at desc") } scope :finished, where(:finished => true) scope :current, where(:finished => false) @@ -32,7 +32,7 @@ class Planting < ActiveRecord::Base :to => :crop, :prefix => true - default_scope order("created_at desc") + default_scope { order("created_at desc") } validates :crop_id, :presence => {:message => "must be present and exist in our database"} diff --git a/app/models/post.rb b/app/models/post.rb index 7f72a4e57..05d95e056 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -11,7 +11,7 @@ class Post < ActiveRecord::Base # also has_many notifications, but kinda meaningless to get at them # from this direction, so we won't set up an association for now. - default_scope order("created_at desc") + default_scope { order("created_at desc") } validates :subject, :format => { diff --git a/app/models/seed.rb b/app/models/seed.rb index 38cd3b714..94cccddcb 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -8,7 +8,7 @@ class Seed < ActiveRecord::Base belongs_to :crop belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id' - default_scope order("created_at desc") + default_scope { order("created_at desc") } validates :crop, :presence => {:message => "must be present and exist in our database"} validates :quantity, diff --git a/config/environments/development.rb b/config/environments/development.rb index 7b25f588c..890d210a7 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,6 +1,8 @@ Growstuff::Application.configure do # Settings specified here will take precedence over those in config/application.rb + config.eager_load = false + # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. @@ -28,10 +30,6 @@ Growstuff::Application.configure do # Raise exception on mass assignment protection for Active Record models config.active_record.mass_assignment_sanitizer = :strict - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - config.active_record.auto_explain_threshold_in_seconds = 0.5 - # Do not compress assets config.assets.compress = false diff --git a/config/environments/production.rb b/config/environments/production.rb index a5b131a4b..e2b6d5735 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,6 +1,8 @@ Growstuff::Application.configure do # Settings specified here will take precedence over those in config/application.rb + config.eager_load = true + # Code is not reloaded between requests config.cache_classes = true @@ -61,10 +63,6 @@ Growstuff::Application.configure do # Send deprecation notices to registered listeners config.active_support.deprecation = :notify - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - # config.active_record.auto_explain_threshold_in_seconds = 0.5 - # Growstuff configuration config.new_crops_request_link = "http://growstuff.org/posts/skud-20130319-requests-for-new-crops" config.action_mailer.default_url_options = { :host => 'growstuff.org' } diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 3c9e83e98..fda2929ef 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -1,6 +1,8 @@ Growstuff::Application.configure do # Settings specified here will take precedence over those in config/application.rb + config.eager_load = true + # Code is not reloaded between requests config.cache_classes = true @@ -61,10 +63,6 @@ Growstuff::Application.configure do # Send deprecation notices to registered listeners config.active_support.deprecation = :notify - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - # config.active_record.auto_explain_threshold_in_seconds = 0.5 - # Growstuff configuration config.new_crops_request_link = "http://example.com/not-a-real-url" config.action_mailer.default_url_options = { :host => 'dev.growstuff.org' } diff --git a/config/environments/test.rb b/config/environments/test.rb index 6fb8cad3e..237e4bef4 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,6 +1,8 @@ Growstuff::Application.configure do # Settings specified here will take precedence over those in config/application.rb + config.eager_load = false + # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped diff --git a/config/routes.rb b/config/routes.rb index d751647d5..0bc238e7e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,29 +11,29 @@ Growstuff::Application.routes.draw do resources :authentications resources :plantings - match '/plantings/owner/:owner' => 'plantings#index', :as => 'plantings_by_owner' - match '/plantings/crop/:crop' => 'plantings#index', :as => 'plantings_by_crop' + get '/plantings/owner/:owner' => 'plantings#index', :as => 'plantings_by_owner' + get '/plantings/crop/:crop' => 'plantings#index', :as => 'plantings_by_crop' resources :gardens - match '/gardens/owner/:owner' => 'gardens#index', :as => 'gardens_by_owner' + get '/gardens/owner/:owner' => 'gardens#index', :as => 'gardens_by_owner' resources :seeds - match '/seeds/owner/:owner' => 'seeds#index', :as => 'seeds_by_owner' - match '/seeds/crop/:crop' => 'seeds#index', :as => 'seeds_by_crop' + get '/seeds/owner/:owner' => 'seeds#index', :as => 'seeds_by_owner' + get '/seeds/crop/:crop' => 'seeds#index', :as => 'seeds_by_crop' resources :harvests - match '/harvests/owner/:owner' => 'harvests#index', :as => 'harvests_by_owner' - match '/harvests/crop/:crop' => 'harvests#index', :as => 'harvests_by_crop' + get '/harvests/owner/:owner' => 'harvests#index', :as => 'harvests_by_owner' + get '/harvests/crop/:crop' => 'harvests#index', :as => 'harvests_by_crop' resources :posts - match '/posts/author/:author' => 'posts#index', :as => 'posts_by_author' + get '/posts/author/:author' => 'posts#index', :as => 'posts_by_author' resources :scientific_names resources :alternate_names - match 'crops/wrangle' => 'crops#wrangle', :as => 'wrangle_crops' - match 'crops/hierarchy' => 'crops#hierarchy', :as => 'crops_hierarchy' - match 'crops/search' => 'crops#search', :as => 'crops_search' + get 'crops/wrangle' => 'crops#wrangle', :as => 'wrangle_crops' + get 'crops/hierarchy' => 'crops#hierarchy', :as => 'crops_hierarchy' + get 'crops/search' => 'crops#search', :as => 'crops_search' resources :crops resources :comments @@ -49,9 +49,9 @@ Growstuff::Application.routes.draw do resources :account_types resources :accounts resources :orders - match 'orders/:id/checkout' => 'orders#checkout', :as => 'checkout_order' - match 'orders/:id/complete' => 'orders#complete', :as => 'complete_order' - match 'orders/:id/cancel' => 'orders#cancel', :as => 'cancel_order' + get 'orders/:id/checkout' => 'orders#checkout', :as => 'checkout_order' + get 'orders/:id/complete' => 'orders#complete', :as => 'complete_order' + get 'orders/:id/cancel' => 'orders#cancel', :as => 'cancel_order' resources :order_items resources :products @@ -59,24 +59,24 @@ Growstuff::Application.routes.draw do get "home/index" root :to => 'home#index' - match 'auth/:provider/callback' => 'authentications#create' + post 'auth/:provider/callback' => 'authentications#create' - match '/policy/:action' => 'policy#:action' + get '/policy/:action' => 'policy#:action' - match '/support' => 'support#index' - match '/support/:action' => 'support#:action' + get '/support' => 'support#index' + get '/support/:action' => 'support#:action' - match '/about' => 'about#index' - match '/about/:action' => 'about#:action' + get '/about' => 'about#index' + get '/about/:action' => 'about#:action' - match '/shop' => 'shop#index' - match '/shop/:action' => 'shop#:action' + get '/shop' => 'shop#index' + get '/shop/:action' => 'shop#:action' - match '/admin/orders' => 'admin/orders#index' - match '/admin/orders/:action' => 'admin/orders#:action' - match '/admin' => 'admin#index' - match '/admin/newsletter' => 'admin#newsletter', :as => :admin_newsletter - match '/admin/:action' => 'admin#:action' + get '/admin/orders' => 'admin/orders#index' + get '/admin/orders/:action' => 'admin/orders#:action' + get '/admin' => 'admin#index' + get '/admin/newsletter' => 'admin#newsletter', :as => :admin_newsletter + get '/admin/:action' => 'admin#:action' end From 8e7919976661ec9533e4a4c67b072cfa4eff1ad4 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sat, 15 Nov 2014 22:55:37 +1100 Subject: [PATCH 019/143] wip: upgrading rspec --- Gemfile | 6 +- Gemfile.lock | 32 ++++--- app/models/account.rb | 2 +- app/models/crop.rb | 2 +- app/models/member.rb | 2 +- config/initializers/friendly_id.rb | 88 +++++++++++++++++++ lib/tasks/growstuff.rake | 14 +-- spec/factories/roles.rb | 2 +- spec/spec_helper.rb | 6 +- .../reset_password_instructions_spec.rb | 4 +- spec/views/devise/shared/_links_spec.rb | 2 +- 11 files changed, 129 insertions(+), 31 deletions(-) create mode 100644 config/initializers/friendly_id.rb diff --git a/Gemfile b/Gemfile index 725100ff2..1faf0532e 100644 --- a/Gemfile +++ b/Gemfile @@ -107,7 +107,7 @@ gem 'will_paginate', '~> 3.0' gem 'devise', '~> 3.2.0' # nicely formatted URLs -gem 'friendly_id', '~> 4.0.10' +gem 'friendly_id', '~> 5.0.4' # gravatars gem 'gravatar-ultimate' @@ -129,10 +129,10 @@ gem 'rake', '>= 10.0.0' group :development, :test do gem 'haml-rails' # HTML templating language - gem 'rspec-rails', '~> 2.12.1' # unit testing framework + gem 'rspec-rails', '~> 3.1.0' # unit testing framework gem 'database_cleaner', '~> 1.3.0' gem 'webrat' # provides HTML matchers for view tests - gem 'factory_girl_rails', '~> 4.0' # for creating test data + gem 'factory_girl_rails', '~> 4.5.0' # for creating test data gem 'coveralls', require: false # coverage analysis gem 'capybara' # integration tests gem 'capybara-email' # integration tests for email diff --git a/Gemfile.lock b/Gemfile.lock index 3a3c2ddda..28383ef0f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,7 +112,7 @@ GEM railties (>= 3.2.6, < 5) thread_safe (~> 0.1) warden (~> 1.2.3) - diff-lcs (1.1.3) + diff-lcs (1.2.5) docile (1.1.5) easy_translate (0.5.0) json @@ -128,7 +128,8 @@ GEM figaro (1.0.0) thor (~> 0.14) flickraw (0.9.8) - friendly_id (4.0.10) + friendly_id (5.0.4) + activerecord (>= 4.0.0) gibbon (1.1.4) httparty multi_json (>= 1.3.4) @@ -256,17 +257,22 @@ GEM rest-client (1.7.2) mime-types (>= 1.16, < 3.0) netrc (~> 0.7) - rspec-core (2.12.2) - rspec-expectations (2.12.1) - diff-lcs (~> 1.1.3) - rspec-mocks (2.12.2) - rspec-rails (2.12.2) + rspec-core (3.1.7) + rspec-support (~> 3.1.0) + rspec-expectations (3.1.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.1.0) + rspec-mocks (3.1.3) + rspec-support (~> 3.1.0) + rspec-rails (3.1.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 2.12.0) - rspec-expectations (~> 2.12.0) - rspec-mocks (~> 2.12.0) + rspec-core (~> 3.1.0) + rspec-expectations (~> 3.1.0) + rspec-mocks (~> 3.1.0) + rspec-support (~> 3.1.0) + rspec-support (3.1.2) sass (3.2.19) sass-rails (4.0.4) railties (>= 4.0.0, < 5.0) @@ -345,10 +351,10 @@ DEPENDENCIES dalli database_cleaner (~> 1.3.0) devise (~> 3.2.0) - factory_girl_rails (~> 4.0) + factory_girl_rails (~> 4.5.0) figaro flickraw - friendly_id (~> 4.0.10) + friendly_id (~> 5.0.4) geocoder! gibbon gravatar-ultimate @@ -380,7 +386,7 @@ DEPENDENCIES rails4_upgrade rails_12factor rake (>= 10.0.0) - rspec-rails (~> 2.12.1) + rspec-rails (~> 3.1.0) sass-rails (~> 4.0.4) therubyracer (~> 0.12) uglifier (~> 2.5.3) diff --git a/app/models/account.rb b/app/models/account.rb index c0348e611..7da4b1d98 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -9,7 +9,7 @@ class Account < ActiveRecord::Base before_create do |account| unless account.account_type - account.account_type = AccountType.find_or_create_by_name( + account.account_type = AccountType.find_or_create_by(name: Growstuff::Application.config.default_account_type ) end diff --git a/app/models/crop.rb b/app/models/crop.rb index c8025a270..39c35b96d 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -132,7 +132,7 @@ class Crop < ActiveRecord::Base cropbot = Member.find_by_login_name('cropbot') raise "cropbot account not found: run rake db:seed" unless cropbot - crop = Crop.find_or_create_by_name(name) + crop = Crop.find_or_create_by(name: name) crop.update_attributes( :en_wikipedia_url => en_wikipedia_url, :creator_id => cropbot.id diff --git a/app/models/member.rb b/app/models/member.rb index d75b39001..844570b81 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -87,7 +87,7 @@ class Member < ActiveRecord::Base # and an account record (for paid accounts etc) # we use find_or_create to avoid accidentally creating a second one, # which can happen sometimes especially with FactoryGirl associations - after_create {|member| Account.find_or_create_by_member_id(:member_id => member.id) } + after_create {|member| Account.find_or_create_by(:member_id => member.id) } after_save :update_newsletter_subscription diff --git a/config/initializers/friendly_id.rb b/config/initializers/friendly_id.rb new file mode 100644 index 000000000..3a88f87be --- /dev/null +++ b/config/initializers/friendly_id.rb @@ -0,0 +1,88 @@ +# FriendlyId Global Configuration +# +# Use this to set up shared configuration options for your entire application. +# Any of the configuration options shown here can also be applied to single +# models by passing arguments to the `friendly_id` class method or defining +# methods in your model. +# +# To learn more, check out the guide: +# +# http://norman.github.io/friendly_id/file.Guide.html + +FriendlyId.defaults do |config| + # ## Reserved Words + # + # Some words could conflict with Rails's routes when used as slugs, or are + # undesirable to allow as slugs. Edit this list as needed for your app. + # config.use :reserved + + # config.reserved_words = %w(new edit index session login logout users admin + # stylesheets assets javascripts images) + + # ## Friendly Finders + # + # Uncomment this to use friendly finders in all models. By default, if + # you wish to find a record by its friendly id, you must do: + # + # MyModel.friendly.find('foo') + # + # If you uncomment this, you can do: + # + # MyModel.find('foo') + # + # This is significantly more convenient but may not be appropriate for + # all applications, so you must explicity opt-in to this behavior. You can + # always also configure it on a per-model basis if you prefer. + # + # Something else to consider is that using the :finders addon boosts + # performance because it will avoid Rails-internal code that makes runtime + # calls to `Module.extend`. + # + # config.use :finders + # + # ## Slugs + # + # Most applications will use the :slugged module everywhere. If you wish + # to do so, uncomment the following line. + # + # config.use :slugged + # + # By default, FriendlyId's :slugged addon expects the slug column to be named + # 'slug', but you can change it if you wish. + # + # config.slug_column = 'slug' + # + # When FriendlyId can not generate a unique ID from your base method, it appends + # a UUID, separated by a single dash. You can configure the character used as the + # separator. If you're upgrading from FriendlyId 4, you may wish to replace this + # with two dashes. + # + # config.sequence_separator = '-' + # + # ## Tips and Tricks + # + # ### Controlling when slugs are generated + # + # As of FriendlyId 5.0, new slugs are generated only when the slug field is + # nil, but if you're using a column as your base method can change this + # behavior by overriding the `should_generate_new_friendly_id` method that + # FriendlyId adds to your model. The change below makes FriendlyId 5.0 behave + # more like 4.0. + # + # config.use Module.new { + # def should_generate_new_friendly_id? + # slug.blank? || _changed? + # end + # } + # + # FriendlyId uses Rails's `parameterize` method to generate slugs, but for + # languages that don't use the Roman alphabet, that's not usually suffient. Here + # we use the Babosa library to transliterate Russian Cyrillic slugs to ASCII. If + # you use this, don't forget to add "babosa" to your Gemfile. + # + # config.use Module.new { + # def normalize_friendly_id(text) + # text.to_slug.normalize! :transliterations => [:russian, :latin] + # end + # } +end diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 0cf0a50f7..5bf0207c5 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -98,36 +98,36 @@ namespace :growstuff do desc "June 2013: create account types and products." task :setup_shop => :environment do puts "Adding account types..." - AccountType.find_or_create_by_name( + AccountType.find_or_create_by( :name => "Free", :is_paid => false, :is_permanent_paid => false ) - @paid_account = AccountType.find_or_create_by_name( + @paid_account = AccountType.find_or_create_by( :name => "Paid", :is_paid => true, :is_permanent_paid => false ) - @seed_account = AccountType.find_or_create_by_name( + @seed_account = AccountType.find_or_create_by( :name => "Seed", :is_paid => true, :is_permanent_paid => true ) - @staff_account = AccountType.find_or_create_by_name( + @staff_account = AccountType.find_or_create_by( :name => "Staff", :is_paid => true, :is_permanent_paid => true ) puts "Adding products..." - Product.find_or_create_by_name( + Product.find_or_create_by( :name => "Annual subscription", :description => "An annual subscription gives you access to paid account features for one year. Does not auto-renew.", :min_price => 3000, :account_type_id => @paid_account.id, :paid_months => 12 ) - Product.find_or_create_by_name( + Product.find_or_create_by( :name => "Seed account", :description => "A seed account helps Growstuff grow in its early days. It gives you all the features of a paid account, in perpetuity. This account type never expires.", :min_price => 15000, @@ -252,7 +252,7 @@ namespace :growstuff do 'other' ] plant_parts.each do |pp| - PlantPart.find_or_create_by_name!(pp) + PlantPart.find_or_create_by!(name: pp) end end diff --git a/spec/factories/roles.rb b/spec/factories/roles.rb index dc4aa3b9c..d2f7ba262 100644 --- a/spec/factories/roles.rb +++ b/spec/factories/roles.rb @@ -4,7 +4,7 @@ FactoryGirl.define do factory :role do name "Moderator" description "These people moderate the forums" - initialize_with { Role.find_or_create_by_name(name) } + initialize_with { Role.find_or_create_by(name: name) } factory :admin do name "admin" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f77c8b267..9176aea29 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -45,7 +45,7 @@ RSpec.configure do |config| # config.mock_with :rr # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" + # config.fixture_path = "#{::Rails.root}/spec/fixtures" # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false @@ -67,4 +67,8 @@ RSpec.configure do |config| # see https://github.com/plataformatec/devise/wiki/How-To%3a-Controllers-and-Views-tests-with-Rails-3-%28and-rspec%29 config.include Devise::TestHelpers, :type => :controller config.extend ControllerMacros, :type => :controller + + config.before(:each) do + ActionController::Caching::Sweeper.any_instance.stub(:expire_fragment) + end end diff --git a/spec/views/devise/mailer/reset_password_instructions_spec.rb b/spec/views/devise/mailer/reset_password_instructions_spec.rb index 4f19281a3..5c3a4f222 100644 --- a/spec/views/devise/mailer/reset_password_instructions_spec.rb +++ b/spec/views/devise/mailer/reset_password_instructions_spec.rb @@ -5,8 +5,8 @@ describe 'devise/mailer/reset_password_instructions.html.haml', :type => "view" context "logged in" do before(:each) do @resource = mock_model(Member) - @resource.stub!(:email).and_return("example@example.com") - @resource.stub!(:reset_password_token).and_return("joe") + @resource.stub(:email).and_return("example@example.com") + @resource.stub(:reset_password_token).and_return("joe") render end diff --git a/spec/views/devise/shared/_links_spec.rb b/spec/views/devise/shared/_links_spec.rb index b86715a46..41f9b45ef 100644 --- a/spec/views/devise/shared/_links_spec.rb +++ b/spec/views/devise/shared/_links_spec.rb @@ -1,7 +1,7 @@ describe 'devise/shared/_links.haml', :type => "view" do def devise_mapping(register, recover, confirm, lock, oauth) - dm = mock("mappings") + dm = double("mappings") dm.stub(:registerable? => register) dm.stub(:recoverable? => recover) dm.stub(:confirmable? => confirm) From 7fc886f43cea7eb7b3928aa127c673b4db44ca10 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 16 Nov 2014 12:01:27 +1100 Subject: [PATCH 020/143] implement custom Sweeper class as stop gap against errors when running specs --- .rspec | 1 + app/models/comment_sweeper.rb | 2 +- app/models/crop_sweeper.rb | 2 +- app/models/forum_sweeper.rb | 2 +- app/models/garden_sweeper.rb | 2 +- app/models/member_sweeper.rb | 2 +- app/models/photo_sweeper.rb | 2 +- app/models/planting_sweeper.rb | 2 +- app/models/post_sweeper.rb | 2 +- app/models/scientific_name_sweeper.rb | 2 +- app/models/seed_sweeper.rb | 2 +- app/models/sweeper.rb | 5 + .../account_types_controller_spec.rb | 2 +- spec/controllers/accounts_controller_spec.rb | 2 +- .../admin/orders_controller_spec.rb | 2 +- spec/controllers/admin_controller_spec.rb | 2 +- .../authentications_controller_spec.rb | 2 +- spec/controllers/comments_controller_spec.rb | 2 +- spec/controllers/crops_controller_spec.rb | 2 +- spec/controllers/forums_controller_spec.rb | 2 +- spec/controllers/gardens_controller_spec.rb | 2 +- spec/controllers/harvests_controller_spec.rb | 2 +- spec/controllers/home_controller_spec.rb | 2 +- spec/controllers/member_controller_spec.rb | 2 +- .../notifications_controller_spec.rb | 2 +- .../order_items_controller_spec.rb | 2 +- spec/controllers/orders_controller_spec.rb | 2 +- spec/controllers/photos_controller_spec.rb | 2 +- spec/controllers/places_controller_spec.rb | 2 +- .../plant_parts_controller_spec.rb | 2 +- spec/controllers/plantings_controller_spec.rb | 2 +- spec/controllers/posts_controller_spec.rb | 2 +- spec/controllers/products_controller_spec.rb | 2 +- .../registrations_controller_spec.rb | 2 +- spec/controllers/roles_controller_spec.rb | 2 +- .../scientific_names_controller_spec.rb | 2 +- spec/controllers/seeds_controller_spec.rb | 2 +- spec/controllers/shop_controller_spec.rb | 2 +- spec/features/admin/account_types_spec.rb | 2 +- spec/features/admin/forums_spec.rb | 2 +- spec/features/alternate_name_spec.rb | 2 +- spec/features/crop_wranglers_spec.rb | 2 +- spec/features/crops/crop_detail_page_spec.rb | 2 +- spec/features/footer_spec.rb | 2 +- spec/features/gardens_spec.rb | 2 +- .../harvests/harvesting_a_crop_spec.rb | 2 +- spec/features/locale_spec.rb | 2 +- spec/features/member_profile_spec.rb | 2 +- spec/features/planting_reminder_spec.rb | 2 +- .../plantings/planting_a_crop_spec.rb | 2 +- spec/features/scientific_name_spec.rb | 2 +- spec/features/seeds/adding_seeds_spec.rb | 2 +- spec/features/seeds/misc_seeds_spec.rb | 2 +- spec/features/shared_examples/crop_suggest.rb | 2 +- spec/features/signin_spec.rb | 2 +- spec/features/signup_spec.rb | 2 +- spec/helpers/application_helper.rb | 2 +- spec/helpers/harvests_helper_spec.rb | 2 +- spec/helpers/notifications_helper_spec.rb | 2 +- .../lib/haml/filters/escaped_markdown_spec.rb | 2 +- .../haml/filters/growstuff_markdown_spec.rb | 2 +- spec/mailers/notifier_spec.rb | 2 +- spec/models/ability_spec.rb | 2 +- spec/models/account_spec.rb | 2 +- spec/models/account_type_spec.rb | 2 +- spec/models/alternate_name_spec.rb | 2 +- spec/models/authentication_spec.rb | 2 +- spec/models/comment_spec.rb | 2 +- spec/models/crop_spec.rb | 2 +- spec/models/forum_spec.rb | 2 +- spec/models/garden_spec.rb | 2 +- spec/models/harvest_spec.rb | 2 +- spec/models/member_spec.rb | 2 +- spec/models/notification_spec.rb | 2 +- spec/models/order_item_spec.rb | 2 +- spec/models/order_spec.rb | 2 +- spec/models/photo_spec.rb | 2 +- spec/models/plant_part_spec.rb | 2 +- spec/models/planting_spec.rb | 2 +- spec/models/post_spec.rb | 2 +- spec/models/product_spec.rb | 2 +- spec/models/role_spec.rb | 2 +- spec/models/scientific_name_spec.rb | 2 +- spec/models/seed_spec.rb | 2 +- spec/rails_helper.rb | 90 ++++++++++++ spec/requests/authentications_spec.rb | 2 +- spec/requests/comments_spec.rb | 2 +- spec/requests/forums_spec.rb | 2 +- spec/requests/gardens_spec.rb | 2 +- spec/requests/harvests_spec.rb | 2 +- spec/requests/notifications_spec.rb | 2 +- spec/requests/photos_spec.rb | 2 +- spec/requests/plant_parts_spec.rb | 2 +- spec/requests/plantings_spec.rb | 2 +- spec/requests/post_spec.rb | 2 +- spec/requests/scientific_names_spec.rb | 2 +- spec/requests/seeds_spec.rb | 2 +- spec/routing/account_types_routing_spec.rb | 2 +- spec/routing/authentications_routing_spec.rb | 2 +- spec/routing/comments_routing_spec.rb | 2 +- spec/routing/crops_routing_spec.rb | 2 +- spec/routing/forums_routing_spec.rb | 2 +- spec/routing/gardens_routing_spec.rb | 2 +- spec/routing/harvests_routing_spec.rb | 2 +- spec/routing/notifications_routing_spec.rb | 2 +- spec/routing/order_items_routing_spec.rb | 2 +- spec/routing/orders_routing_spec.rb | 2 +- spec/routing/photos_routing_spec.rb | 2 +- spec/routing/plant_parts_routing_spec.rb | 2 +- spec/routing/plantings_routing_spec.rb | 2 +- spec/routing/products_routing_spec.rb | 2 +- spec/routing/roles_routing_spec.rb | 2 +- spec/routing/scientific_names_routing_spec.rb | 2 +- spec/routing/seeds_routing_spec.rb | 2 +- spec/routing/updates_routing_spec.rb | 2 +- spec/spec_helper.rb | 135 ++++++++++-------- spec/views/about/contact_spec.rb | 2 +- .../account_types/edit.html.haml_spec.rb | 2 +- .../account_types/index.html.haml_spec.rb | 2 +- .../views/account_types/new.html.haml_spec.rb | 2 +- .../account_types/show.html.haml_spec.rb | 2 +- spec/views/accounts/edit.html.haml_spec.rb | 2 +- spec/views/accounts/index.html.haml_spec.rb | 2 +- spec/views/accounts/new.html.haml_spec.rb | 2 +- spec/views/accounts/show.html.haml_spec.rb | 2 +- spec/views/admin/index_spec.rb | 2 +- spec/views/admin/newsletter_spec.rb | 2 +- spec/views/admin/orders/index_spec.rb | 2 +- .../authentications/index.html.haml_spec.rb | 2 +- spec/views/comments/edit.html.haml_spec.rb | 2 +- spec/views/comments/index.html.haml_spec.rb | 2 +- spec/views/comments/index.rss.haml_spec.rb | 2 +- spec/views/comments/new.html.haml_spec.rb | 2 +- spec/views/comments/show.html.haml_spec.rb | 2 +- spec/views/crops/_grown_for.html.haml_spec.rb | 2 +- .../crops/_planting_advice.html.haml_spec.rb | 2 +- spec/views/crops/_popover.html.haml_spec.rb | 2 +- spec/views/crops/edit.html.haml_spec.rb | 2 +- spec/views/crops/hierarchy.html.haml_spec.rb | 2 +- spec/views/crops/index.html.haml_spec.rb | 2 +- spec/views/crops/index.rss.haml_spec.rb | 2 +- spec/views/crops/new.html.haml_spec.rb | 2 +- spec/views/crops/search.html.haml_spec.rb | 2 +- spec/views/crops/wrangle.html.haml_spec.rb | 2 +- .../mailer/confirmation_instructions_spec.rb | 2 +- .../reset_password_instructions_spec.rb | 2 +- .../devise/mailer/unlock_instructions_spec.rb | 2 +- spec/views/devise/registrations/edit_spec.rb | 2 +- spec/views/devise/registrations/new_spec.rb | 2 +- spec/views/devise/sessions/new_spec.rb | 2 +- spec/views/devise/unlocks/new_spec.rb | 2 +- spec/views/forums/edit.html.haml_spec.rb | 2 +- spec/views/forums/index.html.haml_spec.rb | 2 +- spec/views/forums/new.html.haml_spec.rb | 2 +- spec/views/forums/show.html.haml_spec.rb | 2 +- spec/views/gardens/edit.html.haml_spec.rb | 2 +- spec/views/gardens/index.html.haml_spec.rb | 2 +- spec/views/gardens/new.html.haml_spec.rb | 2 +- spec/views/gardens/show.html.haml_spec.rb | 2 +- spec/views/harvests/edit.html.haml_spec.rb | 2 +- spec/views/harvests/index.html.haml_spec.rb | 2 +- spec/views/harvests/new.html.haml_spec.rb | 2 +- spec/views/harvests/show.html.haml_spec.rb | 2 +- spec/views/home/_blurb.html.haml_spec.rb | 2 +- spec/views/home/_crops.html.haml_spec.rb | 2 +- .../home/_keep_in_touch.html.haml_spec.rb | 2 +- spec/views/home/_members.html.haml_spec.rb | 2 +- spec/views/home/_open.html.haml_spec.rb | 2 +- spec/views/home/_seeds.html.haml_spec.rb | 2 +- spec/views/home/_stats.html.haml_spec.rb | 2 +- spec/views/home/index_spec.rb | 2 +- spec/views/layouts/_footer_spec.rb | 2 +- spec/views/layouts/_header_spec.rb | 2 +- spec/views/layouts/_meta_spec.rb | 2 +- spec/views/layouts/application_spec.rb | 2 +- .../views/members/_location.html.haml_spec.rb | 2 +- spec/views/members/index.html.haml_spec.rb | 2 +- spec/views/members/show.rss.haml_spec.rb | 2 +- .../notifications/index.html.haml_spec.rb | 2 +- .../views/notifications/new.html.haml_spec.rb | 2 +- .../notifications/show.html.haml_spec.rb | 2 +- spec/views/notifier/notify.html.haml_spec.rb | 2 +- spec/views/orders/index.html.haml_spec.rb | 2 +- spec/views/orders/show.html.haml_spec.rb | 2 +- spec/views/photos/edit.html.haml_spec.rb | 2 +- spec/views/photos/index.html.haml_spec.rb | 2 +- spec/views/photos/new.html.haml_spec.rb | 2 +- spec/views/photos/show.html.haml_spec.rb | 2 +- .../places/_map_attribution.html.haml_spec.rb | 2 +- spec/views/places/index.html.haml_spec.rb | 2 +- spec/views/places/show.html.haml_spec.rb | 2 +- spec/views/plant_parts/edit.html.haml_spec.rb | 2 +- .../views/plant_parts/index.html.haml_spec.rb | 2 +- spec/views/plant_parts/new.html.haml_spec.rb | 2 +- spec/views/plant_parts/show.html.haml_spec.rb | 2 +- spec/views/plantings/_form.html.haml_spec.rb | 2 +- .../plantings/_thumbnail.html.haml_spec.rb | 2 +- spec/views/plantings/edit.html.haml_spec.rb | 2 +- spec/views/plantings/index.html.haml_spec.rb | 2 +- spec/views/plantings/index.rss.haml_spec.rb | 2 +- spec/views/plantings/new.html.haml_spec.rb | 2 +- spec/views/plantings/show.html.haml_spec.rb | 2 +- spec/views/policy/community_spec.rb | 2 +- spec/views/policy/tos_spec.rb | 2 +- spec/views/posts/_single.html.haml_spec.rb | 2 +- spec/views/posts/edit.html.haml_spec.rb | 2 +- spec/views/posts/index.html.haml_spec.rb | 2 +- spec/views/posts/index.rss.haml_spec.rb | 2 +- spec/views/posts/new.html.haml_spec.rb | 2 +- spec/views/posts/show.html.haml_spec.rb | 2 +- spec/views/posts/show.rss.haml_spec.rb | 2 +- spec/views/products/edit.html.haml_spec.rb | 2 +- spec/views/products/index.html.haml_spec.rb | 2 +- spec/views/products/new.html.haml_spec.rb | 2 +- spec/views/products/show.html.haml_spec.rb | 2 +- spec/views/roles/edit.html.haml_spec.rb | 2 +- spec/views/roles/index.html.haml_spec.rb | 2 +- spec/views/roles/new.html.haml_spec.rb | 2 +- spec/views/roles/show.html.haml_spec.rb | 2 +- .../scientific_names/edit.html.haml_spec.rb | 2 +- .../scientific_names/index.html.haml_spec.rb | 2 +- .../scientific_names/new.html.haml_spec.rb | 2 +- .../scientific_names/show.html.haml_spec.rb | 2 +- spec/views/seeds/edit.html.haml_spec.rb | 2 +- spec/views/seeds/index.html.haml_spec.rb | 2 +- spec/views/seeds/index.rss.haml_spec.rb | 2 +- spec/views/seeds/new.html.haml_spec.rb | 2 +- spec/views/seeds/show.html.haml_spec.rb | 2 +- spec/views/shop/index_spec.rb | 2 +- spec/views/support/index_spec.rb | 2 +- 230 files changed, 395 insertions(+), 288 deletions(-) create mode 100644 app/models/sweeper.rb create mode 100644 spec/rails_helper.rb diff --git a/.rspec b/.rspec index 4e1e0d2f7..83e16f804 100644 --- a/.rspec +++ b/.rspec @@ -1 +1,2 @@ --color +--require spec_helper diff --git a/app/models/comment_sweeper.rb b/app/models/comment_sweeper.rb index fed7b6f4c..d226d0e7c 100644 --- a/app/models/comment_sweeper.rb +++ b/app/models/comment_sweeper.rb @@ -1,4 +1,4 @@ -class CommentSweeper < ActionController::Caching::Sweeper +class CommentSweeper < Sweeper observe Comment def after_create(comment) diff --git a/app/models/crop_sweeper.rb b/app/models/crop_sweeper.rb index fef9927f3..14d83f0bd 100644 --- a/app/models/crop_sweeper.rb +++ b/app/models/crop_sweeper.rb @@ -1,4 +1,4 @@ -class CropSweeper < ActionController::Caching::Sweeper +class CropSweeper < Sweeper observe Crop def after_create(crop) diff --git a/app/models/forum_sweeper.rb b/app/models/forum_sweeper.rb index cccffc524..f71613d21 100644 --- a/app/models/forum_sweeper.rb +++ b/app/models/forum_sweeper.rb @@ -1,4 +1,4 @@ -class ForumSweeper < ActionController::Caching::Sweeper +class ForumSweeper < Sweeper observe Forum def after_create(forum) diff --git a/app/models/garden_sweeper.rb b/app/models/garden_sweeper.rb index 3913a7c11..a5688d75b 100644 --- a/app/models/garden_sweeper.rb +++ b/app/models/garden_sweeper.rb @@ -1,4 +1,4 @@ -class GardenSweeper < ActionController::Caching::Sweeper +class GardenSweeper < Sweeper observe Garden def after_create(garden) diff --git a/app/models/member_sweeper.rb b/app/models/member_sweeper.rb index 205131e19..fe53ba38d 100644 --- a/app/models/member_sweeper.rb +++ b/app/models/member_sweeper.rb @@ -1,4 +1,4 @@ -class MemberSweeper < ActionController::Caching::Sweeper +class MemberSweeper < Sweeper observe Member def after_create(member) diff --git a/app/models/photo_sweeper.rb b/app/models/photo_sweeper.rb index 1bb388b11..63f463279 100644 --- a/app/models/photo_sweeper.rb +++ b/app/models/photo_sweeper.rb @@ -1,4 +1,4 @@ -class PhotoSweeper < ActionController::Caching::Sweeper +class PhotoSweeper < Sweeper observe Photo def after_create(photo) diff --git a/app/models/planting_sweeper.rb b/app/models/planting_sweeper.rb index 8e8de10df..aea3f08e0 100644 --- a/app/models/planting_sweeper.rb +++ b/app/models/planting_sweeper.rb @@ -1,4 +1,4 @@ -class PlantingSweeper < ActionController::Caching::Sweeper +class PlantingSweeper < Sweeper observe Planting def after_create(planting) diff --git a/app/models/post_sweeper.rb b/app/models/post_sweeper.rb index e6ad03427..08ae39c7a 100644 --- a/app/models/post_sweeper.rb +++ b/app/models/post_sweeper.rb @@ -1,4 +1,4 @@ -class PostSweeper < ActionController::Caching::Sweeper +class PostSweeper < Sweeper observe Post def after_create(post) diff --git a/app/models/scientific_name_sweeper.rb b/app/models/scientific_name_sweeper.rb index 2ac626526..89b894639 100644 --- a/app/models/scientific_name_sweeper.rb +++ b/app/models/scientific_name_sweeper.rb @@ -1,4 +1,4 @@ -class ScientificNameSweeper < ActionController::Caching::Sweeper +class ScientificNameSweeper < Sweeper observe ScientificName def after_create(scientific_name) diff --git a/app/models/seed_sweeper.rb b/app/models/seed_sweeper.rb index 1b7d663a4..755cdd810 100644 --- a/app/models/seed_sweeper.rb +++ b/app/models/seed_sweeper.rb @@ -1,4 +1,4 @@ -class SeedSweeper < ActionController::Caching::Sweeper +class SeedSweeper < Sweeper observe Seed def after_create(seed) diff --git a/app/models/sweeper.rb b/app/models/sweeper.rb new file mode 100644 index 000000000..99da9ee93 --- /dev/null +++ b/app/models/sweeper.rb @@ -0,0 +1,5 @@ +class Sweeper < ActionController::Caching::Sweeper + include ActionController::Caching::Fragments + + +end \ No newline at end of file diff --git a/spec/controllers/account_types_controller_spec.rb b/spec/controllers/account_types_controller_spec.rb index 6beee69b6..a22146a79 100644 --- a/spec/controllers/account_types_controller_spec.rb +++ b/spec/controllers/account_types_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe AccountTypesController do diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/controllers/accounts_controller_spec.rb index 31ac5b014..eb2ff7f65 100644 --- a/spec/controllers/accounts_controller_spec.rb +++ b/spec/controllers/accounts_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe AccountsController do diff --git a/spec/controllers/admin/orders_controller_spec.rb b/spec/controllers/admin/orders_controller_spec.rb index 090bbb68b..08dfb9933 100644 --- a/spec/controllers/admin/orders_controller_spec.rb +++ b/spec/controllers/admin/orders_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Admin::OrdersController do diff --git a/spec/controllers/admin_controller_spec.rb b/spec/controllers/admin_controller_spec.rb index 76f56b78a..fc31f80b9 100644 --- a/spec/controllers/admin_controller_spec.rb +++ b/spec/controllers/admin_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe AdminController do diff --git a/spec/controllers/authentications_controller_spec.rb b/spec/controllers/authentications_controller_spec.rb index 8add74c8c..4fc5b98a5 100644 --- a/spec/controllers/authentications_controller_spec.rb +++ b/spec/controllers/authentications_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe AuthenticationsController do diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index 6b830180a..0e10ffe42 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe CommentsController do diff --git a/spec/controllers/crops_controller_spec.rb b/spec/controllers/crops_controller_spec.rb index 997aa71a9..5cfe9f4d1 100644 --- a/spec/controllers/crops_controller_spec.rb +++ b/spec/controllers/crops_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe CropsController do diff --git a/spec/controllers/forums_controller_spec.rb b/spec/controllers/forums_controller_spec.rb index 324c46120..369919ff6 100644 --- a/spec/controllers/forums_controller_spec.rb +++ b/spec/controllers/forums_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe ForumsController do diff --git a/spec/controllers/gardens_controller_spec.rb b/spec/controllers/gardens_controller_spec.rb index 242ec6ffa..2bba8a2f8 100644 --- a/spec/controllers/gardens_controller_spec.rb +++ b/spec/controllers/gardens_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe GardensController do diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb index 38b0edf8c..9ced0cece 100644 --- a/spec/controllers/harvests_controller_spec.rb +++ b/spec/controllers/harvests_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe HarvestsController do diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb index bfbfc6adf..da5edc384 100644 --- a/spec/controllers/home_controller_spec.rb +++ b/spec/controllers/home_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe HomeController do diff --git a/spec/controllers/member_controller_spec.rb b/spec/controllers/member_controller_spec.rb index ff5a0ae42..35d5b0c6d 100644 --- a/spec/controllers/member_controller_spec.rb +++ b/spec/controllers/member_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe MembersController do diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index 99add1cf4..d55b7df26 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe NotificationsController do diff --git a/spec/controllers/order_items_controller_spec.rb b/spec/controllers/order_items_controller_spec.rb index a33c55cc3..c8d23a4fd 100644 --- a/spec/controllers/order_items_controller_spec.rb +++ b/spec/controllers/order_items_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe OrderItemsController do diff --git a/spec/controllers/orders_controller_spec.rb b/spec/controllers/orders_controller_spec.rb index 9fecc3695..d01f37f92 100644 --- a/spec/controllers/orders_controller_spec.rb +++ b/spec/controllers/orders_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe OrdersController do diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index 1c3b47780..2dd7a6a56 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe PhotosController do diff --git a/spec/controllers/places_controller_spec.rb b/spec/controllers/places_controller_spec.rb index 7d5841a6d..0c83c206a 100644 --- a/spec/controllers/places_controller_spec.rb +++ b/spec/controllers/places_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe PlacesController do before :each do diff --git a/spec/controllers/plant_parts_controller_spec.rb b/spec/controllers/plant_parts_controller_spec.rb index 9aefaa953..e813e0f38 100644 --- a/spec/controllers/plant_parts_controller_spec.rb +++ b/spec/controllers/plant_parts_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe PlantPartsController do diff --git a/spec/controllers/plantings_controller_spec.rb b/spec/controllers/plantings_controller_spec.rb index 4b3a518a5..aa6fcbe4e 100644 --- a/spec/controllers/plantings_controller_spec.rb +++ b/spec/controllers/plantings_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe PlantingsController do diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index bbb8bdccb..8121b318e 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe PostsController do diff --git a/spec/controllers/products_controller_spec.rb b/spec/controllers/products_controller_spec.rb index f2daad383..5804ad09d 100644 --- a/spec/controllers/products_controller_spec.rb +++ b/spec/controllers/products_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe ProductsController do diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index 0ba0e29e6..8c0a669b4 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe RegistrationsController do diff --git a/spec/controllers/roles_controller_spec.rb b/spec/controllers/roles_controller_spec.rb index 0665101b4..f34bb79e3 100644 --- a/spec/controllers/roles_controller_spec.rb +++ b/spec/controllers/roles_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe RolesController do diff --git a/spec/controllers/scientific_names_controller_spec.rb b/spec/controllers/scientific_names_controller_spec.rb index 254ebf1c8..45dd92066 100644 --- a/spec/controllers/scientific_names_controller_spec.rb +++ b/spec/controllers/scientific_names_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe ScientificNamesController do diff --git a/spec/controllers/seeds_controller_spec.rb b/spec/controllers/seeds_controller_spec.rb index d41fe7c3b..7b0da6593 100644 --- a/spec/controllers/seeds_controller_spec.rb +++ b/spec/controllers/seeds_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe SeedsController do describe "GET index" do diff --git a/spec/controllers/shop_controller_spec.rb b/spec/controllers/shop_controller_spec.rb index 2aaaa58ff..626757b52 100644 --- a/spec/controllers/shop_controller_spec.rb +++ b/spec/controllers/shop_controller_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe ShopController do diff --git a/spec/features/admin/account_types_spec.rb b/spec/features/admin/account_types_spec.rb index 2f8cda09f..b56144344 100644 --- a/spec/features/admin/account_types_spec.rb +++ b/spec/features/admin/account_types_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "account types" do context "admin user" do diff --git a/spec/features/admin/forums_spec.rb b/spec/features/admin/forums_spec.rb index a5c6f4fb1..e9f8a43f9 100644 --- a/spec/features/admin/forums_spec.rb +++ b/spec/features/admin/forums_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "forums" do context "admin user" do diff --git a/spec/features/alternate_name_spec.rb b/spec/features/alternate_name_spec.rb index 086584c40..8ec2a21fe 100644 --- a/spec/features/alternate_name_spec.rb +++ b/spec/features/alternate_name_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "Alternate names" do let!(:alternate_eggplant) { FactoryGirl.create(:alternate_eggplant) } diff --git a/spec/features/crop_wranglers_spec.rb b/spec/features/crop_wranglers_spec.rb index 32c96e639..b8d525a3f 100644 --- a/spec/features/crop_wranglers_spec.rb +++ b/spec/features/crop_wranglers_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "crop wranglers" do context "signed in member" do diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index a941cb075..a9740c131 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "crop detail page" do diff --git a/spec/features/footer_spec.rb b/spec/features/footer_spec.rb index aa8449b15..7187793c1 100644 --- a/spec/features/footer_spec.rb +++ b/spec/features/footer_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "footer" do scenario "contact page has Twitter link" do diff --git a/spec/features/gardens_spec.rb b/spec/features/gardens_spec.rb index 1b803a41e..972b269f7 100644 --- a/spec/features/gardens_spec.rb +++ b/spec/features/gardens_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "Planting a crop", :js => true do let!(:garden) { FactoryGirl.create(:garden) } diff --git a/spec/features/harvests/harvesting_a_crop_spec.rb b/spec/features/harvests/harvesting_a_crop_spec.rb index caffb237d..40c0eb8f8 100644 --- a/spec/features/harvests/harvesting_a_crop_spec.rb +++ b/spec/features/harvests/harvesting_a_crop_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "Harvesting a crop", :js => true do let(:member) { FactoryGirl.create(:member) } diff --git a/spec/features/locale_spec.rb b/spec/features/locale_spec.rb index b5893858d..36b07b5c9 100644 --- a/spec/features/locale_spec.rb +++ b/spec/features/locale_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "Changing locales" do diff --git a/spec/features/member_profile_spec.rb b/spec/features/member_profile_spec.rb index 809b052a8..ad5082e3f 100644 --- a/spec/features/member_profile_spec.rb +++ b/spec/features/member_profile_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "member profile" do diff --git a/spec/features/planting_reminder_spec.rb b/spec/features/planting_reminder_spec.rb index 5adb44095..3b8c88bf8 100644 --- a/spec/features/planting_reminder_spec.rb +++ b/spec/features/planting_reminder_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' require 'capybara/email/rspec' feature "Planting reminder email", :js => true do diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 99114ab43..4d53b7117 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" feature "Planting a crop", :js => true do let(:member) { FactoryGirl.create(:member) } diff --git a/spec/features/scientific_name_spec.rb b/spec/features/scientific_name_spec.rb index 1fda79d42..c6cd60c6a 100644 --- a/spec/features/scientific_name_spec.rb +++ b/spec/features/scientific_name_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "Scientific names" do let!(:zea_mays) { FactoryGirl.create(:zea_mays) } diff --git a/spec/features/seeds/adding_seeds_spec.rb b/spec/features/seeds/adding_seeds_spec.rb index ca79c5b8c..668771850 100644 --- a/spec/features/seeds/adding_seeds_spec.rb +++ b/spec/features/seeds/adding_seeds_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "Harvesting a crop", :js => true do let(:member) { FactoryGirl.create(:member) } diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb index e72e3b68f..f962d4c4e 100644 --- a/spec/features/seeds/misc_seeds_spec.rb +++ b/spec/features/seeds/misc_seeds_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "seeds" do context "signed in user" do diff --git a/spec/features/shared_examples/crop_suggest.rb b/spec/features/shared_examples/crop_suggest.rb index 499bab891..141dfbabf 100644 --- a/spec/features/shared_examples/crop_suggest.rb +++ b/spec/features/shared_examples/crop_suggest.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' shared_examples "crop suggest" do |resource| let!(:popcorn) { FactoryGirl.create(:popcorn) } diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index b4a5eb7bb..4cefddbf0 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "signin" do let(:member){FactoryGirl.create(:member)} diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb index 9962df359..c91ad4682 100644 --- a/spec/features/signup_spec.rb +++ b/spec/features/signup_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' feature "signup" do diff --git a/spec/helpers/application_helper.rb b/spec/helpers/application_helper.rb index 912ffbfd5..9a39e59a7 100644 --- a/spec/helpers/application_helper.rb +++ b/spec/helpers/application_helper.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe ApplicationHelper do it "formats prices" do diff --git a/spec/helpers/harvests_helper_spec.rb b/spec/helpers/harvests_helper_spec.rb index ecc30a51e..7bc516162 100644 --- a/spec/helpers/harvests_helper_spec.rb +++ b/spec/helpers/harvests_helper_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe HarvestsHelper do describe "display_quantity" do diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb index 9db3a95aa..85f96d664 100644 --- a/spec/helpers/notifications_helper_spec.rb +++ b/spec/helpers/notifications_helper_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe NotificationsHelper do describe "reply_link" do diff --git a/spec/lib/haml/filters/escaped_markdown_spec.rb b/spec/lib/haml/filters/escaped_markdown_spec.rb index 9e2c1ce1f..60066160f 100644 --- a/spec/lib/haml/filters/escaped_markdown_spec.rb +++ b/spec/lib/haml/filters/escaped_markdown_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' require 'haml/filters' require 'haml/filters/escaped_markdown' require 'haml/helpers' diff --git a/spec/lib/haml/filters/growstuff_markdown_spec.rb b/spec/lib/haml/filters/growstuff_markdown_spec.rb index 718645322..8abe8aee4 100644 --- a/spec/lib/haml/filters/growstuff_markdown_spec.rb +++ b/spec/lib/haml/filters/growstuff_markdown_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' require 'haml/filters' require 'haml/filters/growstuff_markdown' diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb index 6ade0fb78..4c7ac59a3 100644 --- a/spec/mailers/notifier_spec.rb +++ b/spec/mailers/notifier_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe Notifier do diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index 06ac61b7c..4eccf8916 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' require 'cancan/matchers' describe Ability do diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 8b2acd470..b1765ccc0 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Account do before(:each) do diff --git a/spec/models/account_type_spec.rb b/spec/models/account_type_spec.rb index 8dfe24bf7..c65c113ba 100644 --- a/spec/models/account_type_spec.rb +++ b/spec/models/account_type_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe AccountType do end diff --git a/spec/models/alternate_name_spec.rb b/spec/models/alternate_name_spec.rb index f7acd0efc..7819586cc 100644 --- a/spec/models/alternate_name_spec.rb +++ b/spec/models/alternate_name_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe AlternateName do let(:an) { FactoryGirl.create(:alternate_eggplant) } diff --git a/spec/models/authentication_spec.rb b/spec/models/authentication_spec.rb index 2a9df9aec..0159361ff 100644 --- a/spec/models/authentication_spec.rb +++ b/spec/models/authentication_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Authentication do diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index d487d0b91..d54cd5606 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Comment do diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index 661a688a3..76740cdfe 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Crop do context 'all fields present' do diff --git a/spec/models/forum_spec.rb b/spec/models/forum_spec.rb index 98ce1c24a..9769882c6 100644 --- a/spec/models/forum_spec.rb +++ b/spec/models/forum_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Forum do before(:each) do diff --git a/spec/models/garden_spec.rb b/spec/models/garden_spec.rb index 8bf355cd0..2ff2f7436 100644 --- a/spec/models/garden_spec.rb +++ b/spec/models/garden_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Garden do before :each do diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index e1bc76ee7..504c8c414 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Harvest do diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 49b66ef71..0fb6cdacc 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'member' do diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index a8bddb9fa..27924ebed 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Notification do before(:each) do diff --git a/spec/models/order_item_spec.rb b/spec/models/order_item_spec.rb index e12cc9fbf..20c0be94f 100644 --- a/spec/models/order_item_spec.rb +++ b/spec/models/order_item_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe OrderItem do before(:each) do diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb index 60e98ac4d..50fb6f949 100644 --- a/spec/models/order_spec.rb +++ b/spec/models/order_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Order do before(:each) do diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index f17127301..850fa42cc 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Photo do diff --git a/spec/models/plant_part_spec.rb b/spec/models/plant_part_spec.rb index 45536afe4..f8dc1f290 100644 --- a/spec/models/plant_part_spec.rb +++ b/spec/models/plant_part_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe PlantPart do it 'stringifies' do diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 0f64a53f1..fba4fabe1 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Planting do diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 30c19c500..adce855d2 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Post do before(:each) do diff --git a/spec/models/product_spec.rb b/spec/models/product_spec.rb index 59339a8c9..af1a02ba5 100644 --- a/spec/models/product_spec.rb +++ b/spec/models/product_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Product do diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb index 5a74d6165..6ea5d1a9d 100644 --- a/spec/models/role_spec.rb +++ b/spec/models/role_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Role do let(:member) { FactoryGirl.create(:member) } diff --git a/spec/models/scientific_name_spec.rb b/spec/models/scientific_name_spec.rb index 496cf4dad..d8404d0ba 100644 --- a/spec/models/scientific_name_spec.rb +++ b/spec/models/scientific_name_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe ScientificName do context 'all fields present' do diff --git a/spec/models/seed_spec.rb b/spec/models/seed_spec.rb index 355edac10..6a134a47e 100644 --- a/spec/models/seed_spec.rb +++ b/spec/models/seed_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe Seed do diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 000000000..0ab8f09fc --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,90 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV["RAILS_ENV"] ||= 'test' +require 'spec_helper' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' +# Add additional requires below this line. Rails is not loaded until this point! +require 'rspec/autorun' +require 'simplecov' +require 'coveralls' +require 'rails-observers' + +# output coverage locally AND send it to coveralls +SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ + SimpleCov::Formatter::HTMLFormatter, + Coveralls::SimpleCov::Formatter +] + +# fail if there's a significant test coverage drop +SimpleCov.maximum_coverage_drop 1 + +SimpleCov.start :rails do + add_filter 'spec/' + add_filter 'vendor/' +end + +require 'capybara' +require 'capybara/poltergeist' +Capybara.javascript_driver = :poltergeist +Capybara.app_host = 'http://localhost' +Capybara.server_port = 8080 + +include Warden::Test::Helpers + +# Requires supporting ruby files with custom matchers and macros, etc, in +# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are +# run as spec files by default. This means that files in spec/support that end +# in _spec.rb will both be required and run as specs, causing the specs to be +# run twice. It is recommended that you do not name files matching this glob to +# end with _spec.rb. You can configure this pattern with the --pattern +# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. +# +# The following line is provided for convenience purposes. It has the downside +# of increasing the boot-up time by auto-requiring all files in the support +# directory. Alternatively, in the individual `*_spec.rb` files, manually +# require only the support files necessary. +# +Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } +Dir[Rails.root.join("spec/features/shared_examples/**/*.rb")].each {|f| require f} + +# Checks for pending migrations before tests are run. +# If you are not using ActiveRecord, you can remove this line. +ActiveRecord::Migration.maintain_test_schema! + +RSpec.configure do |config| + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + # config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = false + + # If true, the base class of anonymous controllers will be inferred + # automatically. This will be the default behavior in future versions of + # rspec-rails. + config.infer_base_class_for_anonymous_controllers = false + + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, :type => :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://relishapp.com/rspec/rspec-rails/docs + config.infer_spec_type_from_file_location! + + # controller specs require this to work with Devise + # see https://github.com/plataformatec/devise/wiki/How-To%3a-Controllers-and-Views-tests-with-Rails-3-%28and-rspec%29 + config.include Devise::TestHelpers, :type => :controller + config.extend ControllerMacros, :type => :controller + config.before(:each) do + Sweeper.any_instance.stub(:expire_fragment) + end +end diff --git a/spec/requests/authentications_spec.rb b/spec/requests/authentications_spec.rb index f50942928..6cc612f44 100644 --- a/spec/requests/authentications_spec.rb +++ b/spec/requests/authentications_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Authentications" do describe "GET /authentications" do diff --git a/spec/requests/comments_spec.rb b/spec/requests/comments_spec.rb index 7a38a46e8..c9b2ba9dc 100644 --- a/spec/requests/comments_spec.rb +++ b/spec/requests/comments_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Comments" do describe "GET /comments" do diff --git a/spec/requests/forums_spec.rb b/spec/requests/forums_spec.rb index ee85dacfd..ff7cb283d 100644 --- a/spec/requests/forums_spec.rb +++ b/spec/requests/forums_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Forums" do describe "GET /forums" do diff --git a/spec/requests/gardens_spec.rb b/spec/requests/gardens_spec.rb index bc8cd3ec2..91a8dc8b7 100644 --- a/spec/requests/gardens_spec.rb +++ b/spec/requests/gardens_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Gardens" do describe "GET /gardens" do diff --git a/spec/requests/harvests_spec.rb b/spec/requests/harvests_spec.rb index edb408b0b..f3774b3c0 100644 --- a/spec/requests/harvests_spec.rb +++ b/spec/requests/harvests_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Harvests" do describe "GET /harvests" do diff --git a/spec/requests/notifications_spec.rb b/spec/requests/notifications_spec.rb index 62031013e..85afbdd9f 100644 --- a/spec/requests/notifications_spec.rb +++ b/spec/requests/notifications_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Notifications" do describe "GET /notifications" do diff --git a/spec/requests/photos_spec.rb b/spec/requests/photos_spec.rb index bfb595245..b937ded3d 100644 --- a/spec/requests/photos_spec.rb +++ b/spec/requests/photos_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Photos" do describe "GET /photos" do diff --git a/spec/requests/plant_parts_spec.rb b/spec/requests/plant_parts_spec.rb index 4f607b22f..1fc2150b2 100644 --- a/spec/requests/plant_parts_spec.rb +++ b/spec/requests/plant_parts_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "PlantParts" do describe "GET /plant_parts" do diff --git a/spec/requests/plantings_spec.rb b/spec/requests/plantings_spec.rb index cc5580f58..cb66922e0 100644 --- a/spec/requests/plantings_spec.rb +++ b/spec/requests/plantings_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Plantings" do describe "GET /plantings" do diff --git a/spec/requests/post_spec.rb b/spec/requests/post_spec.rb index 5cfcf60bf..3bb479aa8 100644 --- a/spec/requests/post_spec.rb +++ b/spec/requests/post_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Posts" do describe "GET /posts" do diff --git a/spec/requests/scientific_names_spec.rb b/spec/requests/scientific_names_spec.rb index 0b2d8dd5a..922f6f270 100644 --- a/spec/requests/scientific_names_spec.rb +++ b/spec/requests/scientific_names_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "ScientificNames" do describe "GET /scientific_names" do diff --git a/spec/requests/seeds_spec.rb b/spec/requests/seeds_spec.rb index ac3ee1076..8bc5aeccf 100644 --- a/spec/requests/seeds_spec.rb +++ b/spec/requests/seeds_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "Seeds" do describe "GET /seeds" do diff --git a/spec/routing/account_types_routing_spec.rb b/spec/routing/account_types_routing_spec.rb index 456cedebe..440c16956 100644 --- a/spec/routing/account_types_routing_spec.rb +++ b/spec/routing/account_types_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe AccountTypesController do describe "routing" do diff --git a/spec/routing/authentications_routing_spec.rb b/spec/routing/authentications_routing_spec.rb index 1a639dead..db574d686 100644 --- a/spec/routing/authentications_routing_spec.rb +++ b/spec/routing/authentications_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe AuthenticationsController do describe "routing" do diff --git a/spec/routing/comments_routing_spec.rb b/spec/routing/comments_routing_spec.rb index 73c80563e..4a0fe8026 100644 --- a/spec/routing/comments_routing_spec.rb +++ b/spec/routing/comments_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe CommentsController do describe "routing" do diff --git a/spec/routing/crops_routing_spec.rb b/spec/routing/crops_routing_spec.rb index 450ad30f3..1e1fe4aac 100644 --- a/spec/routing/crops_routing_spec.rb +++ b/spec/routing/crops_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe CropsController do describe "routing" do diff --git a/spec/routing/forums_routing_spec.rb b/spec/routing/forums_routing_spec.rb index c783d5199..4bd7d6097 100644 --- a/spec/routing/forums_routing_spec.rb +++ b/spec/routing/forums_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe ForumsController do describe "routing" do diff --git a/spec/routing/gardens_routing_spec.rb b/spec/routing/gardens_routing_spec.rb index e3fbd6f31..1c627e091 100644 --- a/spec/routing/gardens_routing_spec.rb +++ b/spec/routing/gardens_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe GardensController do describe "routing" do diff --git a/spec/routing/harvests_routing_spec.rb b/spec/routing/harvests_routing_spec.rb index 66ab7151e..8b34d920a 100644 --- a/spec/routing/harvests_routing_spec.rb +++ b/spec/routing/harvests_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe HarvestsController do describe "routing" do diff --git a/spec/routing/notifications_routing_spec.rb b/spec/routing/notifications_routing_spec.rb index 421a443b3..35f54689f 100644 --- a/spec/routing/notifications_routing_spec.rb +++ b/spec/routing/notifications_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe NotificationsController do describe "routing" do diff --git a/spec/routing/order_items_routing_spec.rb b/spec/routing/order_items_routing_spec.rb index 1993db17d..858a873ad 100644 --- a/spec/routing/order_items_routing_spec.rb +++ b/spec/routing/order_items_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe OrderItemsController do describe "routing" do diff --git a/spec/routing/orders_routing_spec.rb b/spec/routing/orders_routing_spec.rb index 77e2c131d..7fc9735ee 100644 --- a/spec/routing/orders_routing_spec.rb +++ b/spec/routing/orders_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe OrdersController do describe "routing" do diff --git a/spec/routing/photos_routing_spec.rb b/spec/routing/photos_routing_spec.rb index d7dc394ed..5bdfeca07 100644 --- a/spec/routing/photos_routing_spec.rb +++ b/spec/routing/photos_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe PhotosController do describe "routing" do diff --git a/spec/routing/plant_parts_routing_spec.rb b/spec/routing/plant_parts_routing_spec.rb index 419b4a05e..54d02caa1 100644 --- a/spec/routing/plant_parts_routing_spec.rb +++ b/spec/routing/plant_parts_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe PlantPartsController do describe "routing" do diff --git a/spec/routing/plantings_routing_spec.rb b/spec/routing/plantings_routing_spec.rb index 08fb24301..bf3e1e8b8 100644 --- a/spec/routing/plantings_routing_spec.rb +++ b/spec/routing/plantings_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe PlantingsController do describe "routing" do diff --git a/spec/routing/products_routing_spec.rb b/spec/routing/products_routing_spec.rb index e50a77956..a9c2fa004 100644 --- a/spec/routing/products_routing_spec.rb +++ b/spec/routing/products_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe ProductsController do describe "routing" do diff --git a/spec/routing/roles_routing_spec.rb b/spec/routing/roles_routing_spec.rb index 4084a6e7e..0a7900f9d 100644 --- a/spec/routing/roles_routing_spec.rb +++ b/spec/routing/roles_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe RolesController do describe "routing" do diff --git a/spec/routing/scientific_names_routing_spec.rb b/spec/routing/scientific_names_routing_spec.rb index c78d1ff7d..00c049289 100644 --- a/spec/routing/scientific_names_routing_spec.rb +++ b/spec/routing/scientific_names_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe ScientificNamesController do describe "routing" do diff --git a/spec/routing/seeds_routing_spec.rb b/spec/routing/seeds_routing_spec.rb index d4746d299..4fe46774a 100644 --- a/spec/routing/seeds_routing_spec.rb +++ b/spec/routing/seeds_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe SeedsController do describe "routing" do diff --git a/spec/routing/updates_routing_spec.rb b/spec/routing/updates_routing_spec.rb index 0266d9686..9ff2b5ccd 100644 --- a/spec/routing/updates_routing_spec.rb +++ b/spec/routing/updates_routing_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require "rails_helper" describe PostsController do describe "routing" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9176aea29..a9872e6f6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,74 +1,85 @@ -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV["RAILS_ENV"] ||= 'test' - -require File.expand_path("../../config/environment", __FILE__) -require 'rspec/rails' -require 'rspec/autorun' - -require 'simplecov' -require 'coveralls' - -# output coverage locally AND send it to coveralls -SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ - SimpleCov::Formatter::HTMLFormatter, - Coveralls::SimpleCov::Formatter -] - -# fail if there's a significant test coverage drop -SimpleCov.maximum_coverage_drop 1 - -SimpleCov.start :rails do - add_filter 'spec/' - add_filter 'vendor/' -end - -require 'capybara' -require 'capybara/poltergeist' -Capybara.javascript_driver = :poltergeist -Capybara.app_host = 'http://localhost' -Capybara.server_port = 8080 - -include Warden::Test::Helpers - -# Requires supporting ruby files with custom matchers and macros, etc, -# in spec/support/ and its subdirectories. -Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} -Dir[Rails.root.join("spec/features/shared_examples/**/*.rb")].each {|f| require f} - +# This file was generated by the `rails generate rspec:install` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause this +# file to always be loaded, without a need to explicitly require it in any files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need it. +# +# The `.rspec` file also contains a few flags that are not defaults but that +# users commonly want. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| - # ## Mock Framework - # - # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line - # - # config.mock_with :mocha - # config.mock_with :flexmock - # config.mock_with :rr + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - # config.fixture_path = "#{::Rails.root}/spec/fixtures" + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = false +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. - # If true, the base class of anonymous controllers will be inferred - # automatically. This will be the default behavior in future versions of - # rspec-rails. - config.infer_base_class_for_anonymous_controllers = false + # These two settings work together to allow you to limit a spec run + # to individual examples or groups you care about by tagging them with + # `:focus` metadata. When nothing is tagged with `:focus`, all examples + # get run. + config.filter_run :focus + config.run_all_when_everything_filtered = true + + # Limits the available syntax to the non-monkey patched syntax that is recommended. + # For more details, see: + # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax + # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching + # config.disable_monkey_patching! + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = 'doc' + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 3 # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 - config.order = "random" + config.order = :random - # controller specs require this to work with Devise - # see https://github.com/plataformatec/devise/wiki/How-To%3a-Controllers-and-Views-tests-with-Rails-3-%28and-rspec%29 - config.include Devise::TestHelpers, :type => :controller - config.extend ControllerMacros, :type => :controller + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed - config.before(:each) do - ActionController::Caching::Sweeper.any_instance.stub(:expire_fragment) - end end diff --git a/spec/views/about/contact_spec.rb b/spec/views/about/contact_spec.rb index 85d232126..2dcd31c9d 100644 --- a/spec/views/about/contact_spec.rb +++ b/spec/views/about/contact_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'about/contact.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/account_types/edit.html.haml_spec.rb b/spec/views/account_types/edit.html.haml_spec.rb index bb5fbf433..cf77a0402 100644 --- a/spec/views/account_types/edit.html.haml_spec.rb +++ b/spec/views/account_types/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "account_types/edit" do before(:each) do diff --git a/spec/views/account_types/index.html.haml_spec.rb b/spec/views/account_types/index.html.haml_spec.rb index cded5ef32..1bbd0dc72 100644 --- a/spec/views/account_types/index.html.haml_spec.rb +++ b/spec/views/account_types/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "account_types/index" do before(:each) do diff --git a/spec/views/account_types/new.html.haml_spec.rb b/spec/views/account_types/new.html.haml_spec.rb index 3babc2fb9..a9e97ee54 100644 --- a/spec/views/account_types/new.html.haml_spec.rb +++ b/spec/views/account_types/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "account_types/new" do before(:each) do diff --git a/spec/views/account_types/show.html.haml_spec.rb b/spec/views/account_types/show.html.haml_spec.rb index 941026cf4..bee9cebd5 100644 --- a/spec/views/account_types/show.html.haml_spec.rb +++ b/spec/views/account_types/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "account_types/show" do before(:each) do diff --git a/spec/views/accounts/edit.html.haml_spec.rb b/spec/views/accounts/edit.html.haml_spec.rb index af3931dfa..124ec1d12 100644 --- a/spec/views/accounts/edit.html.haml_spec.rb +++ b/spec/views/accounts/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "accounts/edit" do before(:each) do diff --git a/spec/views/accounts/index.html.haml_spec.rb b/spec/views/accounts/index.html.haml_spec.rb index 56e76b0ff..e8c0f1a79 100644 --- a/spec/views/accounts/index.html.haml_spec.rb +++ b/spec/views/accounts/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "accounts/index" do before(:each) do diff --git a/spec/views/accounts/new.html.haml_spec.rb b/spec/views/accounts/new.html.haml_spec.rb index ab60cc346..3a2b7cdbc 100644 --- a/spec/views/accounts/new.html.haml_spec.rb +++ b/spec/views/accounts/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "accounts/new" do before(:each) do diff --git a/spec/views/accounts/show.html.haml_spec.rb b/spec/views/accounts/show.html.haml_spec.rb index 5b429e13e..99ea2f1a0 100644 --- a/spec/views/accounts/show.html.haml_spec.rb +++ b/spec/views/accounts/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "accounts/show" do before(:each) do diff --git a/spec/views/admin/index_spec.rb b/spec/views/admin/index_spec.rb index fe92a4193..744ac639d 100644 --- a/spec/views/admin/index_spec.rb +++ b/spec/views/admin/index_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'admin/index.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/admin/newsletter_spec.rb b/spec/views/admin/newsletter_spec.rb index a0d871cd4..a3b5e67f6 100644 --- a/spec/views/admin/newsletter_spec.rb +++ b/spec/views/admin/newsletter_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'admin/newsletter.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/admin/orders/index_spec.rb b/spec/views/admin/orders/index_spec.rb index bc49a0028..e4279fdd0 100644 --- a/spec/views/admin/orders/index_spec.rb +++ b/spec/views/admin/orders/index_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'admin/orders/index.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/authentications/index.html.haml_spec.rb b/spec/views/authentications/index.html.haml_spec.rb index f780966ae..8fa3ba9b8 100644 --- a/spec/views/authentications/index.html.haml_spec.rb +++ b/spec/views/authentications/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "authentications/index" do before(:each) do diff --git a/spec/views/comments/edit.html.haml_spec.rb b/spec/views/comments/edit.html.haml_spec.rb index beee78013..87ba9c549 100644 --- a/spec/views/comments/edit.html.haml_spec.rb +++ b/spec/views/comments/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "comments/edit" do before(:each) do diff --git a/spec/views/comments/index.html.haml_spec.rb b/spec/views/comments/index.html.haml_spec.rb index 3cf270149..e0260e207 100644 --- a/spec/views/comments/index.html.haml_spec.rb +++ b/spec/views/comments/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "comments/index" do before(:each) do diff --git a/spec/views/comments/index.rss.haml_spec.rb b/spec/views/comments/index.rss.haml_spec.rb index e5eeeac95..f4d767800 100644 --- a/spec/views/comments/index.rss.haml_spec.rb +++ b/spec/views/comments/index.rss.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'comments/index.rss.haml' do before(:each) do diff --git a/spec/views/comments/new.html.haml_spec.rb b/spec/views/comments/new.html.haml_spec.rb index a27868a16..6b92ce27c 100644 --- a/spec/views/comments/new.html.haml_spec.rb +++ b/spec/views/comments/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "comments/new" do before(:each) do diff --git a/spec/views/comments/show.html.haml_spec.rb b/spec/views/comments/show.html.haml_spec.rb index 9c2af0496..a24dd4136 100644 --- a/spec/views/comments/show.html.haml_spec.rb +++ b/spec/views/comments/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "comments/show" do before(:each) do diff --git a/spec/views/crops/_grown_for.html.haml_spec.rb b/spec/views/crops/_grown_for.html.haml_spec.rb index 3950c1d32..47a475371 100644 --- a/spec/views/crops/_grown_for.html.haml_spec.rb +++ b/spec/views/crops/_grown_for.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/_grown_for" do before(:each) do diff --git a/spec/views/crops/_planting_advice.html.haml_spec.rb b/spec/views/crops/_planting_advice.html.haml_spec.rb index f92fe2bd7..875ee6eef 100644 --- a/spec/views/crops/_planting_advice.html.haml_spec.rb +++ b/spec/views/crops/_planting_advice.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/_planting_advice" do before(:each) do diff --git a/spec/views/crops/_popover.html.haml_spec.rb b/spec/views/crops/_popover.html.haml_spec.rb index ad07f8ada..f9dc0d325 100644 --- a/spec/views/crops/_popover.html.haml_spec.rb +++ b/spec/views/crops/_popover.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/_popover" do before(:each) do diff --git a/spec/views/crops/edit.html.haml_spec.rb b/spec/views/crops/edit.html.haml_spec.rb index 3db9c52b0..eaf76a092 100644 --- a/spec/views/crops/edit.html.haml_spec.rb +++ b/spec/views/crops/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/edit" do before(:each) do diff --git a/spec/views/crops/hierarchy.html.haml_spec.rb b/spec/views/crops/hierarchy.html.haml_spec.rb index e5fbc7883..22b02d18f 100644 --- a/spec/views/crops/hierarchy.html.haml_spec.rb +++ b/spec/views/crops/hierarchy.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/hierarchy" do before(:each) do diff --git a/spec/views/crops/index.html.haml_spec.rb b/spec/views/crops/index.html.haml_spec.rb index ca0ecc39b..0c0554afa 100644 --- a/spec/views/crops/index.html.haml_spec.rb +++ b/spec/views/crops/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/index" do before(:each) do diff --git a/spec/views/crops/index.rss.haml_spec.rb b/spec/views/crops/index.rss.haml_spec.rb index f0c5ac653..4c19c5f26 100644 --- a/spec/views/crops/index.rss.haml_spec.rb +++ b/spec/views/crops/index.rss.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'crops/index.rss.haml' do before(:each) do diff --git a/spec/views/crops/new.html.haml_spec.rb b/spec/views/crops/new.html.haml_spec.rb index 0aa443f74..0c834d738 100644 --- a/spec/views/crops/new.html.haml_spec.rb +++ b/spec/views/crops/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/new" do before(:each) do diff --git a/spec/views/crops/search.html.haml_spec.rb b/spec/views/crops/search.html.haml_spec.rb index c186c6c4c..352d9730d 100644 --- a/spec/views/crops/search.html.haml_spec.rb +++ b/spec/views/crops/search.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/search" do before(:each) do diff --git a/spec/views/crops/wrangle.html.haml_spec.rb b/spec/views/crops/wrangle.html.haml_spec.rb index a4adde063..a91663c09 100644 --- a/spec/views/crops/wrangle.html.haml_spec.rb +++ b/spec/views/crops/wrangle.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "crops/wrangle" do before(:each) do diff --git a/spec/views/devise/mailer/confirmation_instructions_spec.rb b/spec/views/devise/mailer/confirmation_instructions_spec.rb index 3a0921ae7..368446247 100644 --- a/spec/views/devise/mailer/confirmation_instructions_spec.rb +++ b/spec/views/devise/mailer/confirmation_instructions_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'devise/mailer/confirmation_instructions.html.haml', :type => "view" do diff --git a/spec/views/devise/mailer/reset_password_instructions_spec.rb b/spec/views/devise/mailer/reset_password_instructions_spec.rb index 5c3a4f222..48944f266 100644 --- a/spec/views/devise/mailer/reset_password_instructions_spec.rb +++ b/spec/views/devise/mailer/reset_password_instructions_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'devise/mailer/reset_password_instructions.html.haml', :type => "view" do diff --git a/spec/views/devise/mailer/unlock_instructions_spec.rb b/spec/views/devise/mailer/unlock_instructions_spec.rb index 9cbca83a4..02a2bd182 100644 --- a/spec/views/devise/mailer/unlock_instructions_spec.rb +++ b/spec/views/devise/mailer/unlock_instructions_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'devise/mailer/unlock_instructions.html.haml', :type => "view" do context "logged in" do before(:each) do diff --git a/spec/views/devise/registrations/edit_spec.rb b/spec/views/devise/registrations/edit_spec.rb index f9c48ec1a..8e9c11087 100644 --- a/spec/views/devise/registrations/edit_spec.rb +++ b/spec/views/devise/registrations/edit_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'devise/registrations/edit.html.haml', :type => "view" do diff --git a/spec/views/devise/registrations/new_spec.rb b/spec/views/devise/registrations/new_spec.rb index b17b000b7..3c03ba7aa 100644 --- a/spec/views/devise/registrations/new_spec.rb +++ b/spec/views/devise/registrations/new_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'devise/registrations/new.html.haml', :type => "view" do diff --git a/spec/views/devise/sessions/new_spec.rb b/spec/views/devise/sessions/new_spec.rb index 9a178e63f..f795b1d55 100644 --- a/spec/views/devise/sessions/new_spec.rb +++ b/spec/views/devise/sessions/new_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'devise/sessions/new.html.haml', :type => "view" do diff --git a/spec/views/devise/unlocks/new_spec.rb b/spec/views/devise/unlocks/new_spec.rb index 0259691fe..2d1b8f705 100644 --- a/spec/views/devise/unlocks/new_spec.rb +++ b/spec/views/devise/unlocks/new_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'devise/unlocks/new.html.haml', :type => "view" do diff --git a/spec/views/forums/edit.html.haml_spec.rb b/spec/views/forums/edit.html.haml_spec.rb index 306f3bbf0..8a49b38be 100644 --- a/spec/views/forums/edit.html.haml_spec.rb +++ b/spec/views/forums/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "forums/edit" do before(:each) do diff --git a/spec/views/forums/index.html.haml_spec.rb b/spec/views/forums/index.html.haml_spec.rb index d2046de48..99ea944ea 100644 --- a/spec/views/forums/index.html.haml_spec.rb +++ b/spec/views/forums/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "forums/index" do before(:each) do diff --git a/spec/views/forums/new.html.haml_spec.rb b/spec/views/forums/new.html.haml_spec.rb index bfda7bfa1..86043eb8c 100644 --- a/spec/views/forums/new.html.haml_spec.rb +++ b/spec/views/forums/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "forums/new" do before(:each) do diff --git a/spec/views/forums/show.html.haml_spec.rb b/spec/views/forums/show.html.haml_spec.rb index 735f5d482..2e61541fe 100644 --- a/spec/views/forums/show.html.haml_spec.rb +++ b/spec/views/forums/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "forums/show" do before(:each) do diff --git a/spec/views/gardens/edit.html.haml_spec.rb b/spec/views/gardens/edit.html.haml_spec.rb index 781274c2c..e5381c324 100644 --- a/spec/views/gardens/edit.html.haml_spec.rb +++ b/spec/views/gardens/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "gardens/edit" do diff --git a/spec/views/gardens/index.html.haml_spec.rb b/spec/views/gardens/index.html.haml_spec.rb index 123a75db9..a075822be 100644 --- a/spec/views/gardens/index.html.haml_spec.rb +++ b/spec/views/gardens/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "gardens/index" do before(:each) do diff --git a/spec/views/gardens/new.html.haml_spec.rb b/spec/views/gardens/new.html.haml_spec.rb index 5e7d4c1e7..ff52f1f28 100644 --- a/spec/views/gardens/new.html.haml_spec.rb +++ b/spec/views/gardens/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "gardens/new" do before(:each) do diff --git a/spec/views/gardens/show.html.haml_spec.rb b/spec/views/gardens/show.html.haml_spec.rb index cd38a0ec4..fee56002f 100644 --- a/spec/views/gardens/show.html.haml_spec.rb +++ b/spec/views/gardens/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "gardens/show" do before(:each) do diff --git a/spec/views/harvests/edit.html.haml_spec.rb b/spec/views/harvests/edit.html.haml_spec.rb index e47d3ad4a..4802bab88 100644 --- a/spec/views/harvests/edit.html.haml_spec.rb +++ b/spec/views/harvests/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "harvests/edit" do before(:each) do diff --git a/spec/views/harvests/index.html.haml_spec.rb b/spec/views/harvests/index.html.haml_spec.rb index 093a383a9..9a3392155 100644 --- a/spec/views/harvests/index.html.haml_spec.rb +++ b/spec/views/harvests/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "harvests/index" do before(:each) do diff --git a/spec/views/harvests/new.html.haml_spec.rb b/spec/views/harvests/new.html.haml_spec.rb index 81de2671a..93a595188 100644 --- a/spec/views/harvests/new.html.haml_spec.rb +++ b/spec/views/harvests/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "harvests/new" do before(:each) do diff --git a/spec/views/harvests/show.html.haml_spec.rb b/spec/views/harvests/show.html.haml_spec.rb index f03706be8..4261232e9 100644 --- a/spec/views/harvests/show.html.haml_spec.rb +++ b/spec/views/harvests/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "harvests/show" do before(:each) do diff --git a/spec/views/home/_blurb.html.haml_spec.rb b/spec/views/home/_blurb.html.haml_spec.rb index 3660d0900..13b2d1b46 100644 --- a/spec/views/home/_blurb.html.haml_spec.rb +++ b/spec/views/home/_blurb.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'home/_blurb.html.haml', :type => "view" do context 'signed out' do diff --git a/spec/views/home/_crops.html.haml_spec.rb b/spec/views/home/_crops.html.haml_spec.rb index b479f4ee4..e874bb890 100644 --- a/spec/views/home/_crops.html.haml_spec.rb +++ b/spec/views/home/_crops.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'home/_crops.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/home/_keep_in_touch.html.haml_spec.rb b/spec/views/home/_keep_in_touch.html.haml_spec.rb index 637e0ee46..a7b19891d 100644 --- a/spec/views/home/_keep_in_touch.html.haml_spec.rb +++ b/spec/views/home/_keep_in_touch.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'home/_keep_in_touch.html.haml', :type => "view" do before :each do diff --git a/spec/views/home/_members.html.haml_spec.rb b/spec/views/home/_members.html.haml_spec.rb index 4b527f1a8..616694ab3 100644 --- a/spec/views/home/_members.html.haml_spec.rb +++ b/spec/views/home/_members.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'home/_members.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/home/_open.html.haml_spec.rb b/spec/views/home/_open.html.haml_spec.rb index 543db7630..49e541c3b 100644 --- a/spec/views/home/_open.html.haml_spec.rb +++ b/spec/views/home/_open.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'home/_open.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/home/_seeds.html.haml_spec.rb b/spec/views/home/_seeds.html.haml_spec.rb index bc5f6d2fa..82efa194d 100644 --- a/spec/views/home/_seeds.html.haml_spec.rb +++ b/spec/views/home/_seeds.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'home/_seeds.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/home/_stats.html.haml_spec.rb b/spec/views/home/_stats.html.haml_spec.rb index 0f39e9e81..46ab4a9f9 100644 --- a/spec/views/home/_stats.html.haml_spec.rb +++ b/spec/views/home/_stats.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'home/_stats.html.haml', :type => "view" do it 'has activity stats' do diff --git a/spec/views/home/index_spec.rb b/spec/views/home/index_spec.rb index 829c6fa36..a04377b39 100644 --- a/spec/views/home/index_spec.rb +++ b/spec/views/home/index_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'home/index.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/layouts/_footer_spec.rb b/spec/views/layouts/_footer_spec.rb index c3dc3a9b7..987fab00c 100644 --- a/spec/views/layouts/_footer_spec.rb +++ b/spec/views/layouts/_footer_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'layouts/_footer.html.haml', :type => "view" do diff --git a/spec/views/layouts/_header_spec.rb b/spec/views/layouts/_header_spec.rb index 2274b25b5..4a56133b3 100644 --- a/spec/views/layouts/_header_spec.rb +++ b/spec/views/layouts/_header_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'layouts/_header.html.haml', :type => "view" do context "when not logged in" do diff --git a/spec/views/layouts/_meta_spec.rb b/spec/views/layouts/_meta_spec.rb index a81942d0f..8419ea129 100644 --- a/spec/views/layouts/_meta_spec.rb +++ b/spec/views/layouts/_meta_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'layouts/_meta.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/layouts/application_spec.rb b/spec/views/layouts/application_spec.rb index 0c7bd8b50..56f3f26f1 100644 --- a/spec/views/layouts/application_spec.rb +++ b/spec/views/layouts/application_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'layouts/application.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/members/_location.html.haml_spec.rb b/spec/views/members/_location.html.haml_spec.rb index 96c1e3b8d..2e163b1ed 100644 --- a/spec/views/members/_location.html.haml_spec.rb +++ b/spec/views/members/_location.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "members/_location" do context "member with location" do diff --git a/spec/views/members/index.html.haml_spec.rb b/spec/views/members/index.html.haml_spec.rb index 22fd9c04f..b3a65eb76 100644 --- a/spec/views/members/index.html.haml_spec.rb +++ b/spec/views/members/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "members/index" do before(:each) do diff --git a/spec/views/members/show.rss.haml_spec.rb b/spec/views/members/show.rss.haml_spec.rb index df436b8af..98a8f217a 100644 --- a/spec/views/members/show.rss.haml_spec.rb +++ b/spec/views/members/show.rss.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'members/show.rss.haml', :type => "view" do before(:each) do diff --git a/spec/views/notifications/index.html.haml_spec.rb b/spec/views/notifications/index.html.haml_spec.rb index 351bbb44f..ed62d3d7a 100644 --- a/spec/views/notifications/index.html.haml_spec.rb +++ b/spec/views/notifications/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "notifications/index" do before(:each) do diff --git a/spec/views/notifications/new.html.haml_spec.rb b/spec/views/notifications/new.html.haml_spec.rb index d96358da8..15dacb730 100644 --- a/spec/views/notifications/new.html.haml_spec.rb +++ b/spec/views/notifications/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "notifications/new" do before(:each) do diff --git a/spec/views/notifications/show.html.haml_spec.rb b/spec/views/notifications/show.html.haml_spec.rb index 3028e8f0e..9d51cb5c2 100644 --- a/spec/views/notifications/show.html.haml_spec.rb +++ b/spec/views/notifications/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "notifications/show" do before(:each) do diff --git a/spec/views/notifier/notify.html.haml_spec.rb b/spec/views/notifier/notify.html.haml_spec.rb index 687e702cc..d027b9d0c 100644 --- a/spec/views/notifier/notify.html.haml_spec.rb +++ b/spec/views/notifier/notify.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'notifier/notify.html.haml', :type => "view" do diff --git a/spec/views/orders/index.html.haml_spec.rb b/spec/views/orders/index.html.haml_spec.rb index 2eb399abd..a0d558487 100644 --- a/spec/views/orders/index.html.haml_spec.rb +++ b/spec/views/orders/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "orders/index" do before(:each) do diff --git a/spec/views/orders/show.html.haml_spec.rb b/spec/views/orders/show.html.haml_spec.rb index 9621de369..b6b60ec06 100644 --- a/spec/views/orders/show.html.haml_spec.rb +++ b/spec/views/orders/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "orders/show" do diff --git a/spec/views/photos/edit.html.haml_spec.rb b/spec/views/photos/edit.html.haml_spec.rb index 3b8cde557..f3a9a0ed7 100644 --- a/spec/views/photos/edit.html.haml_spec.rb +++ b/spec/views/photos/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "photos/edit" do before(:each) do diff --git a/spec/views/photos/index.html.haml_spec.rb b/spec/views/photos/index.html.haml_spec.rb index bf4699c48..5daaa1eda 100644 --- a/spec/views/photos/index.html.haml_spec.rb +++ b/spec/views/photos/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "photos/index" do before(:each) do diff --git a/spec/views/photos/new.html.haml_spec.rb b/spec/views/photos/new.html.haml_spec.rb index c3e47a6b8..8f0f241e3 100644 --- a/spec/views/photos/new.html.haml_spec.rb +++ b/spec/views/photos/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "photos/new" do before(:each) do diff --git a/spec/views/photos/show.html.haml_spec.rb b/spec/views/photos/show.html.haml_spec.rb index 18a201590..a523965fe 100644 --- a/spec/views/photos/show.html.haml_spec.rb +++ b/spec/views/photos/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "photos/show" do before(:each) do diff --git a/spec/views/places/_map_attribution.html.haml_spec.rb b/spec/views/places/_map_attribution.html.haml_spec.rb index e3197dfba..d85875376 100644 --- a/spec/views/places/_map_attribution.html.haml_spec.rb +++ b/spec/views/places/_map_attribution.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "places/_map_attribution.html.haml", :type => :view do before(:each) do diff --git a/spec/views/places/index.html.haml_spec.rb b/spec/views/places/index.html.haml_spec.rb index 0e4af0bb1..f3a3661ae 100644 --- a/spec/views/places/index.html.haml_spec.rb +++ b/spec/views/places/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "places/index" do before(:each) do diff --git a/spec/views/places/show.html.haml_spec.rb b/spec/views/places/show.html.haml_spec.rb index 987212740..f19d6a0f2 100644 --- a/spec/views/places/show.html.haml_spec.rb +++ b/spec/views/places/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "places/show" do before(:each) do diff --git a/spec/views/plant_parts/edit.html.haml_spec.rb b/spec/views/plant_parts/edit.html.haml_spec.rb index 2011b34c3..6193ef1b0 100644 --- a/spec/views/plant_parts/edit.html.haml_spec.rb +++ b/spec/views/plant_parts/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plant_parts/edit" do before(:each) do diff --git a/spec/views/plant_parts/index.html.haml_spec.rb b/spec/views/plant_parts/index.html.haml_spec.rb index 6d1020717..b68736977 100644 --- a/spec/views/plant_parts/index.html.haml_spec.rb +++ b/spec/views/plant_parts/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plant_parts/index" do before(:each) do diff --git a/spec/views/plant_parts/new.html.haml_spec.rb b/spec/views/plant_parts/new.html.haml_spec.rb index 6a415fd4e..d512ecee1 100644 --- a/spec/views/plant_parts/new.html.haml_spec.rb +++ b/spec/views/plant_parts/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plant_parts/new" do before(:each) do diff --git a/spec/views/plant_parts/show.html.haml_spec.rb b/spec/views/plant_parts/show.html.haml_spec.rb index 40392a65d..33390171c 100644 --- a/spec/views/plant_parts/show.html.haml_spec.rb +++ b/spec/views/plant_parts/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plant_parts/show" do before(:each) do diff --git a/spec/views/plantings/_form.html.haml_spec.rb b/spec/views/plantings/_form.html.haml_spec.rb index 69da79c35..88b12bd9e 100644 --- a/spec/views/plantings/_form.html.haml_spec.rb +++ b/spec/views/plantings/_form.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plantings/_form" do before(:each) do diff --git a/spec/views/plantings/_thumbnail.html.haml_spec.rb b/spec/views/plantings/_thumbnail.html.haml_spec.rb index ac1ffaa78..47501b1fd 100644 --- a/spec/views/plantings/_thumbnail.html.haml_spec.rb +++ b/spec/views/plantings/_thumbnail.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plantings/_thumbnail" do before(:each) do diff --git a/spec/views/plantings/edit.html.haml_spec.rb b/spec/views/plantings/edit.html.haml_spec.rb index f80f6a0b4..6ec152b9b 100644 --- a/spec/views/plantings/edit.html.haml_spec.rb +++ b/spec/views/plantings/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plantings/edit" do before(:each) do diff --git a/spec/views/plantings/index.html.haml_spec.rb b/spec/views/plantings/index.html.haml_spec.rb index f80331117..c51c378a0 100644 --- a/spec/views/plantings/index.html.haml_spec.rb +++ b/spec/views/plantings/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plantings/index" do before(:each) do diff --git a/spec/views/plantings/index.rss.haml_spec.rb b/spec/views/plantings/index.rss.haml_spec.rb index 5a7cb48c5..e7e232ebf 100644 --- a/spec/views/plantings/index.rss.haml_spec.rb +++ b/spec/views/plantings/index.rss.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'plantings/index.rss.haml' do before(:each) do diff --git a/spec/views/plantings/new.html.haml_spec.rb b/spec/views/plantings/new.html.haml_spec.rb index 61e81eb20..0b05b5532 100644 --- a/spec/views/plantings/new.html.haml_spec.rb +++ b/spec/views/plantings/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plantings/new" do before(:each) do diff --git a/spec/views/plantings/show.html.haml_spec.rb b/spec/views/plantings/show.html.haml_spec.rb index 018e5074b..c90220b38 100644 --- a/spec/views/plantings/show.html.haml_spec.rb +++ b/spec/views/plantings/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "plantings/show" do def create_planting_for(member) diff --git a/spec/views/policy/community_spec.rb b/spec/views/policy/community_spec.rb index 70608e463..f4b9c6429 100644 --- a/spec/views/policy/community_spec.rb +++ b/spec/views/policy/community_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'policy/community.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/policy/tos_spec.rb b/spec/views/policy/tos_spec.rb index 548deadc3..2a11532a8 100644 --- a/spec/views/policy/tos_spec.rb +++ b/spec/views/policy/tos_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'policy/tos.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/posts/_single.html.haml_spec.rb b/spec/views/posts/_single.html.haml_spec.rb index eebac11f4..50216c4db 100644 --- a/spec/views/posts/_single.html.haml_spec.rb +++ b/spec/views/posts/_single.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "posts/_single" do diff --git a/spec/views/posts/edit.html.haml_spec.rb b/spec/views/posts/edit.html.haml_spec.rb index 91e2d9b4f..7c68fc4ae 100644 --- a/spec/views/posts/edit.html.haml_spec.rb +++ b/spec/views/posts/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "posts/edit" do before(:each) do diff --git a/spec/views/posts/index.html.haml_spec.rb b/spec/views/posts/index.html.haml_spec.rb index 3b7b02611..d5d49951a 100644 --- a/spec/views/posts/index.html.haml_spec.rb +++ b/spec/views/posts/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "posts/index" do before(:each) do diff --git a/spec/views/posts/index.rss.haml_spec.rb b/spec/views/posts/index.rss.haml_spec.rb index b28deb2db..c06416386 100644 --- a/spec/views/posts/index.rss.haml_spec.rb +++ b/spec/views/posts/index.rss.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'posts/index.rss.haml', :type => "view" do before(:each) do diff --git a/spec/views/posts/new.html.haml_spec.rb b/spec/views/posts/new.html.haml_spec.rb index be69c972c..ca4ee0a48 100644 --- a/spec/views/posts/new.html.haml_spec.rb +++ b/spec/views/posts/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "posts/new" do before(:each) do diff --git a/spec/views/posts/show.html.haml_spec.rb b/spec/views/posts/show.html.haml_spec.rb index d9682b015..c0d1a82d0 100644 --- a/spec/views/posts/show.html.haml_spec.rb +++ b/spec/views/posts/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "posts/show" do before(:each) do diff --git a/spec/views/posts/show.rss.haml_spec.rb b/spec/views/posts/show.rss.haml_spec.rb index 2f2780d09..072b8032c 100644 --- a/spec/views/posts/show.rss.haml_spec.rb +++ b/spec/views/posts/show.rss.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'posts/show.rss.haml' do before(:each) do diff --git a/spec/views/products/edit.html.haml_spec.rb b/spec/views/products/edit.html.haml_spec.rb index 875fab4b2..3505c0216 100644 --- a/spec/views/products/edit.html.haml_spec.rb +++ b/spec/views/products/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "products/edit" do before(:each) do diff --git a/spec/views/products/index.html.haml_spec.rb b/spec/views/products/index.html.haml_spec.rb index 0e18b8ddc..2b96540c1 100644 --- a/spec/views/products/index.html.haml_spec.rb +++ b/spec/views/products/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "products/index" do before(:each) do diff --git a/spec/views/products/new.html.haml_spec.rb b/spec/views/products/new.html.haml_spec.rb index 769fbe6bd..ab7bc5f7e 100644 --- a/spec/views/products/new.html.haml_spec.rb +++ b/spec/views/products/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "products/new" do before(:each) do diff --git a/spec/views/products/show.html.haml_spec.rb b/spec/views/products/show.html.haml_spec.rb index 12710a91f..be9d78dbd 100644 --- a/spec/views/products/show.html.haml_spec.rb +++ b/spec/views/products/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "products/show" do before(:each) do diff --git a/spec/views/roles/edit.html.haml_spec.rb b/spec/views/roles/edit.html.haml_spec.rb index 2e2f66c7b..2b12e05d5 100644 --- a/spec/views/roles/edit.html.haml_spec.rb +++ b/spec/views/roles/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "roles/edit" do before(:each) do diff --git a/spec/views/roles/index.html.haml_spec.rb b/spec/views/roles/index.html.haml_spec.rb index 3c62e0986..1b732c381 100644 --- a/spec/views/roles/index.html.haml_spec.rb +++ b/spec/views/roles/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "roles/index" do before(:each) do diff --git a/spec/views/roles/new.html.haml_spec.rb b/spec/views/roles/new.html.haml_spec.rb index e15e14226..bba7e62b7 100644 --- a/spec/views/roles/new.html.haml_spec.rb +++ b/spec/views/roles/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "roles/new" do before(:each) do diff --git a/spec/views/roles/show.html.haml_spec.rb b/spec/views/roles/show.html.haml_spec.rb index 389a5c8c3..16f48415f 100644 --- a/spec/views/roles/show.html.haml_spec.rb +++ b/spec/views/roles/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "roles/show" do before(:each) do diff --git a/spec/views/scientific_names/edit.html.haml_spec.rb b/spec/views/scientific_names/edit.html.haml_spec.rb index 1b48c51cd..0202243f8 100644 --- a/spec/views/scientific_names/edit.html.haml_spec.rb +++ b/spec/views/scientific_names/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "scientific_names/edit" do context "logged in" do diff --git a/spec/views/scientific_names/index.html.haml_spec.rb b/spec/views/scientific_names/index.html.haml_spec.rb index fff8874f5..9e5a8519e 100644 --- a/spec/views/scientific_names/index.html.haml_spec.rb +++ b/spec/views/scientific_names/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "scientific_names/index" do before(:each) do diff --git a/spec/views/scientific_names/new.html.haml_spec.rb b/spec/views/scientific_names/new.html.haml_spec.rb index 9c892f5ef..151908e7d 100644 --- a/spec/views/scientific_names/new.html.haml_spec.rb +++ b/spec/views/scientific_names/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "scientific_names/new" do before(:each) do diff --git a/spec/views/scientific_names/show.html.haml_spec.rb b/spec/views/scientific_names/show.html.haml_spec.rb index 6fbb95e42..d2927c5a9 100644 --- a/spec/views/scientific_names/show.html.haml_spec.rb +++ b/spec/views/scientific_names/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "scientific_names/show" do before(:each) do diff --git a/spec/views/seeds/edit.html.haml_spec.rb b/spec/views/seeds/edit.html.haml_spec.rb index 03b2064cf..6a0235e4b 100644 --- a/spec/views/seeds/edit.html.haml_spec.rb +++ b/spec/views/seeds/edit.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "seeds/edit" do before(:each) do diff --git a/spec/views/seeds/index.html.haml_spec.rb b/spec/views/seeds/index.html.haml_spec.rb index 036c4aa04..ae6f78047 100644 --- a/spec/views/seeds/index.html.haml_spec.rb +++ b/spec/views/seeds/index.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "seeds/index" do before(:each) do diff --git a/spec/views/seeds/index.rss.haml_spec.rb b/spec/views/seeds/index.rss.haml_spec.rb index 0b30d19a5..22e10f1e7 100644 --- a/spec/views/seeds/index.rss.haml_spec.rb +++ b/spec/views/seeds/index.rss.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'seeds/index.rss.haml' do before(:each) do diff --git a/spec/views/seeds/new.html.haml_spec.rb b/spec/views/seeds/new.html.haml_spec.rb index a88713181..3121f7b3b 100644 --- a/spec/views/seeds/new.html.haml_spec.rb +++ b/spec/views/seeds/new.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "seeds/new" do before(:each) do diff --git a/spec/views/seeds/show.html.haml_spec.rb b/spec/views/seeds/show.html.haml_spec.rb index 737cf0232..b2276ba23 100644 --- a/spec/views/seeds/show.html.haml_spec.rb +++ b/spec/views/seeds/show.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe "seeds/show" do before(:each) do diff --git a/spec/views/shop/index_spec.rb b/spec/views/shop/index_spec.rb index 49034368d..f93d173cd 100644 --- a/spec/views/shop/index_spec.rb +++ b/spec/views/shop/index_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'shop/index.html.haml', :type => "view" do before(:each) do diff --git a/spec/views/support/index_spec.rb b/spec/views/support/index_spec.rb index 0c7491ed7..1b29e2adb 100644 --- a/spec/views/support/index_spec.rb +++ b/spec/views/support/index_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require 'rails_helper' describe 'support/index.html.haml', :type => "view" do before(:each) do From 70185156aa507e03f896d5d3cad16436e6eb4838 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 16 Nov 2014 12:11:56 +1100 Subject: [PATCH 021/143] use lambda instead of just relation in names scope --- app/models/comment.rb | 2 +- app/models/crop.rb | 8 ++++---- app/models/garden.rb | 4 ++-- app/models/member.rb | 8 ++++---- app/models/notification.rb | 2 +- app/models/planting.rb | 4 ++-- app/models/seed.rb | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/models/comment.rb b/app/models/comment.rb index 91d163f98..76a4d25f4 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -4,7 +4,7 @@ class Comment < ActiveRecord::Base belongs_to :post default_scope { order("created_at DESC") } - scope :post_order, reorder("created_at ASC") # for display on post page + scope :post_order, -> { reorder("created_at ASC") } # for display on post page after_create do recipient = self.post.author.id diff --git a/app/models/crop.rb b/app/models/crop.rb index 39c35b96d..d85ab4647 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -23,10 +23,10 @@ class Crop < ActiveRecord::Base default_scope { order("lower(name) asc") } - scope :recent, reorder("created_at desc") - scope :toplevel, where(:parent_id => nil) - scope :popular, reorder("plantings_count desc, lower(name) asc") - scope :randomized, reorder('random()') # ok on sqlite and psql, but not on mysql + scope :recent, -> { reorder("created_at desc") } + scope :toplevel, -> { where(:parent_id => nil) } + scope :popular, -> { reorder("plantings_count desc, lower(name) asc") } + scope :randomized, -> { reorder('random()') } # ok on sqlite and psql, but not on mysql validates :en_wikipedia_url, :format => { diff --git a/app/models/garden.rb b/app/models/garden.rb index cc5492906..9e390f4bd 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -17,8 +17,8 @@ class Garden < ActiveRecord::Base after_save :mark_inactive_garden_plantings_as_finished default_scope { order("lower(name) asc") } - scope :active, where(:active => true) - scope :inactive, where(:active => false) + scope :active, -> { where(:active => true) } + scope :inactive, -> { where(:active => false) } validates :name, :format => { diff --git a/app/models/member.rb b/app/models/member.rb index 844570b81..8eebdcd72 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -28,10 +28,10 @@ class Member < ActiveRecord::Base has_many :photos default_scope { order("lower(login_name) asc") } - scope :confirmed, where('confirmed_at IS NOT NULL') - scope :located, where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL") - scope :recently_signed_in, reorder('updated_at DESC') - scope :wants_newsletter, where(:newsletter => true) + scope :confirmed, -> { where('confirmed_at IS NOT NULL') } + scope :located, -> { where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL") } + scope :recently_signed_in, -> { reorder('updated_at DESC') } + scope :wants_newsletter, -> { where(:newsletter => true) } # Include default devise modules. Others available are: # :token_authenticatable, :confirmable, diff --git a/app/models/notification.rb b/app/models/notification.rb index 9ab2d183b..4568d6975 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -7,7 +7,7 @@ class Notification < ActiveRecord::Base belongs_to :post default_scope { order('created_at DESC') } - scope :unread, where(:read => false) + scope :unread, -> { where(:read => false) } before_create :replace_blank_subject after_create :send_email diff --git a/app/models/planting.rb b/app/models/planting.rb index 132bed8ed..aff4f37ba 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -22,8 +22,8 @@ class Planting < ActiveRecord::Base end default_scope { order("created_at desc") } - scope :finished, where(:finished => true) - scope :current, where(:finished => false) + scope :finished, -> { where(:finished => true) } + scope :current, -> { where(:finished => false) } delegate :name, :en_wikipedia_url, diff --git a/app/models/seed.rb b/app/models/seed.rb index 94cccddcb..c2183c2c9 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -15,7 +15,7 @@ class Seed < ActiveRecord::Base :numericality => { :only_integer => true }, :allow_nil => true - scope :tradable, where("tradable_to != 'nowhere'") + scope :tradable, -> { where("tradable_to != 'nowhere'") } TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally) validates :tradable_to, :inclusion => { :in => TRADABLE_TO_VALUES, From 868e5c2079b9b33068446f76be78ac22765c6de1 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 16 Nov 2014 12:41:57 +1100 Subject: [PATCH 022/143] upgrade jquery-ui-rails gem and config --- Gemfile | 4 ++-- Gemfile.lock | 9 ++++++--- app/assets/javascripts/application.js | 2 +- app/assets/stylesheets/application.css | 2 +- spec/rails_helper.rb | 1 - spec/spec_helper.rb | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Gemfile b/Gemfile index 1faf0532e..911a6ea79 100644 --- a/Gemfile +++ b/Gemfile @@ -73,7 +73,7 @@ gem 'uglifier', '~> 2.5.3' # JavaScript compressor # gem 'compass-rails', '~> 1.0.3' # Yet Another CSS framework gem 'jquery-rails' -gem 'jquery-ui-rails' +gem 'jquery-ui-rails', '~> 5.0.2' gem 'js-routes' # provides access to Rails routes in Javascript gem 'flickraw' @@ -104,7 +104,7 @@ gem 'bluecloth' gem 'will_paginate', '~> 3.0' # user signup/login/etc -gem 'devise', '~> 3.2.0' +gem 'devise', '~> 3.4.1' # nicely formatted URLs gem 'friendly_id', '~> 5.0.4' diff --git a/Gemfile.lock b/Gemfile.lock index 28383ef0f..14eb52d90 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -106,10 +106,11 @@ GEM dalli (2.7.2) database_cleaner (1.3.0) debug_inspector (0.0.2) - devise (3.2.4) + devise (3.4.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 3.2.6, < 5) + responders thread_safe (~> 0.1) warden (~> 1.2.3) diff-lcs (1.2.5) @@ -254,6 +255,8 @@ GEM raindrops (0.13.0) rake (10.3.2) ref (1.0.5) + responders (1.1.2) + railties (>= 3.2, < 4.2) rest-client (1.7.2) mime-types (>= 1.16, < 3.0) netrc (~> 0.7) @@ -350,7 +353,7 @@ DEPENDENCIES csv_shaper dalli database_cleaner (~> 1.3.0) - devise (~> 3.2.0) + devise (~> 3.4.1) factory_girl_rails (~> 4.5.0) figaro flickraw @@ -362,7 +365,7 @@ DEPENDENCIES haml-rails i18n-tasks jquery-rails - jquery-ui-rails + jquery-ui-rails (~> 5.0.2) js-routes leaflet-markercluster-rails leaflet-rails diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index beb65d620..6f1d08c72 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -15,7 +15,7 @@ //= require js-routes //= require jquery //= require jquery_ujs -//= require jquery.ui.autocomplete +//= require jquery-ui/autocomplete //= require twitter/bootstrap //= require_tree . //= require bootstrap-datepicker diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 98c343be5..c9c1a79d1 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -3,7 +3,7 @@ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * the top of the compiled file, but it's generally better to create a new file per style scope. *= require_self - *= require jquery.ui.autocomplete + *= require jquery-ui/autocomplete *= require bootstrap-datepicker *= require leaflet *= require leaflet.markercluster diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 0ab8f09fc..24be064ae 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -7,7 +7,6 @@ require 'rspec/rails' require 'rspec/autorun' require 'simplecov' require 'coveralls' -require 'rails-observers' # output coverage locally AND send it to coveralls SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a9872e6f6..7b09b0a2d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -35,7 +35,7 @@ RSpec.configure do |config| # Prevents you from mocking or stubbing a method that does not exist on # a real object. This is generally recommended, and will default to # `true` in RSpec 4. - mocks.verify_partial_doubles = true + mocks.verify_partial_doubles = false end # The settings below are suggested to provide a good initial experience From cc31e864d56d589947bf71b019ea1883e288d8c6 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 16 Nov 2014 14:31:33 +1100 Subject: [PATCH 023/143] update webrat and webrat matchers --- spec/views/about/contact_spec.rb | 2 +- spec/views/accounts/show.html.haml_spec.rb | 6 ++--- spec/views/admin/index_spec.rb | 2 +- spec/views/admin/newsletter_spec.rb | 2 +- spec/views/comments/index.html.haml_spec.rb | 4 ++-- spec/views/comments/index.rss.haml_spec.rb | 8 +++---- spec/views/comments/new.html.haml_spec.rb | 8 +++---- spec/views/comments/show.html.haml_spec.rb | 4 ++-- spec/views/crops/_grown_for.html.haml_spec.rb | 2 +- .../crops/_planting_advice.html.haml_spec.rb | 20 ++++++++--------- spec/views/crops/_popover.html.haml_spec.rb | 4 ++-- spec/views/crops/edit.html.haml_spec.rb | 2 +- spec/views/crops/index.html.haml_spec.rb | 4 ++-- spec/views/crops/index.rss.haml_spec.rb | 6 ++--- spec/views/crops/search.html.haml_spec.rb | 4 ++-- spec/views/crops/wrangle.html.haml_spec.rb | 4 ++-- spec/views/devise/confirmations/new_spec.rb | 2 +- .../mailer/confirmation_instructions_spec.rb | 4 ++-- .../reset_password_instructions_spec.rb | 4 ++-- .../devise/mailer/unlock_instructions_spec.rb | 4 ++-- spec/views/devise/registrations/edit_spec.rb | 2 +- spec/views/devise/registrations/new_spec.rb | 2 +- spec/views/devise/sessions/new_spec.rb | 4 ++-- spec/views/devise/unlocks/new_spec.rb | 2 +- spec/views/forums/index.html.haml_spec.rb | 4 ++-- spec/views/forums/show.html.haml_spec.rb | 10 ++++----- spec/views/gardens/show.html.haml_spec.rb | 14 ++++++------ spec/views/harvests/index.html.haml_spec.rb | 6 ++--- spec/views/harvests/show.html.haml_spec.rb | 6 ++--- spec/views/home/_blurb.html.haml_spec.rb | 4 ++-- spec/views/home/_crops.html.haml_spec.rb | 2 +- spec/views/home/_members.html.haml_spec.rb | 8 +++---- spec/views/home/_stats.html.haml_spec.rb | 2 +- spec/views/home/index_spec.rb | 6 ++--- spec/views/layouts/_footer_spec.rb | 8 +++---- spec/views/layouts/_header_spec.rb | 20 ++++++++--------- spec/views/layouts/application_spec.rb | 2 +- .../views/members/_location.html.haml_spec.rb | 4 ++-- spec/views/members/index.html.haml_spec.rb | 2 +- spec/views/members/show.rss.haml_spec.rb | 8 +++---- .../notifications/index.html.haml_spec.rb | 4 ++-- .../views/notifications/new.html.haml_spec.rb | 6 ++--- .../notifications/show.html.haml_spec.rb | 4 ++-- spec/views/notifier/notify.html.haml_spec.rb | 6 ++--- spec/views/orders/index.html.haml_spec.rb | 2 +- spec/views/orders/show.html.haml_spec.rb | 4 ++-- spec/views/photos/show.html.haml_spec.rb | 2 +- spec/views/places/show.html.haml_spec.rb | 2 +- .../views/plant_parts/index.html.haml_spec.rb | 2 +- spec/views/plant_parts/show.html.haml_spec.rb | 2 +- .../plantings/_thumbnail.html.haml_spec.rb | 10 ++++----- spec/views/plantings/index.html.haml_spec.rb | 18 +++++++-------- spec/views/plantings/index.rss.haml_spec.rb | 12 +++++----- spec/views/plantings/show.html.haml_spec.rb | 22 +++++++++---------- spec/views/policy/community_spec.rb | 2 +- spec/views/policy/tos_spec.rb | 2 +- spec/views/posts/_single.html.haml_spec.rb | 2 +- spec/views/posts/edit.html.haml_spec.rb | 4 ++-- spec/views/posts/index.rss.haml_spec.rb | 6 ++--- spec/views/posts/new.html.haml_spec.rb | 12 +++++----- spec/views/posts/show.html.haml_spec.rb | 6 ++--- spec/views/posts/show.rss.haml_spec.rb | 8 +++---- spec/views/products/show.html.haml_spec.rb | 6 ++--- .../scientific_names/edit.html.haml_spec.rb | 2 +- .../scientific_names/index.html.haml_spec.rb | 8 +++---- spec/views/seeds/index.html.haml_spec.rb | 2 +- spec/views/seeds/index.rss.haml_spec.rb | 12 +++++----- spec/views/seeds/new.html.haml_spec.rb | 4 ++-- spec/views/seeds/show.html.haml_spec.rb | 10 ++++----- spec/views/shop/index_spec.rb | 8 +++---- spec/views/support/index_spec.rb | 6 ++--- 71 files changed, 204 insertions(+), 204 deletions(-) diff --git a/spec/views/about/contact_spec.rb b/spec/views/about/contact_spec.rb index 2dcd31c9d..f655a1394 100644 --- a/spec/views/about/contact_spec.rb +++ b/spec/views/about/contact_spec.rb @@ -7,6 +7,6 @@ describe 'about/contact.html.haml', :type => "view" do it 'should show support faq' do render - rendered.should contain 'General contact email' + rendered.should have_content 'General contact email' end end diff --git a/spec/views/accounts/show.html.haml_spec.rb b/spec/views/accounts/show.html.haml_spec.rb index 99ea2f1a0..13dfc3589 100644 --- a/spec/views/accounts/show.html.haml_spec.rb +++ b/spec/views/accounts/show.html.haml_spec.rb @@ -9,8 +9,8 @@ describe "accounts/show" do it "renders attributes in

" do render # Run the generator again with the --webrat flag if you want to use webrat matchers - rendered.should contain @account.member_id.to_s - rendered.should contain 'Free' - rendered.should contain @account.paid_until.to_s + rendered.should have_content @account.member_id.to_s + rendered.should have_content 'Free' + rendered.should have_content @account.paid_until.to_s end end diff --git a/spec/views/admin/index_spec.rb b/spec/views/admin/index_spec.rb index 744ac639d..eb9dd9d01 100644 --- a/spec/views/admin/index_spec.rb +++ b/spec/views/admin/index_spec.rb @@ -16,6 +16,6 @@ describe 'admin/index.html.haml', :type => "view" do end it "has a link to newsletter subscribers" do - rendered.should contain "Newsletter subscribers" + rendered.should have_content "Newsletter subscribers" end end diff --git a/spec/views/admin/newsletter_spec.rb b/spec/views/admin/newsletter_spec.rb index a3b5e67f6..d072aee2e 100644 --- a/spec/views/admin/newsletter_spec.rb +++ b/spec/views/admin/newsletter_spec.rb @@ -11,6 +11,6 @@ describe 'admin/newsletter.html.haml', :type => "view" do end it "lists newsletter subscribers by email" do - rendered.should contain @subscriber.email + rendered.should have_content @subscriber.email end end diff --git a/spec/views/comments/index.html.haml_spec.rb b/spec/views/comments/index.html.haml_spec.rb index e0260e207..7161978ab 100644 --- a/spec/views/comments/index.html.haml_spec.rb +++ b/spec/views/comments/index.html.haml_spec.rb @@ -18,8 +18,8 @@ describe "comments/index" do it "renders a list of comments" do render - rendered.should contain 'OMG LOL' - rendered.should contain 'ROFL' + rendered.should have_content 'OMG LOL' + rendered.should have_content 'ROFL' end it "contains an RSS feed link" do diff --git a/spec/views/comments/index.rss.haml_spec.rb b/spec/views/comments/index.rss.haml_spec.rb index f4d767800..5278a8b56 100644 --- a/spec/views/comments/index.rss.haml_spec.rb +++ b/spec/views/comments/index.rss.haml_spec.rb @@ -13,20 +13,20 @@ describe 'comments/index.rss.haml' do end it 'shows RSS feed title' do - rendered.should contain "Recent comments on all posts" + rendered.should have_content "Recent comments on all posts" end it 'shows item title' do - rendered.should contain "Comment by #{@author.login_name}" + rendered.should have_content "Comment by #{@author.login_name}" end it 'escapes html for link to post' do # it's then unescaped by 'render' so we don't actually look for < - rendered.should contain ' 'crops/grown_for', :locals => { :crop => @crop } - rendered.should contain @pp.name + rendered.should have_content @pp.name assert_select "a", :href => plant_part_path(@pp) end end diff --git a/spec/views/crops/_planting_advice.html.haml_spec.rb b/spec/views/crops/_planting_advice.html.haml_spec.rb index 875ee6eef..91034a2fb 100644 --- a/spec/views/crops/_planting_advice.html.haml_spec.rb +++ b/spec/views/crops/_planting_advice.html.haml_spec.rb @@ -14,14 +14,14 @@ describe "crops/_planting_advice" do context "sunniness" do it "doesn't show sunniness if none are set" do render :partial => 'crops/planting_advice', :locals => { :crop => @crop } - rendered.should_not contain "Plant in:" + rendered.should_not have_content "Plant in:" end it "shows sunniness frequencies" do FactoryGirl.create(:sunny_planting, :crop => @crop) render :partial => 'crops/planting_advice', :locals => { :crop => @crop } - rendered.should contain "Plant in:" - rendered.should contain "sun (1)" + rendered.should have_content "Plant in:" + rendered.should have_content "sun (1)" end it "shows multiple sunniness frequencies" do @@ -29,8 +29,8 @@ describe "crops/_planting_advice" do FactoryGirl.create(:sunny_planting, :crop => @crop) FactoryGirl.create(:shady_planting, :crop => @crop) render :partial => 'crops/planting_advice', :locals => { :crop => @crop } - rendered.should contain "Plant in:" - rendered.should contain "sun (2), shade (1)" + rendered.should have_content "Plant in:" + rendered.should have_content "sun (2), shade (1)" end end @@ -39,14 +39,14 @@ describe "crops/_planting_advice" do it "doesn't show planted_from if none are set" do render :partial => 'crops/planting_advice', :locals => { :crop => @crop } - rendered.should_not contain "Plant from:" + rendered.should_not have_content "Plant from:" end it "shows planted_from frequencies" do FactoryGirl.create(:seed_planting, :crop => @crop) render :partial => 'crops/planting_advice', :locals => { :crop => @crop } - rendered.should contain "Plant from:" - rendered.should contain "seed (1)" + rendered.should have_content "Plant from:" + rendered.should have_content "seed (1)" end it "shows multiple planted_from frequencies" do @@ -54,8 +54,8 @@ describe "crops/_planting_advice" do FactoryGirl.create(:seed_planting, :crop => @crop) FactoryGirl.create(:cutting_planting, :crop => @crop) render :partial => 'crops/planting_advice', :locals => { :crop => @crop } - rendered.should contain "Plant from:" - rendered.should contain "seed (2), cutting (1)" + rendered.should have_content "Plant from:" + rendered.should have_content "seed (2), cutting (1)" end end diff --git a/spec/views/crops/_popover.html.haml_spec.rb b/spec/views/crops/_popover.html.haml_spec.rb index f9dc0d325..d503a7235 100644 --- a/spec/views/crops/_popover.html.haml_spec.rb +++ b/spec/views/crops/_popover.html.haml_spec.rb @@ -10,11 +10,11 @@ describe "crops/_popover" do end it 'has a scientific name' do - rendered.should contain 'Solanum lycopersicum' + rendered.should have_content 'Solanum lycopersicum' end it 'shows count of plantings' do - rendered.should contain '1 time' + rendered.should have_content '1 time' end end diff --git a/spec/views/crops/edit.html.haml_spec.rb b/spec/views/crops/edit.html.haml_spec.rb index eaf76a092..031addb30 100644 --- a/spec/views/crops/edit.html.haml_spec.rb +++ b/spec/views/crops/edit.html.haml_spec.rb @@ -14,7 +14,7 @@ describe "crops/edit" do end it "shows the creator" do - rendered.should contain "Added by #{@crop.creator} less than a minute ago." + rendered.should have_content "Added by #{@crop.creator} less than a minute ago." end it "renders the edit crop form" do diff --git a/spec/views/crops/index.html.haml_spec.rb b/spec/views/crops/index.html.haml_spec.rb index 0c0554afa..69792ba76 100644 --- a/spec/views/crops/index.html.haml_spec.rb +++ b/spec/views/crops/index.html.haml_spec.rb @@ -50,14 +50,14 @@ describe "crops/index" do end it "shows a new crop link" do - rendered.should contain "New Crop" + rendered.should have_content "New Crop" end end context "downloads" do it "offers data downloads" do render - rendered.should contain "The data on this page is available in the following formats:" + rendered.should have_content "The data on this page is available in the following formats:" assert_select "a", :href => crops_path(:format => 'csv') assert_select "a", :href => crops_path(:format => 'json') assert_select "a", :href => crops_path(:format => 'rss') diff --git a/spec/views/crops/index.rss.haml_spec.rb b/spec/views/crops/index.rss.haml_spec.rb index 4c19c5f26..0e8887411 100644 --- a/spec/views/crops/index.rss.haml_spec.rb +++ b/spec/views/crops/index.rss.haml_spec.rb @@ -11,12 +11,12 @@ describe 'crops/index.rss.haml' do end it 'shows RSS feed title' do - rendered.should contain "Recently added crops" + rendered.should have_content "Recently added crops" end it 'shows names of crops' do - rendered.should contain @tomato.name - rendered.should contain @maize.name + rendered.should have_content @tomato.name + rendered.should have_content @maize.name end end diff --git a/spec/views/crops/search.html.haml_spec.rb b/spec/views/crops/search.html.haml_spec.rb index 352d9730d..82b6ea87c 100644 --- a/spec/views/crops/search.html.haml_spec.rb +++ b/spec/views/crops/search.html.haml_spec.rb @@ -38,12 +38,12 @@ describe "crops/search" do end it "tells you there are no matches" do - rendered.should contain "No results found" + rendered.should have_content "No results found" end it "links to browse crops" do assert_select "a", :href => crops_path - rendered.should contain "Try browsing our crop database instead" + rendered.should have_content "Try browsing our crop database instead" end end diff --git a/spec/views/crops/wrangle.html.haml_spec.rb b/spec/views/crops/wrangle.html.haml_spec.rb index a91663c09..4426382d2 100644 --- a/spec/views/crops/wrangle.html.haml_spec.rb +++ b/spec/views/crops/wrangle.html.haml_spec.rb @@ -18,8 +18,8 @@ describe "crops/wrangle" do it 'contains handy links for wranglers' do render - rendered.should contain "Crop wrangler guidelines" - rendered.should contain "mailing list" + rendered.should have_content "Crop wrangler guidelines" + rendered.should have_content "mailing list" end it 'has a link to add a crop' do diff --git a/spec/views/devise/confirmations/new_spec.rb b/spec/views/devise/confirmations/new_spec.rb index 1f4de467b..1e1555db3 100644 --- a/spec/views/devise/confirmations/new_spec.rb +++ b/spec/views/devise/confirmations/new_spec.rb @@ -9,6 +9,6 @@ describe 'devise/confirmations/new.html.haml', :type => "view" do end it 'should contain a login field' do - rendered.should contain "Enter either your login name or your email address" + rendered.should have_content "Enter either your login name or your email address" end end diff --git a/spec/views/devise/mailer/confirmation_instructions_spec.rb b/spec/views/devise/mailer/confirmation_instructions_spec.rb index 368446247..e42dd762c 100644 --- a/spec/views/devise/mailer/confirmation_instructions_spec.rb +++ b/spec/views/devise/mailer/confirmation_instructions_spec.rb @@ -9,11 +9,11 @@ describe 'devise/mailer/confirmation_instructions.html.haml', :type => "view" do end it 'should have a confirmation link' do - rendered.should contain 'Confirm my account' + rendered.should have_content 'Confirm my account' end it 'should have a link to the homepage' do - rendered.should contain root_url + rendered.should have_content root_url end end end diff --git a/spec/views/devise/mailer/reset_password_instructions_spec.rb b/spec/views/devise/mailer/reset_password_instructions_spec.rb index 48944f266..d75f69881 100644 --- a/spec/views/devise/mailer/reset_password_instructions_spec.rb +++ b/spec/views/devise/mailer/reset_password_instructions_spec.rb @@ -11,8 +11,8 @@ describe 'devise/mailer/reset_password_instructions.html.haml', :type => "view" end it 'should have some of the right text' do - rendered.should contain 'Change my password' - rendered.should contain 'Someone has requested a link to reset your password' + rendered.should have_content 'Change my password' + rendered.should have_content 'Someone has requested a link to reset your password' end end end diff --git a/spec/views/devise/mailer/unlock_instructions_spec.rb b/spec/views/devise/mailer/unlock_instructions_spec.rb index 02a2bd182..fd4c444f8 100644 --- a/spec/views/devise/mailer/unlock_instructions_spec.rb +++ b/spec/views/devise/mailer/unlock_instructions_spec.rb @@ -7,11 +7,11 @@ describe 'devise/mailer/unlock_instructions.html.haml', :type => "view" do end it "should explain what's happened" do - rendered.should contain "account has been locked" + rendered.should have_content "account has been locked" end it "should have an unlock link" do - rendered.should contain "Unlock my account" + rendered.should have_content "Unlock my account" end end end diff --git a/spec/views/devise/registrations/edit_spec.rb b/spec/views/devise/registrations/edit_spec.rb index 8e9c11087..c99b84aed 100644 --- a/spec/views/devise/registrations/edit_spec.rb +++ b/spec/views/devise/registrations/edit_spec.rb @@ -15,7 +15,7 @@ describe 'devise/registrations/edit.html.haml', :type => "view" do it 'should have some fields' do render - rendered.should contain 'Email' + rendered.should have_content 'Email' end context 'email section' do diff --git a/spec/views/devise/registrations/new_spec.rb b/spec/views/devise/registrations/new_spec.rb index 3c03ba7aa..f7dcfffe1 100644 --- a/spec/views/devise/registrations/new_spec.rb +++ b/spec/views/devise/registrations/new_spec.rb @@ -12,7 +12,7 @@ describe 'devise/registrations/new.html.haml', :type => "view" do end it 'should have some fields' do - rendered.should contain 'Email' + rendered.should have_content 'Email' end it 'has a checkbox for newsletter subscription' do diff --git a/spec/views/devise/sessions/new_spec.rb b/spec/views/devise/sessions/new_spec.rb index f795b1d55..6d66e6a48 100644 --- a/spec/views/devise/sessions/new_spec.rb +++ b/spec/views/devise/sessions/new_spec.rb @@ -12,8 +12,8 @@ describe 'devise/sessions/new.html.haml', :type => "view" do end it 'should have some fields' do - rendered.should contain 'Remember me' - rendered.should contain 'Password' + rendered.should have_content 'Remember me' + rendered.should have_content 'Password' end end end diff --git a/spec/views/devise/unlocks/new_spec.rb b/spec/views/devise/unlocks/new_spec.rb index 2d1b8f705..fec998c4d 100644 --- a/spec/views/devise/unlocks/new_spec.rb +++ b/spec/views/devise/unlocks/new_spec.rb @@ -12,7 +12,7 @@ describe 'devise/unlocks/new.html.haml', :type => "view" do end it 'should have some fields' do - rendered.should contain 'Email' + rendered.should have_content 'Email' end end end diff --git a/spec/views/forums/index.html.haml_spec.rb b/spec/views/forums/index.html.haml_spec.rb index 99ea944ea..a946c2407 100644 --- a/spec/views/forums/index.html.haml_spec.rb +++ b/spec/views/forums/index.html.haml_spec.rb @@ -28,8 +28,8 @@ describe "forums/index" do it "displays posts" do assert_select "table" - rendered.should contain @post.subject - rendered.should contain "less than a minute ago" + rendered.should have_content @post.subject + rendered.should have_content "less than a minute ago" end it "displays comment count" do diff --git a/spec/views/forums/show.html.haml_spec.rb b/spec/views/forums/show.html.haml_spec.rb index 2e61541fe..45ff9aeed 100644 --- a/spec/views/forums/show.html.haml_spec.rb +++ b/spec/views/forums/show.html.haml_spec.rb @@ -8,8 +8,8 @@ describe "forums/show" do it "renders attributes" do render - rendered.should contain "Everything about permaculture" - rendered.should contain @forum.owner.to_s + rendered.should have_content "Everything about permaculture" + rendered.should have_content @forum.owner.to_s end it "parses markdown description into html" do @@ -24,14 +24,14 @@ describe "forums/show" do it 'has no posts' do render - rendered.should contain "No posts yet." + rendered.should have_content "No posts yet." end it 'shows posts' do @post = FactoryGirl.create(:post, :forum => @forum) render assert_select "table" - rendered.should contain @post.subject - rendered.should contain @post.author.to_s + rendered.should have_content @post.subject + rendered.should have_content @post.author.to_s end end diff --git a/spec/views/gardens/show.html.haml_spec.rb b/spec/views/gardens/show.html.haml_spec.rb index fee56002f..6327073ee 100644 --- a/spec/views/gardens/show.html.haml_spec.rb +++ b/spec/views/gardens/show.html.haml_spec.rb @@ -11,15 +11,15 @@ describe "gardens/show" do end it 'should show the location' do - rendered.should contain @garden.location + rendered.should have_content @garden.location end it 'should show the area' do - rendered.should contain pluralize(@garden.area, @garden.area_unit) + rendered.should have_content pluralize(@garden.area, @garden.area_unit) end it 'should show the description' do - rendered.should contain "totally cool garden" + rendered.should have_content "totally cool garden" end it 'renders markdown in the description' do @@ -27,11 +27,11 @@ describe "gardens/show" do end it 'should show plantings on the garden page' do - rendered.should contain @planting.crop.name + rendered.should have_content @planting.crop.name end it "doesn't show the note about random plantings" do - rendered.should_not contain "Note: these are a random selection" + rendered.should_not have_content "Note: these are a random selection" end context 'signed in' do @@ -42,11 +42,11 @@ describe "gardens/show" do end it 'should have an edit button' do - rendered.should contain 'Edit' + rendered.should have_content 'Edit' end it "shows a 'plant something' button" do - rendered.should contain "Plant something" + rendered.should have_content "Plant something" end it "links to the right crop in the planting link" do diff --git a/spec/views/harvests/index.html.haml_spec.rb b/spec/views/harvests/index.html.haml_spec.rb index 9a3392155..8751a5c41 100644 --- a/spec/views/harvests/index.html.haml_spec.rb +++ b/spec/views/harvests/index.html.haml_spec.rb @@ -37,7 +37,7 @@ describe "harvests/index" do it "provides data links" do render - rendered.should contain "The data on this page is available in the following formats:" + rendered.should have_content "The data on this page is available in the following formats:" assert_select "a", :href => harvests_path(:format => 'csv') assert_select "a", :href => harvests_path(:format => 'json') end @@ -45,13 +45,13 @@ describe "harvests/index" do it "displays member's name in title" do assign(:owner, @member) render - view.content_for(:title).should contain @member.login_name + view.content_for(:title).should have_content @member.login_name end it "displays crop's name in title" do assign(:crop, @tomato) render - view.content_for(:title).should contain @tomato.name + view.content_for(:title).should have_content @tomato.name end end diff --git a/spec/views/harvests/show.html.haml_spec.rb b/spec/views/harvests/show.html.haml_spec.rb index 4261232e9..7c897a684 100644 --- a/spec/views/harvests/show.html.haml_spec.rb +++ b/spec/views/harvests/show.html.haml_spec.rb @@ -9,9 +9,9 @@ describe "harvests/show" do end it "renders attributes" do - rendered.should contain @crop.name - rendered.should contain @harvest.harvested_at.to_s - rendered.should contain @harvest.plant_part.to_s + rendered.should have_content @crop.name + rendered.should have_content @harvest.harvested_at.to_s + rendered.should have_content @harvest.plant_part.to_s end end diff --git a/spec/views/home/_blurb.html.haml_spec.rb b/spec/views/home/_blurb.html.haml_spec.rb index 13b2d1b46..285363e5e 100644 --- a/spec/views/home/_blurb.html.haml_spec.rb +++ b/spec/views/home/_blurb.html.haml_spec.rb @@ -8,7 +8,7 @@ describe 'home/_blurb.html.haml', :type => "view" do end it 'has description' do - rendered.should contain 'is a community of food gardeners' + rendered.should have_content 'is a community of food gardeners' end it 'has signup section' do @@ -17,7 +17,7 @@ describe 'home/_blurb.html.haml', :type => "view" do end it 'has a link to sign in' do - rendered.should contain "Or sign in if you already have an account" + rendered.should have_content "Or sign in if you already have an account" assert_select "a", :href => new_member_session_path end end diff --git a/spec/views/home/_crops.html.haml_spec.rb b/spec/views/home/_crops.html.haml_spec.rb index e874bb890..548e0a375 100644 --- a/spec/views/home/_crops.html.haml_spec.rb +++ b/spec/views/home/_crops.html.haml_spec.rb @@ -21,7 +21,7 @@ describe 'home/_crops.html.haml', :type => "view" do it 'shows plantings section' do assert_select 'h2', :text => 'Recently planted' - rendered.should contain @planting.location + rendered.should have_content @planting.location end it 'shows recently added crops' do diff --git a/spec/views/home/_members.html.haml_spec.rb b/spec/views/home/_members.html.haml_spec.rb index 616694ab3..81f812a94 100644 --- a/spec/views/home/_members.html.haml_spec.rb +++ b/spec/views/home/_members.html.haml_spec.rb @@ -11,13 +11,13 @@ describe 'home/_members.html.haml', :type => "view" do end it 'Has a heading' do - rendered.should contain "Some of our members" + rendered.should have_content "Some of our members" end it 'Shows members' do - rendered.should contain @member.login_name - rendered.should contain @member.location - rendered.should contain @planting.crop_name + rendered.should have_content @member.login_name + rendered.should have_content @member.location + rendered.should have_content @planting.crop_name end end diff --git a/spec/views/home/_stats.html.haml_spec.rb b/spec/views/home/_stats.html.haml_spec.rb index 46ab4a9f9..b067e44f8 100644 --- a/spec/views/home/_stats.html.haml_spec.rb +++ b/spec/views/home/_stats.html.haml_spec.rb @@ -3,6 +3,6 @@ require 'rails_helper' describe 'home/_stats.html.haml', :type => "view" do it 'has activity stats' do render - rendered.should contain "So far, 0 members have planted 0 crops" + rendered.should have_content "So far, 0 members have planted 0 crops" end end diff --git a/spec/views/home/index_spec.rb b/spec/views/home/index_spec.rb index a04377b39..fe651e149 100644 --- a/spec/views/home/index_spec.rb +++ b/spec/views/home/index_spec.rb @@ -25,8 +25,8 @@ describe 'home/index.html.haml', :type => "view" do end it 'show interesting members' do - rendered.should contain @member.login_name - rendered.should contain @member.location + rendered.should have_content @member.login_name + rendered.should have_content @member.location end end @@ -38,7 +38,7 @@ describe 'home/index.html.haml', :type => "view" do end it 'should say welcome' do - rendered.should contain "Welcome to #{ENV['GROWSTUFF_SITE_NAME']}, #{@member.login_name}" + rendered.should have_content "Welcome to #{ENV['GROWSTUFF_SITE_NAME']}, #{@member.login_name}" end end diff --git a/spec/views/layouts/_footer_spec.rb b/spec/views/layouts/_footer_spec.rb index 987fab00c..00b1f1b07 100644 --- a/spec/views/layouts/_footer_spec.rb +++ b/spec/views/layouts/_footer_spec.rb @@ -7,16 +7,16 @@ describe 'layouts/_footer.html.haml', :type => "view" do end it 'should have links in footer' do - rendered.should contain 'About' - rendered.should contain 'Contact' + rendered.should have_content 'About' + rendered.should have_content 'Contact' assert_select("a[href=/policy/tos]", 'Terms of Service') assert_select("a[href=/policy/privacy]", 'Privacy Policy') assert_select("a[href=/policy/community]", 'Community Guidelines') - rendered.should contain 'Open Source' + rendered.should have_content 'Open Source' assert_select("a[href=/support]", 'Support/FAQ') end it 'should not have an explicit wiki link' do - rendered.should_not contain 'Wiki' + rendered.should_not have_content 'Wiki' end end diff --git a/spec/views/layouts/_header_spec.rb b/spec/views/layouts/_header_spec.rb index 4a56133b3..f4ca3034a 100644 --- a/spec/views/layouts/_header_spec.rb +++ b/spec/views/layouts/_header_spec.rb @@ -12,24 +12,24 @@ describe 'layouts/_header.html.haml', :type => "view" do end it 'should have signup/signin links' do - rendered.should contain 'Sign up' - rendered.should contain 'Sign in' + rendered.should have_content 'Sign up' + rendered.should have_content 'Sign in' end it 'has a Crops link' do - rendered.should contain "Crops" + rendered.should have_content "Crops" end it 'has a Seeds link' do - rendered.should contain "Seeds" + rendered.should have_content "Seeds" end it 'has a Places link' do - rendered.should contain "Community Map" + rendered.should have_content "Community Map" end it 'has a Community section' do - rendered.should contain "Community" + rendered.should have_content "Community" end it 'links to members' do @@ -62,7 +62,7 @@ describe 'layouts/_header.html.haml', :type => "view" do context "your stuff" do it 'should have a Your Stuff section' do - rendered.should contain "Your Stuff" + rendered.should have_content "Your Stuff" end it "should show link to member's gardens" do assert_select("a[href=#{gardens_by_owner_path(:owner => @member.slug)}]", "Gardens") @@ -79,11 +79,11 @@ describe 'layouts/_header.html.haml', :type => "view" do end it 'should show signout link' do - rendered.should contain 'Sign out' + rendered.should have_content 'Sign out' end it 'should show inbox link' do - rendered.should contain 'Inbox' + rendered.should have_content 'Inbox' rendered.should_not match(/Inbox \(\d+\)/) end @@ -91,7 +91,7 @@ describe 'layouts/_header.html.haml', :type => "view" do it 'should show inbox count' do FactoryGirl.create(:notification, :recipient => @member) render - rendered.should contain 'Inbox (1)' + rendered.should have_content 'Inbox (1)' end end diff --git a/spec/views/layouts/application_spec.rb b/spec/views/layouts/application_spec.rb index 56f3f26f1..45f1e7553 100644 --- a/spec/views/layouts/application_spec.rb +++ b/spec/views/layouts/application_spec.rb @@ -9,7 +9,7 @@ describe 'layouts/application.html.haml', :type => "view" do Growstuff::Application.config.analytics_code = '' render assert_select "script", :text => 'alert("foo!")' - rendered.should_not contain 'script' + rendered.should_not have_content 'script' end end diff --git a/spec/views/members/_location.html.haml_spec.rb b/spec/views/members/_location.html.haml_spec.rb index 2e163b1ed..54c5d1198 100644 --- a/spec/views/members/_location.html.haml_spec.rb +++ b/spec/views/members/_location.html.haml_spec.rb @@ -8,7 +8,7 @@ describe "members/_location" do end it 'shows location if available' do - rendered.should contain @member.location + rendered.should have_content @member.location end it "links to the places page" do @@ -23,7 +23,7 @@ describe "members/_location" do end it 'shows unknown location' do - rendered.should contain "unknown location" + rendered.should have_content "unknown location" end it "doesn't link anywhere" do diff --git a/spec/views/members/index.html.haml_spec.rb b/spec/views/members/index.html.haml_spec.rb index b3a65eb76..e9174ffd7 100644 --- a/spec/views/members/index.html.haml_spec.rb +++ b/spec/views/members/index.html.haml_spec.rb @@ -19,7 +19,7 @@ describe "members/index" do end it 'contains member locations' do - rendered.should contain @member.location + rendered.should have_content @member.location end end diff --git a/spec/views/members/show.rss.haml_spec.rb b/spec/views/members/show.rss.haml_spec.rb index 98a8f217a..e5619cdd6 100644 --- a/spec/views/members/show.rss.haml_spec.rb +++ b/spec/views/members/show.rss.haml_spec.rb @@ -10,21 +10,21 @@ describe 'members/show.rss.haml', :type => "view" do end it 'shows RSS feed title' do - rendered.should contain /member\d+'s recent posts/ + rendered.should have_content /member\d+'s recent posts/ end it 'shows content of posts' do - rendered.should contain "This is some text." + rendered.should have_content "This is some text." end it 'renders post bodies to HTML and XML-escapes them' do # The variable "rendered" has been entity-replaced and tag-stripped # The literal string output contains "<strong>" etc. - rendered.should contain "strong" + rendered.should have_content "strong" end it 'gives the author in the item title' do - rendered.should contain "#{@post1.subject} by #{@post1.author}" + rendered.should have_content "#{@post1.subject} by #{@post1.author}" end end diff --git a/spec/views/notifications/index.html.haml_spec.rb b/spec/views/notifications/index.html.haml_spec.rb index ed62d3d7a..43fd80ede 100644 --- a/spec/views/notifications/index.html.haml_spec.rb +++ b/spec/views/notifications/index.html.haml_spec.rb @@ -31,7 +31,7 @@ describe "notifications/index" do :sender => @member, :recipient => @member, :subject => nil) assign(:notifications, [@notification]) render - rendered.should contain "(no subject)" + rendered.should have_content "(no subject)" end end @@ -41,7 +41,7 @@ describe "notifications/index" do :sender => @member, :recipient => @member, :subject => " ") assign(:notifications, [@notification]) render - rendered.should contain "(no subject)" + rendered.should have_content "(no subject)" end end diff --git a/spec/views/notifications/new.html.haml_spec.rb b/spec/views/notifications/new.html.haml_spec.rb index 15dacb730..8b77f6422 100644 --- a/spec/views/notifications/new.html.haml_spec.rb +++ b/spec/views/notifications/new.html.haml_spec.rb @@ -19,7 +19,7 @@ describe "notifications/new" do it "tells you who the recipient is" do render - rendered.should contain @recipient.login_name + rendered.should have_content @recipient.login_name end it "puts the recipient in a hidden field" do @@ -40,12 +40,12 @@ describe "notifications/new" do it "Tells you to write your message here" do render - rendered.should contain "Type your message here" + rendered.should have_content "Type your message here" end it 'shows markdown help' do render - rendered.should contain 'Markdown' + rendered.should have_content 'Markdown' end end diff --git a/spec/views/notifications/show.html.haml_spec.rb b/spec/views/notifications/show.html.haml_spec.rb index 9d51cb5c2..cc33a07e4 100644 --- a/spec/views/notifications/show.html.haml_spec.rb +++ b/spec/views/notifications/show.html.haml_spec.rb @@ -11,8 +11,8 @@ describe "notifications/show" do end it "renders attributes" do - rendered.should contain @notification.sender.to_s - rendered.should contain @notification.body.to_s + rendered.should have_content @notification.sender.to_s + rendered.should have_content @notification.body.to_s end it "includes a delete button" do diff --git a/spec/views/notifier/notify.html.haml_spec.rb b/spec/views/notifier/notify.html.haml_spec.rb index d027b9d0c..b5740b548 100644 --- a/spec/views/notifier/notify.html.haml_spec.rb +++ b/spec/views/notifier/notify.html.haml_spec.rb @@ -10,12 +10,12 @@ describe 'notifier/notify.html.haml', :type => "view" do end it 'should say that you have a message' do - rendered.should contain 'You have received a message' + rendered.should have_content 'You have received a message' end it 'should include notification metadata' do - rendered.should contain @notification.sender.login_name - rendered.should contain @notification.post.subject + rendered.should have_content @notification.sender.login_name + rendered.should have_content @notification.post.subject end it 'should include a reply link' do diff --git a/spec/views/orders/index.html.haml_spec.rb b/spec/views/orders/index.html.haml_spec.rb index a0d558487..ad2116df7 100644 --- a/spec/views/orders/index.html.haml_spec.rb +++ b/spec/views/orders/index.html.haml_spec.rb @@ -11,7 +11,7 @@ describe "orders/index" do it "shows your current account status" do render - rendered.should contain "Your current account status" + rendered.should have_content "Your current account status" end it "renders a list of orders" do diff --git a/spec/views/orders/show.html.haml_spec.rb b/spec/views/orders/show.html.haml_spec.rb index b6b60ec06..98d0eb5e0 100644 --- a/spec/views/orders/show.html.haml_spec.rb +++ b/spec/views/orders/show.html.haml_spec.rb @@ -20,7 +20,7 @@ describe "orders/show" do end it "displays order number" do - rendered.should contain "Order number" + rendered.should have_content "Order number" end it "shows order items in a table" do @@ -28,7 +28,7 @@ describe "orders/show" do end it "shows the total" do - rendered.should contain "Total:" + rendered.should have_content "Total:" assert_select "strong", /198.00/ end diff --git a/spec/views/photos/show.html.haml_spec.rb b/spec/views/photos/show.html.haml_spec.rb index a523965fe..5ef9dc9c0 100644 --- a/spec/views/photos/show.html.haml_spec.rb +++ b/spec/views/photos/show.html.haml_spec.rb @@ -41,7 +41,7 @@ describe "photos/show" do end it "contains the phrase 'All rights reserved'" do - rendered.should contain "All rights reserved" + rendered.should have_content "All rights reserved" end end diff --git a/spec/views/places/show.html.haml_spec.rb b/spec/views/places/show.html.haml_spec.rb index f19d6a0f2..8e3e346c5 100644 --- a/spec/views/places/show.html.haml_spec.rb +++ b/spec/views/places/show.html.haml_spec.rb @@ -20,7 +20,7 @@ describe "places/show" do it "shows the names of nearby members" do @nearby_members.each do |m| - rendered.should contain m.login_name + rendered.should have_content m.login_name end end diff --git a/spec/views/plant_parts/index.html.haml_spec.rb b/spec/views/plant_parts/index.html.haml_spec.rb index b68736977..1a9469c55 100644 --- a/spec/views/plant_parts/index.html.haml_spec.rb +++ b/spec/views/plant_parts/index.html.haml_spec.rb @@ -9,7 +9,7 @@ describe "plant_parts/index" do it "renders a list of plant_parts" do render - rendered.should contain @pp.name + rendered.should have_content @pp.name assert_select "a", :href => plant_part_path(@pp) end diff --git a/spec/views/plant_parts/show.html.haml_spec.rb b/spec/views/plant_parts/show.html.haml_spec.rb index 33390171c..b65ecb154 100644 --- a/spec/views/plant_parts/show.html.haml_spec.rb +++ b/spec/views/plant_parts/show.html.haml_spec.rb @@ -11,7 +11,7 @@ describe "plant_parts/show" do it "renders a list of crops harvested for this part" do render @pp.crops.each do |c| - rendered.should contain c.name + rendered.should have_content c.name assert_select "a", :href => crop_path(c) end end diff --git a/spec/views/plantings/_thumbnail.html.haml_spec.rb b/spec/views/plantings/_thumbnail.html.haml_spec.rb index 47501b1fd..dd5cc2003 100644 --- a/spec/views/plantings/_thumbnail.html.haml_spec.rb +++ b/spec/views/plantings/_thumbnail.html.haml_spec.rb @@ -21,19 +21,19 @@ describe "plantings/_thumbnail" do end it "renders the quantity planted" do - rendered.should contain "33" + rendered.should have_content "33" end it "renders the date planted" do - rendered.should contain @planting.planted_at.to_s(:default) + rendered.should have_content @planting.planted_at.to_s(:default) end it "shows the name of the crop" do - rendered.should contain @crop.name + rendered.should have_content @crop.name end it "shows the description by default" do - rendered.should contain "This is a" + rendered.should have_content "This is a" end end @@ -46,7 +46,7 @@ describe "plantings/_thumbnail" do end it "hides the description if asked" do - rendered.should_not contain "This is a" + rendered.should_not have_content "This is a" end end diff --git a/spec/views/plantings/index.html.haml_spec.rb b/spec/views/plantings/index.html.haml_spec.rb index c51c378a0..6a130c8c9 100644 --- a/spec/views/plantings/index.html.haml_spec.rb +++ b/spec/views/plantings/index.html.haml_spec.rb @@ -37,23 +37,23 @@ describe "plantings/index" do end it "renders a list of plantings" do - rendered.should contain @tomato.name - rendered.should contain @maize.name - rendered.should contain @member.login_name - rendered.should contain @garden.name + rendered.should have_content @tomato.name + rendered.should have_content @maize.name + rendered.should have_content @member.login_name + rendered.should have_content @garden.name end it "displays planting time" do - rendered.should contain 'January 13, 2013' + rendered.should have_content 'January 13, 2013' end it "displays finished time" do - rendered.should contain 'January 20, 2013' + rendered.should have_content 'January 20, 2013' end it "provides data links" do render - rendered.should contain "The data on this page is available in the following formats:" + rendered.should have_content "The data on this page is available in the following formats:" assert_select "a", :href => plantings_path(:format => 'csv') assert_select "a", :href => plantings_path(:format => 'json') assert_select "a", :href => plantings_path(:format => 'rss') @@ -62,12 +62,12 @@ describe "plantings/index" do it "displays member's name in title" do assign(:owner, @member) render - view.content_for(:title).should contain @member.login_name + view.content_for(:title).should have_content @member.login_name end it "displays crop's name in title" do assign(:crop, @tomato) render - view.content_for(:title).should contain @tomato.name + view.content_for(:title).should have_content @tomato.name end end diff --git a/spec/views/plantings/index.rss.haml_spec.rb b/spec/views/plantings/index.rss.haml_spec.rb index e7e232ebf..c953382ce 100644 --- a/spec/views/plantings/index.rss.haml_spec.rb +++ b/spec/views/plantings/index.rss.haml_spec.rb @@ -15,23 +15,23 @@ describe 'plantings/index.rss.haml' do end it 'shows RSS feed title' do - rendered.should contain "Recent plantings from all members" + rendered.should have_content "Recent plantings from all members" end it 'item title shows owner and location' do - rendered.should contain "#{@planting.crop} in #{@planting.location}" + rendered.should have_content "#{@planting.crop} in #{@planting.location}" end it 'shows formatted content of posts' do - rendered.should contain "This is a really good plant." + rendered.should have_content "This is a really good plant." end it 'shows sunniness' do - rendered.should contain 'Sunniness: sun' + rendered.should have_content 'Sunniness: sun' end it 'shows propagation method' do - rendered.should contain 'Planted from: seedling' + rendered.should have_content 'Planted from: seedling' end end @@ -44,7 +44,7 @@ describe 'plantings/index.rss.haml' do end it 'shows title for single member' do - rendered.should contain "Recent plantings from #{@planting.owner}" + rendered.should have_content "Recent plantings from #{@planting.owner}" end end end diff --git a/spec/views/plantings/show.html.haml_spec.rb b/spec/views/plantings/show.html.haml_spec.rb index c90220b38..28a44078a 100644 --- a/spec/views/plantings/show.html.haml_spec.rb +++ b/spec/views/plantings/show.html.haml_spec.rb @@ -25,16 +25,16 @@ describe "plantings/show" do it "shows the sunniness" do render - rendered.should contain 'Sun or shade?' - rendered.should contain 'sun' + rendered.should have_content 'Sun or shade?' + rendered.should have_content 'sun' end it "doesn't show sunniness if blank" do @p.sunniness = '' @p.save render - rendered.should_not contain 'Sun or shade?' - rendered.should_not contain 'sun' + rendered.should_not have_content 'Sun or shade?' + rendered.should_not have_content 'sun' end end @@ -45,16 +45,16 @@ describe "plantings/show" do it "shows planted_from" do render - rendered.should contain 'Planted from:' - rendered.should contain 'cutting' + rendered.should have_content 'Planted from:' + rendered.should have_content 'cutting' end it "doesn't show planted_from if blank" do @p.planted_from = '' @p.save render - rendered.should_not contain 'Planted from:' - rendered.should_not contain 'cutting' + rendered.should_not have_content 'Planted from:' + rendered.should_not have_content 'cutting' end end @@ -67,7 +67,7 @@ describe "plantings/show" do it "shows a link to add photos" do render - rendered.should contain "Add photo" + rendered.should have_content "Add photo" end context "no location set" do @@ -88,7 +88,7 @@ describe "plantings/show" do end it "doesn't contain a () if no location is set" do - rendered.should_not contain "()" + rendered.should_not have_content "()" end end @@ -100,7 +100,7 @@ describe "plantings/show" do end it "shows the member's location in parentheses" do - rendered.should contain "(#{@p.owner.location})" + rendered.should have_content "(#{@p.owner.location})" end end end diff --git a/spec/views/policy/community_spec.rb b/spec/views/policy/community_spec.rb index f4b9c6429..17f6d3b11 100644 --- a/spec/views/policy/community_spec.rb +++ b/spec/views/policy/community_spec.rb @@ -7,6 +7,6 @@ describe 'policy/community.html.haml', :type => "view" do it 'should show community guidelines' do render - rendered.should contain 'is a community by and for food-gardeners.' + rendered.should have_content 'is a community by and for food-gardeners.' end end diff --git a/spec/views/policy/tos_spec.rb b/spec/views/policy/tos_spec.rb index 2a11532a8..24cacdf0d 100644 --- a/spec/views/policy/tos_spec.rb +++ b/spec/views/policy/tos_spec.rb @@ -7,6 +7,6 @@ describe 'policy/tos.html.haml', :type => "view" do it 'should show terms of service' do render - rendered.should contain 'Terms of Service' + rendered.should have_content 'Terms of Service' end end diff --git a/spec/views/posts/_single.html.haml_spec.rb b/spec/views/posts/_single.html.haml_spec.rb index 50216c4db..268db854d 100644 --- a/spec/views/posts/_single.html.haml_spec.rb +++ b/spec/views/posts/_single.html.haml_spec.rb @@ -101,7 +101,7 @@ describe "posts/_single" do end it "renders no value of comments" do - rendered.should_not contain "1 comment" + rendered.should_not have_content "1 comment" end it "does not contain link to post" do diff --git a/spec/views/posts/edit.html.haml_spec.rb b/spec/views/posts/edit.html.haml_spec.rb index 7c68fc4ae..7b3f0b195 100644 --- a/spec/views/posts/edit.html.haml_spec.rb +++ b/spec/views/posts/edit.html.haml_spec.rb @@ -25,7 +25,7 @@ describe "posts/edit" do end it 'no forum mentioned' do - rendered.should_not contain "This post will be posted in the forum" + rendered.should_not have_content "This post will be posted in the forum" end context "forum specified" do @@ -43,7 +43,7 @@ describe "posts/edit" do end it 'tells the user what forum it will be posted in' do - rendered.should contain "This post will be posted in the forum #{@forum.name}" + rendered.should have_content "This post will be posted in the forum #{@forum.name}" end end diff --git a/spec/views/posts/index.rss.haml_spec.rb b/spec/views/posts/index.rss.haml_spec.rb index c06416386..0a303f19b 100644 --- a/spec/views/posts/index.rss.haml_spec.rb +++ b/spec/views/posts/index.rss.haml_spec.rb @@ -11,15 +11,15 @@ describe 'posts/index.rss.haml', :type => "view" do end it 'shows RSS feed title' do - rendered.should contain "Recent posts from all members" + rendered.should have_content "Recent posts from all members" end it 'shows content of posts' do - rendered.should contain "This is some text." + rendered.should have_content "This is some text." end it 'gives the author in the item title' do - rendered.should contain "#{@post1.subject} by #{@post1.author}" + rendered.should have_content "#{@post1.subject} by #{@post1.author}" end end diff --git a/spec/views/posts/new.html.haml_spec.rb b/spec/views/posts/new.html.haml_spec.rb index ca4ee0a48..73448e24c 100644 --- a/spec/views/posts/new.html.haml_spec.rb +++ b/spec/views/posts/new.html.haml_spec.rb @@ -24,12 +24,12 @@ describe "posts/new" do it 'no forum mentioned' do render - rendered.should_not contain "This post will be posted in the forum" + rendered.should_not have_content "This post will be posted in the forum" end it "asks what's going on in your garden" do render - rendered.should contain "What's going on in your food garden?" + rendered.should have_content "What's going on in your food garden?" end context "forum specified" do @@ -44,19 +44,19 @@ describe "posts/new" do end it 'tells the user what forum it will be posted in' do - rendered.should contain "This post will be posted in the forum #{@forum.name}" + rendered.should have_content "This post will be posted in the forum #{@forum.name}" end it "asks what's going on generally" do render - rendered.should_not contain "What's going on in your food garden?" - rendered.should contain "What's up?" + rendered.should_not have_content "What's going on in your food garden?" + rendered.should have_content "What's up?" end end it 'shows markdown help' do render - rendered.should contain 'Markdown' + rendered.should have_content 'Markdown' end end diff --git a/spec/views/posts/show.html.haml_spec.rb b/spec/views/posts/show.html.haml_spec.rb index c0d1a82d0..e1ea7a77e 100644 --- a/spec/views/posts/show.html.haml_spec.rb +++ b/spec/views/posts/show.html.haml_spec.rb @@ -55,7 +55,7 @@ describe "posts/show" do end it "shows comments" do - rendered.should contain @comment.body + rendered.should have_content @comment.body end it 'has an anchor to the comments' do @@ -79,7 +79,7 @@ describe "posts/show" do end it "shows the oldest comments first" do - rendered.should contain /#{@comment1.body}.*#{@comment2.body}.*#{@comment3.body}.*#{@comment4.body}/m + rendered.should have_content /#{@comment1.body}.*#{@comment2.body}.*#{@comment3.body}.*#{@comment4.body}/m end end @@ -88,7 +88,7 @@ describe "posts/show" do @post = assign(:post, FactoryGirl.create(:forum_post, :author => @author)) render - rendered.should contain "in #{@post.forum.name}" + rendered.should have_content "in #{@post.forum.name}" end end diff --git a/spec/views/posts/show.rss.haml_spec.rb b/spec/views/posts/show.rss.haml_spec.rb index 072b8032c..72e8e7347 100644 --- a/spec/views/posts/show.rss.haml_spec.rb +++ b/spec/views/posts/show.rss.haml_spec.rb @@ -12,20 +12,20 @@ describe 'posts/show.rss.haml' do end it 'shows RSS feed title' do - rendered.should contain "Recent comments on #{@post.subject}" + rendered.should have_content "Recent comments on #{@post.subject}" end it 'shows item title' do - rendered.should contain "Comment by #{@author.login_name}" + rendered.should have_content "Comment by #{@author.login_name}" end it 'escapes html for link to post' do # it's then unescaped by 'render' so we don't actually look for < - rendered.should contain '" do render # Run the generator again with the --webrat flag if you want to use webrat matchers - rendered.should contain @product.name - rendered.should contain @product.min_price.to_s - rendered.should contain @product.recommended_price.to_s + rendered.should have_content @product.name + rendered.should have_content @product.min_price.to_s + rendered.should have_content @product.recommended_price.to_s end end diff --git a/spec/views/scientific_names/edit.html.haml_spec.rb b/spec/views/scientific_names/edit.html.haml_spec.rb index 0202243f8..3e5dc9e91 100644 --- a/spec/views/scientific_names/edit.html.haml_spec.rb +++ b/spec/views/scientific_names/edit.html.haml_spec.rb @@ -13,7 +13,7 @@ describe "scientific_names/edit" do end it "shows the creator" do - rendered.should contain "Added by #{@scientific_name.creator} less than a minute ago." + rendered.should have_content "Added by #{@scientific_name.creator} less than a minute ago." end it "renders the edit scientific_name form" do diff --git a/spec/views/scientific_names/index.html.haml_spec.rb b/spec/views/scientific_names/index.html.haml_spec.rb index 9e5a8519e..a49b9ef88 100644 --- a/spec/views/scientific_names/index.html.haml_spec.rb +++ b/spec/views/scientific_names/index.html.haml_spec.rb @@ -17,8 +17,8 @@ describe "scientific_names/index" do it "doesn't show edit/destroy links" do render - rendered.should_not contain "Edit" - rendered.should_not contain "Delete" + rendered.should_not have_content "Edit" + rendered.should_not have_content "Delete" end context "logged in and crop wrangler" do @@ -30,8 +30,8 @@ describe "scientific_names/index" do it "shows edit/destroy links" do render - rendered.should contain "Edit" - rendered.should contain "Delete" + rendered.should have_content "Edit" + rendered.should have_content "Delete" end end end diff --git a/spec/views/seeds/index.html.haml_spec.rb b/spec/views/seeds/index.html.haml_spec.rb index ae6f78047..a1d478544 100644 --- a/spec/views/seeds/index.html.haml_spec.rb +++ b/spec/views/seeds/index.html.haml_spec.rb @@ -45,7 +45,7 @@ describe "seeds/index" do it "provides data links" do render - rendered.should contain "The data on this page is available in the following formats:" + rendered.should have_content "The data on this page is available in the following formats:" assert_select "a", :href => seeds_path(:format => 'csv') assert_select "a", :href => seeds_path(:format => 'json') assert_select "a", :href => seeds_path(:format => 'rss') diff --git a/spec/views/seeds/index.rss.haml_spec.rb b/spec/views/seeds/index.rss.haml_spec.rb index 22e10f1e7..485f390d0 100644 --- a/spec/views/seeds/index.rss.haml_spec.rb +++ b/spec/views/seeds/index.rss.haml_spec.rb @@ -14,23 +14,23 @@ describe 'seeds/index.rss.haml' do end it 'shows RSS feed title' do - rendered.should contain "Recent seeds from all members" + rendered.should have_content "Recent seeds from all members" end it 'has a useful item title' do - rendered.should contain "#{@seed.owner}'s #{@seed.crop} seeds" + rendered.should have_content "#{@seed.owner}'s #{@seed.crop} seeds" end it 'shows the seed count' do - rendered.should contain "Quantity: #{@seed.quantity}" + rendered.should have_content "Quantity: #{@seed.quantity}" end it 'shows the plant_before date' do - rendered.should contain "Plant before: #{@seed.plant_before.to_s}" + rendered.should have_content "Plant before: #{@seed.plant_before.to_s}" end it 'mentions that one seed is tradable' do - rendered.should contain "Will trade #{@tradable.tradable_to} from #{@tradable.owner.location}" + rendered.should have_content "Will trade #{@tradable.tradable_to} from #{@tradable.owner.location}" end end @@ -44,7 +44,7 @@ describe 'seeds/index.rss.haml' do end it 'shows RSS feed title' do - rendered.should contain "Recent seeds from #{@seed.owner}" + rendered.should have_content "Recent seeds from #{@seed.owner}" end end end diff --git a/spec/views/seeds/new.html.haml_spec.rb b/spec/views/seeds/new.html.haml_spec.rb index 3121f7b3b..9abb2f291 100644 --- a/spec/views/seeds/new.html.haml_spec.rb +++ b/spec/views/seeds/new.html.haml_spec.rb @@ -22,7 +22,7 @@ describe "seeds/new" do it 'reminds you to set your location' do render - rendered.should contain "Don't forget to set your location." + rendered.should have_content "Don't forget to set your location." assert_select "a", :text => "set your location" end @@ -37,7 +37,7 @@ describe "seeds/new" do it 'shows the location' do render - rendered.should contain "from #{@member.location}." + rendered.should have_content "from #{@member.location}." assert_select 'a', :href => place_path(@member.location) end diff --git a/spec/views/seeds/show.html.haml_spec.rb b/spec/views/seeds/show.html.haml_spec.rb index b2276ba23..af00b4efe 100644 --- a/spec/views/seeds/show.html.haml_spec.rb +++ b/spec/views/seeds/show.html.haml_spec.rb @@ -9,7 +9,7 @@ describe "seeds/show" do it "renders attributes in

" do render - rendered.should contain @seed.crop.name + rendered.should have_content @seed.crop.name end context "tradable" do @@ -25,12 +25,12 @@ describe "seeds/show" do it "shows tradable attributes" do render - rendered.should contain "Will trade: locally" + rendered.should have_content "Will trade: locally" end it "shows location of seed owner" do render - rendered.should contain @owner.location + rendered.should have_content @owner.location assert_select 'a', :href => place_path(@owner.location) end @@ -44,7 +44,7 @@ describe "seeds/show" do it 'says "from unspecified location"' do render - rendered.should contain "(from unspecified location)" + rendered.should have_content "(from unspecified location)" end it "links to profile to set location" do @@ -55,7 +55,7 @@ describe "seeds/show" do it "shows button to send message" do render - rendered.should contain "Request seeds" + rendered.should have_content "Request seeds" end end diff --git a/spec/views/shop/index_spec.rb b/spec/views/shop/index_spec.rb index f93d173cd..25f187291 100644 --- a/spec/views/shop/index_spec.rb +++ b/spec/views/shop/index_spec.rb @@ -20,7 +20,7 @@ describe 'shop/index.html.haml', :type => "view" do end it 'shows prices in AUD' do - rendered.should contain '9.99 AUD' + rendered.should have_content '9.99 AUD' end it 'should contain an exchange rate link' do @@ -29,7 +29,7 @@ describe 'shop/index.html.haml', :type => "view" do end it 'shows recommended price for products that have it' do - rendered.should contain '12.00 AUD' + rendered.should have_content '12.00 AUD' end it 'should contain an exchange rate link for recommended price' do @@ -60,7 +60,7 @@ describe 'shop/index.html.haml', :type => "view" do it "tells you you have a paid membership" do render - rendered.should contain "You currently have a paid" + rendered.should have_content "You currently have a paid" end it "doesn't show shop" do @@ -77,7 +77,7 @@ describe 'shop/index.html.haml', :type => "view" do end it "tells you to sign up/sign in" do - rendered.should contain "sign in or sign up" + rendered.should have_content "sign in or sign up" end end diff --git a/spec/views/support/index_spec.rb b/spec/views/support/index_spec.rb index 1b29e2adb..fc3a96b12 100644 --- a/spec/views/support/index_spec.rb +++ b/spec/views/support/index_spec.rb @@ -6,11 +6,11 @@ describe 'support/index.html.haml', :type => "view" do end it 'should show support faq' do - rendered.should contain 'About Growstuff' + rendered.should have_content 'About Growstuff' end it 'should not mention Courtney any more' do - rendered.should_not contain 'Courtney' - rendered.should_not contain 'phazel' + rendered.should_not have_content 'Courtney' + rendered.should_not have_content 'phazel' end end From f1945151c7e3ad6d57527e94b17a1dd166ad26c4 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 16 Nov 2014 14:40:44 +1100 Subject: [PATCH 024/143] update RSpec true / false matchers --- spec/models/alternate_name_spec.rb | 2 +- spec/models/crop_spec.rb | 2 +- spec/models/member_spec.rb | 16 ++++++++-------- spec/models/scientific_name_spec.rb | 2 +- spec/models/seed_spec.rb | 2 +- spec/views/shop/index_spec.rb | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/spec/models/alternate_name_spec.rb b/spec/models/alternate_name_spec.rb index 7819586cc..ecbdc10eb 100644 --- a/spec/models/alternate_name_spec.rb +++ b/spec/models/alternate_name_spec.rb @@ -4,7 +4,7 @@ describe AlternateName do let(:an) { FactoryGirl.create(:alternate_eggplant) } it 'should save a basic alternate name' do - expect(an.save).to be_true + expect(an.save).to be(true) end it 'should be possible to add multiple alternate names to a crop' do diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index 76740cdfe..cce3af187 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -8,7 +8,7 @@ describe Crop do end it 'should save a basic crop' do - @crop.save.should be_true + @crop.save.should be(true) end it 'should be fetchable from the database' do diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 0fb6cdacc..365c8b6a5 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -33,11 +33,11 @@ describe 'member' do it "should have a default-type account by default" do @member.account.account_type.name.should eq Growstuff::Application.config.default_account_type - @member.is_paid?.should be_false + @member.is_paid?.should be(false) end it "doesn't show email by default" do - @member.show_email.should be_false + @member.show_email.should be(false) end it 'should stringify as the login_name' do @@ -101,7 +101,7 @@ describe 'member' do end it "should refuse to save a member who hasn't agreed to the TOS" do - @member.save.should_not be_true + @member.save.should_not be(true) end end @@ -311,7 +311,7 @@ describe 'member' do @account_type = FactoryGirl.create(:account_type, :is_paid => true, :is_permanent_paid => true) @member.account.account_type = @account_type - @member.is_paid?.should be_true + @member.is_paid?.should be(true) end it "recognises a current paid account" do @@ -319,7 +319,7 @@ describe 'member' do :is_paid => true, :is_permanent_paid => false) @member.account.account_type = @account_type @member.account.paid_until = Time.zone.now + 1.month - @member.is_paid?.should be_true + @member.is_paid?.should be(true) end it "recognises an expired paid account" do @@ -327,14 +327,14 @@ describe 'member' do :is_paid => true, :is_permanent_paid => false) @member.account.account_type = @account_type @member.account.paid_until = Time.zone.now - 1.minute - @member.is_paid?.should be_false + @member.is_paid?.should be(false) end it "recognises a free account" do @account_type = FactoryGirl.create(:account_type, :is_paid => false, :is_permanent_paid => false) @member.account.account_type = @account_type - @member.is_paid?.should be_false + @member.is_paid?.should be(false) end it "recognises a free account even with paid_until set" do @@ -342,7 +342,7 @@ describe 'member' do :is_paid => false, :is_permanent_paid => false) @member.account.account_type = @account_type @member.account.paid_until = Time.zone.now + 1.month - @member.is_paid?.should be_false + @member.is_paid?.should be(false) end end diff --git a/spec/models/scientific_name_spec.rb b/spec/models/scientific_name_spec.rb index d8404d0ba..020f1cc0d 100644 --- a/spec/models/scientific_name_spec.rb +++ b/spec/models/scientific_name_spec.rb @@ -8,7 +8,7 @@ describe ScientificName do end it 'should save a basic scientific name' do - @sn.save.should be_true + @sn.save.should be(true) end it 'should be fetchable from the database' do diff --git a/spec/models/seed_spec.rb b/spec/models/seed_spec.rb index 6a134a47e..cfd73bf04 100644 --- a/spec/models/seed_spec.rb +++ b/spec/models/seed_spec.rb @@ -7,7 +7,7 @@ describe Seed do end it 'should save a basic seed' do - @seed.save.should be_true + @seed.save.should be(true) end it "should have a slug" do diff --git a/spec/views/shop/index_spec.rb b/spec/views/shop/index_spec.rb index 25f187291..ee9ee59a9 100644 --- a/spec/views/shop/index_spec.rb +++ b/spec/views/shop/index_spec.rb @@ -55,7 +55,7 @@ describe 'shop/index.html.haml', :type => "view" do end it "recognises the paid member" do - @member.is_paid?.should be_true + @member.is_paid?.should be(true) end it "tells you you have a paid membership" do From 56b4f8a221b06b6dd3394d8a356852eabfa7afc3 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 16 Nov 2014 20:21:34 +1100 Subject: [PATCH 025/143] mimick old FriendlyId behavior when calling find on a model - therefore, Model.find not Model.friendly.find (this probably needs review) --- Gemfile | 3 +++ Gemfile.lock | 12 ++++++++++++ app/controllers/crops_controller.rb | 2 +- app/controllers/plantings_controller.rb | 2 +- app/mailers/notifier.rb | 4 ++-- app/models/crop.rb | 2 +- app/models/forum.rb | 2 +- app/models/garden.rb | 2 +- app/models/harvest.rb | 2 +- app/models/member.rb | 2 +- app/models/plant_part.rb | 2 +- app/models/planting.rb | 2 +- app/models/post.rb | 2 +- app/models/role.rb | 2 +- app/models/seed.rb | 2 +- 15 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Gemfile b/Gemfile index 911a6ea79..2c5656312 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,8 @@ gem 'protected_attributes', '~>1.0.1' gem 'rails-observers', '~>0.1.1' gem 'rails-perftest', '~>0.0.2' +gem 'byebug' + gem 'bundler', '>=1.1.5' gem 'rails', '4.1.7' @@ -130,6 +132,7 @@ gem 'rake', '>= 10.0.0' group :development, :test do gem 'haml-rails' # HTML templating language gem 'rspec-rails', '~> 3.1.0' # unit testing framework + gem 'rspec-activemodel-mocks' gem 'database_cleaner', '~> 1.3.0' gem 'webrat' # provides HTML matchers for view tests gem 'factory_girl_rails', '~> 4.5.0' # for creating test data diff --git a/Gemfile.lock b/Gemfile.lock index 14eb52d90..2a90c791c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -75,6 +75,10 @@ GEM bootstrap-datepicker-rails (1.3.0.2) railties (>= 3.0) builder (3.2.2) + byebug (3.5.1) + columnize (~> 0.8) + debugger-linecache (~> 1.2) + slop (~> 3.6) cancan (1.6.10) capybara (2.4.4) mime-types (>= 1.16) @@ -94,6 +98,7 @@ GEM coffee-script-source execjs coffee-script-source (1.8.0) + columnize (0.8.9) commonjs (0.2.7) coveralls (0.7.1) multi_json (~> 1.3) @@ -106,6 +111,7 @@ GEM dalli (2.7.2) database_cleaner (1.3.0) debug_inspector (0.0.2) + debugger-linecache (1.2.0) devise (3.4.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -260,6 +266,10 @@ GEM rest-client (1.7.2) mime-types (>= 1.16, < 3.0) netrc (~> 0.7) + rspec-activemodel-mocks (1.0.1) + activemodel (>= 3.0) + activesupport (>= 3.0) + rspec-mocks (>= 2.99, < 4.0) rspec-core (3.1.7) rspec-support (~> 3.1.0) rspec-expectations (3.1.2) @@ -345,6 +355,7 @@ DEPENDENCIES bluecloth bootstrap-datepicker-rails bundler (>= 1.1.5) + byebug cancan capybara capybara-email @@ -389,6 +400,7 @@ DEPENDENCIES rails4_upgrade rails_12factor rake (>= 10.0.0) + rspec-activemodel-mocks rspec-rails (~> 3.1.0) sass-rails (~> 4.0.4) therubyracer (~> 0.12) diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index a30de159a..95b42cd01 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -55,7 +55,7 @@ class CropsController < ApplicationController @partial_matches = Crop.search(params[:search]) # exclude exact match from partial match list - @partial_matches.reject!{ |r| @exact_match && r.eql?(@exact_match) } + @partial_matches = @partial_matches.reject{ |r| @exact_match && r.eql?(@exact_match) } @fuzzy = Crop.search(params[:term]) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index b08fe98fd..83a10facd 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -31,7 +31,7 @@ class PlantingsController < ApplicationController # GET /plantings/1 # GET /plantings/1.json def show - @planting = Planting.includes(:owner, :crop, :garden, :photos).find(params[:id]) + @planting = Planting.includes(:owner, :crop, :garden, :photos).friendly.find(params[:id]) respond_to do |format| format.html # show.html.erb diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb index c1c7768b3..750b4ab16 100644 --- a/app/mailers/notifier.rb +++ b/app/mailers/notifier.rb @@ -13,8 +13,8 @@ class Notifier < ActionMailer::Base def planting_reminder(member) @member = member - @plantings = @member.plantings.reorder.last(5) - @harvests = @member.harvests.reorder.last(5) + @plantings = @member.plantings.last(5) + @harvests = @member.harvests.last(5) if @member.send_planting_reminder mail(:to => @member.email, diff --git a/app/models/crop.rb b/app/models/crop.rb index d85ab4647..3f5e5e9e7 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -1,6 +1,6 @@ class Crop < ActiveRecord::Base extend FriendlyId - friendly_id :name, use: :slugged + friendly_id :name, use: [:slugged, :finders] attr_accessible :en_wikipedia_url, :name, :parent_id, :creator_id, :scientific_names_attributes has_many :scientific_names diff --git a/app/models/forum.rb b/app/models/forum.rb index b673dbf19..f671a97c0 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -1,6 +1,6 @@ class Forum < ActiveRecord::Base extend FriendlyId - friendly_id :name, use: :slugged + friendly_id :name, use: [:slugged, :finders] attr_accessible :description, :name, :owner_id, :slug has_many :posts belongs_to :owner, :class_name => "Member" diff --git a/app/models/garden.rb b/app/models/garden.rb index 9e390f4bd..eb7d2e1b2 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -1,7 +1,7 @@ class Garden < ActiveRecord::Base include Geocodable extend FriendlyId - friendly_id :garden_slug, use: :slugged + friendly_id :garden_slug, use: [:slugged, :finders] attr_accessible :name, :slug, :owner_id, :description, :active, :location, :latitude, :longitude, :area, :area_unit diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 184ae595d..76d5a30ec 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -1,7 +1,7 @@ class Harvest < ActiveRecord::Base include ActionView::Helpers::NumberHelper extend FriendlyId - friendly_id :harvest_slug, use: :slugged + friendly_id :harvest_slug, use: [:slugged, :finders] attr_accessible :crop_id, :harvested_at, :description, :owner_id, :quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug diff --git a/app/models/member.rb b/app/models/member.rb index 8eebdcd72..176380800 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -2,7 +2,7 @@ class Member < ActiveRecord::Base include Geocodable extend FriendlyId - friendly_id :login_name, use: :slugged + friendly_id :login_name, use: [:slugged, :finders] has_many :posts, :foreign_key => 'author_id' has_many :comments, :foreign_key => 'author_id' diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index 16241372a..648ddd290 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -1,6 +1,6 @@ class PlantPart < ActiveRecord::Base extend FriendlyId - friendly_id :name, :use => :slugged + friendly_id :name, :use => [:slugged, :finders] has_many :harvests has_many :crops, -> { uniq }, :through => :harvests diff --git a/app/models/planting.rb b/app/models/planting.rb index aff4f37ba..b853cb256 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -1,6 +1,6 @@ class Planting < ActiveRecord::Base extend FriendlyId - friendly_id :planting_slug, use: :slugged + friendly_id :planting_slug, use: [:slugged, :finders] attr_accessible :crop_id, :description, :garden_id, :planted_at, :quantity, :sunniness, :planted_from, :owner_id, :finished, diff --git a/app/models/post.rb b/app/models/post.rb index 05d95e056..7f49ebc2c 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,6 +1,6 @@ class Post < ActiveRecord::Base extend FriendlyId - friendly_id :author_date_subject, use: :slugged + friendly_id :author_date_subject, use: [:slugged, :finders] attr_accessible :body, :subject, :author_id, :forum_id belongs_to :author, :class_name => 'Member' belongs_to :forum diff --git a/app/models/role.rb b/app/models/role.rb index 284fdd0d8..cf002d22d 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,6 +1,6 @@ class Role < ActiveRecord::Base extend FriendlyId - friendly_id :name, use: :slugged + friendly_id :name, use: [:slugged, :finders] attr_accessible :description, :name, :members, :slug has_and_belongs_to_many :members diff --git a/app/models/seed.rb b/app/models/seed.rb index c2183c2c9..ff2538218 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -1,6 +1,6 @@ class Seed < ActiveRecord::Base extend FriendlyId - friendly_id :seed_slug, use: :slugged + friendly_id :seed_slug, use: [:slugged, :finders] attr_accessible :owner_id, :crop_id, :description, :quantity, :plant_before, :tradable_to, :slug From 0ffe9adc865f6741b6d8d5a184e3ed9d480e4507 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 16 Nov 2014 21:40:43 +1100 Subject: [PATCH 026/143] tests are green --- app/controllers/application_controller.rb | 8 ++++++++ app/controllers/notifications_controller.rb | 2 +- app/models/member.rb | 8 +++++--- config/application.rb | 3 +++ spec/features/signup_spec.rb | 1 - spec/models/photo_spec.rb | 6 +++--- spec/views/plantings/edit.html.haml_spec.rb | 2 +- spec/views/plantings/new.html.haml_spec.rb | 2 +- 8 files changed, 22 insertions(+), 10 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e417984fa..01166c2a4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -43,4 +43,12 @@ class ApplicationController < ActionController::Base I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil end + before_action :configure_permitted_parameters, if: :devise_controller? + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:login_name, :email, :password, :password_confirmation, :tos_agreement, :newsletter) } + end + end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 790e5d3ac..8844d2954 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -3,7 +3,7 @@ class NotificationsController < ApplicationController load_and_authorize_resource # GET /notifications def index - @notifications = Notification.find_all_by_recipient_id(current_member) + @notifications = Notification.where(recipient_id: current_member) respond_to do |format| format.html # index.html.erb diff --git a/app/models/member.rb b/app/models/member.rb index 176380800..d177174c5 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -237,17 +237,19 @@ class Member < ActiveRecord::Base end end - def newsletter_subscribe + def newsletter_subscribe(testing=false) + return true if (Rails.env.test? && !testing) gb = Gibbon::API.new res = gb.lists.subscribe({ :id => Gibbon::API.api_key, :email => { :email => email }, :merge_vars => { :login_name => login_name }, - :double_optin => false # they alredy confirmed their email with us + :double_optin => false # they already confirmed their email with us }) end - def newsletter_unsubscribe + def newsletter_unsubscribe(testing=false) + return true if (Rails.env.test? && !testing) gb = Gibbon::API.new res = gb.lists.unsubscribe({ :id => ENV['GROWSTUFF_MAILCHIMP_NEWSLETTER_ID'], diff --git a/config/application.rb b/config/application.rb index 5b01d3aa8..116696f51 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,7 @@ require File.expand_path('../boot', __FILE__) require 'rails/all' +require 'openssl' if defined?(Bundler) # If you precompile assets before deploying to production, use this line @@ -38,6 +39,8 @@ module Growstuff # rails will fallback to en, no matter what is set as config.i18n.default_locale config.i18n.fallbacks = [:en] + config.i18n.enforce_available_locales = true + # Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8" diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb index c91ad4682..aa4c9d65f 100644 --- a/spec/features/signup_spec.rb +++ b/spec/features/signup_spec.rb @@ -11,7 +11,6 @@ feature "signup" do fill_in 'Password confirmation', with: 'abc123' check 'member_tos_agreement' click_button 'Sign up' - page.has_content? 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.' current_path.should eq root_path end diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index 850fa42cc..5a2099c7a 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -44,7 +44,7 @@ describe Photo do planting.photos << photo harvest.destroy # photo is now used by harvest but not planting photo.destroy_if_unused - expect(lambda { photo.reload }).not_to raise_error ActiveRecord::RecordNotFound + expect(lambda { photo.reload }).not_to raise_error end it 'they are used by harvests but not plantings' do @@ -52,7 +52,7 @@ describe Photo do planting.photos << photo planting.destroy # photo is now used by harvest but not planting photo.destroy_if_unused - expect(lambda { photo.reload }).not_to raise_error ActiveRecord::RecordNotFound + expect(lambda { photo.reload }).not_to raise_error end it 'they are no longer used by anything' do @@ -67,7 +67,7 @@ describe Photo do expect(photo.harvests.size).to eq 1 harvest.destroy # photo is now no longer used by anything - photo.reload + expect(photo.plantings.size).to eq 0 expect(photo.harvests.size).to eq 0 photo.destroy_if_unused diff --git a/spec/views/plantings/edit.html.haml_spec.rb b/spec/views/plantings/edit.html.haml_spec.rb index 6ec152b9b..4cc06fcdc 100644 --- a/spec/views/plantings/edit.html.haml_spec.rb +++ b/spec/views/plantings/edit.html.haml_spec.rb @@ -49,7 +49,7 @@ describe "plantings/edit" do it "chooses the right garden" do assert_select "select#planting_garden_id", - :html => /option value="#{@garden.id}" selected="selected"/ + :html => /option selected="selected" value="#{@garden.id}"/ end end diff --git a/spec/views/plantings/new.html.haml_spec.rb b/spec/views/plantings/new.html.haml_spec.rb index 0b05b5532..455b9a411 100644 --- a/spec/views/plantings/new.html.haml_spec.rb +++ b/spec/views/plantings/new.html.haml_spec.rb @@ -46,7 +46,7 @@ describe "plantings/new" do it "selects a garden given in a param" do assert_select "select#planting_garden_id", - :html => /option value="#{@garden_z.id}" selected="selected"/ + :html => /option selected="selected" value="#{@garden_z.id}"/ end end end From 98c1680138e4d1955910eb69a67fab67e607da69 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Mon, 17 Nov 2014 07:16:02 +1100 Subject: [PATCH 027/143] handle misc deprications --- config/environments/development.rb | 3 --- config/environments/test.rb | 3 --- vendor/plugins/.gitkeep | 0 3 files changed, 6 deletions(-) delete mode 100644 vendor/plugins/.gitkeep diff --git a/config/environments/development.rb b/config/environments/development.rb index 890d210a7..69872be10 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -8,9 +8,6 @@ Growstuff::Application.configure do # since you don't have to restart the web server when you make code changes. config.cache_classes = false - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = true - # Show full error reports and disable caching config.consider_all_requests_local = true diff --git a/config/environments/test.rb b/config/environments/test.rb index 237e4bef4..cabe327d4 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -15,9 +15,6 @@ Growstuff::Application.configure do config.serve_static_assets = true config.static_cache_control = "public, max-age=3600" - # Log error messages when you accidentally call methods on nil - config.whiny_nils = true - # Show full error reports and disable caching config.consider_all_requests_local = true config.action_controller.perform_caching = false diff --git a/vendor/plugins/.gitkeep b/vendor/plugins/.gitkeep deleted file mode 100644 index e69de29bb..000000000 From acbd3f9a9e372c8de759139de38028906cd8e3d4 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Tue, 18 Nov 2014 20:08:54 +1100 Subject: [PATCH 028/143] implement strong parameters instead of protected attributes --- Gemfile | 4 ++-- Gemfile.lock | 7 ++----- app/controllers/account_types_controller.rb | 10 ++++++++-- app/controllers/accounts_controller.rb | 8 +++++++- app/controllers/alternate_names_controller.rb | 10 ++++++++-- app/controllers/application_controller.rb | 12 +++++++++++- app/controllers/comments_controller.rb | 10 ++++++++-- app/controllers/crops_controller.rb | 10 ++++++++-- app/controllers/forums_controller.rb | 10 ++++++++-- app/controllers/gardens_controller.rb | 11 +++++++++-- app/controllers/harvests_controller.rb | 11 +++++++++-- app/controllers/notifications_controller.rb | 8 +++++++- app/controllers/order_items_controller.rb | 8 +++++++- app/controllers/photos_controller.rb | 11 +++++++++-- app/controllers/plant_parts_controller.rb | 10 ++++++++-- app/controllers/plantings_controller.rb | 18 ++++++++++++++---- app/controllers/posts_controller.rb | 10 ++++++++-- app/controllers/products_controller.rb | 11 +++++++++-- app/controllers/roles_controller.rb | 10 ++++++++-- app/controllers/scientific_names_controller.rb | 10 ++++++++-- app/controllers/seeds_controller.rb | 11 +++++++++-- app/models/account.rb | 1 - app/models/account_type.rb | 1 - app/models/alternate_name.rb | 1 - app/models/authentication.rb | 1 - app/models/comment.rb | 1 - app/models/crop.rb | 1 - app/models/forum.rb | 2 +- app/models/garden.rb | 3 --- app/models/harvest.rb | 3 --- app/models/member.rb | 10 ---------- app/models/notification.rb | 3 --- app/models/order.rb | 1 - app/models/order_item.rb | 2 -- app/models/photo.rb | 2 -- app/models/plant_part.rb | 2 -- app/models/planting.rb | 4 ---- app/models/post.rb | 1 - app/models/product.rb | 3 --- app/models/role.rb | 2 +- app/models/scientific_name.rb | 1 - app/models/seed.rb | 3 --- config/application.rb | 6 +++--- config/environments/development.rb | 4 +++- config/environments/test.rb | 2 +- spec/controllers/harvests_controller_spec.rb | 4 ++-- 46 files changed, 178 insertions(+), 96 deletions(-) diff --git a/Gemfile b/Gemfile index 2c5656312..6a26ea327 100644 --- a/Gemfile +++ b/Gemfile @@ -10,7 +10,7 @@ gem 'actionpack-xml_parser', '~>1.0.0' gem 'actionview-encoded_mail_to', '~>1.0.4' gem 'activerecord-session_store', '~>0.0.1' gem 'activeresource', '~>4.0.0.beta1' -gem 'protected_attributes', '~>1.0.1' +# gem 'protected_attributes', '~>1.0.1' gem 'rails-observers', '~>0.1.1' gem 'rails-perftest', '~>0.0.2' @@ -30,7 +30,7 @@ gem 'pg' gem 'figaro' # for handling config via ENV variables -gem 'cancan' # for checking member privileges +gem 'cancancan', '~> 1.9' # for checking member privileges gem 'gibbon' # for Mailchimp newsletter subscriptions diff --git a/Gemfile.lock b/Gemfile.lock index 2a90c791c..cbf90269d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -79,7 +79,7 @@ GEM columnize (~> 0.8) debugger-linecache (~> 1.2) slop (~> 3.6) - cancan (1.6.10) + cancancan (1.9.2) capybara (2.4.4) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -223,8 +223,6 @@ GEM cliver (~> 0.3.1) multi_json (~> 1.0) websocket-driver (>= 0.2.0) - protected_attributes (1.0.8) - activemodel (>= 4.0.1, < 5.0) pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) @@ -356,7 +354,7 @@ DEPENDENCIES bootstrap-datepicker-rails bundler (>= 1.1.5) byebug - cancan + cancancan (~> 1.9) capybara capybara-email coffee-rails (~> 4.1.0) @@ -392,7 +390,6 @@ DEPENDENCIES omniauth-twitter pg poltergeist (~> 1.5.1) - protected_attributes (~> 1.0.1) pry rails (= 4.1.7) rails-observers (~> 0.1.1) diff --git a/app/controllers/account_types_controller.rb b/app/controllers/account_types_controller.rb index 9095beb37..8bea1e144 100644 --- a/app/controllers/account_types_controller.rb +++ b/app/controllers/account_types_controller.rb @@ -34,7 +34,7 @@ class AccountTypesController < ApplicationController # POST /account_types def create - @account_type = AccountType.new(params[:account_type]) + @account_type = AccountType.new(account_type_params) respond_to do |format| if @account_type.save @@ -50,7 +50,7 @@ class AccountTypesController < ApplicationController @account_type = AccountType.find(params[:id]) respond_to do |format| - if @account_type.update_attributes(params[:account_type]) + if @account_type.update(account_type_params) format.html { redirect_to @account_type, notice: 'Account type was successfully updated.' } else format.html { render action: "edit" } @@ -67,4 +67,10 @@ class AccountTypesController < ApplicationController format.html { redirect_to account_types_url, notice: 'Account type was successfully deleted.' } end end + + private + + def account_type_params + params.require(:account_type).permit(:is_paid, :is_permanent_paid, :name) + end end diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 4ee11c36a..3c06ec0ab 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -28,7 +28,7 @@ class AccountsController < ApplicationController @account = Account.find(params[:id]) respond_to do |format| - if @account.update_attributes(params[:account]) + if @account.update(params[:account]) format.html { redirect_to @account, notice: 'Account detail was successfully updated.' } else format.html { render action: "edit" } @@ -36,4 +36,10 @@ class AccountsController < ApplicationController end end + private + + def account_params + params.require(:account).permit(:account_type_id, :member_id, :paid_until) + end + end diff --git a/app/controllers/alternate_names_controller.rb b/app/controllers/alternate_names_controller.rb index ea8a8f76c..8fdcffd65 100644 --- a/app/controllers/alternate_names_controller.rb +++ b/app/controllers/alternate_names_controller.rb @@ -44,7 +44,7 @@ class AlternateNamesController < ApplicationController # POST /alternate_names.json def create params[:alternate_name][:creator_id] = current_member.id - @alternate_name = AlternateName.new(params[:alternate_name]) + @alternate_name = AlternateName.new(alternate_name_params) respond_to do |format| if @alternate_name.save @@ -63,7 +63,7 @@ class AlternateNamesController < ApplicationController @alternate_name = AlternateName.find(params[:id]) respond_to do |format| - if @alternate_name.update_attributes(params[:alternate_name]) + if @alternate_name.update(alternate_name_params) format.html { redirect_to @alternate_name.crop, notice: 'Alternate name was successfully updated.' } format.json { head :no_content } else @@ -87,4 +87,10 @@ class AlternateNamesController < ApplicationController format.json { head :no_content } end end + + private + + def alternate_name_params + params.require(:alternate_name).permit(:crop_id, :name, :creator_id) + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 01166c2a4..305377882 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -48,7 +48,17 @@ class ApplicationController < ActionController::Base protected def configure_permitted_parameters - devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:login_name, :email, :password, :password_confirmation, :tos_agreement, :newsletter) } + devise_parameter_sanitizer.for(:sign_up) do |u| + u.permit(:login_name, :email, :password, :password_confirmation, + :remember_me, :login, + # terms of service + :tos_agreement, + # profile stuff + :bio, :location, :latitude, :longitude, + # email settings + :show_email, :newsletter, :send_notification_email, :send_planting_reminder + ) + end end end diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 543f120ae..750614bee 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -54,7 +54,7 @@ class CommentsController < ApplicationController # POST /comments.json def create params[:comment][:author_id] = current_member.id - @comment = Comment.new(params[:comment]) + @comment = Comment.new(comment_params) respond_to do |format| if @comment.save @@ -78,7 +78,7 @@ class CommentsController < ApplicationController params[:comment].delete("author_id") respond_to do |format| - if @comment.update_attributes(params[:comment]) + if @comment.update(comment_params) format.html { redirect_to @comment.post, notice: 'Comment was successfully updated.' } format.json { head :no_content } else @@ -100,4 +100,10 @@ class CommentsController < ApplicationController format.json { head :no_content } end end + + private + + def comment_params + params.require(:comment).permit(:author_id, :body, :post_id) + end end diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 95b42cd01..8bd238282 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -103,7 +103,7 @@ class CropsController < ApplicationController # POST /crops.json def create params[:crop][:creator_id] = current_member.id - @crop = Crop.new(params[:crop]) + @crop = Crop.new(crop_params) respond_to do |format| if @crop.save @@ -122,7 +122,7 @@ class CropsController < ApplicationController @crop = Crop.find(params[:id]) respond_to do |format| - if @crop.update_attributes(params[:crop]) + if @crop.update(crop_params) format.html { redirect_to @crop, notice: 'Crop was successfully updated.' } format.json { head :no_content } else @@ -143,4 +143,10 @@ class CropsController < ApplicationController format.json { head :no_content } end end + + private + + def crop_params + require(:crop).permit(:en_wikipedia_url, :name, :parent_id, :creator_id, :scientific_names_attributes) + end end diff --git a/app/controllers/forums_controller.rb b/app/controllers/forums_controller.rb index b77939111..845a4f43a 100644 --- a/app/controllers/forums_controller.rb +++ b/app/controllers/forums_controller.rb @@ -44,7 +44,7 @@ class ForumsController < ApplicationController # POST /forums # POST /forums.json def create - @forum = Forum.new(params[:forum]) + @forum = Forum.new(forum_params) respond_to do |format| if @forum.save @@ -63,7 +63,7 @@ class ForumsController < ApplicationController @forum = Forum.find(params[:id]) respond_to do |format| - if @forum.update_attributes(params[:forum]) + if @forum.update(forum_params) format.html { redirect_to @forum, notice: 'Forum was successfully updated.' } format.json { head :no_content } else @@ -84,4 +84,10 @@ class ForumsController < ApplicationController format.json { head :no_content } end end + + private + + def forum_params + params.require(:forum).permit(:description, :name, :owner_id, :slug) + end end diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index 570dcdfca..581cdc8dc 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -49,7 +49,7 @@ class GardensController < ApplicationController # POST /gardens.json def create params[:garden][:owner_id] = current_member.id - @garden = Garden.new(params[:garden]) + @garden = Garden.new(garden_params) respond_to do |format| if @garden.save @@ -68,7 +68,7 @@ class GardensController < ApplicationController @garden = Garden.find(params[:id]) respond_to do |format| - if @garden.update_attributes(params[:garden]) + if @garden.update(garden_params) format.html { redirect_to @garden, notice: 'Garden was successfully updated.' } format.json { head :no_content } else @@ -89,4 +89,11 @@ class GardensController < ApplicationController format.json { head :no_content } end end + + private + + def garden_params + params.require(:garden).permit(:name, :slug, :owner_id, :description, :active, + :location, :latitude, :longitude, :area, :area_unit) + end end diff --git a/app/controllers/harvests_controller.rb b/app/controllers/harvests_controller.rb index 524007d47..a35993015 100644 --- a/app/controllers/harvests_controller.rb +++ b/app/controllers/harvests_controller.rb @@ -61,7 +61,7 @@ class HarvestsController < ApplicationController def create params[:harvest][:owner_id] = current_member.id params[:harvested_at] = parse_date(params[:harvested_at]) - @harvest = Harvest.new(params[:harvest]) + @harvest = Harvest.new(harvest_params) respond_to do |format| if @harvest.save @@ -80,7 +80,7 @@ class HarvestsController < ApplicationController @harvest = Harvest.find(params[:id]) respond_to do |format| - if @harvest.update_attributes(params[:harvest]) + if @harvest.update(harvest_params) format.html { redirect_to @harvest, notice: 'Harvest was successfully updated.' } format.json { head :no_content } else @@ -101,4 +101,11 @@ class HarvestsController < ApplicationController format.json { head :no_content } end end + + private + + def harvest_params + params.require(:harvest).permit(:crop_id, :harvested_at, :description, :owner_id, + :quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug) + end end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 8844d2954..e79815b59 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -47,7 +47,7 @@ class NotificationsController < ApplicationController # POST /notifications def create params[:notification][:sender_id] = current_member.id - @notification = Notification.new(params[:notification]) + @notification = Notification.new(notification_params) @recipient = Member.find_by_id(params[:notification][:recipient_id]) respond_to do |format| @@ -58,4 +58,10 @@ class NotificationsController < ApplicationController end end end + + private + + def notification_params + params.require(:notification).permit(:sender_id, :recipient_id, :subject, :body, :post_id, :read) + end end diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index e9f4a2e11..c488119a6 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -6,7 +6,7 @@ class OrderItemsController < ApplicationController if params[:order_item][:price] params[:order_item][:price] = params[:order_item][:price].to_f * 100 # convert to cents end - @order_item = OrderItem.new(params[:order_item]) + @order_item = OrderItem.new(order_item_params) @order_item.order = current_member.current_order || Order.create(:member_id => current_member.id) respond_to do |format| @@ -19,4 +19,10 @@ class OrderItemsController < ApplicationController end end end + + private + + def order_item_params + params.require(:order_item).permit(:order_id, :price, :product_id, :quantity) + end end diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 45755db84..8e1243d4b 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -60,7 +60,7 @@ class PhotosController < ApplicationController # POST /photos.json def create @photo = Photo.find_by_flickr_photo_id(params[:photo][:flickr_photo_id]) || - Photo.new(params[:photo]) + Photo.new(photo_params) @photo.owner_id = current_member.id @photo.set_flickr_metadata @@ -110,7 +110,7 @@ class PhotosController < ApplicationController @photo = Photo.find(params[:id]) respond_to do |format| - if @photo.update_attributes(params[:photo]) + if @photo.update(photo_params) format.html { redirect_to @photo, notice: 'Photo was successfully updated.' } format.json { head :no_content } else @@ -131,4 +131,11 @@ class PhotosController < ApplicationController format.json { head :no_content } end end + + private + + def photo_params + params.require(:photo).permit(:flickr_photo_id, :owner_id, :title, :license_name, + :license_url, :thumbnail_url, :fullsize_url, :link_url) + end end diff --git a/app/controllers/plant_parts_controller.rb b/app/controllers/plant_parts_controller.rb index f27f0ead3..ed67926c7 100644 --- a/app/controllers/plant_parts_controller.rb +++ b/app/controllers/plant_parts_controller.rb @@ -42,7 +42,7 @@ class PlantPartsController < ApplicationController # POST /plant_parts # POST /plant_parts.json def create - @plant_part = PlantPart.new(params[:plant_part]) + @plant_part = PlantPart.new(plant_part_params) respond_to do |format| if @plant_part.save @@ -61,7 +61,7 @@ class PlantPartsController < ApplicationController @plant_part = PlantPart.find(params[:id]) respond_to do |format| - if @plant_part.update_attributes(params[:plant_part]) + if @plant_part.update(plant_part_params) format.html { redirect_to @plant_part, notice: 'Plant part was successfully updated.' } format.json { head :no_content } else @@ -82,4 +82,10 @@ class PlantPartsController < ApplicationController format.json { head :no_content } end end + + private + + def plant_part_params + params.require(:plant_part).permit(:name, :slug) + end end diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 83a10facd..ff3416623 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -66,9 +66,11 @@ class PlantingsController < ApplicationController # POST /plantings # POST /plantings.json def create - params[:planting][:owner_id] = current_member.id - params[:planted_at] = parse_date(params[:planted_at]) - @planting = Planting.new(params[:planting]) + # params[:planting][:owner_id] = current_member.id + # params[:planted_at] = parse_date(params[:planted_at]) + @planting = Planting.new(planting_params) + @planting.owner = current_member + @planting.planted_at = parse_date(params[:planted_at]) respond_to do |format| if @planting.save @@ -88,7 +90,7 @@ class PlantingsController < ApplicationController params[:planted_at] = parse_date(params[:planted_at]) respond_to do |format| - if @planting.update_attributes(params[:planting]) + if @planting.update(planting_params) format.html { redirect_to @planting, notice: 'Planting was successfully updated.' } format.json { head :no_content } else @@ -110,4 +112,12 @@ class PlantingsController < ApplicationController format.json { head :no_content } end end + + private + + def planting_params + params.require(:planting).permit(:crop_id, :description, :garden_id, :planted_at, + :quantity, :sunniness, :planted_from, :owner_id, :finished, + :finished_at) + end end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index b7167e9d2..0875716fb 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -57,7 +57,7 @@ class PostsController < ApplicationController # POST /posts.json def create params[:post][:author_id] = current_member.id - @post = Post.new(params[:post]) + @post = Post.new(post_params) respond_to do |format| if @post.save @@ -76,7 +76,7 @@ class PostsController < ApplicationController @post = Post.find(params[:id]) respond_to do |format| - if @post.update_attributes(params[:post]) + if @post.update(post_params) format.html { redirect_to @post, notice: 'Post was successfully updated.' } format.json { head :no_content } else @@ -97,4 +97,10 @@ class PostsController < ApplicationController format.json { head :no_content } end end + + private + + def post_params + params.require(:post).permit(:body, :subject, :author_id, :forum_id) + end end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 9e50b7311..07e8d67fe 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -34,7 +34,7 @@ class ProductsController < ApplicationController # POST /products def create - @product = Product.new(params[:product]) + @product = Product.new(product_params) respond_to do |format| if @product.save @@ -50,7 +50,7 @@ class ProductsController < ApplicationController @product = Product.find(params[:id]) respond_to do |format| - if @product.update_attributes(params[:product]) + if @product.update(product_params) format.html { redirect_to @product, notice: 'Product was successfully updated.' } else format.html { render action: "edit" } @@ -67,4 +67,11 @@ class ProductsController < ApplicationController format.html { redirect_to products_url } end end + + private + + def product_params + params.require(:product).permit(:description, :min_price, :recommended_price, :name, + :account_type_id, :paid_months) + end end diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 5763e949b..219420c05 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -34,7 +34,7 @@ class RolesController < ApplicationController # POST /roles def create - @role = Role.new(params[:role]) + @role = Role.new(role_params) respond_to do |format| if @role.save @@ -50,7 +50,7 @@ class RolesController < ApplicationController @role = Role.find(params[:id]) respond_to do |format| - if @role.update_attributes(params[:role]) + if @role.update(role_params) format.html { redirect_to @role, notice: 'Role was successfully updated.' } else format.html { render action: "edit" } @@ -67,4 +67,10 @@ class RolesController < ApplicationController format.html { redirect_to roles_url } end end + + private + + def role_params + params.require(:role).permit(:description, :name, :members, :slug) + end end diff --git a/app/controllers/scientific_names_controller.rb b/app/controllers/scientific_names_controller.rb index 3911a6618..cc6fac919 100644 --- a/app/controllers/scientific_names_controller.rb +++ b/app/controllers/scientific_names_controller.rb @@ -46,7 +46,7 @@ class ScientificNamesController < ApplicationController # POST /scientific_names.json def create params[:scientific_name][:creator_id] = current_member.id - @scientific_name = ScientificName.new(params[:scientific_name]) + @scientific_name = ScientificName.new(scientific_name_params) respond_to do |format| if @scientific_name.save @@ -65,7 +65,7 @@ class ScientificNamesController < ApplicationController @scientific_name = ScientificName.find(params[:id]) respond_to do |format| - if @scientific_name.update_attributes(params[:scientific_name]) + if @scientific_name.update(scientific_name_params) format.html { redirect_to @scientific_name.crop, notice: 'Scientific name was successfully updated.' } format.json { head :no_content } else @@ -89,4 +89,10 @@ class ScientificNamesController < ApplicationController format.json { head :no_content } end end + + private + + def scientific_name_params + params.require(:scientific_name).permit(:crop_id, :scientific_name, :creator_id) + end end diff --git a/app/controllers/seeds_controller.rb b/app/controllers/seeds_controller.rb index 03960624b..7b859498a 100644 --- a/app/controllers/seeds_controller.rb +++ b/app/controllers/seeds_controller.rb @@ -67,7 +67,7 @@ class SeedsController < ApplicationController # POST /seeds.json def create params[:seed][:owner_id] = current_member.id - @seed = Seed.new(params[:seed]) + @seed = Seed.new(seed_params) respond_to do |format| if @seed.save @@ -86,7 +86,7 @@ class SeedsController < ApplicationController @seed = Seed.find(params[:id]) respond_to do |format| - if @seed.update_attributes(params[:seed]) + if @seed.update(seed_params) format.html { redirect_to @seed, notice: 'Seed was successfully updated.' } format.json { head :no_content } else @@ -107,4 +107,11 @@ class SeedsController < ApplicationController format.json { head :no_content } end end + + private + + def seed_params + params.require(:seed).permit(:owner_id, :crop_id, :description, :quantity, :plant_before, + :tradable_to, :slug) + end end diff --git a/app/models/account.rb b/app/models/account.rb index 7da4b1d98..547fc57bf 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -1,5 +1,4 @@ class Account < ActiveRecord::Base - attr_accessible :account_type_id, :member_id, :paid_until belongs_to :member belongs_to :account_type diff --git a/app/models/account_type.rb b/app/models/account_type.rb index dc464707b..d6be51a94 100644 --- a/app/models/account_type.rb +++ b/app/models/account_type.rb @@ -1,5 +1,4 @@ class AccountType < ActiveRecord::Base - attr_accessible :is_paid, :is_permanent_paid, :name has_many :products def to_s diff --git a/app/models/alternate_name.rb b/app/models/alternate_name.rb index fb92a2bc9..408740680 100644 --- a/app/models/alternate_name.rb +++ b/app/models/alternate_name.rb @@ -1,5 +1,4 @@ class AlternateName < ActiveRecord::Base - attr_accessible :crop_id, :name, :creator_id belongs_to :crop belongs_to :creator, :class_name => 'Member' end diff --git a/app/models/authentication.rb b/app/models/authentication.rb index 325bffe40..e6171c8b7 100644 --- a/app/models/authentication.rb +++ b/app/models/authentication.rb @@ -1,4 +1,3 @@ class Authentication < ActiveRecord::Base belongs_to :member - attr_accessible :provider, :uid, :token, :secret, :name end diff --git a/app/models/comment.rb b/app/models/comment.rb index 76a4d25f4..f7da18842 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,5 +1,4 @@ class Comment < ActiveRecord::Base - attr_accessible :author_id, :body, :post_id belongs_to :author, :class_name => 'Member' belongs_to :post diff --git a/app/models/crop.rb b/app/models/crop.rb index 3f5e5e9e7..7e36e9f51 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -1,7 +1,6 @@ class Crop < ActiveRecord::Base extend FriendlyId friendly_id :name, use: [:slugged, :finders] - attr_accessible :en_wikipedia_url, :name, :parent_id, :creator_id, :scientific_names_attributes has_many :scientific_names accepts_nested_attributes_for :scientific_names, diff --git a/app/models/forum.rb b/app/models/forum.rb index f671a97c0..fd4a79509 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -1,7 +1,7 @@ class Forum < ActiveRecord::Base extend FriendlyId friendly_id :name, use: [:slugged, :finders] - attr_accessible :description, :name, :owner_id, :slug + has_many :posts belongs_to :owner, :class_name => "Member" diff --git a/app/models/garden.rb b/app/models/garden.rb index eb7d2e1b2..9741b80af 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -3,9 +3,6 @@ class Garden < ActiveRecord::Base extend FriendlyId friendly_id :garden_slug, use: [:slugged, :finders] - attr_accessible :name, :slug, :owner_id, :description, :active, - :location, :latitude, :longitude, :area, :area_unit - belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id' has_many :plantings, -> { order(created_at: :desc) }, :dependent => :destroy has_many :crops, :through => :plantings diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 76d5a30ec..4e43c6ee7 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -3,9 +3,6 @@ class Harvest < ActiveRecord::Base extend FriendlyId friendly_id :harvest_slug, use: [:slugged, :finders] - attr_accessible :crop_id, :harvested_at, :description, :owner_id, - :quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug - belongs_to :crop belongs_to :owner, :class_name => 'Member' belongs_to :plant_part diff --git a/app/models/member.rb b/app/models/member.rb index d177174c5..24218dd17 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -40,16 +40,6 @@ class Member < ActiveRecord::Base :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :timeoutable - # Setup accessible (or protected) attributes for your model - attr_accessible :login_name, :email, :password, :password_confirmation, - :remember_me, :login, - # terms of service - :tos_agreement, - # profile stuff - :bio, :location, :latitude, :longitude, - # email settings - :show_email, :newsletter, :send_notification_email, :send_planting_reminder - # set up geocoding geocoded_by :location after_validation :geocode diff --git a/app/models/notification.rb b/app/models/notification.rb index 4568d6975..304b86b03 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -1,7 +1,4 @@ class Notification < ActiveRecord::Base - attr_accessible :sender_id, :recipient_id, - :subject, :body, :post_id, :read - belongs_to :sender, :class_name => 'Member' belongs_to :recipient, :class_name => 'Member' belongs_to :post diff --git a/app/models/order.rb b/app/models/order.rb index 68fcd80ac..e9f97034f 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,5 +1,4 @@ class Order < ActiveRecord::Base - attr_accessible :member_id, :completed_at, :referral_code belongs_to :member has_many :order_items, :dependent => :destroy diff --git a/app/models/order_item.rb b/app/models/order_item.rb index 3a06097d1..159876dd5 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -1,6 +1,4 @@ class OrderItem < ActiveRecord::Base - attr_accessible :order_id, :price, :product_id, :quantity - belongs_to :order belongs_to :product diff --git a/app/models/photo.rb b/app/models/photo.rb index 995fecc71..9ab411d09 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -1,6 +1,4 @@ class Photo < ActiveRecord::Base - attr_accessible :flickr_photo_id, :owner_id, :title, :license_name, - :license_url, :thumbnail_url, :fullsize_url, :link_url belongs_to :owner, :class_name => 'Member' has_and_belongs_to_many :plantings diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index 648ddd290..33d2292fa 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -5,8 +5,6 @@ class PlantPart < ActiveRecord::Base has_many :harvests has_many :crops, -> { uniq }, :through => :harvests - attr_accessible :name, :slug - def to_s return name end diff --git a/app/models/planting.rb b/app/models/planting.rb index b853cb256..e9c11368b 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -2,10 +2,6 @@ class Planting < ActiveRecord::Base extend FriendlyId friendly_id :planting_slug, use: [:slugged, :finders] - attr_accessible :crop_id, :description, :garden_id, :planted_at, - :quantity, :sunniness, :planted_from, :owner_id, :finished, - :finished_at - belongs_to :garden belongs_to :owner, :class_name => 'Member', :counter_cache => true belongs_to :crop, :counter_cache => true diff --git a/app/models/post.rb b/app/models/post.rb index 7f49ebc2c..88c6355cc 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,7 +1,6 @@ class Post < ActiveRecord::Base extend FriendlyId friendly_id :author_date_subject, use: [:slugged, :finders] - attr_accessible :body, :subject, :author_id, :forum_id belongs_to :author, :class_name => 'Member' belongs_to :forum has_many :comments, :dependent => :destroy diff --git a/app/models/product.rb b/app/models/product.rb index 70193ea7a..876207f47 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,7 +1,4 @@ class Product < ActiveRecord::Base - attr_accessible :description, :min_price, :recommended_price, :name, - :account_type_id, :paid_months - has_and_belongs_to_many :orders belongs_to :account_type diff --git a/app/models/role.rb b/app/models/role.rb index cf002d22d..a3364fb89 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,7 +1,7 @@ class Role < ActiveRecord::Base extend FriendlyId friendly_id :name, use: [:slugged, :finders] - attr_accessible :description, :name, :members, :slug + has_and_belongs_to_many :members class << self diff --git a/app/models/scientific_name.rb b/app/models/scientific_name.rb index 56c86b21b..1a585e713 100644 --- a/app/models/scientific_name.rb +++ b/app/models/scientific_name.rb @@ -1,5 +1,4 @@ class ScientificName < ActiveRecord::Base - attr_accessible :crop_id, :scientific_name, :creator_id belongs_to :crop belongs_to :creator, :class_name => 'Member' end diff --git a/app/models/seed.rb b/app/models/seed.rb index ff2538218..c7128da72 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -2,9 +2,6 @@ class Seed < ActiveRecord::Base extend FriendlyId friendly_id :seed_slug, use: [:slugged, :finders] - attr_accessible :owner_id, :crop_id, :description, :quantity, :plant_before, - :tradable_to, :slug - belongs_to :crop belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id' diff --git a/config/application.rb b/config/application.rb index 116696f51..d9b29247c 100644 --- a/config/application.rb +++ b/config/application.rb @@ -31,6 +31,8 @@ module Growstuff config.time_zone = 'UTC' config.active_record.default_timezone = :local + config.i18n.enforce_available_locales = true + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}')] I18n.default_locale = :en @@ -39,8 +41,6 @@ module Growstuff # rails will fallback to en, no matter what is set as config.i18n.default_locale config.i18n.fallbacks = [:en] - config.i18n.enforce_available_locales = true - # Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8" @@ -62,7 +62,7 @@ module Growstuff # This will create an empty whitelist of attributes available for mass-assignment for all models # in your app. As such, your models will need to explicitly whitelist or blacklist accessible # parameters by using an attr_accessible or attr_protected declaration. - config.active_record.whitelist_attributes = true + # config.active_record.whitelist_attributes = true # Enable the asset pipeline config.assets.enabled = true diff --git a/config/environments/development.rb b/config/environments/development.rb index 69872be10..ba15889c5 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -25,7 +25,7 @@ Growstuff::Application.configure do config.action_dispatch.best_standards_support = :builtin # Raise exception on mass assignment protection for Active Record models - config.active_record.mass_assignment_sanitizer = :strict + # config.active_record.mass_assignment_sanitizer = :strict # Do not compress assets config.assets.compress = false @@ -63,4 +63,6 @@ Growstuff::Application.configure do ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options) ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options) end + + config.action_controller.action_on_unpermitted_parameters = :raise end diff --git a/config/environments/test.rb b/config/environments/test.rb index cabe327d4..0ac2b3ba7 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -31,7 +31,7 @@ Growstuff::Application.configure do config.action_mailer.delivery_method = :test # Raise exception on mass assignment protection for Active Record models - config.active_record.mass_assignment_sanitizer = :strict + # config.active_record.mass_assignment_sanitizer = :strict # Print deprecation notices to the stderr config.active_support.deprecation = :stderr diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb index 9ced0cece..efbaf4697 100644 --- a/spec/controllers/harvests_controller_spec.rb +++ b/spec/controllers/harvests_controller_spec.rb @@ -105,9 +105,9 @@ describe HarvestsController do harvest = Harvest.create! valid_attributes # Assuming there are no other harvests in the database, this # specifies that the Harvest created on the previous line - # receives the :update_attributes message with whatever params are + # receives the :update message with whatever params are # submitted in the request. - Harvest.any_instance.should_receive(:update_attributes).with({ "crop_id" => "1" }) + Harvest.any_instance.should_receive(:update).with({ "crop_id" => "1" }) put :update, {:id => harvest.to_param, :harvest => { "crop_id" => "1" }} end From fb595de457788e84b2587e54d9b1d2f68fcffac9 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Tue, 18 Nov 2014 22:24:58 +1100 Subject: [PATCH 029/143] edited configuration and dependencies --- Gemfile | 144 +++++++++++------------------ Gemfile.lock | 37 +------- config/application.rb | 4 +- config/environments/development.rb | 16 +++- config/environments/production.rb | 27 +++--- config/environments/staging.rb | 27 +++--- config/environments/test.rb | 9 +- spec/rails_helper.rb | 1 - spec/spec_helper.rb | 2 + 9 files changed, 110 insertions(+), 157 deletions(-) diff --git a/Gemfile b/Gemfile index 6a26ea327..5701d9bbc 100644 --- a/Gemfile +++ b/Gemfile @@ -1,103 +1,54 @@ source 'https://rubygems.org' -ruby "2.1.2" +ruby '2.1.2' + +gem 'rails', '4.1.7' -# gems for Rails 4 upgrade -gem 'rails4_upgrade' -gem 'actionpack-action_caching', '~>1.0.0' -gem 'actionpack-page_caching', '~>1.0.0' -gem 'actionpack-xml_parser', '~>1.0.0' -gem 'actionview-encoded_mail_to', '~>1.0.4' -gem 'activerecord-session_store', '~>0.0.1' -gem 'activeresource', '~>4.0.0.beta1' -# gem 'protected_attributes', '~>1.0.1' gem 'rails-observers', '~>0.1.1' -gem 'rails-perftest', '~>0.0.2' - -gem 'byebug' gem 'bundler', '>=1.1.5' -gem 'rails', '4.1.7' -# gem 'rack', '~>1.4.5' -# gem 'json', '~>1.7.7' -gem 'haml' -gem 'leaflet-rails' -gem 'leaflet-markercluster-rails' -gem 'unicorn' # http server - -gem 'pg' - -gem 'figaro' # for handling config via ENV variables - -gem 'cancancan', '~> 1.9' # for checking member privileges - -gem 'gibbon' # for Mailchimp newsletter subscriptions - -gem 'csv_shaper' # CSV export - -# vendored activemerchant for testing- needed for bogus paypal -# gateway monkeypatch -gem 'activemerchant', '1.33.0', - :path => 'vendor/gems/activemerchant-1.33.0', - :require => 'active_merchant' -gem 'active_utils', '1.0.5', - :path => 'vendor/gems/active_utils-1.0.5' - -group :production, :staging do - gem 'newrelic_rpm' - gem 'dalli' - gem 'memcachier' - gem 'rails_12factor' # supresses heroku plugin injection -end - -# CSS preprocessor, used for app/assets/stylesheets/application.css gem 'sass-rails', '~> 4.0.4' -# CoffeeScript is a Python-like language that compiles to JavaScript gem 'coffee-rails', '~> 4.1.0' - -# less-rails depends on a JavaScript engine; we use therubyracer. -# See https://github.com/sstephenson/execjs#readme for more supported runtimes -# long term, we'll probably want node.js for performance, but this will do -# for now as it's easier for new people to install -gem "therubyracer", "~> 0.12", :platforms => :ruby -# libv8 is needed by therubyracer and is a bit finicky -gem 'libv8', '3.16.14.3' +gem 'haml' # Another CSS preprocessor, used for Bootstrap overrides -gem "less", '~>2.5.0' -gem "less-rails", '~> 2.5.0' +gem 'less', '~>2.5.0' +gem 'less-rails', '~> 2.5.0' # CSS framework -gem "less-rails-bootstrap", '~> 3.2.0' +gem 'less-rails-bootstrap', '~> 3.2.0' -gem 'uglifier', '~> 2.5.3' # JavaScript compressor - -# gem 'compass-rails', '~> 1.0.3' # Yet Another CSS framework +gem 'uglifier', '~> 2.5.3' # JavaScript compressor gem 'jquery-rails' gem 'jquery-ui-rails', '~> 5.0.2' gem 'js-routes' # provides access to Rails routes in Javascript gem 'flickraw' -# To use ActiveModel has_secure_password -# gem 'bcrypt-ruby', '~> 3.0.0' +gem 'leaflet-rails' +gem 'leaflet-markercluster-rails' +gem 'unicorn' # http server +gem 'pg' +gem 'figaro' # for handling config via ENV variables +gem 'cancancan', '~> 1.9' # for checking member privileges +gem 'gibbon' # for Mailchimp newsletter subscriptions +gem 'csv_shaper' # CSV export -# To use Jbuilder templates for JSON -# gem 'jbuilder' +# vendored activemerchant for testing- needed for bogus paypal +# gateway monkeypatch +gem 'activemerchant', '1.33.0', + :path => 'vendor/gems/activemerchant-1.33.0', + :require => 'active_merchant' +gem 'active_utils', '1.0.5', + :path => 'vendor/gems/active_utils-1.0.5' -# Use unicorn as the app server -# gem 'unicorn' - -# To use debugger -group :development do - # A debugger and irb alternative. Pry doesn't play nice - # with unicorn, so start a Webrick server when debugging - # with Pry - gem 'pry' - gem 'better_errors' - gem 'binding_of_caller' - gem 'letter_opener' -end +# less-rails depends on a JavaScript engine; we use therubyracer. +# See https://github.com/sstephenson/execjs#readme for more supported runtimes +# long term, we'll probably want node.js for performance, but this will do +# for now as it's easier for new people to install +gem 'therubyracer', '~> 0.12', :platforms => :ruby +# libv8 is needed by therubyracer and is a bit finicky +gem 'libv8', '3.16.14.3' # Markdown formatting for updates etc gem 'bluecloth' @@ -129,16 +80,33 @@ gem 'omniauth-flickr', '>= 0.0.15' gem 'rake', '>= 10.0.0' +group :production, :staging do + gem 'newrelic_rpm' + gem 'dalli' + gem 'memcachier' + gem 'rails_12factor' # supresses heroku plugin injection +end + +group :development do + # A debugger and irb alternative. Pry doesn't play nice + # with unicorn, so start a Webrick server when debugging + # with Pry + gem 'pry' + gem 'better_errors' + gem 'binding_of_caller' + gem 'letter_opener' +end + group :development, :test do - gem 'haml-rails' # HTML templating language - gem 'rspec-rails', '~> 3.1.0' # unit testing framework + gem 'haml-rails' # HTML templating language + gem 'rspec-rails', '~> 3.1.0' # unit testing framework gem 'rspec-activemodel-mocks' gem 'database_cleaner', '~> 1.3.0' - gem 'webrat' # provides HTML matchers for view tests - gem 'factory_girl_rails', '~> 4.5.0' # for creating test data - gem 'coveralls', require: false # coverage analysis - gem 'capybara' # integration tests - gem 'capybara-email' # integration tests for email - gem 'poltergeist', '~> 1.5.1' # for headless JS testing - gem 'i18n-tasks' # adds tests for finding missing and unused translations + gem 'webrat' # provides HTML matchers for view tests + gem 'factory_girl_rails', '~> 4.5.0' # for creating test data + gem 'coveralls', require: false # coverage analysis + gem 'capybara' # integration tests + gem 'capybara-email' # integration tests for email + gem 'poltergeist', '~> 1.5.1' # for headless JS testing + gem 'i18n-tasks' # adds tests for finding missing and unused translations end diff --git a/Gemfile.lock b/Gemfile.lock index cbf90269d..cd1ae9ba1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -29,18 +29,10 @@ GEM activesupport (= 4.1.7) rack (~> 1.5.2) rack-test (~> 0.6.2) - actionpack-action_caching (1.0.0) - actionpack (>= 4.0.0.beta, < 5.0) - actionpack-page_caching (1.0.2) - actionpack (>= 4.0.0, < 5) - actionpack-xml_parser (1.0.1) - actionpack (>= 4.0.0.rc1) actionview (4.1.7) activesupport (= 4.1.7) builder (~> 3.1) erubis (~> 2.7.0) - actionview-encoded_mail_to (1.0.5) - rails activemodel (4.1.7) activesupport (= 4.1.7) builder (~> 3.1) @@ -48,14 +40,6 @@ GEM activemodel (= 4.1.7) activesupport (= 4.1.7) arel (~> 5.0.0) - activerecord-session_store (0.0.1) - actionpack (>= 4.0.0.beta, < 5) - activerecord (>= 4.0.0.beta, < 5) - railties (>= 4.0.0.beta, < 5) - activeresource (4.0.0.beta1) - activemodel (>= 4.0.0.beta1) - activesupport (>= 4.0.0.beta1) - rails-observers (~> 0.1.1) activesupport (4.1.7) i18n (~> 0.6, >= 0.6.9) json (~> 1.7, >= 1.7.7) @@ -75,10 +59,6 @@ GEM bootstrap-datepicker-rails (1.3.0.2) railties (>= 3.0) builder (3.2.2) - byebug (3.5.1) - columnize (~> 0.8) - debugger-linecache (~> 1.2) - slop (~> 3.6) cancancan (1.9.2) capybara (2.4.4) mime-types (>= 1.16) @@ -98,7 +78,6 @@ GEM coffee-script-source execjs coffee-script-source (1.8.0) - columnize (0.8.9) commonjs (0.2.7) coveralls (0.7.1) multi_json (~> 1.3) @@ -111,7 +90,6 @@ GEM dalli (2.7.2) database_cleaner (1.3.0) debug_inspector (0.0.2) - debugger-linecache (1.2.0) devise (3.4.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -201,7 +179,7 @@ GEM multi_json (1.10.1) multi_xml (0.5.5) netrc (0.8.0) - newrelic_rpm (3.9.6.257) + newrelic_rpm (3.9.7.266) nokogiri (1.6.4.1) mini_portile (~> 0.6.0) oauth (0.4.7) @@ -242,10 +220,6 @@ GEM sprockets-rails (~> 2.0) rails-observers (0.1.2) activemodel (~> 4.0) - rails-perftest (0.0.5) - rails4_upgrade (0.5.0) - bundler (>= 1.2.2) - terminal-table (>= 1.4.5) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging @@ -340,20 +314,13 @@ PLATFORMS ruby DEPENDENCIES - actionpack-action_caching (~> 1.0.0) - actionpack-page_caching (~> 1.0.0) - actionpack-xml_parser (~> 1.0.0) - actionview-encoded_mail_to (~> 1.0.4) active_utils (= 1.0.5)! activemerchant (= 1.33.0)! - activerecord-session_store (~> 0.0.1) - activeresource (~> 4.0.0.beta1) better_errors binding_of_caller bluecloth bootstrap-datepicker-rails bundler (>= 1.1.5) - byebug cancancan (~> 1.9) capybara capybara-email @@ -393,8 +360,6 @@ DEPENDENCIES pry rails (= 4.1.7) rails-observers (~> 0.1.1) - rails-perftest (~> 0.0.2) - rails4_upgrade rails_12factor rake (>= 10.0.0) rspec-activemodel-mocks diff --git a/config/application.rb b/config/application.rb index d9b29247c..113d0bc66 100644 --- a/config/application.rb +++ b/config/application.rb @@ -26,13 +26,13 @@ module Growstuff # Activate observers that should always be running. # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + I18n.config.enforce_available_locales = true + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. config.time_zone = 'UTC' config.active_record.default_timezone = :local - config.i18n.enforce_available_locales = true - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}')] I18n.default_locale = :en diff --git a/config/environments/development.rb b/config/environments/development.rb index ba15889c5..45d7b96bf 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,6 +1,7 @@ Growstuff::Application.configure do # Settings specified here will take precedence over those in config/application.rb + # Do not eager load code on boot. config.eager_load = false # In the development environment your application's code is reloaded on @@ -24,15 +25,24 @@ Growstuff::Application.configure do # Only use best-standards-support built into browsers config.action_dispatch.best_standards_support = :builtin - # Raise exception on mass assignment protection for Active Record models - # config.active_record.mass_assignment_sanitizer = :strict - # Do not compress assets config.assets.compress = false # Expands the lines which load the assets config.assets.debug = true + # Asset digests allow you to set far-future HTTP expiration dates on all assets, + # yet still be able to expire them through the digest params. + config.assets.digest = true + + # Adds additional error checking when serving assets at runtime. + # Checks for improperly declared sprockets dependencies. + # Raises helpful error messages. + config.assets.raise_runtime_errors = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + # Growstuff config config.new_crops_request_link = "http://example.com/not-a-real-url" config.action_mailer.default_url_options = { :host => 'localhost:8080' } diff --git a/config/environments/production.rb b/config/environments/production.rb index e2b6d5735..523418b32 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,6 +1,10 @@ Growstuff::Application.configure do # Settings specified here will take precedence over those in config/application.rb + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. config.eager_load = true # Code is not reloaded between requests @@ -13,8 +17,9 @@ Growstuff::Application.configure do # Disable Rails's static asset server (Apache or nginx will already do this) config.serve_static_assets = false - # Compress JavaScripts and CSS - config.assets.compress = true + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + config.assets.css_compressor = :sass # Don't fallback to assets pipeline if a precompiled asset is missed config.assets.compile = true @@ -22,9 +27,6 @@ Growstuff::Application.configure do # Generate digests for assets URLs config.assets.digest = true - # Defaults to nil and saved in location specified by config.assets.prefix - # config.assets.manifest = YOUR_PATH - # Specifies the header that your server uses for sending files # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx @@ -47,15 +49,10 @@ Growstuff::Application.configure do # Enable serving of images, stylesheets, and JavaScripts from an asset server # config.action_controller.asset_host = "http://assets.example.com" - # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) - # config.assets.precompile += %w( search.js ) - - # Disable delivery errors, bad email addresses will be ignored + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false - # Enable threaded mode - # config.threadsafe! - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) config.i18n.fallbacks = true @@ -63,6 +60,12 @@ Growstuff::Application.configure do # Send deprecation notices to registered listeners config.active_support.deprecation = :notify + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false + # Growstuff configuration config.new_crops_request_link = "http://growstuff.org/posts/skud-20130319-requests-for-new-crops" config.action_mailer.default_url_options = { :host => 'growstuff.org' } diff --git a/config/environments/staging.rb b/config/environments/staging.rb index fda2929ef..a40a82dfd 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -1,6 +1,10 @@ Growstuff::Application.configure do # Settings specified here will take precedence over those in config/application.rb + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. config.eager_load = true # Code is not reloaded between requests @@ -13,8 +17,9 @@ Growstuff::Application.configure do # Disable Rails's static asset server (Apache or nginx will already do this) config.serve_static_assets = false - # Compress JavaScripts and CSS - config.assets.compress = true + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + config.assets.css_compressor = :sass # Don't fallback to assets pipeline if a precompiled asset is missed config.assets.compile = true @@ -22,9 +27,6 @@ Growstuff::Application.configure do # Generate digests for assets URLs config.assets.digest = true - # Defaults to nil and saved in location specified by config.assets.prefix - # config.assets.manifest = YOUR_PATH - # Specifies the header that your server uses for sending files # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx @@ -47,15 +49,10 @@ Growstuff::Application.configure do # Enable serving of images, stylesheets, and JavaScripts from an asset server # config.action_controller.asset_host = "http://assets.example.com" - # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) - # config.assets.precompile += %w( search.js ) - - # Disable delivery errors, bad email addresses will be ignored + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false - # Enable threaded mode - # config.threadsafe! - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) config.i18n.fallbacks = true @@ -63,6 +60,12 @@ Growstuff::Application.configure do # Send deprecation notices to registered listeners config.active_support.deprecation = :notify + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false + # Growstuff configuration config.new_crops_request_link = "http://example.com/not-a-real-url" config.action_mailer.default_url_options = { :host => 'dev.growstuff.org' } diff --git a/config/environments/test.rb b/config/environments/test.rb index 0ac2b3ba7..ffdc4c972 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,6 +1,9 @@ Growstuff::Application.configure do # Settings specified here will take precedence over those in config/application.rb + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. config.eager_load = false # The test environment is used exclusively to run your application's @@ -30,12 +33,12 @@ Growstuff::Application.configure do # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test - # Raise exception on mass assignment protection for Active Record models - # config.active_record.mass_assignment_sanitizer = :strict - # Print deprecation notices to the stderr config.active_support.deprecation = :stderr + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + # Growstuff config config.new_crops_request_link = "http://example.com/not-a-real-url" config.action_mailer.default_url_options = { :host => 'localhost:8080' } diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 24be064ae..8080d4651 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -4,7 +4,6 @@ require 'spec_helper' require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' # Add additional requires below this line. Rails is not loaded until this point! -require 'rspec/autorun' require 'simplecov' require 'coveralls' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7b09b0a2d..191e049ee 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,6 +26,7 @@ RSpec.configure do |config| # # => "be bigger than 2 and smaller than 4" # ...rather than: # # => "be bigger than 2" + expectations.syntax = [:should, :expect] expectations.include_chain_clauses_in_custom_matcher_descriptions = true end @@ -36,6 +37,7 @@ RSpec.configure do |config| # a real object. This is generally recommended, and will default to # `true` in RSpec 4. mocks.verify_partial_doubles = false + mocks.syntax = [:should, :expect] end # The settings below are suggested to provide a good initial experience From 0eb5ae58aa44f46f2af9e90efdc1657e91ec9650 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Thu, 20 Nov 2014 00:42:46 +1100 Subject: [PATCH 030/143] Renamed member_id column in Follow table to follower_id. Made necessary modifications to models and tests. --- app/models/follow.rb | 12 ++++++------ app/models/member.rb | 4 ++-- ...130555_change_follows_member_id_to_follower_id.rb | 5 +++++ db/schema.rb | 4 ++-- spec/factories/follows.rb | 2 +- spec/models/follow_spec.rb | 2 +- 6 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 db/migrate/20141119130555_change_follows_member_id_to_follower_id.rb diff --git a/app/models/follow.rb b/app/models/follow.rb index e312efc90..b1b011c41 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -1,15 +1,15 @@ class Follow < ActiveRecord::Base - attr_accessible :followed_id, :member_id - belongs_to :member + attr_accessible :followed_id, :follower_id + belongs_to :follower, class_name: "Member" belongs_to :followed, class_name: "Member" - validates :member_id, uniqueness: { :scope => :followed_id } + validates :follower_id, uniqueness: { :scope => :followed_id } after_create do Notification.create( :recipient_id => self.followed_id, - :sender_id => self.member_id, - :subject => "#{self.member.login_name} has followed you", - :body => "#{self.member.login_name} has followed you" + :sender_id => self.follower_id, + :subject => "#{self.follower.login_name} has followed you", + :body => "#{self.follower.login_name} has followed you" ) end diff --git a/app/models/member.rb b/app/models/member.rb index 22749491b..c34c2f558 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -27,11 +27,11 @@ class Member < ActiveRecord::Base has_many :photos - has_many :follows + has_many :follows, :class_name => "Follow", :foreign_key => "follower_id" has_many :followed, :through => :follows has_many :inverse_follows, :class_name => "Follow", :foreign_key => "followed_id" - has_many :followers, :through => :inverse_follows, :source => :member + has_many :followers, :through => :inverse_follows, :source => :follower default_scope order("lower(login_name) asc") scope :confirmed, where('confirmed_at IS NOT NULL') diff --git a/db/migrate/20141119130555_change_follows_member_id_to_follower_id.rb b/db/migrate/20141119130555_change_follows_member_id_to_follower_id.rb new file mode 100644 index 000000000..1ac6af7f2 --- /dev/null +++ b/db/migrate/20141119130555_change_follows_member_id_to_follower_id.rb @@ -0,0 +1,5 @@ +class ChangeFollowsMemberIdToFollowerId < ActiveRecord::Migration + def change + rename_column :follows, :member_id, :follower_id + end +end diff --git a/db/schema.rb b/db/schema.rb index e22a2289b..c3a45bf0c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20141111130849) do +ActiveRecord::Schema.define(:version => 20141119130555) do create_table "account_types", :force => true do |t| t.string "name", :null => false @@ -81,7 +81,7 @@ ActiveRecord::Schema.define(:version => 20141111130849) do add_index "crops_posts", ["crop_id"], :name => "index_crops_posts_on_crop_id" create_table "follows", :force => true do |t| - t.integer "member_id" + t.integer "follower_id" t.integer "followed_id" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false diff --git a/spec/factories/follows.rb b/spec/factories/follows.rb index 711402374..d9bd13616 100644 --- a/spec/factories/follows.rb +++ b/spec/factories/follows.rb @@ -1,6 +1,6 @@ FactoryGirl.define do factory :follow do - member_id 1 + follower_id 1 followed_id 2 end diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb index f9302c9d3..c1beb68c5 100644 --- a/spec/models/follow_spec.rb +++ b/spec/models/follow_spec.rb @@ -10,7 +10,7 @@ describe Follow do it "sends a notification when a follow is created" do expect { - Follow.create(:member_id => @member1.id, :followed_id => @member2.id) + Follow.create(:follower_id => @member1.id, :followed_id => @member2.id) }.to change(Notification, :count).by(1) end end From 996043d8fbca7b9dd46e61bd75633cc1a77b9c3d Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Thu, 20 Nov 2014 01:04:35 +1100 Subject: [PATCH 031/143] Renamed get_follow_id to get_follow as it does not return id. Also added unit tests for the new methods in the member model. --- app/models/member.rb | 2 +- app/views/members/show.html.haml | 2 +- spec/features/member_profile_spec.rb | 2 +- spec/models/member_spec.rb | 26 ++++++++++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index c34c2f558..63682bcdf 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -265,7 +265,7 @@ class Member < ActiveRecord::Base self.follows.exists?(:followed_id => member.id) end - def get_follow_id(member) + def get_follow(member) self.follows.where(:followed_id => member.id).first if already_following?(member) end diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index 71152ac52..e7c0bc93d 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -10,7 +10,7 @@ - if member_signed_in? && current_member != @member && !current_member.already_following?(@member) = link_to 'Follow', follows_path(:followed_id => @member.id), :method => :post, :class => 'btn btn-default' - if member_signed_in? && current_member.already_following?(@member) - - follow = current_member.get_follow_id(@member) + - follow = current_member.get_follow(@member) = link_to 'Unfollow', follow_path(follow), :method => :delete, :class => 'btn btn-default' - content_for :member_rss_login_name, @member.login_name - content_for :member_rss_slug, @member.slug diff --git a/spec/features/member_profile_spec.rb b/spec/features/member_profile_spec.rb index 1520b215e..b2efe71d3 100644 --- a/spec/features/member_profile_spec.rb +++ b/spec/features/member_profile_spec.rb @@ -151,7 +151,7 @@ feature "member profile" do scenario "following and unfollowing" do click_link 'Follow' expect(page).to have_content "Followed #{other_member.login_name}" - expect(page).to have_link "Unfollow", :href => follow_path(member.get_follow_id(other_member)) + expect(page).to have_link "Unfollow", :href => follow_path(member.get_follow(other_member)) visit member_follows_path(member) expect(page).to have_content "#{other_member.login_name}" diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 49b66ef71..dbffaf941 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -381,4 +381,30 @@ describe 'member' do end end + context 'member who followed another member' do + before(:each) do + @member1 = FactoryGirl.create(:member) + @member2 = FactoryGirl.create(:member) + @member3 = FactoryGirl.create(:member) + @follow = @member1.follows.create(:follower_id => @member1.id, :followed_id => @member2.id) + end + + it 'detects that member is already following a member' do + expect(@member1.already_following?(@member2)).to eq true + end + + it 'detects that member is not already following a member' do + expect(@member1.already_following?(@member3)).to eq false + end + + it 'gets the correct follow for a followed member' do + expect(@member1.get_follow(@member2).id).to eq @follow.id + end + + it 'returns nil for a member that is not followed' do + expect(@member1.get_follow(@member3).nil?).to eq true + end + + end + end From 0ba6562d797ab1b8c299cb405e56c1517432be91 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Thu, 20 Nov 2014 01:46:04 +1100 Subject: [PATCH 032/143] Added more model tests for following behaviour --- spec/models/follow_spec.rb | 45 ++++++++++++++++++++++++++++++-------- spec/models/member_spec.rb | 2 +- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb index c1beb68c5..4cba917be 100644 --- a/spec/models/follow_spec.rb +++ b/spec/models/follow_spec.rb @@ -2,16 +2,43 @@ require 'spec_helper' describe Follow do - context "basic" do - before(:each) do - @member1 = FactoryGirl.create(:member) - @member2 = FactoryGirl.create(:member) - end + before(:each) do + @member1 = FactoryGirl.create(:member) + @member2 = FactoryGirl.create(:member) + end - it "sends a notification when a follow is created" do - expect { - Follow.create(:follower_id => @member1.id, :followed_id => @member2.id) - }.to change(Notification, :count).by(1) + it "sends a notification when a follow is created" do + expect { + Follow.create(:follower_id => @member1.id, :followed_id => @member2.id) + }.to change(Notification, :count).by(1) + end + + it "does not delete any members when follow is deleted" do + expect { + follow = Follow.create(:follower_id => @member1.id, :followed_id => @member2.id) + follow.destroy + }.not_to change(Member, :count) + end + + context "when follow is created" do + + before (:each) do + @follow = Follow.create(:follower_id => @member1.id, :followed_id => @member2.id) + end + + it "should not duplicate follows" do + expect(Follow.create(:follower_id => @member1.id, :followed_id => @member2.id)).not_to be_valid + end + + it "should list users in following/follower collections when follow is created" do + expect(@member1.followed).to include(@member2) + expect(@member2.followers).to include(@member1) + end + + it "should no longer list users in following/follower collections when follow is deleted" do + @follow.destroy + expect(@member1.followed).not_to include(@member2) + expect(@member2.followers).not_to include(@member1) end end diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index dbffaf941..5594c9dbd 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -402,7 +402,7 @@ describe 'member' do end it 'returns nil for a member that is not followed' do - expect(@member1.get_follow(@member3).nil?).to eq true + expect(@member1.get_follow(@member3)).to be_nil end end From aeb7192f487025c664a5925be1033feb64a60e4c Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Thu, 20 Nov 2014 23:46:15 +1100 Subject: [PATCH 033/143] Break up tests into different scenarios. Defined cancan ability for follows and updated member profile view --- app/models/ability.rb | 5 ++++ app/views/members/show.html.haml | 11 +++++---- spec/features/member_profile_spec.rb | 36 ++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 92bfce14e..579a87022 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -93,6 +93,11 @@ class Ability cannot :update, OrderItem, :order => { :member_id => member.id, :completed_at => nil } cannot :destroy, OrderItem, :order => { :member_id => member.id, :completed_at => nil } + # following/unfollowing permissions + can :create, Follow do |f| + !member.already_following?(f.followed) && f.followed_id != member.id + end + if member.has_role? :admin can :read, :all diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index e7c0bc93d..5ff19b2eb 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -7,11 +7,12 @@ = link_to "Upgrade account", shop_path, :class => 'btn btn-default' -if can? :create, Notification and current_member != @member =link_to 'Send message', new_notification_path(:recipient_id => @member.id), :class => 'btn btn-default' - - if member_signed_in? && current_member != @member && !current_member.already_following?(@member) - = link_to 'Follow', follows_path(:followed_id => @member.id), :method => :post, :class => 'btn btn-default' - - if member_signed_in? && current_member.already_following?(@member) - - follow = current_member.get_follow(@member) - = link_to 'Unfollow', follow_path(follow), :method => :delete, :class => 'btn btn-default' + - if can? :create, Follow and current_member != @member + - if !current_member.already_following?(@member) + = link_to 'Follow', follows_path(:followed_id => @member.id), :method => :post, :class => 'btn btn-default' + - else + - follow = current_member.get_follow(@member) + = link_to 'Unfollow', follow_path(follow), :method => :delete, :class => 'btn btn-default' - content_for :member_rss_login_name, @member.login_name - content_for :member_rss_slug, @member.slug diff --git a/spec/features/member_profile_spec.rb b/spec/features/member_profile_spec.rb index b2efe71d3..626f00657 100644 --- a/spec/features/member_profile_spec.rb +++ b/spec/features/member_profile_spec.rb @@ -13,6 +13,8 @@ feature "member profile" do expect(page).to have_content "Account type: Free account" expect(page).to have_content "#{member.login_name}'s gardens" expect(page).to have_link "More about this garden...", :href => garden_path(member.gardens.first) + expect(page).to_not have_link "Follow" + expect(page).to_not have_link "Unfollow" end scenario "no bio" do @@ -147,27 +149,47 @@ feature "member profile" do scenario "has a follow button" do expect(page).to have_link "Follow", :href => follows_path(:followed_id => other_member.id) end + end - scenario "following and unfollowing" do + context "following another member" do + background do + visit member_path(other_member) click_link 'Follow' + end + + scenario "has correct message and unfollow button" do expect(page).to have_content "Followed #{other_member.login_name}" expect(page).to have_link "Unfollow", :href => follow_path(member.get_follow(other_member)) + end + scenario "has a followed member listed in the following page" do visit member_follows_path(member) expect(page).to have_content "#{other_member.login_name}" + end - visit member_followers_path(other_member) - expect(page).to have_content "#{member.login_name}" - - visit member_path(other_member) + scenario "has correct message and follow button after unfollow" do click_link 'Unfollow' expect(page).to have_content "Unfollowed #{other_member.login_name}" + visit member_path(other_member) # unfollowing redirects to root + expect(page).to have_link "Follow", :href => follows_path(:followed_id => other_member.id) + end + scenario "has member in following list" do visit member_follows_path(member) - expect(page).to_not have_content "#{other_member.login_name}" + expect(page).to have_content "#{other_member.login_name}" + end + scenario "appears in in followed member's followers list" do visit member_followers_path(other_member) - expect(page).to_not have_content "#{member.login_name}" + expect(page).to have_content "#{member.login_name}" + end + + scenario "removes members from following and followers lists after unfollow" do + click_link 'Unfollow' + visit member_follows_path(member) + expect(page).not_to have_content "#{other_member.login_name}" + visit member_followers_path(other_member) + expect(page).not_to have_content "#{member.login_name}" end end From 5de6759917329bd90eb5ebfa0004b73d9f5f581c Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Fri, 21 Nov 2014 00:29:45 +1100 Subject: [PATCH 034/143] Moved number of follows/followers under activity and added pagination. --- app/controllers/members_controller.rb | 4 ++-- app/views/members/_account.html.haml | 7 ------- app/views/members/_stats.html.haml | 13 +++++++++++++ app/views/members/view_followers.html.haml | 11 ++++++++--- app/views/members/view_follows.html.haml | 10 ++++++++-- 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index dbdaaf9ef..ac53f4194 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -36,12 +36,12 @@ class MembersController < ApplicationController def view_follows @member = Member.confirmed.find(params[:login_name]) - @follows = @member.followed + @follows = @member.followed.paginate(:page => params[:page]) end def view_followers @member = Member.confirmed.find(params[:login_name]) - @followers = @member.followers + @followers = @member.followers.paginate(:page => params[:page]) end end diff --git a/app/views/members/_account.html.haml b/app/views/members/_account.html.haml index e44bae027..68dfbd591 100644 --- a/app/views/members/_account.html.haml +++ b/app/views/members/_account.html.haml @@ -9,10 +9,3 @@ = member.account_type account -%p - %strong Following: - = link_to member.follows.count, member_follows_path(member) - -%p - %strong Followed by: - = link_to member.followers.count, member_followers_path(member) diff --git a/app/views/members/_stats.html.haml b/app/views/members/_stats.html.haml index 38d6b96c3..0929e5998 100644 --- a/app/views/members/_stats.html.haml +++ b/app/views/members/_stats.html.haml @@ -21,3 +21,16 @@ = link_to pluralize(member.posts.count, "post"), posts_by_author_path(:author => member) - else 0 posts + + %li + - if member.followed.count > 0 + = link_to pluralize(member.followed.count, "follow"), member_follows_path(member) + - else + 0 following + + %li + - if member.followers.count > 0 + = link_to pluralize(member.followers.count, "follower"), member_followers_path(member) + - else + 0 followers + diff --git a/app/views/members/view_followers.html.haml b/app/views/members/view_followers.html.haml index e196a8130..25a10a860 100644 --- a/app/views/members/view_followers.html.haml +++ b/app/views/members/view_followers.html.haml @@ -1,6 +1,8 @@ -- content_for :title, @member.login_name +- content_for :title, "#{@member.login_name}'s followers" -%p Followed by: +%div.pagination + = page_entries_info @followers, :model => "members" + = will_paginate @followers .row .col-md-12 @@ -8,4 +10,7 @@ .col-md-4.three-across .thumbnail = render :partial => "members/thumbnail", :locals => { :member => f } - \ No newline at end of file + +%div.pagination + = page_entries_info @followers, :model => "members" + = will_paginate @followers \ No newline at end of file diff --git a/app/views/members/view_follows.html.haml b/app/views/members/view_follows.html.haml index ee2248239..93d2695ac 100644 --- a/app/views/members/view_follows.html.haml +++ b/app/views/members/view_follows.html.haml @@ -1,6 +1,8 @@ -- content_for :title, @member.login_name +- content_for :title, "#{@member.login_name}'s follows" -%p Follows: +%div.pagination + = page_entries_info @follows, :model => "members" + = will_paginate @follows .row .col-md-12 @@ -8,3 +10,7 @@ .col-md-4.three-across .thumbnail = render :partial => "members/thumbnail", :locals => { :member => f } + +%div.pagination + = page_entries_info @follows, :model => "members" + = will_paginate @follows \ No newline at end of file From 2ca42bbae38f50f3b3cda0c7bb8fcca6462c3b0f Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Fri, 21 Nov 2014 01:05:23 +1100 Subject: [PATCH 035/143] Slight modification to the notification wording. --- app/models/follow.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/follow.rb b/app/models/follow.rb index b1b011c41..55b2ce95c 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -8,8 +8,8 @@ class Follow < ActiveRecord::Base Notification.create( :recipient_id => self.followed_id, :sender_id => self.follower_id, - :subject => "#{self.follower.login_name} has followed you", - :body => "#{self.follower.login_name} has followed you" + :subject => "#{self.follower.login_name} is now following you", + :body => "#{self.follower.login_name} just followed you on Growstuff. " ) end From 8c55a6101d27ed76838b165c3ca77740564a6f83 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Fri, 21 Nov 2014 01:14:12 +1100 Subject: [PATCH 036/143] Formatting problem --- spec/models/follow_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb index 4cba917be..3b672af34 100644 --- a/spec/models/follow_spec.rb +++ b/spec/models/follow_spec.rb @@ -7,7 +7,7 @@ describe Follow do @member2 = FactoryGirl.create(:member) end - it "sends a notification when a follow is created" do + it "sends a notification when a follow is created" do expect { Follow.create(:follower_id => @member1.id, :followed_id => @member2.id) }.to change(Notification, :count).by(1) From eb4fae463f0fd482f2b5b38008a0060d4641632d Mon Sep 17 00:00:00 2001 From: Kevin Rio Date: Sun, 23 Nov 2014 11:47:48 -0500 Subject: [PATCH 037/143] Comments RSS tests --- spec/features/rss/comments_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 spec/features/rss/comments_spec.rb diff --git a/spec/features/rss/comments_spec.rb b/spec/features/rss/comments_spec.rb new file mode 100644 index 000000000..c4ba7f307 --- /dev/null +++ b/spec/features/rss/comments_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +feature 'Comments RSS feed' do + scenario 'This RSS feed exists' do + visit comments_path(:format => 'rss') + expect(page.status_code).to equal 200 + end + + scenario 'The feed title is what we expect' do + visit comments_path(:format => 'rss') + expect(page).to have_content "#{ENV['GROWSTUFF_SITE_NAME']} - Recent comments on all posts" + end +end \ No newline at end of file From 2111cddaef1dfd0130f2f1f1a7f23402dc31739c Mon Sep 17 00:00:00 2001 From: Kevin Rio Date: Sun, 23 Nov 2014 21:02:56 -0500 Subject: [PATCH 038/143] RSS feed tests --- spec/features/rss/comments_spec.rb | 6 +++--- spec/features/rss/crops_spec.rb | 13 +++++++++++++ spec/features/rss/members_spec.rb | 15 +++++++++++++++ spec/features/rss/plantings_spec.rb | 13 +++++++++++++ spec/features/rss/posts_spec.rb | 13 +++++++++++++ spec/features/rss/seeds_spec.rb | 13 +++++++++++++ 6 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 spec/features/rss/crops_spec.rb create mode 100644 spec/features/rss/members_spec.rb create mode 100644 spec/features/rss/plantings_spec.rb create mode 100644 spec/features/rss/posts_spec.rb create mode 100644 spec/features/rss/seeds_spec.rb diff --git a/spec/features/rss/comments_spec.rb b/spec/features/rss/comments_spec.rb index c4ba7f307..3f7ce9dc8 100644 --- a/spec/features/rss/comments_spec.rb +++ b/spec/features/rss/comments_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' feature 'Comments RSS feed' do - scenario 'This RSS feed exists' do + scenario 'The index feed exists' do visit comments_path(:format => 'rss') expect(page.status_code).to equal 200 end - scenario 'The feed title is what we expect' do + scenario 'The index title is what we expect' do visit comments_path(:format => 'rss') - expect(page).to have_content "#{ENV['GROWSTUFF_SITE_NAME']} - Recent comments on all posts" + expect(page).to have_content "Recent comments on all posts (#{ENV['GROWSTUFF_SITE_NAME']})" end end \ No newline at end of file diff --git a/spec/features/rss/crops_spec.rb b/spec/features/rss/crops_spec.rb new file mode 100644 index 000000000..971ec1b80 --- /dev/null +++ b/spec/features/rss/crops_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +feature 'Crops RSS feed' do + scenario 'The index feed exists' do + visit crops_path(:format => 'rss') + expect(page.status_code).to equal 200 + end + + scenario 'The index title is what we expect' do + visit crops_path(:format => 'rss') + expect(page).to have_content "Recently added crops (#{ENV['GROWSTUFF_SITE_NAME']})" + end +end \ No newline at end of file diff --git a/spec/features/rss/members_spec.rb b/spec/features/rss/members_spec.rb new file mode 100644 index 000000000..69abb5a25 --- /dev/null +++ b/spec/features/rss/members_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +feature 'Members RSS feed' do + let(:member) { FactoryGirl.create(:member) } + + scenario 'The show action exists' do + visit member_path(member, :format => 'rss') + expect(page.status_code).to equal 200 + end + + scenario 'The show action title is what we expect' do + visit member_path(member, :format => 'rss') + expect(page).to have_content "#{member.login_name}'s recent posts (#{ENV['GROWSTUFF_SITE_NAME']})" + end +end \ No newline at end of file diff --git a/spec/features/rss/plantings_spec.rb b/spec/features/rss/plantings_spec.rb new file mode 100644 index 000000000..5a0e98371 --- /dev/null +++ b/spec/features/rss/plantings_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +feature 'Plantings RSS feed' do + scenario 'The index feed exists' do + visit plantings_path(:format => 'rss') + expect(page.status_code).to equal 200 + end + + scenario 'The index title is what we expect' do + visit plantings_path(:format => 'rss') + expect(page).to have_content "Recent plantings from #{ @owner ? @owner : 'all members' } (#{ENV['GROWSTUFF_SITE_NAME']})" + end +end \ No newline at end of file diff --git a/spec/features/rss/posts_spec.rb b/spec/features/rss/posts_spec.rb new file mode 100644 index 000000000..899c1427b --- /dev/null +++ b/spec/features/rss/posts_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +feature 'Posts RSS feed' do + scenario 'The index feed exists' do + visit posts_path(:format => 'rss') + expect(page.status_code).to equal 200 + end + + scenario 'The index title is what we expect' do + visit posts_path(:format => 'rss') + expect(page).to have_content "Recent posts from #{ @author ? @author : 'all members' } (#{ENV['GROWSTUFF_SITE_NAME']})" + end +end \ No newline at end of file diff --git a/spec/features/rss/seeds_spec.rb b/spec/features/rss/seeds_spec.rb new file mode 100644 index 000000000..e0d016939 --- /dev/null +++ b/spec/features/rss/seeds_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +feature 'Seeds RSS feed' do + scenario 'The index feed exists' do + visit seeds_path(:format => 'rss') + expect(page.status_code).to equal 200 + end + + scenario 'The index title is what we expect' do + visit seeds_path(:format => 'rss') + expect(page).to have_content "Recent seeds from #{ @owner ? @owner : 'all members' } (#{ENV['GROWSTUFF_SITE_NAME']})" + end +end \ No newline at end of file From 81d118920372819ed18849ca13cb9f6cbabbee85 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Sat, 22 Nov 2014 23:00:59 +1100 Subject: [PATCH 039/143] Added a before_filter for any action that requires authentication. Will redirect to login page if not logged in --- app/controllers/account_types_controller.rb | 2 ++ app/controllers/accounts_controller.rb | 2 ++ app/controllers/alternate_names_controller.rb | 1 + app/controllers/authentications_controller.rb | 1 + app/controllers/comments_controller.rb | 1 + app/controllers/crops_controller.rb | 1 + app/controllers/gardens_controller.rb | 3 ++- app/controllers/harvests_controller.rb | 1 + app/controllers/notifications_controller.rb | 2 ++ app/controllers/order_items_controller.rb | 1 + app/controllers/orders_controller.rb | 1 + app/controllers/photos_controller.rb | 1 + app/controllers/plantings_controller.rb | 1 + app/controllers/posts_controller.rb | 1 + app/controllers/products_controller.rb | 2 ++ app/controllers/roles_controller.rb | 2 ++ app/controllers/scientific_names_controller.rb | 1 + app/controllers/seeds_controller.rb | 1 + spec/features/signin_spec.rb | 6 ++++++ 19 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/controllers/account_types_controller.rb b/app/controllers/account_types_controller.rb index 9095beb37..350c007a2 100644 --- a/app/controllers/account_types_controller.rb +++ b/app/controllers/account_types_controller.rb @@ -1,5 +1,7 @@ class AccountTypesController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member! + # GET /account_types def index @account_types = AccountType.all diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 4ee11c36a..7c4c0018d 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -1,5 +1,7 @@ class AccountsController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member! + # GET /accounts def index @accounts = Account.all diff --git a/app/controllers/alternate_names_controller.rb b/app/controllers/alternate_names_controller.rb index ea8a8f76c..dce855975 100644 --- a/app/controllers/alternate_names_controller.rb +++ b/app/controllers/alternate_names_controller.rb @@ -1,5 +1,6 @@ class AlternateNamesController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member!, :except => [:index, :show] # GET /alternate_names # GET /alternate_names.json diff --git a/app/controllers/authentications_controller.rb b/app/controllers/authentications_controller.rb index 6e416202b..898310a3b 100644 --- a/app/controllers/authentications_controller.rb +++ b/app/controllers/authentications_controller.rb @@ -1,4 +1,5 @@ class AuthenticationsController < ApplicationController + before_filter :authenticate_member! load_and_authorize_resource # GET /authentications diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 543f120ae..3234a379d 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,5 +1,6 @@ class CommentsController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member!, :except => [:index, :show] cache_sweeper :comment_sweeper diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index a30de159a..770db8d19 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -1,6 +1,7 @@ class CropsController < ApplicationController load_and_authorize_resource skip_authorize_resource :only => [:hierarchy, :search] + before_filter :authenticate_member!, :except => [:index, :hierarchy, :search, :show] cache_sweeper :crop_sweeper diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index 570dcdfca..cc2d091d5 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -1,6 +1,7 @@ class GardensController < ApplicationController load_and_authorize_resource - + before_filter :authenticate_member!, :except => [:index, :show] + cache_sweeper :garden_sweeper # GET /gardens diff --git a/app/controllers/harvests_controller.rb b/app/controllers/harvests_controller.rb index 524007d47..d6535940f 100644 --- a/app/controllers/harvests_controller.rb +++ b/app/controllers/harvests_controller.rb @@ -1,6 +1,7 @@ class HarvestsController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member!, :except => [:index, :show] # GET /harvests # GET /harvests.json diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 790e5d3ac..a5905d088 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -1,6 +1,8 @@ class NotificationsController < ApplicationController include NotificationsHelper + before_filter :authenticate_member! load_and_authorize_resource + # GET /notifications def index @notifications = Notification.find_all_by_recipient_id(current_member) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index e9f4a2e11..d9c072b28 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -1,4 +1,5 @@ class OrderItemsController < ApplicationController + before_filter :authenticate_member! load_and_authorize_resource # POST /order_items diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index fa0e65718..7ee0b5a56 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,4 +1,5 @@ class OrdersController < ApplicationController + before_filter :authenticate_member! load_and_authorize_resource # GET /orders diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 45755db84..ccbb2048d 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -1,5 +1,6 @@ class PhotosController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member!, :except => [:index, :show] cache_sweeper :photo_sweeper diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index b08fe98fd..acdff628f 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -1,5 +1,6 @@ class PlantingsController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member!, :except => [:index, :show] cache_sweeper :planting_sweeper diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index b7167e9d2..4a88ee053 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -1,5 +1,6 @@ class PostsController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member!, :except => [:index, :show] cache_sweeper :post_sweeper diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 9e50b7311..9349301b4 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,5 +1,7 @@ class ProductsController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member! + # GET /products def index @products = Product.all diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 5763e949b..9ed8308d4 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -1,5 +1,7 @@ class RolesController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member! + # GET /roles def index @roles = Role.all diff --git a/app/controllers/scientific_names_controller.rb b/app/controllers/scientific_names_controller.rb index 3911a6618..893e17ba1 100644 --- a/app/controllers/scientific_names_controller.rb +++ b/app/controllers/scientific_names_controller.rb @@ -1,5 +1,6 @@ class ScientificNamesController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member!, :except => [:index, :show] cache_sweeper :scientific_name_sweeper diff --git a/app/controllers/seeds_controller.rb b/app/controllers/seeds_controller.rb index 03960624b..6a89bfdfa 100644 --- a/app/controllers/seeds_controller.rb +++ b/app/controllers/seeds_controller.rb @@ -1,5 +1,6 @@ class SeedsController < ApplicationController load_and_authorize_resource + before_filter :authenticate_member!, :except => [:index, :show] cache_sweeper :seed_sweeper diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index b4a5eb7bb..424d2efd4 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' feature "signin" do let(:member){FactoryGirl.create(:member)} + let(:notification){FactoryGirl.create(:notification)} scenario "redirect to previous page after signin" do visit crops_path # some random page @@ -21,4 +22,9 @@ feature "signin" do current_path.should eq root_path end + scenario "redirect to signin page for if not authenticated to view notification" do + visit notification_path(notification) + current_path.should eq new_member_session_path + end + end From 924efe6af5d4959d96640bc945f60f8103dfb77d Mon Sep 17 00:00:00 2001 From: Skud Date: Sun, 30 Nov 2014 14:19:55 +1100 Subject: [PATCH 040/143] Fixed a bug which only occurs in the few months before February This is the fundamental problem: 2.1.2 :005 > Time.zone.now + 3.months => Sat, 28 Feb 2015 03:17:24 UTC +00:00 2.1.2 :006 > Time.zone.now + 3.months + 3.months => Thu, 28 May 2015 03:17:32 UTC +00:00 2.1.2 :007 > Time.zone.now + 6.months => Sat, 30 May 2015 03:17:37 UTC +00:00 I changed the test to use the "3.months + 3.months" formulation and it now passes. --- spec/models/member_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 49b66ef71..17d305c68 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -369,7 +369,7 @@ describe 'member' do # and again to make sure it works for currently paid accounts @member.update_account_after_purchase(@product) - @member.account.paid_until.to_s.should eq (Time.zone.now + 6.months).to_s + @member.account.paid_until.to_s.should eq (Time.zone.now + 3.months + 3.months).to_s end end From 4e19da56a0f204a45a344d3fb8fa764fcf1e79e4 Mon Sep 17 00:00:00 2001 From: Skud Date: Sun, 30 Nov 2014 14:51:33 +1100 Subject: [PATCH 041/143] Rearrange fields in crop uploads (sci names last) --- app/models/crop.rb | 4 +- db/schema.rb | 1 + db/seeds/crops-00.csv | 466 ++++++++++++++++----------------- db/seeds/crops-10-peppers.csv | 122 ++++----- db/seeds/crops-11-tomatoes.csv | 82 +++--- spec/models/crop_spec.rb | 9 +- 6 files changed, 342 insertions(+), 342 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 9777d8fd4..5f4758366 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -122,12 +122,12 @@ class Crop < ActiveRecord::Base # used by db/seeds.rb and rake growstuff:import_crops # CSV fields: # - name (required) -# - scientific name (optional, can be picked up from parent if it has one) # - en_wikipedia_url (required) # - parent (name, optional) +# - scientific name (optional, can be picked up from parent if it has one) def Crop.create_from_csv(row) - name,scientific_name,en_wikipedia_url,parent = row + name,en_wikipedia_url,parent,scientific_name = row cropbot = Member.find_by_login_name('cropbot') raise "cropbot account not found: run rake db:seed" unless cropbot diff --git a/db/schema.rb b/db/schema.rb index 39a68cab2..72fcb7231 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -262,6 +262,7 @@ ActiveRecord::Schema.define(:version => 20141018111015) do t.datetime "updated_at", :null => false t.string "slug" t.integer "forum_id" + t.integer "parent_id" end add_index "posts", ["created_at", "author_id"], :name => "index_updates_on_created_at_and_user_id" diff --git a/db/seeds/crops-00.csv b/db/seeds/crops-00.csv index ab0d135fa..adad852cb 100644 --- a/db/seeds/crops-00.csv +++ b/db/seeds/crops-00.csv @@ -1,233 +1,233 @@ -achiote,Bixa orellana,https://en.wikipedia.org/wiki/Bixa_orellana -ackee,Blighia sapida,https://en.wikipedia.org/wiki/Ackee -acuyo,Piper auritum,https://en.wikipedia.org/wiki/Piper_auritum -alexanders,Smyrnium olusatrum,https://en.wikipedia.org/wiki/Alexanders -alfalfa,Medicago sativa,https://en.wikipedia.org/wiki/Alfalfa -allspice,Pimenta dioica,https://en.wikipedia.org/wiki/Allspice -almond,Prunus dulcis,https://en.wikipedia.org/wiki/Almond -amaranth,Amaranthus spp.,https://en.wikipedia.org/wiki/Amaranth -anise,Pimpinella anisum,https://en.wikipedia.org/wiki/Anise -apple,Malus domestica,https://en.wikipedia.org/wiki/Apple -apple mint,Mentha suaveolens,https://en.wikipedia.org/wiki/Apple_mint -apricot,Prunus armeniaca,https://en.wikipedia.org/wiki/Apricot -arrowroot,Maranta arundinacea,https://en.wikipedia.org/wiki/Maranta_arundinacea -artichoke,Cynara cardunculus,https://en.wikipedia.org/wiki/Artichoke -arugula,Eruca sativa,https://en.wikipedia.org/wiki/Arugula -asparagus,Asparagus officinalis,https://en.wikipedia.org/wiki/Asparagus -avocado,Persea americana,https://en.wikipedia.org/wiki/Avocado -banana,Musa spp.,https://en.wikipedia.org/wiki/Banana -barley,Hordeum vulgare,https://en.wikipedia.org/wiki/Barley -basil,Ocimum basilicum,https://en.wikipedia.org/wiki/Basil -bay,Laurus nobilis,https://en.wikipedia.org/wiki/Bay_Laurel -bean,Phaseolus vulgaris,https://en.wikipedia.org/wiki/Common_bean -beet,Beta vulgaris,https://en.wikipedia.org/wiki/Beet -bell pepper,Capsicum annuum,https://en.wikipedia.org/wiki/Bell_pepper -bitter melon,Momordica charantia,https://en.wikipedia.org/wiki/Bitter_melon -blackberry,Rubus fruticosus,https://en.wikipedia.org/wiki/Blackberry -blackcurrant,Ribes spp.,https://en.wikipedia.org/wiki/Ribes -borage,Borago officinalis,https://en.wikipedia.org/wiki/Borage -breadfruit,Artocarpus altilis,https://en.wikipedia.org/wiki/Breadfruit -broccoli,Brassica oleracea,https://en.wikipedia.org/wiki/Broccoli -Brussels sprout,Brassica oleracea,https://en.wikipedia.org/wiki/Brussels_sprout -buckwheat,Fagopyrum esculentum,https://en.wikipedia.org/wiki/Buckwheat -cabbage,Brassica oleracea,https://en.wikipedia.org/wiki/Cabbage -cape gooseberry,Physalis peruviana,https://en.wikipedia.org/wiki/Physalis_peruviana -caper,Capparis spinosa,https://en.wikipedia.org/wiki/Caper -cardoon,Cynara cardunculus,https://en.wikipedia.org/wiki/Cardoon -carrot,Daucus carota,https://en.wikipedia.org/wiki/Carrot -cassava,Manihot esculenta,https://en.wikipedia.org/wiki/Cassava -catnip,Nepeta cataria,https://en.wikipedia.org/wiki/Nepeta_cataria -cauliflower,Brassica oleracea,https://en.wikipedia.org/wiki/Cauliflower -cayenne pepper,Capsicum annuum,https://en.wikipedia.org/wiki/Cayenne_pepper -celeriac,Apium graveolens var. rapaceum,https://en.wikipedia.org/wiki/Celeriac -celery,Apium graveolens,https://en.wikipedia.org/wiki/Celery -chamomile,Matricaria chamomila,https://en.wikipedia.org/wiki/Matricaria_recutita -chaya,Cnidoscolus aconitifolius,https://en.wikipedia.org/wiki/Cnidoscolus_aconitifolius -chayote,Sechium edule,https://en.wikipedia.org/wiki/Chayote -cherry,Prunus avium,https://en.wikipedia.org/wiki/Cherry -chervil,Anthriscus cerefolium,https://en.wikipedia.org/wiki/Chervil -chestnut,Castanea spp.,https://en.wikipedia.org/wiki/Chestnut -chickpeas,Cicer arietinum,https://en.wikipedia.org/wiki/Chickpea -chickweed,Stellaria,https://en.wikipedia.org/wiki/Stellaria -chicory,Cichorium intybus,https://en.wikipedia.org/wiki/Chicory -chinese cabbage,Brassica rapa (pekinensis),https://en.wikipedia.org/wiki/Chinese_cabbage -chives,Allium schoenoprasum,https://en.wikipedia.org/wiki/Chives -cicely,Myrrhis odorata,https://en.wikipedia.org/wiki/Cicely -citron,Citrus medica,https://en.wikipedia.org/wiki/Citron -coconut,Cocos nucifera,https://en.wikipedia.org/wiki/Coconut -collard greens,Brassica oleracea (acephala),https://en.wikipedia.org/wiki/Collard_greens -comfrey,Symphytum officinale,https://en.wikipedia.org/wiki/Comfrey -coriander,Coriandrum sativum,https://en.wikipedia.org/wiki/Coriander -corn,Zea mays,https://en.wikipedia.org/wiki/Corn -corn salad,Valerianella locusta,https://en.wikipedia.org/wiki/Corn_salad -cress,Lepidium sativum,https://en.wikipedia.org/wiki/Garden_cress -cucumber,Cucumis sativus,https://en.wikipedia.org/wiki/Cucumbers -cumin,Cuminum cyminum,https://en.wikipedia.org/wiki/Cumin -cumquat,Citrus japonica,https://en.wikipedia.org/wiki/Kumquat -curry leaf,Murraya koenigii,https://en.wikipedia.org/wiki/Curry-leaf_Tree -curry plant,Helichrysum italicum,https://en.wikipedia.org/wiki/Helichrysum_italicum -daikon,Raphanus sativus Longipinnatus group,https://en.wikipedia.org/wiki/Daikon -dandelion,Taraxacum officinale,https://en.wikipedia.org/wiki/Dandelion -dates,Phoenix dactylifera,https://en.wikipedia.org/wiki/Date_%28fruit%29 -desert lime,Citrus glauca,https://en.wikipedia.org/wiki/Citrus_glauca -dill,Anethum graveolens,https://en.wikipedia.org/wiki/Dill -dog rose,Rosa canina,https://en.wikipedia.org/wiki/Rosa_canina -durian,Durio,https://en.wikipedia.org/wiki/Durian -eggplant,Solanum melongena,https://en.wikipedia.org/wiki/Eggplant -elderberry,Sambucus nigra,https://en.wikipedia.org/wiki/Sambucus_nigra -endive,Cichorium endivia,https://en.wikipedia.org/wiki/Endive -epazote,Dysphania ambrosioides,https://en.wikipedia.org/wiki/Epazote -fava bean,Vicia faba,https://en.wikipedia.org/wiki/Vicia_faba -feijoa,Acca sellowiana,https://en.wikipedia.org/wiki/Acca_sellowiana -fennel,Foeniculum vulgare,https://en.wikipedia.org/wiki/Fennel -fenugreek,Trigonella foenum-graecum,https://en.wikipedia.org/wiki/Fenugreek -fiddlehead,Pteridium aquilinum,https://en.wikipedia.org/wiki/Fiddlehead -fig,Ficus carica,https://en.wikipedia.org/wiki/Common_fig -flax,Linum usitatissimum,https://en.wikipedia.org/wiki/Flax -garlic,Allium sativum,https://en.wikipedia.org/wiki/Garlic -garlic chives,Allium tuberosum,https://en.wikipedia.org/wiki/Garlic_chives -ginger,Zingiber officinale,https://en.wikipedia.org/wiki/Ginger -gooseberry,Ribes uva-crispa,https://en.wikipedia.org/wiki/Gooseberry -grapefruit,Citrus paradisi,https://en.wikipedia.org/wiki/Grapefruit -grapes,Vitis spp.,https://en.wikipedia.org/wiki/Grape -guava,Psidium spp.,https://en.wikipedia.org/wiki/Guava -habanero,Capsicum chinense,https://en.wikipedia.org/wiki/Habanero -hibiscus,Hibiscus,https://en.wikipedia.org/wiki/Hibiscus -horseradish,Armoracia rusticana,https://en.wikipedia.org/wiki/Horseradish -jasmine,Jasminum officinale,https://en.wikipedia.org/wiki/Jasmine -Jerusalem artichoke,Helianthus tuberosus,https://en.wikipedia.org/wiki/Jerusalem_artichoke -jicama,Pachyrhizus erosus,https://en.wikipedia.org/wiki/Jicama -juniper berry,Juniperus communis,https://en.wikipedia.org/wiki/Juniper_berry -kaffir lime,Citrus x hystrix,https://en.wikipedia.org/wiki/Kaffir_lime -kale,Brassica oleracea (acephala),https://en.wikipedia.org/wiki/Kale -kava,Piper methysticum,https://en.wikipedia.org/wiki/Kava -kohlrabi,Brassica oleracea (gongylodes),https://en.wikipedia.org/wiki/Kohlrabi -lavender,Lavandula spp.,https://en.wikipedia.org/wiki/Lavender -leek,Allium ampeloprasum var. porrum,https://en.wikipedia.org/wiki/Leeks -lemon,Citrus limon,https://en.wikipedia.org/wiki/Lemon -lemon balm,Melissa officinalis,https://en.wikipedia.org/wiki/Lemon_balm -lemon myrtle,Backhousia citriodora,https://en.wikipedia.org/wiki/Backhousia_citriodora -lemon verbena,Aloysia citrodora,https://en.wikipedia.org/wiki/Aloysia_citrodora -lemongrass,Cymbopogon spp.,https://en.wikipedia.org/wiki/Lemongrass -lentils,Lens culinaris,https://en.wikipedia.org/wiki/Lentil -lettuce,Lactuca sativa,https://en.wikipedia.org/wiki/Lettuce -licorice,Glycyrrhiza glabra,https://en.wikipedia.org/wiki/Licorice -lillipilli,Syzygium luehmannii,https://en.wikipedia.org/wiki/Syzygium_luehmannii -lima bean,Phaseolus lunatus,https://en.wikipedia.org/wiki/Phaseolus_lunatus -lime,Citrus spp.,https://en.wikipedia.org/wiki/Lime_%28fruit%29 -lovage,Levisticum officinale,https://en.wikipedia.org/wiki/Lovage -luffa,Luffa cylindrica,https://en.wikipedia.org/wiki/Luffa -lupin bean,Lupinus luteus,https://en.wikipedia.org/wiki/Lupin_bean -macadamia,Macadamia,https://en.wikipedia.org/wiki/Macadamia -Malabar spinach,Basella alba,https://en.wikipedia.org/wiki/Basella_alba -mandarin,Citrus reticulata,https://en.wikipedia.org/wiki/Mandarin_orange -mango,Mangifera spp.,https://en.wikipedia.org/wiki/Mango -maracuja,Passiflora edulis,https://en.wikipedia.org/wiki/Maracuja -marjoram,Origanum majorana,https://en.wikipedia.org/wiki/Marjoram -marshmallow,Althaea officinalis,https://en.wikipedia.org/wiki/Althaea_officinalis -medlar,Mespilus germanica,https://en.wikipedia.org/wiki/Mespilus_germanica -melon,Cucumis melo,https://en.wikipedia.org/wiki/Melon -miner's lettuce,Claytonia perfoliata,https://en.wikipedia.org/wiki/Claytonia_perfoliata -mint,Mentha spicata,https://en.wikipedia.org/wiki/Mentha_spicata -mung bean,Vigna radiata,https://en.wikipedia.org/wiki/Mung_bean -mustard,Brassica juncea,https://en.wikipedia.org/wiki/Mustard_plant -nasturtium,Tropaeloum spp.,https://en.wikipedia.org/wiki/Tropaeolum -New Zealand spinach,Tetragonia tetragonioides,https://en.wikipedia.org/wiki/Tetragonia -nigella,Nigella sativa,https://en.wikipedia.org/wiki/Nigella_sativa -oats,Avena sativa,https://en.wikipedia.org/wiki/Oats -okra,Abelmoschus esculentus,https://en.wikipedia.org/wiki/Okra -olive,Olea europaea,https://en.wikipedia.org/wiki/Olive -onion,Allium cepa,https://en.wikipedia.org/wiki/Onions -orange,Citrus sinensis,https://en.wikipedia.org/wiki/Orange_%28fruit%29 -oregano,Origanum vulgare,https://en.wikipedia.org/wiki/Oregano -parsley,Petroselinum hortense,https://en.wikipedia.org/wiki/Parsley -parsnip,Pastinaca sativa,https://en.wikipedia.org/wiki/Parsnip -passion fruit,Passiflora edulis,https://en.wikipedia.org/wiki/Passionfruit -pea,Pisum sativum,https://en.wikipedia.org/wiki/Pea -peach,Prunus persica,https://en.wikipedia.org/wiki/Peach -peach,Prunus persica,https://en.wikipedia.org/wiki/Peach -peanut,Arachis hypogaea,https://en.wikipedia.org/wiki/Peanut -pear,Pyrus spp.,https://en.wikipedia.org/wiki/Pear -pearl millet,Pennisetum glaucum,https://en.wikipedia.org/wiki/Pearl_millet -pecan,Carya illinoinensis,https://en.wikipedia.org/wiki/Pecan -peppermint,Mentha x piperita,https://en.wikipedia.org/wiki/Peppermint -Persian lime,Citrus latifolia,https://en.wikipedia.org/wiki/Persian_lime -persimmon,Diospyros spp.,https://en.wikipedia.org/wiki/Persimmon -pigeon pea,Cajanus cajan,https://en.wikipedia.org/wiki/Pigeon_pea -pigface,Carpobrotus glaucescens,https://en.wikipedia.org/wiki/Carpobrotus_glaucescens -pineapple,Ananas comosus,https://en.wikipedia.org/wiki/Pineapple -pistachio,Pistacia vera,https://en.wikipedia.org/wiki/Pistachio -plantain,Musa spp.,https://en.wikipedia.org/wiki/Plantain -plum,Prunus spp.,https://en.wikipedia.org/wiki/Plum -pomegranate,Punica granatum,https://en.wikipedia.org/wiki/Pomegranate -pomelo,Citrus maxima,https://en.wikipedia.org/wiki/Pomelo -potato,Solanum tuberosum,https://en.wikipedia.org/wiki/Potatoes -prickly pear,Opuntia,https://en.wikipedia.org/wiki/Opuntia -pumpkin,Cucurbita spp.,https://en.wikipedia.org/wiki/Pumpkin -purslane,Portulaca oleracea,https://en.wikipedia.org/wiki/Portulaca_oleracea -quandong,Santalum acuminatum,https://en.wikipedia.org/wiki/Santalum_acuminatum -quince,Cydonia oblonga,https://en.wikipedia.org/wiki/Quince -quinoa,Chenopodium quinoa,https://en.wikipedia.org/wiki/Quinoa -radicchio,Cichorium intybus,https://en.wikipedia.org/wiki/Radicchio -radish,Raphanus sativus,https://en.wikipedia.org/wiki/Radish -rapeseed,Brassica napus,https://en.wikipedia.org/wiki/Rapeseed -raspberry,Rubus idaeus,https://en.wikipedia.org/wiki/Rubus_idaeus -rhubarb,Rheum rhabarbarum,https://en.wikipedia.org/wiki/Rhubarb -rice,Oryza sativa,https://en.wikipedia.org/wiki/Rice -rice bean,Vigna umbellata,https://en.wikipedia.org/wiki/Ricebean -rose,Rosa,https://en.wikipedia.org/wiki/Rose -roselle,Hibiscus sabdariffa,https://en.wikipedia.org/wiki/Roselle_%28plant%29 -rosemary,Rosmarinus officinalis,https://en.wikipedia.org/wiki/Rosemary -rue,Ruta graveolens,https://en.wikipedia.org/wiki/Common_Rue -runner bean,Phaseolus coccineus,https://en.wikipedia.org/wiki/Runner_bean -rutabaga,Brassica napus Napobrassica group,https://en.wikipedia.org/wiki/Rutabaga -rye,Secale cereale,https://en.wikipedia.org/wiki/Rye -safflower,Carthamus tinctorius,https://en.wikipedia.org/wiki/Safflower -saffron,Crocus sativus,https://en.wikipedia.org/wiki/Saffron -sage,Salvia officinalis,https://en.wikipedia.org/wiki/Salvia_officinalis -salad burnet,Sanguisorba minor,https://en.wikipedia.org/wiki/Salad_burnet -salsify,Tragopogon porrifolius,https://en.wikipedia.org/wiki/Salsify -samphire,Crithmum maritimum,https://en.wikipedia.org/wiki/Rock_samphire -sassafras,Sassafras albidum,https://en.wikipedia.org/wiki/Sassafras_albidum -sesame,Sesamum indicum,https://en.wikipedia.org/wiki/Sesame -shallot,Allium cepa var. aggregatum,https://en.wikipedia.org/wiki/Shallot -sorghum,Sorghum spp.,https://en.wikipedia.org/wiki/Sorghum -sorrel,Rumex acetosa,https://en.wikipedia.org/wiki/Sorrel -soursop,Annona muricata,https://en.wikipedia.org/wiki/Soursop -soybean,Glycine max,https://en.wikipedia.org/wiki/Soybean -spearmint,Mentha spicata,https://en.wikipedia.org/wiki/Mentha_spicata -spinach,Spinacia oleracea,https://en.wikipedia.org/wiki/Spinach -star anise,Illicium verum,https://en.wikipedia.org/wiki/Star_anise -starfruit,Averrhoa carambola,https://en.wikipedia.org/wiki/Starfruit -stevia,Stevia rebaudiana,https://en.wikipedia.org/wiki/Stevia -strawberry,Fragaria ananassa,https://en.wikipedia.org/wiki/Strawberry -summer savory,Satureja hortensis,https://en.wikipedia.org/wiki/Summer_savory -sunflowers,Helianthus annuus,https://en.wikipedia.org/wiki/Sunflower -sweet potato,Ipomoea batatas,https://en.wikipedia.org/wiki/Sweet_potato -Swiss chard,Beta vulgaris var. cicla,https://en.wikipedia.org/wiki/Swiss_chard -tamarillo,Solanum betaceum ,https://en.wikipedia.org/wiki/Tamarillo -tamarind,Tamarindus indica,https://en.wikipedia.org/wiki/Tamarind -tangerine,Citrus tangerina,https://en.wikipedia.org/wiki/Tangerine -tansy,Tanacetum vulgare,https://en.wikipedia.org/wiki/Tansy -taro,Colocasia esculenta,https://en.wikipedia.org/wiki/Taro -tarragon,Artemisia dracunculus,https://en.wikipedia.org/wiki/Tarragon -thyme,Thymus mongolicus,https://en.wikipedia.org/wiki/Thyme -tomatillo,Physalis philadelphica,https://en.wikipedia.org/wiki/Tomatillo -tomato,Solanum lycopersicum,https://en.wikipedia.org/wiki/Tomato -turmeric,Curcuma longa,https://en.wikipedia.org/wiki/Turmeric -turnip,Brassica rapa var. rapa,https://en.wikipedia.org/wiki/Turnip -urad bean,Vigna mungo,https://en.wikipedia.org/wiki/Urad_(bean) -valerian,Valeriana officinalis,https://en.wikipedia.org/wiki/Valerian_%28plant%29 -vanilla,Vanilla planifolia,https://en.wikipedia.org/wiki/Vanilla -walnut,Juglans spp.,https://en.wikipedia.org/wiki/Walnut -wasabi,Wasabia japonica,https://en.wikipedia.org/wiki/Wasabi -watermelon,Citrullus lanatus,https://en.wikipedia.org/wiki/Watermelon -wheat,Triticum spp.,https://en.wikipedia.org/wiki/Wheat -winter savory,Satureja montana,https://en.wikipedia.org/wiki/Winter_savory -wormwood,Artemisia absinthium,https://en.wikipedia.org/wiki/Artemisia_absinthium -yam,Dioscorea spp.,https://en.wikipedia.org/wiki/Yam_(vegetable) -yardlong bean,Vigna unguiculata (sesquipedalis),https://en.wikipedia.org/wiki/Yardlong_bean -yarrow,Achillea millefolium,https://en.wikipedia.org/wiki/Achillea_millefolium -zucchini,Cucurbita pepo.,https://en.wikipedia.org/wiki/Zucchini -coffee,Coffea,https://en.wikipedia.org/wiki/Coffee -tea,Camellia sinensis,https://en.wikipedia.org/wiki/Tea +achiote,https://en.wikipedia.org/wiki/Bixa_orellana,,Bixa orellana +ackee,https://en.wikipedia.org/wiki/Ackee,,Blighia sapida +acuyo,https://en.wikipedia.org/wiki/Piper_auritum,,Piper auritum +alexanders,https://en.wikipedia.org/wiki/Alexanders,,Smyrnium olusatrum +alfalfa,https://en.wikipedia.org/wiki/Alfalfa,,Medicago sativa +allspice,https://en.wikipedia.org/wiki/Allspice,,Pimenta dioica +almond,https://en.wikipedia.org/wiki/Almond,,Prunus dulcis +amaranth,https://en.wikipedia.org/wiki/Amaranth,,Amaranthus spp. +anise,https://en.wikipedia.org/wiki/Anise,,Pimpinella anisum +apple,https://en.wikipedia.org/wiki/Apple,,Malus domestica +apple mint,https://en.wikipedia.org/wiki/Apple_mint,,Mentha suaveolens +apricot,https://en.wikipedia.org/wiki/Apricot,,Prunus armeniaca +arrowroot,https://en.wikipedia.org/wiki/Maranta_arundinacea,,Maranta arundinacea +artichoke,https://en.wikipedia.org/wiki/Artichoke,,Cynara cardunculus +arugula,https://en.wikipedia.org/wiki/Arugula,,Eruca sativa +asparagus,https://en.wikipedia.org/wiki/Asparagus,,Asparagus officinalis +avocado,https://en.wikipedia.org/wiki/Avocado,,Persea americana +banana,https://en.wikipedia.org/wiki/Banana,,Musa spp. +barley,https://en.wikipedia.org/wiki/Barley,,Hordeum vulgare +basil,https://en.wikipedia.org/wiki/Basil,,Ocimum basilicum +bay,https://en.wikipedia.org/wiki/Bay_Laurel,,Laurus nobilis +bean,https://en.wikipedia.org/wiki/Common_bean,,Phaseolus vulgaris +beet,https://en.wikipedia.org/wiki/Beet,,Beta vulgaris +bell pepper,https://en.wikipedia.org/wiki/Bell_pepper,,Capsicum annuum +bitter melon,https://en.wikipedia.org/wiki/Bitter_melon,,Momordica charantia +blackberry,https://en.wikipedia.org/wiki/Blackberry,,Rubus fruticosus +blackcurrant,https://en.wikipedia.org/wiki/Ribes,,Ribes spp. +borage,https://en.wikipedia.org/wiki/Borage,,Borago officinalis +breadfruit,https://en.wikipedia.org/wiki/Breadfruit,,Artocarpus altilis +broccoli,https://en.wikipedia.org/wiki/Broccoli,,Brassica oleracea +Brussels sprout,https://en.wikipedia.org/wiki/Brussels_sprout,,Brassica oleracea +buckwheat,https://en.wikipedia.org/wiki/Buckwheat,,Fagopyrum esculentum +cabbage,https://en.wikipedia.org/wiki/Cabbage,,Brassica oleracea +cape gooseberry,https://en.wikipedia.org/wiki/Physalis_peruviana,,Physalis peruviana +caper,https://en.wikipedia.org/wiki/Caper,,Capparis spinosa +cardoon,https://en.wikipedia.org/wiki/Cardoon,,Cynara cardunculus +carrot,https://en.wikipedia.org/wiki/Carrot,,Daucus carota +cassava,https://en.wikipedia.org/wiki/Cassava,,Manihot esculenta +catnip,https://en.wikipedia.org/wiki/Nepeta_cataria,,Nepeta cataria +cauliflower,https://en.wikipedia.org/wiki/Cauliflower,,Brassica oleracea +cayenne pepper,https://en.wikipedia.org/wiki/Cayenne_pepper,,Capsicum annuum +celeriac,https://en.wikipedia.org/wiki/Celeriac,,Apium graveolens var. rapaceum +celery,https://en.wikipedia.org/wiki/Celery,,Apium graveolens +chamomile,https://en.wikipedia.org/wiki/Matricaria_recutita,,Matricaria chamomila +chaya,https://en.wikipedia.org/wiki/Cnidoscolus_aconitifolius,,Cnidoscolus aconitifolius +chayote,https://en.wikipedia.org/wiki/Chayote,,Sechium edule +cherry,https://en.wikipedia.org/wiki/Cherry,,Prunus avium +chervil,https://en.wikipedia.org/wiki/Chervil,,Anthriscus cerefolium +chestnut,https://en.wikipedia.org/wiki/Chestnut,,Castanea spp. +chickpeas,https://en.wikipedia.org/wiki/Chickpea,,Cicer arietinum +chickweed,https://en.wikipedia.org/wiki/Stellaria,,Stellaria +chicory,https://en.wikipedia.org/wiki/Chicory,,Cichorium intybus +chinese cabbage,https://en.wikipedia.org/wiki/Chinese_cabbage,,Brassica rapa (pekinensis) +chives,https://en.wikipedia.org/wiki/Chives,,Allium schoenoprasum +cicely,https://en.wikipedia.org/wiki/Cicely,,Myrrhis odorata +citron,https://en.wikipedia.org/wiki/Citron,,Citrus medica +coconut,https://en.wikipedia.org/wiki/Coconut,,Cocos nucifera +collard greens,https://en.wikipedia.org/wiki/Collard_greens,,Brassica oleracea (acephala) +comfrey,https://en.wikipedia.org/wiki/Comfrey,,Symphytum officinale +coriander,https://en.wikipedia.org/wiki/Coriander,,Coriandrum sativum +corn,https://en.wikipedia.org/wiki/Corn,,Zea mays +corn salad,https://en.wikipedia.org/wiki/Corn_salad,,Valerianella locusta +cress,https://en.wikipedia.org/wiki/Garden_cress,,Lepidium sativum +cucumber,https://en.wikipedia.org/wiki/Cucumbers,,Cucumis sativus +cumin,https://en.wikipedia.org/wiki/Cumin,,Cuminum cyminum +cumquat,https://en.wikipedia.org/wiki/Kumquat,,Citrus japonica +curry leaf,https://en.wikipedia.org/wiki/Curry-leaf_Tree,,Murraya koenigii +curry plant,https://en.wikipedia.org/wiki/Helichrysum_italicum,,Helichrysum italicum +daikon,https://en.wikipedia.org/wiki/Daikon,,Raphanus sativus Longipinnatus group +dandelion,https://en.wikipedia.org/wiki/Dandelion,,Taraxacum officinale +dates,https://en.wikipedia.org/wiki/Date_%28fruit%29,,Phoenix dactylifera +desert lime,https://en.wikipedia.org/wiki/Citrus_glauca,,Citrus glauca +dill,https://en.wikipedia.org/wiki/Dill,,Anethum graveolens +dog rose,https://en.wikipedia.org/wiki/Rosa_canina,,Rosa canina +durian,https://en.wikipedia.org/wiki/Durian,,Durio +eggplant,https://en.wikipedia.org/wiki/Eggplant,,Solanum melongena +elderberry,https://en.wikipedia.org/wiki/Sambucus_nigra,,Sambucus nigra +endive,https://en.wikipedia.org/wiki/Endive,,Cichorium endivia +epazote,https://en.wikipedia.org/wiki/Epazote,,Dysphania ambrosioides +fava bean,https://en.wikipedia.org/wiki/Vicia_faba,,Vicia faba +feijoa,https://en.wikipedia.org/wiki/Acca_sellowiana,,Acca sellowiana +fennel,https://en.wikipedia.org/wiki/Fennel,,Foeniculum vulgare +fenugreek,https://en.wikipedia.org/wiki/Fenugreek,,Trigonella foenum-graecum +fiddlehead,https://en.wikipedia.org/wiki/Fiddlehead,,Pteridium aquilinum +fig,https://en.wikipedia.org/wiki/Common_fig,,Ficus carica +flax,https://en.wikipedia.org/wiki/Flax,,Linum usitatissimum +garlic,https://en.wikipedia.org/wiki/Garlic,,Allium sativum +garlic chives,https://en.wikipedia.org/wiki/Garlic_chives,,Allium tuberosum +ginger,https://en.wikipedia.org/wiki/Ginger,,Zingiber officinale +gooseberry,https://en.wikipedia.org/wiki/Gooseberry,,Ribes uva-crispa +grapefruit,https://en.wikipedia.org/wiki/Grapefruit,,Citrus paradisi +grapes,https://en.wikipedia.org/wiki/Grape,,Vitis spp. +guava,https://en.wikipedia.org/wiki/Guava,,Psidium spp. +habanero,https://en.wikipedia.org/wiki/Habanero,,Capsicum chinense +hibiscus,https://en.wikipedia.org/wiki/Hibiscus,,Hibiscus +horseradish,https://en.wikipedia.org/wiki/Horseradish,,Armoracia rusticana +jasmine,https://en.wikipedia.org/wiki/Jasmine,,Jasminum officinale +Jerusalem artichoke,https://en.wikipedia.org/wiki/Jerusalem_artichoke,,Helianthus tuberosus +jicama,https://en.wikipedia.org/wiki/Jicama,,Pachyrhizus erosus +juniper berry,https://en.wikipedia.org/wiki/Juniper_berry,,Juniperus communis +kaffir lime,https://en.wikipedia.org/wiki/Kaffir_lime,,Citrus x hystrix +kale,https://en.wikipedia.org/wiki/Kale,,Brassica oleracea (acephala) +kava,https://en.wikipedia.org/wiki/Kava,,Piper methysticum +kohlrabi,https://en.wikipedia.org/wiki/Kohlrabi,,Brassica oleracea (gongylodes) +lavender,https://en.wikipedia.org/wiki/Lavender,,Lavandula spp. +leek,https://en.wikipedia.org/wiki/Leeks,,Allium ampeloprasum var. porrum +lemon,https://en.wikipedia.org/wiki/Lemon,,Citrus limon +lemon balm,https://en.wikipedia.org/wiki/Lemon_balm,,Melissa officinalis +lemon myrtle,https://en.wikipedia.org/wiki/Backhousia_citriodora,,Backhousia citriodora +lemon verbena,https://en.wikipedia.org/wiki/Aloysia_citrodora,,Aloysia citrodora +lemongrass,https://en.wikipedia.org/wiki/Lemongrass,,Cymbopogon spp. +lentils,https://en.wikipedia.org/wiki/Lentil,,Lens culinaris +lettuce,https://en.wikipedia.org/wiki/Lettuce,,Lactuca sativa +licorice,https://en.wikipedia.org/wiki/Licorice,,Glycyrrhiza glabra +lillipilli,https://en.wikipedia.org/wiki/Syzygium_luehmannii,,Syzygium luehmannii +lima bean,https://en.wikipedia.org/wiki/Phaseolus_lunatus,,Phaseolus lunatus +lime,https://en.wikipedia.org/wiki/Lime_%28fruit%29,,Citrus spp. +lovage,https://en.wikipedia.org/wiki/Lovage,,Levisticum officinale +luffa,https://en.wikipedia.org/wiki/Luffa,,Luffa cylindrica +lupin bean,https://en.wikipedia.org/wiki/Lupin_bean,,Lupinus luteus +macadamia,https://en.wikipedia.org/wiki/Macadamia,,Macadamia +Malabar spinach,https://en.wikipedia.org/wiki/Basella_alba,,Basella alba +mandarin,https://en.wikipedia.org/wiki/Mandarin_orange,,Citrus reticulata +mango,https://en.wikipedia.org/wiki/Mango,,Mangifera spp. +maracuja,https://en.wikipedia.org/wiki/Maracuja,,Passiflora edulis +marjoram,https://en.wikipedia.org/wiki/Marjoram,,Origanum majorana +marshmallow,https://en.wikipedia.org/wiki/Althaea_officinalis,,Althaea officinalis +medlar,https://en.wikipedia.org/wiki/Mespilus_germanica,,Mespilus germanica +melon,https://en.wikipedia.org/wiki/Melon,,Cucumis melo +miner's lettuce,https://en.wikipedia.org/wiki/Claytonia_perfoliata,,Claytonia perfoliata +mint,https://en.wikipedia.org/wiki/Mentha_spicata,,Mentha spicata +mung bean,https://en.wikipedia.org/wiki/Mung_bean,,Vigna radiata +mustard,https://en.wikipedia.org/wiki/Mustard_plant,,Brassica juncea +nasturtium,https://en.wikipedia.org/wiki/Tropaeolum,,Tropaeloum spp. +New Zealand spinach,https://en.wikipedia.org/wiki/Tetragonia,,Tetragonia tetragonioides +nigella,https://en.wikipedia.org/wiki/Nigella_sativa,,Nigella sativa +oats,https://en.wikipedia.org/wiki/Oats,,Avena sativa +okra,https://en.wikipedia.org/wiki/Okra,,Abelmoschus esculentus +olive,https://en.wikipedia.org/wiki/Olive,,Olea europaea +onion,https://en.wikipedia.org/wiki/Onions,,Allium cepa +orange,https://en.wikipedia.org/wiki/Orange_%28fruit%29,,Citrus sinensis +oregano,https://en.wikipedia.org/wiki/Oregano,,Origanum vulgare +parsley,https://en.wikipedia.org/wiki/Parsley,,Petroselinum hortense +parsnip,https://en.wikipedia.org/wiki/Parsnip,,Pastinaca sativa +passion fruit,https://en.wikipedia.org/wiki/Passionfruit,,Passiflora edulis +pea,https://en.wikipedia.org/wiki/Pea,,Pisum sativum +peach,https://en.wikipedia.org/wiki/Peach,,Prunus persica +peach,https://en.wikipedia.org/wiki/Peach,,Prunus persica +peanut,https://en.wikipedia.org/wiki/Peanut,,Arachis hypogaea +pear,https://en.wikipedia.org/wiki/Pear,,Pyrus spp. +pearl millet,https://en.wikipedia.org/wiki/Pearl_millet,,Pennisetum glaucum +pecan,https://en.wikipedia.org/wiki/Pecan,,Carya illinoinensis +peppermint,https://en.wikipedia.org/wiki/Peppermint,,Mentha x piperita +Persian lime,https://en.wikipedia.org/wiki/Persian_lime,,Citrus latifolia +persimmon,https://en.wikipedia.org/wiki/Persimmon,,Diospyros spp. +pigeon pea,https://en.wikipedia.org/wiki/Pigeon_pea,,Cajanus cajan +pigface,https://en.wikipedia.org/wiki/Carpobrotus_glaucescens,,Carpobrotus glaucescens +pineapple,https://en.wikipedia.org/wiki/Pineapple,,Ananas comosus +pistachio,https://en.wikipedia.org/wiki/Pistachio,,Pistacia vera +plantain,https://en.wikipedia.org/wiki/Plantain,,Musa spp. +plum,https://en.wikipedia.org/wiki/Plum,,Prunus spp. +pomegranate,https://en.wikipedia.org/wiki/Pomegranate,,Punica granatum +pomelo,https://en.wikipedia.org/wiki/Pomelo,,Citrus maxima +potato,https://en.wikipedia.org/wiki/Potatoes,,Solanum tuberosum +prickly pear,https://en.wikipedia.org/wiki/Opuntia,,Opuntia +pumpkin,https://en.wikipedia.org/wiki/Pumpkin,,Cucurbita spp. +purslane,https://en.wikipedia.org/wiki/Portulaca_oleracea,,Portulaca oleracea +quandong,https://en.wikipedia.org/wiki/Santalum_acuminatum,,Santalum acuminatum +quince,https://en.wikipedia.org/wiki/Quince,,Cydonia oblonga +quinoa,https://en.wikipedia.org/wiki/Quinoa,,Chenopodium quinoa +radicchio,https://en.wikipedia.org/wiki/Radicchio,,Cichorium intybus +radish,https://en.wikipedia.org/wiki/Radish,,Raphanus sativus +rapeseed,https://en.wikipedia.org/wiki/Rapeseed,,Brassica napus +raspberry,https://en.wikipedia.org/wiki/Rubus_idaeus,,Rubus idaeus +rhubarb,https://en.wikipedia.org/wiki/Rhubarb,,Rheum rhabarbarum +rice,https://en.wikipedia.org/wiki/Rice,,Oryza sativa +rice bean,https://en.wikipedia.org/wiki/Ricebean,,Vigna umbellata +rose,https://en.wikipedia.org/wiki/Rose,,Rosa +roselle,https://en.wikipedia.org/wiki/Roselle_%28plant%29,,Hibiscus sabdariffa +rosemary,https://en.wikipedia.org/wiki/Rosemary,,Rosmarinus officinalis +rue,https://en.wikipedia.org/wiki/Common_Rue,,Ruta graveolens +runner bean,https://en.wikipedia.org/wiki/Runner_bean,,Phaseolus coccineus +rutabaga,https://en.wikipedia.org/wiki/Rutabaga,,Brassica napus Napobrassica group +rye,https://en.wikipedia.org/wiki/Rye,,Secale cereale +safflower,https://en.wikipedia.org/wiki/Safflower,,Carthamus tinctorius +saffron,https://en.wikipedia.org/wiki/Saffron,,Crocus sativus +sage,https://en.wikipedia.org/wiki/Salvia_officinalis,,Salvia officinalis +salad burnet,https://en.wikipedia.org/wiki/Salad_burnet,,Sanguisorba minor +salsify,https://en.wikipedia.org/wiki/Salsify,,Tragopogon porrifolius +samphire,https://en.wikipedia.org/wiki/Rock_samphire,,Crithmum maritimum +sassafras,https://en.wikipedia.org/wiki/Sassafras_albidum,,Sassafras albidum +sesame,https://en.wikipedia.org/wiki/Sesame,,Sesamum indicum +shallot,https://en.wikipedia.org/wiki/Shallot,,Allium cepa var. aggregatum +sorghum,https://en.wikipedia.org/wiki/Sorghum,,Sorghum spp. +sorrel,https://en.wikipedia.org/wiki/Sorrel,,Rumex acetosa +soursop,https://en.wikipedia.org/wiki/Soursop,,Annona muricata +soybean,https://en.wikipedia.org/wiki/Soybean,,Glycine max +spearmint,https://en.wikipedia.org/wiki/Mentha_spicata,,Mentha spicata +spinach,https://en.wikipedia.org/wiki/Spinach,,Spinacia oleracea +star anise,https://en.wikipedia.org/wiki/Star_anise,,Illicium verum +starfruit,https://en.wikipedia.org/wiki/Starfruit,,Averrhoa carambola +stevia,https://en.wikipedia.org/wiki/Stevia,,Stevia rebaudiana +strawberry,https://en.wikipedia.org/wiki/Strawberry,,Fragaria ananassa +summer savory,https://en.wikipedia.org/wiki/Summer_savory,,Satureja hortensis +sunflowers,https://en.wikipedia.org/wiki/Sunflower,,Helianthus annuus +sweet potato,https://en.wikipedia.org/wiki/Sweet_potato,,Ipomoea batatas +Swiss chard,https://en.wikipedia.org/wiki/Swiss_chard,,Beta vulgaris var. cicla +tamarillo,https://en.wikipedia.org/wiki/Tamarillo,,Solanum betaceum +tamarind,https://en.wikipedia.org/wiki/Tamarind,,Tamarindus indica +tangerine,https://en.wikipedia.org/wiki/Tangerine,,Citrus tangerina +tansy,https://en.wikipedia.org/wiki/Tansy,,Tanacetum vulgare +taro,https://en.wikipedia.org/wiki/Taro,,Colocasia esculenta +tarragon,https://en.wikipedia.org/wiki/Tarragon,,Artemisia dracunculus +thyme,https://en.wikipedia.org/wiki/Thyme,,Thymus mongolicus +tomatillo,https://en.wikipedia.org/wiki/Tomatillo,,Physalis philadelphica +tomato,https://en.wikipedia.org/wiki/Tomato,,Solanum lycopersicum +turmeric,https://en.wikipedia.org/wiki/Turmeric,,Curcuma longa +turnip,https://en.wikipedia.org/wiki/Turnip,,Brassica rapa var. rapa +urad bean,https://en.wikipedia.org/wiki/Urad_(bean),,Vigna mungo +valerian,https://en.wikipedia.org/wiki/Valerian_%28plant%29,,Valeriana officinalis +vanilla,https://en.wikipedia.org/wiki/Vanilla,,Vanilla planifolia +walnut,https://en.wikipedia.org/wiki/Walnut,,Juglans spp. +wasabi,https://en.wikipedia.org/wiki/Wasabi,,Wasabia japonica +watermelon,https://en.wikipedia.org/wiki/Watermelon,,Citrullus lanatus +wheat,https://en.wikipedia.org/wiki/Wheat,,Triticum spp. +winter savory,https://en.wikipedia.org/wiki/Winter_savory,,Satureja montana +wormwood,https://en.wikipedia.org/wiki/Artemisia_absinthium,,Artemisia absinthium +yam,https://en.wikipedia.org/wiki/Yam_(vegetable),,Dioscorea spp. +yardlong bean,https://en.wikipedia.org/wiki/Yardlong_bean,,Vigna unguiculata (sesquipedalis) +yarrow,https://en.wikipedia.org/wiki/Achillea_millefolium,,Achillea millefolium +zucchini,https://en.wikipedia.org/wiki/Zucchini,,Cucurbita pepo. +coffee,https://en.wikipedia.org/wiki/Coffee,,Coffea +tea,https://en.wikipedia.org/wiki/Tea,,Camellia sinensis diff --git a/db/seeds/crops-10-peppers.csv b/db/seeds/crops-10-peppers.csv index 55c3aff62..c0d231519 100644 --- a/db/seeds/crops-10-peppers.csv +++ b/db/seeds/crops-10-peppers.csv @@ -1,61 +1,61 @@ -Capsicum,Capsicum,http://en.wikipedia.org/wiki/Capsicum,,This is the top parent variety -- the entire family of all kinds of peppers -Capsicum annuum,Capsicum annuum,http://en.wikipedia.org/wiki/Capsicum_annuum,Capsicum, -Capsicum baccatum,Capsicum baccatum,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum, -Capsicum chinense,Capsicum chinense,http://en.wikipedia.org/wiki/Capsicum_chinense,Capsicum, -rocoto,Capsicum pubescens,http://en.wikipedia.org/wiki/Capsicum_pubescens,Capsicum,AKA locoto -Capsicum frutescens,Capsicum frutescens,http://en.wikipedia.org/wiki/Capsicum_frutescens,Capsicum, -Aleppo pepper,,http://en.wikipedia.org/wiki/Aleppo_pepper,Capsicum annuum,"AKA pul biber, halaby pepper" -Anaheim pepper,,http://en.wikipedia.org/wiki/Anaheim_pepper,Capsicum annuum,"AKA New Mexico pepper, California chili, Magdalena chili" -banana pepper,,http://en.wikipedia.org/wiki/Banana_pepper,Capsicum annuum,"AKA yellow wax pepper, banana chili" -bell pepper,,http://en.wikipedia.org/wiki/Bell_pepper,Capsicum annuum,"AKA capsicum, sweet pepper, pepper, poivron, peperoni, piment" -bird's eye chili,,http://en.wikipedia.org/wiki/Bird%27s_eye_chili,Capsicum annuum,"AKA Thai chili pepper, bird's chili" -cascabel chili,,http://en.wikipedia.org/wiki/Cascabel_chili,Capsicum annuum,"AKA rattle chile, bola chile, chile bola" -cayenne pepper,,http://en.wikipedia.org/wiki/Cayenne_pepper,Capsicum annuum,"AKA Guinea spice, cow-horn pepper, aleva, bird pepper, red pepper" -pasilla pepper,,http://en.wikipedia.org/wiki/Pasilla,Capsicum annuum,"AKA chilaca pepper, chile negro" -chiltepin pepper,Capsicum annuum var. glabriusculum,http://en.wikipedia.org/wiki/Capsicum_annuum_var._glabriusculum,Capsicum annuum,"AKA wild chiltepin, chiltepe, chile tepin, turkey pepper, bird’s eye pepper, bird pepper" -Chungyang red pepper,,http://en.wikipedia.org/wiki/Chungyang_Red_Pepper,Capsicum annuum, -cubanelle pepper,,http://en.wikipedia.org/wiki/Cubanelle,Capsicum annuum, -chile de árbol pepper,,http://en.wikipedia.org/wiki/Chile_de_%C3%A1rbol,Capsicum annuum,"AKA bird's beak chile, rat's tail chile" -dundicut,,http://en.wikipedia.org/wiki/Dundicut,Capsicum annuum,AKA lal mirch -facing heaven pepper,Capsicum annuum var. conoides,http://en.wikipedia.org/wiki/Facing_heaven_pepper,Capsicum annuum, -Fresno pepper,,http://en.wikipedia.org/wiki/Fresno_pepper,Capsicum annuum, -guajillo pepper,,http://en.wikipedia.org/wiki/Guajillo_chili,Capsicum annuum,"AKA guajillo chili, guajillo chilli, chile guajillo" -Guntur Sannam chili,Capsicum Annuum var. Longhum,http://en.wikipedia.org/wiki/Guntur_Sannam,Capsicum annuum, -Hungarian wax pepper,,http://en.wikipedia.org/wiki/Hungarian_wax_pepper,Capsicum annuum, -Italian sweet pepper,,http://en.wikipedia.org/wiki/Italian_sweet_pepper,Capsicum annuum, -jalapeño pepper,,http://en.wikipedia.org/wiki/Jalape%C3%B1o,Capsicum annuum, -shishito pepper,,http://en.wikipedia.org/wiki/Shishito,Capsicum annuum, -medusa pepper,,http://en.wikipedia.org/wiki/Medusa_pepper,Capsicum annuum, -mulato pepper,,http://en.wikipedia.org/wiki/Mulato_pepper,Capsicum annuum, -peter pepper,Capsicum annuum var. annuum,http://en.wikipedia.org/wiki/Peter_pepper,Capsicum annuum,AKA chilli willy pepper -peperoncini pepper,,http://en.wikipedia.org/wiki/Peperoncini,Capsicum annuum,"AKA friggitello, peperone" -pequin pepper,"Capsicum annuum var. glabriusculum -",http://en.wikipedia.org/wiki/Pequin_pepper,Capsicum annuum,AKA piquin -pimento pepper,,http://en.wikipedia.org/wiki/Pimiento,Capsicum annuum,"AKA cherry pepper, pimiento pepper" -poblano pepper,,http://en.wikipedia.org/wiki/Poblano,Capsicum annuum, -Santa Fe Grande pepper,,http://en.wikipedia.org/wiki/Santa_Fe_Grande_pepper,Capsicum annuum,"AKA yellow hot chili pepper, guero chili pepper" -serrano pepper,,http://en.wikipedia.org/wiki/Serrano_pepper,Capsicum annuum, -bishop's crown pepper,Capsicum baccatum var. pendulum,http://en.wikipedia.org/wiki/Bishop%27s_Crown,Capsicum baccatum,AKA Christmas bell -lemon drop pepper,,http://en.wikipedia.org/wiki/Lemon_drop_%28pepper%29,Capsicum baccatum,"AKA ají limon, kellu uchu, hot lemon" -peppadew pepper,,http://en.wikipedia.org/wiki/Peppadew,Capsicum baccatum, -Brazilian starfish,,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum baccatum, -wild baccatum,,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum baccatum, -adjuma pepper,,http://en.wikipedia.org/wiki/Adjuma,Capsicum chinense,"AKA adjoema, aji umba, ojemma" -ají dulce pepper,,http://en.wikipedia.org/wiki/Aj%C3%AD_dulce,Capsicum chinense,"AKA ajicito, ajice, rubra, biquinho" -datil pepper,,http://en.wikipedia.org/wiki/Datil_pepper,Capsicum chinense, -fatalii pepper,,http://en.wikipedia.org/wiki/Fatalii,Capsicum chinense, -Madame Jeanette pepper,,http://en.wikipedia.org/wiki/Madame_Jeanette,Capsicum chinense, -habanero pepper,,http://en.wikipedia.org/wiki/Habanero,Capsicum chinense,AKA habañero -black habanero pepper,,http://en.wikipedia.org/wiki/Habanero,Capsicum chinense, -red savino pepper,,http://en.wikipedia.org/wiki/Red_Savina_pepper,Capsicum chinense, -bhut jolokia pepper,,http://en.wikipedia.org/wiki/Bhut_Jolokia,Capsicum chinense,"AKA ghost pepper, ghost chili pepper, red naga chilli, ghost chilli, naga jolokia" -Scotch bonnet pepper,,http://en.wikipedia.org/wiki/Scotch_bonnet_%28pepper%29,Capsicum chinense,"AKA boabs bonnet, Scotty bons, Bonney peppers, Caribbean red peppers, ball of fire" -cachucha pepper,,http://en.wikipedia.org/wiki/Scotch_bonnet_%28pepper%29,Capsicum chinense, -Trinidad scorpion butch T pepper,,http://en.wikipedia.org/wiki/Trinidad_Scorpion_Butch_T_pepper,Capsicum chinense, -Trinidad Moruga scorpion pepper,,http://en.wikipedia.org/wiki/Trinidad_Moruga_Scorpion,Capsicum chinense, -Hainan yellow lantern,,http://en.wikipedia.org/wiki/Hainan_Yellow_Lantern_Chili,Capsicum chinense,AKA yellow emperor chili -piri-piri pepper,,http://en.wikipedia.org/wiki/Piri_piri,Capsicum frutescens,"AKA African bird's eye pepper, peri peri, pili pili" -Tabasco pepper,,http://en.wikipedia.org/wiki/Tabasco_pepper,Capsicum frutescens, -malagueta pepper,,http://en.wikipedia.org/wiki/Malagueta_pepper,Capsicum frutescens, -siling labuyo pepper,,http://en.wikipedia.org/wiki/Siling_labuyo,Capsicum frutescens,"AKA chileng bundok, siling palay, pasitis, pasite, katumbal, kitikot, siling kolikot, silit-diablo, lada, rimorimo, paktin" -kambuzi,,http://en.wikipedia.org/wiki/Kambuzi,Capsicum frutescens, +Capsicum,http://en.wikipedia.org/wiki/Capsicum,,Capsicum +Capsicum annuum,http://en.wikipedia.org/wiki/Capsicum_annuum,Capsicum,Capsicum annuum +Capsicum baccatum,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum,Capsicum baccatum +Capsicum chinense,http://en.wikipedia.org/wiki/Capsicum_chinense,Capsicum,Capsicum chinense +rocoto,http://en.wikipedia.org/wiki/Capsicum_pubescens,Capsicum,Capsicum pubescens +Capsicum frutescens,http://en.wikipedia.org/wiki/Capsicum_frutescens,Capsicum,Capsicum frutescens +Aleppo pepper,http://en.wikipedia.org/wiki/Aleppo_pepper,Capsicum annuum, +Anaheim pepper,http://en.wikipedia.org/wiki/Anaheim_pepper,Capsicum annuum, +banana pepper,http://en.wikipedia.org/wiki/Banana_pepper,Capsicum annuum, +bell pepper,http://en.wikipedia.org/wiki/Bell_pepper,Capsicum annuum, +bird's eye chili,http://en.wikipedia.org/wiki/Bird%27s_eye_chili,Capsicum annuum, +cascabel chili,http://en.wikipedia.org/wiki/Cascabel_chili,Capsicum annuum, +cayenne pepper,http://en.wikipedia.org/wiki/Cayenne_pepper,Capsicum annuum, +pasilla pepper,http://en.wikipedia.org/wiki/Pasilla,Capsicum annuum, +chiltepin pepper,http://en.wikipedia.org/wiki/Capsicum_annuum_var._glabriusculum,Capsicum annuum,Capsicum annuum var. glabriusculum +Chungyang red pepper,http://en.wikipedia.org/wiki/Chungyang_Red_Pepper,Capsicum annuum, +cubanelle pepper,http://en.wikipedia.org/wiki/Cubanelle,Capsicum annuum, +chile de árbol pepper,http://en.wikipedia.org/wiki/Chile_de_%C3%A1rbol,Capsicum annuum, +dundicut,http://en.wikipedia.org/wiki/Dundicut,Capsicum annuum, +facing heaven pepper,http://en.wikipedia.org/wiki/Facing_heaven_pepper,Capsicum annuum,Capsicum annuum var. conoides +Fresno pepper,http://en.wikipedia.org/wiki/Fresno_pepper,Capsicum annuum, +guajillo pepper,http://en.wikipedia.org/wiki/Guajillo_chili,Capsicum annuum, +Guntur Sannam chili,http://en.wikipedia.org/wiki/Guntur_Sannam,Capsicum annuum,Capsicum Annuum var. Longhum +Hungarian wax pepper,http://en.wikipedia.org/wiki/Hungarian_wax_pepper,Capsicum annuum, +Italian sweet pepper,http://en.wikipedia.org/wiki/Italian_sweet_pepper,Capsicum annuum, +jalapeño pepper,http://en.wikipedia.org/wiki/Jalape%C3%B1o,Capsicum annuum, +shishito pepper,http://en.wikipedia.org/wiki/Shishito,Capsicum annuum, +medusa pepper,http://en.wikipedia.org/wiki/Medusa_pepper,Capsicum annuum, +mulato pepper,http://en.wikipedia.org/wiki/Mulato_pepper,Capsicum annuum, +peter pepper,http://en.wikipedia.org/wiki/Peter_pepper,Capsicum annuum,Capsicum annuum var. annuum +peperoncini pepper,http://en.wikipedia.org/wiki/Peperoncini,Capsicum annuum, +pequin pepper,http://en.wikipedia.org/wiki/Pequin_pepper,Capsicum annuum,"Capsicum annuum var. glabriusculum +" +pimento pepper,http://en.wikipedia.org/wiki/Pimiento,Capsicum annuum, +poblano pepper,http://en.wikipedia.org/wiki/Poblano,Capsicum annuum, +Santa Fe Grande pepper,http://en.wikipedia.org/wiki/Santa_Fe_Grande_pepper,Capsicum annuum, +serrano pepper,http://en.wikipedia.org/wiki/Serrano_pepper,Capsicum annuum, +bishop's crown pepper,http://en.wikipedia.org/wiki/Bishop%27s_Crown,Capsicum baccatum,Capsicum baccatum var. pendulum +lemon drop pepper,http://en.wikipedia.org/wiki/Lemon_drop_%28pepper%29,Capsicum baccatum, +peppadew pepper,http://en.wikipedia.org/wiki/Peppadew,Capsicum baccatum, +Brazilian starfish,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum baccatum, +wild baccatum,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum baccatum, +adjuma pepper,http://en.wikipedia.org/wiki/Adjuma,Capsicum chinense, +ají dulce pepper,http://en.wikipedia.org/wiki/Aj%C3%AD_dulce,Capsicum chinense, +datil pepper,http://en.wikipedia.org/wiki/Datil_pepper,Capsicum chinense, +fatalii pepper,http://en.wikipedia.org/wiki/Fatalii,Capsicum chinense, +Madame Jeanette pepper,http://en.wikipedia.org/wiki/Madame_Jeanette,Capsicum chinense, +habanero pepper,http://en.wikipedia.org/wiki/Habanero,Capsicum chinense, +black habanero pepper,http://en.wikipedia.org/wiki/Habanero,Capsicum chinense, +red savino pepper,http://en.wikipedia.org/wiki/Red_Savina_pepper,Capsicum chinense, +bhut jolokia pepper,http://en.wikipedia.org/wiki/Bhut_Jolokia,Capsicum chinense, +Scotch bonnet pepper,http://en.wikipedia.org/wiki/Scotch_bonnet_%28pepper%29,Capsicum chinense, +cachucha pepper,http://en.wikipedia.org/wiki/Scotch_bonnet_%28pepper%29,Capsicum chinense, +Trinidad scorpion butch T pepper,http://en.wikipedia.org/wiki/Trinidad_Scorpion_Butch_T_pepper,Capsicum chinense, +Trinidad Moruga scorpion pepper,http://en.wikipedia.org/wiki/Trinidad_Moruga_Scorpion,Capsicum chinense, +Hainan yellow lantern,http://en.wikipedia.org/wiki/Hainan_Yellow_Lantern_Chili,Capsicum chinense, +piri-piri pepper,http://en.wikipedia.org/wiki/Piri_piri,Capsicum frutescens, +Tabasco pepper,http://en.wikipedia.org/wiki/Tabasco_pepper,Capsicum frutescens, +malagueta pepper,http://en.wikipedia.org/wiki/Malagueta_pepper,Capsicum frutescens, +siling labuyo pepper,http://en.wikipedia.org/wiki/Siling_labuyo,Capsicum frutescens, +kambuzi,http://en.wikipedia.org/wiki/Kambuzi,Capsicum frutescens, diff --git a/db/seeds/crops-11-tomatoes.csv b/db/seeds/crops-11-tomatoes.csv index acb39a039..b56ed850a 100644 --- a/db/seeds/crops-11-tomatoes.csv +++ b/db/seeds/crops-11-tomatoes.csv @@ -1,41 +1,41 @@ -adoration tomato,,https://en.wikipedia.org/wiki/Adoration_%28Tomato%29,tomato -alicante tomato,,https://en.wikipedia.org/wiki/Alicante_%28tomato%29,tomato -Amish paste tomato,,http://en.wikipedia.org/wiki/Amish_Paste,tomato -Aunt Ruby's German green tomato,,http://en.wikipedia.org/wiki/Aunt_Ruby%27s_German_Green,tomato -azoychka tomato,,https://en.wikipedia.org/wiki/Azoychka%28Tomato%29,tomato -beefsteak tomato,,https://en.wikipedia.org/wiki/Beefsteak_(tomato),tomato -better boy tomato,,https://en.wikipedia.org/wiki/Better_Boy,tomato -big rainbow tomato,,https://en.wikipedia.org/wiki/Big_Rainbow_(Tomato),tomato -Blaby special tomato,,https://en.wikipedia.org/wiki/Blaby_Special_(Tomato),tomato -black krim tomato,,https://en.wikipedia.org/wiki/Black_Krim_%28tomato%29,tomato -brandywine tomato,,https://en.wikipedia.org/wiki/Brandywine_(tomato),tomato -campari tomato,,https://en.wikipedia.org/wiki/Campari_tomato,tomato -celebrity tomato,,http://en.wikipedia.org/wiki/Celebrity_(tomato),tomato -Cherokee purple tomato,,https://en.wikipedia.org/wiki/Cherokee_purple,tomato -cherry tomato,Solanum lycopersicum var. cerasiforme,http://en.wikipedia.org/wiki/Cherry_tomato,tomato -currant tomato,solanum pimpinellifolium,https://en.wikipedia.org/wiki/Solanum_pimpinellifolium, -early girl tomato,,https://en.wikipedia.org/wiki/Early_Girl,tomato -Fourth of July tomato,,https://en.wikipedia.org/wiki/Fourth_of_July_(tomato_variety),tomato -garden peach tomato,,https://en.wikipedia.org/wiki/Garden_peach_tomato,tomato -grape tomato,,http://en.wikipedia.org/wiki/Grape_tomato,tomato -green zebra tomato,,https://en.wikipedia.org/wiki/Green_Zebra,tomato -Hanover tomato,,http://en.wikipedia.org/wiki/Hanover_tomato,tomato -hillbilly tomato,,http://en.wikipedia.org/wiki/Hillbilly_(tomato),tomato -jubilee tomato,,http://en.wikipedia.org/wiki/Jubilee_(tomato),tomato -lillian's yellow tomato,,http://en.wikipedia.org/wiki/Lillian%27s_Yellow_(tomato),tomato -marglobe tomato,,http://en.wikipedia.org/wiki/Marglobe,tomato -Matt's wild cherry tomato,,http://en.wikipedia.org/wiki/Matt%27s_Wild_Cherry,cherry tomato -mortgage lifter tomato,,http://en.wikipedia.org/wiki/Mortgage_Lifter,tomato -Mr. Stripey tomato,,http://en.wikipedia.org/wiki/Mr._Stripey,tomato -pear tomato,,http://en.wikipedia.org/wiki/Pear_tomato,tomato -Roma tomato,,http://en.wikipedia.org/wiki/Roma_tomato,tomato -San Marzano tomato,,http://en.wikipedia.org/wiki/San_Marzano_tomato,tomato -Santorini tomato,,http://en.wikipedia.org/wiki/Santorini_(tomato),cherry tomato -stupice tomato,,http://en.wikipedia.org/wiki/Super_Sweet_100,tomato -super sweet 100 tomato,,http://en.wikipedia.org/wiki/Super_Sweet_100,cherry tomato -three sisters tomato,,http://en.wikipedia.org/wiki/Three_Sisters_(tomato),tomato -tigerella tomato,,http://en.wikipedia.org/wiki/Tigerella,tomato -tomaccio tomato,,http://en.wikipedia.org/wiki/Tomaccio_(tomato),cherry tomato -tomberry,,http://en.wikipedia.org/wiki/Tomberry,tomato -traveller tomato,,http://en.wikipedia.org/wiki/Traveller_(tomato),tomato -white queen tomato,,http://en.wikipedia.org/wiki/White_Queen_tomato,tomato +adoration tomato,https://en.wikipedia.org/wiki/Adoration_%28Tomato%29,tomato, +alicante tomato,https://en.wikipedia.org/wiki/Alicante_%28tomato%29,tomato, +Amish paste tomato,http://en.wikipedia.org/wiki/Amish_Paste,tomato, +Aunt Ruby's German green tomato,http://en.wikipedia.org/wiki/Aunt_Ruby%27s_German_Green,tomato, +azoychka tomato,https://en.wikipedia.org/wiki/Azoychka%28Tomato%29,tomato, +beefsteak tomato,https://en.wikipedia.org/wiki/Beefsteak_(tomato),tomato, +better boy tomato,https://en.wikipedia.org/wiki/Better_Boy,tomato, +big rainbow tomato,https://en.wikipedia.org/wiki/Big_Rainbow_(Tomato),tomato, +Blaby special tomato,https://en.wikipedia.org/wiki/Blaby_Special_(Tomato),tomato, +black krim tomato,https://en.wikipedia.org/wiki/Black_Krim_%28tomato%29,tomato, +brandywine tomato,https://en.wikipedia.org/wiki/Brandywine_(tomato),tomato, +campari tomato,https://en.wikipedia.org/wiki/Campari_tomato,tomato, +celebrity tomato,http://en.wikipedia.org/wiki/Celebrity_(tomato),tomato, +Cherokee purple tomato,https://en.wikipedia.org/wiki/Cherokee_purple,tomato, +cherry tomato,http://en.wikipedia.org/wiki/Cherry_tomato,tomato,Solanum lycopersicum var. cerasiforme +currant tomato,https://en.wikipedia.org/wiki/Solanum_pimpinellifolium,,solanum pimpinellifolium +early girl tomato,https://en.wikipedia.org/wiki/Early_Girl,tomato, +Fourth of July tomato,https://en.wikipedia.org/wiki/Fourth_of_July_(tomato_variety),tomato, +garden peach tomato,https://en.wikipedia.org/wiki/Garden_peach_tomato,tomato, +grape tomato,http://en.wikipedia.org/wiki/Grape_tomato,tomato, +green zebra tomato,https://en.wikipedia.org/wiki/Green_Zebra,tomato, +Hanover tomato,http://en.wikipedia.org/wiki/Hanover_tomato,tomato, +hillbilly tomato,http://en.wikipedia.org/wiki/Hillbilly_(tomato),tomato, +jubilee tomato,http://en.wikipedia.org/wiki/Jubilee_(tomato),tomato, +lillian's yellow tomato,http://en.wikipedia.org/wiki/Lillian%27s_Yellow_(tomato),tomato, +marglobe tomato,http://en.wikipedia.org/wiki/Marglobe,tomato, +Matt's wild cherry tomato,http://en.wikipedia.org/wiki/Matt%27s_Wild_Cherry,cherry tomato, +mortgage lifter tomato,http://en.wikipedia.org/wiki/Mortgage_Lifter,tomato, +Mr. Stripey tomato,http://en.wikipedia.org/wiki/Mr._Stripey,tomato, +pear tomato,http://en.wikipedia.org/wiki/Pear_tomato,tomato, +Roma tomato,http://en.wikipedia.org/wiki/Roma_tomato,tomato, +San Marzano tomato,http://en.wikipedia.org/wiki/San_Marzano_tomato,tomato, +Santorini tomato,http://en.wikipedia.org/wiki/Santorini_(tomato),cherry tomato, +stupice tomato,http://en.wikipedia.org/wiki/Super_Sweet_100,tomato, +super sweet 100 tomato,http://en.wikipedia.org/wiki/Super_Sweet_100,cherry tomato, +three sisters tomato,http://en.wikipedia.org/wiki/Three_Sisters_(tomato),tomato, +tigerella tomato,http://en.wikipedia.org/wiki/Tigerella,tomato, +tomaccio tomato,http://en.wikipedia.org/wiki/Tomaccio_(tomato),cherry tomato, +tomberry,http://en.wikipedia.org/wiki/Tomberry,tomato, +traveller tomato,http://en.wikipedia.org/wiki/Traveller_(tomato),tomato, +white queen tomato,http://en.wikipedia.org/wiki/White_Queen_tomato,tomato, diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index 661a688a3..1f44f4a89 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -398,9 +398,8 @@ describe Crop do expect(tomato.scientific_names.size).to eq 1 # shouldn't increase now end - it "loads the simplest possible crop" do - tomato_row = "tomato,,http://en.wikipedia.org/wiki/Tomato" + tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato" CSV.parse(tomato_row) do |row| Crop.create_from_csv(row) @@ -413,7 +412,7 @@ describe Crop do end it "loads a crop with a scientific name" do - tomato_row = "tomato,Solanum lycopersicum,http://en.wikipedia.org/wiki/Tomato" + tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,,Solanum lycopersicum" CSV.parse(tomato_row) do |row| Crop.create_from_csv(row) @@ -427,7 +426,7 @@ describe Crop do it "loads a crop with a parent" do parent = FactoryGirl.create(:crop, :name => 'parent') - tomato_row = "tomato,,http://en.wikipedia.org/wiki/Tomato,parent" + tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,parent" CSV.parse(tomato_row) do |row| Crop.create_from_csv(row) @@ -438,7 +437,7 @@ describe Crop do end it "doesn't add unnecessary duplicate crops" do - tomato_row = "tomato,Solanum lycopersicum,http://en.wikipedia.org/wiki/Tomato" + tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,,Solanum lycopersicum" CSV.parse(tomato_row) do |row| Crop.create_from_csv(row) From 13c98eac895c8694002299b0b0429f070a90839f Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Sun, 30 Nov 2014 15:14:56 +1100 Subject: [PATCH 042/143] Wrapped tests around context blocks to clarify the purpose of the tests. --- spec/models/member_spec.rb | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 5594c9dbd..b15f022fc 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -389,20 +389,24 @@ describe 'member' do @follow = @member1.follows.create(:follower_id => @member1.id, :followed_id => @member2.id) end - it 'detects that member is already following a member' do - expect(@member1.already_following?(@member2)).to eq true + context 'already_following' do + it 'detects that member is already following a member' do + expect(@member1.already_following?(@member2)).to eq true + end + + it 'detects that member is not already following a member' do + expect(@member1.already_following?(@member3)).to eq false + end end - it 'detects that member is not already following a member' do - expect(@member1.already_following?(@member3)).to eq false - end + context 'get_follow' do + it 'gets the correct follow for a followed member' do + expect(@member1.get_follow(@member2).id).to eq @follow.id + end - it 'gets the correct follow for a followed member' do - expect(@member1.get_follow(@member2).id).to eq @follow.id - end - - it 'returns nil for a member that is not followed' do - expect(@member1.get_follow(@member3)).to be_nil + it 'returns nil for a member that is not followed' do + expect(@member1.get_follow(@member3)).to be_nil + end end end From 2036a0f2e9e58c622285140eb24e7b643984895e Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Sun, 30 Nov 2014 15:18:13 +1100 Subject: [PATCH 043/143] Used environment variable for site name instead --- app/models/follow.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/follow.rb b/app/models/follow.rb index 55b2ce95c..f8767c10c 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -9,7 +9,7 @@ class Follow < ActiveRecord::Base :recipient_id => self.followed_id, :sender_id => self.follower_id, :subject => "#{self.follower.login_name} is now following you", - :body => "#{self.follower.login_name} just followed you on Growstuff. " + :body => "#{self.follower.login_name} just followed you on #{ENV["GROWSTUFF_SITE_NAME"]}. " ) end From 7ddaca6e11faeb496cc88fcad9db6359fdd39fec Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Sun, 30 Nov 2014 15:19:50 +1100 Subject: [PATCH 044/143] Use .size instead of .count --- app/views/members/_stats.html.haml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/members/_stats.html.haml b/app/views/members/_stats.html.haml index 0929e5998..b6e52873d 100644 --- a/app/views/members/_stats.html.haml +++ b/app/views/members/_stats.html.haml @@ -3,34 +3,34 @@ %ul %li - if member.plantings.count > 0 - = link_to pluralize(member.plantings.count, "planting"), plantings_by_owner_path(:owner => member) + = link_to pluralize(member.plantings.size, "planting"), plantings_by_owner_path(:owner => member) - else 0 plantings %li - if member.harvests.count > 0 - = link_to pluralize(member.harvests.count, "harvest"), harvests_by_owner_path(:owner => member) + = link_to pluralize(member.harvests.size, "harvest"), harvests_by_owner_path(:owner => member) - else 0 harvests %li - if member.seeds.count > 0 - = link_to pluralize(member.seeds.count, "seeds"), seeds_by_owner_path(:owner => member) + = link_to pluralize(member.seeds.size, "seeds"), seeds_by_owner_path(:owner => member) - else 0 seeds %li - if member.posts.count > 0 - = link_to pluralize(member.posts.count, "post"), posts_by_author_path(:author => member) + = link_to pluralize(member.posts.size, "post"), posts_by_author_path(:author => member) - else 0 posts %li - if member.followed.count > 0 - = link_to pluralize(member.followed.count, "follow"), member_follows_path(member) + = link_to pluralize(member.followed.size, "follow"), member_follows_path(member) - else 0 following %li - if member.followers.count > 0 - = link_to pluralize(member.followers.count, "follower"), member_followers_path(member) + = link_to pluralize(member.followers.size, "follower"), member_followers_path(member) - else 0 followers From 73d6b5065b29d4937c1b3f0d7815073049f4165c Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Sun, 30 Nov 2014 15:25:48 +1100 Subject: [PATCH 045/143] Use factorygirl aliases --- spec/factories/follows.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/factories/follows.rb b/spec/factories/follows.rb index d9bd13616..6de32b7a1 100644 --- a/spec/factories/follows.rb +++ b/spec/factories/follows.rb @@ -1,7 +1,7 @@ FactoryGirl.define do factory :follow do - follower_id 1 - followed_id 2 + follower + followed end end From 844791ead9b1d4f4e8b88965e61eafe9ad08a655 Mon Sep 17 00:00:00 2001 From: Skud Date: Sun, 30 Nov 2014 15:48:58 +1100 Subject: [PATCH 046/143] Allow multiple comma-separated scientific names --- app/models/crop.rb | 38 +++++++++++++++++---------------- spec/models/crop_spec.rb | 45 ++++++++++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 5f4758366..f2a182472 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -127,7 +127,7 @@ class Crop < ActiveRecord::Base # - scientific name (optional, can be picked up from parent if it has one) def Crop.create_from_csv(row) - name,en_wikipedia_url,parent,scientific_name = row + name,en_wikipedia_url,parent,scientific_names = row cropbot = Member.find_by_login_name('cropbot') raise "cropbot account not found: run rake db:seed" unless cropbot @@ -147,31 +147,33 @@ class Crop < ActiveRecord::Base end end - crop.add_scientific_name_from_csv(scientific_name) + crop.add_scientific_names_from_csv(scientific_names) end - def add_scientific_name_from_csv(scientific_name) - name_to_add = nil - if ! scientific_name.blank? # i.e. we actually passed one in, which isn't a given - name_to_add = scientific_name - elsif parent && parent.default_scientific_name - name_to_add = parent.default_scientific_name + def add_scientific_names_from_csv(scientific_names) + names_to_add = [] + if ! scientific_names.blank? # i.e. we actually passed something in, which isn't a given + names_to_add = scientific_names.split(%r{,\s*}) + elsif parent && parent.scientific_names.size > 0 # pick up from parent + names_to_add = parent.scientific_names.map{|s| s.scientific_name} else logger.warn("Warning: no scientific name (not even on parent crop) for #{self}") end - if name_to_add - if scientific_names.exists?(:scientific_name => name_to_add) - logger.warn("Warning: skipping duplicate scientific name #{name_to_add} for #{self}") - else - cropbot = Member.find_by_login_name('cropbot') - raise "cropbot account not found: run rake db:seed" unless cropbot + if names_to_add.size > 0 + names_to_add.each do |n| + if self.scientific_names.exists?(:scientific_name => n) + logger.warn("Warning: skipping duplicate scientific name #{n} for #{self}") + else + cropbot = Member.find_by_login_name('cropbot') + raise "cropbot account not found: run rake db:seed" unless cropbot - scientific_names.create( - :scientific_name => name_to_add, - :creator_id => cropbot.id - ) + self.scientific_names.create( + :scientific_name => n, + :creator_id => cropbot.id + ) + end end end diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index 1f44f4a89..0c41a343f 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -354,14 +354,14 @@ describe Crop do it "adds a scientific name to a crop that has none" do tomato = FactoryGirl.create(:tomato) expect(tomato.scientific_names.size).to eq 0 - tomato.add_scientific_name_from_csv("Foo bar") + tomato.add_scientific_names_from_csv("Foo bar") expect(tomato.scientific_names.size).to eq 1 expect(tomato.default_scientific_name).to eq "Foo bar" end it "picks up scientific name from parent crop if available" do parent = FactoryGirl.create(:crop, :name => 'parent crop') - parent.add_scientific_name_from_csv("Parentis cropis") + parent.add_scientific_names_from_csv("Parentis cropis") parent.save parent.reload @@ -369,32 +369,32 @@ describe Crop do expect(tomato.parent).to eq parent expect(tomato.parent.default_scientific_name).to eq "Parentis cropis" - tomato.add_scientific_name_from_csv('') + tomato.add_scientific_names_from_csv('') expect(tomato.default_scientific_name).to eq "Parentis cropis" end it "doesn't add a duplicate scientific name" do tomato = FactoryGirl.create(:tomato) expect(tomato.scientific_names.size).to eq 0 - tomato.add_scientific_name_from_csv("Foo bar") + tomato.add_scientific_names_from_csv("Foo bar") expect(tomato.scientific_names.size).to eq 1 - tomato.add_scientific_name_from_csv("Foo bar") + tomato.add_scientific_names_from_csv("Foo bar") expect(tomato.scientific_names.size).to eq 1 # shouldn't increase - tomato.add_scientific_name_from_csv("Baz quux") + tomato.add_scientific_names_from_csv("Baz quux") expect(tomato.scientific_names.size).to eq 2 end it "doesn't add a duplicate scientific name from parent" do parent = FactoryGirl.create(:crop, :name => 'parent') - parent.add_scientific_name_from_csv("Parentis cropis") + parent.add_scientific_names_from_csv("Parentis cropis") parent.save parent.reload tomato = FactoryGirl.create(:tomato, :parent => parent) expect(tomato.scientific_names.size).to eq 0 - tomato.add_scientific_name_from_csv('') + tomato.add_scientific_names_from_csv('') expect(tomato.scientific_names.size).to eq 1 # picks up parent SN - tomato.add_scientific_name_from_csv('') + tomato.add_scientific_names_from_csv('') expect(tomato.scientific_names.size).to eq 1 # shouldn't increase now end @@ -424,6 +424,33 @@ describe Crop do expect(loaded.scientific_names.last.scientific_name).to eq "Solanum lycopersicum" end + it "loads a crop with multiple scientific names" do + tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,,\"Foo, Bar\"" + CSV.parse(tomato_row) do |row| + Crop.create_from_csv(row) + end + + loaded = Crop.last + expect(loaded.name).to eq "tomato" + expect(loaded.scientific_names.size).to eq 2 + expect(loaded.scientific_names.first.scientific_name).to eq "Foo" + expect(loaded.scientific_names.last.scientific_name).to eq "Bar" + end + + it "loads multiple scientific names with variant spacing" do + tomato_row = "tomato2,http://en.wikipedia.org/wiki/Tomato,,\"Foo,Bar\"" # no space + CSV.parse(tomato_row) do |row| + Crop.create_from_csv(row) + end + expect(Crop.last.scientific_names.size).to eq 2 + + tomato_row = "tomato3,http://en.wikipedia.org/wiki/Tomato,,\"Foo, Bar\"" # double space + CSV.parse(tomato_row) do |row| + Crop.create_from_csv(row) + end + expect(Crop.last.scientific_names.size).to eq 2 + end + it "loads a crop with a parent" do parent = FactoryGirl.create(:crop, :name => 'parent') tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,parent" From b06d48091e0e78b7e3d9497e224acd244f23cb26 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Sun, 30 Nov 2014 15:50:13 +1100 Subject: [PATCH 047/143] Indentation problem --- spec/models/follow_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb index 3b672af34..27b42de15 100644 --- a/spec/models/follow_spec.rb +++ b/spec/models/follow_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' describe Follow do - before(:each) do - @member1 = FactoryGirl.create(:member) - @member2 = FactoryGirl.create(:member) - end + before(:each) do + @member1 = FactoryGirl.create(:member) + @member2 = FactoryGirl.create(:member) + end it "sends a notification when a follow is created" do expect { From d174f25d039ebfd6a33be791b12b9fc717153482 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 30 Nov 2014 16:06:06 +1100 Subject: [PATCH 048/143] order messages to be most recent --- app/mailers/notifier.rb | 4 +- app/views/layouts/_header.html.haml | 2 +- app/views/layouts/_meta.html.haml | 2 +- db/schema.rb | 279 ++++++++++++++-------------- 4 files changed, 145 insertions(+), 142 deletions(-) diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb index 750b4ab16..0d6aa6db3 100644 --- a/app/mailers/notifier.rb +++ b/app/mailers/notifier.rb @@ -13,8 +13,8 @@ class Notifier < ActionMailer::Base def planting_reminder(member) @member = member - @plantings = @member.plantings.last(5) - @harvests = @member.harvests.last(5) + @plantings = @member.plantings.first(5) + @harvests = @member.harvests.first(5) if @member.send_planting_reminder mail(:to => @member.email, diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index d68f6dc73..691de3681 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -9,7 +9,7 @@ %span.icon-bar %span.icon-bar %a.navbar-brand(href=root_path) - = image_tag("/assets/growstuff-brand.png", :size => "200x50", :alt => ENV['GROWSTUFF_SITE_NAME']) + = image_tag("growstuff-brand.png", :size => "200x50", :alt => ENV['GROWSTUFF_SITE_NAME']) .navbar-collapse.collapse#navbar-collapse %ul.nav.navbar-nav %li.dropdown< diff --git a/app/views/layouts/_meta.html.haml b/app/views/layouts/_meta.html.haml index c5313fb8d..fec08061a 100644 --- a/app/views/layouts/_meta.html.haml +++ b/app/views/layouts/_meta.html.haml @@ -17,4 +17,4 @@ = stylesheet_link_tag "application", :media => "all" %link(href="/assets/growstuff-apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed") - = favicon_link_tag '/assets/favicon.ico' + = favicon_link_tag 'favicon.ico' diff --git a/db/schema.rb b/db/schema.rb index 39a68cab2..f5b159089 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,96 +9,99 @@ # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # -# It's strongly recommended to check this file into your version control system. +# It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(:version => 20141018111015) do +ActiveRecord::Schema.define(version: 20141018111015) do - create_table "account_types", :force => true do |t| - t.string "name", :null => false + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "account_types", force: true do |t| + t.string "name", null: false t.boolean "is_paid" t.boolean "is_permanent_paid" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "accounts", :force => true do |t| - t.integer "member_id", :null => false + create_table "accounts", force: true do |t| + t.integer "member_id", null: false t.integer "account_type_id" t.datetime "paid_until" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "alternate_names", :force => true do |t| - t.string "name", :null => false - t.integer "crop_id", :null => false - t.integer "creator_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "alternate_names", force: true do |t| + t.string "name", null: false + t.integer "crop_id", null: false + t.integer "creator_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "authentications", :force => true do |t| - t.integer "member_id", :null => false - t.string "provider", :null => false + create_table "authentications", force: true do |t| + t.integer "member_id", null: false + t.string "provider", null: false t.string "uid" t.string "token" t.string "secret" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "name" end - add_index "authentications", ["member_id"], :name => "index_authentications_on_member_id" + add_index "authentications", ["member_id"], name: "index_authentications_on_member_id", using: :btree - create_table "comments", :force => true do |t| - t.integer "post_id", :null => false - t.integer "author_id", :null => false - t.text "body", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "comments", force: true do |t| + t.integer "post_id", null: false + t.integer "author_id", null: false + t.text "body", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "crops", :force => true do |t| - t.string "name", :null => false + create_table "crops", force: true do |t| + t.string "name", null: false t.string "en_wikipedia_url" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "slug" t.integer "parent_id" - t.integer "plantings_count", :default => 0 + t.integer "plantings_count", default: 0 t.integer "creator_id" end - add_index "crops", ["name"], :name => "index_crops_on_name" - add_index "crops", ["slug"], :name => "index_crops_on_slug", :unique => true + add_index "crops", ["name"], name: "index_crops_on_name", using: :btree + add_index "crops", ["slug"], name: "index_crops_on_slug", unique: true, using: :btree - create_table "crops_posts", :id => false, :force => true do |t| + create_table "crops_posts", id: false, force: true do |t| t.integer "crop_id" t.integer "post_id" end - add_index "crops_posts", ["crop_id", "post_id"], :name => "index_crops_posts_on_crop_id_and_post_id" - add_index "crops_posts", ["crop_id"], :name => "index_crops_posts_on_crop_id" + add_index "crops_posts", ["crop_id", "post_id"], name: "index_crops_posts_on_crop_id_and_post_id", using: :btree + add_index "crops_posts", ["crop_id"], name: "index_crops_posts_on_crop_id", using: :btree - create_table "forums", :force => true do |t| - t.string "name", :null => false - t.text "description", :null => false - t.integer "owner_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "forums", force: true do |t| + t.string "name", null: false + t.text "description", null: false + t.integer "owner_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "slug" end - add_index "forums", ["slug"], :name => "index_forums_on_slug", :unique => true + add_index "forums", ["slug"], name: "index_forums_on_slug", unique: true, using: :btree - create_table "gardens", :force => true do |t| - t.string "name", :null => false + create_table "gardens", force: true do |t| + t.string "name", null: false t.integer "owner_id" - t.string "slug", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.string "slug", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.text "description" - t.boolean "active", :default => true + t.boolean "active", default: true t.string "location" t.float "latitude" t.float "longitude" @@ -106,38 +109,38 @@ ActiveRecord::Schema.define(:version => 20141018111015) do t.string "area_unit" end - add_index "gardens", ["owner_id"], :name => "index_gardens_on_user_id" - add_index "gardens", ["slug"], :name => "index_gardens_on_slug", :unique => true + add_index "gardens", ["owner_id"], name: "index_gardens_on_user_id", using: :btree + add_index "gardens", ["slug"], name: "index_gardens_on_slug", unique: true, using: :btree - create_table "harvests", :force => true do |t| - t.integer "crop_id", :null => false - t.integer "owner_id", :null => false + create_table "harvests", force: true do |t| + t.integer "crop_id", null: false + t.integer "owner_id", null: false t.date "harvested_at" t.decimal "quantity" t.string "unit" t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "slug" t.decimal "weight_quantity" t.string "weight_unit" t.integer "plant_part_id" end - create_table "harvests_photos", :id => false, :force => true do |t| + create_table "harvests_photos", id: false, force: true do |t| t.integer "photo_id" t.integer "harvest_id" end - add_index "harvests_photos", ["harvest_id", "photo_id"], :name => "index_harvests_photos_on_harvest_id_and_photo_id" + add_index "harvests_photos", ["harvest_id", "photo_id"], name: "index_harvests_photos_on_harvest_id_and_photo_id", using: :btree - create_table "members", :force => true do |t| - t.string "email", :default => "", :null => false - t.string "encrypted_password", :default => "", :null => false + create_table "members", force: true do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", :default => 0 + t.integer "sign_in_count", default: 0 t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" t.string "current_sign_in_ip" @@ -146,11 +149,11 @@ ActiveRecord::Schema.define(:version => 20141018111015) do t.datetime "confirmed_at" t.datetime "confirmation_sent_at" t.string "unconfirmed_email" - t.integer "failed_attempts", :default => 0 + t.integer "failed_attempts", default: 0 t.string "unlock_token" t.datetime "locked_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "login_name" t.string "slug" t.boolean "tos_agreement" @@ -158,47 +161,47 @@ ActiveRecord::Schema.define(:version => 20141018111015) do t.string "location" t.float "latitude" t.float "longitude" - t.boolean "send_notification_email", :default => true + t.boolean "send_notification_email", default: true t.text "bio" t.integer "plantings_count" t.boolean "newsletter" - t.boolean "send_planting_reminder", :default => true + t.boolean "send_planting_reminder", default: true end - add_index "members", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true - add_index "members", ["email"], :name => "index_users_on_email", :unique => true - add_index "members", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true - add_index "members", ["slug"], :name => "index_users_on_slug", :unique => true - add_index "members", ["unlock_token"], :name => "index_users_on_unlock_token", :unique => true + add_index "members", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree + add_index "members", ["email"], name: "index_users_on_email", unique: true, using: :btree + add_index "members", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree + add_index "members", ["slug"], name: "index_users_on_slug", unique: true, using: :btree + add_index "members", ["unlock_token"], name: "index_users_on_unlock_token", unique: true, using: :btree - create_table "members_roles", :id => false, :force => true do |t| + create_table "members_roles", id: false, force: true do |t| t.integer "member_id" t.integer "role_id" end - create_table "notifications", :force => true do |t| + create_table "notifications", force: true do |t| t.integer "sender_id" - t.integer "recipient_id", :null => false + t.integer "recipient_id", null: false t.string "subject" t.text "body" - t.boolean "read", :default => false + t.boolean "read", default: false t.integer "post_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "order_items", :force => true do |t| + create_table "order_items", force: true do |t| t.integer "order_id" t.integer "product_id" t.integer "price" t.integer "quantity" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "orders", :force => true do |t| - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "orders", force: true do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.datetime "completed_at" t.integer "member_id" t.string "paypal_express_token" @@ -206,108 +209,108 @@ ActiveRecord::Schema.define(:version => 20141018111015) do t.string "referral_code" end - create_table "orders_products", :id => false, :force => true do |t| + create_table "orders_products", id: false, force: true do |t| t.integer "order_id" t.integer "product_id" end - create_table "photos", :force => true do |t| - t.integer "owner_id", :null => false - t.string "thumbnail_url", :null => false - t.string "fullsize_url", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "title", :null => false - t.string "license_name", :null => false + create_table "photos", force: true do |t| + t.integer "owner_id", null: false + t.string "thumbnail_url", null: false + t.string "fullsize_url", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "title", null: false + t.string "license_name", null: false t.string "license_url" - t.string "link_url", :null => false + t.string "link_url", null: false t.string "flickr_photo_id" end - create_table "photos_plantings", :id => false, :force => true do |t| + create_table "photos_plantings", id: false, force: true do |t| t.integer "photo_id" t.integer "planting_id" end - create_table "plant_parts", :force => true do |t| + create_table "plant_parts", force: true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "slug" end - create_table "plantings", :force => true do |t| - t.integer "garden_id", :null => false - t.integer "crop_id", :null => false + create_table "plantings", force: true do |t| + t.integer "garden_id", null: false + t.integer "crop_id", null: false t.date "planted_at" t.integer "quantity" t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "slug" t.string "sunniness" t.string "planted_from" t.integer "owner_id" - t.boolean "finished", :default => false + t.boolean "finished", default: false t.date "finished_at" end - add_index "plantings", ["slug"], :name => "index_plantings_on_slug", :unique => true + add_index "plantings", ["slug"], name: "index_plantings_on_slug", unique: true, using: :btree - create_table "posts", :force => true do |t| - t.integer "author_id", :null => false - t.string "subject", :null => false - t.text "body", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "posts", force: true do |t| + t.integer "author_id", null: false + t.string "subject", null: false + t.text "body", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "slug" t.integer "forum_id" end - add_index "posts", ["created_at", "author_id"], :name => "index_updates_on_created_at_and_user_id" - add_index "posts", ["slug"], :name => "index_updates_on_slug", :unique => true + add_index "posts", ["created_at", "author_id"], name: "index_updates_on_created_at_and_user_id", using: :btree + add_index "posts", ["slug"], name: "index_updates_on_slug", unique: true, using: :btree - create_table "products", :force => true do |t| - t.string "name", :null => false - t.text "description", :null => false - t.integer "min_price", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "products", force: true do |t| + t.string "name", null: false + t.text "description", null: false + t.integer "min_price", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "account_type_id" t.integer "paid_months" t.integer "recommended_price" end - create_table "roles", :force => true do |t| - t.string "name", :null => false + create_table "roles", force: true do |t| + t.string "name", null: false t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "slug" end - add_index "roles", ["slug"], :name => "index_roles_on_slug", :unique => true + add_index "roles", ["slug"], name: "index_roles_on_slug", unique: true, using: :btree - create_table "scientific_names", :force => true do |t| - t.string "scientific_name", :null => false - t.integer "crop_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "scientific_names", force: true do |t| + t.string "scientific_name", null: false + t.integer "crop_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "creator_id" end - create_table "seeds", :force => true do |t| - t.integer "owner_id", :null => false - t.integer "crop_id", :null => false + create_table "seeds", force: true do |t| + t.integer "owner_id", null: false + t.integer "crop_id", null: false t.text "description" t.integer "quantity" t.date "plant_before" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "tradable_to", :default => "nowhere" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "tradable_to", default: "nowhere" t.string "slug" end - add_index "seeds", ["slug"], :name => "index_seeds_on_slug", :unique => true + add_index "seeds", ["slug"], name: "index_seeds_on_slug", unique: true, using: :btree end From 593a20c0c58e28f6bfc9d971c78d78dc4be0bee0 Mon Sep 17 00:00:00 2001 From: Skud Date: Sun, 30 Nov 2014 16:06:43 +1100 Subject: [PATCH 049/143] Load alternate names from CSV --- app/models/crop.rb | 29 ++++++- spec/models/crop_spec.rb | 163 +++++++++++++++++++++++++-------------- 2 files changed, 130 insertions(+), 62 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index f2a182472..b63f9a8a5 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -127,7 +127,7 @@ class Crop < ActiveRecord::Base # - scientific name (optional, can be picked up from parent if it has one) def Crop.create_from_csv(row) - name,en_wikipedia_url,parent,scientific_names = row + name,en_wikipedia_url,parent,scientific_names,alternate_names = row cropbot = Member.find_by_login_name('cropbot') raise "cropbot account not found: run rake db:seed" unless cropbot @@ -148,6 +148,7 @@ class Crop < ActiveRecord::Base end crop.add_scientific_names_from_csv(scientific_names) + crop.add_alternate_names_from_csv(alternate_names) end @@ -162,12 +163,13 @@ class Crop < ActiveRecord::Base end if names_to_add.size > 0 + cropbot = Member.find_by_login_name('cropbot') + raise "cropbot account not found: run rake db:seed" unless cropbot + names_to_add.each do |n| if self.scientific_names.exists?(:scientific_name => n) logger.warn("Warning: skipping duplicate scientific name #{n} for #{self}") else - cropbot = Member.find_by_login_name('cropbot') - raise "cropbot account not found: run rake db:seed" unless cropbot self.scientific_names.create( :scientific_name => n, @@ -176,7 +178,28 @@ class Crop < ActiveRecord::Base end end end + end + def add_alternate_names_from_csv(alternate_names) + names_to_add = [] + if ! alternate_names.blank? # i.e. we actually passed something in, which isn't a given + cropbot = Member.find_by_login_name('cropbot') + raise "cropbot account not found: run rake db:seed" unless cropbot + + names_to_add = alternate_names.split(%r{,\s*}) + + names_to_add.each do |n| + if self.alternate_names.exists?(:name => n) + logger.warn("Warning: skipping duplicate alternate name #{n} for #{self}") + else + self.alternate_names.create( + :name => n, + :creator_id => cropbot.id + ) + end + end + + end end # Crop.search(string) diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index 0c41a343f..5bd7d01ba 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -351,52 +351,111 @@ describe Crop do @cropbot = FactoryGirl.create(:cropbot) end - it "adds a scientific name to a crop that has none" do - tomato = FactoryGirl.create(:tomato) - expect(tomato.scientific_names.size).to eq 0 - tomato.add_scientific_names_from_csv("Foo bar") - expect(tomato.scientific_names.size).to eq 1 - expect(tomato.default_scientific_name).to eq "Foo bar" - end + context "scientific names" do - it "picks up scientific name from parent crop if available" do - parent = FactoryGirl.create(:crop, :name => 'parent crop') - parent.add_scientific_names_from_csv("Parentis cropis") - parent.save - parent.reload + it "adds a scientific name to a crop that has none" do + tomato = FactoryGirl.create(:tomato) + expect(tomato.scientific_names.size).to eq 0 + tomato.add_scientific_names_from_csv("Foo bar") + expect(tomato.scientific_names.size).to eq 1 + expect(tomato.default_scientific_name).to eq "Foo bar" + end - tomato = FactoryGirl.create(:tomato, :parent => parent) - expect(tomato.parent).to eq parent - expect(tomato.parent.default_scientific_name).to eq "Parentis cropis" + it "picks up scientific name from parent crop if available" do + parent = FactoryGirl.create(:crop, :name => 'parent crop') + parent.add_scientific_names_from_csv("Parentis cropis") + parent.save + parent.reload - tomato.add_scientific_names_from_csv('') - expect(tomato.default_scientific_name).to eq "Parentis cropis" - end + tomato = FactoryGirl.create(:tomato, :parent => parent) + expect(tomato.parent).to eq parent + expect(tomato.parent.default_scientific_name).to eq "Parentis cropis" - it "doesn't add a duplicate scientific name" do - tomato = FactoryGirl.create(:tomato) - expect(tomato.scientific_names.size).to eq 0 - tomato.add_scientific_names_from_csv("Foo bar") - expect(tomato.scientific_names.size).to eq 1 - tomato.add_scientific_names_from_csv("Foo bar") - expect(tomato.scientific_names.size).to eq 1 # shouldn't increase - tomato.add_scientific_names_from_csv("Baz quux") - expect(tomato.scientific_names.size).to eq 2 - end + tomato.add_scientific_names_from_csv('') + expect(tomato.default_scientific_name).to eq "Parentis cropis" + end - it "doesn't add a duplicate scientific name from parent" do - parent = FactoryGirl.create(:crop, :name => 'parent') - parent.add_scientific_names_from_csv("Parentis cropis") - parent.save - parent.reload + it "doesn't add a duplicate scientific name" do + tomato = FactoryGirl.create(:tomato) + expect(tomato.scientific_names.size).to eq 0 + tomato.add_scientific_names_from_csv("Foo bar") + expect(tomato.scientific_names.size).to eq 1 + tomato.add_scientific_names_from_csv("Foo bar") + expect(tomato.scientific_names.size).to eq 1 # shouldn't increase + tomato.add_scientific_names_from_csv("Baz quux") + expect(tomato.scientific_names.size).to eq 2 + end - tomato = FactoryGirl.create(:tomato, :parent => parent) - expect(tomato.scientific_names.size).to eq 0 - tomato.add_scientific_names_from_csv('') - expect(tomato.scientific_names.size).to eq 1 # picks up parent SN - tomato.add_scientific_names_from_csv('') - expect(tomato.scientific_names.size).to eq 1 # shouldn't increase now - end + it "doesn't add a duplicate scientific name from parent" do + parent = FactoryGirl.create(:crop, :name => 'parent') + parent.add_scientific_names_from_csv("Parentis cropis") + parent.save + parent.reload + + tomato = FactoryGirl.create(:tomato, :parent => parent) + expect(tomato.scientific_names.size).to eq 0 + tomato.add_scientific_names_from_csv('') + expect(tomato.scientific_names.size).to eq 1 # picks up parent SN + tomato.add_scientific_names_from_csv('') + expect(tomato.scientific_names.size).to eq 1 # shouldn't increase now + end + + it "loads a crop with multiple scientific names" do + tomato = FactoryGirl.create(:tomato) + expect(tomato.scientific_names.size).to eq 0 + tomato.add_scientific_names_from_csv("Foo, Bar") + expect(tomato.scientific_names.size).to eq 2 + expect(tomato.scientific_names[0].scientific_name).to eq "Foo" + expect(tomato.scientific_names[1].scientific_name).to eq "Bar" + end + + it "loads multiple scientific names with variant spacing" do + tomato = FactoryGirl.create(:tomato) + expect(tomato.scientific_names.size).to eq 0 + tomato.add_scientific_names_from_csv("Foo,Bar") # no space + expect(tomato.scientific_names.size).to eq 2 + tomato.add_scientific_names_from_csv("Baz, Quux") # multiple spaces + expect(tomato.scientific_names.size).to eq 4 + end + + end # scientific names + + context "alternate names" do + it "loads an alternate name" do + tomato = FactoryGirl.create(:tomato) + expect(tomato.alternate_names.size).to eq 0 + tomato.add_alternate_names_from_csv("Foo") + expect(tomato.alternate_names.size).to eq 1 + expect(tomato.alternate_names.last.name).to eq "Foo" + end + + it "doesn't load duplicate alternate names" do + tomato = FactoryGirl.create(:tomato) + expect(tomato.alternate_names.size).to eq 0 + tomato.add_alternate_names_from_csv("Foo") + expect(tomato.alternate_names.size).to eq 1 + tomato.add_alternate_names_from_csv("Foo") + expect(tomato.alternate_names.size).to eq 1 # still 1, doesn't add another + end + + it "adds multiple alternate names" do + tomato = FactoryGirl.create(:tomato) + expect(tomato.alternate_names.size).to eq 0 + tomato.add_alternate_names_from_csv("Foo, Bar") + expect(tomato.alternate_names.size).to eq 2 + expect(tomato.alternate_names[0].name).to eq "Foo" + expect(tomato.alternate_names[1].name).to eq "Bar" + end + + it "adds multiple alt names with variant spacing" do + tomato = FactoryGirl.create(:tomato) + expect(tomato.alternate_names.size).to eq 0 + tomato.add_alternate_names_from_csv("Foo,Bar") # no space + expect(tomato.alternate_names.size).to eq 2 + tomato.add_alternate_names_from_csv("Baz, Quux") # mutliple spaces + expect(tomato.alternate_names.size).to eq 4 + end + end # alternate names it "loads the simplest possible crop" do tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato" @@ -424,31 +483,17 @@ describe Crop do expect(loaded.scientific_names.last.scientific_name).to eq "Solanum lycopersicum" end - it "loads a crop with multiple scientific names" do - tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,,\"Foo, Bar\"" + it "loads a crop with an alternate name" do + tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,,,Foo" + CSV.parse(tomato_row) do |row| Crop.create_from_csv(row) end loaded = Crop.last expect(loaded.name).to eq "tomato" - expect(loaded.scientific_names.size).to eq 2 - expect(loaded.scientific_names.first.scientific_name).to eq "Foo" - expect(loaded.scientific_names.last.scientific_name).to eq "Bar" - end - - it "loads multiple scientific names with variant spacing" do - tomato_row = "tomato2,http://en.wikipedia.org/wiki/Tomato,,\"Foo,Bar\"" # no space - CSV.parse(tomato_row) do |row| - Crop.create_from_csv(row) - end - expect(Crop.last.scientific_names.size).to eq 2 - - tomato_row = "tomato3,http://en.wikipedia.org/wiki/Tomato,,\"Foo, Bar\"" # double space - CSV.parse(tomato_row) do |row| - Crop.create_from_csv(row) - end - expect(Crop.last.scientific_names.size).to eq 2 + expect(loaded.alternate_names.size).to eq 1 + expect(loaded.alternate_names.last.name).to eq "Foo" end it "loads a crop with a parent" do From 82a5379a256fb5a9666211352a90e52d50b00e5d Mon Sep 17 00:00:00 2001 From: Skud Date: Mon, 1 Dec 2014 20:53:17 +1100 Subject: [PATCH 050/143] Added mint family and brassica crops (seed files) --- db/seeds/crops-12-mint.csv | 63 +++++++++++++++++++++++++++++++++ db/seeds/crops-13-brassicas.csv | 36 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 db/seeds/crops-12-mint.csv create mode 100644 db/seeds/crops-13-brassicas.csv diff --git a/db/seeds/crops-12-mint.csv b/db/seeds/crops-12-mint.csv new file mode 100644 index 000000000..3da0e6fdc --- /dev/null +++ b/db/seeds/crops-12-mint.csv @@ -0,0 +1,63 @@ +salvia,http://en.wikipedia.org/wiki/Salvia,,Salvia, +white sage,http://en.wikipedia.org/wiki/Salvia_apiana,salvia,Salvia apiana,"bee sage, sacred sage" +pineapple sage,http://en.wikipedia.org/wiki/Salvia_elegans,salvia,Salvia elegans,tangerine sage +Greek sage,http://en.wikipedia.org/wiki/Salvia_fruticosa,salvia,Salvia fruticosa, +chia,http://en.wikipedia.org/wiki/Salvia_hispanica,salvia,Salvia hispanica, +baby sage,http://en.wikipedia.org/wiki/Salvia_microphylla,salvia,Salvia microphylla,"Graham's sage, Blackcurrant sage" +sage,http://en.wikipedia.org/wiki/Salvia_officinalis,salvia,Salvia officinalis,common sage +rosemary,http://en.wikipedia.org/wiki/Rosemary,,Rosemarinus officinalis, +catnip,http://en.wikipedia.org/wiki/Nepeta_cataria,,Nepeta cataria,catmint +beebalm,http://en.wikipedia.org/wiki/Monarda,,Monarda, +lemon beebalm,http://en.wikipedia.org/wiki/Monarda_citriodora,beebalm,Monarda citriodora,"purple horsemint, lemon mint" +basil beebalm,http://en.wikipedia.org/wiki/Monarda_clinopodioides,beebalm,Monarda clinopodioides, +crimson beebalm,http://en.wikipedia.org/wiki/Monarda_didyma,beebalm,Monarda didyma,"bergamot, scarlet beebalm, scarlet monarda, Oswego tea" +wild bergamot,http://en.wikipedia.org/wiki/Monarda_fistulosa,beebalm,Monarda fistulosa, +perilla,http://en.wikipedia.org/wiki/Perilla_frutescens,,Perilla frutescens, +shiso,http://en.wikipedia.org/wiki/Shiso,perilla,Perilla frutescens var. crispa, +winter savory,http://en.wikipedia.org/wiki/Winter_savory,,Satureja montana, +summer savory,http://en.wikipedia.org/wiki/Summer_savory,,Satureja hortensis, +yerba buena,http://en.wikipedia.org/wiki/Micromeria_douglasii,,Micromeria douglasii, +anise hyssop,http://en.wikipedia.org/wiki/Agastache_foeniculum,,Agastache foeniculum,"blue giant hyssop, Fragrant giant hyssop, lavender giant hyssop" +Korean mint,http://en.wikipedia.org/wiki/Agastache_rugosa,,Agastache rugosa,"Blue Licorice, Purple Giant Hyssop, Huo xiang, Indian Mint, Patchouli Herb, Wrinkled Giant Hyssop" +oregano,http://en.wikipedia.org/wiki/Oregano,,Origanum vulgare,wild marjoram +Amanum oregano,http://en.wikipedia.org/wiki/Origanum_amanum,oregano,Origanum amanum, +marjoram,http://en.wikipedia.org/wiki/Marjoram,oregano,Origanum majorana,"sweet marjoram, knotted marjoram" +Cretan oregano,http://en.wikipedia.org/wiki/Origanum_onites,oregano,Origanum onites,"Turkish oregano, pot marjoram, rίgani" +round-leafed oregano,http://en.wikipedia.org/wiki/Origanum_rotundifolium,oregano,Origanum rotundifolium, +za'atar,http://en.wikipedia.org/wiki/Origanum_syriacum,oregano,Origanum syriacum,"bible hyssop, Biblical-hyssop, Lebanese oregano, Syrian oregano" +calamint,http://en.wikipedia.org/wiki/Calamint,,Calamintha, +lesser calamint,http://en.wikipedia.org/wiki/Calamintha_nepeta,calamint,Calamintha nepeta, +thyme,http://en.wikipedia.org/wiki/Thymus_%28plant%29,,Thymus, +common thyme,http://en.wikipedia.org/wiki/Thymus_vulgaris,thyme,Thymus vulgaris,garden thyme +caraway thyme,http://en.wikipedia.org/wiki/Thymus_herba-barona,thyme,Thymus herba-barona, +cantueso,http://en.wikipedia.org/wiki/Thymus_moroderi,thyme,Thymus moroderi, +lemon thyme,http://en.wikipedia.org/wiki/Thymus_citriodorus,thyme,Thymus citriodorus,Citrus thyme +Hungarian thyme,http://en.wikipedia.org/wiki/Thymus_pannonicus,thyme,Thymus pannonicus, +creeping thyme,http://en.wikipedia.org/wiki/Thymus_praecox,thyme,Thymus praecox,Mother-of-Thyme +mint,http://en.wikipedia.org/wiki/Mentha,,Mentha, +water mint,http://en.wikipedia.org/wiki/Mentha_aquatica,mint,Mentha aquatica, +wild mint,http://en.wikipedia.org/wiki/Mentha_arvensis,mint,Mentha arvensis,"field mint, corn mint" +Asian mint,http://en.wikipedia.org/wiki/Mentha_asiatica,mint,Mentha asiatica, +Australian mint,http://en.wikipedia.org/wiki/Mentha_australis,mint,Mentha australis, +American wild mint,http://en.wikipedia.org/wiki/Mentha_canadensis,mint,Mentha candensis, +bergamot mint,http://en.wikipedia.org/wiki/Mentha_citrata,mint,Mentha citrata, +wrinkled-leaf mint,http://en.wikipedia.org/wiki/Mentha_crispata,mint,Mentha crispata, +peppermint,http://en.wikipedia.org/wiki/Peppermint,mint,Mentha piperita, +pennyroyal,http://en.wikipedia.org/wiki/Mentha_pulegium,mint,Mentha pulegium,"squaw mint, mosquito plant, pudding grass" +Corsican mint,http://en.wikipedia.org/wiki/Mentha_requienii,mint,Mentha requienii, +garden mint,http://en.wikipedia.org/wiki/Mentha_sachalinensis,mint,Mentha sachalinensis, +spearmint,http://en.wikipedia.org/wiki/Spearmint,mint,Mentha spicata, +apple mint,http://en.wikipedia.org/wiki/Mentha_suaveolens,mint,Mentha suaveolens, +lemon balm,http://en.wikipedia.org/wiki/Melissa_officinalis,,Melissa officinalis, +basil,http://en.wikipedia.org/wiki/Basil,,Ocimum basilicum, +Thai basil,http://en.wikipedia.org/wiki/Thai_basil,basil,Ocimum basilicum var. thyrsiflora, +spicy globe basil,http://en.wikipedia.org/wiki/Spicy_globe_basil,basil,Ocimum basilicum, +cinnamon basil,http://en.wikipedia.org/wiki/Cinnamon_basil,basil,Ocimum basilicum,"Vietnamese basil, Saigon basil" +dark opal basil,http://en.wikipedia.org/wiki/Dark_opal_basil,basil,Ocimum basilicum, +red rubin basil,http://en.wikipedia.org/wiki/Red_rubin_basil,basil,Ocimum basilicum, +lemon basil,http://en.wikipedia.org/wiki/Lemon_basil,basil,Ocimum × citriodorum,"Thai lemon basil, Lao basil" +holy basil,http://en.wikipedia.org/wiki/Holy_basil,,Ocimum tenuiflorum,tulasī +lavender,http://en.wikipedia.org/wiki/Lavandula,,Lavandula, +English lavender,http://en.wikipedia.org/wiki/Lavandula_angustifolia,lavender,Lavandula angustifolia,"common lavender, true lavender, narrow-leaved lavender" +French lavender,http://en.wikipedia.org/wiki/Lavandula_stoechas,lavender,Lavandula stoechas,"French lavender, Spanish lavender, topped lavender" +hyssop,http://en.wikipedia.org/wiki/Hyssop,,Hyssopus officinalis, diff --git a/db/seeds/crops-13-brassicas.csv b/db/seeds/crops-13-brassicas.csv new file mode 100644 index 000000000..9dfd355fa --- /dev/null +++ b/db/seeds/crops-13-brassicas.csv @@ -0,0 +1,36 @@ +Ethiopian mustard,https://en.wikipedia.org/wiki/Brassica_carinata,Brassica,Brassica carinata,Abyssinian mustard +elongated mustard,https://en.wikipedia.org/wiki/Brassica_elongata,Brassica,Brassica elongata, +Mediterranean cabbage,https://en.wikipedia.org/wiki/Brassica_fruticulosa,Brassica,Brassica fruticulosa,twiggy turnip +mustard greens,https://en.wikipedia.org/wiki/Brassica_juncea,Brassica,Brassica juncea,"Indian mustard, Chinese mustard, leaf mustard, kai choi" +rutabaga,https://en.wikipedia.org/wiki/Rutabaga,Brassica,"Brassica napobrassica, Brassica napus var. napobrassica","swede, Swedish turnip, turnip, yellow turnip, neep" +rapeseed,https://en.wikipedia.org/wiki/Brassica_napus,Brassica,Brassica napus," rape, oilseed rape, rapa, rappi, rapaseed, canola" +tatsoi,https://en.wikipedia.org/wiki/Brassica_narinosa,Brassica,"Brassica narinosa, Brassica rapa var. rosularis","spinach mustard, spoon mustard, Rosette bok choy" +black mustard,https://en.wikipedia.org/wiki/Brassica_nigra,Brassica,Brassica nigra, +Brassica oleracea,https://en.wikipedia.org/wiki/Brassica_oleracea,Brassica,Brassica oleracea,wild mustard +Brassica oleracea Acephela group,https://en.wikipedia.org/wiki/Acephala_group,Brassica,Brassica oleracea Acephala group, +kai lan,https://en.wikipedia.org/wiki/Kai-lan,Brassica,Brassica oleracea Alboglabra Group,"Chinese broccoli, Chinese kale, gai-lan" +Brassica rapa,https://en.wikipedia.org/wiki/Brassica_rapa,Brassica,Brassica rapa, +kohlrabi,https://en.wikipedia.org/wiki/Kohlrabi,Brassica oleracea,Brassica oleracea,"German turnip, German cabbage, turnip cabbage" +spring greens,https://en.wikipedia.org/wiki/Spring_greens,Brassica oleracea,Brassica oleracea Acephala group, +cauliflower,https://en.wikipedia.org/wiki/Cauliflower,Brassica oleracea,Brassica oleracea Botrytis group, +Romanesco broccoli,https://en.wikipedia.org/wiki/Romanesco_broccoli,Brassica oleracea,Brassica oleracea Botrytis group,"Romanesque cauliflower, Romanesco" +broccoflower,https://en.wikipedia.org/wiki/Broccoflower,Brassica oleracea,Brassica oleracea Botrytis group, +cabbage,https://en.wikipedia.org/wiki/Cabbage,Brassica oleracea,Brassica oleracea Capitata group, +red cabbage,https://en.wikipedia.org/wiki/Red_cabbage,Brassica oleracea,Brassica oleracea Capitata group,"purple cabbage, red kraut, blue kraut" +broccolini,https://en.wikipedia.org/wiki/Broccolini,Brassica oleracea,Brassica oleracea Capitata group x Alboglabra Group,"tenderstem broccoli, broccolette" +Brussels sprouts,https://en.wikipedia.org/wiki/Brussels_sprouts,Brassica oleracea,Brassica oleracea Gemmifera group, +broccoli,https://en.wikipedia.org/wiki/Broccoli,Brassica oleracea,Brassica oleracea Italica group, +Savoy cabbage,https://en.wikipedia.org/wiki/Savoy_cabbage,Brassica oleracea,Brassica oleracea var. sabauda, +January king cabbage,https://en.wikipedia.org/wiki/January_King_Cabbage,Brassica oleracea,Brassica oleracea var. sabauda, +collard greens,https://en.wikipedia.org/wiki/Collard_greens,Brassica oleracea acephela group,Brassica oleracea Acephala group,Dalmatian cabbage +kale,https://en.wikipedia.org/wiki/Kale,Brassica oleracea acephela group,Brassica oleracea Acephala group,borecole +mizuna,https://en.wikipedia.org/wiki/Mizuna,Brassica rapa,"Brassica rapa nipposinica, Brassica juncea var. japonica","shui cai, kyona, Japanese mustard, potherb mustard, Japanese greens, California peppergrass, spider mustard" +napa cabbage,https://en.wikipedia.org/wiki/Napa_cabbage,Brassica rapa,Brassica rapa subsp. pekinensis,"nappa cabbage, celery cabbage" +rapini,https://en.wikipedia.org/wiki/Rapini,Brassica rapa,"Brassica rapa subspecies rapa, Brassica rapa ruvo, Brassica rapa rapifera +","broccoli raab, broccoli rabe" +turnip,https://en.wikipedia.org/wiki/Turnip,Brassica rapa,Brassica rapa subspecies rapa,white turnip +choy sum,https://en.wikipedia.org/wiki/Choy_sum,Brassica rapa,"Brassica rapa var. parachinensis, Brassica chinensis var. parachinensis +","choi sum, Chinese flowering cabbage" +komatsuna,https://en.wikipedia.org/wiki/Komatsuna,Brassica rapa,Brassica rapa var. perviridis,Japanese mustard spinach +lacinato kale,https://en.wikipedia.org/wiki/Lacinato_kale,kale,Brassica oleracea Acephala group,"Tuscan kale, Tuscan cabbage, Italian kale, Dinosaur kale, cavolo nero, cavalo nero, black kale, flat back cabbage, palm tree kale, black Tuscan palm" +Brassica,https://en.wikipedia.org/wiki/Brassicas,,Brassica, From 30c91eb23f44213faa91ec183b86d88f329cabdf Mon Sep 17 00:00:00 2001 From: Skud Date: Mon, 1 Dec 2014 21:14:44 +1100 Subject: [PATCH 051/143] Tidy up sidebar on crop detail page --- app/views/crops/_alternate_names.html.haml | 16 +++++++ app/views/crops/_grown_for.html.haml | 8 ++-- app/views/crops/_planting_advice.html.haml | 17 ++++--- app/views/crops/_scientific_names.html.haml | 16 +++++++ app/views/crops/_varieties.html.haml | 11 +++-- app/views/crops/_wrangle.html.haml | 11 +++++ app/views/crops/show.html.haml | 48 ++++--------------- .../crops/_planting_advice.html.haml_spec.rb | 4 +- 8 files changed, 77 insertions(+), 54 deletions(-) create mode 100644 app/views/crops/_alternate_names.html.haml create mode 100644 app/views/crops/_scientific_names.html.haml create mode 100644 app/views/crops/_wrangle.html.haml diff --git a/app/views/crops/_alternate_names.html.haml b/app/views/crops/_alternate_names.html.haml new file mode 100644 index 000000000..83b595510 --- /dev/null +++ b/app/views/crops/_alternate_names.html.haml @@ -0,0 +1,16 @@ +.alternate_names + %h4 Alternate names + - if crop.alternate_names.empty? + %p None known. + - else + %ul + - crop.alternate_names.each do |an| + %li + = an.name + - if can? :edit, an + = link_to 'Edit', edit_alternate_name_path(an), { :class => 'btn btn-default btn-xs' } + - if can? :destroy, an + = link_to 'Delete', an, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' + %p + - if can? :edit, crop + = link_to 'Add', new_alternate_name_path( :crop_id => crop.id ), { :class => 'btn btn-default btn-xs' } diff --git a/app/views/crops/_grown_for.html.haml b/app/views/crops/_grown_for.html.haml index 555371a23..e1d8544f7 100644 --- a/app/views/crops/_grown_for.html.haml +++ b/app/views/crops/_grown_for.html.haml @@ -1,5 +1,7 @@ -- if ! crop.harvests.empty? - %p - %strong Grown for: +%p + %strong Grown for: + - if crop.harvests.empty? + not known. + - else - popular_plant_parts = crop.popular_plant_parts.sort_by {|s, freq| freq }.reverse != popular_plant_parts.map {|p, freq| link_to(p, p) + " (#{freq})" }.join(", ") diff --git a/app/views/crops/_planting_advice.html.haml b/app/views/crops/_planting_advice.html.haml index bdd3ceb4d..713e6ded8 100644 --- a/app/views/crops/_planting_advice.html.haml +++ b/app/views/crops/_planting_advice.html.haml @@ -1,10 +1,15 @@ -- if crop.planted_from.length > 0 - %p - %strong Plant from: +%p + %strong Plant from: + - if crop.planted_from.empty? + not known. + - else - planted_from = crop.planted_from.sort_by {|s, freq| freq }.reverse = planted_from.map {|s, freq| "#{s} (#{freq})" }.join(", ") -- if crop.sunniness.length > 0 - %p - %strong Plant in: + +%p + %strong Plant in: + - if crop.sunniness.empty? + not known. + - else - sunniness = crop.sunniness.sort_by {|s, freq| freq }.reverse = sunniness.map {|s, freq| "#{s} (#{freq})" }.join(", ") diff --git a/app/views/crops/_scientific_names.html.haml b/app/views/crops/_scientific_names.html.haml new file mode 100644 index 000000000..ee845e543 --- /dev/null +++ b/app/views/crops/_scientific_names.html.haml @@ -0,0 +1,16 @@ +.scientific_names + %h4 Scientific names + - if crop.scientific_names.empty? + %p None known. + - else + %ul + - crop.scientific_names.each do |sn| + %li + = sn.scientific_name + - if can? :edit, sn + = link_to 'Edit', edit_scientific_name_path(sn), { :class => 'btn btn-default btn-xs' } + - if can? :destroy, sn + = link_to 'Delete', sn, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' + %p + - if can? :edit, crop + = link_to 'Add', new_scientific_name_path( :crop_id => crop.id ), { :class => 'btn btn-default btn-xs' } diff --git a/app/views/crops/_varieties.html.haml b/app/views/crops/_varieties.html.haml index 434ea3c1f..8fec3e3a3 100644 --- a/app/views/crops/_varieties.html.haml +++ b/app/views/crops/_varieties.html.haml @@ -4,7 +4,12 @@ is a variety of = succeed "." do = link_to crop.parent, crop.parent -- if crop.varieties.count > 0 - %h3 - Varieties: + +- unless crop.varieties.empty? + %p + Varieties of #{crop.name}: + = render :partial => 'hierarchy', :locals => { :display_crops => [ crop ] } + +- if ! crop.parent and crop.varieties.empty? + %p None known. diff --git a/app/views/crops/_wrangle.html.haml b/app/views/crops/_wrangle.html.haml new file mode 100644 index 000000000..d68fadfb1 --- /dev/null +++ b/app/views/crops/_wrangle.html.haml @@ -0,0 +1,11 @@ +- if can? :edit, crop or can? :destroy, crop + %h4 Crop wrangling + %p + You are a + = succeed "." do + %strong CROP WRANGLER + %p + - if can? :edit, crop + = link_to 'Edit crop', edit_crop_path(crop), { :class => 'btn btn-default btn-xs' } + - if can? :destroy, crop + = link_to 'Delete crop', crop, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index f1518aeb2..7aae050c7 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -47,52 +47,20 @@ = will_paginate @posts, :params => {:anchor => "posts"} .col-md-3 - - if can? :edit, @crop or can? :destroy, @crop - %h4 Crop wrangling - %p - You are a - = succeed "." do - %strong CROP WRANGLER - %p - - if can? :edit, @crop - = link_to 'Edit crop', edit_crop_path(@crop), { :class => 'btn btn-default btn-xs' } - - if can? :destroy, @crop - = link_to 'Delete crop', @crop, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' - .scientific_names - %h4 Scientific names - %ul - - @crop.scientific_names.each do |sn| - %li - = sn.scientific_name - - if can? :edit, sn - = link_to 'Edit', edit_scientific_name_path(sn), { :class => 'btn btn-default btn-xs' } - - if can? :destroy, sn - = link_to 'Delete', sn, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' - %p - - if can? :edit, @crop - = link_to 'Add', new_scientific_name_path( :crop_id => @crop.id ), { :class => 'btn btn-default btn-xs' } + = render :partial => 'wrangle', :locals => { :crop => @crop } + = render :partial => 'scientific_names', :locals => { :crop => @crop } + = render :partial => 'alternate_names', :locals => { :crop => @crop } - .alternate_names - %h4 Alternate names - %ul - - @crop.alternate_names.each do |an| - %li - = an.name - - if can? :edit, an - = link_to 'Edit', edit_alternate_name_path(an), { :class => 'btn btn-default btn-xs' } - - if can? :destroy, an - = link_to 'Delete', an, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' - %p - - if can? :edit, @crop - = link_to 'Add', new_alternate_name_path( :crop_id => @crop.id ), { :class => 'btn btn-default btn-xs' } - - = render :partial => 'varieties', :locals => { :crop => @crop } + %h4 Planting advice = render :partial => 'grown_for', :locals => { :crop => @crop } - = render :partial => 'planting_advice', :locals => { :crop => @crop } + %h4 Varieties + = render :partial => 'varieties', :locals => { :crop => @crop } + + %h4 More information %ul %li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url diff --git a/spec/views/crops/_planting_advice.html.haml_spec.rb b/spec/views/crops/_planting_advice.html.haml_spec.rb index f92fe2bd7..19a756a7c 100644 --- a/spec/views/crops/_planting_advice.html.haml_spec.rb +++ b/spec/views/crops/_planting_advice.html.haml_spec.rb @@ -14,7 +14,7 @@ describe "crops/_planting_advice" do context "sunniness" do it "doesn't show sunniness if none are set" do render :partial => 'crops/planting_advice', :locals => { :crop => @crop } - rendered.should_not contain "Plant in:" + rendered.should contain "Plant in: not known." end it "shows sunniness frequencies" do @@ -39,7 +39,7 @@ describe "crops/_planting_advice" do it "doesn't show planted_from if none are set" do render :partial => 'crops/planting_advice', :locals => { :crop => @crop } - rendered.should_not contain "Plant from:" + rendered.should contain "Plant from: not known." end it "shows planted_from frequencies" do From d0b61c259d2f577bd34448b8e7e88eec20dc51b0 Mon Sep 17 00:00:00 2001 From: Skud Date: Mon, 1 Dec 2014 21:20:44 +1100 Subject: [PATCH 052/143] Added squashes and new crops from London working bee --- db/seeds/crops-14-london-workingbee.csv | 15 +++++++++++++++ db/seeds/crops-15-squashes.csv | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 db/seeds/crops-14-london-workingbee.csv create mode 100644 db/seeds/crops-15-squashes.csv diff --git a/db/seeds/crops-14-london-workingbee.csv b/db/seeds/crops-14-london-workingbee.csv new file mode 100644 index 000000000..42bddb9ec --- /dev/null +++ b/db/seeds/crops-14-london-workingbee.csv @@ -0,0 +1,15 @@ +greenstripe amaranth,https://en.wikipedia.org/wiki/Amaranthus_acanthochiton,Amaranthus,Amaranthus Acanthochiton,greenstripe +slender amaranth,https://en.wikipedia.org/wiki/Amaranthus_viridis,amaranth,Amaranthus viridis,"green amaranth, callaloo" +purple amaranth,https://en.wikipedia.org/wiki/Amaranthus_blitum,amaranth,Amaranthus blitum, +red amaranth,https://en.wikipedia.org/wiki/Amaranthus_caudatus,amaranth,Amaranthus caudatus,"blood amaranth, purple amaranth, prince's feather, Mexican grain amaranth" +red spinach,https://en.wikipedia.org/wiki/Amaranthus_dubius,amaranth,Amaranthus dubius,"Chinese spinach, spleen amaranth" +smooth amaranth,https://en.wikipedia.org/wiki/Amaranthus_hybridus,amaranth,Amaranthus hybridus,"smooth pigweed, red amaranth, slim amaranth" +Prince of Wales,https://en.wikipedia.org/wiki/Amaranthus_hypochondriacus,amaranth,Amaranthus hypochondriacus," Prince-of-Wales feather, Prince's feather" +Palmer's amaranth,https://en.wikipedia.org/wiki/Amaranthus_palmeri,amaranth,Amaranthus palmeri,"Palmer amaranth, Palmer's pigweed, carelessweed" +red-root amaranth,https://en.wikipedia.org/wiki/Amaranthus_retroflexus,amaranth,Amaranthus retroflexus,"redroot pigweed, red-rooted pigweed, common amaranth, pigweed amaranth, common tumbleweed" +spiny amaranth,https://en.wikipedia.org/wiki/Amaranthus_spinosus,amaranth,Amaranthus spinosus,"prickly amaranth, thorny amaranth" +stinging nettle,https://en.wikipedia.org/wiki/Urtica_dioica,nettle,Urtica dioica, +tree nettle,https://en.wikipedia.org/wiki/Urtica_incisa,nettle,Urtica incisa,"scrub nettle, stinging nettle" +Thunberg's amaranth,https://en.wikipedia.org/wiki/Amaranthus_thunbergii,amaranth,Amaranthus thunbergii, +tampala,https://en.wikipedia.org/wiki/Amaranthus_tricolor,amaranth,Amaranthus tricolor,"callaloo, Joseph's coat " +star anise,http://en.wikipedia.org/wiki/Illicium_verum,,Illicium verum,"star aniseed, Chinese star anise" diff --git a/db/seeds/crops-15-squashes.csv b/db/seeds/crops-15-squashes.csv new file mode 100644 index 000000000..a5f30e645 --- /dev/null +++ b/db/seeds/crops-15-squashes.csv @@ -0,0 +1,20 @@ +squash,http://en.wikipedia.org/wiki/Squash_(plant),,Cucurbita,, +Japanese pie pumpkin,http://en.wikipedia.org/wiki/Cucurbita_argyrosperma,squash,Cucurbita argyosperma,"pipian, cushaw pumpkin", +seven year melon,http://en.wikipedia.org/wiki/Cucurbita_ficifolia,squash,Cucurbita ficifolia,"Siam pumpkin, Thai marrow, thin Vermicelli pumpkin, Asian pumpkin, fig-leaf gourd, pie melon, Malabar gourd, Malabar squash, shark's-fin gourd, shark's-fin melon", +Cucurbita maxima,http://en.wikipedia.org/wiki/Cucurbita_maxima,squash,Cucurbita maxima,, +Cucurbita moschata,http://en.wikipedia.org/wiki/Cucurbita_moschata,squash,Cucurbita moschata,, +Cucurbita pepo,http://en.wikipedia.org/wiki/Cucurbita_pepo,squash,Cucurbita pepo,, +kabocha,http://en.wikipedia.org/wiki/Kabocha,Cucurbita maxima,Cucurbita maxima,"kabocha squash, Japanese pumpkin", +turban squash,http://en.wikipedia.org/wiki/Turban_squash,Cucurbita maxima,Cucurbita maxima,"Turk's turban, French turban", +red kuri squash,http://en.wikipedia.org/wiki/Red_kuri_squash,Cucurbita maxima,Cucurbita maxima,"Japanese squash, orange Hokkaido squash, baby red Hubbard squash, Uchiki kuri squash", +butternut squash,http://en.wikipedia.org/wiki/Butternut_squash,Cucurbita moschata,Cucurbita moschata,butternut pumpkin, +tromboncino,http://en.wikipedia.org/wiki/Tromboncino_(squash),Cucurbita moschata,Cucurbita moschata,zucchetta, +acorn squash,http://en.wikipedia.org/wiki/Acorn_squash,Cucurbita pepo,Cucurbita pepo var. turbinata,"pepper squash, Des Moines squash", +yellow crookneck squash,http://en.wikipedia.org/wiki/Yellow_crookneck_squash,Cucurbita pepo,Cucurbita pepo var. torticollia,, +pumpkin,http://en.wikipedia.org/wiki/Pumpkin,Cucurbita pepo,Cucurbita pepo var. pepo,,Appears no varieties have their own wikipedia pages +pattypan squash ,http://en.wikipedia.org/wiki/Pattypan_squash,Cucurbita pepo,Cucurbita pepo var. clypeata,"scallop squash, sunburst squash, granny squash, custard marrow, custard squash, cibleme, white squash, scallopini squash, schwoughksie squash", +yellow summer squash,http://en.wikipedia.org/wiki/Yellow_summer_squash,Cucurbita pepo,Cucurbita pepo var. recticollis,straightneck squash, +spaghetti squash,http://en.wikipedia.org/wiki/Spaghetti_squash,Cucurbita pepo,Cucurbita pepo var. fastigata,"vegetable spaghetti, noodle squash, vegetable marrow, spaghetti marrow, squaghetti", +zucchini,http://en.wikipedia.org/wiki/Zucchini,Cucurbita pepo,Cucurbita pepo var. cylindrica,courgette, +Delicata squash,http://en.wikipedia.org/wiki/Delicata_squash,Cucurbita pepo,Cucurbita pepo var. pepo,"peanut squash, Bohemian squash, sweet potato squash", +gem squash,http://en.wikipedia.org/wiki/Gem_squash,Cucurbita pepo,Cucurbita pepo,, From 6f3e430840b17a3fd077df572af97d4da1fb9641 Mon Sep 17 00:00:00 2001 From: Skud Date: Mon, 1 Dec 2014 21:23:15 +1100 Subject: [PATCH 053/143] Add deploy tasks for new crops --- script/deploy-tasks.sh | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/script/deploy-tasks.sh b/script/deploy-tasks.sh index 451fe0032..957ddc1b6 100755 --- a/script/deploy-tasks.sh +++ b/script/deploy-tasks.sh @@ -10,11 +10,8 @@ # echo "YYYY-MM-DD - do something or other" # rake growstuff:oneoff:something -echo "2014-09-28 - upload tomatoes" -rake growstuff:import_crops file=db/seeds/crops-11-tomatoes.csv - -echo "2014-10-02 - remove unused photos" -rake growstuff:oneoff:remove_unused_photos - -echo "2014-10-05 - generate crops_posts records for existing posts" -rake growstuff:oneoff:generate_crops_posts_records +echo "2014-12-01 - load lots of new crops" +rake growstuff:import_crops file=db/seeds/crops-12-mint.csv +rake growstuff:import_crops file=db/seeds/crops-13-brassicas.csv +rake growstuff:import_crops file=db/seeds/crops-14-london-workingbee.csv +rake growstuff:import_crops file=db/seeds/crops-15-squashes.csv From 9f54641e9585dbf54d90602de6c1d9186e34b9c5 Mon Sep 17 00:00:00 2001 From: Miles Gould Date: Mon, 1 Dec 2014 11:03:27 +0000 Subject: [PATCH 054/143] Find crops by name when loading altnames Crop IDs are not guaranteed to be the same on staging and production. --- lib/tasks/growstuff.rake | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index b0f6c68cd..d78f6c66f 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -301,12 +301,16 @@ namespace :growstuff do if alternate_names.blank? then next end - alternate_names.split(/,\s*/).each do |an| - AlternateName.find_or_create( - name: an, - crop_id: crop_id, - creator_id: cropbot.id - ) + crop = Crop.find_by_name(crop_name) + if crop + alternate_names.split(/,\s*/).each do |an| + AlternateName.where( + name: an, + crop_id: crop.id, + ).first_or_create do |x| + x.creator = cropbot + end + end end end end From a47328eed45b748e413bfb062e77eb76e2d8fdd2 Mon Sep 17 00:00:00 2001 From: Skud Date: Wed, 3 Dec 2014 14:50:25 +1100 Subject: [PATCH 055/143] Fixed ordering and capitalisation in brassica import --- db/seeds/crops-13-brassicas.csv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/seeds/crops-13-brassicas.csv b/db/seeds/crops-13-brassicas.csv index 9dfd355fa..75d04e82d 100644 --- a/db/seeds/crops-13-brassicas.csv +++ b/db/seeds/crops-13-brassicas.csv @@ -1,3 +1,4 @@ +Brassica,https://en.wikipedia.org/wiki/Brassicas,,Brassica, Ethiopian mustard,https://en.wikipedia.org/wiki/Brassica_carinata,Brassica,Brassica carinata,Abyssinian mustard elongated mustard,https://en.wikipedia.org/wiki/Brassica_elongata,Brassica,Brassica elongata, Mediterranean cabbage,https://en.wikipedia.org/wiki/Brassica_fruticulosa,Brassica,Brassica fruticulosa,twiggy turnip @@ -22,8 +23,8 @@ Brussels sprouts,https://en.wikipedia.org/wiki/Brussels_sprouts,Brassica olerace broccoli,https://en.wikipedia.org/wiki/Broccoli,Brassica oleracea,Brassica oleracea Italica group, Savoy cabbage,https://en.wikipedia.org/wiki/Savoy_cabbage,Brassica oleracea,Brassica oleracea var. sabauda, January king cabbage,https://en.wikipedia.org/wiki/January_King_Cabbage,Brassica oleracea,Brassica oleracea var. sabauda, -collard greens,https://en.wikipedia.org/wiki/Collard_greens,Brassica oleracea acephela group,Brassica oleracea Acephala group,Dalmatian cabbage -kale,https://en.wikipedia.org/wiki/Kale,Brassica oleracea acephela group,Brassica oleracea Acephala group,borecole +collard greens,https://en.wikipedia.org/wiki/Collard_greens,Brassica oleracea Acephela group,Brassica oleracea Acephala group,Dalmatian cabbage +kale,https://en.wikipedia.org/wiki/Kale,Brassica oleracea Acephela group,Brassica oleracea Acephala group,borecole mizuna,https://en.wikipedia.org/wiki/Mizuna,Brassica rapa,"Brassica rapa nipposinica, Brassica juncea var. japonica","shui cai, kyona, Japanese mustard, potherb mustard, Japanese greens, California peppergrass, spider mustard" napa cabbage,https://en.wikipedia.org/wiki/Napa_cabbage,Brassica rapa,Brassica rapa subsp. pekinensis,"nappa cabbage, celery cabbage" rapini,https://en.wikipedia.org/wiki/Rapini,Brassica rapa,"Brassica rapa subspecies rapa, Brassica rapa ruvo, Brassica rapa rapifera @@ -33,4 +34,3 @@ choy sum,https://en.wikipedia.org/wiki/Choy_sum,Brassica rapa,"Brassica rapa var ","choi sum, Chinese flowering cabbage" komatsuna,https://en.wikipedia.org/wiki/Komatsuna,Brassica rapa,Brassica rapa var. perviridis,Japanese mustard spinach lacinato kale,https://en.wikipedia.org/wiki/Lacinato_kale,kale,Brassica oleracea Acephala group,"Tuscan kale, Tuscan cabbage, Italian kale, Dinosaur kale, cavolo nero, cavalo nero, black kale, flat back cabbage, palm tree kale, black Tuscan palm" -Brassica,https://en.wikipedia.org/wiki/Brassicas,,Brassica, From c1bcbd2e7da9bc63ff10578684a2165a574161cf Mon Sep 17 00:00:00 2001 From: Skud Date: Wed, 3 Dec 2014 14:56:13 +1100 Subject: [PATCH 056/143] Fix parent crop for B. oleracea Acephela group --- db/seeds/crops-13-brassicas.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seeds/crops-13-brassicas.csv b/db/seeds/crops-13-brassicas.csv index 75d04e82d..858538b74 100644 --- a/db/seeds/crops-13-brassicas.csv +++ b/db/seeds/crops-13-brassicas.csv @@ -8,7 +8,7 @@ rapeseed,https://en.wikipedia.org/wiki/Brassica_napus,Brassica,Brassica napus," tatsoi,https://en.wikipedia.org/wiki/Brassica_narinosa,Brassica,"Brassica narinosa, Brassica rapa var. rosularis","spinach mustard, spoon mustard, Rosette bok choy" black mustard,https://en.wikipedia.org/wiki/Brassica_nigra,Brassica,Brassica nigra, Brassica oleracea,https://en.wikipedia.org/wiki/Brassica_oleracea,Brassica,Brassica oleracea,wild mustard -Brassica oleracea Acephela group,https://en.wikipedia.org/wiki/Acephala_group,Brassica,Brassica oleracea Acephala group, +Brassica oleracea Acephela group,https://en.wikipedia.org/wiki/Acephala_group,Brassica oleracea,Brassica oleracea Acephala group, kai lan,https://en.wikipedia.org/wiki/Kai-lan,Brassica,Brassica oleracea Alboglabra Group,"Chinese broccoli, Chinese kale, gai-lan" Brassica rapa,https://en.wikipedia.org/wiki/Brassica_rapa,Brassica,Brassica rapa, kohlrabi,https://en.wikipedia.org/wiki/Kohlrabi,Brassica oleracea,Brassica oleracea,"German turnip, German cabbage, turnip cabbage" From 58728f6a611d3acc3f7bf4aad1f206c4506b3b5b Mon Sep 17 00:00:00 2001 From: emmawinston Date: Fri, 5 Dec 2014 02:45:39 +0000 Subject: [PATCH 057/143] Made crop thumbnail markup more semantic --- app/assets/stylesheets/overrides.css.less | 18 ++++++++++++++++++ app/views/crops/_thumbnail.html.haml | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/overrides.css.less b/app/assets/stylesheets/overrides.css.less index 8b9938c33..e08579efb 100644 --- a/app/assets/stylesheets/overrides.css.less +++ b/app/assets/stylesheets/overrides.css.less @@ -159,6 +159,24 @@ p.stats { .thumbnail { margin-bottom: 1.5em; + + .scientific-name small, .crop-name a { + display: inline-block; + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 1em; + padding-bottom: 2px; + } + + .crop-name a { + padding-top: 2px; + } + + .scientific-name small { + margin-bottom: -2px; + } } li.crop-hierarchy { diff --git a/app/views/crops/_thumbnail.html.haml b/app/views/crops/_thumbnail.html.haml index b6844dabb..7ac7d786b 100644 --- a/app/views/crops/_thumbnail.html.haml +++ b/app/views/crops/_thumbnail.html.haml @@ -1,11 +1,11 @@ .thumbnail(style='height: 220px') - if crop = link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => crop.name, :class => 'img-rounded'), crop - %p + %p.crop-name = link_to crop.name, crop - if crop.scientific_names.count > 0 %br/ - %i + %i.scientific-name %small = crop.scientific_names.first.scientific_name %br/ From 899d3c3dbe856fe379af2f842d7258ac67a0a8e6 Mon Sep 17 00:00:00 2001 From: Kevin Yang Date: Tue, 9 Dec 2014 20:25:45 +1100 Subject: [PATCH 058/143] Modified ruby from 2.1.2 to 2.1.5 --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 451b2d3fc..3fed461ad 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -ruby "2.1.2" +ruby "2.1.5" gem 'bundler', '>=1.1.5' From 969c5301936f181950d7a33471c5db3aa979c698 Mon Sep 17 00:00:00 2001 From: kevieyang Date: Tue, 9 Dec 2014 20:32:47 +1100 Subject: [PATCH 059/143] Update .travis.yml upgrading ruby 2.1.2 to 2.1.5 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7ed73fce0..af5732a70 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ language: ruby env: GROWSTUFF_SITE_NAME="Growstuff (travis)" RAILS_SECRET_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' bundler_args: --without development production staging rvm: - - 2.1.2 + - 2.1.5 before_script: - psql -c 'create database growstuff_test;' -U postgres script: From 5e2a3db8c258f0f44ef8d5d396270b0b5d29933e Mon Sep 17 00:00:00 2001 From: Kevin Yang Date: Tue, 9 Dec 2014 20:44:46 +1100 Subject: [PATCH 060/143] Added myself to Contributors.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index b66986240..d0719b1e1 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -50,4 +50,5 @@ submit the change with your pull request. - Emma Winston / [emmawinston](https://github.com/emmawinston) - Kevin Rio / [krio](https://github.com/krio) - Yoong Kang Lim / [yoongkang](https://github.com/yoongkang) +- Kevin Yang / [kevieyang] (https://github.com/kevieyang) From 837121265a5d4a06e4d4baa05c147b83aa9a6ce4 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Tue, 9 Dec 2014 21:27:16 +1100 Subject: [PATCH 061/143] Reversed order of authorization and authentication. Also added tests --- app/controllers/account_types_controller.rb | 2 +- app/controllers/accounts_controller.rb | 2 +- app/controllers/alternate_names_controller.rb | 2 +- app/controllers/comments_controller.rb | 2 +- app/controllers/crops_controller.rb | 2 +- app/controllers/gardens_controller.rb | 2 +- app/controllers/harvests_controller.rb | 4 ++-- app/controllers/photos_controller.rb | 4 ++-- app/controllers/plantings_controller.rb | 3 ++- app/controllers/posts_controller.rb | 2 +- app/controllers/products_controller.rb | 2 +- app/controllers/roles_controller.rb | 2 +- app/controllers/scientific_names_controller.rb | 2 +- app/controllers/seeds_controller.rb | 2 +- spec/features/signin_spec.rb | 14 ++++++++++++++ 15 files changed, 31 insertions(+), 16 deletions(-) diff --git a/app/controllers/account_types_controller.rb b/app/controllers/account_types_controller.rb index 350c007a2..ce448ceba 100644 --- a/app/controllers/account_types_controller.rb +++ b/app/controllers/account_types_controller.rb @@ -1,6 +1,6 @@ class AccountTypesController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member! + load_and_authorize_resource # GET /account_types def index diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 7c4c0018d..c163e0ffc 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -1,6 +1,6 @@ class AccountsController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member! + load_and_authorize_resource # GET /accounts def index diff --git a/app/controllers/alternate_names_controller.rb b/app/controllers/alternate_names_controller.rb index dce855975..21cb294a0 100644 --- a/app/controllers/alternate_names_controller.rb +++ b/app/controllers/alternate_names_controller.rb @@ -1,6 +1,6 @@ class AlternateNamesController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] + load_and_authorize_resource # GET /alternate_names # GET /alternate_names.json diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 3234a379d..a24b4fed3 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,6 +1,6 @@ class CommentsController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] + load_and_authorize_resource cache_sweeper :comment_sweeper diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 770db8d19..be4eccc2e 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -1,7 +1,7 @@ class CropsController < ApplicationController + before_filter :authenticate_member!, :except => [:index, :hierarchy, :search, :show] load_and_authorize_resource skip_authorize_resource :only => [:hierarchy, :search] - before_filter :authenticate_member!, :except => [:index, :hierarchy, :search, :show] cache_sweeper :crop_sweeper diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index cc2d091d5..dd3d56542 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -1,6 +1,6 @@ class GardensController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] + load_and_authorize_resource cache_sweeper :garden_sweeper diff --git a/app/controllers/harvests_controller.rb b/app/controllers/harvests_controller.rb index d6535940f..a51ee574e 100644 --- a/app/controllers/harvests_controller.rb +++ b/app/controllers/harvests_controller.rb @@ -1,7 +1,7 @@ class HarvestsController < ApplicationController - - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] + load_and_authorize_resource + # GET /harvests # GET /harvests.json diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index ccbb2048d..c745f403d 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -1,7 +1,7 @@ class PhotosController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] - + load_and_authorize_resource + cache_sweeper :photo_sweeper # GET /photos diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index acdff628f..c9086307e 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -1,6 +1,7 @@ class PlantingsController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] + load_and_authorize_resource + cache_sweeper :planting_sweeper diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 4a88ee053..d36a809ae 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -1,6 +1,6 @@ class PostsController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] + load_and_authorize_resource cache_sweeper :post_sweeper diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 9349301b4..41754199b 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,6 +1,6 @@ class ProductsController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member! + load_and_authorize_resource # GET /products def index diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 9ed8308d4..8aecf5c2a 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -1,6 +1,6 @@ class RolesController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member! + load_and_authorize_resource # GET /roles def index diff --git a/app/controllers/scientific_names_controller.rb b/app/controllers/scientific_names_controller.rb index 893e17ba1..1a727f715 100644 --- a/app/controllers/scientific_names_controller.rb +++ b/app/controllers/scientific_names_controller.rb @@ -1,6 +1,6 @@ class ScientificNamesController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] + load_and_authorize_resource cache_sweeper :scientific_name_sweeper diff --git a/app/controllers/seeds_controller.rb b/app/controllers/seeds_controller.rb index 6a89bfdfa..d1205dab7 100644 --- a/app/controllers/seeds_controller.rb +++ b/app/controllers/seeds_controller.rb @@ -1,6 +1,6 @@ class SeedsController < ApplicationController - load_and_authorize_resource before_filter :authenticate_member!, :except => [:index, :show] + load_and_authorize_resource cache_sweeper :seed_sweeper diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index 424d2efd4..181111959 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -4,6 +4,8 @@ feature "signin" do let(:member){FactoryGirl.create(:member)} let(:notification){FactoryGirl.create(:notification)} + MODELS = [:plantings, :harvests, :posts, :photos, :gardens, :seeds] + scenario "redirect to previous page after signin" do visit crops_path # some random page click_link 'Sign in' @@ -27,4 +29,16 @@ feature "signin" do current_path.should eq new_member_session_path end + scenario "after signin, redirect to what you were trying to do" do + MODELS.each do |model| + visit "/#{model.to_s}/new" + current_path.should eq new_member_session_path + fill_in 'Login', with: member.login_name + fill_in 'Password', with: member.password + click_button 'Sign in' + current_path.should eq "/#{model.to_s}/new" + click_link 'Sign out' + end + end + end From de26dd370885f7e0a98ad15d6f326c035daae6fa Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Tue, 9 Dec 2014 21:42:17 +1100 Subject: [PATCH 062/143] to_s not needed --- spec/features/signin_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index 181111959..047bd68cb 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -31,12 +31,12 @@ feature "signin" do scenario "after signin, redirect to what you were trying to do" do MODELS.each do |model| - visit "/#{model.to_s}/new" + visit "/#{model}/new" current_path.should eq new_member_session_path fill_in 'Login', with: member.login_name fill_in 'Password', with: member.password click_button 'Sign in' - current_path.should eq "/#{model.to_s}/new" + current_path.should eq "/#{model}/new" click_link 'Sign out' end end From a69210ae6b95673d0035bdf96ce8f93b176838f0 Mon Sep 17 00:00:00 2001 From: Yoong Kang Lim Date: Tue, 9 Dec 2014 22:07:41 +1100 Subject: [PATCH 063/143] Explicitly add spec for notification --- spec/features/signin_spec.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index 047bd68cb..3ad259213 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -2,10 +2,9 @@ require 'spec_helper' feature "signin" do let(:member){FactoryGirl.create(:member)} + let(:recipient){FactoryGirl.create(:member)} let(:notification){FactoryGirl.create(:notification)} - MODELS = [:plantings, :harvests, :posts, :photos, :gardens, :seeds] - scenario "redirect to previous page after signin" do visit crops_path # some random page click_link 'Sign in' @@ -30,7 +29,8 @@ feature "signin" do end scenario "after signin, redirect to what you were trying to do" do - MODELS.each do |model| + models = %w[plantings harvests posts photos gardens seeds] + models.each do |model| visit "/#{model}/new" current_path.should eq new_member_session_path fill_in 'Login', with: member.login_name @@ -41,4 +41,13 @@ feature "signin" do end end + scenario "after signin, redirect to new notifications page" do + visit new_notification_path(recipient: recipient) + current_path.should eq new_member_session_path + fill_in 'Login', with: member.login_name + fill_in 'Password', with: member.password + click_button 'Sign in' + current_path.should eq new_notification_path + end + end From 7f8815769657cf5f2f861b01b0ed5c2832855a36 Mon Sep 17 00:00:00 2001 From: Kevin Yang Date: Tue, 9 Dec 2014 14:11:29 +0000 Subject: [PATCH 064/143] removed whitespace --- CONTRIBUTORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d0719b1e1..83bf19f30 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -50,5 +50,5 @@ submit the change with your pull request. - Emma Winston / [emmawinston](https://github.com/emmawinston) - Kevin Rio / [krio](https://github.com/krio) - Yoong Kang Lim / [yoongkang](https://github.com/yoongkang) -- Kevin Yang / [kevieyang] (https://github.com/kevieyang) +- Kevin Yang / [kevieyang](https://github.com/kevieyang) From b520f9e78b0e5027b1bc98ace312c61f15bf26e8 Mon Sep 17 00:00:00 2001 From: Skud Date: Fri, 12 Dec 2014 18:43:42 +1100 Subject: [PATCH 065/143] Update CONTRIBUTORS.md Removed duplicate contributor --- CONTRIBUTORS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 83bf19f30..f5c68da86 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -38,7 +38,6 @@ submit the change with your pull request. - Yaw Boakye / [yawboakye](https://github.com/yawboakye) - Ryan Clark / [IAMRYO](https://github.com/IAMRYO) - Marty Hines / [martyhines](https://github.com/martyhines) -- Mackenzie "Maco" King / [maco](https://github.com/maco) - Amelia Greenhall / [ameliagreenhall](https://github.com/ameliagreenhall) - Barb Natali / [barbnatali](https://github.com/barbnatali) - Taylor Griffin / [tygriffin](https://github.com/tygriffin) From df3b300967eec01d37d436741c6b728db7a00e1d Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Fri, 12 Dec 2014 21:31:22 +1100 Subject: [PATCH 066/143] remove '/assets' from references to assets --- app/assets/stylesheets/overrides.css.less | 2 ++ app/views/home/_keep_in_touch.html.haml | 6 +++--- app/views/layouts/_header.html.haml | 2 +- app/views/layouts/_meta.html.haml | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/overrides.css.less b/app/assets/stylesheets/overrides.css.less index 8b9938c33..8335f6e38 100644 --- a/app/assets/stylesheets/overrides.css.less +++ b/app/assets/stylesheets/overrides.css.less @@ -1,3 +1,5 @@ + + @import "twitter/bootstrap/bootstrap"; @import "custom_bootstrap/variables"; // this padding needs to be done before the responsive stuff is imported diff --git a/app/views/home/_keep_in_touch.html.haml b/app/views/home/_keep_in_touch.html.haml index 5bc821887..4219ba2c9 100644 --- a/app/views/home/_keep_in_touch.html.haml +++ b/app/views/home/_keep_in_touch.html.haml @@ -1,14 +1,14 @@ %h2= t('.keep_in_touch') %p - =image_tag("twitter_32.png", :alt => '') + = image_tag("twitter_32.png", :alt => '') = t('.twitter_html', link: link_to(t('.twitter_linktext'), 'http://twitter.com/growstufforg')) %p - =image_tag("blog_32.png", :alt => '') + = image_tag("blog_32.png", :alt => '') = t('.blog_html', link: link_to(t('.blog_linktext'), 'http://blog.growstuff.org/')) %p - =image_tag("email_32.png", :alt => '') + = image_tag("email_32.png", :alt => '') = t('.newsletter_html', link: link_to(t('.newsletter_linktext'), 'http://blog.growstuff.org/newsletter')) diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index d68f6dc73..691de3681 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -9,7 +9,7 @@ %span.icon-bar %span.icon-bar %a.navbar-brand(href=root_path) - = image_tag("/assets/growstuff-brand.png", :size => "200x50", :alt => ENV['GROWSTUFF_SITE_NAME']) + = image_tag("growstuff-brand.png", :size => "200x50", :alt => ENV['GROWSTUFF_SITE_NAME']) .navbar-collapse.collapse#navbar-collapse %ul.nav.navbar-nav %li.dropdown< diff --git a/app/views/layouts/_meta.html.haml b/app/views/layouts/_meta.html.haml index c5313fb8d..13acb28bc 100644 --- a/app/views/layouts/_meta.html.haml +++ b/app/views/layouts/_meta.html.haml @@ -16,5 +16,5 @@ = javascript_include_tag "http://html5shim.googlecode.com/svn/trunk/html5.js" = stylesheet_link_tag "application", :media => "all" - %link(href="/assets/growstuff-apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed") - = favicon_link_tag '/assets/favicon.ico' + %link(href="/growstuff-apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed") + = favicon_link_tag 'favicon.ico' From 314cdc687acd26395c8cea179c9cb0d8826f4d9e Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Fri, 12 Dec 2014 22:00:30 +1100 Subject: [PATCH 067/143] precompiled assets --- ...ation-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css | 14194 ++++++++ ...on-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css.gz | Bin 0 -> 46379 bytes ...cation-f56a930e8b43a3cc1181ac77bbbfd62c.js | 28346 ++++++++++++++++ ...ion-f56a930e8b43a3cc1181ac77bbbfd62c.js.gz | Bin 0 -> 207326 bytes ...og_32-cd9d23bb128848f966b93b5a6be60eaf.png | Bin 0 -> 5165 bytes ...il_32-27c42d56fd6fab63459f65beeaf2c433.png | Bin 0 -> 1091 bytes ...vicon-2d9538be1ba21dd336d216f1edc1af43.ico | Bin 0 -> 920 bytes ...kr_32-240521c8709386cde2a640f695c3a0d8.png | Bin 0 -> 2528 bytes ...posed-173fa2bf5c06e04b71a5fd2e7d39a45b.png | Bin 0 -> 10621 bytes ...brand-8165eeeb282a4d0e97f5d62ffd7f955c.png | Bin 0 -> 8246 bytes ...0x100-a796aaba676780590a0ff7cfd46ee344.png | Bin 0 -> 180 bytes ...0x100-ffb44d89b6dc89450392f1e1f58eb7b7.png | Bin 0 -> 178 bytes ...1x400-5a6117b272a6325f0df26aaaad7fa802.png | Bin 0 -> 120 bytes ...1x400-d09189c91e975a548a3e480466276edb.png | Bin 0 -> 105 bytes ...1x400-13a0d3dbe7ea3d5166ec518867c977f0.png | Bin 0 -> 111 bytes ...1x400-e0c3ddf50a54d67bca9270fbd3cc087d.png | Bin 0 -> 110 bytes ...1x400-9fe6add609a5109b0469dcac1c1d1e2d.png | Bin 0 -> 119 bytes ...1x100-ac6e5795700a84d9d45b9097e3a074af.png | Bin 0 -> 101 bytes ...6x240-739d28849235f1a0058c9441531ff036.png | Bin 0 -> 4369 bytes ...6x240-94fb86e64e2b65cc08912ee8ce12b5fb.png | Bin 0 -> 4369 bytes ...6x240-2f7323df209cc257b99c61fa63d59805.png | Bin 0 -> 4369 bytes ...6x240-c32e88858033b8e7d639857641a66f35.png | Bin 0 -> 4369 bytes ...6x240-16f7ed302044e242d145bbc57e60056c.png | Bin 0 -> 4369 bytes ...rs-2x-f3fa5498abaa53605391bf570244d276.png | Bin 0 -> 2898 bytes ...ayers-de3cc6e2e79af04f639a69468dde5e73.png | Bin 0 -> 1502 bytes ...fest-e0f2b07848288951a86f5d557ee2e4bd.json | 1 + ...on-2x-9cdf383d9b3b2bc63b12543881d4bd4a.png | Bin 0 -> 4033 bytes ...-icon-8cc661004b1c7549f04fc18bb0570ebc.png | Bin 0 -> 1747 bytes ...hadow-92bb3c28975f7df3fc4803a7fdf322ec.png | Bin 0 -> 797 bytes ...r_150-0034c8a70cd90db3456cfad4ef55c941.png | Bin 0 -> 2501 bytes ...rails-114159e903e0d9812cd5086001ca07b6.png | Bin 0 -> 6646 bytes ...gular-01ac2925443b477770637236eac3ae93.svg | 229 + ...gular-7adc8d5445918d3b2ccb2ee19d3cc85e.ttf | Bin 0 -> 41280 bytes ...ular-827db11d800feb83e913d47915a9b4f3.woff | Bin 0 -> 23320 bytes ...gular-aeb099b68de9718c8af59d46df10f80c.eot | Bin 0 -> 20335 bytes ...er_32-ae1546acdb3bf1b2e7ddc34daaf2e781.png | Bin 0 -> 1561 bytes 36 files changed, 42770 insertions(+) create mode 100644 public/assets/application-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css create mode 100644 public/assets/application-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css.gz create mode 100644 public/assets/application-f56a930e8b43a3cc1181ac77bbbfd62c.js create mode 100644 public/assets/application-f56a930e8b43a3cc1181ac77bbbfd62c.js.gz create mode 100644 public/assets/blog_32-cd9d23bb128848f966b93b5a6be60eaf.png create mode 100644 public/assets/email_32-27c42d56fd6fab63459f65beeaf2c433.png create mode 100644 public/assets/favicon-2d9538be1ba21dd336d216f1edc1af43.ico create mode 100644 public/assets/flickr_32-240521c8709386cde2a640f695c3a0d8.png create mode 100644 public/assets/growstuff-apple-touch-icon-precomposed-173fa2bf5c06e04b71a5fd2e7d39a45b.png create mode 100644 public/assets/growstuff-brand-8165eeeb282a4d0e97f5d62ffd7f955c.png create mode 100644 public/assets/jquery-ui/ui-bg_flat_0_aaaaaa_40x100-a796aaba676780590a0ff7cfd46ee344.png create mode 100644 public/assets/jquery-ui/ui-bg_flat_75_ffffff_40x100-ffb44d89b6dc89450392f1e1f58eb7b7.png create mode 100644 public/assets/jquery-ui/ui-bg_glass_55_fbf9ee_1x400-5a6117b272a6325f0df26aaaad7fa802.png create mode 100644 public/assets/jquery-ui/ui-bg_glass_65_ffffff_1x400-d09189c91e975a548a3e480466276edb.png create mode 100644 public/assets/jquery-ui/ui-bg_glass_75_dadada_1x400-13a0d3dbe7ea3d5166ec518867c977f0.png create mode 100644 public/assets/jquery-ui/ui-bg_glass_75_e6e6e6_1x400-e0c3ddf50a54d67bca9270fbd3cc087d.png create mode 100644 public/assets/jquery-ui/ui-bg_glass_95_fef1ec_1x400-9fe6add609a5109b0469dcac1c1d1e2d.png create mode 100644 public/assets/jquery-ui/ui-bg_highlight-soft_75_cccccc_1x100-ac6e5795700a84d9d45b9097e3a074af.png create mode 100644 public/assets/jquery-ui/ui-icons_222222_256x240-739d28849235f1a0058c9441531ff036.png create mode 100644 public/assets/jquery-ui/ui-icons_2e83ff_256x240-94fb86e64e2b65cc08912ee8ce12b5fb.png create mode 100644 public/assets/jquery-ui/ui-icons_454545_256x240-2f7323df209cc257b99c61fa63d59805.png create mode 100644 public/assets/jquery-ui/ui-icons_888888_256x240-c32e88858033b8e7d639857641a66f35.png create mode 100644 public/assets/jquery-ui/ui-icons_cd0a0a_256x240-16f7ed302044e242d145bbc57e60056c.png create mode 100644 public/assets/layers-2x-f3fa5498abaa53605391bf570244d276.png create mode 100644 public/assets/layers-de3cc6e2e79af04f639a69468dde5e73.png create mode 100644 public/assets/manifest-e0f2b07848288951a86f5d557ee2e4bd.json create mode 100644 public/assets/marker-icon-2x-9cdf383d9b3b2bc63b12543881d4bd4a.png create mode 100644 public/assets/marker-icon-8cc661004b1c7549f04fc18bb0570ebc.png create mode 100644 public/assets/marker-shadow-92bb3c28975f7df3fc4803a7fdf322ec.png create mode 100644 public/assets/placeholder_150-0034c8a70cd90db3456cfad4ef55c941.png create mode 100644 public/assets/rails-114159e903e0d9812cd5086001ca07b6.png create mode 100644 public/assets/twitter/bootstrap/glyphicons-halflings-regular-01ac2925443b477770637236eac3ae93.svg create mode 100644 public/assets/twitter/bootstrap/glyphicons-halflings-regular-7adc8d5445918d3b2ccb2ee19d3cc85e.ttf create mode 100644 public/assets/twitter/bootstrap/glyphicons-halflings-regular-827db11d800feb83e913d47915a9b4f3.woff create mode 100644 public/assets/twitter/bootstrap/glyphicons-halflings-regular-aeb099b68de9718c8af59d46df10f80c.eot create mode 100644 public/assets/twitter_32-ae1546acdb3bf1b2e7ddc34daaf2e781.png diff --git a/public/assets/application-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css b/public/assets/application-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css new file mode 100644 index 000000000..f973ece8d --- /dev/null +++ b/public/assets/application-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css @@ -0,0 +1,14194 @@ +/* + * This is a manifest file that'll automatically include all the stylesheets available in this directory + * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at + * the top of the compiled file, but it's generally better to create a new file per style scope. + + + + + + + + + +*/ + +/*! + * jQuery UI CSS Framework 1.11.2 + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/category/theming/ + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/ + */ + +/* + + + + + + + + + + + + + + */ + + + +/* Component containers +----------------------------------*/ + +.ui-widget { + font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; + font-size: 1.1em/*{fsDefault}*/; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; + font-size: 1em; +} +.ui-widget-content { + border: 1px solid #aaaaaa/*{borderColorContent}*/; + background: #ffffff/*{bgColorContent}*/ url(/assets/jquery-ui/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; + color: #222222/*{fcContent}*/; +} +.ui-widget-content a { + color: #222222/*{fcContent}*/; +} +.ui-widget-header { + border: 1px solid #aaaaaa/*{borderColorHeader}*/; + background: #cccccc/*{bgColorHeader}*/ url(/assets/jquery-ui/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; + color: #222222/*{fcHeader}*/; + font-weight: bold; +} +.ui-widget-header a { + color: #222222/*{fcHeader}*/; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default { + border: 1px solid #d3d3d3/*{borderColorDefault}*/; + background: #e6e6e6/*{bgColorDefault}*/ url(/assets/jquery-ui/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; + font-weight: normal/*{fwDefault}*/; + color: #555555/*{fcDefault}*/; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited { + color: #555555/*{fcDefault}*/; + text-decoration: none; +} +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { + border: 1px solid #999999/*{borderColorHover}*/; + background: #dadada/*{bgColorHover}*/ url(/assets/jquery-ui/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; + font-weight: normal/*{fwDefault}*/; + color: #212121/*{fcHover}*/; +} +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited, +.ui-state-focus a, +.ui-state-focus a:hover, +.ui-state-focus a:link, +.ui-state-focus a:visited { + color: #212121/*{fcHover}*/; + text-decoration: none; +} +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active { + border: 1px solid #aaaaaa/*{borderColorActive}*/; + background: #ffffff/*{bgColorActive}*/ url(/assets/jquery-ui/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; + font-weight: normal/*{fwDefault}*/; + color: #212121/*{fcActive}*/; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #212121/*{fcActive}*/; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #fcefa1/*{borderColorHighlight}*/; + background: #fbf9ee/*{bgColorHighlight}*/ url(/assets/jquery-ui/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; + color: #363636/*{fcHighlight}*/; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #363636/*{fcHighlight}*/; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #cd0a0a/*{borderColorError}*/; + background: #fef1ec/*{bgColorError}*/ url(/assets/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; + color: #cd0a0a/*{fcError}*/; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #cd0a0a/*{fcError}*/; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #cd0a0a/*{fcError}*/; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + filter:Alpha(Opacity=70); /* support: IE8 */ + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + filter:Alpha(Opacity=35); /* support: IE8 */ + background-image: none; +} +.ui-state-disabled .ui-icon { + filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ +} + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url(/assets/jquery-ui/ui-icons_222222_256x240.png)/*{iconsContent}*/; +} +.ui-widget-header .ui-icon { + background-image: url(/assets/jquery-ui/ui-icons_222222_256x240.png)/*{iconsHeader}*/; +} +.ui-state-default .ui-icon { + background-image: url(/assets/jquery-ui/ui-icons_888888_256x240.png)/*{iconsDefault}*/; +} +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon { + background-image: url(/assets/jquery-ui/ui-icons_454545_256x240.png)/*{iconsHover}*/; +} +.ui-state-active .ui-icon { + background-image: url(/assets/jquery-ui/ui-icons_454545_256x240.png)/*{iconsActive}*/; +} +.ui-state-highlight .ui-icon { + background-image: url(/assets/jquery-ui/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url(/assets/jquery-ui/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; +} + +/* positioning */ +.ui-icon-blank { background-position: 16px 16px; } +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + border-top-left-radius: 4px/*{cornerRadius}*/; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + border-top-right-radius: 4px/*{cornerRadius}*/; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + border-bottom-left-radius: 4px/*{cornerRadius}*/; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + border-bottom-right-radius: 4px/*{cornerRadius}*/; +} + +/* Overlays */ +.ui-widget-overlay { + background: #aaaaaa/*{bgColorOverlay}*/ url(/assets/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; + opacity: .3/*{opacityOverlay}*/; + filter: Alpha(Opacity=30)/*{opacityFilterOverlay}*/; /* support: IE8 */ +} +.ui-widget-shadow { + margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; + padding: 8px/*{thicknessShadow}*/; + background: #aaaaaa/*{bgColorShadow}*/ url(/assets/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; + opacity: .3/*{opacityShadow}*/; + filter: Alpha(Opacity=30)/*{opacityFilterShadow}*/; /* support: IE8 */ + border-radius: 8px/*{cornerRadiusShadow}*/; +} +/*! + * jQuery UI CSS Framework 1.11.2 + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/category/theming/ + */ +/* + + */ + +/* Layout helpers +----------------------------------*/ + +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; /* support: IE7 */ +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); /* support: IE8 */ +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; +} + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +/*! + * jQuery UI Menu 1.11.2 + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/menu/#theming + */ +/* + + + */ + +.ui-menu { + list-style: none; + padding: 0; + margin: 0; + display: block; + outline: none; +} +.ui-menu .ui-menu { + position: absolute; +} +.ui-menu .ui-menu-item { + position: relative; + margin: 0; + padding: 3px 1em 3px .4em; + cursor: pointer; + min-height: 0; /* support: IE7 */ + /* support: IE10, see #8844 */ + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); +} +.ui-menu .ui-menu-divider { + margin: 5px 0; + height: 0; + font-size: 0; + line-height: 0; + border-width: 1px 0 0 0; +} +.ui-menu .ui-state-focus, +.ui-menu .ui-state-active { + margin: -1px; +} + +/* icon support */ +.ui-menu-icons { + position: relative; +} +.ui-menu-icons .ui-menu-item { + padding-left: 2em; +} + +/* left-aligned */ +.ui-menu .ui-icon { + position: absolute; + top: 0; + bottom: 0; + left: .2em; + margin: auto 0; +} + +/* right-aligned */ +.ui-menu .ui-menu-icon { + left: auto; + right: 0; +} +/*! + * jQuery UI Autocomplete 1.11.2 + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/autocomplete/#theming + */ +/* + + + + */ + +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} +/*! + * Datepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ + +.datepicker { + padding: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + direction: ltr; + /*.dow { + border-top: 1px solid #ddd !important; + }*/ +} +.datepicker-inline { + width: 220px; +} +.datepicker.datepicker-rtl { + direction: rtl; +} +.datepicker.datepicker-rtl table tr td span { + float: right; +} +.datepicker-dropdown { + top: 0; + left: 0; +} +.datepicker-dropdown:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-top: 0; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; +} +.datepicker-dropdown:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + border-top: 0; + position: absolute; +} +.datepicker-dropdown.datepicker-orient-left:before { + left: 6px; +} +.datepicker-dropdown.datepicker-orient-left:after { + left: 7px; +} +.datepicker-dropdown.datepicker-orient-right:before { + right: 6px; +} +.datepicker-dropdown.datepicker-orient-right:after { + right: 7px; +} +.datepicker-dropdown.datepicker-orient-top:before { + top: -7px; +} +.datepicker-dropdown.datepicker-orient-top:after { + top: -6px; +} +.datepicker-dropdown.datepicker-orient-bottom:before { + bottom: -7px; + border-bottom: 0; + border-top: 7px solid #999; +} +.datepicker-dropdown.datepicker-orient-bottom:after { + bottom: -6px; + border-bottom: 0; + border-top: 6px solid #ffffff; +} +.datepicker > div { + display: none; +} +.datepicker.days div.datepicker-days { + display: block; +} +.datepicker.months div.datepicker-months { + display: block; +} +.datepicker.years div.datepicker-years { + display: block; +} +.datepicker table { + margin: 0; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.datepicker td, +.datepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + border: none; +} +.table-striped .datepicker table tr td, +.table-striped .datepicker table tr th { + background-color: transparent; +} +.datepicker table tr td.day:hover, +.datepicker table tr td.day.focused { + background: #eeeeee; + cursor: pointer; +} +.datepicker table tr td.old, +.datepicker table tr td.new { + color: #999999; +} +.datepicker table tr td.disabled, +.datepicker table tr td.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datepicker table tr td.today, +.datepicker table tr td.today:hover, +.datepicker table tr td.today.disabled, +.datepicker table tr td.today.disabled:hover { + background-color: #fde19a; + background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); + background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); + background-image: linear-gradient(top, #fdd49a, #fdf59a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); + border-color: #fdf59a #fdf59a #fbed50; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #000; +} +.datepicker table tr td.today:hover, +.datepicker table tr td.today:hover:hover, +.datepicker table tr td.today.disabled:hover, +.datepicker table tr td.today.disabled:hover:hover, +.datepicker table tr td.today:active, +.datepicker table tr td.today:hover:active, +.datepicker table tr td.today.disabled:active, +.datepicker table tr td.today.disabled:hover:active, +.datepicker table tr td.today.active, +.datepicker table tr td.today:hover.active, +.datepicker table tr td.today.disabled.active, +.datepicker table tr td.today.disabled:hover.active, +.datepicker table tr td.today.disabled, +.datepicker table tr td.today:hover.disabled, +.datepicker table tr td.today.disabled.disabled, +.datepicker table tr td.today.disabled:hover.disabled, +.datepicker table tr td.today[disabled], +.datepicker table tr td.today:hover[disabled], +.datepicker table tr td.today.disabled[disabled], +.datepicker table tr td.today.disabled:hover[disabled] { + background-color: #fdf59a; +} +.datepicker table tr td.today:active, +.datepicker table tr td.today:hover:active, +.datepicker table tr td.today.disabled:active, +.datepicker table tr td.today.disabled:hover:active, +.datepicker table tr td.today.active, +.datepicker table tr td.today:hover.active, +.datepicker table tr td.today.disabled.active, +.datepicker table tr td.today.disabled:hover.active { + background-color: #fbf069 \9; +} +.datepicker table tr td.today:hover:hover { + color: #000; +} +.datepicker table tr td.today.active:hover { + color: #fff; +} +.datepicker table tr td.range, +.datepicker table tr td.range:hover, +.datepicker table tr td.range.disabled, +.datepicker table tr td.range.disabled:hover { + background: #eeeeee; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.datepicker table tr td.range.today, +.datepicker table tr td.range.today:hover, +.datepicker table tr td.range.today.disabled, +.datepicker table tr td.range.today.disabled:hover { + background-color: #f3d17a; + background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a)); + background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -o-linear-gradient(top, #f3c17a, #f3e97a); + background-image: linear-gradient(top, #f3c17a, #f3e97a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0); + border-color: #f3e97a #f3e97a #edde34; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.datepicker table tr td.range.today:hover, +.datepicker table tr td.range.today:hover:hover, +.datepicker table tr td.range.today.disabled:hover, +.datepicker table tr td.range.today.disabled:hover:hover, +.datepicker table tr td.range.today:active, +.datepicker table tr td.range.today:hover:active, +.datepicker table tr td.range.today.disabled:active, +.datepicker table tr td.range.today.disabled:hover:active, +.datepicker table tr td.range.today.active, +.datepicker table tr td.range.today:hover.active, +.datepicker table tr td.range.today.disabled.active, +.datepicker table tr td.range.today.disabled:hover.active, +.datepicker table tr td.range.today.disabled, +.datepicker table tr td.range.today:hover.disabled, +.datepicker table tr td.range.today.disabled.disabled, +.datepicker table tr td.range.today.disabled:hover.disabled, +.datepicker table tr td.range.today[disabled], +.datepicker table tr td.range.today:hover[disabled], +.datepicker table tr td.range.today.disabled[disabled], +.datepicker table tr td.range.today.disabled:hover[disabled] { + background-color: #f3e97a; +} +.datepicker table tr td.range.today:active, +.datepicker table tr td.range.today:hover:active, +.datepicker table tr td.range.today.disabled:active, +.datepicker table tr td.range.today.disabled:hover:active, +.datepicker table tr td.range.today.active, +.datepicker table tr td.range.today:hover.active, +.datepicker table tr td.range.today.disabled.active, +.datepicker table tr td.range.today.disabled:hover.active { + background-color: #efe24b \9; +} +.datepicker table tr td.selected, +.datepicker table tr td.selected:hover, +.datepicker table tr td.selected.disabled, +.datepicker table tr td.selected.disabled:hover { + background-color: #9e9e9e; + background-image: -moz-linear-gradient(top, #b3b3b3, #808080); + background-image: -ms-linear-gradient(top, #b3b3b3, #808080); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080)); + background-image: -webkit-linear-gradient(top, #b3b3b3, #808080); + background-image: -o-linear-gradient(top, #b3b3b3, #808080); + background-image: linear-gradient(top, #b3b3b3, #808080); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0); + border-color: #808080 #808080 #595959; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td.selected:hover, +.datepicker table tr td.selected:hover:hover, +.datepicker table tr td.selected.disabled:hover, +.datepicker table tr td.selected.disabled:hover:hover, +.datepicker table tr td.selected:active, +.datepicker table tr td.selected:hover:active, +.datepicker table tr td.selected.disabled:active, +.datepicker table tr td.selected.disabled:hover:active, +.datepicker table tr td.selected.active, +.datepicker table tr td.selected:hover.active, +.datepicker table tr td.selected.disabled.active, +.datepicker table tr td.selected.disabled:hover.active, +.datepicker table tr td.selected.disabled, +.datepicker table tr td.selected:hover.disabled, +.datepicker table tr td.selected.disabled.disabled, +.datepicker table tr td.selected.disabled:hover.disabled, +.datepicker table tr td.selected[disabled], +.datepicker table tr td.selected:hover[disabled], +.datepicker table tr td.selected.disabled[disabled], +.datepicker table tr td.selected.disabled:hover[disabled] { + background-color: #808080; +} +.datepicker table tr td.selected:active, +.datepicker table tr td.selected:hover:active, +.datepicker table tr td.selected.disabled:active, +.datepicker table tr td.selected.disabled:hover:active, +.datepicker table tr td.selected.active, +.datepicker table tr td.selected:hover.active, +.datepicker table tr td.selected.disabled.active, +.datepicker table tr td.selected.disabled:hover.active { + background-color: #666666 \9; +} +.datepicker table tr td.active, +.datepicker table tr td.active:hover, +.datepicker table tr td.active.disabled, +.datepicker table tr td.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td.active:hover, +.datepicker table tr td.active:hover:hover, +.datepicker table tr td.active.disabled:hover, +.datepicker table tr td.active.disabled:hover:hover, +.datepicker table tr td.active:active, +.datepicker table tr td.active:hover:active, +.datepicker table tr td.active.disabled:active, +.datepicker table tr td.active.disabled:hover:active, +.datepicker table tr td.active.active, +.datepicker table tr td.active:hover.active, +.datepicker table tr td.active.disabled.active, +.datepicker table tr td.active.disabled:hover.active, +.datepicker table tr td.active.disabled, +.datepicker table tr td.active:hover.disabled, +.datepicker table tr td.active.disabled.disabled, +.datepicker table tr td.active.disabled:hover.disabled, +.datepicker table tr td.active[disabled], +.datepicker table tr td.active:hover[disabled], +.datepicker table tr td.active.disabled[disabled], +.datepicker table tr td.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datepicker table tr td.active:active, +.datepicker table tr td.active:hover:active, +.datepicker table tr td.active.disabled:active, +.datepicker table tr td.active.disabled:hover:active, +.datepicker table tr td.active.active, +.datepicker table tr td.active:hover.active, +.datepicker table tr td.active.disabled.active, +.datepicker table tr td.active.disabled:hover.active { + background-color: #003399 \9; +} +.datepicker table tr td span { + display: block; + width: 23%; + height: 54px; + line-height: 54px; + float: left; + margin: 1%; + cursor: pointer; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.datepicker table tr td span:hover { + background: #eeeeee; +} +.datepicker table tr td span.disabled, +.datepicker table tr td span.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datepicker table tr td span.active, +.datepicker table tr td span.active:hover, +.datepicker table tr td span.active.disabled, +.datepicker table tr td span.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td span.active:hover, +.datepicker table tr td span.active:hover:hover, +.datepicker table tr td span.active.disabled:hover, +.datepicker table tr td span.active.disabled:hover:hover, +.datepicker table tr td span.active:active, +.datepicker table tr td span.active:hover:active, +.datepicker table tr td span.active.disabled:active, +.datepicker table tr td span.active.disabled:hover:active, +.datepicker table tr td span.active.active, +.datepicker table tr td span.active:hover.active, +.datepicker table tr td span.active.disabled.active, +.datepicker table tr td span.active.disabled:hover.active, +.datepicker table tr td span.active.disabled, +.datepicker table tr td span.active:hover.disabled, +.datepicker table tr td span.active.disabled.disabled, +.datepicker table tr td span.active.disabled:hover.disabled, +.datepicker table tr td span.active[disabled], +.datepicker table tr td span.active:hover[disabled], +.datepicker table tr td span.active.disabled[disabled], +.datepicker table tr td span.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datepicker table tr td span.active:active, +.datepicker table tr td span.active:hover:active, +.datepicker table tr td span.active.disabled:active, +.datepicker table tr td span.active.disabled:hover:active, +.datepicker table tr td span.active.active, +.datepicker table tr td span.active:hover.active, +.datepicker table tr td span.active.disabled.active, +.datepicker table tr td span.active.disabled:hover.active { + background-color: #003399 \9; +} +.datepicker table tr td span.old, +.datepicker table tr td span.new { + color: #999999; +} +.datepicker th.datepicker-switch { + width: 145px; +} +.datepicker thead tr:first-child th, +.datepicker tfoot tr th { + cursor: pointer; +} +.datepicker thead tr:first-child th:hover, +.datepicker tfoot tr th:hover { + background: #eeeeee; +} +.datepicker .cw { + font-size: 10px; + width: 12px; + padding: 0 2px 0 5px; + vertical-align: middle; +} +.datepicker thead tr:first-child th.cw { + cursor: default; + background-color: transparent; +} +.input-append.date .add-on i, +.input-prepend.date .add-on i { + cursor: pointer; + width: 16px; + height: 16px; +} +.input-daterange input { + text-align: center; +} +.input-daterange input:first-child { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-daterange input:last-child { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.input-daterange .add-on { + display: inline-block; + width: auto; + min-width: 16px; + height: 20px; + padding: 4px 5px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + vertical-align: middle; + background-color: #eeeeee; + border: 1px solid #ccc; + margin-left: -5px; + margin-right: -5px; +} +.datepicker.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + float: left; + display: none; + min-width: 160px; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + *border-right-width: 2px; + *border-bottom-width: 2px; + color: #333333; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 20px; +} +.datepicker.dropdown-menu th, +.datepicker.dropdown-menu td { + padding: 4px 5px; +} +/* required styles */ + + +.leaflet-map-pane, +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-tile-pane, +.leaflet-tile-container, +.leaflet-overlay-pane, +.leaflet-shadow-pane, +.leaflet-marker-pane, +.leaflet-popup-pane, +.leaflet-overlay-pane svg, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; + } +.leaflet-container { + overflow: hidden; + -ms-touch-action: none; + } +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } +/* map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container img { + max-width: none !important; + } +/* stupid Android 2 doesn't understand "max-width: none" properly */ +.leaflet-container img.leaflet-image-layer { + max-width: 15000px !important; + } +.leaflet-tile { + filter: inherit; + visibility: hidden; + } +.leaflet-tile-loaded { + visibility: inherit; + } +.leaflet-zoom-box { + width: 0; + height: 0; + } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; + } + +.leaflet-tile-pane { z-index: 2; } +.leaflet-objects-pane { z-index: 3; } +.leaflet-overlay-pane { z-index: 4; } +.leaflet-shadow-pane { z-index: 5; } +.leaflet-marker-pane { z-index: 6; } +.leaflet-popup-pane { z-index: 7; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 7; + pointer-events: auto; + } +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; + } +.leaflet-top { + top: 0; + } +.leaflet-right { + right: 0; + } +.leaflet-bottom { + bottom: 0; + } +.leaflet-left { + left: 0; + } +.leaflet-control { + float: left; + clear: both; + } +.leaflet-right .leaflet-control { + float: right; + } +.leaflet-top .leaflet-control { + margin-top: 10px; + } +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; + } +.leaflet-left .leaflet-control { + margin-left: 10px; + } +.leaflet-right .leaflet-control { + margin-right: 10px; + } + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-tile, +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } +.leaflet-fade-anim .leaflet-tile-loaded, +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; + } + +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile, +.leaflet-touching .leaflet-zoom-animated { + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; + } + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; + } + + +/* cursors */ + +.leaflet-clickable { + cursor: pointer; + } +.leaflet-container { + cursor: -webkit-grab; + cursor: -moz-grab; + } +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; + } +.leaflet-dragging .leaflet-container, +.leaflet-dragging .leaflet-clickable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + } + + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline: 0; + } +.leaflet-container a { + color: #0078A8; + } +.leaflet-container a.leaflet-active { + outline: 2px solid orange; + } +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); + } + + +/* general typography */ +.leaflet-container { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + } + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; + } +.leaflet-bar a, +.leaflet-bar a:hover { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; + } +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-bar a:hover { + background-color: #f4f4f4; + } +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + } +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; + } + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; + } + + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; + } +.leaflet-control-zoom-out { + font-size: 20px; + } + +.leaflet-touch .leaflet-control-zoom-in { + font-size: 22px; + } +.leaflet-touch .leaflet-control-zoom-out { + font-size: 24px; + } + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; + } +.leaflet-control-layers-toggle { + background-image: url(/assets/layers.png); + width: 36px; + height: 36px; + } +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(/assets/layers-2x.png); + background-size: 26px 26px; + } +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; + } +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; + } +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; + } +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; + } +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; + } +.leaflet-control-layers label { + display: block; + } +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; + } + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.7); + margin: 0; + } +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; + } +.leaflet-control-attribution a { + text-decoration: none; + } +.leaflet-control-attribution a:hover { + text-decoration: underline; + } +.leaflet-container .leaflet-control-attribution, +.leaflet-container .leaflet-control-scale { + font-size: 11px; + } +.leaflet-left .leaflet-control-scale { + margin-left: 5px; + } +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; + } +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + font-size: 11px; + white-space: nowrap; + overflow: hidden; + -moz-box-sizing: content-box; + box-sizing: content-box; + + background: #fff; + background: rgba(255, 255, 255, 0.5); + } +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; + } +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; + } + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; + } +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + } + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + } +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; + } +.leaflet-popup-content { + margin: 13px 19px; + line-height: 1.4; + } +.leaflet-popup-content p { + margin: 18px 0; + } +.leaflet-popup-tip-container { + margin: 0 auto; + width: 40px; + height: 20px; + position: relative; + overflow: hidden; + } +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + } +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + + box-shadow: 0 3px 14px rgba(0,0,0,0.4); + } +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + padding: 4px 4px 0 0; + text-align: center; + width: 18px; + height: 14px; + font: 16px/14px Tahoma, Verdana, sans-serif; + color: #c3c3c3; + text-decoration: none; + font-weight: bold; + background: transparent; + } +.leaflet-container a.leaflet-popup-close-button:hover { + color: #999; + } +.leaflet-popup-scrolled { + overflow: auto; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + } + +.leaflet-oldie .leaflet-popup-content-wrapper { + zoom: 1; + } +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + } +.leaflet-oldie .leaflet-popup-tip-container { + margin-top: -1px; + } + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; + } + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; + } +.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow { + -webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in; + -moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in; + -o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in; + transition: transform 0.3s ease-out, opacity 0.3s ease-in; + } +.marker-cluster-small { + background-color: rgba(181, 226, 140, 0.6); + } +.marker-cluster-small div { + background-color: rgba(110, 204, 57, 0.6); + } + +.marker-cluster-medium { + background-color: rgba(241, 211, 87, 0.6); + } +.marker-cluster-medium div { + background-color: rgba(240, 194, 12, 0.6); + } + +.marker-cluster-large { + background-color: rgba(253, 156, 115, 0.6); + } +.marker-cluster-large div { + background-color: rgba(241, 128, 23, 0.6); + } + + /* IE 6-8 fallback colors */ +.leaflet-oldie .marker-cluster-small { + background-color: rgb(181, 226, 140); + } +.leaflet-oldie .marker-cluster-small div { + background-color: rgb(110, 204, 57); + } + +.leaflet-oldie .marker-cluster-medium { + background-color: rgb(241, 211, 87); + } +.leaflet-oldie .marker-cluster-medium div { + background-color: rgb(240, 194, 12); + } + +.leaflet-oldie .marker-cluster-large { + background-color: rgb(253, 156, 115); + } +.leaflet-oldie .marker-cluster-large div { + background-color: rgb(241, 128, 23); +} + +.marker-cluster { + background-clip: padding-box; + border-radius: 20px; + } +.marker-cluster div { + width: 30px; + height: 30px; + margin-left: 5px; + margin-top: 5px; + + text-align: center; + border-radius: 15px; + font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif; + } +.marker-cluster span { + line-height: 30px; + } +/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +@media print { + * { + text-shadow: none !important; + color: #000 !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url(/assets/twitter/bootstrap/glyphicons-halflings-regular.eot); + src: url(/assets/twitter/bootstrap/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'), url(/assets/twitter/bootstrap/glyphicons-halflings-regular.woff) format('woff'), url(/assets/twitter/bootstrap/glyphicons-halflings-regular.ttf) format('truetype'), url(/assets/twitter/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.5; + color: #413f3b; + background-color: #f3f1ee; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #5f8e43; + text-decoration: none; +} +a:hover, +a:focus { + color: #3c5a2a; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + width: 100% \9; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.5; + background-color: #f3f1ee; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + width: 100% \9; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 21px; + margin-bottom: 21px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: bold; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 21px; + margin-bottom: 10.5px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10.5px; + margin-bottom: 10.5px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10.5px; +} +.lead { + margin-bottom: 21px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +cite { + font-style: normal; +} +mark, +.mark { + background-color: #fcf8e3; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777777; +} +.text-primary { + color: #5f8e43; +} +a.text-primary:hover { + color: #486b33; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #5f8e43; +} +a.bg-primary:hover { + background-color: #486b33; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9.5px; + margin: 42px 0 21px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10.5px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 21px; +} +dt, +dd { + line-height: 1.5; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 992px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10.5px 21px; + margin: 0 0 21px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.5; + color: #777777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +blockquote:before, +blockquote:after { + content: ""; +} +address { + margin-bottom: 21px; + font-style: normal; + line-height: 1.5; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + box-shadow: none; +} +pre { + display: block; + padding: 10px; + margin: 0 0 10.5px; + font-size: 13px; + line-height: 1.5; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 21px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.5; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #dddddd; +} +.table .table { + background-color: #f3f1ee; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-child(odd) > td, +.table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover > td, +.table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15.75px; + overflow-y: hidden; + overflow-x: auto; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #dddddd; + -webkit-overflow-scrolling: touch; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 21px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.5; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 35px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.5; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #777777; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #777777; +} +.form-control::-webkit-input-placeholder { + color: #777777; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + line-height: 35px; + line-height: 1.5 \0; +} +input[type="date"].input-sm, +input[type="time"].input-sm, +input[type="datetime-local"].input-sm, +input[type="month"].input-sm { + line-height: 30px; +} +input[type="date"].input-lg, +input[type="time"].input-lg, +input[type="datetime-local"].input-lg, +input[type="month"].input-lg { + line-height: 46px; +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + min-height: 21px; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm, +.form-horizontal .form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.input-lg, +.form-horizontal .form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 43.75px; +} +.form-control-feedback { + position: absolute; + top: 26px; + right: 0; + z-index: 2; + display: block; + width: 35px; + height: 35px; + line-height: 35px; + text-align: center; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #848078; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 28px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + top: 0; + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.3px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.5; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default .badge { + color: #ffffff; + background-color: #333333; +} +.btn-primary { + color: #ffffff; + background-color: #5f8e43; + border-color: #537d3b; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #486b33; + border-color: #385327; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #5f8e43; + border-color: #537d3b; +} +.btn-primary .badge { + color: #5f8e43; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #ffffff; +} +.btn-link { + color: #5f8e43; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #3c5a2a; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9.5px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.5; + color: #413f3b; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #413f3b; + background-color: #e6f0e0; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #5f8e43; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.5; + color: #777777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 992px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus { + outline: 0; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn > input[type="radio"], +[data-toggle="buttons"] > .btn > input[type="checkbox"] { + position: absolute; + z-index: -1; + opacity: 0; + filter: alpha(opacity=0); +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.nav > li.disabled > a { + color: #777777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + border-color: #5f8e43; +} +.nav .nav-divider { + height: 1px; + margin: 9.5px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #dddddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.5; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + background-color: #f3f1ee; + border: 1px solid #dddddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #f3f1ee; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #5f8e43; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #f3f1ee; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 21px; + border: 1px solid transparent; +} +@media (min-width: 992px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 992px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 992px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 992px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 992px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +@media (min-width: 992px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 14.5px 15px; + font-size: 18px; + line-height: 21px; + height: 50px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +@media (min-width: 992px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 992px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.25px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 21px; +} +@media (max-width: 991px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 21px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 992px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 14.5px; + padding-bottom: 14.5px; + } + .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } +} +@media (min-width: 992px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 7.5px; + margin-bottom: 7.5px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 991px) { + .navbar-form .form-group { + margin-bottom: 5px; + } +} +@media (min-width: 992px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-form.navbar-right:last-child { + margin-right: -15px; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 7.5px; + margin-bottom: 7.5px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 14.5px; + margin-bottom: 14.5px; +} +@media (min-width: 992px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } + .navbar-text.navbar-right:last-child { + margin-right: 0; + } +} +.navbar-default { + background-color: #413f3b; + border-color: #302e2b; +} +.navbar-default .navbar-brand { + color: #92bf78; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #77af55; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #f3f1ee; +} +.navbar-default .navbar-nav > li > a { + color: #c9c0b2; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #f3f1ee; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #f3f1ee; + background-color: #302e2b; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #dddddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #dddddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #302e2b; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #302e2b; + color: #f3f1ee; +} +@media (max-width: 991px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #c9c0b2; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #f3f1ee; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #f3f1ee; + background-color: #302e2b; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #c9c0b2; +} +.navbar-default .navbar-link:hover { + color: #f3f1ee; +} +.navbar-default .btn-link { + color: #c9c0b2; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #f3f1ee; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #cccccc; +} +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #777777; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #777777; +} +.navbar-inverse .navbar-nav > li > a { + color: #777777; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #ffffff; +} +@media (max-width: 991px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #777777; +} +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} +.navbar-inverse .btn-link { + color: #777777; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #ffffff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 21px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; +} +.breadcrumb > .active { + color: #777777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 21px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.5; + text-decoration: none; + color: #5f8e43; + background-color: #ffffff; + border: 1px solid #dddddd; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #3c5a2a; + background-color: #eeeeee; + border-color: #dddddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #5f8e43; + border-color: #5f8e43; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777777; + background-color: #ffffff; + border-color: #dddddd; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 21px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777777; + background-color: #ffffff; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #5f8e43; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #486b33; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #777777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +a.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #5f8e43; + background-color: #ffffff; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #ded8d0; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #c9c0b2; +} +.container .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 21px; + line-height: 1.5; + background-color: #f3f1ee; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #5f8e43; +} +.thumbnail .caption { + padding: 9px; + color: #413f3b; +} +.alert { + padding: 15px; + margin-bottom: 21px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 21px; + margin-bottom: 21px; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 21px; + color: #ffffff; + text-align: center; + background-color: #5f8e43; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar[aria-valuenow="1"], +.progress-bar[aria-valuenow="2"] { + min-width: 30px; +} +.progress-bar[aria-valuenow="0"] { + color: #777777; + min-width: 30px; + background-color: transparent; + background-image: none; + box-shadow: none; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media, +.media .media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media-object { + display: block; +} +.media-heading { + margin: 0 0 5px; +} +.media > .pull-left { + margin-right: 10px; +} +.media > .pull-right { + margin-left: 10px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +a.list-group-item { + color: #555555; +} +a.list-group-item .list-group-item-heading { + color: #333333; +} +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #eeeeee; + color: #777777; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #5f8e43; + border-color: #5f8e43; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #cae0bd; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 21px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive { + border-top: 1px solid #dddddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 21px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body { + border-top: 1px solid #dddddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; +} +.panel-default { + border-color: #dddddd; +} +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #dddddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #dddddd; +} +.panel-primary { + border-color: #5f8e43; +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #5f8e43; + border-color: #5f8e43; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #5f8e43; +} +.panel-primary > .panel-heading .badge { + color: #5f8e43; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #5f8e43; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate3d(0, -25%, 0); + transform: translate3d(0, -25%, 0); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.5px; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.5; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + visibility: visible; + font-size: 12px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + right: 5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +@media print { + * { + text-shadow: none !important; + color: #000 !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url(/assets/twitter/bootstrap/glyphicons-halflings-regular-aeb099b68de9718c8af59d46df10f80c.eot); + src: url(/assets/twitter/bootstrap/glyphicons-halflings-regular-aeb099b68de9718c8af59d46df10f80c.eot?#iefix) format('embedded-opentype'), url(/assets/twitter/bootstrap/glyphicons-halflings-regular-827db11d800feb83e913d47915a9b4f3.woff) format('woff'), url(/assets/twitter/bootstrap/glyphicons-halflings-regular-7adc8d5445918d3b2ccb2ee19d3cc85e.ttf) format('truetype'), url(/assets/twitter/bootstrap/glyphicons-halflings-regular-01ac2925443b477770637236eac3ae93.svg#glyphicons_halflingsregular) format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.5; + color: #413f3b; + background-color: #f3f1ee; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #5f8e43; + text-decoration: none; +} +a:hover, +a:focus { + color: #3c5a2a; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + width: 100% \9; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.5; + background-color: #f3f1ee; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + width: 100% \9; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 21px; + margin-bottom: 21px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: bold; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 21px; + margin-bottom: 10.5px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10.5px; + margin-bottom: 10.5px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10.5px; +} +.lead { + margin-bottom: 21px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +cite { + font-style: normal; +} +mark, +.mark { + background-color: #fcf8e3; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777777; +} +.text-primary { + color: #5f8e43; +} +a.text-primary:hover { + color: #486b33; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #5f8e43; +} +a.bg-primary:hover { + background-color: #486b33; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9.5px; + margin: 42px 0 21px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10.5px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 21px; +} +dt, +dd { + line-height: 1.5; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 992px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10.5px 21px; + margin: 0 0 21px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.5; + color: #777777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +blockquote:before, +blockquote:after { + content: ""; +} +address { + margin-bottom: 21px; + font-style: normal; + line-height: 1.5; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + box-shadow: none; +} +pre { + display: block; + padding: 10px; + margin: 0 0 10.5px; + font-size: 13px; + line-height: 1.5; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 21px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.5; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #dddddd; +} +.table .table { + background-color: #f3f1ee; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-child(odd) > td, +.table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover > td, +.table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15.75px; + overflow-y: hidden; + overflow-x: auto; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #dddddd; + -webkit-overflow-scrolling: touch; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 21px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.5; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 35px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.5; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #777777; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #777777; +} +.form-control::-webkit-input-placeholder { + color: #777777; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + line-height: 35px; + line-height: 1.5 \0; +} +input[type="date"].input-sm, +input[type="time"].input-sm, +input[type="datetime-local"].input-sm, +input[type="month"].input-sm { + line-height: 30px; +} +input[type="date"].input-lg, +input[type="time"].input-lg, +input[type="datetime-local"].input-lg, +input[type="month"].input-lg { + line-height: 46px; +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + min-height: 21px; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm, +.form-horizontal .form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.input-lg, +.form-horizontal .form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 43.75px; +} +.form-control-feedback { + position: absolute; + top: 26px; + right: 0; + z-index: 2; + display: block; + width: 35px; + height: 35px; + line-height: 35px; + text-align: center; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #848078; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 28px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + top: 0; + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.3px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.5; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default .badge { + color: #ffffff; + background-color: #333333; +} +.btn-primary { + color: #ffffff; + background-color: #5f8e43; + border-color: #537d3b; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #486b33; + border-color: #385327; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #5f8e43; + border-color: #537d3b; +} +.btn-primary .badge { + color: #5f8e43; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #ffffff; +} +.btn-link { + color: #5f8e43; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #3c5a2a; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9.5px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.5; + color: #413f3b; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #413f3b; + background-color: #e6f0e0; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #5f8e43; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.5; + color: #777777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 992px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus { + outline: 0; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn > input[type="radio"], +[data-toggle="buttons"] > .btn > input[type="checkbox"] { + position: absolute; + z-index: -1; + opacity: 0; + filter: alpha(opacity=0); +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.nav > li.disabled > a { + color: #777777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + border-color: #5f8e43; +} +.nav .nav-divider { + height: 1px; + margin: 9.5px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #dddddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.5; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + background-color: #f3f1ee; + border: 1px solid #dddddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #f3f1ee; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #5f8e43; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #f3f1ee; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 21px; + border: 1px solid transparent; +} +@media (min-width: 992px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 992px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 992px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 992px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 992px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +@media (min-width: 992px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 14.5px 15px; + font-size: 18px; + line-height: 21px; + height: 50px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +@media (min-width: 992px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 992px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.25px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 21px; +} +@media (max-width: 991px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 21px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 992px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 14.5px; + padding-bottom: 14.5px; + } + .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } +} +@media (min-width: 992px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 7.5px; + margin-bottom: 7.5px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 991px) { + .navbar-form .form-group { + margin-bottom: 5px; + } +} +@media (min-width: 992px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-form.navbar-right:last-child { + margin-right: -15px; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 7.5px; + margin-bottom: 7.5px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 14.5px; + margin-bottom: 14.5px; +} +@media (min-width: 992px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } + .navbar-text.navbar-right:last-child { + margin-right: 0; + } +} +.navbar-default { + background-color: #413f3b; + border-color: #302e2b; +} +.navbar-default .navbar-brand { + color: #92bf78; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #77af55; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #f3f1ee; +} +.navbar-default .navbar-nav > li > a { + color: #c9c0b2; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #f3f1ee; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #f3f1ee; + background-color: #302e2b; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #dddddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #dddddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #302e2b; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #302e2b; + color: #f3f1ee; +} +@media (max-width: 991px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #c9c0b2; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #f3f1ee; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #f3f1ee; + background-color: #302e2b; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #c9c0b2; +} +.navbar-default .navbar-link:hover { + color: #f3f1ee; +} +.navbar-default .btn-link { + color: #c9c0b2; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #f3f1ee; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #cccccc; +} +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #777777; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #777777; +} +.navbar-inverse .navbar-nav > li > a { + color: #777777; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #ffffff; +} +@media (max-width: 991px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #777777; +} +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} +.navbar-inverse .btn-link { + color: #777777; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #ffffff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 21px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; +} +.breadcrumb > .active { + color: #777777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 21px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.5; + text-decoration: none; + color: #5f8e43; + background-color: #ffffff; + border: 1px solid #dddddd; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #3c5a2a; + background-color: #eeeeee; + border-color: #dddddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #5f8e43; + border-color: #5f8e43; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777777; + background-color: #ffffff; + border-color: #dddddd; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 21px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777777; + background-color: #ffffff; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #5f8e43; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #486b33; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #777777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +a.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #5f8e43; + background-color: #ffffff; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #ded8d0; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #c9c0b2; +} +.container .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 21px; + line-height: 1.5; + background-color: #f3f1ee; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #5f8e43; +} +.thumbnail .caption { + padding: 9px; + color: #413f3b; +} +.alert { + padding: 15px; + margin-bottom: 21px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 21px; + margin-bottom: 21px; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 21px; + color: #ffffff; + text-align: center; + background-color: #5f8e43; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar[aria-valuenow="1"], +.progress-bar[aria-valuenow="2"] { + min-width: 30px; +} +.progress-bar[aria-valuenow="0"] { + color: #777777; + min-width: 30px; + background-color: transparent; + background-image: none; + box-shadow: none; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media, +.media .media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media-object { + display: block; +} +.media-heading { + margin: 0 0 5px; +} +.media > .pull-left { + margin-right: 10px; +} +.media > .pull-right { + margin-left: 10px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +a.list-group-item { + color: #555555; +} +a.list-group-item .list-group-item-heading { + color: #333333; +} +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #eeeeee; + color: #777777; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #5f8e43; + border-color: #5f8e43; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #cae0bd; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 21px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive { + border-top: 1px solid #dddddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 21px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body { + border-top: 1px solid #dddddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; +} +.panel-default { + border-color: #dddddd; +} +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #dddddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #dddddd; +} +.panel-primary { + border-color: #5f8e43; +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #5f8e43; + border-color: #5f8e43; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #5f8e43; +} +.panel-primary > .panel-heading .badge { + color: #5f8e43; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #5f8e43; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate3d(0, -25%, 0); + transform: translate3d(0, -25%, 0); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.5px; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.5; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + visibility: visible; + font-size: 12px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + right: 5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +body { + padding-top: 50px; +} +.list-inline > li.first { + padding-left: 0px; +} +h2 { + font-size: 150%; +} +/* +#subtitle { + color: lighten(@brown, 30%); + margin-top: 0px; + padding-top: 0px; + padding-left: 1em; + font-style: italic; + font-weight: normal; +} +*/ +h3 { + font-size: 120%; +} +.main { + padding-right: 1em; +} +.sidebar { + margin-left: -1px; + border-left: 1px solid #ded8d0; + padding-left: 1em; +} +.six-across:nth-child(6n+1) { + margin-left: 0px; +} +.three-across:nth-child(3n+1) { + margin-left: 0px; + clear: both; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; +} +.jumbotron .info { + padding-top: 15px; +} +.jumbotron .signup { + background-color: #cae0bd; + border: 1px solid #92bf78; + border-radius: 6px; + padding: 15px; + text-align: center; + line-height: 200%; +} +p.stats { + font-weight: bold; +} +.homepage-members { + height: 100px; +} +.homepage-members:nth-child(odd) { + margin-left: 0px; +} +#placesmap, +#cropmap { + height: 500px; +} +#membermap { + height: 250px; +} +.member-location { + font-size: small; + font-style: italic; +} +.member-location a { + color: #413f3b; +} +.crop-thumbnail { + position: relative; + padding: 0; +} +.crop-thumbnail img { + width: 100%; +} +.crop-thumbnail .text { + display: none; + color: #000; + position: absolute; + bottom: 0; + background: rgba(0, 0, 0, 0.8); + width: 100%; + margin: 0; +} +.crop-thumbnail p { + padding: 5px; + margin: 0; + color: #fff; +} +.crop-thumbnail:hover .text { + display: block; +} +.member-thumbnail img { + height: 85px; + width: 85px; + max-width: 85px; +} +.thumbnail { + margin-bottom: 1.5em; +} +li.crop-hierarchy { + list-style-type: disc; +} +.navbar-brand { + margin: 0px; + padding: 0px; +} +.navbar-bottom { + margin: 40px 0px 0px 0px !important; +} +footer .navbar .nav { + float: none; + display: inline-block; + *display: inline; + /* ie7 fix */ + *zoom: 1; + /* hasLayout ie7 trigger */ + vertical-align: top; +} +footer .navbar .nav > li { + float: none; + display: inline-block; + *display: inline; + /* ie7 fix */ + *zoom: 1; + /* hasLayout ie7 trigger */ + vertical-align: top; +} +.navbar-bottom.navbar { + text-align: center; + border-radius: 0; +} +.crop-image, +.member-image { + width: 100%; + height: 100%; +} +.ui-autocomplete { + z-index: 1070; +} +.crowdfunding-banner { + text-align: center; + font-weight: bold; + background-color: #aed09a; + margin-top: 0px; + margin-bottom: 5px; + padding: 15px; +} +.crowdfunding-banner a { + color: #413f3b; + text-decoration: underline; +} +@media only screen and (max-width: 767px) { + .sidebar { + margin-left: 0; + border-left: none; + padding-left: 0; + } + #map { + height: 300px; + } + .navbar .nav > li { + display: block; + } +} +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + border: none; +} diff --git a/public/assets/application-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css.gz b/public/assets/application-af32ddb47c1f3b6b6aa6ddc3ad915e8d.css.gz new file mode 100644 index 0000000000000000000000000000000000000000..ecd669f425b3eff3477b2285485a3e1fa17f7854 GIT binary patch literal 46379 zcmZr$Ly#!QwrtzBZQHhO+qP}n#%5(&N@nGSxyJy4*WNC0fQ0}Um-wKlt|A*|i!UTm*I|2VVE#|mb{vTSV= za30KlU+eRB>1C=eXAt^+=1OSioKH?q{tGYDo}Y`6z3Ksccu{78Uup2MCzY$mGTf_Z zCj92`W?#*;;HO2kv1VE~OHDqQsHNI&llOoxA%X|NCB76-=kdoh1&?$z(@xU%kw_Gz zEKSAJuGT7i3(<2*;$MFZmh@{0G!#!}ysx^8hsIg(PcHHnwO|%vhf`-sE1T#G7B791 zMm())2xd4+!NDQm!v~+)C9j0mX0k~Q?OgEXyzlnvICG$U#y|T8-j?8^pN*JXr{&#d zH5(_k*{dlZwX;iU33xdVuia_Plm;#ES-P&XWAvT;`aOR42hZw#MXW!^{yGmIhIjmZ z_+KCJ{up1zxp;X6u%h3-dMB2`T4Dy2zaR&GPZ0?+)y5uidkY%3NQybc;@FCFN#+k6au4zn90pf7svodQz?r)$4X4n#|Nj_knpt~K$aeC!0_ z=v+K3Up8Atv>}W#cB0flVsC!(-%d4uKU&?J$NijoJ{TsE96p}^q$Pg*c>MBTDiya# z^rE=d%m3cns{;G{=pQ)eBLB|E@tv9WneTc)yQL@(ex-aDE^eOFf`q0jIX(;W98q4E z-3$GghXIUxjQvnxx(DbX;zy)YR+eM3F6TjJFTFp4B()S#nojnuC7tLC3O*JEMh!66j= z+KByTeXw)Y8v?v1{iuQ!5cHrq=qCYHdBn-1@VledEhKTF<=ZSr&lTK=X4d)$ca>N1 zm657$dKYIZ)j+?5S1vzymkETHH}mbJj-1o#42n@Q+4#Yzy}JL!M4r}FZ5qgU@ST)p zgIn(EhQo+}KFkOQ8|1&L-Y$ilcQwT6gaKjfg#9$;#GM2;aMG0ewc-=+AHl>K3xlmK z{@a1_F>ufPM0{mtF|i!RmOJ0KNdbIcqW?B`hsou81NG~00;Ppfj6w@7DGtHVgXQWZLblURsdV2q@?Gbz7_SMt^o6) z=(Ju~7NAy4Mmcd8C;1HOi>+`9ixtY7;`_PuS6~AapHLohuwzFlh|sNN7ZFpQW{%8} zU}@uq-Luw{9hPmd6K%K?19W)k{4ZBH89!H^99sX5T$+&MvW?{L!;W3^3!>5pL9A*R z=(%DzVzy{Q@~SH;7QZe=I4D?<#t@zK;_w4gU+G-}>CvZT?Z^re-5?a(Fcb!x4Ja;Y zrNzs@3g0J$RbHxq)@@eXZlxM05u6ovkkGJ=1!wICqANWkPI~|YG7Mc(ytA%~>jK|A zew^iZz{5W1-?#ex&P+}g@AClc108uym2U=$VL@<7&x+aeIG=9p7XzCKvO4PZ3CM* zG>FZr*SH9(8)u4)bE@L}s9X)n$XYX&H{m?^UJbHn*czpnh!B~pMikQVlYE=~n1*$j z;WvtP!XPX7VO!cc{0JC0A^5M=F*u~u9+JZ-U{@WK(s$;3fnU!~4Zn<8?(&gIA!*F~ zDm`PO+u6N5mFui;!0HjQEFLd*)&lSy`2+Lb0)IosfJa2cb>Awf#69KMJ9%ZV-n>K% z9Ge<`A%NpLSP*%mXn0%#?GFW^&-)IddzQ$c=%t>WVDU{R-X2^Z91B-zg`H?mb-apN zo{dtHMLbzCau`}n5(c3-!x#-&2DCVq>>>%+I9B~b4T?plIN~1hh84)DP-0sL#TVj7~68W6&89=$ru_d zsVY`48pP!EIPJEpDu8xcxENGlM?!;U)Q}%TnjIaWs@~R)hY~s3FVK|(6hXA-h}f+1 z@|L-5E2J2*%^PcqtREcUR2kc9n`LPrC;ntQ zocBu7MqgI9AeHgd@rYLIb&}H?Zyj!t($nP zT7L_OR1@utedP;>hZ*Dmo(LhDam{sIt#Im`AW@=z71Tumw?RlhR~UCna1H0#KF6ss zoG{f5>&gXQBiB@frCOMPB)WAQj5{aDi(Y;Qf-VOA%7I=ZgWv6K_wsa{qnCAOmd&g@ z_1I=&_f`mN*Akd<%H@x~We&_J34yj{0*rW0fXRXp`SDR57}!mJQC9j2)09&$XP<65 z1el7gAnItf!7~%H?HVgV0=}`QmmA#WJ!|qy-!TU%hp^pUEycwCl>P2O$rXKMgn3F77uoDzinF&HJt7)30Q9tljHALwmg z*O%YVLwh&gA4)6+!_UI5Lkn!7M|nC{-{;3e3@i!4%~@uO>F+BBEDC2C@CW7alTf+lu?P8+aztiI2g;442Hzyr0e8~^H*9BXls(}m*B1ni4380(FeR$FOLiKxk^Od8) z`>Luhks>JU7X7y2G47{Cnc}g+Z*GXj=&fn5y=;Jz?o7cvjM1>=E-XY-UEjyJp#NO2 zrMUoc^`GTZLP$kzSEdAV)lSkdP26wU?F-ps2zh&2g@(;N+v^pab+f8Fe^TC189y%F z=%yXiUz@z@o~62*`)DR0-ispt2lKett;bb~32VlKWM6GDAF$i02&V7R7`KIhfQVfc z+l!ll{!Y|{Evh$v69OzW7uo?1x?P;bKVI^r9x|7oLC?x%kW7jMLLbJiKfu8SvJz{f zrD`ACM%=oL`*%5JnvR`)*bW4(KyH)SV&V5xQp?XOyp&Q(_+QaAq(7)CNc2z_681XH zQ7A}0jv?+S>+CCXyYp1OU;fm~Q`Tv@q9vA?Uv$0&fVjH37wM6q#xZcBX~$OverhZ( zz9Zd5#saa6+i@7qf{zfE>F-Eh+ch+^?!Z}`XR3ppl1|n7DTb?Noj)V~rM=erYPYvw zIh{Mc6q2kCW!g-O`dWi3?ug>L-H13z^AY5pi7g~-yt%qWjg1_~U+5o86~?YSLv@>2 znOaFl(qUT(^em8w6dXwIWzW5D4sA29s5H$T@4dZlCC&HZ%7|I#sak4o&9q;>H=E=iO^AM5$DSps=CD*Z<1+jqJRYu5R7^g$k8sSJ;E8CC2oVVOuc&IZynKS0u;zLbmWIdy`%P!r_>`5niupT6!+VnFa4ku=bC&aoi!`1AegI7#4g z&syjI`d#P$N$>x59U%-IXcF}rPY)J6+qZy<^YD4*+v}^{Ol;jsBptszCxQ5tTE1g4 zNVl2g=lQ*?AtTq)g2c?OnTCltzRUZ-AnPc10CM510UVN?DTjW(%kzybD<(avFxpo3U5o2$NipGywh#=0 z9y1!Aq+(AMg>34|8=){@6~n+8|BNBs><+g3lpRRPRTSw(lKZ+x5M5{Z1kU8^UjIHu z(CDy^A{TwIT)(20z8#1cN;}~r#HNF)kEMhvpHz+7%iBDLL|F_>q_o%%+Am%W$&woT z^BIWEluOX0aAzj~=E1hFFr+_NBP_Q6@M?}XdmN-Z#)ixuxpH|Rv$V|-Wg+TpwCBOx zGSP#f215^PnXM`W+bV4s5gfB_6HM!U=DI*qeg$t^%3L=@T{8(&7iac-5{x;AG4iPI zwOQbV2}Gsv;E}~=VTsE`&PIZ~_le)--kf7?b@@KE zz=NA4c!^q)Rp3SPkE*;-ACx-X^u#v07LB{o_|s|c_>JEq{_Yag&$yk7>a*jQa6>h9 z7LC`|@<`lSgDuGccdsX+VU-j!giDXa@YZbRsfgkTH))|Lcr%5d$jraf+ombFn zWij~bp`T4m-F_#z63(t~&r7NuAKJAz zGs#o61HUT8q?N0%;;66=#iYP;pJ&=})BA61;o0fcFK?%tPJ86*jkUu^Jv!FNR@qa3 z1pWbU?0N7;7we%l2DbigR<*)s^J!<|ktDDJ|51j-ilv%-iJl?zPJP5)X2*y|-MzH_ zr}h)8jQcxZ{%l*IK{kERr;N5xNKS1?^cgK&1^@i!(UbkHfIWAy{{;MH$j>$IndreQ z#1n@o;u&O>I;dCT|9AR|4C>XbMm~SYBLeD$qw?LgHsANlUdI`=ZP$7_T!(yTU2;W% zKHh)WlkaGcw*2US&Yjp~|09)TN;X^Y z9NCv-(zA2D2LJeOx61t!HGGTc?-)h&gQQXy)kmaRofqPVdP5%7=TRf~HR2f&)yGls zbIYPj{#!S!@7rmwBLniXm$#Sr^>iGmcF_f{yY#72j%lWDjztMG?wE(iU3%%{ikxih1PPzIRvNQ z#nqn^-|LCOj@L%G@QCgP=Xv`w*4t<|_xW2Q`4eb@u(EiK zDy?fKl`}FV8Dt!Glw-ezPmeKCqa(-zWbpMZ%3syv2aI}lTX5(fT{DrC^wl`gv{X+M zZIfp?8GL8uKODLA*A%?@k`==jSTT_CET@i)DW&FEd7LBlPpZl3C$3#L>n?K1i$>z) zU{~%>A9!H~<9oz>ZP}62Sj;|g=7DcgiguGMVVGi}$|CWgSp>aG0hpCJ@x9RdLV`T- zV418-CO7r7N2rp#z(FjUW>>eMdyyg4mgmz;qpcA@dsot7JwxZ2k z-$QaRAovhXcKgCc4$^ynKq3(7@A8@fyypjd%|8W~xMp&Nb4f>m>q^1J_#cwUWs_*i zb7dTaD=66z2((cV0_&c>pp-g{6y7GMQ4G5nDy7fECfK$-N7M~kJ(FIEHOJgL24=|@P@nxVI0pOv zBX_%?_O!pDHGLC-7)%Z(i@(0Mvb>oCB3nMd|8rQd29H-YwU>|-@txs^VOePh=cVM)+ zk`D-1{xDMa)K3vp+j&x{rJ3@{lV%)smQ_`U_qUgK$8QJ4l#2{Z>bEqr9BcT+cfRC= zhr9llZ=!FLUY&VzET!%yw@dDz`F(uY@0AZO?MH=B{5f`U$8uV4*`k94tc_XVIgF)& zGqTKMj96(jyF$EEe;QfFLyj4;n*E>FUhcH!3uimZ*poiy<+9%TD2O7F^^+2GG?$Q4 zN{~JT<#PI;@9^F2-iD7>L@{t3dgGLJh^ZH~R9p&7p&XUQ4=Bw*ag;Z?Gv)VbmoA#&Cw~WfakXAQVKQ5J^gbAZd8Qz4QRiY$nMF zJV9Mr>F{=PyR0t(F?g$h*lk*i`v^4n`Eeis!=2)26BRE*=Qs0eg25Y5gj{46BlIaK zwxU9C7vvgnmTLmV`FO*Q2t#@TJWTy?5H>(@bT+9hkS_TrKt}GUC2Vt_;!SNE>?+JF zx=kbYjT3%!PgydHBl>rqoGmXG1D{LLNyUWw8gfc$@6k37rFg&h4Kn!@^Z)}!E?l#Z zO9+VOdn55Q0gO15F-_FS2PcZCrec21#l}*JvDk$3w;S3y4>FwY786WH;v|ZVo9~xc zO_JkMR9>+1;Izk-<^;zaIrSUZk)TI)02t(fhKnHRib(Cw_CR)JYBjCB^I`DoPafY* zfy6jM4P!^%DJDTV>A$y2avLq>o2MEzecGRno%T*s!&OcjHBqWIvaCjp1n7S$sQf7` z??!BT{100bYlLLcqYJk^DSPE~(TTvDNhV<^dJh-RpCYA>4C%+4-p3sK}<5wwnR)?9KajC*asyX+BPqZp;8|xSI1^h)RYOPlo7!5aY0Bs3tV;IhJ(--9P~VWp}J#yYRVdapjAT zW7dS);dq6`e*r^EojY0Lq@U=SD!dC`q;TI-adl#$DOc+pCV4ALcVM?4{kDBkY#Tgo z^p(r?GHEZ*d&N0{T3DL|{nqDAxn!po#)9WeIZFv4jFk1%$M&(`iP@w3Kbj1iO!#R5 z$x+$9bE7}JN1LT12_xZno`AtUauvq=frE~006*uOba%F39cYsLr4H*vu%3_LZ!*x- zD&iDh?FMqKRNO#k2aC+O&lHZb{Z%;Wc`W5)5@cxK*-o@&iqtP;iNv@}iROzgCBVh( zd>><0-~8y7cS%{c0(~NpwO(m*cFL_`&Z#_8lwzwN-ocMz!*76ySoD`Ki?j#YYU5d2g7FToO3A~=Jn068Q5}7q<3?w&5zUPs+y;9I=8VbVD)6UsG zF0r%tt4?I20f!?)I6qPF z;7-Ue4}&faqZ`S$iVl1cZ6QakY_4tcSe)J9>b;-D1jYCMGJNs`yNOuhAF>Ij7Cbn= z44IkT@??9l6L8$Umy=k}z4Ip3E#Z{4GXkSZ$VNT0#HH1aFhd6RgNTN7L-;8GIdSZ5 z5fQv6Oo|t;5>%gr+XK~!h-aqav|}eo*V~81`C!%;vmUM>j)-8@+l{fCfw?R|U%#YU zKDZWShzDmuePlPcpxoU@&gBUX!uW$Oi1)dX<1fGux+0&E($oDy~<5PJB zXeN$Q*jyWk;AG2yfh3P09syfM;t({IfaK78K{?u>K1kD8j+XQ3gZLle-Tj|y15PdY z7ZLmvFnsWL=jAl-Gi!u0-ioy01Xz}71{m2RzePi2MjDc|Lk?|58Pcrdf`tq=+uR_Am2F%0@=&O z4gv2_pwoZ$^hmEmQTdPewU%JFW``y`m|x`Hry6`~pZUR`MY!n8mvCt>8XtcOI<+b7 zdop4g&e6N1#S+9UU(g4$J0q53Jt2kC9;W#e@!?cgD1`2 zjP$o|7n!vS3;Fe}lqBrq7B5Slg2+D8vF1GA4kU=m_oJ0R?B0s@?Jtt>>BN;5fFBf$ zy(Xfp-i*@oc1lZ_u#i?fh5d@^;?#eleP2R3KY+Nj_flQfKbGU2K!3`$&myIL^bkbVvvdXq&FIBp9t81qqRkm3D$!zyDV zl9~@)>aK<|j1UuS{1@p?9;Tc{rAvlx8t};<=9-eTW>%HXIYsn_=~6A& zfjy~rwjZBovoP4%QO!}q1McYzp7J3PH*|D}xgB`D)${fDs%Kj{^F&owcv4fYs5Yc` z?U*+#$K_?cc)Ie6x!DTx3F_@e95e4QpYK4sjJSOibF~-B-{tVH;qkSMwk!Rx_4F7# z34Lo`2JYyb1cxo4xR1u`e5W=%O)uP*dr5`u8?t-%OMX-m}4`d%! zek5!TH4^GZk4?EMr6he_!ULCt^nQ*)y?~%%(U}`S65OR|bhj9h4dvsL0&?>#k8nCc zTPrU%?WVK3ppV7uliXAAW7BTo-fw6dSj1&a?*7=7U@MKTca*?Oi~#+*aN0e7oRAOp zB9I^Y{>?cLOSaRd0J@JQ12Pt46W{156f3IR9w-*G68sv`l;V^_vtL zweWykwU%rPiZ{GyF-!HVl9`j0Bc1hMywOn(FH@DvDU?Vybb8*k49SO^b#*)#e3ue& z9L@FlR4a5{VRM{J*xwCpdMTm_5P$e}k@$5M*EOQfBYL?ply1g{ckTU^^v3ZafPJ)c zVD@kwk|XUd5@-v~-pq!R7sVsg0W&3PlKOpRXZM$soNuj;cJ_8BK7)CFptobVz@=q# zgZ1EfTa{jRQzrEokfMp*O{Pe|Sl2!(==pkH2wip&r^wbD%ZD4|R-)Vjlhn&O@9EoqhDiAEs)Tyy6hqgM z1fmH!(N)MgLNV}CzJRN}!yzTd{1~v;j00UWjngHP7-?ah&fT~r{a1xA2j1nm3G>TY z>qe5l&t6Yyx@;#?{CVRQG!yM_T^orCX>!oh*GKOVE-uMU#q2G;saCu*(mWq>Zr^Xw z`0GfxwiobQMr)nki3tXIgCkqjY>9Pp;nnf=9i?k`-HW$q?$3)zkZtvX^`-O=j7(C; zAUf3E9Bu%G`ZHpGI?uBKxSgrWf;s1QCCBa`_C>QN&H^cQiH>BNZR{xD^u zDbUQ|#Pjs1%BquKV0Zm;_$!OZ^*2SSRmG^2>uol2rpXZ#AvkFNtTJ}A!H#YgjJp-E zS$fw{K=SihFn%=hoHrMymVI|q*9nF?@oUH{-@4cx8ib)bjMTb2|kvP@&}GgZ^l;*7TM$QRfH92#3=_Zb zVh%5|IQ(!olr5Ck^5$Vg9Msz?Z=8)~hg`Py(Xu!%_+>=&GZ&z>Z1AlGJMFiMu8*2U z7;yJyX=Ut%uI1w9;b&G|0}GC*;)AL6_&tjbj>Jq9xIVYBxF^GA>Wf_YZtOPxdTk?& zK^jNI7uTDH_{?I5wC!o~-OOSauCK$rxW!k~DC{>IIF9Qp9|C0nABs#)Du4CVbmN=r z$|lkvkr~i2EkccS=D0(P-#S)Z;t@ogkz~z8bmN;&$M}R(WB@Gm+pPtTNKwbwIdcRK z-Ig&$oSLR*1e_hkH#*)E*C=9+NwerdinmEyp~$Y_j$(t}mO$cmyPVqc2nO^aEfNB> z{F7pdxY~6-(A^c0#4-k?-HqV|GX|||`xTtgBJJQ2y!cWy=yCV`J?T~RCGIFd$v+5x z1hTjKV`cuFpK%yw{PyP`qhpKE~5&}3SU?^6-&2z1`Kg)J&mSLwP0_Yny0xw_-Y;c8FV@*v8s~&uOB20orQ8+k= z@1CYi^EkX^QU^le@2fel_N@5*pchmGSx74|3$lp+a?W&y4b=gDda0`ewsmY6SoqmD z$Q6`=vN`uVlIgJx7pD1{e z^a_C>LQJe$3!o6<5M*(OCa}dxmbmKnyl(EA0TI8~*fWPV@E~5BffaiQpU&X8JnT%2 zn(bdi=HhJVOZmw4XcB2$aX`eKctyf@F&#@Tbc=B~qBq?@>nI|-(?;V}4h?K`sszTz zB@g5J;5)TK#1+#JptuzRjyaad_%O^=VIV9+VRXplS?TEKq`gxPrJs=9aB1Y`HA3lf zWVcrvbX|B%-vgK*(1qeIeJbAwW*8X*@63_iL}iFPJU2&n(W#wYe{PN8A_SIHtiD6;re?NJ+1YM%+d90V){|UohGeu?+irG_zjpmSjNbxf$I`#!KoWIY-D+&+ zw4t68F*&I1&RufWYf8SRm_^wdd$?th-BN9DZ-pm8Gt^H zI;EH*8UgHW=5s_}*D>+GuHBHgX&@U*?E?UE%o2wX2Vh%x1H|fUb5`Hv;)(ZnRo|Mt z*lD`t(3A_{MetEKYs?Ws^Buk>zrRNr3DB*QTT&PatH&`q~?ibt&lU`;0Y2t2_U=B?{uA+P_c(VszJ`OSL= z(Wp{h-q(NznW|QFZ;6Yk&|FyL3@taMHi-ZHd&PT$s8QF|Y^rxSRNSR9Hm6?%VQmrR zQHCDGBjtpCK0bbpudz+a1$O(~a08^P-SgUF3WuX>c`w+nn`X`Q%Qrf#o5~HMxb@?| z-bmbwH@lVUm4}cZ646`5#-OE^s=Z~#1{u?WA?uI>8PoK%FJqXK3O^S6Ui}CxpK`J3 zm1`3qxYt_%4!d5Jj_(eLCk&0(p3zQii?iT=Wz?wIl}Bi9FOJH0TfZJ)q1j8_C>@H| zG*u3%{-(Yn9JGdta*7tN8Izg-1p+Sokj$0x14+$t>y&kC;?~Bp^mrz4Rc^ut!r$m? zt+U}XdOCm7?`)BLFVwfsoJxP~yv)anU>F zot_jt;+H#TzI_-a$A#qvugv3{wbQ_@3ie~uCQ(iqQK#GD!Q#+Go%2*;?ar_K*_*(b z@fTCeE4|w6(x=%7HVZG$@?2ilZmJR_q_#b`T6rjc*%Vr`yqN-gcTpO8 zG`;z=wOF1DF*b6_Y!_}+G#h_tBnZf(PQ8?0D-n2#yQifI&4yJx0bnce#2* zPMwY*lK!1`_kmh<;*qOSH~B^>P|lgX(GF%^=f*@*^J-|emrCv=_?&g|hOs*Rbb77c z8RY!zEU)Mp7QOFFL>VW6a>L3~^Gd0~1jg;q(@VIQ#3rqhoKQ<3nC}RjNBGL$kcI65 z>Bc1U%8ntEx1b#quIcgL)1zPLhhNhDXtWs1i43$@%k>PjIQS`ZY{6-5Z-FfNy*P%h zz*#nM%EN8>rkirl*QKIQOGZ681JnE;0L40Z;W6?kajOvTAs-FfUgFhS?)M%qv z@W!!`4WlC(#>Ri{8CNhcwb_r2>5L@QTa5fm4#t!|jV*zU9rbC7;^mSWJPK9PDGRb0 zOUPu8!Z-xZ;|wLK1J?l;od$4cbu{SMw`QBu<*-eSeQI)m*^06uEbOKNtgPDA{1jWVqSmO66<^dsjZ1y+kPpjRl<)}*HlBa9Hsa%Lbx$<}U% zWtmq^I`gg?1k2k%^j7okp?&0-6kHQuQ(sJ;tR%IDA6YB1WFsTI@J(x>F1iPDP<3d# zie_?our9cGb8BEdtuUyC!=k9&NEmW4i5EO3>lEWPOD6Ddy#bHZt_6mp1JPjot?Pgf z%td|cCYt6BQp$nJd#MHTG&2VTG1F0hUCx7VUIHqyI+a2l3NbGgLTXj4HNDJEz5T-& zRT_ji^^TS;S1p|)oON9~EUq{~A|GH0XsxB$v9;*inlg!2b=m{v8C0|V}5aJ@Q;3TQFS~NBWaZ$@fn4{XeNoN9@rAN3%nHhSF z>nlD0AjP+9*SZC_Uh3MrQ7u2;*u;Q%b^&+dJfd93peNHp*&c9tUI_#wII0E zupCz!>#_l2A&M>S2|Id^o0z5RZLL`IYuKPdJqOB$q$(CYL1C}fFaqTb%Y2bP6}}6D zV(t@Da(*ZJnyOij8E0r!wt59YjDA}$$N6OwCVX$oNj~Y_M{<2b*vp&^7o!ENeEO40 z(cHA=j14{!CqqY7il?eJu3Av?I|YU{Q$%#AxrWdXMZpsa*nDx-`hK3blb7Uko` zhqh$_1KQ`LMgblhXQV|#Yi{DScKv^DOD*>U)(D{3ZKNaCG--p`Z&em&od9E{9N!=O z#^p^*^|lXh?@DJJ93C$(l+Z)w{3mvIF(#fkESIR|JZFE{3-YglCYD_o=NeMaXZ$+z zjicw{n+erbI?VkOsLZe66^^g|xOIx4RUe2f#gN(zq<$G+Ys8jEYfqF6Ss2Ab8kuf* z){9E}pK)p10yv4|wUCvpG7q(Z?IeReqDYrO0rS55)*~y6!3lKhuF^M>OvNoo3(cCj+DDA;hxM-%H!3n2>xYMZ+9+o1? z>Q3!pcBX0SyPjcbfuI+Md|AM8AakVTMrg3r3z;x2fW}mZqD6rk{d1tqj>#D_$s{92 zO^T2e6^ea5DI4Xf+8k#d&NiLnBRkru62x%P81omx%~&wu*5YRxKJPPJ`O{vv<3Zf2 z49cPYU&;*3q1^tHT7y$4xBsNj03FKhKdCfGhjRN*N)6PZ-2RgqgH{9VELA10hMEcm19AbE6Zb1Z&ud8_V|`rX5yMDV@Y11 z5mIh1lb6-aVq-D9Z2WsXY|?KG?)y{8I4T`mqh8}ulx|0MNc!8vREUIY#fv>Rj1O#8 z3>>K&S}W?c?gXjcv>1qH-JVtoXwqs{m_Cy@I_+A3xtNv-$HKa41chQ5O{iW%NfUtj zk!WUm9v&>?f*>P_!?GaAD9bn>3ujpw4fw|uK*k)#sZ^NGr$!emK|mXwtAA_tZwDOb zV~b0fuv}nT7S&zL-}#Wb!Z5r}U^rY6=Y%M9z0n2k&c|HK^jVzI zjZf02r$;h^k^)sO(qRfT`wRejoH{_t(Zs&0L))~TszA%Nt|~**w2mr3!?d=_#a+FI zM~fIebiWkM?X6@vho3eBGBuR3g}2dcj0UrG`$M+ZlIg&WY=tt!?1O4$6qYt*=Sx8^ zT0IPfrg>rWwBt8DHn^Du%k8{vO+7ZO&xeC2*XP{m_y|r$h3I7VDSMlfp_z5*TQ3CrN>kcimHm~fC|vURCr1tI0O5jB@Imj z}$jk_)8IS54fPfLp5P;;gzeH&AN}3s$ScwR*`!Lx$uEOPBCVt z9OG`0Fz05-ABVVBcBY(Sr6`!w3Y+hJ990n$4)JAl%vr_K&mm4L!o+{xw_w!_+E^sc?`N0`KDhUZT%hLVOQ$!Zzr0lp_=ma)R#A=O}yplZ2w9 z&Qjj_?dJ^sGeg;3;UE|I3Vq6Q{Q`N4qD7FiqzCwduj-ou|1*eg$<3rD0BSNSK*tS< zwHu{wI?>1aXngjDZV+0IQ*ZR!<3~{xG3s^IV=u`2;@?Ef2%XYNeZ1lfIF=4t$MMS54c_ zf{hm8C=lx_^k;>8<24V~d6iVX3?95hY7;u55bynMFRp9%d!B*CC9(GtQig~u1@@F( z^V;$e$DiP)9JDoCz?}>lVph$FuErg&V7qZ5B@D&}FvubWFu>BSh!U=d3a*1v41-_5 z5KspN15kB@_!o$V&K1WO4{4l_-TmPj2EcTkz?xo>h0$#M`b&L!%BUUqJgray8l(Sk z1*_^9;m`42jVPKI4O+0mONd}V3r^5~7<}ghGP5?hf!MI6X@Q6wyQ+8_ip&i^nPX4wg1#p!N^2%2{#Qjh|Bkf2`+Zs0%c ziwFW5vnoM=UbCWYfW)+ENee5cIAWH3p4*+a=;rN>8+XzLn0EZb_CPAQLMpgkDv``F z3q$}@SqK1?5yJmRjt7-NotIQqL5CO+w!{6X)dgu79bUDar(S@ae0E;~i-i38UTW(< z-}-Aiw{7*RrG8*;iMli!&<>Y{$fOqSuP-SRI&bm+`T@;E?YMX*ngGFl#0nwUya*6> zee}s%$L-J5|7oP8E`rIWU2I-9bw5K(${qEquCow~^b3mU*Aj!+(VK)E*u3QGd7JQh zNPa#NFDrjAZ5FD`tTt1-IMq-Q2mWw6W5|oBOrws>=i@(&W(G?w1+E8Vo$>r^#U1x44ZDP(`e{cP;l8M#F+OJm+;`9N6jfua)e5)rh zg#~-c4eg$`fFow_ic5^xb}-x6XKF=PK6!nogzgKt1FIZL$JF!-!XE@cMgXLIE&R%a z{zz}gw|iX77h&p_?*u^Nn6in#(oDeL40rySkxedtz9C4<;@_{P_R3}PRTNF{d5*u* zWo$V$p|WhNQKoR@1dX6NoctqFpB{RhA2s959up=IJ{SC9my;W zN71h+bijJ4hNDydvJE06!K;vfJa6jp5$a9;_&)D#ms7K|tBWYNLA!#_R-6AybBV66 zsb;Eub>pl>TLDIvUNp%=`L+t%lSD|Vtl=no)k<62ksSFGXMXHdY;yK{ZDKcJ6 zoOWqPD@``x!jbU@ZD_!St(Z$=)T#zuw5!s6S~+>AX$t1_kA=-<5!g^tQ4nJi+4U6Xtx4 zinxjr@m(!Vdh>K^K#`R6rIRs-GEH{xMylbr`L64 zIxwFe=%JwM%GZUae9kp8a5LF&2KVYI#AYR%@gNrUC=|8l0T7zp6-~v*vdleu@F zt&5}4KexKbdp&3sYSg=1=0qx7kc(}_skhwODGplyAD%DsY7n#K|amvge- zj^_=eryQaL5-oYP+0>QRzeISdYVCn!nAtTlX)}F zM8JDfdVs}nhW#q^C_tKp1vKJggz7yf5OZW#xNjq((7e##{T@_Y#jdFsz&AG zyT|PD8NT$gd;gP7N8;O{V@p2u%z6bZa`obneI%FQa&!S=HB}7v3&^YDRyIStLI~g3 zj<%gDfVPc#fmXvH6U`PV8|~&m5Uplkk;y?Ao#x?B91ZsVRHJx*x|=sreR@ZVv!seG}umU%;-uU1$=;Dbh!1M^#Le8@wpF2O;Eo;+dW?<2DAR^`lICv;;! zE5Xb4_N4#g>m6Wx3BGONv2ELDY@28B8{77rv2EM7J#)skZQC}_oBzEp-%D<8zNC9s ztxmcstGd&vuG)L;UzAjK?PPw=P*Jq43BjuS8Z-SV6pJo65oWsi-Ge>D=6#v)_5k1^HSEHI^N?_@c*zQq(#PGg|iG3uR=)4;kALh4kO|r9am@eYYLw&s(jz!Af2#q??1gp za=6NG5DM=k`W|#tN;j)<;V)`jDooShB|nFEVK1a446m9<@5j(`177Vp7v6nf-c)u- z16;_AM}*}dpfU-MZo=N!D@?ZX{fs+}*;^TYzwe$9(ftG&CsTc!S`gIQ@5lx1C>3cV zS6?njuaQJN|g_HZyRBcv%OYDKKIuR?%&!hH^$SDD$9Ji5ZC8WBMaEdDlQ7UIoQxi zI6`uqxZ;+EuLzNf z)1_^&;WWnM8gbQ?m;KYy3`Y-fLt;2R@z_n|p26OO!rW41O3?}=_OrM&0Ta;3> z+QjNg*${JjAvh6)WY5TN>=Hra>`4kjO^TldIxVusGsx81Kj*MVY*V^D)duu4MscY8{z=0V}xOUm>b`LqYs;EtjCuNyR6|3#*j-fm^T=v*%8 zVQ2}mox`RMDxoQt(O|8XNm`k6iOp}FNfW&y_ek_R4W5REbf+R=*OHvaFS54)4(&AR zZ9Yy0pG$0ae(O`YPwR>svW`E~>ftF7@HoVR3^&<9XJ!)Rh&h#5zlO-PFBLAk5V;`I zVJEL_w+kO0^HuZ}#$`8k=BRNcx39mXP7b6*csfc-2S}E6ip7fLYr6;`DOPb4q09@? z`kgR7OXc`Qm9ajb&1yy5R}8c&q@OdJqs|^kJmUcy_H>Lyu?jMbWa#YEL9U!)ZV7qWFGF$*cb zHK$h<@2KasTe`UU9CqliZXoY${uft<1DBqBN+r+(=GE3i%r97AFa~heVWSy~Wwy^) zQNTG{Kz7kbMv0n(yf$0dFnD6>H`j| zogoNKXRiN>54Gxp`K|U($8n$drDL;3E4%jK}s)*G{?DDZ*Z5mO4^v_+vSi+)zM~ z%1~6HF2ue1y;<6`P{9}UjK2p08s5(H$h!?_GsuSk1*!^-@h6z9ODBpcMz}QtNA~2a zUW*bw8}1@dQ=L97><>s|FNMfGL=NdeW8;kT1w85NL3~#qTAO{hOeVJJ+Kr?Iq48lI zMlEfZ>Pp?(3^=>u+2Zr3^rLWd(qv+dPtSFixDDP08G8||Cwp?gt0aI#0B8Kq71Ko5 zBH+THU}Wt}dJ-^5(L8Q2{47Q!oWk7o%0VKCo(>$s4{*K9m!l4ChC>X?W~ALq6Ipi3 z2yZrte18VRo-gWRa-GA(DsC%AcwTj-Zm9?E(P>=7%?0PanLffZz9xz-BE93ydQFjb z+g~Y=fr*Wp|DNYR|6SXj-^v@CvB>_*rHQ*6ekIIt{J>vP;r7KWU&%l49%gO(&a^cI z=E!tBLTjUBAnY*H(Do+f5^A@{3)EFtFkkM%vO0Gd-G~jdlPF``>}35L)c+`aTK6+0 zPa$}Fp?PtWp@%eu81#5kCd14|<88<84-NVW(ql#_5>Olt8PL$uHukyMOj{TSA~+}x zHaM=irA&rImKGvWuN_&_KGqaHc0w*DaI!Hg28q(If2BSZLq-F5M8*U3X#Im`zsn*x z5WpiFcemlA$Mzx|FMy+(^$ACS7y6G*#7?dH=9t0hu$UzXj9ww3F2h|yT||2?RCjR4 zey=?zSpb5ZqJU1N0jfwdA)r}FbnMZRi#dFsFmPG?Lmxq+H<EVSVZihgHm3W+OJ%k8eAeKeNwFB_0ZvKd;%5H6Z7iY(C21K5qw0;It??7O#@NBki z{2@vF+0THST3zhth^;?F3jWPpCobWIL;4>FCTNjJ%anCth&En>nmF7xz9C1>xo*z) z@60%dNAWhgM^Y#|&`>jFQFv0KjNPhXx4L9eD>f9QLk=t$)Wa>#xhn@=VDnvlS00K2 zy~VD-cZ6oP$wq_L`HZQ}>jJIs0Q;xv_p|bsM%>FtEwh^YS$|phb)B&)VIi7mqF8iS z@0gHQ4QQWv*Od_B3{E zH!ey}pe1A4xGNt4wH6mx*;^YUX;a@tFC6d+8L?*|0ZQtC1bz+*6+}DXrO20g0by6( zGr}i^Wse7SYSp4lRJh&s?tfpyYd!(Pr{`Oaj10%s3&Wl9|8q zGnS&d`CnaLgfVyo7$(sU$N_xOaUJN1m$2s}z>@AGz|~MhxVw+pxTU!;O~T*oF-0RL zjc9QmR}v~b6-I$wrl4tAtf4|~@uyyL+e%q8Q~ZLwl7Wp|5(M~yuGb)WD?s;54%@tr z%pBrp_ONSR!%|keNPi;Fr=d!*uNVaq8$Y9Bn8&4_|HRFl;6XRXbM^qF=JaOHpgY_x zg{)A`-L6Lh1@i)hD1CDr-24g0UnUu!Ca+*$EvC!+AaQ&owwV}{^|O23qq@uUwjAwC z2xBXbNDs#AvLvGUH{rL@Wr?5nt{fwde_h_oAM`JWxRQYM93|X7gf4)4Kec}Vm~*h+ zQh3-ib!1n~7QX(rUn1D~g*dAflg|gPP=Xe)ih_0G?r*yLPjhCZ3UVLQuAACneO7Sh zRJO|kNKkvaO^(pkYfWHO7dO?-7lpyrP?%YYOEiLF25XPvmU)araL{}mS)fd}@BGn$ zs(6J$xny`=?6LK@bO=xX>YRi-J4@0LOs+sT7d$4x>#DGIX;G$_{Jt+=D?Zs|t>?rZ zhLSk>lR>tw1-kgJWQf`flMs%9X%R-^<6hBN7pYo4kyx%Tf#}u?{Bv2X&i7rj2(!>e z*c_`N)*2J*qZhG^s&J8eNaB>c)0>3r%vEcO1kvV_Bpd7ub(Bx+g(Tm*!}r*9GEYm; zus%5I?;CAm>9k$PBpiR7I<~p2Ft;LLP92b(M~KW)NQ`VB$_80>Qo%SmtA(XiST zXyjt|3xb4h{`umG$QeE)$|3XXePc_l>Z#j4BX)1FnFT?^C@blZ{r)=0rxQK!S+smX&wvO*vZIQDU_gl;$1_B|1eKj$x_-4cAHplr<6i358LQ(;X~(ph%JT!RW+ z;n`&InSGE37z4QJaM!k3S4SSai~2!Dwb%neH{?|i$sDsULS2oA#=FPJEQf7N0{tl5 zb5`Sc)#ZF9DPBa+4m5sN`d}`Zz8vXwBI67|iyhGKYwnQ2HJKLA@8@>R5#2n0|2(CjGXfqdlTt)6N!Q;EuCVrK zW(fI;J2weetQc&I=7&*~f8;OM|32VkRbNoea$bXuaPZ28F>)vbCkrqUa5g~uCswU@ zrB~X_wi)k`mvA6Z?ziTba7LQS<9v;_SBcU4&1ZbwDLA;+S%=Z5on8e8txtmXBKyT3 zBe@!@H$cB7w-Uiu@SCEKx`-d&&Sh3~kS*p0b&DQ8e}yG?{L%u#<7vz3PXzPFR}W7N zF_m5U-S3nDD7|B~AfiWis8Cq;=K(!wj=9CE-gXI#hV3;I;zj3Tkjw*mO*U4dRYMVpS74SUD@H{3Lp?@B7P8PIIr5tfvqCgqCGwmD4#%L+AT;m+r zy8o!9<`0KC^WsLoX!Vy3hUYtnt)+ z86YdnGd5a3w|7RAWck&;WPX|(2~eR|;#vHK2XEQR*xwJ{)BJoBCeaQzl60#<8Uh30 zLAxnb3v$i3IvMMO>zV}v{d}MQ2uSz1YVO0i?4wgp)obuH$gFffS`a9S28E2foYs%=O!>hfUsh!-3 zz{)PVuWD5nfJ5O^oY7w%57P!zPu}qy=V=Xjr(y%|628q+25kvh3*>A-9xn5EE{cZZ z~ffTLHJ%Mx^Q-hd1mE^hz_) z@Rh$BaQ|jqwn1sZKBMCn2i-WC+iKIIA^Y6kR!qsYC`75x9=Wy&9vZF0aL-)7F_}=V zZZ6sQu_;h?b|bpc)^{c?@r$*d{&Yqgu;;;<8!6nW=`?OIwV^do$vZh_jN&5x+lgsf z5)XE%ZZTgAy`xesL9tK##Qv>z=Ey!AvXlw6M^q5ZLs>~oH!=A|GSkw9$P}h6Eg7A2 zB2j2Y{X1@NSC3u-MQ+&zG+*a|EjY+Hdl{!#UZCGjFPyH$RPE#~{6tUC z7BpQ&%k1#P>he8<)}1vGGViceVYKBun-_gTl+=u7;gx8~qRfPAVS2g+62$9wB=h6n zJKj1P_`_r`%K))M1JA#7BzhUt6GF^6?15RYvdp3}6|g<6s$%}Z25`vrQMn>tk?G*d z7c=+I!R`dwrg2i}&_~aUl*n^dxsSp2yoeS1R-Mu_Tik6v8+aa%+4?2q*r8QR$wNx> z82J|$oh1W!-ATZ&_%Xfz6gB|8ej9y0JbCFf8#js8@YM%&4^y^p!|Lj~ zbY|Fs>n9@*XD$$Vs~%S|={A^-$gTEJdPvze_trfiZadfaPupoy(-f7)T`gz(QKb`J z2|QkT+B297N8*79L)$#_?)k~b-Whgp*pt`VuI-bL)9dlW?mM;jV=lmX`j-r;k>SKn zzN6i_32`9nB6*!=A*%~hUi`W3N%qGNZz)k<^bo@z9{i-JQ0!?F{`)rHb+rpd+i=s) z&U&bhxOboI&i2#p600jT$&r?M=Ps-oiS3lDs{E^>9Wbvgl^(ReSm#sEsB5lh!P5e7 zI?D07>G^|oBc61@Mi`r1Tqvh@F&AH}x9C}sTiiryc{H|JTY-+Y#O}jQigZj@Ho^qj zE=K$U$S9ye8V>8>kqCj2wheVYH%l7*^W*Z%a}iES)3U{xWmN?IZpt-~=ejc(8a{o( zwjT9169{|o&h0}#4C1}cNRg;?*A6ccTmH1;lWhOnX*%lh5pfeR`&Opdxu{ZtSmwW2 z3beDRI13L8eLa3$rWO~SaLY@z`kVd{3W4T5~`^m<-v0rN;3ailFsAgXW* zZ$m-8OnWni{dXJkz`w+yz6?iuuKf>(yg-^o_`9YFms=F&DF&!Q=|DN3ra-tOabAQ34fCQ$;eHN@6Ai{We4vrp_QMi8 z?{K@DRC?0sbBBUA*hnP?=67cqgpuEh+y{78f*!TRCOm~``=4+`8`vS75$_slrmQ&N z3?pJWLhXcd`OsV(l-^H64?as)iAj#!xAe!NZD6`uxb`dyE_;bh(_A?9%N*kJ@fF`vA1OcfeXzoWgV${{&(57g9X{c8k>xB*lI zNd&3$djZR=#R1X@$spX%Y=1ar%s#MnGbQ>o>vKyhl`GT!Dpw-Zt~#GZ8a~G(-^`(w z-SHdpzfxYPBlU~X0BhU7<7Qr$es**Ho-edUB^ljhqgiR?P^rQHsIOdDj=eNu-#*}u zL*i}X-32Ujlm<#GCv_w|vL_J;^fygWdnDNa1#xzWFX3F2R5Y_F^0#rDQN&}K&#eMw z@N1p8n(ce6Q$r#G*RDU(@`mF7(qd{hIOYcX zsG2x?A6V5Ac)=#$x8`+uNmFr`MCLmSTMkj%KMa&jXF57t4jz$0hOI1gAyNyGSjYCA zRX;4*=+wBze_6G9!w-}HyUHtmZ|GSX4rTZ3e&&@3W@pCd=eL5*(cVKR;qtP@$IH=z z44tVC46LQ}uE;6qygE6f%6YG0-Y`4-SN^19(v++A9cq^HZ;xf-pPwjXHyO1!D(M>+3t;^+Meq!=dtAYbO=&rXRMae9&AeatUDP{8$} zCwQL~K1$^)q;L4;9RL3cW^2*qSma^X6i&!@V?}}o9~ekJN%yD^YP?6HBc>~}1!0$L zjE0l{uLy}+JXe_>B`}Qj11QLW(a9Ih^okH_Ds&R&C?JIXI{M=#&V?5z8!;leJXv=q zg#(iSQvH4Q(-``|>)xC3pH?}D(33==PIo_Ip7x=28@)XaaEf8})Yavm1;8&vTu!uZ z2ubYpSZzEbHM~@)s0X&D5tFN7iD`#PnBFcfL=lkfBgnnstvy$4=7w4ihx3cN9bv_0 z#Jdrjh?m;RT=tqWpwaBI`YUe(xcsQ|E3Ka6KgZG9&8KaDP?sy4DRYGo7oCfj_kXzw z4@(E#CpI55+7%i3EhKZ*eRpFx-o8OQ>ujtP`~qq!sgEWk9HtiNs$H9`eEiw(XGfi_ ztxXG@SW$H?^+-l{M)*$~<+ZOcdHyo>(YeP% z)B+k-2oLWz4xG5T@aIb!i&Fa+mFjQiN9(^YQ`x=im7cK6 zGp_i6Gl5&|6OWz^j5fEf5q>j_EDWW_8y|0kVoREkOLoo-i7{myR7jJWo5kl^?`B0x zJ)WrVdiA4v|Tmrz?E_Z zgvZjMwMmrTUuCFu4vb9>Fr<=Q0#Z5Wd5dyR7lO~Tt|L;Mo{T3yue+(VDz2M&3Fp-c z9y2W*D&4NHC+>GPwV+h56tExQ1_4U_}&pQlm>wJZ^@k4-iSpk)H$|G3md5y9xXf0)|u-VB`aV+cn&LM*>1aJ7O z&{#Rv+E=vjAAP%e2aEDICkrO3g#+&lWWW?|I=Y3%7Va8k`syj_s&IgD@2DB}l`v_F z23gycq8mhhUR1su-yoVP2}}EAollhyyL~$%R6x3e@;40VMI4nnW%a&Oa#ccI9$1*g zp9}-%jITT`#g`|cVlP+hAPFy~&Gff}ry#PZC^x$$ky1O4SojZ6%=K?~k4P^4%Wnj4 zJ`>O=yxFI0psMAX2BIw`_))^TYt{nE$C4=W+R~Q?_kdAN58Y7k?PdWSTMXBRkUM9x zh(s}>egG`aI_#}niLY0EV%Kexn~@kt;*pzydNENAJj8p!y}2dOMr!LiF})OeVc1q?IWoNTZHIpjK6PN7lC-@^B9eaPu!ymS#;oO}d>^v|$^S zWE=ZubEyZJO0XP(A1!}Ft)xl2y4(p~3gUNTUf+coGiY02v*tc~4h#pawi$;g)8!(| zzMFXqb4gVOT!mt!#IVjlZj}(LrpB1?X`HHfDmb@P^9;e6*y@j?qMHYTk_;-Mj?jdy zrkctZ0$Amjy{cju$6-jlICPE0v>xY4Abnu0JWQ|T-o*f}ZmE?aJtD^%2@ulOVF&;N z=GX*_>I5CPa&3$J^*Pw=Yw{Hl;|kTvHi#C@M3n;w4sPIwV9G*~N9$mp@qyExkju^1yu|b~ zSc>a7SVnzu@ED?KL-{1C7J@Zs1~TlV49S{ZEToJ-rfQm5>GmMFtoTCdM`3ek8GYE# zP;xb?V082~=zh0pp%Up&D zw8!VV7VUC86Liqxjoq%TCepp>vU(Nu05Epdew^uKv)02d z=A(L_pgXhAdN}n|1CR8@z}_!}wSN(7TE;r-oO!?f;b)B7BKB2N<28*2Q_1c-*cEeH zuNI+;DtEFsGyrAHlVC@*75t-X5E{NRAq_25^MsA=qTrr4T=%VxzXcKAc0=V0shTw? z-};kbLkevBC!q!+lS9jt6yn5`+t+_$g{&W#$=LBYye&r1H0q_b=E?ck7iEvcjNpnZ zhNgls=xK?gXI@9jAgy;iCGXYaRK%HSUJHq@1qqH{H)b0JVqal}({$_?DAM8Wc5y-8?&8fVfh zVfWjG>gbIGWQ-4d&Y={W8hPIIXXDNO4a#{mRz7_GxYS~M6cKH2Nq{`e5riyvV(D(b z{RAZY@oo@B8<}Ri#BEy>3s~iURq+tsJ|4TkBf)8s4i}io3Taq0)Q!Nj(pO_jM&>%y zF0XmLblCLO<ET@Qif9wa|UW#17YAq8JHaIx_Cq#O_w+YWU9mM%J84SAk zZ(ft?_$z)c!T*HvFas&0NrJU6F9JKm0uIe^n9j3q5qab7LU%zEf=>5H+7DV}*`}Xj zxrt`Fq=iRPM$@+vue&ow`30qJle(28A2F+Ycf~(#F(MZ%*poi3fhRuj5!}>>kf+bO zR^gT9e!_2-$Fc7(rGIRud57((L^6UH>l#y$x!ZHfDBwHqPlGPdy zP7b%2Qbx#wm%q=5DhE1y`+n{P9}i)_lF#nIG;NiBc&%}=-qO&&I1~C>@7q-yy3<~= z@vuZU$DD_ieC_~uqZ({eG-_T7u|zOD+O+nA|9Mf?7$GWiu@|OS8t2+7Q(}G_*ZF3{ zDbgv|{r&a><~xRVJD5g1A(~YVv*?IF%W*=!l)QZ)ApCbzXvE^7c6ej)^)5;=v4h@` z1<4RaP5kl`=Tzon5wp%PBJ&}Zh4px@9e)VH%gTS}hW~yn$RTl>D3bSaEJ(=me=Dgk zvy`ENFYxE}eqrqc>E~3VmTl+zlH}OP6mHyzh)ij}o_C?u==?5_4#Tcpft&H*9Dkl0 zQ89j3p-JL7F|cfb5Z5E|#FNPax?Zjvmgxr7gYv!%!)ukuQrDVHR(r=mFJJZ0&_ETq zKb#iq6J_(?BbV%{Hn+4X;y8oM z!hsY6N33GE%nQnNN?e_p^Bh}eHI-LwQx1dB*=o&pSQx&miJ^f@Sbw+;HFvu;OmXV% zZX{&hwK&FhKns?@QE55^@BIBN4itx9+^5G0jir5P`KzWOcVgM_lg!-`77o&*wzTM} zGY!v5Fy}Nj@?RQ#pdME>aE1Eq2+&X-+JWZxs!)P?8`(vlJAR5*AN)p35wZL3d)`> z%&XQiUDvw6THPMbrjZ7%T=@<^;|zWjE&oS)PnP{(s9+XJroL^gnji_b7E_p?*?J>>RV|Z?XecJe%(*Q06S0W z#_cx0#~-nvAE7tP_9Ub2G8SX=s+R`bC@Ny}@yegTzn$Ul72Mw}jj3?86*kIdW(hkv z-N>nYoJ-Wl?0h=G65cGt1PFA$##?>R_Uz^re+8(Jzl_JAi${>|a!NA~{w!1R zS>#|#ymLq<>YW0wyV>7Du7DT)W*s9XV=5@ zjC_?YdEd;XONchG5|+(8-XO+IA$ec4X8ihpXcQf&XVbVmn3VZ6*+u+Gzn!ESz#KaB zB0kV|wiU~z2%ykOe-1^YtG9g}lWEJV@Mi3UEwyDU?wGB#JV`F!QnsmAeCCB7*Cs!B z9!bdoZ{Gvw5C~@vs~yZdtp18$9j+(Ri(bU_IL45J-Aqlz`;_zo!9Q=zh0|@X)s_R% zI)qSJb#q`P0{8+Pn>656?zhdM8!&xk1_3o>@!Z+k1SzDC7s6yIf5T|@+Tj;OC%J#BB&zXSg2=wxklWab`H6svv@!Hahl4h`4%XNSN~ypaN=H~*(5 zk>#>@<4fQIGeO<`mlm5)5#DGTk&Ld;IjSRyHt7G5Bs#KX^dya4R=zo^jiv7#Mno+c zieWeAo?9o-m%8K^X-r25a_vv4_8-?nkVAi`W-KG|pg-4g@gYBvurlY)o6xW>a1{#~ zzLNe%+G5^{$P~`Y4qHUh6p4b-_61ooDBdW2d-Jcwo)$|nnT1mlHS5@nUef(e{?Kc{r_Z%=Djkl z**A{3Cpap{JX+*lB4ye2Oh2R=^e8**vL)vu8b3^6OD82RvNun(oG(gOdBLQHr{;Lee|wgDm>mdP_49!*KD)t zjvt0h8>US+&TLzTAN0S#HzC5

  • Ct0B$FO31Gx*>_f=r@7diRad_^l@{**^9t*%=ZzfB6+uQWpxZt1ggnDILii zcXh}sigjMlt{i&?zM)U8_X4hq=K7g(SE`bq~z-m}OePSOh zru6F{e`K^aL7$RWhZC%!%%=e_(V>)_;KP2l8;)JJita&T00^c8><=yHHj9A)PZ&Lw zk7MmSsGNqQX*O8?hs?Tz(7^E0-RsX_iQ7Gq23qwO^y8 z5l(rB;dCK7>pItF6?8QDG((Hkb}Egu<>h`~>314k&aD_3lTjUs%{_jL%M*j?NIviW zA+mRiXGeQ?)?1ChQe9q4ZNMOV47&9f6V zfYZ$l5GmB-!2P20aZF~UB(V_obi_z zG~OGwE&E;QieuWp1T+;io8Oic5yxje$XxnvuUrOt$2KIfe|Km53x{|M|6&}D`;Ux` z(FH=yr|BAq)xr28WA@!%?)B(pM6Rkt>?VJkckqk<@k)%VwPnaO65MAIM?y~Z;-?fv z9w6>)6M?hXOAm^gL;u?&CPx}vZO2qn4?=KNkf#t(^I#~9aNjpHT=4irR?AVX=kl51 z!DLc*n2k;_MM%zH?XuJzfn$4ZXUb>iE_U>-yIfPg%-h-%vVPxal=GH&b0U7-_&`M- zJYRfiV9!fkiROT;Fcp@5fmAk37+I;~SoT)kwz&hzqZax;YMXWRO}~2Hy2H^KnE0V( z@Nxb&3x+hjx!L>DxVeM8Aeo<&^6_DKa{OKoZ7;#8Ke8Z2<%qt@GUaHf)0}u>BeZbm zI)EBRH;yj1JGSVwd_TsuNw^YtGaeF~K zoyI!?lgs)uE}OQVuRMs?H@)F}Y6RO0A7@7mTsENl_Z({sz(VetUb+yXhi5kqaFd$f z;u%1M^a6+`oGm8$1&=KY+KX`lnIE`TI9(mm{rl)boqw`XQ;sg4I(53W->RQBcZ?t6 z2bw=D1xBYbLezYuIQL6kijI-PM4GNs0B%hWt{ZT=`d&}2n=T_Kz2!#yQ{gN~KYMby zG378Ip-F8$e6HsF2m-c<&Ed@=M98-L=U7->VK(g%JK_^xI_-I$CwBAD=fJj~I`XC@sDE2mXQjFRD0IR(!g?B_9+TB zpI{DB4%wPcgCjS0EH01+R_O1CHVLsa#Dgw3Lc~Ld0z@k_m;U;2HLP4_*e_H6IA($c z`cfY7vGomUOKJIsmp-$!a{WX9HHav;6j=vXYTB+^x>wSit3wnxX7$*Brt{D1Ng#78 zRNQ(3?z_v~LYEJIGPJa>C#z-Yddz+A_aW0gYV~?4c4DVGrZl~4uLFBHN~$hUw$Q#?xc z3roBt;5*XE@o1a*=!nzP4!HnjxV)jGbZN(CF8gqfIBYMqv+m_hy9-U71{b--A|L)~w=VVqs+Dc`Ml%z0L&7<|4-z_!tEZVTDe$XcBUojb{kVJzh+ zXK!_01tzh*sVSH316KYPy7 zXi=hLl4#MQYm#U&>Cb$h-9O%AF=bZbL8jCyl$qR#rC z=Wk}(g_3~nDY zy;9-uL-vpsRd{^$LZt~yPn%AC!sn?T_3CiHJ|8T^3$-fEktRWwIrGh~r|W>D49;#J zehqlTLJ$$Gw92pLzI2v?a=^%k!xIk7x*87qI2a|#Ge3!BXHk&Q@};@(ES_7Gw#1&qaq>k}y zRVNhHfF6JM#cZgk8=ZQ>P{?PDIn-ZX%6C`YxOnb?OihBr@>;b-R@BRw@s==OFjt18 zx)7yZAY}utDNp@3Gu-<8(91)oX;IL7q@ktm3K-q?CxQ5Bx zA=JOjIq|espqx1RudViYsg*+8S1I-{uaw@LXGl78(RAz!VpXpLCbPR>hb@v&I}-m2 zLb3xX-0t*g)4VMf$teJT(m^q0j?W?wk|+Rg6qv5i_t9@eRzzhGtHgnF%zz~SCeIB# zBq6dMReF)u(Wx|$E)*+s5kZ=ek>Fov?O5oLw`O4lwnfx>bJ7Z)2D6UK>=lJN|nHyVKhVmcuC zsr8V(fNcwVj*i65VQ;E5r`%-HqAgP~EA$8TTF~2u@5gp)HJ%wXQtc=A;b&y6mM}#p zro{K)Fxpr`^0bTDHJHlfB=**LmaCsM4vRssT^vi0oH((CnXy6&n12(a&X32&{|NU8 z^qFSx(rEt*6h)HEixwh58gAw>um`p97BGaR92BQ$ikA?s&dzRrz|j8Pu0UU=K}}b- z^CMk&{mS|}aVKBB?)%S+w<$zhCkLYT+sli~PK*Cv*V`+M*yn}hfr7#-GpgOA(m|Cy znc0EE{2!i$$R{_xJ@(w5u#io8a>?WqHH}dL(d41A9H(-5t&PC2;FK}=m1jZ<@OJ%q zBUZ-~ux6Gk@%sQKoUc9%8Nu&Kqn99kK5$>w+j^Tnn2;6K1+b9K8|ffS^%pn$ph;9n zIQfH$pC&Pws`rSs26HYu4b0!8lZbfXcu6VS@*Py+;Vy8}*|@Y++Nx&u?$V(?D3ov% zI$NUU!XMHi$a-r1uH}hN{M4)YGm8|hi9FB%POhu*2}-MGT+9BzmY}q#A}iJ;*1h9cs?9-vkP43OvTb& zuJ*_Lx3M-bfQ8jkU+wRgqrDvbZlsF;(qm#tMt*_K; z>?Z~k4C)Qy3~U2rAfh46C57Fpv5I75l(r@f3EASLe?~$m+abULmn>A~&P20F2-fT; zc&^;n1eGFN>cqwZr96G6Spo&sQW9i>TEc`1rOaqUEw5{~i9su0LMK@xqf`W1`B*qL zJ_mqI5J8fY!Z(Ky;*yn`1rKssBnLi5@>@s`%F377$X}N0%GyK_ga)R_FOefMMz*v7 zCLR%$u7?q(6U%^NLp$r!{=KN@+jU%8o*$ac0R$*g9v2pflVUv#jL?!a$+s+A{=KHALs~_1!)<0t zp&eq%TVC!1hx|c-lSQ5imT;gR5}fk|m}@{Di-j<-5h<97oKbQuiGP=jHX}S%A&6Y* z70XDGIqCO60x>Ht23-D%9Q|A|_`R>cCv2zMZWhQ6YHLcbBUlXa?MI#(Bp>@(^xVh3 z9+9V!*;szc4itrJ3cKVMf^~?2J!Wqmtn1v7&?FNWy9XTiK;G&))9E7cla{t&m{eXL zDy5BQUKcn7{>PPbGO~GXVWOa8e(Zr87n*(yu*i7GH^RXk5)>>PpbY<&Kk7xKcZSgm zJ8^W;-|SGquue(_4;4;tut-7wm5CHy&6~-BQ!@&BU@m`~x%bbqQ9nN_cq(aY9kRwv z_;W7QD>w+H?5LY!6N8xF43gWbUzA$#Ck;r2sC;4?5d~Cd*jT>cu8}xG%)FsPZ+m1o zuvJV0-lcCm0akRJ5)`pkf4BN9E-5l58i9e%CZKkV9%bTt)2G#CT*t(3MG zDokydbZy@4aMh!^W0-VoQ$*{nWaeyx^y-nAR+@e&inUv@a-&f;nhskE7`~6pd^$oF5-8E2>uOF~S`oDlE)%i{?c!Gyx zGVK5kv)!N8L32;1EMDt4O7njJe9jNJ{og=g6q%izh(u=_MpZ5cB+|RPBT#)VhZ%BW zCl~DYOlG6oS0`6w>fw~et9f?%zUn|Zrvy;<&B&|j{5zvvb1Klr+%sbV}?KXU8?o%n{Ndh0@$oJd%bppzk zXqz*NkF_gv9$GTD(wJ5bsF9LILizSGD-tJrz95wEUAp)(OL<~8 zHE~ZHv`a}OsW6GO#XzK;^-|8aY4f2t-(|NkSLC+Ke05gi7A5kx!3(&{vpOpaC5Ig? zEW1(lvD$flP9w1M3e^7`4(+ngo^7%MpPrm#ak0IT5CMz{{zOsws}bjJV$PifwabQ+ zzgQP+y=Dtm$>({tpi3l6k=ojKI;GlcwjL4Z! zw%QOBUzd6nqG!4G`>!jJ#r5Z3UWrNa)qk-egw)o7ekSZ>U|)$Oc?V1QT03-~biw99 z6*lT=2Q#aUOsphkaw7n+SrP!)=welDVpVKHRj4w4isk@J6&wIn#U@t8CRRm)&9RmX z<*j4p1%WrIzz8n6137w0q02VEnTx+cQ&q7a0=7y(IL1mqIMy1gWfQGs6RbrS1}v6? zu=d13khN^0wQQobY~t}bB4&#scSP+r6&eGkTdt#_B+9%DvSzWG25nbF76}-xTkKe^ zTkM!@koYD{e8Ur$B>^)fi>>vL#Xj*(nD{14d=roC60u7g^CfDONuU5K-5j9~;xySt zuO>~gE`o-rg3ttPk$`Z_k$`Y4GFHnbTFWL_i!KaUCkJ6|h=U+&*+gsEL~Gf^0|iBl z6@?Ir+G{E_228hFM?*=Jc^Ope@oE*c-7dgUz;t~8$8voD$8aN6Y+_YxLRF};fYCAl z)|waqs)|jlicPGFO+4^a#9m=Ys;Idp0wcI|W5s$&q09TK%PuZ}In(YkBn_%VJ@^Ui zTh694bGqHtYJ)%1r^tR(ta3Cfb)Y2pY9EF`GT%Sh^8^tU{bJ%G=>Qz!n}BGsWr9Na z^nY2MJB(n2WgAV|5|!w3ljeGSS#8Wlve(%6a7T*@^bM$vzT4;+#Kq7284G^9ihm``V*Z9gA71Kgxsg%XO`lx zWWQQAyKoT6_&I4w1aQ{T9%WjPU$37}%`dMmO?6&v)K>FX%(?>W6yb}GV%r;jlzH)5 zV8x1wKPm%RLFJf((Jq++QiP2L4N0%JyGD_9?ZIWNbp{zoFK$SeP3719%kH{8$?%Zs zi!hXqhMU#FXR6Ch@I;A+DzZZQW|>dg?`{3za9^EHW`1n1gj6=A{3DkYBEF?KBD|iD zyR_bGVqBF@f{AI{okeWKy}0*rO;pHU;_&q$)#eSLX>z}~jET~utZpJi4Hmxfq4 z%F!oE$FE%p?k4nK+kP)Rin<+BalyHD1VwU}wm^Fd7I@$fAUY)P;V3R4iTL+5)3I$t zR4fslE6b-H8r;cQwK|>J&(&cCB2h!6y1F**ta#n-y>9|ed>^)hVzqNi_brRMW;D#{ zG149T27k?HPDY*bE_;e4rqJb$0aHwxQi5BRO@n1?_Z(o$Eo9ho!7y99XP>Q!&UGct zp}Sv1#6h*u`@~!>(sikcI}m=&pX^{jHYaC{%CW*^Sb>!fq&o>&u>K_u?>45%W$*aB zIJ$qGj$4!2qN|nk_qsA2E1d>0Y|?%YfS~9&UL>8f3Wrj3nk^+eQSPN_&YOX+%Jv&l zDR2cZazbTNky z0EpRxG{*>>V{YVh<46`T;mR+}pQ8^7g3?EjCsU(0N_ZtKM4e58 zxWsU?R?N7bLDL1Jf1p^+N<>(7C;nxo;`r-{uA>Rk41mc(P~}~TB6F58V&$esc`w}) zlTMKc60H}jxMgmwq*vYvqp=S#`4$4Q}%k6i0#s)AEvcS%{b z8t!BM){ZH4^QkR-7h0HWCo|}D>W@rnEF-fwg8={f)!`IZ7}S`x)D+UXUnKPtsUv-N zY9vyCbo2O=Q=%)><1H%GE(XR>V<-u1r)LreO$1&hER5rsm9s|Hc;9-rBE%=ZqSr~h zZs)dJb&HLp@29h6KAqpfK0(B7PiK?eAlP=~!=WtN=1{{pF^krC{~(Jd`3&t*b?M(8V$rLt%BRaaEm{+C+Y`2E zD|J>K;oDNI>}ZR2tfM)fk7vT3)pyF8RS~ph4UH`s0%ALM;3+G%x%(hS%!W1AKgfm& zE_n;qIR_tO!OeU!FYdKqMFh7dY`<3GtSZ8{rx>}>*6Ub>fsyuU@^k<15Gn9T&00Nk zz5-Y8Wngy+CX$?Ivw1=sUdf=cdw2URun9tMc!ah*zRKu_5b2{iNuE{*k*n;Nyf%HYmjiuu_Mt%q@?cTQN| zpd^TW2#zedlf_mN*w5m&s{Krn6f^v)6^~DLgi`r+ylnzK^Lhnf{-u%ZEX?AjY+fQw z`#VxM@!VAixA^BAE&8w_EfrA8sEpVndLfgWlkNu8h8?ZeR0FZ<=$BL~w%tTE6>*ULk`HO9ZI;kz<(&=myX@ekEMxAj-g8qUe23!Y(w21_ zah6Sa8qSnl=mO$nrx<-PNB*qdI)YCl_~{#5(2;ED`}2l9yr?&q(YmDI&FXlrx?vqP z%slP1&A<)F!p0DC>)Vbb+v$4b`IujVgmF5i;dx5?D?B5jP9${4Vr~W~n;$kGTJycw zmYGWd*=QJCV+(D7b31vaVisS4MH+yGVE;qHh~v z!q7&{H(J*&Yz>qqKoz<;RtKq24Lb@~GD@rj zj%4?Dqn314KjW>Nr2MUl%<0_P-1&1lez~4ElY-!{EM|IR3lK(zp}#>@>TgK6>SJ18 z>fMCNe7Y>CCKU6s7|*;WJchMMH`jEXZmvG3baMszMAM@bk>1S%+N8U=Uqhsu2W*4s z=6)5i9vD<8-Oas9Mv0X~x_QrTM0ImOf*(c{8GYoE-pyCbdATC^o2;s4vT_L{!_eQL zD)l!cT=g-nFZFK1WU{Cy6RMjp=96OKHQ_O=MY_4B>vVJVIi;K1un`nJN)hSZJfKaw zoBK6Hx_Q7hm~QS@5$l0Lh0@*Jt7Mc|Nvxaq>qcZZwpJzCc4`?gd=^HR5#OG9m=s@#Hfkxq?q<7g?6la_UHj*-?aGAzNycMlTCe{RrQ2o zu4$@qF?9(e)$4CiYx*0Ksrs1KF?u(lSuJKcwV0{Pd6|#BCOn3cr*vK$ zbcCWuDI&cW2ee7|Wxs|9PR(we@Si@o@2KtTX04|Tve&q*faiA5% zjVmW4dyJ-Y5wxtv6?taVHn=&91EF^*f#3<*#(FNvV|veIT4W!+22a7drwZZ+b5i`? zo*R9Q7YN;gbdPGi?8#am_8>%7_347@{B)sP+MU8ZrpnOeGbg|TfPXV^kiC0q&imV! z<$im8^vZ5P;8r;GF6&{(}L*4TcOjO&>PQW0T}A0?oO9+LpunH;QLFDB?K zN7}-qgmo}77!i$ z%hm?-%T1|QbSQ+-*anr^Z7)|HD9_OLuc7#9Op?wLgF!%Gp?AYUUy4YL7Lu8ZG(Iij zl6ML?Xx?ty>dC&k{NyWnBr{}5Ta@~SZ^vNLBhNTmU-rXR2Zk{72)xqvcCZ*36;fTF z+6OVwl$`3`w;FH%SA_%G$T`crxL)nrAy%eR*#!L1P)wOg-nz<5_Bs^HrE!9oV%q^3 zmxf}2yoa&Qnv7(`hOw`nf~7345XSe)Y?oo1z+OLc*9a8*<{dNB09ej90YUMu<(EfS zz{(`L_TX=6>8nep^YM9Gzx~(${5Mhl9|B!mSseXkyE-2)$MtpeEC!yI-cQY;WA2y1 zy4qcu*Y5%kxxHNlGY9x?g$AyolL#1Ea1J%}2pgjaK!5>nkotp>h%u-}p~PV!(HZua zAJH*D=uZ6N%$)1(r|y=T-yRiQ4qOJcmuAgmx>$5l0z);ar^whXo(M?yr?ull^s8+;kymr53vU+Vf_C*UBK`&?T7%vuM zbL&^J&`Fc1(KS~r-7gUm)`XGLi4>Gyz(Ni!>a=5-5_!h;U^%B0R;HGWbe(WHNmh;A zID#zN1t5w05V`>FlhCLhgf2k)LNu-qqDn?_WVqu7AJ%`ly%p2|YH3L=yzvwTzx$>G zK6ALJlz*WB*8kVzQN*4mph^PDW6Tt|@2n_8(!j_<@kf&Qd!IZ`CJ8u2x@xDwpI{u{ z*WDKz0=4_#uA^SV5z^nZ#OB~c33eaiL~w3kNF@Z5BM#&aj_H0W#fPodmz3L)+@+?6 zK(Hu;z;fso5)4Mn$p=kPI2;0#G^{A&tb>mDo>I{qDSj2Ts+v)pU(!?`r7X`j`~kP~ zE6L`wW8`}?8d7NZ`Q04HA=3GynQ=kIGKrJbZlpsuAG?GD?fXZ(!3Z&hk4$bk5rJ+b zGu+A7T&}OFGuNvI_+BRp8f~1+7`;qW#I1Ly<cGIu}l>~^#mv18wuVsE#IJGZ-yom9iFrA)a>70F4ygP+tkEi z5HWOhheRz%J6D5U4|}#P&z9Z}F3qVrSJ#HEjTnjDLf_{LCRMe({t&4ZuCRV*4mZP? z{$>K+jQO>$u9Y$&eP(%i^yr<&;^ukICr)pNP!~C6h7)rmB%wB_VY*qu2?FnNq zVM_p1seHPQn)}6f#`0PVL4}zj@3>zIiMd z(a0p&NK;e7Jo4NI0118*p)JR3bjg_ff(Wc6ld%|?I`Kc@t(JfdcK|UP_MsRizEMC` zzHuyAng#c6Xi5xMp4$Lmss)EQj+hoNzaTgWi@T)pF{ ztH{L3b3Ai_(N_)~+&>IQrhpoP@O8WaqYQjRr{c@qRgYOS#DUxcun2~;>LU>RJ=C=A z`V>-dIUQa+-@G#%6gwI~k{oNi=JtuR#bo=_Wt55#*C(-wPaS-uS{l1-f57&7NW73d z+(x5DdFGhcjwD&=21H<1X09YM7;h{heHKaMnZsnJSRckR#r(1EV@I6diEwXpyYA`- zyz~y$2P*AN#w@7)OO}d;yvUZG5(i@GOGBy2bet)!1TFDy+o6v)UB)ub0H^}p@#3zJ zk-#2fsrS+Dxj@FM@ zDbRpLFxQJe`jXkSA%?Mg_Zl(toGkc#1#v zU#|7|S}9iq&4~u^Z9km9u~_GO)I|9M-t~62`}_pBJi2Qwo&{3y z+DPc-3zaQ4L@@nU9p0mk#LSE}nB9eUmXlv%#I!WHH1vtW#62zxEa!Mhl7=4w^EyEg z*p0rz52=)tVm)Zh|R9g{1W0XZDd1)q@B!@~E-$8x4_< z7#VLL5FN1xXRgN$oC$+w@__k`2Fq_aP$mtMJqF0f4UR3fp}M~>NQqxh)q#6?>Og}9 zG`;rgoIs+3Q8$0?xxCO_$`7nCVdVCbPR%(+e6a3!;u{031m_0Mm*kfU;GK)N{P<#9 zK15H3^*UFwad_Oeyy@a{cDoP}LqYAjuC1Q#N7E|;vke>g5h)@$>>Y?PyT%ZAO% z>fEv~m;2Y_%WCtEXqb5_t&u(l$7Dj3NJK>55bwqYfg;mXaBk8n6h6)IG~-Tkny10#IGf%_tat<3lTe*mfm=v)`k{uyc!EN0up&_J?J zY!~VK&rw(?RPQvsF=AEMdkkEbIU-%I-#1W9%Y-wlP zrl|F;^VcRaLkJ{Q2B1kyN9rjWCshfnBDO9xK2u&fCYj?6Ize)I76S{huV^>FCvtN% zFVk*uX%7ZFI!=Yq-L@a2+vcfm&wJPxQ5{bVlE~7qXzx{Rh4ST)syyo+73bB+%+g9j9?VPd^ea2&KM)X~UoZiDZu0le)qnNegiZ%9li$}`u#OEF!myZ z*WGC-X#LH0`t;?WwrFpPutuIy4Felb-lCC!v|@7;YAFp6y}^_@6ww2D_gVt$IHrpP zys-yO3#^80C<;6qcqm}9Z#|a2x!dS7>*R$rv*VNyqA+dY{gkvc|5|k62sIngsY=!N zl>IxSqpzQt)UWNUWhO;cJu)*XOPI+_ng*{klk(7snMqj!>6u9piHBt-MO1BOQe4?L z&rIrb1u~P;yrpC&CCGA_N$E-+nVA&TaBF7LG@pzaN2p_@KGT$$LfDwa!7bIlI7EBdska}*BpM{b@Hsh>vT-wB zz9T64`xqK$F;vVwOrH`}21$le5|N0$?M z+*nh*O*1NteqvqDCKo|zF8_om`6pN|gmET%k3vdq_yTYOV4^vsT^ZJFQsYXRlSWma zvJ2!6MtJ(@P1WBL>Q4f05&3;TVdw6~77*7?Zl`dUAh-)FY0?1JbgLxrAbCHH`=r4P zsnnpFWF7oq;AQKG&(SuwL#kgurUeO9OWJc$<1Di-YCqIiqhl`W{cR7p zs8P@~?(eu^95=V1i<$tO*o26SI+1_wvq9EH1=+)cxUr_BxTvXh#a&d8)QO?wyQnS% z=c4AB_?uuBzKa?GOf-iy7gbxYZ|tcqDpfr@<&%e?%=nG{oaAayriMtHzueXi($%() z8SkR%`&9i&kj|wU!+N^fee_Ga+P6`-OAt|4J1C9&ErfNoZ>4dcG@`Dyog8|)+AbHK z2ORe`I9Hn=oJm(ZP!Z?V`T+dgA0XSy)$Y$!FIPLINm|(=yx+MUh*#&A{SpUQnS+CT z=D7fsl8BmPOYt{wqYJQLZf`KBi3GHGp7nOww6m~I=BRTr{OPY*R%Nfy1%*tXXA!Fo zL>WHuAPnqOwGxrn1jD(th%-l%+$nd0{kn1ib#QVa;W}5s|JruoW1?k-dV+`o#ouD0&6O8v-z_g^uZBVQo1}f<7c| zCxPP1L>FODLpeJ8gjE1L(WoZ83}lJ~CwwW>e2gB0VFck2vC_a%HhVo@WkXKT&-*by zVD2ZS;*>MZcA@CDJ4;-?FkVYIUP!`F;u#VjE5tI<1&$;}QBYt9(zI}7WCg*&iUDE< z1vLCj!=uxbXDBd0(J)D4)HE_i5e&)5hm;CzfvIZZlFw@yzHRoW>u2WGyG&|gMNO|8z*BZjGX7yp0Wl;7LAkS&)y(e7Yc810?uRbS?mGKmjHR&*(Yk-8QNu$}@5NtI&5jJVye zj~a2?5nT98-6MilpnJPi>}qo29)YE%0l^{UQg&A8C{KtU+Wye);NM>Mtvh*k16UXI ztz7+C)xJG!n)8-RKVCQWyw03jHu)3$b+pN0TMa>kbE2Yq5|4)UmL=*OoCG-#AX{hiKzrH#Fy7&vsYam>;b4PwM=bo?Wk}o)T086ej z3Z1Loi&HVp06DBo^g*i=sbyM#yYtsg3w)@yyI5}HNn}@=h%0$-fJG*;y*w7tnPzso zK{gs+22DF|wo~Nr_|iRGJ0^j}VUUPq#Lp-A1xEn|{aL@h!1uv*1ewZ`u*07Hq&#}? z32uz@aZoK^qg8b>`{eMoIhFLi#jJMiJml=Il=p-!V)xg(nl=;qQ3f&YbO_x)_V|gI za1HGHfrvz*e}369!H6OJ;LX6#5m!Q%hi%{3Z!dCf_2hh$@o|3lLmm|@g;qhkPs6 z+wDZKCi_nCdJMs4;3?oguIiDl5QQ&;A+Fsh1>6AN_fR?hTzpJriVZ#l=P*D!%}p~p zgIf1$*SIF?6>luNlQWt|H=u&2NFlKd!DDvVMn2_k7=v<>q$FC9Y3JJz{t*EYEQaFm zY`PvGg*;*X7@*(D=ro#Xp@J6pS(sHT+Mgz6-8?^WFa68c?T@fIv+jQq7aZ>!;lYWLC{jvs${mCKwlaSb`~2q9v{6qP?r_zx5QCMKMI3>C3rhR`2| z{D&cb6GKiu$Bfu9P3I3Y{=OW%pI6o`JE zaABW)TtEmPo!5K!|5)fZ#4*1zLv!bW(zBbSj)HSPpx)uX)%6H~i*2qJ<2NbOvgoN@ zVqZe$ZsHSPWUu;g0Ey`$scUZxNmi&)K5xS88jzw$c#4D)nrR@(nedF?#X`eh5#|C1c`;#oQ|+!K)`!<3q$k@OSH25#mLv0eo?W8(Xc% z-FtJEWI)*%BFfw?DhJ$Sm4j^JNI`B^*rs+ke4UNw{0OLTo9!% z%XD{va^fyf=HHWv0PA+y?JwuXs{w#Q59Zp4rqKvL0!?|e3i+Xv34LIjIsjmyV+qW%6&vZF7 zBc!XkC5}G~&&}m@JY3Y{BM+#n$K;39APKf7;b7}RbvuviedO>SZeN4($-f_5g}&Tx zXY}D(KdwEGsL(|g)5kY$!QB1*{AJKBDmjuNQvCbNAY z|M%8+lhJ-#`EMR9|IIg+|Az4nLP1hc6BF4*L0df3o)KJ<97eAWEfDvvYxR}hTjRlPU4$K zN__JTCBErBd3^B}cXHF|4ZHS3#c;X!dwlo9>vpNL@zafnZIkcfd;fA zbhXnYIh4Po4v+WKf_PGQ58|N@Er=&<_)$Fcp~cFtexNSu8+B1XP#5)$x~Lzhi<+B} z;Wfha&XP8O-c2fC-uH0OgH*t{@8O^aseoxeObhjGTBskVh59xv)Q{6b&CJv`D`#R4 zac97Ll#@V<6zKza=tC=s_ss+4u(?qVn+M8a!yHn4Nn{PXjdy7%N{Y1l`#I=ADuwaQ z<7BY8O$M9C$spZ4NSB>GVl~HC{7Zox9doH;E%snOoY=sl@P;6TA|LrU=v17S2#xcG zI^%Lq;}cgoxB~KQF2In2_xWMC@lW`DhEVj?KumoI`<{}jdx<~oP`rO#{j_mI1w`yb zz;-ah7(8TJ~Nzh7D@%?mOs_x^C23dIfhxykscftu>E%6pn!oSLVTn z`&!Dy=R4}UwXY>tKxhrH&0inpDc|4MT;^@~0Xj+>1`O*f<>KPxyfoVNVUf5%N#=6#V@FH=({*Xv!viw|-RA!3A$3{IA6EUt#7(q9Re7>M#E@sKMU(q6@Da7B~12QIFsZK)C zGLV+~-!E-L*qD%Q$;&c{cB5yWjj*2u|%u z5%UozCC^FOak6}AP51y~7NaqVAa9NQEqzg5p_)*8r&Ck4a4Q&KVSlWv-B9LT{hb^7 zBn*|;fDUQ&Z#7>I_C*{Bpt$W9CtEo|UKty0+nEb#CVkDV^)_Wwnv4yj+F( zn6Mav>Cw8X+mX6!WWB9+$7d9MP>M~Yz*Z7$Cyb`3MHd>%$RgQm6T&kJMMVtt>S;}( zP?6Dfg!TRLH;iLGFbFv0sQ#4(hL9|nk=FKbldQ71pcDu;IAB;tv!9?PnXjL1$akMX zdd64N9gZIl1CmHGD&J~=PT%kz3;BmGbjRoMYisfWQ?r!$m_Atb?x8LFv}0J$oLG2?ZF|CFitBPAOpM?>7U>1 zlo_7NcaC?HPe&!PN<|z@25?h(I7YzkVv{#vzhgo zEodzSm$1x{^QQa93nWCx;K^tzdXqXt(4^V%v8Csw5Y;bKnq7n2%|;>=*}ffAU(QX; zZy$;wqHB;Erb^|wYK7_F?flwR0+Ot7nN_^;(Nr?cOdb?%Dk6HU86&?~bT}?@V^OJ| zn=u27I~+y8LFJb{=DWx;n`wn;{bDh8TEBBzzJL@)*W+<_-JSwk0wdEbqt}lgwwLX4 zyOZOF{CU@;1VqnAlXv~bEX6G`SS@(mg@b%O`e`|ag|nzCySH=zjfv{zBH9pQ8nNr3 zUX}40-Kb-#vqo!d6-MMG8fR4cv3b9k^nLPS+JyphdZ^j0&gbLDfCbw3aL!f*Uh&Zn zWK|S3Io^6^K(Ihe&}FwvfVF_#6D}j&<=Fr$oY)~J(05B?CDY8j!?)-{oTwp!r1)_54_Quz zLD9s_@vfS~_7Sznes!OYCmAWJ=iVZi5~p}d)WabhcV|;~!_M~;b%K%b3M;ZqAy#0k zRTsA6>#V?Zrf!y04`3%T<#}K2po-{O+pJ(UR4nwShGXVr5006FT{v#xVN^Z`8LgpP zG$A$sb>m%cY0mHG&cxrya%(C65*ju`=K%Eyyd3~GJr&cS_lW$KqMJVXpWasMYp{R$ z&g5ffdzT?9Y(mbo2Qcqom=u{(L~jSLUU{~PDh!O>c}|U0Pzc1l>TaySLa%%2{SY0h z)oCu`7Bty5Ztw~cz!{!Uhv?Y~c*_IzUnD!h>pI3OR~T*u zK8EP$=i~0KyAWEy_+hi)NpQ2jl6;&{~dmUdKTG3w)NY8{m*|BZ2X5lv>g3qyE-2) z$Mtn&IJ#V`^Yza{-LOzHFP^JybNR-5L-`PliaiJ-PK1O|BJotk~95-p{-2kABt6MACv=mtdB z6|S3jyS%Ir^j;sT(0JvM8sqwtb(jMZeD0`!Cw83FRJgA8+g&U0OLN|?V~o6AHf;}U zu)qG}U&mRo_%S9n9=H0@^(pG@s=BsaGGIeyDX$uXlxjCOOW-a{DUBE1$D{-{v}3@q zzT0Bo6k9ZK60yc|q%pkFDjFrEHZ;f0#CEBBo5gIBnH`_d)ib!mJoxK^E_BB3*Q^Yn z(~UM2b>qiQK9?)>Td)d|ms4CD1 zVz0>nnT@CRXW=nIPPz|WAYX$J0@8%UOuJIVDL}d{ponVR)?zvH7>n^l)pQGo2|N6igsIF zsLMv}oZ|+#VB3Sb8zy1loiT8~Ue3;@S}`lNll`BvK?Pg|=je}^&{I;tqc=Yt2a%>y zOuLP&)@>Kzt^_~!`uIN&_m|;^ZSzso4;M0Z^I^McI_E_)rQ|;Rba}GBT=w9XeGPt5 zHwJ?`wXS#neDk1p&(tT6fcZxCSVBbRa;Cis zGMmnfA893{+=M{q>0Ass6bJCsP_2N^G034f?;>j1AaiLy)KN++@kYxf)k6Y6qER{Y zA=~N8rK`T)Pnc#Kl?5vCmKWWs!`8i6G@$oooVIbqyBE}PBEgYqowcIF} z8;$7J+HSS2`|5j?$*F7NZrynh8C?n<{*i+2!&Qx>JjJpwQF4d_2y+7|6JN?VcU`;wYut7bAkZ4T+1 zOxwBEgu6kwvT zBr4ZidEj`5mAFoy4bWq{Ek^CWhHe**)oruW=yI*D7i$?fFp1bKJMJ5?2|C=1kT&X^ z1BBR7O?AP5W{!2utMmJ|L$smw7C zuy&b=o$ELRI!Z+O{Uk5eDk7KQa(Laex;<3eUCMj%jKb5mKD|4T7;I$Hu6mbX!3p%c z=<$E%Mow|hQs=LUU`gOC+Gp*ApNo|EJl?&;Lr~DE>-{F$>nutwzTC6{%uDp3d~Vn< z9@^YInMF!-p48`~vKy7!2|%*B**53uyxM$Lmvi+chvD_}sWqLJ*UoU%(ZTX8JVSJV z@4nqtY-j}cS<>6VL_C>-|KWL7zt!&u$baFczP1bYCdJQAiTL)Xp9kA!Cbq2y?Ih8{ z{C1SmP-UCy^1rIj;;OTNy0#O8h-xMw^$Cm~YTB`nWAeSeuGM^57YUW?Y8JM|h*?|9gK##b}wWh3-S{16r0Q9N);w8fDZ zn8do`dp)thdlc}@pR{M{98Y@Ft-rBuH99;UPcJ9^yl(jMEMifKV?$i7gEHvZU*A;u MKLw^Y3U1j10CNa2+W-In literal 0 HcmV?d00001 diff --git a/public/assets/application-f56a930e8b43a3cc1181ac77bbbfd62c.js b/public/assets/application-f56a930e8b43a3cc1181ac77bbbfd62c.js new file mode 100644 index 000000000..eabd68d1e --- /dev/null +++ b/public/assets/application-f56a930e8b43a3cc1181ac77bbbfd62c.js @@ -0,0 +1,28346 @@ +/* + Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com + (c) 2010-2013, Vladimir Agafonkin + (c) 2010-2011, CloudMade +*/ + + + + + +(function (window, document, undefined) { +var oldL = window.L, + L = {}; + +L.version = '0.7.3'; + +// define Leaflet for Node module pattern loaders, including Browserify +if (typeof module === 'object' && typeof module.exports === 'object') { + module.exports = L; + +// define Leaflet as an AMD module +} else if (typeof define === 'function' && define.amd) { + define(L); +} + +// define Leaflet as a global L variable, saving the original L to restore later if needed + +L.noConflict = function () { + window.L = oldL; + return this; +}; + +window.L = L; + + +/* + * L.Util contains various utility functions used throughout Leaflet code. + */ + +L.Util = { + extend: function (dest) { // (Object[, Object, ...]) -> + var sources = Array.prototype.slice.call(arguments, 1), + i, j, len, src; + + for (j = 0, len = sources.length; j < len; j++) { + src = sources[j] || {}; + for (i in src) { + if (src.hasOwnProperty(i)) { + dest[i] = src[i]; + } + } + } + return dest; + }, + + bind: function (fn, obj) { // (Function, Object) -> Function + var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null; + return function () { + return fn.apply(obj, args || arguments); + }; + }, + + stamp: (function () { + var lastId = 0, + key = '_leaflet_id'; + return function (obj) { + obj[key] = obj[key] || ++lastId; + return obj[key]; + }; + }()), + + invokeEach: function (obj, method, context) { + var i, args; + + if (typeof obj === 'object') { + args = Array.prototype.slice.call(arguments, 3); + + for (i in obj) { + method.apply(context, [i, obj[i]].concat(args)); + } + return true; + } + + return false; + }, + + limitExecByInterval: function (fn, time, context) { + var lock, execOnUnlock; + + return function wrapperFn() { + var args = arguments; + + if (lock) { + execOnUnlock = true; + return; + } + + lock = true; + + setTimeout(function () { + lock = false; + + if (execOnUnlock) { + wrapperFn.apply(context, args); + execOnUnlock = false; + } + }, time); + + fn.apply(context, args); + }; + }, + + falseFn: function () { + return false; + }, + + formatNum: function (num, digits) { + var pow = Math.pow(10, digits || 5); + return Math.round(num * pow) / pow; + }, + + trim: function (str) { + return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); + }, + + splitWords: function (str) { + return L.Util.trim(str).split(/\s+/); + }, + + setOptions: function (obj, options) { + obj.options = L.extend({}, obj.options, options); + return obj.options; + }, + + getParamString: function (obj, existingUrl, uppercase) { + var params = []; + for (var i in obj) { + params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); + } + return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); + }, + template: function (str, data) { + return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) { + var value = data[key]; + if (value === undefined) { + throw new Error('No value provided for variable ' + str); + } else if (typeof value === 'function') { + value = value(data); + } + return value; + }); + }, + + isArray: Array.isArray || function (obj) { + return (Object.prototype.toString.call(obj) === '[object Array]'); + }, + + emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' +}; + +(function () { + + // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + + function getPrefixed(name) { + var i, fn, + prefixes = ['webkit', 'moz', 'o', 'ms']; + + for (i = 0; i < prefixes.length && !fn; i++) { + fn = window[prefixes[i] + name]; + } + + return fn; + } + + var lastTime = 0; + + function timeoutDefer(fn) { + var time = +new Date(), + timeToCall = Math.max(0, 16 - (time - lastTime)); + + lastTime = time + timeToCall; + return window.setTimeout(fn, timeToCall); + } + + var requestFn = window.requestAnimationFrame || + getPrefixed('RequestAnimationFrame') || timeoutDefer; + + var cancelFn = window.cancelAnimationFrame || + getPrefixed('CancelAnimationFrame') || + getPrefixed('CancelRequestAnimationFrame') || + function (id) { window.clearTimeout(id); }; + + + L.Util.requestAnimFrame = function (fn, context, immediate, element) { + fn = L.bind(fn, context); + + if (immediate && requestFn === timeoutDefer) { + fn(); + } else { + return requestFn.call(window, fn, element); + } + }; + + L.Util.cancelAnimFrame = function (id) { + if (id) { + cancelFn.call(window, id); + } + }; + +}()); + +// shortcuts for most used utility functions +L.extend = L.Util.extend; +L.bind = L.Util.bind; +L.stamp = L.Util.stamp; +L.setOptions = L.Util.setOptions; + + +/* + * L.Class powers the OOP facilities of the library. + * Thanks to John Resig and Dean Edwards for inspiration! + */ + +L.Class = function () {}; + +L.Class.extend = function (props) { + + // extended class with the new prototype + var NewClass = function () { + + // call the constructor + if (this.initialize) { + this.initialize.apply(this, arguments); + } + + // call all constructor hooks + if (this._initHooks) { + this.callInitHooks(); + } + }; + + // instantiate class without calling constructor + var F = function () {}; + F.prototype = this.prototype; + + var proto = new F(); + proto.constructor = NewClass; + + NewClass.prototype = proto; + + //inherit parent's statics + for (var i in this) { + if (this.hasOwnProperty(i) && i !== 'prototype') { + NewClass[i] = this[i]; + } + } + + // mix static properties into the class + if (props.statics) { + L.extend(NewClass, props.statics); + delete props.statics; + } + + // mix includes into the prototype + if (props.includes) { + L.Util.extend.apply(null, [proto].concat(props.includes)); + delete props.includes; + } + + // merge options + if (props.options && proto.options) { + props.options = L.extend({}, proto.options, props.options); + } + + // mix given properties into the prototype + L.extend(proto, props); + + proto._initHooks = []; + + var parent = this; + // jshint camelcase: false + NewClass.__super__ = parent.prototype; + + // add method for calling all hooks + proto.callInitHooks = function () { + + if (this._initHooksCalled) { return; } + + if (parent.prototype.callInitHooks) { + parent.prototype.callInitHooks.call(this); + } + + this._initHooksCalled = true; + + for (var i = 0, len = proto._initHooks.length; i < len; i++) { + proto._initHooks[i].call(this); + } + }; + + return NewClass; +}; + + +// method for adding properties to prototype +L.Class.include = function (props) { + L.extend(this.prototype, props); +}; + +// merge new default options to the Class +L.Class.mergeOptions = function (options) { + L.extend(this.prototype.options, options); +}; + +// add a constructor hook +L.Class.addInitHook = function (fn) { // (Function) || (String, args...) + var args = Array.prototype.slice.call(arguments, 1); + + var init = typeof fn === 'function' ? fn : function () { + this[fn].apply(this, args); + }; + + this.prototype._initHooks = this.prototype._initHooks || []; + this.prototype._initHooks.push(init); +}; + + +/* + * L.Mixin.Events is used to add custom events functionality to Leaflet classes. + */ + +var eventsKey = '_leaflet_events'; + +L.Mixin = {}; + +L.Mixin.Events = { + + addEventListener: function (types, fn, context) { // (String, Function[, Object]) or (Object[, Object]) + + // types can be a map of types/handlers + if (L.Util.invokeEach(types, this.addEventListener, this, fn, context)) { return this; } + + var events = this[eventsKey] = this[eventsKey] || {}, + contextId = context && context !== this && L.stamp(context), + i, len, event, type, indexKey, indexLenKey, typeIndex; + + // types can be a string of space-separated words + types = L.Util.splitWords(types); + + for (i = 0, len = types.length; i < len; i++) { + event = { + action: fn, + context: context || this + }; + type = types[i]; + + if (contextId) { + // store listeners of a particular context in a separate hash (if it has an id) + // gives a major performance boost when removing thousands of map layers + + indexKey = type + '_idx'; + indexLenKey = indexKey + '_len'; + + typeIndex = events[indexKey] = events[indexKey] || {}; + + if (!typeIndex[contextId]) { + typeIndex[contextId] = []; + + // keep track of the number of keys in the index to quickly check if it's empty + events[indexLenKey] = (events[indexLenKey] || 0) + 1; + } + + typeIndex[contextId].push(event); + + + } else { + events[type] = events[type] || []; + events[type].push(event); + } + } + + return this; + }, + + hasEventListeners: function (type) { // (String) -> Boolean + var events = this[eventsKey]; + return !!events && ((type in events && events[type].length > 0) || + (type + '_idx' in events && events[type + '_idx_len'] > 0)); + }, + + removeEventListener: function (types, fn, context) { // ([String, Function, Object]) or (Object[, Object]) + + if (!this[eventsKey]) { + return this; + } + + if (!types) { + return this.clearAllEventListeners(); + } + + if (L.Util.invokeEach(types, this.removeEventListener, this, fn, context)) { return this; } + + var events = this[eventsKey], + contextId = context && context !== this && L.stamp(context), + i, len, type, listeners, j, indexKey, indexLenKey, typeIndex, removed; + + types = L.Util.splitWords(types); + + for (i = 0, len = types.length; i < len; i++) { + type = types[i]; + indexKey = type + '_idx'; + indexLenKey = indexKey + '_len'; + + typeIndex = events[indexKey]; + + if (!fn) { + // clear all listeners for a type if function isn't specified + delete events[type]; + delete events[indexKey]; + delete events[indexLenKey]; + + } else { + listeners = contextId && typeIndex ? typeIndex[contextId] : events[type]; + + if (listeners) { + for (j = listeners.length - 1; j >= 0; j--) { + if ((listeners[j].action === fn) && (!context || (listeners[j].context === context))) { + removed = listeners.splice(j, 1); + // set the old action to a no-op, because it is possible + // that the listener is being iterated over as part of a dispatch + removed[0].action = L.Util.falseFn; + } + } + + if (context && typeIndex && (listeners.length === 0)) { + delete typeIndex[contextId]; + events[indexLenKey]--; + } + } + } + } + + return this; + }, + + clearAllEventListeners: function () { + delete this[eventsKey]; + return this; + }, + + fireEvent: function (type, data) { // (String[, Object]) + if (!this.hasEventListeners(type)) { + return this; + } + + var event = L.Util.extend({}, data, { type: type, target: this }); + + var events = this[eventsKey], + listeners, i, len, typeIndex, contextId; + + if (events[type]) { + // make sure adding/removing listeners inside other listeners won't cause infinite loop + listeners = events[type].slice(); + + for (i = 0, len = listeners.length; i < len; i++) { + listeners[i].action.call(listeners[i].context, event); + } + } + + // fire event for the context-indexed listeners as well + typeIndex = events[type + '_idx']; + + for (contextId in typeIndex) { + listeners = typeIndex[contextId].slice(); + + if (listeners) { + for (i = 0, len = listeners.length; i < len; i++) { + listeners[i].action.call(listeners[i].context, event); + } + } + } + + return this; + }, + + addOneTimeEventListener: function (types, fn, context) { + + if (L.Util.invokeEach(types, this.addOneTimeEventListener, this, fn, context)) { return this; } + + var handler = L.bind(function () { + this + .removeEventListener(types, fn, context) + .removeEventListener(types, handler, context); + }, this); + + return this + .addEventListener(types, fn, context) + .addEventListener(types, handler, context); + } +}; + +L.Mixin.Events.on = L.Mixin.Events.addEventListener; +L.Mixin.Events.off = L.Mixin.Events.removeEventListener; +L.Mixin.Events.once = L.Mixin.Events.addOneTimeEventListener; +L.Mixin.Events.fire = L.Mixin.Events.fireEvent; + + +/* + * L.Browser handles different browser and feature detections for internal Leaflet use. + */ + +(function () { + + var ie = 'ActiveXObject' in window, + ielt9 = ie && !document.addEventListener, + + // terrible browser detection to work around Safari / iOS / Android browser bugs + ua = navigator.userAgent.toLowerCase(), + webkit = ua.indexOf('webkit') !== -1, + chrome = ua.indexOf('chrome') !== -1, + phantomjs = ua.indexOf('phantom') !== -1, + android = ua.indexOf('android') !== -1, + android23 = ua.search('android [23]') !== -1, + gecko = ua.indexOf('gecko') !== -1, + + mobile = typeof orientation !== undefined + '', + msPointer = window.navigator && window.navigator.msPointerEnabled && + window.navigator.msMaxTouchPoints && !window.PointerEvent, + pointer = (window.PointerEvent && window.navigator.pointerEnabled && window.navigator.maxTouchPoints) || + msPointer, + retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) || + ('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') && + window.matchMedia('(min-resolution:144dpi)').matches), + + doc = document.documentElement, + ie3d = ie && ('transition' in doc.style), + webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23, + gecko3d = 'MozPerspective' in doc.style, + opera3d = 'OTransition' in doc.style, + any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs; + + + // PhantomJS has 'ontouchstart' in document.documentElement, but doesn't actually support touch. + // https://github.com/Leaflet/Leaflet/pull/1434#issuecomment-13843151 + + var touch = !window.L_NO_TOUCH && !phantomjs && (function () { + + var startName = 'ontouchstart'; + + // IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.Pointer) or WebKit, etc. + if (pointer || (startName in doc)) { + return true; + } + + // Firefox/Gecko + var div = document.createElement('div'), + supported = false; + + if (!div.setAttribute) { + return false; + } + div.setAttribute(startName, 'return;'); + + if (typeof div[startName] === 'function') { + supported = true; + } + + div.removeAttribute(startName); + div = null; + + return supported; + }()); + + + L.Browser = { + ie: ie, + ielt9: ielt9, + webkit: webkit, + gecko: gecko && !webkit && !window.opera && !ie, + + android: android, + android23: android23, + + chrome: chrome, + + ie3d: ie3d, + webkit3d: webkit3d, + gecko3d: gecko3d, + opera3d: opera3d, + any3d: any3d, + + mobile: mobile, + mobileWebkit: mobile && webkit, + mobileWebkit3d: mobile && webkit3d, + mobileOpera: mobile && window.opera, + + touch: touch, + msPointer: msPointer, + pointer: pointer, + + retina: retina + }; + +}()); + + +/* + * L.Point represents a point with x and y coordinates. + */ + +L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) { + this.x = (round ? Math.round(x) : x); + this.y = (round ? Math.round(y) : y); +}; + +L.Point.prototype = { + + clone: function () { + return new L.Point(this.x, this.y); + }, + + // non-destructive, returns a new point + add: function (point) { + return this.clone()._add(L.point(point)); + }, + + // destructive, used directly for performance in situations where it's safe to modify existing point + _add: function (point) { + this.x += point.x; + this.y += point.y; + return this; + }, + + subtract: function (point) { + return this.clone()._subtract(L.point(point)); + }, + + _subtract: function (point) { + this.x -= point.x; + this.y -= point.y; + return this; + }, + + divideBy: function (num) { + return this.clone()._divideBy(num); + }, + + _divideBy: function (num) { + this.x /= num; + this.y /= num; + return this; + }, + + multiplyBy: function (num) { + return this.clone()._multiplyBy(num); + }, + + _multiplyBy: function (num) { + this.x *= num; + this.y *= num; + return this; + }, + + round: function () { + return this.clone()._round(); + }, + + _round: function () { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + return this; + }, + + floor: function () { + return this.clone()._floor(); + }, + + _floor: function () { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + return this; + }, + + distanceTo: function (point) { + point = L.point(point); + + var x = point.x - this.x, + y = point.y - this.y; + + return Math.sqrt(x * x + y * y); + }, + + equals: function (point) { + point = L.point(point); + + return point.x === this.x && + point.y === this.y; + }, + + contains: function (point) { + point = L.point(point); + + return Math.abs(point.x) <= Math.abs(this.x) && + Math.abs(point.y) <= Math.abs(this.y); + }, + + toString: function () { + return 'Point(' + + L.Util.formatNum(this.x) + ', ' + + L.Util.formatNum(this.y) + ')'; + } +}; + +L.point = function (x, y, round) { + if (x instanceof L.Point) { + return x; + } + if (L.Util.isArray(x)) { + return new L.Point(x[0], x[1]); + } + if (x === undefined || x === null) { + return x; + } + return new L.Point(x, y, round); +}; + + +/* + * L.Bounds represents a rectangular area on the screen in pixel coordinates. + */ + +L.Bounds = function (a, b) { //(Point, Point) or Point[] + if (!a) { return; } + + var points = b ? [a, b] : a; + + for (var i = 0, len = points.length; i < len; i++) { + this.extend(points[i]); + } +}; + +L.Bounds.prototype = { + // extend the bounds to contain the given point + extend: function (point) { // (Point) + point = L.point(point); + + if (!this.min && !this.max) { + this.min = point.clone(); + this.max = point.clone(); + } else { + this.min.x = Math.min(point.x, this.min.x); + this.max.x = Math.max(point.x, this.max.x); + this.min.y = Math.min(point.y, this.min.y); + this.max.y = Math.max(point.y, this.max.y); + } + return this; + }, + + getCenter: function (round) { // (Boolean) -> Point + return new L.Point( + (this.min.x + this.max.x) / 2, + (this.min.y + this.max.y) / 2, round); + }, + + getBottomLeft: function () { // -> Point + return new L.Point(this.min.x, this.max.y); + }, + + getTopRight: function () { // -> Point + return new L.Point(this.max.x, this.min.y); + }, + + getSize: function () { + return this.max.subtract(this.min); + }, + + contains: function (obj) { // (Bounds) or (Point) -> Boolean + var min, max; + + if (typeof obj[0] === 'number' || obj instanceof L.Point) { + obj = L.point(obj); + } else { + obj = L.bounds(obj); + } + + if (obj instanceof L.Bounds) { + min = obj.min; + max = obj.max; + } else { + min = max = obj; + } + + return (min.x >= this.min.x) && + (max.x <= this.max.x) && + (min.y >= this.min.y) && + (max.y <= this.max.y); + }, + + intersects: function (bounds) { // (Bounds) -> Boolean + bounds = L.bounds(bounds); + + var min = this.min, + max = this.max, + min2 = bounds.min, + max2 = bounds.max, + xIntersects = (max2.x >= min.x) && (min2.x <= max.x), + yIntersects = (max2.y >= min.y) && (min2.y <= max.y); + + return xIntersects && yIntersects; + }, + + isValid: function () { + return !!(this.min && this.max); + } +}; + +L.bounds = function (a, b) { // (Bounds) or (Point, Point) or (Point[]) + if (!a || a instanceof L.Bounds) { + return a; + } + return new L.Bounds(a, b); +}; + + +/* + * L.Transformation is an utility class to perform simple point transformations through a 2d-matrix. + */ + +L.Transformation = function (a, b, c, d) { + this._a = a; + this._b = b; + this._c = c; + this._d = d; +}; + +L.Transformation.prototype = { + transform: function (point, scale) { // (Point, Number) -> Point + return this._transform(point.clone(), scale); + }, + + // destructive transform (faster) + _transform: function (point, scale) { + scale = scale || 1; + point.x = scale * (this._a * point.x + this._b); + point.y = scale * (this._c * point.y + this._d); + return point; + }, + + untransform: function (point, scale) { + scale = scale || 1; + return new L.Point( + (point.x / scale - this._b) / this._a, + (point.y / scale - this._d) / this._c); + } +}; + + +/* + * L.DomUtil contains various utility functions for working with DOM. + */ + +L.DomUtil = { + get: function (id) { + return (typeof id === 'string' ? document.getElementById(id) : id); + }, + + getStyle: function (el, style) { + + var value = el.style[style]; + + if (!value && el.currentStyle) { + value = el.currentStyle[style]; + } + + if ((!value || value === 'auto') && document.defaultView) { + var css = document.defaultView.getComputedStyle(el, null); + value = css ? css[style] : null; + } + + return value === 'auto' ? null : value; + }, + + getViewportOffset: function (element) { + + var top = 0, + left = 0, + el = element, + docBody = document.body, + docEl = document.documentElement, + pos; + + do { + top += el.offsetTop || 0; + left += el.offsetLeft || 0; + + //add borders + top += parseInt(L.DomUtil.getStyle(el, 'borderTopWidth'), 10) || 0; + left += parseInt(L.DomUtil.getStyle(el, 'borderLeftWidth'), 10) || 0; + + pos = L.DomUtil.getStyle(el, 'position'); + + if (el.offsetParent === docBody && pos === 'absolute') { break; } + + if (pos === 'fixed') { + top += docBody.scrollTop || docEl.scrollTop || 0; + left += docBody.scrollLeft || docEl.scrollLeft || 0; + break; + } + + if (pos === 'relative' && !el.offsetLeft) { + var width = L.DomUtil.getStyle(el, 'width'), + maxWidth = L.DomUtil.getStyle(el, 'max-width'), + r = el.getBoundingClientRect(); + + if (width !== 'none' || maxWidth !== 'none') { + left += r.left + el.clientLeft; + } + + //calculate full y offset since we're breaking out of the loop + top += r.top + (docBody.scrollTop || docEl.scrollTop || 0); + + break; + } + + el = el.offsetParent; + + } while (el); + + el = element; + + do { + if (el === docBody) { break; } + + top -= el.scrollTop || 0; + left -= el.scrollLeft || 0; + + el = el.parentNode; + } while (el); + + return new L.Point(left, top); + }, + + documentIsLtr: function () { + if (!L.DomUtil._docIsLtrCached) { + L.DomUtil._docIsLtrCached = true; + L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === 'ltr'; + } + return L.DomUtil._docIsLtr; + }, + + create: function (tagName, className, container) { + + var el = document.createElement(tagName); + el.className = className; + + if (container) { + container.appendChild(el); + } + + return el; + }, + + hasClass: function (el, name) { + if (el.classList !== undefined) { + return el.classList.contains(name); + } + var className = L.DomUtil._getClass(el); + return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); + }, + + addClass: function (el, name) { + if (el.classList !== undefined) { + var classes = L.Util.splitWords(name); + for (var i = 0, len = classes.length; i < len; i++) { + el.classList.add(classes[i]); + } + } else if (!L.DomUtil.hasClass(el, name)) { + var className = L.DomUtil._getClass(el); + L.DomUtil._setClass(el, (className ? className + ' ' : '') + name); + } + }, + + removeClass: function (el, name) { + if (el.classList !== undefined) { + el.classList.remove(name); + } else { + L.DomUtil._setClass(el, L.Util.trim((' ' + L.DomUtil._getClass(el) + ' ').replace(' ' + name + ' ', ' '))); + } + }, + + _setClass: function (el, name) { + if (el.className.baseVal === undefined) { + el.className = name; + } else { + // in case of SVG element + el.className.baseVal = name; + } + }, + + _getClass: function (el) { + return el.className.baseVal === undefined ? el.className : el.className.baseVal; + }, + + setOpacity: function (el, value) { + + if ('opacity' in el.style) { + el.style.opacity = value; + + } else if ('filter' in el.style) { + + var filter = false, + filterName = 'DXImageTransform.Microsoft.Alpha'; + + // filters collection throws an error if we try to retrieve a filter that doesn't exist + try { + filter = el.filters.item(filterName); + } catch (e) { + // don't set opacity to 1 if we haven't already set an opacity, + // it isn't needed and breaks transparent pngs. + if (value === 1) { return; } + } + + value = Math.round(value * 100); + + if (filter) { + filter.Enabled = (value !== 100); + filter.Opacity = value; + } else { + el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; + } + } + }, + + testProp: function (props) { + + var style = document.documentElement.style; + + for (var i = 0; i < props.length; i++) { + if (props[i] in style) { + return props[i]; + } + } + return false; + }, + + getTranslateString: function (point) { + // on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate + // makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care + // (same speed either way), Opera 12 doesn't support translate3d + + var is3d = L.Browser.webkit3d, + open = 'translate' + (is3d ? '3d' : '') + '(', + close = (is3d ? ',0' : '') + ')'; + + return open + point.x + 'px,' + point.y + 'px' + close; + }, + + getScaleString: function (scale, origin) { + + var preTranslateStr = L.DomUtil.getTranslateString(origin.add(origin.multiplyBy(-1 * scale))), + scaleStr = ' scale(' + scale + ') '; + + return preTranslateStr + scaleStr; + }, + + setPosition: function (el, point, disable3D) { // (HTMLElement, Point[, Boolean]) + + // jshint camelcase: false + el._leaflet_pos = point; + + if (!disable3D && L.Browser.any3d) { + el.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(point); + } else { + el.style.left = point.x + 'px'; + el.style.top = point.y + 'px'; + } + }, + + getPosition: function (el) { + // this method is only used for elements previously positioned using setPosition, + // so it's safe to cache the position for performance + + // jshint camelcase: false + return el._leaflet_pos; + } +}; + + +// prefix style property names + +L.DomUtil.TRANSFORM = L.DomUtil.testProp( + ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']); + +// webkitTransition comes first because some browser versions that drop vendor prefix don't do +// the same for the transitionend event, in particular the Android 4.1 stock browser + +L.DomUtil.TRANSITION = L.DomUtil.testProp( + ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); + +L.DomUtil.TRANSITION_END = + L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ? + L.DomUtil.TRANSITION + 'End' : 'transitionend'; + +(function () { + if ('onselectstart' in document) { + L.extend(L.DomUtil, { + disableTextSelection: function () { + L.DomEvent.on(window, 'selectstart', L.DomEvent.preventDefault); + }, + + enableTextSelection: function () { + L.DomEvent.off(window, 'selectstart', L.DomEvent.preventDefault); + } + }); + } else { + var userSelectProperty = L.DomUtil.testProp( + ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); + + L.extend(L.DomUtil, { + disableTextSelection: function () { + if (userSelectProperty) { + var style = document.documentElement.style; + this._userSelect = style[userSelectProperty]; + style[userSelectProperty] = 'none'; + } + }, + + enableTextSelection: function () { + if (userSelectProperty) { + document.documentElement.style[userSelectProperty] = this._userSelect; + delete this._userSelect; + } + } + }); + } + + L.extend(L.DomUtil, { + disableImageDrag: function () { + L.DomEvent.on(window, 'dragstart', L.DomEvent.preventDefault); + }, + + enableImageDrag: function () { + L.DomEvent.off(window, 'dragstart', L.DomEvent.preventDefault); + } + }); +})(); + + +/* + * L.LatLng represents a geographical point with latitude and longitude coordinates. + */ + +L.LatLng = function (lat, lng, alt) { // (Number, Number, Number) + lat = parseFloat(lat); + lng = parseFloat(lng); + + if (isNaN(lat) || isNaN(lng)) { + throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); + } + + this.lat = lat; + this.lng = lng; + + if (alt !== undefined) { + this.alt = parseFloat(alt); + } +}; + +L.extend(L.LatLng, { + DEG_TO_RAD: Math.PI / 180, + RAD_TO_DEG: 180 / Math.PI, + MAX_MARGIN: 1.0E-9 // max margin of error for the "equals" check +}); + +L.LatLng.prototype = { + equals: function (obj) { // (LatLng) -> Boolean + if (!obj) { return false; } + + obj = L.latLng(obj); + + var margin = Math.max( + Math.abs(this.lat - obj.lat), + Math.abs(this.lng - obj.lng)); + + return margin <= L.LatLng.MAX_MARGIN; + }, + + toString: function (precision) { // (Number) -> String + return 'LatLng(' + + L.Util.formatNum(this.lat, precision) + ', ' + + L.Util.formatNum(this.lng, precision) + ')'; + }, + + // Haversine distance formula, see http://en.wikipedia.org/wiki/Haversine_formula + // TODO move to projection code, LatLng shouldn't know about Earth + distanceTo: function (other) { // (LatLng) -> Number + other = L.latLng(other); + + var R = 6378137, // earth radius in meters + d2r = L.LatLng.DEG_TO_RAD, + dLat = (other.lat - this.lat) * d2r, + dLon = (other.lng - this.lng) * d2r, + lat1 = this.lat * d2r, + lat2 = other.lat * d2r, + sin1 = Math.sin(dLat / 2), + sin2 = Math.sin(dLon / 2); + + var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2); + + return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + }, + + wrap: function (a, b) { // (Number, Number) -> LatLng + var lng = this.lng; + + a = a || -180; + b = b || 180; + + lng = (lng + b) % (b - a) + (lng < a || lng === b ? b : a); + + return new L.LatLng(this.lat, lng); + } +}; + +L.latLng = function (a, b) { // (LatLng) or ([Number, Number]) or (Number, Number) + if (a instanceof L.LatLng) { + return a; + } + if (L.Util.isArray(a)) { + if (typeof a[0] === 'number' || typeof a[0] === 'string') { + return new L.LatLng(a[0], a[1], a[2]); + } else { + return null; + } + } + if (a === undefined || a === null) { + return a; + } + if (typeof a === 'object' && 'lat' in a) { + return new L.LatLng(a.lat, 'lng' in a ? a.lng : a.lon); + } + if (b === undefined) { + return null; + } + return new L.LatLng(a, b); +}; + + + +/* + * L.LatLngBounds represents a rectangular area on the map in geographical coordinates. + */ + +L.LatLngBounds = function (southWest, northEast) { // (LatLng, LatLng) or (LatLng[]) + if (!southWest) { return; } + + var latlngs = northEast ? [southWest, northEast] : southWest; + + for (var i = 0, len = latlngs.length; i < len; i++) { + this.extend(latlngs[i]); + } +}; + +L.LatLngBounds.prototype = { + // extend the bounds to contain the given point or bounds + extend: function (obj) { // (LatLng) or (LatLngBounds) + if (!obj) { return this; } + + var latLng = L.latLng(obj); + if (latLng !== null) { + obj = latLng; + } else { + obj = L.latLngBounds(obj); + } + + if (obj instanceof L.LatLng) { + if (!this._southWest && !this._northEast) { + this._southWest = new L.LatLng(obj.lat, obj.lng); + this._northEast = new L.LatLng(obj.lat, obj.lng); + } else { + this._southWest.lat = Math.min(obj.lat, this._southWest.lat); + this._southWest.lng = Math.min(obj.lng, this._southWest.lng); + + this._northEast.lat = Math.max(obj.lat, this._northEast.lat); + this._northEast.lng = Math.max(obj.lng, this._northEast.lng); + } + } else if (obj instanceof L.LatLngBounds) { + this.extend(obj._southWest); + this.extend(obj._northEast); + } + return this; + }, + + // extend the bounds by a percentage + pad: function (bufferRatio) { // (Number) -> LatLngBounds + var sw = this._southWest, + ne = this._northEast, + heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, + widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio; + + return new L.LatLngBounds( + new L.LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), + new L.LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)); + }, + + getCenter: function () { // -> LatLng + return new L.LatLng( + (this._southWest.lat + this._northEast.lat) / 2, + (this._southWest.lng + this._northEast.lng) / 2); + }, + + getSouthWest: function () { + return this._southWest; + }, + + getNorthEast: function () { + return this._northEast; + }, + + getNorthWest: function () { + return new L.LatLng(this.getNorth(), this.getWest()); + }, + + getSouthEast: function () { + return new L.LatLng(this.getSouth(), this.getEast()); + }, + + getWest: function () { + return this._southWest.lng; + }, + + getSouth: function () { + return this._southWest.lat; + }, + + getEast: function () { + return this._northEast.lng; + }, + + getNorth: function () { + return this._northEast.lat; + }, + + contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean + if (typeof obj[0] === 'number' || obj instanceof L.LatLng) { + obj = L.latLng(obj); + } else { + obj = L.latLngBounds(obj); + } + + var sw = this._southWest, + ne = this._northEast, + sw2, ne2; + + if (obj instanceof L.LatLngBounds) { + sw2 = obj.getSouthWest(); + ne2 = obj.getNorthEast(); + } else { + sw2 = ne2 = obj; + } + + return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) && + (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng); + }, + + intersects: function (bounds) { // (LatLngBounds) + bounds = L.latLngBounds(bounds); + + var sw = this._southWest, + ne = this._northEast, + sw2 = bounds.getSouthWest(), + ne2 = bounds.getNorthEast(), + + latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat), + lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng); + + return latIntersects && lngIntersects; + }, + + toBBoxString: function () { + return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(','); + }, + + equals: function (bounds) { // (LatLngBounds) + if (!bounds) { return false; } + + bounds = L.latLngBounds(bounds); + + return this._southWest.equals(bounds.getSouthWest()) && + this._northEast.equals(bounds.getNorthEast()); + }, + + isValid: function () { + return !!(this._southWest && this._northEast); + } +}; + +//TODO International date line? + +L.latLngBounds = function (a, b) { // (LatLngBounds) or (LatLng, LatLng) + if (!a || a instanceof L.LatLngBounds) { + return a; + } + return new L.LatLngBounds(a, b); +}; + + +/* + * L.Projection contains various geographical projections used by CRS classes. + */ + +L.Projection = {}; + + +/* + * Spherical Mercator is the most popular map projection, used by EPSG:3857 CRS used by default. + */ + +L.Projection.SphericalMercator = { + MAX_LATITUDE: 85.0511287798, + + project: function (latlng) { // (LatLng) -> Point + var d = L.LatLng.DEG_TO_RAD, + max = this.MAX_LATITUDE, + lat = Math.max(Math.min(max, latlng.lat), -max), + x = latlng.lng * d, + y = lat * d; + + y = Math.log(Math.tan((Math.PI / 4) + (y / 2))); + + return new L.Point(x, y); + }, + + unproject: function (point) { // (Point, Boolean) -> LatLng + var d = L.LatLng.RAD_TO_DEG, + lng = point.x * d, + lat = (2 * Math.atan(Math.exp(point.y)) - (Math.PI / 2)) * d; + + return new L.LatLng(lat, lng); + } +}; + + +/* + * Simple equirectangular (Plate Carree) projection, used by CRS like EPSG:4326 and Simple. + */ + +L.Projection.LonLat = { + project: function (latlng) { + return new L.Point(latlng.lng, latlng.lat); + }, + + unproject: function (point) { + return new L.LatLng(point.y, point.x); + } +}; + + +/* + * L.CRS is a base object for all defined CRS (Coordinate Reference Systems) in Leaflet. + */ + +L.CRS = { + latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point + var projectedPoint = this.projection.project(latlng), + scale = this.scale(zoom); + + return this.transformation._transform(projectedPoint, scale); + }, + + pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng + var scale = this.scale(zoom), + untransformedPoint = this.transformation.untransform(point, scale); + + return this.projection.unproject(untransformedPoint); + }, + + project: function (latlng) { + return this.projection.project(latlng); + }, + + scale: function (zoom) { + return 256 * Math.pow(2, zoom); + }, + + getSize: function (zoom) { + var s = this.scale(zoom); + return L.point(s, s); + } +}; + + +/* + * A simple CRS that can be used for flat non-Earth maps like panoramas or game maps. + */ + +L.CRS.Simple = L.extend({}, L.CRS, { + projection: L.Projection.LonLat, + transformation: new L.Transformation(1, 0, -1, 0), + + scale: function (zoom) { + return Math.pow(2, zoom); + } +}); + + +/* + * L.CRS.EPSG3857 (Spherical Mercator) is the most common CRS for web mapping + * and is used by Leaflet by default. + */ + +L.CRS.EPSG3857 = L.extend({}, L.CRS, { + code: 'EPSG:3857', + + projection: L.Projection.SphericalMercator, + transformation: new L.Transformation(0.5 / Math.PI, 0.5, -0.5 / Math.PI, 0.5), + + project: function (latlng) { // (LatLng) -> Point + var projectedPoint = this.projection.project(latlng), + earthRadius = 6378137; + return projectedPoint.multiplyBy(earthRadius); + } +}); + +L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, { + code: 'EPSG:900913' +}); + + +/* + * L.CRS.EPSG4326 is a CRS popular among advanced GIS specialists. + */ + +L.CRS.EPSG4326 = L.extend({}, L.CRS, { + code: 'EPSG:4326', + + projection: L.Projection.LonLat, + transformation: new L.Transformation(1 / 360, 0.5, -1 / 360, 0.5) +}); + + +/* + * L.Map is the central class of the API - it is used to create a map. + */ + +L.Map = L.Class.extend({ + + includes: L.Mixin.Events, + + options: { + crs: L.CRS.EPSG3857, + + /* + center: LatLng, + zoom: Number, + layers: Array, + */ + + fadeAnimation: L.DomUtil.TRANSITION && !L.Browser.android23, + trackResize: true, + markerZoomAnimation: L.DomUtil.TRANSITION && L.Browser.any3d + }, + + initialize: function (id, options) { // (HTMLElement or String, Object) + options = L.setOptions(this, options); + + + this._initContainer(id); + this._initLayout(); + + // hack for https://github.com/Leaflet/Leaflet/issues/1980 + this._onResize = L.bind(this._onResize, this); + + this._initEvents(); + + if (options.maxBounds) { + this.setMaxBounds(options.maxBounds); + } + + if (options.center && options.zoom !== undefined) { + this.setView(L.latLng(options.center), options.zoom, {reset: true}); + } + + this._handlers = []; + + this._layers = {}; + this._zoomBoundLayers = {}; + this._tileLayersNum = 0; + + this.callInitHooks(); + + this._addLayers(options.layers); + }, + + + // public methods that modify map state + + // replaced by animation-powered implementation in Map.PanAnimation.js + setView: function (center, zoom) { + zoom = zoom === undefined ? this.getZoom() : zoom; + this._resetView(L.latLng(center), this._limitZoom(zoom)); + return this; + }, + + setZoom: function (zoom, options) { + if (!this._loaded) { + this._zoom = this._limitZoom(zoom); + return this; + } + return this.setView(this.getCenter(), zoom, {zoom: options}); + }, + + zoomIn: function (delta, options) { + return this.setZoom(this._zoom + (delta || 1), options); + }, + + zoomOut: function (delta, options) { + return this.setZoom(this._zoom - (delta || 1), options); + }, + + setZoomAround: function (latlng, zoom, options) { + var scale = this.getZoomScale(zoom), + viewHalf = this.getSize().divideBy(2), + containerPoint = latlng instanceof L.Point ? latlng : this.latLngToContainerPoint(latlng), + + centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale), + newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset)); + + return this.setView(newCenter, zoom, {zoom: options}); + }, + + fitBounds: function (bounds, options) { + + options = options || {}; + bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds); + + var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]), + paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]), + + zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR)), + paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), + + swPoint = this.project(bounds.getSouthWest(), zoom), + nePoint = this.project(bounds.getNorthEast(), zoom), + center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom); + + zoom = options && options.maxZoom ? Math.min(options.maxZoom, zoom) : zoom; + + return this.setView(center, zoom, options); + }, + + fitWorld: function (options) { + return this.fitBounds([[-90, -180], [90, 180]], options); + }, + + panTo: function (center, options) { // (LatLng) + return this.setView(center, this._zoom, {pan: options}); + }, + + panBy: function (offset) { // (Point) + // replaced with animated panBy in Map.PanAnimation.js + this.fire('movestart'); + + this._rawPanBy(L.point(offset)); + + this.fire('move'); + return this.fire('moveend'); + }, + + setMaxBounds: function (bounds) { + bounds = L.latLngBounds(bounds); + + this.options.maxBounds = bounds; + + if (!bounds) { + return this.off('moveend', this._panInsideMaxBounds, this); + } + + if (this._loaded) { + this._panInsideMaxBounds(); + } + + return this.on('moveend', this._panInsideMaxBounds, this); + }, + + panInsideBounds: function (bounds, options) { + var center = this.getCenter(), + newCenter = this._limitCenter(center, this._zoom, bounds); + + if (center.equals(newCenter)) { return this; } + + return this.panTo(newCenter, options); + }, + + addLayer: function (layer) { + // TODO method is too big, refactor + + var id = L.stamp(layer); + + if (this._layers[id]) { return this; } + + this._layers[id] = layer; + + // TODO getMaxZoom, getMinZoom in ILayer (instead of options) + if (layer.options && (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom))) { + this._zoomBoundLayers[id] = layer; + this._updateZoomLevels(); + } + + // TODO looks ugly, refactor!!! + if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { + this._tileLayersNum++; + this._tileLayersToLoad++; + layer.on('load', this._onTileLayerLoad, this); + } + + if (this._loaded) { + this._layerAdd(layer); + } + + return this; + }, + + removeLayer: function (layer) { + var id = L.stamp(layer); + + if (!this._layers[id]) { return this; } + + if (this._loaded) { + layer.onRemove(this); + } + + delete this._layers[id]; + + if (this._loaded) { + this.fire('layerremove', {layer: layer}); + } + + if (this._zoomBoundLayers[id]) { + delete this._zoomBoundLayers[id]; + this._updateZoomLevels(); + } + + // TODO looks ugly, refactor + if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { + this._tileLayersNum--; + this._tileLayersToLoad--; + layer.off('load', this._onTileLayerLoad, this); + } + + return this; + }, + + hasLayer: function (layer) { + if (!layer) { return false; } + + return (L.stamp(layer) in this._layers); + }, + + eachLayer: function (method, context) { + for (var i in this._layers) { + method.call(context, this._layers[i]); + } + return this; + }, + + invalidateSize: function (options) { + if (!this._loaded) { return this; } + + options = L.extend({ + animate: false, + pan: true + }, options === true ? {animate: true} : options); + + var oldSize = this.getSize(); + this._sizeChanged = true; + this._initialCenter = null; + + var newSize = this.getSize(), + oldCenter = oldSize.divideBy(2).round(), + newCenter = newSize.divideBy(2).round(), + offset = oldCenter.subtract(newCenter); + + if (!offset.x && !offset.y) { return this; } + + if (options.animate && options.pan) { + this.panBy(offset); + + } else { + if (options.pan) { + this._rawPanBy(offset); + } + + this.fire('move'); + + if (options.debounceMoveend) { + clearTimeout(this._sizeTimer); + this._sizeTimer = setTimeout(L.bind(this.fire, this, 'moveend'), 200); + } else { + this.fire('moveend'); + } + } + + return this.fire('resize', { + oldSize: oldSize, + newSize: newSize + }); + }, + + // TODO handler.addTo + addHandler: function (name, HandlerClass) { + if (!HandlerClass) { return this; } + + var handler = this[name] = new HandlerClass(this); + + this._handlers.push(handler); + + if (this.options[name]) { + handler.enable(); + } + + return this; + }, + + remove: function () { + if (this._loaded) { + this.fire('unload'); + } + + this._initEvents('off'); + + try { + // throws error in IE6-8 + delete this._container._leaflet; + } catch (e) { + this._container._leaflet = undefined; + } + + this._clearPanes(); + if (this._clearControlPos) { + this._clearControlPos(); + } + + this._clearHandlers(); + + return this; + }, + + + // public methods for getting map state + + getCenter: function () { // (Boolean) -> LatLng + this._checkIfLoaded(); + + if (this._initialCenter && !this._moved()) { + return this._initialCenter; + } + return this.layerPointToLatLng(this._getCenterLayerPoint()); + }, + + getZoom: function () { + return this._zoom; + }, + + getBounds: function () { + var bounds = this.getPixelBounds(), + sw = this.unproject(bounds.getBottomLeft()), + ne = this.unproject(bounds.getTopRight()); + + return new L.LatLngBounds(sw, ne); + }, + + getMinZoom: function () { + return this.options.minZoom === undefined ? + (this._layersMinZoom === undefined ? 0 : this._layersMinZoom) : + this.options.minZoom; + }, + + getMaxZoom: function () { + return this.options.maxZoom === undefined ? + (this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) : + this.options.maxZoom; + }, + + getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number + bounds = L.latLngBounds(bounds); + + var zoom = this.getMinZoom() - (inside ? 1 : 0), + maxZoom = this.getMaxZoom(), + size = this.getSize(), + + nw = bounds.getNorthWest(), + se = bounds.getSouthEast(), + + zoomNotFound = true, + boundsSize; + + padding = L.point(padding || [0, 0]); + + do { + zoom++; + boundsSize = this.project(se, zoom).subtract(this.project(nw, zoom)).add(padding); + zoomNotFound = !inside ? size.contains(boundsSize) : boundsSize.x < size.x || boundsSize.y < size.y; + + } while (zoomNotFound && zoom <= maxZoom); + + if (zoomNotFound && inside) { + return null; + } + + return inside ? zoom : zoom - 1; + }, + + getSize: function () { + if (!this._size || this._sizeChanged) { + this._size = new L.Point( + this._container.clientWidth, + this._container.clientHeight); + + this._sizeChanged = false; + } + return this._size.clone(); + }, + + getPixelBounds: function () { + var topLeftPoint = this._getTopLeftPoint(); + return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize())); + }, + + getPixelOrigin: function () { + this._checkIfLoaded(); + return this._initialTopLeftPoint; + }, + + getPanes: function () { + return this._panes; + }, + + getContainer: function () { + return this._container; + }, + + + // TODO replace with universal implementation after refactoring projections + + getZoomScale: function (toZoom) { + var crs = this.options.crs; + return crs.scale(toZoom) / crs.scale(this._zoom); + }, + + getScaleZoom: function (scale) { + return this._zoom + (Math.log(scale) / Math.LN2); + }, + + + // conversion methods + + project: function (latlng, zoom) { // (LatLng[, Number]) -> Point + zoom = zoom === undefined ? this._zoom : zoom; + return this.options.crs.latLngToPoint(L.latLng(latlng), zoom); + }, + + unproject: function (point, zoom) { // (Point[, Number]) -> LatLng + zoom = zoom === undefined ? this._zoom : zoom; + return this.options.crs.pointToLatLng(L.point(point), zoom); + }, + + layerPointToLatLng: function (point) { // (Point) + var projectedPoint = L.point(point).add(this.getPixelOrigin()); + return this.unproject(projectedPoint); + }, + + latLngToLayerPoint: function (latlng) { // (LatLng) + var projectedPoint = this.project(L.latLng(latlng))._round(); + return projectedPoint._subtract(this.getPixelOrigin()); + }, + + containerPointToLayerPoint: function (point) { // (Point) + return L.point(point).subtract(this._getMapPanePos()); + }, + + layerPointToContainerPoint: function (point) { // (Point) + return L.point(point).add(this._getMapPanePos()); + }, + + containerPointToLatLng: function (point) { + var layerPoint = this.containerPointToLayerPoint(L.point(point)); + return this.layerPointToLatLng(layerPoint); + }, + + latLngToContainerPoint: function (latlng) { + return this.layerPointToContainerPoint(this.latLngToLayerPoint(L.latLng(latlng))); + }, + + mouseEventToContainerPoint: function (e) { // (MouseEvent) + return L.DomEvent.getMousePosition(e, this._container); + }, + + mouseEventToLayerPoint: function (e) { // (MouseEvent) + return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e)); + }, + + mouseEventToLatLng: function (e) { // (MouseEvent) + return this.layerPointToLatLng(this.mouseEventToLayerPoint(e)); + }, + + + // map initialization methods + + _initContainer: function (id) { + var container = this._container = L.DomUtil.get(id); + + if (!container) { + throw new Error('Map container not found.'); + } else if (container._leaflet) { + throw new Error('Map container is already initialized.'); + } + + container._leaflet = true; + }, + + _initLayout: function () { + var container = this._container; + + L.DomUtil.addClass(container, 'leaflet-container' + + (L.Browser.touch ? ' leaflet-touch' : '') + + (L.Browser.retina ? ' leaflet-retina' : '') + + (L.Browser.ielt9 ? ' leaflet-oldie' : '') + + (this.options.fadeAnimation ? ' leaflet-fade-anim' : '')); + + var position = L.DomUtil.getStyle(container, 'position'); + + if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') { + container.style.position = 'relative'; + } + + this._initPanes(); + + if (this._initControlPos) { + this._initControlPos(); + } + }, + + _initPanes: function () { + var panes = this._panes = {}; + + this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container); + + this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane); + panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane); + panes.shadowPane = this._createPane('leaflet-shadow-pane'); + panes.overlayPane = this._createPane('leaflet-overlay-pane'); + panes.markerPane = this._createPane('leaflet-marker-pane'); + panes.popupPane = this._createPane('leaflet-popup-pane'); + + var zoomHide = ' leaflet-zoom-hide'; + + if (!this.options.markerZoomAnimation) { + L.DomUtil.addClass(panes.markerPane, zoomHide); + L.DomUtil.addClass(panes.shadowPane, zoomHide); + L.DomUtil.addClass(panes.popupPane, zoomHide); + } + }, + + _createPane: function (className, container) { + return L.DomUtil.create('div', className, container || this._panes.objectsPane); + }, + + _clearPanes: function () { + this._container.removeChild(this._mapPane); + }, + + _addLayers: function (layers) { + layers = layers ? (L.Util.isArray(layers) ? layers : [layers]) : []; + + for (var i = 0, len = layers.length; i < len; i++) { + this.addLayer(layers[i]); + } + }, + + + // private methods that modify map state + + _resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) { + + var zoomChanged = (this._zoom !== zoom); + + if (!afterZoomAnim) { + this.fire('movestart'); + + if (zoomChanged) { + this.fire('zoomstart'); + } + } + + this._zoom = zoom; + this._initialCenter = center; + + this._initialTopLeftPoint = this._getNewTopLeftPoint(center); + + if (!preserveMapOffset) { + L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0)); + } else { + this._initialTopLeftPoint._add(this._getMapPanePos()); + } + + this._tileLayersToLoad = this._tileLayersNum; + + var loading = !this._loaded; + this._loaded = true; + + this.fire('viewreset', {hard: !preserveMapOffset}); + + if (loading) { + this.fire('load'); + this.eachLayer(this._layerAdd, this); + } + + this.fire('move'); + + if (zoomChanged || afterZoomAnim) { + this.fire('zoomend'); + } + + this.fire('moveend', {hard: !preserveMapOffset}); + }, + + _rawPanBy: function (offset) { + L.DomUtil.setPosition(this._mapPane, this._getMapPanePos().subtract(offset)); + }, + + _getZoomSpan: function () { + return this.getMaxZoom() - this.getMinZoom(); + }, + + _updateZoomLevels: function () { + var i, + minZoom = Infinity, + maxZoom = -Infinity, + oldZoomSpan = this._getZoomSpan(); + + for (i in this._zoomBoundLayers) { + var layer = this._zoomBoundLayers[i]; + if (!isNaN(layer.options.minZoom)) { + minZoom = Math.min(minZoom, layer.options.minZoom); + } + if (!isNaN(layer.options.maxZoom)) { + maxZoom = Math.max(maxZoom, layer.options.maxZoom); + } + } + + if (i === undefined) { // we have no tilelayers + this._layersMaxZoom = this._layersMinZoom = undefined; + } else { + this._layersMaxZoom = maxZoom; + this._layersMinZoom = minZoom; + } + + if (oldZoomSpan !== this._getZoomSpan()) { + this.fire('zoomlevelschange'); + } + }, + + _panInsideMaxBounds: function () { + this.panInsideBounds(this.options.maxBounds); + }, + + _checkIfLoaded: function () { + if (!this._loaded) { + throw new Error('Set map center and zoom first.'); + } + }, + + // map events + + _initEvents: function (onOff) { + if (!L.DomEvent) { return; } + + onOff = onOff || 'on'; + + L.DomEvent[onOff](this._container, 'click', this._onMouseClick, this); + + var events = ['dblclick', 'mousedown', 'mouseup', 'mouseenter', + 'mouseleave', 'mousemove', 'contextmenu'], + i, len; + + for (i = 0, len = events.length; i < len; i++) { + L.DomEvent[onOff](this._container, events[i], this._fireMouseEvent, this); + } + + if (this.options.trackResize) { + L.DomEvent[onOff](window, 'resize', this._onResize, this); + } + }, + + _onResize: function () { + L.Util.cancelAnimFrame(this._resizeRequest); + this._resizeRequest = L.Util.requestAnimFrame( + function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container); + }, + + _onMouseClick: function (e) { + if (!this._loaded || (!e._simulated && + ((this.dragging && this.dragging.moved()) || + (this.boxZoom && this.boxZoom.moved()))) || + L.DomEvent._skipped(e)) { return; } + + this.fire('preclick'); + this._fireMouseEvent(e); + }, + + _fireMouseEvent: function (e) { + if (!this._loaded || L.DomEvent._skipped(e)) { return; } + + var type = e.type; + + type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type)); + + if (!this.hasEventListeners(type)) { return; } + + if (type === 'contextmenu') { + L.DomEvent.preventDefault(e); + } + + var containerPoint = this.mouseEventToContainerPoint(e), + layerPoint = this.containerPointToLayerPoint(containerPoint), + latlng = this.layerPointToLatLng(layerPoint); + + this.fire(type, { + latlng: latlng, + layerPoint: layerPoint, + containerPoint: containerPoint, + originalEvent: e + }); + }, + + _onTileLayerLoad: function () { + this._tileLayersToLoad--; + if (this._tileLayersNum && !this._tileLayersToLoad) { + this.fire('tilelayersload'); + } + }, + + _clearHandlers: function () { + for (var i = 0, len = this._handlers.length; i < len; i++) { + this._handlers[i].disable(); + } + }, + + whenReady: function (callback, context) { + if (this._loaded) { + callback.call(context || this, this); + } else { + this.on('load', callback, context); + } + return this; + }, + + _layerAdd: function (layer) { + layer.onAdd(this); + this.fire('layeradd', {layer: layer}); + }, + + + // private methods for getting map state + + _getMapPanePos: function () { + return L.DomUtil.getPosition(this._mapPane); + }, + + _moved: function () { + var pos = this._getMapPanePos(); + return pos && !pos.equals([0, 0]); + }, + + _getTopLeftPoint: function () { + return this.getPixelOrigin().subtract(this._getMapPanePos()); + }, + + _getNewTopLeftPoint: function (center, zoom) { + var viewHalf = this.getSize()._divideBy(2); + // TODO round on display, not calculation to increase precision? + return this.project(center, zoom)._subtract(viewHalf)._round(); + }, + + _latLngToNewLayerPoint: function (latlng, newZoom, newCenter) { + var topLeft = this._getNewTopLeftPoint(newCenter, newZoom).add(this._getMapPanePos()); + return this.project(latlng, newZoom)._subtract(topLeft); + }, + + // layer point of the current center + _getCenterLayerPoint: function () { + return this.containerPointToLayerPoint(this.getSize()._divideBy(2)); + }, + + // offset of the specified place to the current center in pixels + _getCenterOffset: function (latlng) { + return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint()); + }, + + // adjust center for view to get inside bounds + _limitCenter: function (center, zoom, bounds) { + + if (!bounds) { return center; } + + var centerPoint = this.project(center, zoom), + viewHalf = this.getSize().divideBy(2), + viewBounds = new L.Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), + offset = this._getBoundsOffset(viewBounds, bounds, zoom); + + return this.unproject(centerPoint.add(offset), zoom); + }, + + // adjust offset for view to get inside bounds + _limitOffset: function (offset, bounds) { + if (!bounds) { return offset; } + + var viewBounds = this.getPixelBounds(), + newBounds = new L.Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset)); + + return offset.add(this._getBoundsOffset(newBounds, bounds)); + }, + + // returns offset needed for pxBounds to get inside maxBounds at a specified zoom + _getBoundsOffset: function (pxBounds, maxBounds, zoom) { + var nwOffset = this.project(maxBounds.getNorthWest(), zoom).subtract(pxBounds.min), + seOffset = this.project(maxBounds.getSouthEast(), zoom).subtract(pxBounds.max), + + dx = this._rebound(nwOffset.x, -seOffset.x), + dy = this._rebound(nwOffset.y, -seOffset.y); + + return new L.Point(dx, dy); + }, + + _rebound: function (left, right) { + return left + right > 0 ? + Math.round(left - right) / 2 : + Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right)); + }, + + _limitZoom: function (zoom) { + var min = this.getMinZoom(), + max = this.getMaxZoom(); + + return Math.max(min, Math.min(max, zoom)); + } +}); + +L.map = function (id, options) { + return new L.Map(id, options); +}; + + +/* + * Mercator projection that takes into account that the Earth is not a perfect sphere. + * Less popular than spherical mercator; used by projections like EPSG:3395. + */ + +L.Projection.Mercator = { + MAX_LATITUDE: 85.0840591556, + + R_MINOR: 6356752.314245179, + R_MAJOR: 6378137, + + project: function (latlng) { // (LatLng) -> Point + var d = L.LatLng.DEG_TO_RAD, + max = this.MAX_LATITUDE, + lat = Math.max(Math.min(max, latlng.lat), -max), + r = this.R_MAJOR, + r2 = this.R_MINOR, + x = latlng.lng * d * r, + y = lat * d, + tmp = r2 / r, + eccent = Math.sqrt(1.0 - tmp * tmp), + con = eccent * Math.sin(y); + + con = Math.pow((1 - con) / (1 + con), eccent * 0.5); + + var ts = Math.tan(0.5 * ((Math.PI * 0.5) - y)) / con; + y = -r * Math.log(ts); + + return new L.Point(x, y); + }, + + unproject: function (point) { // (Point, Boolean) -> LatLng + var d = L.LatLng.RAD_TO_DEG, + r = this.R_MAJOR, + r2 = this.R_MINOR, + lng = point.x * d / r, + tmp = r2 / r, + eccent = Math.sqrt(1 - (tmp * tmp)), + ts = Math.exp(- point.y / r), + phi = (Math.PI / 2) - 2 * Math.atan(ts), + numIter = 15, + tol = 1e-7, + i = numIter, + dphi = 0.1, + con; + + while ((Math.abs(dphi) > tol) && (--i > 0)) { + con = eccent * Math.sin(phi); + dphi = (Math.PI / 2) - 2 * Math.atan(ts * + Math.pow((1.0 - con) / (1.0 + con), 0.5 * eccent)) - phi; + phi += dphi; + } + + return new L.LatLng(phi * d, lng); + } +}; + + + +L.CRS.EPSG3395 = L.extend({}, L.CRS, { + code: 'EPSG:3395', + + projection: L.Projection.Mercator, + + transformation: (function () { + var m = L.Projection.Mercator, + r = m.R_MAJOR, + scale = 0.5 / (Math.PI * r); + + return new L.Transformation(scale, 0.5, -scale, 0.5); + }()) +}); + + +/* + * L.TileLayer is used for standard xyz-numbered tile layers. + */ + +L.TileLayer = L.Class.extend({ + includes: L.Mixin.Events, + + options: { + minZoom: 0, + maxZoom: 18, + tileSize: 256, + subdomains: 'abc', + errorTileUrl: '', + attribution: '', + zoomOffset: 0, + opacity: 1, + /* + maxNativeZoom: null, + zIndex: null, + tms: false, + continuousWorld: false, + noWrap: false, + zoomReverse: false, + detectRetina: false, + reuseTiles: false, + bounds: false, + */ + unloadInvisibleTiles: L.Browser.mobile, + updateWhenIdle: L.Browser.mobile + }, + + initialize: function (url, options) { + options = L.setOptions(this, options); + + // detecting retina displays, adjusting tileSize and zoom levels + if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) { + + options.tileSize = Math.floor(options.tileSize / 2); + options.zoomOffset++; + + if (options.minZoom > 0) { + options.minZoom--; + } + this.options.maxZoom--; + } + + if (options.bounds) { + options.bounds = L.latLngBounds(options.bounds); + } + + this._url = url; + + var subdomains = this.options.subdomains; + + if (typeof subdomains === 'string') { + this.options.subdomains = subdomains.split(''); + } + }, + + onAdd: function (map) { + this._map = map; + this._animated = map._zoomAnimated; + + // create a container div for tiles + this._initContainer(); + + // set up events + map.on({ + 'viewreset': this._reset, + 'moveend': this._update + }, this); + + if (this._animated) { + map.on({ + 'zoomanim': this._animateZoom, + 'zoomend': this._endZoomAnim + }, this); + } + + if (!this.options.updateWhenIdle) { + this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this); + map.on('move', this._limitedUpdate, this); + } + + this._reset(); + this._update(); + }, + + addTo: function (map) { + map.addLayer(this); + return this; + }, + + onRemove: function (map) { + this._container.parentNode.removeChild(this._container); + + map.off({ + 'viewreset': this._reset, + 'moveend': this._update + }, this); + + if (this._animated) { + map.off({ + 'zoomanim': this._animateZoom, + 'zoomend': this._endZoomAnim + }, this); + } + + if (!this.options.updateWhenIdle) { + map.off('move', this._limitedUpdate, this); + } + + this._container = null; + this._map = null; + }, + + bringToFront: function () { + var pane = this._map._panes.tilePane; + + if (this._container) { + pane.appendChild(this._container); + this._setAutoZIndex(pane, Math.max); + } + + return this; + }, + + bringToBack: function () { + var pane = this._map._panes.tilePane; + + if (this._container) { + pane.insertBefore(this._container, pane.firstChild); + this._setAutoZIndex(pane, Math.min); + } + + return this; + }, + + getAttribution: function () { + return this.options.attribution; + }, + + getContainer: function () { + return this._container; + }, + + setOpacity: function (opacity) { + this.options.opacity = opacity; + + if (this._map) { + this._updateOpacity(); + } + + return this; + }, + + setZIndex: function (zIndex) { + this.options.zIndex = zIndex; + this._updateZIndex(); + + return this; + }, + + setUrl: function (url, noRedraw) { + this._url = url; + + if (!noRedraw) { + this.redraw(); + } + + return this; + }, + + redraw: function () { + if (this._map) { + this._reset({hard: true}); + this._update(); + } + return this; + }, + + _updateZIndex: function () { + if (this._container && this.options.zIndex !== undefined) { + this._container.style.zIndex = this.options.zIndex; + } + }, + + _setAutoZIndex: function (pane, compare) { + + var layers = pane.children, + edgeZIndex = -compare(Infinity, -Infinity), // -Infinity for max, Infinity for min + zIndex, i, len; + + for (i = 0, len = layers.length; i < len; i++) { + + if (layers[i] !== this._container) { + zIndex = parseInt(layers[i].style.zIndex, 10); + + if (!isNaN(zIndex)) { + edgeZIndex = compare(edgeZIndex, zIndex); + } + } + } + + this.options.zIndex = this._container.style.zIndex = + (isFinite(edgeZIndex) ? edgeZIndex : 0) + compare(1, -1); + }, + + _updateOpacity: function () { + var i, + tiles = this._tiles; + + if (L.Browser.ielt9) { + for (i in tiles) { + L.DomUtil.setOpacity(tiles[i], this.options.opacity); + } + } else { + L.DomUtil.setOpacity(this._container, this.options.opacity); + } + }, + + _initContainer: function () { + var tilePane = this._map._panes.tilePane; + + if (!this._container) { + this._container = L.DomUtil.create('div', 'leaflet-layer'); + + this._updateZIndex(); + + if (this._animated) { + var className = 'leaflet-tile-container'; + + this._bgBuffer = L.DomUtil.create('div', className, this._container); + this._tileContainer = L.DomUtil.create('div', className, this._container); + + } else { + this._tileContainer = this._container; + } + + tilePane.appendChild(this._container); + + if (this.options.opacity < 1) { + this._updateOpacity(); + } + } + }, + + _reset: function (e) { + for (var key in this._tiles) { + this.fire('tileunload', {tile: this._tiles[key]}); + } + + this._tiles = {}; + this._tilesToLoad = 0; + + if (this.options.reuseTiles) { + this._unusedTiles = []; + } + + this._tileContainer.innerHTML = ''; + + if (this._animated && e && e.hard) { + this._clearBgBuffer(); + } + + this._initContainer(); + }, + + _getTileSize: function () { + var map = this._map, + zoom = map.getZoom() + this.options.zoomOffset, + zoomN = this.options.maxNativeZoom, + tileSize = this.options.tileSize; + + if (zoomN && zoom > zoomN) { + tileSize = Math.round(map.getZoomScale(zoom) / map.getZoomScale(zoomN) * tileSize); + } + + return tileSize; + }, + + _update: function () { + + if (!this._map) { return; } + + var map = this._map, + bounds = map.getPixelBounds(), + zoom = map.getZoom(), + tileSize = this._getTileSize(); + + if (zoom > this.options.maxZoom || zoom < this.options.minZoom) { + return; + } + + var tileBounds = L.bounds( + bounds.min.divideBy(tileSize)._floor(), + bounds.max.divideBy(tileSize)._floor()); + + this._addTilesFromCenterOut(tileBounds); + + if (this.options.unloadInvisibleTiles || this.options.reuseTiles) { + this._removeOtherTiles(tileBounds); + } + }, + + _addTilesFromCenterOut: function (bounds) { + var queue = [], + center = bounds.getCenter(); + + var j, i, point; + + for (j = bounds.min.y; j <= bounds.max.y; j++) { + for (i = bounds.min.x; i <= bounds.max.x; i++) { + point = new L.Point(i, j); + + if (this._tileShouldBeLoaded(point)) { + queue.push(point); + } + } + } + + var tilesToLoad = queue.length; + + if (tilesToLoad === 0) { return; } + + // load tiles in order of their distance to center + queue.sort(function (a, b) { + return a.distanceTo(center) - b.distanceTo(center); + }); + + var fragment = document.createDocumentFragment(); + + // if its the first batch of tiles to load + if (!this._tilesToLoad) { + this.fire('loading'); + } + + this._tilesToLoad += tilesToLoad; + + for (i = 0; i < tilesToLoad; i++) { + this._addTile(queue[i], fragment); + } + + this._tileContainer.appendChild(fragment); + }, + + _tileShouldBeLoaded: function (tilePoint) { + if ((tilePoint.x + ':' + tilePoint.y) in this._tiles) { + return false; // already loaded + } + + var options = this.options; + + if (!options.continuousWorld) { + var limit = this._getWrapTileNum(); + + // don't load if exceeds world bounds + if ((options.noWrap && (tilePoint.x < 0 || tilePoint.x >= limit.x)) || + tilePoint.y < 0 || tilePoint.y >= limit.y) { return false; } + } + + if (options.bounds) { + var tileSize = options.tileSize, + nwPoint = tilePoint.multiplyBy(tileSize), + sePoint = nwPoint.add([tileSize, tileSize]), + nw = this._map.unproject(nwPoint), + se = this._map.unproject(sePoint); + + // TODO temporary hack, will be removed after refactoring projections + // https://github.com/Leaflet/Leaflet/issues/1618 + if (!options.continuousWorld && !options.noWrap) { + nw = nw.wrap(); + se = se.wrap(); + } + + if (!options.bounds.intersects([nw, se])) { return false; } + } + + return true; + }, + + _removeOtherTiles: function (bounds) { + var kArr, x, y, key; + + for (key in this._tiles) { + kArr = key.split(':'); + x = parseInt(kArr[0], 10); + y = parseInt(kArr[1], 10); + + // remove tile if it's out of bounds + if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) { + this._removeTile(key); + } + } + }, + + _removeTile: function (key) { + var tile = this._tiles[key]; + + this.fire('tileunload', {tile: tile, url: tile.src}); + + if (this.options.reuseTiles) { + L.DomUtil.removeClass(tile, 'leaflet-tile-loaded'); + this._unusedTiles.push(tile); + + } else if (tile.parentNode === this._tileContainer) { + this._tileContainer.removeChild(tile); + } + + // for https://github.com/CloudMade/Leaflet/issues/137 + if (!L.Browser.android) { + tile.onload = null; + tile.src = L.Util.emptyImageUrl; + } + + delete this._tiles[key]; + }, + + _addTile: function (tilePoint, container) { + var tilePos = this._getTilePos(tilePoint); + + // get unused tile - or create a new tile + var tile = this._getTile(); + + /* + Chrome 20 layouts much faster with top/left (verify with timeline, frames) + Android 4 browser has display issues with top/left and requires transform instead + (other browsers don't currently care) - see debug/hacks/jitter.html for an example + */ + L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome); + + this._tiles[tilePoint.x + ':' + tilePoint.y] = tile; + + this._loadTile(tile, tilePoint); + + if (tile.parentNode !== this._tileContainer) { + container.appendChild(tile); + } + }, + + _getZoomForUrl: function () { + + var options = this.options, + zoom = this._map.getZoom(); + + if (options.zoomReverse) { + zoom = options.maxZoom - zoom; + } + + zoom += options.zoomOffset; + + return options.maxNativeZoom ? Math.min(zoom, options.maxNativeZoom) : zoom; + }, + + _getTilePos: function (tilePoint) { + var origin = this._map.getPixelOrigin(), + tileSize = this._getTileSize(); + + return tilePoint.multiplyBy(tileSize).subtract(origin); + }, + + // image-specific code (override to implement e.g. Canvas or SVG tile layer) + + getTileUrl: function (tilePoint) { + return L.Util.template(this._url, L.extend({ + s: this._getSubdomain(tilePoint), + z: tilePoint.z, + x: tilePoint.x, + y: tilePoint.y + }, this.options)); + }, + + _getWrapTileNum: function () { + var crs = this._map.options.crs, + size = crs.getSize(this._map.getZoom()); + return size.divideBy(this._getTileSize())._floor(); + }, + + _adjustTilePoint: function (tilePoint) { + + var limit = this._getWrapTileNum(); + + // wrap tile coordinates + if (!this.options.continuousWorld && !this.options.noWrap) { + tilePoint.x = ((tilePoint.x % limit.x) + limit.x) % limit.x; + } + + if (this.options.tms) { + tilePoint.y = limit.y - tilePoint.y - 1; + } + + tilePoint.z = this._getZoomForUrl(); + }, + + _getSubdomain: function (tilePoint) { + var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length; + return this.options.subdomains[index]; + }, + + _getTile: function () { + if (this.options.reuseTiles && this._unusedTiles.length > 0) { + var tile = this._unusedTiles.pop(); + this._resetTile(tile); + return tile; + } + return this._createTile(); + }, + + // Override if data stored on a tile needs to be cleaned up before reuse + _resetTile: function (/*tile*/) {}, + + _createTile: function () { + var tile = L.DomUtil.create('img', 'leaflet-tile'); + tile.style.width = tile.style.height = this._getTileSize() + 'px'; + tile.galleryimg = 'no'; + + tile.onselectstart = tile.onmousemove = L.Util.falseFn; + + if (L.Browser.ielt9 && this.options.opacity !== undefined) { + L.DomUtil.setOpacity(tile, this.options.opacity); + } + // without this hack, tiles disappear after zoom on Chrome for Android + // https://github.com/Leaflet/Leaflet/issues/2078 + if (L.Browser.mobileWebkit3d) { + tile.style.WebkitBackfaceVisibility = 'hidden'; + } + return tile; + }, + + _loadTile: function (tile, tilePoint) { + tile._layer = this; + tile.onload = this._tileOnLoad; + tile.onerror = this._tileOnError; + + this._adjustTilePoint(tilePoint); + tile.src = this.getTileUrl(tilePoint); + + this.fire('tileloadstart', { + tile: tile, + url: tile.src + }); + }, + + _tileLoaded: function () { + this._tilesToLoad--; + + if (this._animated) { + L.DomUtil.addClass(this._tileContainer, 'leaflet-zoom-animated'); + } + + if (!this._tilesToLoad) { + this.fire('load'); + + if (this._animated) { + // clear scaled tiles after all new tiles are loaded (for performance) + clearTimeout(this._clearBgBufferTimer); + this._clearBgBufferTimer = setTimeout(L.bind(this._clearBgBuffer, this), 500); + } + } + }, + + _tileOnLoad: function () { + var layer = this._layer; + + //Only if we are loading an actual image + if (this.src !== L.Util.emptyImageUrl) { + L.DomUtil.addClass(this, 'leaflet-tile-loaded'); + + layer.fire('tileload', { + tile: this, + url: this.src + }); + } + + layer._tileLoaded(); + }, + + _tileOnError: function () { + var layer = this._layer; + + layer.fire('tileerror', { + tile: this, + url: this.src + }); + + var newUrl = layer.options.errorTileUrl; + if (newUrl) { + this.src = newUrl; + } + + layer._tileLoaded(); + } +}); + +L.tileLayer = function (url, options) { + return new L.TileLayer(url, options); +}; + + +/* + * L.TileLayer.WMS is used for putting WMS tile layers on the map. + */ + +L.TileLayer.WMS = L.TileLayer.extend({ + + defaultWmsParams: { + service: 'WMS', + request: 'GetMap', + version: '1.1.1', + layers: '', + styles: '', + format: 'image/jpeg', + transparent: false + }, + + initialize: function (url, options) { // (String, Object) + + this._url = url; + + var wmsParams = L.extend({}, this.defaultWmsParams), + tileSize = options.tileSize || this.options.tileSize; + + if (options.detectRetina && L.Browser.retina) { + wmsParams.width = wmsParams.height = tileSize * 2; + } else { + wmsParams.width = wmsParams.height = tileSize; + } + + for (var i in options) { + // all keys that are not TileLayer options go to WMS params + if (!this.options.hasOwnProperty(i) && i !== 'crs') { + wmsParams[i] = options[i]; + } + } + + this.wmsParams = wmsParams; + + L.setOptions(this, options); + }, + + onAdd: function (map) { + + this._crs = this.options.crs || map.options.crs; + + this._wmsVersion = parseFloat(this.wmsParams.version); + + var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs'; + this.wmsParams[projectionKey] = this._crs.code; + + L.TileLayer.prototype.onAdd.call(this, map); + }, + + getTileUrl: function (tilePoint) { // (Point, Number) -> String + + var map = this._map, + tileSize = this.options.tileSize, + + nwPoint = tilePoint.multiplyBy(tileSize), + sePoint = nwPoint.add([tileSize, tileSize]), + + nw = this._crs.project(map.unproject(nwPoint, tilePoint.z)), + se = this._crs.project(map.unproject(sePoint, tilePoint.z)), + bbox = this._wmsVersion >= 1.3 && this._crs === L.CRS.EPSG4326 ? + [se.y, nw.x, nw.y, se.x].join(',') : + [nw.x, se.y, se.x, nw.y].join(','), + + url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)}); + + return url + L.Util.getParamString(this.wmsParams, url, true) + '&BBOX=' + bbox; + }, + + setParams: function (params, noRedraw) { + + L.extend(this.wmsParams, params); + + if (!noRedraw) { + this.redraw(); + } + + return this; + } +}); + +L.tileLayer.wms = function (url, options) { + return new L.TileLayer.WMS(url, options); +}; + + +/* + * L.TileLayer.Canvas is a class that you can use as a base for creating + * dynamically drawn Canvas-based tile layers. + */ + +L.TileLayer.Canvas = L.TileLayer.extend({ + options: { + async: false + }, + + initialize: function (options) { + L.setOptions(this, options); + }, + + redraw: function () { + if (this._map) { + this._reset({hard: true}); + this._update(); + } + + for (var i in this._tiles) { + this._redrawTile(this._tiles[i]); + } + return this; + }, + + _redrawTile: function (tile) { + this.drawTile(tile, tile._tilePoint, this._map._zoom); + }, + + _createTile: function () { + var tile = L.DomUtil.create('canvas', 'leaflet-tile'); + tile.width = tile.height = this.options.tileSize; + tile.onselectstart = tile.onmousemove = L.Util.falseFn; + return tile; + }, + + _loadTile: function (tile, tilePoint) { + tile._layer = this; + tile._tilePoint = tilePoint; + + this._redrawTile(tile); + + if (!this.options.async) { + this.tileDrawn(tile); + } + }, + + drawTile: function (/*tile, tilePoint*/) { + // override with rendering code + }, + + tileDrawn: function (tile) { + this._tileOnLoad.call(tile); + } +}); + + +L.tileLayer.canvas = function (options) { + return new L.TileLayer.Canvas(options); +}; + + +/* + * L.ImageOverlay is used to overlay images over the map (to specific geographical bounds). + */ + +L.ImageOverlay = L.Class.extend({ + includes: L.Mixin.Events, + + options: { + opacity: 1 + }, + + initialize: function (url, bounds, options) { // (String, LatLngBounds, Object) + this._url = url; + this._bounds = L.latLngBounds(bounds); + + L.setOptions(this, options); + }, + + onAdd: function (map) { + this._map = map; + + if (!this._image) { + this._initImage(); + } + + map._panes.overlayPane.appendChild(this._image); + + map.on('viewreset', this._reset, this); + + if (map.options.zoomAnimation && L.Browser.any3d) { + map.on('zoomanim', this._animateZoom, this); + } + + this._reset(); + }, + + onRemove: function (map) { + map.getPanes().overlayPane.removeChild(this._image); + + map.off('viewreset', this._reset, this); + + if (map.options.zoomAnimation) { + map.off('zoomanim', this._animateZoom, this); + } + }, + + addTo: function (map) { + map.addLayer(this); + return this; + }, + + setOpacity: function (opacity) { + this.options.opacity = opacity; + this._updateOpacity(); + return this; + }, + + // TODO remove bringToFront/bringToBack duplication from TileLayer/Path + bringToFront: function () { + if (this._image) { + this._map._panes.overlayPane.appendChild(this._image); + } + return this; + }, + + bringToBack: function () { + var pane = this._map._panes.overlayPane; + if (this._image) { + pane.insertBefore(this._image, pane.firstChild); + } + return this; + }, + + setUrl: function (url) { + this._url = url; + this._image.src = this._url; + }, + + getAttribution: function () { + return this.options.attribution; + }, + + _initImage: function () { + this._image = L.DomUtil.create('img', 'leaflet-image-layer'); + + if (this._map.options.zoomAnimation && L.Browser.any3d) { + L.DomUtil.addClass(this._image, 'leaflet-zoom-animated'); + } else { + L.DomUtil.addClass(this._image, 'leaflet-zoom-hide'); + } + + this._updateOpacity(); + + //TODO createImage util method to remove duplication + L.extend(this._image, { + galleryimg: 'no', + onselectstart: L.Util.falseFn, + onmousemove: L.Util.falseFn, + onload: L.bind(this._onImageLoad, this), + src: this._url + }); + }, + + _animateZoom: function (e) { + var map = this._map, + image = this._image, + scale = map.getZoomScale(e.zoom), + nw = this._bounds.getNorthWest(), + se = this._bounds.getSouthEast(), + + topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), + size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft), + origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale))); + + image.style[L.DomUtil.TRANSFORM] = + L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') '; + }, + + _reset: function () { + var image = this._image, + topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()), + size = this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(topLeft); + + L.DomUtil.setPosition(image, topLeft); + + image.style.width = size.x + 'px'; + image.style.height = size.y + 'px'; + }, + + _onImageLoad: function () { + this.fire('load'); + }, + + _updateOpacity: function () { + L.DomUtil.setOpacity(this._image, this.options.opacity); + } +}); + +L.imageOverlay = function (url, bounds, options) { + return new L.ImageOverlay(url, bounds, options); +}; + + +/* + * L.Icon is an image-based icon class that you can use with L.Marker for custom markers. + */ + +L.Icon = L.Class.extend({ + options: { + /* + iconUrl: (String) (required) + iconRetinaUrl: (String) (optional, used for retina devices if detected) + iconSize: (Point) (can be set through CSS) + iconAnchor: (Point) (centered by default, can be set in CSS with negative margins) + popupAnchor: (Point) (if not specified, popup opens in the anchor point) + shadowUrl: (String) (no shadow by default) + shadowRetinaUrl: (String) (optional, used for retina devices if detected) + shadowSize: (Point) + shadowAnchor: (Point) + */ + className: '' + }, + + initialize: function (options) { + L.setOptions(this, options); + }, + + createIcon: function (oldIcon) { + return this._createIcon('icon', oldIcon); + }, + + createShadow: function (oldIcon) { + return this._createIcon('shadow', oldIcon); + }, + + _createIcon: function (name, oldIcon) { + var src = this._getIconUrl(name); + + if (!src) { + if (name === 'icon') { + throw new Error('iconUrl not set in Icon options (see the docs).'); + } + return null; + } + + var img; + if (!oldIcon || oldIcon.tagName !== 'IMG') { + img = this._createImg(src); + } else { + img = this._createImg(src, oldIcon); + } + this._setIconStyles(img, name); + + return img; + }, + + _setIconStyles: function (img, name) { + var options = this.options, + size = L.point(options[name + 'Size']), + anchor; + + if (name === 'shadow') { + anchor = L.point(options.shadowAnchor || options.iconAnchor); + } else { + anchor = L.point(options.iconAnchor); + } + + if (!anchor && size) { + anchor = size.divideBy(2, true); + } + + img.className = 'leaflet-marker-' + name + ' ' + options.className; + + if (anchor) { + img.style.marginLeft = (-anchor.x) + 'px'; + img.style.marginTop = (-anchor.y) + 'px'; + } + + if (size) { + img.style.width = size.x + 'px'; + img.style.height = size.y + 'px'; + } + }, + + _createImg: function (src, el) { + el = el || document.createElement('img'); + el.src = src; + return el; + }, + + _getIconUrl: function (name) { + if (L.Browser.retina && this.options[name + 'RetinaUrl']) { + return this.options[name + 'RetinaUrl']; + } + return this.options[name + 'Url']; + } +}); + +L.icon = function (options) { + return new L.Icon(options); +}; + + +/* + * L.Icon.Default is the blue marker icon used by default in Leaflet. + */ + +L.Icon.Default = L.Icon.extend({ + + options: { + iconSize: [25, 41], + iconAnchor: [12, 41], + popupAnchor: [1, -34], + + shadowSize: [41, 41] + }, + + _getIconUrl: function (name) { + var key = name + 'Url'; + + if (this.options[key]) { + return this.options[key]; + } + + if (L.Browser.retina && name === 'icon') { + return "/assets/marker-icon-2x.png"; + } + + if (name == 'shadow') { + return "/assets/marker-shadow.png"; + } else { + return "/assets/marker-icon.png"; + } + } +}); + +L.Icon.Default.imagePath = (function () { + var scripts = document.getElementsByTagName('script'), + leafletRe = /[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/; + + var i, len, src, matches, path; + + for (i = 0, len = scripts.length; i < len; i++) { + src = scripts[i].src; + matches = src.match(leafletRe); + + if (matches) { + path = src.split(leafletRe)[0]; + return (path ? path + '/' : ''); + } + } +}()); + + +/* + * L.Marker is used to display clickable/draggable icons on the map. + */ + +L.Marker = L.Class.extend({ + + includes: L.Mixin.Events, + + options: { + icon: new L.Icon.Default(), + title: '', + alt: '', + clickable: true, + draggable: false, + keyboard: true, + zIndexOffset: 0, + opacity: 1, + riseOnHover: false, + riseOffset: 250 + }, + + initialize: function (latlng, options) { + L.setOptions(this, options); + this._latlng = L.latLng(latlng); + }, + + onAdd: function (map) { + this._map = map; + + map.on('viewreset', this.update, this); + + this._initIcon(); + this.update(); + this.fire('add'); + + if (map.options.zoomAnimation && map.options.markerZoomAnimation) { + map.on('zoomanim', this._animateZoom, this); + } + }, + + addTo: function (map) { + map.addLayer(this); + return this; + }, + + onRemove: function (map) { + if (this.dragging) { + this.dragging.disable(); + } + + this._removeIcon(); + this._removeShadow(); + + this.fire('remove'); + + map.off({ + 'viewreset': this.update, + 'zoomanim': this._animateZoom + }, this); + + this._map = null; + }, + + getLatLng: function () { + return this._latlng; + }, + + setLatLng: function (latlng) { + this._latlng = L.latLng(latlng); + + this.update(); + + return this.fire('move', { latlng: this._latlng }); + }, + + setZIndexOffset: function (offset) { + this.options.zIndexOffset = offset; + this.update(); + + return this; + }, + + setIcon: function (icon) { + + this.options.icon = icon; + + if (this._map) { + this._initIcon(); + this.update(); + } + + if (this._popup) { + this.bindPopup(this._popup); + } + + return this; + }, + + update: function () { + if (this._icon) { + var pos = this._map.latLngToLayerPoint(this._latlng).round(); + this._setPos(pos); + } + + return this; + }, + + _initIcon: function () { + var options = this.options, + map = this._map, + animation = (map.options.zoomAnimation && map.options.markerZoomAnimation), + classToAdd = animation ? 'leaflet-zoom-animated' : 'leaflet-zoom-hide'; + + var icon = options.icon.createIcon(this._icon), + addIcon = false; + + // if we're not reusing the icon, remove the old one and init new one + if (icon !== this._icon) { + if (this._icon) { + this._removeIcon(); + } + addIcon = true; + + if (options.title) { + icon.title = options.title; + } + + if (options.alt) { + icon.alt = options.alt; + } + } + + L.DomUtil.addClass(icon, classToAdd); + + if (options.keyboard) { + icon.tabIndex = '0'; + } + + this._icon = icon; + + this._initInteraction(); + + if (options.riseOnHover) { + L.DomEvent + .on(icon, 'mouseover', this._bringToFront, this) + .on(icon, 'mouseout', this._resetZIndex, this); + } + + var newShadow = options.icon.createShadow(this._shadow), + addShadow = false; + + if (newShadow !== this._shadow) { + this._removeShadow(); + addShadow = true; + } + + if (newShadow) { + L.DomUtil.addClass(newShadow, classToAdd); + } + this._shadow = newShadow; + + + if (options.opacity < 1) { + this._updateOpacity(); + } + + + var panes = this._map._panes; + + if (addIcon) { + panes.markerPane.appendChild(this._icon); + } + + if (newShadow && addShadow) { + panes.shadowPane.appendChild(this._shadow); + } + }, + + _removeIcon: function () { + if (this.options.riseOnHover) { + L.DomEvent + .off(this._icon, 'mouseover', this._bringToFront) + .off(this._icon, 'mouseout', this._resetZIndex); + } + + this._map._panes.markerPane.removeChild(this._icon); + + this._icon = null; + }, + + _removeShadow: function () { + if (this._shadow) { + this._map._panes.shadowPane.removeChild(this._shadow); + } + this._shadow = null; + }, + + _setPos: function (pos) { + L.DomUtil.setPosition(this._icon, pos); + + if (this._shadow) { + L.DomUtil.setPosition(this._shadow, pos); + } + + this._zIndex = pos.y + this.options.zIndexOffset; + + this._resetZIndex(); + }, + + _updateZIndex: function (offset) { + this._icon.style.zIndex = this._zIndex + offset; + }, + + _animateZoom: function (opt) { + var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); + + this._setPos(pos); + }, + + _initInteraction: function () { + + if (!this.options.clickable) { return; } + + // TODO refactor into something shared with Map/Path/etc. to DRY it up + + var icon = this._icon, + events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu']; + + L.DomUtil.addClass(icon, 'leaflet-clickable'); + L.DomEvent.on(icon, 'click', this._onMouseClick, this); + L.DomEvent.on(icon, 'keypress', this._onKeyPress, this); + + for (var i = 0; i < events.length; i++) { + L.DomEvent.on(icon, events[i], this._fireMouseEvent, this); + } + + if (L.Handler.MarkerDrag) { + this.dragging = new L.Handler.MarkerDrag(this); + + if (this.options.draggable) { + this.dragging.enable(); + } + } + }, + + _onMouseClick: function (e) { + var wasDragged = this.dragging && this.dragging.moved(); + + if (this.hasEventListeners(e.type) || wasDragged) { + L.DomEvent.stopPropagation(e); + } + + if (wasDragged) { return; } + + if ((!this.dragging || !this.dragging._enabled) && this._map.dragging && this._map.dragging.moved()) { return; } + + this.fire(e.type, { + originalEvent: e, + latlng: this._latlng + }); + }, + + _onKeyPress: function (e) { + if (e.keyCode === 13) { + this.fire('click', { + originalEvent: e, + latlng: this._latlng + }); + } + }, + + _fireMouseEvent: function (e) { + + this.fire(e.type, { + originalEvent: e, + latlng: this._latlng + }); + + // TODO proper custom event propagation + // this line will always be called if marker is in a FeatureGroup + if (e.type === 'contextmenu' && this.hasEventListeners(e.type)) { + L.DomEvent.preventDefault(e); + } + if (e.type !== 'mousedown') { + L.DomEvent.stopPropagation(e); + } else { + L.DomEvent.preventDefault(e); + } + }, + + setOpacity: function (opacity) { + this.options.opacity = opacity; + if (this._map) { + this._updateOpacity(); + } + + return this; + }, + + _updateOpacity: function () { + L.DomUtil.setOpacity(this._icon, this.options.opacity); + if (this._shadow) { + L.DomUtil.setOpacity(this._shadow, this.options.opacity); + } + }, + + _bringToFront: function () { + this._updateZIndex(this.options.riseOffset); + }, + + _resetZIndex: function () { + this._updateZIndex(0); + } +}); + +L.marker = function (latlng, options) { + return new L.Marker(latlng, options); +}; + + +/* + * L.DivIcon is a lightweight HTML-based icon class (as opposed to the image-based L.Icon) + * to use with L.Marker. + */ + +L.DivIcon = L.Icon.extend({ + options: { + iconSize: [12, 12], // also can be set through CSS + /* + iconAnchor: (Point) + popupAnchor: (Point) + html: (String) + bgPos: (Point) + */ + className: 'leaflet-div-icon', + html: false + }, + + createIcon: function (oldIcon) { + var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'), + options = this.options; + + if (options.html !== false) { + div.innerHTML = options.html; + } else { + div.innerHTML = ''; + } + + if (options.bgPos) { + div.style.backgroundPosition = + (-options.bgPos.x) + 'px ' + (-options.bgPos.y) + 'px'; + } + + this._setIconStyles(div, 'icon'); + return div; + }, + + createShadow: function () { + return null; + } +}); + +L.divIcon = function (options) { + return new L.DivIcon(options); +}; + + +/* + * L.Popup is used for displaying popups on the map. + */ + +L.Map.mergeOptions({ + closePopupOnClick: true +}); + +L.Popup = L.Class.extend({ + includes: L.Mixin.Events, + + options: { + minWidth: 50, + maxWidth: 300, + // maxHeight: null, + autoPan: true, + closeButton: true, + offset: [0, 7], + autoPanPadding: [5, 5], + // autoPanPaddingTopLeft: null, + // autoPanPaddingBottomRight: null, + keepInView: false, + className: '', + zoomAnimation: true + }, + + initialize: function (options, source) { + L.setOptions(this, options); + + this._source = source; + this._animated = L.Browser.any3d && this.options.zoomAnimation; + this._isOpen = false; + }, + + onAdd: function (map) { + this._map = map; + + if (!this._container) { + this._initLayout(); + } + + var animFade = map.options.fadeAnimation; + + if (animFade) { + L.DomUtil.setOpacity(this._container, 0); + } + map._panes.popupPane.appendChild(this._container); + + map.on(this._getEvents(), this); + + this.update(); + + if (animFade) { + L.DomUtil.setOpacity(this._container, 1); + } + + this.fire('open'); + + map.fire('popupopen', {popup: this}); + + if (this._source) { + this._source.fire('popupopen', {popup: this}); + } + }, + + addTo: function (map) { + map.addLayer(this); + return this; + }, + + openOn: function (map) { + map.openPopup(this); + return this; + }, + + onRemove: function (map) { + map._panes.popupPane.removeChild(this._container); + + L.Util.falseFn(this._container.offsetWidth); // force reflow + + map.off(this._getEvents(), this); + + if (map.options.fadeAnimation) { + L.DomUtil.setOpacity(this._container, 0); + } + + this._map = null; + + this.fire('close'); + + map.fire('popupclose', {popup: this}); + + if (this._source) { + this._source.fire('popupclose', {popup: this}); + } + }, + + getLatLng: function () { + return this._latlng; + }, + + setLatLng: function (latlng) { + this._latlng = L.latLng(latlng); + if (this._map) { + this._updatePosition(); + this._adjustPan(); + } + return this; + }, + + getContent: function () { + return this._content; + }, + + setContent: function (content) { + this._content = content; + this.update(); + return this; + }, + + update: function () { + if (!this._map) { return; } + + this._container.style.visibility = 'hidden'; + + this._updateContent(); + this._updateLayout(); + this._updatePosition(); + + this._container.style.visibility = ''; + + this._adjustPan(); + }, + + _getEvents: function () { + var events = { + viewreset: this._updatePosition + }; + + if (this._animated) { + events.zoomanim = this._zoomAnimation; + } + if ('closeOnClick' in this.options ? this.options.closeOnClick : this._map.options.closePopupOnClick) { + events.preclick = this._close; + } + if (this.options.keepInView) { + events.moveend = this._adjustPan; + } + + return events; + }, + + _close: function () { + if (this._map) { + this._map.closePopup(this); + } + }, + + _initLayout: function () { + var prefix = 'leaflet-popup', + containerClass = prefix + ' ' + this.options.className + ' leaflet-zoom-' + + (this._animated ? 'animated' : 'hide'), + container = this._container = L.DomUtil.create('div', containerClass), + closeButton; + + if (this.options.closeButton) { + closeButton = this._closeButton = + L.DomUtil.create('a', prefix + '-close-button', container); + closeButton.href = '#close'; + closeButton.innerHTML = '×'; + L.DomEvent.disableClickPropagation(closeButton); + + L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this); + } + + var wrapper = this._wrapper = + L.DomUtil.create('div', prefix + '-content-wrapper', container); + L.DomEvent.disableClickPropagation(wrapper); + + this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper); + + L.DomEvent.disableScrollPropagation(this._contentNode); + L.DomEvent.on(wrapper, 'contextmenu', L.DomEvent.stopPropagation); + + this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container); + this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer); + }, + + _updateContent: function () { + if (!this._content) { return; } + + if (typeof this._content === 'string') { + this._contentNode.innerHTML = this._content; + } else { + while (this._contentNode.hasChildNodes()) { + this._contentNode.removeChild(this._contentNode.firstChild); + } + this._contentNode.appendChild(this._content); + } + this.fire('contentupdate'); + }, + + _updateLayout: function () { + var container = this._contentNode, + style = container.style; + + style.width = ''; + style.whiteSpace = 'nowrap'; + + var width = container.offsetWidth; + width = Math.min(width, this.options.maxWidth); + width = Math.max(width, this.options.minWidth); + + style.width = (width + 1) + 'px'; + style.whiteSpace = ''; + + style.height = ''; + + var height = container.offsetHeight, + maxHeight = this.options.maxHeight, + scrolledClass = 'leaflet-popup-scrolled'; + + if (maxHeight && height > maxHeight) { + style.height = maxHeight + 'px'; + L.DomUtil.addClass(container, scrolledClass); + } else { + L.DomUtil.removeClass(container, scrolledClass); + } + + this._containerWidth = this._container.offsetWidth; + }, + + _updatePosition: function () { + if (!this._map) { return; } + + var pos = this._map.latLngToLayerPoint(this._latlng), + animated = this._animated, + offset = L.point(this.options.offset); + + if (animated) { + L.DomUtil.setPosition(this._container, pos); + } + + this._containerBottom = -offset.y - (animated ? 0 : pos.y); + this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x + (animated ? 0 : pos.x); + + // bottom position the popup in case the height of the popup changes (images loading etc) + this._container.style.bottom = this._containerBottom + 'px'; + this._container.style.left = this._containerLeft + 'px'; + }, + + _zoomAnimation: function (opt) { + var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center); + + L.DomUtil.setPosition(this._container, pos); + }, + + _adjustPan: function () { + if (!this.options.autoPan) { return; } + + var map = this._map, + containerHeight = this._container.offsetHeight, + containerWidth = this._containerWidth, + + layerPos = new L.Point(this._containerLeft, -containerHeight - this._containerBottom); + + if (this._animated) { + layerPos._add(L.DomUtil.getPosition(this._container)); + } + + var containerPos = map.layerPointToContainerPoint(layerPos), + padding = L.point(this.options.autoPanPadding), + paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding), + paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding), + size = map.getSize(), + dx = 0, + dy = 0; + + if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right + dx = containerPos.x + containerWidth - size.x + paddingBR.x; + } + if (containerPos.x - dx - paddingTL.x < 0) { // left + dx = containerPos.x - paddingTL.x; + } + if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom + dy = containerPos.y + containerHeight - size.y + paddingBR.y; + } + if (containerPos.y - dy - paddingTL.y < 0) { // top + dy = containerPos.y - paddingTL.y; + } + + if (dx || dy) { + map + .fire('autopanstart') + .panBy([dx, dy]); + } + }, + + _onCloseButtonClick: function (e) { + this._close(); + L.DomEvent.stop(e); + } +}); + +L.popup = function (options, source) { + return new L.Popup(options, source); +}; + + +L.Map.include({ + openPopup: function (popup, latlng, options) { // (Popup) or (String || HTMLElement, LatLng[, Object]) + this.closePopup(); + + if (!(popup instanceof L.Popup)) { + var content = popup; + + popup = new L.Popup(options) + .setLatLng(latlng) + .setContent(content); + } + popup._isOpen = true; + + this._popup = popup; + return this.addLayer(popup); + }, + + closePopup: function (popup) { + if (!popup || popup === this._popup) { + popup = this._popup; + this._popup = null; + } + if (popup) { + this.removeLayer(popup); + popup._isOpen = false; + } + return this; + } +}); + + +/* + * Popup extension to L.Marker, adding popup-related methods. + */ + +L.Marker.include({ + openPopup: function () { + if (this._popup && this._map && !this._map.hasLayer(this._popup)) { + this._popup.setLatLng(this._latlng); + this._map.openPopup(this._popup); + } + + return this; + }, + + closePopup: function () { + if (this._popup) { + this._popup._close(); + } + return this; + }, + + togglePopup: function () { + if (this._popup) { + if (this._popup._isOpen) { + this.closePopup(); + } else { + this.openPopup(); + } + } + return this; + }, + + bindPopup: function (content, options) { + var anchor = L.point(this.options.icon.options.popupAnchor || [0, 0]); + + anchor = anchor.add(L.Popup.prototype.options.offset); + + if (options && options.offset) { + anchor = anchor.add(options.offset); + } + + options = L.extend({offset: anchor}, options); + + if (!this._popupHandlersAdded) { + this + .on('click', this.togglePopup, this) + .on('remove', this.closePopup, this) + .on('move', this._movePopup, this); + this._popupHandlersAdded = true; + } + + if (content instanceof L.Popup) { + L.setOptions(content, options); + this._popup = content; + } else { + this._popup = new L.Popup(options, this) + .setContent(content); + } + + return this; + }, + + setPopupContent: function (content) { + if (this._popup) { + this._popup.setContent(content); + } + return this; + }, + + unbindPopup: function () { + if (this._popup) { + this._popup = null; + this + .off('click', this.togglePopup, this) + .off('remove', this.closePopup, this) + .off('move', this._movePopup, this); + this._popupHandlersAdded = false; + } + return this; + }, + + getPopup: function () { + return this._popup; + }, + + _movePopup: function (e) { + this._popup.setLatLng(e.latlng); + } +}); + + +/* + * L.LayerGroup is a class to combine several layers into one so that + * you can manipulate the group (e.g. add/remove it) as one layer. + */ + +L.LayerGroup = L.Class.extend({ + initialize: function (layers) { + this._layers = {}; + + var i, len; + + if (layers) { + for (i = 0, len = layers.length; i < len; i++) { + this.addLayer(layers[i]); + } + } + }, + + addLayer: function (layer) { + var id = this.getLayerId(layer); + + this._layers[id] = layer; + + if (this._map) { + this._map.addLayer(layer); + } + + return this; + }, + + removeLayer: function (layer) { + var id = layer in this._layers ? layer : this.getLayerId(layer); + + if (this._map && this._layers[id]) { + this._map.removeLayer(this._layers[id]); + } + + delete this._layers[id]; + + return this; + }, + + hasLayer: function (layer) { + if (!layer) { return false; } + + return (layer in this._layers || this.getLayerId(layer) in this._layers); + }, + + clearLayers: function () { + this.eachLayer(this.removeLayer, this); + return this; + }, + + invoke: function (methodName) { + var args = Array.prototype.slice.call(arguments, 1), + i, layer; + + for (i in this._layers) { + layer = this._layers[i]; + + if (layer[methodName]) { + layer[methodName].apply(layer, args); + } + } + + return this; + }, + + onAdd: function (map) { + this._map = map; + this.eachLayer(map.addLayer, map); + }, + + onRemove: function (map) { + this.eachLayer(map.removeLayer, map); + this._map = null; + }, + + addTo: function (map) { + map.addLayer(this); + return this; + }, + + eachLayer: function (method, context) { + for (var i in this._layers) { + method.call(context, this._layers[i]); + } + return this; + }, + + getLayer: function (id) { + return this._layers[id]; + }, + + getLayers: function () { + var layers = []; + + for (var i in this._layers) { + layers.push(this._layers[i]); + } + return layers; + }, + + setZIndex: function (zIndex) { + return this.invoke('setZIndex', zIndex); + }, + + getLayerId: function (layer) { + return L.stamp(layer); + } +}); + +L.layerGroup = function (layers) { + return new L.LayerGroup(layers); +}; + + +/* + * L.FeatureGroup extends L.LayerGroup by introducing mouse events and additional methods + * shared between a group of interactive layers (like vectors or markers). + */ + +L.FeatureGroup = L.LayerGroup.extend({ + includes: L.Mixin.Events, + + statics: { + EVENTS: 'click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose' + }, + + addLayer: function (layer) { + if (this.hasLayer(layer)) { + return this; + } + + if ('on' in layer) { + layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this); + } + + L.LayerGroup.prototype.addLayer.call(this, layer); + + if (this._popupContent && layer.bindPopup) { + layer.bindPopup(this._popupContent, this._popupOptions); + } + + return this.fire('layeradd', {layer: layer}); + }, + + removeLayer: function (layer) { + if (!this.hasLayer(layer)) { + return this; + } + if (layer in this._layers) { + layer = this._layers[layer]; + } + + layer.off(L.FeatureGroup.EVENTS, this._propagateEvent, this); + + L.LayerGroup.prototype.removeLayer.call(this, layer); + + if (this._popupContent) { + this.invoke('unbindPopup'); + } + + return this.fire('layerremove', {layer: layer}); + }, + + bindPopup: function (content, options) { + this._popupContent = content; + this._popupOptions = options; + return this.invoke('bindPopup', content, options); + }, + + openPopup: function (latlng) { + // open popup on the first layer + for (var id in this._layers) { + this._layers[id].openPopup(latlng); + break; + } + return this; + }, + + setStyle: function (style) { + return this.invoke('setStyle', style); + }, + + bringToFront: function () { + return this.invoke('bringToFront'); + }, + + bringToBack: function () { + return this.invoke('bringToBack'); + }, + + getBounds: function () { + var bounds = new L.LatLngBounds(); + + this.eachLayer(function (layer) { + bounds.extend(layer instanceof L.Marker ? layer.getLatLng() : layer.getBounds()); + }); + + return bounds; + }, + + _propagateEvent: function (e) { + e = L.extend({ + layer: e.target, + target: this + }, e); + this.fire(e.type, e); + } +}); + +L.featureGroup = function (layers) { + return new L.FeatureGroup(layers); +}; + + +/* + * L.Path is a base class for rendering vector paths on a map. Inherited by Polyline, Circle, etc. + */ + +L.Path = L.Class.extend({ + includes: [L.Mixin.Events], + + statics: { + // how much to extend the clip area around the map view + // (relative to its size, e.g. 0.5 is half the screen in each direction) + // set it so that SVG element doesn't exceed 1280px (vectors flicker on dragend if it is) + CLIP_PADDING: (function () { + var max = L.Browser.mobile ? 1280 : 2000, + target = (max / Math.max(window.outerWidth, window.outerHeight) - 1) / 2; + return Math.max(0, Math.min(0.5, target)); + })() + }, + + options: { + stroke: true, + color: '#0033ff', + dashArray: null, + lineCap: null, + lineJoin: null, + weight: 5, + opacity: 0.5, + + fill: false, + fillColor: null, //same as color by default + fillOpacity: 0.2, + + clickable: true + }, + + initialize: function (options) { + L.setOptions(this, options); + }, + + onAdd: function (map) { + this._map = map; + + if (!this._container) { + this._initElements(); + this._initEvents(); + } + + this.projectLatlngs(); + this._updatePath(); + + if (this._container) { + this._map._pathRoot.appendChild(this._container); + } + + this.fire('add'); + + map.on({ + 'viewreset': this.projectLatlngs, + 'moveend': this._updatePath + }, this); + }, + + addTo: function (map) { + map.addLayer(this); + return this; + }, + + onRemove: function (map) { + map._pathRoot.removeChild(this._container); + + // Need to fire remove event before we set _map to null as the event hooks might need the object + this.fire('remove'); + this._map = null; + + if (L.Browser.vml) { + this._container = null; + this._stroke = null; + this._fill = null; + } + + map.off({ + 'viewreset': this.projectLatlngs, + 'moveend': this._updatePath + }, this); + }, + + projectLatlngs: function () { + // do all projection stuff here + }, + + setStyle: function (style) { + L.setOptions(this, style); + + if (this._container) { + this._updateStyle(); + } + + return this; + }, + + redraw: function () { + if (this._map) { + this.projectLatlngs(); + this._updatePath(); + } + return this; + } +}); + +L.Map.include({ + _updatePathViewport: function () { + var p = L.Path.CLIP_PADDING, + size = this.getSize(), + panePos = L.DomUtil.getPosition(this._mapPane), + min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)._round()), + max = min.add(size.multiplyBy(1 + p * 2)._round()); + + this._pathViewport = new L.Bounds(min, max); + } +}); + + +/* + * Extends L.Path with SVG-specific rendering code. + */ + +L.Path.SVG_NS = 'http://www.w3.org/2000/svg'; + +L.Browser.svg = !!(document.createElementNS && document.createElementNS(L.Path.SVG_NS, 'svg').createSVGRect); + +L.Path = L.Path.extend({ + statics: { + SVG: L.Browser.svg + }, + + bringToFront: function () { + var root = this._map._pathRoot, + path = this._container; + + if (path && root.lastChild !== path) { + root.appendChild(path); + } + return this; + }, + + bringToBack: function () { + var root = this._map._pathRoot, + path = this._container, + first = root.firstChild; + + if (path && first !== path) { + root.insertBefore(path, first); + } + return this; + }, + + getPathString: function () { + // form path string here + }, + + _createElement: function (name) { + return document.createElementNS(L.Path.SVG_NS, name); + }, + + _initElements: function () { + this._map._initPathRoot(); + this._initPath(); + this._initStyle(); + }, + + _initPath: function () { + this._container = this._createElement('g'); + + this._path = this._createElement('path'); + + if (this.options.className) { + L.DomUtil.addClass(this._path, this.options.className); + } + + this._container.appendChild(this._path); + }, + + _initStyle: function () { + if (this.options.stroke) { + this._path.setAttribute('stroke-linejoin', 'round'); + this._path.setAttribute('stroke-linecap', 'round'); + } + if (this.options.fill) { + this._path.setAttribute('fill-rule', 'evenodd'); + } + if (this.options.pointerEvents) { + this._path.setAttribute('pointer-events', this.options.pointerEvents); + } + if (!this.options.clickable && !this.options.pointerEvents) { + this._path.setAttribute('pointer-events', 'none'); + } + this._updateStyle(); + }, + + _updateStyle: function () { + if (this.options.stroke) { + this._path.setAttribute('stroke', this.options.color); + this._path.setAttribute('stroke-opacity', this.options.opacity); + this._path.setAttribute('stroke-width', this.options.weight); + if (this.options.dashArray) { + this._path.setAttribute('stroke-dasharray', this.options.dashArray); + } else { + this._path.removeAttribute('stroke-dasharray'); + } + if (this.options.lineCap) { + this._path.setAttribute('stroke-linecap', this.options.lineCap); + } + if (this.options.lineJoin) { + this._path.setAttribute('stroke-linejoin', this.options.lineJoin); + } + } else { + this._path.setAttribute('stroke', 'none'); + } + if (this.options.fill) { + this._path.setAttribute('fill', this.options.fillColor || this.options.color); + this._path.setAttribute('fill-opacity', this.options.fillOpacity); + } else { + this._path.setAttribute('fill', 'none'); + } + }, + + _updatePath: function () { + var str = this.getPathString(); + if (!str) { + // fix webkit empty string parsing bug + str = 'M0 0'; + } + this._path.setAttribute('d', str); + }, + + // TODO remove duplication with L.Map + _initEvents: function () { + if (this.options.clickable) { + if (L.Browser.svg || !L.Browser.vml) { + L.DomUtil.addClass(this._path, 'leaflet-clickable'); + } + + L.DomEvent.on(this._container, 'click', this._onMouseClick, this); + + var events = ['dblclick', 'mousedown', 'mouseover', + 'mouseout', 'mousemove', 'contextmenu']; + for (var i = 0; i < events.length; i++) { + L.DomEvent.on(this._container, events[i], this._fireMouseEvent, this); + } + } + }, + + _onMouseClick: function (e) { + if (this._map.dragging && this._map.dragging.moved()) { return; } + + this._fireMouseEvent(e); + }, + + _fireMouseEvent: function (e) { + if (!this.hasEventListeners(e.type)) { return; } + + var map = this._map, + containerPoint = map.mouseEventToContainerPoint(e), + layerPoint = map.containerPointToLayerPoint(containerPoint), + latlng = map.layerPointToLatLng(layerPoint); + + this.fire(e.type, { + latlng: latlng, + layerPoint: layerPoint, + containerPoint: containerPoint, + originalEvent: e + }); + + if (e.type === 'contextmenu') { + L.DomEvent.preventDefault(e); + } + if (e.type !== 'mousemove') { + L.DomEvent.stopPropagation(e); + } + } +}); + +L.Map.include({ + _initPathRoot: function () { + if (!this._pathRoot) { + this._pathRoot = L.Path.prototype._createElement('svg'); + this._panes.overlayPane.appendChild(this._pathRoot); + + if (this.options.zoomAnimation && L.Browser.any3d) { + L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-animated'); + + this.on({ + 'zoomanim': this._animatePathZoom, + 'zoomend': this._endPathZoom + }); + } else { + L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-hide'); + } + + this.on('moveend', this._updateSvgViewport); + this._updateSvgViewport(); + } + }, + + _animatePathZoom: function (e) { + var scale = this.getZoomScale(e.zoom), + offset = this._getCenterOffset(e.center)._multiplyBy(-scale)._add(this._pathViewport.min); + + this._pathRoot.style[L.DomUtil.TRANSFORM] = + L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ') '; + + this._pathZooming = true; + }, + + _endPathZoom: function () { + this._pathZooming = false; + }, + + _updateSvgViewport: function () { + + if (this._pathZooming) { + // Do not update SVGs while a zoom animation is going on otherwise the animation will break. + // When the zoom animation ends we will be updated again anyway + // This fixes the case where you do a momentum move and zoom while the move is still ongoing. + return; + } + + this._updatePathViewport(); + + var vp = this._pathViewport, + min = vp.min, + max = vp.max, + width = max.x - min.x, + height = max.y - min.y, + root = this._pathRoot, + pane = this._panes.overlayPane; + + // Hack to make flicker on drag end on mobile webkit less irritating + if (L.Browser.mobileWebkit) { + pane.removeChild(root); + } + + L.DomUtil.setPosition(root, min); + root.setAttribute('width', width); + root.setAttribute('height', height); + root.setAttribute('viewBox', [min.x, min.y, width, height].join(' ')); + + if (L.Browser.mobileWebkit) { + pane.appendChild(root); + } + } +}); + + +/* + * Popup extension to L.Path (polylines, polygons, circles), adding popup-related methods. + */ + +L.Path.include({ + + bindPopup: function (content, options) { + + if (content instanceof L.Popup) { + this._popup = content; + } else { + if (!this._popup || options) { + this._popup = new L.Popup(options, this); + } + this._popup.setContent(content); + } + + if (!this._popupHandlersAdded) { + this + .on('click', this._openPopup, this) + .on('remove', this.closePopup, this); + + this._popupHandlersAdded = true; + } + + return this; + }, + + unbindPopup: function () { + if (this._popup) { + this._popup = null; + this + .off('click', this._openPopup) + .off('remove', this.closePopup); + + this._popupHandlersAdded = false; + } + return this; + }, + + openPopup: function (latlng) { + + if (this._popup) { + // open the popup from one of the path's points if not specified + latlng = latlng || this._latlng || + this._latlngs[Math.floor(this._latlngs.length / 2)]; + + this._openPopup({latlng: latlng}); + } + + return this; + }, + + closePopup: function () { + if (this._popup) { + this._popup._close(); + } + return this; + }, + + _openPopup: function (e) { + this._popup.setLatLng(e.latlng); + this._map.openPopup(this._popup); + } +}); + + +/* + * Vector rendering for IE6-8 through VML. + * Thanks to Dmitry Baranovsky and his Raphael library for inspiration! + */ + +L.Browser.vml = !L.Browser.svg && (function () { + try { + var div = document.createElement('div'); + div.innerHTML = ''; + + var shape = div.firstChild; + shape.style.behavior = 'url(#default#VML)'; + + return shape && (typeof shape.adj === 'object'); + + } catch (e) { + return false; + } +}()); + +L.Path = L.Browser.svg || !L.Browser.vml ? L.Path : L.Path.extend({ + statics: { + VML: true, + CLIP_PADDING: 0.02 + }, + + _createElement: (function () { + try { + document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml'); + return function (name) { + return document.createElement(''); + }; + } catch (e) { + return function (name) { + return document.createElement( + '<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">'); + }; + } + }()), + + _initPath: function () { + var container = this._container = this._createElement('shape'); + + L.DomUtil.addClass(container, 'leaflet-vml-shape' + + (this.options.className ? ' ' + this.options.className : '')); + + if (this.options.clickable) { + L.DomUtil.addClass(container, 'leaflet-clickable'); + } + + container.coordsize = '1 1'; + + this._path = this._createElement('path'); + container.appendChild(this._path); + + this._map._pathRoot.appendChild(container); + }, + + _initStyle: function () { + this._updateStyle(); + }, + + _updateStyle: function () { + var stroke = this._stroke, + fill = this._fill, + options = this.options, + container = this._container; + + container.stroked = options.stroke; + container.filled = options.fill; + + if (options.stroke) { + if (!stroke) { + stroke = this._stroke = this._createElement('stroke'); + stroke.endcap = 'round'; + container.appendChild(stroke); + } + stroke.weight = options.weight + 'px'; + stroke.color = options.color; + stroke.opacity = options.opacity; + + if (options.dashArray) { + stroke.dashStyle = L.Util.isArray(options.dashArray) ? + options.dashArray.join(' ') : + options.dashArray.replace(/( *, *)/g, ' '); + } else { + stroke.dashStyle = ''; + } + if (options.lineCap) { + stroke.endcap = options.lineCap.replace('butt', 'flat'); + } + if (options.lineJoin) { + stroke.joinstyle = options.lineJoin; + } + + } else if (stroke) { + container.removeChild(stroke); + this._stroke = null; + } + + if (options.fill) { + if (!fill) { + fill = this._fill = this._createElement('fill'); + container.appendChild(fill); + } + fill.color = options.fillColor || options.color; + fill.opacity = options.fillOpacity; + + } else if (fill) { + container.removeChild(fill); + this._fill = null; + } + }, + + _updatePath: function () { + var style = this._container.style; + + style.display = 'none'; + this._path.v = this.getPathString() + ' '; // the space fixes IE empty path string bug + style.display = ''; + } +}); + +L.Map.include(L.Browser.svg || !L.Browser.vml ? {} : { + _initPathRoot: function () { + if (this._pathRoot) { return; } + + var root = this._pathRoot = document.createElement('div'); + root.className = 'leaflet-vml-container'; + this._panes.overlayPane.appendChild(root); + + this.on('moveend', this._updatePathViewport); + this._updatePathViewport(); + } +}); + + +/* + * Vector rendering for all browsers that support canvas. + */ + +L.Browser.canvas = (function () { + return !!document.createElement('canvas').getContext; +}()); + +L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({ + statics: { + //CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value + CANVAS: true, + SVG: false + }, + + redraw: function () { + if (this._map) { + this.projectLatlngs(); + this._requestUpdate(); + } + return this; + }, + + setStyle: function (style) { + L.setOptions(this, style); + + if (this._map) { + this._updateStyle(); + this._requestUpdate(); + } + return this; + }, + + onRemove: function (map) { + map + .off('viewreset', this.projectLatlngs, this) + .off('moveend', this._updatePath, this); + + if (this.options.clickable) { + this._map.off('click', this._onClick, this); + this._map.off('mousemove', this._onMouseMove, this); + } + + this._requestUpdate(); + + this.fire('remove'); + this._map = null; + }, + + _requestUpdate: function () { + if (this._map && !L.Path._updateRequest) { + L.Path._updateRequest = L.Util.requestAnimFrame(this._fireMapMoveEnd, this._map); + } + }, + + _fireMapMoveEnd: function () { + L.Path._updateRequest = null; + this.fire('moveend'); + }, + + _initElements: function () { + this._map._initPathRoot(); + this._ctx = this._map._canvasCtx; + }, + + _updateStyle: function () { + var options = this.options; + + if (options.stroke) { + this._ctx.lineWidth = options.weight; + this._ctx.strokeStyle = options.color; + } + if (options.fill) { + this._ctx.fillStyle = options.fillColor || options.color; + } + }, + + _drawPath: function () { + var i, j, len, len2, point, drawMethod; + + this._ctx.beginPath(); + + for (i = 0, len = this._parts.length; i < len; i++) { + for (j = 0, len2 = this._parts[i].length; j < len2; j++) { + point = this._parts[i][j]; + drawMethod = (j === 0 ? 'move' : 'line') + 'To'; + + this._ctx[drawMethod](point.x, point.y); + } + // TODO refactor ugly hack + if (this instanceof L.Polygon) { + this._ctx.closePath(); + } + } + }, + + _checkIfEmpty: function () { + return !this._parts.length; + }, + + _updatePath: function () { + if (this._checkIfEmpty()) { return; } + + var ctx = this._ctx, + options = this.options; + + this._drawPath(); + ctx.save(); + this._updateStyle(); + + if (options.fill) { + ctx.globalAlpha = options.fillOpacity; + ctx.fill(); + } + + if (options.stroke) { + ctx.globalAlpha = options.opacity; + ctx.stroke(); + } + + ctx.restore(); + + // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature + }, + + _initEvents: function () { + if (this.options.clickable) { + // TODO dblclick + this._map.on('mousemove', this._onMouseMove, this); + this._map.on('click', this._onClick, this); + } + }, + + _onClick: function (e) { + if (this._containsPoint(e.layerPoint)) { + this.fire('click', e); + } + }, + + _onMouseMove: function (e) { + if (!this._map || this._map._animatingZoom) { return; } + + // TODO don't do on each move + if (this._containsPoint(e.layerPoint)) { + this._ctx.canvas.style.cursor = 'pointer'; + this._mouseInside = true; + this.fire('mouseover', e); + + } else if (this._mouseInside) { + this._ctx.canvas.style.cursor = ''; + this._mouseInside = false; + this.fire('mouseout', e); + } + } +}); + +L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : { + _initPathRoot: function () { + var root = this._pathRoot, + ctx; + + if (!root) { + root = this._pathRoot = document.createElement('canvas'); + root.style.position = 'absolute'; + ctx = this._canvasCtx = root.getContext('2d'); + + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + + this._panes.overlayPane.appendChild(root); + + if (this.options.zoomAnimation) { + this._pathRoot.className = 'leaflet-zoom-animated'; + this.on('zoomanim', this._animatePathZoom); + this.on('zoomend', this._endPathZoom); + } + this.on('moveend', this._updateCanvasViewport); + this._updateCanvasViewport(); + } + }, + + _updateCanvasViewport: function () { + // don't redraw while zooming. See _updateSvgViewport for more details + if (this._pathZooming) { return; } + this._updatePathViewport(); + + var vp = this._pathViewport, + min = vp.min, + size = vp.max.subtract(min), + root = this._pathRoot; + + //TODO check if this works properly on mobile webkit + L.DomUtil.setPosition(root, min); + root.width = size.x; + root.height = size.y; + root.getContext('2d').translate(-min.x, -min.y); + } +}); + + +/* + * L.LineUtil contains different utility functions for line segments + * and polylines (clipping, simplification, distances, etc.) + */ + +/*jshint bitwise:false */ // allow bitwise operations for this file + +L.LineUtil = { + + // Simplify polyline with vertex reduction and Douglas-Peucker simplification. + // Improves rendering performance dramatically by lessening the number of points to draw. + + simplify: function (/*Point[]*/ points, /*Number*/ tolerance) { + if (!tolerance || !points.length) { + return points.slice(); + } + + var sqTolerance = tolerance * tolerance; + + // stage 1: vertex reduction + points = this._reducePoints(points, sqTolerance); + + // stage 2: Douglas-Peucker simplification + points = this._simplifyDP(points, sqTolerance); + + return points; + }, + + // distance from a point to a segment between two points + pointToSegmentDistance: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { + return Math.sqrt(this._sqClosestPointOnSegment(p, p1, p2, true)); + }, + + closestPointOnSegment: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { + return this._sqClosestPointOnSegment(p, p1, p2); + }, + + // Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm + _simplifyDP: function (points, sqTolerance) { + + var len = points.length, + ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array, + markers = new ArrayConstructor(len); + + markers[0] = markers[len - 1] = 1; + + this._simplifyDPStep(points, markers, sqTolerance, 0, len - 1); + + var i, + newPoints = []; + + for (i = 0; i < len; i++) { + if (markers[i]) { + newPoints.push(points[i]); + } + } + + return newPoints; + }, + + _simplifyDPStep: function (points, markers, sqTolerance, first, last) { + + var maxSqDist = 0, + index, i, sqDist; + + for (i = first + 1; i <= last - 1; i++) { + sqDist = this._sqClosestPointOnSegment(points[i], points[first], points[last], true); + + if (sqDist > maxSqDist) { + index = i; + maxSqDist = sqDist; + } + } + + if (maxSqDist > sqTolerance) { + markers[index] = 1; + + this._simplifyDPStep(points, markers, sqTolerance, first, index); + this._simplifyDPStep(points, markers, sqTolerance, index, last); + } + }, + + // reduce points that are too close to each other to a single point + _reducePoints: function (points, sqTolerance) { + var reducedPoints = [points[0]]; + + for (var i = 1, prev = 0, len = points.length; i < len; i++) { + if (this._sqDist(points[i], points[prev]) > sqTolerance) { + reducedPoints.push(points[i]); + prev = i; + } + } + if (prev < len - 1) { + reducedPoints.push(points[len - 1]); + } + return reducedPoints; + }, + + // Cohen-Sutherland line clipping algorithm. + // Used to avoid rendering parts of a polyline that are not currently visible. + + clipSegment: function (a, b, bounds, useLastCode) { + var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds), + codeB = this._getBitCode(b, bounds), + + codeOut, p, newCode; + + // save 2nd code to avoid calculating it on the next segment + this._lastCode = codeB; + + while (true) { + // if a,b is inside the clip window (trivial accept) + if (!(codeA | codeB)) { + return [a, b]; + // if a,b is outside the clip window (trivial reject) + } else if (codeA & codeB) { + return false; + // other cases + } else { + codeOut = codeA || codeB; + p = this._getEdgeIntersection(a, b, codeOut, bounds); + newCode = this._getBitCode(p, bounds); + + if (codeOut === codeA) { + a = p; + codeA = newCode; + } else { + b = p; + codeB = newCode; + } + } + } + }, + + _getEdgeIntersection: function (a, b, code, bounds) { + var dx = b.x - a.x, + dy = b.y - a.y, + min = bounds.min, + max = bounds.max; + + if (code & 8) { // top + return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y); + } else if (code & 4) { // bottom + return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y); + } else if (code & 2) { // right + return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx); + } else if (code & 1) { // left + return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx); + } + }, + + _getBitCode: function (/*Point*/ p, bounds) { + var code = 0; + + if (p.x < bounds.min.x) { // left + code |= 1; + } else if (p.x > bounds.max.x) { // right + code |= 2; + } + if (p.y < bounds.min.y) { // bottom + code |= 4; + } else if (p.y > bounds.max.y) { // top + code |= 8; + } + + return code; + }, + + // square distance (to avoid unnecessary Math.sqrt calls) + _sqDist: function (p1, p2) { + var dx = p2.x - p1.x, + dy = p2.y - p1.y; + return dx * dx + dy * dy; + }, + + // return closest point on segment or distance to that point + _sqClosestPointOnSegment: function (p, p1, p2, sqDist) { + var x = p1.x, + y = p1.y, + dx = p2.x - x, + dy = p2.y - y, + dot = dx * dx + dy * dy, + t; + + if (dot > 0) { + t = ((p.x - x) * dx + (p.y - y) * dy) / dot; + + if (t > 1) { + x = p2.x; + y = p2.y; + } else if (t > 0) { + x += dx * t; + y += dy * t; + } + } + + dx = p.x - x; + dy = p.y - y; + + return sqDist ? dx * dx + dy * dy : new L.Point(x, y); + } +}; + + +/* + * L.Polyline is used to display polylines on a map. + */ + +L.Polyline = L.Path.extend({ + initialize: function (latlngs, options) { + L.Path.prototype.initialize.call(this, options); + + this._latlngs = this._convertLatLngs(latlngs); + }, + + options: { + // how much to simplify the polyline on each zoom level + // more = better performance and smoother look, less = more accurate + smoothFactor: 1.0, + noClip: false + }, + + projectLatlngs: function () { + this._originalPoints = []; + + for (var i = 0, len = this._latlngs.length; i < len; i++) { + this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]); + } + }, + + getPathString: function () { + for (var i = 0, len = this._parts.length, str = ''; i < len; i++) { + str += this._getPathPartStr(this._parts[i]); + } + return str; + }, + + getLatLngs: function () { + return this._latlngs; + }, + + setLatLngs: function (latlngs) { + this._latlngs = this._convertLatLngs(latlngs); + return this.redraw(); + }, + + addLatLng: function (latlng) { + this._latlngs.push(L.latLng(latlng)); + return this.redraw(); + }, + + spliceLatLngs: function () { // (Number index, Number howMany) + var removed = [].splice.apply(this._latlngs, arguments); + this._convertLatLngs(this._latlngs, true); + this.redraw(); + return removed; + }, + + closestLayerPoint: function (p) { + var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null; + + for (var j = 0, jLen = parts.length; j < jLen; j++) { + var points = parts[j]; + for (var i = 1, len = points.length; i < len; i++) { + p1 = points[i - 1]; + p2 = points[i]; + var sqDist = L.LineUtil._sqClosestPointOnSegment(p, p1, p2, true); + if (sqDist < minDistance) { + minDistance = sqDist; + minPoint = L.LineUtil._sqClosestPointOnSegment(p, p1, p2); + } + } + } + if (minPoint) { + minPoint.distance = Math.sqrt(minDistance); + } + return minPoint; + }, + + getBounds: function () { + return new L.LatLngBounds(this.getLatLngs()); + }, + + _convertLatLngs: function (latlngs, overwrite) { + var i, len, target = overwrite ? latlngs : []; + + for (i = 0, len = latlngs.length; i < len; i++) { + if (L.Util.isArray(latlngs[i]) && typeof latlngs[i][0] !== 'number') { + return; + } + target[i] = L.latLng(latlngs[i]); + } + return target; + }, + + _initEvents: function () { + L.Path.prototype._initEvents.call(this); + }, + + _getPathPartStr: function (points) { + var round = L.Path.VML; + + for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) { + p = points[j]; + if (round) { + p._round(); + } + str += (j ? 'L' : 'M') + p.x + ' ' + p.y; + } + return str; + }, + + _clipPoints: function () { + var points = this._originalPoints, + len = points.length, + i, k, segment; + + if (this.options.noClip) { + this._parts = [points]; + return; + } + + this._parts = []; + + var parts = this._parts, + vp = this._map._pathViewport, + lu = L.LineUtil; + + for (i = 0, k = 0; i < len - 1; i++) { + segment = lu.clipSegment(points[i], points[i + 1], vp, i); + if (!segment) { + continue; + } + + parts[k] = parts[k] || []; + parts[k].push(segment[0]); + + // if segment goes out of screen, or it's the last one, it's the end of the line part + if ((segment[1] !== points[i + 1]) || (i === len - 2)) { + parts[k].push(segment[1]); + k++; + } + } + }, + + // simplify each clipped part of the polyline + _simplifyPoints: function () { + var parts = this._parts, + lu = L.LineUtil; + + for (var i = 0, len = parts.length; i < len; i++) { + parts[i] = lu.simplify(parts[i], this.options.smoothFactor); + } + }, + + _updatePath: function () { + if (!this._map) { return; } + + this._clipPoints(); + this._simplifyPoints(); + + L.Path.prototype._updatePath.call(this); + } +}); + +L.polyline = function (latlngs, options) { + return new L.Polyline(latlngs, options); +}; + + +/* + * L.PolyUtil contains utility functions for polygons (clipping, etc.). + */ + +/*jshint bitwise:false */ // allow bitwise operations here + +L.PolyUtil = {}; + +/* + * Sutherland-Hodgeman polygon clipping algorithm. + * Used to avoid rendering parts of a polygon that are not currently visible. + */ +L.PolyUtil.clipPolygon = function (points, bounds) { + var clippedPoints, + edges = [1, 4, 2, 8], + i, j, k, + a, b, + len, edge, p, + lu = L.LineUtil; + + for (i = 0, len = points.length; i < len; i++) { + points[i]._code = lu._getBitCode(points[i], bounds); + } + + // for each edge (left, bottom, right, top) + for (k = 0; k < 4; k++) { + edge = edges[k]; + clippedPoints = []; + + for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { + a = points[i]; + b = points[j]; + + // if a is inside the clip window + if (!(a._code & edge)) { + // if b is outside the clip window (a->b goes out of screen) + if (b._code & edge) { + p = lu._getEdgeIntersection(b, a, edge, bounds); + p._code = lu._getBitCode(p, bounds); + clippedPoints.push(p); + } + clippedPoints.push(a); + + // else if b is inside the clip window (a->b enters the screen) + } else if (!(b._code & edge)) { + p = lu._getEdgeIntersection(b, a, edge, bounds); + p._code = lu._getBitCode(p, bounds); + clippedPoints.push(p); + } + } + points = clippedPoints; + } + + return points; +}; + + +/* + * L.Polygon is used to display polygons on a map. + */ + +L.Polygon = L.Polyline.extend({ + options: { + fill: true + }, + + initialize: function (latlngs, options) { + L.Polyline.prototype.initialize.call(this, latlngs, options); + this._initWithHoles(latlngs); + }, + + _initWithHoles: function (latlngs) { + var i, len, hole; + if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { + this._latlngs = this._convertLatLngs(latlngs[0]); + this._holes = latlngs.slice(1); + + for (i = 0, len = this._holes.length; i < len; i++) { + hole = this._holes[i] = this._convertLatLngs(this._holes[i]); + if (hole[0].equals(hole[hole.length - 1])) { + hole.pop(); + } + } + } + + // filter out last point if its equal to the first one + latlngs = this._latlngs; + + if (latlngs.length >= 2 && latlngs[0].equals(latlngs[latlngs.length - 1])) { + latlngs.pop(); + } + }, + + projectLatlngs: function () { + L.Polyline.prototype.projectLatlngs.call(this); + + // project polygon holes points + // TODO move this logic to Polyline to get rid of duplication + this._holePoints = []; + + if (!this._holes) { return; } + + var i, j, len, len2; + + for (i = 0, len = this._holes.length; i < len; i++) { + this._holePoints[i] = []; + + for (j = 0, len2 = this._holes[i].length; j < len2; j++) { + this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]); + } + } + }, + + setLatLngs: function (latlngs) { + if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { + this._initWithHoles(latlngs); + return this.redraw(); + } else { + return L.Polyline.prototype.setLatLngs.call(this, latlngs); + } + }, + + _clipPoints: function () { + var points = this._originalPoints, + newParts = []; + + this._parts = [points].concat(this._holePoints); + + if (this.options.noClip) { return; } + + for (var i = 0, len = this._parts.length; i < len; i++) { + var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport); + if (clipped.length) { + newParts.push(clipped); + } + } + + this._parts = newParts; + }, + + _getPathPartStr: function (points) { + var str = L.Polyline.prototype._getPathPartStr.call(this, points); + return str + (L.Browser.svg ? 'z' : 'x'); + } +}); + +L.polygon = function (latlngs, options) { + return new L.Polygon(latlngs, options); +}; + + +/* + * Contains L.MultiPolyline and L.MultiPolygon layers. + */ + +(function () { + function createMulti(Klass) { + + return L.FeatureGroup.extend({ + + initialize: function (latlngs, options) { + this._layers = {}; + this._options = options; + this.setLatLngs(latlngs); + }, + + setLatLngs: function (latlngs) { + var i = 0, + len = latlngs.length; + + this.eachLayer(function (layer) { + if (i < len) { + layer.setLatLngs(latlngs[i++]); + } else { + this.removeLayer(layer); + } + }, this); + + while (i < len) { + this.addLayer(new Klass(latlngs[i++], this._options)); + } + + return this; + }, + + getLatLngs: function () { + var latlngs = []; + + this.eachLayer(function (layer) { + latlngs.push(layer.getLatLngs()); + }); + + return latlngs; + } + }); + } + + L.MultiPolyline = createMulti(L.Polyline); + L.MultiPolygon = createMulti(L.Polygon); + + L.multiPolyline = function (latlngs, options) { + return new L.MultiPolyline(latlngs, options); + }; + + L.multiPolygon = function (latlngs, options) { + return new L.MultiPolygon(latlngs, options); + }; +}()); + + +/* + * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object. + */ + +L.Rectangle = L.Polygon.extend({ + initialize: function (latLngBounds, options) { + L.Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options); + }, + + setBounds: function (latLngBounds) { + this.setLatLngs(this._boundsToLatLngs(latLngBounds)); + }, + + _boundsToLatLngs: function (latLngBounds) { + latLngBounds = L.latLngBounds(latLngBounds); + return [ + latLngBounds.getSouthWest(), + latLngBounds.getNorthWest(), + latLngBounds.getNorthEast(), + latLngBounds.getSouthEast() + ]; + } +}); + +L.rectangle = function (latLngBounds, options) { + return new L.Rectangle(latLngBounds, options); +}; + + +/* + * L.Circle is a circle overlay (with a certain radius in meters). + */ + +L.Circle = L.Path.extend({ + initialize: function (latlng, radius, options) { + L.Path.prototype.initialize.call(this, options); + + this._latlng = L.latLng(latlng); + this._mRadius = radius; + }, + + options: { + fill: true + }, + + setLatLng: function (latlng) { + this._latlng = L.latLng(latlng); + return this.redraw(); + }, + + setRadius: function (radius) { + this._mRadius = radius; + return this.redraw(); + }, + + projectLatlngs: function () { + var lngRadius = this._getLngRadius(), + latlng = this._latlng, + pointLeft = this._map.latLngToLayerPoint([latlng.lat, latlng.lng - lngRadius]); + + this._point = this._map.latLngToLayerPoint(latlng); + this._radius = Math.max(this._point.x - pointLeft.x, 1); + }, + + getBounds: function () { + var lngRadius = this._getLngRadius(), + latRadius = (this._mRadius / 40075017) * 360, + latlng = this._latlng; + + return new L.LatLngBounds( + [latlng.lat - latRadius, latlng.lng - lngRadius], + [latlng.lat + latRadius, latlng.lng + lngRadius]); + }, + + getLatLng: function () { + return this._latlng; + }, + + getPathString: function () { + var p = this._point, + r = this._radius; + + if (this._checkIfEmpty()) { + return ''; + } + + if (L.Browser.svg) { + return 'M' + p.x + ',' + (p.y - r) + + 'A' + r + ',' + r + ',0,1,1,' + + (p.x - 0.1) + ',' + (p.y - r) + ' z'; + } else { + p._round(); + r = Math.round(r); + return 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r + ' 0,' + (65535 * 360); + } + }, + + getRadius: function () { + return this._mRadius; + }, + + // TODO Earth hardcoded, move into projection code! + + _getLatRadius: function () { + return (this._mRadius / 40075017) * 360; + }, + + _getLngRadius: function () { + return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat); + }, + + _checkIfEmpty: function () { + if (!this._map) { + return false; + } + var vp = this._map._pathViewport, + r = this._radius, + p = this._point; + + return p.x - r > vp.max.x || p.y - r > vp.max.y || + p.x + r < vp.min.x || p.y + r < vp.min.y; + } +}); + +L.circle = function (latlng, radius, options) { + return new L.Circle(latlng, radius, options); +}; + + +/* + * L.CircleMarker is a circle overlay with a permanent pixel radius. + */ + +L.CircleMarker = L.Circle.extend({ + options: { + radius: 10, + weight: 2 + }, + + initialize: function (latlng, options) { + L.Circle.prototype.initialize.call(this, latlng, null, options); + this._radius = this.options.radius; + }, + + projectLatlngs: function () { + this._point = this._map.latLngToLayerPoint(this._latlng); + }, + + _updateStyle : function () { + L.Circle.prototype._updateStyle.call(this); + this.setRadius(this.options.radius); + }, + + setLatLng: function (latlng) { + L.Circle.prototype.setLatLng.call(this, latlng); + if (this._popup && this._popup._isOpen) { + this._popup.setLatLng(latlng); + } + return this; + }, + + setRadius: function (radius) { + this.options.radius = this._radius = radius; + return this.redraw(); + }, + + getRadius: function () { + return this._radius; + } +}); + +L.circleMarker = function (latlng, options) { + return new L.CircleMarker(latlng, options); +}; + + +/* + * Extends L.Polyline to be able to manually detect clicks on Canvas-rendered polylines. + */ + +L.Polyline.include(!L.Path.CANVAS ? {} : { + _containsPoint: function (p, closed) { + var i, j, k, len, len2, dist, part, + w = this.options.weight / 2; + + if (L.Browser.touch) { + w += 10; // polyline click tolerance on touch devices + } + + for (i = 0, len = this._parts.length; i < len; i++) { + part = this._parts[i]; + for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { + if (!closed && (j === 0)) { + continue; + } + + dist = L.LineUtil.pointToSegmentDistance(p, part[k], part[j]); + + if (dist <= w) { + return true; + } + } + } + return false; + } +}); + + +/* + * Extends L.Polygon to be able to manually detect clicks on Canvas-rendered polygons. + */ + +L.Polygon.include(!L.Path.CANVAS ? {} : { + _containsPoint: function (p) { + var inside = false, + part, p1, p2, + i, j, k, + len, len2; + + // TODO optimization: check if within bounds first + + if (L.Polyline.prototype._containsPoint.call(this, p, true)) { + // click on polygon border + return true; + } + + // ray casting algorithm for detecting if point is in polygon + + for (i = 0, len = this._parts.length; i < len; i++) { + part = this._parts[i]; + + for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { + p1 = part[j]; + p2 = part[k]; + + if (((p1.y > p.y) !== (p2.y > p.y)) && + (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) { + inside = !inside; + } + } + } + + return inside; + } +}); + + +/* + * Extends L.Circle with Canvas-specific code. + */ + +L.Circle.include(!L.Path.CANVAS ? {} : { + _drawPath: function () { + var p = this._point; + this._ctx.beginPath(); + this._ctx.arc(p.x, p.y, this._radius, 0, Math.PI * 2, false); + }, + + _containsPoint: function (p) { + var center = this._point, + w2 = this.options.stroke ? this.options.weight / 2 : 0; + + return (p.distanceTo(center) <= this._radius + w2); + } +}); + + +/* + * CircleMarker canvas specific drawing parts. + */ + +L.CircleMarker.include(!L.Path.CANVAS ? {} : { + _updateStyle: function () { + L.Path.prototype._updateStyle.call(this); + } +}); + + +/* + * L.GeoJSON turns any GeoJSON data into a Leaflet layer. + */ + +L.GeoJSON = L.FeatureGroup.extend({ + + initialize: function (geojson, options) { + L.setOptions(this, options); + + this._layers = {}; + + if (geojson) { + this.addData(geojson); + } + }, + + addData: function (geojson) { + var features = L.Util.isArray(geojson) ? geojson : geojson.features, + i, len, feature; + + if (features) { + for (i = 0, len = features.length; i < len; i++) { + // Only add this if geometry or geometries are set and not null + feature = features[i]; + if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { + this.addData(features[i]); + } + } + return this; + } + + var options = this.options; + + if (options.filter && !options.filter(geojson)) { return; } + + var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng, options); + layer.feature = L.GeoJSON.asFeature(geojson); + + layer.defaultOptions = layer.options; + this.resetStyle(layer); + + if (options.onEachFeature) { + options.onEachFeature(geojson, layer); + } + + return this.addLayer(layer); + }, + + resetStyle: function (layer) { + var style = this.options.style; + if (style) { + // reset any custom styles + L.Util.extend(layer.options, layer.defaultOptions); + + this._setLayerStyle(layer, style); + } + }, + + setStyle: function (style) { + this.eachLayer(function (layer) { + this._setLayerStyle(layer, style); + }, this); + }, + + _setLayerStyle: function (layer, style) { + if (typeof style === 'function') { + style = style(layer.feature); + } + if (layer.setStyle) { + layer.setStyle(style); + } + } +}); + +L.extend(L.GeoJSON, { + geometryToLayer: function (geojson, pointToLayer, coordsToLatLng, vectorOptions) { + var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, + coords = geometry.coordinates, + layers = [], + latlng, latlngs, i, len; + + coordsToLatLng = coordsToLatLng || this.coordsToLatLng; + + switch (geometry.type) { + case 'Point': + latlng = coordsToLatLng(coords); + return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng); + + case 'MultiPoint': + for (i = 0, len = coords.length; i < len; i++) { + latlng = coordsToLatLng(coords[i]); + layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng)); + } + return new L.FeatureGroup(layers); + + case 'LineString': + latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng); + return new L.Polyline(latlngs, vectorOptions); + + case 'Polygon': + if (coords.length === 2 && !coords[1].length) { + throw new Error('Invalid GeoJSON object.'); + } + latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); + return new L.Polygon(latlngs, vectorOptions); + + case 'MultiLineString': + latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); + return new L.MultiPolyline(latlngs, vectorOptions); + + case 'MultiPolygon': + latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng); + return new L.MultiPolygon(latlngs, vectorOptions); + + case 'GeometryCollection': + for (i = 0, len = geometry.geometries.length; i < len; i++) { + + layers.push(this.geometryToLayer({ + geometry: geometry.geometries[i], + type: 'Feature', + properties: geojson.properties + }, pointToLayer, coordsToLatLng, vectorOptions)); + } + return new L.FeatureGroup(layers); + + default: + throw new Error('Invalid GeoJSON object.'); + } + }, + + coordsToLatLng: function (coords) { // (Array[, Boolean]) -> LatLng + return new L.LatLng(coords[1], coords[0], coords[2]); + }, + + coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) { // (Array[, Number, Function]) -> Array + var latlng, i, len, + latlngs = []; + + for (i = 0, len = coords.length; i < len; i++) { + latlng = levelsDeep ? + this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) : + (coordsToLatLng || this.coordsToLatLng)(coords[i]); + + latlngs.push(latlng); + } + + return latlngs; + }, + + latLngToCoords: function (latlng) { + var coords = [latlng.lng, latlng.lat]; + + if (latlng.alt !== undefined) { + coords.push(latlng.alt); + } + return coords; + }, + + latLngsToCoords: function (latLngs) { + var coords = []; + + for (var i = 0, len = latLngs.length; i < len; i++) { + coords.push(L.GeoJSON.latLngToCoords(latLngs[i])); + } + + return coords; + }, + + getFeature: function (layer, newGeometry) { + return layer.feature ? L.extend({}, layer.feature, {geometry: newGeometry}) : L.GeoJSON.asFeature(newGeometry); + }, + + asFeature: function (geoJSON) { + if (geoJSON.type === 'Feature') { + return geoJSON; + } + + return { + type: 'Feature', + properties: {}, + geometry: geoJSON + }; + } +}); + +var PointToGeoJSON = { + toGeoJSON: function () { + return L.GeoJSON.getFeature(this, { + type: 'Point', + coordinates: L.GeoJSON.latLngToCoords(this.getLatLng()) + }); + } +}; + +L.Marker.include(PointToGeoJSON); +L.Circle.include(PointToGeoJSON); +L.CircleMarker.include(PointToGeoJSON); + +L.Polyline.include({ + toGeoJSON: function () { + return L.GeoJSON.getFeature(this, { + type: 'LineString', + coordinates: L.GeoJSON.latLngsToCoords(this.getLatLngs()) + }); + } +}); + +L.Polygon.include({ + toGeoJSON: function () { + var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())], + i, len, hole; + + coords[0].push(coords[0][0]); + + if (this._holes) { + for (i = 0, len = this._holes.length; i < len; i++) { + hole = L.GeoJSON.latLngsToCoords(this._holes[i]); + hole.push(hole[0]); + coords.push(hole); + } + } + + return L.GeoJSON.getFeature(this, { + type: 'Polygon', + coordinates: coords + }); + } +}); + +(function () { + function multiToGeoJSON(type) { + return function () { + var coords = []; + + this.eachLayer(function (layer) { + coords.push(layer.toGeoJSON().geometry.coordinates); + }); + + return L.GeoJSON.getFeature(this, { + type: type, + coordinates: coords + }); + }; + } + + L.MultiPolyline.include({toGeoJSON: multiToGeoJSON('MultiLineString')}); + L.MultiPolygon.include({toGeoJSON: multiToGeoJSON('MultiPolygon')}); + + L.LayerGroup.include({ + toGeoJSON: function () { + + var geometry = this.feature && this.feature.geometry, + jsons = [], + json; + + if (geometry && geometry.type === 'MultiPoint') { + return multiToGeoJSON('MultiPoint').call(this); + } + + var isGeometryCollection = geometry && geometry.type === 'GeometryCollection'; + + this.eachLayer(function (layer) { + if (layer.toGeoJSON) { + json = layer.toGeoJSON(); + jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json)); + } + }); + + if (isGeometryCollection) { + return L.GeoJSON.getFeature(this, { + geometries: jsons, + type: 'GeometryCollection' + }); + } + + return { + type: 'FeatureCollection', + features: jsons + }; + } + }); +}()); + +L.geoJson = function (geojson, options) { + return new L.GeoJSON(geojson, options); +}; + + +/* + * L.DomEvent contains functions for working with DOM events. + */ + +L.DomEvent = { + /* inspired by John Resig, Dean Edwards and YUI addEvent implementations */ + addListener: function (obj, type, fn, context) { // (HTMLElement, String, Function[, Object]) + + var id = L.stamp(fn), + key = '_leaflet_' + type + id, + handler, originalHandler, newType; + + if (obj[key]) { return this; } + + handler = function (e) { + return fn.call(context || obj, e || L.DomEvent._getEvent()); + }; + + if (L.Browser.pointer && type.indexOf('touch') === 0) { + return this.addPointerListener(obj, type, handler, id); + } + if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) { + this.addDoubleTapListener(obj, handler, id); + } + + if ('addEventListener' in obj) { + + if (type === 'mousewheel') { + obj.addEventListener('DOMMouseScroll', handler, false); + obj.addEventListener(type, handler, false); + + } else if ((type === 'mouseenter') || (type === 'mouseleave')) { + + originalHandler = handler; + newType = (type === 'mouseenter' ? 'mouseover' : 'mouseout'); + + handler = function (e) { + if (!L.DomEvent._checkMouse(obj, e)) { return; } + return originalHandler(e); + }; + + obj.addEventListener(newType, handler, false); + + } else if (type === 'click' && L.Browser.android) { + originalHandler = handler; + handler = function (e) { + return L.DomEvent._filterClick(e, originalHandler); + }; + + obj.addEventListener(type, handler, false); + } else { + obj.addEventListener(type, handler, false); + } + + } else if ('attachEvent' in obj) { + obj.attachEvent('on' + type, handler); + } + + obj[key] = handler; + + return this; + }, + + removeListener: function (obj, type, fn) { // (HTMLElement, String, Function) + + var id = L.stamp(fn), + key = '_leaflet_' + type + id, + handler = obj[key]; + + if (!handler) { return this; } + + if (L.Browser.pointer && type.indexOf('touch') === 0) { + this.removePointerListener(obj, type, id); + } else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) { + this.removeDoubleTapListener(obj, id); + + } else if ('removeEventListener' in obj) { + + if (type === 'mousewheel') { + obj.removeEventListener('DOMMouseScroll', handler, false); + obj.removeEventListener(type, handler, false); + + } else if ((type === 'mouseenter') || (type === 'mouseleave')) { + obj.removeEventListener((type === 'mouseenter' ? 'mouseover' : 'mouseout'), handler, false); + } else { + obj.removeEventListener(type, handler, false); + } + } else if ('detachEvent' in obj) { + obj.detachEvent('on' + type, handler); + } + + obj[key] = null; + + return this; + }, + + stopPropagation: function (e) { + + if (e.stopPropagation) { + e.stopPropagation(); + } else { + e.cancelBubble = true; + } + L.DomEvent._skipped(e); + + return this; + }, + + disableScrollPropagation: function (el) { + var stop = L.DomEvent.stopPropagation; + + return L.DomEvent + .on(el, 'mousewheel', stop) + .on(el, 'MozMousePixelScroll', stop); + }, + + disableClickPropagation: function (el) { + var stop = L.DomEvent.stopPropagation; + + for (var i = L.Draggable.START.length - 1; i >= 0; i--) { + L.DomEvent.on(el, L.Draggable.START[i], stop); + } + + return L.DomEvent + .on(el, 'click', L.DomEvent._fakeStop) + .on(el, 'dblclick', stop); + }, + + preventDefault: function (e) { + + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + return this; + }, + + stop: function (e) { + return L.DomEvent + .preventDefault(e) + .stopPropagation(e); + }, + + getMousePosition: function (e, container) { + if (!container) { + return new L.Point(e.clientX, e.clientY); + } + + var rect = container.getBoundingClientRect(); + + return new L.Point( + e.clientX - rect.left - container.clientLeft, + e.clientY - rect.top - container.clientTop); + }, + + getWheelDelta: function (e) { + + var delta = 0; + + if (e.wheelDelta) { + delta = e.wheelDelta / 120; + } + if (e.detail) { + delta = -e.detail / 3; + } + return delta; + }, + + _skipEvents: {}, + + _fakeStop: function (e) { + // fakes stopPropagation by setting a special event flag, checked/reset with L.DomEvent._skipped(e) + L.DomEvent._skipEvents[e.type] = true; + }, + + _skipped: function (e) { + var skipped = this._skipEvents[e.type]; + // reset when checking, as it's only used in map container and propagates outside of the map + this._skipEvents[e.type] = false; + return skipped; + }, + + // check if element really left/entered the event target (for mouseenter/mouseleave) + _checkMouse: function (el, e) { + + var related = e.relatedTarget; + + if (!related) { return true; } + + try { + while (related && (related !== el)) { + related = related.parentNode; + } + } catch (err) { + return false; + } + return (related !== el); + }, + + _getEvent: function () { // evil magic for IE + /*jshint noarg:false */ + var e = window.event; + if (!e) { + var caller = arguments.callee.caller; + while (caller) { + e = caller['arguments'][0]; + if (e && window.Event === e.constructor) { + break; + } + caller = caller.caller; + } + } + return e; + }, + + // this is a horrible workaround for a bug in Android where a single touch triggers two click events + _filterClick: function (e, handler) { + var timeStamp = (e.timeStamp || e.originalEvent.timeStamp), + elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick); + + // are they closer together than 500ms yet more than 100ms? + // Android typically triggers them ~300ms apart while multiple listeners + // on the same event should be triggered far faster; + // or check if click is simulated on the element, and if it is, reject any non-simulated events + + if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) { + L.DomEvent.stop(e); + return; + } + L.DomEvent._lastClick = timeStamp; + + return handler(e); + } +}; + +L.DomEvent.on = L.DomEvent.addListener; +L.DomEvent.off = L.DomEvent.removeListener; + + +/* + * L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too. + */ + +L.Draggable = L.Class.extend({ + includes: L.Mixin.Events, + + statics: { + START: L.Browser.touch ? ['touchstart', 'mousedown'] : ['mousedown'], + END: { + mousedown: 'mouseup', + touchstart: 'touchend', + pointerdown: 'touchend', + MSPointerDown: 'touchend' + }, + MOVE: { + mousedown: 'mousemove', + touchstart: 'touchmove', + pointerdown: 'touchmove', + MSPointerDown: 'touchmove' + } + }, + + initialize: function (element, dragStartTarget) { + this._element = element; + this._dragStartTarget = dragStartTarget || element; + }, + + enable: function () { + if (this._enabled) { return; } + + for (var i = L.Draggable.START.length - 1; i >= 0; i--) { + L.DomEvent.on(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); + } + + this._enabled = true; + }, + + disable: function () { + if (!this._enabled) { return; } + + for (var i = L.Draggable.START.length - 1; i >= 0; i--) { + L.DomEvent.off(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); + } + + this._enabled = false; + this._moved = false; + }, + + _onDown: function (e) { + this._moved = false; + + if (e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; } + + L.DomEvent.stopPropagation(e); + + if (L.Draggable._disabled) { return; } + + L.DomUtil.disableImageDrag(); + L.DomUtil.disableTextSelection(); + + if (this._moving) { return; } + + var first = e.touches ? e.touches[0] : e; + + this._startPoint = new L.Point(first.clientX, first.clientY); + this._startPos = this._newPos = L.DomUtil.getPosition(this._element); + + L.DomEvent + .on(document, L.Draggable.MOVE[e.type], this._onMove, this) + .on(document, L.Draggable.END[e.type], this._onUp, this); + }, + + _onMove: function (e) { + if (e.touches && e.touches.length > 1) { + this._moved = true; + return; + } + + var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e), + newPoint = new L.Point(first.clientX, first.clientY), + offset = newPoint.subtract(this._startPoint); + + if (!offset.x && !offset.y) { return; } + if (L.Browser.touch && Math.abs(offset.x) + Math.abs(offset.y) < 3) { return; } + + L.DomEvent.preventDefault(e); + + if (!this._moved) { + this.fire('dragstart'); + + this._moved = true; + this._startPos = L.DomUtil.getPosition(this._element).subtract(offset); + + L.DomUtil.addClass(document.body, 'leaflet-dragging'); + this._lastTarget = e.target || e.srcElement; + L.DomUtil.addClass(this._lastTarget, 'leaflet-drag-target'); + } + + this._newPos = this._startPos.add(offset); + this._moving = true; + + L.Util.cancelAnimFrame(this._animRequest); + this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget); + }, + + _updatePosition: function () { + this.fire('predrag'); + L.DomUtil.setPosition(this._element, this._newPos); + this.fire('drag'); + }, + + _onUp: function () { + L.DomUtil.removeClass(document.body, 'leaflet-dragging'); + + if (this._lastTarget) { + L.DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target'); + this._lastTarget = null; + } + + for (var i in L.Draggable.MOVE) { + L.DomEvent + .off(document, L.Draggable.MOVE[i], this._onMove) + .off(document, L.Draggable.END[i], this._onUp); + } + + L.DomUtil.enableImageDrag(); + L.DomUtil.enableTextSelection(); + + if (this._moved && this._moving) { + // ensure drag is not fired after dragend + L.Util.cancelAnimFrame(this._animRequest); + + this.fire('dragend', { + distance: this._newPos.distanceTo(this._startPos) + }); + } + + this._moving = false; + } +}); + + +/* + L.Handler is a base class for handler classes that are used internally to inject + interaction features like dragging to classes like Map and Marker. +*/ + +L.Handler = L.Class.extend({ + initialize: function (map) { + this._map = map; + }, + + enable: function () { + if (this._enabled) { return; } + + this._enabled = true; + this.addHooks(); + }, + + disable: function () { + if (!this._enabled) { return; } + + this._enabled = false; + this.removeHooks(); + }, + + enabled: function () { + return !!this._enabled; + } +}); + + +/* + * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default. + */ + +L.Map.mergeOptions({ + dragging: true, + + inertia: !L.Browser.android23, + inertiaDeceleration: 3400, // px/s^2 + inertiaMaxSpeed: Infinity, // px/s + inertiaThreshold: L.Browser.touch ? 32 : 18, // ms + easeLinearity: 0.25, + + // TODO refactor, move to CRS + worldCopyJump: false +}); + +L.Map.Drag = L.Handler.extend({ + addHooks: function () { + if (!this._draggable) { + var map = this._map; + + this._draggable = new L.Draggable(map._mapPane, map._container); + + this._draggable.on({ + 'dragstart': this._onDragStart, + 'drag': this._onDrag, + 'dragend': this._onDragEnd + }, this); + + if (map.options.worldCopyJump) { + this._draggable.on('predrag', this._onPreDrag, this); + map.on('viewreset', this._onViewReset, this); + + map.whenReady(this._onViewReset, this); + } + } + this._draggable.enable(); + }, + + removeHooks: function () { + this._draggable.disable(); + }, + + moved: function () { + return this._draggable && this._draggable._moved; + }, + + _onDragStart: function () { + var map = this._map; + + if (map._panAnim) { + map._panAnim.stop(); + } + + map + .fire('movestart') + .fire('dragstart'); + + if (map.options.inertia) { + this._positions = []; + this._times = []; + } + }, + + _onDrag: function () { + if (this._map.options.inertia) { + var time = this._lastTime = +new Date(), + pos = this._lastPos = this._draggable._newPos; + + this._positions.push(pos); + this._times.push(time); + + if (time - this._times[0] > 200) { + this._positions.shift(); + this._times.shift(); + } + } + + this._map + .fire('move') + .fire('drag'); + }, + + _onViewReset: function () { + // TODO fix hardcoded Earth values + var pxCenter = this._map.getSize()._divideBy(2), + pxWorldCenter = this._map.latLngToLayerPoint([0, 0]); + + this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x; + this._worldWidth = this._map.project([0, 180]).x; + }, + + _onPreDrag: function () { + // TODO refactor to be able to adjust map pane position after zoom + var worldWidth = this._worldWidth, + halfWidth = Math.round(worldWidth / 2), + dx = this._initialWorldOffset, + x = this._draggable._newPos.x, + newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, + newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, + newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2; + + this._draggable._newPos.x = newX; + }, + + _onDragEnd: function (e) { + var map = this._map, + options = map.options, + delay = +new Date() - this._lastTime, + + noInertia = !options.inertia || delay > options.inertiaThreshold || !this._positions[0]; + + map.fire('dragend', e); + + if (noInertia) { + map.fire('moveend'); + + } else { + + var direction = this._lastPos.subtract(this._positions[0]), + duration = (this._lastTime + delay - this._times[0]) / 1000, + ease = options.easeLinearity, + + speedVector = direction.multiplyBy(ease / duration), + speed = speedVector.distanceTo([0, 0]), + + limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), + limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), + + decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease), + offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round(); + + if (!offset.x || !offset.y) { + map.fire('moveend'); + + } else { + offset = map._limitOffset(offset, map.options.maxBounds); + + L.Util.requestAnimFrame(function () { + map.panBy(offset, { + duration: decelerationDuration, + easeLinearity: ease, + noMoveStart: true + }); + }); + } + } + } +}); + +L.Map.addInitHook('addHandler', 'dragging', L.Map.Drag); + + +/* + * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default. + */ + +L.Map.mergeOptions({ + doubleClickZoom: true +}); + +L.Map.DoubleClickZoom = L.Handler.extend({ + addHooks: function () { + this._map.on('dblclick', this._onDoubleClick, this); + }, + + removeHooks: function () { + this._map.off('dblclick', this._onDoubleClick, this); + }, + + _onDoubleClick: function (e) { + var map = this._map, + zoom = map.getZoom() + (e.originalEvent.shiftKey ? -1 : 1); + + if (map.options.doubleClickZoom === 'center') { + map.setZoom(zoom); + } else { + map.setZoomAround(e.containerPoint, zoom); + } + } +}); + +L.Map.addInitHook('addHandler', 'doubleClickZoom', L.Map.DoubleClickZoom); + + +/* + * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map. + */ + +L.Map.mergeOptions({ + scrollWheelZoom: true +}); + +L.Map.ScrollWheelZoom = L.Handler.extend({ + addHooks: function () { + L.DomEvent.on(this._map._container, 'mousewheel', this._onWheelScroll, this); + L.DomEvent.on(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); + this._delta = 0; + }, + + removeHooks: function () { + L.DomEvent.off(this._map._container, 'mousewheel', this._onWheelScroll); + L.DomEvent.off(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); + }, + + _onWheelScroll: function (e) { + var delta = L.DomEvent.getWheelDelta(e); + + this._delta += delta; + this._lastMousePos = this._map.mouseEventToContainerPoint(e); + + if (!this._startTime) { + this._startTime = +new Date(); + } + + var left = Math.max(40 - (+new Date() - this._startTime), 0); + + clearTimeout(this._timer); + this._timer = setTimeout(L.bind(this._performZoom, this), left); + + L.DomEvent.preventDefault(e); + L.DomEvent.stopPropagation(e); + }, + + _performZoom: function () { + var map = this._map, + delta = this._delta, + zoom = map.getZoom(); + + delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta); + delta = Math.max(Math.min(delta, 4), -4); + delta = map._limitZoom(zoom + delta) - zoom; + + this._delta = 0; + this._startTime = null; + + if (!delta) { return; } + + if (map.options.scrollWheelZoom === 'center') { + map.setZoom(zoom + delta); + } else { + map.setZoomAround(this._lastMousePos, zoom + delta); + } + } +}); + +L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom); + + +/* + * Extends the event handling code with double tap support for mobile browsers. + */ + +L.extend(L.DomEvent, { + + _touchstart: L.Browser.msPointer ? 'MSPointerDown' : L.Browser.pointer ? 'pointerdown' : 'touchstart', + _touchend: L.Browser.msPointer ? 'MSPointerUp' : L.Browser.pointer ? 'pointerup' : 'touchend', + + // inspired by Zepto touch code by Thomas Fuchs + addDoubleTapListener: function (obj, handler, id) { + var last, + doubleTap = false, + delay = 250, + touch, + pre = '_leaflet_', + touchstart = this._touchstart, + touchend = this._touchend, + trackedTouches = []; + + function onTouchStart(e) { + var count; + + if (L.Browser.pointer) { + trackedTouches.push(e.pointerId); + count = trackedTouches.length; + } else { + count = e.touches.length; + } + if (count > 1) { + return; + } + + var now = Date.now(), + delta = now - (last || now); + + touch = e.touches ? e.touches[0] : e; + doubleTap = (delta > 0 && delta <= delay); + last = now; + } + + function onTouchEnd(e) { + if (L.Browser.pointer) { + var idx = trackedTouches.indexOf(e.pointerId); + if (idx === -1) { + return; + } + trackedTouches.splice(idx, 1); + } + + if (doubleTap) { + if (L.Browser.pointer) { + // work around .type being readonly with MSPointer* events + var newTouch = { }, + prop; + + // jshint forin:false + for (var i in touch) { + prop = touch[i]; + if (typeof prop === 'function') { + newTouch[i] = prop.bind(touch); + } else { + newTouch[i] = prop; + } + } + touch = newTouch; + } + touch.type = 'dblclick'; + handler(touch); + last = null; + } + } + obj[pre + touchstart + id] = onTouchStart; + obj[pre + touchend + id] = onTouchEnd; + + // on pointer we need to listen on the document, otherwise a drag starting on the map and moving off screen + // will not come through to us, so we will lose track of how many touches are ongoing + var endElement = L.Browser.pointer ? document.documentElement : obj; + + obj.addEventListener(touchstart, onTouchStart, false); + endElement.addEventListener(touchend, onTouchEnd, false); + + if (L.Browser.pointer) { + endElement.addEventListener(L.DomEvent.POINTER_CANCEL, onTouchEnd, false); + } + + return this; + }, + + removeDoubleTapListener: function (obj, id) { + var pre = '_leaflet_'; + + obj.removeEventListener(this._touchstart, obj[pre + this._touchstart + id], false); + (L.Browser.pointer ? document.documentElement : obj).removeEventListener( + this._touchend, obj[pre + this._touchend + id], false); + + if (L.Browser.pointer) { + document.documentElement.removeEventListener(L.DomEvent.POINTER_CANCEL, obj[pre + this._touchend + id], + false); + } + + return this; + } +}); + + +/* + * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. + */ + +L.extend(L.DomEvent, { + + //static + POINTER_DOWN: L.Browser.msPointer ? 'MSPointerDown' : 'pointerdown', + POINTER_MOVE: L.Browser.msPointer ? 'MSPointerMove' : 'pointermove', + POINTER_UP: L.Browser.msPointer ? 'MSPointerUp' : 'pointerup', + POINTER_CANCEL: L.Browser.msPointer ? 'MSPointerCancel' : 'pointercancel', + + _pointers: [], + _pointerDocumentListener: false, + + // Provides a touch events wrapper for (ms)pointer events. + // Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019 + //ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 + + addPointerListener: function (obj, type, handler, id) { + + switch (type) { + case 'touchstart': + return this.addPointerListenerStart(obj, type, handler, id); + case 'touchend': + return this.addPointerListenerEnd(obj, type, handler, id); + case 'touchmove': + return this.addPointerListenerMove(obj, type, handler, id); + default: + throw 'Unknown touch event type'; + } + }, + + addPointerListenerStart: function (obj, type, handler, id) { + var pre = '_leaflet_', + pointers = this._pointers; + + var cb = function (e) { + + L.DomEvent.preventDefault(e); + + var alreadyInArray = false; + for (var i = 0; i < pointers.length; i++) { + if (pointers[i].pointerId === e.pointerId) { + alreadyInArray = true; + break; + } + } + if (!alreadyInArray) { + pointers.push(e); + } + + e.touches = pointers.slice(); + e.changedTouches = [e]; + + handler(e); + }; + + obj[pre + 'touchstart' + id] = cb; + obj.addEventListener(this.POINTER_DOWN, cb, false); + + // need to also listen for end events to keep the _pointers list accurate + // this needs to be on the body and never go away + if (!this._pointerDocumentListener) { + var internalCb = function (e) { + for (var i = 0; i < pointers.length; i++) { + if (pointers[i].pointerId === e.pointerId) { + pointers.splice(i, 1); + break; + } + } + }; + //We listen on the documentElement as any drags that end by moving the touch off the screen get fired there + document.documentElement.addEventListener(this.POINTER_UP, internalCb, false); + document.documentElement.addEventListener(this.POINTER_CANCEL, internalCb, false); + + this._pointerDocumentListener = true; + } + + return this; + }, + + addPointerListenerMove: function (obj, type, handler, id) { + var pre = '_leaflet_', + touches = this._pointers; + + function cb(e) { + + // don't fire touch moves when mouse isn't down + if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } + + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId === e.pointerId) { + touches[i] = e; + break; + } + } + + e.touches = touches.slice(); + e.changedTouches = [e]; + + handler(e); + } + + obj[pre + 'touchmove' + id] = cb; + obj.addEventListener(this.POINTER_MOVE, cb, false); + + return this; + }, + + addPointerListenerEnd: function (obj, type, handler, id) { + var pre = '_leaflet_', + touches = this._pointers; + + var cb = function (e) { + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId === e.pointerId) { + touches.splice(i, 1); + break; + } + } + + e.touches = touches.slice(); + e.changedTouches = [e]; + + handler(e); + }; + + obj[pre + 'touchend' + id] = cb; + obj.addEventListener(this.POINTER_UP, cb, false); + obj.addEventListener(this.POINTER_CANCEL, cb, false); + + return this; + }, + + removePointerListener: function (obj, type, id) { + var pre = '_leaflet_', + cb = obj[pre + type + id]; + + switch (type) { + case 'touchstart': + obj.removeEventListener(this.POINTER_DOWN, cb, false); + break; + case 'touchmove': + obj.removeEventListener(this.POINTER_MOVE, cb, false); + break; + case 'touchend': + obj.removeEventListener(this.POINTER_UP, cb, false); + obj.removeEventListener(this.POINTER_CANCEL, cb, false); + break; + } + + return this; + } +}); + + +/* + * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers. + */ + +L.Map.mergeOptions({ + touchZoom: L.Browser.touch && !L.Browser.android23, + bounceAtZoomLimits: true +}); + +L.Map.TouchZoom = L.Handler.extend({ + addHooks: function () { + L.DomEvent.on(this._map._container, 'touchstart', this._onTouchStart, this); + }, + + removeHooks: function () { + L.DomEvent.off(this._map._container, 'touchstart', this._onTouchStart, this); + }, + + _onTouchStart: function (e) { + var map = this._map; + + if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; } + + var p1 = map.mouseEventToLayerPoint(e.touches[0]), + p2 = map.mouseEventToLayerPoint(e.touches[1]), + viewCenter = map._getCenterLayerPoint(); + + this._startCenter = p1.add(p2)._divideBy(2); + this._startDist = p1.distanceTo(p2); + + this._moved = false; + this._zooming = true; + + this._centerOffset = viewCenter.subtract(this._startCenter); + + if (map._panAnim) { + map._panAnim.stop(); + } + + L.DomEvent + .on(document, 'touchmove', this._onTouchMove, this) + .on(document, 'touchend', this._onTouchEnd, this); + + L.DomEvent.preventDefault(e); + }, + + _onTouchMove: function (e) { + var map = this._map; + + if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; } + + var p1 = map.mouseEventToLayerPoint(e.touches[0]), + p2 = map.mouseEventToLayerPoint(e.touches[1]); + + this._scale = p1.distanceTo(p2) / this._startDist; + this._delta = p1._add(p2)._divideBy(2)._subtract(this._startCenter); + + if (this._scale === 1) { return; } + + if (!map.options.bounceAtZoomLimits) { + if ((map.getZoom() === map.getMinZoom() && this._scale < 1) || + (map.getZoom() === map.getMaxZoom() && this._scale > 1)) { return; } + } + + if (!this._moved) { + L.DomUtil.addClass(map._mapPane, 'leaflet-touching'); + + map + .fire('movestart') + .fire('zoomstart'); + + this._moved = true; + } + + L.Util.cancelAnimFrame(this._animRequest); + this._animRequest = L.Util.requestAnimFrame( + this._updateOnMove, this, true, this._map._container); + + L.DomEvent.preventDefault(e); + }, + + _updateOnMove: function () { + var map = this._map, + origin = this._getScaleOrigin(), + center = map.layerPointToLatLng(origin), + zoom = map.getScaleZoom(this._scale); + + map._animateZoom(center, zoom, this._startCenter, this._scale, this._delta, false, true); + }, + + _onTouchEnd: function () { + if (!this._moved || !this._zooming) { + this._zooming = false; + return; + } + + var map = this._map; + + this._zooming = false; + L.DomUtil.removeClass(map._mapPane, 'leaflet-touching'); + L.Util.cancelAnimFrame(this._animRequest); + + L.DomEvent + .off(document, 'touchmove', this._onTouchMove) + .off(document, 'touchend', this._onTouchEnd); + + var origin = this._getScaleOrigin(), + center = map.layerPointToLatLng(origin), + + oldZoom = map.getZoom(), + floatZoomDelta = map.getScaleZoom(this._scale) - oldZoom, + roundZoomDelta = (floatZoomDelta > 0 ? + Math.ceil(floatZoomDelta) : Math.floor(floatZoomDelta)), + + zoom = map._limitZoom(oldZoom + roundZoomDelta), + scale = map.getZoomScale(zoom) / this._scale; + + map._animateZoom(center, zoom, origin, scale); + }, + + _getScaleOrigin: function () { + var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale); + return this._startCenter.add(centerOffset); + } +}); + +L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom); + + +/* + * L.Map.Tap is used to enable mobile hacks like quick taps and long hold. + */ + +L.Map.mergeOptions({ + tap: true, + tapTolerance: 15 +}); + +L.Map.Tap = L.Handler.extend({ + addHooks: function () { + L.DomEvent.on(this._map._container, 'touchstart', this._onDown, this); + }, + + removeHooks: function () { + L.DomEvent.off(this._map._container, 'touchstart', this._onDown, this); + }, + + _onDown: function (e) { + if (!e.touches) { return; } + + L.DomEvent.preventDefault(e); + + this._fireClick = true; + + // don't simulate click or track longpress if more than 1 touch + if (e.touches.length > 1) { + this._fireClick = false; + clearTimeout(this._holdTimeout); + return; + } + + var first = e.touches[0], + el = first.target; + + this._startPos = this._newPos = new L.Point(first.clientX, first.clientY); + + // if touching a link, highlight it + if (el.tagName && el.tagName.toLowerCase() === 'a') { + L.DomUtil.addClass(el, 'leaflet-active'); + } + + // simulate long hold but setting a timeout + this._holdTimeout = setTimeout(L.bind(function () { + if (this._isTapValid()) { + this._fireClick = false; + this._onUp(); + this._simulateEvent('contextmenu', first); + } + }, this), 1000); + + L.DomEvent + .on(document, 'touchmove', this._onMove, this) + .on(document, 'touchend', this._onUp, this); + }, + + _onUp: function (e) { + clearTimeout(this._holdTimeout); + + L.DomEvent + .off(document, 'touchmove', this._onMove, this) + .off(document, 'touchend', this._onUp, this); + + if (this._fireClick && e && e.changedTouches) { + + var first = e.changedTouches[0], + el = first.target; + + if (el && el.tagName && el.tagName.toLowerCase() === 'a') { + L.DomUtil.removeClass(el, 'leaflet-active'); + } + + // simulate click if the touch didn't move too much + if (this._isTapValid()) { + this._simulateEvent('click', first); + } + } + }, + + _isTapValid: function () { + return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance; + }, + + _onMove: function (e) { + var first = e.touches[0]; + this._newPos = new L.Point(first.clientX, first.clientY); + }, + + _simulateEvent: function (type, e) { + var simulatedEvent = document.createEvent('MouseEvents'); + + simulatedEvent._simulated = true; + e.target._simulatedClick = true; + + simulatedEvent.initMouseEvent( + type, true, true, window, 1, + e.screenX, e.screenY, + e.clientX, e.clientY, + false, false, false, false, 0, null); + + e.target.dispatchEvent(simulatedEvent); + } +}); + +if (L.Browser.touch && !L.Browser.pointer) { + L.Map.addInitHook('addHandler', 'tap', L.Map.Tap); +} + + +/* + * L.Handler.ShiftDragZoom is used to add shift-drag zoom interaction to the map + * (zoom to a selected bounding box), enabled by default. + */ + +L.Map.mergeOptions({ + boxZoom: true +}); + +L.Map.BoxZoom = L.Handler.extend({ + initialize: function (map) { + this._map = map; + this._container = map._container; + this._pane = map._panes.overlayPane; + this._moved = false; + }, + + addHooks: function () { + L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this); + }, + + removeHooks: function () { + L.DomEvent.off(this._container, 'mousedown', this._onMouseDown); + this._moved = false; + }, + + moved: function () { + return this._moved; + }, + + _onMouseDown: function (e) { + this._moved = false; + + if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; } + + L.DomUtil.disableTextSelection(); + L.DomUtil.disableImageDrag(); + + this._startLayerPoint = this._map.mouseEventToLayerPoint(e); + + L.DomEvent + .on(document, 'mousemove', this._onMouseMove, this) + .on(document, 'mouseup', this._onMouseUp, this) + .on(document, 'keydown', this._onKeyDown, this); + }, + + _onMouseMove: function (e) { + if (!this._moved) { + this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane); + L.DomUtil.setPosition(this._box, this._startLayerPoint); + + //TODO refactor: move cursor to styles + this._container.style.cursor = 'crosshair'; + this._map.fire('boxzoomstart'); + } + + var startPoint = this._startLayerPoint, + box = this._box, + + layerPoint = this._map.mouseEventToLayerPoint(e), + offset = layerPoint.subtract(startPoint), + + newPos = new L.Point( + Math.min(layerPoint.x, startPoint.x), + Math.min(layerPoint.y, startPoint.y)); + + L.DomUtil.setPosition(box, newPos); + + this._moved = true; + + // TODO refactor: remove hardcoded 4 pixels + box.style.width = (Math.max(0, Math.abs(offset.x) - 4)) + 'px'; + box.style.height = (Math.max(0, Math.abs(offset.y) - 4)) + 'px'; + }, + + _finish: function () { + if (this._moved) { + this._pane.removeChild(this._box); + this._container.style.cursor = ''; + } + + L.DomUtil.enableTextSelection(); + L.DomUtil.enableImageDrag(); + + L.DomEvent + .off(document, 'mousemove', this._onMouseMove) + .off(document, 'mouseup', this._onMouseUp) + .off(document, 'keydown', this._onKeyDown); + }, + + _onMouseUp: function (e) { + + this._finish(); + + var map = this._map, + layerPoint = map.mouseEventToLayerPoint(e); + + if (this._startLayerPoint.equals(layerPoint)) { return; } + + var bounds = new L.LatLngBounds( + map.layerPointToLatLng(this._startLayerPoint), + map.layerPointToLatLng(layerPoint)); + + map.fitBounds(bounds); + + map.fire('boxzoomend', { + boxZoomBounds: bounds + }); + }, + + _onKeyDown: function (e) { + if (e.keyCode === 27) { + this._finish(); + } + } +}); + +L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom); + + +/* + * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default. + */ + +L.Map.mergeOptions({ + keyboard: true, + keyboardPanOffset: 80, + keyboardZoomOffset: 1 +}); + +L.Map.Keyboard = L.Handler.extend({ + + keyCodes: { + left: [37], + right: [39], + down: [40], + up: [38], + zoomIn: [187, 107, 61, 171], + zoomOut: [189, 109, 173] + }, + + initialize: function (map) { + this._map = map; + + this._setPanOffset(map.options.keyboardPanOffset); + this._setZoomOffset(map.options.keyboardZoomOffset); + }, + + addHooks: function () { + var container = this._map._container; + + // make the container focusable by tabbing + if (container.tabIndex === -1) { + container.tabIndex = '0'; + } + + L.DomEvent + .on(container, 'focus', this._onFocus, this) + .on(container, 'blur', this._onBlur, this) + .on(container, 'mousedown', this._onMouseDown, this); + + this._map + .on('focus', this._addHooks, this) + .on('blur', this._removeHooks, this); + }, + + removeHooks: function () { + this._removeHooks(); + + var container = this._map._container; + + L.DomEvent + .off(container, 'focus', this._onFocus, this) + .off(container, 'blur', this._onBlur, this) + .off(container, 'mousedown', this._onMouseDown, this); + + this._map + .off('focus', this._addHooks, this) + .off('blur', this._removeHooks, this); + }, + + _onMouseDown: function () { + if (this._focused) { return; } + + var body = document.body, + docEl = document.documentElement, + top = body.scrollTop || docEl.scrollTop, + left = body.scrollLeft || docEl.scrollLeft; + + this._map._container.focus(); + + window.scrollTo(left, top); + }, + + _onFocus: function () { + this._focused = true; + this._map.fire('focus'); + }, + + _onBlur: function () { + this._focused = false; + this._map.fire('blur'); + }, + + _setPanOffset: function (pan) { + var keys = this._panKeys = {}, + codes = this.keyCodes, + i, len; + + for (i = 0, len = codes.left.length; i < len; i++) { + keys[codes.left[i]] = [-1 * pan, 0]; + } + for (i = 0, len = codes.right.length; i < len; i++) { + keys[codes.right[i]] = [pan, 0]; + } + for (i = 0, len = codes.down.length; i < len; i++) { + keys[codes.down[i]] = [0, pan]; + } + for (i = 0, len = codes.up.length; i < len; i++) { + keys[codes.up[i]] = [0, -1 * pan]; + } + }, + + _setZoomOffset: function (zoom) { + var keys = this._zoomKeys = {}, + codes = this.keyCodes, + i, len; + + for (i = 0, len = codes.zoomIn.length; i < len; i++) { + keys[codes.zoomIn[i]] = zoom; + } + for (i = 0, len = codes.zoomOut.length; i < len; i++) { + keys[codes.zoomOut[i]] = -zoom; + } + }, + + _addHooks: function () { + L.DomEvent.on(document, 'keydown', this._onKeyDown, this); + }, + + _removeHooks: function () { + L.DomEvent.off(document, 'keydown', this._onKeyDown, this); + }, + + _onKeyDown: function (e) { + var key = e.keyCode, + map = this._map; + + if (key in this._panKeys) { + + if (map._panAnim && map._panAnim._inProgress) { return; } + + map.panBy(this._panKeys[key]); + + if (map.options.maxBounds) { + map.panInsideBounds(map.options.maxBounds); + } + + } else if (key in this._zoomKeys) { + map.setZoom(map.getZoom() + this._zoomKeys[key]); + + } else { + return; + } + + L.DomEvent.stop(e); + } +}); + +L.Map.addInitHook('addHandler', 'keyboard', L.Map.Keyboard); + + +/* + * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable. + */ + +L.Handler.MarkerDrag = L.Handler.extend({ + initialize: function (marker) { + this._marker = marker; + }, + + addHooks: function () { + var icon = this._marker._icon; + if (!this._draggable) { + this._draggable = new L.Draggable(icon, icon); + } + + this._draggable + .on('dragstart', this._onDragStart, this) + .on('drag', this._onDrag, this) + .on('dragend', this._onDragEnd, this); + this._draggable.enable(); + L.DomUtil.addClass(this._marker._icon, 'leaflet-marker-draggable'); + }, + + removeHooks: function () { + this._draggable + .off('dragstart', this._onDragStart, this) + .off('drag', this._onDrag, this) + .off('dragend', this._onDragEnd, this); + + this._draggable.disable(); + L.DomUtil.removeClass(this._marker._icon, 'leaflet-marker-draggable'); + }, + + moved: function () { + return this._draggable && this._draggable._moved; + }, + + _onDragStart: function () { + this._marker + .closePopup() + .fire('movestart') + .fire('dragstart'); + }, + + _onDrag: function () { + var marker = this._marker, + shadow = marker._shadow, + iconPos = L.DomUtil.getPosition(marker._icon), + latlng = marker._map.layerPointToLatLng(iconPos); + + // update shadow position + if (shadow) { + L.DomUtil.setPosition(shadow, iconPos); + } + + marker._latlng = latlng; + + marker + .fire('move', {latlng: latlng}) + .fire('drag'); + }, + + _onDragEnd: function (e) { + this._marker + .fire('moveend') + .fire('dragend', e); + } +}); + + +/* + * L.Control is a base class for implementing map controls. Handles positioning. + * All other controls extend from this class. + */ + +L.Control = L.Class.extend({ + options: { + position: 'topright' + }, + + initialize: function (options) { + L.setOptions(this, options); + }, + + getPosition: function () { + return this.options.position; + }, + + setPosition: function (position) { + var map = this._map; + + if (map) { + map.removeControl(this); + } + + this.options.position = position; + + if (map) { + map.addControl(this); + } + + return this; + }, + + getContainer: function () { + return this._container; + }, + + addTo: function (map) { + this._map = map; + + var container = this._container = this.onAdd(map), + pos = this.getPosition(), + corner = map._controlCorners[pos]; + + L.DomUtil.addClass(container, 'leaflet-control'); + + if (pos.indexOf('bottom') !== -1) { + corner.insertBefore(container, corner.firstChild); + } else { + corner.appendChild(container); + } + + return this; + }, + + removeFrom: function (map) { + var pos = this.getPosition(), + corner = map._controlCorners[pos]; + + corner.removeChild(this._container); + this._map = null; + + if (this.onRemove) { + this.onRemove(map); + } + + return this; + }, + + _refocusOnMap: function () { + if (this._map) { + this._map.getContainer().focus(); + } + } +}); + +L.control = function (options) { + return new L.Control(options); +}; + + +// adds control-related methods to L.Map + +L.Map.include({ + addControl: function (control) { + control.addTo(this); + return this; + }, + + removeControl: function (control) { + control.removeFrom(this); + return this; + }, + + _initControlPos: function () { + var corners = this._controlCorners = {}, + l = 'leaflet-', + container = this._controlContainer = + L.DomUtil.create('div', l + 'control-container', this._container); + + function createCorner(vSide, hSide) { + var className = l + vSide + ' ' + l + hSide; + + corners[vSide + hSide] = L.DomUtil.create('div', className, container); + } + + createCorner('top', 'left'); + createCorner('top', 'right'); + createCorner('bottom', 'left'); + createCorner('bottom', 'right'); + }, + + _clearControlPos: function () { + this._container.removeChild(this._controlContainer); + } +}); + + +/* + * L.Control.Zoom is used for the default zoom buttons on the map. + */ + +L.Control.Zoom = L.Control.extend({ + options: { + position: 'topleft', + zoomInText: '+', + zoomInTitle: 'Zoom in', + zoomOutText: '-', + zoomOutTitle: 'Zoom out' + }, + + onAdd: function (map) { + var zoomName = 'leaflet-control-zoom', + container = L.DomUtil.create('div', zoomName + ' leaflet-bar'); + + this._map = map; + + this._zoomInButton = this._createButton( + this.options.zoomInText, this.options.zoomInTitle, + zoomName + '-in', container, this._zoomIn, this); + this._zoomOutButton = this._createButton( + this.options.zoomOutText, this.options.zoomOutTitle, + zoomName + '-out', container, this._zoomOut, this); + + this._updateDisabled(); + map.on('zoomend zoomlevelschange', this._updateDisabled, this); + + return container; + }, + + onRemove: function (map) { + map.off('zoomend zoomlevelschange', this._updateDisabled, this); + }, + + _zoomIn: function (e) { + this._map.zoomIn(e.shiftKey ? 3 : 1); + }, + + _zoomOut: function (e) { + this._map.zoomOut(e.shiftKey ? 3 : 1); + }, + + _createButton: function (html, title, className, container, fn, context) { + var link = L.DomUtil.create('a', className, container); + link.innerHTML = html; + link.href = '#'; + link.title = title; + + var stop = L.DomEvent.stopPropagation; + + L.DomEvent + .on(link, 'click', stop) + .on(link, 'mousedown', stop) + .on(link, 'dblclick', stop) + .on(link, 'click', L.DomEvent.preventDefault) + .on(link, 'click', fn, context) + .on(link, 'click', this._refocusOnMap, context); + + return link; + }, + + _updateDisabled: function () { + var map = this._map, + className = 'leaflet-disabled'; + + L.DomUtil.removeClass(this._zoomInButton, className); + L.DomUtil.removeClass(this._zoomOutButton, className); + + if (map._zoom === map.getMinZoom()) { + L.DomUtil.addClass(this._zoomOutButton, className); + } + if (map._zoom === map.getMaxZoom()) { + L.DomUtil.addClass(this._zoomInButton, className); + } + } +}); + +L.Map.mergeOptions({ + zoomControl: true +}); + +L.Map.addInitHook(function () { + if (this.options.zoomControl) { + this.zoomControl = new L.Control.Zoom(); + this.addControl(this.zoomControl); + } +}); + +L.control.zoom = function (options) { + return new L.Control.Zoom(options); +}; + + + +/* + * L.Control.Attribution is used for displaying attribution on the map (added by default). + */ + +L.Control.Attribution = L.Control.extend({ + options: { + position: 'bottomright', + prefix: 'Leaflet' + }, + + initialize: function (options) { + L.setOptions(this, options); + + this._attributions = {}; + }, + + onAdd: function (map) { + this._container = L.DomUtil.create('div', 'leaflet-control-attribution'); + L.DomEvent.disableClickPropagation(this._container); + + for (var i in map._layers) { + if (map._layers[i].getAttribution) { + this.addAttribution(map._layers[i].getAttribution()); + } + } + + map + .on('layeradd', this._onLayerAdd, this) + .on('layerremove', this._onLayerRemove, this); + + this._update(); + + return this._container; + }, + + onRemove: function (map) { + map + .off('layeradd', this._onLayerAdd) + .off('layerremove', this._onLayerRemove); + + }, + + setPrefix: function (prefix) { + this.options.prefix = prefix; + this._update(); + return this; + }, + + addAttribution: function (text) { + if (!text) { return; } + + if (!this._attributions[text]) { + this._attributions[text] = 0; + } + this._attributions[text]++; + + this._update(); + + return this; + }, + + removeAttribution: function (text) { + if (!text) { return; } + + if (this._attributions[text]) { + this._attributions[text]--; + this._update(); + } + + return this; + }, + + _update: function () { + if (!this._map) { return; } + + var attribs = []; + + for (var i in this._attributions) { + if (this._attributions[i]) { + attribs.push(i); + } + } + + var prefixAndAttribs = []; + + if (this.options.prefix) { + prefixAndAttribs.push(this.options.prefix); + } + if (attribs.length) { + prefixAndAttribs.push(attribs.join(', ')); + } + + this._container.innerHTML = prefixAndAttribs.join(' | '); + }, + + _onLayerAdd: function (e) { + if (e.layer.getAttribution) { + this.addAttribution(e.layer.getAttribution()); + } + }, + + _onLayerRemove: function (e) { + if (e.layer.getAttribution) { + this.removeAttribution(e.layer.getAttribution()); + } + } +}); + +L.Map.mergeOptions({ + attributionControl: true +}); + +L.Map.addInitHook(function () { + if (this.options.attributionControl) { + this.attributionControl = (new L.Control.Attribution()).addTo(this); + } +}); + +L.control.attribution = function (options) { + return new L.Control.Attribution(options); +}; + + +/* + * L.Control.Scale is used for displaying metric/imperial scale on the map. + */ + +L.Control.Scale = L.Control.extend({ + options: { + position: 'bottomleft', + maxWidth: 100, + metric: true, + imperial: true, + updateWhenIdle: false + }, + + onAdd: function (map) { + this._map = map; + + var className = 'leaflet-control-scale', + container = L.DomUtil.create('div', className), + options = this.options; + + this._addScales(options, className, container); + + map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); + map.whenReady(this._update, this); + + return container; + }, + + onRemove: function (map) { + map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); + }, + + _addScales: function (options, className, container) { + if (options.metric) { + this._mScale = L.DomUtil.create('div', className + '-line', container); + } + if (options.imperial) { + this._iScale = L.DomUtil.create('div', className + '-line', container); + } + }, + + _update: function () { + var bounds = this._map.getBounds(), + centerLat = bounds.getCenter().lat, + halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180), + dist = halfWorldMeters * (bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 180, + + size = this._map.getSize(), + options = this.options, + maxMeters = 0; + + if (size.x > 0) { + maxMeters = dist * (options.maxWidth / size.x); + } + + this._updateScales(options, maxMeters); + }, + + _updateScales: function (options, maxMeters) { + if (options.metric && maxMeters) { + this._updateMetric(maxMeters); + } + + if (options.imperial && maxMeters) { + this._updateImperial(maxMeters); + } + }, + + _updateMetric: function (maxMeters) { + var meters = this._getRoundNum(maxMeters); + + this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px'; + this._mScale.innerHTML = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; + }, + + _updateImperial: function (maxMeters) { + var maxFeet = maxMeters * 3.2808399, + scale = this._iScale, + maxMiles, miles, feet; + + if (maxFeet > 5280) { + maxMiles = maxFeet / 5280; + miles = this._getRoundNum(maxMiles); + + scale.style.width = this._getScaleWidth(miles / maxMiles) + 'px'; + scale.innerHTML = miles + ' mi'; + + } else { + feet = this._getRoundNum(maxFeet); + + scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px'; + scale.innerHTML = feet + ' ft'; + } + }, + + _getScaleWidth: function (ratio) { + return Math.round(this.options.maxWidth * ratio) - 10; + }, + + _getRoundNum: function (num) { + var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), + d = num / pow10; + + d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1; + + return pow10 * d; + } +}); + +L.control.scale = function (options) { + return new L.Control.Scale(options); +}; + + +/* + * L.Control.Layers is a control to allow users to switch between different layers on the map. + */ + +L.Control.Layers = L.Control.extend({ + options: { + collapsed: true, + position: 'topright', + autoZIndex: true + }, + + initialize: function (baseLayers, overlays, options) { + L.setOptions(this, options); + + this._layers = {}; + this._lastZIndex = 0; + this._handlingClick = false; + + for (var i in baseLayers) { + this._addLayer(baseLayers[i], i); + } + + for (i in overlays) { + this._addLayer(overlays[i], i, true); + } + }, + + onAdd: function (map) { + this._initLayout(); + this._update(); + + map + .on('layeradd', this._onLayerChange, this) + .on('layerremove', this._onLayerChange, this); + + return this._container; + }, + + onRemove: function (map) { + map + .off('layeradd', this._onLayerChange, this) + .off('layerremove', this._onLayerChange, this); + }, + + addBaseLayer: function (layer, name) { + this._addLayer(layer, name); + this._update(); + return this; + }, + + addOverlay: function (layer, name) { + this._addLayer(layer, name, true); + this._update(); + return this; + }, + + removeLayer: function (layer) { + var id = L.stamp(layer); + delete this._layers[id]; + this._update(); + return this; + }, + + _initLayout: function () { + var className = 'leaflet-control-layers', + container = this._container = L.DomUtil.create('div', className); + + //Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released + container.setAttribute('aria-haspopup', true); + + if (!L.Browser.touch) { + L.DomEvent + .disableClickPropagation(container) + .disableScrollPropagation(container); + } else { + L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation); + } + + var form = this._form = L.DomUtil.create('form', className + '-list'); + + if (this.options.collapsed) { + if (!L.Browser.android) { + L.DomEvent + .on(container, 'mouseover', this._expand, this) + .on(container, 'mouseout', this._collapse, this); + } + var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container); + link.href = '#'; + link.title = 'Layers'; + + if (L.Browser.touch) { + L.DomEvent + .on(link, 'click', L.DomEvent.stop) + .on(link, 'click', this._expand, this); + } + else { + L.DomEvent.on(link, 'focus', this._expand, this); + } + //Work around for Firefox android issue https://github.com/Leaflet/Leaflet/issues/2033 + L.DomEvent.on(form, 'click', function () { + setTimeout(L.bind(this._onInputClick, this), 0); + }, this); + + this._map.on('click', this._collapse, this); + // TODO keyboard accessibility + } else { + this._expand(); + } + + this._baseLayersList = L.DomUtil.create('div', className + '-base', form); + this._separator = L.DomUtil.create('div', className + '-separator', form); + this._overlaysList = L.DomUtil.create('div', className + '-overlays', form); + + container.appendChild(form); + }, + + _addLayer: function (layer, name, overlay) { + var id = L.stamp(layer); + + this._layers[id] = { + layer: layer, + name: name, + overlay: overlay + }; + + if (this.options.autoZIndex && layer.setZIndex) { + this._lastZIndex++; + layer.setZIndex(this._lastZIndex); + } + }, + + _update: function () { + if (!this._container) { + return; + } + + this._baseLayersList.innerHTML = ''; + this._overlaysList.innerHTML = ''; + + var baseLayersPresent = false, + overlaysPresent = false, + i, obj; + + for (i in this._layers) { + obj = this._layers[i]; + this._addItem(obj); + overlaysPresent = overlaysPresent || obj.overlay; + baseLayersPresent = baseLayersPresent || !obj.overlay; + } + + this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; + }, + + _onLayerChange: function (e) { + var obj = this._layers[L.stamp(e.layer)]; + + if (!obj) { return; } + + if (!this._handlingClick) { + this._update(); + } + + var type = obj.overlay ? + (e.type === 'layeradd' ? 'overlayadd' : 'overlayremove') : + (e.type === 'layeradd' ? 'baselayerchange' : null); + + if (type) { + this._map.fire(type, obj); + } + }, + + // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) + _createRadioElement: function (name, checked) { + + var radioHtml = '= 0) { + this._onZoomTransitionEnd(); + } + }, + + _nothingToAnimate: function () { + return !this._container.getElementsByClassName('leaflet-zoom-animated').length; + }, + + _tryAnimatedZoom: function (center, zoom, options) { + + if (this._animatingZoom) { return true; } + + options = options || {}; + + // don't animate if disabled, not supported or zoom difference is too large + if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || + Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; } + + // offset is the pixel coords of the zoom origin relative to the current center + var scale = this.getZoomScale(zoom), + offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale), + origin = this._getCenterLayerPoint()._add(offset); + + // don't animate if the zoom origin isn't within one screen from the current center, unless forced + if (options.animate !== true && !this.getSize().contains(offset)) { return false; } + + this + .fire('movestart') + .fire('zoomstart'); + + this._animateZoom(center, zoom, origin, scale, null, true); + + return true; + }, + + _animateZoom: function (center, zoom, origin, scale, delta, backwards, forTouchZoom) { + + if (!forTouchZoom) { + this._animatingZoom = true; + } + + // put transform transition on all layers with leaflet-zoom-animated class + L.DomUtil.addClass(this._mapPane, 'leaflet-zoom-anim'); + + // remember what center/zoom to set after animation + this._animateToCenter = center; + this._animateToZoom = zoom; + + // disable any dragging during animation + if (L.Draggable) { + L.Draggable._disabled = true; + } + + L.Util.requestAnimFrame(function () { + this.fire('zoomanim', { + center: center, + zoom: zoom, + origin: origin, + scale: scale, + delta: delta, + backwards: backwards + }); + }, this); + }, + + _onZoomTransitionEnd: function () { + + this._animatingZoom = false; + + L.DomUtil.removeClass(this._mapPane, 'leaflet-zoom-anim'); + + this._resetView(this._animateToCenter, this._animateToZoom, true, true); + + if (L.Draggable) { + L.Draggable._disabled = false; + } + } +}); + + +/* + Zoom animation logic for L.TileLayer. +*/ + +L.TileLayer.include({ + _animateZoom: function (e) { + if (!this._animating) { + this._animating = true; + this._prepareBgBuffer(); + } + + var bg = this._bgBuffer, + transform = L.DomUtil.TRANSFORM, + initialTransform = e.delta ? L.DomUtil.getTranslateString(e.delta) : bg.style[transform], + scaleStr = L.DomUtil.getScaleString(e.scale, e.origin); + + bg.style[transform] = e.backwards ? + scaleStr + ' ' + initialTransform : + initialTransform + ' ' + scaleStr; + }, + + _endZoomAnim: function () { + var front = this._tileContainer, + bg = this._bgBuffer; + + front.style.visibility = ''; + front.parentNode.appendChild(front); // Bring to fore + + // force reflow + L.Util.falseFn(bg.offsetWidth); + + this._animating = false; + }, + + _clearBgBuffer: function () { + var map = this._map; + + if (map && !map._animatingZoom && !map.touchZoom._zooming) { + this._bgBuffer.innerHTML = ''; + this._bgBuffer.style[L.DomUtil.TRANSFORM] = ''; + } + }, + + _prepareBgBuffer: function () { + + var front = this._tileContainer, + bg = this._bgBuffer; + + // if foreground layer doesn't have many tiles but bg layer does, + // keep the existing bg layer and just zoom it some more + + var bgLoaded = this._getLoadedTilesPercentage(bg), + frontLoaded = this._getLoadedTilesPercentage(front); + + if (bg && bgLoaded > 0.5 && frontLoaded < 0.5) { + + front.style.visibility = 'hidden'; + this._stopLoadingImages(front); + return; + } + + // prepare the buffer to become the front tile pane + bg.style.visibility = 'hidden'; + bg.style[L.DomUtil.TRANSFORM] = ''; + + // switch out the current layer to be the new bg layer (and vice-versa) + this._tileContainer = bg; + bg = this._bgBuffer = front; + + this._stopLoadingImages(bg); + + //prevent bg buffer from clearing right after zoom + clearTimeout(this._clearBgBufferTimer); + }, + + _getLoadedTilesPercentage: function (container) { + var tiles = container.getElementsByTagName('img'), + i, len, count = 0; + + for (i = 0, len = tiles.length; i < len; i++) { + if (tiles[i].complete) { + count++; + } + } + return count / len; + }, + + // stops loading all tiles in the background layer + _stopLoadingImages: function (container) { + var tiles = Array.prototype.slice.call(container.getElementsByTagName('img')), + i, len, tile; + + for (i = 0, len = tiles.length; i < len; i++) { + tile = tiles[i]; + + if (!tile.complete) { + tile.onload = L.Util.falseFn; + tile.onerror = L.Util.falseFn; + tile.src = L.Util.emptyImageUrl; + + tile.parentNode.removeChild(tile); + } + } + } +}); + + +/* + * Provides L.Map with convenient shortcuts for using browser geolocation features. + */ + +L.Map.include({ + _defaultLocateOptions: { + watch: false, + setView: false, + maxZoom: Infinity, + timeout: 10000, + maximumAge: 0, + enableHighAccuracy: false + }, + + locate: function (/*Object*/ options) { + + options = this._locateOptions = L.extend(this._defaultLocateOptions, options); + + if (!navigator.geolocation) { + this._handleGeolocationError({ + code: 0, + message: 'Geolocation not supported.' + }); + return this; + } + + var onResponse = L.bind(this._handleGeolocationResponse, this), + onError = L.bind(this._handleGeolocationError, this); + + if (options.watch) { + this._locationWatchId = + navigator.geolocation.watchPosition(onResponse, onError, options); + } else { + navigator.geolocation.getCurrentPosition(onResponse, onError, options); + } + return this; + }, + + stopLocate: function () { + if (navigator.geolocation) { + navigator.geolocation.clearWatch(this._locationWatchId); + } + if (this._locateOptions) { + this._locateOptions.setView = false; + } + return this; + }, + + _handleGeolocationError: function (error) { + var c = error.code, + message = error.message || + (c === 1 ? 'permission denied' : + (c === 2 ? 'position unavailable' : 'timeout')); + + if (this._locateOptions.setView && !this._loaded) { + this.fitWorld(); + } + + this.fire('locationerror', { + code: c, + message: 'Geolocation error: ' + message + '.' + }); + }, + + _handleGeolocationResponse: function (pos) { + var lat = pos.coords.latitude, + lng = pos.coords.longitude, + latlng = new L.LatLng(lat, lng), + + latAccuracy = 180 * pos.coords.accuracy / 40075017, + lngAccuracy = latAccuracy / Math.cos(L.LatLng.DEG_TO_RAD * lat), + + bounds = L.latLngBounds( + [lat - latAccuracy, lng - lngAccuracy], + [lat + latAccuracy, lng + lngAccuracy]), + + options = this._locateOptions; + + if (options.setView) { + var zoom = Math.min(this.getBoundsZoom(bounds), options.maxZoom); + this.setView(latlng, zoom); + } + + var data = { + latlng: latlng, + bounds: bounds, + timestamp: pos.timestamp + }; + + for (var i in pos.coords) { + if (typeof pos.coords[i] === 'number') { + data[i] = pos.coords[i]; + } + } + + this.fire('locationfound', data); + } +}); + + +}(window, document)); +/* + Leaflet.markercluster, Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps. + https://github.com/Leaflet/Leaflet.markercluster + (c) 2012-2013, Dave Leaver, smartrak +*/ + +!function(t,e){L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animateAddingMarkers:!1,spiderfyDistanceMultiplier:1,chunkedLoading:!1,chunkInterval:200,chunkDelay:50,chunkProgress:null,polygonOptions:{}},initialize:function(t){L.Util.setOptions(this,t),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),this._featureGroup=L.featureGroup(),this._featureGroup.on(L.FeatureGroup.EVENTS,this._propagateEvent,this),this._nonPointGroup=L.featureGroup(),this._nonPointGroup.on(L.FeatureGroup.EVENTS,this._propagateEvent,this),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null,this._queue=[]},addLayer:function(t){if(t instanceof L.LayerGroup){var e=[];for(var i in t._layers)e.push(t._layers[i]);return this.addLayers(e)}if(!t.getLatLng)return this._nonPointGroup.addLayer(t),this;if(!this._map)return this._needsClustering.push(t),this;if(this.hasLayer(t))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(t,this._maxZoom);var n=t,s=this._map.getZoom();if(t.__parent)for(;n.__parent._zoom>=s;)n=n.__parent;return this._currentShownBounds.contains(n.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(t,n):this._animationAddLayerNonAnimated(t,n)),this},removeLayer:function(t){if(t instanceof L.LayerGroup){var e=[];for(var i in t._layers)e.push(t._layers[i]);return this.removeLayers(e)}return t.getLatLng?this._map?t.__parent?(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(t)),this._removeLayer(t,!0),this._featureGroup.hasLayer(t)&&(this._featureGroup.removeLayer(t),t.setOpacity&&t.setOpacity(1)),this):this:(!this._arraySplice(this._needsClustering,t)&&this.hasLayer(t)&&this._needsRemoving.push(t),this):(this._nonPointGroup.removeLayer(t),this)},addLayers:function(t){var e,i,n,s,r=this._featureGroup,o=this._nonPointGroup,a=this.options.chunkedLoading,h=this.options.chunkInterval,_=this.options.chunkProgress;if(this._map){var u=0,l=(new Date).getTime(),d=L.bind(function(){for(var e=(new Date).getTime();uh)break}if(s=t[u],s.getLatLng){if(!this.hasLayer(s)&&(this._addLayer(s,this._maxZoom),s.__parent&&2===s.__parent.getChildCount())){var n=s.__parent.getAllChildMarkers(),p=n[0]===s?n[1]:n[0];r.removeLayer(p)}}else o.addLayer(s)}_&&_(u,t.length,(new Date).getTime()-l),u===t.length?(this._featureGroup.eachLayer(function(t){t instanceof L.MarkerCluster&&t._iconNeedsUpdate&&t._updateIcon()}),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds)):setTimeout(d,this.options.chunkDelay)},this);d()}else{for(e=[],i=0,n=t.length;n>i;i++)s=t[i],s.getLatLng?this.hasLayer(s)||e.push(s):o.addLayer(s);this._needsClustering=this._needsClustering.concat(e)}return this},removeLayers:function(t){var e,i,n,s=this._featureGroup,r=this._nonPointGroup;if(!this._map){for(e=0,i=t.length;i>e;e++)n=t[e],this._arraySplice(this._needsClustering,n),r.removeLayer(n);return this}for(e=0,i=t.length;i>e;e++)n=t[e],n.__parent?(this._removeLayer(n,!0,!0),s.hasLayer(n)&&(s.removeLayer(n),n.setOpacity&&n.setOpacity(1))):r.removeLayer(n);return this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds),s.eachLayer(function(t){t instanceof L.MarkerCluster&&t._updateIcon()}),this},clearLayers:function(){return this._map||(this._needsClustering=[],delete this._gridClusters,delete this._gridUnclustered),this._noanimationUnspiderfy&&this._noanimationUnspiderfy(),this._featureGroup.clearLayers(),this._nonPointGroup.clearLayers(),this.eachLayer(function(t){delete t.__parent}),this._map&&this._generateInitialClusters(),this},getBounds:function(){var t=new L.LatLngBounds;if(this._topClusterLevel)t.extend(this._topClusterLevel._bounds);else for(var e=this._needsClustering.length-1;e>=0;e--)t.extend(this._needsClustering[e].getLatLng());return t.extend(this._nonPointGroup.getBounds()),t},eachLayer:function(t,e){var i,n=this._needsClustering.slice();for(this._topClusterLevel&&this._topClusterLevel.getAllChildMarkers(n),i=n.length-1;i>=0;i--)t.call(e,n[i]);this._nonPointGroup.eachLayer(t,e)},getLayers:function(){var t=[];return this.eachLayer(function(e){t.push(e)}),t},getLayer:function(t){var e=null;return this.eachLayer(function(i){L.stamp(i)===t&&(e=i)}),e},hasLayer:function(t){if(!t)return!1;var e,i=this._needsClustering;for(e=i.length-1;e>=0;e--)if(i[e]===t)return!0;for(i=this._needsRemoving,e=i.length-1;e>=0;e--)if(i[e]===t)return!1;return!(!t.__parent||t.__parent._group!==this)||this._nonPointGroup.hasLayer(t)},zoomToShowLayer:function(t,e){var i=function(){if((t._icon||t.__parent._icon)&&!this._inZoomAnimation)if(this._map.off("moveend",i,this),this.off("animationend",i,this),t._icon)e();else if(t.__parent._icon){var n=function(){this.off("spiderfied",n,this),e()};this.on("spiderfied",n,this),t.__parent.spiderfy()}};t._icon&&this._map.getBounds().contains(t.getLatLng())?e():t.__parent._zoome;e++)n=this._needsRemoving[e],this._removeLayer(n,!0);this._needsRemoving=[],this._zoom=this._map.getZoom(),this._currentShownBounds=this._getExpandedVisibleBounds(),this._map.on("zoomend",this._zoomEnd,this),this._map.on("moveend",this._moveEnd,this),this._spiderfierOnAdd&&this._spiderfierOnAdd(),this._bindEvents(),i=this._needsClustering,this._needsClustering=[],this.addLayers(i)},onRemove:function(t){t.off("zoomend",this._zoomEnd,this),t.off("moveend",this._moveEnd,this),this._unbindEvents(),this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim",""),this._spiderfierOnRemove&&this._spiderfierOnRemove(),this._hideCoverage(),this._featureGroup.onRemove(t),this._nonPointGroup.onRemove(t),this._featureGroup.clearLayers(),this._map=null},getVisibleParent:function(t){for(var e=t;e&&!e._icon;)e=e.__parent;return e||null},_arraySplice:function(t,e){for(var i=t.length-1;i>=0;i--)if(t[i]===e)return t.splice(i,1),!0},_removeLayer:function(t,e,i){var n=this._gridClusters,s=this._gridUnclustered,r=this._featureGroup,o=this._map;if(e)for(var a=this._maxZoom;a>=0&&s[a].removeObject(t,o.project(t.getLatLng(),a));a--);var h,_=t.__parent,u=_._markers;for(this._arraySplice(u,t);_&&(_._childCount--,!(_._zoom<0));)e&&_._childCount<=1?(h=_._markers[0]===t?_._markers[1]:_._markers[0],n[_._zoom].removeObject(_,o.project(_._cLatLng,_._zoom)),s[_._zoom].addObject(h,o.project(h.getLatLng(),_._zoom)),this._arraySplice(_.__parent._childClusters,_),_.__parent._markers.push(h),h.__parent=_.__parent,_._icon&&(r.removeLayer(_),i||r.addLayer(h))):(_._recalculateBounds(),i&&_._icon||_._updateIcon()),_=_.__parent;delete t.__parent},_isOrIsParent:function(t,e){for(;e;){if(t===e)return!0;e=e.parentNode}return!1},_propagateEvent:function(t){if(t.layer instanceof L.MarkerCluster){if(t.originalEvent&&this._isOrIsParent(t.layer._icon,t.originalEvent.relatedTarget))return;t.type="cluster"+t.type}this.fire(t.type,t)},_defaultIconCreateFunction:function(t){var e=t.getChildCount(),i=" marker-cluster-";return i+=10>e?"small":100>e?"medium":"large",new L.DivIcon({html:"
    "+e+"
    ",className:"marker-cluster"+i,iconSize:new L.Point(40,40)})},_bindEvents:function(){var t=this._map,e=this.options.spiderfyOnMaxZoom,i=this.options.showCoverageOnHover,n=this.options.zoomToBoundsOnClick;(e||n)&&this.on("clusterclick",this._zoomOrSpiderfy,this),i&&(this.on("clustermouseover",this._showCoverage,this),this.on("clustermouseout",this._hideCoverage,this),t.on("zoomend",this._hideCoverage,this))},_zoomOrSpiderfy:function(t){var e=this._map;e.getMaxZoom()===e.getZoom()?this.options.spiderfyOnMaxZoom&&t.layer.spiderfy():this.options.zoomToBoundsOnClick&&t.layer.zoomToBounds(),t.originalEvent&&13===t.originalEvent.keyCode&&e._container.focus()},_showCoverage:function(t){var e=this._map;this._inZoomAnimation||(this._shownPolygon&&e.removeLayer(this._shownPolygon),t.layer.getChildCount()>2&&t.layer!==this._spiderfied&&(this._shownPolygon=new L.Polygon(t.layer.getConvexHull(),this.options.polygonOptions),e.addLayer(this._shownPolygon)))},_hideCoverage:function(){this._shownPolygon&&(this._map.removeLayer(this._shownPolygon),this._shownPolygon=null)},_unbindEvents:function(){var t=this.options.spiderfyOnMaxZoom,e=this.options.showCoverageOnHover,i=this.options.zoomToBoundsOnClick,n=this._map;(t||i)&&this.off("clusterclick",this._zoomOrSpiderfy,this),e&&(this.off("clustermouseover",this._showCoverage,this),this.off("clustermouseout",this._hideCoverage,this),n.off("zoomend",this._hideCoverage,this))},_zoomEnd:function(){this._map&&(this._mergeSplitClusters(),this._zoom=this._map._zoom,this._currentShownBounds=this._getExpandedVisibleBounds())},_moveEnd:function(){if(!this._inZoomAnimation){var t=this._getExpandedVisibleBounds();this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._map._zoom,t),this._currentShownBounds=t}},_generateInitialClusters:function(){var t=this._map.getMaxZoom(),e=this.options.maxClusterRadius,i=e;"function"!=typeof e&&(i=function(){return e}),this.options.disableClusteringAtZoom&&(t=this.options.disableClusteringAtZoom-1),this._maxZoom=t,this._gridClusters={},this._gridUnclustered={};for(var n=t;n>=0;n--)this._gridClusters[n]=new L.DistanceGrid(i(n)),this._gridUnclustered[n]=new L.DistanceGrid(i(n));this._topClusterLevel=new L.MarkerCluster(this,-1)},_addLayer:function(t,e){var i,n,s=this._gridClusters,r=this._gridUnclustered;for(this.options.singleMarkerMode&&(t.options.icon=this.options.iconCreateFunction({getChildCount:function(){return 1},getAllChildMarkers:function(){return[t]}}));e>=0;e--){i=this._map.project(t.getLatLng(),e);var o=s[e].getNearObject(i);if(o)return o._addChild(t),t.__parent=o,void 0;if(o=r[e].getNearObject(i)){var a=o.__parent;a&&this._removeLayer(o,!1);var h=new L.MarkerCluster(this,e,o,t);s[e].addObject(h,this._map.project(h._cLatLng,e)),o.__parent=h,t.__parent=h;var _=h;for(n=e-1;n>a._zoom;n--)_=new L.MarkerCluster(this,n,_),s[n].addObject(_,this._map.project(o.getLatLng(),n));for(a._addChild(_),n=e;n>=0&&r[n].removeObject(o,this._map.project(o.getLatLng(),n));n--);return}r[e].addObject(t,i)}this._topClusterLevel._addChild(t),t.__parent=this._topClusterLevel},_enqueue:function(t){this._queue.push(t),this._queueTimeout||(this._queueTimeout=setTimeout(L.bind(this._processQueue,this),300))},_processQueue:function(){for(var t=0;tthis._map._zoom?(this._animationStart(),this._animationZoomOut(this._zoom,this._map._zoom)):this._moveEnd()},_getExpandedVisibleBounds:function(){if(!this.options.removeOutsideVisibleBounds)return this.getBounds();var t=this._map,e=t.getBounds(),i=e._southWest,n=e._northEast,s=L.Browser.mobile?0:Math.abs(i.lat-n.lat),r=L.Browser.mobile?0:Math.abs(i.lng-n.lng);return new L.LatLngBounds(new L.LatLng(i.lat-s,i.lng-r,!0),new L.LatLng(n.lat+s,n.lng+r,!0))},_animationAddLayerNonAnimated:function(t,e){if(e===t)this._featureGroup.addLayer(t);else if(2===e._childCount){e._addToMap();var i=e.getAllChildMarkers();this._featureGroup.removeLayer(i[0]),this._featureGroup.removeLayer(i[1])}else e._updateIcon()}}),L.MarkerClusterGroup.include(L.DomUtil.TRANSITION?{_animationStart:function(){this._map._mapPane.className+=" leaflet-cluster-anim",this._inZoomAnimation++},_animationEnd:function(){this._map&&(this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim","")),this._inZoomAnimation--,this.fire("animationend")},_animationZoomIn:function(t,e){var i,n=this._getExpandedVisibleBounds(),s=this._featureGroup;this._topClusterLevel._recursively(n,t,0,function(r){var o,a=r._latlng,h=r._markers;for(n.contains(a)||(a=null),r._isSingleParent()&&t+1===e?(s.removeLayer(r),r._recursivelyAddChildrenToMap(null,e,n)):(r.setOpacity(0),r._recursivelyAddChildrenToMap(a,e,n)),i=h.length-1;i>=0;i--)o=h[i],n.contains(o._latlng)||s.removeLayer(o)}),this._forceLayout(),this._topClusterLevel._recursivelyBecomeVisible(n,e),s.eachLayer(function(t){t instanceof L.MarkerCluster||!t._icon||t.setOpacity(1)}),this._topClusterLevel._recursively(n,t,e,function(t){t._recursivelyRestoreChildPositions(e)}),this._enqueue(function(){this._topClusterLevel._recursively(n,t,0,function(t){s.removeLayer(t),t.setOpacity(1)}),this._animationEnd()})},_animationZoomOut:function(t,e){this._animationZoomOutSingle(this._topClusterLevel,t-1,e),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t,this._getExpandedVisibleBounds())},_animationZoomOutSingle:function(t,e,i){var n=this._getExpandedVisibleBounds();t._recursivelyAnimateChildrenInAndAddSelfToMap(n,e+1,i);var s=this;this._forceLayout(),t._recursivelyBecomeVisible(n,i),this._enqueue(function(){if(1===t._childCount){var r=t._markers[0];r.setLatLng(r.getLatLng()),r.setOpacity&&r.setOpacity(1)}else t._recursively(n,i,0,function(t){t._recursivelyRemoveChildrenFromMap(n,e+1)});s._animationEnd()})},_animationAddLayer:function(t,e){var i=this,n=this._featureGroup;n.addLayer(t),e!==t&&(e._childCount>2?(e._updateIcon(),this._forceLayout(),this._animationStart(),t._setPos(this._map.latLngToLayerPoint(e.getLatLng())),t.setOpacity(0),this._enqueue(function(){n.removeLayer(t),t.setOpacity(1),i._animationEnd()})):(this._forceLayout(),i._animationStart(),i._animationZoomOutSingle(e,this._map.getMaxZoom(),this._map.getZoom())))},_forceLayout:function(){L.Util.falseFn(e.body.offsetWidth)}}:{_animationStart:function(){},_animationZoomIn:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this.fire("animationend")},_animationZoomOut:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this.fire("animationend")},_animationAddLayer:function(t,e){this._animationAddLayerNonAnimated(t,e)}}),L.markerClusterGroup=function(t){return new L.MarkerClusterGroup(t)},L.MarkerCluster=L.Marker.extend({initialize:function(t,e,i,n){L.Marker.prototype.initialize.call(this,i?i._cLatLng||i.getLatLng():new L.LatLng(0,0),{icon:this}),this._group=t,this._zoom=e,this._markers=[],this._childClusters=[],this._childCount=0,this._iconNeedsUpdate=!0,this._bounds=new L.LatLngBounds,i&&this._addChild(i),n&&this._addChild(n)},getAllChildMarkers:function(t){t=t||[];for(var e=this._childClusters.length-1;e>=0;e--)this._childClusters[e].getAllChildMarkers(t);for(var i=this._markers.length-1;i>=0;i--)t.push(this._markers[i]);return t},getChildCount:function(){return this._childCount},zoomToBounds:function(){for(var t,e=this._childClusters.slice(),i=this._group._map,n=i.getBoundsZoom(this._bounds),s=this._zoom+1,r=i.getZoom();e.length>0&&n>s;){s++;var o=[];for(t=0;ts?this._group._map.setView(this._latlng,s):r>=n?this._group._map.setView(this._latlng,r+1):this._group._map.fitBounds(this._bounds)},getBounds:function(){var t=new L.LatLngBounds;return t.extend(this._bounds),t},_updateIcon:function(){this._iconNeedsUpdate=!0,this._icon&&this.setIcon(this)},createIcon:function(){return this._iconNeedsUpdate&&(this._iconObj=this._group.options.iconCreateFunction(this),this._iconNeedsUpdate=!1),this._iconObj.createIcon()},createShadow:function(){return this._iconObj.createShadow()},_addChild:function(t,e){this._iconNeedsUpdate=!0,this._expandBounds(t),t instanceof L.MarkerCluster?(e||(this._childClusters.push(t),t.__parent=this),this._childCount+=t._childCount):(e||this._markers.push(t),this._childCount++),this.__parent&&this.__parent._addChild(t,!0)},_expandBounds:function(t){var e,i=t._wLatLng||t._latlng;t instanceof L.MarkerCluster?(this._bounds.extend(t._bounds),e=t._childCount):(this._bounds.extend(i),e=1),this._cLatLng||(this._cLatLng=t._cLatLng||i);var n=this._childCount+e;this._wLatLng?(this._wLatLng.lat=(i.lat*e+this._wLatLng.lat*this._childCount)/n,this._wLatLng.lng=(i.lng*e+this._wLatLng.lng*this._childCount)/n):this._latlng=this._wLatLng=new L.LatLng(i.lat,i.lng)},_addToMap:function(t){t&&(this._backupLatlng=this._latlng,this.setLatLng(t)),this._group._featureGroup.addLayer(this)},_recursivelyAnimateChildrenIn:function(t,e,i){this._recursively(t,0,i-1,function(t){var i,n,s=t._markers;for(i=s.length-1;i>=0;i--)n=s[i],n._icon&&(n._setPos(e),n.setOpacity(0))},function(t){var i,n,s=t._childClusters;for(i=s.length-1;i>=0;i--)n=s[i],n._icon&&(n._setPos(e),n.setOpacity(0))})},_recursivelyAnimateChildrenInAndAddSelfToMap:function(t,e,i){this._recursively(t,i,0,function(n){n._recursivelyAnimateChildrenIn(t,n._group._map.latLngToLayerPoint(n.getLatLng()).round(),e),n._isSingleParent()&&e-1===i?(n.setOpacity(1),n._recursivelyRemoveChildrenFromMap(t,e)):n.setOpacity(0),n._addToMap()})},_recursivelyBecomeVisible:function(t,e){this._recursively(t,0,e,null,function(t){t.setOpacity(1)})},_recursivelyAddChildrenToMap:function(t,e,i){this._recursively(i,-1,e,function(n){if(e!==n._zoom)for(var s=n._markers.length-1;s>=0;s--){var r=n._markers[s];i.contains(r._latlng)&&(t&&(r._backupLatlng=r.getLatLng(),r.setLatLng(t),r.setOpacity&&r.setOpacity(0)),n._group._featureGroup.addLayer(r))}},function(e){e._addToMap(t)})},_recursivelyRestoreChildPositions:function(t){for(var e=this._markers.length-1;e>=0;e--){var i=this._markers[e];i._backupLatlng&&(i.setLatLng(i._backupLatlng),delete i._backupLatlng)}if(t-1===this._zoom)for(var n=this._childClusters.length-1;n>=0;n--)this._childClusters[n]._restorePosition();else for(var s=this._childClusters.length-1;s>=0;s--)this._childClusters[s]._recursivelyRestoreChildPositions(t)},_restorePosition:function(){this._backupLatlng&&(this.setLatLng(this._backupLatlng),delete this._backupLatlng)},_recursivelyRemoveChildrenFromMap:function(t,e,i){var n,s;this._recursively(t,-1,e-1,function(t){for(s=t._markers.length-1;s>=0;s--)n=t._markers[s],i&&i.contains(n._latlng)||(t._group._featureGroup.removeLayer(n),n.setOpacity&&n.setOpacity(1))},function(t){for(s=t._childClusters.length-1;s>=0;s--)n=t._childClusters[s],i&&i.contains(n._latlng)||(t._group._featureGroup.removeLayer(n),n.setOpacity&&n.setOpacity(1))})},_recursively:function(t,e,i,n,s){var r,o,a=this._childClusters,h=this._zoom;if(e>h)for(r=a.length-1;r>=0;r--)o=a[r],t.intersects(o._bounds)&&o._recursively(t,e,i,n,s);else if(n&&n(this),s&&this._zoom===i&&s(this),i>h)for(r=a.length-1;r>=0;r--)o=a[r],t.intersects(o._bounds)&&o._recursively(t,e,i,n,s)},_recalculateBounds:function(){var t,e=this._markers,i=this._childClusters;for(this._bounds=new L.LatLngBounds,delete this._wLatLng,t=e.length-1;t>=0;t--)this._expandBounds(e[t]);for(t=i.length-1;t>=0;t--)this._expandBounds(i[t])},_isSingleParent:function(){return this._childClusters.length>0&&this._childClusters[0]._childCount===this._childCount}}),L.DistanceGrid=function(t){this._cellSize=t,this._sqCellSize=t*t,this._grid={},this._objectPoint={}},L.DistanceGrid.prototype={addObject:function(t,e){var i=this._getCoord(e.x),n=this._getCoord(e.y),s=this._grid,r=s[n]=s[n]||{},o=r[i]=r[i]||[],a=L.Util.stamp(t);this._objectPoint[a]=e,o.push(t)},updateObject:function(t,e){this.removeObject(t),this.addObject(t,e)},removeObject:function(t,e){var i,n,s=this._getCoord(e.x),r=this._getCoord(e.y),o=this._grid,a=o[r]=o[r]||{},h=a[s]=a[s]||[];for(delete this._objectPoint[L.Util.stamp(t)],i=0,n=h.length;n>i;i++)if(h[i]===t)return h.splice(i,1),1===n&&delete a[s],!0},eachObject:function(t,e){var i,n,s,r,o,a,h,_=this._grid;for(i in _){o=_[i];for(n in o)for(a=o[n],s=0,r=a.length;r>s;s++)h=t.call(e,a[s]),h&&(s--,r--)}},getNearObject:function(t){var e,i,n,s,r,o,a,h,_=this._getCoord(t.x),u=this._getCoord(t.y),l=this._objectPoint,d=this._sqCellSize,p=null;for(e=u-1;u+1>=e;e++)if(s=this._grid[e])for(i=_-1;_+1>=i;i++)if(r=s[i])for(n=0,o=r.length;o>n;n++)a=r[n],h=this._sqDist(l[L.Util.stamp(a)],t),d>h&&(d=h,p=a);return p},_getCoord:function(t){return Math.floor(t/this._cellSize)},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n}},function(){L.QuickHull={getDistant:function(t,e){var i=e[1].lat-e[0].lat,n=e[0].lng-e[1].lng;return n*(t.lat-e[0].lat)+i*(t.lng-e[0].lng)},findMostDistantPointFromBaseLine:function(t,e){var i,n,s,r=0,o=null,a=[];for(i=e.length-1;i>=0;i--)n=e[i],s=this.getDistant(n,t),s>0&&(a.push(n),s>r&&(r=s,o=n));return{maxPoint:o,newPoints:a}},buildConvexHull:function(t,e){var i=[],n=this.findMostDistantPointFromBaseLine(t,e);return n.maxPoint?(i=i.concat(this.buildConvexHull([t[0],n.maxPoint],n.newPoints)),i=i.concat(this.buildConvexHull([n.maxPoint,t[1]],n.newPoints))):[t[0]]},getConvexHull:function(t){var e,i=!1,n=!1,s=null,r=null;for(e=t.length-1;e>=0;e--){var o=t[e];(i===!1||o.lat>i)&&(s=o,i=o.lat),(n===!1||o.lat=0;e--)t=i[e].getLatLng(),n.push(t);return L.QuickHull.getConvexHull(n)}}),L.MarkerCluster.include({_2PI:2*Math.PI,_circleFootSeparation:25,_circleStartAngle:Math.PI/6,_spiralFootSeparation:28,_spiralLengthStart:11,_spiralLengthFactor:5,_circleSpiralSwitchover:9,spiderfy:function(){if(this._group._spiderfied!==this&&!this._group._inZoomAnimation){var t,e=this.getAllChildMarkers(),i=this._group,n=i._map,s=n.latLngToLayerPoint(this._latlng);this._group._unspiderfy(),this._group._spiderfied=this,e.length>=this._circleSpiralSwitchover?t=this._generatePointsSpiral(e.length,s):(s.y+=10,t=this._generatePointsCircle(e.length,s)),this._animationSpiderfy(e,t)}},unspiderfy:function(t){this._group._inZoomAnimation||(this._animationUnspiderfy(t),this._group._spiderfied=null)},_generatePointsCircle:function(t,e){var i,n,s=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+t),r=s/this._2PI,o=this._2PI/t,a=[];for(a.length=t,i=t-1;i>=0;i--)n=this._circleStartAngle+i*o,a[i]=new L.Point(e.x+r*Math.cos(n),e.y+r*Math.sin(n))._round();return a},_generatePointsSpiral:function(t,e){var i,n=this._group.options.spiderfyDistanceMultiplier*this._spiralLengthStart,s=this._group.options.spiderfyDistanceMultiplier*this._spiralFootSeparation,r=this._group.options.spiderfyDistanceMultiplier*this._spiralLengthFactor,o=0,a=[];for(a.length=t,i=t-1;i>=0;i--)o+=s/n+5e-4*i,a[i]=new L.Point(e.x+n*Math.cos(o),e.y+n*Math.sin(o))._round(),n+=this._2PI*r/o;return a},_noanimationUnspiderfy:function(){var t,e,i=this._group,n=i._map,s=i._featureGroup,r=this.getAllChildMarkers();for(this.setOpacity(1),e=r.length-1;e>=0;e--)t=r[e],s.removeLayer(t),t._preSpiderfyLatlng&&(t.setLatLng(t._preSpiderfyLatlng),delete t._preSpiderfyLatlng),t.setZIndexOffset&&t.setZIndexOffset(0),t._spiderLeg&&(n.removeLayer(t._spiderLeg),delete t._spiderLeg);i._spiderfied=null}}),L.MarkerCluster.include(L.DomUtil.TRANSITION?{SVG_ANIMATION:function(){return e.createElementNS("http://www.w3.org/2000/svg","animate").toString().indexOf("SVGAnimate")>-1}(),_animationSpiderfy:function(t,i){var n,s,r,o,a=this,h=this._group,_=h._map,u=h._featureGroup,l=_.latLngToLayerPoint(this._latlng);for(n=t.length-1;n>=0;n--)s=t[n],s.setOpacity?(s.setZIndexOffset(1e6),s.setOpacity(0),u.addLayer(s),s._setPos(l)):u.addLayer(s);h._forceLayout(),h._animationStart();var d=L.Path.SVG?0:.3,p=L.Path.SVG_NS;for(n=t.length-1;n>=0;n--)if(o=_.layerPointToLatLng(i[n]),s=t[n],s._preSpiderfyLatlng=s._latlng,s.setLatLng(o),s.setOpacity&&s.setOpacity(1),r=new L.Polyline([a._latlng,o],{weight:1.5,color:"#222",opacity:d}),_.addLayer(r),s._spiderLeg=r,L.Path.SVG&&this.SVG_ANIMATION){var c=r._path.getTotalLength();r._path.setAttribute("stroke-dasharray",c+","+c);var m=e.createElementNS(p,"animate");m.setAttribute("attributeName","stroke-dashoffset"),m.setAttribute("begin","indefinite"),m.setAttribute("from",c),m.setAttribute("to",0),m.setAttribute("dur",.25),r._path.appendChild(m),m.beginElement(),m=e.createElementNS(p,"animate"),m.setAttribute("attributeName","stroke-opacity"),m.setAttribute("attributeName","stroke-opacity"),m.setAttribute("begin","indefinite"),m.setAttribute("from",0),m.setAttribute("to",.5),m.setAttribute("dur",.25),r._path.appendChild(m),m.beginElement()}if(a.setOpacity(.3),L.Path.SVG)for(this._group._forceLayout(),n=t.length-1;n>=0;n--)s=t[n]._spiderLeg,s.options.opacity=.5,s._path.setAttribute("stroke-opacity",.5);setTimeout(function(){h._animationEnd(),h.fire("spiderfied")},200)},_animationUnspiderfy:function(t){var e,i,n,s=this._group,r=s._map,o=s._featureGroup,a=t?r._latLngToNewLayerPoint(this._latlng,t.zoom,t.center):r.latLngToLayerPoint(this._latlng),h=this.getAllChildMarkers(),_=L.Path.SVG&&this.SVG_ANIMATION;for(s._animationStart(),this.setOpacity(1),i=h.length-1;i>=0;i--)e=h[i],e._preSpiderfyLatlng&&(e.setLatLng(e._preSpiderfyLatlng),delete e._preSpiderfyLatlng,e.setOpacity?(e._setPos(a),e.setOpacity(0)):o.removeLayer(e),_&&(n=e._spiderLeg._path.childNodes[0],n.setAttribute("to",n.getAttribute("from")),n.setAttribute("from",0),n.beginElement(),n=e._spiderLeg._path.childNodes[1],n.setAttribute("from",.5),n.setAttribute("to",0),n.setAttribute("stroke-opacity",0),n.beginElement(),e._spiderLeg._path.setAttribute("stroke-opacity",0)));setTimeout(function(){var t=0;for(i=h.length-1;i>=0;i--)e=h[i],e._spiderLeg&&t++;for(i=h.length-1;i>=0;i--)e=h[i],e._spiderLeg&&(e.setOpacity&&(e.setOpacity(1),e.setZIndexOffset(0)),t>1&&o.removeLayer(e),r.removeLayer(e._spiderLeg),delete e._spiderLeg);s._animationEnd()},200)}}:{_animationSpiderfy:function(t,e){var i,n,s,r,o=this._group,a=o._map,h=o._featureGroup;for(i=t.length-1;i>=0;i--)r=a.layerPointToLatLng(e[i]),n=t[i],n._preSpiderfyLatlng=n._latlng,n.setLatLng(r),n.setZIndexOffset&&n.setZIndexOffset(1e6),h.addLayer(n),s=new L.Polyline([this._latlng,r],{weight:1.5,color:"#222"}),a.addLayer(s),n._spiderLeg=s;this.setOpacity(.3),o.fire("spiderfied")},_animationUnspiderfy:function(){this._noanimationUnspiderfy()}}),L.MarkerClusterGroup.include({_spiderfied:null,_spiderfierOnAdd:function(){this._map.on("click",this._unspiderfyWrapper,this),this._map.options.zoomAnimation&&this._map.on("zoomstart",this._unspiderfyZoomStart,this),this._map.on("zoomend",this._noanimationUnspiderfy,this),L.Path.SVG&&!L.Browser.touch&&this._map._initPathRoot()},_spiderfierOnRemove:function(){this._map.off("click",this._unspiderfyWrapper,this),this._map.off("zoomstart",this._unspiderfyZoomStart,this),this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy()},_unspiderfyZoomStart:function(){this._map&&this._map.on("zoomanim",this._unspiderfyZoomAnim,this)},_unspiderfyZoomAnim:function(t){L.DomUtil.hasClass(this._map._mapPane,"leaflet-touching")||(this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy(t))},_unspiderfyWrapper:function(){this._unspiderfy()},_unspiderfy:function(t){this._spiderfied&&this._spiderfied.unspiderfy(t)},_noanimationUnspiderfy:function(){this._spiderfied&&this._spiderfied._noanimationUnspiderfy()},_unspiderfyLayer:function(t){t._spiderLeg&&(this._featureGroup.removeLayer(t),t.setOpacity(1),t.setZIndexOffset(0),this._map.removeLayer(t._spiderLeg),delete t._spiderLeg)}})}(window,document); +(function() { + var NodeTypes, ParameterMissing, Utils, createGlobalJsRoutesObject, defaults, root, + __hasProp = {}.hasOwnProperty; + + root = typeof exports !== "undefined" && exports !== null ? exports : this; + + ParameterMissing = function(message) { + this.message = message; + }; + + ParameterMissing.prototype = new Error(); + + defaults = { + prefix: "", + default_url_options: {} + }; + + NodeTypes = {"GROUP":1,"CAT":2,"SYMBOL":3,"OR":4,"STAR":5,"LITERAL":6,"SLASH":7,"DOT":8}; + + Utils = { + serialize: function(object, prefix) { + var element, i, key, prop, result, s, _i, _len; + + if (prefix == null) { + prefix = null; + } + if (!object) { + return ""; + } + if (!prefix && !(this.get_object_type(object) === "object")) { + throw new Error("Url parameters should be a javascript hash"); + } + if (root.jQuery) { + result = root.jQuery.param(object); + return (!result ? "" : result); + } + s = []; + switch (this.get_object_type(object)) { + case "array": + for (i = _i = 0, _len = object.length; _i < _len; i = ++_i) { + element = object[i]; + s.push(this.serialize(element, prefix + "[]")); + } + break; + case "object": + for (key in object) { + if (!__hasProp.call(object, key)) continue; + prop = object[key]; + if (!(prop != null)) { + continue; + } + if (prefix != null) { + key = "" + prefix + "[" + key + "]"; + } + s.push(this.serialize(prop, key)); + } + break; + default: + if (object) { + s.push("" + (encodeURIComponent(prefix.toString())) + "=" + (encodeURIComponent(object.toString()))); + } + } + if (!s.length) { + return ""; + } + return s.join("&"); + }, + clean_path: function(path) { + var last_index; + + path = path.split("://"); + last_index = path.length - 1; + path[last_index] = path[last_index].replace(/\/+/g, "/"); + return path.join("://"); + }, + set_default_url_options: function(optional_parts, options) { + var i, part, _i, _len, _results; + + _results = []; + for (i = _i = 0, _len = optional_parts.length; _i < _len; i = ++_i) { + part = optional_parts[i]; + if (!options.hasOwnProperty(part) && defaults.default_url_options.hasOwnProperty(part)) { + _results.push(options[part] = defaults.default_url_options[part]); + } + } + return _results; + }, + extract_anchor: function(options) { + var anchor; + + anchor = ""; + if (options.hasOwnProperty("anchor")) { + anchor = "#" + options.anchor; + delete options.anchor; + } + return anchor; + }, + extract_trailing_slash: function(options) { + var trailing_slash; + + trailing_slash = false; + if (defaults.default_url_options.hasOwnProperty("trailing_slash")) { + trailing_slash = defaults.default_url_options.trailing_slash; + } + if (options.hasOwnProperty("trailing_slash")) { + trailing_slash = options.trailing_slash; + delete options.trailing_slash; + } + return trailing_slash; + }, + extract_options: function(number_of_params, args) { + var last_el; + + last_el = args[args.length - 1]; + if (args.length > number_of_params || ((last_el != null) && "object" === this.get_object_type(last_el) && !this.look_like_serialized_model(last_el))) { + return args.pop(); + } else { + return {}; + } + }, + look_like_serialized_model: function(object) { + return "id" in object || "to_param" in object; + }, + path_identifier: function(object) { + var property; + + if (object === 0) { + return "0"; + } + if (!object) { + return ""; + } + property = object; + if (this.get_object_type(object) === "object") { + if ("to_param" in object) { + property = object.to_param; + } else if ("id" in object) { + property = object.id; + } else { + property = object; + } + if (this.get_object_type(property) === "function") { + property = property.call(object); + } + } + return property.toString(); + }, + clone: function(obj) { + var attr, copy, key; + + if ((obj == null) || "object" !== this.get_object_type(obj)) { + return obj; + } + copy = obj.constructor(); + for (key in obj) { + if (!__hasProp.call(obj, key)) continue; + attr = obj[key]; + copy[key] = attr; + } + return copy; + }, + prepare_parameters: function(required_parameters, actual_parameters, options) { + var i, result, val, _i, _len; + + result = this.clone(options) || {}; + for (i = _i = 0, _len = required_parameters.length; _i < _len; i = ++_i) { + val = required_parameters[i]; + if (i < actual_parameters.length) { + result[val] = actual_parameters[i]; + } + } + return result; + }, + build_path: function(required_parameters, optional_parts, route, args) { + var anchor, opts, parameters, result, trailing_slash, url, url_params; + + args = Array.prototype.slice.call(args); + opts = this.extract_options(required_parameters.length, args); + if (args.length > required_parameters.length) { + throw new Error("Too many parameters provided for path"); + } + parameters = this.prepare_parameters(required_parameters, args, opts); + this.set_default_url_options(optional_parts, parameters); + anchor = this.extract_anchor(parameters); + trailing_slash = this.extract_trailing_slash(parameters); + result = "" + (this.get_prefix()) + (this.visit(route, parameters)); + url = Utils.clean_path("" + result); + if (trailing_slash === true) { + url = url.replace(/(.*?)[\/]?$/, "$1/"); + } + if ((url_params = this.serialize(parameters)).length) { + url += "?" + url_params; + } + url += anchor; + return url; + }, + visit: function(route, parameters, optional) { + var left, left_part, right, right_part, type, value; + + if (optional == null) { + optional = false; + } + type = route[0], left = route[1], right = route[2]; + switch (type) { + case NodeTypes.GROUP: + return this.visit(left, parameters, true); + case NodeTypes.STAR: + return this.visit_globbing(left, parameters, true); + case NodeTypes.LITERAL: + case NodeTypes.SLASH: + case NodeTypes.DOT: + return left; + case NodeTypes.CAT: + left_part = this.visit(left, parameters, optional); + right_part = this.visit(right, parameters, optional); + if (optional && !(left_part && right_part)) { + return ""; + } + return "" + left_part + right_part; + case NodeTypes.SYMBOL: + value = parameters[left]; + if (value != null) { + delete parameters[left]; + return this.path_identifier(value); + } + if (optional) { + return ""; + } else { + throw new ParameterMissing("Route parameter missing: " + left); + } + break; + default: + throw new Error("Unknown Rails node type"); + } + }, + visit_globbing: function(route, parameters, optional) { + var left, right, type, value; + + type = route[0], left = route[1], right = route[2]; + if (left.replace(/^\*/i, "") !== left) { + route[1] = left = left.replace(/^\*/i, ""); + } + value = parameters[left]; + if (value == null) { + return this.visit(route, parameters, optional); + } + parameters[left] = (function() { + switch (this.get_object_type(value)) { + case "array": + return value.join("/"); + default: + return value; + } + }).call(this); + return this.visit(route, parameters, optional); + }, + get_prefix: function() { + var prefix; + + prefix = defaults.prefix; + if (prefix !== "") { + prefix = (prefix.match("/$") ? prefix : "" + prefix + "/"); + } + return prefix; + }, + _classToTypeCache: null, + _classToType: function() { + var name, _i, _len, _ref; + + if (this._classToTypeCache != null) { + return this._classToTypeCache; + } + this._classToTypeCache = {}; + _ref = "Boolean Number String Function Array Date RegExp Object Error".split(" "); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + name = _ref[_i]; + this._classToTypeCache["[object " + name + "]"] = name.toLowerCase(); + } + return this._classToTypeCache; + }, + get_object_type: function(obj) { + if (root.jQuery && (root.jQuery.type != null)) { + return root.jQuery.type(obj); + } + if (obj == null) { + return "" + obj; + } + if (typeof obj === "object" || typeof obj === "function") { + return this._classToType()[Object.prototype.toString.call(obj)] || "object"; + } else { + return typeof obj; + } + } + }; + + createGlobalJsRoutesObject = function() { + var namespace; + + namespace = function(mainRoot, namespaceString) { + var current, parts; + + parts = (namespaceString ? namespaceString.split(".") : []); + if (!parts.length) { + return; + } + current = parts.shift(); + mainRoot[current] = mainRoot[current] || {}; + return namespace(mainRoot[current], parts.join(".")); + }; + namespace(root, "Routes"); + root.Routes = { +// about => /about(.:format) + about_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"about",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// account => /accounts/:id(.:format) + account_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"accounts",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// account_type => /account_types/:id(.:format) + account_type_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"account_types",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// account_types => /account_types(.:format) + account_types_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"account_types",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// accounts => /accounts(.:format) + accounts_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"accounts",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// admin => /admin(.:format) + admin_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"admin",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// admin_newsletter => /admin/newsletter(.:format) + admin_newsletter_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"admin",false]],[7,"/",false]],[6,"newsletter",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// admin_orders => /admin/orders(.:format) + admin_orders_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"admin",false]],[7,"/",false]],[6,"orders",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// alternate_name => /alternate_names/:id(.:format) + alternate_name_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"alternate_names",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// alternate_names => /alternate_names(.:format) + alternate_names_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"alternate_names",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// authentication => /authentications/:id(.:format) + authentication_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"authentications",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// authentications => /authentications(.:format) + authentications_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"authentications",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// cancel_member_registration => /members/cancel(.:format) + cancel_member_registration_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"cancel",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// cancel_order => /orders/:id/cancel(.:format) + cancel_order_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"orders",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"cancel",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// checkout_order => /orders/:id/checkout(.:format) + checkout_order_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"orders",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"checkout",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// comment => /comments/:id(.:format) + comment_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"comments",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// comments => /comments(.:format) + comments_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"comments",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// complete_order => /orders/:id/complete(.:format) + complete_order_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"orders",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"complete",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// crop => /crops/:id(.:format) + crop_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"crops",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// crops => /crops(.:format) + crops_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"crops",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// crops_hierarchy => /crops/hierarchy(.:format) + crops_hierarchy_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"crops",false]],[7,"/",false]],[6,"hierarchy",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// crops_search => /crops/search(.:format) + crops_search_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"crops",false]],[7,"/",false]],[6,"search",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// destroy_member_session => /members/sign_out(.:format) + destroy_member_session_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"sign_out",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_account => /accounts/:id/edit(.:format) + edit_account_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"accounts",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_account_type => /account_types/:id/edit(.:format) + edit_account_type_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"account_types",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_alternate_name => /alternate_names/:id/edit(.:format) + edit_alternate_name_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"alternate_names",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_authentication => /authentications/:id/edit(.:format) + edit_authentication_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"authentications",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_comment => /comments/:id/edit(.:format) + edit_comment_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"comments",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_crop => /crops/:id/edit(.:format) + edit_crop_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"crops",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_forum => /forums/:id/edit(.:format) + edit_forum_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"forums",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_garden => /gardens/:id/edit(.:format) + edit_garden_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"gardens",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_harvest => /harvests/:id/edit(.:format) + edit_harvest_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"harvests",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_member => /members/:id/edit(.:format) + edit_member_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_member_password => /members/password/edit(.:format) + edit_member_password_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"password",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_member_registration => /members/edit(.:format) + edit_member_registration_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_notification => /notifications/:id/edit(.:format) + edit_notification_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"notifications",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_order => /orders/:id/edit(.:format) + edit_order_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"orders",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_order_item => /order_items/:id/edit(.:format) + edit_order_item_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"order_items",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_photo => /photos/:id/edit(.:format) + edit_photo_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"photos",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_plant_part => /plant_parts/:id/edit(.:format) + edit_plant_part_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"plant_parts",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_planting => /plantings/:id/edit(.:format) + edit_planting_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"plantings",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_post => /posts/:id/edit(.:format) + edit_post_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"posts",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_product => /products/:id/edit(.:format) + edit_product_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"products",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_role => /roles/:id/edit(.:format) + edit_role_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"roles",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_scientific_name => /scientific_names/:id/edit(.:format) + edit_scientific_name_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"scientific_names",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// edit_seed => /seeds/:id/edit(.:format) + edit_seed_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"seeds",false]],[7,"/",false]],[3,"id",false]],[7,"/",false]],[6,"edit",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// forum => /forums/:id(.:format) + forum_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"forums",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// forums => /forums(.:format) + forums_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"forums",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// garden => /gardens/:id(.:format) + garden_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"gardens",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// gardens => /gardens(.:format) + gardens_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"gardens",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// gardens_by_owner => /gardens/owner/:owner(.:format) + gardens_by_owner_path: function(_owner, options) { + return Utils.build_path(["owner"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"gardens",false]],[7,"/",false]],[6,"owner",false]],[7,"/",false]],[3,"owner",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// harvest => /harvests/:id(.:format) + harvest_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"harvests",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// harvests => /harvests(.:format) + harvests_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"harvests",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// harvests_by_crop => /harvests/crop/:crop(.:format) + harvests_by_crop_path: function(_crop, options) { + return Utils.build_path(["crop"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"harvests",false]],[7,"/",false]],[6,"crop",false]],[7,"/",false]],[3,"crop",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// harvests_by_owner => /harvests/owner/:owner(.:format) + harvests_by_owner_path: function(_owner, options) { + return Utils.build_path(["owner"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"harvests",false]],[7,"/",false]],[6,"owner",false]],[7,"/",false]],[3,"owner",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// home_index => /home/index(.:format) + home_index_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"home",false]],[7,"/",false]],[6,"index",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// member => /members/:id(.:format) + member_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// member_confirmation => /members/confirmation(.:format) + member_confirmation_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"confirmation",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// member_password => /members/password(.:format) + member_password_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"password",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// member_registration => /members(.:format) + member_registration_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"members",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// member_session => /members/sign_in(.:format) + member_session_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"sign_in",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// member_unlock => /members/unlock(.:format) + member_unlock_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"unlock",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// members => /members(.:format) + members_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"members",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_account => /accounts/new(.:format) + new_account_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"accounts",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_account_type => /account_types/new(.:format) + new_account_type_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"account_types",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_alternate_name => /alternate_names/new(.:format) + new_alternate_name_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"alternate_names",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_authentication => /authentications/new(.:format) + new_authentication_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"authentications",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_comment => /comments/new(.:format) + new_comment_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"comments",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_crop => /crops/new(.:format) + new_crop_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"crops",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_forum => /forums/new(.:format) + new_forum_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"forums",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_garden => /gardens/new(.:format) + new_garden_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"gardens",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_harvest => /harvests/new(.:format) + new_harvest_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"harvests",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_member => /members/new(.:format) + new_member_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_member_confirmation => /members/confirmation/new(.:format) + new_member_confirmation_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"confirmation",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_member_password => /members/password/new(.:format) + new_member_password_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"password",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_member_registration => /members/sign_up(.:format) + new_member_registration_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"sign_up",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_member_session => /members/sign_in(.:format) + new_member_session_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"sign_in",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_member_unlock => /members/unlock/new(.:format) + new_member_unlock_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"members",false]],[7,"/",false]],[6,"unlock",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_notification => /notifications/new(.:format) + new_notification_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"notifications",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_order => /orders/new(.:format) + new_order_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"orders",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_order_item => /order_items/new(.:format) + new_order_item_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"order_items",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_photo => /photos/new(.:format) + new_photo_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"photos",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_plant_part => /plant_parts/new(.:format) + new_plant_part_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"plant_parts",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_planting => /plantings/new(.:format) + new_planting_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"plantings",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_post => /posts/new(.:format) + new_post_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"posts",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_product => /products/new(.:format) + new_product_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"products",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_role => /roles/new(.:format) + new_role_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"roles",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_scientific_name => /scientific_names/new(.:format) + new_scientific_name_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"scientific_names",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// new_seed => /seeds/new(.:format) + new_seed_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"seeds",false]],[7,"/",false]],[6,"new",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// notification => /notifications/:id(.:format) + notification_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"notifications",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// notifications => /notifications(.:format) + notifications_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"notifications",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// order => /orders/:id(.:format) + order_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"orders",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// order_item => /order_items/:id(.:format) + order_item_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"order_items",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// order_items => /order_items(.:format) + order_items_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"order_items",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// orders => /orders(.:format) + orders_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"orders",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// photo => /photos/:id(.:format) + photo_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"photos",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// photos => /photos(.:format) + photos_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"photos",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// place => /places/:place(.:format) + place_path: function(_place, options) { + return Utils.build_path(["place"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"places",false]],[7,"/",false]],[3,"place",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// places => /places(.:format) + places_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"places",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// plant_part => /plant_parts/:id(.:format) + plant_part_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"plant_parts",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// plant_parts => /plant_parts(.:format) + plant_parts_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"plant_parts",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// planting => /plantings/:id(.:format) + planting_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"plantings",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// plantings => /plantings(.:format) + plantings_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"plantings",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// plantings_by_crop => /plantings/crop/:crop(.:format) + plantings_by_crop_path: function(_crop, options) { + return Utils.build_path(["crop"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"plantings",false]],[7,"/",false]],[6,"crop",false]],[7,"/",false]],[3,"crop",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// plantings_by_owner => /plantings/owner/:owner(.:format) + plantings_by_owner_path: function(_owner, options) { + return Utils.build_path(["owner"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"plantings",false]],[7,"/",false]],[6,"owner",false]],[7,"/",false]],[3,"owner",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// post => /posts/:id(.:format) + post_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"posts",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// posts => /posts(.:format) + posts_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"posts",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// posts_by_author => /posts/author/:author(.:format) + posts_by_author_path: function(_author, options) { + return Utils.build_path(["author"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"posts",false]],[7,"/",false]],[6,"author",false]],[7,"/",false]],[3,"author",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// product => /products/:id(.:format) + product_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"products",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// products => /products(.:format) + products_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"products",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// rails_info => /rails/info(.:format) + rails_info_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"rails",false]],[7,"/",false]],[6,"info",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// rails_info_properties => /rails/info/properties(.:format) + rails_info_properties_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"rails",false]],[7,"/",false]],[6,"info",false]],[7,"/",false]],[6,"properties",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// rails_info_routes => /rails/info/routes(.:format) + rails_info_routes_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"rails",false]],[7,"/",false]],[6,"info",false]],[7,"/",false]],[6,"routes",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// rails_mailers => /rails/mailers(.:format) + rails_mailers_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"rails",false]],[7,"/",false]],[6,"mailers",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// role => /roles/:id(.:format) + role_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"roles",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// roles => /roles(.:format) + roles_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"roles",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// root => / + root_path: function(options) { + return Utils.build_path([], [], [7,"/",false], arguments); + }, +// scientific_name => /scientific_names/:id(.:format) + scientific_name_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"scientific_names",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// scientific_names => /scientific_names(.:format) + scientific_names_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"scientific_names",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// search_places => /places/search(.:format) + search_places_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"places",false]],[7,"/",false]],[6,"search",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// seed => /seeds/:id(.:format) + seed_path: function(_id, options) { + return Utils.build_path(["id"], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"seeds",false]],[7,"/",false]],[3,"id",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// seeds => /seeds(.:format) + seeds_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"seeds",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// seeds_by_crop => /seeds/crop/:crop(.:format) + seeds_by_crop_path: function(_crop, options) { + return Utils.build_path(["crop"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"seeds",false]],[7,"/",false]],[6,"crop",false]],[7,"/",false]],[3,"crop",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// seeds_by_owner => /seeds/owner/:owner(.:format) + seeds_by_owner_path: function(_owner, options) { + return Utils.build_path(["owner"], ["format"], [2,[2,[2,[2,[2,[2,[7,"/",false],[6,"seeds",false]],[7,"/",false]],[6,"owner",false]],[7,"/",false]],[3,"owner",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// shop => /shop(.:format) + shop_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"shop",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// support => /support(.:format) + support_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[7,"/",false],[6,"support",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }, +// wrangle_crops => /crops/wrangle(.:format) + wrangle_crops_path: function(options) { + return Utils.build_path([], ["format"], [2,[2,[2,[2,[7,"/",false],[6,"crops",false]],[7,"/",false]],[6,"wrangle",false]],[1,[2,[8,".",false],[3,"format",false]],false]], arguments); + }} +; + root.Routes.options = defaults; + return root.Routes; + }; + + if (typeof define === "function" && define.amd) { + define([], function() { + return createGlobalJsRoutesObject(); + }); + } else { + createGlobalJsRoutesObject(); + } + +}).call(this); +/*! + * jQuery JavaScript Library v1.11.1 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-05-01T17:42Z + */ + + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper window is present, + // execute the factory and get jQuery + // For environments that do not inherently posses a window with a document + // (such as Node.js), expose a jQuery-making factory as module.exports + // This accentuates the need for the creation of a real window + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +// + +var deletedIds = []; + +var slice = deletedIds.slice; + +var concat = deletedIds.concat; + +var push = deletedIds.push; + +var indexOf = deletedIds.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + version = "1.11.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1, IE<9 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: deletedIds.sort, + splice: deletedIds.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( support.ownLast ) { + for ( key in obj ) { + return hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call(obj) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Support: Android<4.1, IE<9 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( indexOf ) { + return indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + while ( j < len ) { + first[ i++ ] = second[ j++ ]; + } + + // Support: IE<9 + // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) + if ( len !== len ) { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: function() { + return +( new Date() ); + }, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v1.10.19 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-04-18 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + characterEncoding + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document (jQuery #6963) + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== strundefined && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, + doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent !== parent.top ) { + // IE11 does not have attachEvent, so all must suffer + if ( parent.addEventListener ) { + parent.addEventListener( "unload", function() { + setDocument(); + }, false ); + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", function() { + setDocument(); + }); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { + div.innerHTML = "
    "; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowclip^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (oldCache = outerCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + outerCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context !== document && context; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is no seed and only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +}); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof rootjQuery.ready !== "undefined" ? + rootjQuery.ready( selector ) : + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.extend({ + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +jQuery.fn.extend({ + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.unique( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); +var rnotwhite = (/\S+/g); + + + +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + + } else if ( !(--remaining) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend({ + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +}); + +/** + * Clean-up method for dom ready events + */ +function detach() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } +} + +/** + * The ready event handler and self cleanup method + */ +function completed() { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + + +var strundefined = typeof undefined; + + + +// Support: IE<9 +// Iteration over object's inherited properties before its own +var i; +for ( i in jQuery( support ) ) { + break; +} +support.ownLast = i !== "0"; + +// Note: most support tests are defined in their respective modules. +// false until the test is run +support.inlineBlockNeedsLayout = false; + +// Execute ASAP in case we need to set body.style.zoom +jQuery(function() { + // Minified: var a,b,c,d + var val, div, body, container; + + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { + // Return for frameset docs that don't have a body + return; + } + + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); + + if ( typeof div.style.zoom !== strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; + + support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; + if ( val ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); +}); + + + + +(function() { + var div = document.createElement( "div" ); + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +/** + * Determines whether an object can have data + */ +jQuery.acceptData = function( elem ) { + var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ], + nodeType = +elem.nodeType || 1; + + // Do not set data on non-element DOM nodes because it will not be cleared (#8335). + return nodeType !== 1 && nodeType !== 9 ? + false : + + // Nodes accept data unless otherwise specified; rejection can be conditional + !noData || noData !== true && elem.getAttribute("classid") === noData; +}; + + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /([A-Z])/g; + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + +function internalData( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements (space-suffixed to avoid Object.prototype collisions) + // throw uncatchable exceptions if you attempt to set expando properties + noData: { + "applet ": true, + "embed ": true, + // ...but Flash objects (which have this classid) *can* handle expandos + "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var i, name, data, + elem = this[0], + attrs = elem && elem.attributes; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + + +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + }; + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; +}; +var rcheckableType = (/^(?:checkbox|radio)$/i); + + + +(function() { + // Minified: var a,b,c + var input = document.createElement( "input" ), + div = document.createElement( "div" ), + fragment = document.createDocumentFragment(); + + // Setup + div.innerHTML = "
    a"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName( "tbody" ).length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = + document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + input.type = "checkbox"; + input.checked = true; + fragment.appendChild( input ); + support.appendChecked = input.checked; + + // Make sure textarea (and checkbox) defaultValue is properly cloned + // Support: IE6-IE11+ + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // #11217 - WebKit loses check when the name is after the checked attribute + fragment.appendChild( div ); + div.innerHTML = ""; + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + support.noCloneEvent = true; + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } +})(); + + +(function() { + var i, eventName, + div = document.createElement( "div" ); + + // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) + for ( i in { submit: true, change: true, focusin: true }) { + eventName = "on" + i; + + if ( !(support[ i + "Bubbles" ] = eventName in window) ) { + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + div.setAttribute( eventName, "t" ); + support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && jQuery.acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + // Support: IE < 9, Android < 4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + jQuery._removeData( doc, fix ); + } else { + jQuery._data( doc, fix, attaches ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
    ", "
    " ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + col: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
    ", "
    " ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!support.noCloneEvent || !support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
    " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + deletedIds.push( id ); + } + } + } + } + } +}); + +jQuery.fn.extend({ + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + remove: function( selector, keepData /* Internal Use Only */ ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map(function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var arg = arguments[ 0 ]; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + arg = this.parentNode; + + jQuery.cleanData( getAll( this ) ); + + if ( arg ) { + arg.replaceChild( elem, this ); + } + }); + + // Force removal if there was no new content (e.g., from empty arguments) + return arg && (arg.length || arg.nodeType) ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + + +var iframe, + elemdisplay = {}; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var style, + elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + // getDefaultComputedStyle might be reliably used only on attached element + display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? + + // Use of this method is a temporary fix (more like optmization) until something better comes along, + // since it was removed from specification and supported only in FF + style.display : jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = (iframe || jQuery( "