12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857 |
- /*! Tablesaw - v3.1.2 - 2019-03-19
- * https://github.com/filamentgroup/tablesaw
- * Copyright (c) 2019 Filament Group; Licensed MIT */
- /*! Shoestring - v2.0.0 - 2017-02-14
- * http://github.com/filamentgroup/shoestring/
- * Copyright (c) 2017 Scott Jehl, Filament Group, Inc; Licensed MIT & GPLv2 */
- (function( factory ) {
- if( typeof define === 'function' && define.amd ) {
- // AMD. Register as an anonymous module.
- define( [ 'shoestring' ], factory );
- } else if (typeof module === 'object' && module.exports) {
- // Node/CommonJS
- module.exports = factory();
- } else {
- // Browser globals
- factory();
- }
- }(function () {
- var win = typeof window !== "undefined" ? window : this;
- var doc = win.document;
- /**
- * The shoestring object constructor.
- *
- * @param {string,object} prim The selector to find or element to wrap.
- * @param {object} sec The context in which to match the `prim` selector.
- * @returns shoestring
- * @this window
- */
- function shoestring( prim, sec ){
- var pType = typeof( prim ),
- ret = [],
- sel;
- // return an empty shoestring object
- if( !prim ){
- return new Shoestring( ret );
- }
- // ready calls
- if( prim.call ){
- return shoestring.ready( prim );
- }
- // handle re-wrapping shoestring objects
- if( prim.constructor === Shoestring && !sec ){
- return prim;
- }
- // if string starting with <, make html
- if( pType === "string" && prim.indexOf( "<" ) === 0 ){
- var dfrag = doc.createElement( "div" );
- dfrag.innerHTML = prim;
- // TODO depends on children (circular)
- return shoestring( dfrag ).children().each(function(){
- dfrag.removeChild( this );
- });
- }
- // if string, it's a selector, use qsa
- if( pType === "string" ){
- if( sec ){
- return shoestring( sec ).find( prim );
- }
- sel = doc.querySelectorAll( prim );
- return new Shoestring( sel, prim );
- }
- // array like objects or node lists
- if( Object.prototype.toString.call( pType ) === '[object Array]' ||
- (win.NodeList && prim instanceof win.NodeList) ){
- return new Shoestring( prim, prim );
- }
- // if it's an array, use all the elements
- if( prim.constructor === Array ){
- return new Shoestring( prim, prim );
- }
- // otherwise assume it's an object the we want at an index
- return new Shoestring( [prim], prim );
- }
- var Shoestring = function( ret, prim ) {
- this.length = 0;
- this.selector = prim;
- shoestring.merge(this, ret);
- };
- // TODO only required for tests
- Shoestring.prototype.reverse = [].reverse;
- // For adding element set methods
- shoestring.fn = Shoestring.prototype;
- shoestring.Shoestring = Shoestring;
- // For extending objects
- // TODO move to separate module when we use prototypes
- shoestring.extend = function( first, second ){
- for( var i in second ){
- if( second.hasOwnProperty( i ) ){
- first[ i ] = second[ i ];
- }
- }
- return first;
- };
- // taken directly from jQuery
- shoestring.merge = function( first, second ) {
- var len, j, i;
- len = +second.length,
- j = 0,
- i = first.length;
- for ( ; j < len; j++ ) {
- first[ i++ ] = second[ j ];
- }
- first.length = i;
- return first;
- };
- // expose
- win.shoestring = shoestring;
- /**
- * Iterates over `shoestring` collections.
- *
- * @param {function} callback The callback to be invoked on each element and index
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.each = function( callback ){
- return shoestring.each( this, callback );
- };
- shoestring.each = function( collection, callback ) {
- var val;
- for( var i = 0, il = collection.length; i < il; i++ ){
- val = callback.call( collection[i], i, collection[i] );
- if( val === false ){
- break;
- }
- }
- return collection;
- };
- /**
- * Check for array membership.
- *
- * @param {object} needle The thing to find.
- * @param {object} haystack The thing to find the needle in.
- * @return {boolean}
- * @this window
- */
- shoestring.inArray = function( needle, haystack ){
- var isin = -1;
- for( var i = 0, il = haystack.length; i < il; i++ ){
- if( haystack.hasOwnProperty( i ) && haystack[ i ] === needle ){
- isin = i;
- }
- }
- return isin;
- };
- /**
- * Bind callbacks to be run when the DOM is "ready".
- *
- * @param {function} fn The callback to be run
- * @return shoestring
- * @this shoestring
- */
- shoestring.ready = function( fn ){
- if( ready && fn ){
- fn.call( doc );
- }
- else if( fn ){
- readyQueue.push( fn );
- }
- else {
- runReady();
- }
- return [doc];
- };
- // TODO necessary?
- shoestring.fn.ready = function( fn ){
- shoestring.ready( fn );
- return this;
- };
- // Empty and exec the ready queue
- var ready = false,
- readyQueue = [],
- runReady = function(){
- if( !ready ){
- while( readyQueue.length ){
- readyQueue.shift().call( doc );
- }
- ready = true;
- }
- };
- // If DOM is already ready at exec time, depends on the browser.
- // From: https://github.com/mobify/mobifyjs/blob/526841be5509e28fc949038021799e4223479f8d/src/capture.js#L128
- if (doc.attachEvent ? doc.readyState === "complete" : doc.readyState !== "loading") {
- runReady();
- } else {
- doc.addEventListener( "DOMContentLoaded", runReady, false );
- doc.addEventListener( "readystatechange", runReady, false );
- win.addEventListener( "load", runReady, false );
- }
- /**
- * Checks the current set of elements against the selector, if one matches return `true`.
- *
- * @param {string} selector The selector to check.
- * @return {boolean}
- * @this {shoestring}
- */
- shoestring.fn.is = function( selector ){
- var ret = false, self = this, parents, check;
- // assume a dom element
- if( typeof selector !== "string" ){
- // array-like, ie shoestring objects or element arrays
- if( selector.length && selector[0] ){
- check = selector;
- } else {
- check = [selector];
- }
- return _checkElements(this, check);
- }
- parents = this.parent();
- if( !parents.length ){
- parents = shoestring( doc );
- }
- parents.each(function( i, e ) {
- var children;
- children = e.querySelectorAll( selector );
- ret = _checkElements( self, children );
- });
- return ret;
- };
- function _checkElements(needles, haystack){
- var ret = false;
- needles.each(function() {
- var j = 0;
- while( j < haystack.length ){
- if( this === haystack[j] ){
- ret = true;
- }
- j++;
- }
- });
- return ret;
- }
- /**
- * Get data attached to the first element or set data values on all elements in the current set.
- *
- * @param {string} name The data attribute name.
- * @param {any} value The value assigned to the data attribute.
- * @return {any|shoestring}
- * @this shoestring
- */
- shoestring.fn.data = function( name, value ){
- if( name !== undefined ){
- if( value !== undefined ){
- return this.each(function(){
- if( !this.shoestringData ){
- this.shoestringData = {};
- }
- this.shoestringData[ name ] = value;
- });
- }
- else {
- if( this[ 0 ] ) {
- if( this[ 0 ].shoestringData ) {
- return this[ 0 ].shoestringData[ name ];
- }
- }
- }
- }
- else {
- return this[ 0 ] ? this[ 0 ].shoestringData || {} : undefined;
- }
- };
- /**
- * Remove data associated with `name` or all the data, for each element in the current set.
- *
- * @param {string} name The data attribute name.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.removeData = function( name ){
- return this.each(function(){
- if( name !== undefined && this.shoestringData ){
- this.shoestringData[ name ] = undefined;
- delete this.shoestringData[ name ];
- } else {
- this[ 0 ].shoestringData = {};
- }
- });
- };
- /**
- * An alias for the `shoestring` constructor.
- */
- win.$ = shoestring;
- /**
- * Add a class to each DOM element in the set of elements.
- *
- * @param {string} className The name of the class to be added.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.addClass = function( className ){
- var classes = className.replace(/^\s+|\s+$/g, '').split( " " );
- return this.each(function(){
- for( var i = 0, il = classes.length; i < il; i++ ){
- if( this.className !== undefined &&
- (this.className === "" ||
- !this.className.match( new RegExp( "(^|\\s)" + classes[ i ] + "($|\\s)"))) ){
- this.className += " " + classes[ i ];
- }
- }
- });
- };
- /**
- * Add elements matching the selector to the current set.
- *
- * @param {string} selector The selector for the elements to add from the DOM
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.add = function( selector ){
- var ret = [];
- this.each(function(){
- ret.push( this );
- });
- shoestring( selector ).each(function(){
- ret.push( this );
- });
- return shoestring( ret );
- };
- /**
- * Insert an element or HTML string as the last child of each element in the set.
- *
- * @param {string|HTMLElement} fragment The HTML or HTMLElement to insert.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.append = function( fragment ){
- if( typeof( fragment ) === "string" || fragment.nodeType !== undefined ){
- fragment = shoestring( fragment );
- }
- return this.each(function( i ){
- for( var j = 0, jl = fragment.length; j < jl; j++ ){
- this.appendChild( i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ] );
- }
- });
- };
- /**
- * Insert the current set as the last child of the elements matching the selector.
- *
- * @param {string} selector The selector after which to append the current set.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.appendTo = function( selector ){
- return this.each(function(){
- shoestring( selector ).append( this );
- });
- };
- /**
- * Get the value of the first element of the set or set the value of all the elements in the set.
- *
- * @param {string} name The attribute name.
- * @param {string} value The new value for the attribute.
- * @return {shoestring|string|undefined}
- * @this {shoestring}
- */
- shoestring.fn.attr = function( name, value ){
- var nameStr = typeof( name ) === "string";
- if( value !== undefined || !nameStr ){
- return this.each(function(){
- if( nameStr ){
- this.setAttribute( name, value );
- } else {
- for( var i in name ){
- if( name.hasOwnProperty( i ) ){
- this.setAttribute( i, name[ i ] );
- }
- }
- }
- });
- } else {
- return this[ 0 ] ? this[ 0 ].getAttribute( name ) : undefined;
- }
- };
- /**
- * Insert an element or HTML string before each element in the current set.
- *
- * @param {string|HTMLElement} fragment The HTML or HTMLElement to insert.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.before = function( fragment ){
- if( typeof( fragment ) === "string" || fragment.nodeType !== undefined ){
- fragment = shoestring( fragment );
- }
- return this.each(function( i ){
- for( var j = 0, jl = fragment.length; j < jl; j++ ){
- this.parentNode.insertBefore( i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ], this );
- }
- });
- };
- /**
- * Get the children of the current collection.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.children = function(){
- var ret = [],
- childs,
- j;
- this.each(function(){
- childs = this.children;
- j = -1;
- while( j++ < childs.length-1 ){
- if( shoestring.inArray( childs[ j ], ret ) === -1 ){
- ret.push( childs[ j ] );
- }
- }
- });
- return shoestring(ret);
- };
- /**
- * Find an element matching the selector in the set of the current element and its parents.
- *
- * @param {string} selector The selector used to identify the target element.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.closest = function( selector ){
- var ret = [];
- if( !selector ){
- return shoestring( ret );
- }
- this.each(function(){
- var element, $self = shoestring( element = this );
- if( $self.is(selector) ){
- ret.push( this );
- return;
- }
- while( element.parentElement ) {
- if( shoestring(element.parentElement).is(selector) ){
- ret.push( element.parentElement );
- break;
- }
- element = element.parentElement;
- }
- });
- return shoestring( ret );
- };
- shoestring.cssExceptions = {
- 'float': [ 'cssFloat' ]
- };
- (function() {
- var cssExceptions = shoestring.cssExceptions;
- // IE8 uses marginRight instead of margin-right
- function convertPropertyName( str ) {
- return str.replace( /\-([A-Za-z])/g, function ( match, character ) {
- return character.toUpperCase();
- });
- }
- function _getStyle( element, property ) {
- return win.getComputedStyle( element, null ).getPropertyValue( property );
- }
- var vendorPrefixes = [ '', '-webkit-', '-ms-', '-moz-', '-o-', '-khtml-' ];
- /**
- * Private function for getting the computed style of an element.
- *
- * **NOTE** Please use the [css](../css.js.html) method instead.
- *
- * @method _getStyle
- * @param {HTMLElement} element The element we want the style property for.
- * @param {string} property The css property we want the style for.
- */
- shoestring._getStyle = function( element, property ) {
- var convert, value, j, k;
- if( cssExceptions[ property ] ) {
- for( j = 0, k = cssExceptions[ property ].length; j < k; j++ ) {
- value = _getStyle( element, cssExceptions[ property ][ j ] );
- if( value ) {
- return value;
- }
- }
- }
- for( j = 0, k = vendorPrefixes.length; j < k; j++ ) {
- convert = convertPropertyName( vendorPrefixes[ j ] + property );
- // VendorprefixKeyName || key-name
- value = _getStyle( element, convert );
- if( convert !== property ) {
- value = value || _getStyle( element, property );
- }
- if( vendorPrefixes[ j ] ) {
- // -vendorprefix-key-name
- value = value || _getStyle( element, vendorPrefixes[ j ] + property );
- }
- if( value ) {
- return value;
- }
- }
- return undefined;
- };
- })();
- (function() {
- var cssExceptions = shoestring.cssExceptions;
- // IE8 uses marginRight instead of margin-right
- function convertPropertyName( str ) {
- return str.replace( /\-([A-Za-z])/g, function ( match, character ) {
- return character.toUpperCase();
- });
- }
- /**
- * Private function for setting the style of an element.
- *
- * **NOTE** Please use the [css](../css.js.html) method instead.
- *
- * @method _setStyle
- * @param {HTMLElement} element The element we want to style.
- * @param {string} property The property being used to style the element.
- * @param {string} value The css value for the style property.
- */
- shoestring._setStyle = function( element, property, value ) {
- var convertedProperty = convertPropertyName(property);
- element.style[ property ] = value;
- if( convertedProperty !== property ) {
- element.style[ convertedProperty ] = value;
- }
- if( cssExceptions[ property ] ) {
- for( var j = 0, k = cssExceptions[ property ].length; j<k; j++ ) {
- element.style[ cssExceptions[ property ][ j ] ] = value;
- }
- }
- };
- })();
- /**
- * Get the compute style property of the first element or set the value of a style property
- * on all elements in the set.
- *
- * @method _setStyle
- * @param {string} property The property being used to style the element.
- * @param {string|undefined} value The css value for the style property.
- * @return {string|shoestring}
- * @this shoestring
- */
- shoestring.fn.css = function( property, value ){
- if( !this[0] ){
- return;
- }
- if( typeof property === "object" ) {
- return this.each(function() {
- for( var key in property ) {
- if( property.hasOwnProperty( key ) ) {
- shoestring._setStyle( this, key, property[key] );
- }
- }
- });
- } else {
- // assignment else retrieve first
- if( value !== undefined ){
- return this.each(function(){
- shoestring._setStyle( this, property, value );
- });
- }
- return shoestring._getStyle( this[0], property );
- }
- };
- /**
- * Returns the indexed element wrapped in a new `shoestring` object.
- *
- * @param {integer} index The index of the element to wrap and return.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.eq = function( index ){
- if( this[index] ){
- return shoestring( this[index] );
- }
- return shoestring([]);
- };
- /**
- * Filter out the current set if they do *not* match the passed selector or
- * the supplied callback returns false
- *
- * @param {string,function} selector The selector or boolean return value callback used to filter the elements.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.filter = function( selector ){
- var ret = [];
- this.each(function( index ){
- var wsel;
- if( typeof selector === 'function' ) {
- if( selector.call( this, index ) !== false ) {
- ret.push( this );
- }
- } else {
- if( !this.parentNode ){
- var context = shoestring( doc.createDocumentFragment() );
- context[ 0 ].appendChild( this );
- wsel = shoestring( selector, context );
- } else {
- wsel = shoestring( selector, this.parentNode );
- }
- if( shoestring.inArray( this, wsel ) > -1 ){
- ret.push( this );
- }
- }
- });
- return shoestring( ret );
- };
- /**
- * Find descendant elements of the current collection.
- *
- * @param {string} selector The selector used to find the children
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.find = function( selector ){
- var ret = [],
- finds;
- this.each(function(){
- finds = this.querySelectorAll( selector );
- for( var i = 0, il = finds.length; i < il; i++ ){
- ret = ret.concat( finds[i] );
- }
- });
- return shoestring( ret );
- };
- /**
- * Returns the first element of the set wrapped in a new `shoestring` object.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.first = function(){
- return this.eq( 0 );
- };
- /**
- * Returns the raw DOM node at the passed index.
- *
- * @param {integer} index The index of the element to wrap and return.
- * @return {HTMLElement|undefined|array}
- * @this shoestring
- */
- shoestring.fn.get = function( index ){
- // return an array of elements if index is undefined
- if( index === undefined ){
- var elements = [];
- for( var i = 0; i < this.length; i++ ){
- elements.push( this[ i ] );
- }
- return elements;
- } else {
- return this[ index ];
- }
- };
- var set = function( html ){
- if( typeof html === "string" || typeof html === "number" ){
- return this.each(function(){
- this.innerHTML = "" + html;
- });
- } else {
- var h = "";
- if( typeof html.length !== "undefined" ){
- for( var i = 0, l = html.length; i < l; i++ ){
- h += html[i].outerHTML;
- }
- } else {
- h = html.outerHTML;
- }
- return this.each(function(){
- this.innerHTML = h;
- });
- }
- };
- /**
- * Gets or sets the `innerHTML` from all the elements in the set.
- *
- * @param {string|undefined} html The html to assign
- * @return {string|shoestring}
- * @this shoestring
- */
- shoestring.fn.html = function( html ){
- if( typeof html !== "undefined" ){
- return set.call( this, html );
- } else { // get
- var pile = "";
- this.each(function(){
- pile += this.innerHTML;
- });
- return pile;
- }
- };
- (function() {
- function _getIndex( set, test ) {
- var i, result, element;
- for( i = result = 0; i < set.length; i++ ) {
- element = set.item ? set.item(i) : set[i];
- if( test(element) ){
- return result;
- }
- // ignore text nodes, etc
- // NOTE may need to be more permissive
- if( element.nodeType === 1 ){
- result++;
- }
- }
- return -1;
- }
- /**
- * Find the index in the current set for the passed selector.
- * Without a selector it returns the index of the first node within the array of its siblings.
- *
- * @param {string|undefined} selector The selector used to search for the index.
- * @return {integer}
- * @this {shoestring}
- */
- shoestring.fn.index = function( selector ){
- var self, children;
- self = this;
- // no arg? check the children, otherwise check each element that matches
- if( selector === undefined ){
- children = ( ( this[ 0 ] && this[0].parentNode ) || doc.documentElement).childNodes;
- // check if the element matches the first of the set
- return _getIndex(children, function( element ) {
- return self[0] === element;
- });
- } else {
- // check if the element matches the first selected node from the parent
- return _getIndex(self, function( element ) {
- return element === (shoestring( selector, element.parentNode )[ 0 ]);
- });
- }
- };
- })();
- /**
- * Insert the current set before the elements matching the selector.
- *
- * @param {string} selector The selector before which to insert the current set.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.insertBefore = function( selector ){
- return this.each(function(){
- shoestring( selector ).before( this );
- });
- };
- /**
- * Returns the last element of the set wrapped in a new `shoestring` object.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.last = function(){
- return this.eq( this.length - 1 );
- };
- /**
- * Returns a `shoestring` object with the set of siblings of each element in the original set.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.next = function(){
-
- var result = [];
- // TODO need to implement map
- this.each(function() {
- var children, item, found;
- // get the child nodes for this member of the set
- children = shoestring( this.parentNode )[0].childNodes;
- for( var i = 0; i < children.length; i++ ){
- item = children.item( i );
- // found the item we needed (found) which means current item value is
- // the next node in the list, as long as it's viable grab it
- // NOTE may need to be more permissive
- if( found && item.nodeType === 1 ){
- result.push( item );
- break;
- }
- // find the current item and mark it as found
- if( item === this ){
- found = true;
- }
- }
- });
- return shoestring( result );
- };
- /**
- * Removes elements from the current set.
- *
- * @param {string} selector The selector to use when removing the elements.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.not = function( selector ){
- var ret = [];
- this.each(function(){
- var found = shoestring( selector, this.parentNode );
- if( shoestring.inArray(this, found) === -1 ){
- ret.push( this );
- }
- });
- return shoestring( ret );
- };
- /**
- * Returns the set of first parents for each element in the current set.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.parent = function(){
- var ret = [],
- parent;
- this.each(function(){
- // no parent node, assume top level
- // jQuery parent: return the document object for <html> or the parent node if it exists
- parent = (this === doc.documentElement ? doc : this.parentNode);
- // if there is a parent and it's not a document fragment
- if( parent && parent.nodeType !== 11 ){
- ret.push( parent );
- }
- });
- return shoestring(ret);
- };
- /**
- * Add an HTML string or element before the children of each element in the current set.
- *
- * @param {string|HTMLElement} fragment The HTML string or element to add.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.prepend = function( fragment ){
- if( typeof( fragment ) === "string" || fragment.nodeType !== undefined ){
- fragment = shoestring( fragment );
- }
- return this.each(function( i ){
- for( var j = 0, jl = fragment.length; j < jl; j++ ){
- var insertEl = i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ];
- if ( this.firstChild ){
- this.insertBefore( insertEl, this.firstChild );
- } else {
- this.appendChild( insertEl );
- }
- }
- });
- };
- /**
- * Returns a `shoestring` object with the set of *one* siblingx before each element in the original set.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.prev = function(){
-
- var result = [];
- // TODO need to implement map
- this.each(function() {
- var children, item, found;
- // get the child nodes for this member of the set
- children = shoestring( this.parentNode )[0].childNodes;
- for( var i = children.length -1; i >= 0; i-- ){
- item = children.item( i );
- // found the item we needed (found) which means current item value is
- // the next node in the list, as long as it's viable grab it
- // NOTE may need to be more permissive
- if( found && item.nodeType === 1 ){
- result.push( item );
- break;
- }
- // find the current item and mark it as found
- if( item === this ){
- found = true;
- }
- }
- });
- return shoestring( result );
- };
- /**
- * Returns a `shoestring` object with the set of *all* siblings before each element in the original set.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.prevAll = function(){
-
- var result = [];
- this.each(function() {
- var $previous = shoestring( this ).prev();
- while( $previous.length ){
- result.push( $previous[0] );
- $previous = $previous.prev();
- }
- });
- return shoestring( result );
- };
- /**
- * Remove an attribute from each element in the current set.
- *
- * @param {string} name The name of the attribute.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.removeAttr = function( name ){
- return this.each(function(){
- this.removeAttribute( name );
- });
- };
- /**
- * Remove a class from each DOM element in the set of elements.
- *
- * @param {string} className The name of the class to be removed.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.removeClass = function( cname ){
- var classes = cname.replace(/^\s+|\s+$/g, '').split( " " );
- return this.each(function(){
- var newClassName, regex;
- for( var i = 0, il = classes.length; i < il; i++ ){
- if( this.className !== undefined ){
- regex = new RegExp( "(^|\\s)" + classes[ i ] + "($|\\s)", "gmi" );
- newClassName = this.className.replace( regex, " " );
- this.className = newClassName.replace(/^\s+|\s+$/g, '');
- }
- }
- });
- };
- /**
- * Remove the current set of elements from the DOM.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.remove = function(){
- return this.each(function(){
- if( this.parentNode ) {
- this.parentNode.removeChild( this );
- }
- });
- };
- /**
- * Replace each element in the current set with that argument HTML string or HTMLElement.
- *
- * @param {string|HTMLElement} fragment The value to assign.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.replaceWith = function( fragment ){
- if( typeof( fragment ) === "string" ){
- fragment = shoestring( fragment );
- }
- var ret = [];
- if( fragment.length > 1 ){
- fragment = fragment.reverse();
- }
- this.each(function( i ){
- var clone = this.cloneNode( true ),
- insertEl;
- ret.push( clone );
- // If there is no parentNode, this is pointless, drop it.
- if( !this.parentNode ){ return; }
- if( fragment.length === 1 ){
- insertEl = i > 0 ? fragment[ 0 ].cloneNode( true ) : fragment[ 0 ];
- this.parentNode.replaceChild( insertEl, this );
- } else {
- for( var j = 0, jl = fragment.length; j < jl; j++ ){
- insertEl = i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ];
- this.parentNode.insertBefore( insertEl, this.nextSibling );
- }
- this.parentNode.removeChild( this );
- }
- });
- return shoestring( ret );
- };
- /**
- * Get all of the sibling elements for each element in the current set.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.siblings = function(){
-
- if( !this.length ) {
- return shoestring( [] );
- }
- var sibs = [], el = this[ 0 ].parentNode.firstChild;
- do {
- if( el.nodeType === 1 && el !== this[ 0 ] ) {
- sibs.push( el );
- }
- el = el.nextSibling;
- } while( el );
- return shoestring( sibs );
- };
- var 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;
- };
- /**
- * Recursively retrieve the text content of the each element in the current set.
- *
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.text = function() {
-
- return getText( this );
- };
- /**
- * Get the value of the first element or set the value of all elements in the current set.
- *
- * @param {string} value The value to set.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.val = function( value ){
- var el;
- if( value !== undefined ){
- return this.each(function(){
- if( this.tagName === "SELECT" ){
- var optionSet, option,
- options = this.options,
- values = [],
- i = options.length,
- newIndex;
- values[0] = value;
- while ( i-- ) {
- option = options[ i ];
- if ( (option.selected = shoestring.inArray( option.value, values ) >= 0) ) {
- optionSet = true;
- newIndex = i;
- }
- }
- // force browsers to behave consistently when non-matching value is set
- if ( !optionSet ) {
- this.selectedIndex = -1;
- } else {
- this.selectedIndex = newIndex;
- }
- } else {
- this.value = value;
- }
- });
- } else {
- el = this[0];
- if( el.tagName === "SELECT" ){
- if( el.selectedIndex < 0 ){ return ""; }
- return el.options[ el.selectedIndex ].value;
- } else {
- return el.value;
- }
- }
- };
- /**
- * Private function for setting/getting the offset property for height/width.
- *
- * **NOTE** Please use the [width](width.js.html) or [height](height.js.html) methods instead.
- *
- * @param {shoestring} set The set of elements.
- * @param {string} name The string "height" or "width".
- * @param {float|undefined} value The value to assign.
- * @return shoestring
- * @this window
- */
- shoestring._dimension = function( set, name, value ){
- var offsetName;
- if( value === undefined ){
- offsetName = name.replace(/^[a-z]/, function( letter ) {
- return letter.toUpperCase();
- });
- return set[ 0 ][ "offset" + offsetName ];
- } else {
- // support integer values as pixels
- value = typeof value === "string" ? value : value + "px";
- return set.each(function(){
- this.style[ name ] = value;
- });
- }
- };
- /**
- * Gets the width value of the first element or sets the width for the whole set.
- *
- * @param {float|undefined} value The value to assign.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.width = function( value ){
- return shoestring._dimension( this, "width", value );
- };
- /**
- * Wraps the child elements in the provided HTML.
- *
- * @param {string} html The wrapping HTML.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.wrapInner = function( html ){
- return this.each(function(){
- var inH = this.innerHTML;
- this.innerHTML = "";
- shoestring( this ).append( shoestring( html ).html( inH ) );
- });
- };
- function initEventCache( el, evt ) {
- if ( !el.shoestringData ) {
- el.shoestringData = {};
- }
- if ( !el.shoestringData.events ) {
- el.shoestringData.events = {};
- }
- if ( !el.shoestringData.loop ) {
- el.shoestringData.loop = {};
- }
- if ( !el.shoestringData.events[ evt ] ) {
- el.shoestringData.events[ evt ] = [];
- }
- }
- function addToEventCache( el, evt, eventInfo ) {
- var obj = {};
- obj.isCustomEvent = eventInfo.isCustomEvent;
- obj.callback = eventInfo.callfunc;
- obj.originalCallback = eventInfo.originalCallback;
- obj.namespace = eventInfo.namespace;
- el.shoestringData.events[ evt ].push( obj );
- if( eventInfo.customEventLoop ) {
- el.shoestringData.loop[ evt ] = eventInfo.customEventLoop;
- }
- }
- /**
- * Bind a callback to an event for the currrent set of elements.
- *
- * @param {string} evt The event(s) to watch for.
- * @param {object,function} data Data to be included with each event or the callback.
- * @param {function} originalCallback Callback to be invoked when data is define.d.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.bind = function( evt, data, originalCallback ){
- if( typeof data === "function" ){
- originalCallback = data;
- data = null;
- }
- var evts = evt.split( " " );
- // NOTE the `triggeredElement` is purely for custom events from IE
- function encasedCallback( e, namespace, triggeredElement ){
- var result;
- if( e._namespace && e._namespace !== namespace ) {
- return;
- }
- e.data = data;
- e.namespace = e._namespace;
- var returnTrue = function(){
- return true;
- };
- e.isDefaultPrevented = function(){
- return false;
- };
- var originalPreventDefault = e.preventDefault;
- var preventDefaultConstructor = function(){
- if( originalPreventDefault ) {
- return function(){
- e.isDefaultPrevented = returnTrue;
- originalPreventDefault.call(e);
- };
- } else {
- return function(){
- e.isDefaultPrevented = returnTrue;
- e.returnValue = false;
- };
- }
- };
- // thanks https://github.com/jonathantneal/EventListener
- e.target = triggeredElement || e.target || e.srcElement;
- e.preventDefault = preventDefaultConstructor();
- e.stopPropagation = e.stopPropagation || function () {
- e.cancelBubble = true;
- };
- result = originalCallback.apply(this, [ e ].concat( e._args ) );
- if( result === false ){
- e.preventDefault();
- e.stopPropagation();
- }
- return result;
- }
- return this.each(function(){
- var domEventCallback,
- customEventCallback,
- customEventLoop,
- oEl = this;
- for( var i = 0, il = evts.length; i < il; i++ ){
- var split = evts[ i ].split( "." ),
- evt = split[ 0 ],
- namespace = split.length > 0 ? split[ 1 ] : null;
- domEventCallback = function( originalEvent ) {
- if( oEl.ssEventTrigger ) {
- originalEvent._namespace = oEl.ssEventTrigger._namespace;
- originalEvent._args = oEl.ssEventTrigger._args;
- oEl.ssEventTrigger = null;
- }
- return encasedCallback.call( oEl, originalEvent, namespace );
- };
- customEventCallback = null;
- customEventLoop = null;
- initEventCache( this, evt );
- this.addEventListener( evt, domEventCallback, false );
- addToEventCache( this, evt, {
- callfunc: customEventCallback || domEventCallback,
- isCustomEvent: !!customEventCallback,
- customEventLoop: customEventLoop,
- originalCallback: originalCallback,
- namespace: namespace
- });
- }
- });
- };
- shoestring.fn.on = shoestring.fn.bind;
-
- /**
- * Unbind a previous bound callback for an event.
- *
- * @param {string} event The event(s) the callback was bound to..
- * @param {function} callback Callback to unbind.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.unbind = function( event, callback ){
-
- var evts = event ? event.split( " " ) : [];
- return this.each(function(){
- if( !this.shoestringData || !this.shoestringData.events ) {
- return;
- }
- if( !evts.length ) {
- unbindAll.call( this );
- } else {
- var split, evt, namespace;
- for( var i = 0, il = evts.length; i < il; i++ ){
- split = evts[ i ].split( "." ),
- evt = split[ 0 ],
- namespace = split.length > 0 ? split[ 1 ] : null;
- if( evt ) {
- unbind.call( this, evt, namespace, callback );
- } else {
- unbindAll.call( this, namespace, callback );
- }
- }
- }
- });
- };
- function unbind( evt, namespace, callback ) {
- var bound = this.shoestringData.events[ evt ];
- if( !(bound && bound.length) ) {
- return;
- }
- var matched = [], j, jl;
- for( j = 0, jl = bound.length; j < jl; j++ ) {
- if( !namespace || namespace === bound[ j ].namespace ) {
- if( callback === undefined || callback === bound[ j ].originalCallback ) {
- this.removeEventListener( evt, bound[ j ].callback, false );
- matched.push( j );
- }
- }
- }
- for( j = 0, jl = matched.length; j < jl; j++ ) {
- this.shoestringData.events[ evt ].splice( j, 1 );
- }
- }
- function unbindAll( namespace, callback ) {
- for( var evtKey in this.shoestringData.events ) {
- unbind.call( this, evtKey, namespace, callback );
- }
- }
- shoestring.fn.off = shoestring.fn.unbind;
- /**
- * Bind a callback to an event for the currrent set of elements, unbind after one occurence.
- *
- * @param {string} event The event(s) to watch for.
- * @param {function} callback Callback to invoke on the event.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.one = function( event, callback ){
- var evts = event.split( " " );
- return this.each(function(){
- var thisevt, cbs = {}, $t = shoestring( this );
- for( var i = 0, il = evts.length; i < il; i++ ){
- thisevt = evts[ i ];
- cbs[ thisevt ] = function( e ){
- var $t = shoestring( this );
- for( var j in cbs ) {
- $t.unbind( j, cbs[ j ] );
- }
- return callback.apply( this, [ e ].concat( e._args ) );
- };
- $t.bind( thisevt, cbs[ thisevt ] );
- }
- });
- };
- /**
- * Trigger an event on the first element in the set, no bubbling, no defaults.
- *
- * @param {string} event The event(s) to trigger.
- * @param {object} args Arguments to append to callback invocations.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.triggerHandler = function( event, args ){
- var e = event.split( " " )[ 0 ],
- el = this[ 0 ],
- ret;
- // See this.fireEvent( 'on' + evts[ i ], document.createEventObject() ); instead of click() etc in trigger.
- if( doc.createEvent && el.shoestringData && el.shoestringData.events && el.shoestringData.events[ e ] ){
- var bindings = el.shoestringData.events[ e ];
- for (var i in bindings ){
- if( bindings.hasOwnProperty( i ) ){
- event = doc.createEvent( "Event" );
- event.initEvent( e, true, true );
- event._args = args;
- args.unshift( event );
- ret = bindings[ i ].originalCallback.apply( event.target, args );
- }
- }
- }
- return ret;
- };
- /**
- * Trigger an event on each of the DOM elements in the current set.
- *
- * @param {string} event The event(s) to trigger.
- * @param {object} args Arguments to append to callback invocations.
- * @return shoestring
- * @this shoestring
- */
- shoestring.fn.trigger = function( event, args ){
- var evts = event.split( " " );
- return this.each(function(){
- var split, evt, namespace;
- for( var i = 0, il = evts.length; i < il; i++ ){
- split = evts[ i ].split( "." ),
- evt = split[ 0 ],
- namespace = split.length > 0 ? split[ 1 ] : null;
- if( evt === "click" ){
- if( this.tagName === "INPUT" && this.type === "checkbox" && this.click ){
- this.click();
- return false;
- }
- }
- if( doc.createEvent ){
- var event = doc.createEvent( "Event" );
- event.initEvent( evt, true, true );
- event._args = args;
- event._namespace = namespace;
- this.dispatchEvent( event );
- }
- }
- });
- };
- return shoestring;
- }));
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define(["shoestring"], function (shoestring) {
- return (root.Tablesaw = factory(shoestring, root));
- });
- } else if (typeof exports === 'object') {
- module.exports = factory(require('shoestring'), root);
- } else {
- root.Tablesaw = factory(shoestring, root);
- }
- }(typeof window !== "undefined" ? window : this, function ($, window) {
- "use strict";
- var document = window.document;
- // Account for Tablesaw being loaded either before or after the DOMContentLoaded event is fired.
- var domContentLoadedTriggered = /complete|loaded/.test(document.readyState);
- document.addEventListener("DOMContentLoaded", function() {
- domContentLoadedTriggered = true;
- });
- var Tablesaw = {
- i18n: {
- modeStack: "Stack",
- modeSwipe: "Swipe",
- modeToggle: "Toggle",
- modeSwitchColumnsAbbreviated: "Cols",
- modeSwitchColumns: "Columns",
- columnToggleButton: "Columns",
- columnToggleError: "No eligible columns.",
- sort: "Sort",
- swipePreviousColumn: "Previous column",
- swipeNextColumn: "Next column"
- },
- // cut the mustard
- mustard:
- "head" in document && // IE9+, Firefox 4+, Safari 5.1+, Mobile Safari 4.1+, Opera 11.5+, Android 2.3+
- (!window.blackberry || window.WebKitPoint) && // only WebKit Blackberry (OS 6+)
- !window.operamini,
- $: $,
- _init: function(element) {
- Tablesaw.$(element || document).trigger("enhance.tablesaw");
- },
- init: function(element) {
- // Account for Tablesaw being loaded either before or after the DOMContentLoaded event is fired.
- domContentLoadedTriggered =
- domContentLoadedTriggered || /complete|loaded/.test(document.readyState);
- if (!domContentLoadedTriggered) {
- if ("addEventListener" in document) {
- // Use raw DOMContentLoaded instead of shoestring (may have issues in Android 2.3, exhibited by stack table)
- document.addEventListener("DOMContentLoaded", function() {
- Tablesaw._init(element);
- });
- }
- } else {
- Tablesaw._init(element);
- }
- }
- };
- $(document).on("enhance.tablesaw", function() {
- // Extend i18n config, if one exists.
- if (typeof TablesawConfig !== "undefined" && TablesawConfig.i18n) {
- Tablesaw.i18n = $.extend(Tablesaw.i18n, TablesawConfig.i18n || {});
- }
- Tablesaw.i18n.modes = [
- Tablesaw.i18n.modeStack,
- Tablesaw.i18n.modeSwipe,
- Tablesaw.i18n.modeToggle
- ];
- });
- if (Tablesaw.mustard) {
- $(document.documentElement).addClass("tablesaw-enhanced");
- }
- (function() {
- var pluginName = "tablesaw";
- var classes = {
- toolbar: "tablesaw-bar"
- };
- var events = {
- create: "tablesawcreate",
- destroy: "tablesawdestroy",
- refresh: "tablesawrefresh",
- resize: "tablesawresize"
- };
- var defaultMode = "stack";
- var initSelector = "table";
- var initFilterSelector = "[data-tablesaw],[data-tablesaw-mode],[data-tablesaw-sortable]";
- var defaultConfig = {};
- Tablesaw.events = events;
- var Table = function(element) {
- if (!element) {
- throw new Error("Tablesaw requires an element.");
- }
- this.table = element;
- this.$table = $(element);
- // only one <thead> and <tfoot> are allowed, per the specification
- this.$thead = this.$table
- .children()
- .filter("thead")
- .eq(0);
- // multiple <tbody> are allowed, per the specification
- this.$tbody = this.$table.children().filter("tbody");
- this.mode = this.$table.attr("data-tablesaw-mode") || defaultMode;
- this.$toolbar = null;
- this.attributes = {
- subrow: "data-tablesaw-subrow",
- ignorerow: "data-tablesaw-ignorerow"
- };
- this.init();
- };
- Table.prototype.init = function() {
- if (!this.$thead.length) {
- throw new Error("tablesaw: a <thead> is required, but none was found.");
- }
- if (!this.$thead.find("th").length) {
- throw new Error("tablesaw: no header cells found. Are you using <th> inside of <thead>?");
- }
- // assign an id if there is none
- if (!this.$table.attr("id")) {
- this.$table.attr("id", pluginName + "-" + Math.round(Math.random() * 10000));
- }
- this.createToolbar();
- this._initCells();
- this.$table.data(pluginName, this);
- this.$table.trigger(events.create, [this]);
- };
- Table.prototype.getConfig = function(pluginSpecificConfig) {
- // shoestring extend doesn’t support arbitrary args
- var configs = $.extend(defaultConfig, pluginSpecificConfig || {});
- return $.extend(configs, typeof TablesawConfig !== "undefined" ? TablesawConfig : {});
- };
- Table.prototype._getPrimaryHeaderRow = function() {
- return this._getHeaderRows().eq(0);
- };
- Table.prototype._getHeaderRows = function() {
- return this.$thead
- .children()
- .filter("tr")
- .filter(function() {
- return !$(this).is("[data-tablesaw-ignorerow]");
- });
- };
- Table.prototype._getRowIndex = function($row) {
- return $row.prevAll().length;
- };
- Table.prototype._getHeaderRowIndeces = function() {
- var self = this;
- var indeces = [];
- this._getHeaderRows().each(function() {
- indeces.push(self._getRowIndex($(this)));
- });
- return indeces;
- };
- Table.prototype._getPrimaryHeaderCells = function($row) {
- return ($row || this._getPrimaryHeaderRow()).find("th");
- };
- Table.prototype._$getCells = function(th) {
- var self = this;
- return $(th)
- .add(th.cells)
- .filter(function() {
- var $t = $(this);
- var $row = $t.parent();
- var hasColspan = $t.is("[colspan]");
- // no subrows or ignored rows (keep cells in ignored rows that do not have a colspan)
- return (
- !$row.is("[" + self.attributes.subrow + "]") &&
- (!$row.is("[" + self.attributes.ignorerow + "]") || !hasColspan)
- );
- });
- };
- Table.prototype._getVisibleColspan = function() {
- var colspan = 0;
- this._getPrimaryHeaderCells().each(function() {
- var $t = $(this);
- if ($t.css("display") !== "none") {
- colspan += parseInt($t.attr("colspan"), 10) || 1;
- }
- });
- return colspan;
- };
- Table.prototype.getColspanForCell = function($cell) {
- var visibleColspan = this._getVisibleColspan();
- var visibleSiblingColumns = 0;
- if ($cell.closest("tr").data("tablesaw-rowspanned")) {
- visibleSiblingColumns++;
- }
- $cell.siblings().each(function() {
- var $t = $(this);
- var colColspan = parseInt($t.attr("colspan"), 10) || 1;
- if ($t.css("display") !== "none") {
- visibleSiblingColumns += colColspan;
- }
- });
- // console.log( $cell[ 0 ], visibleColspan, visibleSiblingColumns );
- return visibleColspan - visibleSiblingColumns;
- };
- Table.prototype.isCellInColumn = function(header, cell) {
- return $(header)
- .add(header.cells)
- .filter(function() {
- return this === cell;
- }).length;
- };
- Table.prototype.updateColspanCells = function(cls, header, userAction) {
- var self = this;
- var primaryHeaderRow = self._getPrimaryHeaderRow();
- // find persistent column rowspans
- this.$table.find("[rowspan][data-tablesaw-priority]").each(function() {
- var $t = $(this);
- if ($t.attr("data-tablesaw-priority") !== "persist") {
- return;
- }
- var $row = $t.closest("tr");
- var rowspan = parseInt($t.attr("rowspan"), 10);
- if (rowspan > 1) {
- $row = $row.next();
- $row.data("tablesaw-rowspanned", true);
- rowspan--;
- }
- });
- this.$table
- .find("[colspan],[data-tablesaw-maxcolspan]")
- .filter(function() {
- // is not in primary header row
- return $(this).closest("tr")[0] !== primaryHeaderRow[0];
- })
- .each(function() {
- var $cell = $(this);
- if (userAction === undefined || self.isCellInColumn(header, this)) {
- } else {
- // if is not a user action AND the cell is not in the updating column, kill it
- return;
- }
- var colspan = self.getColspanForCell($cell);
- if (cls && userAction !== undefined) {
- // console.log( colspan === 0 ? "addClass" : "removeClass", $cell );
- $cell[colspan === 0 ? "addClass" : "removeClass"](cls);
- }
- // cache original colspan
- var maxColspan = parseInt($cell.attr("data-tablesaw-maxcolspan"), 10);
- if (!maxColspan) {
- $cell.attr("data-tablesaw-maxcolspan", $cell.attr("colspan"));
- } else if (colspan > maxColspan) {
- colspan = maxColspan;
- }
- // console.log( this, "setting colspan to ", colspan );
- $cell.attr("colspan", colspan);
- });
- };
- Table.prototype._findPrimaryHeadersForCell = function(cell) {
- var $headerRow = this._getPrimaryHeaderRow();
- var headerRowIndex = this._getRowIndex($headerRow);
- var results = [];
- for (var rowNumber = 0; rowNumber < this.headerMapping.length; rowNumber++) {
- if (rowNumber === headerRowIndex) {
- continue;
- }
- for (var colNumber = 0; colNumber < this.headerMapping[rowNumber].length; colNumber++) {
- if (this.headerMapping[rowNumber][colNumber] === cell) {
- results.push(this.headerMapping[headerRowIndex][colNumber]);
- }
- }
- }
- return results;
- };
- // used by init cells
- Table.prototype.getRows = function() {
- var self = this;
- return this.$table.find("tr").filter(function() {
- return $(this)
- .closest("table")
- .is(self.$table);
- });
- };
- // used by sortable
- Table.prototype.getBodyRows = function(tbody) {
- return (tbody ? $(tbody) : this.$tbody).children().filter("tr");
- };
- Table.prototype.getHeaderCellIndex = function(cell) {
- var lookup = this.headerMapping[0];
- for (var colIndex = 0; colIndex < lookup.length; colIndex++) {
- if (lookup[colIndex] === cell) {
- return colIndex;
- }
- }
- return -1;
- };
- Table.prototype._initCells = function() {
- // re-establish original colspans
- this.$table.find("[data-tablesaw-maxcolspan]").each(function() {
- var $t = $(this);
- $t.attr("colspan", $t.attr("data-tablesaw-maxcolspan"));
- });
- var $rows = this.getRows();
- var columnLookup = [];
- $rows.each(function(rowNumber) {
- columnLookup[rowNumber] = [];
- });
- $rows.each(function(rowNumber) {
- var coltally = 0;
- var $t = $(this);
- var children = $t.children();
- children.each(function() {
- var colspan = parseInt(
- this.getAttribute("data-tablesaw-maxcolspan") || this.getAttribute("colspan"),
- 10
- );
- var rowspan = parseInt(this.getAttribute("rowspan"), 10);
- // set in a previous rowspan
- while (columnLookup[rowNumber][coltally]) {
- coltally++;
- }
- columnLookup[rowNumber][coltally] = this;
- // TODO? both colspan and rowspan
- if (colspan) {
- for (var k = 0; k < colspan - 1; k++) {
- coltally++;
- columnLookup[rowNumber][coltally] = this;
- }
- }
- if (rowspan) {
- for (var j = 1; j < rowspan; j++) {
- columnLookup[rowNumber + j][coltally] = this;
- }
- }
- coltally++;
- });
- });
- var headerRowIndeces = this._getHeaderRowIndeces();
- for (var colNumber = 0; colNumber < columnLookup[0].length; colNumber++) {
- for (var headerIndex = 0, k = headerRowIndeces.length; headerIndex < k; headerIndex++) {
- var headerCol = columnLookup[headerRowIndeces[headerIndex]][colNumber];
- var rowNumber = headerRowIndeces[headerIndex];
- var rowCell;
- if (!headerCol.cells) {
- headerCol.cells = [];
- }
- while (rowNumber < columnLookup.length) {
- rowCell = columnLookup[rowNumber][colNumber];
- if (headerCol !== rowCell) {
- headerCol.cells.push(rowCell);
- }
- rowNumber++;
- }
- }
- }
- this.headerMapping = columnLookup;
- };
- Table.prototype.refresh = function() {
- this._initCells();
- this.$table.trigger(events.refresh, [this]);
- };
- Table.prototype._getToolbarAnchor = function() {
- var $parent = this.$table.parent();
- if ($parent.is(".tablesaw-overflow")) {
- return $parent;
- }
- return this.$table;
- };
- Table.prototype._getToolbar = function($anchor) {
- if (!$anchor) {
- $anchor = this._getToolbarAnchor();
- }
- return $anchor.prev().filter("." + classes.toolbar);
- };
- Table.prototype.createToolbar = function() {
- // Insert the toolbar
- // TODO move this into a separate component
- var $anchor = this._getToolbarAnchor();
- var $toolbar = this._getToolbar($anchor);
- if (!$toolbar.length) {
- $toolbar = $("<div>")
- .addClass(classes.toolbar)
- .insertBefore($anchor);
- }
- this.$toolbar = $toolbar;
- if (this.mode) {
- this.$toolbar.addClass("tablesaw-mode-" + this.mode);
- }
- };
- Table.prototype.destroy = function() {
- // Don’t remove the toolbar, just erase the classes on it.
- // Some of the table features are not yet destroy-friendly.
- this._getToolbar().each(function() {
- this.className = this.className.replace(/\btablesaw-mode\-\w*\b/gi, "");
- });
- var tableId = this.$table.attr("id");
- $(document).off("." + tableId);
- $(window).off("." + tableId);
- // other plugins
- this.$table.trigger(events.destroy, [this]);
- this.$table.removeData(pluginName);
- };
- // Collection method.
- $.fn[pluginName] = function() {
- return this.each(function() {
- var $t = $(this);
- if ($t.data(pluginName)) {
- return;
- }
- new Table(this);
- });
- };
- var $doc = $(document);
- $doc.on("enhance.tablesaw", function(e) {
- // Cut the mustard
- if (Tablesaw.mustard) {
- var $target = $(e.target);
- if ($target.parent().length) {
- $target = $target.parent();
- }
- $target
- .find(initSelector)
- .filter(initFilterSelector)
- [pluginName]();
- }
- });
- // Avoid a resize during scroll:
- // Some Mobile devices trigger a resize during scroll (sometimes when
- // doing elastic stretch at the end of the document or from the
- // location bar hide)
- var isScrolling = false;
- var scrollTimeout;
- $doc.on("scroll.tablesaw", function() {
- isScrolling = true;
- window.clearTimeout(scrollTimeout);
- scrollTimeout = window.setTimeout(function() {
- isScrolling = false;
- }, 300); // must be greater than the resize timeout below
- });
- var resizeTimeout;
- $(window).on("resize", function() {
- if (!isScrolling) {
- window.clearTimeout(resizeTimeout);
- resizeTimeout = window.setTimeout(function() {
- $doc.trigger(events.resize);
- }, 150); // must be less than the scrolling timeout above.
- }
- });
- Tablesaw.Table = Table;
- })();
- (function() {
- var classes = {
- stackTable: "tablesaw-stack",
- cellLabels: "tablesaw-cell-label",
- cellContentLabels: "tablesaw-cell-content"
- };
- var data = {
- key: "tablesaw-stack"
- };
- var attrs = {
- labelless: "data-tablesaw-no-labels",
- hideempty: "data-tablesaw-hide-empty"
- };
- var Stack = function(element, tablesaw) {
- this.tablesaw = tablesaw;
- this.$table = $(element);
- this.labelless = this.$table.is("[" + attrs.labelless + "]");
- this.hideempty = this.$table.is("[" + attrs.hideempty + "]");
- this.$table.data(data.key, this);
- };
- Stack.prototype.init = function() {
- this.$table.addClass(classes.stackTable);
- if (this.labelless) {
- return;
- }
- var self = this;
- this.$table
- .find("th, td")
- .filter(function() {
- return !$(this).closest("thead").length;
- })
- .filter(function() {
- return (
- !$(this).is("[" + attrs.labelless + "]") &&
- !$(this)
- .closest("tr")
- .is("[" + attrs.labelless + "]") &&
- (!self.hideempty || !!$(this).html())
- );
- })
- .each(function() {
- var $newHeader = $(document.createElement("b")).addClass(classes.cellLabels);
- var $cell = $(this);
- $(self.tablesaw._findPrimaryHeadersForCell(this)).each(function(index) {
- var $header = $(this.cloneNode(true));
- // TODO decouple from sortable better
- // Changed from .text() in https://github.com/filamentgroup/tablesaw/commit/b9c12a8f893ec192830ec3ba2d75f062642f935b
- // to preserve structural html in headers, like <a>
- var $sortableButton = $header.find(".tablesaw-sortable-btn");
- $header.find(".tablesaw-sortable-arrow").remove();
- // TODO decouple from checkall better
- var $checkall = $header.find("[data-tablesaw-checkall]");
- $checkall.closest("label").remove();
- if ($checkall.length) {
- $newHeader = $([]);
- return;
- }
- if (index > 0) {
- $newHeader.append(document.createTextNode(", "));
- }
- var parentNode = $sortableButton.length ? $sortableButton[0] : $header[0];
- var el;
- while ((el = parentNode.firstChild)) {
- $newHeader[0].appendChild(el);
- }
- });
- if ($newHeader.length && !$cell.find("." + classes.cellContentLabels).length) {
- $cell.wrapInner("<span class='" + classes.cellContentLabels + "'></span>");
- }
- // Update if already exists.
- var $label = $cell.find("." + classes.cellLabels);
- if (!$label.length) {
- $cell.prepend(document.createTextNode(" "));
- $cell.prepend($newHeader);
- } else {
- // only if changed
- $label.replaceWith($newHeader);
- }
- });
- };
- Stack.prototype.destroy = function() {
- this.$table.removeClass(classes.stackTable);
- this.$table.find("." + classes.cellLabels).remove();
- this.$table.find("." + classes.cellContentLabels).each(function() {
- $(this).replaceWith($(this.childNodes));
- });
- };
- // on tablecreate, init
- $(document)
- .on(Tablesaw.events.create, function(e, tablesaw) {
- if (tablesaw.mode === "stack") {
- var table = new Stack(tablesaw.table, tablesaw);
- table.init();
- }
- })
- .on(Tablesaw.events.refresh, function(e, tablesaw) {
- if (tablesaw.mode === "stack") {
- $(tablesaw.table)
- .data(data.key)
- .init();
- }
- })
- .on(Tablesaw.events.destroy, function(e, tablesaw) {
- if (tablesaw.mode === "stack") {
- $(tablesaw.table)
- .data(data.key)
- .destroy();
- }
- });
- Tablesaw.Stack = Stack;
- })();
- (function() {
- var pluginName = "tablesawbtn",
- methods = {
- _create: function() {
- return $(this).each(function() {
- $(this)
- .trigger("beforecreate." + pluginName)
- [pluginName]("_init")
- .trigger("create." + pluginName);
- });
- },
- _init: function() {
- var oEl = $(this),
- sel = this.getElementsByTagName("select")[0];
- if (sel) {
- // TODO next major version: remove .btn-select
- $(this)
- .addClass("btn-select tablesaw-btn-select")
- [pluginName]("_select", sel);
- }
- return oEl;
- },
- _select: function(sel) {
- var update = function(oEl, sel) {
- var opts = $(sel).find("option");
- var label = document.createElement("span");
- var el;
- var children;
- var found = false;
- label.setAttribute("aria-hidden", "true");
- label.innerHTML = " ";
- opts.each(function() {
- var opt = this;
- if (opt.selected) {
- label.innerHTML = opt.text;
- }
- });
- children = oEl.childNodes;
- if (opts.length > 0) {
- for (var i = 0, l = children.length; i < l; i++) {
- el = children[i];
- if (el && el.nodeName.toUpperCase() === "SPAN") {
- oEl.replaceChild(label, el);
- found = true;
- }
- }
- if (!found) {
- oEl.insertBefore(label, oEl.firstChild);
- }
- }
- };
- update(this, sel);
- // todo should this be tablesawrefresh?
- $(this).on("change refresh", function() {
- update(this, sel);
- });
- }
- };
- // Collection method.
- $.fn[pluginName] = function(arrg, a, b, c) {
- return this.each(function() {
- // if it's a method
- if (arrg && typeof arrg === "string") {
- return $.fn[pluginName].prototype[arrg].call(this, a, b, c);
- }
- // don't re-init
- if ($(this).data(pluginName + "active")) {
- return $(this);
- }
- $(this).data(pluginName + "active", true);
- $.fn[pluginName].prototype._create.call(this);
- });
- };
- // add methods
- $.extend($.fn[pluginName].prototype, methods);
- // TODO OOP this and add to Tablesaw object
- })();
- (function() {
- var data = {
- key: "tablesaw-coltoggle"
- };
- var ColumnToggle = function(element) {
- this.$table = $(element);
- if (!this.$table.length) {
- return;
- }
- this.tablesaw = this.$table.data("tablesaw");
- this.attributes = {
- btnTarget: "data-tablesaw-columntoggle-btn-target",
- set: "data-tablesaw-columntoggle-set"
- };
- this.classes = {
- columnToggleTable: "tablesaw-columntoggle",
- columnBtnContain: "tablesaw-columntoggle-btnwrap tablesaw-advance",
- columnBtn: "tablesaw-columntoggle-btn tablesaw-nav-btn down",
- popup: "tablesaw-columntoggle-popup",
- priorityPrefix: "tablesaw-priority-"
- };
- this.set = [];
- this.$headers = this.tablesaw._getPrimaryHeaderCells();
- this.$table.data(data.key, this);
- };
- // Column Toggle Sets (one column chooser can control multiple tables)
- ColumnToggle.prototype.initSet = function() {
- var set = this.$table.attr(this.attributes.set);
- if (set) {
- // Should not include the current table
- var table = this.$table[0];
- this.set = $("table[" + this.attributes.set + "='" + set + "']")
- .filter(function() {
- return this !== table;
- })
- .get();
- }
- };
- ColumnToggle.prototype.init = function() {
- if (!this.$table.length) {
- return;
- }
- var tableId,
- id,
- $menuButton,
- $popup,
- $menu,
- $btnContain,
- self = this;
- var cfg = this.tablesaw.getConfig({
- getColumnToggleLabelTemplate: function(text) {
- return "<label><input type='checkbox' checked>" + text + "</label>";
- }
- });
- this.$table.addClass(this.classes.columnToggleTable);
- tableId = this.$table.attr("id");
- id = tableId + "-popup";
- $btnContain = $("<div class='" + this.classes.columnBtnContain + "'></div>");
- // TODO next major version: remove .btn
- $menuButton = $(
- "<a href='#" +
- id +
- "' class='btn tablesaw-btn btn-micro " +
- this.classes.columnBtn +
- "' data-popup-link>" +
- "<span>" +
- Tablesaw.i18n.columnToggleButton +
- "</span></a>"
- );
- $popup = $("<div class='" + this.classes.popup + "' id='" + id + "'></div>");
- $menu = $("<div class='tablesaw-btn-group'></div>");
- this.$popup = $popup;
- var hasNonPersistentHeaders = false;
- this.$headers.each(function() {
- var $this = $(this),
- priority = $this.attr("data-tablesaw-priority"),
- $cells = self.tablesaw._$getCells(this);
- if (priority && priority !== "persist") {
- $cells.addClass(self.classes.priorityPrefix + priority);
- $(cfg.getColumnToggleLabelTemplate($this.text()))
- .appendTo($menu)
- .find('input[type="checkbox"]')
- .data("tablesaw-header", this);
- hasNonPersistentHeaders = true;
- }
- });
- if (!hasNonPersistentHeaders) {
- $menu.append("<label>" + Tablesaw.i18n.columnToggleError + "</label>");
- }
- $menu.appendTo($popup);
- function onToggleCheckboxChange(checkbox) {
- var checked = checkbox.checked;
- var header = self.getHeaderFromCheckbox(checkbox);
- var $cells = self.tablesaw._$getCells(header);
- $cells[!checked ? "addClass" : "removeClass"]("tablesaw-toggle-cellhidden");
- $cells[checked ? "addClass" : "removeClass"]("tablesaw-toggle-cellvisible");
- self.updateColspanCells(header, checked);
- self.$table.trigger("tablesawcolumns");
- }
- // bind change event listeners to inputs - TODO: move to a private method?
- $menu.find('input[type="checkbox"]').on("change", function(e) {
- onToggleCheckboxChange(e.target);
- if (self.set.length) {
- var index;
- $(self.$popup)
- .find("input[type='checkbox']")
- .each(function(j) {
- if (this === e.target) {
- index = j;
- return false;
- }
- });
- $(self.set).each(function() {
- var checkbox = $(this)
- .data(data.key)
- .$popup.find("input[type='checkbox']")
- .get(index);
- if (checkbox) {
- checkbox.checked = e.target.checked;
- onToggleCheckboxChange(checkbox);
- }
- });
- }
- });
- $menuButton.appendTo($btnContain);
- // Use a different target than the toolbar
- var $btnTarget = $(this.$table.attr(this.attributes.btnTarget));
- $btnContain.appendTo($btnTarget.length ? $btnTarget : this.tablesaw.$toolbar);
- function closePopup(event) {
- // Click came from inside the popup, ignore.
- if (event && $(event.target).closest("." + self.classes.popup).length) {
- return;
- }
- $(document).off("click." + tableId);
- $menuButton.removeClass("up").addClass("down");
- $btnContain.removeClass("visible");
- }
- var closeTimeout;
- function openPopup() {
- $btnContain.addClass("visible");
- $menuButton.removeClass("down").addClass("up");
- $(document).off("click." + tableId, closePopup);
- window.clearTimeout(closeTimeout);
- closeTimeout = window.setTimeout(function() {
- $(document).on("click." + tableId, closePopup);
- }, 15);
- }
- $menuButton.on("click.tablesaw", function(event) {
- event.preventDefault();
- if (!$btnContain.is(".visible")) {
- openPopup();
- } else {
- closePopup();
- }
- });
- $popup.appendTo($btnContain);
- this.$menu = $menu;
- // Fix for iOS not rendering shadows correctly when using `-webkit-overflow-scrolling`
- var $overflow = this.$table.closest(".tablesaw-overflow");
- if ($overflow.css("-webkit-overflow-scrolling")) {
- var timeout;
- $overflow.on("scroll", function() {
- var $div = $(this);
- window.clearTimeout(timeout);
- timeout = window.setTimeout(function() {
- $div.css("-webkit-overflow-scrolling", "auto");
- window.setTimeout(function() {
- $div.css("-webkit-overflow-scrolling", "touch");
- }, 0);
- }, 100);
- });
- }
- $(window).on(Tablesaw.events.resize + "." + tableId, function() {
- self.refreshToggle();
- });
- this.initSet();
- this.refreshToggle();
- };
- ColumnToggle.prototype.getHeaderFromCheckbox = function(checkbox) {
- return $(checkbox).data("tablesaw-header");
- };
- ColumnToggle.prototype.refreshToggle = function() {
- var self = this;
- var invisibleColumns = 0;
- this.$menu.find("input").each(function() {
- var header = self.getHeaderFromCheckbox(this);
- this.checked =
- self.tablesaw
- ._$getCells(header)
- .eq(0)
- .css("display") === "table-cell";
- });
- this.updateColspanCells();
- };
- ColumnToggle.prototype.updateColspanCells = function(header, userAction) {
- this.tablesaw.updateColspanCells("tablesaw-toggle-cellhidden", header, userAction);
- };
- ColumnToggle.prototype.destroy = function() {
- this.$table.removeClass(this.classes.columnToggleTable);
- this.$table.find("th, td").each(function() {
- var $cell = $(this);
- $cell.removeClass("tablesaw-toggle-cellhidden").removeClass("tablesaw-toggle-cellvisible");
- this.className = this.className.replace(/\bui\-table\-priority\-\d\b/g, "");
- });
- };
- // on tablecreate, init
- $(document).on(Tablesaw.events.create, function(e, tablesaw) {
- if (tablesaw.mode === "columntoggle") {
- var table = new ColumnToggle(tablesaw.table);
- table.init();
- }
- });
- $(document).on(Tablesaw.events.destroy, function(e, tablesaw) {
- if (tablesaw.mode === "columntoggle") {
- $(tablesaw.table)
- .data(data.key)
- .destroy();
- }
- });
- $(document).on(Tablesaw.events.refresh, function(e, tablesaw) {
- if (tablesaw.mode === "columntoggle") {
- $(tablesaw.table)
- .data(data.key)
- .refreshToggle();
- }
- });
- Tablesaw.ColumnToggle = ColumnToggle;
- })();
- (function() {
- function getSortValue(cell) {
- var text = [];
- $(cell.childNodes).each(function() {
- var $el = $(this);
- if ($el.is("input, select")) {
- text.push($el.val());
- } else if ($el.is(".tablesaw-cell-label")) {
- } else {
- text.push(($el.text() || "").replace(/^\s+|\s+$/g, ""));
- }
- });
- return text.join("");
- }
- var pluginName = "tablesaw-sortable",
- initSelector = "table[data-" + pluginName + "]",
- sortableSwitchSelector = "[data-" + pluginName + "-switch]",
- attrs = {
- sortCol: "data-tablesaw-sortable-col",
- defaultCol: "data-tablesaw-sortable-default-col",
- numericCol: "data-tablesaw-sortable-numeric",
- subRow: "data-tablesaw-subrow",
- ignoreRow: "data-tablesaw-ignorerow"
- },
- classes = {
- head: pluginName + "-head",
- ascend: pluginName + "-ascending",
- descend: pluginName + "-descending",
- switcher: pluginName + "-switch",
- tableToolbar: "tablesaw-bar-section",
- sortButton: pluginName + "-btn"
- },
- methods = {
- _create: function(o) {
- return $(this).each(function() {
- var init = $(this).data(pluginName + "-init");
- if (init) {
- return false;
- }
- $(this)
- .data(pluginName + "-init", true)
- .trigger("beforecreate." + pluginName)
- [pluginName]("_init", o)
- .trigger("create." + pluginName);
- });
- },
- _init: function() {
- var el = $(this);
- var tblsaw = el.data("tablesaw");
- var heads;
- var $switcher;
- function addClassToHeads(h) {
- $.each(h, function(i, v) {
- $(v).addClass(classes.head);
- });
- }
- function makeHeadsActionable(h, fn) {
- $.each(h, function(i, col) {
- var b = $("<button class='" + classes.sortButton + "'/>");
- b.on("click", { col: col }, fn);
- $(col)
- .wrapInner(b)
- .find("button")
- .append("<span class='tablesaw-sortable-arrow'>");
- });
- }
- function clearOthers(headcells) {
- $.each(headcells, function(i, v) {
- var col = $(v);
- col.removeAttr(attrs.defaultCol);
- col.removeClass(classes.ascend);
- col.removeClass(classes.descend);
- });
- }
- function headsOnAction(e) {
- if ($(e.target).is("a[href]")) {
- return;
- }
- e.stopPropagation();
- var headCell = $(e.target).closest("[" + attrs.sortCol + "]"),
- v = e.data.col,
- newSortValue = heads.index(headCell[0]);
- clearOthers(
- headCell
- .closest("thead")
- .find("th")
- .filter(function() {
- return this !== headCell[0];
- })
- );
- if (headCell.is("." + classes.descend) || !headCell.is("." + classes.ascend)) {
- el[pluginName]("sortBy", v, true);
- newSortValue += "_asc";
- } else {
- el[pluginName]("sortBy", v);
- newSortValue += "_desc";
- }
- if ($switcher) {
- $switcher
- .find("select")
- .val(newSortValue)
- .trigger("refresh");
- }
- e.preventDefault();
- }
- function handleDefault(heads) {
- $.each(heads, function(idx, el) {
- var $el = $(el);
- if ($el.is("[" + attrs.defaultCol + "]")) {
- if (!$el.is("." + classes.descend)) {
- $el.addClass(classes.ascend);
- }
- }
- });
- }
- function addSwitcher(heads) {
- $switcher = $("<div>")
- .addClass(classes.switcher)
- .addClass(classes.tableToolbar);
- var html = ["<label>" + Tablesaw.i18n.sort + ":"];
- // TODO next major version: remove .btn
- html.push('<span class="btn tablesaw-btn"><select>');
- heads.each(function(j) {
- var $t = $(this);
- var isDefaultCol = $t.is("[" + attrs.defaultCol + "]");
- var isDescending = $t.is("." + classes.descend);
- var hasNumericAttribute = $t.is("[" + attrs.numericCol + "]");
- var numericCount = 0;
- // Check only the first four rows to see if the column is numbers.
- var numericCountMax = 5;
- $(this.cells.slice(0, numericCountMax)).each(function() {
- if (!isNaN(parseInt(getSortValue(this), 10))) {
- numericCount++;
- }
- });
- var isNumeric = numericCount === numericCountMax;
- if (!hasNumericAttribute) {
- $t.attr(attrs.numericCol, isNumeric ? "" : "false");
- }
- html.push(
- "<option" +
- (isDefaultCol && !isDescending ? " selected" : "") +
- ' value="' +
- j +
- '_asc">' +
- $t.text() +
- " " +
- (isNumeric ? "↑" : "(A-Z)") +
- "</option>"
- );
- html.push(
- "<option" +
- (isDefaultCol && isDescending ? " selected" : "") +
- ' value="' +
- j +
- '_desc">' +
- $t.text() +
- " " +
- (isNumeric ? "↓" : "(Z-A)") +
- "</option>"
- );
- });
- html.push("</select></span></label>");
- $switcher.html(html.join(""));
- var $firstChild = tblsaw.$toolbar.children().eq(0);
- if ($firstChild.length) {
- $switcher.insertBefore($firstChild);
- } else {
- $switcher.appendTo(tblsaw.$toolbar);
- }
- $switcher.find(".tablesaw-btn").tablesawbtn();
- $switcher.find("select").on("change", function() {
- var val = $(this)
- .val()
- .split("_"),
- head = heads.eq(val[0]);
- clearOthers(head.siblings());
- el[pluginName]("sortBy", head.get(0), val[1] === "asc");
- });
- }
- el.addClass(pluginName);
- heads = el
- .children()
- .filter("thead")
- .find("th[" + attrs.sortCol + "]");
- addClassToHeads(heads);
- makeHeadsActionable(heads, headsOnAction);
- handleDefault(heads);
- if (el.is(sortableSwitchSelector)) {
- addSwitcher(heads);
- }
- },
- sortRows: function(rows, colNum, ascending, col, tbody) {
- function convertCells(cellArr, belongingToTbody) {
- var cells = [];
- $.each(cellArr, function(i, cell) {
- var row = cell.parentNode;
- var $row = $(row);
- // next row is a subrow
- var subrows = [];
- var $next = $row.next();
- while ($next.is("[" + attrs.subRow + "]")) {
- subrows.push($next[0]);
- $next = $next.next();
- }
- var tbody = row.parentNode;
- // current row is a subrow
- if ($row.is("[" + attrs.subRow + "]")) {
- } else if (tbody === belongingToTbody) {
- cells.push({
- element: cell,
- cell: getSortValue(cell),
- row: row,
- subrows: subrows.length ? subrows : null,
- ignored: $row.is("[" + attrs.ignoreRow + "]")
- });
- }
- });
- return cells;
- }
- function getSortFxn(ascending, forceNumeric) {
- var fn,
- regex = /[^\-\+\d\.]/g;
- if (ascending) {
- fn = function(a, b) {
- if (a.ignored || b.ignored) {
- return 0;
- }
- if (forceNumeric) {
- return (
- parseFloat(a.cell.replace(regex, "")) - parseFloat(b.cell.replace(regex, ""))
- );
- } else {
- return a.cell.toLowerCase() > b.cell.toLowerCase() ? 1 : -1;
- }
- };
- } else {
- fn = function(a, b) {
- if (a.ignored || b.ignored) {
- return 0;
- }
- if (forceNumeric) {
- return (
- parseFloat(b.cell.replace(regex, "")) - parseFloat(a.cell.replace(regex, ""))
- );
- } else {
- return a.cell.toLowerCase() < b.cell.toLowerCase() ? 1 : -1;
- }
- };
- }
- return fn;
- }
- function convertToRows(sorted) {
- var newRows = [],
- i,
- l;
- for (i = 0, l = sorted.length; i < l; i++) {
- newRows.push(sorted[i].row);
- if (sorted[i].subrows) {
- newRows.push(sorted[i].subrows);
- }
- }
- return newRows;
- }
- var fn;
- var sorted;
- var cells = convertCells(col.cells, tbody);
- var customFn = $(col).data("tablesaw-sort");
- fn =
- (customFn && typeof customFn === "function" ? customFn(ascending) : false) ||
- getSortFxn(
- ascending,
- $(col).is("[" + attrs.numericCol + "]") &&
- !$(col).is("[" + attrs.numericCol + '="false"]')
- );
- sorted = cells.sort(fn);
- rows = convertToRows(sorted);
- return rows;
- },
- makeColDefault: function(col, a) {
- var c = $(col);
- c.attr(attrs.defaultCol, "true");
- if (a) {
- c.removeClass(classes.descend);
- c.addClass(classes.ascend);
- } else {
- c.removeClass(classes.ascend);
- c.addClass(classes.descend);
- }
- },
- sortBy: function(col, ascending) {
- var el = $(this);
- var colNum;
- var tbl = el.data("tablesaw");
- tbl.$tbody.each(function() {
- var tbody = this;
- var $tbody = $(this);
- var rows = tbl.getBodyRows(tbody);
- var sortedRows;
- var map = tbl.headerMapping[0];
- var j, k;
- // find the column number that we’re sorting
- for (j = 0, k = map.length; j < k; j++) {
- if (map[j] === col) {
- colNum = j;
- break;
- }
- }
- sortedRows = el[pluginName]("sortRows", rows, colNum, ascending, col, tbody);
- // replace Table rows
- for (j = 0, k = sortedRows.length; j < k; j++) {
- $tbody.append(sortedRows[j]);
- }
- });
- el[pluginName]("makeColDefault", col, ascending);
- el.trigger("tablesaw-sorted");
- }
- };
- // Collection method.
- $.fn[pluginName] = function(arrg) {
- var args = Array.prototype.slice.call(arguments, 1),
- returnVal;
- // if it's a method
- if (arrg && typeof arrg === "string") {
- returnVal = $.fn[pluginName].prototype[arrg].apply(this[0], args);
- return typeof returnVal !== "undefined" ? returnVal : $(this);
- }
- // check init
- if (!$(this).data(pluginName + "-active")) {
- $(this).data(pluginName + "-active", true);
- $.fn[pluginName].prototype._create.call(this, arrg);
- }
- return $(this);
- };
- // add methods
- $.extend($.fn[pluginName].prototype, methods);
- $(document).on(Tablesaw.events.create, function(e, Tablesaw) {
- if (Tablesaw.$table.is(initSelector)) {
- Tablesaw.$table[pluginName]();
- }
- });
- // TODO OOP this and add to Tablesaw object
- })();
- (function() {
- var classes = {
- hideBtn: "disabled",
- persistWidths: "tablesaw-fix-persist",
- hiddenCol: "tablesaw-swipe-cellhidden",
- persistCol: "tablesaw-swipe-cellpersist",
- allColumnsVisible: "tablesaw-all-cols-visible"
- };
- var attrs = {
- disableTouchEvents: "data-tablesaw-no-touch",
- ignorerow: "data-tablesaw-ignorerow",
- subrow: "data-tablesaw-subrow"
- };
- function createSwipeTable(tbl, $table) {
- var tblsaw = $table.data("tablesaw");
- var $btns = $("<div class='tablesaw-advance'></div>");
- // TODO next major version: remove .btn
- var $prevBtn = $(
- "<a href='#' class='btn tablesaw-nav-btn tablesaw-btn btn-micro left'>" +
- Tablesaw.i18n.swipePreviousColumn +
- "</a>"
- ).appendTo($btns);
- // TODO next major version: remove .btn
- var $nextBtn = $(
- "<a href='#' class='btn tablesaw-nav-btn tablesaw-btn btn-micro right'>" +
- Tablesaw.i18n.swipeNextColumn +
- "</a>"
- ).appendTo($btns);
- var $headerCells = tbl._getPrimaryHeaderCells();
- var $headerCellsNoPersist = $headerCells.not('[data-tablesaw-priority="persist"]');
- var headerWidths = [];
- var headerWidthsNoPersist = [];
- var $head = $(document.head || "head");
- var tableId = $table.attr("id");
- if (!$headerCells.length) {
- throw new Error("tablesaw swipe: no header cells found.");
- }
- $table.addClass("tablesaw-swipe");
- function initMinHeaderWidths() {
- $table.css({
- width: "1px"
- });
- // remove any hidden columns
- $table.find("." + classes.hiddenCol).removeClass(classes.hiddenCol);
- headerWidths = [];
- headerWidthsNoPersist = [];
- // Calculate initial widths
- $headerCells.each(function() {
- var width = this.offsetWidth;
- headerWidths.push(width);
- if (!isPersistent(this)) {
- headerWidthsNoPersist.push(width);
- }
- });
- // reset props
- $table.css({
- width: ""
- });
- }
- initMinHeaderWidths();
- $btns.appendTo(tblsaw.$toolbar);
- if (!tableId) {
- tableId = "tableswipe-" + Math.round(Math.random() * 10000);
- $table.attr("id", tableId);
- }
- function showColumn(headerCell) {
- tblsaw._$getCells(headerCell).removeClass(classes.hiddenCol);
- }
- function hideColumn(headerCell) {
- tblsaw._$getCells(headerCell).addClass(classes.hiddenCol);
- }
- function persistColumn(headerCell) {
- tblsaw._$getCells(headerCell).addClass(classes.persistCol);
- }
- function isPersistent(headerCell) {
- return $(headerCell).is('[data-tablesaw-priority="persist"]');
- }
- function unmaintainWidths() {
- $table.removeClass(classes.persistWidths);
- $("#" + tableId + "-persist").remove();
- }
- function maintainWidths() {
- var prefix = "#" + tableId + ".tablesaw-swipe ";
- var styles = [];
- var tableWidth = $table.width();
- var tableWidthNoPersistantColumns = tableWidth;
- var hash = [];
- var newHash;
- // save persistent column widths (as long as they take up less than 75% of table width)
- $headerCells.each(function(index) {
- var width;
- if (isPersistent(this)) {
- width = this.offsetWidth;
- tableWidthNoPersistantColumns -= width;
- if (width < tableWidth * 0.75) {
- hash.push(index + "-" + width);
- styles.push(
- prefix +
- " ." +
- classes.persistCol +
- ":nth-child(" +
- (index + 1) +
- ") { width: " +
- width +
- "px; }"
- );
- }
- }
- });
- newHash = hash.join("_");
- if (styles.length) {
- $table.addClass(classes.persistWidths);
- var $style = $("#" + tableId + "-persist");
- // If style element not yet added OR if the widths have changed
- if (!$style.length || $style.data("tablesaw-hash") !== newHash) {
- // Remove existing
- $style.remove();
- $("<style>" + styles.join("\n") + "</style>")
- .attr("id", tableId + "-persist")
- .data("tablesaw-hash", newHash)
- .appendTo($head);
- }
- }
- return tableWidthNoPersistantColumns;
- }
- function getNext() {
- var next = [];
- var checkFound;
- $headerCellsNoPersist.each(function(i) {
- var $t = $(this);
- var isHidden = $t.css("display") === "none" || $t.is("." + classes.hiddenCol);
- if (!isHidden && !checkFound) {
- checkFound = true;
- next[0] = i;
- } else if (isHidden && checkFound) {
- next[1] = i;
- return false;
- }
- });
- return next;
- }
- function getPrev() {
- var next = getNext();
- return [next[1] - 1, next[0] - 1];
- }
- function canNavigate(pair) {
- return pair[1] > -1 && pair[1] < $headerCellsNoPersist.length;
- }
- function matchesMedia() {
- var matchMedia = $table.attr("data-tablesaw-swipe-media");
- return !matchMedia || ("matchMedia" in window && window.matchMedia(matchMedia).matches);
- }
- function fakeBreakpoints() {
- if (!matchesMedia()) {
- return;
- }
- var containerWidth = $table.parent().width(),
- persist = [],
- sum = 0,
- sums = [],
- visibleNonPersistantCount = $headerCells.length;
- $headerCells.each(function(index) {
- var $t = $(this),
- isPersist = $t.is('[data-tablesaw-priority="persist"]');
- persist.push(isPersist);
- sum += headerWidths[index];
- sums.push(sum);
- // is persistent or is hidden
- if (isPersist || sum > containerWidth) {
- visibleNonPersistantCount--;
- }
- });
- // We need at least one column to swipe.
- var needsNonPersistentColumn = visibleNonPersistantCount === 0;
- $headerCells.each(function(index) {
- if (sums[index] > containerWidth) {
- hideColumn(this);
- }
- });
- var firstPersist = true;
- $headerCells.each(function(index) {
- if (persist[index]) {
- // for visual box-shadow
- persistColumn(this);
- if (firstPersist) {
- tblsaw._$getCells(this).css("width", sums[index] + "px");
- firstPersist = false;
- }
- return;
- }
- if (sums[index] <= containerWidth || needsNonPersistentColumn) {
- needsNonPersistentColumn = false;
- showColumn(this);
- tblsaw.updateColspanCells(classes.hiddenCol, this, true);
- }
- });
- unmaintainWidths();
- $table.trigger("tablesawcolumns");
- }
- function goForward() {
- navigate(true);
- }
- function goBackward() {
- navigate(false);
- }
- function navigate(isNavigateForward) {
- var pair;
- if (isNavigateForward) {
- pair = getNext();
- } else {
- pair = getPrev();
- }
- if (canNavigate(pair)) {
- if (isNaN(pair[0])) {
- if (isNavigateForward) {
- pair[0] = 0;
- } else {
- pair[0] = $headerCellsNoPersist.length - 1;
- }
- }
- var roomForColumnsWidth = maintainWidths();
- var hideColumnIndex = pair[0];
- var showColumnIndex = pair[1];
- // Hide one column, show one or more based on how much space was freed up
- var columnToShow;
- var columnToHide = $headerCellsNoPersist.get(hideColumnIndex);
- var wasAtLeastOneColumnShown = false;
- var atLeastOneColumnIsVisible = false;
- hideColumn(columnToHide);
- tblsaw.updateColspanCells(classes.hiddenCol, columnToHide, true);
- var columnIndex = hideColumnIndex + (isNavigateForward ? 1 : -1);
- while (columnIndex >= 0 && columnIndex < headerWidthsNoPersist.length) {
- roomForColumnsWidth -= headerWidthsNoPersist[columnIndex];
- var $columnToShow = $headerCellsNoPersist.eq(columnIndex);
- if ($columnToShow.is(".tablesaw-swipe-cellhidden")) {
- if (roomForColumnsWidth > 0) {
- columnToShow = $columnToShow.get(0);
- wasAtLeastOneColumnShown = true;
- atLeastOneColumnIsVisible = true;
- showColumn(columnToShow);
- tblsaw.updateColspanCells(classes.hiddenCol, columnToShow, false);
- }
- } else {
- atLeastOneColumnIsVisible = true;
- }
- if (isNavigateForward) {
- columnIndex++;
- } else {
- columnIndex--;
- }
- }
- if (!atLeastOneColumnIsVisible) {
- // if no columns are showing, at least show the first one we were aiming for.
- columnToShow = $headerCellsNoPersist.get(showColumnIndex);
- showColumn(columnToShow);
- tblsaw.updateColspanCells(classes.hiddenCol, columnToShow, false);
- } else if (
- !wasAtLeastOneColumnShown &&
- canNavigate(isNavigateForward ? getNext() : getPrev())
- ) {
- // if our one new column was hidden but no new columns were shown, let’s navigate again automatically.
- navigate(isNavigateForward);
- }
- $table.trigger("tablesawcolumns");
- }
- }
- $prevBtn.add($nextBtn).on("click", function(e) {
- if (!!$(e.target).closest($nextBtn).length) {
- goForward();
- } else {
- goBackward();
- }
- e.preventDefault();
- });
- function getCoord(event, key) {
- return (event.touches || event.originalEvent.touches)[0][key];
- }
- if (!$table.is("[" + attrs.disableTouchEvents + "]")) {
- $table.on("touchstart.swipetoggle", function(e) {
- var originX = getCoord(e, "pageX");
- var originY = getCoord(e, "pageY");
- var x;
- var y;
- var scrollTop = window.pageYOffset;
- $(window).off(Tablesaw.events.resize, fakeBreakpoints);
- $(this)
- .on("touchmove.swipetoggle", function(e) {
- x = getCoord(e, "pageX");
- y = getCoord(e, "pageY");
- })
- .on("touchend.swipetoggle", function() {
- var cfg = tbl.getConfig({
- swipeHorizontalThreshold: 30,
- swipeVerticalThreshold: 30
- });
- // This config code is a little awkward because shoestring doesn’t support deep $.extend
- // Trying to work around when devs only override one of (not both) horizontalThreshold or
- // verticalThreshold in their TablesawConfig.
- // @TODO major version bump: remove cfg.swipe, move to just use the swipePrefix keys
- var verticalThreshold = cfg.swipe
- ? cfg.swipe.verticalThreshold
- : cfg.swipeVerticalThreshold;
- var horizontalThreshold = cfg.swipe
- ? cfg.swipe.horizontalThreshold
- : cfg.swipeHorizontalThreshold;
- var isPageScrolled = Math.abs(window.pageYOffset - scrollTop) >= verticalThreshold;
- var isVerticalSwipe = Math.abs(y - originY) >= verticalThreshold;
- if (!isVerticalSwipe && !isPageScrolled) {
- if (x - originX < -1 * horizontalThreshold) {
- goForward();
- }
- if (x - originX > horizontalThreshold) {
- goBackward();
- }
- }
- window.setTimeout(function() {
- $(window).on(Tablesaw.events.resize, fakeBreakpoints);
- }, 300);
- $(this).off("touchmove.swipetoggle touchend.swipetoggle");
- });
- });
- }
- $table
- .on("tablesawcolumns.swipetoggle", function() {
- var canGoPrev = canNavigate(getPrev());
- var canGoNext = canNavigate(getNext());
- $prevBtn[canGoPrev ? "removeClass" : "addClass"](classes.hideBtn);
- $nextBtn[canGoNext ? "removeClass" : "addClass"](classes.hideBtn);
- tblsaw.$toolbar[!canGoPrev && !canGoNext ? "addClass" : "removeClass"](
- classes.allColumnsVisible
- );
- })
- .on("tablesawnext.swipetoggle", function() {
- goForward();
- })
- .on("tablesawprev.swipetoggle", function() {
- goBackward();
- })
- .on(Tablesaw.events.destroy + ".swipetoggle", function() {
- var $t = $(this);
- $t.removeClass("tablesaw-swipe");
- tblsaw.$toolbar.find(".tablesaw-advance").remove();
- $(window).off(Tablesaw.events.resize, fakeBreakpoints);
- $t.off(".swipetoggle");
- })
- .on(Tablesaw.events.refresh, function() {
- unmaintainWidths();
- initMinHeaderWidths();
- fakeBreakpoints();
- });
- fakeBreakpoints();
- $(window).on(Tablesaw.events.resize, fakeBreakpoints);
- }
- // on tablecreate, init
- $(document).on(Tablesaw.events.create, function(e, tablesaw) {
- if (tablesaw.mode === "swipe") {
- createSwipeTable(tablesaw, tablesaw.$table);
- }
- });
- // TODO OOP this and add to Tablesaw object
- })();
- (function() {
- var MiniMap = {
- attr: {
- init: "data-tablesaw-minimap"
- },
- show: function(table) {
- var mq = table.getAttribute(MiniMap.attr.init);
- if (mq === "") {
- // value-less but exists
- return true;
- } else if (mq && "matchMedia" in window) {
- // has a mq value
- return window.matchMedia(mq).matches;
- }
- return false;
- }
- };
- function createMiniMap($table) {
- var tblsaw = $table.data("tablesaw");
- var $btns = $('<div class="tablesaw-advance minimap">');
- var $dotNav = $('<ul class="tablesaw-advance-dots">').appendTo($btns);
- var hideDot = "tablesaw-advance-dots-hide";
- var $headerCells = $table.data("tablesaw")._getPrimaryHeaderCells();
- // populate dots
- $headerCells.each(function() {
- $dotNav.append("<li><i></i></li>");
- });
- $btns.appendTo(tblsaw.$toolbar);
- function showHideNav() {
- if (!MiniMap.show($table[0])) {
- $btns.css("display", "none");
- return;
- }
- $btns.css("display", "block");
- // show/hide dots
- var dots = $dotNav.find("li").removeClass(hideDot);
- $table.find("thead th").each(function(i) {
- if ($(this).css("display") === "none") {
- dots.eq(i).addClass(hideDot);
- }
- });
- }
- // run on init and resize
- showHideNav();
- $(window).on(Tablesaw.events.resize, showHideNav);
- $table
- .on("tablesawcolumns.minimap", function() {
- showHideNav();
- })
- .on(Tablesaw.events.destroy + ".minimap", function() {
- var $t = $(this);
- tblsaw.$toolbar.find(".tablesaw-advance").remove();
- $(window).off(Tablesaw.events.resize, showHideNav);
- $t.off(".minimap");
- });
- }
- // on tablecreate, init
- $(document).on(Tablesaw.events.create, function(e, tablesaw) {
- if (
- (tablesaw.mode === "swipe" || tablesaw.mode === "columntoggle") &&
- tablesaw.$table.is("[ " + MiniMap.attr.init + "]")
- ) {
- createMiniMap(tablesaw.$table);
- }
- });
- // TODO OOP this better
- Tablesaw.MiniMap = MiniMap;
- })();
- (function() {
- var S = {
- selectors: {
- init: "table[data-tablesaw-mode-switch]"
- },
- attributes: {
- excludeMode: "data-tablesaw-mode-exclude"
- },
- classes: {
- main: "tablesaw-modeswitch",
- toolbar: "tablesaw-bar-section"
- },
- modes: ["stack", "swipe", "columntoggle"],
- init: function(table) {
- var $table = $(table);
- var tblsaw = $table.data("tablesaw");
- var ignoreMode = $table.attr(S.attributes.excludeMode);
- var $toolbar = tblsaw.$toolbar;
- var $switcher = $("<div>").addClass(S.classes.main + " " + S.classes.toolbar);
- var html = [
- '<label><span class="abbreviated">' +
- Tablesaw.i18n.modeSwitchColumnsAbbreviated +
- '</span><span class="longform">' +
- Tablesaw.i18n.modeSwitchColumns +
- "</span>:"
- ],
- dataMode = $table.attr("data-tablesaw-mode"),
- isSelected;
- // TODO next major version: remove .btn
- html.push('<span class="btn tablesaw-btn"><select>');
- for (var j = 0, k = S.modes.length; j < k; j++) {
- if (ignoreMode && ignoreMode.toLowerCase() === S.modes[j]) {
- continue;
- }
- isSelected = dataMode === S.modes[j];
- html.push(
- "<option" +
- (isSelected ? " selected" : "") +
- ' value="' +
- S.modes[j] +
- '">' +
- Tablesaw.i18n.modes[j] +
- "</option>"
- );
- }
- html.push("</select></span></label>");
- $switcher.html(html.join(""));
- var $otherToolbarItems = $toolbar.find(".tablesaw-advance").eq(0);
- if ($otherToolbarItems.length) {
- $switcher.insertBefore($otherToolbarItems);
- } else {
- $switcher.appendTo($toolbar);
- }
- $switcher.find(".tablesaw-btn").tablesawbtn();
- $switcher.find("select").on("change", function(event) {
- return S.onModeChange.call(table, event, $(this).val());
- });
- },
- onModeChange: function(event, val) {
- var $table = $(this);
- var tblsaw = $table.data("tablesaw");
- var $switcher = tblsaw.$toolbar.find("." + S.classes.main);
- $switcher.remove();
- tblsaw.destroy();
- $table.attr("data-tablesaw-mode", val);
- $table.tablesaw();
- }
- };
- $(document).on(Tablesaw.events.create, function(e, Tablesaw) {
- if (Tablesaw.$table.is(S.selectors.init)) {
- S.init(Tablesaw.table);
- }
- });
- // TODO OOP this and add to Tablesaw object
- })();
- (function() {
- var pluginName = "tablesawCheckAll";
- function CheckAll(tablesaw) {
- this.tablesaw = tablesaw;
- this.$table = tablesaw.$table;
- this.attr = "data-tablesaw-checkall";
- this.checkAllSelector = "[" + this.attr + "]";
- this.forceCheckedSelector = "[" + this.attr + "-checked]";
- this.forceUncheckedSelector = "[" + this.attr + "-unchecked]";
- this.checkboxSelector = 'input[type="checkbox"]';
- this.$triggers = null;
- this.$checkboxes = null;
- if (this.$table.data(pluginName)) {
- return;
- }
- this.$table.data(pluginName, this);
- this.init();
- }
- CheckAll.prototype._filterCells = function($checkboxes) {
- return $checkboxes
- .filter(function() {
- return !$(this)
- .closest("tr")
- .is("[data-tablesaw-subrow],[data-tablesaw-ignorerow]");
- })
- .find(this.checkboxSelector)
- .not(this.checkAllSelector);
- };
- // With buttons you can use a scoping selector like: data-tablesaw-checkall="#my-scoped-id input[type='checkbox']"
- CheckAll.prototype.getCheckboxesForButton = function(button) {
- return this._filterCells($($(button).attr(this.attr)));
- };
- CheckAll.prototype.getCheckboxesForCheckbox = function(checkbox) {
- return this._filterCells($($(checkbox).closest("th")[0].cells));
- };
- CheckAll.prototype.init = function() {
- var self = this;
- this.$table.find(this.checkAllSelector).each(function() {
- var $trigger = $(this);
- if ($trigger.is(self.checkboxSelector)) {
- self.addCheckboxEvents(this);
- } else {
- self.addButtonEvents(this);
- }
- });
- };
- CheckAll.prototype.addButtonEvents = function(trigger) {
- var self = this;
- // Update body checkboxes when header checkbox is changed
- $(trigger).on("click", function(event) {
- event.preventDefault();
- var $checkboxes = self.getCheckboxesForButton(this);
- var allChecked = true;
- $checkboxes.each(function() {
- if (!this.checked) {
- allChecked = false;
- }
- });
- var setChecked;
- if ($(this).is(self.forceCheckedSelector)) {
- setChecked = true;
- } else if ($(this).is(self.forceUncheckedSelector)) {
- setChecked = false;
- } else {
- setChecked = allChecked ? false : true;
- }
- $checkboxes.each(function() {
- this.checked = setChecked;
- $(this).trigger("change." + pluginName);
- });
- });
- };
- CheckAll.prototype.addCheckboxEvents = function(trigger) {
- var self = this;
- // Update body checkboxes when header checkbox is changed
- $(trigger).on("change", function() {
- var setChecked = this.checked;
- self.getCheckboxesForCheckbox(this).each(function() {
- this.checked = setChecked;
- });
- });
- var $checkboxes = self.getCheckboxesForCheckbox(trigger);
- // Update header checkbox when body checkboxes are changed
- $checkboxes.on("change." + pluginName, function() {
- var checkedCount = 0;
- $checkboxes.each(function() {
- if (this.checked) {
- checkedCount++;
- }
- });
- var allSelected = checkedCount === $checkboxes.length;
- trigger.checked = allSelected;
- // only indeterminate if some are selected (not all and not none)
- trigger.indeterminate = checkedCount !== 0 && !allSelected;
- });
- };
- // on tablecreate, init
- $(document).on(Tablesaw.events.create, function(e, tablesaw) {
- new CheckAll(tablesaw);
- });
- Tablesaw.CheckAll = CheckAll;
- })();
- return Tablesaw;
- }));
|