您的位置:首页 > 其它

Advanced Plugin Concepts

2015-11-13 17:10 351 查看
ProvidePublicAccesstoDefaultPluginSettingsAnimprovementwecan,andshould,maketothecodeaboveistoexposethedefaultpluginsettings.Thisisimportantbecauseitmakesitveryeasyforpluginuserstooverride/customizethepluginwithminimalcode.Andthisiswherewebegintotakeadvantageofthefunctionobject.
//Plugindefinition.


$.fn.hilight=function(options){




//Extendourdefaultoptionswiththoseprovided.


//Notethatthefirstargumenttoextendisanempty


//object–thisistokeepfromoverridingour"defaults"object.


varopts=$.extend({},$.fn.hilight.defaults,options);




//Ourpluginimplementationcodegoeshere.




};




//Plugindefaults–addedasapropertyonourpluginfunction.


$.fn.hilight.defaults={


foreground:"red",


background:"yellow"


};


[/code]
Nowuserscanincludealinelikethisintheirscripts:
//Thisneedsonlybecalledonceanddoesnot


//havetobecalledfromwithina"ready"block


$.fn.hilight.defaults.foreground="blue";


[/code]
Andnowwecancallthepluginmethodlikethisanditwilluseablueforegroundcolor:
1
$("#myDiv").hilight();


[/code]
Asyoucansee,we'veallowedtheusertowriteasinglelineofcodetoalterthedefaultforegroundcoloroftheplugin.Anduserscanstillselectivelyoverridethisnewdefaultvaluewhentheywant:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Overrideplugindefaultforegroundcolor.


$.fn.hilight.defaults.foreground="blue";




//...




//Invokepluginusingnewdefaults.


$(".hilightDiv").hilight();




//...




//Overridedefaultbypassingoptionstopluginmethod.


$("#green").hilight({


foreground:"green"


});


[/code]
linkProvidePublicAccesstoSecondaryFunctionsasApplicable
Thisitemgoeshand-in-handwiththepreviousitemandisaninterestingwaytoextendyourplugin(andtoletothersextendyourplugin).Forexample,theimplementationofourpluginmaydefineafunctioncalled"format"whichformatsthehilighttext.Ourpluginmaynowlooklikethis,withthedefaultimplementationoftheformatmethoddefinedbelowthehilightfunction:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//Plugindefinition.


$.fn.hilight=function(options){




//Iterateandreformateachmatchedelement.


returnthis.each(function(){




varelem=$(this);




//...




varmarkup=elem.html();




//Callourformatfunction.


markup=$.fn.hilight.format(markup);




elem.html(markup);




});




};




//Defineourformatfunction.


$.fn.hilight.format=function(txt){


return"<strong>"+txt+"</strong>";


};


[/code]
Wecouldhavejustaseasilysupportedanotherpropertyontheoptionsobjectthatallowedacallbackfunctiontobeprovidedtooverridethedefaultformatting.That'sanotherexcellentwaytosupportcustomizationofyourplugin.Thetechniqueshownheretakesthisastepfurtherbyactuallyexposingtheformatfunctionsothatitcanberedefined.Withthistechniqueitwouldbepossibleforotherstoshiptheirowncustomoverridesofyourplugin–inotherwords,itmeansotherscanwritepluginsforyourplugin.
Consideringthetrivialexamplepluginwe'rebuildinginthisarticle,youmaybewonderingwhenthiswouldeverbeuseful.Onereal-worldexampleistheCyclePlugin.TheCyclePluginisaslideshowpluginwhichsupportsanumberofbuilt-intransitioneffects–scroll,slide,fade,etc.Butrealistically,thereisnowaytodefineeverysingletypeofeffectthatonemightwishtoapplytoaslidetransition.Andthat'swherethistypeofextensibilityisuseful.TheCyclePluginexposesa"transitions"objecttowhichuserscanaddtheirowncustomtransitiondefinitions.It'sdefinedinthepluginlikethis:
1
2
3
4
5
$.fn.cycle.transitions={




//...




};


[/code]
Thistechniquemakesitpossibleforotherstodefineandshiptransitiondefinitionsthatplug-intotheCyclePlugin.
linkKeepPrivateFunctionsPrivate
Thetechniqueofexposingpartofyourplugintobeoverriddencanbeverypowerful.Butyouneedtothinkcarefullyaboutwhatpartsofyourimplementationtoexpose.Onceit'sexposed,youneedtokeepinmindthatanychangestothecallingargumentsorsemanticsmaybreakbackwardcompatibility.Asageneralrule,ifyou'renotsurewhethertoexposeaparticularfunction,thenyouprobablyshouldn't.
Sohowthendowedefinemorefunctionswithoutclutteringthenamespaceandwithoutexposingtheimplementation?Thisisajobforclosures.Todemonstrate,we'lladdanotherfunctiontoourplugincalled"debug".Thedebugfunctionwilllogthenumberofselectedelementstotheconsole.Tocreateaclosure,wewraptheentireplugindefinitioninafunction(asdetailedinthejQueryAuthoringGuidelines).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Createclosure.


(function($){




//Plugindefinition.


$.fn.hilight=function(options){


debug(this);


//...


};




//Privatefunctionfordebugging.


functiondebug(obj){


if(window.console&&window.console.log){


window.console.log("hilightselectioncount:"+obj.length);


}


};




//...




//Endofclosure.




})(jQuery);


[/code]
Our"debug"methodcannotbeaccessedfromoutsideoftheclosureandthusisprivatetoourimplementation.
linkBobandSue
Let'ssayBobhascreatedawickednewgalleryplugin(called"superGallery")whichtakesalistofimagesandmakesthemnavigable.Bob'sthrowninsomeanimationtomakeitmoreinteresting.He'striedtomakethepluginascustomizableaspossible,andhasendedupwithsomethinglikethis:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
jQuery.fn.superGallery=function(options){




//Bob'sdefaultsettings:


vardefaults={


textColor:"#000",


backgroundColor:"#fff",


fontSize:"1em",


delay:"quitelong",


getTextFromTitle:true,


getTextFromRel:false,


getTextFromAlt:false,


animateWidth:true,


animateOpacity:true,


animateHeight:true,


animationDuration:500,


clickImgToGoToNext:true,


clickImgToGoToLast:false,


nextButtonText:"next",


previousButtonText:"previous",


nextButtonTextColor:"red",


previousButtonTextColor:"red"


};




varsettings=$.extend({},defaults,options);




returnthis.each(function(){


//Plugincodewouldgohere...


});




};


[/code]
Thefirstthingthatprobablycomestoyourmind(OK,maybenotthefirst)istheprospectofhowhugethispluginmustbetoaccommodatesuchalevelofcustomization.Theplugin,ifitweren'tfictional,wouldprobablybealotlargerthannecessary.Thereareonlysomanykilobytespeoplewillbewillingtospend!
Now,ourfriendBobthinksthisisallfine;infact,he'squiteimpressedwiththepluginanditslevelofcustomization.Hebelievesthatalltheoptionsmakeforamoreversatilesolution,onewhichcanbeusedinmanydifferentsituations.
Sue,anotherfriendofours,hasdecidedtousethisnewplugin.Shehassetupalloftheoptionsrequiredandnowhasaworkingsolutionsittinginfrontofher.It'sonlyfiveminuteslater,afterplayingwiththeplugin,thatsherealizesthegallerywouldlookmuchnicerifeachimage'swidthwereanimatedataslowerspeed.ShehastilysearchesthroughBob'sdocumentationbutfindsnoanimateWidthDurationoption!
linkDoYouSeeTheProblem?
It'snotreallyabouthowmanyoptionsyourpluginhas;butwhatoptionsithas!
Bobhasgonealittleoverthetop.Thelevelofcustomizationhe'soffering,whileitmayseemhigh,isactuallyquitelow,especiallyconsideringallthepossiblethingsonemightwanttocontrolwhenusingthisplugin.Bobhasmadethemistakeofofferingalotofridiculouslyspecificoptions,renderinghispluginmuchmoredifficulttocustomize!
linkABetterModel
Soit'sprettyobvious:Bobneedsanewcustomizationmodel,onewhichdoesnotrelinquishcontrolorabstractawaythenecessarydetails.
ThereasonBobissodrawntothishigh-levelsimplicityisthatthejQueryframeworkverymuchlendsitselftothismindset.OfferingapreviousButtonTextColoroptionisniceandsimple,butlet'sfaceit,thevastmajorityofpluginusersaregoingtowantwaymorecontrol!
Hereareafewtipswhichshouldhelpyoucreateabettersetofcustomizableoptionsforyourplugins:
linkDon'tCreatePlugin-specificSyntax
Developerswhouseyourpluginshouldn'thavetolearnanewlanguageorterminologyjusttogetthejobdone.
Bobthoughthewasofferingmaximumcustomizationwithhisdelayoption(lookabove).Hemadeitsothatwithhispluginyoucanspecifyfourdifferentdelays,"quiteshort,""veryshort,""quitelong,"or"verylong":
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vardelayDuration=0;




switch(settings.delay){




case"veryshort":


delayDuration=100;


break;




case"quiteshort":


delayDuration=200;


break;




case"quitelong":


delayDuration=300;


break;




case"verylong":


delayDuration=400;


break;




default:


delayDuration=200;




}


[/code]
Notonlydoesthislimitthelevelofcontrolpeoplehave,butittakesupquiteabitofspace.Twelvelinesofcodejusttodefinethedelaytimeisabitmuch,don'tyouthink?Abetterwaytoconstructthisoptionwouldbetoletpluginusersspecifytheamountoftime(inmilliseconds)asanumber,sothatnoprocessingoftheoptionneedstotakeplace.
Thekeyhereisnottodiminishthelevelofcontrolthroughyourabstraction.Yourabstraction,whateveritis,canbeassimplisticasyouwant,butmakesurethatpeoplewhouseyourpluginwillstillhavethatmuch-sought-afterlow-levelcontrol!(Bylow-levelImeannon-abstracted.)
linkGiveFullControlofElements
IfyourplugincreateselementstobeusedwithintheDOM,thenit'sagoodideatoofferpluginuserssomewaytoaccessthoseelements.SometimesthismeansgivingcertainelementsIDsorclasses.Butnotethatyourpluginshouldn'trelyonthesehooksinternally:
Abadimplementation:
1
2
3
4
//Plugincode


$("<divclass='gallery-wrapper'/>").appendTo("body");




$(".gallery-wrapper").append("...");


[/code]
Toallowuserstoaccessandevenmanipulatethatinformation,youcanstoreitinavariablecontainingthesettingsofyourplugin.Abetterimplementationofthepreviouscodeisshownbelow:
1
2
3
4
5
6
7
//Retainaninternalreference:


varwrapper=$("<div/>")


.attr(settings.wrapperAttrs)


.appendTo(settings.container);




//Easytoreferencelater...


wrapper.append("...");


[/code]
Noticethatwe'vecreatedareferencetotheinjectedwrapperandwe'realsocallingthe
.attr()
methodtoaddanyspecifiedattributestotheelement.So,inoursettingsitmightbehandledlikethis:
1
2
3
4
5
6
7
8
9
10
vardefaults={


wrapperAttrs:{


class:"gallery-wrapper"


},


//...restofsettings...


};




//Wecanusetheextendmethodtomergeoptions/settingsasusual:


//ButwiththeaddedfirstparameterofTRUEtosignifyaDEEPCOPY:


varsettings=$.extend(true,{},defaults,options);


[/code]
The$.extend()methodwillnowrecursethroughallnestedobjectstogiveusamergedversionofboththedefaultsandthepassedoptions,givingthepassedoptionsprecedence.
ThepluginusernowhasthepowertospecifyanyattributeofthatwrapperelementsoiftheyrequirethattherebeahookforanyCSSstylesthentheycanquiteeasilyaddaclassorchangethenameoftheIDwithouthavingtogodiggingaroundinpluginsource.
ThesamemodelcanbeusedtolettheuserdefineCSSstyles:
1
2
3
4
5
6
7
8
9
10
vardefaults={


wrapperCSS:{},


//...restofsettings...


};




//Lateroninthepluginwherewedefinethewrapper:


varwrapper=$("<div/>")


.attr(settings.wrapperAttrs)


.css(settings.wrapperCSS)//**SetCSS!


.appendTo(settings.container);


[/code]
YourpluginmayhaveanassociatedstylesheetwheredeveloperscanaddCSSstyles.Eveninthissituationit'sagoodideatooffersomeconvenientwayofsettingstylesinJavaScript,withouthavingtouseaselectortogetattheelements.
linkProvideCallbackCapabilities
Whatisacallback?–Acallbackisessentiallyafunctiontobecalledlater,normallytriggeredbyanevent.It'spassedasanargument,usuallytotheinitiatingcallofacomponent,inthiscase,ajQueryplugin.
Ifyourpluginisdrivenbyeventsthenitmightbeagoodideatoprovideacallbackcapabilityforeachevent.Plus,youcancreateyourowncustomeventsandthenprovidecallbacksforthose.Inthisgallerypluginitmightmakesensetoaddan"onImageShow"callback.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vardefaults={




//Wedefineanemptyanonymousfunctionsothat


//wedon'tneedtocheckitsexistencebeforecallingit.


onImageShow:function(){},




//...restofsettings...




};




//Lateronintheplugin:




nextButton.on("click",showNextImage);




functionshowNextImage(){




//Returnsreferencetothenextimagenode


varimage=getNextImage();




//Stufftoshowtheimagehere...




//Here'sthecallback:


settings.onImageShow.call(image);


}


[/code]
Insteadofinitiatingthecallbackviatraditionalmeans(addingparenthesis)we'recallingitinthecontextof
image
whichwillbeareferencetotheimagenode.Thismeansthatyouhaveaccesstotheactualimagenodethroughthe
this
keywordwithinthecallback:
1
2
3
4
5
6
7
$("ul.imgsli").superGallery({


onImageShow:function(){


$(this).after("<span>"+$(this).attr("longdesc")+"</span>");


},




//...otheroptions...


});


[/code]
Similarlyyoucouldaddan"onImageHide"callbackandnumerousotherones.Thepointofcallbacksistogivepluginusersaneasywaytoaddadditionalfunctionalitywithoutdiggingaroundinthesource.
linkRemember,It'saCompromise
Yourpluginisnotgoingtobeabletoworkineverysituation.Andequally,it'snotgoingtobeveryusefulifyouoffernoorveryfewmethodsofcontrol.So,remember,it'salwaysgoingtobeacompromise.Threethingsyoumustalwaystakeintoaccountare:

Flexibility:Howmanysituationswillyourpluginbeabletodealwith?
Size:Doesthesizeofyourplugincorrespondtoitsleveloffunctionality?I.e.Wouldyouuseaverybasictooltippluginifitwas20kinsize?–Probablynot!
Performance:Doesyourpluginheavilyprocesstheoptionsinanyway?Doesthisaffectspeed?Istheoverheadcausedworthitfortheenduser?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: