Plugin Customizer: Ad WordPress ^T f^T fBOOKMOBIS#*H'<MOBIZ736 @EXTHdPer Soderlindi!general ,proof of conceptg

tl;dr -  The commented demo plugin is available at GitHub.Introduction I've wanted to add a customizer to my Read Offline plugin for a long time, letting the user easily change the PDF and ePub design. As I like …

j'Wed, 28 Sep 2016 20:16:29 +0000p#http://soderlind.no/?p=4908ePer Søderlindf5Copyright Per Soderlind - http://soderlind.noPlugin Customizer: Ad WordPress customizer to a plugin

Plugin Customizer: Ad WordPress customizer to a plugin

tl;dr –  The commented demo plugin is available at GitHub.

Introduction

I’ve wanted to add a customizer to my Read Offline plugin for a long time, letting the user easily change the PDF and ePub design. As I like to write a demo plugin before adding new functionality, here’s my take on adding WordPress customizer to a plugin.

Understanding how the customizer works wasn’t easy.

Understanding how the customizer works wasn’t easy. I’ve read the documentation and read a lot of source code. After viewing the loopconf presentation Patrick Rauland held last year, I asked him and got an early beta version of the WooCommerce Email Customizer plugin. I’ve also followed the work Weston Ruter and XWP have done and have skimmed through their customizer plugins, I’ve also viewed tickets and followed the discussions on Slack.

The thing I found hardest was understanding how to remove the other sections from the customizer, so I asked on Twitter

Any idea how I can reset the #WordPress Customizer. i.e. remove existing panels and controls before I add mine ?

— Per Søderlind (@soderlind) September 11, 2016

Fortunately, Weston came to the rescue :)

@soderlind @bjornjohansen @tommcfarlin I just did a writeup for what I think may be the most concise way to do it: https://t.co/2pXoYtEjrZ

— Weston Ruter âš¡ (@westonruter) September 11, 2016

The important parts

Timing is everything.

Timing is everything, and so is understanding when parts of the code is used. WordPress customizer relies on ajax for communication between the controls and the preview, and customizer uses ajax for saving settings.

“Blank Slate” loads at a priority of 1, so the Plugin Customizer must load after it, but if it’s loaded at the default priority of 10, it will not be available. As shown below, I add the customizer_register  at priority 9.

So, everything looked fine, but I couldn’t save the settings (!!), and the only error message I got was a 500 Server error. I understood that when saving & publishing the customizer settings, admin-ajax.php expects to find the settings, and if I removed the bailout test everything worked fine.

The problem was that I couldn’t “see” the solution. When I removed the bailout test, Plugin Customizer sections would pop up in the default Appearance -> Customize, and if I added the bailout test, I couldn’t save the settings.

Now, after the problem is solved, it’s a simple fix (isn’t it always). Register the customizer settings before the bailout test and register the customizer sections and controls after the bailout test.

Adding a preview

Weston describes how to add a preview in Navigating to a URL in the Customizer Preview when a Section is Expanded. I’ve extended his code to add a template per section.

Loading the template, I tested the hooks template_redirect and template_include, but I ended up creating a permalink. It fitted well to script above.

Like to learn how to create a custom permalink? I’ve written another demo plugin that shows you how to do it.

Code

The Plugin Customizer demo plugin is available at GitHub. The code is documented. If you find logical flaws, typos etc, please contribute.

Credits

I couldn’t, at least not in the near future, have developed this plugin without the help from Patrick Rauland and Weston Ruter.

Btw, any flaws in the plugin are mine.

 

Contents

Introduction
The important parts
Adding a preview
Code
Credits
JFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222ml" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?Т((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ۏڤW2,G* hԨ)ϕU(g3 4WVpG4w1W]NmZaI)ttQEQEQEQEQEQEQEQEQEQEQTo_׼ Wؿ'EPEPEPF*XhHSzR!vM2B+e$'1萧"#7 =}3T,T)-?]j&*zB: TQEiR7L+fY`=YYRqLKd8Ic |quyϾi%=݋$7i:/]PWGvl]0xڵ<8U\b'v> fL-Wz槬J^Ys3EUuZ?1m. xFq~Ȣ{5븙('a<{V'1pO_h)+nI-W]@xėɬ$\;'|u![o&RFAIH((((((((((_;^uo_D@}Wi$Y rGqZ'n/os_&"~\k~<cL~9O&x[5Ey;8M>T }vhef8dS ( +\񎓡1iL#XÆa?kr\LWB=6>*^+?M׿O4/iZ[]7)z@%Q@x{#mUrIU\UIT;e zRM|U6.4#9+KJ%ǚK0^[B$PsqBi(ѦFO+@V"ٚ;x$[tQEQY׉?'̤easvWuRBYM&ITWN0tf\ƺmHNv8Q)PYEPEPEP޾vξ_;^uo@#[ƋxzD0X:Zm#d5{ח|Q#ZI1ض0?!UWY4'->_:-j#W3ԓPEŮ|O3hÚgՄwM.>za5@q;chabog=~] I|j/k7wsJ/EX _4V |!s{^gI11 }"=@UFQ$'@=&hn.mg9ִ[&axq؊%إLJ̶anPz[[>\byOFz[^1]nߖg7an8(rxzm50gcS!שQ@|,Be@P?SYɰԲgLCfyQz$_VN;*PAs^vMsA ;no*F? >!ږkqas#'S!+~Eƀ=.꺔F=K{N*y-Ii\e٨5sP{,DŽAQ{]>Q.oQǷt{ڠy&5йȟW oREa yn-.5,-9>uUOV5{R+:?IQEQE:_WWmiZONkǧܸ1+zBVp+~xw (O `ϬgPjEP޹B}kiU?*H??eϕ}[rq_@/j_/kր=A_Τi)n9z%xgĺ7_o?ߞIwZ]J;T<"V~1} ^_5_B4??b;wzzV*At+O1 6XyowۻɯZ-{xwr_hоȦum"wwej~rWUK@VroI+#*jʵ#*jʀ<&)RT8d`}li/^tI'vo\Jp[he^UR=A5$CmAIH0 oGUQdĞ*־iset/1)z%|c{>{ &ܧ}oԴkظI{W,C[0p@3^S/A9ο?ր:ce87B~κJOxf8Ȍz?Q|I=ԧ|9;J+tQ}u<GMhHNWGyo}1k.ᖉ,dC%؇ ?"+|G᛿]s$2gʙFc;jj|qbhCWïK{n^XS|ǒJ-v^(fP?x((|{տ}޾v΀:7z}n)!==ğ ger)W/D7|ѻ#WS`^k*E Em4x/]޹<}Oұ}:|Q};hw^OG^}+?F-u6;V[C5@u :(?rFϵ6\72*Gh_c_?I jOr[>VhՊoKTEqkWp77z7ގI㞄׿@fOibp׸R@Wi:r lqOauOk0@TFMW\Q裀? +< ;8t5[RkÌ׶|[h,.  =+F/x^F=ZT׷R$IJ+}+UsOi>*\__4f=:g$apWkk٫"c|FFߌJD}.>f)?E5W+6A&W?Z JM\zoOut_S_8OE:((ͷ?_W΄$8 +m7ڦS"܏€=sDŽS! +n?:ͦ\iGnbTnb(+_yp=a׮⎨mi!ݼ=2O@mo(w 2C:y׿/j_/kZ>(/}I/ѪԟYZO9/1^@Z7Q}Bm"wwGk]W]ހ8__s#|?O]W/Y9'dȩ׻*׬ȩ׻*;Bv?!_C4 dЅ}ހ (<3C/Ա=Gs"_yύ?pԿEz7ß"q$oѵ ms 4R郊 $7Ī*L@JwLj%?ƽW+w=6E9 ~[t"l4Mړ#J0={Z7 sxWtQ@ EPEP޾vξ_;^uo@#[Ճ#[Wx?ٳ6ac½^,Q *+UAxo|EqHL{w,=j+}B+Y7+ּo 9ic|/>pŴ|h٫<]q S9{r$tpYNAd"1CCGC!tkDeOԴ)/-G,2?Si-4;mBO,tIp>€=֑cFwuTQp#uDa_+YVM| Ҁ=zm]h}*}`{V^YDVk)b0 ۜ<:x^X$Lyk=ּMz7_|t __`6AP!O17[ Ris [5Zyѝ:&LW~_?N8 fGOcre}AG84ףnmr1辍Кeu 2Am{h.c&2w0,ړN.F"%1G@\ϊQZ}ͣ%6C\e?yߋ)66G|R>Ե[YZ Hi<̘GJ'qTuQ@Q@p>jɺkU"UOКh##dZH.4mJc*z0lмEa E@%1==W^Cl0+֝wǝmsGS}ExE}"^c V~i|>:[ܦۛR9D>]P~"^}^Կ_׀>}Q@ ^_5OB5^%T?#@/1s_%iI?cWG@ ڼ;9j?=üo# @E5+\opg_?+W+F딟ʺ_s#|?O@Y+STvUY+STvTw?B_*I6ZLۣ+Օ2Aw%31&}ۈ*GO֫i%4 e,qfp@Hp$i"x*!\>-_U^jȇڇ0?J|]bK]\M&b9T_a[~ 59u岘Z&敗jd((Vb[H$INJѥhV"HN#P>TQ@Q@\Ba)'%%@=OT Ң#mX`"FBRQE#H$Uea2 bx?o].cH(_xh63ViOG GТ ( ¿vHeOEZ"S?n/DɎ3c5ZXXCZ[ݍ*ETl/ZaL+Ea`vV1%Lp*QEŴpnahH sxÓ9o4d9X5P =tF?"@Dx7UdadKEf=OT  QEQEQEU[6QMN1ǘ= ţ>3SK<7#h zu,!jPEPd%VV@}?+J ( &O+K.e$K3'~X xc%ơTw*J(ϢWS4ey Vc$U(kKk8|[x9 ( +K]prhÀ}y2a5ic|P*>U(KsMI2:0Eg.#]"YNA?hEQEQEҮfi,YV'H6ֶpmm s$ 3-QE ǻzۧw1V?O>LUeOekm6]z9]?ZPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPERUgHn`WT@qEVlF9™\.~PY +A'}Y7֋d/!lWp \![j6JN?O_€4ךP۫)4Sk*1 qh%P4:a 2v;GڹxPc8 J˃Ě-uKV*dgjPEAw{ka (#F 3{oKԤ1_46>hRT#qY$ [|wr=wP ,#(74{{ͩZH8>K Al daq@bfH]5Puu+ۼ-Q@ uUBY:e\}9cڙqcy O#pH(Xkn4.+8m\q?,>Aק4n>akwEq&6D6N֟{gC^\yi>fĺլ30ZݖwʞPSIT`}I ]c8~u жRI(>EG4[*G`l^'Drp tEΡw{-LhcePr>j쨪[]GJ]n78 |}:+>]Ҵ|BíYKсOEc}V'Lϥj<7PJu`"EgkMh }}?:k5hp>p zPyE\JDm4%i"qo$O0% XV(?>? zs@M%y_Zi ;YmCeʧ U_ k:4C&D,c8F}zUxw]ԯ<{L4#*0_zV6*]S&HHn264QT6h-D橕AL`vζWN*8$]_i1ApG 6֙[+gu*>h%:.Y4%Ī08};*( ( ( ( ( ( ( 'nic?Z*Gi:|L =ADZ<\W[En$mh&&{"~?w|~{ ڞp f3Z?4}5!{3G@qN4mXb.oR^Yio2#I]_ ghg>\3wЍc] RN?d[3 ;?Z<#iQ=ԗkpA,cޯ© KHEv-mv*5v1 f|-~׏~1Vk=H3}+w{GEY.,9|[٫SSԼ_Osmn zy5o It'LԦZ/*?,=d|7 ЉfB V=rMzG2%K+`gzq\>Q\%q=8'=>wU-uy~CFOv~k|Ioh8gǺm.IZۘ\U]rd## v uR\եLX\FI'j] (^@2º <1g]/S.MسH8;u?_]}gozXh^)T4nYOBQ@iúN]]_.&³px=yWڱ #IqAwֺ/3G2_Ⱥ}ms ]PGk4&ⶓ]ZP}fydel;^<څťG{Ԩ=u /FRNpִ~+#=XiwŊ&q߰<zg<) ?~}~r?Dv_Ao iz>ewc G+JI펵?Gbn?C[njlj|9 Jo F1@ֿ߁4V;G<?>ۤ:߆Քn#, _λ qivڴ|{xЍxgj7Pˮks^ b 33 [}} =pz;}k{e-Crq?4nf E(8P}>-;N\({?0mVݧ,|=m6f2^Gm#1;sk~f>ev }ֺmv@Yi(NOCVtKjjk5H95~oIk{%·O:#G5wMtӪjwmRs$mi'Ef0q)9=zd֏ɭ3M2ƾ*olmYyBri9>zhui<.?N5lkc'ζI{p8e[21 6lL)p͓̂3=*m5-կ!dRNTl^=;κx`h o;gݷ?j {6K?}|]^d(2}?Z|)%;YzF<)%;YzF fxYw!|wҍ'?~'~|+nnJ&Y_Fde}=G=]:-YHXݎz{ eYw!|wサ});h+6ۋAL3*9Qv?zZxCf B8p{Oǣ Xٽ}CCE4MQk|+{y9$z q?|]⫍SBvOމUWP'//z Oo 4mE' OxN->=l]H[|@lʻ +ح44aQ蓇s ( ('5zOj.R8ڒ/~[{Q巵KEBWzmK/AQQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEX註Ա@(("'c-/|/vkw?ֲ4]Ϣ\iz͔wv4 FO~G^_-G;~϶Mzt] Mp]c{? ~ͼ'i%Ǜ; gRoR{ l}RoG-Ϳh@qU_(?덷)|4qqyYU0['T-t?y~BDw>{h߅Tҿ?VSҬ4K3/~|_|(Z(#Iz ((((((((((((((((((((((((((REEޥ}Q@Q@.ЧicO5_t}-&FV{x&eHP8PEPEPEOTԡ4(W,#d_ZEPѵh5.B$XeHaGb}*QE2Oj.,t]ҙOKEPrI/AQQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEX註Ա@(()k'iQ2YdQepx0(+n_iHW*wUV^*6.mbr@z1[1<{]:t۲qFFqZ/iu=i1Buwu??!OlGP9V UѰAEsOury&iY/#'7>ȑaF5uCbK:"q)%I8##zSVZXFA1QE>騻Բ}Qw?Je>/~-Q@Tu$G@ EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPcRE>((?>>%{YD\q]:'FK[Ռ "a.rAEzeKk>M&ͤ'%#@M.eӒXC,`ޙz{H0)9S{ν/UEM BH .?1 *NFh7X>0-4w9yJd>N{$,&?0~Mc1CnHwj(e*2HԼ-חar ;efo:.zn\CY28>ޟhO7P78$[ yǂ|kZv#۴%o+b{IxDZN6J?x.q==+@.-㷗LhcTU[;k6A$Hg(z('5zOj.SLҀ%(9z ((((((((((((((((((((((((((^,tT]XEQEQEbIx]ѺaMnig*QEQ\_={RЭ,_MW`"@xA=q@-'AXzOs 4ϘnQ@ K'5z)}S@EGRKTtQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE/z?*.,tP袊(Z-1C&ॹ>{V4<7ooPۖ6*玼ީNGlh-ǟop{9(|qi,2މ߹R$qkfSe+/i{8e0ym@hռcӛ{>q)r\p>h"ҵcݬz2 8\ýN%/㻺fΡ{ISeni1s;0!jkPqֺ:({Elo!A)7Rq8xrL5=^F/շ)\OvԔh,uEiI1qstխ3:޷uyq-+d t'騻Բ}Qw?Je>/~-Q@Tu$G@ EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPcRE>((((((((IMEޥS)} h^%*:J( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (Kz?@(xQcҿ4vO'hd2}M6vO'hd2}M6vO'hd2}M6\QE->/~|_|(Z(#Iz ((((((((((((((((((((((((((QңaOEP3Ȩ%AEOEAEOEAEOEAEOEAEOEAEOEAEOEANMEQEG/AQԒ%Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?>,uP{tLZ2=hh#րLZ2=hh#րLZ2=hh#րLZ2=hh#րLZ2=hK! (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((FLIS00 00 00 0800 4100 0000 00 00 00ff ff ff ff00 0100 0300 00 00 0300 00 00 01ff ff ff ffFCIS00 00 00 1400 00 00 1000 00 00 0100 00 00 0000 00 27 3c00 00 00 0000 00 00 2000 00 00 0800 0100 0100 00 00 003918400778