Skip to content

Instantly share code, notes, and snippets.

@reynish
Created March 6, 2013 21:47
Show Gist options
  • Save reynish/5103382 to your computer and use it in GitHub Desktop.
Save reynish/5103382 to your computer and use it in GitHub Desktop.
A CodePen by Alex Reynish. fauxSelector - Change a <select> into a searchable list!
%h2 Something
%section.wrapper
%h1 fauxSelector
%select.fauxSelector
%option{:value => "PS"} Please select
%option{:value => "S"} Soemthing
%option{:value => "SE"} Something else
%section.wrapper
%h1 fauxSelector
%select.fauxSelector
%option{:value => "Blah"} Blah
%option{:value => "Blog"} Blog
%option{:value => "Dog"} Dog
%option{:value => "Fog"} Fog
%option{:value => "Bog"} Bog
;(function ( $, window, document, undefined ) {
// Create the defaults once
var pluginName = "fauxSelector",
defaults = {
inputPlaceholder: "Type to search",
inputWrapper: ".wrapper",
inputAttrView: "viewing"
};
// The actual plugin constructor
function Plugin( element, options ) {
this.element = element;
this.options = $.extend( {}, defaults, options );
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function() {
var self = this;
// Build elements to add to the DOM
var input = '<input type="text" placeholder="' + self.options.inputPlaceholder + '" class="fs-input" />';
var list = '<ul class="fs-list"></ul>';
var stuff = input + list + "";
// Add them
$(stuff).insertAfter(this.element);
// Build a list thing
var optionsList = this.optionsIterate();
var aList = this.buildList(optionsList);
console.log();
// Add it
$(this.element).nextAll(".fs-list").html(aList.join(""));
// Hide select
$(this.element).removeClass("fs-init").addClass("visuallyhidden focusable fs-ready");
// Set viewing to 0;
self.viewing("init");
// Setup the Input element
var inputDOM = $(this.element).nextAll(".fs-input");
inputDOM.on("focus blur keyup", function (event) {
var el = $(this);
var viewing = el.data(self.options.inputAttrView);
var list = $(this).nextAll(".fs-list");
if (event.type === "focus") {
self.viewing("up");
list.addClass("active");
}
if (event.type === "blur") {
self.viewing("down");
}
if (event.type === "keyup") {
var query = $(this).val();
self.queryList(query);
};
});
// Setup the list
var listDOM = $(this.element).nextAll(".fs-list");
listDOM
.on("focusin mouseenter", function (event) {
self.viewing("up");
})
.on("focusout mouseleave", function (event) {
self.viewing("down");
})
.on("click", "a", function (event) {
self.select($(event.target));
});
},
// Name: optionsIterate
// Desc: Iterates over the child <option> of this.element
// Returns: Object of options
optionsIterate: function() {
var options = $(this.element).children("option");
var listOptions = [];
var numOfOpt = 0;
options.each(function(){
var listOption = {
value: $(this).val(),
text: $(this).text()
}
listOptions.push(listOption);
});
return listOptions;
},
buildList: function(listOptions) {
var list = [];
for (var key in listOptions){
var opt = listOptions[key];
list.push('<li><a data-key="' + key + '" data-value="' + opt.value + '">' + opt.text + '</a></li>');
};
return list;
},
queryList: function(query) {
var self = this;
var query = query.toLowerCase();
var list = $(this.element).nextAll(".fs-list");
if (query.length >= 1) {
$(self.element).trigger("fs-searchstart");
var listAs = list.find("a");
listAs.each(function() {
var text = $(this).text().toLowerCase()
if (!$(this).is(':contains("' + query + '")')) {
$(this).hide();
} else {
$(this).show();
};
//console.log($(this).is(':contains("' + query + '")'));
});
} else {
list.find("a").show();
};
$(self.element).trigger("fs-searchend");
},
list: function(option){
var list = $(this.element).nextAll(".fs-list");
if(option === "hide"){
list.removeClass("active");
}
},
select: function(item) {
var index = item.attr("data-key");
var value = item.attr("data-value");
var text = item.text();
$(this.element).val(value).trigger("change");
$(this.element).nextAll(".fs-input").attr("placeholder", text);
},
viewing: function(option) {
var self = this;
var wrapper = $(this.element).parents(self.options.inputWrapper);
var viewing = wrapper.data(self.options.inputAttrView);
if (option === "init") {
wrapper.data(self.options.inputAttrView, 0);
}
if (option === "up" && viewing !== 2) {
wrapper.data(self.options.inputAttrView, ++viewing);
}
if (option === "down" && viewing !== 0) {
wrapper.data(self.options.inputAttrView, --viewing);
}
if (wrapper.data(self.options.inputAttrView) === 0) {
self.list("hide");
}
console.log(wrapper.data(self.options.inputAttrView));
}
};
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new Plugin( this, options ));
}
});
};
})( jQuery, window, document );
$('.fauxSelector').fauxSelector();
$('.fauxSelector').on("change", function (event) {
console.log($(this).val());
});
@import "compass";
@import "compass";
.wrapper {
width: 50%;
margin: 0 auto;
padding: 2em;
}
.fauxSelector {
@include transition-property(width);
}
.fs-list {
margin: 0;
padding: 0;
list-style: none;
display: none;
border: 1px solid #000;
&.active {
display: block;
}
li {
}
a {
display: block;
padding: .25em;
}
}
/*
* Hide from both screenreaders and browsers: h5bp.com/u
*/
.hidden {
display: none !important;
visibility: hidden;
}
/*
* Hide only visually, but have it available for screenreaders: h5bp.com/v
*/
.visuallyhidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
/*
* Extends the .visuallyhidden class to allow the element to be focusable
* when navigated to via the keyboard: h5bp.com/p
*/
.visuallyhidden.focusable:active,
.visuallyhidden.focusable:focus {
clip: auto;
height: auto;
margin: 0;
overflow: visible;
position: static;
width: auto;
}
@mixin animation($value) {
@include experimental(animation, $value,
-moz, -webkit, -o, not -ms, not -khtml, official);
}
@mixin keyframes($name){
@-webkit-keyframes #{$name} { @content; }
@-moz-keyframes #{$name} { @content; }
@-o-keyframes #{$name} { @content; }
@keyframes #{$name} { @content; }
}
@include keyframes(fold) {
0% {
margin-bottom: -8px;
visibility: visible;
line-height: 0;
@include transform-origin(0, 0, 0);
@include transform(rotate3d(1, 0, 0, -90deg));
}
33.333% {
margin-bottom: 4px;
line-height: 16px;
@include transform(rotate3d(1, 0, 0, 0deg));
}
66.667% {
margin-bottom: 2px;
@include transform(rotate3d(1, 0, 0, 25deg));
}
100% {
margin-bottom: 0;
visibility: visible;
height: auto;
@include transform-origin(0, 0, 0);
@include transform(rotate3d(1, 0, 0, 0deg));
}
}
body {
@include perspective(400);
}
.fs-list {
@include animation(fold ease-in 500ms);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment