1 var Zepto = (function(){ 2 var undefined, key, $, classList, 3 emptyArray = [], 4 concat = emptyArray.concat, 5 //[].filter(callback [, thisArg] ); 6 filter = emptyArray.filter, 7 //slice 数组的拷贝 8 slice = emptyArray.slice, 9 document = window.document, 10 elementDisplay = {}, 11 classCase = {}, 12 cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1, 13 'opacity': 1, 'z-index': 1, 'zoom': 1 }, 14 15 fragmentRE = /^s*<(w+|!)[^>]*>/, //匹配<a href="www.baidu.com" xxx> 16 singleTagRE = /^<(w+)s*/?>(?:</1>|)$/, //匹配的单个标签 17 //非(标签里) 18 tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([w:]+)[^>]*)/>/ig, 19 rootNodeRE = /^(?:body|html)$/i, 20 capitalRE = /([A-Z])/g, 21 22 methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'], 23 adjacencyOperators = ['after', 'prepend', 'before', 'append'], 24 table = document.createElement('table'), 25 tableRow = document.createElement('tr'), 26 containers = { 27 'tr': document.createElement('tbody'), 28 'tbody': table, 'thead': table, 'tfoot': table, 29 'td': tableRow, 'th': tableRow, 30 '*': docuemnt.createElement('div') 31 32 }, 33 34 readyRE = /complete|loaded|interactive/, 35 simpleSelectorRE = /^[w-]*$/, 36 classw2type = {}, 37 toString = class2type.toString, 38 zepto = {}, 39 camelize, uning, 40 tempParent = document.createElement('div'), 41 propMap = { 42 'tabindex': 'tabIndex', 43 'readonly': 'readOnly', 44 'for': 'htmlFor', 45 'class': 'className', 46 'maxlength': 'maxLength', 47 'cellspacinng': 'cellSpacing', 48 'cellpadding': 'cellPadding', 49 'rowspan': 'rowspan', 50 'usemap': 'useMap', 51 'frameborder': 'frameBorder', 52 'contenteditable': 'contentEditable' 53 }, 54 55 isArray = Array.isArray || function( obj ){ 56 return obj instanceof Array; 57 }; 58 59 60 zepto.matches = function( element, selector ){ 61 if( !selector || !element || !elment.nodeType !== 1 ){ 62 return false; 63 } 64 65 var matchesSelecotr = element.webkitMatchesSelector || element.mozMatchesSelector || 66 element.oMatchesSelector || element.matchesSelecotr; 67 68 if( matchesSelecotr ){ 69 return matchesSelector.call( element, selector ); 70 } 71 72 // fall back to performing a selector: 73 var match, parent = element.parentNode, temp = !parent; 74 75 if( temp ){ 76 //没有父节点 77 (parent = tempParent).appendChild( element ); 78 } 79 80 //how to implement it? 81 match = ~zepto.qsa( parent, selector ).indexOf( element ); 82 temp && tempParent.removeChild( element ); 83 return match; 84 } 85 86 //获取参数的类型 {'[object Object]':'objct'} 87 function type( obj ){ 88 return obj == null ? String( obj ) : 89 class2typep[toString.call( obj ) ] || 'object'; 90 } 91 92 function isFunction( valuue ){ 93 return type( value ) === 'function'; 94 } 95 96 function isWindow( obj ){ 97 return obj != null && obj == obj.window; 98 } 99 100 function isDocument( obj ){ 101 return obj != null && obj.nodeType === obj.DOCUMENT_NODE; 102 } 103 104 function isObject( obj ){ 105 return type( obj ) == 'object'; 106 } 107 108 function isPlainObject( obj ){ 109 return isObject( obj ) && !isWindow( obj ) && Object.getPrototypeOf( obj ) == Object.prototype; 110 }; 111 } 112 113 function likeArray( obj ){ 114 return typeof obj.length === 'number'; 115 } 116 117 //过滤空元素 118 function compact( array ){ 119 return filter.call( array, function( item ){ 120 return item != null; 121 }); 122 } 123 124 //concat... 125 function flatten( array ){ 126 return array.length > 0 ? $.fn.concat.apply( [], array ) : array ; 127 } 128 129 //-(-..)a ->-(-..)A. 130 camelize = function( str ){ 131 return str.replace( /-+(.)?)/g, function( match, chr ){ 132 return chr ? char.toUpperCase() : ''; 133 } 134 }; 135 136 137 //::---> / 138 function dasherize( str ){ 139 return str.replace( /::/g, '/') 140 .replace(/([A-Z]+)([A-Z)[a-z]/g, '$1_$2') 141 .replace(/([a-zd])([A-Z])/g, '$1_$2') 142 .replace(/_/g, '-') 143 .toLowerCase(); 144 } 145 146 //剔除掉重复的元素 147 uniq = function( array ){ 148 return filter.call( array, function( item, idx ){ 149 return array.indexOf( item ) == idx ; 150 }); 151 }; 152 153 //存储RegExp对象到classCache对象上. 154 function classRE( name ){ 155 return name in classCache ? 156 classCache[ name ] : ( classCache[ name ] = new RegExp('(^|\s)' + name + '(\s|$)') ); 157 } 158 159 160 //非cssNuber对象上的属性,为数值时,带上 'px' 161 function maybeAddPx( name, value ){ 162 return ( typeof value === 'number' && !cssNumber[dasherize(name)] ) ? value + 'px' : value; 163 } 164 165 // 166 function defaultDisplay( nodeName ){ 167 var element, display; 168 169 if( !elementDisplay[ nodeName ] ){ 170 element = document.createElement( nodeName ); 171 document.body.appendChild( element ); 172 display = getComputedStyle( element, '' ).getPropertyValue('display'); 173 element.parentNode.removeChild( element ); 174 display == 'none' && ( display = 'block' ); 175 elementDisplay[ nodeName ] = display; 176 } 177 178 return elementDisplay[ nodeName ]; 179 } 180 181 //转换成数组,并返回 182 function children( element ){ 183 return 'children' in element ? 184 slice.call( element.children ) : 185 $.map( element.childNodes, function( node ){ 186 if( node.nodeType == 1 ){ 187 return node; 188 } 189 } ); 190 } 191 192 function Z( dom, selector ){ 193 var i, len = dom ? dom.length : 0; 194 for( i = 0; i < len; i++ ){ 195 this[ i ] = dom[ i ]; 196 } 197 this.selector = selector || ''; 198 } 199 200 /* 201 202 */ 203 zepto.fragment = function( html, name, properties ){ 204 var dom, nodes, conntainer; 205 206 //<a ></a> <input /> 207 if( singleTagRE.test( html ) ){ 208 dom = $(document.createElement( RegExp.$1 ) ); 209 } 210 211 if( !dom ){ 212 //将$1,$2 填充成<X></X> 213 if( html.replace ) html = html.replace( tagExpanderRE, "<$1></$2>" ); 214 215 if( name === undefined ) name = fragmentRE.test( html ) && RegExp.$1; 216 217 if( !(name in containers ) ) name = '*'; 218 //取个包装元素 219 container = containers[ name ]; 220 container.innerHTML = '' + html; 221 dom = $.each( slice.call( container.childNodes ), function(){ 222 container.removeChild( this ); // 返回container里子元素 223 }); 224 } 225 226 //是对象的话 227 if( isPlainObject( properties ) ){ 228 nodes = $(dom); 229 $.each(properties, funnction( key, value ){ 230 if(methodAttributes.indexOf( key ) > -1 ){ 231 nodes[ key ]( value ); //对象css赋值 232 }else{ 233 nodes.attr( key, value ); //将值挂到对象上 234 } 235 }); 236 } 237 238 return dom; 239 } 240 241 // 242 zepto.Z = function( dom, selector ){ 243 return new Z( dom, selector ); 244 } 245 246 zepto.isZ = function( object ){ 247 return object instanceof zepto.Z; 248 } 249 250 // 251 zepto.init = function( selector, context ){ 252 var dom; 253 254 if( !selector ) { 255 return zepto.Z(); 256 } else if(typeof selector === 'string' ) { 257 selector = selector.trim(); 258 259 if( selector[ 0 ] == '<' && fragmentRE.test( selector ) ){ 260 dom = zepto.fragment( selector, RegExp.$1, context); 261 selector = null; 262 } else if( context !== undefined ){ 263 return $(context).find( selector ); 264 }else { 265 dom = zepto.qsa( document, selector ); 266 } 267 268 }else if( isFunction( selector ) ){ 269 return $(document).ready( selector ); 270 }else if( zepto.isZ( selector ) ){ 271 return selector; 272 }else{ 273 if( isArray(selector) ){ 274 dom = compact( selector ); 275 }else if( isObject( selector ) ){ 276 dom = [ selector ], selector = null; 277 }else if( fragmentRE.test( selector ) ){ 278 dom = zepto.fragment( selector.trim() , RegExp.$1, context ); 279 selector = null; 280 }else if( context !== undefined ){ 281 return $(context).find( selector ); 282 }else{ 283 dom = zepto.qsa( document, selector ); 284 } 285 } 286 //返回 Z(dom, selector) 287 return zepto.Z( dom, selector ); 288 } 289 290 //调用的zepto.init... 291 $ = function( selector, context ){ 292 return zepto.init( selector, context ); 293 } 294 295 //私有方法, 扩展属性 296 function extend( target, source, deep ){ 297 for( key in source ){ 298 if( deep && (isPlainObject(source[key] ) || isArray( source[key]) ) ){ 299 if( isPlainObject(source[key]) && !isPlainObject( target[key] ) ){ 300 target[ key ] = {}; 301 } 302 if( isArray(source[key]) && !isArray( target[key]) ){ 303 target[ key ] = []; 304 } 305 306 extend( target[ key ], source[key], deep ); 307 }else if( source[key] !== undefined ){ 308 target[ key ] = source[key]; 309 } 310 } 311 } 312 313 // may be target is boolean arguments[1] is really target object. 314 $.extend = function( target ){ 315 var deep, args = slice.call( arguments, 1 ); 316 if( typeof target === 'boolean' ){ 317 deep = target; 318 target = args.shift(); 319 } 320 321 args.forEach( function( arg ){ extend( target, arg, deep )} ); 322 323 return target; 324 } 325 326 //高版本浏览器 qsa查询元素 327 zepto.qsa = function( element, selector ){ 328 var found, 329 maybeID = selector[ 0 ] == '#', 330 maybeClass = !maybeID && selector[ 0 ] == '.', 331 nameOnly = maybeID || maybeClass ? selector.slice( 1 ) : selector , 332 isSimple = simpleSelectorRE.test( nameOnly ); 333 334 return ( element.getElementById && isSimple && maybeId ) ? 335 (( found = element.getElementById( nameOnly ) ) ? [ found ] : []) : 336 ( element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11 ) ? [] : 337 slice.call( 338 isSimple && !maybeId && element.getElementsByClassName ? 339 maybeClass ? element.getElementsByClassName( nameOnly ) : 340 element.getElementsByTagName( selector ) : 341 element.querySelectorAll( selector ); 342 ); 343 344 }; 345 346 //筛选元素通过selector 347 function filtered( node, selector ){ 348 return selector == null ? $(nodes) : $(nodes).filter( selector ) 349 }; 350 351 //给$对象,挂上 contains函数 352 $.contains = document.documentElement.contains ? 353 function( parent, node ){ 354 return parent !== node && parent.contains( node ); 355 } : 356 function( parent, node ){ 357 while( node && ( node = node.parentNode ) ){ 358 if( node === parent ) 359 return true; 360 } 361 return false; 362 }; 363 364 //如果 arg是对象的话,那么给arg绑定执行上下文的 this 对象 365 function funcArg( context, arg, idx, payload ){ 366 return isFunction( arg ) ? arg.call( context, idx, payload ) : arg; 367 }; 368 369 //取值,或设置 370 function className( node, value ){ 371 var klass = node.className || '', 372 svg = klass && klass.baseVal !== undefined; 373 374 if( value === undefined ) 375 return svg ? klass.baseVal : klass 376 svg ? ( klass.baseVal = value ) : ( node.className = value ); 377 } 378 379 380 /* 381 'true'-> true 382 'false'-> false 383 'null' -> null 384 '42'-> 42 385 '08'->'08' 386 JSON-> parse if valid 387 string-> self 388 */ 389 //将数据转化 390 function deserializeValue( value ){ 391 try{ 392 return value ? 393 value == 'true' || 394 ( value == 'false') ? false : 395 value == 'null' ? null : 396 +value + "" == value ? +value : 397 /^[[{]/.test(value) ? $.parseJSON( value ) : 398 value ) 399 : value; 400 } catch( e ){ 401 return value; 402 } 403 } 404 405 $.type = type; 406 $.isFunction = isFunction; 407 $.isArray = isArray; 408 $.isPlainObject = isPlainObject; 409 410 //判断是否为空对象, 411 $.isEmptyObject = function( obj ){ 412 var name; 413 for( name in obj ) return false; 414 return true; 415 } 416 417 //从 i 处 开始搜索 下标 418 $.inArray = function( elem, array, i ){ 419 return emptyArray.indexOf.call( array, elem, i ); 420 } 421 422 $.camelCase = camelize; 423 $.trim = function( str ){ 424 return str == null ? "" : String.prototype.trim.call( str ); 425 } 426 427 $.uuid = 0; 428 $.support = {}; 429 $.expr = {}; 430 $.noop = function(){}; 431 432 $.map = function( elements, callback ){ 433 var value, values = [], i, key; 434 //如果是类数组的话,那么就映射, 435 if( likeArray( elements ) ){ 436 for( i = 0; i < elements.length; i++ ){ 437 value = callback( elements[i], i ); 438 if( value != null ){ 439 values.push( value ); 440 } 441 } 442 } else { 443 //是对象的话,那么遍历对象,调用callback映射 444 for( key in elements ){ 445 value = callback( elements[ kye ], key ); 446 if( value != null ){ 447 values.push( value ); 448 } 449 } 450 } 451 452 return flatten( values ); 453 } 454 455 $.each = function( elements, callback ){ 456 var i, key; 457 458 if( likeArray( elements ) ){ 459 for( i = 0; i < elements.length; i++ ){ 460 if( callback.call( elements[ i ], i, elements[i] ) === false ){ 461 return elements; 462 } 463 } 464 } else { 465 for( key in elements ){ 466 if( callback.call( elements[ key ], key, elements[ key ]) === false ) 467 return elements; 468 } 469 } 470 }; 471 472 $.grep = function( elements, callback ){ 473 return filter.call( elements, callback ); 474 }; 475 476 if( window.JSON ) $.parseJSON = JSON.parse; 477 478 $.each("Boolean Number String Function Array Data RegExp Object Error".split(" "), function( i, name ){ 479 class2type[ '[objct ' + name + ']' ] = name.toLowerCase(); 480 }); 481 482 //原型函数是绑定了this执行上下文。 483 $.fn = { 484 constructor : zepto.Z, // 将原型函数的构造函数指向 zepto.Z 485 length = 0, 486 487 forEach: emptyArray.forEach, 488 reduce: emptyArray.reduce, 489 push: emptyArray.push, 490 sort: emptyArray.sort, 491 splice: emptyArray.splice, 492 indexOf: emptyArray.indexOf, 493 concat: function(){ 494 var i, value, args = []; 495 for( i = 0; i < arguments.lengtjh; i++ ){ 496 value = arguments[ i ]; 497 args[ i ] = zepto.isZ( value ) ? value.toArray() : value; 498 } 499 500 return concat.apply( zepto.isZ(this) ? this.toArray() : this, args ); 501 }, 502 503 map: function( fn ){ 504 return $( $.map(this, function( el, i ){ 505 return fn.call( el, i, el ); 506 }) ); 507 }, 508 509 slice: function(){ 510 return $( slice.apply( this, arguments ) ); 511 }, 512 513 ready: function( callback ){ 514 if( readyRE.test( document.readyState ) && document.body ){ 515 callback( $ ); 516 } else { 517 document.addEventListener( 'DOMContentLoaded', function(){ 518 callback( $ ); 519 }, false ); 520 } 521 522 return this; 523 }, 524 525 get: function( idx ){ 526 return idx === undefined ? slice.call( this ) : this[ idx >= 0 ? idx : idx + this.length ]; 527 }, 528 529 toArray: function(){ return this.get() }, 530 size: function(){ 531 return this.length; 532 }, 533 534 remove: function(){ 535 return this.each(function(){ 536 if( this.parentNode != null ){ 537 this.parentNode.removeChild( this ); 538 } 539 }); 540 }, 541 542 each: function( callback ){ 543 emptyArray.every.call( this, function( el, idx ){ 544 return callback.call( el, idx, el ) !== false; 545 }); 546 547 return this; 548 }, 549 550 filter: function( selector ){ 551 if( isFunction( selector ) ){ 552 return this.not( this.not( selector ) ); 553 } 554 555 return $( filter.call( this, function(){ 556 return zepto.matches( element, selector ); 557 }) ); 558 }, 559 560 add: function( selector, context ){ 561 return $(uniq(this.concat( $(slector, context) ))); 562 }, 563 564 is: function( selector ){ 565 return this.length > 0 && zepto.matches( this[ 0 ], selector ); 566 }, 567 568 not: function( selector ){ 569 var nodes = []; 570 571 if( isFunction( selector ) && selector.call !== undefined ){ 572 this.each( function( idx ){ 573 if( !selector.call( this, idx ) ){ 574 nodes.push( this );; 575 } 576 }); 577 } else { 578 var excludes = typeof selector === 'string' ? this.filter( selector ) : 579 ( likeArray( selector ) && isFunction( selector.item ) ) ? slice.call( selector ) : $(selector); 580 581 this.forEach( function( el ){ 582 if( excludes.indexOf( el ) < 0 ){ 583 nodes.push( el ); 584 } 585 }) 586 } 587 588 return $(nodes); 589 }, 590 591 has: function( selector ){ 592 return this.filter(function(){ 593 return isObject( selector ) ? 594 $.contains( this, selector ) : 595 $(this).find( selector ).size(); 596 }); 597 }, 598 599 eq: function( idx ){ 600 return idx === -1 ? this.slice( idx ) : this.slice( idx, + idx + 1 ) ; 601 }, 602 603 first: function(){ 604 var el = this[ 0 ]; 605 return el && !isObject( el ) ? el : $(el); 606 }, 607 608 last: function(){ 609 var el = this[ this.length - 1 ]; 610 return el && !isObject( el ) ? el : $(el); 611 }, 612 613 find: function( selector ){ 614 var result, $this = this; 615 if( !selector ){ 616 result = $(); 617 } else if( typeof selector == 'object' ){ 618 result = $(selector).filter( function(){ 619 var node = this; 620 return emptyArray.some.call( $this, function( parent ){ 621 return $.contains(parent, node); 622 }); 623 }); 624 } else if( this.length == 1 ){ 625 result = $(zepto.qsa(this[0], selector)); 626 } else { 627 result = this.map( function(){ 628 return zepto.qsa( this, selector ); 629 }); 630 } 631 632 return result; 633 }, 634 635 closest: function( selector, context ){ 636 var node = this[ 0 ], collection = false; 637 if( typeof selector == 'object' ) collection = $(selector); 638 while( node && !(collection ? collection.indexOf( node ) >= 0 zepto.matches(node, selector ))) 639 node = node !== context && !isDocument( node ) && node.parentNode; 640 return $(node); 641 }, 642 643 parents: function( selector ){ 644 var ancestors = [], nodes = this; 645 while( nodes.length > 0 ){ 646 nodes = $.map( nodes, function( node ){ 647 if((node = node.parentNode) && !isDocument( node ) && ancestors.indexOf(node) < 0 ){ 648 ancestors.push( node ); 649 return node; 650 } 651 }); 652 } 653 return filtered( ancestors, selector ); 654 }, 655 656 parent: function( selector ){ 657 return filtered( uniq( this.pluck('parentNode')), selector ); 658 }, 659 660 children: function( selector ){ 661 return filtered( this.map( function(){ return children(this) }), selector ); 662 }, 663 664 contents: function(){ 665 return this.map( function(){ return this.contentDocument || slice.call(this.childNodes ) }); 666 }, 667 668 siblings: function(){ 669 return filtered( this.map(function(i,el){ 670 return filter.call( children(el.parentNode), function(child){ return child !== el }); 671 })); 672 }, 673 674 empty: function(){ 675 return this.each( function(){this.innerHTML = '' }); 676 }, 677 678 pluck: function( property ){ 679 return $.map(this, function(el){ return el[property] };) 680 }, 681 682 show: function(){ 683 return this.each( function(){ 684 this.style.display == 'none' && (this.style.display = ''); 685 686 if( getComputedStyle(this, '').getPropertyValue( 'display' ) == 'none' ){ 687 this.style.display = defaultDisplay( this.nodeName ); 688 } 689 }); 690 }, 691 692 replaceWith: function( newContent ){ 693 return this.before( newContent ).remove(); 694 }, 695 696 wrap: function( structure ){ 697 var func = isFunction( structure ); 698 699 if( this[ 0 ] && !func ){ 700 var dom = $(structure).get( 0 ), 701 clone = dom.parentNode || this.length > 1; 702 703 return this.each( function( index ){ 704 $(this).wrapAll( 705 func ? structure.call( this, index ) : 706 clone ? dom.cloneNode( true ) : dom; 707 ); 708 }); 709 } 710 }, 711 712 wrapAll: function( structure ){ 713 if( this[ 0 ] ){ 714 $(this[0]).before(structrue = $(structure) ); 715 var children; 716 while( ( children = structure.children() ).length ) 717 structure = children.first(); 718 $(structure).append( this );; 719 } 720 721 return this; 722 }, 723 724 wrapInner: function( structure ){ 725 var func = isFunction( structure ); 726 return this.each( function(index){ 727 var self = $(this), contents = self.contents(), 728 dom = func ? structure.call(this, index) : structure; 729 contents.length ? contents.wrapAll( dom ) : self.append( dom ); 730 }); 731 }, 732 733 unwrap: function(){ 734 this.parent().each(function(){ 735 $(this).replaceWith( $(this).children() ); 736 }); 737 738 return this; 739 }, 740 741 clone: function(){ 742 return this.map( function(){return this.cloneNode(true)} ); 743 }, 744 745 hide: function(){ 746 return this.css("display", 'none'); 747 }, 748 749 toggle: function( setting ){ 750 return this.each(function(){ 751 var el = $(this); 752 (setting === undefined ? el.css('display') == 'none' : seeting) ? el.show() : el.hide(); 753 }); 754 }, 755 756 prev: function( selector ){ 757 return $(this.pluck('previousElementSibling')).filter( slector || '*' ); 758 }, 759 next: function( select ){ 760 return $(this.pluck('nextElementSibling')).filter( selector || '*' ); 761 }, 762 html: function( html ){ 763 return 0 in argumennts ? 764 this.each( function(idx){ 765 var originHtml = this.innerHTML; 766 $(this).empty().append( funcArg(this,html, idx, originHtml) ) 767 }) : 768 ( 0 in this ? this[0].innerHTML : null ); 769 770 }, 771 772 text: function( text ){ 773 return 0 in arguments ? 774 this.each(function(idx){ 775 var newText = funcArg(this, text, idx, this.textContent ); 776 this.textContent = newText == null ? '' : '' + newText; 777 }) : 778 ( 0 in this ? this.pluck('textContent').join("") : null ); 779 }, 780 781 attr: function( name, value ){ 782 return ( typeof name === 'string' && !(1 in arguments)) ? 783 (!this.length || this[0].nodeType !== 1 ? undefined : 784 (!(result = this[0].getAttribute(name) ) && name in this[0]) ? this[0][name] : result 785 ) : 786 this.each( function( idx ){ 787 if( this.nodeType !== 1) return; 788 if( isObject(name) ) for( key in name ) setAttribute( this, key, name[key] ); 789 else setAttribute( this, name, funcArg(this, value, idx, this.getAttribute(name) )); 790 }); 791 }, 792 793 removeAttr: function( name ){ 794 return this.each(function(){ 795 this.nodeType === 1 && name.split(' ').forEach(function(attribute){ 796 setAttribute(this, attribute); 797 }, this); 798 }) 799 }, 800 801 prop: function( name, value ){ 802 name = propMap[ name ] || name; 803 return (1 in arguments ) ? 804 this.each( function(idx){ 805 this[name] = funcArg( this, value, idx, this[name] ); 806 }) : 807 ( this[0] && this[0][name]); 808 }, 809 810 data: function( name, value ){ 811 var attrName = 'data-' + name.replace(capitalRE,'-$1').toLowerCase(); 812 813 var data = (1 in arguments) ? 814 this.attr(attrName, value) : 815 this.attr(attrName); 816 817 return data !== null ? deserializeValue( data ) : undefined; 818 }, 819 820 val: function(value){ 821 return 0 in arguments ? 822 this.each(function(idx){ 823 this.value = funcArg( this, value, idx, this.value ); 824 }) : 825 ( this[0] && (this[0].multiple ? 826 $(this[0]).find('option').filter(function(){ return this.selected }).pluck('value') : 827 this[0].value; 828 )); 829 }, 830 831 offset: function( coordinates ){ 832 if( coordinates )return this.each(function(index){ 833 var $this = $(this), 834 coords = funcArg(this, coordinates, index, $this.offset() ), 835 parentOffset = $this.offsetParent().offset(), 836 props = { 837 top: coords.top - parentOffset.top, 838 left: coords.left - parentOffset.left 839 }; 840 841 if($this.css('position') == 'static') props['prosition'] = 'relative'; 842 $this.css(props); 843 }); 844 845 if( !this.length ) return null; 846 if( !$.contains(document.documentElement, this[0]) ) 847 return {top: 0, left: 0}; 848 var obj = this[0].getBoundingClientRect() 849 return { 850 left: obj.left + window.pageXOffset, 851 top: obj.top + window.pageYOffset, 852 Math.round( obj.width ), 853 height: Math.round( obj.height ) 854 }; 855 }, 856 857 css: function( property, value ){ 858 if( arguments.length < 2 ){ 859 var computedStyle, element = this[0]; 860 if( !element ) return; 861 computedStyle = getComputedStyle(element, ''); 862 if( typeof property == 'string' ){ 863 return element.style[camelize(property)] || computedStyle.getPropertyValue( prop ); 864 } else if( isArray( property ) ){ 865 var props = {}; 866 $.each(property, function(_,prop){ 867 props[ prop ] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop)); 868 }); 869 870 return props; 871 } 872 } 873 874 var css = ''; 875 if( type(property) == 'string' ){ 876 if( !value && value !== 0 ){ 877 this.each( function(){ this.stye.removeProperty( dasherize(property) ) }); 878 } else { 879 css = desherize(property) + ":" + maybeAddPx(property, value); 880 } 881 } else { 882 for( key in property ){ 883 if( !property[ key ] && property[ key ] !== 0 ){ 884 this.each( function(){ this.style.removeProperty(dasherize(key)) }); 885 } else { 886 css += dasherize( key ) + ":" + maybeAddPx(key, property[key] ) + ";" 887 } 888 } 889 } 890 891 return this.each( function(){ this.style.cssText += ';' + css }); 892 }, 893 894 index: function( element ){ 895 return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf( this[0] ); 896 }, 897 898 hasClass: function( name ){ 899 if( !name ) return false; 900 return emptyArray.some.call( this, function( el ){ 901 return this.test( className(el) ); 902 }, classRE(name) ); 903 }, 904 905 addClass: function( name ){ 906 if( !name ) return this; 907 return this.each(function( idx ){ 908 if( !('className') in this ) return; 909 classList = []; 910 var cls = className( this ), 911 newName = funcArg(this, name, idx, cls ); 912 newName.split(/s+/g).forEach(function(klass){ 913 if( !$(this).hasClass(klass) ) classList.push( klass ); 914 915 }, this); 916 classList.length && className( this, cls + (cls ? " " : "") + classList.join( " ")); 917 }); 918 }, 919 920 removeClass: function( name ){ 921 return this.each( function(idx)P{ 922 if( !('className' in this ) ) return; 923 if( name === undefined ) return className(this, ''); 924 classList = className(this); 925 funcArg( this, name, idx, classList ) 926 .split(/s+/g).forEach(function(klass){ 927 classList = classList.replace(classRE(klass), " "); 928 }); 929 className( this, classList.trim() ); 930 }); 931 }, 932 933 toggleClass: function( name, when ){ 934 if( !name ) return this; 935 return this.each(function(idx){ 936 var $this = $(this), 937 names = funcArg( this, name, idx, className( this ) ); 938 939 names.split(/s+/g).forEach(function(klass){ 940 (when === undefiend ? !$this.hasClass(klass) : when )? 941 $this.addClass(klass) : $this.removeClass(klass); 942 }); 943 }); 944 }, 945 946 scrollTop: function( value ){ 947 if( !this.length ) return; 948 var hasScrollTop = 'scrollTop' in this[0] ; 949 if( value === undefined ) return hasScrollTop ? this[0].scrollTo : this[0].pageYOffset; 950 return this.each( hasScrollTop ? 951 function(){ this.scrollTop = value } : 952 function(){ this.scrollTo(this.scrollX, value); }); 953 }, 954 955 scrollLeft: function( value ){ 956 if( !this.length ) return; 957 var hasScrollLeft = 'scrollLeft' in this[0]; 958 if( value === undefined ) 959 return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset; 960 return this.each(hasScrollLeft ? 961 function(){ this.scrollLeft = value } : 962 function(){ this.scrollTo(value, this.scrollY) }); 963 }, 964 965 position: function(){ 966 if( !this.length ) return; 967 968 var elem = this[0], 969 offsetParent = this.offsetParent(), 970 971 offset = this.offset(), 972 parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? 973 { top: 0, left: 0 } : offsetParent.offset(); 974 975 offset.top -= parseFloat( $(elem).css('margin-top') ) || 0; 976 offset.left -= parseFloat( $(elem).css('margin-left') ) || 0; 977 978 parentOffset.top += parsetFloat( $(offsetParent[0]).css('border-top-width') ) || 0; 979 parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0; 980 981 return { 982 top: offset.top - parentOffset.top, 983 left: offset.lefft - parentOffset.left 984 } 985 }, 986 987 offsetParent: function(){ 988 return this.map( function(){ 989 var parent = this.offsetParent || document.body; 990 while( parent && !rootNodeRE.test(parent.nodeName) && $(parent).css('position') == 'static') 991 parent = parent.offsetParent; 992 return parent; 993 }); 994 }, 995 996 $.fn.detach = $.fn.remove; 997 998 ;['width', 'height'].forEach(function(dimension){ 999 var offset, el = this[0]; 1000 if( value === undefined ) 1001 return iwWindow( el ) ? el['inner' + dimensionProperty] : 1002 isDocument(el) ? el.documentElement['scroll' + dimensionProperty] : 1003 (offset = this.offset()) && offset[dimension]; 1004 else 1005 return this.each( function(idx){ 1006 el = $(this); 1007 el.css(dimension, funcArg(this, value, idx, el[dimension]() )); 1008 }); 1009 }); 1010 1011 function traverseNode( node, fun ){ 1012 fun(node); 1013 for( var i = 0, len = node.childNodes.length; i < len; i++ ){ 1014 traverseNode(node.childNodes[i], fun ); 1015 } 1016 }, 1017 1018 adjacencyOperators.forEach(function(operator, operatorIndex) { 1019 var inside = operatorIndex % 2 //=> prepend, append 1020 1021 $.fn[operator] = function(){ 1022 // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings 1023 var argType, nodes = $.map(arguments, function(arg) { 1024 argType = type(arg) 1025 return argType == "object" || argType == "array" || arg == null ? 1026 arg : zepto.fragment(arg) 1027 }), 1028 parent, copyByClone = this.length > 1 1029 if (nodes.length < 1) return this 1030 1031 return this.each(function(_, target){ 1032 parent = inside ? target : target.parentNode 1033 1034 // convert all methods to a "before" operation 1035 target = operatorIndex == 0 ? target.nextSibling : 1036 operatorIndex == 1 ? target.firstChild : 1037 operatorIndex == 2 ? target : 1038 null 1039 1040 var parentInDocument = $.contains(document.documentElement, parent) 1041 1042 nodes.forEach(function(node){ 1043 if (copyByClone) node = node.cloneNode(true) 1044 else if (!parent) return $(node).remove() 1045 1046 parent.insertBefore(node, target) 1047 if (parentInDocument) traverseNode(node, function(el){ 1048 if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' && 1049 (!el.type || el.type === 'text/javascript') && !el.src) 1050 window['eval'].call(window, el.innerHTML) 1051 }) 1052 }) 1053 }) 1054 } 1055 1056 // after => insertAfter 1057 // prepend => prependTo 1058 // before => insertBefore 1059 // append => appendTo 1060 $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){ 1061 $(html)[operator](this) 1062 return this 1063 } 1064 }); 1065 1066 zepto.Z.prototype = Z.prototype = $.fn; 1067 1068 zepto.uniq = uniq; 1069 1070 zepto.deserializeValue = deserializeValue; 1071 $.zepto = zepto; 1072 1073 return $; 1074 } 1075 })(); 1076 1077 window.Zepto = Zepto; 1078 window.$ === undefined && (window.$ = Zepto );