$(document).ready(function(){ var imgurl = 'http://userserve-ak.last.fm/serve/_/29590905/Telepathe+outtake_main.jpg'; var mt = $('meta[property=og:image]'); mt = mt.length ? mt : $('').appendTo('head'); mt.attr('content', imgurl); $("#container").append('
'); $("h2:not(#circles h2)").wrap(''); $('#circles li a img').each(function(){ var imgSrc = $(this).attr('src'); $(this).css('background', 'url(' + imgSrc + ') no-repeat center center'); $(this).attr('src', 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='); }); $('#circles li a').tooltip({ effect: 'slide', direction: 'down', slideOutSpeed: 100, layout: '', position: 'bottom center', tipClass: 'tooltip', offset: [-30, 0], predelay: 100 }); $('#submitsearch').click(function(){ var query = $('#inputsearch').val(); var url = '/tagged/' + query $(location).attr('href', url); return false; }); var $search = $('#inputsearch'); original_val = $search.val(); $search.autocompleteArray([ "Ólöf Arnalds", ".", "2forJoy", "???", "A Grave With No Name", "A K U A", "A Silver Mt. Zion", "A$AP Rocky", "A-Minor", "A-Trak", "ALECS", "ANG LOW", "ANR", "ASAP Rocky", "ASTR", "Aaliyah", "Abigail Wyles", "Acid Girls", "Acrylics", "Active Child", "Actress", "Adele", "Adrian Lux", "Adult Jazz", "Aeroplane", "Air", "Air France", "Air Tycoon", "Alex Winston", "Ali Love", "Alice Gold", "Alice Jemima", "Allie X", "Alt-J", "AlunaGeorge", "Amadou and Mariam", "Amateur Best", "Ana Lola Roman", "Ancienne Belgique", "André 3000", "Andrew Bird", "Ang Low", "Angel Haze", "Animal Collective", "Anna Calvi", "Anne-Marie", "Annie", "Anoraak", "Antony and the Johnsons", "Aosoon", "App", "Appaloosa", "Aquilo", "Arcade Fire", "Architecture in Helsinki", "Aria", "Ariel Pink's Haunted Graffiti", "Arthur Beatrice", "Asobi Seksu", "Astronomer", "Astronomyy", "Atella", "Atoms For Peace", "Au Revoir Simone", "Austra", "Autre Ne Veut", "Autumn Falls", "Avey Tare", "Avi Buffalo", "Azari & III", "Azari and III", "Azealia Banks", "Azekel", "B L O O M", "BL?CK R?!NB0VV", "BL?CK R?INB0VV", "Babe Terror", "Baby Alpaca", "Bag Raiders", "Balam Acab", "Balistiq", "Banana Clipz", "Banjo or Freakout", "Banks", "Barnaby", "Basecamp", "Bat For Lashes", "Battlekat", "Bayou", "Beach House", "Bear In Heaven", "Beat Connection", "Beat Culture", "Beatrice Eli", "Beck", "Beirut", "Bell", "Ben Khan", "BenZel", "Beneath The Beach", "Bernard Sumner", "Best Coast", "Best Dressed Dog", "Best of 2012", "Best of 2013", "Beyoncé", "Big Boi", "Bird Call", "Bishi", "Björk", "Black Gold Buffalo", "Blackbird Blackbird", "Blaqstarr", "Blaue Blume", "Blawan", "Blonde Redhead", "Blondes", "Blood Diamonds", "Blood Orange", "Blossomer", "Blue Hawaii", "Bluebell", "Bobby Womack", "Body Language", "Bon Iver", "Boots", "Botanique", "Boy Crisis", "Boy Friend", "Boy George", "Breakbot", "Brenmar", "Bright Light Bright Light", "Brigitte", "Broken Bells", "Brolin", "Broods", "Brooke Candy", "Brothertiger", "Bryce Dessner", "Bullion", "Burial", "Butterclock", "CANT", "CEO", "CFCF", "CMJ", "CREEP", "CRIM3S", "CROSSOVER", "CSLSX", "CSS", "CTM", "Cajmere", "Candy Claws", "Caribou", "Cascadeur", "Casey Spooner", "Cass Lowe", "Cassie", "Cat Power", "CeCe", "Chad Valley", "Chairlift", "Chapel Club", "Charli XCX", "Charlotte OC", "Check ou", "Chilly Gonzales", "Chlöe Howl", "Chloe Black", "Chorus Grant", "Chris Isaak", "Christopher Owens", "Chromatics", "Chrome Sparks", "Chromeo", "Citizens!", "Clams Casino", "Clare Maguire", "Clarence Clarity", "Class Actress", "Classixx", "Clive Tanaka", "Clock Opera", "Cloud Nothings", "Cloud Seeding", "Cocknbullkid", "CocoRosie", "Cold Specks", "Com Truise", "Coma Cinema", "ConcertWall", "Cosmo V", "Craft Spells", "Crystal Castles", "Crystal Fighters", "Cults", "Cursed Kids", "Cut Copy", "Cyril Hahn", "D E N A", "Dâm-Funk", "D. Lissvik", "D/R/U/G/S", "DARKSIDE", "DENA", "DESERT", "DJ Mehdi", "DRÆMINGS", "DRC Music", "DROPxLIFE", "DaM-Funk", "Dahga Bloom", "Dahlia Black", "Dan Bodan", "Dan Deacon", "Dandi Wind", "Daniel Rossen", "DannielRadall", "Darkside", "Darwin Deez", "David Byrne", "David E. Sugar", "David Harks", "David's Lyre", "Dayna Kurtz", "Daytrotter", "Dazed TV", "Dead Times", "Deadboy", "Deerhunter", "Delorean", "Denai Moore", "Deptford Goth", "Desire", "Destroyer", "Dev Hynes", "Devendra Banhart", "Devlin", "Diamond Rings", "Diamonds Rings", "Digitalism", "Diplo", "Dirty Projectors", "Disa", "Disclosure", "Ditt Inre", "Dom", "Don Trip", "Dornik", "Drake", "Dream Boat", "Dreams", "Ducktails", "Dum Dum Girls", "Dummy Mix", "Dyymond Of Durham", "EDDI", "EDDI FRONT", "EDDI LINES", "ETML", "Echo Lake", "Eddi Front", "El Guincho", "El Perro Del Mar", "Elite Gymnastics", "Eliza Doolittle", "Ella Eyre", "Ella Fitzgerald", "Elli Ingram", "Ellie Goulding", "Elliphant", "Emannuel Jal", "Emay", "Empress Of", "Entrepreneurs", "Erykah Baduh", "Esben and the Witch", "Esser", "Estère", "Evan Abeele", "Evan Voytas", "Everything Everything", "Evian Christ", "Example", "Extraperlo", "Eyedress", "FACT", "FAMY", "FAYE", "FKA Twigs", "FOE", "Faithless", "Falcon Lake", "Familjen", "Fan Death", "Fanfarlo", "Fantasy Island", "Fatima", "Faws", "Fe", "Feist", "Felix and Volcano!", "Fenech-Soler", "Fever Ray", "Firebreather", "First Aid Kit", "Fiveng", "Fixers", "Flak Attack", "Fleetwood Mac", "Flight Facilities", "Float Fall", "Florence + The Machine", "Florence and the Machine", "Florrie", "Flying Lotus", "Foals", "Fool's Gold", "Ford and Lopatin", "Foreign Fields", "Forest", "Forest Swords", "Forss", "Fostercare", "Four Tet", "Francis and the Lights", "Frank Ocean", "Franki Chan", "Frankmusik", "Franz Ferdinand", "Freddie Dickson", "Friendly Fires", "Friends", "Fryars", "Fyfe", "GANGI", "GEMS", "Gabriel Bruce", "Games", "Gang Gang Dance", "Gaspard Augé", "Gauntlet Hair", "Gazelle Twin", "Geneva Jacuzzi", "Gesaffelstein", "Ghost Loft", "Ghostpoet", "Gil Scott-Heron", "Giraffage", "Girl Crisis", "Girls", "Glass Candy", "Glasser", "Golau Glau", "Gold Panda", "Gold Zebra", "Golden Bug", "Goldfrapp", "Gonzales", "Granit", "Grimes", "Grizzly Bear", "Grovesnor", "Guards", "Gullfisk", "H.U.N.X.", "H5C", "HAERTS", "HEALTH", "HEARTSREVOLUTION", "HIM", "HURTS", "Haim", "Haleek Maul", "Halls", "Halona King", "Hannah Holland", "Hard Mix", "HeartsRevolution", "Heavy Hawaii", "Hecuba", "Henning Fürst", "High Highs", "Highlife", "Holly Miranda", "Holy Fuck", "Holy Ghost!", "Holy Other", "Hooray For Earth", "Hot Chip", "Hot City", "How To Dress Well", "How to Dress Well", "Howl", "Hozier", "Hudson Mohawke", "Hunter Sounder", "Hunx and his Punx", "Hurts", "Husky Rescue", "Hw", "Hype Williams", "I Blame Coco", "I Ching", "I will I swear", "IYES", "Iberia", "Ice Choir", "Icky Blossoms", "Icona Pop", "Idiot Glee", "Ifan Dafydd", "Illangelo", "Imaginary Family", "Inc.", "Indians", "Ing", "Is Tropical", "Izzy Bizu", "Jónsi", "JMSN", "JSMN", "Jack Colwell", "Jack Magma", "Jai Paul", "Jamaica", "James Blake", "James Ferraro", "James Yuill", "Jamie Harley", "Jamie Isaac", "Jamie Lidell", "Jamie N Commons", "Jamie Woon", "Jamie xx", "Jamiroquai", "Janelle Monáe", "Janet Jackson", "Jay-Z", "Jaymes Young", "Jean Deaux", "Jed Nayef", "Jens Lekman", "Jensen Sportag", "Jeppe", "Jeremy Jay", "Jesse Ruins", "Jessica Agombar", "Jessie Ware", "Jitwam", "João Brasil", "Joanna Newsom", "Joel Compass", "Joel Rampage", "John Talabot", "John Wizards", "Johnny Jewel", "Jonas Lundqvist", "Joni Mitchell", "Josef Salvat", "Josh Record", "Jr Hi", "Julianna Barwick", "Julio Bashmore", "Jungle", "Jupiter", "Just A Number 05272011", "Justin Parker", "K H U S H I", "KHUSHI", "KO KO", "Kamp!", "Kanye West", "Karen O", "Karin Dreijer Andersson", "Kasper Bjørke", "Kat Dahlia", "Kate Boy", "Kate Bush", "Kate Moss", "Katy Perry", "Keep Shelly in Athens", "Kele", "Kelela", "Kelis", "Kendrick Lamar", "Kenzie May", "Kid Cudi", "Kid Sister", "Kids Of The Apocalypse", "Kids of the Apocalypse", "Kiesza", "Kill J", "Kimbra", "Kindness", "King Krule", "Kingdom", "Kirk Spencer", "Kisses", "Kitty", "Klaxons", "Kool A.D.", "Korallreven", "Koreless", "Koudlam", "Kuhrye-oo", "Kurt Vile", "Kwabs", "Kwes", "Kyan", "Kylie Minogue", "Låpsley", "L'Étoile Mystérieuse", "LAKE R?DIO", "LCD Soundsystem", "La Blogothèque", "La Roux", "La Sera", "Lady Gaga", "Ladyhawke", "Ladytron", "Lake Heartbeat", "Lana Del Rey", "Laura Groves", "Laura Marling", "Laura Mvula", "Laura Welsh", "Laurel", "Laurel Halo", "Le Corps Mince de Françoise", "Le Kid", "Le1f", "Lee Scratch Perry", "Left Right Arms", "Leo Kalyan", "Leo Zero", "Lianna La Havas", "Light Asylum", "Lindstrøm", "Linus Young", "Lion Babe", "Lisa Alma", "Lissi Dancefloor Disaster", "Litanic Mask", "Little Boots", "Little Loud", "Little Wings", "Lizbet Sempa", "Lo-Fi-Fnk", "Local Natives", "Logo", "Lolo", "London Grammar", "Lorde", "Loredana", "Lorine Chia", "Los Campesinos!", "Los Porcos", "Low Sea", "Lower Dens", "Lulu James", "Lunice", "Lykke Li", "MØ", "M.I.A.", "M.I.A.video", "M83", "MEN", "MGMT", "MNDR", "MONEY", "MOVEMENT", "MS MR", "Madonna", "Magic Island", "Magic Kids", "Mahaut Mondino", "Maigret Jnr", "Majical Cloudz", "Majid Jordan", "Major Lazer", "Mannequins on 7th Street", "Manou", "Mapei", "Marina Gasolina", "Marina and the Diamonds", "Marissa Nadler", "Mark Ronson", "Marlene", "Marooned", "Mater Suspiria Vision", "Mathemagic", "Matthew Dear", "Maximum Balloon", "Me And My Drummer", "Megafortress", "Memory Tapes", "Memoryhouse", "Metronomy", "Miami Horror", "Micachu and the Shapes", "Michael Jackson", "Midi Matilda", "Midnight Juggernauts", "Midnight Magic", "Miike Snow", "Mikky Ekko", "Miley Cyrus", "Milky Sway and Candy Starlight", "Mind Enterprises", "Missy Elliot", "Moko", "Monarchy", "Money", "Mononoke", "Moullinex", "Mountain Man", "Mozart's Sister", "Mr Little Jeans", "Mr. Little Jeans", "Mr. Oizo", "Ms Mr", "Mt. Sims", "Museum of Bellas Artes", "Music Go Music", "Mutya Keisha Siobhan", "My Brightest Diamond", "Mykki Blanco", "Mylo", "Mzwètwo", "NGUZUNGUZU", "NIKE7UP", "NIVA", "NO CEREMONY", "NO CEREMONY///", "NZCA/LINES", "NZCA/Lines", "Naomi Pilgrim", "Narrow Sparrow", "Ne-Yo", "Neil Young", "Neon Indian", "Neon Jungle", "Neon Lights", "New Build", "New Look", "New Needs", "NewVillager", "Nicki Minaj", "Nico Muhly", "Nicolas Jaar", "Nicole Atkins", "Night Works", "Niia", "Niki and The Dove", "Niki and the Dove", "Ninetails", "Nite Jewel", "No Fear Of Pop", "Noami Pilgrim", "Nottee", "Oceaán", "Of Montreal", "Ofei", "Oh Land", "Oliver Tank", "Olivia Sebastianelli", "Olof Dreijer", "Omari Shakir", "Oneohtrix Point Never", "Only Girl", "Oupa", "Outer Limitz", "Owen Pallett", "PINS", "PNAU", "POP ETC", "PS I Love You", "Pacific Air", "Pale", "Panama Wedding", "Panda Bear", "Pandit", "Pandr Eyez", "Pantha du Prince", "Pariah", "Partpanda", "Party Trash", "Passion Pit", "Patrick Wolf", "Peaches", "Pearl Fiction", "Pearl and the Puppets", "Penguin Prison", "Perfume Genius", "Peter Bjorn and John", "Peter Gabriel", "Petite Noir", "Phèdre", "Phoenix", "Picture", "Pink Priest", "Pional", "Piresian beach", "Piu Piu", "Plaid Dragon", "Planningtorock", "Poly Styrene", "Porcelain Raft", "Post Louis", "Postiljonen", "Pretty Heart", "Primary 1", "Prinzhorn Dance School", "Prizes", "Pukkelpop", "Pure Bathing Culture", "Purity Ring", "Puro Instinct", "Quiet Lights", "Róisín Murphy", "Röyksopp", "R??", "RAINER", "RY X", "Ra Ra Riot", "Rainbow Arabia", "Rainbow Chan", "Rainy Milo", "Raleigh Ritchie", "Ranvir Bassi", "Ratking", "Readers Poll", "Reading Rainbow", "Recycle Culture", "Reva DeVito", "Rhye", "Rihanna", "Rina Sawayama", "Rob da Bank", "Robert Smith", "Robin Hannibal", "Robyn", "Roman", "Roman Photos", "Romare", "Rosemary", "Rosie Lowe", "Royksöpp", "Rules", "Rush Midnight", "Rusko", "Rye Rye", "S O H N", "Sébastien Tellier", "S. Carey", "SALEM", "SBTRKT", "SISTER ACT", "SISU", "SITA", "SLEEP ? OVER", "SOHN", "SOL", "SSION", "Sacred Animals", "Sade", "Sail A Whale", "Sailor & I", "Saint Lou Lou", "Saint Saviour", "Sam Smith", "Sam Sparro", "Sampha", "Santigold", "Saol Álainn", "Sasha Keable", "Savoir", "Savoir Adore", "Say Lou Lou", "ScHoolboy Q", "School is Cool", "School of Seven Bells", "Schoolboy Q", "Seal", "Seams", "Seapony", "SebastiAn", "Secret Mountains", "Seeing Suge", "Seinabo Sey", "Serengeti", "Service", "Shara Gibson", "Shara Worden", "She Wants Revenge", "Shine 2009", "Shivum Sharma", "Shlohmo", "Short Stories", "Shy Girls", "Sia", "Silent Portraits", "Silver Columns", "Simon Bookish", "Sin Fang", "Sinead Harnett", "Sinkane", "Sir Sly", "Sirena", "Sivu", "Skeletal System", "Sleigh Bells", "Slime", "Slow Animal", "Slow Magic", "Slow Skies", "Soap&Skin", "Soars", "Soft Powers", "Solange", "Solange Knowles", "Solar Bear", "Soldier's Heart", "Son Lux", "Sonia Stein", "Sophie", "Soul Clap", "Sound of 2013", "Sound of 2014", "Southern", "Southern Shores", "Space Ghost", "Spark", "Sportsman", "St. Lucia", "St. Vincent", "Stacks", "Star Slinger", "Stay Bless", "Stay+", "Steffaloo", "Steve Mason", "Still Corners", "Stornoway", "Stubborn Heart", "Suckers", "Sufjan Stevens", "Summer Camp", "Susanne Sundfør", "Suuns", "Suvi", "Sv?", "Switch", "Symmetry", "Syron", "TEMPELHOF", "THEESatisfaction", "Ta-ku", "Tabloid", "Taken By Trees", "Taken by Trees", "Tame Impala", "Tanlines", "Taped Rai", "Tara Busch", "Taragana Pyjarama", "Team Rockit", "Tears For Fears", "Teeel", "Teen Daze", "Teen Inc.", "Teengirl Fantasy", "Tei Shi", "Telepathe", "Telephoned", "Tennis", "Tesla Boy", "Tev'n", "Tex Taiwan", "The Acid", "The Antlers", "The Big Pink", "The Books", "The Concretes", "The Dø", "The Drums", "The Embassy", "The Flaming Lips", "The Go! Team", "The Golden Filter", "The Good Natured", "The Hics", "The Horrors", "The Hundred In The Hands", "The Hundred in the Hands", "The Irrepressibles", "The Knife", "The Long Wives", "The Magician", "The Morning Benders", "The National", "The Neighbourhood", "The New Sins", "The Night VI", "The Present Moment", "The Radio Dept.", "The Shoes", "The Slow Revolt", "The Sound of Arrows", "The Strokes", "The Temper Trap", "The Tough Alliance", "The Very Best", "The Weeknd", "The xx", "The-Drum", "Theme Park", "Theophilus London", "Theopilus London", "Therapies Son", "These New Puritans", "This Is Head", "Thom Yorke", "Those Dancing Days", "Thumpers", "Tirzah", "Toddla T", "Tom Vek", "Tor Miller", "Torches", "Toro Y Moi", "Toro y Moi", "Totally Enormous Extinct Dinosaurs", "Tourist", "Tove Lo", "Trentemøller", "Trixie Whitley", "Twigs", "Twin Caverns", "Twin Shadow", "Twin Sister", "Two Bicycles", "Two Door Cinema Club", "Two Inch Punch", "UNKLE", "Uffie", "Unison", "Until The Ribbon Breaks", "VOICEsVOICEs", "Valentina", "Vampire Weekend", "Van Rivers", "Vaults", "Veronica Falls", "Video Villain", "Villa", "Villagers", "Visions of Trees", "Von Haze", "Vondelpark", "Vortex Rikers", "Vuurwerk", "WIM", "WIN WIN", "WU LYF", "Warpaint", "Washed Out", "Waterbaby", "Wavves", "We Are Standard", "We Are The World", "We Have Band", "Wet", "Whinnie Williams", "White Hinterland", "White Ring", "White Sea", "Wild Nothing", "William Arcane", "Willis Earl Beal", "Win Win", "Wintercoats", "Wise Blood", "Wolf Gang", "Wolf Parade", "Woodkid", "World Tour", "XXYYXX", "Xander The Great", "Xaphoon Jones", "YACHT", "Yasmin", "Yeah Yeah Yeahs", "Yeasayer", "Yelle", "You Love Her Coz She's Dead", "Young & Sick", "Young Dreams", "Young Eagle", "Young Galaxy", "Young Hunting", "Young Magic", "Young Waves", "Yours Truly", "Youth Lagoon", "Yuck", "Yuksek", "Yumi Zouma", "Zach Hill", "Zacho", "Zambri", "Zebra Katz", "Zhala", "Zola Jesus", "Zomby", "amiina", "araabMUZIK", "autoKratz", "b£b£ Tune$", "best of 2010", "best of 2011", "cat+power", "ceo", "cocknbullkid", "d'Eon", "disco naïveté presents", "eineinmeier", "frYars", "guards", "iPhone", "iamamiwhoami", "jj", "just a number 05272011", "memoryhouse", "mixtape", "o F F Love", "oOoOO", "of Montreal", "oki-ni", "patten", "readers poll", "sound of 2011", "spêcial club", "tUnE-yArDs", "team rockit", "unofficial", "vi", "xxxchange", "xxxoooo" ], { matchContains:1, maxItemsToShow:10, width: 249 }); $search.focus(function(){ if($(this).val()===original_val){ $(this).val(''); } $("#inputsearch").addClass("short"); $("#submitsearch").show(); }) .blur(function(){ if($(this).val()===''){ $(this).val(original_val); $(this).removeClass("active"); $("#submitsearch").hide(); $("#inputsearch").removeClass("short"); } else{ $(this).addClass("active"); } }); }); // AUTOCOMPLETE jQuery.autocomplete = function(input, options) { // Create a link to self var me = this; // Create jQuery object for input element var $input = $(input).attr("autocomplete", "off"); // Apply inputClass if necessary if (options.inputClass) $input.addClass(options.inputClass); // Create results var results = document.createElement("div"); // Create jQuery object for results var $results = $(results); $results.hide().addClass(options.resultsClass).css("position", "absolute"); if( options.width > 0 ) $results.css("width", options.width); // Add to body element $("body").append(results); input.autocompleter = me; var timeout = null; var prev = ""; var active = -1; var cache = {}; var keyb = false; var hasFocus = false; var lastKeyPressCode = null; // flush cache function flushCache(){ cache = {}; cache.data = {}; cache.length = 0; }; // flush cache flushCache(); // if there is a data array supplied if( options.data != null ){ var sFirstChar = "", stMatchSets = {}, row = []; // no url was specified, we need to adjust the cache length to make sure it fits the local data store if( typeof options.url != "string" ) options.cacheLength = 1; // loop through the array and create a lookup structure for( var i=0; i < options.data.length; i++ ){ // if row is a string, make an array otherwise just reference the array row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]); // if the length is zero, don't add to list if( row[0].length > 0 ){ // get the first character sFirstChar = row[0].substring(0, 1).toLowerCase(); // if no lookup array for this character exists, look it up now if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = []; // if the match is a string stMatchSets[sFirstChar].push(row); } } // add the data items to the cache for( var k in stMatchSets ){ // increase the cache size options.cacheLength++; // add to the cache addToCache(k, stMatchSets[k]); } } $input .keydown(function(e) { // track last key pressed lastKeyPressCode = e.keyCode; switch(e.keyCode) { case 38: // up e.preventDefault(); moveSelect(-1); break; case 40: // down e.preventDefault(); moveSelect(1); break; case 9: // tab case 13: // return if( selectCurrent() ){ // make sure to blur off the current field $input.get(0).blur(); e.preventDefault(); } break; default: active = -1; if (timeout) clearTimeout(timeout); timeout = setTimeout(function(){onChange();}, options.delay); break; } }) .focus(function(){ // track whether the field has focus, we shouldn't process any results if the field no longer has focus hasFocus = true; }) .blur(function() { // track whether the field has focus hasFocus = false; hideResults(); }); hideResultsNow(); function onChange() { // ignore if the following keys are pressed: [del] [shift] [capslock] if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide(); var v = $input.val(); if (v == prev) return; prev = v; if (v.length >= options.minChars) { $input.addClass(options.loadingClass); requestData(v); } else { $input.removeClass(options.loadingClass); $results.hide(); $('#search input#inputsearch').removeClass('alt'); } }; function moveSelect(step) { var lis = $("li", results); if (!lis) return; active += step; if (active < 0) { active = 0; } else if (active >= lis.size()) { active = lis.size() - 1; } lis.removeClass("ac_over"); $(lis[active]).addClass("ac_over"); // Weird behaviour in IE // if (lis[active] && lis[active].scrollIntoView) { // lis[active].scrollIntoView(false); // } }; function selectCurrent() { var li = $("li.ac_over", results)[0]; if (!li) { var $li = $("li", results); if (options.selectOnly) { if ($li.length == 1) li = $li[0]; } else if (options.selectFirst) { li = $li[0]; } } if (li) { selectItem(li); return true; } else { return false; } }; function selectItem(li) { if (!li) { li = document.createElement("li"); li.extra = []; li.selectValue = ""; } var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML); input.lastSelected = v; prev = v; $results.html(""); $input.val(v); hideResultsNow(); if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1); }; // selects a portion of the input string function createSelection(start, end){ // get a reference to the input element var field = $input.get(0); if( field.createTextRange ){ var selRange = field.createTextRange(); selRange.collapse(true); selRange.moveStart("character", start); selRange.moveEnd("character", end); selRange.select(); } else if( field.setSelectionRange ){ field.setSelectionRange(start, end); } else { if( field.selectionStart ){ field.selectionStart = start; field.selectionEnd = end; } } field.focus(); }; // fills in the input box w/the first match (assumed to be the best match) function autoFill(sValue){ // if the last user key pressed was backspace, don't autofill if( lastKeyPressCode != 8 ){ // fill in the value (keep the case the user has typed) $input.val($input.val() + sValue.substring(prev.length)); // select the portion of the value not typed by the user (so the next character will erase) createSelection(prev.length, sValue.length); } }; function showResults() { // get the position of the input field right now (in case the DOM is shifted) var pos = findPos(input); // either use the specified width, or autocalculate based on form element var iWidth = (options.width > 0) ? options.width : $input.width(); // reposition $results.css({ width: parseInt(iWidth) + "px", top: (pos.y + input.offsetHeight) + "px", left: pos.x + "px" }).show(); $('#search input#inputsearch').addClass('alt'); }; function hideResults() { if (timeout) clearTimeout(timeout); timeout = setTimeout(hideResultsNow, 200); }; function hideResultsNow() { if (timeout) clearTimeout(timeout); $input.removeClass(options.loadingClass); if ($results.is(":visible")) { $results.hide(); } if (options.mustMatch) { var v = $input.val(); if (v != input.lastSelected) { selectItem(null); } } $('#search input#inputsearch').removeClass('alt'); }; function receiveData(q, data) { if (data) { $input.removeClass(options.loadingClass); results.innerHTML = ""; // if the field no longer has focus or if there are no matches, do not display the drop down if( !hasFocus || data.length == 0 ) return hideResultsNow(); if ($.browser.msie) { // we put a styled iframe behind the calendar so HTML SELECT elements don't show through $results.append(document.createElement('iframe')); } results.appendChild(dataToDom(data)); // autofill in the complete box w/the first match as long as the user hasn't entered in more data if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]); showResults(); } else { hideResultsNow(); } }; function parseData(data) { if (!data) return null; var parsed = []; var rows = data.split(options.lineSeparator); for (var i=0; i < rows.length; i++) { var row = $.trim(rows[i]); if (row) { parsed[parsed.length] = row.split(options.cellSeparator); } } return parsed; }; function dataToDom(data) { var ul = document.createElement("ul"); var num = data.length; // limited results to a max number if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow; for (var i=0; i < num; i++) { var row = data[i]; if (!row) continue; var li = document.createElement("li"); if (options.formatItem) { li.innerHTML = options.formatItem(row, i, num); li.selectValue = row[0]; } else { li.innerHTML = row[0]; li.selectValue = row[0]; } var extra = null; if (row.length > 1) { extra = []; for (var j=1; j < row.length; j++) { extra[extra.length] = row[j]; } } li.extra = extra; ul.appendChild(li); $(li).hover( function() { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); }, function() { $(this).removeClass("ac_over"); } ).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) }); } return ul; }; function requestData(q) { if (!options.matchCase) q = q.toLowerCase(); var data = options.cacheLength ? loadFromCache(q) : null; // recieve the cached data if (data) { receiveData(q, data); // if an AJAX url has been supplied, try loading the data now } else if( (typeof options.url == "string") && (options.url.length > 0) ){ $.get(makeUrl(q), function(data) { data = parseData(data); addToCache(q, data); receiveData(q, data); }); // if there's been no data found, remove the loading class } else { $input.removeClass(options.loadingClass); } }; function makeUrl(q) { var url = options.url + "?q=" + encodeURI(q); for (var i in options.extraParams) { url += "&" + i + "=" + encodeURI(options.extraParams[i]); } return url; }; function loadFromCache(q) { if (!q) return null; if (cache.data[q]) return cache.data[q]; if (options.matchSubset) { for (var i = q.length - 1; i >= options.minChars; i--) { var qs = q.substr(0, i); var c = cache.data[qs]; if (c) { var csub = []; for (var j = 0; j < c.length; j++) { var x = c[j]; var x0 = x[0]; if (matchSubset(x0, q)) { csub[csub.length] = x; } } return csub; } } } return null; }; function matchSubset(s, sub) { if (!options.matchCase) s = s.toLowerCase(); var i = s.indexOf(sub); if (i == -1) return false; return i == 0 || options.matchContains; }; this.flushCache = function() { flushCache(); }; this.setExtraParams = function(p) { options.extraParams = p; }; this.findValue = function(){ var q = $input.val(); if (!options.matchCase) q = q.toLowerCase(); var data = options.cacheLength ? loadFromCache(q) : null; if (data) { findValueCallback(q, data); } else if( (typeof options.url == "string") && (options.url.length > 0) ){ $.get(makeUrl(q), function(data) { data = parseData(data) addToCache(q, data); findValueCallback(q, data); }); } else { // no matches findValueCallback(q, null); } } function findValueCallback(q, data){ if (data) $input.removeClass(options.loadingClass); var num = (data) ? data.length : 0; var li = null; for (var i=0; i < num; i++) { var row = data[i]; if( row[0].toLowerCase() == q.toLowerCase() ){ li = document.createElement("li"); if (options.formatItem) { li.innerHTML = options.formatItem(row, i, num); li.selectValue = row[0]; } else { li.innerHTML = row[0]; li.selectValue = row[0]; } var extra = null; if( row.length > 1 ){ extra = []; for (var j=1; j < row.length; j++) { extra[extra.length] = row[j]; } } li.extra = extra; } } if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1); } function addToCache(q, data) { if (!data || !q || !options.cacheLength) return; if (!cache.length || cache.length > options.cacheLength) { flushCache(); cache.length++; } else if (!cache[q]) { cache.length++; } cache.data[q] = data; }; function findPos(obj) { var curleft = obj.offsetLeft || 0; var curtop = obj.offsetTop || 0; while (obj = obj.offsetParent) { curleft += obj.offsetLeft curtop += obj.offsetTop } return {x:curleft,y:curtop}; } } jQuery.fn.autocomplete = function(url, options, data) { // Make sure options exists options = options || {}; // Set url as option options.url = url; // set some bulk local data options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null; // Set default values for required options options.inputClass = options.inputClass || "ac_input"; options.resultsClass = options.resultsClass || "ac_results"; options.lineSeparator = options.lineSeparator || "\n"; options.cellSeparator = options.cellSeparator || "|"; options.minChars = options.minChars || 1; options.delay = options.delay || 400; options.matchCase = options.matchCase || 0; options.matchSubset = options.matchSubset || 1; options.matchContains = options.matchContains || 0; options.cacheLength = options.cacheLength || 1; options.mustMatch = options.mustMatch || 0; options.extraParams = options.extraParams || {}; options.loadingClass = options.loadingClass || "ac_loading"; options.selectFirst = options.selectFirst || false; options.selectOnly = options.selectOnly || false; options.maxItemsToShow = options.maxItemsToShow || -1; options.autoFill = options.autoFill || false; options.width = parseInt(options.width, 10) || 0; this.each(function() { var input = this; new jQuery.autocomplete(input, options); }); // Don't break the chain return this; } jQuery.fn.autocompleteArray = function(data, options) { return this.autocomplete(null, options, data); } jQuery.fn.indexOf = function(e){ for( var i=0; i