展开运算符解构赋值_解构式展开式搜索栏

展开运算符解构赋值

展开运算符解构赋值

ExpandingSearchBar

Maybe you have noticed the little adjustments that we did to our theme lately here on Codrops. One of the things we thought might be nice to change is the search input. We’ve put it from the sidebar into the header and we use a common effect where you have to click to expand the input. We have received many requests on explaining how we did it and today we’d like to show you how to create a search input like that from scratch. The aim is to maximize compatibility for mobile devices and older browsers (down to IE8). Although this might seem like a super-easy thing, we’ll have to apply some tricks in order to make it work properly.

也许您已经注意到最近在Codrops上对主题所做的一些小的调整。 我们认为可能会改变的一件事是搜索输入。 我们已将其从侧边栏中放入标题中,并且使用了一种常见效果,您必须单击以展开输入。 我们收到了许多关于如何解释的请求,今天,我们想向您展示如何从头开始创建搜索输入。 目的是最大程度地提高与移动设备和旧版浏览器(低至IE8)的兼容性。 尽管这似乎是一件非常容易的事,但我们必须应用一些技巧才能使其正常工作。

Summarized, this is what we want the search component to do:

总而言之,这就是我们希望搜索组件执行的操作:

  • Initially, we only want to show a button with a search icon.

    最初,我们只想显示带有搜索图标的按钮。

  • When clicking on the icon, we want a search input to slide out.

    单击图标时,我们希望搜索输入滑出。

  • The component should be fluid, meaning that we can use it in a responsive context.

    该组件应该是可变的,这意味着我们可以在响应上下文中使用它。

  • When we type something we want to be able to submit the form by either hitting enter or clicking on the search icon.

    当我们键入内容时,我们希望能够通过按Enter或单击搜索图标来提交表单。

  • If the input is expanded and empty, and we click on the search icon, we want the input to close again.

    如果输入被展开并且为空,然后单击搜索图标,我们希望输入再次关闭。

  • We also want the input to close when we click outside of the search bar, be it empty or not.

    当我们在搜索栏之外单击时,也希望输入关闭,无论是否为空。

  • Without JavaScript, we want the search bar to be shown expanded.

    没有JavaScript,我们希望搜索栏显示为展开。

  • For a smoother experience on touch devices, we’ll also want to add support for touch events.

    为了在触摸设备上获得更流畅的体验,我们还希望增加对触摸事件的支持。

Now that we know what we want to do, let’s start with the markup.

现在我们知道我们想要做什么,让我们从标记开始。

标记 (The Markup)

For the markup we need a main container, a form, the text and submit inputs, and a span for the icon:

对于标记,我们需要一个主容器,一个表单,文本和提交输入以及图标的span


<div id="sb-search" class="sb-search">
	<form>
		<input class="sb-search-input" placeholder="Enter your search term..." type="search" value="" name="search" id="search">
		<input class="sb-search-submit" type="submit" value="">
		<span class="sb-icon-search"></span>
	</form>
</div>

Usually, we could use a pseudo-element for the icon, but because it’s not intended to be used on replaced elements like form elements, we will simply use a span in this case.

通常,我们可以为图标使用伪元素,但是由于它不打算在诸如表单元素之类的替换元素上使用,因此在这种情况下,我们将仅使用span

With all the elements in place, let’s start styling them.

在所有元素都准备就绪后,让我们开始对其进行样式设计。

CSS (The CSS)

Following our requirements, we should first make sure that we have a button with a search icon visible. The rest should be hidden. But let’s also think one step ahead and imagine what happens when we enlarge the search bar (the main wrapper). How do we do this? Let’s make use of overflow: hidden and expanding the width of the sb-search wrapper should reveal the input.

按照我们的要求,我们首先应确保有一个带有可见搜索图标的按钮。 其余应隐藏。 但是,让我们先思考一步,想象一下扩大搜索栏(主包装器)时会发生什么。 我们如何做到这一点? 让我们利用overflow: hidden和扩展sb-search包装器的宽度应该显示输入。

So, the first thing we style is the sb-search wrapper. We make it float on the right side and set the overflow to hidden. The width should naturally be 60px but since we will want to animate to a width of 100%, be will get in trouble on mobile (iOS) browsers. They don’t like to transition from a pixel-based width to a percentage-based one. They’ll simply omit the transition. So instead we define a min-width value of 60px and a width of 0%. This brilliant solution is by @julienknebel and he writes about it here: CSS transition from a fixed px width to an auto width.

因此,我们样式化的第一件事是sb-search包装器。 我们将其浮动在右侧,并将溢出设置为hidden 。 宽度自然应该是60像素,但是由于我们要为100%的宽度设置动画,因此在移动(iOS)浏览器上会遇到麻烦。 他们不喜欢从基于像素的宽度过渡到基于百分比的宽度。 他们只会忽略过渡。 因此,我们定义的最小宽度值为60px,宽度为0%。 这个出色的解决方案是@julienknebel撰写的,他在这里写道: CSS从固定px宽度过渡到自动width

We’ll also add a transition for the width and -webkit-backface-visibility: hidden to avoid some traces of the input for mobile (iOS) browsers:

我们还将为width和-webkit-backface-visibility: hidden添加过渡,以避免对移动(iOS)浏览器的输入产生一些痕迹:


.sb-search {
	position: relative;
	margin-top: 10px;
	width: 0%;
	min-width: 60px;
	height: 60px;
	float: right;
	overflow: hidden;

	-webkit-transition: width 0.3s;
	-moz-transition: width 0.3s;
	transition: width 0.3s;

	-webkit-backface-visibility: hidden;
}

Everything that is overflowing this little box, won’t be visible.

这个小盒子满溢的所有东西都不可见。

Now, let’s position the search input. We’ll set a percentage-based width so that when we expand the parent, the input will expand with it. Setting the right height, font-size and padding will ensure that the text is centered (using line-height won’t work as expected in IE8, so let’s set the paddings instead). Setting the input to position absolute might not seem necessary, but it solves a nasty little thing that happens sometimes when closing the search: the input seems visible on the right side for a very short moment.

现在,让我们放置搜索输入。 我们将设置一个基于百分比的宽度,以便在扩展父级时,输入将随之扩展。 设置正确的高度,字体大小和填充将确保文本居中(使用line-height不能按预期在IE8中工作,因此让我们设置填充)。 将输入设置为绝对位置似乎不是必需的,但是它解决了有时在关闭搜索时发生的讨厌的小事情:在很短的时间内,输入在右侧似乎是可见的。


.sb-search-input {
	position: absolute;
	top: 0;
	right: 0;
	border: none;
	outline: none;
	background: #fff;
	width: 100%;
	height: 60px;
	margin: 0;
	z-index: 10;
	padding: 20px 65px 20px 20px;
	font-family: inherit;
	font-size: 20px;
	color: #2c3e50;
}

input[type="search"].sb-search-input {
	-webkit-appearance: none;
	-webkit-border-radius: 0px;
}

Additionally, we are removing the default styles of the search input for WebKit browsers.

此外,我们将删除WebKit浏览器的搜索输入的默认样式。

Let’s define the color of the placeholder text with these vendor-specific rules:

让我们使用这些特定于供应商的规则定义占位符文本的颜色:


.sb-search-input::-webkit-input-placeholder {
	color: #efb480;
}

.sb-search-input:-moz-placeholder {
	color: #efb480;
}

.sb-search-input::-moz-placeholder {
	color: #efb480;
}

.sb-search-input:-ms-input-placeholder {
	color: #efb480;
}

Now, let’s take care of the search icon button and the submit input. We know that we want them in the same place, so let’s position them on the right corner and set the same dimensions. Since they will be on top of each other, we’ll set them to absolute positioning:

现在,让我们处理搜索图标按钮和提交输入。 我们知道我们希望它们在同一位置,因此让我们将它们放置在右角并设置相同的尺寸。 由于它们将彼此重叠,因此我们将它们设置为绝对定位:


.sb-icon-search,
.sb-search-submit  {
	width: 60px;
	height: 60px;
	display: block;
	position: absolute;
	right: 0;
	top: 0;
	padding: 0;
	margin: 0;
	line-height: 60px;
	text-align: center;
	cursor: pointer;
}

Initially, we will want to have the icon button clickable. Then, when we open the input, we want the submit input to be clickable. So, well set the z-index of the submit input to -1 in the beginning and make it transparent, so that we always see the search icon span:

最初,我们要使图标按钮可单击。 然后,当我们打开输入时,我们希望提交输入是可单击的。 因此,在开始时将提交输入的z-index设置为-1并使其透明,以便我们始终看到搜索图标的范围:


.sb-search-submit {
	background: #fff; /* IE needs this */
	-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* IE 8 */
    filter: alpha(opacity=0); /* IE 5-7 */
    opacity: 0;
	color: transparent;
	border: none;
	outline: none;
	z-index: -1;
}

Why not just setting the background to transparent? That does not seem to work nicely in IE because the element is not clickable like that. So we use a solid background color and set the opacity to 0 instead.

为什么不只是将背景设置为透明? 在IE中,这似乎不太好用,因为该元素不可单击。 因此,我们使用纯色背景色并将不透明度设置为0。

The search icon span will have a high z-index initially, because we want it to be on top of everything. We’ll use the pseudo-element :before to add the search icon:

搜索图标范围最初将具有较高的z-index,因为我们希望它位于一切之上。 我们将使用伪元素:before添加搜索图标:


.sb-icon-search {
	color: #fff;
	background: #e67e22;
	z-index: 90;
	font-size: 22px;
	font-family: 'icomoon';
	speak: none;
	font-style: normal;
	font-weight: normal;
	font-variant: normal;
	text-transform: none;
	-webkit-font-smoothing: antialiased;
}

.sb-icon-search:before {
	content: "e000";
}

Let’s not forget to include the web font at the beginning of our CSS:

我们不要忘记在CSS的开头包含网络字体:


/* Search icon by IcoMoon, made with http://icomoon.io/app/ */
@font-face {
	font-family: 'icomoon';
	src:url('../fonts/icomoon/icomoon.eot');
	src:url('../fonts/icomoon/icomoon.eot?#iefix') format('embedded-opentype'),
		url('../fonts/icomoon/icomoon.woff') format('woff'),
		url('../fonts/icomoon/icomoon.ttf') format('truetype'),
		url('../fonts/icomoon/icomoon.svg#icomoon') format('svg');
	font-weight: normal;
	font-style: normal;
}

With the styles defined the way we did, we can now simply set the width of the sb-search wrapper to be 100% when we add the sb-search-open class. Without JavaScript, we want the search input to be open by default:

通过定义样式的方式,我们现在可以简单地在添加sb-search-open类时将sb-search包装器的宽度设置为100%。 如果没有JavaScript,我们希望默认情况下打开搜索输入:


.sb-search.sb-search-open,
.no-js .sb-search {
	width: 100%;
}

Let’s change the color of the search icon span and put it below the submit input by setting the z-index to a lower value:

让我们通过将z-index设置为较低的值来更改搜索图标跨度的颜色并将其置于提交输入下方:


.sb-search.sb-search-open .sb-icon-search,
.no-js .sb-search .sb-icon-search {
	background: #da6d0d;
	color: #fff;
	z-index: 11;
}

And finally, we set the submit input’s z-index to a higher value so that we can click on it:

最后,我们将提交输入的z-index设置为较高的值,以便可以单击它:


.sb-search.sb-search-open .sb-search-submit,
.no-js .sb-search .sb-search-submit {
	z-index: 90;
}

With all the necessary styles defined, let’s do the JavaScript.

定义了所有必需的样式后,我们来编写JavaScript。

JavaScript (The JavaScript)

Let’s start by toggling the sb-search-open class. We add the class when we click on the main wrapper (sb-search) and we remove it when we click on the submit input, only if the search input is empty. Otherwise we submit the form. In order not to trigger the class removal when we click on the input (since our trigger is the whole wrapper), we need to prevent the click event bubbling on that element. This means that clicking on the input will not cause a click being triggered on its parents.

让我们从切换sb-search-open类开始。 我们在单击主包装器(sb-search)时添加该类,并在单击Submit输入时将其删除,前提是搜索输入为空。 否则,我们将提交表格。 为了在单击输入时不触发类的移除(因为触发器是整个包装器),我们需要防止click事件在该元素上冒泡。 这意味着单击输入不会导致对其父项触发单击。


;( function( window ) {
	
	function UISearch( el, options ) {	
		this.el = el;
		this.inputEl = el.querySelector( 'form > input.sb-search-input' );
		this._initEvents();
	}

	UISearch.prototype = {
		_initEvents : function() {
			var self = this,
				initSearchFn = function( ev ) {
					if( !classie.has( self.el, 'sb-search-open' ) ) { // open it
						ev.preventDefault();
						self.open();
					}
					else if( classie.has( self.el, 'sb-search-open' ) && /^s*$/.test( self.inputEl.value ) ) { // close it
						self.close();
					}
				}

			this.el.addEventListener( 'click', initSearchFn );
			this.inputEl.addEventListener( 'click', function( ev ) { ev.stopPropagation(); });
		},
		open : function() {
			classie.add( this.el, 'sb-search-open' );
		},
		close : function() {
			classie.remove( this.el, 'sb-search-open' );
		}
	}

	// add to global namespace
	window.UISearch = UISearch;

} )( window );

Next, we’ll need to add the events for removing the sb-search-open class when we click somewhere else, outside of our search bar. For this to work we also need to take care of the event bubbling when clicking on the main wrapper.

接下来,我们需要添加事件,以在单击搜索栏之外的其他位置时删除sb-search-open类。 为此,我们还需要在单击主包装时注意事件冒泡。


;( function( window ) {
	
	function UISearch( el, options ) {	
		this.el = el;
		this.inputEl = el.querySelector( 'form > input.sb-search-input' );
		this._initEvents();
	}

	UISearch.prototype = {
		_initEvents : function() {
			var self = this,
				initSearchFn = function( ev ) {
					ev.stopPropagation();
					
					if( !classie.has( self.el, 'sb-search-open' ) ) { // open it
						ev.preventDefault();
						self.open();
					}
					else if( classie.has( self.el, 'sb-search-open' ) && /^s*$/.test( self.inputEl.value ) ) { // close it
						self.close();
					}
				}

			this.el.addEventListener( 'click', initSearchFn );
			this.inputEl.addEventListener( 'click', function( ev ) { ev.stopPropagation(); });
		},
		open : function() {
			var self = this;
			classie.add( this.el, 'sb-search-open' );
			// close the search input if body is clicked
			var bodyFn = function( ev ) {
				self.close();
				this.removeEventListener( 'click', bodyFn );
			};
			document.addEventListener( 'click', bodyFn );
		},
		close : function() {
			classie.remove( this.el, 'sb-search-open' );
		}
	}

	// add to global namespace
	window.UISearch = UISearch;

} )( window );

Another thing that we want to take care of is trimming the search term. Also, when we click on the search icon, we want the input to be focused. Since this causes some jerky transition on mobile (iOS) browsers (the keyboard will open at the same time), we will want to avoid that for this case. When we close the search bar, we’ll blur the search input. This will solve some issues on some devices that show the cursor blinking even after the input is closed.

我们要注意的另一件事是修剪搜索词。 另外,当我们单击搜索图标时,我们希望输入内容集中。 由于这会导致在移动(iOS)浏览器上出现剧烈变化(键盘将同时打开),因此在这种情况下,我们希望避免这种情况。 关闭搜索栏时,将模糊搜索输入。 这将解决某些设备上的一些问题,即使关闭输入后,这些设备仍会显示光标闪烁。


;( function( window ) {

	// http://stackoverflow.com/a/11381730/989439
	function mobilecheck() {
		var check = false;
		(function(a){if(/(android|ipad|playbook|silk|bbd+|meego).+mobile|avantgo|bada/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)/|plucker|pocket|psp|series(4|6)0|symbian|treo|up.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
		return check;
	}

	// http://www.jonathantneal.com/blog/polyfills-and-prototypes/
	!String.prototype.trim && (String.prototype.trim = function() {
		return this.replace(/^s+|s+$/g, '');
	});
	
	function UISearch( el, options ) {	
		this.el = el;
		this.inputEl = el.querySelector( 'form > input.sb-search-input' );
		this._initEvents();
	}

	UISearch.prototype = {
		_initEvents : function() {
			var self = this,
				initSearchFn = function( ev ) {
					ev.stopPropagation();
					// trim its value
					self.inputEl.value = self.inputEl.value.trim();
					
					if( !classie.has( self.el, 'sb-search-open' ) ) { // open it
						ev.preventDefault();
						self.open();
					}
					else if( classie.has( self.el, 'sb-search-open' ) && /^s*$/.test( self.inputEl.value ) ) { // close it
						self.close();
					}
				}

			this.el.addEventListener( 'click', initSearchFn );
			this.inputEl.addEventListener( 'click', function( ev ) { ev.stopPropagation(); });
		},
		open : function() {
			var self = this;
			classie.add( this.el, 'sb-search-open' );
			// focus the input
			if( !mobilecheck() ) {
				this.inputEl.focus();
			}
			// close the search input if body is clicked
			var bodyFn = function( ev ) {
				self.close();
				this.removeEventListener( 'click', bodyFn );
			};
			document.addEventListener( 'click', bodyFn );
		},
		close : function() {
			this.inputEl.blur();
			classie.remove( this.el, 'sb-search-open' );
		}
	}

	// add to global namespace
	window.UISearch = UISearch;

} )( window );

For everything to work smoothly on mobile devices, we’ll need to add the respective touch events. Adding preventDefault in the initSearchFn function will prevent the touch and the click events to trigger simultaneously on touch devices.

为了使一切在移动设备上都能正常运行,我们需要添加相应的触摸事件。 在initSearchFn函数中添加preventDefault将防止触摸事件和click事件在触摸设备上同时触发。


;( function( window ) {
	
	// http://stackoverflow.com/a/11381730/989439
	function mobilecheck() {
		var check = false;
		(function(a){if(/(android|ipad|playbook|silk|bbd+|meego).+mobile|avantgo|bada/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)/|plucker|pocket|psp|series(4|6)0|symbian|treo|up.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
		return check;
	}
	
	// http://www.jonathantneal.com/blog/polyfills-and-prototypes/
	!String.prototype.trim && (String.prototype.trim = function() {
		return this.replace(/^s+|s+$/g, '');
	});

	function UISearch( el, options ) {	
		this.el = el;
		this.inputEl = el.querySelector( 'form > input.sb-search-input' );
		this._initEvents();
	}

	UISearch.prototype = {
		_initEvents : function() {
			var self = this,
				initSearchFn = function( ev ) {
					ev.stopPropagation();
					// trim its value
					self.inputEl.value = self.inputEl.value.trim();
					
					if( !classie.has( self.el, 'sb-search-open' ) ) { // open it
						ev.preventDefault();
						self.open();
					}
					else if( classie.has( self.el, 'sb-search-open' ) && /^s*$/.test( self.inputEl.value ) ) { // close it
						ev.preventDefault();
						self.close();
					}
				}

			this.el.addEventListener( 'click', initSearchFn );
			this.el.addEventListener( 'touchstart', initSearchFn );
			this.inputEl.addEventListener( 'click', function( ev ) { ev.stopPropagation(); });
			this.inputEl.addEventListener( 'touchstart', function( ev ) { ev.stopPropagation(); } );
		},
		open : function() {
			var self = this;
			classie.add( this.el, 'sb-search-open' );
			// focus the input
			if( !mobilecheck() ) {
				this.inputEl.focus();
			}
			// close the search input if body is clicked
			var bodyFn = function( ev ) {
				self.close();
				this.removeEventListener( 'click', bodyFn );
				this.removeEventListener( 'touchstart', bodyFn );
			};
			document.addEventListener( 'click', bodyFn );
			document.addEventListener( 'touchstart', bodyFn );
		},
		close : function() {
			this.inputEl.blur();
			classie.remove( this.el, 'sb-search-open' );
		}
	}

	// add to global namespace
	window.UISearch = UISearch;

} )( window );

Finally, for browsers that don’t support the addEventListener and removeEventListener we use Jonathan Neal’s EventListener polyfill.

最后,对于不支持addEventListenerremoveEventListener浏览器,我们使用Jonathan Neal的EventListener polyfill


// EventListener | @jon_neal | //github.com/jonathantneal/EventListener
!window.addEventListener && window.Element && (function () {
	function addToPrototype(name, method) {
		Window.prototype[name] = HTMLDocument.prototype[name] = Element.prototype[name] = method;
	}

	var registry = [];

	addToPrototype("addEventListener", function (type, listener) {
		var target = this;

		registry.unshift({
			__listener: function (event) {
				event.currentTarget = target;
				event.pageX = event.clientX + document.documentElement.scrollLeft;
				event.pageY = event.clientY + document.documentElement.scrollTop;
				event.preventDefault = function () { event.returnValue = false };
				event.relatedTarget = event.fromElement || null;
				event.stopPropagation = function () { event.cancelBubble = true };
				event.relatedTarget = event.fromElement || null;
				event.target = event.srcElement || target;
				event.timeStamp = +new Date;

				listener.call(target, event);
			},
			listener: listener,
			target: target,
			type: type
		});

		this.attachEvent("on" + type, registry[0].__listener);
	});

	addToPrototype("removeEventListener", function (type, listener) {
		for (var index = 0, length = registry.length; index < length; ++index) {
			if (registry[index].target == this && registry[index].type == type && registry[index].listener == listener) {
				return this.detachEvent("on" + type, registry.splice(index, 1)[0].__listener);
			}
		}
	});

	addToPrototype("dispatchEvent", function (eventObject) {
		try {
			return this.fireEvent("on" + eventObject.type, eventObject);
		} catch (error) {
			for (var index = 0, length = registry.length; index < length; ++index) {
				if (registry[index].target == this && registry[index].type == eventObject.type) {
					registry[index].call(this, eventObject);
				}
			}
		}
	});
})();

And that’s it! We hope you enjoyed this tutorial and find it useful!

就是这样! 我们希望您喜欢本教程并发现它有用!

翻译自: https://tympanus.net/codrops/2013/06/26/expanding-search-bar-deconstructed/

展开运算符解构赋值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值