123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777 |
- /*! Tablesaw - v3.0.9 - 2018-02-14
- * https://github.com/filamentgroup/tablesaw
- * Copyright (c) 2018 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;
- var domContentLoadedTriggered = false;
- 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) {
- 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 $headers = this._getPrimaryHeaderCells($headerRow);
- 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($headers[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) {
- $(e.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)
- .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($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='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)
- .refreshPriority();
- }
- });
- 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 $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 = [];
- // Calculate initial widths
- $headerCells.each(function() {
- headerWidths.push(this.offsetWidth);
- });
- // 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 ",
- styles = [],
- tableWidth = $table.width(),
- hash = [],
- 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;
- 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);
- }
- }
- }
- function getNext() {
- var next = [],
- checkFound;
- $headerCellsNoPersist.each(function(i) {
- var $t = $(this),
- 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 nextpair(fwd) {
- return fwd ? getNext() : getPrev();
- }
- function canAdvance(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);
- }
- });
- $headerCells.each(function(index) {
- if (persist[index]) {
- // for visual box-shadow
- persistColumn(this);
- return;
- }
- if (sums[index] <= containerWidth || needsNonPersistentColumn) {
- needsNonPersistentColumn = false;
- showColumn(this);
- tblsaw.updateColspanCells(classes.hiddenCol, this, true);
- }
- });
- unmaintainWidths();
- $table.trigger("tablesawcolumns");
- }
- function advance(fwd) {
- var pair = nextpair(fwd);
- if (canAdvance(pair)) {
- if (isNaN(pair[0])) {
- if (fwd) {
- pair[0] = 0;
- } else {
- pair[0] = $headerCellsNoPersist.length - 1;
- }
- }
- // TODO just blindly hiding the previous column and showing the next column can result in
- // column content overflow
- maintainWidths();
- hideColumn($headerCellsNoPersist.get(pair[0]));
- tblsaw.updateColspanCells(classes.hiddenCol, $headerCellsNoPersist.get(pair[0]), false);
- showColumn($headerCellsNoPersist.get(pair[1]));
- tblsaw.updateColspanCells(classes.hiddenCol, $headerCellsNoPersist.get(pair[1]), true);
- $table.trigger("tablesawcolumns");
- }
- }
- $prevBtn.add($nextBtn).on("click", function(e) {
- advance(!!$(e.target).closest($nextBtn).length);
- 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) {
- advance(true);
- }
- if (x - originX > horizontalThreshold) {
- advance(false);
- }
- }
- window.setTimeout(function() {
- $(window).on(Tablesaw.events.resize, fakeBreakpoints);
- }, 300);
- $(this).off("touchmove.swipetoggle touchend.swipetoggle");
- });
- });
- }
- $table
- .on("tablesawcolumns.swipetoggle", function() {
- var canGoPrev = canAdvance(getPrev());
- var canGoNext = canAdvance(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() {
- advance(true);
- })
- .on("tablesawprev.swipetoggle", function() {
- advance(false);
- })
- .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;
- }));
|