WordPress Landing Pages - Version 2.6.9

Version Description

  • Maintenance work on impression storing.
Download this release

Release Info

Developer adbox
Plugin Icon 128x128 WordPress Landing Pages
Version 2.6.9
Comparing to
See all releases

Code changes from version 2.6.7 to 2.6.9

Files changed (856) hide show
  1. assets/lang/{inbound-pro-ach.mo → landing-pages-ach.mo} +0 -0
  2. assets/lang/{inbound-pro-ady.mo → landing-pages-ady.mo} +0 -0
  3. assets/lang/{inbound-pro-af.mo → landing-pages-af.mo} +0 -0
  4. assets/lang/{inbound-pro-af_ZA.mo → landing-pages-af_ZA.mo} +0 -0
  5. assets/lang/{inbound-pro-ak.mo → landing-pages-ak.mo} +0 -0
  6. assets/lang/{inbound-pro-aln.mo → landing-pages-aln.mo} +0 -0
  7. assets/lang/{inbound-pro-am.mo → landing-pages-am.mo} +0 -0
  8. assets/lang/{inbound-pro-am_ET.mo → landing-pages-am_ET.mo} +0 -0
  9. assets/lang/{inbound-pro-an.mo → landing-pages-an.mo} +0 -0
  10. assets/lang/{inbound-pro-ar.mo → landing-pages-ar.mo} +0 -0
  11. assets/lang/{inbound-pro-ar_AA.mo → landing-pages-ar_AA.mo} +0 -0
  12. assets/lang/{inbound-pro-ar_EG.mo → landing-pages-ar_EG.mo} +0 -0
  13. assets/lang/{inbound-pro-ar_SA.mo → landing-pages-ar_SA.mo} +0 -0
  14. assets/lang/{inbound-pro-ar_SD.mo → landing-pages-ar_SD.mo} +0 -0
  15. assets/lang/{inbound-pro-ar_SY.mo → landing-pages-ar_SY.mo} +0 -0
  16. assets/lang/{inbound-pro-arn.mo → landing-pages-arn.mo} +0 -0
  17. assets/lang/{inbound-pro-as.mo → landing-pages-as.mo} +0 -0
  18. assets/lang/{inbound-pro-as_IN.mo → landing-pages-as_IN.mo} +0 -0
  19. assets/lang/{inbound-pro-ast.mo → landing-pages-ast.mo} +0 -0
  20. assets/lang/{inbound-pro-ast_ES.mo → landing-pages-ast_ES.mo} +0 -0
  21. assets/lang/{inbound-pro-az.mo → landing-pages-az.mo} +0 -0
  22. assets/lang/{inbound-pro-az@Arab.mo → landing-pages-az@Arab.mo} +0 -0
  23. assets/lang/{inbound-pro-az@latin.mo → landing-pages-az@latin.mo} +0 -0
  24. assets/lang/{inbound-pro-az_AZ.mo → landing-pages-az_AZ.mo} +0 -0
  25. assets/lang/{inbound-pro-az_IR.mo → landing-pages-az_IR.mo} +0 -0
  26. assets/lang/{inbound-pro-ba.mo → landing-pages-ba.mo} +0 -0
  27. assets/lang/{inbound-pro-bal.mo → landing-pages-bal.mo} +0 -0
  28. assets/lang/{inbound-pro-bar.mo → landing-pages-bar.mo} +0 -0
  29. assets/lang/{inbound-pro-be.mo → landing-pages-be.mo} +0 -0
  30. assets/lang/{inbound-pro-be@tarask.mo → landing-pages-be@tarask.mo} +0 -0
  31. assets/lang/{inbound-pro-be_BY.mo → landing-pages-be_BY.mo} +0 -0
  32. assets/lang/{inbound-pro-bg.mo → landing-pages-bg.mo} +0 -0
  33. assets/lang/{inbound-pro-bg_BG.mo → landing-pages-bg_BG.mo} +0 -0
  34. assets/lang/{inbound-pro-bn.mo → landing-pages-bn.mo} +0 -0
  35. assets/lang/{inbound-pro-bn_BD.mo → landing-pages-bn_BD.mo} +0 -0
  36. assets/lang/{inbound-pro-bn_IN.mo → landing-pages-bn_IN.mo} +0 -0
  37. assets/lang/{inbound-pro-bo.mo → landing-pages-bo.mo} +0 -0
  38. assets/lang/{inbound-pro-bo_CN.mo → landing-pages-bo_CN.mo} +0 -0
  39. assets/lang/{inbound-pro-br.mo → landing-pages-br.mo} +0 -0
  40. assets/lang/{inbound-pro-brx.mo → landing-pages-brx.mo} +0 -0
  41. assets/lang/{inbound-pro-bs.mo → landing-pages-bs.mo} +0 -0
  42. assets/lang/{inbound-pro-bs_BA.mo → landing-pages-bs_BA.mo} +0 -0
  43. assets/lang/{inbound-pro-ca.mo → landing-pages-ca.mo} +0 -0
  44. assets/lang/{inbound-pro-ca@valencia.mo → landing-pages-ca@valencia.mo} +0 -0
  45. assets/lang/{inbound-pro-ca_ES.mo → landing-pages-ca_ES.mo} +0 -0
  46. assets/lang/{inbound-pro-cdo.mo → landing-pages-cdo.mo} +0 -0
  47. assets/lang/{inbound-pro-ceb.mo → landing-pages-ceb.mo} +0 -0
  48. assets/lang/{inbound-pro-cgg.mo → landing-pages-cgg.mo} +0 -0
  49. assets/lang/{inbound-pro-cjy.mo → landing-pages-cjy.mo} +0 -0
  50. assets/lang/{inbound-pro-cmn.mo → landing-pages-cmn.mo} +0 -0
  51. assets/lang/{inbound-pro-co.mo → landing-pages-co.mo} +0 -0
  52. assets/lang/{inbound-pro-cpx.mo → landing-pages-cpx.mo} +0 -0
  53. assets/lang/{inbound-pro-crh.mo → landing-pages-crh.mo} +0 -0
  54. assets/lang/{inbound-pro-cs.mo → landing-pages-cs.mo} +0 -0
  55. assets/lang/{inbound-pro-cs_CZ.mo → landing-pages-cs_CZ.mo} +0 -0
  56. assets/lang/{inbound-pro-cv.mo → landing-pages-cv.mo} +0 -0
  57. assets/lang/{inbound-pro-cy.mo → landing-pages-cy.mo} +0 -0
  58. assets/lang/{inbound-pro-cy_GB.mo → landing-pages-cy_GB.mo} +0 -0
  59. assets/lang/{inbound-pro-czh.mo → landing-pages-czh.mo} +0 -0
  60. assets/lang/{inbound-pro-czo.mo → landing-pages-czo.mo} +0 -0
  61. assets/lang/{inbound-pro-da.mo → landing-pages-da.mo} +0 -0
  62. assets/lang/{inbound-pro-da_DK.mo → landing-pages-da_DK.mo} +0 -0
  63. assets/lang/{inbound-pro-de.mo → landing-pages-de.mo} +0 -0
  64. assets/lang/{inbound-pro-de_AT.mo → landing-pages-de_AT.mo} +0 -0
  65. assets/lang/{inbound-pro-de_CH.mo → landing-pages-de_CH.mo} +0 -0
  66. assets/lang/{inbound-pro-de_DE.mo → landing-pages-de_DE.mo} +0 -0
  67. assets/lang/{inbound-pro-doi.mo → landing-pages-doi.mo} +0 -0
  68. assets/lang/{inbound-pro-dv.mo → landing-pages-dv.mo} +0 -0
  69. assets/lang/{inbound-pro-dz.mo → landing-pages-dz.mo} +0 -0
  70. assets/lang/{inbound-pro-dz_BT.mo → landing-pages-dz_BT.mo} +0 -0
  71. assets/lang/{inbound-pro-el.mo → landing-pages-el.mo} +0 -0
  72. assets/lang/{inbound-pro-el_GR.mo → landing-pages-el_GR.mo} +0 -0
  73. assets/lang/{inbound-pro-en.mo → landing-pages-en.mo} +0 -0
  74. assets/lang/{inbound-pro-en@pirate.mo → landing-pages-en@pirate.mo} +0 -0
  75. assets/lang/{inbound-pro-en_AT.mo → landing-pages-en_AT.mo} +0 -0
  76. assets/lang/{inbound-pro-en_AU.mo → landing-pages-en_AU.mo} +0 -0
  77. assets/lang/{inbound-pro-en_BD.mo → landing-pages-en_BD.mo} +0 -0
  78. assets/lang/{inbound-pro-en_BE.mo → landing-pages-en_BE.mo} +0 -0
  79. assets/lang/{inbound-pro-en_CA.mo → landing-pages-en_CA.mo} +0 -0
  80. assets/lang/{inbound-pro-en_CH.mo → landing-pages-en_CH.mo} +0 -0
  81. assets/lang/{inbound-pro-en_CL.mo → landing-pages-en_CL.mo} +0 -0
  82. assets/lang/{inbound-pro-en_CZ.mo → landing-pages-en_CZ.mo} +0 -0
  83. assets/lang/{inbound-pro-en_DE.mo → landing-pages-en_DE.mo} +0 -0
  84. assets/lang/{inbound-pro-en_EG.mo → landing-pages-en_EG.mo} +0 -0
  85. assets/lang/{inbound-pro-en_ES.mo → landing-pages-en_ES.mo} +0 -0
  86. assets/lang/{inbound-pro-en_FI.mo → landing-pages-en_FI.mo} +0 -0
  87. assets/lang/{inbound-pro-en_GB.mo → landing-pages-en_GB.mo} +0 -0
  88. assets/lang/{inbound-pro-en_GH.mo → landing-pages-en_GH.mo} +0 -0
  89. assets/lang/{inbound-pro-en_GR.mo → landing-pages-en_GR.mo} +0 -0
  90. assets/lang/{inbound-pro-en_HK.mo → landing-pages-en_HK.mo} +0 -0
  91. assets/lang/{inbound-pro-en_HR.mo → landing-pages-en_HR.mo} +0 -0
  92. assets/lang/{inbound-pro-en_HU.mo → landing-pages-en_HU.mo} +0 -0
  93. assets/lang/{inbound-pro-en_IE.mo → landing-pages-en_IE.mo} +0 -0
  94. assets/lang/{inbound-pro-en_IN.mo → landing-pages-en_IN.mo} +0 -0
  95. assets/lang/{inbound-pro-en_IT.mo → landing-pages-en_IT.mo} +0 -0
  96. assets/lang/{inbound-pro-en_LK.mo → landing-pages-en_LK.mo} +0 -0
  97. assets/lang/{inbound-pro-en_NG.mo → landing-pages-en_NG.mo} +0 -0
  98. assets/lang/{inbound-pro-en_NL.mo → landing-pages-en_NL.mo} +0 -0
  99. assets/lang/{inbound-pro-en_NO.mo → landing-pages-en_NO.mo} +0 -0
  100. assets/lang/{inbound-pro-en_NZ.mo → landing-pages-en_NZ.mo} +0 -0
  101. assets/lang/{inbound-pro-en_PK.mo → landing-pages-en_PK.mo} +0 -0
  102. assets/lang/{inbound-pro-en_PL.mo → landing-pages-en_PL.mo} +0 -0
  103. assets/lang/{inbound-pro-en_PT.mo → landing-pages-en_PT.mo} +0 -0
  104. assets/lang/{inbound-pro-en_RO.mo → landing-pages-en_RO.mo} +0 -0
  105. assets/lang/{inbound-pro-en_SE.mo → landing-pages-en_SE.mo} +0 -0
  106. assets/lang/{inbound-pro-en_SK.mo → landing-pages-en_SK.mo} +0 -0
  107. assets/lang/{inbound-pro-en_ZA.mo → landing-pages-en_ZA.mo} +0 -0
  108. assets/lang/{inbound-pro-en_ee.mo → landing-pages-en_ee.mo} +0 -0
  109. assets/lang/{inbound-pro-en_lt.mo → landing-pages-en_lt.mo} +0 -0
  110. assets/lang/{inbound-pro-en_lv.mo → landing-pages-en_lv.mo} +0 -0
  111. assets/lang/{inbound-pro-eo.mo → landing-pages-eo.mo} +0 -0
  112. assets/lang/{inbound-pro-es.mo → landing-pages-es.mo} +0 -0
  113. assets/lang/{inbound-pro-es_419.mo → landing-pages-es_419.mo} +0 -0
  114. assets/lang/{inbound-pro-es_AR.mo → landing-pages-es_AR.mo} +0 -0
  115. assets/lang/{inbound-pro-es_BO.mo → landing-pages-es_BO.mo} +0 -0
  116. assets/lang/{inbound-pro-es_CL.mo → landing-pages-es_CL.mo} +0 -0
  117. assets/lang/{inbound-pro-es_CO.mo → landing-pages-es_CO.mo} +0 -0
  118. assets/lang/{inbound-pro-es_CR.mo → landing-pages-es_CR.mo} +0 -0
  119. assets/lang/{inbound-pro-es_DO.mo → landing-pages-es_DO.mo} +0 -0
  120. assets/lang/{inbound-pro-es_EC.mo → landing-pages-es_EC.mo} +0 -0
  121. assets/lang/{inbound-pro-es_ES.mo → landing-pages-es_ES.mo} +0 -0
  122. assets/lang/{inbound-pro-es_GT.mo → landing-pages-es_GT.mo} +0 -0
  123. assets/lang/{inbound-pro-es_HN.mo → landing-pages-es_HN.mo} +0 -0
  124. assets/lang/{inbound-pro-es_MX.mo → landing-pages-es_MX.mo} +0 -0
  125. assets/lang/{inbound-pro-es_NI.mo → landing-pages-es_NI.mo} +0 -0
  126. assets/lang/{inbound-pro-es_PA.mo → landing-pages-es_PA.mo} +0 -0
  127. assets/lang/{inbound-pro-es_PE.mo → landing-pages-es_PE.mo} +0 -0
  128. assets/lang/{inbound-pro-es_PR.mo → landing-pages-es_PR.mo} +0 -0
  129. assets/lang/{inbound-pro-es_PY.mo → landing-pages-es_PY.mo} +0 -0
  130. assets/lang/{inbound-pro-es_SV.mo → landing-pages-es_SV.mo} +0 -0
  131. assets/lang/{inbound-pro-es_US.mo → landing-pages-es_US.mo} +0 -0
  132. assets/lang/{inbound-pro-es_UY.mo → landing-pages-es_UY.mo} +0 -0
  133. assets/lang/{inbound-pro-es_VE.mo → landing-pages-es_VE.mo} +0 -0
  134. assets/lang/{inbound-pro-et.mo → landing-pages-et.mo} +0 -0
  135. assets/lang/{inbound-pro-et_EE.mo → landing-pages-et_EE.mo} +0 -0
  136. assets/lang/{inbound-pro-eu.mo → landing-pages-eu.mo} +0 -0
  137. assets/lang/{inbound-pro-eu_ES.mo → landing-pages-eu_ES.mo} +0 -0
  138. assets/lang/{inbound-pro-fa.mo → landing-pages-fa.mo} +0 -0
  139. assets/lang/{inbound-pro-fa_AF.mo → landing-pages-fa_AF.mo} +0 -0
  140. assets/lang/{inbound-pro-fa_IR.mo → landing-pages-fa_IR.mo} +0 -0
  141. assets/lang/{inbound-pro-ff.mo → landing-pages-ff.mo} +0 -0
  142. assets/lang/{inbound-pro-ff_SN.mo → landing-pages-ff_SN.mo} +0 -0
  143. assets/lang/{inbound-pro-fi.mo → landing-pages-fi.mo} +0 -0
  144. assets/lang/{inbound-pro-fi_FI.mo → landing-pages-fi_FI.mo} +0 -0
  145. assets/lang/{inbound-pro-fil.mo → landing-pages-fil.mo} +0 -0
  146. assets/lang/{inbound-pro-fo.mo → landing-pages-fo.mo} +0 -0
  147. assets/lang/{inbound-pro-fo_FO.mo → landing-pages-fo_FO.mo} +0 -0
  148. assets/lang/{inbound-pro-fr.mo → landing-pages-fr.mo} +0 -0
  149. assets/lang/{inbound-pro-fr_BE.mo → landing-pages-fr_BE.mo} +0 -0
  150. assets/lang/{inbound-pro-fr_CA.mo → landing-pages-fr_CA.mo} +0 -0
  151. assets/lang/{inbound-pro-fr_CH.mo → landing-pages-fr_CH.mo} +0 -0
  152. assets/lang/{inbound-pro-fr_FR.mo → landing-pages-fr_FR.mo} +0 -0
  153. assets/lang/{inbound-pro-frp.mo → landing-pages-frp.mo} +0 -0
  154. assets/lang/{inbound-pro-fur.mo → landing-pages-fur.mo} +0 -0
  155. assets/lang/{inbound-pro-fy.mo → landing-pages-fy.mo} +0 -0
  156. assets/lang/{inbound-pro-fy_NL.mo → landing-pages-fy_NL.mo} +0 -0
  157. assets/lang/{inbound-pro-ga.mo → landing-pages-ga.mo} +0 -0
  158. assets/lang/{inbound-pro-ga_IE.mo → landing-pages-ga_IE.mo} +0 -0
  159. assets/lang/{inbound-pro-gan.mo → landing-pages-gan.mo} +0 -0
  160. assets/lang/{inbound-pro-gd.mo → landing-pages-gd.mo} +0 -0
  161. assets/lang/{inbound-pro-gl.mo → landing-pages-gl.mo} +0 -0
  162. assets/lang/{inbound-pro-gl_ES.mo → landing-pages-gl_ES.mo} +0 -0
  163. assets/lang/{inbound-pro-gu.mo → landing-pages-gu.mo} +0 -0
  164. assets/lang/{inbound-pro-gu_IN.mo → landing-pages-gu_IN.mo} +0 -0
  165. assets/lang/{inbound-pro-gun.mo → landing-pages-gun.mo} +0 -0
  166. assets/lang/{inbound-pro-ha.mo → landing-pages-ha.mo} +0 -0
  167. assets/lang/{inbound-pro-hak.mo → landing-pages-hak.mo} +0 -0
  168. assets/lang/{inbound-pro-haw.mo → landing-pages-haw.mo} +0 -0
  169. assets/lang/{inbound-pro-he.mo → landing-pages-he.mo} +0 -0
  170. assets/lang/{inbound-pro-he_IL.mo → landing-pages-he_IL.mo} +0 -0
  171. assets/lang/{inbound-pro-hi.mo → landing-pages-hi.mo} +0 -0
  172. assets/lang/{inbound-pro-hi_IN.mo → landing-pages-hi_IN.mo} +0 -0
  173. assets/lang/{inbound-pro-hne.mo → landing-pages-hne.mo} +0 -0
  174. assets/lang/{inbound-pro-hr.mo → landing-pages-hr.mo} +0 -0
  175. assets/lang/{inbound-pro-hr_HR.mo → landing-pages-hr_HR.mo} +0 -0
  176. assets/lang/{inbound-pro-hsb.mo → landing-pages-hsb.mo} +0 -0
  177. assets/lang/{inbound-pro-hsn.mo → landing-pages-hsn.mo} +0 -0
  178. assets/lang/{inbound-pro-ht.mo → landing-pages-ht.mo} +0 -0
  179. assets/lang/{inbound-pro-ht_HT.mo → landing-pages-ht_HT.mo} +0 -0
  180. assets/lang/{inbound-pro-hu.mo → landing-pages-hu.mo} +0 -0
  181. assets/lang/{inbound-pro-hu_HU.mo → landing-pages-hu_HU.mo} +0 -0
  182. assets/lang/{inbound-pro-hu_RO.mo → landing-pages-hu_RO.mo} +0 -0
  183. assets/lang/{inbound-pro-hy.mo → landing-pages-hy.mo} +0 -0
  184. assets/lang/{inbound-pro-hy_AM.mo → landing-pages-hy_AM.mo} +0 -0
  185. assets/lang/{inbound-pro-ia.mo → landing-pages-ia.mo} +0 -0
  186. assets/lang/{inbound-pro-id.mo → landing-pages-id.mo} +0 -0
  187. assets/lang/{inbound-pro-id_ID.mo → landing-pages-id_ID.mo} +0 -0
  188. assets/lang/{inbound-pro-ig.mo → landing-pages-ig.mo} +0 -0
  189. assets/lang/{inbound-pro-ilo.mo → landing-pages-ilo.mo} +0 -0
  190. assets/lang/{inbound-pro-io.mo → landing-pages-io.mo} +0 -0
  191. assets/lang/{inbound-pro-is.mo → landing-pages-is.mo} +0 -0
  192. assets/lang/{inbound-pro-is_IS.mo → landing-pages-is_IS.mo} +0 -0
  193. assets/lang/{inbound-pro-it.mo → landing-pages-it.mo} +0 -0
  194. assets/lang/{inbound-pro-it_CH.mo → landing-pages-it_CH.mo} +0 -0
  195. assets/lang/{inbound-pro-it_IT.mo → landing-pages-it_IT.mo} +0 -0
  196. assets/lang/{inbound-pro-iu.mo → landing-pages-iu.mo} +0 -0
  197. assets/lang/{inbound-pro-ja.mo → landing-pages-ja.mo} +0 -0
  198. assets/lang/{inbound-pro-ja_JP.mo → landing-pages-ja_JP.mo} +0 -0
  199. assets/lang/{inbound-pro-jv.mo → landing-pages-jv.mo} +0 -0
  200. assets/lang/{inbound-pro-ka.mo → landing-pages-ka.mo} +0 -0
  201. assets/lang/{inbound-pro-ka_GE.mo → landing-pages-ka_GE.mo} +0 -0
  202. assets/lang/{inbound-pro-kab.mo → landing-pages-kab.mo} +0 -0
  203. assets/lang/{inbound-pro-kl.mo → landing-pages-kl.mo} +0 -0
  204. assets/lang/{inbound-pro-kn.mo → landing-pages-kn.mo} +0 -0
  205. assets/lang/{inbound-pro-kn_IN.mo → landing-pages-kn_IN.mo} +0 -0
  206. assets/lang/{inbound-pro-ksh.mo → landing-pages-ksh.mo} +0 -0
  207. assets/lang/{inbound-pro-ku.mo → landing-pages-ku.mo} +0 -0
  208. assets/lang/{inbound-pro-kw.mo → landing-pages-kw.mo} +0 -0
  209. assets/lang/{inbound-pro-la.mo → landing-pages-la.mo} +0 -0
  210. assets/lang/{inbound-pro-lg.mo → landing-pages-lg.mo} +0 -0
  211. assets/lang/{inbound-pro-lzh.mo → landing-pages-lzh.mo} +0 -0
  212. assets/lang/{inbound-pro-mh.mo → landing-pages-mh.mo} +0 -0
  213. assets/lang/{inbound-pro-mi.mo → landing-pages-mi.mo} +0 -0
  214. assets/lang/{inbound-pro-mn.mo → landing-pages-mn.mo} +0 -0
  215. assets/lang/{inbound-pro-mn_MN.mo → landing-pages-mn_MN.mo} +0 -0
  216. assets/lang/{inbound-pro-mni.mo → landing-pages-mni.mo} +0 -0
  217. assets/lang/{inbound-pro-mnp.mo → landing-pages-mnp.mo} +0 -0
  218. assets/lang/{inbound-pro-mr.mo → landing-pages-mr.mo} +0 -0
  219. assets/lang/{inbound-pro-mr_IN.mo → landing-pages-mr_IN.mo} +0 -0
  220. assets/lang/{inbound-pro-ms.mo → landing-pages-ms.mo} +0 -0
  221. assets/lang/{inbound-pro-mw1.mo → landing-pages-mw1.mo} +0 -0
  222. assets/lang/{inbound-pro-my.mo → landing-pages-my.mo} +0 -0
  223. assets/lang/{inbound-pro-my_MM.mo → landing-pages-my_MM.mo} +0 -0
  224. assets/lang/{inbound-pro-myv.mo → landing-pages-myv.mo} +0 -0
  225. assets/lang/{inbound-pro-nah.mo → landing-pages-nah.mo} +0 -0
  226. assets/lang/{inbound-pro-nan.mo → landing-pages-nan.mo} +0 -0
  227. assets/lang/{inbound-pro-nap.mo → landing-pages-nap.mo} +0 -0
  228. assets/lang/{inbound-pro-nb.mo → landing-pages-nb.mo} +0 -0
  229. assets/lang/{inbound-pro-nb_NO.mo → landing-pages-nb_NO.mo} +0 -0
  230. assets/lang/{inbound-pro-ne.mo → landing-pages-ne.mo} +0 -0
  231. assets/lang/{inbound-pro-ne_NP.mo → landing-pages-ne_NP.mo} +0 -0
  232. assets/lang/{inbound-pro-nia.mo → landing-pages-nia.mo} +0 -0
  233. assets/lang/{inbound-pro-nl.mo → landing-pages-nl.mo} +0 -0
  234. assets/lang/{inbound-pro-nl_BE.mo → landing-pages-nl_BE.mo} +0 -0
  235. assets/lang/{inbound-pro-nl_NL.mo → landing-pages-nl_NL.mo} +0 -0
  236. assets/lang/{inbound-pro-nn.mo → landing-pages-nn.mo} +0 -0
  237. assets/lang/{inbound-pro-nn_NO.mo → landing-pages-nn_NO.mo} +0 -0
  238. assets/lang/{inbound-pro-no.mo → landing-pages-no.mo} +0 -0
  239. assets/lang/{inbound-pro-no_NO.mo → landing-pages-no_NO.mo} +0 -0
  240. assets/lang/{inbound-pro-nqo.mo → landing-pages-nqo.mo} +0 -0
  241. assets/lang/{inbound-pro-nr.mo → landing-pages-nr.mo} +0 -0
  242. assets/lang/{inbound-pro-nso.mo → landing-pages-nso.mo} +0 -0
  243. assets/lang/{inbound-pro-nv.mo → landing-pages-nv.mo} +0 -0
  244. assets/lang/{inbound-pro-ny.mo → landing-pages-ny.mo} +0 -0
  245. assets/lang/{inbound-pro-oc.mo → landing-pages-oc.mo} +0 -0
  246. assets/lang/{inbound-pro-om.mo → landing-pages-om.mo} +0 -0
  247. assets/lang/{inbound-pro-or.mo → landing-pages-or.mo} +0 -0
  248. assets/lang/{inbound-pro-or_IN.mo → landing-pages-or_IN.mo} +0 -0
  249. assets/lang/{inbound-pro-os.mo → landing-pages-os.mo} +0 -0
  250. assets/lang/{inbound-pro-pa.mo → landing-pages-pa.mo} +0 -0
  251. assets/lang/{inbound-pro-pa_IN.mo → landing-pages-pa_IN.mo} +0 -0
  252. assets/lang/{inbound-pro-pam.mo → landing-pages-pam.mo} +0 -0
  253. assets/lang/{inbound-pro-pap.mo → landing-pages-pap.mo} +0 -0
  254. assets/lang/{inbound-pro-pfl.mo → landing-pages-pfl.mo} +0 -0
  255. assets/lang/{inbound-pro-pl.mo → landing-pages-pl.mo} +0 -0
  256. assets/lang/{inbound-pro-pl_PL.mo → landing-pages-pl_PL.mo} +0 -0
  257. assets/lang/{inbound-pro-pms.mo → landing-pages-pms.mo} +0 -0
  258. assets/lang/{inbound-pro-ps.mo → landing-pages-ps.mo} +0 -0
  259. assets/lang/{inbound-pro-pt.mo → landing-pages-pt.mo} +0 -0
  260. assets/lang/{inbound-pro-pt_BR.mo → landing-pages-pt_BR.mo} +0 -0
  261. assets/lang/{inbound-pro-pt_PT.mo → landing-pages-pt_PT.mo} +0 -0
  262. assets/lang/{inbound-pro-rm.mo → landing-pages-rm.mo} +0 -0
  263. assets/lang/{inbound-pro-ro.mo → landing-pages-ro.mo} +0 -0
  264. assets/lang/{inbound-pro-ro_RO.mo → landing-pages-ro_RO.mo} +0 -0
  265. assets/lang/{inbound-pro-ru.mo → landing-pages-ru.mo} +0 -0
  266. assets/lang/{inbound-pro-ru@petr1708.mo → landing-pages-ru@petr1708.mo} +0 -0
  267. assets/lang/{inbound-pro-ru_RU.mo → landing-pages-ru_RU.mo} +0 -0
  268. assets/lang/{inbound-pro-ru_ee.mo → landing-pages-ru_ee.mo} +0 -0
  269. assets/lang/{inbound-pro-ru_lt.mo → landing-pages-ru_lt.mo} +0 -0
  270. assets/lang/{inbound-pro-ru_lv.mo → landing-pages-ru_lv.mo} +0 -0
  271. assets/lang/{inbound-pro-sa.mo → landing-pages-sa.mo} +0 -0
  272. assets/lang/{inbound-pro-sah.mo → landing-pages-sah.mo} +0 -0
  273. assets/lang/{inbound-pro-sat.mo → landing-pages-sat.mo} +0 -0
  274. assets/lang/{inbound-pro-sc.mo → landing-pages-sc.mo} +0 -0
  275. assets/lang/{inbound-pro-scn.mo → landing-pages-scn.mo} +0 -0
  276. assets/lang/{inbound-pro-sco.mo → landing-pages-sco.mo} +0 -0
  277. assets/lang/{inbound-pro-sd.mo → landing-pages-sd.mo} +0 -0
  278. assets/lang/{inbound-pro-se.mo → landing-pages-se.mo} +0 -0
  279. assets/lang/{inbound-pro-sg.mo → landing-pages-sg.mo} +0 -0
  280. assets/lang/{inbound-pro-si.mo → landing-pages-si.mo} +0 -0
  281. assets/lang/{inbound-pro-si_LK.mo → landing-pages-si_LK.mo} +0 -0
  282. assets/lang/{inbound-pro-sk.mo → landing-pages-sk.mo} +0 -0
  283. assets/lang/{inbound-pro-sk_SK.mo → landing-pages-sk_SK.mo} +0 -0
  284. assets/lang/{inbound-pro-sl.mo → landing-pages-sl.mo} +0 -0
  285. assets/lang/{inbound-pro-sl_SI.mo → landing-pages-sl_SI.mo} +0 -0
  286. assets/lang/{inbound-pro-sm.mo → landing-pages-sm.mo} +0 -0
  287. assets/lang/{inbound-pro-sma.mo → landing-pages-sma.mo} +0 -0
  288. assets/lang/{inbound-pro-sn.mo → landing-pages-sn.mo} +0 -0
  289. assets/lang/{inbound-pro-so.mo → landing-pages-so.mo} +0 -0
  290. assets/lang/{inbound-pro-son.mo → landing-pages-son.mo} +0 -0
  291. assets/lang/{inbound-pro-sq.mo → landing-pages-sq.mo} +0 -0
  292. assets/lang/{inbound-pro-sq_AL.mo → landing-pages-sq_AL.mo} +0 -0
  293. assets/lang/{inbound-pro-sr.mo → landing-pages-sr.mo} +0 -0
  294. assets/lang/{inbound-pro-sr@Ijekavian.mo → landing-pages-sr@Ijekavian.mo} +0 -0
  295. assets/lang/{inbound-pro-sr@ijekavianlatin.mo → landing-pages-sr@ijekavianlatin.mo} +0 -0
  296. assets/lang/{inbound-pro-sr@latin.mo → landing-pages-sr@latin.mo} +0 -0
  297. assets/lang/{inbound-pro-sr_RS.mo → landing-pages-sr_RS.mo} +0 -0
  298. assets/lang/{inbound-pro-sr_RS@latin.mo → landing-pages-sr_RS@latin.mo} +0 -0
  299. assets/lang/{inbound-pro-ss.mo → landing-pages-ss.mo} +0 -0
  300. assets/lang/{inbound-pro-st.mo → landing-pages-st.mo} +0 -0
  301. assets/lang/{inbound-pro-st_ZA.mo → landing-pages-st_ZA.mo} +0 -0
  302. assets/lang/{inbound-pro-su.mo → landing-pages-su.mo} +0 -0
  303. assets/lang/{inbound-pro-sv.mo → landing-pages-sv.mo} +0 -0
  304. assets/lang/{inbound-pro-sv_FI.mo → landing-pages-sv_FI.mo} +0 -0
  305. assets/lang/{inbound-pro-sv_SE.mo → landing-pages-sv_SE.mo} +0 -0
  306. assets/lang/{inbound-pro-sw.mo → landing-pages-sw.mo} +0 -0
  307. assets/lang/{inbound-pro-sw_CD.mo → landing-pages-sw_CD.mo} +0 -0
  308. assets/lang/{inbound-pro-sw_KE.mo → landing-pages-sw_KE.mo} +0 -0
  309. assets/lang/{inbound-pro-szl.mo → landing-pages-szl.mo} +0 -0
  310. assets/lang/{inbound-pro-ta.mo → landing-pages-ta.mo} +0 -0
  311. assets/lang/{inbound-pro-ta_IN.mo → landing-pages-ta_IN.mo} +0 -0
  312. assets/lang/{inbound-pro-ta_LK.mo → landing-pages-ta_LK.mo} +0 -0
  313. assets/lang/{inbound-pro-te.mo → landing-pages-te.mo} +0 -0
  314. assets/lang/{inbound-pro-te_IN.mo → landing-pages-te_IN.mo} +0 -0
  315. assets/lang/{inbound-pro-tet.mo → landing-pages-tet.mo} +0 -0
  316. assets/lang/{inbound-pro-tg.mo → landing-pages-tg.mo} +0 -0
  317. assets/lang/{inbound-pro-tg_TJ.mo → landing-pages-tg_TJ.mo} +0 -0
  318. assets/lang/{inbound-pro-th.mo → landing-pages-th.mo} +0 -0
  319. assets/lang/{inbound-pro-th_TH.mo → landing-pages-th_TH.mo} +0 -0
  320. assets/lang/{inbound-pro-ti.mo → landing-pages-ti.mo} +0 -0
  321. assets/lang/{inbound-pro-tk.mo → landing-pages-tk.mo} +0 -0
  322. assets/lang/{inbound-pro-tk_TM.mo → landing-pages-tk_TM.mo} +0 -0
  323. assets/lang/{inbound-pro-tl.mo → landing-pages-tl.mo} +0 -0
  324. assets/lang/{inbound-pro-tl_PH.mo → landing-pages-tl_PH.mo} +0 -0
  325. assets/lang/{inbound-pro-tn.mo → landing-pages-tn.mo} +0 -0
  326. assets/lang/{inbound-pro-to.mo → landing-pages-to.mo} +0 -0
  327. assets/lang/{inbound-pro-tr.mo → landing-pages-tr.mo} +0 -0
  328. assets/lang/{inbound-pro-tr_TR.mo → landing-pages-tr_TR.mo} +0 -0
  329. assets/lang/{inbound-pro-ts.mo → landing-pages-ts.mo} +0 -0
  330. assets/lang/{inbound-pro-tt.mo → landing-pages-tt.mo} +0 -0
  331. assets/lang/{inbound-pro-tzl.mo → landing-pages-tzl.mo} +0 -0
  332. assets/lang/{inbound-pro-tzm.mo → landing-pages-tzm.mo} +0 -0
  333. assets/lang/{inbound-pro-udm.mo → landing-pages-udm.mo} +0 -0
  334. assets/lang/{inbound-pro-ug.mo → landing-pages-ug.mo} +0 -0
  335. assets/lang/{inbound-pro-ug@Arab.mo → landing-pages-ug@Arab.mo} +0 -0
  336. assets/lang/{inbound-pro-ug@Cyrl.mo → landing-pages-ug@Cyrl.mo} +0 -0
  337. assets/lang/{inbound-pro-ug@Latin.mo → landing-pages-ug@Latin.mo} +0 -0
  338. assets/lang/{inbound-pro-uk.mo → landing-pages-uk.mo} +0 -0
  339. assets/lang/{inbound-pro-uk_UA.mo → landing-pages-uk_UA.mo} +0 -0
  340. assets/lang/{inbound-pro-ur.mo → landing-pages-ur.mo} +0 -0
  341. assets/lang/{inbound-pro-ur_PK.mo → landing-pages-ur_PK.mo} +0 -0
  342. assets/lang/{inbound-pro-uz.mo → landing-pages-uz.mo} +0 -0
  343. assets/lang/{inbound-pro-uz@Arab.mo → landing-pages-uz@Arab.mo} +0 -0
  344. assets/lang/{inbound-pro-uz@Cyrl.mo → landing-pages-uz@Cyrl.mo} +0 -0
  345. assets/lang/{inbound-pro-uz@Latn.mo → landing-pages-uz@Latn.mo} +0 -0
  346. assets/lang/{inbound-pro-uz_UZ.mo → landing-pages-uz_UZ.mo} +0 -0
  347. assets/lang/{inbound-pro-ve.mo → landing-pages-ve.mo} +0 -0
  348. assets/lang/{inbound-pro-vec.mo → landing-pages-vec.mo} +0 -0
  349. assets/lang/{inbound-pro-vi.mo → landing-pages-vi.mo} +0 -0
  350. assets/lang/{inbound-pro-vi_VN.mo → landing-pages-vi_VN.mo} +0 -0
  351. assets/lang/{inbound-pro-vls.mo → landing-pages-vls.mo} +0 -0
  352. assets/lang/{inbound-pro-vmf.mo → landing-pages-vmf.mo} +0 -0
  353. assets/lang/{inbound-pro-wa.mo → landing-pages-wa.mo} +0 -0
  354. assets/lang/{inbound-pro-war.mo → landing-pages-war.mo} +0 -0
  355. assets/lang/{inbound-pro-wo.mo → landing-pages-wo.mo} +0 -0
  356. assets/lang/{inbound-pro-wo_SN.mo → landing-pages-wo_SN.mo} +0 -0
  357. assets/lang/{inbound-pro-wuu.mo → landing-pages-wuu.mo} +0 -0
  358. assets/lang/{inbound-pro-xh.mo → landing-pages-xh.mo} +0 -0
  359. assets/lang/{inbound-pro-yi.mo → landing-pages-yi.mo} +0 -0
  360. assets/lang/{inbound-pro-yo.mo → landing-pages-yo.mo} +0 -0
  361. assets/lang/{inbound-pro-yue.mo → landing-pages-yue.mo} +0 -0
  362. assets/lang/{inbound-pro-zh-Hans.mo → landing-pages-zh-Hans.mo} +0 -0
  363. assets/lang/{inbound-pro-zh-Hant.mo → landing-pages-zh-Hant.mo} +0 -0
  364. assets/lang/{inbound-pro-zh.mo → landing-pages-zh.mo} +0 -0
  365. assets/lang/{inbound-pro-zh_CN.GB2312.mo → landing-pages-zh_CN.GB2312.mo} +0 -0
  366. assets/lang/{inbound-pro-zh_CN.mo → landing-pages-zh_CN.mo} +0 -0
  367. assets/lang/{inbound-pro-zh_HK.mo → landing-pages-zh_HK.mo} +0 -0
  368. assets/lang/{inbound-pro-zh_TW.Big5.mo → landing-pages-zh_TW.Big5.mo} +0 -0
  369. assets/lang/{inbound-pro-zh_TW.mo → landing-pages-zh_TW.mo} +0 -0
  370. assets/lang/{inbound-pro-zu.mo → landing-pages-zu.mo} +0 -0
  371. assets/lang/{inbound-pro-zu_ZA.mo → landing-pages-zu_ZA.mo} +0 -0
  372. landing-pages.php +3 -2
  373. readme.txt +7 -1
  374. shared/assets/js/frontend/analytics-src/analytics.page.js +5 -3
  375. shared/assets/js/frontend/analytics/inboundAnalytics.js +146 -144
  376. shared/assets/js/frontend/analytics/inboundAnalytics.min.js +2 -2
  377. shared/assets/plugins/advanced-custom-fields-font-awesome/acf-font-awesome-v4.php +8 -8
  378. shared/assets/plugins/advanced-custom-fields-font-awesome/acf-font-awesome-v5.php +4 -4
  379. shared/classes/class.ajax.php +9 -10
  380. shared/classes/class.confirm-double-optin.php +9 -0
  381. shared/classes/class.database-routines.php +8 -2
  382. shared/classes/class.events.php +60 -1
  383. shared/shortcodes/js/shortcodes.js +863 -886
  384. trunk/README.md +53 -0
  385. trunk/assets/css/admin-ab-testing.css +311 -0
  386. trunk/assets/css/admin-post-edit.css +212 -0
  387. trunk/assets/css/admin-post-new.css +110 -0
  388. trunk/assets/css/admin-templates.css +48 -0
  389. trunk/assets/css/admin-tour.css +216 -0
  390. trunk/assets/css/admin/acf-hide-wp-elements.css +1 -0
  391. trunk/assets/css/admin/content-stats.css +87 -0
  392. trunk/assets/css/admin/customizer-edit.css +247 -0
  393. trunk/assets/css/admin/edit-landing-page.css +167 -0
  394. trunk/assets/css/admin/global-settings.css +231 -0
  395. trunk/assets/css/admin/install-plugins.css +13 -0
  396. trunk/assets/css/admin/landing-page-edit-style.css +542 -0
  397. trunk/assets/css/admin/landing-page-list.css +492 -0
  398. trunk/assets/css/customizer-load.css +76 -0
  399. trunk/assets/css/customizer.frontend.css +157 -0
  400. trunk/assets/css/customizer.media-uploader.css +34 -0
  401. trunk/assets/css/frontend/customizer-preview.css +1 -0
  402. trunk/assets/css/frontend/global-landing-page-style.css +43 -0
  403. trunk/assets/css/frontend/index.php +2 -0
  404. trunk/assets/css/iframe-preview.css +3 -0
  405. trunk/assets/css/images/dropdownback.png +0 -0
  406. trunk/assets/css/images/headerback.png +0 -0
  407. trunk/assets/css/images/hover.png +0 -0
  408. trunk/assets/css/images/index.php +2 -0
  409. trunk/assets/css/images/linkback.png +0 -0
  410. trunk/assets/css/images/question-light.png +0 -0
  411. trunk/assets/css/images/tooltip.png +0 -0
  412. trunk/assets/css/index.php +2 -0
  413. trunk/assets/images/ab-retina-icons.png +0 -0
  414. trunk/assets/images/add-on-image.png +0 -0
  415. trunk/assets/images/cta-install.png +0 -0
  416. trunk/assets/images/custom-setup-image.png +0 -0
  417. trunk/assets/images/get-custom-setup.png +0 -0
  418. trunk/assets/images/get-wordpress-templates.png +0 -0
  419. trunk/assets/images/github-help.jpg +0 -0
  420. trunk/assets/images/image.php +76 -0
  421. trunk/assets/images/index.php +2 -0
  422. trunk/assets/images/leads-install.png +0 -0
  423. trunk/assets/images/localhost.png +0 -0
  424. trunk/assets/images/templates-image.png +0 -0
  425. trunk/assets/images/variation-normal.png +0 -0
  426. trunk/assets/images/variation-up.png +0 -0
  427. trunk/assets/js/admin/admin.global-settings.js +73 -0
  428. trunk/assets/js/admin/admin.install-plugins.js +30 -0
  429. trunk/assets/js/admin/admin.landing-page-list.js +117 -0
  430. trunk/assets/js/admin/admin.metaboxes.js +1 -0
  431. trunk/assets/js/admin/admin.post-edit-ab-testing.js +64 -0
  432. trunk/assets/js/admin/admin.post-edit.js +308 -0
  433. trunk/assets/js/admin/admin.post-new.js +144 -0
  434. trunk/assets/js/admin/admin.post.js +35 -0
  435. trunk/assets/js/admin/admin.templates-upload.js +25 -0
  436. trunk/assets/js/admin/admin.templates.js +1 -0
  437. trunk/assets/js/admin/index.php +2 -0
  438. trunk/assets/js/admin/intro.js +758 -0
  439. trunk/assets/js/admin/tour/tour.post-edit.js +9 -0
  440. trunk/assets/js/admin/tour/tour.post-list.js +8 -0
  441. trunk/assets/js/ajax.clearstats.js +1 -0
  442. trunk/assets/js/index.php +2 -0
  443. trunk/assets/js/jquery.bindfirst.js +15 -0
  444. trunk/assets/js/jquery.cookie.js +1 -0
  445. trunk/assets/js/jquery.easing.min.js +44 -0
  446. trunk/assets/js/jquery.form-population.js +1 -0
  447. trunk/assets/js/jquery.lp.cookie.js +1 -0
  448. trunk/assets/js/jquery.tablesorter.js +1031 -0
  449. trunk/assets/js/jquery.total-storage.min.js +22 -0
  450. trunk/assets/js/stop_page_stats.js +7 -0
  451. trunk/assets/js/wordpress/editor.min.js +1 -0
  452. trunk/assets/js/wordpress/index.php +2 -0
  453. trunk/assets/lang/landing-pages-ach.mo +0 -0
  454. trunk/assets/lang/landing-pages-ady.mo +0 -0
  455. trunk/assets/lang/landing-pages-af.mo +0 -0
  456. trunk/assets/lang/landing-pages-af_ZA.mo +0 -0
  457. trunk/assets/lang/landing-pages-ak.mo +0 -0
  458. trunk/assets/lang/landing-pages-aln.mo +0 -0
  459. trunk/assets/lang/landing-pages-am.mo +0 -0
  460. trunk/assets/lang/landing-pages-am_ET.mo +0 -0
  461. trunk/assets/lang/landing-pages-an.mo +0 -0
  462. trunk/assets/lang/landing-pages-ar.mo +0 -0
  463. trunk/assets/lang/landing-pages-ar_AA.mo +0 -0
  464. trunk/assets/lang/landing-pages-ar_EG.mo +0 -0
  465. trunk/assets/lang/landing-pages-ar_SA.mo +0 -0
  466. trunk/assets/lang/landing-pages-ar_SD.mo +0 -0
  467. trunk/assets/lang/landing-pages-ar_SY.mo +0 -0
  468. trunk/assets/lang/landing-pages-arn.mo +0 -0
  469. trunk/assets/lang/landing-pages-as.mo +0 -0
  470. trunk/assets/lang/landing-pages-as_IN.mo +0 -0
  471. trunk/assets/lang/landing-pages-ast.mo +0 -0
  472. trunk/assets/lang/landing-pages-ast_ES.mo +0 -0
  473. trunk/assets/lang/landing-pages-az.mo +0 -0
  474. trunk/assets/lang/landing-pages-az@Arab.mo +0 -0
  475. trunk/assets/lang/landing-pages-az@latin.mo +0 -0
  476. trunk/assets/lang/landing-pages-az_AZ.mo +0 -0
  477. trunk/assets/lang/landing-pages-az_IR.mo +0 -0
  478. trunk/assets/lang/landing-pages-ba.mo +0 -0
  479. trunk/assets/lang/landing-pages-bal.mo +0 -0
  480. trunk/assets/lang/landing-pages-bar.mo +0 -0
  481. trunk/assets/lang/landing-pages-be.mo +0 -0
  482. trunk/assets/lang/landing-pages-be@tarask.mo +0 -0
  483. trunk/assets/lang/landing-pages-be_BY.mo +0 -0
  484. trunk/assets/lang/landing-pages-bg.mo +0 -0
  485. trunk/assets/lang/landing-pages-bg_BG.mo +0 -0
  486. trunk/assets/lang/landing-pages-bn.mo +0 -0
  487. trunk/assets/lang/landing-pages-bn_BD.mo +0 -0
  488. trunk/assets/lang/landing-pages-bn_IN.mo +0 -0
  489. trunk/assets/lang/landing-pages-bo.mo +0 -0
  490. trunk/assets/lang/landing-pages-bo_CN.mo +0 -0
  491. trunk/assets/lang/landing-pages-br.mo +0 -0
  492. trunk/assets/lang/landing-pages-brx.mo +0 -0
  493. trunk/assets/lang/landing-pages-bs.mo +0 -0
  494. trunk/assets/lang/landing-pages-bs_BA.mo +0 -0
  495. trunk/assets/lang/landing-pages-ca.mo +0 -0
  496. trunk/assets/lang/landing-pages-ca@valencia.mo +0 -0
  497. trunk/assets/lang/landing-pages-ca_ES.mo +0 -0
  498. trunk/assets/lang/landing-pages-cdo.mo +0 -0
  499. trunk/assets/lang/landing-pages-ceb.mo +0 -0
  500. trunk/assets/lang/landing-pages-cgg.mo +0 -0
  501. trunk/assets/lang/landing-pages-cjy.mo +0 -0
  502. trunk/assets/lang/landing-pages-cmn.mo +0 -0
  503. trunk/assets/lang/landing-pages-co.mo +0 -0
  504. trunk/assets/lang/landing-pages-cpx.mo +0 -0
  505. trunk/assets/lang/landing-pages-crh.mo +0 -0
  506. trunk/assets/lang/landing-pages-cs.mo +0 -0
  507. trunk/assets/lang/landing-pages-cs_CZ.mo +0 -0
  508. trunk/assets/lang/landing-pages-cv.mo +0 -0
  509. trunk/assets/lang/landing-pages-cy.mo +0 -0
  510. trunk/assets/lang/landing-pages-cy_GB.mo +0 -0
  511. trunk/assets/lang/landing-pages-czh.mo +0 -0
  512. trunk/assets/lang/landing-pages-czo.mo +0 -0
  513. trunk/assets/lang/landing-pages-da.mo +0 -0
  514. trunk/assets/lang/landing-pages-da_DK.mo +0 -0
  515. trunk/assets/lang/landing-pages-de.mo +0 -0
  516. trunk/assets/lang/landing-pages-de_AT.mo +0 -0
  517. trunk/assets/lang/landing-pages-de_CH.mo +0 -0
  518. trunk/assets/lang/landing-pages-de_DE.mo +0 -0
  519. trunk/assets/lang/landing-pages-doi.mo +0 -0
  520. trunk/assets/lang/landing-pages-dv.mo +0 -0
  521. trunk/assets/lang/landing-pages-dz.mo +0 -0
  522. trunk/assets/lang/landing-pages-dz_BT.mo +0 -0
  523. trunk/assets/lang/landing-pages-el.mo +0 -0
  524. trunk/assets/lang/landing-pages-el_GR.mo +0 -0
  525. trunk/assets/lang/landing-pages-en.mo +0 -0
  526. trunk/assets/lang/landing-pages-en@pirate.mo +0 -0
  527. trunk/assets/lang/landing-pages-en_AT.mo +0 -0
  528. trunk/assets/lang/landing-pages-en_AU.mo +0 -0
  529. trunk/assets/lang/landing-pages-en_BD.mo +0 -0
  530. trunk/assets/lang/landing-pages-en_BE.mo +0 -0
  531. trunk/assets/lang/landing-pages-en_CA.mo +0 -0
  532. trunk/assets/lang/landing-pages-en_CH.mo +0 -0
  533. trunk/assets/lang/landing-pages-en_CL.mo +0 -0
  534. trunk/assets/lang/landing-pages-en_CZ.mo +0 -0
  535. trunk/assets/lang/landing-pages-en_DE.mo +0 -0
  536. trunk/assets/lang/landing-pages-en_EG.mo +0 -0
  537. trunk/assets/lang/landing-pages-en_ES.mo +0 -0
  538. trunk/assets/lang/landing-pages-en_FI.mo +0 -0
  539. trunk/assets/lang/landing-pages-en_GB.mo +0 -0
  540. trunk/assets/lang/landing-pages-en_GH.mo +0 -0
  541. trunk/assets/lang/landing-pages-en_GR.mo +0 -0
  542. trunk/assets/lang/landing-pages-en_HK.mo +0 -0
  543. trunk/assets/lang/landing-pages-en_HR.mo +0 -0
  544. trunk/assets/lang/landing-pages-en_HU.mo +0 -0
  545. trunk/assets/lang/landing-pages-en_IE.mo +0 -0
  546. trunk/assets/lang/landing-pages-en_IN.mo +0 -0
  547. trunk/assets/lang/landing-pages-en_IT.mo +0 -0
  548. trunk/assets/lang/landing-pages-en_LK.mo +0 -0
  549. trunk/assets/lang/landing-pages-en_NG.mo +0 -0
  550. trunk/assets/lang/landing-pages-en_NL.mo +0 -0
  551. trunk/assets/lang/landing-pages-en_NO.mo +0 -0
  552. trunk/assets/lang/landing-pages-en_NZ.mo +0 -0
  553. trunk/assets/lang/landing-pages-en_PK.mo +0 -0
  554. trunk/assets/lang/landing-pages-en_PL.mo +0 -0
  555. trunk/assets/lang/landing-pages-en_PT.mo +0 -0
  556. trunk/assets/lang/landing-pages-en_RO.mo +0 -0
  557. trunk/assets/lang/landing-pages-en_SE.mo +0 -0
  558. trunk/assets/lang/landing-pages-en_SK.mo +0 -0
  559. trunk/assets/lang/landing-pages-en_ZA.mo +0 -0
  560. trunk/assets/lang/landing-pages-en_ee.mo +0 -0
  561. trunk/assets/lang/landing-pages-en_lt.mo +0 -0
  562. trunk/assets/lang/landing-pages-en_lv.mo +0 -0
  563. trunk/assets/lang/landing-pages-eo.mo +0 -0
  564. trunk/assets/lang/landing-pages-es.mo +0 -0
  565. trunk/assets/lang/landing-pages-es_419.mo +0 -0
  566. trunk/assets/lang/landing-pages-es_AR.mo +0 -0
  567. trunk/assets/lang/landing-pages-es_BO.mo +0 -0
  568. trunk/assets/lang/landing-pages-es_CL.mo +0 -0
  569. trunk/assets/lang/landing-pages-es_CO.mo +0 -0
  570. trunk/assets/lang/landing-pages-es_CR.mo +0 -0
  571. trunk/assets/lang/landing-pages-es_DO.mo +0 -0
  572. trunk/assets/lang/landing-pages-es_EC.mo +0 -0
  573. trunk/assets/lang/landing-pages-es_ES.mo +0 -0
  574. trunk/assets/lang/landing-pages-es_GT.mo +0 -0
  575. trunk/assets/lang/landing-pages-es_HN.mo +0 -0
  576. trunk/assets/lang/landing-pages-es_MX.mo +0 -0
  577. trunk/assets/lang/landing-pages-es_NI.mo +0 -0
  578. trunk/assets/lang/landing-pages-es_PA.mo +0 -0
  579. trunk/assets/lang/landing-pages-es_PE.mo +0 -0
  580. trunk/assets/lang/landing-pages-es_PR.mo +0 -0
  581. trunk/assets/lang/landing-pages-es_PY.mo +0 -0
  582. trunk/assets/lang/landing-pages-es_SV.mo +0 -0
  583. trunk/assets/lang/landing-pages-es_US.mo +0 -0
  584. trunk/assets/lang/landing-pages-es_UY.mo +0 -0
  585. trunk/assets/lang/landing-pages-es_VE.mo +0 -0
  586. trunk/assets/lang/landing-pages-et.mo +0 -0
  587. trunk/assets/lang/landing-pages-et_EE.mo +0 -0
  588. trunk/assets/lang/landing-pages-eu.mo +0 -0
  589. trunk/assets/lang/landing-pages-eu_ES.mo +0 -0
  590. trunk/assets/lang/landing-pages-fa.mo +0 -0
  591. trunk/assets/lang/landing-pages-fa_AF.mo +0 -0
  592. trunk/assets/lang/landing-pages-fa_IR.mo +0 -0
  593. trunk/assets/lang/landing-pages-ff.mo +0 -0
  594. trunk/assets/lang/landing-pages-ff_SN.mo +0 -0
  595. trunk/assets/lang/landing-pages-fi.mo +0 -0
  596. trunk/assets/lang/landing-pages-fi_FI.mo +0 -0
  597. trunk/assets/lang/landing-pages-fil.mo +0 -0
  598. trunk/assets/lang/landing-pages-fo.mo +0 -0
  599. trunk/assets/lang/landing-pages-fo_FO.mo +0 -0
  600. trunk/assets/lang/landing-pages-fr.mo +0 -0
  601. trunk/assets/lang/landing-pages-fr_BE.mo +0 -0
  602. trunk/assets/lang/landing-pages-fr_CA.mo +0 -0
  603. trunk/assets/lang/landing-pages-fr_CH.mo +0 -0
  604. trunk/assets/lang/landing-pages-fr_FR.mo +0 -0
  605. trunk/assets/lang/landing-pages-frp.mo +0 -0
  606. trunk/assets/lang/landing-pages-fur.mo +0 -0
  607. trunk/assets/lang/landing-pages-fy.mo +0 -0
  608. trunk/assets/lang/landing-pages-fy_NL.mo +0 -0
  609. trunk/assets/lang/landing-pages-ga.mo +0 -0
  610. trunk/assets/lang/landing-pages-ga_IE.mo +0 -0
  611. trunk/assets/lang/landing-pages-gan.mo +0 -0
  612. trunk/assets/lang/landing-pages-gd.mo +0 -0
  613. trunk/assets/lang/landing-pages-gl.mo +0 -0
  614. trunk/assets/lang/landing-pages-gl_ES.mo +0 -0
  615. trunk/assets/lang/landing-pages-gu.mo +0 -0
  616. trunk/assets/lang/landing-pages-gu_IN.mo +0 -0
  617. trunk/assets/lang/landing-pages-gun.mo +0 -0
  618. trunk/assets/lang/landing-pages-ha.mo +0 -0
  619. trunk/assets/lang/landing-pages-hak.mo +0 -0
  620. trunk/assets/lang/landing-pages-haw.mo +0 -0
  621. trunk/assets/lang/landing-pages-he.mo +0 -0
  622. trunk/assets/lang/landing-pages-he_IL.mo +0 -0
  623. trunk/assets/lang/landing-pages-hi.mo +0 -0
  624. trunk/assets/lang/landing-pages-hi_IN.mo +0 -0
  625. trunk/assets/lang/landing-pages-hne.mo +0 -0
  626. trunk/assets/lang/landing-pages-hr.mo +0 -0
  627. trunk/assets/lang/landing-pages-hr_HR.mo +0 -0
  628. trunk/assets/lang/landing-pages-hsb.mo +0 -0
  629. trunk/assets/lang/landing-pages-hsn.mo +0 -0
  630. trunk/assets/lang/landing-pages-ht.mo +0 -0
  631. trunk/assets/lang/landing-pages-ht_HT.mo +0 -0
  632. trunk/assets/lang/landing-pages-hu.mo +0 -0
  633. trunk/assets/lang/landing-pages-hu_HU.mo +0 -0
  634. trunk/assets/lang/landing-pages-hu_RO.mo +0 -0
  635. trunk/assets/lang/landing-pages-hy.mo +0 -0
  636. trunk/assets/lang/landing-pages-hy_AM.mo +0 -0
  637. trunk/assets/lang/landing-pages-ia.mo +0 -0
  638. trunk/assets/lang/landing-pages-id.mo +0 -0
  639. trunk/assets/lang/landing-pages-id_ID.mo +0 -0
  640. trunk/assets/lang/landing-pages-ig.mo +0 -0
  641. trunk/assets/lang/landing-pages-ilo.mo +0 -0
  642. trunk/assets/lang/landing-pages-io.mo +0 -0
  643. trunk/assets/lang/landing-pages-is.mo +0 -0
  644. trunk/assets/lang/landing-pages-is_IS.mo +0 -0
  645. trunk/assets/lang/landing-pages-it.mo +0 -0
  646. trunk/assets/lang/landing-pages-it_CH.mo +0 -0
  647. trunk/assets/lang/landing-pages-it_IT.mo +0 -0
  648. trunk/assets/lang/landing-pages-iu.mo +0 -0
  649. trunk/assets/lang/landing-pages-ja.mo +0 -0
  650. trunk/assets/lang/landing-pages-ja_JP.mo +0 -0
  651. trunk/assets/lang/landing-pages-jv.mo +0 -0
  652. trunk/assets/lang/landing-pages-ka.mo +0 -0
  653. trunk/assets/lang/landing-pages-ka_GE.mo +0 -0
  654. trunk/assets/lang/landing-pages-kab.mo +0 -0
  655. trunk/assets/lang/landing-pages-kl.mo +0 -0
  656. trunk/assets/lang/landing-pages-kn.mo +0 -0
  657. trunk/assets/lang/landing-pages-kn_IN.mo +0 -0
  658. trunk/assets/lang/landing-pages-ksh.mo +0 -0
  659. trunk/assets/lang/landing-pages-ku.mo +0 -0
  660. trunk/assets/lang/landing-pages-kw.mo +0 -0
  661. trunk/assets/lang/landing-pages-la.mo +0 -0
  662. trunk/assets/lang/landing-pages-lg.mo +0 -0
  663. trunk/assets/lang/landing-pages-lzh.mo +0 -0
  664. trunk/assets/lang/landing-pages-mh.mo +0 -0
  665. trunk/assets/lang/landing-pages-mi.mo +0 -0
  666. trunk/assets/lang/landing-pages-mn.mo +0 -0
  667. trunk/assets/lang/landing-pages-mn_MN.mo +0 -0
  668. trunk/assets/lang/landing-pages-mni.mo +0 -0
  669. trunk/assets/lang/landing-pages-mnp.mo +0 -0
  670. trunk/assets/lang/landing-pages-mr.mo +0 -0
  671. trunk/assets/lang/landing-pages-mr_IN.mo +0 -0
  672. trunk/assets/lang/landing-pages-ms.mo +0 -0
  673. trunk/assets/lang/landing-pages-mw1.mo +0 -0
  674. trunk/assets/lang/landing-pages-my.mo +0 -0
  675. trunk/assets/lang/landing-pages-my_MM.mo +0 -0
  676. trunk/assets/lang/landing-pages-myv.mo +0 -0
  677. trunk/assets/lang/landing-pages-nah.mo +0 -0
  678. trunk/assets/lang/landing-pages-nan.mo +0 -0
  679. trunk/assets/lang/landing-pages-nap.mo +0 -0
  680. trunk/assets/lang/landing-pages-nb.mo +0 -0
  681. trunk/assets/lang/landing-pages-nb_NO.mo +0 -0
  682. trunk/assets/lang/landing-pages-ne.mo +0 -0
  683. trunk/assets/lang/landing-pages-ne_NP.mo +0 -0
  684. trunk/assets/lang/landing-pages-nia.mo +0 -0
  685. trunk/assets/lang/landing-pages-nl.mo +0 -0
  686. trunk/assets/lang/landing-pages-nl_BE.mo +0 -0
  687. trunk/assets/lang/landing-pages-nl_NL.mo +0 -0
  688. trunk/assets/lang/landing-pages-nn.mo +0 -0
  689. trunk/assets/lang/landing-pages-nn_NO.mo +0 -0
  690. trunk/assets/lang/landing-pages-no.mo +0 -0
  691. trunk/assets/lang/landing-pages-no_NO.mo +0 -0
  692. trunk/assets/lang/landing-pages-nqo.mo +0 -0
  693. trunk/assets/lang/landing-pages-nr.mo +0 -0
  694. trunk/assets/lang/landing-pages-nso.mo +0 -0
  695. trunk/assets/lang/landing-pages-nv.mo +0 -0
  696. trunk/assets/lang/landing-pages-ny.mo +0 -0
  697. trunk/assets/lang/landing-pages-oc.mo +0 -0
  698. trunk/assets/lang/landing-pages-om.mo +0 -0
  699. trunk/assets/lang/landing-pages-or.mo +0 -0
  700. trunk/assets/lang/landing-pages-or_IN.mo +0 -0
  701. trunk/assets/lang/landing-pages-os.mo +0 -0
  702. trunk/assets/lang/landing-pages-pa.mo +0 -0
  703. trunk/assets/lang/landing-pages-pa_IN.mo +0 -0
  704. trunk/assets/lang/landing-pages-pam.mo +0 -0
  705. trunk/assets/lang/landing-pages-pap.mo +0 -0
  706. trunk/assets/lang/landing-pages-pfl.mo +0 -0
  707. trunk/assets/lang/landing-pages-pl.mo +0 -0
  708. trunk/assets/lang/landing-pages-pl_PL.mo +0 -0
  709. trunk/assets/lang/landing-pages-pms.mo +0 -0
  710. trunk/assets/lang/landing-pages-ps.mo +0 -0
  711. trunk/assets/lang/landing-pages-pt.mo +0 -0
  712. trunk/assets/lang/landing-pages-pt_BR.mo +0 -0
  713. trunk/assets/lang/landing-pages-pt_PT.mo +0 -0
  714. trunk/assets/lang/landing-pages-rm.mo +0 -0
  715. trunk/assets/lang/landing-pages-ro.mo +0 -0
  716. trunk/assets/lang/landing-pages-ro_RO.mo +0 -0
  717. trunk/assets/lang/landing-pages-ru.mo +0 -0
  718. trunk/assets/lang/landing-pages-ru@petr1708.mo +0 -0
  719. trunk/assets/lang/landing-pages-ru_RU.mo +0 -0
  720. trunk/assets/lang/landing-pages-ru_ee.mo +0 -0
  721. trunk/assets/lang/landing-pages-ru_lt.mo +0 -0
  722. trunk/assets/lang/landing-pages-ru_lv.mo +0 -0
  723. trunk/assets/lang/landing-pages-sa.mo +0 -0
  724. trunk/assets/lang/landing-pages-sah.mo +0 -0
  725. trunk/assets/lang/landing-pages-sat.mo +0 -0
  726. trunk/assets/lang/landing-pages-sc.mo +0 -0
  727. trunk/assets/lang/landing-pages-scn.mo +0 -0
  728. trunk/assets/lang/landing-pages-sco.mo +0 -0
  729. trunk/assets/lang/landing-pages-sd.mo +0 -0
  730. trunk/assets/lang/landing-pages-se.mo +0 -0
  731. trunk/assets/lang/landing-pages-sg.mo +0 -0
  732. trunk/assets/lang/landing-pages-si.mo +0 -0
  733. trunk/assets/lang/landing-pages-si_LK.mo +0 -0
  734. trunk/assets/lang/landing-pages-sk.mo +0 -0
  735. trunk/assets/lang/landing-pages-sk_SK.mo +0 -0
  736. trunk/assets/lang/landing-pages-sl.mo +0 -0
  737. trunk/assets/lang/landing-pages-sl_SI.mo +0 -0
  738. trunk/assets/lang/landing-pages-sm.mo +0 -0
  739. trunk/assets/lang/landing-pages-sma.mo +0 -0
  740. trunk/assets/lang/landing-pages-sn.mo +0 -0
  741. trunk/assets/lang/landing-pages-so.mo +0 -0
  742. trunk/assets/lang/landing-pages-son.mo +0 -0
  743. trunk/assets/lang/landing-pages-sq.mo +0 -0
  744. trunk/assets/lang/landing-pages-sq_AL.mo +0 -0
  745. trunk/assets/lang/landing-pages-sr.mo +0 -0
  746. trunk/assets/lang/landing-pages-sr@Ijekavian.mo +0 -0
  747. trunk/assets/lang/landing-pages-sr@ijekavianlatin.mo +0 -0
  748. trunk/assets/lang/landing-pages-sr@latin.mo +0 -0
  749. trunk/assets/lang/landing-pages-sr_RS.mo +0 -0
  750. trunk/assets/lang/landing-pages-sr_RS@latin.mo +0 -0
  751. trunk/assets/lang/landing-pages-ss.mo +0 -0
  752. trunk/assets/lang/landing-pages-st.mo +0 -0
  753. trunk/assets/lang/landing-pages-st_ZA.mo +0 -0
  754. trunk/assets/lang/landing-pages-su.mo +0 -0
  755. trunk/assets/lang/landing-pages-sv.mo +0 -0
  756. trunk/assets/lang/landing-pages-sv_FI.mo +0 -0
  757. trunk/assets/lang/landing-pages-sv_SE.mo +0 -0
  758. trunk/assets/lang/landing-pages-sw.mo +0 -0
  759. trunk/assets/lang/landing-pages-sw_CD.mo +0 -0
  760. trunk/assets/lang/landing-pages-sw_KE.mo +0 -0
  761. trunk/assets/lang/landing-pages-szl.mo +0 -0
  762. trunk/assets/lang/landing-pages-ta.mo +0 -0
  763. trunk/assets/lang/landing-pages-ta_IN.mo +0 -0
  764. trunk/assets/lang/landing-pages-ta_LK.mo +0 -0
  765. trunk/assets/lang/landing-pages-te.mo +0 -0
  766. trunk/assets/lang/landing-pages-te_IN.mo +0 -0
  767. trunk/assets/lang/landing-pages-tet.mo +0 -0
  768. trunk/assets/lang/landing-pages-tg.mo +0 -0
  769. trunk/assets/lang/landing-pages-tg_TJ.mo +0 -0
  770. trunk/assets/lang/landing-pages-th.mo +0 -0
  771. trunk/assets/lang/landing-pages-th_TH.mo +0 -0
  772. trunk/assets/lang/landing-pages-ti.mo +0 -0
  773. trunk/assets/lang/landing-pages-tk.mo +0 -0
  774. trunk/assets/lang/landing-pages-tk_TM.mo +0 -0
  775. trunk/assets/lang/landing-pages-tl.mo +0 -0
  776. trunk/assets/lang/landing-pages-tl_PH.mo +0 -0
  777. trunk/assets/lang/landing-pages-tn.mo +0 -0
  778. trunk/assets/lang/landing-pages-to.mo +0 -0
  779. trunk/assets/lang/landing-pages-tr.mo +0 -0
  780. trunk/assets/lang/landing-pages-tr_TR.mo +0 -0
  781. trunk/assets/lang/landing-pages-ts.mo +0 -0
  782. trunk/assets/lang/landing-pages-tt.mo +0 -0
  783. trunk/assets/lang/landing-pages-tzl.mo +0 -0
  784. trunk/assets/lang/landing-pages-tzm.mo +0 -0
  785. trunk/assets/lang/landing-pages-udm.mo +0 -0
  786. trunk/assets/lang/landing-pages-ug.mo +0 -0
  787. trunk/assets/lang/landing-pages-ug@Arab.mo +0 -0
  788. trunk/assets/lang/landing-pages-ug@Cyrl.mo +0 -0
  789. trunk/assets/lang/landing-pages-ug@Latin.mo +0 -0
  790. trunk/assets/lang/landing-pages-uk.mo +0 -0
  791. trunk/assets/lang/landing-pages-uk_UA.mo +0 -0
  792. trunk/assets/lang/landing-pages-ur.mo +0 -0
  793. trunk/assets/lang/landing-pages-ur_PK.mo +0 -0
  794. trunk/assets/lang/landing-pages-uz.mo +0 -0
  795. trunk/assets/lang/landing-pages-uz@Arab.mo +0 -0
  796. trunk/assets/lang/landing-pages-uz@Cyrl.mo +0 -0
  797. trunk/assets/lang/landing-pages-uz@Latn.mo +0 -0
  798. trunk/assets/lang/landing-pages-uz_UZ.mo +0 -0
  799. trunk/assets/lang/landing-pages-ve.mo +0 -0
  800. trunk/assets/lang/landing-pages-vec.mo +0 -0
  801. trunk/assets/lang/landing-pages-vi.mo +0 -0
  802. trunk/assets/lang/landing-pages-vi_VN.mo +0 -0
  803. trunk/assets/lang/landing-pages-vls.mo +0 -0
  804. trunk/assets/lang/landing-pages-vmf.mo +0 -0
  805. trunk/assets/lang/landing-pages-wa.mo +0 -0
  806. trunk/assets/lang/landing-pages-war.mo +0 -0
  807. trunk/assets/lang/landing-pages-wo.mo +0 -0
  808. trunk/assets/lang/landing-pages-wo_SN.mo +0 -0
  809. trunk/assets/lang/landing-pages-wuu.mo +0 -0
  810. trunk/assets/lang/landing-pages-xh.mo +0 -0
  811. trunk/assets/lang/landing-pages-yi.mo +0 -0
  812. trunk/assets/lang/landing-pages-yo.mo +0 -0
  813. trunk/assets/lang/landing-pages-yue.mo +0 -0
  814. trunk/assets/lang/landing-pages-zh-Hans.mo +0 -0
  815. trunk/assets/lang/landing-pages-zh-Hant.mo +0 -0
  816. trunk/assets/lang/landing-pages-zh.mo +0 -0
  817. trunk/assets/lang/landing-pages-zh_CN.GB2312.mo +0 -0
  818. trunk/assets/lang/landing-pages-zh_CN.mo +0 -0
  819. trunk/assets/lang/landing-pages-zh_HK.mo +0 -0
  820. trunk/assets/lang/landing-pages-zh_TW.Big5.mo +0 -0
  821. trunk/assets/lang/landing-pages-zh_TW.mo +0 -0
  822. trunk/assets/lang/landing-pages-zu.mo +0 -0
  823. trunk/assets/lang/landing-pages-zu_ZA.mo +0 -0
  824. trunk/assets/libraries/class-tgm-plugin-activation.php +3541 -0
  825. trunk/assets/libraries/datetimepicker/MIT-LICENSE.txt +19 -0
  826. trunk/assets/libraries/datetimepicker/README.md +28 -0
  827. trunk/assets/libraries/datetimepicker/bower.json +52 -0
  828. trunk/assets/libraries/datetimepicker/datetimepicker.jquery.json +47 -0
  829. trunk/assets/libraries/datetimepicker/jquery.datetimepicker.css +545 -0
  830. trunk/assets/libraries/datetimepicker/jquery.datetimepicker.js +2073 -0
  831. trunk/assets/libraries/datetimepicker/package.json +28 -0
  832. trunk/assets/libraries/datetimepicker/picker_functions.js +56 -0
  833. trunk/assets/libraries/easyXDM.debug.js +1 -0
  834. trunk/assets/libraries/index.php +2 -0
  835. trunk/assets/libraries/jpicker/css/jPicker-1.1.6.css +232 -0
  836. trunk/assets/libraries/jpicker/css/jPicker-1.1.6.min.css +1 -0
  837. trunk/assets/libraries/jpicker/css/jPicker.css +17 -0
  838. trunk/assets/libraries/jpicker/images/AlphaBar.png +0 -0
  839. trunk/assets/libraries/jpicker/images/Bars.png +0 -0
  840. trunk/assets/libraries/jpicker/images/Maps.png +0 -0
  841. trunk/assets/libraries/jpicker/images/NoColor.png +0 -0
  842. trunk/assets/libraries/jpicker/images/bar-opacity.png +0 -0
  843. trunk/assets/libraries/jpicker/images/map-opacity.png +0 -0
  844. trunk/assets/libraries/jpicker/images/mappoint.gif +0 -0
  845. trunk/assets/libraries/jpicker/images/picker.gif +0 -0
  846. trunk/assets/libraries/jpicker/images/preview-opacity.png +0 -0
  847. trunk/assets/libraries/jpicker/images/rangearrows.gif +0 -0
  848. trunk/assets/libraries/jpicker/jpicker-1.1.6.min.js +1 -0
  849. trunk/assets/libraries/jquery.zoomer.js +441 -0
  850. trunk/assets/libraries/script.js +36 -0
  851. trunk/assets/libraries/shareme/index.php +2 -0
  852. trunk/assets/libraries/shareme/library.shareme.php +1 -0
  853. trunk/assets/libraries/shareme/sharrre/index.php +2 -0
  854. trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.js +584 -0
  855. trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.min.js +1 -0
  856. trunk/classes/class.acf-integration.php +222 -0
assets/lang/{inbound-pro-ach.mo → landing-pages-ach.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ady.mo → landing-pages-ady.mo} RENAMED
File without changes
assets/lang/{inbound-pro-af.mo → landing-pages-af.mo} RENAMED
File without changes
assets/lang/{inbound-pro-af_ZA.mo → landing-pages-af_ZA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ak.mo → landing-pages-ak.mo} RENAMED
File without changes
assets/lang/{inbound-pro-aln.mo → landing-pages-aln.mo} RENAMED
File without changes
assets/lang/{inbound-pro-am.mo → landing-pages-am.mo} RENAMED
File without changes
assets/lang/{inbound-pro-am_ET.mo → landing-pages-am_ET.mo} RENAMED
File without changes
assets/lang/{inbound-pro-an.mo → landing-pages-an.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ar.mo → landing-pages-ar.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ar_AA.mo → landing-pages-ar_AA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ar_EG.mo → landing-pages-ar_EG.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ar_SA.mo → landing-pages-ar_SA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ar_SD.mo → landing-pages-ar_SD.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ar_SY.mo → landing-pages-ar_SY.mo} RENAMED
File without changes
assets/lang/{inbound-pro-arn.mo → landing-pages-arn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-as.mo → landing-pages-as.mo} RENAMED
File without changes
assets/lang/{inbound-pro-as_IN.mo → landing-pages-as_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ast.mo → landing-pages-ast.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ast_ES.mo → landing-pages-ast_ES.mo} RENAMED
File without changes
assets/lang/{inbound-pro-az.mo → landing-pages-az.mo} RENAMED
File without changes
assets/lang/{inbound-pro-az@Arab.mo → landing-pages-az@Arab.mo} RENAMED
File without changes
assets/lang/{inbound-pro-az@latin.mo → landing-pages-az@latin.mo} RENAMED
File without changes
assets/lang/{inbound-pro-az_AZ.mo → landing-pages-az_AZ.mo} RENAMED
File without changes
assets/lang/{inbound-pro-az_IR.mo → landing-pages-az_IR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ba.mo → landing-pages-ba.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bal.mo → landing-pages-bal.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bar.mo → landing-pages-bar.mo} RENAMED
File without changes
assets/lang/{inbound-pro-be.mo → landing-pages-be.mo} RENAMED
File without changes
assets/lang/{inbound-pro-be@tarask.mo → landing-pages-be@tarask.mo} RENAMED
File without changes
assets/lang/{inbound-pro-be_BY.mo → landing-pages-be_BY.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bg.mo → landing-pages-bg.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bg_BG.mo → landing-pages-bg_BG.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bn.mo → landing-pages-bn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bn_BD.mo → landing-pages-bn_BD.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bn_IN.mo → landing-pages-bn_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bo.mo → landing-pages-bo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bo_CN.mo → landing-pages-bo_CN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-br.mo → landing-pages-br.mo} RENAMED
File without changes
assets/lang/{inbound-pro-brx.mo → landing-pages-brx.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bs.mo → landing-pages-bs.mo} RENAMED
File without changes
assets/lang/{inbound-pro-bs_BA.mo → landing-pages-bs_BA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ca.mo → landing-pages-ca.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ca@valencia.mo → landing-pages-ca@valencia.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ca_ES.mo → landing-pages-ca_ES.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cdo.mo → landing-pages-cdo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ceb.mo → landing-pages-ceb.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cgg.mo → landing-pages-cgg.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cjy.mo → landing-pages-cjy.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cmn.mo → landing-pages-cmn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-co.mo → landing-pages-co.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cpx.mo → landing-pages-cpx.mo} RENAMED
File without changes
assets/lang/{inbound-pro-crh.mo → landing-pages-crh.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cs.mo → landing-pages-cs.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cs_CZ.mo → landing-pages-cs_CZ.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cv.mo → landing-pages-cv.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cy.mo → landing-pages-cy.mo} RENAMED
File without changes
assets/lang/{inbound-pro-cy_GB.mo → landing-pages-cy_GB.mo} RENAMED
File without changes
assets/lang/{inbound-pro-czh.mo → landing-pages-czh.mo} RENAMED
File without changes
assets/lang/{inbound-pro-czo.mo → landing-pages-czo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-da.mo → landing-pages-da.mo} RENAMED
File without changes
assets/lang/{inbound-pro-da_DK.mo → landing-pages-da_DK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-de.mo → landing-pages-de.mo} RENAMED
File without changes
assets/lang/{inbound-pro-de_AT.mo → landing-pages-de_AT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-de_CH.mo → landing-pages-de_CH.mo} RENAMED
File without changes
assets/lang/{inbound-pro-de_DE.mo → landing-pages-de_DE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-doi.mo → landing-pages-doi.mo} RENAMED
File without changes
assets/lang/{inbound-pro-dv.mo → landing-pages-dv.mo} RENAMED
File without changes
assets/lang/{inbound-pro-dz.mo → landing-pages-dz.mo} RENAMED
File without changes
assets/lang/{inbound-pro-dz_BT.mo → landing-pages-dz_BT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-el.mo → landing-pages-el.mo} RENAMED
File without changes
assets/lang/{inbound-pro-el_GR.mo → landing-pages-el_GR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en.mo → landing-pages-en.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en@pirate.mo → landing-pages-en@pirate.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_AT.mo → landing-pages-en_AT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_AU.mo → landing-pages-en_AU.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_BD.mo → landing-pages-en_BD.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_BE.mo → landing-pages-en_BE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_CA.mo → landing-pages-en_CA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_CH.mo → landing-pages-en_CH.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_CL.mo → landing-pages-en_CL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_CZ.mo → landing-pages-en_CZ.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_DE.mo → landing-pages-en_DE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_EG.mo → landing-pages-en_EG.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_ES.mo → landing-pages-en_ES.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_FI.mo → landing-pages-en_FI.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_GB.mo → landing-pages-en_GB.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_GH.mo → landing-pages-en_GH.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_GR.mo → landing-pages-en_GR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_HK.mo → landing-pages-en_HK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_HR.mo → landing-pages-en_HR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_HU.mo → landing-pages-en_HU.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_IE.mo → landing-pages-en_IE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_IN.mo → landing-pages-en_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_IT.mo → landing-pages-en_IT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_LK.mo → landing-pages-en_LK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_NG.mo → landing-pages-en_NG.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_NL.mo → landing-pages-en_NL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_NO.mo → landing-pages-en_NO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_NZ.mo → landing-pages-en_NZ.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_PK.mo → landing-pages-en_PK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_PL.mo → landing-pages-en_PL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_PT.mo → landing-pages-en_PT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_RO.mo → landing-pages-en_RO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_SE.mo → landing-pages-en_SE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_SK.mo → landing-pages-en_SK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_ZA.mo → landing-pages-en_ZA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_ee.mo → landing-pages-en_ee.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_lt.mo → landing-pages-en_lt.mo} RENAMED
File without changes
assets/lang/{inbound-pro-en_lv.mo → landing-pages-en_lv.mo} RENAMED
File without changes
assets/lang/{inbound-pro-eo.mo → landing-pages-eo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es.mo → landing-pages-es.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_419.mo → landing-pages-es_419.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_AR.mo → landing-pages-es_AR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_BO.mo → landing-pages-es_BO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_CL.mo → landing-pages-es_CL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_CO.mo → landing-pages-es_CO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_CR.mo → landing-pages-es_CR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_DO.mo → landing-pages-es_DO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_EC.mo → landing-pages-es_EC.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_ES.mo → landing-pages-es_ES.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_GT.mo → landing-pages-es_GT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_HN.mo → landing-pages-es_HN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_MX.mo → landing-pages-es_MX.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_NI.mo → landing-pages-es_NI.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_PA.mo → landing-pages-es_PA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_PE.mo → landing-pages-es_PE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_PR.mo → landing-pages-es_PR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_PY.mo → landing-pages-es_PY.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_SV.mo → landing-pages-es_SV.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_US.mo → landing-pages-es_US.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_UY.mo → landing-pages-es_UY.mo} RENAMED
File without changes
assets/lang/{inbound-pro-es_VE.mo → landing-pages-es_VE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-et.mo → landing-pages-et.mo} RENAMED
File without changes
assets/lang/{inbound-pro-et_EE.mo → landing-pages-et_EE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-eu.mo → landing-pages-eu.mo} RENAMED
File without changes
assets/lang/{inbound-pro-eu_ES.mo → landing-pages-eu_ES.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fa.mo → landing-pages-fa.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fa_AF.mo → landing-pages-fa_AF.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fa_IR.mo → landing-pages-fa_IR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ff.mo → landing-pages-ff.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ff_SN.mo → landing-pages-ff_SN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fi.mo → landing-pages-fi.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fi_FI.mo → landing-pages-fi_FI.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fil.mo → landing-pages-fil.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fo.mo → landing-pages-fo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fo_FO.mo → landing-pages-fo_FO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fr.mo → landing-pages-fr.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fr_BE.mo → landing-pages-fr_BE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fr_CA.mo → landing-pages-fr_CA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fr_CH.mo → landing-pages-fr_CH.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fr_FR.mo → landing-pages-fr_FR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-frp.mo → landing-pages-frp.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fur.mo → landing-pages-fur.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fy.mo → landing-pages-fy.mo} RENAMED
File without changes
assets/lang/{inbound-pro-fy_NL.mo → landing-pages-fy_NL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ga.mo → landing-pages-ga.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ga_IE.mo → landing-pages-ga_IE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-gan.mo → landing-pages-gan.mo} RENAMED
File without changes
assets/lang/{inbound-pro-gd.mo → landing-pages-gd.mo} RENAMED
File without changes
assets/lang/{inbound-pro-gl.mo → landing-pages-gl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-gl_ES.mo → landing-pages-gl_ES.mo} RENAMED
File without changes
assets/lang/{inbound-pro-gu.mo → landing-pages-gu.mo} RENAMED
File without changes
assets/lang/{inbound-pro-gu_IN.mo → landing-pages-gu_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-gun.mo → landing-pages-gun.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ha.mo → landing-pages-ha.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hak.mo → landing-pages-hak.mo} RENAMED
File without changes
assets/lang/{inbound-pro-haw.mo → landing-pages-haw.mo} RENAMED
File without changes
assets/lang/{inbound-pro-he.mo → landing-pages-he.mo} RENAMED
File without changes
assets/lang/{inbound-pro-he_IL.mo → landing-pages-he_IL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hi.mo → landing-pages-hi.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hi_IN.mo → landing-pages-hi_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hne.mo → landing-pages-hne.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hr.mo → landing-pages-hr.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hr_HR.mo → landing-pages-hr_HR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hsb.mo → landing-pages-hsb.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hsn.mo → landing-pages-hsn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ht.mo → landing-pages-ht.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ht_HT.mo → landing-pages-ht_HT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hu.mo → landing-pages-hu.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hu_HU.mo → landing-pages-hu_HU.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hu_RO.mo → landing-pages-hu_RO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hy.mo → landing-pages-hy.mo} RENAMED
File without changes
assets/lang/{inbound-pro-hy_AM.mo → landing-pages-hy_AM.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ia.mo → landing-pages-ia.mo} RENAMED
File without changes
assets/lang/{inbound-pro-id.mo → landing-pages-id.mo} RENAMED
File without changes
assets/lang/{inbound-pro-id_ID.mo → landing-pages-id_ID.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ig.mo → landing-pages-ig.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ilo.mo → landing-pages-ilo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-io.mo → landing-pages-io.mo} RENAMED
File without changes
assets/lang/{inbound-pro-is.mo → landing-pages-is.mo} RENAMED
File without changes
assets/lang/{inbound-pro-is_IS.mo → landing-pages-is_IS.mo} RENAMED
File without changes
assets/lang/{inbound-pro-it.mo → landing-pages-it.mo} RENAMED
File without changes
assets/lang/{inbound-pro-it_CH.mo → landing-pages-it_CH.mo} RENAMED
File without changes
assets/lang/{inbound-pro-it_IT.mo → landing-pages-it_IT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-iu.mo → landing-pages-iu.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ja.mo → landing-pages-ja.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ja_JP.mo → landing-pages-ja_JP.mo} RENAMED
File without changes
assets/lang/{inbound-pro-jv.mo → landing-pages-jv.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ka.mo → landing-pages-ka.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ka_GE.mo → landing-pages-ka_GE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-kab.mo → landing-pages-kab.mo} RENAMED
File without changes
assets/lang/{inbound-pro-kl.mo → landing-pages-kl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-kn.mo → landing-pages-kn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-kn_IN.mo → landing-pages-kn_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ksh.mo → landing-pages-ksh.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ku.mo → landing-pages-ku.mo} RENAMED
File without changes
assets/lang/{inbound-pro-kw.mo → landing-pages-kw.mo} RENAMED
File without changes
assets/lang/{inbound-pro-la.mo → landing-pages-la.mo} RENAMED
File without changes
assets/lang/{inbound-pro-lg.mo → landing-pages-lg.mo} RENAMED
File without changes
assets/lang/{inbound-pro-lzh.mo → landing-pages-lzh.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mh.mo → landing-pages-mh.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mi.mo → landing-pages-mi.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mn.mo → landing-pages-mn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mn_MN.mo → landing-pages-mn_MN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mni.mo → landing-pages-mni.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mnp.mo → landing-pages-mnp.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mr.mo → landing-pages-mr.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mr_IN.mo → landing-pages-mr_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ms.mo → landing-pages-ms.mo} RENAMED
File without changes
assets/lang/{inbound-pro-mw1.mo → landing-pages-mw1.mo} RENAMED
File without changes
assets/lang/{inbound-pro-my.mo → landing-pages-my.mo} RENAMED
File without changes
assets/lang/{inbound-pro-my_MM.mo → landing-pages-my_MM.mo} RENAMED
File without changes
assets/lang/{inbound-pro-myv.mo → landing-pages-myv.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nah.mo → landing-pages-nah.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nan.mo → landing-pages-nan.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nap.mo → landing-pages-nap.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nb.mo → landing-pages-nb.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nb_NO.mo → landing-pages-nb_NO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ne.mo → landing-pages-ne.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ne_NP.mo → landing-pages-ne_NP.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nia.mo → landing-pages-nia.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nl.mo → landing-pages-nl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nl_BE.mo → landing-pages-nl_BE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nl_NL.mo → landing-pages-nl_NL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nn.mo → landing-pages-nn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nn_NO.mo → landing-pages-nn_NO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-no.mo → landing-pages-no.mo} RENAMED
File without changes
assets/lang/{inbound-pro-no_NO.mo → landing-pages-no_NO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nqo.mo → landing-pages-nqo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nr.mo → landing-pages-nr.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nso.mo → landing-pages-nso.mo} RENAMED
File without changes
assets/lang/{inbound-pro-nv.mo → landing-pages-nv.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ny.mo → landing-pages-ny.mo} RENAMED
File without changes
assets/lang/{inbound-pro-oc.mo → landing-pages-oc.mo} RENAMED
File without changes
assets/lang/{inbound-pro-om.mo → landing-pages-om.mo} RENAMED
File without changes
assets/lang/{inbound-pro-or.mo → landing-pages-or.mo} RENAMED
File without changes
assets/lang/{inbound-pro-or_IN.mo → landing-pages-or_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-os.mo → landing-pages-os.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pa.mo → landing-pages-pa.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pa_IN.mo → landing-pages-pa_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pam.mo → landing-pages-pam.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pap.mo → landing-pages-pap.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pfl.mo → landing-pages-pfl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pl.mo → landing-pages-pl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pl_PL.mo → landing-pages-pl_PL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pms.mo → landing-pages-pms.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ps.mo → landing-pages-ps.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pt.mo → landing-pages-pt.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pt_BR.mo → landing-pages-pt_BR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-pt_PT.mo → landing-pages-pt_PT.mo} RENAMED
File without changes
assets/lang/{inbound-pro-rm.mo → landing-pages-rm.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ro.mo → landing-pages-ro.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ro_RO.mo → landing-pages-ro_RO.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ru.mo → landing-pages-ru.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ru@petr1708.mo → landing-pages-ru@petr1708.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ru_RU.mo → landing-pages-ru_RU.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ru_ee.mo → landing-pages-ru_ee.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ru_lt.mo → landing-pages-ru_lt.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ru_lv.mo → landing-pages-ru_lv.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sa.mo → landing-pages-sa.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sah.mo → landing-pages-sah.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sat.mo → landing-pages-sat.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sc.mo → landing-pages-sc.mo} RENAMED
File without changes
assets/lang/{inbound-pro-scn.mo → landing-pages-scn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sco.mo → landing-pages-sco.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sd.mo → landing-pages-sd.mo} RENAMED
File without changes
assets/lang/{inbound-pro-se.mo → landing-pages-se.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sg.mo → landing-pages-sg.mo} RENAMED
File without changes
assets/lang/{inbound-pro-si.mo → landing-pages-si.mo} RENAMED
File without changes
assets/lang/{inbound-pro-si_LK.mo → landing-pages-si_LK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sk.mo → landing-pages-sk.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sk_SK.mo → landing-pages-sk_SK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sl.mo → landing-pages-sl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sl_SI.mo → landing-pages-sl_SI.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sm.mo → landing-pages-sm.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sma.mo → landing-pages-sma.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sn.mo → landing-pages-sn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-so.mo → landing-pages-so.mo} RENAMED
File without changes
assets/lang/{inbound-pro-son.mo → landing-pages-son.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sq.mo → landing-pages-sq.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sq_AL.mo → landing-pages-sq_AL.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sr.mo → landing-pages-sr.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sr@Ijekavian.mo → landing-pages-sr@Ijekavian.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sr@ijekavianlatin.mo → landing-pages-sr@ijekavianlatin.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sr@latin.mo → landing-pages-sr@latin.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sr_RS.mo → landing-pages-sr_RS.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sr_RS@latin.mo → landing-pages-sr_RS@latin.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ss.mo → landing-pages-ss.mo} RENAMED
File without changes
assets/lang/{inbound-pro-st.mo → landing-pages-st.mo} RENAMED
File without changes
assets/lang/{inbound-pro-st_ZA.mo → landing-pages-st_ZA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-su.mo → landing-pages-su.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sv.mo → landing-pages-sv.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sv_FI.mo → landing-pages-sv_FI.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sv_SE.mo → landing-pages-sv_SE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sw.mo → landing-pages-sw.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sw_CD.mo → landing-pages-sw_CD.mo} RENAMED
File without changes
assets/lang/{inbound-pro-sw_KE.mo → landing-pages-sw_KE.mo} RENAMED
File without changes
assets/lang/{inbound-pro-szl.mo → landing-pages-szl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ta.mo → landing-pages-ta.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ta_IN.mo → landing-pages-ta_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ta_LK.mo → landing-pages-ta_LK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-te.mo → landing-pages-te.mo} RENAMED
File without changes
assets/lang/{inbound-pro-te_IN.mo → landing-pages-te_IN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tet.mo → landing-pages-tet.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tg.mo → landing-pages-tg.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tg_TJ.mo → landing-pages-tg_TJ.mo} RENAMED
File without changes
assets/lang/{inbound-pro-th.mo → landing-pages-th.mo} RENAMED
File without changes
assets/lang/{inbound-pro-th_TH.mo → landing-pages-th_TH.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ti.mo → landing-pages-ti.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tk.mo → landing-pages-tk.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tk_TM.mo → landing-pages-tk_TM.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tl.mo → landing-pages-tl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tl_PH.mo → landing-pages-tl_PH.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tn.mo → landing-pages-tn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-to.mo → landing-pages-to.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tr.mo → landing-pages-tr.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tr_TR.mo → landing-pages-tr_TR.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ts.mo → landing-pages-ts.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tt.mo → landing-pages-tt.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tzl.mo → landing-pages-tzl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-tzm.mo → landing-pages-tzm.mo} RENAMED
File without changes
assets/lang/{inbound-pro-udm.mo → landing-pages-udm.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ug.mo → landing-pages-ug.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ug@Arab.mo → landing-pages-ug@Arab.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ug@Cyrl.mo → landing-pages-ug@Cyrl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ug@Latin.mo → landing-pages-ug@Latin.mo} RENAMED
File without changes
assets/lang/{inbound-pro-uk.mo → landing-pages-uk.mo} RENAMED
File without changes
assets/lang/{inbound-pro-uk_UA.mo → landing-pages-uk_UA.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ur.mo → landing-pages-ur.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ur_PK.mo → landing-pages-ur_PK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-uz.mo → landing-pages-uz.mo} RENAMED
File without changes
assets/lang/{inbound-pro-uz@Arab.mo → landing-pages-uz@Arab.mo} RENAMED
File without changes
assets/lang/{inbound-pro-uz@Cyrl.mo → landing-pages-uz@Cyrl.mo} RENAMED
File without changes
assets/lang/{inbound-pro-uz@Latn.mo → landing-pages-uz@Latn.mo} RENAMED
File without changes
assets/lang/{inbound-pro-uz_UZ.mo → landing-pages-uz_UZ.mo} RENAMED
File without changes
assets/lang/{inbound-pro-ve.mo → landing-pages-ve.mo} RENAMED
File without changes
assets/lang/{inbound-pro-vec.mo → landing-pages-vec.mo} RENAMED
File without changes
assets/lang/{inbound-pro-vi.mo → landing-pages-vi.mo} RENAMED
File without changes
assets/lang/{inbound-pro-vi_VN.mo → landing-pages-vi_VN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-vls.mo → landing-pages-vls.mo} RENAMED
File without changes
assets/lang/{inbound-pro-vmf.mo → landing-pages-vmf.mo} RENAMED
File without changes
assets/lang/{inbound-pro-wa.mo → landing-pages-wa.mo} RENAMED
File without changes
assets/lang/{inbound-pro-war.mo → landing-pages-war.mo} RENAMED
File without changes
assets/lang/{inbound-pro-wo.mo → landing-pages-wo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-wo_SN.mo → landing-pages-wo_SN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-wuu.mo → landing-pages-wuu.mo} RENAMED
File without changes
assets/lang/{inbound-pro-xh.mo → landing-pages-xh.mo} RENAMED
File without changes
assets/lang/{inbound-pro-yi.mo → landing-pages-yi.mo} RENAMED
File without changes
assets/lang/{inbound-pro-yo.mo → landing-pages-yo.mo} RENAMED
File without changes
assets/lang/{inbound-pro-yue.mo → landing-pages-yue.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zh-Hans.mo → landing-pages-zh-Hans.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zh-Hant.mo → landing-pages-zh-Hant.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zh.mo → landing-pages-zh.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zh_CN.GB2312.mo → landing-pages-zh_CN.GB2312.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zh_CN.mo → landing-pages-zh_CN.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zh_HK.mo → landing-pages-zh_HK.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zh_TW.Big5.mo → landing-pages-zh_TW.Big5.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zh_TW.mo → landing-pages-zh_TW.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zu.mo → landing-pages-zu.mo} RENAMED
File without changes
assets/lang/{inbound-pro-zu_ZA.mo → landing-pages-zu_ZA.mo} RENAMED
File without changes
landing-pages.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Landing Pages
4
  Plugin URI: http://www.inboundnow.com/landing-pages/
5
  Description: Landing page template framework with variant testing and lead capturing through cooperation with Inbound Now's Leads plugin. This is the stand alone version served through WordPress.org.
6
- Version: 2.6.7
7
  Author: Inbound Now
8
  Author URI: https://www.inboundnow.com/?innercity=true
9
  Text Domain: inbound-pro
@@ -42,7 +42,7 @@ if (!class_exists('Inbound_Landing_Pages_Plugin')) {
42
  */
43
  private static function load_constants() {
44
 
45
- define('LANDINGPAGES_CURRENT_VERSION', '2.6.7' );
46
  define('LANDINGPAGES_URLPATH', plugins_url( '/' , __FILE__ ) );
47
  define('LANDINGPAGES_PATH', WP_PLUGIN_DIR.'/'.plugin_basename( dirname(__FILE__) ).'/' );
48
  define('LANDINGPAGES_PLUGIN_SLUG', 'landing-pages' );
@@ -53,6 +53,7 @@ if (!class_exists('Inbound_Landing_Pages_Plugin')) {
53
  define('LANDINGPAGES_UPLOADS_URLPATH', $uploads['baseurl'].'/landing-pages/templates/' );
54
  define('LANDINGPAGES_THEME_TEMPLATES_PATH' , get_template_directory(). '/landing-pages/' );
55
  define('LANDINGPAGES_THEME_TEMPLATES_URLPATH' , get_template_directory_uri(). '/landing-pages/' );
 
56
  }
57
 
58
  /**
3
  Plugin Name: Landing Pages
4
  Plugin URI: http://www.inboundnow.com/landing-pages/
5
  Description: Landing page template framework with variant testing and lead capturing through cooperation with Inbound Now's Leads plugin. This is the stand alone version served through WordPress.org.
6
+ Version: 2.6.9
7
  Author: Inbound Now
8
  Author URI: https://www.inboundnow.com/?innercity=true
9
  Text Domain: inbound-pro
42
  */
43
  private static function load_constants() {
44
 
45
+ define('LANDINGPAGES_CURRENT_VERSION', '2.6.9' );
46
  define('LANDINGPAGES_URLPATH', plugins_url( '/' , __FILE__ ) );
47
  define('LANDINGPAGES_PATH', WP_PLUGIN_DIR.'/'.plugin_basename( dirname(__FILE__) ).'/' );
48
  define('LANDINGPAGES_PLUGIN_SLUG', 'landing-pages' );
53
  define('LANDINGPAGES_UPLOADS_URLPATH', $uploads['baseurl'].'/landing-pages/templates/' );
54
  define('LANDINGPAGES_THEME_TEMPLATES_PATH' , get_template_directory(). '/landing-pages/' );
55
  define('LANDINGPAGES_THEME_TEMPLATES_URLPATH' , get_template_directory_uri(). '/landing-pages/' );
56
+
57
  }
58
 
59
  /**
readme.txt CHANGED
@@ -7,7 +7,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
7
  Tags: landing pages, inbound marketing, conversion pages, split testing, a b test, a b testing, a/b test, a/b testing, coming soon page, email list, landing page, list building, maintenance page, squeeze page, inbound now, landing-pages, splash pages, cpa, click tracking, goal tracking, analytics, free landing page templates
8
  Requires at least: 3.8
9
  Tested up to: 4.8.1
10
- Stable Tag: 2.6.7
11
 
12
 
13
  Create landing pages for your WordPress site. Monitor and improve conversion rates, run A/B split tests, customize your own templates and more.
@@ -85,6 +85,12 @@ We also offer a guide for using <a href="https://github.com/inboundnow/inbound-p
85
 
86
  == Changelog ==
87
 
 
 
 
 
 
 
88
  = 2.6.7 =
89
  * Maintenance work on localization features
90
 
7
  Tags: landing pages, inbound marketing, conversion pages, split testing, a b test, a b testing, a/b test, a/b testing, coming soon page, email list, landing page, list building, maintenance page, squeeze page, inbound now, landing-pages, splash pages, cpa, click tracking, goal tracking, analytics, free landing page templates
8
  Requires at least: 3.8
9
  Tested up to: 4.8.1
10
+ Stable Tag: 2.6.9
11
 
12
 
13
  Create landing pages for your WordPress site. Monitor and improve conversion rates, run A/B split tests, customize your own templates and more.
85
 
86
  == Changelog ==
87
 
88
+ = 2.6.9 =
89
+ * Maintenance work on impression storing.
90
+
91
+ = 2.6.8 =
92
+ * Shared database upgrade routine fixed.
93
+
94
  = 2.6.7 =
95
  * Maintenance work on localization features
96
 
shared/assets/js/frontend/analytics-src/analytics.page.js CHANGED
@@ -305,11 +305,13 @@ var _inboundPageTracking = (function(_inbound) {
305
 
306
  /* Let's try and fire this last - also defines what constitutes a bounce - */
307
  var stored = false;
308
- document.onreadystatechange = function () {
309
- if (document.readyState !== 'loading' && stored === false) {
 
310
  _inbound.PageTracking.storePageView();
311
  }
312
- }
 
313
  }
314
  ,
315
  CheckTimeOut: function() {
305
 
306
  /* Let's try and fire this last - also defines what constitutes a bounce - */
307
  var stored = false;
308
+ jQuery(document).ready(function() {
309
+
310
+ if (stored === false) {
311
  _inbound.PageTracking.storePageView();
312
  }
313
+
314
+ });
315
  }
316
  ,
317
  CheckTimeOut: function() {
shared/assets/js/frontend/analytics/inboundAnalytics.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! Inbound Analyticsv1.0.0 | (c) 2017 Inbound Now | https://github.com/inboundnow/cta */
2
  /**
3
  * # _inbound
4
  *
@@ -130,7 +130,7 @@ var _inbound = (function(options) {
130
  return Analytics;
131
 
132
  })(_inboundOptions);
133
-
134
  /**
135
  * # Hooks & Filters
136
  *
@@ -536,7 +536,7 @@ var _inboundHooks = (function (_inbound) {
536
  return _inbound;
537
 
538
  })(_inbound || {});
539
-
540
  /**
541
  * # _inbound UTILS
542
  *
@@ -1395,7 +1395,7 @@ var _inboundUtils = (function(_inbound) {
1395
  return _inbound;
1396
 
1397
  })(_inbound || {});
1398
-
1399
  /**
1400
  * # Inbound Forms
1401
  *
@@ -2611,7 +2611,7 @@ var InboundForms = (function(_inbound) {
2611
  return _inbound;
2612
 
2613
  })(_inbound || {});
2614
-
2615
  /**
2616
  * # Analytics Events
2617
  *
@@ -3221,140 +3221,140 @@ function inboundFormNoRedirectContent(){
3221
  }
3222
 
3223
  _inbound.add_action( 'form_after_submission', inboundFormNoRedirectContent, 10 );
3224
-
3225
- /* LocalStorage Component */
3226
- var InboundTotalStorage = (function (_inbound){
3227
-
3228
- var supported, ls, mod = '_inbound';
3229
- if ('localStorage' in window){
3230
- try {
3231
- ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
3232
- if (typeof ls == 'undefined' || typeof window.JSON == 'undefined'){
3233
- supported = false;
3234
- } else {
3235
- supported = true;
3236
- }
3237
- window.localStorage.setItem(mod, '1');
3238
- window.localStorage.removeItem(mod);
3239
- }
3240
- catch (err){
3241
- supported = false;
3242
- }
3243
- }
3244
-
3245
- /* Make the methods public */
3246
- _inbound.totalStorage = function(key, value, options){
3247
- return _inbound.totalStorage.impl.init(key, value);
3248
- };
3249
-
3250
- _inbound.totalStorage.setItem = function(key, value){
3251
- return _inbound.totalStorage.impl.setItem(key, value);
3252
- };
3253
-
3254
- _inbound.totalStorage.getItem = function(key){
3255
- return _inbound.totalStorage.impl.getItem(key);
3256
- };
3257
-
3258
- _inbound.totalStorage.getAll = function(){
3259
- return _inbound.totalStorage.impl.getAll();
3260
- };
3261
-
3262
- _inbound.totalStorage.deleteItem = function(key){
3263
- return _inbound.totalStorage.impl.deleteItem(key);
3264
- };
3265
-
3266
-
3267
- _inbound.totalStorage.impl = {
3268
-
3269
- init: function(key, value){
3270
- if (typeof value != 'undefined') {
3271
- return this.setItem(key, value);
3272
- } else {
3273
- return this.getItem(key);
3274
- }
3275
- },
3276
-
3277
- setItem: function(key, value){
3278
- if (!supported){
3279
- try {
3280
- _inbound.Utils.createCookie(key, value);
3281
- return value;
3282
- } catch(e){
3283
- console.log('Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie');
3284
- }
3285
- }
3286
- var saver = JSON.stringify(value);
3287
- ls.setItem(key, saver);
3288
- return this.parseResult(saver);
3289
- },
3290
- getItem: function(key){
3291
- if (!supported){
3292
- try {
3293
- return this.parseResult(_inbound.Utils.readCookie(key));
3294
- } catch(e){
3295
- return null;
3296
- }
3297
- }
3298
- var item = ls.getItem(key);
3299
- return this.parseResult(item);
3300
- },
3301
- deleteItem: function(key){
3302
- if (!supported){
3303
- try {
3304
- _inbound.Utils.eraseCookie(key, null);
3305
- return true;
3306
- } catch(e){
3307
- return false;
3308
- }
3309
- }
3310
- ls.removeItem(key);
3311
- return true;
3312
- },
3313
- getAll: function(){
3314
- var items = [];
3315
- if (!supported){
3316
- try {
3317
- var pairs = document.cookie.split(";");
3318
- for (var i = 0; i<pairs.length; i++){
3319
- var pair = pairs[i].split('=');
3320
- var key = pair[0];
3321
- items.push({key:key, value:this.parseResult(_inbound.Utils.readCookie(key))});
3322
- }
3323
- } catch(e){
3324
- return null;
3325
- }
3326
- } else {
3327
- for (var j in ls){
3328
- if (j.length){
3329
- items.push({key:j, value:this.parseResult(ls.getItem(j))});
3330
- }
3331
- }
3332
- }
3333
- return items;
3334
- },
3335
- parseResult: function(res){
3336
- var ret;
3337
- try {
3338
- ret = JSON.parse(res);
3339
- if (typeof ret == 'undefined'){
3340
- ret = res;
3341
- }
3342
- if (ret == 'true'){
3343
- ret = true;
3344
- }
3345
- if (ret == 'false'){
3346
- ret = false;
3347
- }
3348
- if (parseFloat(ret) == ret && typeof ret != "object"){
3349
- ret = parseFloat(ret);
3350
- }
3351
- } catch(e){
3352
- ret = res;
3353
- }
3354
- return ret;
3355
- }
3356
- };
3357
- })(_inbound || {});
3358
  /**
3359
  * Leads API functions
3360
  * @param Object _inbound - Main JS object
@@ -3442,7 +3442,7 @@ var _inboundLeadsAPI = (function(_inbound) {
3442
 
3443
  return _inbound;
3444
 
3445
- })(_inbound || {});
3446
  /**
3447
  * # Page View Tracking
3448
  *
@@ -3750,11 +3750,13 @@ var _inboundPageTracking = (function(_inbound) {
3750
 
3751
  /* Let's try and fire this last - also defines what constitutes a bounce - */
3752
  var stored = false;
3753
- document.onreadystatechange = function () {
3754
- if (document.readyState !== 'loading' && stored === false) {
 
3755
  _inbound.PageTracking.storePageView();
3756
  }
3757
- }
 
3758
  }
3759
  ,
3760
  CheckTimeOut: function() {
@@ -3816,7 +3818,7 @@ var _inboundPageTracking = (function(_inbound) {
3816
 
3817
  return _inbound;
3818
 
3819
- })(_inbound || {});
3820
  /**
3821
  * # Start
3822
  *
1
+ /*! Inbound Analyticsv1.0.0 | (c) 2018 Inbound Now | https://github.com/inboundnow/cta */
2
  /**
3
  * # _inbound
4
  *
130
  return Analytics;
131
 
132
  })(_inboundOptions);
133
+
134
  /**
135
  * # Hooks & Filters
136
  *
536
  return _inbound;
537
 
538
  })(_inbound || {});
539
+
540
  /**
541
  * # _inbound UTILS
542
  *
1395
  return _inbound;
1396
 
1397
  })(_inbound || {});
1398
+
1399
  /**
1400
  * # Inbound Forms
1401
  *
2611
  return _inbound;
2612
 
2613
  })(_inbound || {});
2614
+
2615
  /**
2616
  * # Analytics Events
2617
  *
3221
  }
3222
 
3223
  _inbound.add_action( 'form_after_submission', inboundFormNoRedirectContent, 10 );
3224
+
3225
+ /* LocalStorage Component */
3226
+ var InboundTotalStorage = (function (_inbound){
3227
+
3228
+ var supported, ls, mod = '_inbound';
3229
+ if ('localStorage' in window){
3230
+ try {
3231
+ ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
3232
+ if (typeof ls == 'undefined' || typeof window.JSON == 'undefined'){
3233
+ supported = false;
3234
+ } else {
3235
+ supported = true;
3236
+ }
3237
+ window.localStorage.setItem(mod, '1');
3238
+ window.localStorage.removeItem(mod);
3239
+ }
3240
+ catch (err){
3241
+ supported = false;
3242
+ }
3243
+ }
3244
+
3245
+ /* Make the methods public */
3246
+ _inbound.totalStorage = function(key, value, options){
3247
+ return _inbound.totalStorage.impl.init(key, value);
3248
+ };
3249
+
3250
+ _inbound.totalStorage.setItem = function(key, value){
3251
+ return _inbound.totalStorage.impl.setItem(key, value);
3252
+ };
3253
+
3254
+ _inbound.totalStorage.getItem = function(key){
3255
+ return _inbound.totalStorage.impl.getItem(key);
3256
+ };
3257
+
3258
+ _inbound.totalStorage.getAll = function(){
3259
+ return _inbound.totalStorage.impl.getAll();
3260
+ };
3261
+
3262
+ _inbound.totalStorage.deleteItem = function(key){
3263
+ return _inbound.totalStorage.impl.deleteItem(key);
3264
+ };
3265
+
3266
+
3267
+ _inbound.totalStorage.impl = {
3268
+
3269
+ init: function(key, value){
3270
+ if (typeof value != 'undefined') {
3271
+ return this.setItem(key, value);
3272
+ } else {
3273
+ return this.getItem(key);
3274
+ }
3275
+ },
3276
+
3277
+ setItem: function(key, value){
3278
+ if (!supported){
3279
+ try {
3280
+ _inbound.Utils.createCookie(key, value);
3281
+ return value;
3282
+ } catch(e){
3283
+ console.log('Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie');
3284
+ }
3285
+ }
3286
+ var saver = JSON.stringify(value);
3287
+ ls.setItem(key, saver);
3288
+ return this.parseResult(saver);
3289
+ },
3290
+ getItem: function(key){
3291
+ if (!supported){
3292
+ try {
3293
+ return this.parseResult(_inbound.Utils.readCookie(key));
3294
+ } catch(e){
3295
+ return null;
3296
+ }
3297
+ }
3298
+ var item = ls.getItem(key);
3299
+ return this.parseResult(item);
3300
+ },
3301
+ deleteItem: function(key){
3302
+ if (!supported){
3303
+ try {
3304
+ _inbound.Utils.eraseCookie(key, null);
3305
+ return true;
3306
+ } catch(e){
3307
+ return false;
3308
+ }
3309
+ }
3310
+ ls.removeItem(key);
3311
+ return true;
3312
+ },
3313
+ getAll: function(){
3314
+ var items = [];
3315
+ if (!supported){
3316
+ try {
3317
+ var pairs = document.cookie.split(";");
3318
+ for (var i = 0; i<pairs.length; i++){
3319
+ var pair = pairs[i].split('=');
3320
+ var key = pair[0];
3321
+ items.push({key:key, value:this.parseResult(_inbound.Utils.readCookie(key))});
3322
+ }
3323
+ } catch(e){
3324
+ return null;
3325
+ }
3326
+ } else {
3327
+ for (var j in ls){
3328
+ if (j.length){
3329
+ items.push({key:j, value:this.parseResult(ls.getItem(j))});
3330
+ }
3331
+ }
3332
+ }
3333
+ return items;
3334
+ },
3335
+ parseResult: function(res){
3336
+ var ret;
3337
+ try {
3338
+ ret = JSON.parse(res);
3339
+ if (typeof ret == 'undefined'){
3340
+ ret = res;
3341
+ }
3342
+ if (ret == 'true'){
3343
+ ret = true;
3344
+ }
3345
+ if (ret == 'false'){
3346
+ ret = false;
3347
+ }
3348
+ if (parseFloat(ret) == ret && typeof ret != "object"){
3349
+ ret = parseFloat(ret);
3350
+ }
3351
+ } catch(e){
3352
+ ret = res;
3353
+ }
3354
+ return ret;
3355
+ }
3356
+ };
3357
+ })(_inbound || {});
3358
  /**
3359
  * Leads API functions
3360
  * @param Object _inbound - Main JS object
3442
 
3443
  return _inbound;
3444
 
3445
+ })(_inbound || {});
3446
  /**
3447
  * # Page View Tracking
3448
  *
3750
 
3751
  /* Let's try and fire this last - also defines what constitutes a bounce - */
3752
  var stored = false;
3753
+ jQuery(document).ready(function() {
3754
+
3755
+ if (stored === false) {
3756
  _inbound.PageTracking.storePageView();
3757
  }
3758
+
3759
+ });
3760
  }
3761
  ,
3762
  CheckTimeOut: function() {
3818
 
3819
  return _inbound;
3820
 
3821
+ })(_inbound || {});
3822
  /**
3823
  * # Start
3824
  *
shared/assets/js/frontend/analytics/inboundAnalytics.min.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! Inbound Analyticsv1.0.0 | (c) 2017 Inbound Now | https://github.com/inboundnow/cta */
2
- function inboundFormNoRedirect(){if(null==window.frames.frameElement)e=document.querySelectorAll("button.inbound-button-submit[disabled]")[0];else if("iframe"==window.frames.frameElement.tagName.toLowerCase())var e=window.frames.frameElement.contentWindow.document.querySelectorAll("button.inbound-button-submit")[0];if(void 0!==e){var t=e.form,n=t.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])');0!=n.length&&"IA=="!=n[0].value||(t.action="javascript:void(0)")}}function inboundFormNoRedirectContent(){if(null==window.frames.frameElement)e=document.querySelectorAll("button.inbound-button-submit[disabled]")[0];else if("iframe"==window.frames.frameElement.tagName.toLowerCase())var e=window.frames.frameElement.contentWindow.document.querySelectorAll("button.inbound-button-submit")[0];if(void 0!==e){var t=e.form.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])'),n=jQuery(e).css("background"),o=jQuery(e).css("color"),i=jQuery(e).css("height"),a=e.getElementsByClassName("inbound-form-spinner");0!=t.length&&"IA=="!=t[0].value||(jQuery(a).remove(),jQuery(e).prepend('<div id="redir-check"><i class="fa fa-check-square" aria-hidden="true" style="background='+n+"; color="+o+"; font-size:calc("+i+' * .42);"></i></div>'))}}var inbound_data=inbound_data||{},_inboundOptions=_inboundOptions||{},_gaq=_gaq||[],_inbound=function(e){var t={timeout:inbound_settings.is_admin?500:1e4,formAutoTracking:!0,formAutoPopulation:!0},n={init:function(){_inbound.Utils.init(),_inbound.Utils.domReady(window,function(){_inbound.DomLoaded()})},DomLoaded:function(){_inbound.PageTracking.init(),_inbound.Forms.init(),_inbound.Utils.setUrlParams(),_inbound.LeadsAPI.init(),setTimeout(function(){_inbound.Forms.init()},2e3),_inbound.trigger("analytics_ready")},extend:function(e,t){var n,o={};for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(o[n]=e[n]);for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(o[n]=t[n]);return o},debug:function(e,t){},deBugger:function(e,t,n){if(console){var o,i,a,r=document.location.hash?document.location.hash:"",s=r.indexOf("#debug")>-1,t=t||!1;r&&r.match(/debug/)&&(a=(r=r.split("-"))[1]),i="true"===_inbound.Utils.readCookie("inbound_debug"),((o="true"===_inbound.Utils.readCookie("inbound_debug_"+e))||s||i)&&(t&&"string"==typeof t&&(i||"all"===a?console.log('logAll "'+e+'" =>',t):o?console.log('log "'+e+'" =>',t):e===a&&console.log('#log "'+e+'" =>',t)),n&&n instanceof Function&&n())}}},o=n.extend(t,e);return n.Settings=o||{},n}(_inboundOptions),_inboundHooks=function(e){return e.hooks=new function(){function e(e,t,n,o){if(a[e][t])if(n){var i,r=a[e][t];if(o)for(i=r.length;i--;){var s=r[i];s.callback===n&&s.context===o&&r.splice(i,1)}else for(i=r.length;i--;)r[i].callback===n&&r.splice(i,1)}else a[e][t]=[]}function t(e,t,o,i,r){var s={callback:o,priority:i,context:r},l=a[e][t];l?(l.push(s),l=n(l)):l=[s],a[e][t]=l}function n(e){for(var t,n,o,i=1,a=e.length;i<a;i++){for(t=e[i],n=i;(o=e[n-1])&&o.priority>t.priority;)e[n]=e[n-1],--n;e[n]=t}return e}function o(e,t,n){var o=a[e][t];if(!o)return"filters"===e&&n[0];var i=0,r=o.length;if("filters"===e)for(;i<r;i++)n[0]=o[i].callback.apply(o[i].context,n);else for(;i<r;i++)o[i].callback.apply(o[i].context,n);return"filters"!==e||n[0]}var i={removeFilter:function(t,n){return"string"==typeof t&&e("filters",t,n),i},applyFilters:function(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t?o("filters",t,e):i},addFilter:function(e,n,o,a){return"string"==typeof e&&"function"==typeof n&&t("filters",e,n,o=parseInt(o||10,10)),i},removeAction:function(t,n){return"string"==typeof t&&e("actions",t,n),i},doAction:function(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t&&o("actions",t,e),i},addAction:function(e,n,o,a){return"string"==typeof e&&"function"==typeof n&&t("actions",e,n,o=parseInt(o||10,10),a),i}},a={actions:{},filters:{}};return i},e.add_action=function(){var t=arguments[0].split(" ");for(k in t)arguments[0]="inbound."+t[k],e.hooks.addAction.apply(this,arguments);return this},e.remove_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeAction.apply(this,arguments),this},e.do_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.doAction.apply(this,arguments),this},e.add_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.addFilter.apply(this,arguments),this},e.remove_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeFilter.apply(this,arguments),this},e.apply_filters=function(){return arguments[0]="inbound."+arguments[0],e.hooks.applyFilters.apply(this,arguments)},e}(_inbound||{}),_inboundUtils=function(e){var t,n=window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest,o=(Object.prototype.toString,{api_host:("https:"==location.protocol?"https://":"http://")+location.hostname+location.pathname.replace(/\/$/,""),track_pageview:!0,track_links_timeout:300,cookie_name:"_sp",cookie_expiration:365,cookie_domain:(host=location.hostname.match(/[a-z0-9][a-z0-9\-]+\.[a-z\.]{2,6}$/i))?host[0]:""});return e.Utils={init:function(){this.polyFills(),this.checkLocalStorage(),this.SetUID(),this.storeReferralData()},polyFills:function(){window.console||(window.console={});for(var e=["log","info","warn","error","debug","trace","dir","group","groupCollapsed","groupEnd","time","timeEnd","profile","profileEnd","dirxml","assert","count","markTimeline","timeStamp","clear"],t=0;t<e.length;t++)window.console[e[t]]||(window.console[e[t]]=function(){});Date.prototype.toISOString||function(){function e(e){var t=String(e);return 1===t.length&&(t="0"+t),t}Date.prototype.toISOString=function(){return this.getUTCFullYear()+"-"+e(this.getUTCMonth()+1)+"-"+e(this.getUTCDate())+"T"+e(this.getUTCHours())+":"+e(this.getUTCMinutes())+":"+e(this.getUTCSeconds())+"."+String((this.getUTCMilliseconds()/1e3).toFixed(3)).slice(2,5)+"Z"}}();try{new CustomEvent("?")}catch(e){this.CustomEvent=function(e,t){function n(t,n,o,i){this["init"+e](t,n,o,i),"detail"in this||(this.detail=i)}return function(o,i){var a=document.createEvent(e);return null!==o?n.call(a,o,(i||(i=t)).bubbles,i.cancelable,i.detail):a.initCustomEvent=n,a}}(this.CustomEvent?"CustomEvent":"Event",{bubbles:!1,cancelable:!1,detail:null})}document.querySelectorAll||(document.querySelectorAll=function(e){var t,n=document.createElement("style"),o=[];for(document.documentElement.firstChild.appendChild(n),document._qsa=[],n.styleSheet.cssText=e+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",window.scrollBy(0,0),n.parentNode.removeChild(n);document._qsa.length;)(t=document._qsa.shift()).style.removeAttribute("x-qsa"),o.push(t);return document._qsa=null,o}),document.querySelector||(document.querySelector=function(e){var t=document.querySelectorAll(e);return t.length?t[0]:null}),!("innerText"in document.createElement("a"))&&"getSelection"in window&&HTMLElement.prototype.__defineGetter__("innerText",function(){for(var e,t=window.getSelection(),n=[],o=0;o<t.rangeCount;o++)n[o]=t.getRangeAt(o);t.removeAllRanges(),t.selectAllChildren(this),e=t.toString(),t.removeAllRanges();for(o=0;o<n.length;o++)t.addRange(n[o]);return e})},createCookie:function(e,t,n){var o="";if(n){var i=new Date;i.setTime(i.getTime()+24*n*60*60*1e3),o="; expires="+i.toGMTString()}document.cookie=e+"="+t+o+"; path=/"},readCookie:function(e){for(var t=e+"=",n=document.cookie.split(";"),o=0;o<n.length;o++){for(var i=n[o];" "===i.charAt(0);)i=i.substring(1,i.length);if(0===i.indexOf(t))return i.substring(t.length,i.length)}return null},eraseCookie:function(e){this.createCookie(e,"",-1)},getAllCookies:function(){var t={};if(document.cookie&&""!==document.cookie)for(var n=document.cookie.split(";"),o=0;o<n.length;o++){var i=n[o].split("=");i[0]=i[0].replace(/^ /,""),t[decodeURIComponent(i[0])]=decodeURIComponent(i[1])}return e.totalStorage("inbound_cookies",t),t},setUrlParams:function(){var n={};!function(){for(var e,t=function(e){return decodeURIComponent(e).replace(/\+/g," ")},o=window.location.search.substring(1),i=/([^&=]+)=?([^&]*)/g;e=i.exec(o);)if("-1"==e[1].indexOf("["))n[t(e[1])]=t(e[2]);else{var a=e[1].indexOf("["),r=e[1].slice(a+1,e[1].indexOf("]",a)),s=t(e[1].slice(0,a));"object"!=typeof n[s]&&(n[t(s)]={},n[t(s)].length=0),r?n[t(s)][t(r)]=t(e[2]):Array.prototype.push.call(n[t(s)],t(e[2]))}}();for(var o in n)if("action"!=o)if("object"==typeof n[o])for(var i in n[o])this.createCookie(i,n[o][i],30);else this.createCookie(o,n[o],30);if(t){var a=e.totalStorage("inbound_url_params")||{},r=this.mergeObjs(a,n);e.totalStorage("inbound_url_params",r)}var s={option1:"yo",option2:"woooo"};e.trigger("url_parameters",n,s)},getAllUrlParams:function(){n={};if(t)var n=e.totalStorage("inbound_url_params");return n},getParameterVal:function(e,t){return(RegExp(e+"=(.+?)(&|$)").exec(t)||[,!1])[1]},checkLocalStorage:function(){if("localStorage"in window)try{ls=void 0===window.localStorage?void 0:window.localStorage,t="undefined"!=typeof ls&&void 0!==window.JSON}catch(e){t=!1}return t},showLocalStorageSize:function(){function e(e){return 2*e.length}function t(e){return e/1024/1024}var n=Object.keys(localStorage).map(function(t){return{name:t,size:e(localStorage[t])}}).map(function(e){return e.size=t(e.size).toFixed(2)+" MB",e});console.table(n)},addDays:function(e,t){return new Date(e.getTime()+24*t*60*60*1e3)},GetDate:function(){var e=new Date,t=e.getDate(),n=t<10?"0":"",o=e.getFullYear(),i=e.getHours(),a=i<10?"0":"",r=e.getMinutes(),s=r<10?"0":"",l=e.getSeconds(),u=l<10?"0":"",c=e.getMonth()+1;return o+"/"+(c<10?"0":"")+c+"/"+n+t+" "+a+i+":"+s+r+":"+u+l},SetSessionTimeout:function(){this.readCookie("lead_session_expire");var e=new Date;e.setTime(e.getTime()+18e5),this.createCookie("lead_session_expire",!0,e)},storeReferralData:function(){var t=new Date,n=document.referrer||"Direct Traffic",o=e.Utils.readCookie("inbound_referral_site"),i=e.totalStorage("inbound_original_referral");t.setTime(t.getTime()+18e5),o||this.createCookie("inbound_referral_site",n,t),i||e.totalStorage("inbound_original_referral",i)},CreateUID:function(e){var t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".split(""),n="";e||(e=Math.floor(Math.random()*t.length));for(var o=0;o<e;o++)n+=t[Math.floor(Math.random()*t.length)];return n},generateGUID:function(e){return e?(e^16*Math.random()>>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,guid)},SetUID:function(e){if(!this.readCookie("wp_lead_uid")){var t=e||this.CreateUID(35);this.createCookie("wp_lead_uid",t)}},countProperties:function(e){var t=0;for(var n in e)e.hasOwnProperty(n)&&++t;return t},mergeObjs:function(e,t){var n={};for(var o in e)n[o]=e[o];for(var o in t)n[o]=t[o];return n},hasClass:function(e,t){if("classList"in document.documentElement)n=t.classList.contains(e);else var n=new RegExp("(^|\\s)"+e+"(\\s|$)").test(t.className);return n},addClass:function(e,t){"classList"in document.documentElement?t.classList.add(e):this.hasClass(t,e)||(t.className+=(t.className?" ":"")+e)},removeClass:function(e,t){"classList"in document.documentElement?t.classList.remove(e):this.hasClass(t,e)&&(t.className=t.className.replace(new RegExp("(^|\\s)*"+e+"(\\s|$)*","g"),""))},removeElement:function(e){e.parentNode.removeChild(e)},trim:function(e){return e=e.replace(/(^\s*)|(\s*$)/gi,""),e=e.replace(/[ ]{2,}/gi," "),e=e.replace(/\n /,"\n")},ajaxPolyFill:function(){if("undefined"!=typeof XMLHttpRequest)return new XMLHttpRequest;for(var e,t=["MSXML2.XmlHttp.5.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp.2.0","Microsoft.XmlHttp"],n=0;n<t.length;n++)try{e=new ActiveXObject(t[n]);break}catch(e){}return e},ajaxSendData:function(e,t,n,o,i){var a=this.ajaxPolyFill();setTimeout(function(){a.open(n,e,!0),a.onreadystatechange=function(){4==a.readyState&&t(a.responseText)},"POST"==n&&a.setRequestHeader("Content-type","application/x-www-form-urlencoded"),a.send(o)},100)},ajaxGet:function(e,t,n,o){var i=[];for(var a in t)i.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e+"?"+i.join("&"),n,"GET",null,o)},ajaxPost:function(e,t,n,o){var i=[];for(var a in t)i.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e,n,"POST",i.join("&"),o)},sendEvent:function(e,t,i){t=t||{},async=!0;var a=getCookie();if(a){var r;for(r in a)t[r]=a[r]}t.id||(t.id=getId());var s={e:e,t:(new Date).toISOString(),kv:t},l=o.api_host+"/track?data="+encodeURIComponent(JSON.stringify(s));if(n){var u=new XMLHttpRequest;u.open("GET",l,async),u.withCredentials=async,u.send(null)}else{var c=document.createElement("script");c.type="text/javascript",c.async=async,c.defer=async,c.src=l;var d=document.getElementsByTagName("script")[0];d.parentNode.insertBefore(c,d)}return action(i),self},domReady:function(e,t){var n=!1,o=!0,i=e.document,a=i.documentElement,r=i.addEventListener?"addEventListener":"attachEvent",s=i.addEventListener?"removeEventListener":"detachEvent",l=i.addEventListener?"":"on",u=function(o){"readystatechange"==o.type&&"complete"!=i.readyState||(("load"==o.type?e:i)[s](l+o.type,u,!1),!n&&(n=!0)&&t.call(e,o.type||o))},c=function(){try{a.doScroll("left")}catch(e){return void setTimeout(c,50)}u("poll")};if("complete"==i.readyState)t.call(e,"lazy");else{if(i.createEventObject&&a.doScroll){try{o=!e.frameElement}catch(e){}o&&c()}i[r](l+"DOMContentLoaded",u,!1),i[r](l+"readystatechange",u,!1),e[r](l+"load",u,!1)}},addListener:function(e,t,n){e&&(e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):e["on"+t]=n)},removeListener:function(e,t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):e["on"+t]=null},throttle:function(e,t){var n,o,i,a=null,r=0,s=function(){r=new Date,a=null,i=e.apply(n,o)};return function(){var l=new Date;r||(r=l);var u=t-(l-r);return n=this,o=arguments,u<=0?(clearTimeout(a),a=null,r=l,i=e.apply(n,o)):a||(a=setTimeout(s,u)),i}},checkTypeofGA:function(){"function"==typeof ga&&(universalGA=!0),void 0!==_gaq&&"function"==typeof _gaq.push&&(classicGA=!0),"undefined"!=typeof dataLayer&&"function"==typeof dataLayer.push&&(googleTagManager=!0)},cacheSearchData:function(n,o){if(t){var i=e.totalStorage.getItem("inbound_search_storage");if(i)i.unshift(n),e.totalStorage.setItem("inbound_search_storage",i);else{var a=[n];e.totalStorage.setItem("inbound_search_storage",a)}}else{var r=JSON.stringify(n),s=this.readCookie("inbound_search_storage");s&&(r+="SPLIT-TOKEN"+s),this.createCookie("inbound_search_storage",r,"180")}e.Forms.releaseFormSubmit(o)},storeSearchData:function(){if(inbound_settings.wp_lead_data.lead_id&&inbound_settings.wp_lead_data.lead_nonce){var t=[],n=e.totalStorage.getItem("inbound_search_storage"),o=this.readCookie("inbound_search_storage");if(n||o){if(o){o=o.split("SPLIT-TOKEN");for(var i in o)t.push(JSON.parse(o[i]))}n&&(t=t.concat(n)),t.sort(function(e,t){return e.timestamp-t.timestamp});var a={action:"inbound_search_store",data:t=encodeURIComponent(JSON.stringify(t)),nonce:inbound_settings.wp_lead_data.lead_nonce,lead_id:inbound_settings.wp_lead_data.lead_id};callback=function(t){t&&(t=JSON.parse(t)),t.success&&(console.log(t.success),e.Utils.eraseCookie("inbound_search_storage"),e.totalStorage.deleteItem("inbound_search_storage")),t.error&&console.log(t.error)},this.ajaxPost(inbound_settings.admin_url,a,callback)}}}},e}(_inbound||{}),InboundForms=function(e){var t=e.Utils,n=[],o=[],a=[],r={},s=e.Settings,l=["first name","last name","name","email","e-mail","phone","website","job title","your favorite food","company","tele","address","comment"];if(e.Forms={init:function(){e.Forms.runFieldMappingFilters(),e.Forms.formTrackInit(),e.Forms.searchTrackInit()},runFieldMappingFilters:function(){l=e.hooks.applyFilters("forms.field_map",l)},debug:function(e,t){return},formTrackInit:function(){for(var e=0;e<window.document.forms.length;e++){var t=window.document.forms[e];t.dataset.formProcessed||(t.dataset.formProcessed=!0,this.checkTrackStatus(t)&&(this.attachFormSubmitEvent(t),this.initFormMapping(t)))}},searchTrackInit:function(){if("off"!=inbound_settings.search_tracking&&!r.searchTrackInit){for(var e=0;e<window.document.forms.length;e++){var n=window.document.forms[e];n.dataset.searchChecked||(n.dataset.searchChecked=!0,this.checkSearchTrackStatus(n)&&this.attachSearchFormSubmitEvent(n))}t.storeSearchData(),r.searchTrackInit=!0}},checkTrackStatus:function(t){var n=t.getAttribute("class");if(""!==n&&null!==n)return n.toLowerCase().indexOf("wpl-track-me")>-1||(n.toLowerCase().indexOf("inbound-track")>-1||(cb=function(){console.log(t)},e.deBugger("forms","This form not tracked. Please assign on in settings...",cb),!1))},checkSearchTrackStatus:function(t){var n=t.getAttribute("class"),o=t.getAttribute("id");return""!==n&&null!==n&&n.toLowerCase().indexOf("search")>-1||(""===o||null===o?(cb=function(){console.log(t)},e.deBugger("searches","This search form is not tracked. Please assign on in settings...",cb),!1):o.toLowerCase().indexOf("search")>-1||void 0)},loopClassSelectors:function(n,o){for(var i=n.length-1;i>=0;i--){var a=t.trim(n[i]);-1===a.indexOf("#")&&-1===a.indexOf(".")&&(a="#"+a),(a=document.querySelector(a))&&("add"===o?(e.Utils.addClass("wpl-track-me",a),e.Utils.addClass("inbound-track",a)):(e.Utils.removeClass("wpl-track-me",a),e.Utils.removeClass("inbound-track",a)))}},initFormMapping:function(t){for(var n=[],o=0;o<t.elements.length;o++)formInput=t.elements[o],"hidden"!==formInput.type?(this.mapField(formInput),this.rememberInputValues(formInput),s.formAutoPopulation&&!e.Utils.hasClass("nopopulate",t)&&this.fillInputValues(formInput)):n.push(formInput);for(var i=n.length-1;i>=0;i--)formInput=n[i],this.mapField(formInput)},mapField:function(o){var a=o.id||!1,r=o.name||!1,s=this.getInputLabel(o);if(s&&this.ignoreFieldByLabel(s[0].innerText))return o.dataset.ignoreFormField=!0,!1;for(i=0;i<l.length;i++){var u=!1,c=l[i],d=t.trim(c),m=d.replace(/ /g,"_");r&&r.toLowerCase().indexOf(d)>-1?(u=!0,e.deBugger("forms","Found matching name attribute for -> "+d)):a&&a.toLowerCase().indexOf(d)>-1?(u=!0,e.deBugger("forms","Found matching ID attribute for ->"+d)):s?s[0].innerText.toLowerCase().indexOf(d)>-1&&(u=!0,e.deBugger("forms","Found matching sibling label for -> "+d)):n.push(d),u&&(this.addDataAttr(o,m),this.removeArrayItem(l,d),i--)}return inbound_data},formListener:function(t){t.preventDefault(),e.Forms.saveFormData(t.target),document.body.style.cursor="wait"},searchFormListener:function(t){t.preventDefault(),e.Forms.saveSearchData(t.target)},attachFormSubmitEvent:function(e){t.addListener(e,"submit",this.formListener);document.querySelector(".inbound-email")},attachSearchFormSubmitEvent:function(e){t.addListener(e,"submit",this.searchFormListener)},ignoreFieldByLabel:function(t){var n=!1;return!!t&&(-1==t.toLowerCase().indexOf("credit card")&&-1==t.toLowerCase().indexOf("card number")||(n=!0),-1==t.toLowerCase().indexOf("expiration")&&-1==t.toLowerCase().indexOf("expiry")||(n=!0),"month"!=t.toLowerCase()&&"mm"!=t.toLowerCase()&&"yy"!=t.toLowerCase()&&"yyyy"!=t.toLowerCase()&&"year"!=t.toLowerCase()||(n=!0),-1==t.toLowerCase().indexOf("cvv")&&-1==t.toLowerCase().indexOf("cvc")&&-1==t.toLowerCase().indexOf("secure code")&&-1==t.toLowerCase().indexOf("security code")||(n=!0),n&&e.deBugger("forms","ignore "+t),n)},ignoreFieldByValue:function(e){var t=!1;if(!e)return!1;if("visa"!=e.toLowerCase()&&"mastercard"!=e.toLowerCase()&&"american express"!=e.toLowerCase()&&"amex"!=e.toLowerCase()&&"discover"!=e.toLowerCase()||(t=!0),new RegExp("/^[0-9]+$/").test(e)){var n=e.replace(" ","");this.isInt(n)&&n.length>=16&&(t=!0)}return t},isInt:function(e){return"number"==typeof e&&isFinite(e)&&e%1==0},releaseFormSubmit:function(e){document.body.style.cursor="default",t.removeClass("wpl-track-me",e),t.removeListener(e,"submit",this.formListener);var n=e.getAttribute("class");if(""!==n&&null!==n&&-1!=n.toLowerCase().indexOf("wpcf7-form"))return setTimeout(function(){document.body.style.cursor="default"},300),!0;"function"==typeof e.submit?e.submit():"function"==typeof e.click&&jQuery("#"+e.id).find("button").click(),setTimeout(function(){for(var t=0;t<e.elements.length;t++)formInput=e.elements[t],type=formInput.type||!1,"submit"===type&&"submit"===formInput.name&&e.elements[t].click()},2e3)},saveFormData:function(n){for(var i=i||{},r=0;r<n.elements.length;r++)if(formInput=n.elements[r],multiple=!1,formInput.name){if(formInput.dataset.ignoreFormField){e.deBugger("forms","ignore "+formInput.name);continue}switch(inputName=formInput.name.replace(/\[([^\[]*)\]/g,"%5B%5D$1"),i[inputName]||(i[inputName]={}),formInput.type&&(i[inputName].type=formInput.type),i[inputName].name||(i[inputName].name=formInput.name),formInput.dataset.mapFormField&&(i[inputName].map=formInput.dataset.mapFormField),formInput.nodeName){case"INPUT":if(!1===(l=this.getInputValue(formInput)))continue;break;case"TEXTAREA":l=formInput.value;break;case"SELECT":if(formInput.multiple){values=[],multiple=!0;for(var s=0;s<formInput.length;s++)formInput[s].selected&&values.push(encodeURIComponent(formInput[s].value))}else l=formInput.value}if(e.deBugger("forms","Input Value = "+l),l){i[inputName].value||(i[inputName].value=[]),i[inputName].value.push(multiple?values.join(","):encodeURIComponent(l));var l=multiple?values.join(","):encodeURIComponent(l)}}e.deBugger("forms",i);for(var u in i){var c=i[u].value,d=i[u].map;if(void 0!==c&&null!=c&&""!=c&&o.push(u+"="+i[u].value.join(",")),void 0!==d&&null!=d&&i[u].value&&(a.push(d+"="+i[u].value.join(",")),"email"===u))var m=i[u].value.join(",")}var f=o.join("&");e.deBugger("forms","Stringified Raw Form PARAMS: "+f);var g=a.join("&");e.deBugger("forms","Stringified Mapped PARAMS"+g),(m=t.getParameterVal("email",g)||t.readCookie("wp_lead_email"))||(m=t.getParameterVal("wpleads_email_address",g));var p=t.getParameterVal("name",g),h=t.getParameterVal("first_name",g),v=t.getParameterVal("last_name",g);if(!v&&h&&(_=decodeURI(h).split(" ")).length>0&&(h=_[0],v=_[1]),p&&!v&&!h){var _=decodeURI(p).split(" ");_.length>0&&(h=_[0],v=_[1])}p=h&&v?h+" "+v:p,h||(h=""),v||(v=""),e.deBugger("forms","fName = "+h),e.deBugger("forms","lName = "+v),e.deBugger("forms","fullName = "+p);var b=e.totalStorage("page_views")||{},y=e.totalStorage("inbound_url_params")||{},w=n.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])'),k=!1;if(0==w.length||"IA=="==w[0].value)k=!0;var S=n.querySelectorAll('input[value][type="hidden"][name="inbound_form_id"]');S=S.length>0?S[0].value:0;if("undefined"!=typeof landing_path_info)I=landing_path_info.variation;else if("undefined"!=typeof cta_path_info)I=cta_path_info.variation;else var I=inbound_settings.variation_id;var C=inbound_settings.post_type||"page",L=inbound_settings.post_id||0;search_data={},formData={action:"inbound_lead_store",email:m,full_name:p,first_name:h,last_name:v,raw_params:f,mapped_params:g,url_params:JSON.stringify(y),search_data:"test",page_views:JSON.stringify(b),post_type:C,page_id:L,variation:I,source:t.readCookie("inbound_referral_site"),inbound_submitted:k,inbound_form_id:S,inbound_nonce:inbound_settings.ajax_nonce,event:n},callback=function(o){e.deBugger("forms","Lead Created with ID: "+o),o=parseInt(o,10),formData.leadID=o,o&&(t.createCookie("wp_lead_id",o),e.totalStorage.deleteItem("page_views"),e.totalStorage.deleteItem("tracking_events")),e.trigger("form_after_submission",formData),e.Forms.releaseFormSubmit(n)},e.trigger("form_before_submission",formData),t.ajaxPost(inbound_settings.admin_url,formData,callback)},saveSearchData:function(n){for(var o=o||{},i=0;i<n.elements.length;i++)if(formInput=n.elements[i],multiple=!1,formInput.name){if(formInput.dataset.ignoreFormField){e.deBugger("searches","ignore "+formInput.name);continue}switch(d=formInput.name.replace(/\[([^\[]*)\]/g,"%5B%5D$1"),o[d]||(o[d]={}),formInput.type&&(o[d].type=formInput.type),o[d].name||(o[d].name=formInput.name),formInput.dataset.mapFormField&&(o[d].map=formInput.dataset.mapFormField),formInput.nodeName){case"INPUT":if(!1===(r=this.getInputValue(formInput)))continue;break;case"TEXTAREA":r=formInput.value;break;case"SELECT":if(formInput.multiple){values=[],multiple=!0;for(var a=0;a<formInput.length;a++)formInput[a].selected&&values.push(encodeURIComponent(formInput[a].value))}else r=formInput.value}if(e.deBugger("searches","Input Value = "+r),r){o[d].value||(o[d].value=[]),o[d].value.push(multiple?values.join(","):encodeURIComponent(r));var r=multiple?values.join(","):encodeURIComponent(r)}}e.deBugger("searches",o);var s=[];for(var l in o){var u=o[l].value,c=o[l].type,d=o[l].name;void 0!==u&&null!=u&&""!=u&&("search"==c?s.push("search_text|value|"+o[l].value):"s"==d&&s.push("search_text|value|"+o[l].value))}s[0]||e.Forms.releaseFormSubmit(n);var m=s.join("|field|");if(e.deBugger("searches","Stringified Search Form PARAMS: "+m),"undefined"!=typeof landing_path_info)f=landing_path_info.variation;else if("undefined"!=typeof cta_path_info)f=cta_path_info.variation;else var f=inbound_settings.variation_id;var g=inbound_settings.post_type||"page",p=inbound_settings.post_id||0,h=t.readCookie("wp_lead_uid");inbound_settings.wp_lead_data.lead_email?email=inbound_settings.wp_lead_data.lead_email:t.readCookie("inbound_wpleads_email_address")?email=t.readCookie("inbound_wpleads_email_address"):email="",searchData={email:email,search_data:m,user_UID:h,post_type:g,page_id:p,variation:f,source:t.readCookie("inbound_referral_site"),ip_address:inbound_settings.ip_address,timestamp:Math.floor((new Date).getTime()/1e3)},e.trigger("search_before_caching",searchData),inbound_settings.wp_lead_data.lead_id?(searchData.lead_id=inbound_settings.wp_lead_data.lead_id,t.cacheSearchData(searchData,n)):t.cacheSearchData(searchData,n)},rememberInputValues:function(n){n.name&&n.name;var o=n.type?n.type:"text";if("submit"===o||"hidden"===o||"file"===o||"password"===o||n.dataset.ignoreFormField)return!1;t.addListener(n,"change",function(n){if(n.target.name){if("checkbox"!==o)var i=n.target.value;else for(var a=[],r=document.querySelectorAll('input[name="'+n.target.name+'"]'),s=0;s<r.length;s++)r[s].checked&&a.push(r[s].value),i=a.join(",");inputData={name:n.target.name,node:n.target.nodeName.toLowerCase(),type:o,value:i,mapping:n.target.dataset.mapFormField},e.trigger("form_input_change",inputData),t.createCookie("inbound_"+n.target.name,encodeURIComponent(i))}})},fillInputValues:function(e){var n=e.name?"inbound_"+e.name:"",o=e.type?e.type:"text";if("submit"===o||"hidden"===o||"file"===o||"password"===o)return!1;if(t.readCookie(n)&&"comment"!=n)if(value=decodeURIComponent(t.readCookie(n)),"checkbox"===o||"radio"===o)for(var i=value.split(","),a=0;a<i.length;a++)e.value.indexOf(i[a])>-1&&(e.checked=!0);else"undefined"!==value&&(e.value=value)},getInputLabel:function(e){var t;return(t=this.siblingsIsLabel(e))?t:!!(t=this.CheckParentForLabel(e))&&t},getInputValue:function(e){var t=!1;switch(e.type){case"radio":case"checkbox":e.checked&&(t=e.value);break;case"text":case"hidden":default:t=e.value}return t},addDataAttr:function(e,t){for(var n=document.getElementsByName(e.name),o=n.length-1;o>=0;o--)e.dataset.mapFormField||(n[o].dataset.mapFormField=t)},removeArrayItem:function(e,t){if(e.indexOf)index=e.indexOf(t);else for(index=e.length-1;index>=0&&e[index]!==t;--index);index>=0&&e.splice(index,1)},siblingsIsLabel:function(e){for(var t=this.getSiblings(e),n=[],o=t.length-1;o>=0;o--)"label"===t[o].nodeName.toLowerCase()&&n.push(t[o]);return n.length>0&&n.length<2&&n},getChildren:function(e,t){for(var n=[];e;e=e.nextSibling)1==e.nodeType&&e!=t&&n.push(e);return n},getSiblings:function(e){return this.getChildren(e.parentNode.firstChild,e)},CheckParentForLabel:function(e){if("FORM"===e.nodeName)return null;do{var t=e.getElementsByTagName("label");if(t.length>0&&t.length<2)return e.getElementsByTagName("label")}while(e=e.parentNode);return null},mailCheck:function(){var e=document.querySelector(".inbound-email");e&&(t.addListener(e,"blur",this.mailCheck),u.run({email:document.querySelector(".inbound-email").value,suggested:function(n){var o=document.querySelector(".email_suggestion");o&&t.removeElement(o);var i=document.createElement("span");i.innerHTML="<span class=\"email_suggestion\">Did youu mean <b><i id='email_correction' style='cursor: pointer;' title=\"click to update\">"+n.full+"</b></i>?</span>",e.parentNode.insertBefore(i,e.nextSibling);var a=document.getElementById("email_correction");t.addListener(a,"click",function(){e.value=a.innerHTML,a.parentNode.parentNode.innerHTML="Fixed!"})},empty:function(){}}))}},void 0===u)var u={domainThreshold:1,topLevelThreshold:3,defaultDomains:["yahoo.com","google.com","hotmail.com","gmail.com","me.com","aol.com","mac.com","live.com","comcast.net","googlemail.com","msn.com","hotmail.co.uk","yahoo.co.uk","facebook.com","verizon.net","sbcglobal.net","att.net","gmx.com","mail.com","outlook.com","icloud.com"],defaultTopLevelDomains:["co.jp","co.uk","com","net","org","info","edu","gov","mil","ca","de"],run:function(e){e.domains=e.domains||u.defaultDomains,e.topLevelDomains=e.topLevelDomains||u.defaultTopLevelDomains,e.distanceFunction=e.distanceFunction||u.sift3Distance;var t=function(e){return e},n=e.suggested||t,o=e.empty||t,i=u.suggest(u.encodeEmail(e.email),e.domains,e.topLevelDomains,e.distanceFunction);return i?n(i):o()},suggest:function(e,t,n,o){e=e.toLowerCase();var i=this.splitEmail(e),a=this.findClosestDomain(i.domain,t,o,this.domainThreshold);if(a){if(a!=i.domain)return{address:i.address,domain:a,full:i.address+"@"+a}}else{var r=this.findClosestDomain(i.topLevelDomain,n,o,this.topLevelThreshold);if(i.domain&&r&&r!=i.topLevelDomain){var s=i.domain;return a=s.substring(0,s.lastIndexOf(i.topLevelDomain))+r,{address:i.address,domain:a,full:i.address+"@"+a}}}return!1},findClosestDomain:function(e,t,n,o){o=o||this.topLevelThreshold;var i,a=99,r=null;if(!e||!t)return!1;n||(n=this.sift3Distance);for(var s=0;s<t.length;s++){if(e===t[s])return e;(i=n(e,t[s]))<a&&(a=i,r=t[s])}return a<=o&&null!==r&&r},sift3Distance:function(e,t){if(null===e||0===e.length)return null===t||0===t.length?0:t.length;if(null===t||0===t.length)return e.length;for(var n=0,o=0,i=0,a=0;n+o<e.length&&n+i<t.length;){if(e.charAt(n+o)==t.charAt(n+i))a++;else{o=0,i=0;for(var r=0;r<5;r++){if(n+r<e.length&&e.charAt(n+r)==t.charAt(n)){o=r;break}if(n+r<t.length&&e.charAt(n)==t.charAt(n+r)){i=r;break}}}n++}return(e.length+t.length)/2-a},splitEmail:function(e){var t=e.trim().split("@");if(t.length<2)return!1;for(a=0;a<t.length;a++)if(""===t[a])return!1;var n=t.pop(),o=n.split("."),i="";if(0===o.length)return!1;if(1==o.length)i=o[0];else{for(var a=1;a<o.length;a++)i+=o[a]+".";o.length>=2&&(i=i.substring(0,i.length-1))}return{topLevelDomain:i,domain:n,address:t.join("@")}},encodeEmail:function(e){var t=encodeURI(e);return t=t.replace("%20"," ").replace("%25","%").replace("%5E","^").replace("%60","`").replace("%7B","{").replace("%7C","|").replace("%7D","}")}};return e}(_inbound||{}),_inboundEvents=function(e){function t(t,o,i){var o=o||{};(i=i||{}).bubbles=i.bubbles||!0,i.cancelable=i.cancelable||!0,o=e.apply_filters("filter_"+t,o);!window.ActiveXObject&&window;if("function"==typeof CustomEvent)var a=new CustomEvent(t,{detail:o,bubbles:i.bubbles,cancelable:i.cancelable});else(a=document.createEvent("Event")).initEvent(t,!0,!0);window.dispatchEvent(a),e.do_action(t,o),n(t,o)}function n(e,t){if(window.jQuery){var t=t||{};jQuery(document).trigger(e,t)}}e.trigger=function(t,n){e.Events[t](n)};return e.Events={analytics_ready:function(){t("analytics_ready",{data:"xyxy"},{opt1:!0})},url_parameters:function(e){t("url_parameters",e)},session_start:function(){console.log(""),t("session_start")},session_end:function(e){t("session_end",e),console.log("Session End")},session_active:function(){t("session_active")},session_idle:function(e){t("session_idle",e)},session_resume:function(){t("session_resume")},session_heartbeat:function(e){t("session_heartbeat",{clock:e,leadData:InboundLeadData})},page_visit:function(e){t("page_view",e)},page_first_visit:function(n){t("page_first_visit"),e.deBugger("pages","First Ever Page View of this Page")},page_revisit:function(n){t("page_revisit",n);e.deBugger("pages",status,function(){console.log("pageData",n),console.log("Page Revisit viewed "+n+" times")})},tab_hidden:function(n){e.deBugger("pages","Tab Hidden"),t("tab_hidden")},tab_visible:function(n){e.deBugger("pages","Tab Visible"),t("tab_visible")},tab_mouseout:function(n){e.deBugger("pages","Tab Mouseout"),t("tab_mouseout")},form_input_change:function(n){e.deBugger("forms","inputData change. Data=",function(){console.log(n)}),t("form_input_change",n)},form_before_submission:function(e){t("form_before_submission",e)},form_after_submission:function(e){t("form_after_submission",e)},search_before_caching:function(e){t("search_before_caching",e)},analyticsError:function(e,t,n){var o=new CustomEvent("inbound_analytics_error",{detail:{MLHttpRequest:e,textStatus:t,errorThrown:n}});window.dispatchEvent(o),console.log("Page Save Error")}},e}(_inbound||{});_inbound.add_action("form_before_submission",inboundFormNoRedirect,10),_inbound.add_action("form_after_submission",inboundFormNoRedirectContent,10);var InboundTotalStorage=function(e){var t,n;if("localStorage"in window)try{n=void 0===window.localStorage?void 0:window.localStorage,t=void 0!==n&&void 0!==window.JSON,window.localStorage.setItem("_inbound","1"),window.localStorage.removeItem("_inbound")}catch(e){t=!1}e.totalStorage=function(t,n,o){return e.totalStorage.impl.init(t,n)},e.totalStorage.setItem=function(t,n){return e.totalStorage.impl.setItem(t,n)},e.totalStorage.getItem=function(t){return e.totalStorage.impl.getItem(t)},e.totalStorage.getAll=function(){return e.totalStorage.impl.getAll()},e.totalStorage.deleteItem=function(t){return e.totalStorage.impl.deleteItem(t)},e.totalStorage.impl={init:function(e,t){return void 0!==t?this.setItem(e,t):this.getItem(e)},setItem:function(o,i){if(!t)try{return e.Utils.createCookie(o,i),i}catch(e){console.log("Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie")}var a=JSON.stringify(i);return n.setItem(o,a),this.parseResult(a)},getItem:function(o){if(!t)try{return this.parseResult(e.Utils.readCookie(o))}catch(e){return null}var i=n.getItem(o);return this.parseResult(i)},deleteItem:function(o){if(!t)try{return e.Utils.eraseCookie(o,null),!0}catch(e){return!1}return n.removeItem(o),!0},getAll:function(){var o=[];if(t)for(var i in n)i.length&&o.push({key:i,value:this.parseResult(n.getItem(i))});else try{for(var a=document.cookie.split(";"),r=0;r<a.length;r++){var s=a[r].split("=")[0];o.push({key:s,value:this.parseResult(e.Utils.readCookie(s))})}}catch(e){return null}return o},parseResult:function(e){var t;try{void 0===(t=JSON.parse(e))&&(t=e),"true"==t&&(t=!0),"false"==t&&(t=!1),parseFloat(t)==t&&"object"!=typeof t&&(t=parseFloat(t))}catch(n){t=e}return t}}}(_inbound||{}),_inboundLeadsAPI=function(e){return e.LeadsAPI={init:function(){var t=e.Utils,n=(t.readCookie("wp_lead_uid"),t.readCookie("wp_lead_id"));t.readCookie("lead_data_expire")||(e.deBugger("leads","expired vistor. Run Processes"),n&&e.LeadsAPI.getAllLeadData())},setGlobalLeadData:function(e){InboundLeadData=e},getAllLeadData:function(t){var n=e.Utils.readCookie("wp_lead_id"),o=e.totalStorage("inbound_lead_data"),i=e.Utils.readCookie("lead_data_expire");data={action:"inbound_get_all_lead_data",wp_lead_id:n},success=function(t){var n=JSON.parse(t);e.LeadsAPI.setGlobalLeadData(n),e.totalStorage("inbound_lead_data",n);var o=new Date;o.setTime(o.getTime()+18e5);var i=e.Utils.addDays(o,3);e.Utils.createCookie("lead_data_expire",!0,i)},o?(e.LeadsAPI.setGlobalLeadData(o),e.deBugger("lead","Set Global Lead Data from Localstorage"),i||(e.Utils.ajaxPost(inbound_settings.admin_url,data,success),e.deBugger("lead","localized data old. Pull new from DB"))):e.Utils.ajaxPost(inbound_settings.admin_url,data,success)},getLeadLists:function(){var t={action:"wpl_check_lists",wp_lead_id:e.Utils.readCookie("wp_lead_id")};e.Utils.ajaxPost(inbound_settings.admin_url,t,function(t){e.Utils.createCookie("lead_session_list_check",!0,{path:"/",expires:1}),e.deBugger("lead","Lists checked")})}},e}(_inbound||{}),_inboundPageTracking=function(e){var t,n,o=!1,i=!1,a=!1,r=parseInt(e.Utils.readCookie("lead_session"),10)||0,s=0,l=(new Date,null),u=null,c=null,d=e.Utils,m=e.Utils.GetDate(),f="page_views",g=e.totalStorage(f)||{},p=inbound_settings.post_id||window.location.pathname;e.Settings.timeout;return e.PageTracking={init:function(o){var i=this.isRevisit(g);this.triggerPageView(i),o=o||{},t=parseInt(o.reportInterval,10)||10,n=parseInt(o.idleTimeout,10)||3,d.addListener(document,"keydown",d.throttle(e.PageTracking.pingSession,1e3)),d.addListener(document,"click",d.throttle(e.PageTracking.pingSession,1e3)),d.addListener(window,"mousemove",d.throttle(e.PageTracking.pingSession,1e3)),e.PageTracking.checkVisibility(),this.startSession()},setIdle:function(t){var n="Session IDLE. Activity Timeout due to "+(t=t||"No Movement");e.deBugger("pages",n),clearTimeout(e.PageTracking.idleTimer),e.PageTracking.stopClock(),e.trigger("session_idle")},checkVisibility:function(){var t,n;void 0!==document.hidden?(t="hidden",n="visibilitychange"):void 0!==document.mozHidden?(t="mozHidden",n="mozvisibilitychange"):void 0!==document.msHidden?(t="msHidden",n="msvisibilitychange"):void 0!==document.webkitHidden&&(t="webkitHidden",n="webkitvisibilitychange");var o=document[t];e.Utils.addListener(document,n,function(n){o!=document[t]&&(document[t]?(e.trigger("tab_hidden"),e.PageTracking.setIdle("browser tab switch")):(e.trigger("tab_visible"),e.PageTracking.pingSession()),o=document[t])})},clock:function(){var n="Total time spent on Page in this Session: "+((r+=1)/60).toFixed(2)+" min";if(e.deBugger("pages",n),r>0&&r%t==0){var o=new Date;o.setTime(o.getTime()+18e5),d.createCookie("lead_session",r,o),e.trigger("session_heartbeat",r)}},inactiveClock:function(){var t="Time until Session Timeout: "+((1800-(s+=1))/60).toFixed(2)+" min";e.deBugger("pages",t),s>1800&&(e.trigger("session_end",InboundLeadData),e.Utils.eraseCookie("lead_session"),s=0,clearTimeout(u))},stopClock:function(){i=!0,clearTimeout(l),clearTimeout(u),u=setInterval(e.PageTracking.inactiveClock,1e3)},restartClock:function(){i=!1,e.trigger("session_resume"),e.deBugger("pages","Activity resumed. Session Active"),clearTimeout(l),s=0,clearTimeout(u),l=setInterval(e.PageTracking.clock,1e3)},turnOff:function(){e.PageTracking.setIdle(),a=!0},turnOn:function(){a=!1},startSession:function(){new Date;if(o=!0,l=setInterval(e.PageTracking.clock,1e3),d.readCookie("lead_session"))e.trigger("session_active");else{e.trigger("session_start");var t=new Date;t.setTime(t.getTime()+18e5),e.Utils.createCookie("lead_session",1,t)}this.pingSession()},resetInactiveFunc:function(){s=0,clearTimeout(u)},pingSession:function(t){a||(o||e.PageTracking.startSession(),i&&e.PageTracking.restartClock(),clearTimeout(c),c=setTimeout(e.PageTracking.setIdle,1e3*n+100),void 0!==t&&"mousemove"===t.type&&e.PageTracking.mouseEvents(t))},mouseEvents:function(t){t.pageY<=5&&e.trigger("tab_mouseout")},getPageViews:function(){if(e.Utils.checkLocalStorage()){var t=localStorage.getItem(f),n=JSON.parse(t);return n}},isRevisit:function(e){var t=!1,n=(e=e||{})[p];return void 0!==n&&null!==n&&(t=!0),t},triggerPageView:function(t){var n={title:document.title,url:document.location.href,path:document.location.pathname,count:1};t?(g[p].push(m),n.count=g[p].length,e.trigger("page_revisit",n)):(g[p]=[],g[p].push(m),e.trigger("page_first_visit",n)),e.trigger("page_visit",n),e.totalStorage(f,g);document.onreadystatechange=function(){"loading"!==document.readyState&&e.PageTracking.storePageView()}},CheckTimeOut:function(){e.deBugger("pages",status)},storePageView:function(){"off"==inbound_settings.page_tracking&&"landing-page"!=inbound_settings.post_type||setTimeout(function(){var t=e.Utils.readCookie("wp_lead_id")?e.Utils.readCookie("wp_lead_id"):"",n=e.Utils.readCookie("wp_lead_uid")?e.Utils.readCookie("wp_lead_uid"):"",o=e.totalStorage("wp_cta_loaded"),i=e.totalStorage("wp_cta_impressions");stored=!0,e.totalStorage("wp_cta_impressions",{});var a={action:"inbound_track_lead",wp_lead_uid:n,wp_lead_id:t,page_id:inbound_settings.post_id,variation_id:inbound_settings.variation_id,post_type:inbound_settings.post_type,current_url:window.location.href,page_views:JSON.stringify(e.PageTracking.getPageViews()),cta_impressions:JSON.stringify(i),cta_history:JSON.stringify(o),json:"0"};e.Utils.ajaxPost(inbound_settings.admin_url,a,function(e){})},200)}},e}(_inbound||{});_inbound.init(),InboundLeadData=_inbound.totalStorage("inbound_lead_data")||null;
1
+ /*! Inbound Analyticsv1.0.0 | (c) 2018 Inbound Now | https://github.com/inboundnow/cta */
2
+ function inboundFormNoRedirect(){if(null==window.frames.frameElement)e=document.querySelectorAll("button.inbound-button-submit[disabled]")[0];else if("iframe"==window.frames.frameElement.tagName.toLowerCase())var e=window.frames.frameElement.contentWindow.document.querySelectorAll("button.inbound-button-submit")[0];if(void 0!==e){var t=e.form,n=t.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])');0!=n.length&&"IA=="!=n[0].value||(t.action="javascript:void(0)")}}function inboundFormNoRedirectContent(){if(null==window.frames.frameElement)e=document.querySelectorAll("button.inbound-button-submit[disabled]")[0];else if("iframe"==window.frames.frameElement.tagName.toLowerCase())var e=window.frames.frameElement.contentWindow.document.querySelectorAll("button.inbound-button-submit")[0];if(void 0!==e){var t=e.form.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])'),n=jQuery(e).css("background"),o=jQuery(e).css("color"),i=jQuery(e).css("height"),a=e.getElementsByClassName("inbound-form-spinner");0!=t.length&&"IA=="!=t[0].value||(jQuery(a).remove(),jQuery(e).prepend('<div id="redir-check"><i class="fa fa-check-square" aria-hidden="true" style="background='+n+"; color="+o+"; font-size:calc("+i+' * .42);"></i></div>'))}}var inbound_data=inbound_data||{},_inboundOptions=_inboundOptions||{},_gaq=_gaq||[],_inbound=function(e){var t={timeout:inbound_settings.is_admin?500:1e4,formAutoTracking:!0,formAutoPopulation:!0},n={init:function(){_inbound.Utils.init(),_inbound.Utils.domReady(window,function(){_inbound.DomLoaded()})},DomLoaded:function(){_inbound.PageTracking.init(),_inbound.Forms.init(),_inbound.Utils.setUrlParams(),_inbound.LeadsAPI.init(),setTimeout(function(){_inbound.Forms.init()},2e3),_inbound.trigger("analytics_ready")},extend:function(e,t){var n,o={};for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(o[n]=e[n]);for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(o[n]=t[n]);return o},debug:function(e,t){},deBugger:function(e,t,n){if(console){var o,i,a,r=document.location.hash?document.location.hash:"",s=r.indexOf("#debug")>-1,t=t||!1;r&&r.match(/debug/)&&(a=(r=r.split("-"))[1]),i="true"===_inbound.Utils.readCookie("inbound_debug"),((o="true"===_inbound.Utils.readCookie("inbound_debug_"+e))||s||i)&&(t&&"string"==typeof t&&(i||"all"===a?console.log('logAll "'+e+'" =>',t):o?console.log('log "'+e+'" =>',t):e===a&&console.log('#log "'+e+'" =>',t)),n&&n instanceof Function&&n())}}},o=n.extend(t,e);return n.Settings=o||{},n}(_inboundOptions),_inboundHooks=function(e){return e.hooks=new function(){function e(e,t,n,o){if(a[e][t])if(n){var i,r=a[e][t];if(o)for(i=r.length;i--;){var s=r[i];s.callback===n&&s.context===o&&r.splice(i,1)}else for(i=r.length;i--;)r[i].callback===n&&r.splice(i,1)}else a[e][t]=[]}function t(e,t,o,i,r){var s={callback:o,priority:i,context:r},l=a[e][t];l?(l.push(s),l=n(l)):l=[s],a[e][t]=l}function n(e){for(var t,n,o,i=1,a=e.length;i<a;i++){for(t=e[i],n=i;(o=e[n-1])&&o.priority>t.priority;)e[n]=e[n-1],--n;e[n]=t}return e}function o(e,t,n){var o=a[e][t];if(!o)return"filters"===e&&n[0];var i=0,r=o.length;if("filters"===e)for(;i<r;i++)n[0]=o[i].callback.apply(o[i].context,n);else for(;i<r;i++)o[i].callback.apply(o[i].context,n);return"filters"!==e||n[0]}var i={removeFilter:function(t,n){return"string"==typeof t&&e("filters",t,n),i},applyFilters:function(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t?o("filters",t,e):i},addFilter:function(e,n,o,a){return"string"==typeof e&&"function"==typeof n&&t("filters",e,n,o=parseInt(o||10,10)),i},removeAction:function(t,n){return"string"==typeof t&&e("actions",t,n),i},doAction:function(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t&&o("actions",t,e),i},addAction:function(e,n,o,a){return"string"==typeof e&&"function"==typeof n&&t("actions",e,n,o=parseInt(o||10,10),a),i}},a={actions:{},filters:{}};return i},e.add_action=function(){var t=arguments[0].split(" ");for(k in t)arguments[0]="inbound."+t[k],e.hooks.addAction.apply(this,arguments);return this},e.remove_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeAction.apply(this,arguments),this},e.do_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.doAction.apply(this,arguments),this},e.add_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.addFilter.apply(this,arguments),this},e.remove_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeFilter.apply(this,arguments),this},e.apply_filters=function(){return arguments[0]="inbound."+arguments[0],e.hooks.applyFilters.apply(this,arguments)},e}(_inbound||{}),_inboundUtils=function(e){var t,n=window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest,o=(Object.prototype.toString,{api_host:("https:"==location.protocol?"https://":"http://")+location.hostname+location.pathname.replace(/\/$/,""),track_pageview:!0,track_links_timeout:300,cookie_name:"_sp",cookie_expiration:365,cookie_domain:(host=location.hostname.match(/[a-z0-9][a-z0-9\-]+\.[a-z\.]{2,6}$/i))?host[0]:""});return e.Utils={init:function(){this.polyFills(),this.checkLocalStorage(),this.SetUID(),this.storeReferralData()},polyFills:function(){window.console||(window.console={});for(var e=["log","info","warn","error","debug","trace","dir","group","groupCollapsed","groupEnd","time","timeEnd","profile","profileEnd","dirxml","assert","count","markTimeline","timeStamp","clear"],t=0;t<e.length;t++)window.console[e[t]]||(window.console[e[t]]=function(){});Date.prototype.toISOString||function(){function e(e){var t=String(e);return 1===t.length&&(t="0"+t),t}Date.prototype.toISOString=function(){return this.getUTCFullYear()+"-"+e(this.getUTCMonth()+1)+"-"+e(this.getUTCDate())+"T"+e(this.getUTCHours())+":"+e(this.getUTCMinutes())+":"+e(this.getUTCSeconds())+"."+String((this.getUTCMilliseconds()/1e3).toFixed(3)).slice(2,5)+"Z"}}();try{new CustomEvent("?")}catch(e){this.CustomEvent=function(e,t){function n(t,n,o,i){this["init"+e](t,n,o,i),"detail"in this||(this.detail=i)}return function(o,i){var a=document.createEvent(e);return null!==o?n.call(a,o,(i||(i=t)).bubbles,i.cancelable,i.detail):a.initCustomEvent=n,a}}(this.CustomEvent?"CustomEvent":"Event",{bubbles:!1,cancelable:!1,detail:null})}document.querySelectorAll||(document.querySelectorAll=function(e){var t,n=document.createElement("style"),o=[];for(document.documentElement.firstChild.appendChild(n),document._qsa=[],n.styleSheet.cssText=e+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",window.scrollBy(0,0),n.parentNode.removeChild(n);document._qsa.length;)(t=document._qsa.shift()).style.removeAttribute("x-qsa"),o.push(t);return document._qsa=null,o}),document.querySelector||(document.querySelector=function(e){var t=document.querySelectorAll(e);return t.length?t[0]:null}),!("innerText"in document.createElement("a"))&&"getSelection"in window&&HTMLElement.prototype.__defineGetter__("innerText",function(){for(var e,t=window.getSelection(),n=[],o=0;o<t.rangeCount;o++)n[o]=t.getRangeAt(o);t.removeAllRanges(),t.selectAllChildren(this),e=t.toString(),t.removeAllRanges();for(o=0;o<n.length;o++)t.addRange(n[o]);return e})},createCookie:function(e,t,n){var o="";if(n){var i=new Date;i.setTime(i.getTime()+24*n*60*60*1e3),o="; expires="+i.toGMTString()}document.cookie=e+"="+t+o+"; path=/"},readCookie:function(e){for(var t=e+"=",n=document.cookie.split(";"),o=0;o<n.length;o++){for(var i=n[o];" "===i.charAt(0);)i=i.substring(1,i.length);if(0===i.indexOf(t))return i.substring(t.length,i.length)}return null},eraseCookie:function(e){this.createCookie(e,"",-1)},getAllCookies:function(){var t={};if(document.cookie&&""!==document.cookie)for(var n=document.cookie.split(";"),o=0;o<n.length;o++){var i=n[o].split("=");i[0]=i[0].replace(/^ /,""),t[decodeURIComponent(i[0])]=decodeURIComponent(i[1])}return e.totalStorage("inbound_cookies",t),t},setUrlParams:function(){var n={};!function(){for(var e,t=function(e){return decodeURIComponent(e).replace(/\+/g," ")},o=window.location.search.substring(1),i=/([^&=]+)=?([^&]*)/g;e=i.exec(o);)if("-1"==e[1].indexOf("["))n[t(e[1])]=t(e[2]);else{var a=e[1].indexOf("["),r=e[1].slice(a+1,e[1].indexOf("]",a)),s=t(e[1].slice(0,a));"object"!=typeof n[s]&&(n[t(s)]={},n[t(s)].length=0),r?n[t(s)][t(r)]=t(e[2]):Array.prototype.push.call(n[t(s)],t(e[2]))}}();for(var o in n)if("action"!=o)if("object"==typeof n[o])for(var i in n[o])this.createCookie(i,n[o][i],30);else this.createCookie(o,n[o],30);if(t){var a=e.totalStorage("inbound_url_params")||{},r=this.mergeObjs(a,n);e.totalStorage("inbound_url_params",r)}var s={option1:"yo",option2:"woooo"};e.trigger("url_parameters",n,s)},getAllUrlParams:function(){n={};if(t)var n=e.totalStorage("inbound_url_params");return n},getParameterVal:function(e,t){return(RegExp(e+"=(.+?)(&|$)").exec(t)||[,!1])[1]},checkLocalStorage:function(){if("localStorage"in window)try{ls=void 0===window.localStorage?void 0:window.localStorage,t="undefined"!=typeof ls&&void 0!==window.JSON}catch(e){t=!1}return t},showLocalStorageSize:function(){function e(e){return 2*e.length}function t(e){return e/1024/1024}var n=Object.keys(localStorage).map(function(t){return{name:t,size:e(localStorage[t])}}).map(function(e){return e.size=t(e.size).toFixed(2)+" MB",e});console.table(n)},addDays:function(e,t){return new Date(e.getTime()+24*t*60*60*1e3)},GetDate:function(){var e=new Date,t=e.getDate(),n=t<10?"0":"",o=e.getFullYear(),i=e.getHours(),a=i<10?"0":"",r=e.getMinutes(),s=r<10?"0":"",l=e.getSeconds(),u=l<10?"0":"",c=e.getMonth()+1;return o+"/"+(c<10?"0":"")+c+"/"+n+t+" "+a+i+":"+s+r+":"+u+l},SetSessionTimeout:function(){this.readCookie("lead_session_expire");var e=new Date;e.setTime(e.getTime()+18e5),this.createCookie("lead_session_expire",!0,e)},storeReferralData:function(){var t=new Date,n=document.referrer||"Direct Traffic",o=e.Utils.readCookie("inbound_referral_site"),i=e.totalStorage("inbound_original_referral");t.setTime(t.getTime()+18e5),o||this.createCookie("inbound_referral_site",n,t),i||e.totalStorage("inbound_original_referral",i)},CreateUID:function(e){var t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".split(""),n="";e||(e=Math.floor(Math.random()*t.length));for(var o=0;o<e;o++)n+=t[Math.floor(Math.random()*t.length)];return n},generateGUID:function(e){return e?(e^16*Math.random()>>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,guid)},SetUID:function(e){if(!this.readCookie("wp_lead_uid")){var t=e||this.CreateUID(35);this.createCookie("wp_lead_uid",t)}},countProperties:function(e){var t=0;for(var n in e)e.hasOwnProperty(n)&&++t;return t},mergeObjs:function(e,t){var n={};for(var o in e)n[o]=e[o];for(var o in t)n[o]=t[o];return n},hasClass:function(e,t){if("classList"in document.documentElement)n=t.classList.contains(e);else var n=new RegExp("(^|\\s)"+e+"(\\s|$)").test(t.className);return n},addClass:function(e,t){"classList"in document.documentElement?t.classList.add(e):this.hasClass(t,e)||(t.className+=(t.className?" ":"")+e)},removeClass:function(e,t){"classList"in document.documentElement?t.classList.remove(e):this.hasClass(t,e)&&(t.className=t.className.replace(new RegExp("(^|\\s)*"+e+"(\\s|$)*","g"),""))},removeElement:function(e){e.parentNode.removeChild(e)},trim:function(e){return e=e.replace(/(^\s*)|(\s*$)/gi,""),e=e.replace(/[ ]{2,}/gi," "),e=e.replace(/\n /,"\n")},ajaxPolyFill:function(){if("undefined"!=typeof XMLHttpRequest)return new XMLHttpRequest;for(var e,t=["MSXML2.XmlHttp.5.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp.2.0","Microsoft.XmlHttp"],n=0;n<t.length;n++)try{e=new ActiveXObject(t[n]);break}catch(e){}return e},ajaxSendData:function(e,t,n,o,i){var a=this.ajaxPolyFill();setTimeout(function(){a.open(n,e,!0),a.onreadystatechange=function(){4==a.readyState&&t(a.responseText)},"POST"==n&&a.setRequestHeader("Content-type","application/x-www-form-urlencoded"),a.send(o)},100)},ajaxGet:function(e,t,n,o){var i=[];for(var a in t)i.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e+"?"+i.join("&"),n,"GET",null,o)},ajaxPost:function(e,t,n,o){var i=[];for(var a in t)i.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e,n,"POST",i.join("&"),o)},sendEvent:function(e,t,i){t=t||{},async=!0;var a=getCookie();if(a){var r;for(r in a)t[r]=a[r]}t.id||(t.id=getId());var s={e:e,t:(new Date).toISOString(),kv:t},l=o.api_host+"/track?data="+encodeURIComponent(JSON.stringify(s));if(n){var u=new XMLHttpRequest;u.open("GET",l,async),u.withCredentials=async,u.send(null)}else{var c=document.createElement("script");c.type="text/javascript",c.async=async,c.defer=async,c.src=l;var d=document.getElementsByTagName("script")[0];d.parentNode.insertBefore(c,d)}return action(i),self},domReady:function(e,t){var n=!1,o=!0,i=e.document,a=i.documentElement,r=i.addEventListener?"addEventListener":"attachEvent",s=i.addEventListener?"removeEventListener":"detachEvent",l=i.addEventListener?"":"on",u=function(o){"readystatechange"==o.type&&"complete"!=i.readyState||(("load"==o.type?e:i)[s](l+o.type,u,!1),!n&&(n=!0)&&t.call(e,o.type||o))},c=function(){try{a.doScroll("left")}catch(e){return void setTimeout(c,50)}u("poll")};if("complete"==i.readyState)t.call(e,"lazy");else{if(i.createEventObject&&a.doScroll){try{o=!e.frameElement}catch(e){}o&&c()}i[r](l+"DOMContentLoaded",u,!1),i[r](l+"readystatechange",u,!1),e[r](l+"load",u,!1)}},addListener:function(e,t,n){e&&(e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):e["on"+t]=n)},removeListener:function(e,t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):e["on"+t]=null},throttle:function(e,t){var n,o,i,a=null,r=0,s=function(){r=new Date,a=null,i=e.apply(n,o)};return function(){var l=new Date;r||(r=l);var u=t-(l-r);return n=this,o=arguments,u<=0?(clearTimeout(a),a=null,r=l,i=e.apply(n,o)):a||(a=setTimeout(s,u)),i}},checkTypeofGA:function(){"function"==typeof ga&&(universalGA=!0),void 0!==_gaq&&"function"==typeof _gaq.push&&(classicGA=!0),"undefined"!=typeof dataLayer&&"function"==typeof dataLayer.push&&(googleTagManager=!0)},cacheSearchData:function(n,o){if(t){var i=e.totalStorage.getItem("inbound_search_storage");if(i)i.unshift(n),e.totalStorage.setItem("inbound_search_storage",i);else{var a=[n];e.totalStorage.setItem("inbound_search_storage",a)}}else{var r=JSON.stringify(n),s=this.readCookie("inbound_search_storage");s&&(r+="SPLIT-TOKEN"+s),this.createCookie("inbound_search_storage",r,"180")}e.Forms.releaseFormSubmit(o)},storeSearchData:function(){if(inbound_settings.wp_lead_data.lead_id&&inbound_settings.wp_lead_data.lead_nonce){var t=[],n=e.totalStorage.getItem("inbound_search_storage"),o=this.readCookie("inbound_search_storage");if(n||o){if(o){o=o.split("SPLIT-TOKEN");for(var i in o)t.push(JSON.parse(o[i]))}n&&(t=t.concat(n)),t.sort(function(e,t){return e.timestamp-t.timestamp});var a={action:"inbound_search_store",data:t=encodeURIComponent(JSON.stringify(t)),nonce:inbound_settings.wp_lead_data.lead_nonce,lead_id:inbound_settings.wp_lead_data.lead_id};callback=function(t){t&&(t=JSON.parse(t)),t.success&&(console.log(t.success),e.Utils.eraseCookie("inbound_search_storage"),e.totalStorage.deleteItem("inbound_search_storage")),t.error&&console.log(t.error)},this.ajaxPost(inbound_settings.admin_url,a,callback)}}}},e}(_inbound||{}),InboundForms=function(e){var t=e.Utils,n=[],o=[],a=[],r={},s=e.Settings,l=["first name","last name","name","email","e-mail","phone","website","job title","your favorite food","company","tele","address","comment"];if(e.Forms={init:function(){e.Forms.runFieldMappingFilters(),e.Forms.formTrackInit(),e.Forms.searchTrackInit()},runFieldMappingFilters:function(){l=e.hooks.applyFilters("forms.field_map",l)},debug:function(e,t){return},formTrackInit:function(){for(var e=0;e<window.document.forms.length;e++){var t=window.document.forms[e];t.dataset.formProcessed||(t.dataset.formProcessed=!0,this.checkTrackStatus(t)&&(this.attachFormSubmitEvent(t),this.initFormMapping(t)))}},searchTrackInit:function(){if("off"!=inbound_settings.search_tracking&&!r.searchTrackInit){for(var e=0;e<window.document.forms.length;e++){var n=window.document.forms[e];n.dataset.searchChecked||(n.dataset.searchChecked=!0,this.checkSearchTrackStatus(n)&&this.attachSearchFormSubmitEvent(n))}t.storeSearchData(),r.searchTrackInit=!0}},checkTrackStatus:function(t){var n=t.getAttribute("class");if(""!==n&&null!==n)return n.toLowerCase().indexOf("wpl-track-me")>-1||(n.toLowerCase().indexOf("inbound-track")>-1||(cb=function(){console.log(t)},e.deBugger("forms","This form not tracked. Please assign on in settings...",cb),!1))},checkSearchTrackStatus:function(t){var n=t.getAttribute("class"),o=t.getAttribute("id");return""!==n&&null!==n&&n.toLowerCase().indexOf("search")>-1||(""===o||null===o?(cb=function(){console.log(t)},e.deBugger("searches","This search form is not tracked. Please assign on in settings...",cb),!1):o.toLowerCase().indexOf("search")>-1||void 0)},loopClassSelectors:function(n,o){for(var i=n.length-1;i>=0;i--){var a=t.trim(n[i]);-1===a.indexOf("#")&&-1===a.indexOf(".")&&(a="#"+a),(a=document.querySelector(a))&&("add"===o?(e.Utils.addClass("wpl-track-me",a),e.Utils.addClass("inbound-track",a)):(e.Utils.removeClass("wpl-track-me",a),e.Utils.removeClass("inbound-track",a)))}},initFormMapping:function(t){for(var n=[],o=0;o<t.elements.length;o++)formInput=t.elements[o],"hidden"!==formInput.type?(this.mapField(formInput),this.rememberInputValues(formInput),s.formAutoPopulation&&!e.Utils.hasClass("nopopulate",t)&&this.fillInputValues(formInput)):n.push(formInput);for(var i=n.length-1;i>=0;i--)formInput=n[i],this.mapField(formInput)},mapField:function(o){var a=o.id||!1,r=o.name||!1,s=this.getInputLabel(o);if(s&&this.ignoreFieldByLabel(s[0].innerText))return o.dataset.ignoreFormField=!0,!1;for(i=0;i<l.length;i++){var u=!1,c=l[i],d=t.trim(c),m=d.replace(/ /g,"_");r&&r.toLowerCase().indexOf(d)>-1?(u=!0,e.deBugger("forms","Found matching name attribute for -> "+d)):a&&a.toLowerCase().indexOf(d)>-1?(u=!0,e.deBugger("forms","Found matching ID attribute for ->"+d)):s?s[0].innerText.toLowerCase().indexOf(d)>-1&&(u=!0,e.deBugger("forms","Found matching sibling label for -> "+d)):n.push(d),u&&(this.addDataAttr(o,m),this.removeArrayItem(l,d),i--)}return inbound_data},formListener:function(t){t.preventDefault(),e.Forms.saveFormData(t.target),document.body.style.cursor="wait"},searchFormListener:function(t){t.preventDefault(),e.Forms.saveSearchData(t.target)},attachFormSubmitEvent:function(e){t.addListener(e,"submit",this.formListener);document.querySelector(".inbound-email")},attachSearchFormSubmitEvent:function(e){t.addListener(e,"submit",this.searchFormListener)},ignoreFieldByLabel:function(t){var n=!1;return!!t&&(-1==t.toLowerCase().indexOf("credit card")&&-1==t.toLowerCase().indexOf("card number")||(n=!0),-1==t.toLowerCase().indexOf("expiration")&&-1==t.toLowerCase().indexOf("expiry")||(n=!0),"month"!=t.toLowerCase()&&"mm"!=t.toLowerCase()&&"yy"!=t.toLowerCase()&&"yyyy"!=t.toLowerCase()&&"year"!=t.toLowerCase()||(n=!0),-1==t.toLowerCase().indexOf("cvv")&&-1==t.toLowerCase().indexOf("cvc")&&-1==t.toLowerCase().indexOf("secure code")&&-1==t.toLowerCase().indexOf("security code")||(n=!0),n&&e.deBugger("forms","ignore "+t),n)},ignoreFieldByValue:function(e){var t=!1;if(!e)return!1;if("visa"!=e.toLowerCase()&&"mastercard"!=e.toLowerCase()&&"american express"!=e.toLowerCase()&&"amex"!=e.toLowerCase()&&"discover"!=e.toLowerCase()||(t=!0),new RegExp("/^[0-9]+$/").test(e)){var n=e.replace(" ","");this.isInt(n)&&n.length>=16&&(t=!0)}return t},isInt:function(e){return"number"==typeof e&&isFinite(e)&&e%1==0},releaseFormSubmit:function(e){document.body.style.cursor="default",t.removeClass("wpl-track-me",e),t.removeListener(e,"submit",this.formListener);var n=e.getAttribute("class");if(""!==n&&null!==n&&-1!=n.toLowerCase().indexOf("wpcf7-form"))return setTimeout(function(){document.body.style.cursor="default"},300),!0;"function"==typeof e.submit?e.submit():"function"==typeof e.click&&jQuery("#"+e.id).find("button").click(),setTimeout(function(){for(var t=0;t<e.elements.length;t++)formInput=e.elements[t],type=formInput.type||!1,"submit"===type&&"submit"===formInput.name&&e.elements[t].click()},2e3)},saveFormData:function(n){for(var i=i||{},r=0;r<n.elements.length;r++)if(formInput=n.elements[r],multiple=!1,formInput.name){if(formInput.dataset.ignoreFormField){e.deBugger("forms","ignore "+formInput.name);continue}switch(inputName=formInput.name.replace(/\[([^\[]*)\]/g,"%5B%5D$1"),i[inputName]||(i[inputName]={}),formInput.type&&(i[inputName].type=formInput.type),i[inputName].name||(i[inputName].name=formInput.name),formInput.dataset.mapFormField&&(i[inputName].map=formInput.dataset.mapFormField),formInput.nodeName){case"INPUT":if(!1===(l=this.getInputValue(formInput)))continue;break;case"TEXTAREA":l=formInput.value;break;case"SELECT":if(formInput.multiple){values=[],multiple=!0;for(var s=0;s<formInput.length;s++)formInput[s].selected&&values.push(encodeURIComponent(formInput[s].value))}else l=formInput.value}if(e.deBugger("forms","Input Value = "+l),l){i[inputName].value||(i[inputName].value=[]),i[inputName].value.push(multiple?values.join(","):encodeURIComponent(l));var l=multiple?values.join(","):encodeURIComponent(l)}}e.deBugger("forms",i);for(var u in i){var c=i[u].value,d=i[u].map;if(void 0!==c&&null!=c&&""!=c&&o.push(u+"="+i[u].value.join(",")),void 0!==d&&null!=d&&i[u].value&&(a.push(d+"="+i[u].value.join(",")),"email"===u))var m=i[u].value.join(",")}var f=o.join("&");e.deBugger("forms","Stringified Raw Form PARAMS: "+f);var g=a.join("&");e.deBugger("forms","Stringified Mapped PARAMS"+g),(m=t.getParameterVal("email",g)||t.readCookie("wp_lead_email"))||(m=t.getParameterVal("wpleads_email_address",g));var p=t.getParameterVal("name",g),h=t.getParameterVal("first_name",g),v=t.getParameterVal("last_name",g);if(!v&&h&&(_=decodeURI(h).split(" ")).length>0&&(h=_[0],v=_[1]),p&&!v&&!h){var _=decodeURI(p).split(" ");_.length>0&&(h=_[0],v=_[1])}p=h&&v?h+" "+v:p,h||(h=""),v||(v=""),e.deBugger("forms","fName = "+h),e.deBugger("forms","lName = "+v),e.deBugger("forms","fullName = "+p);var b=e.totalStorage("page_views")||{},y=e.totalStorage("inbound_url_params")||{},w=n.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])'),k=!1;if(0==w.length||"IA=="==w[0].value)k=!0;var S=n.querySelectorAll('input[value][type="hidden"][name="inbound_form_id"]');S=S.length>0?S[0].value:0;if("undefined"!=typeof landing_path_info)I=landing_path_info.variation;else if("undefined"!=typeof cta_path_info)I=cta_path_info.variation;else var I=inbound_settings.variation_id;var C=inbound_settings.post_type||"page",L=inbound_settings.post_id||0;search_data={},formData={action:"inbound_lead_store",email:m,full_name:p,first_name:h,last_name:v,raw_params:f,mapped_params:g,url_params:JSON.stringify(y),search_data:"test",page_views:JSON.stringify(b),post_type:C,page_id:L,variation:I,source:t.readCookie("inbound_referral_site"),inbound_submitted:k,inbound_form_id:S,inbound_nonce:inbound_settings.ajax_nonce,event:n},callback=function(o){e.deBugger("forms","Lead Created with ID: "+o),o=parseInt(o,10),formData.leadID=o,o&&(t.createCookie("wp_lead_id",o),e.totalStorage.deleteItem("page_views"),e.totalStorage.deleteItem("tracking_events")),e.trigger("form_after_submission",formData),e.Forms.releaseFormSubmit(n)},e.trigger("form_before_submission",formData),t.ajaxPost(inbound_settings.admin_url,formData,callback)},saveSearchData:function(n){for(var o=o||{},i=0;i<n.elements.length;i++)if(formInput=n.elements[i],multiple=!1,formInput.name){if(formInput.dataset.ignoreFormField){e.deBugger("searches","ignore "+formInput.name);continue}switch(d=formInput.name.replace(/\[([^\[]*)\]/g,"%5B%5D$1"),o[d]||(o[d]={}),formInput.type&&(o[d].type=formInput.type),o[d].name||(o[d].name=formInput.name),formInput.dataset.mapFormField&&(o[d].map=formInput.dataset.mapFormField),formInput.nodeName){case"INPUT":if(!1===(r=this.getInputValue(formInput)))continue;break;case"TEXTAREA":r=formInput.value;break;case"SELECT":if(formInput.multiple){values=[],multiple=!0;for(var a=0;a<formInput.length;a++)formInput[a].selected&&values.push(encodeURIComponent(formInput[a].value))}else r=formInput.value}if(e.deBugger("searches","Input Value = "+r),r){o[d].value||(o[d].value=[]),o[d].value.push(multiple?values.join(","):encodeURIComponent(r));var r=multiple?values.join(","):encodeURIComponent(r)}}e.deBugger("searches",o);var s=[];for(var l in o){var u=o[l].value,c=o[l].type,d=o[l].name;void 0!==u&&null!=u&&""!=u&&("search"==c?s.push("search_text|value|"+o[l].value):"s"==d&&s.push("search_text|value|"+o[l].value))}s[0]||e.Forms.releaseFormSubmit(n);var m=s.join("|field|");if(e.deBugger("searches","Stringified Search Form PARAMS: "+m),"undefined"!=typeof landing_path_info)f=landing_path_info.variation;else if("undefined"!=typeof cta_path_info)f=cta_path_info.variation;else var f=inbound_settings.variation_id;var g=inbound_settings.post_type||"page",p=inbound_settings.post_id||0,h=t.readCookie("wp_lead_uid");inbound_settings.wp_lead_data.lead_email?email=inbound_settings.wp_lead_data.lead_email:t.readCookie("inbound_wpleads_email_address")?email=t.readCookie("inbound_wpleads_email_address"):email="",searchData={email:email,search_data:m,user_UID:h,post_type:g,page_id:p,variation:f,source:t.readCookie("inbound_referral_site"),ip_address:inbound_settings.ip_address,timestamp:Math.floor((new Date).getTime()/1e3)},e.trigger("search_before_caching",searchData),inbound_settings.wp_lead_data.lead_id?(searchData.lead_id=inbound_settings.wp_lead_data.lead_id,t.cacheSearchData(searchData,n)):t.cacheSearchData(searchData,n)},rememberInputValues:function(n){n.name&&n.name;var o=n.type?n.type:"text";if("submit"===o||"hidden"===o||"file"===o||"password"===o||n.dataset.ignoreFormField)return!1;t.addListener(n,"change",function(n){if(n.target.name){if("checkbox"!==o)var i=n.target.value;else for(var a=[],r=document.querySelectorAll('input[name="'+n.target.name+'"]'),s=0;s<r.length;s++)r[s].checked&&a.push(r[s].value),i=a.join(",");inputData={name:n.target.name,node:n.target.nodeName.toLowerCase(),type:o,value:i,mapping:n.target.dataset.mapFormField},e.trigger("form_input_change",inputData),t.createCookie("inbound_"+n.target.name,encodeURIComponent(i))}})},fillInputValues:function(e){var n=e.name?"inbound_"+e.name:"",o=e.type?e.type:"text";if("submit"===o||"hidden"===o||"file"===o||"password"===o)return!1;if(t.readCookie(n)&&"comment"!=n)if(value=decodeURIComponent(t.readCookie(n)),"checkbox"===o||"radio"===o)for(var i=value.split(","),a=0;a<i.length;a++)e.value.indexOf(i[a])>-1&&(e.checked=!0);else"undefined"!==value&&(e.value=value)},getInputLabel:function(e){var t;return(t=this.siblingsIsLabel(e))?t:!!(t=this.CheckParentForLabel(e))&&t},getInputValue:function(e){var t=!1;switch(e.type){case"radio":case"checkbox":e.checked&&(t=e.value);break;case"text":case"hidden":default:t=e.value}return t},addDataAttr:function(e,t){for(var n=document.getElementsByName(e.name),o=n.length-1;o>=0;o--)e.dataset.mapFormField||(n[o].dataset.mapFormField=t)},removeArrayItem:function(e,t){if(e.indexOf)index=e.indexOf(t);else for(index=e.length-1;index>=0&&e[index]!==t;--index);index>=0&&e.splice(index,1)},siblingsIsLabel:function(e){for(var t=this.getSiblings(e),n=[],o=t.length-1;o>=0;o--)"label"===t[o].nodeName.toLowerCase()&&n.push(t[o]);return n.length>0&&n.length<2&&n},getChildren:function(e,t){for(var n=[];e;e=e.nextSibling)1==e.nodeType&&e!=t&&n.push(e);return n},getSiblings:function(e){return this.getChildren(e.parentNode.firstChild,e)},CheckParentForLabel:function(e){if("FORM"===e.nodeName)return null;do{var t=e.getElementsByTagName("label");if(t.length>0&&t.length<2)return e.getElementsByTagName("label")}while(e=e.parentNode);return null},mailCheck:function(){var e=document.querySelector(".inbound-email");e&&(t.addListener(e,"blur",this.mailCheck),u.run({email:document.querySelector(".inbound-email").value,suggested:function(n){var o=document.querySelector(".email_suggestion");o&&t.removeElement(o);var i=document.createElement("span");i.innerHTML="<span class=\"email_suggestion\">Did youu mean <b><i id='email_correction' style='cursor: pointer;' title=\"click to update\">"+n.full+"</b></i>?</span>",e.parentNode.insertBefore(i,e.nextSibling);var a=document.getElementById("email_correction");t.addListener(a,"click",function(){e.value=a.innerHTML,a.parentNode.parentNode.innerHTML="Fixed!"})},empty:function(){}}))}},void 0===u)var u={domainThreshold:1,topLevelThreshold:3,defaultDomains:["yahoo.com","google.com","hotmail.com","gmail.com","me.com","aol.com","mac.com","live.com","comcast.net","googlemail.com","msn.com","hotmail.co.uk","yahoo.co.uk","facebook.com","verizon.net","sbcglobal.net","att.net","gmx.com","mail.com","outlook.com","icloud.com"],defaultTopLevelDomains:["co.jp","co.uk","com","net","org","info","edu","gov","mil","ca","de"],run:function(e){e.domains=e.domains||u.defaultDomains,e.topLevelDomains=e.topLevelDomains||u.defaultTopLevelDomains,e.distanceFunction=e.distanceFunction||u.sift3Distance;var t=function(e){return e},n=e.suggested||t,o=e.empty||t,i=u.suggest(u.encodeEmail(e.email),e.domains,e.topLevelDomains,e.distanceFunction);return i?n(i):o()},suggest:function(e,t,n,o){e=e.toLowerCase();var i=this.splitEmail(e),a=this.findClosestDomain(i.domain,t,o,this.domainThreshold);if(a){if(a!=i.domain)return{address:i.address,domain:a,full:i.address+"@"+a}}else{var r=this.findClosestDomain(i.topLevelDomain,n,o,this.topLevelThreshold);if(i.domain&&r&&r!=i.topLevelDomain){var s=i.domain;return a=s.substring(0,s.lastIndexOf(i.topLevelDomain))+r,{address:i.address,domain:a,full:i.address+"@"+a}}}return!1},findClosestDomain:function(e,t,n,o){o=o||this.topLevelThreshold;var i,a=99,r=null;if(!e||!t)return!1;n||(n=this.sift3Distance);for(var s=0;s<t.length;s++){if(e===t[s])return e;(i=n(e,t[s]))<a&&(a=i,r=t[s])}return a<=o&&null!==r&&r},sift3Distance:function(e,t){if(null===e||0===e.length)return null===t||0===t.length?0:t.length;if(null===t||0===t.length)return e.length;for(var n=0,o=0,i=0,a=0;n+o<e.length&&n+i<t.length;){if(e.charAt(n+o)==t.charAt(n+i))a++;else{o=0,i=0;for(var r=0;r<5;r++){if(n+r<e.length&&e.charAt(n+r)==t.charAt(n)){o=r;break}if(n+r<t.length&&e.charAt(n)==t.charAt(n+r)){i=r;break}}}n++}return(e.length+t.length)/2-a},splitEmail:function(e){var t=e.trim().split("@");if(t.length<2)return!1;for(a=0;a<t.length;a++)if(""===t[a])return!1;var n=t.pop(),o=n.split("."),i="";if(0===o.length)return!1;if(1==o.length)i=o[0];else{for(var a=1;a<o.length;a++)i+=o[a]+".";o.length>=2&&(i=i.substring(0,i.length-1))}return{topLevelDomain:i,domain:n,address:t.join("@")}},encodeEmail:function(e){var t=encodeURI(e);return t=t.replace("%20"," ").replace("%25","%").replace("%5E","^").replace("%60","`").replace("%7B","{").replace("%7C","|").replace("%7D","}")}};return e}(_inbound||{}),_inboundEvents=function(e){function t(t,o,i){var o=o||{};(i=i||{}).bubbles=i.bubbles||!0,i.cancelable=i.cancelable||!0,o=e.apply_filters("filter_"+t,o);!window.ActiveXObject&&window;if("function"==typeof CustomEvent)var a=new CustomEvent(t,{detail:o,bubbles:i.bubbles,cancelable:i.cancelable});else(a=document.createEvent("Event")).initEvent(t,!0,!0);window.dispatchEvent(a),e.do_action(t,o),n(t,o)}function n(e,t){if(window.jQuery){var t=t||{};jQuery(document).trigger(e,t)}}e.trigger=function(t,n){e.Events[t](n)};return e.Events={analytics_ready:function(){t("analytics_ready",{data:"xyxy"},{opt1:!0})},url_parameters:function(e){t("url_parameters",e)},session_start:function(){console.log(""),t("session_start")},session_end:function(e){t("session_end",e),console.log("Session End")},session_active:function(){t("session_active")},session_idle:function(e){t("session_idle",e)},session_resume:function(){t("session_resume")},session_heartbeat:function(e){t("session_heartbeat",{clock:e,leadData:InboundLeadData})},page_visit:function(e){t("page_view",e)},page_first_visit:function(n){t("page_first_visit"),e.deBugger("pages","First Ever Page View of this Page")},page_revisit:function(n){t("page_revisit",n);e.deBugger("pages",status,function(){console.log("pageData",n),console.log("Page Revisit viewed "+n+" times")})},tab_hidden:function(n){e.deBugger("pages","Tab Hidden"),t("tab_hidden")},tab_visible:function(n){e.deBugger("pages","Tab Visible"),t("tab_visible")},tab_mouseout:function(n){e.deBugger("pages","Tab Mouseout"),t("tab_mouseout")},form_input_change:function(n){e.deBugger("forms","inputData change. Data=",function(){console.log(n)}),t("form_input_change",n)},form_before_submission:function(e){t("form_before_submission",e)},form_after_submission:function(e){t("form_after_submission",e)},search_before_caching:function(e){t("search_before_caching",e)},analyticsError:function(e,t,n){var o=new CustomEvent("inbound_analytics_error",{detail:{MLHttpRequest:e,textStatus:t,errorThrown:n}});window.dispatchEvent(o),console.log("Page Save Error")}},e}(_inbound||{});_inbound.add_action("form_before_submission",inboundFormNoRedirect,10),_inbound.add_action("form_after_submission",inboundFormNoRedirectContent,10);var InboundTotalStorage=function(e){var t,n;if("localStorage"in window)try{n=void 0===window.localStorage?void 0:window.localStorage,t=void 0!==n&&void 0!==window.JSON,window.localStorage.setItem("_inbound","1"),window.localStorage.removeItem("_inbound")}catch(e){t=!1}e.totalStorage=function(t,n,o){return e.totalStorage.impl.init(t,n)},e.totalStorage.setItem=function(t,n){return e.totalStorage.impl.setItem(t,n)},e.totalStorage.getItem=function(t){return e.totalStorage.impl.getItem(t)},e.totalStorage.getAll=function(){return e.totalStorage.impl.getAll()},e.totalStorage.deleteItem=function(t){return e.totalStorage.impl.deleteItem(t)},e.totalStorage.impl={init:function(e,t){return void 0!==t?this.setItem(e,t):this.getItem(e)},setItem:function(o,i){if(!t)try{return e.Utils.createCookie(o,i),i}catch(e){console.log("Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie")}var a=JSON.stringify(i);return n.setItem(o,a),this.parseResult(a)},getItem:function(o){if(!t)try{return this.parseResult(e.Utils.readCookie(o))}catch(e){return null}var i=n.getItem(o);return this.parseResult(i)},deleteItem:function(o){if(!t)try{return e.Utils.eraseCookie(o,null),!0}catch(e){return!1}return n.removeItem(o),!0},getAll:function(){var o=[];if(t)for(var i in n)i.length&&o.push({key:i,value:this.parseResult(n.getItem(i))});else try{for(var a=document.cookie.split(";"),r=0;r<a.length;r++){var s=a[r].split("=")[0];o.push({key:s,value:this.parseResult(e.Utils.readCookie(s))})}}catch(e){return null}return o},parseResult:function(e){var t;try{void 0===(t=JSON.parse(e))&&(t=e),"true"==t&&(t=!0),"false"==t&&(t=!1),parseFloat(t)==t&&"object"!=typeof t&&(t=parseFloat(t))}catch(n){t=e}return t}}}(_inbound||{}),_inboundLeadsAPI=function(e){return e.LeadsAPI={init:function(){var t=e.Utils,n=(t.readCookie("wp_lead_uid"),t.readCookie("wp_lead_id"));t.readCookie("lead_data_expire")||(e.deBugger("leads","expired vistor. Run Processes"),n&&e.LeadsAPI.getAllLeadData())},setGlobalLeadData:function(e){InboundLeadData=e},getAllLeadData:function(t){var n=e.Utils.readCookie("wp_lead_id"),o=e.totalStorage("inbound_lead_data"),i=e.Utils.readCookie("lead_data_expire");data={action:"inbound_get_all_lead_data",wp_lead_id:n},success=function(t){var n=JSON.parse(t);e.LeadsAPI.setGlobalLeadData(n),e.totalStorage("inbound_lead_data",n);var o=new Date;o.setTime(o.getTime()+18e5);var i=e.Utils.addDays(o,3);e.Utils.createCookie("lead_data_expire",!0,i)},o?(e.LeadsAPI.setGlobalLeadData(o),e.deBugger("lead","Set Global Lead Data from Localstorage"),i||(e.Utils.ajaxPost(inbound_settings.admin_url,data,success),e.deBugger("lead","localized data old. Pull new from DB"))):e.Utils.ajaxPost(inbound_settings.admin_url,data,success)},getLeadLists:function(){var t={action:"wpl_check_lists",wp_lead_id:e.Utils.readCookie("wp_lead_id")};e.Utils.ajaxPost(inbound_settings.admin_url,t,function(t){e.Utils.createCookie("lead_session_list_check",!0,{path:"/",expires:1}),e.deBugger("lead","Lists checked")})}},e}(_inbound||{}),_inboundPageTracking=function(e){var t,n,o=!1,i=!1,a=!1,r=parseInt(e.Utils.readCookie("lead_session"),10)||0,s=0,l=(new Date,null),u=null,c=null,d=e.Utils,m=e.Utils.GetDate(),f="page_views",g=e.totalStorage(f)||{},p=inbound_settings.post_id||window.location.pathname;e.Settings.timeout;return e.PageTracking={init:function(o){var i=this.isRevisit(g);this.triggerPageView(i),o=o||{},t=parseInt(o.reportInterval,10)||10,n=parseInt(o.idleTimeout,10)||3,d.addListener(document,"keydown",d.throttle(e.PageTracking.pingSession,1e3)),d.addListener(document,"click",d.throttle(e.PageTracking.pingSession,1e3)),d.addListener(window,"mousemove",d.throttle(e.PageTracking.pingSession,1e3)),e.PageTracking.checkVisibility(),this.startSession()},setIdle:function(t){var n="Session IDLE. Activity Timeout due to "+(t=t||"No Movement");e.deBugger("pages",n),clearTimeout(e.PageTracking.idleTimer),e.PageTracking.stopClock(),e.trigger("session_idle")},checkVisibility:function(){var t,n;void 0!==document.hidden?(t="hidden",n="visibilitychange"):void 0!==document.mozHidden?(t="mozHidden",n="mozvisibilitychange"):void 0!==document.msHidden?(t="msHidden",n="msvisibilitychange"):void 0!==document.webkitHidden&&(t="webkitHidden",n="webkitvisibilitychange");var o=document[t];e.Utils.addListener(document,n,function(n){o!=document[t]&&(document[t]?(e.trigger("tab_hidden"),e.PageTracking.setIdle("browser tab switch")):(e.trigger("tab_visible"),e.PageTracking.pingSession()),o=document[t])})},clock:function(){var n="Total time spent on Page in this Session: "+((r+=1)/60).toFixed(2)+" min";if(e.deBugger("pages",n),r>0&&r%t==0){var o=new Date;o.setTime(o.getTime()+18e5),d.createCookie("lead_session",r,o),e.trigger("session_heartbeat",r)}},inactiveClock:function(){var t="Time until Session Timeout: "+((1800-(s+=1))/60).toFixed(2)+" min";e.deBugger("pages",t),s>1800&&(e.trigger("session_end",InboundLeadData),e.Utils.eraseCookie("lead_session"),s=0,clearTimeout(u))},stopClock:function(){i=!0,clearTimeout(l),clearTimeout(u),u=setInterval(e.PageTracking.inactiveClock,1e3)},restartClock:function(){i=!1,e.trigger("session_resume"),e.deBugger("pages","Activity resumed. Session Active"),clearTimeout(l),s=0,clearTimeout(u),l=setInterval(e.PageTracking.clock,1e3)},turnOff:function(){e.PageTracking.setIdle(),a=!0},turnOn:function(){a=!1},startSession:function(){new Date;if(o=!0,l=setInterval(e.PageTracking.clock,1e3),d.readCookie("lead_session"))e.trigger("session_active");else{e.trigger("session_start");var t=new Date;t.setTime(t.getTime()+18e5),e.Utils.createCookie("lead_session",1,t)}this.pingSession()},resetInactiveFunc:function(){s=0,clearTimeout(u)},pingSession:function(t){a||(o||e.PageTracking.startSession(),i&&e.PageTracking.restartClock(),clearTimeout(c),c=setTimeout(e.PageTracking.setIdle,1e3*n+100),void 0!==t&&"mousemove"===t.type&&e.PageTracking.mouseEvents(t))},mouseEvents:function(t){t.pageY<=5&&e.trigger("tab_mouseout")},getPageViews:function(){if(e.Utils.checkLocalStorage()){var t=localStorage.getItem(f),n=JSON.parse(t);return n}},isRevisit:function(e){var t=!1,n=(e=e||{})[p];return void 0!==n&&null!==n&&(t=!0),t},triggerPageView:function(t){var n={title:document.title,url:document.location.href,path:document.location.pathname,count:1};t?(g[p].push(m),n.count=g[p].length,e.trigger("page_revisit",n)):(g[p]=[],g[p].push(m),e.trigger("page_first_visit",n)),e.trigger("page_visit",n),e.totalStorage(f,g);jQuery(document).ready(function(){e.PageTracking.storePageView()})},CheckTimeOut:function(){e.deBugger("pages",status)},storePageView:function(){"off"==inbound_settings.page_tracking&&"landing-page"!=inbound_settings.post_type||setTimeout(function(){var t=e.Utils.readCookie("wp_lead_id")?e.Utils.readCookie("wp_lead_id"):"",n=e.Utils.readCookie("wp_lead_uid")?e.Utils.readCookie("wp_lead_uid"):"",o=e.totalStorage("wp_cta_loaded"),i=e.totalStorage("wp_cta_impressions");stored=!0,e.totalStorage("wp_cta_impressions",{});var a={action:"inbound_track_lead",wp_lead_uid:n,wp_lead_id:t,page_id:inbound_settings.post_id,variation_id:inbound_settings.variation_id,post_type:inbound_settings.post_type,current_url:window.location.href,page_views:JSON.stringify(e.PageTracking.getPageViews()),cta_impressions:JSON.stringify(i),cta_history:JSON.stringify(o),json:"0"};e.Utils.ajaxPost(inbound_settings.admin_url,a,function(e){})},200)}},e}(_inbound||{});_inbound.init(),InboundLeadData=_inbound.totalStorage("inbound_lead_data")||null;
shared/assets/plugins/advanced-custom-fields-font-awesome/acf-font-awesome-v4.php CHANGED
@@ -301,10 +301,10 @@ if (!class_exists('acf_field_font_awesome')) {
301
  {
302
  // register acf scripts
303
  /* wp_enqueue_script('acf-input-font-awesome-select2', $this->settings['dir'] . 'js/select2/select2.min.js', array(), $this->settings['version']); */
304
- wp_enqueue_script('acf-input-font-awesome-edit-input', $this->settings['dir'] . 'js/edit_input.js', array(), $this->settings['version']);
305
- wp_enqueue_style('acf-input-font-awesome-input', $this->settings['dir'] . 'css/input.css', array(), $this->settings['version']);
306
  wp_enqueue_style('acf-input-font-awesome-fa', $this->stylesheet, array(), $this->version);
307
- wp_enqueue_style('acf-input-font-awesome-select2-css', $this->settings['dir'] . 'css/select2.css', array(), $this->settings['version']);
308
  }
309
 
310
  /*
@@ -322,11 +322,11 @@ if (!class_exists('acf_field_font_awesome')) {
322
  function field_group_admin_enqueue_scripts()
323
  {
324
  // register acf scripts
325
- wp_enqueue_script('font-awesome-select2', $this->settings['dir'] . 'js/select2/select2.min.js', array(), $this->settings['version']);
326
- wp_enqueue_script('font-awesome-create-input', $this->settings['dir'] . 'js/create_input.js', array(), $this->settings['version']);
327
- wp_enqueue_style('acf-input-font-awesome-input', $this->settings['dir'] . 'css/input.css', array(), $this->settings['version']);
328
- wp_enqueue_style('acf-input-font-awesome-fa', $this->stylesheet, array(), $this->version);
329
- wp_enqueue_style('acf-input-font-awesome-select2-css', $this->settings['dir'] . 'css/select2.css', array(), $this->settings['version']);
330
  }
331
 
332
  /*
301
  {
302
  // register acf scripts
303
  /* wp_enqueue_script('acf-input-font-awesome-select2', $this->settings['dir'] . 'js/select2/select2.min.js', array(), $this->settings['version']); */
304
+ wp_enqueue_script('acf-input-font-awesome-edit-input', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/js/edit_input.js', array(), $this->settings['version']);
305
+ wp_enqueue_style('acf-input-font-awesome-input', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/css/input.css', array(), $this->settings['version']);
306
  wp_enqueue_style('acf-input-font-awesome-fa', $this->stylesheet, array(), $this->version);
307
+ wp_enqueue_style('acf-input-font-awesome-select2-css', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/css/select2.css', array(), $this->settings['version']);
308
  }
309
 
310
  /*
322
  function field_group_admin_enqueue_scripts()
323
  {
324
  // register acf scripts
325
+ wp_enqueue_script('select2', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/js/select2/select2.min.js', array(), $this->settings['version']);
326
+ wp_enqueue_script('font-awesome-create-input', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/js/create_input.js', array(), $this->settings['version']);
327
+ wp_enqueue_style('acf-input-font-awesome-input', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/css/input.css', array(), $this->settings['version']);
328
+ wp_enqueue_style('font-awesome', $this->stylesheet, array(), $this->version);
329
+ wp_enqueue_style('select2', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/css/select2.css', array(), $this->settings['version']);
330
  }
331
 
332
  /*
shared/assets/plugins/advanced-custom-fields-font-awesome/acf-font-awesome-v5.php CHANGED
@@ -294,8 +294,8 @@ if (!class_exists('acf_field_font_awesome')) {
294
  {
295
 
296
  // register acf scripts
297
- wp_enqueue_script('acf-input-font-awesome-edit-input', $this->settings['dir'] . 'js/edit_input.js', array(), $this->settings['version']);
298
- wp_enqueue_style('acf-input-font-awesome-input', $this->settings['dir'] . 'css/input.css', array(), $this->settings['version']);
299
  wp_enqueue_style('acf-input-font-awesome-fa', $this->stylesheet, array(), $this->version);
300
  }
301
 
@@ -317,8 +317,8 @@ if (!class_exists('acf_field_font_awesome')) {
317
  {
318
 
319
  // register acf scripts
320
- wp_enqueue_script('font-awesome-create-input', $this->settings['dir'] . 'js/create_input.js', array(), $this->settings['version']);
321
- wp_enqueue_style('acf-input-font-awesome-input', $this->settings['dir'] . 'css/input.css', array(), $this->settings['version']);
322
  wp_enqueue_style('acf-input-font-awesome-fa', $this->stylesheet, array(), $this->version);
323
  }
324
 
294
  {
295
 
296
  // register acf scripts
297
+ wp_enqueue_script('acf-input-font-awesome-edit-input', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/js/edit_input.js', array(), $this->settings['version']);
298
+ wp_enqueue_style('acf-input-font-awesome-input', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/css/input.css', array(), $this->settings['version']);
299
  wp_enqueue_style('acf-input-font-awesome-fa', $this->stylesheet, array(), $this->version);
300
  }
301
 
317
  {
318
 
319
  // register acf scripts
320
+ wp_enqueue_script('font-awesome-create-input', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/js/create_input.js', array(), $this->settings['version']);
321
+ wp_enqueue_style('acf-input-font-awesome-input', INBOUNDNOW_SHARED_URLPATH . 'assets/plugins/advanced-custom-fields-font-awesome/css/input.css', array(), $this->settings['version']);
322
  wp_enqueue_style('acf-input-font-awesome-fa', $this->stylesheet, array(), $this->version);
323
  }
324
 
shared/classes/class.ajax.php CHANGED
@@ -76,14 +76,12 @@ if (!class_exists('Inbound_Ajax')) {
76
  /* record CTA impressions */
77
  $cta_impressions = ( isset($_POST['cta_impressions']) ) ? json_decode(stripslashes($_POST['cta_impressions']),true) : array();
78
 
79
- if (!is_array($cta_impressions)) {
80
- error_log('Bad CTA Impression Object');
81
- return;
82
- }
83
- foreach ( $cta_impressions as $cta_id => $vid ) {
84
- $lead_data['cta_id'] = (int) $cta_id;
85
- $lead_data['variation_id'] = (int) $vid;
86
- do_action('wp_cta_record_impression', $lead_data );
87
  }
88
 
89
  /* update content data */
@@ -148,8 +146,9 @@ if (!class_exists('Inbound_Ajax')) {
148
  $count++;
149
  }
150
 
151
- $list_array = json_encode(array('ids' => $lead_list));;
152
- setcookie('wp_lead_list', $list_array, time() + (20 * 365 * 24 * 60 * 60), '/');
 
153
  }
154
  }
155
 
76
  /* record CTA impressions */
77
  $cta_impressions = ( isset($_POST['cta_impressions']) ) ? json_decode(stripslashes($_POST['cta_impressions']),true) : array();
78
 
79
+ if (is_array($cta_impressions)) {
80
+ foreach ( $cta_impressions as $cta_id => $vid ) {
81
+ $lead_data['cta_id'] = (int) $cta_id;
82
+ $lead_data['variation_id'] = (int) $vid;
83
+ do_action('wp_cta_record_impression', $lead_data );
84
+ }
 
 
85
  }
86
 
87
  /* update content data */
146
  $count++;
147
  }
148
 
149
+ $list_array = json_encode(array('ids' => $lead_list));
150
+
151
+ setcookie('wp_lead_list', $list_array, (int) ( time() + (20 * 365 * 24 * 60 * 60) ), '/');
152
  }
153
  }
154
 
shared/classes/class.confirm-double-optin.php CHANGED
@@ -193,8 +193,17 @@ if(!class_exists('Inbound_Confirm_Double_Optin')){
193
  /*update the lead status*/
194
  update_post_meta( $params['lead_id'], 'wp_lead_status', 'active');
195
  }
 
 
 
 
 
 
 
 
196
  }
197
  }
 
198
  new Inbound_Confirm_Double_Optin;
199
 
200
  }
193
  /*update the lead status*/
194
  update_post_meta( $params['lead_id'], 'wp_lead_status', 'active');
195
  }
196
+
197
+ /* unset empty data */
198
+ unset($params['wp_lead_status']);
199
+ unset($params['variation_id']);
200
+ unset($params['wpleads_raw_post_data']);
201
+
202
+ /* run hook/trigger */
203
+ do_action('inbound_double_optin_confirm' , $params);
204
  }
205
  }
206
+
207
  new Inbound_Confirm_Double_Optin;
208
 
209
  }
shared/classes/class.database-routines.php CHANGED
@@ -296,11 +296,17 @@ if ( !class_exists('Inbound_Upgrade_Routines') ) {
296
 
297
  /**
298
  * @migration-type: inbound pro settings array
299
- * @mirgration: change the 'mailer' key to 'mailer' key in $inbound_settings
300
  */
301
  public static function alter_inbound_settings_109() {
302
  if (class_exists('Inbound_Options_API')) {
303
  $inbound_settings = Inbound_Options_API::get_option('inbound-pro', 'settings', array());
 
 
 
 
 
 
304
  $inbound_settings['mailer'] = (isset($inbound_settings['inbound-mailer'])) ? $inbound_settings['inbound-mailer'] : array();
305
  unset($inbound_settings['inbound-mailer']);
306
  Inbound_Options_API::update_option('inbound-pro', 'settings', $inbound_settings);
@@ -324,7 +330,7 @@ if ( !class_exists('Inbound_Upgrade_Routines') ) {
324
  MODIFY COLUMN `email_id` BIGINT(20),
325
  MODIFY COLUMN `rule_id` BIGINT(20),
326
  MODIFY COLUMN `job_id` BIGINT(20),
327
- MODIFY COLUMN `list_id` BIGINT(20)
328
  MODIFY COLUMN `comment_id` BIGINT(20)");
329
 
330
  }
296
 
297
  /**
298
  * @migration-type: inbound pro settings array
299
+ * @mirgrationcomment_id change the 'mailer' key to 'mailer' key in $inbound_settings
300
  */
301
  public static function alter_inbound_settings_109() {
302
  if (class_exists('Inbound_Options_API')) {
303
  $inbound_settings = Inbound_Options_API::get_option('inbound-pro', 'settings', array());
304
+
305
+ /* ignore if already created */
306
+ if (isset($inbound_settings['mailer'])) {
307
+ return;
308
+ }
309
+
310
  $inbound_settings['mailer'] = (isset($inbound_settings['inbound-mailer'])) ? $inbound_settings['inbound-mailer'] : array();
311
  unset($inbound_settings['inbound-mailer']);
312
  Inbound_Options_API::update_option('inbound-pro', 'settings', $inbound_settings);
330
  MODIFY COLUMN `email_id` BIGINT(20),
331
  MODIFY COLUMN `rule_id` BIGINT(20),
332
  MODIFY COLUMN `job_id` BIGINT(20),
333
+ MODIFY COLUMN `list_id` BIGINT(20),
334
  MODIFY COLUMN `comment_id` BIGINT(20)");
335
 
336
  }
shared/classes/class.events.php CHANGED
@@ -790,8 +790,67 @@ class Inbound_Events {
790
  return $results;
791
  }
792
 
 
 
 
 
 
 
 
 
 
793
 
794
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
795
  /**
796
  * Get page view events given conditions
797
  *
@@ -844,7 +903,7 @@ class Inbound_Events {
844
 
845
  $query .= 'GROUP BY DATE(datetime)';
846
 
847
- $results = $wpdb->get_results( $query , ARRAY_A );
848
 
849
  return $results;
850
  }
790
  return $results;
791
  }
792
 
793
+ /**
794
+ * Get page view events given conditions
795
+ *
796
+ */
797
+ public static function get_page_views_count_by( $nature = 'lead_id' , $params ){
798
+ global $wpdb;
799
+
800
+ $table_name = $wpdb->prefix . "inbound_page_views";
801
+ $query = 'SELECT COUNT(*) FROM '.$table_name.' WHERE ';
802
 
803
 
804
+ switch ($nature) {
805
+ case 'lead_id':
806
+ $query .=' `lead_id` = "'.$params['lead_id'].'" ';
807
+ break;
808
+ case 'lead_uid':
809
+ $query .=' `lead_uid` = "'.$params['lead_uid'].'" ';
810
+ break;
811
+ case 'page_id':
812
+ $query .=' `page_id` = "'.$params['page_id'].'" ';
813
+ break;
814
+ case 'cta_id':
815
+ $query .=' `cta_id` = "'.$params['cta_id'].'" ';
816
+ break;
817
+ case 'mixed':
818
+ if (isset($params['lead_id']) && $params['lead_id'] ) {
819
+ $queries[] = ' `lead_id` = "'.$params['lead_id'].'" ';
820
+ }
821
+ if (isset($params['lead_uid']) && $params['lead_uid']) {
822
+ $queries[] = ' `lead_uid` = "'.$params['lead_uid'].'" ';
823
+ }
824
+ if (isset($params['page_id']) && $params['page_id']) {
825
+ $queries[] = ' `page_id` = "'.$params['page_id'].'" ';
826
+ }
827
+
828
+ /* combine queries into a usable string */
829
+ foreach ($queries as $i => $q) {
830
+ $query .= $q . ( isset($queries[$i+1]) ? ' AND ' : '' );
831
+ }
832
+
833
+ break;
834
+ }
835
+
836
+
837
+ $query .=' AND `page_id` != "0" ';
838
+
839
+ if (isset($params['start_date'])) {
840
+ $query .= ' AND datetime >= "'.$params['start_date'].'" AND datetime <= "'.$params['end_date'].'" ';
841
+ }
842
+
843
+ if (isset($params['group_by'])) {
844
+ $query .= ' GROUP BY `'.$params['group_by'].'` ';
845
+ }
846
+
847
+ $query .= ' ORDER BY `datetime` DESC';
848
+ //print_r($query);exit;
849
+ $results = $wpdb->get_var( $query , ARRAY_A );
850
+
851
+ return $results;
852
+ }
853
+
854
  /**
855
  * Get page view events given conditions
856
  *
903
 
904
  $query .= 'GROUP BY DATE(datetime)';
905
 
906
+ $results = $wpdb->get_results( $query);
907
 
908
  return $results;
909
  }
shared/shortcodes/js/shortcodes.js CHANGED
@@ -1,886 +1,863 @@
1
- // Row add function
2
- function row_add_callback() {
3
- var length = jQuery('.child-clone-row').length;
4
-
5
- jQuery('.form-field-row-number').each(function (i) {
6
- var addition = i + 1;
7
- jQuery(this).text(addition);
8
- jQuery(this).parent().attr('id', 'row-' + addition);
9
- });
10
- jQuery('.child-clone-row').each(function (i) {
11
- var number = i + 1;
12
- var the_id = jQuery(this).attr('id');
13
- jQuery(this).find('input, select, textarea').each(function (i) {
14
- var this_id = the_id.replace('row-', '');
15
- var current_name = jQuery(this).attr('name');
16
- var clean_name = current_name.replace(/_[a-zA-Z0-9]*$/g, "");
17
- jQuery(this).attr('name', clean_name + '_' + this_id);
18
- });
19
- });
20
-
21
- jQuery('.child-clone-row .minimize-class').not("#row-" + length + " .minimize-class").addClass('tog-hide-it');
22
- jQuery('.child-clone-row-shrink').not("#row-" + length + " .child-clone-row-shrink").text("Expand");
23
- InboundShortcodes.generate(); // runs refresh
24
- InboundShortcodes.generateChild();
25
- jQuery('.child-clone-row').last().find('input').first().focus(); // focus on new input
26
- //InboundShortcodes.updatePreview();
27
-
28
- /* make sure correct hidden fields are displayed */
29
- setTimeout(function() {
30
- jQuery('select[data-field-name="field_type"]').trigger('change');
31
- } , 1000);
32
-
33
- }
34
-
35
- var InboundShortcodes = {
36
- getUrlVars: function () {
37
- var vars = [], hash;
38
- var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
39
- for (var i = 0; i < hashes.length; i++) {
40
- hash = hashes[i].split('=');
41
- vars.push(hash[0]);
42
- vars[hash[0]] = hash[1];
43
- }
44
- return vars;
45
- },
46
- getUrlVar: function (name) {
47
- return InboundShortcodes.getUrlVars()[name];
48
- },
49
- generate: function () {
50
-
51
- var output = jQuery('#_inbound_shortcodes_output').text(),
52
- newoutput = output;
53
-
54
- jQuery('.inbound-shortcodes-input').each(function () {
55
-
56
- var input = jQuery(this),
57
- theid = input.attr('id'),
58
- id = theid.replace('inbound_shortcode_', ''),
59
- re = new RegExp('{{' + id + '}}', 'g');
60
-
61
- if (input.is(':checkbox')) {
62
- var val = ( jQuery(this).is(':checked') ) ? '1' : '0';
63
- newoutput = newoutput.replace(re, val);
64
- } else {
65
- newoutput = newoutput.replace(re, input.val());
66
- }
67
- // Add fix to remove empty params. maybe
68
- });
69
-
70
- jQuery('#_inbound_shortcodes_newoutput').remove();
71
- jQuery('#inbound-shortcodes-form-table').prepend('<textarea id="_inbound_shortcodes_newoutput" class="hidden">' + newoutput + '</textarea>');
72
- /* new stuff */
73
- jQuery("#insert_new_shortcode_here").val(newoutput);
74
- InboundShortcodes.updatePreview();
75
-
76
- },
77
-
78
- generateChild: function () {
79
-
80
- var output = jQuery('#_inbound_shortcodes_child_output').text(),
81
- parent_output = '',
82
- outputs = '';
83
-
84
- jQuery('.child-clone-row').each(function () {
85
-
86
- var row = jQuery(this),
87
- row_output = output;
88
-
89
- jQuery('.inbound-shortcodes-child-input', this).each(function () {
90
- var input = jQuery(this),
91
- theid = input.attr('id'),
92
- id = theid.replace('inbound_shortcode_', ''),
93
- re = new RegExp('{{' + id + '}}', 'g');
94
-
95
- if (input.is(':checkbox')) {
96
- var val = ( jQuery(this).is(':checked') ) ? '1' : '0';
97
- row_output = row_output.replace(re, val);
98
- }
99
- else {
100
- if (input.val() == null ) {
101
- input.val('');
102
- }
103
- row_output = row_output.replace(re, input.val().replace(/"/g, "'"));
104
- }
105
- //console.log(newoutput);
106
- });
107
-
108
- outputs = outputs + row_output + "\n";
109
- });
110
-
111
- jQuery('#_inbound_shortcodes_child_newoutput').remove();
112
- jQuery('.child-clone-rows').prepend('<div id="_inbound_shortcodes_child_newoutput" class="hidden">' + outputs + '</div>');
113
-
114
- this.generate();
115
- parent_output = jQuery('#_inbound_shortcodes_newoutput').text().replace('{{child}}', outputs);
116
-
117
- jQuery('#_inbound_shortcodes_newoutput').remove();
118
- jQuery('#inbound-shortcodes-form-table').prepend('<textarea id="_inbound_shortcodes_newoutput" class="hidden">' + parent_output + '</textarea>');
119
- /* new stuff */
120
- jQuery("#insert_new_shortcode_here").val(parent_output);
121
- InboundShortcodes.updatePreview();
122
-
123
- },
124
-
125
- children: function () {
126
-
127
- jQuery('.child-clone-rows').appendo({
128
- subSelect: '> div.child-clone-row:last-child',
129
- allowDelete: false,
130
- focusFirst: false,
131
- onAdd: row_add_callback
132
- });
133
-
134
- jQuery("body").on('click', '.child-clone-row', function () {
135
- var exlcude_id = jQuery(this).attr('id');
136
- console.log(exlcude_id);
137
- jQuery('.child-clone-row .minimize-class').not("#" + exlcude_id + " .minimize-class").addClass('tog-hide-it');
138
- jQuery(this).find(".minimize-class").removeClass('tog-hide-it');
139
- jQuery(this).find('.child-clone-row-shrink').text("Minimize");
140
-
141
- });
142
- // Clone Field values
143
- jQuery("body").on('click', '.child-clone-row-exact', function () {
144
- var btn = jQuery(this),
145
- clone_box = btn.parent();
146
- var new_clone = clone_box.clone();
147
- jQuery(clone_box).after(new_clone);
148
- row_add_callback();
149
- });
150
- // Shrink Rows
151
- jQuery("body").on('click', '.child-clone-row-shrink', function () {
152
- var btn = jQuery(this),
153
- btn_class = btn.hasClass('shrunken'),
154
- row = btn.parent();
155
- console.log('clicked');
156
- if (btn_class === false) {
157
- console.log('nope.');
158
- btn.addClass('shrunken');
159
- row.find(".minimize-class").addClass('tog-hide-it');
160
- btn.text("Expand");
161
- } else {
162
- console.log('yep');
163
- btn.removeClass('shrunken');
164
- row.find(".minimize-class").removeClass('tog-hide-it');
165
- btn.text("minimize");
166
- }
167
-
168
- return false;
169
- });
170
-
171
- jQuery('.child-clone-row-remove').live('click', function () {
172
- var btn = jQuery(this),
173
- row = btn.parent();
174
-
175
-
176
- if (jQuery('.child-clone-row').size() > 1) {
177
- row.remove();
178
- row_add_callback();
179
- }
180
- else {
181
- alert('You need a minimum of one row');
182
- }
183
- return false;
184
- });
185
-
186
- jQuery('.child-clone-rows').sortable({
187
- placeholder: 'sortable-placeholder',
188
- items: '.child-clone-row',
189
- stop: row_add_callback
190
- });
191
-
192
- },
193
-
194
- updatePreview: function () {
195
-
196
- if (jQuery('#inbound-shortcodes-preview').size() > 0) {
197
-
198
- var shortcode = jQuery('#_inbound_shortcodes_newoutput').val(),
199
- iframe = jQuery('#inbound-shortcodes-preview'),
200
- theiframeSrc = iframe.attr('src'),
201
- thesiframeSrc = theiframeSrc.split('preview.php'),
202
- shortcode_name = jQuery("#inbound_current_shortcode").val(),
203
- form_id = jQuery("#post_ID").val(),
204
- iframeSrc = thesiframeSrc[0] + 'preview.php';
205
- // Add form id to CPT preview
206
- if (shortcode_name === "insert_inbound_form_shortcode") {
207
- if (typeof (inbound_forms) != "undefined" && inbound_forms !== null) {
208
- var shortcode = shortcode.replace('[inbound_form', '[inbound_form id="' + form_id + '"');
209
- }
210
- }
211
- if (shortcode_name === "insert_styled_list_shortcode" || shortcode_name === "insert_button_shortcode") {
212
- var shortcode = shortcode.replace(/#/g, '');
213
- }
214
- // updates the src value
215
- iframe.attr('src', iframeSrc + '?post=' + inbound_shortcodes.form_id + '&sc=' + InboundShortcodes.htmlEncode(shortcode));
216
-
217
- }
218
-
219
- },
220
-
221
- fill_form_fields: function () {
222
- var SelectionData = jQuery("#cpt-form-serialize").text();
223
-
224
- if (SelectionData != "") {
225
- jQuery.each(SelectionData.split('&'), function (index, elem) {
226
- var vals = elem.split('=');
227
-
228
- var $select_val = jQuery('select[name="' + vals[0] + '"]').attr('name');
229
- var $select = jQuery('select[name="' + vals[0] + '"]');
230
- var $input = jQuery('input[name="' + vals[0] + '"]'); // input vals
231
- var input_type = jQuery('input[name="' + vals[0] + '"]').attr('type');
232
- var $checkbox = jQuery('input[name="' + vals[0] + '"]'); // input vals
233
- var $textarea = jQuery('textarea[name="' + vals[0] + '"]'); // input vals
234
- var separator = '';
235
- /*if ($div.html().length > 0) {
236
- separator = ', ';
237
- }*/
238
- //console.log(input_type);
239
- $input.val(decodeURIComponent(vals[1].replace(/\+/g, ' ')));
240
-
241
- if (input_type === 'checkbox' && vals[1] === 'on') {
242
- $input.prop("checked", true);
243
- }
244
- if ($select_val != 'inbound_shortcode_insert_default') {
245
- $select.val(decodeURIComponent(vals[1].replace(/\+/g, ' ')));
246
- }
247
-
248
- $textarea.val(decodeURIComponent(vals[1].replace(/\+/g, ' ')));
249
-
250
- });
251
- }
252
-
253
- },
254
- update_fields: function () {
255
- var insert_form = jQuery("#inbound_shortcode_insert_default").val();
256
- var current_code = jQuery("#inbound_current_shortcode").val();
257
- if (current_code === "quick_insert_inbound_form_shortcode") {
258
- return false;
259
- }
260
-
261
- var patt = /^form_/gi;
262
- var result = patt.test(insert_form);
263
- if (result === false) {
264
-
265
- var form_insert = window[insert_form];
266
- if (typeof (form_insert) != "undefined" && form_insert != null && form_insert != "") {
267
- var fields = form_insert.form_fields;
268
- var field_count = form_insert.field_length;
269
- } else {
270
- var fields = "";
271
- var field_count = 1;
272
- }
273
-
274
- if (jQuery('.child-clone-row').length != "1") {
275
- if (confirm('Are you sure you want to overwrite the current form you are building? Selecting another form template will clear your current fields/settings')) {
276
- //jQuery(".child-clone-rows.ui-sortable").html(form_insert); // old dom junk
277
- jQuery("#cpt-form-serialize").text(fields);
278
- jQuery(".child-clone-row").remove(); // clear old fields
279
- var i = 0;
280
- while (i < field_count) {
281
- jQuery("#form-child-add").click();
282
- i++;
283
- }
284
- InboundShortcodes.fill_form_fields();
285
- } else {
286
- jQuery("#inbound_shortcode_insert_default").val(jQuery.data(this, 'current')); // added parenthesis (edit)
287
- return false;
288
- }
289
- } else {
290
- jQuery("#cpt-form-serialize").text(fields);
291
- jQuery(".child-clone-row").remove(); // clear old fields
292
- var i = 0;
293
- while (i < field_count) {
294
- jQuery("#form-child-add").click();
295
- i++;
296
- }
297
- InboundShortcodes.fill_form_fields();
298
- }
299
-
300
-
301
- } else {
302
- var form_insert = 'custom';
303
- var form_id = insert_form.replace('form_', '');
304
-
305
- //run ajax
306
- jQuery.ajax({
307
- type: 'POST',
308
- url: ajaxurl,
309
- context: this,
310
- data: {
311
- action: 'inbound_form_get_data',
312
- form_id: form_id,
313
- nonce: inbound_shortcodes.inbound_shortcode_nonce
314
- },
315
-
316
- success: function (data) {
317
- var self = this;
318
- var str = data;
319
-
320
- // If form name already exists
321
- var obj = JSON.parse(str);
322
- //console.log(obj);
323
- var field_count = obj.field_count;
324
- console.log(field_count);
325
- var i = 1;
326
- var form_values = obj.field_values;
327
- var form_insert = obj.form_settings_data;
328
- jQuery("#cpt-form-serialize").text(form_values);
329
- // Stop form overwrites from happening
330
- if (jQuery('.child-clone-row').length != "1") {
331
- if (confirm('Are you sure you want to overwrite the current form you are building? Selecting another form template will clear your current fields/settings')) {
332
- //jQuery(".child-clone-rows.ui-sortable").html(form_insert); // old insert method
333
- // new method
334
- jQuery(".child-clone-row").remove(); // clear old fields
335
- var i = 0;
336
- while (i < field_count) {
337
- jQuery("#form-child-add").click();
338
- i++;
339
- }
340
- InboundShortcodes.fill_form_fields();
341
- jQuery("#_inbound_shortcodes_newoutput").text(obj.inbound_shortcode);
342
- /* new stuff */
343
- jQuery("#insert_new_shortcode_here").val(obj.inbound_shortcode);
344
- InboundShortcodes.generate();
345
- InboundShortcodes.generateChild();
346
- } else {
347
- jQuery(this).val(jQuery.data(this, 'current')); // added parenthesis (edit)
348
- return false;
349
- }
350
-
351
- } else {
352
- while (i < field_count) {
353
- jQuery("#form-child-add").click();
354
- i++;
355
- }
356
- InboundShortcodes.fill_form_fields();
357
- jQuery("#_inbound_shortcodes_newoutput").text(obj.inbound_shortcode);
358
- /* new stuff */
359
- jQuery("#insert_new_shortcode_here").val(obj.inbound_shortcode);
360
- InboundShortcodes.generate();
361
- InboundShortcodes.generateChild();
362
- }
363
-
364
- jQuery('body').trigger("inbound_forms_data_ready");
365
- jQuery.data(this, 'current', jQuery(this).val());
366
-
367
- /* Make sure field type options are revealed */
368
- setTimeout(function() {
369
- jQuery('[data-field-name="field_type"]').each(function () {
370
- jQuery(this).trigger('change');
371
- });
372
- } , 1000 );
373
- },
374
-
375
- error: function (MLHttpRequest, textStatus, errorThrown) {
376
- alert("Ajax not enabled");
377
- }
378
-
379
- });
380
-
381
- return form_insert;
382
- }
383
-
384
- },
385
- load: function () {
386
-
387
- var InboundShortcodes = this,
388
- popup = jQuery('#inbound-shortcodes-popup'),
389
- form = jQuery('#inbound-shortcodes-form', popup),
390
- output = jQuery('#_inbound_shortcodes_output', form).text(),
391
- popupType = jQuery('#_inbound_shortcodes_popup', form).text(),
392
- shortcode_name = jQuery("#inbound_current_shortcode").val(),
393
- newoutput = '';
394
-
395
-
396
- InboundShortcodes.generate();
397
- InboundShortcodes.children();
398
- InboundShortcodes.generateChild();
399
- jQuery("#inbound-shortcodes-popup").addClass('shortcode-' + shortcode_name);
400
- // Conditional Form Only extras
401
- if (shortcode_name === "insert_inbound_form_shortcode") {
402
- jQuery("#inbound_insert_shortcode_two, .inbound_shortcode_child_tbody, .main-design-settings").hide();
403
- jQuery("#inbound_save_form").show();
404
- jQuery("#inbound_insert_shortcode_two").removeClass('button-primary').addClass('button').text('Insert Full Shortcode')
405
- jQuery('.step-item').on('click', function () {
406
- jQuery(this).addClass('active').siblings().removeClass('active');
407
- var show = jQuery(this).attr('data-display-options');
408
- jQuery('.inbound_tbody').hide();
409
- jQuery(show).show();
410
- });
411
- // Insert default forms
412
- jQuery('body').on('change', '#inbound_shortcode_insert_default', function () {
413
- InboundShortcodes.update_fields();
414
- });
415
-
416
- }
417
- if (shortcode_name === 'insert_button_shortcode' || shortcode_name === 'insert_styled_list_shortcode' || shortcode_name === "insert_inbound_form_shortcode") {
418
-
419
- function format(state) {
420
- if (!state.id) return state.text; // optgroup
421
- return "<i class='fa-" + state.id.toLowerCase() + " inbound-icon-padding'></i>" + state.text + '';
422
- }
423
-
424
- jQuery("body").on("inbound_forms_data_ready", function () {
425
- jQuery("#inbound_shortcode_icon").select2({
426
- placeholder: "Select an icon for the button",
427
- allowClear: true,
428
- formatResult: format,
429
- formatSelection: format,
430
- escapeMarkup: function (m) {
431
- return m;
432
- }
433
- });
434
- });
435
- }
436
-
437
- if (shortcode_name === "insert_inbound_form_shortcode") {
438
-
439
- jQuery("#inbound_shortcode_lists").select2({
440
- placeholder: "Select one or more lists",
441
-
442
- });
443
- jQuery("#inbound_shortcode_tags").select2({
444
- placeholder: "Select one or more tags",
445
-
446
- });
447
-
448
-
449
- jQuery("body").on("inbound_forms_data_ready", function () {
450
- setTimeout(function () {
451
- var fill_list_vals = jQuery("#inbound_shortcode_lists_hidden").val().split(",");
452
- jQuery("#inbound_shortcode_lists").val(fill_list_vals).select2();
453
- var fill_tag_vals = jQuery("#inbound_shortcode_tags_hidden").val().split(",");
454
- jQuery("#inbound_shortcode_tags").val(fill_tag_vals).select2();
455
- }, 200);
456
- });
457
-
458
- /* add selected lists to hidden fields */
459
- jQuery("body").on('change', '#inbound_shortcode_lists', function () {
460
- var list_ids = jQuery("#inbound_shortcode_lists").select2("data");
461
- var list_ids_array = new Array();
462
- jQuery.each(list_ids, function (key, valueObj) {
463
- var the_id = valueObj['id'];
464
- list_ids_array.push(the_id);
465
- });
466
-
467
- var final_list_ids = list_ids_array.join();
468
- console.log(final_list_ids);
469
- jQuery("#inbound_shortcode_lists_hidden").val(final_list_ids);
470
- });
471
-
472
- /* add selected tags to hidden fields */
473
- jQuery("body").on('change', '#inbound_shortcode_tags', function () {
474
- var tag_ids = jQuery("#inbound_shortcode_tags").select2("data");
475
- var tag_ids_array = new Array();
476
- jQuery.each(tag_ids, function (key, valueObj) {
477
- var the_id = valueObj['id'];
478
- tag_ids_array.push(the_id);
479
- });
480
-
481
- var final_tag_ids = tag_ids_array.join();
482
- console.log(final_tag_ids);
483
- jQuery("#inbound_shortcode_tags_hidden").val(final_tag_ids);
484
- });
485
- }
486
-
487
- if (shortcode_name === 'insert_call_to_action') {
488
-
489
- jQuery("body").on('change', '#insert_inbound_cta, #inbound_shortcode_align', function () {
490
- var cta_id = jQuery("#insert_inbound_cta").find('option:selected').val();
491
-
492
- var align = jQuery('#inbound_shortcode_align').val();
493
- setTimeout(function () {
494
- jQuery("#_inbound_shortcodes_newoutput").html('[cta id="' + cta_id + '" align="' + align + '"]');
495
- /* new stuff */
496
- jQuery("#insert_new_shortcode_here").val('[cta id="' + cta_id + '" align="' + align + '"]');
497
- }, 1000);
498
- });
499
- }
500
- if (shortcode_name === "quick_insert_inbound_form_shortcode") {
501
- console.log("QUICK INSERT");
502
-
503
- jQuery('#inbound_shortcode_insert_default option').each(function () {
504
- var option_name = jQuery(this).val();
505
- var option_fix = option_name.replace('form_', '');
506
- jQuery(this).val(option_fix);
507
- if (option_name === "none") {
508
- jQuery(this).text('Choose Form');
509
- }
510
- });
511
- //row_add_callback();
512
- // Insert default forms
513
- jQuery('body').on('change', '#inbound_shortcode_insert_default', function () {
514
- var val = jQuery(this).val();
515
- var option = jQuery(this).find("option[value='" + val + "']").text();
516
- jQuery('#inbound_shortcode_form_name').val(option);
517
- InboundShortcodes.update_fields();
518
- });
519
- }
520
-
521
-
522
- // Save Shortcode Function
523
- var shortcode_nonce_val = inbound_shortcodes.inbound_shortcode_nonce;
524
- jQuery("body").on('mousedown', '#inbound_save_form', function () {
525
-
526
- var post_id = jQuery("#post_ID").val();
527
- var form_settings = jQuery(".child-clone-rows.ui-sortable").html().trim();
528
- var shortcode_name = jQuery("#inbound_current_shortcode").val();
529
- var shortcode_value = jQuery('#_inbound_shortcodes_newoutput').html().trim();
530
- var form_name = jQuery("#inbound_shortcode_form_name").val();
531
- var form_values = jQuery("#inbound-shortcodes-form").serialize();
532
- var notify_email = jQuery("#inbound_shortcode_notify").val();
533
- var notify_email_subject = jQuery("#inbound_shortcode_notify_subject").val();
534
- var field_count = jQuery('.child-clone-row').length;
535
- var redirect_value = jQuery('#inbound_shortcode_redirect').val().trim();
536
-
537
- if (typeof (inbound_forms) != "undefined" && inbound_forms !== null) {
538
- var post_type = 'inbound-forms';
539
- var send_email = jQuery("#inbound_email_send_notification").val();
540
- var send_email_template = jQuery("#inbound_email_send_notification_template").val();
541
- var send_email_subject = jQuery("#inbound_confirmation_subject").val();
542
- var email_contents = jQuery("#content_ifr").contents().find('body').html(); // email responder
543
- } else {
544
- var post_type = 'normal';
545
- var send_email = 'off';
546
- var send_email_subject = '';
547
- var email_contents = ''; // if post created on other post
548
- }
549
-
550
- if (typeof email_contents == 'undefined') {
551
- email_contents = jQuery('#content').val();
552
- }
553
-
554
- var email_exists = InboundShortcodes.get_email();
555
- console.log(email_exists);
556
- if (email_exists != "") {
557
- console.log('There is an email!');
558
- } else {
559
- if (confirm('We have detected no email field being used in this form. This will cause lead tracking to not work. Are you sure you want to not track this form? Click Cancel to add an email field')) {
560
- console.log('continue');
561
- } else {
562
-
563
- jQuery('.step-item').eq(1).click();
564
- jQuery('.form-row.has-child').before('<h2 style="text-align:center; margin:0px;">Add an Email Field to the form</h2>');
565
- return false;
566
- }
567
- }
568
-
569
- /*Redirect whitespace cleaning*/
570
- if(form_values.indexOf("&inbound_shortcode_redirect_2=+")){
571
- var form_values2 = form_values.substring(form_values.indexOf("&inbound_shortcode_redirect_2=") + 30, form_values.indexOf("inbound_shortcode_notify"));
572
- var saveString = form_values2;
573
- var length = form_values2.length;
574
-
575
- for(i = 0; i < length; i++){
576
- if(form_values2.charAt(0) == '+'){
577
- form_values2 = form_values2.replace('+', '');
578
- }else{
579
- break;
580
- }
581
- }
582
- form_values = form_values.replace(saveString, form_values2);
583
- }
584
-
585
- if (shortcode_name === "insert_inbound_form_shortcode" && form_name == "") {
586
- jQuery(".step-item.first").click();
587
-
588
- alert("Please Insert a Form Name!");
589
- jQuery("#inbound_shortcode_form_name").addClass('need-value').focus();
590
- } else {
591
- function killBadGuys(str) {
592
- if (typeof str === 'string') {
593
- if (str.indexOf('<script') != -1) {
594
- return 'bad';
595
- } else {
596
- return 'good';
597
- }
598
- }
599
- }
600
-
601
- var payload = {
602
- action: 'inbound_form_save',
603
- name: form_name,
604
- shortcode: shortcode_value,
605
- field_count: field_count,
606
- form_values: form_values,
607
- notify_email: notify_email,
608
- notify_email_subject: notify_email_subject.replace(/\[~/g, '&#91;').replace(/\]/g, '&#93;'),
609
- send_email: send_email,
610
- send_email_template: send_email_template,
611
- send_subject: send_email_subject,
612
- form_settings: form_settings,
613
- post_id: post_id,
614
- post_type: post_type,
615
- email_contents: email_contents,
616
- redirect_value: redirect_value,
617
- nonce: shortcode_nonce_val
618
- };
619
-
620
- for (var key in payload) {
621
- //console.log( payload[key] );
622
- var test = killBadGuys(payload[key]);
623
- console.log(test);
624
- console.log(payload[key]);
625
- if (test === "bad") {
626
- return false;
627
- }
628
- }
629
- console.log('run');
630
- jQuery.ajax({
631
- type: 'POST',
632
- url: ajaxurl,
633
- context: this,
634
- data: payload,
635
-
636
- success: function (data) {
637
- var self = this;
638
-
639
- console.log(data);
640
- var str = data;
641
- // If form name already exists
642
- if (str === "\"Found\"") {
643
- alert("A Form by this name already exists. Please choose another name or select your existing form from the dropdown");
644
- return false;
645
- }
646
- // If form name already exists
647
- var obj = JSON.parse(str);
648
- console.log(obj);
649
-
650
-
651
- var form_id = obj.post_id;
652
- var final_form_name = obj.form_name;
653
-
654
- //var post_id_final = new_post.replace('"', '');
655
- var site_base = inbound_shortcodes.adminurl + '/post.php?post=' + form_id + '&action=edit';
656
-
657
- var worked = '<span class="lp-success-message">Form Created & Saved</span><a style="padding-left:10px;" target="_blank" href="' + site_base + '" class="event-view-post">View/Edit Form</a>';
658
-
659
- var final_short_form = '[inbound_forms id="' + form_id + '" name="' + final_form_name + '"]';
660
- if (typeof (inbound_forms) != "undefined" && inbound_forms !== null) {
661
- jQuery(self).text('Form Updated').css('font-size', '25px');
662
- var draft = jQuery("#hidden_post_status").val();
663
- if (draft === 'draft') {
664
- window.location.href = inbound_shortcodes.adminurl + '/post.php?post=' + form_id + '&action=edit&reload=true'
665
- }
666
- setTimeout(function () {
667
- jQuery(self).text('Save Form').css('font-size', '17px');
668
- }, 5000);
669
- } else {
670
- // set correct ID for insert
671
- /* legacy if for old shortcode inserter */
672
-
673
- }
674
-
675
- },
676
-
677
- error: function (MLHttpRequest, textStatus, errorThrown) {
678
- alert("Ajax not enabled");
679
- }
680
- });
681
- }
682
- return false;
683
- });
684
- function debounce(func, wait, immediate) {
685
- var timeout;
686
- return function () {
687
- var context = this, args = arguments;
688
- var later = function () {
689
- timeout = null;
690
- if (!immediate) func.apply(context, args);
691
- };
692
- var callNow = immediate && !timeout;
693
- clearTimeout(timeout);
694
- timeout = setTimeout(later, wait);
695
- if (callNow) func.apply(context, args);
696
- };
697
- };
698
-
699
- jQuery('body').on('change, keyup', '.inbound-shortcodes-child-input', function () {
700
- clearTimeout(jQuery.data(this, 'typeTimer'));
701
- jQuery.data(this, 'typeTimer', setTimeout(function () {
702
- InboundShortcodes.generateChild(); // runs refresh for children
703
- var update_dom = jQuery(this).val();
704
- var update_dom = update_dom.replace(/"/g, "'");
705
- jQuery(this).attr('value', update_dom);
706
- }, 1000));
707
- });
708
-
709
- jQuery('.inbound-shortcodes-input', form).on('change, keyup', function () {
710
- clearTimeout(jQuery.data(this, 'typeTimer'));
711
- jQuery.data(this, 'typeTimer', setTimeout(function () {
712
- var exclude_input = jQuery(this).parent().parent().parent().parent().hasClass('exclude-from-refresh');
713
- console.log('yes');
714
- console.log(exclude_input);
715
- if (exclude_input != 'true') {
716
- InboundShortcodes.generate(); // runs refresh
717
- InboundShortcodes.generateChild();
718
- }
719
- var update_dom = jQuery(this).val();
720
- var update_dom = update_dom.replace(/"/g, "'");
721
- jQuery(this).attr('value', update_dom);
722
- }, 1000));
723
- });
724
-
725
- jQuery('body').on('change', 'input[type="checkbox"], input[type="radio"], input[type="color"], select', function () {
726
- var exclude_input = jQuery(this).closest('tbody').hasClass('exclude-from-refresh');
727
-
728
- if (!exclude_input) {
729
- InboundShortcodes.generateChild(); // runs refresh for fields
730
- }
731
-
732
- var input_type = jQuery(this).attr('type');
733
- var update_dom = jQuery(this).val();
734
- if (input_type === "checkbox") {
735
- var checked = jQuery(this).is(":checked");
736
- if (checked === true) {
737
- jQuery(this).attr('checked', true);
738
- } else {
739
- jQuery(this).removeAttr("checked");
740
- }
741
-
742
- } else if (input_type === "radio") {
743
-
744
- } else if(jQuery(this).attr("multiple") && jQuery(this).hasClass("select2-offscreen")){
745
-
746
- } else {
747
- jQuery(this).find("option").removeAttr("selected");
748
- jQuery(this).find("option[value='" + update_dom + "']").attr('selected', update_dom);
749
-
750
- }
751
-
752
- });
753
-
754
- jQuery("body").on('click', '.show-advanced-fields', function () {
755
-
756
- jQuery(this).parent().parent().parent().parent().find(".inbound-tab-class-advanced").show();
757
- jQuery(this).removeClass("show-advanced-fields");
758
- jQuery(this).addClass("hide-advanced-options");
759
- jQuery(this).text("Hide advanced options");
760
-
761
- });
762
-
763
- jQuery("body").on('click', '.hide-advanced-options', function () {
764
-
765
- jQuery(this).parent().parent().parent().parent().find(".inbound-tab-class-advanced").hide();
766
- jQuery(this).removeClass("hide-advanced-options");
767
- jQuery(this).text("Show advanced options");
768
- jQuery(this).addClass("show-advanced-fields");
769
-
770
- });
771
-
772
- jQuery('body').on('change', 'select', function () {
773
- var find_this = jQuery(this).attr('data-field-name'),
774
- exclude_status = jQuery(this).hasClass('exclude'),
775
- this_val = jQuery(this).val();
776
- var parent_el = jQuery(this).parent().parent().parent();
777
-
778
- if (exclude_status != true) {
779
- jQuery(parent_el).find(".dynamic-visable-on").hide();
780
- jQuery(parent_el).find('.reveal-' + this_val).removeClass('inbound-hidden-row').show().addClass('dynamic-visable-on');
781
- }
782
- if (this_val === "html-block") {
783
- var empty = jQuery(parent_el).find(".child-clone-row-form-row input").first().val();
784
- if (empty == "") {
785
- jQuery(parent_el).find(".child-clone-row-form-row input").first().val('HTML Block');
786
- }
787
- }
788
- if (this_val === "divider") {
789
- var empty = jQuery(parent_el).find(".child-clone-row-form-row input").first().val();
790
- if (empty == "") {
791
- jQuery(parent_el).find(".child-clone-row-form-row input").first().val('Divider');
792
- }
793
- }
794
- });
795
-
796
- setTimeout(function () {
797
- jQuery('.inbound_shortcode_child_tbody select').each(function () {
798
- var find_this = jQuery(this).attr('data-field-name'),
799
- exclude_status = jQuery(this).hasClass('exclude'),
800
- this_val = jQuery(this).val();
801
- var parent_el = jQuery(this).parent().parent().parent();
802
-
803
- if (exclude_status != true) {
804
- jQuery(parent_el).find(".dynamic-visable-on").hide();
805
- jQuery(parent_el).find('.reveal-' + this_val).removeClass('inbound-hidden-row').show().addClass('dynamic-visable-on');
806
- }
807
- });
808
- }, 2000);
809
-
810
- },
811
- get_email: function () {
812
- var email_field = '';
813
- jQuery('.inbound-form-label-input').each(function () {
814
- var this_val = jQuery(this).val();
815
- var res = this_val.match(/email|e-mail/gi);
816
- if (res != null) {
817
- console.log(this_val);
818
- return email_field = 'yes';
819
- }
820
- });
821
- return email_field;
822
- },
823
- htmlEncode: function (html) {
824
- var html = html.replace(/</g, "&lt;");
825
- var html = html.replace(/>/g, "&gt;");
826
- var html = html.replace(/\?/g, "%3F");
827
- var html = html.replace(/\/>/, "%2F%3E");
828
- //var html = html.replace(/&/g, "%26");
829
- var html = encodeURIComponent(html);
830
- //console.log(html);
831
- return html;
832
- }
833
-
834
- };
835
-
836
-
837
- jQuery(document).ready(function () {
838
-
839
- jQuery('#inbound-shortcodes-popup').livequery(function () {
840
- InboundShortcodes.load();
841
- });
842
-
843
-
844
- if (InboundShortcodes.getUrlVar("reload") === 'true') {
845
- jQuery("#post-body-content").hide();
846
- var window_url = window.location.href.replace('&reload=true', "");
847
- var window_url = window_url.replace('wp-admin//', 'wp-admin/');
848
- jQuery("#post-body").before('<h2>Please Refresh this Page to Edit your Form<h2><a href="' + window_url + '">Click to Refresh</a>');
849
- window.history.replaceState({}, document.title, window_url);
850
- }
851
-
852
- jQuery('#list-add-toggle').click(function () {
853
- jQuery('#list-add-wrap').toggleClass('wp-hidden-child');
854
- return false;
855
- });
856
-
857
- jQuery('#list-add-submit').click(function () {
858
- var list_val = jQuery('#newformlist').val();
859
- var list_parent_val = jQuery('#newlist_parent').val();
860
- if (list_val == '') {
861
-
862
- jQuery('#newformlist').focus();
863
- return false;
864
-
865
- } else {
866
- jQuery.ajax({
867
- type: "POST",
868
- url: ajaxurl,
869
- data: "list_val=" + list_val + "&list_parent_val=" + list_parent_val + "&action=inbound_form_add_lead_list",
870
- success: function (data) {
871
- var returned = jQuery.parseJSON(data);
872
- if (returned.status != 'false') {
873
- jQuery('#inbound_shortcode_lists').append('<option value="' + returned.term_id + '">' + returned.name + '</option>');
874
- jQuery('#list-ajax-response').html('List Added. Please Select From Above.');
875
- } else {
876
- alert('Not able to add list at this monent. Please try again');
877
- }
878
- }
879
- });
880
-
881
- }
882
-
883
- });
884
-
885
-
886
- });
1
+ // Row add function
2
+ function row_add_callback() {
3
+ var length = jQuery('.child-clone-row').length;
4
+
5
+ jQuery('.form-field-row-number').each(function (i) {
6
+ var addition = i + 1;
7
+ jQuery(this).text(addition);
8
+ jQuery(this).parent().attr('id', 'row-' + addition);
9
+ });
10
+ jQuery('.child-clone-row').each(function (i) {
11
+ var number = i + 1;
12
+ var the_id = jQuery(this).attr('id');
13
+ jQuery(this).find('input, select, textarea').each(function (i) {
14
+ var this_id = the_id.replace('row-', '');
15
+ var current_name = jQuery(this).attr('name');
16
+ var clean_name = current_name.replace(/_[a-zA-Z0-9]*$/g, "");
17
+ jQuery(this).attr('name', clean_name + '_' + this_id);
18
+ });
19
+ });
20
+
21
+ jQuery('.child-clone-row .minimize-class').not("#row-" + length + " .minimize-class").addClass('tog-hide-it');
22
+ jQuery('.child-clone-row-shrink').not("#row-" + length + " .child-clone-row-shrink").text("Expand");
23
+ InboundShortcodes.generate(); // runs refresh
24
+ InboundShortcodes.generateChild();
25
+ jQuery('.child-clone-row').last().find('input').first().focus(); // focus on new input
26
+ //InboundShortcodes.updatePreview();
27
+
28
+ /* make sure correct hidden fields are displayed */
29
+ setTimeout(function() {
30
+ jQuery('select[data-field-name="field_type"]').trigger('change');
31
+ } , 1000);
32
+
33
+ }
34
+
35
+ var InboundShortcodes = {
36
+ getUrlVars: function () {
37
+ var vars = [], hash;
38
+ var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
39
+ for (var i = 0; i < hashes.length; i++) {
40
+ hash = hashes[i].split('=');
41
+ vars.push(hash[0]);
42
+ vars[hash[0]] = hash[1];
43
+ }
44
+ return vars;
45
+ },
46
+ getUrlVar: function (name) {
47
+ return InboundShortcodes.getUrlVars()[name];
48
+ },
49
+ generate: function () {
50
+
51
+ var output = jQuery('#_inbound_shortcodes_output').text(),
52
+ newoutput = output;
53
+
54
+ jQuery('.inbound-shortcodes-input').each(function () {
55
+
56
+ var input = jQuery(this),
57
+ theid = input.attr('id'),
58
+ id = theid.replace('inbound_shortcode_', ''),
59
+ re = new RegExp('{{' + id + '}}', 'g');
60
+
61
+ if (input.is(':checkbox')) {
62
+ var val = ( jQuery(this).is(':checked') ) ? '1' : '0';
63
+ newoutput = newoutput.replace(re, val);
64
+ } else {
65
+ newoutput = newoutput.replace(re, input.val());
66
+ }
67
+ // Add fix to remove empty params. maybe
68
+ });
69
+
70
+ jQuery('#_inbound_shortcodes_newoutput').remove();
71
+ jQuery('#inbound-shortcodes-form-table').prepend('<textarea id="_inbound_shortcodes_newoutput" class="hidden">' + newoutput + '</textarea>');
72
+ /* new stuff */
73
+ jQuery("#insert_new_shortcode_here").val(newoutput);
74
+ InboundShortcodes.updatePreview();
75
+
76
+ },
77
+
78
+ generateChild: function () {
79
+
80
+ var output = jQuery('#_inbound_shortcodes_child_output').text(),
81
+ parent_output = '',
82
+ outputs = '';
83
+
84
+ jQuery('.child-clone-row').each(function () {
85
+
86
+ var row = jQuery(this),
87
+ row_output = output;
88
+
89
+ jQuery('.inbound-shortcodes-child-input', this).each(function () {
90
+ var input = jQuery(this),
91
+ theid = input.attr('id'),
92
+ id = theid.replace('inbound_shortcode_', ''),
93
+ re = new RegExp('{{' + id + '}}', 'g');
94
+
95
+ if (input.is(':checkbox')) {
96
+ var val = ( jQuery(this).is(':checked') ) ? '1' : '0';
97
+ row_output = row_output.replace(re, val);
98
+ }
99
+ else {
100
+ if (input.val() == null ) {
101
+ input.val('');
102
+ }
103
+ row_output = row_output.replace(re, input.val().replace(/"/g, "'"));
104
+ }
105
+ //console.log(newoutput);
106
+ });
107
+
108
+ outputs = outputs + row_output + "\n";
109
+ });
110
+
111
+ jQuery('#_inbound_shortcodes_child_newoutput').remove();
112
+ jQuery('.child-clone-rows').prepend('<div id="_inbound_shortcodes_child_newoutput" class="hidden">' + outputs + '</div>');
113
+
114
+ this.generate();
115
+ parent_output = jQuery('#_inbound_shortcodes_newoutput').text().replace('{{child}}', outputs);
116
+
117
+ jQuery('#_inbound_shortcodes_newoutput').remove();
118
+ jQuery('#inbound-shortcodes-form-table').prepend('<textarea id="_inbound_shortcodes_newoutput" class="hidden">' + parent_output + '</textarea>');
119
+ /* new stuff */
120
+ jQuery("#insert_new_shortcode_here").val(parent_output);
121
+ InboundShortcodes.updatePreview();
122
+
123
+ },
124
+
125
+ children: function () {
126
+
127
+ jQuery('.child-clone-rows').appendo({
128
+ subSelect: '> div.child-clone-row:last-child',
129
+ allowDelete: false,
130
+ focusFirst: false,
131
+ onAdd: row_add_callback
132
+ });
133
+
134
+ jQuery("body").on('click', '.child-clone-row', function () {
135
+ var exlcude_id = jQuery(this).attr('id');
136
+ console.log(exlcude_id);
137
+ jQuery('.child-clone-row .minimize-class').not("#" + exlcude_id + " .minimize-class").addClass('tog-hide-it');
138
+ jQuery(this).find(".minimize-class").removeClass('tog-hide-it');
139
+ jQuery(this).find('.child-clone-row-shrink').text("Minimize");
140
+
141
+ });
142
+ // Clone Field values
143
+ jQuery("body").on('click', '.child-clone-row-exact', function () {
144
+ var btn = jQuery(this),
145
+ clone_box = btn.parent();
146
+ var new_clone = clone_box.clone();
147
+ jQuery(clone_box).after(new_clone);
148
+ row_add_callback();
149
+ });
150
+ // Shrink Rows
151
+ jQuery("body").on('click', '.child-clone-row-shrink', function () {
152
+ var btn = jQuery(this),
153
+ btn_class = btn.hasClass('shrunken'),
154
+ row = btn.parent();
155
+ console.log('clicked');
156
+ if (btn_class === false) {
157
+ console.log('nope.');
158
+ btn.addClass('shrunken');
159
+ row.find(".minimize-class").addClass('tog-hide-it');
160
+ btn.text("Expand");
161
+ } else {
162
+ console.log('yep');
163
+ btn.removeClass('shrunken');
164
+ row.find(".minimize-class").removeClass('tog-hide-it');
165
+ btn.text("minimize");
166
+ }
167
+
168
+ return false;
169
+ });
170
+
171
+ jQuery('.child-clone-row-remove').live('click', function () {
172
+ var btn = jQuery(this),
173
+ row = btn.parent();
174
+
175
+
176
+ if (jQuery('.child-clone-row').size() > 1) {
177
+ row.remove();
178
+ row_add_callback();
179
+ }
180
+ else {
181
+ alert('You need a minimum of one row');
182
+ }
183
+ return false;
184
+ });
185
+
186
+ jQuery('.child-clone-rows').sortable({
187
+ placeholder: 'sortable-placeholder',
188
+ items: '.child-clone-row',
189
+ stop: row_add_callback
190
+ });
191
+
192
+ },
193
+
194
+ updatePreview: function () {
195
+
196
+ if (jQuery('#inbound-shortcodes-preview').size() > 0) {
197
+
198
+ var shortcode = jQuery('#_inbound_shortcodes_newoutput').val(),
199
+ iframe = jQuery('#inbound-shortcodes-preview'),
200
+ theiframeSrc = iframe.attr('src'),
201
+ thesiframeSrc = theiframeSrc.split('preview.php'),
202
+ shortcode_name = jQuery("#inbound_current_shortcode").val(),
203
+ form_id = jQuery("#post_ID").val(),
204
+ iframeSrc = thesiframeSrc[0] + 'preview.php';
205
+ // Add form id to CPT preview
206
+ if (shortcode_name === "insert_inbound_form_shortcode") {
207
+ if (typeof (inbound_forms) != "undefined" && inbound_forms !== null) {
208
+ var shortcode = shortcode.replace('[inbound_form', '[inbound_form id="' + form_id + '"');
209
+ }
210
+ }
211
+ if (shortcode_name === "insert_styled_list_shortcode" || shortcode_name === "insert_button_shortcode") {
212
+ var shortcode = shortcode.replace(/#/g, '');
213
+ }
214
+ // updates the src value
215
+ iframe.attr('src', iframeSrc + '?post=' + inbound_shortcodes.form_id + '&sc=' + InboundShortcodes.htmlEncode(shortcode));
216
+
217
+ }
218
+
219
+ },
220
+
221
+ fill_form_fields: function () {
222
+ var SelectionData = jQuery("#cpt-form-serialize").text();
223
+
224
+ if (SelectionData != "") {
225
+ jQuery.each(SelectionData.split('&'), function (index, elem) {
226
+ var vals = elem.split('=');
227
+
228
+ var $select_val = jQuery('select[name="' + vals[0] + '"]').attr('name');
229
+ var $select = jQuery('select[name="' + vals[0] + '"]');
230
+ var $input = jQuery('input[name="' + vals[0] + '"]'); // input vals
231
+ var input_type = jQuery('input[name="' + vals[0] + '"]').attr('type');
232
+ var $checkbox = jQuery('input[name="' + vals[0] + '"]'); // input vals
233
+ var $textarea = jQuery('textarea[name="' + vals[0] + '"]'); // input vals
234
+ var separator = '';
235
+ /*if ($div.html().length > 0) {
236
+ separator = ', ';
237
+ }*/
238
+ //console.log(input_type);
239
+ $input.val(decodeURIComponent(vals[1].replace(/\+/g, ' ')));
240
+
241
+ if (input_type === 'checkbox' && vals[1] === 'on') {
242
+ $input.prop("checked", true);
243
+ }
244
+ if ($select_val != 'inbound_shortcode_insert_default') {
245
+ $select.val(decodeURIComponent(vals[1].replace(/\+/g, ' ')));
246
+ }
247
+
248
+ $textarea.val(decodeURIComponent(vals[1].replace(/\+/g, ' ')));
249
+
250
+ });
251
+ }
252
+
253
+ },
254
+ update_fields: function () {
255
+ var insert_form = jQuery("#inbound_shortcode_insert_default").val();
256
+ var current_code = jQuery("#inbound_current_shortcode").val();
257
+ if (current_code === "quick_insert_inbound_form_shortcode") {
258
+ return false;
259
+ }
260
+
261
+ var patt = /^form_/gi;
262
+ var result = patt.test(insert_form);
263
+ if (result === false) {
264
+
265
+ var form_insert = window[insert_form];
266
+ if (typeof (form_insert) != "undefined" && form_insert != null && form_insert != "") {
267
+ var fields = form_insert.form_fields;
268
+ var field_count = form_insert.field_length;
269
+ } else {
270
+ var fields = "";
271
+ var field_count = 1;
272
+ }
273
+
274
+ if (jQuery('.child-clone-row').length != "1") {
275
+ if (confirm('Are you sure you want to overwrite the current form you are building? Selecting another form template will clear your current fields/settings')) {
276
+ //jQuery(".child-clone-rows.ui-sortable").html(form_insert); // old dom junk
277
+ jQuery("#cpt-form-serialize").text(fields);
278
+ jQuery(".child-clone-row").remove(); // clear old fields
279
+ var i = 0;
280
+ while (i < field_count) {
281
+ jQuery("#form-child-add").click();
282
+ i++;
283
+ }
284
+ InboundShortcodes.fill_form_fields();
285
+ } else {
286
+ jQuery("#inbound_shortcode_insert_default").val(jQuery.data(this, 'current')); // added parenthesis (edit)
287
+ return false;
288
+ }
289
+ } else {
290
+ jQuery("#cpt-form-serialize").text(fields);
291
+ jQuery(".child-clone-row").remove(); // clear old fields
292
+ var i = 0;
293
+ while (i < field_count) {
294
+ jQuery("#form-child-add").click();
295
+ i++;
296
+ }
297
+ InboundShortcodes.fill_form_fields();
298
+ }
299
+
300
+
301
+ } else {
302
+ var form_insert = 'custom';
303
+ var form_id = insert_form.replace('form_', '');
304
+
305
+ //run ajax
306
+ jQuery.ajax({
307
+ type: 'POST',
308
+ url: ajaxurl,
309
+ context: this,
310
+ data: {
311
+ action: 'inbound_form_get_data',
312
+ form_id: form_id,
313
+ nonce: inbound_shortcodes.inbound_shortcode_nonce
314
+ },
315
+
316
+ success: function (data) {
317
+ var self = this;
318
+ var str = data;
319
+
320
+ // If form name already exists
321
+ var obj = JSON.parse(str);
322
+ //console.log(obj);
323
+ var field_count = obj.field_count;
324
+ console.log(field_count);
325
+ var i = 1;
326
+ var form_values = obj.field_values;
327
+ var form_insert = obj.form_settings_data;
328
+ jQuery("#cpt-form-serialize").text(form_values);
329
+ // Stop form overwrites from happening
330
+ if (jQuery('.child-clone-row').length != "1") {
331
+ if (confirm('Are you sure you want to overwrite the current form you are building? Selecting another form template will clear your current fields/settings')) {
332
+ //jQuery(".child-clone-rows.ui-sortable").html(form_insert); // old insert method
333
+ // new method
334
+ jQuery(".child-clone-row").remove(); // clear old fields
335
+ var i = 0;
336
+ while (i < field_count) {
337
+ jQuery("#form-child-add").click();
338
+ i++;
339
+ }
340
+ InboundShortcodes.fill_form_fields();
341
+ jQuery("#_inbound_shortcodes_newoutput").text(obj.inbound_shortcode);
342
+ /* new stuff */
343
+ jQuery("#insert_new_shortcode_here").val(obj.inbound_shortcode);
344
+ InboundShortcodes.generate();
345
+ InboundShortcodes.generateChild();
346
+ } else {
347
+ jQuery(this).val(jQuery.data(this, 'current')); // added parenthesis (edit)
348
+ return false;
349
+ }
350
+
351
+ } else {
352
+ while (i < field_count) {
353
+ jQuery("#form-child-add").click();
354
+ i++;
355
+ }
356
+ InboundShortcodes.fill_form_fields();
357
+ jQuery("#_inbound_shortcodes_newoutput").text(obj.inbound_shortcode);
358
+ /* new stuff */
359
+ jQuery("#insert_new_shortcode_here").val(obj.inbound_shortcode);
360
+ InboundShortcodes.generate();
361
+ InboundShortcodes.generateChild();
362
+ }
363
+
364
+ jQuery('body').trigger("inbound_forms_data_ready");
365
+ jQuery.data(this, 'current', jQuery(this).val());
366
+
367
+ /* Make sure field type options are revealed */
368
+ setTimeout(function() {
369
+ jQuery('[data-field-name="field_type"]').each(function () {
370
+ jQuery(this).trigger('change');
371
+ });
372
+ } , 1000 );
373
+ },
374
+
375
+ error: function (MLHttpRequest, textStatus, errorThrown) {
376
+ alert("Ajax not enabled");
377
+ }
378
+
379
+ });
380
+
381
+ return form_insert;
382
+ }
383
+
384
+ },
385
+ load: function () {
386
+
387
+ var InboundShortcodes = this,
388
+ popup = jQuery('#inbound-shortcodes-popup'),
389
+ form = jQuery('#inbound-shortcodes-form', popup),
390
+ output = jQuery('#_inbound_shortcodes_output', form).text(),
391
+ popupType = jQuery('#_inbound_shortcodes_popup', form).text(),
392
+ shortcode_name = jQuery("#inbound_current_shortcode").val(),
393
+ newoutput = '';
394
+
395
+
396
+ InboundShortcodes.generate();
397
+ InboundShortcodes.children();
398
+ InboundShortcodes.generateChild();
399
+ jQuery("#inbound-shortcodes-popup").addClass('shortcode-' + shortcode_name);
400
+ // Conditional Form Only extras
401
+ if (shortcode_name === "insert_inbound_form_shortcode") {
402
+ jQuery("#inbound_insert_shortcode_two, .inbound_shortcode_child_tbody, .main-design-settings").hide();
403
+ jQuery("#inbound_save_form").show();
404
+ jQuery("#inbound_insert_shortcode_two").removeClass('button-primary').addClass('button').text('Insert Full Shortcode')
405
+ jQuery('.step-item').on('click', function () {
406
+ jQuery(this).addClass('active').siblings().removeClass('active');
407
+ var show = jQuery(this).attr('data-display-options');
408
+ jQuery('.inbound_tbody').hide();
409
+ jQuery(show).show();
410
+ });
411
+ // Insert default forms
412
+ jQuery('body').on('change', '#inbound_shortcode_insert_default', function () {
413
+ InboundShortcodes.update_fields();
414
+ });
415
+
416
+ }
417
+ if (shortcode_name === 'insert_button_shortcode' || shortcode_name === 'insert_styled_list_shortcode' || shortcode_name === "insert_inbound_form_shortcode") {
418
+
419
+ function format(state) {
420
+ if (!state.id) return state.text; // optgroup
421
+ return "<i class='fa-" + state.id.toLowerCase() + " inbound-icon-padding'></i>" + state.text + '';
422
+ }
423
+
424
+ jQuery("body").on("inbound_forms_data_ready", function () {
425
+ jQuery("#inbound_shortcode_icon").select2({
426
+ placeholder: "Select an icon for the button",
427
+ allowClear: true,
428
+ formatResult: format,
429
+ formatSelection: format,
430
+ escapeMarkup: function (m) {
431
+ return m;
432
+ }
433
+ });
434
+ });
435
+ }
436
+
437
+ if (shortcode_name === "insert_inbound_form_shortcode") {
438
+
439
+ jQuery("#inbound_shortcode_lists").select2({
440
+ placeholder: "Select one or more lists",
441
+
442
+ });
443
+ jQuery("#inbound_shortcode_tags").select2({
444
+ placeholder: "Select one or more tags",
445
+
446
+ });
447
+
448
+
449
+ jQuery("body").on("inbound_forms_data_ready", function () {
450
+ setTimeout(function () {
451
+ var fill_list_vals = jQuery("#inbound_shortcode_lists_hidden").val().split(",");
452
+ jQuery("#inbound_shortcode_lists").val(fill_list_vals).select2();
453
+ var fill_tag_vals = jQuery("#inbound_shortcode_tags_hidden").val().split(",");
454
+ jQuery("#inbound_shortcode_tags").val(fill_tag_vals).select2();
455
+ }, 200);
456
+ });
457
+
458
+ /* add selected lists to hidden fields */
459
+ jQuery("body").on('change', '#inbound_shortcode_lists', function () {
460
+ var list_ids = jQuery("#inbound_shortcode_lists").select2("data");
461
+ var list_ids_array = new Array();
462
+ jQuery.each(list_ids, function (key, valueObj) {
463
+ var the_id = valueObj['id'];
464
+ list_ids_array.push(the_id);
465
+ });
466
+
467
+ var final_list_ids = list_ids_array.join();
468
+ console.log(final_list_ids);
469
+ jQuery("#inbound_shortcode_lists_hidden").val(final_list_ids);
470
+ });
471
+
472
+ /* add selected tags to hidden fields */
473
+ jQuery("body").on('change', '#inbound_shortcode_tags', function () {
474
+ var tag_ids = jQuery("#inbound_shortcode_tags").select2("data");
475
+ var tag_ids_array = new Array();
476
+ jQuery.each(tag_ids, function (key, valueObj) {
477
+ var the_id = valueObj['id'];
478
+ tag_ids_array.push(the_id);
479
+ });
480
+
481
+ var final_tag_ids = tag_ids_array.join();
482
+ console.log(final_tag_ids);
483
+ jQuery("#inbound_shortcode_tags_hidden").val(final_tag_ids);
484
+ });
485
+ }
486
+
487
+ if (shortcode_name === 'insert_call_to_action') {
488
+
489
+ jQuery("body").on('change', '#insert_inbound_cta, #inbound_shortcode_align', function () {
490
+ var cta_id = jQuery("#insert_inbound_cta").find('option:selected').val();
491
+
492
+ var align = jQuery('#inbound_shortcode_align').val();
493
+ setTimeout(function () {
494
+ jQuery("#_inbound_shortcodes_newoutput").html('[cta id="' + cta_id + '" align="' + align + '"]');
495
+ /* new stuff */
496
+ jQuery("#insert_new_shortcode_here").val('[cta id="' + cta_id + '" align="' + align + '"]');
497
+ }, 1000);
498
+ });
499
+ }
500
+ if (shortcode_name === "quick_insert_inbound_form_shortcode") {
501
+ console.log("QUICK INSERT");
502
+
503
+ jQuery('#inbound_shortcode_insert_default option').each(function () {
504
+ var option_name = jQuery(this).val();
505
+ var option_fix = option_name.replace('form_', '');
506
+ jQuery(this).val(option_fix);
507
+ if (option_name === "none") {
508
+ jQuery(this).text('Choose Form');
509
+ }
510
+ });
511
+ //row_add_callback();
512
+ // Insert default forms
513
+ jQuery('body').on('change', '#inbound_shortcode_insert_default', function () {
514
+ var val = jQuery(this).val();
515
+ var option = jQuery(this).find("option[value='" + val + "']").text();
516
+ jQuery('#inbound_shortcode_form_name').val(option);
517
+ InboundShortcodes.update_fields();
518
+ });
519
+ }
520
+
521
+
522
+ // Save Shortcode Function
523
+ var shortcode_nonce_val = inbound_shortcodes.inbound_shortcode_nonce;
524
+ jQuery("body").on('mousedown', '#inbound_save_form', function () {
525
+
526
+ var post_id = jQuery("#post_ID").val();
527
+ var form_settings = jQuery(".child-clone-rows.ui-sortable").html().trim();
528
+ var shortcode_name = jQuery("#inbound_current_shortcode").val();
529
+ var shortcode_value = jQuery('#_inbound_shortcodes_newoutput').html().trim();
530
+ var form_name = jQuery("#inbound_shortcode_form_name").val();
531
+ var form_values = jQuery("#inbound-shortcodes-form").serialize();
532
+ var notify_email = jQuery("#inbound_shortcode_notify").val();
533
+ var notify_email_subject = jQuery("#inbound_shortcode_notify_subject").val();
534
+ var field_count = jQuery('.child-clone-row').length;
535
+ var redirect_value = jQuery('#inbound_shortcode_redirect').val().trim();
536
+
537
+ if (typeof (inbound_forms) != "undefined" && inbound_forms !== null) {
538
+ var post_type = 'inbound-forms';
539
+ var send_email = jQuery("#inbound_email_send_notification").val();
540
+ var send_email_template = jQuery("#inbound_email_send_notification_template").val();
541
+ var send_email_subject = jQuery("#inbound_confirmation_subject").val();
542
+ var email_contents = jQuery("#content_ifr").contents().find('body').html(); // email responder
543
+ } else {
544
+ var post_type = 'normal';
545
+ var send_email = 'off';
546
+ var send_email_subject = '';
547
+ var email_contents = ''; // if post created on other post
548
+ }
549
+
550
+ if (typeof email_contents == 'undefined') {
551
+ email_contents = jQuery('#content').val();
552
+ }
553
+
554
+ /*Redirect whitespace cleaning*/
555
+ if(form_values.indexOf("&inbound_shortcode_redirect_2=+")){
556
+ var form_values2 = form_values.substring(form_values.indexOf("&inbound_shortcode_redirect_2=") + 30, form_values.indexOf("inbound_shortcode_notify"));
557
+ var saveString = form_values2;
558
+ var length = form_values2.length;
559
+
560
+ for(i = 0; i < length; i++){
561
+ if(form_values2.charAt(0) == '+'){
562
+ form_values2 = form_values2.replace('+', '');
563
+ }else{
564
+ break;
565
+ }
566
+ }
567
+ form_values = form_values.replace(saveString, form_values2);
568
+ }
569
+
570
+ if (shortcode_name === "insert_inbound_form_shortcode" && form_name == "") {
571
+ jQuery(".step-item.first").click();
572
+
573
+ alert("Please Insert a Form Name!");
574
+ jQuery("#inbound_shortcode_form_name").addClass('need-value').focus();
575
+ } else {
576
+ function killBadGuys(str) {
577
+ if (typeof str === 'string') {
578
+ if (str.indexOf('<script') != -1) {
579
+ return 'bad';
580
+ } else {
581
+ return 'good';
582
+ }
583
+ }
584
+ }
585
+
586
+ var payload = {
587
+ action: 'inbound_form_save',
588
+ name: form_name,
589
+ shortcode: shortcode_value,
590
+ field_count: field_count,
591
+ form_values: form_values,
592
+ notify_email: notify_email,
593
+ notify_email_subject: notify_email_subject.replace(/\[~/g, '&#91;').replace(/\]/g, '&#93;'),
594
+ send_email: send_email,
595
+ send_email_template: send_email_template,
596
+ send_subject: send_email_subject,
597
+ form_settings: form_settings,
598
+ post_id: post_id,
599
+ post_type: post_type,
600
+ email_contents: email_contents,
601
+ redirect_value: redirect_value,
602
+ nonce: shortcode_nonce_val
603
+ };
604
+
605
+ for (var key in payload) {
606
+ //console.log( payload[key] );
607
+ var test = killBadGuys(payload[key]);
608
+ console.log(test);
609
+ console.log(payload[key]);
610
+ if (test === "bad") {
611
+ return false;
612
+ }
613
+ }
614
+ console.log('Saving form');
615
+ jQuery('#inbound_save_form').text('Saving...');
616
+ jQuery.ajax({
617
+ type: 'POST',
618
+ url: ajaxurl,
619
+ context: this,
620
+ data: payload,
621
+
622
+ success: function (data) {
623
+ var self = this;
624
+
625
+ console.log(data);
626
+ var str = data;
627
+ // If form name already exists
628
+ if (str === "\"Found\"") {
629
+ alert("A Form by this name already exists. Please choose another name or select your existing form from the dropdown");
630
+ return false;
631
+ }
632
+ // If form name already exists
633
+ var obj = JSON.parse(str);
634
+ console.log(obj);
635
+
636
+
637
+ var form_id = obj.post_id;
638
+ var final_form_name = obj.form_name;
639
+
640
+ //var post_id_final = new_post.replace('"', '');
641
+ var site_base = inbound_shortcodes.adminurl + '/post.php?post=' + form_id + '&action=edit';
642
+
643
+ var worked = '<span class="lp-success-message">Form Created & Saved</span><a style="padding-left:10px;" target="_blank" href="' + site_base + '" class="event-view-post">View/Edit Form</a>';
644
+
645
+ var final_short_form = '[inbound_forms id="' + form_id + '" name="' + final_form_name + '"]';
646
+
647
+ if (typeof (inbound_forms) != "undefined" && inbound_forms !== null) {
648
+
649
+ jQuery(self).text('Form Updated');
650
+ var draft = jQuery("#original_post_status").val();
651
+
652
+ if (draft === 'auto-draft') {
653
+ window.location.href = inbound_shortcodes.adminurl + '/post.php?post=' + form_id + '&action=edit&reload=true'
654
+ }
655
+ setTimeout(function () {
656
+ jQuery(self).text('Save Form').css('font-size', '17px');
657
+ }, 5000);
658
+ } else {
659
+ // set correct ID for insert
660
+ /* legacy if for old shortcode inserter */
661
+
662
+ }
663
+
664
+ },
665
+
666
+ error: function (MLHttpRequest, textStatus, errorThrown) {
667
+ alert("Ajax not enabled");
668
+ }
669
+ });
670
+ }
671
+ return false;
672
+ });
673
+ function debounce(func, wait, immediate) {
674
+ var timeout;
675
+ return function () {
676
+ var context = this, args = arguments;
677
+ var later = function () {
678
+ timeout = null;
679
+ if (!immediate) func.apply(context, args);
680
+ };
681
+ var callNow = immediate && !timeout;
682
+ clearTimeout(timeout);
683
+ timeout = setTimeout(later, wait);
684
+ if (callNow) func.apply(context, args);
685
+ };
686
+ };
687
+
688
+ jQuery('body').on('change, keyup', '.inbound-shortcodes-child-input', function () {
689
+ clearTimeout(jQuery.data(this, 'typeTimer'));
690
+ jQuery.data(this, 'typeTimer', setTimeout(function () {
691
+ InboundShortcodes.generateChild(); // runs refresh for children
692
+ var update_dom = jQuery(this).val();
693
+ var update_dom = update_dom.replace(/"/g, "'");
694
+ jQuery(this).attr('value', update_dom);
695
+ }, 1000));
696
+ });
697
+
698
+ jQuery('.inbound-shortcodes-input', form).on('change, keyup', function () {
699
+ clearTimeout(jQuery.data(this, 'typeTimer'));
700
+ jQuery.data(this, 'typeTimer', setTimeout(function () {
701
+ var exclude_input = jQuery(this).parent().parent().parent().parent().hasClass('exclude-from-refresh');
702
+ console.log('yes');
703
+ console.log(exclude_input);
704
+ if (exclude_input != 'true') {
705
+ InboundShortcodes.generate(); // runs refresh
706
+ InboundShortcodes.generateChild();
707
+ }
708
+ var update_dom = jQuery(this).val();
709
+ var update_dom = update_dom.replace(/"/g, "'");
710
+ jQuery(this).attr('value', update_dom);
711
+ }, 1000));
712
+ });
713
+
714
+ jQuery('body').on('change', 'input[type="checkbox"], input[type="radio"], input[type="color"], select', function () {
715
+ var exclude_input = jQuery(this).closest('tbody').hasClass('exclude-from-refresh');
716
+
717
+ if (!exclude_input) {
718
+ InboundShortcodes.generateChild(); // runs refresh for fields
719
+ }
720
+
721
+ var input_type = jQuery(this).attr('type');
722
+ var update_dom = jQuery(this).val();
723
+ if (input_type === "checkbox") {
724
+ var checked = jQuery(this).is(":checked");
725
+ if (checked === true) {
726
+ jQuery(this).attr('checked', true);
727
+ } else {
728
+ jQuery(this).removeAttr("checked");
729
+ }
730
+
731
+ } else if (input_type === "radio") {
732
+
733
+ } else if(jQuery(this).attr("multiple") && jQuery(this).hasClass("select2-offscreen")){
734
+
735
+ } else {
736
+ jQuery(this).find("option").removeAttr("selected");
737
+ jQuery(this).find("option[value='" + update_dom + "']").attr('selected', update_dom);
738
+
739
+ }
740
+
741
+ });
742
+
743
+ jQuery("body").on('click', '.show-advanced-fields', function () {
744
+
745
+ jQuery(this).parent().parent().parent().parent().find(".inbound-tab-class-advanced").show();
746
+ jQuery(this).removeClass("show-advanced-fields");
747
+ jQuery(this).addClass("hide-advanced-options");
748
+ jQuery(this).text("Hide advanced options");
749
+
750
+ });
751
+
752
+ jQuery("body").on('click', '.hide-advanced-options', function () {
753
+
754
+ jQuery(this).parent().parent().parent().parent().find(".inbound-tab-class-advanced").hide();
755
+ jQuery(this).removeClass("hide-advanced-options");
756
+ jQuery(this).text("Show advanced options");
757
+ jQuery(this).addClass("show-advanced-fields");
758
+
759
+ });
760
+
761
+ jQuery('body').on('change', 'select', function () {
762
+ var find_this = jQuery(this).attr('data-field-name'),
763
+ exclude_status = jQuery(this).hasClass('exclude'),
764
+ this_val = jQuery(this).val();
765
+ var parent_el = jQuery(this).parent().parent().parent();
766
+
767
+ if (exclude_status != true) {
768
+ jQuery(parent_el).find(".dynamic-visable-on").hide();
769
+ jQuery(parent_el).find('.reveal-' + this_val).removeClass('inbound-hidden-row').show().addClass('dynamic-visable-on');
770
+ }
771
+ if (this_val === "html-block") {
772
+ var empty = jQuery(parent_el).find(".child-clone-row-form-row input").first().val();
773
+ if (empty == "") {
774
+ jQuery(parent_el).find(".child-clone-row-form-row input").first().val('HTML Block');
775
+ }
776
+ }
777
+ if (this_val === "divider") {
778
+ var empty = jQuery(parent_el).find(".child-clone-row-form-row input").first().val();
779
+ if (empty == "") {
780
+ jQuery(parent_el).find(".child-clone-row-form-row input").first().val('Divider');
781
+ }
782
+ }
783
+ });
784
+
785
+ setTimeout(function () {
786
+ jQuery('.inbound_shortcode_child_tbody select').each(function () {
787
+ var find_this = jQuery(this).attr('data-field-name'),
788
+ exclude_status = jQuery(this).hasClass('exclude'),
789
+ this_val = jQuery(this).val();
790
+ var parent_el = jQuery(this).parent().parent().parent();
791
+
792
+ if (exclude_status != true) {
793
+ jQuery(parent_el).find(".dynamic-visable-on").hide();
794
+ jQuery(parent_el).find('.reveal-' + this_val).removeClass('inbound-hidden-row').show().addClass('dynamic-visable-on');
795
+ }
796
+ });
797
+ }, 2000);
798
+
799
+ },
800
+ htmlEncode: function (html) {
801
+ var html = html.replace(/</g, "&lt;");
802
+ var html = html.replace(/>/g, "&gt;");
803
+ var html = html.replace(/\?/g, "%3F");
804
+ var html = html.replace(/\/>/, "%2F%3E");
805
+ //var html = html.replace(/&/g, "%26");
806
+ var html = encodeURIComponent(html);
807
+ //console.log(html);
808
+ return html;
809
+ }
810
+
811
+ };
812
+
813
+
814
+ jQuery(document).ready(function () {
815
+
816
+ jQuery('#inbound-shortcodes-popup').livequery(function () {
817
+ InboundShortcodes.load();
818
+ });
819
+
820
+
821
+ if (InboundShortcodes.getUrlVar("reload") === 'true') {
822
+ jQuery("#post-body-content").hide();
823
+ var window_url = window.location.href.replace('&reload=true', "");
824
+ var window_url = window_url.replace('wp-admin//', 'wp-admin/');
825
+ jQuery("#post-body").before('<h2>Please Refresh this Page to Edit your Form<h2><a href="' + window_url + '">Click to Refresh</a>');
826
+ window.history.replaceState({}, document.title, window_url);
827
+ }
828
+
829
+ jQuery('#list-add-toggle').click(function () {
830
+ jQuery('#list-add-wrap').toggleClass('wp-hidden-child');
831
+ return false;
832
+ });
833
+
834
+ jQuery('#list-add-submit').click(function () {
835
+ var list_val = jQuery('#newformlist').val();
836
+ var list_parent_val = jQuery('#newlist_parent').val();
837
+ if (list_val == '') {
838
+
839
+ jQuery('#newformlist').focus();
840
+ return false;
841
+
842
+ } else {
843
+ jQuery.ajax({
844
+ type: "POST",
845
+ url: ajaxurl,
846
+ data: "list_val=" + list_val + "&list_parent_val=" + list_parent_val + "&action=inbound_form_add_lead_list",
847
+ success: function (data) {
848
+ var returned = jQuery.parseJSON(data);
849
+ if (returned.status != 'false') {
850
+ jQuery('#inbound_shortcode_lists').append('<option value="' + returned.term_id + '">' + returned.name + '</option>');
851
+ jQuery('#list-ajax-response').html('List Added. Please Select From Above.');
852
+ } else {
853
+ alert('Not able to add list at this monent. Please try again');
854
+ }
855
+ }
856
+ });
857
+
858
+ }
859
+
860
+ });
861
+
862
+
863
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/README.md ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Description ##
2
+
3
+ > WordPress Landing Pages works as a standalone plugin or hand in hand with [WordPress Calls to Action](http://wordpress.org/plugins/cta/ "Learn more about Calls to Action") & [WordPress Leads](http://wordpress.org/plugins/leads/ "Learn more about WordPress Leads") to create a powerful & free lead generation system for your business.
4
+
5
+ This plugin creates landing pages (a.k.a. conversion or splash pages) for your WordPress site. It gives site owners the ability to monitor and track conversion rates, run a/b or multivariate split tests on landing pages, and most importantly increase lead flow!
6
+
7
+ The landing page plugin was specifically designed with inbound marketing best practices in mind and will help you drive & convert more leads on your site.
8
+
9
+ Landing pages are an ideal way to convert more of your passive website visitors into active leads or email list subscribers.
10
+
11
+ ### Highlights ###
12
+
13
+ * Create beautiful Landing Pages on your WordPress site.
14
+ * Visual Editor to view changes being made on the fly!
15
+ * Track conversion rates on your landing pages for continual optimization.
16
+ * Easily clone existing landing pages and run A/B Split tests on variations.
17
+ * Use your current WordPress theme or choose from our library of custom landing page designs.
18
+ * Pre-populate Forms with visitor information to increase conversion rates
19
+ * Gather lead intelligence and track lead activity with <a href="http://wordpress.org/plugins/leads/screenshots/">WordPress Leads</a>
20
+ * Extend functionality with our growing repository of <a href="http://www.inboundnow.com/market/category/landing-pages/extensions/">third party add ons</a>.
21
+ * Easily implement your own custom landing page design.
22
+
23
+ This plugin is form agnostic meaning it will work with any form system you use.
24
+
25
+ Recommended form plugins (Gravity forms, Ninja Forms or Contact form 7)
26
+
27
+ ### About the Plugin ###
28
+
29
+ http://www.youtube.com/watch?v=flEd0sRTFUo
30
+
31
+ ### Developers & Designers ###
32
+
33
+ We built the landing page plugin as a framework! Need A/B testing out of the box implemented for your existing designs? Use WordPress Landing Pages to quickly spin up new landing pages that have all the functionality your clients will need.
34
+
35
+ You can quickly take your existing designs and implement them using our <a href="http://docs.inboundnow.com/section/developer/">templating framework</a>.
36
+
37
+ The plugin is also fully extendable and has a number of actions, filters, and hooks available for use. If a hook doesn't exist, simply ask and we can implement custom changes.
38
+
39
+
40
+ [Follow Development on GitHub ](https://github.com/inboundnow/landing-pages "Follow & Contribute to core development on GitHub")
41
+ |
42
+ [Follow Development on Twitter ](https://twitter.com/gitlandingpages "See our latest development commits on Twitter")
43
+
44
+
45
+ ## Installation ##
46
+
47
+ 1. Upload `landing-pages` folder to the `/wp-content/plugins/` directory
48
+ 1. Activate the plugin through the 'Plugins' menu in WordPress
49
+
50
+ ## Frequently Asked Questions ##
51
+ *Can I create my own landing page designs?,
52
+ *Yes! You can learn how to <a href="http://docs.inboundnow.com/guide/creating-landing-page-templates/">create your own landing page template here</a>.
53
+
trunk/assets/css/admin-ab-testing.css ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /******************************************************* ab testing admin css */
2
+
3
+
4
+ .nav-tab-special-inactive
5
+ {
6
+ border-color: #DFDFDF #DFDFDF #FFFFFF;
7
+ border-top-left-radius: 3px;
8
+ border-top-right-radius: 3px;
9
+ border-width: 1px 1px 0;
10
+ color: #AAAAAA;
11
+ display: inline-block;
12
+ font-size: 12px;
13
+ line-height: 16px;
14
+ margin: 0 6px -1px 0;
15
+ padding: 4px 14px 6px;
16
+ text-decoration: none;
17
+ text-shadow: 0 1px 0 #FFFFFF;
18
+ cursor:pointer;
19
+ }
20
+
21
+ .nav-tab-special-active
22
+ {
23
+
24
+ border-top-left-radius: 3px;
25
+ border-top-right-radius: 3px;
26
+ border-width: 1px 1px 1px;
27
+ border-bottom: 0px;
28
+ color: #000;
29
+ display: inline-block;
30
+ font-size: 12px;
31
+ line-height: 16px;
32
+ margin: 0 6px -1px 0;
33
+ padding: 4px 14px 6px;
34
+ text-decoration: none;
35
+ text-shadow: 0 1px 0 #FFFFFF;
36
+ cursor:pointer;
37
+ background: rgba(241,241,241, 1) !important;
38
+
39
+
40
+ }
41
+ h2.nav-tab-wrapper.a_b_tabs .nav-tab {
42
+ padding: 6px 14px;
43
+ font-weight: 700;
44
+ font-size: 17px;
45
+ line-height: 24px;
46
+ }
47
+ .variation-off .stat-control-pause, .variation-on .stat-control-play, .variation-off .pause-sep,.variation-on .play-sep, .variation-on .is-paused{
48
+ display: none;
49
+ }
50
+ .stat-control-container {
51
+
52
+ bottom: 0px;
53
+ left: 0px;
54
+ }
55
+ .stat-control-container:hover {
56
+
57
+ bottom: 0px;
58
+ left: 0px;
59
+ display: block;
60
+ }
61
+ .variation-row {
62
+ position: relative;
63
+ //margin-bottom: -27px;
64
+ //-moz-transition: all .4s ease-in-out;
65
+ //-webkit-transition: all .4s ease-in-out;
66
+ //-o-transition: all .4s ease-in-out;
67
+ //transition: all .4s ease-in-out;
68
+ }
69
+
70
+ .variation-row:last-child {
71
+ margin-bottom: 0px;
72
+ }
73
+ .variation-row:hover {
74
+ margin-bottom: 0px;
75
+ //-moz-transition: all .4s ease-in-out;
76
+ //-webkit-transition: all .4s ease-in-out;
77
+ //-o-transition: all .4s ease-in-out;
78
+ //transition: all .4s ease-in-out;
79
+
80
+ }
81
+ .stat-control-container span {
82
+ vertical-align: bottom;
83
+ display: inline-block;
84
+ }
85
+ .stat-seperator {
86
+ padding-left: 3px;
87
+ padding-right: 3px;
88
+ font-size: 0px;
89
+ }
90
+ .variation-on .stat-control-pause a {
91
+ color: red;
92
+ font-weight: bold;
93
+ }
94
+ .variation-off .number-box {
95
+ color: rgb(117, 117, 117);
96
+ }
97
+ .is-paused { font-size: 10px;
98
+ font-style: italic;
99
+ color: red;
100
+ opacity: .8;
101
+ padding-left: 10px;
102
+ }
103
+ .variation-off .stat-control-play a {
104
+ color: green;
105
+ font-weight: bold;
106
+ }
107
+ .variation-off .varation-header {
108
+ font-weight: normal;
109
+ }
110
+ .lp-tab-display
111
+ {
112
+ padding:13px;
113
+ }
114
+
115
+ .lp-tab-display td
116
+ {
117
+ padding:10px;
118
+ }
119
+ .lp-tab-display th
120
+ {
121
+ padding:10px;
122
+ }
123
+
124
+ .lp-tab-display th,.lp-tab-display .lp-gs-th
125
+ {
126
+ width:300px;
127
+ font-size: 14px;
128
+ font-weight:300px;
129
+ text-align:left;
130
+ }
131
+
132
+
133
+ /* Begin with quick stats! */
134
+
135
+ .stat-letter {
136
+ border-radius: 3px;
137
+ border-style:solid;
138
+ border-width:1px;
139
+ padding:2px;
140
+ }
141
+
142
+ .stat-container-conversions, .stat-container-impressions, .stat-container-conversion_rate {
143
+ display:inline;
144
+ }
145
+
146
+ #a-b-testing {
147
+ padding: 0px;
148
+ }
149
+ .lp-delete-var-stats {
150
+ cursor: pointer;
151
+ }
152
+ #lp_ab_display_stats_metabox .inside {
153
+ padding: 0px;
154
+ margin-top: 0px;
155
+ }
156
+ #lp_ab_display_stats_metabox h3.hndle {
157
+ border-bottom: none !important;
158
+ }
159
+
160
+ /* --- UI improvement style added by Ahmed Kaludi ( http://AhmedKaludi.com ) - START --- */
161
+ .settings_icon{
162
+ top: 12px;
163
+ }
164
+ .settings_wrapper{ display: none }
165
+ .settings_icon:hover + .settings_wrapper,
166
+ .settings_wrapper:hover{
167
+ display: block;
168
+ position: absolute;
169
+ background: #fff;
170
+ padding: 15px 10px 10px 10px;
171
+ right: 0;
172
+ float: right;
173
+ z-index: 999;
174
+ margin-top: -2px;
175
+ border-color: rgb(204, 204, 204);
176
+ box-shadow: 0px 0px 8px 0px rgba(51, 51, 51, 0.4);
177
+ border-radius: 2px;
178
+ border: 1px solid #cccccc;
179
+ width: 128px
180
+ }
181
+ .settings_icon{
182
+ background: url(../images/ab-retina-icons.png) no-repeat;
183
+ width: 17px;
184
+ height: 21px;
185
+ display: inline-block;
186
+ background-position: 0px -34px;
187
+ content: "";
188
+ background-size: 250px;
189
+ padding-right: 10px;
190
+ padding-bottom: 10px;
191
+ position: absolute;
192
+ right: 15px;
193
+ opacity: 0.4;
194
+ }
195
+ .settings_wrapper_heading{
196
+ font-size: 10px;
197
+ color: #999999;
198
+ text-transform: uppercase;
199
+ letter-spacing: 0.65px;
200
+ font-weight: normal;
201
+ width: 100%;
202
+ text-align: center;
203
+ display: inline-block;
204
+ }
205
+ .settings_list_li a, .lp-delete-var-stats{
206
+ font-size: 13px;
207
+ color: #333333;
208
+ text-decoration: none;
209
+ letter-spacing: 0.5px;
210
+ font-weight: normal;
211
+ padding-left: 15px;
212
+ }
213
+ .settings_list_li li a:before, .settings_list_li .settings_clearstat:before{
214
+ background: url(../images/ab-retina-icons.png) no-repeat;
215
+ width: 15px;
216
+ position: absolute;
217
+ height: 15px;
218
+ display: inline-block;
219
+ background-position: -5px -70px;
220
+ content: "";
221
+ background-size: 250px;
222
+ padding-right: 0px;
223
+ padding-bottom: 0px;
224
+ opacity: 0.4;
225
+ left: 20px;
226
+ margin-top: 0px;
227
+ }
228
+ .settings_list_li{
229
+ margin-left: 17px;
230
+ margin-bottom: 13px;
231
+ margin-top: 18px;
232
+ }
233
+ .settings_list_li li{
234
+ margin-bottom: 16px
235
+ }
236
+ .settings_preview a:before{
237
+ background-position: -5px -97px !important;
238
+ }
239
+ .settings_clone a:before{
240
+ background-position: -5px -124px !important;
241
+ height: 17px !important;
242
+ width: 17px !important;
243
+ }
244
+
245
+ .settings_delete a:before{
246
+ background-position: -3px -155px !important;
247
+ }
248
+ .settings_clearstat:before{
249
+ background-position: -3px -183px !important;
250
+ }
251
+ .settings_list_li a:hover{
252
+ color: #000
253
+ }
254
+ #wpbody .varation-header{
255
+ font-size: 14px;
256
+ font-weight: normal;
257
+ color: #000;
258
+ padding-left: 18px !important;
259
+ }
260
+ .stat-letter {
261
+ border-radius: 0px;
262
+ border-style: solid;
263
+ border-width: 0px;
264
+ padding: 0px;
265
+ background: none !important;
266
+ font-weight: bold;
267
+ }
268
+ .stat-control-pause a:before{
269
+ background: url(../images/ab-retina-icons.png) no-repeat;
270
+ width: 15px;
271
+ position: absolute;
272
+ height: 15px;
273
+ display: inline-block;
274
+ background-position: -5px -5px;
275
+ content: "";
276
+ background-size: 250px;
277
+ padding-right: 0px;
278
+ padding-bottom: 0px;
279
+ opacity: 0.6;
280
+ right: 55px;
281
+ margin-top: 0px;
282
+ }
283
+
284
+ .stat-control-play a:before{
285
+ background: url(../images/ab-retina-icons.png) no-repeat;
286
+ width: 15px;
287
+ position: absolute;
288
+ height: 15px;
289
+ display: inline-block;
290
+ background-position:-5px -212px;
291
+ content: "";
292
+ background-size: 250px;
293
+ padding-right: 0px;
294
+ padding-bottom: 0px;
295
+ right: 55px;
296
+ margin-top: 0px;
297
+ }
298
+ .variation-off{
299
+
300
+ }
301
+ .stat-control-play a:before{
302
+ }
303
+ #wpbody .varation-header {
304
+ line-height: 1;
305
+ background-color: #ededed;
306
+ border-color: #dddddd;
307
+ padding: 15px 5px;
308
+ border-bottom: 0px solid #dddddd;
309
+ border-top: 1px solid #D2D1D1;
310
+ }
311
+ /* --- UI improvement style added by Ahmed Kaludi ( http://AhmedKaludi.com ) - END --- */
trunk/assets/css/admin-post-edit.css ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #titlediv #title, #lp-notes-area input {
2
+ background-color: #f1f1f1;
3
+ border: solid 1px #dfdfdf;
4
+ box-shadow: none;
5
+ }
6
+
7
+ #wpbody-content {
8
+ overflow: visible !important;
9
+ }
10
+
11
+ h2#convert-header {
12
+ margin-bottom: 0px;
13
+ }
14
+
15
+ .quicktags-toolbar, .wp_themeSkin tr.mceFirst td.mceToolbar {
16
+ height: 38px;
17
+ }
18
+
19
+ .quicktags-toolbar {
20
+ height: auto;
21
+ }
22
+
23
+ .mceIframeContainer.mceFirst.mceLast iframe {
24
+ height: 335px !important;
25
+ }
26
+
27
+ #slugdiv {
28
+ display: none;
29
+ }
30
+
31
+ /* FIX WORDPRESS modal button */
32
+ body.modal-open {
33
+ overflow: visible !important;
34
+ }
35
+
36
+ #lp-notes-area input {
37
+ width: 100%;
38
+ color: #AAAAAA;
39
+ padding-top: 7px;
40
+ }
41
+
42
+ #local-storage-notice {
43
+ display: none !important;
44
+ }
45
+
46
+ #lp-notes-area input:focus {
47
+ color: #000;
48
+ }
49
+
50
+ #date-picking span {
51
+ vertical-align: bottom;
52
+ }
53
+
54
+ #template-display-options .hndle {
55
+ background-color: transparent;
56
+ background-image: none !important;
57
+ }
58
+
59
+ #titlediv #title:focus, #lp-notes-area input:focus {
60
+ border: solid 1px #dfdfdf;
61
+ }
62
+
63
+ .select2-container {
64
+ min-width: 320px;
65
+ }
66
+
67
+ .lp-clear-success {
68
+ color: red;
69
+ opacity: .7;
70
+ font-size: 9px;
71
+ float: right;
72
+ font-weight: normal;
73
+ }
74
+
75
+ .lp-clear-success {
76
+ color: green;
77
+ }
78
+
79
+ #post-body-content .a_b_tabs {
80
+ padding: 0px;
81
+ margin-bottom: 9px;
82
+ margin-left: -22px;
83
+ padding-left: 22px;
84
+ margin-top: 5px;
85
+ margin-right: -20px;
86
+ position: relative;
87
+ }
88
+
89
+ #wp-landing-page-myeditor-wrap #landing-page-myeditor_path_row {
90
+ display: none;
91
+ }
92
+
93
+ #wp-landing-page-myeditor-wrap #wp-landing-page-myeditor-editor-container {
94
+ min-height: 200px;
95
+ }
96
+
97
+ #adminmenu .wp-menu-arrow div {
98
+ left: -2px;
99
+ }
100
+
101
+ #add-lp-notes {
102
+ display: none;
103
+ vertical-align: middle;
104
+ font-weight: 600;
105
+ padding-right: 2px;
106
+ }
107
+
108
+ .add-new-h2, #lp-current-view, #switch-lp, #preview-action {
109
+ display: none;
110
+ }
111
+
112
+ #lp-notes-area {
113
+ position: relative;
114
+ }
115
+
116
+ #post-body-content #main-title-area {
117
+ margin-top: 5px;
118
+ margin-bottom: 15px;
119
+ position: relative;
120
+ }
121
+
122
+ #main-title-area .button-primary.new-save-lp {
123
+ position: absolute !important;
124
+ top: 2px !important;
125
+ font-size: 17px !important;
126
+ padding-top: 3px !important;
127
+ right: 0px !important;
128
+ height: 31px !important;
129
+ max-width: 100px !important;
130
+ text-align: center !important;
131
+ }
132
+
133
+ .jPicker {
134
+ display: inline-block;
135
+ vertical-align: top;
136
+ margin-top: 3px;
137
+ }
138
+
139
+ #lp-notes-area .button-primary.new-save-lp {
140
+ position: absolute !important;
141
+ top: 2px !important;
142
+ font-size: 17px !important;
143
+ padding-top: 3px !important;
144
+ right: 0px !important;
145
+ height: 31px !important;
146
+
147
+ }
148
+
149
+ #main-title-area .lp-success-message, #lp-notes-area .lp-success-message {
150
+ position: absolute !important;
151
+ top: 1px !important;
152
+ font-size: 17px !important;
153
+ padding-top: 3px !important;
154
+ right: 0px !important;
155
+ height: 31px !important;
156
+ vertical-align: middle;
157
+ margin-top: 0px;
158
+ padding-bottom: 0px;
159
+ }
160
+
161
+ #main-title-area .lp-success-message {
162
+ margin-top: 4px;
163
+ }
164
+
165
+ #post-body .new-save-lp-frontend {
166
+ font-weight: 200;
167
+ top: 2px;
168
+ font-size: 14px;
169
+ margin-left: 21px;
170
+ line-height: 28px;
171
+ height: 30px;
172
+ float: right;
173
+ margin-right: 19px;
174
+ }
175
+
176
+ @media screen and (max-width: 782px) {
177
+ #launch-visual-editer {
178
+ display: none;
179
+ }
180
+ }
181
+
182
+ #template-box, .thumbnail-lander img {
183
+ background: #FCFDFE;
184
+ padding: 3%;
185
+ margin-right: 10px;
186
+ border: 1px solid #E0E0E0;
187
+ -moz-border-radius: 7px;
188
+ border-radius: 7px;
189
+ position: relative;
190
+ overflow: hidden;
191
+ display: block;
192
+ }
193
+
194
+ .default_template_highlight {
195
+ -webkit-box-shadow: inset 0px 0px 12px 1px rgba(82, 168, 238, 1);
196
+ box-shadow: inset 0px 0px 12px 1px rgba(82, 168, 238, 1);
197
+ }
198
+
199
+ .currently_selected {
200
+ position: absolute;
201
+ top: 72px;
202
+ left: 16px;
203
+ font-size: 19px;
204
+ line-height: 26px;
205
+ text-align: center;
206
+ background: black;
207
+ width: 90%;
208
+ height: 36px;
209
+ color: white;
210
+ opacity: 0.5;
211
+ border-radius: 7px;
212
+ }
trunk/assets/css/admin-post-new.css ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #wpbody-content .wrap {
2
+ display: none;
3
+ }
4
+
5
+ #wpbody-content #screen-options-link-wrap, #post-body-content .a_b_tabs, #switch-lp, #lp-current-view {
6
+ display: none;
7
+ }
8
+
9
+ #lp-thumbnail-sidebar-preview, #main-title-area, #lp-notes-area {
10
+ display: none;
11
+ }
12
+
13
+ #wp-content-wrap, #postdivrich, #postbox-container-2, #misc-publishing-actions, #preview-action, #major-publishing-actions, #edit-slug-box, #submitdiv .handlediv {
14
+ display: none;
15
+ }
16
+
17
+ .quicktags-toolbar, .wp_themeSkin tr.mceFirst td.mceToolbar {
18
+ height: 38px;
19
+ }
20
+
21
+ .quicktags-toolbar {
22
+ height: auto;
23
+ }
24
+
25
+ .mceIframeContainer.mceFirst.mceLast iframe {
26
+ height: 335px !important;
27
+ }
28
+
29
+ #titlediv #title {
30
+ -webkit-border-radius: 3px;
31
+ border-radius: 3px;
32
+ border-color: #dfdfdf !important;
33
+ border-width: 1px !important;
34
+ border-style: solid !important;
35
+ }
36
+
37
+ #descriptor {
38
+ padding-left: 5px;
39
+ display: block;
40
+ padding-top: 5px;
41
+ margin-bottom: 10px;
42
+ }
43
+
44
+ #lp-main-headline-wrap {
45
+ display: none !important;
46
+ }
47
+
48
+ #timage .template-thumbnail {
49
+ width: 242px;
50
+ border-radius: 0px !important;
51
+ }
52
+
53
+ #templates {
54
+ position: relative;
55
+
56
+ }
57
+
58
+ .new-lp-button {
59
+ margin-bottom: 10px !important;
60
+ margin-top: 3px !important;
61
+ }
62
+
63
+ #templates #lp_template_change {
64
+
65
+ position: absolute;
66
+ top: 55px;
67
+ left: 290px;
68
+ }
69
+
70
+ #template_current {
71
+ width: 340px;
72
+ padding-right: 10px;
73
+ display: inline-block;
74
+ vertical-align: top;
75
+ }
76
+
77
+ #template_current h3 {
78
+ font-weight: bold;
79
+ padding: 7px 0px;
80
+ }
81
+
82
+ #lp_the_image {
83
+ display: inline-block;
84
+ width: 410px;
85
+ margin-top: 10px;
86
+ margin-left: 10px;
87
+ }
88
+
89
+ #lp_the_image img {
90
+ padding: 8px;
91
+ margin-bottom: 15px;
92
+ box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
93
+ -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
94
+ -moz-box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
95
+ -o-box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
96
+ border-radius: 5px;
97
+ -moz-border-radius: 5px;
98
+ -webkit-border-radius: 5px;
99
+ -html-border-radius: 5px;
100
+ border: 0px;
101
+ display: block;
102
+ max-width: 240px;
103
+ margin-left: 15px;
104
+ border-top-left-radius: 3px;
105
+ border-top-right-radius: 3px;
106
+ border-bottom-right-radius: 3px;
107
+ border-bottom-left-radius: 3px;
108
+ }
109
+
110
+
trunk/assets/css/admin-templates.css ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .update-message {
2
+ background-color: #FFFBE4;
3
+ border-color: #DFDFDF;
4
+ border-bottom-color: #DFDFDF;
5
+ border-top-color: #FFFFFF;
6
+ padding:3px;
7
+ }
8
+
9
+ .update-available
10
+ {
11
+ font-weight:600;
12
+ color:cadetblue;
13
+ }
14
+
15
+ .template-thumbnail {
16
+ background-color: #A9A9A9;
17
+ border-radius: 2px;
18
+ height: 120px;
19
+ width: 150px;
20
+ padding:6px;
21
+ }
22
+
23
+ .wp-list-table .column-thumbnail
24
+ {
25
+ height:0px;
26
+ }
27
+
28
+ .capty-wrapper
29
+ {
30
+ margin-left:20px;
31
+ height:140px;
32
+ }
33
+
34
+ .column-template
35
+ {
36
+ width:200px;
37
+ }
38
+
39
+ .column-description
40
+ {
41
+ width:377px;
42
+ font-style:italic;
43
+ }
44
+
45
+ .column-category
46
+ {
47
+ width:160px;
48
+ }
trunk/assets/css/admin-tour.css ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .introjs-overlay {
2
+ position: absolute;
3
+ z-index: 999999;
4
+ background-color: #000;
5
+ opacity: 0;
6
+ background: -moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
7
+ background: -webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9)));
8
+ background: -webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
9
+ background: -o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
10
+ background: -ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
11
+ background: radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
12
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1);
13
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
14
+ filter: alpha(opacity=50);
15
+ -webkit-transition: all 0.3s ease-out;
16
+ -moz-transition: all 0.3s ease-out;
17
+ -ms-transition: all 0.3s ease-out;
18
+ -o-transition: all 0.3s ease-out;
19
+ transition: all 0.3s ease-out;
20
+ }
21
+
22
+ .introjs-fixParent {
23
+ z-index: auto !important;
24
+ }
25
+
26
+ .introjs-showElement {
27
+ z-index: 9999999 !important;
28
+ }
29
+
30
+ .introjs-relativePosition {
31
+ position: relative;
32
+ }
33
+
34
+ .introjs-helperLayer {
35
+ position: absolute;
36
+ z-index: 9999998;
37
+ background-color: #FFF;
38
+ background-color: rgba(255,255,255,.9);
39
+ border: 1px solid #777;
40
+ border: 1px solid rgba(0,0,0,.5);
41
+ border-radius: 4px;
42
+ box-shadow: 0 2px 15px rgba(0,0,0,.4);
43
+ -webkit-transition: all 0.3s ease-out;
44
+ -moz-transition: all 0.3s ease-out;
45
+ -ms-transition: all 0.3s ease-out;
46
+ -o-transition: all 0.3s ease-out;
47
+ transition: all 0.3s ease-out;
48
+ }
49
+
50
+ .introjs-helperNumberLayer {
51
+ position: absolute;
52
+ top: -18px;
53
+ left: -25px;
54
+ z-index: 9999999999 !important;
55
+ padding: 2px;
56
+ font-family: Arial, verdana, tahoma;
57
+ font-size: 13px;
58
+ font-weight: bold;
59
+ color: white;
60
+ text-align: center;
61
+ text-shadow: 1px 1px 1px rgba(0,0,0,.3);
62
+ background: #ff3019; /* Old browsers */
63
+ background: -webkit-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* Chrome10+,Safari5.1+ */
64
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ff3019), color-stop(100%, #cf0404)); /* Chrome,Safari4+ */
65
+ background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* FF3.6+ */
66
+ background: -ms-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* IE10+ */
67
+ background: -o-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* Opera 11.10+ */
68
+ background: linear-gradient(to bottom, #ff3019 0%, #cf0404 100%); /* W3C */
69
+ width: 20px;
70
+ height:20px;
71
+ line-height: 20px;
72
+ border: 3px solid white;
73
+ border-radius: 50%;
74
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019', endColorstr='#cf0404', GradientType=0); /* IE6-9 */
75
+ filter: progid:DXImageTransform.Microsoft.Shadow(direction=135, strength=2, color=ff0000); /* IE10 text shadows */
76
+ box-shadow: 0 2px 5px rgba(0,0,0,.4);
77
+ }
78
+
79
+ .introjs-arrow {
80
+ border: 5px solid white;
81
+ content:'';
82
+ position: absolute;
83
+ }
84
+ .introjs-arrow.top {
85
+ top: -10px;
86
+ border-top-color:transparent;
87
+ border-right-color:transparent;
88
+ border-bottom-color:white;
89
+ border-left-color:transparent;
90
+ }
91
+ .introjs-arrow.right {
92
+ right: -10px;
93
+ top: 10px;
94
+ border-top-color:transparent;
95
+ border-right-color:transparent;
96
+ border-bottom-color:transparent;
97
+ border-left-color:white;
98
+ }
99
+ .introjs-arrow.bottom {
100
+ bottom: -10px;
101
+ border-top-color:white;
102
+ border-right-color:transparent;
103
+ border-bottom-color:transparent;
104
+ border-left-color:transparent;
105
+ }
106
+ .introjs-arrow.left {
107
+ left: -10px;
108
+ top: 10px;
109
+ border-top-color:transparent;
110
+ border-right-color:white;
111
+ border-bottom-color:transparent;
112
+ border-left-color:transparent;
113
+ }
114
+
115
+ .introjs-tooltip {
116
+ position: absolute;
117
+ padding: 10px;
118
+ background-color: white;
119
+ min-width: 200px;
120
+ max-width: 300px;
121
+ border-radius: 3px;
122
+ box-shadow: 0 1px 10px rgba(0,0,0,.4);
123
+ -webkit-transition: opacity 0.1s ease-out;
124
+ -moz-transition: opacity 0.1s ease-out;
125
+ -ms-transition: opacity 0.1s ease-out;
126
+ -o-transition: opacity 0.1s ease-out;
127
+ transition: opacity 0.1s ease-out;
128
+ }
129
+
130
+ .introjs-tooltipbuttons {
131
+ text-align: right;
132
+ }
133
+
134
+ /*
135
+ Buttons style by http://nicolasgallagher.com/lab/css3-github-buttons/
136
+ Changed by Afshin Mehrabani
137
+ */
138
+ .introjs-button {
139
+ position: relative;
140
+ overflow: visible;
141
+ display: inline-block;
142
+ padding: 0.3em 0.8em;
143
+ border: 1px solid #d4d4d4;
144
+ margin: 0;
145
+ text-decoration: none;
146
+ text-shadow: 1px 1px 0 #fff;
147
+ font: 11px/normal sans-serif;
148
+ color: #333;
149
+ white-space: nowrap;
150
+ cursor: pointer;
151
+ outline: none;
152
+ background-color: #ececec;
153
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f4f4f4), to(#ececec));
154
+ background-image: -moz-linear-gradient(#f4f4f4, #ececec);
155
+ background-image: -o-linear-gradient(#f4f4f4, #ececec);
156
+ background-image: linear-gradient(#f4f4f4, #ececec);
157
+ -webkit-background-clip: padding;
158
+ -moz-background-clip: padding;
159
+ -o-background-clip: padding-box;
160
+ /*background-clip: padding-box;*/ /* commented out due to Opera 11.10 bug */
161
+ -webkit-border-radius: 0.2em;
162
+ -moz-border-radius: 0.2em;
163
+ border-radius: 0.2em;
164
+ /* IE hacks */
165
+ zoom: 1;
166
+ *display: inline;
167
+ margin-top: 10px;
168
+ }
169
+
170
+ .introjs-button:hover {
171
+ border-color: #bcbcbc;
172
+ text-decoration: none;
173
+ box-shadow: 0px 1px 1px #e3e3e3;
174
+ }
175
+
176
+ .introjs-button:focus,
177
+ .introjs-button:active {
178
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ececec), to(#f4f4f4));
179
+ background-image: -moz-linear-gradient(#ececec, #f4f4f4);
180
+ background-image: -o-linear-gradient(#ececec, #f4f4f4);
181
+ background-image: linear-gradient(#ececec, #f4f4f4);
182
+ }
183
+
184
+ /* overrides extra padding on button elements in Firefox */
185
+ .introjs-button::-moz-focus-inner {
186
+ padding: 0;
187
+ border: 0;
188
+ }
189
+
190
+ .introjs-skipbutton {
191
+ margin-right: 5px;
192
+ color: #7a7a7a;
193
+ }
194
+
195
+ .introjs-prevbutton {
196
+ -webkit-border-radius: 0.2em 0 0 0.2em;
197
+ -moz-border-radius: 0.2em 0 0 0.2em;
198
+ border-radius: 0.2em 0 0 0.2em;
199
+ border-right: none;
200
+ }
201
+
202
+ .introjs-nextbutton {
203
+ -webkit-border-radius: 0 0.2em 0.2em 0;
204
+ -moz-border-radius: 0 0.2em 0.2em 0;
205
+ border-radius: 0 0.2em 0.2em 0;
206
+ }
207
+
208
+ .introjs-disabled, .introjs-disabled:hover, .introjs-disabled:focus {
209
+ color: #9a9a9a;
210
+ border-color: #d4d4d4;
211
+ box-shadow: none;
212
+ cursor: default;
213
+ background-color: #f4f4f4;
214
+ background-image: none;
215
+ text-decoration: none;
216
+ }
trunk/assets/css/admin/acf-hide-wp-elements.css ADDED
@@ -0,0 +1 @@
 
1
+ #postdivrich, #lp_2_form_content, #main-title-area {display:none !important;}
trunk/assets/css/admin/content-stats.css ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #stat-box
2
+ {
3
+ font-size: 12px;
4
+ margin-bottom: 10px;
5
+ text-align: left;
6
+
7
+ border-top: none;
8
+ border-left: none;
9
+ /* border: 1px solid #CECDCA;
10
+
11
+ -webkit-box-shadow: 0px 0px 15px rgba(0,0,0,0.1);
12
+ -moz-box-shadow: 0px 0px 15px rgba(0,0,0,0.1);
13
+ box-shadow: 0px 0px 15px rgba(0,0,0,0.1);*/
14
+ z-index: 200;
15
+ width: 100%;
16
+ }
17
+ #stat-box:last-child {
18
+ margin-bottom: 0px;
19
+ }
20
+ .number-box
21
+ {
22
+ background: transparent;
23
+ display: inline-block;
24
+ width: 31%;
25
+ padding-top: 15px
26
+ }
27
+ .number-box span
28
+ {
29
+ text-align: center;
30
+ padding: 20px;
31
+ padding-bottom: 15px;
32
+ color: #111;
33
+ display: block;
34
+ font-size: 16px;
35
+ padding-top: 6px;
36
+ }
37
+
38
+ .varation-header
39
+ {
40
+ font-size: 19px;
41
+ font-weight: bold;
42
+ background-color: #e0e0e0;
43
+ border-color: #CECDCA;
44
+ padding: 8px 5px;
45
+ border-bottom: 1px solid #CECDCA;
46
+ border-top: 1px solid #CECDCA;
47
+ }
48
+
49
+ .stat-control-container
50
+ {
51
+ text-align: center;
52
+ padding: 5px;
53
+ }
54
+
55
+ .variation-row
56
+ {
57
+ display: block;
58
+ }
59
+
60
+ .stat-letter
61
+ {
62
+ background: #fff;
63
+ padding-top: 0px;
64
+ padding-bottom: 0px;
65
+ }
66
+
67
+ .notes
68
+ {
69
+ float: right;
70
+ font-size: 12px;
71
+ font-weight: normal;
72
+ }
73
+
74
+ .number-box span.stat-id{
75
+ line-height: 1;
76
+ font-size: 9px;
77
+ font-weight: normal;
78
+ display: block;
79
+ padding: 0px;
80
+ letter-spacing: 0.15px;
81
+ color: #333333
82
+ }
83
+
84
+ .rate
85
+ {
86
+ font-size: 9px !important;
87
+ }
trunk/assets/css/admin/customizer-edit.css ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* moving to shared customizer */
2
+ #wpadminbar,.page-title-action, #edit-slug-box, #post-status-info, #screen-options-link-wrap, #leads-table-container, .misc-pub-section, #minor-publishing, .misc-pub-section, .misc-pub-section.curtime, #delete-action, #convert-header, #lp-tour, #view-post-btn, #launch-visual-editer, #adminmenuwrap, #lp_ab_display_stats_metabox, #lp-thumbnail-sidebar-preview, #landing_page_categorydiv, #postimagediv, #leads-table-container-inside, .updated.below-h2 a, .mceButton.mceButtonEnabled.mce_fullscreen, .mce_strikethrough, .mce_wp_more, #setting-error-tgmpa, #lp_preview_this_template {
3
+ display: none !important;
4
+ }
5
+ html.wp-toolbar {
6
+ padding-top: 0px !important;
7
+ }
8
+ .auto-fold #adminmenuback, .auto-fold #adminmenuwrap, .auto-fold #adminmenu, .auto-fold #adminmenu li.menu-top {
9
+ width: 0px !important;
10
+ }
11
+ .auto-fold #wpcontent, .auto-fold #wpfooter {
12
+ margin-left: 10px !important;
13
+ }
14
+ #wpbody-content {
15
+ padding-bottom: 90px !important;
16
+ width: 100% !important;
17
+ }
18
+ .wp_themeSkin .mceButton {
19
+ display: block;
20
+ width: 20px !important;
21
+ height: 20px !important;
22
+ }
23
+ .quicktags-toolbar input {
24
+ min-width: 10px !important;
25
+ padding: 2px 2px !important;
26
+ }
27
+ #post-body-content {
28
+ width: 103% !important;
29
+ margin-left: -10px !important; }
30
+ #lp_2_form_content {
31
+ margin-left: -10px !important;
32
+ }
33
+ .inbound-textarea-row .inbound-meta-box-option.inbound-textarea-option textarea {
34
+ width: 90% !important;
35
+ }
36
+ .wp_themeSkin .mceButton .mceIcon {
37
+ margin-top: 0px !important;
38
+ margin-left: 0px !important;
39
+ }
40
+ #inbound-meta .inbound-meta-box-row.inbound-wysiwyg-row {
41
+ width: 105%;
42
+ margin-left: -6px;
43
+ }
44
+
45
+ @media screen and (max-width: 600px) {
46
+ .version-3-8 #wpbody {
47
+ padding-top: 5px !important;
48
+ }
49
+ }
50
+ #submitdiv .handlediv , #submitdiv .hndle {
51
+ display: none !important;
52
+ }
53
+ .wrap div.updated, .wrap div.error, .media-upload-form div.error {
54
+ margin: 5px 0 0px !important;
55
+ }
56
+ .inbound-meta-box-option.inbound-dropdown-option {
57
+ width: 95% !important;
58
+ }
59
+ #publishing-action {
60
+ text-align: center !important;
61
+ float: none !important;
62
+ margin-bottom: 15px;
63
+ line-height: 32px; }
64
+ #minor-publishing-actions input, #major-publishing-actions input, #minor-publishing-actions .preview {
65
+ text-align: center !important;
66
+ width: 280px !important;
67
+ margin: auto !important;
68
+ height: 44px !important;
69
+ font-size: 17px !important;
70
+ }
71
+ #major-publishing-actions {
72
+ padding: 10px 10px 10px !important;}
73
+ .select2-container {
74
+ min-width: 100% !important;
75
+ }
76
+ .inbound-meta-box-option.inbound-media-option input[type=text] {
77
+ width: 100%;
78
+ }
79
+ #submitdiv {
80
+ position: fixed !important;
81
+ bottom: 0px !important;
82
+ z-index: 999999 !important;
83
+ width: 100% !important;
84
+ margin-left: -10px !important;
85
+ padding-bottom: 10px !important;
86
+ margin-bottom: 0px !important;
87
+
88
+ }
89
+ .version-3-8 #submitdiv {
90
+ margin-left: -20px !important;
91
+ }
92
+ .jPicker .Grid {
93
+ display: none;
94
+ }
95
+ .jPicker .Button {
96
+ text-align: center;
97
+ padding: 0 4px;
98
+ width: 264px;
99
+ position: absolute;
100
+ border-bottom: none;
101
+ left: 0px;
102
+ bottom: 3px;
103
+ }
104
+ .jPicker .Button input {
105
+ font-size: 18px !important;
106
+ }
107
+ .jPicker .Icon span.Color, .jPicker .Icon span.Alpha {
108
+ width: 97% !important;
109
+ }
110
+ .jPicker .Title {
111
+ width: 254px;
112
+ }
113
+ .jPicker hr {
114
+ display: none !important;
115
+ }
116
+ .inbound-meta-box-option.inbound-datepicker-option span{
117
+ display: block;
118
+ }
119
+ .inbound-meta-box-option.inbound-datepicker-option input {
120
+ width: 70%;
121
+ }
122
+ .template-thumbnail {
123
+ height: auto !important;
124
+ }
125
+ #template-item #template-box {
126
+ display: block;
127
+ width: 65%;
128
+ margin: auto;
129
+ }
130
+ table.jPicker {
131
+ width: 430px !important;}
132
+ @media only screen and (max-width: 600px) {
133
+ .media-modal {
134
+ width: 432px !important;
135
+ position: fixed !important;
136
+ height: 484px !important;
137
+ }
138
+ .media-modal-backdrop {
139
+ width: 600px;
140
+ position: fixed !important;
141
+ }
142
+ }
143
+ @media screen and (max-width: 782px) {
144
+ #wp-content-editor-tools {
145
+ overflow: hidden;
146
+ padding: 0px 15px 1px 0; }
147
+ }
148
+ ul#template-filter {
149
+ clear: both !important;
150
+ margin: 0px 0;
151
+ padding: 0;
152
+ padding-left: 0px;
153
+ line-height: 28px;
154
+ }
155
+ #lp-cancel-selection {
156
+ display: block;
157
+ float: none;
158
+ width: 70%;
159
+ text-align: center;
160
+ margin: auto;
161
+ margin-bottom: 10px;
162
+ margin-top: 10px;
163
+ }
164
+ #template-item {
165
+ width: 100%
166
+ }
167
+ .currently_selected {
168
+ width: 90% !important;
169
+ }
170
+ ul#template-filter li {
171
+ display: inline-block;
172
+
173
+ padding-bottom: 0px;
174
+ padding-top: 0px;
175
+ margin: 0px;
176
+ line-height: 20px;
177
+ }
178
+ .lp-selection-heading h1 {
179
+ font-size: 18px;
180
+ display: block;
181
+ text-align: center;
182
+ }
183
+ .inbound-meta-box-label {
184
+ font-weight: bold;
185
+ text-decoration: none;
186
+ }
187
+ .form-table .inbound-meta-box-label label{
188
+ width: 100% !important;
189
+ display: block !important;
190
+ margin-bottom: 15px;
191
+ margin-top: 10px;
192
+ font-size: 15px !important;
193
+ }
194
+ .form-table .inbound-wysiwyg-row .inbound-meta-box-label label{
195
+ margin-left: -10px !important;
196
+ }
197
+
198
+
199
+ .mceIframeContainer.mceFirst.mceLast iframe {
200
+ width: 100% !important;
201
+ }
202
+ .mceIframeContainer.mceFirst.mceLast {
203
+ margin-top: 30px;
204
+ }
205
+ .mceToolbar.mceLeft.mceFirst.mceLast div {
206
+ background: #F5F5F5;
207
+ }
208
+ #lp_metabox_select_template {
209
+ margin-left: -20px !important;
210
+ width: 108%;
211
+ }
212
+ .wp-editor-container {
213
+ border-right-color: transparent !important;
214
+ }
215
+
216
+ #inbound-shortcodes-preview-wrap {
217
+ display: none !important;
218
+ }
219
+ .wp-editor-wrap {
220
+
221
+ border-right: 1px solid #E6E6E6 !important;
222
+ }
223
+ #inbound-shortcodes-form-wrap {
224
+ width: 96% !important;}
225
+ #inbound-shortcodes-form-wrap tbody tr.form-row td.label {
226
+ line-height: 29px !important;
227
+ display: block !important;
228
+ }
229
+ #popup-controls {
230
+ position: fixed;
231
+ border-top: 1px solid transparent !important;
232
+ bottom: 90px !important;
233
+ width: 300px !important;
234
+ left: 0% !important;
235
+ background: transparent !important;}
236
+ #inbound-shortcodes-form-table tbody tr.form-row {
237
+ display: block;
238
+ padding: 0px !important;
239
+ border-bottom: none !important;}
240
+ #inbound-shortcodes-form-wrap #inbound-shortcodes-form {
241
+ padding-bottom: 300px !important;
242
+ }
243
+ #inbound-shortcodes-form-table input[type="text"], #inbound-shortcodes-form-table input[type="email"], #inbound-shortcodes-form-table input[type="url"], #inbound-shortcodes-form-table input[type="number"], #inbound-shortcodes-form-table input[type="password"], #inbound-shortcodes-form-table textarea {
244
+ width: 100% !important;
245
+ }
246
+ #inbound_insert_shortcode_two, #shortcode_cancel, #inbound_save_form {
247
+ margin-bottom: 10px !important; }
trunk/assets/css/admin/edit-landing-page.css ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #main-title-area #lp-main-headline {
2
+ width: 100%;
3
+ font-size: 23px;
4
+ outline: 0 none;
5
+ padding: 0px 7px;
6
+ }
7
+
8
+ #post-body-content, .edit-form-section {
9
+ margin-bottom: 0px;
10
+ }
11
+
12
+ #main-title-header h3 {
13
+ display: inline-block;
14
+ padding-left: 0px;
15
+ }
16
+
17
+ #titlediv {
18
+ margin-bottom: 0px;
19
+ }
20
+
21
+ #TB_window {
22
+ z-index: 999999999999;
23
+ }
24
+
25
+ .currently_selected {
26
+ position: absolute;
27
+ top: 72px;
28
+ left: 16px;
29
+ font-size: 19px;
30
+ line-height: 21px;
31
+ padding-top: 15px;
32
+ text-align: center;
33
+ background: black;
34
+ width: 90%;
35
+ height: 36px;
36
+ color: white;
37
+ opacity: 0.5;
38
+ border-radius: 7px;
39
+ }
40
+
41
+ .lp-template-selector-container ul#template-filter li {
42
+ display: inline-block;
43
+
44
+ margin-right: 5px;
45
+ text-align: center;
46
+ margin-bottom: 10px;
47
+ }
48
+
49
+ .lp-template-selector-container ul#template-filter {
50
+ margin-bottom: 10px;
51
+ }
52
+
53
+ .lp-template-selector-container ul#template-filter {
54
+ line-height: 30px;
55
+ margin-top: 10px;
56
+ margin-bottom: 0px;
57
+ }
58
+
59
+ .lp-template-selector-container ul#template-filter a {
60
+ margin-right: 0px;
61
+ padding: 0px;
62
+ font-weight: bold;
63
+ text-decoration: none;
64
+ }
65
+
66
+ ul#template-filter .button-primary a {
67
+ color: #fff;
68
+ }
69
+
70
+ #more-templates-button {
71
+ display: inline-block;
72
+ vertical-align: middle;
73
+ float: none !important;
74
+ font-weight: normal;
75
+ font-size: 20px;
76
+ }
77
+
78
+ #more-templates-button a {
79
+ font-size: 15px;
80
+ }
81
+
82
+ #lp_2_form_content {
83
+ margin-top: 20px;
84
+ }
85
+
86
+ #lp_2_form_content .hndle em {
87
+ font-size: 13px;
88
+ }
89
+
90
+ .template-thumbnail {
91
+ width: 100%;
92
+ height: 190px;
93
+ -webkit-border-radius: 4px;
94
+ -khtml-border-radius: 4px;
95
+ -moz-border-radius: 4px;
96
+ border-radius: 4px;
97
+ background-color: #A9A9A9;
98
+ -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 0 0 1px, rgba(0, 0, 0, 0.3) 0 2px 5px;
99
+ -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 0 0 1px, rgba(0, 0, 0, 0.3) 0 2px 5px;
100
+ box-shadow: rgba(0, 0, 0, 0.2) 0 0 0 1px, rgba(0, 0, 0, 0.3) 0 2px 5px;
101
+ }
102
+
103
+ ul#template-filter {
104
+ margin: 0px 0;
105
+ padding: 0;
106
+ padding-left: 0px;
107
+ line-height: 64px;
108
+ }
109
+
110
+ ul#template-filter li {
111
+ display: inline;
112
+ }
113
+
114
+ ul#template-filter a {
115
+ margin-right: 0.5em;
116
+ padding: 0em 1em;
117
+ font-weight: bold;
118
+ text-decoration: none;
119
+ }
120
+
121
+ ul#template-filter .button-primary a:hover {
122
+ color: #fff;
123
+ }
124
+
125
+ ul#template-filter a.current {
126
+ background-color: #DDD;
127
+ }
128
+
129
+ #template-item {
130
+ float: left;
131
+ margin-right: 18px;
132
+ overflow: hidden;
133
+ margin: 0px 0 0 0;
134
+ padding: 0;
135
+ list-style: none;
136
+ width: 300px;
137
+ margin-bottom: 10px;
138
+ }
139
+
140
+ #template-item div {
141
+ display: block;
142
+ }
143
+
144
+ /* #template-item div a{ display: block; width: 163px; height: 120px; overflow: hidden; border: 1px solid #CDCDCD; background: #eee; }*/
145
+ #template-item li p {
146
+ font-size: 11px;
147
+ line-height: 15px;
148
+ color: #AAA;
149
+ margin: 5px 0;
150
+ }
151
+
152
+ #template-box .lp_tooltip_templates {
153
+ bottom: 6px;
154
+ position: absolute;
155
+ right: 8px;
156
+ }
157
+
158
+ .lp_tooltip {
159
+ display: inline;
160
+ }
161
+
162
+ .lp_tooltip:after {
163
+ font-family: "fontawesome";
164
+ content: "\f05a";
165
+ padding-left: 10px;
166
+ opacity: .3;
167
+ }
trunk/assets/css/admin/global-settings.css ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .nav-tab-special-inactive {
3
+ border-color: #DFDFDF #DFDFDF #FFFFFF;
4
+ border-top-left-radius: 3px;
5
+ border-top-right-radius: 3px;
6
+ border-width: 1px 1px 0;
7
+ color: #AAAAAA;
8
+ display: inline-block;
9
+ font-size: 12px;
10
+ line-height: 16px;
11
+ margin: 0 6px -1px 0;
12
+ padding: 4px 14px 6px;
13
+ text-decoration: none;
14
+ text-shadow: 0 1px 0 #FFFFFF;
15
+ cursor: pointer;
16
+ }
17
+
18
+ .nav-tab-special-active {
19
+ border-color: #DFDFDF #DFDFDF transparent !important;
20
+ border-top-left-radius: 3px;
21
+ border-top-right-radius: 3px;
22
+ border-width: 1px 1px 1px;
23
+ color: #000;
24
+ display: inline-block;
25
+ font-size: 12px;
26
+ line-height: 16px;
27
+ margin: 0 6px -1px 0;
28
+ padding: 4px 14px 6px;
29
+ text-decoration: none;
30
+ text-shadow: 0 1px 0 #FFFFFF;
31
+ cursor: pointer;
32
+ background: rgba(241, 241, 241, 1) !important;
33
+
34
+ }
35
+
36
+ .lp-tab-display textarea {
37
+ width: 90%;
38
+ }
39
+
40
+ .lp-tab-display {
41
+ width: 70%;
42
+ }
43
+
44
+ .lp-settings-tab-sidebar {
45
+ float: right;
46
+ width: 26%;
47
+ }
48
+
49
+ .lp-sidebar-settings {
50
+ background: #fff;
51
+ border: 1px solid #EBEBEA;
52
+ -webkit-box-shadow: inset 1px 1px 1px #f9f9f9;
53
+ -moz-box-shadow: inset 1px 1px 1px #f9f9f9;
54
+ box-shadow: inset 1px 1px 1px #f9f9f9;
55
+ padding: 15px 15px 15px;
56
+ margin-bottom: 20px;
57
+ margin-right: 20px;
58
+ }
59
+
60
+ .lp-sidebar-settings .review-button {
61
+ background: #94BA65;
62
+ border: 1px solid rgba(0, 0, 0, 0.15);
63
+ -webkit-border-radius: 2px;
64
+ -moz-border-radius: 2px;
65
+ border-radius: 2px;
66
+ -webkit-box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.15), inset 1px 1px 1px rgba(255, 255, 255, 0.2);
67
+ -moz-box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.15), inset 1px 1px 1px rgba(255, 255, 255, 0.2);
68
+ box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.15), inset 1px 1px 1px rgba(255, 255, 255, 0.2);
69
+ color: #fff;
70
+ cursor: pointer;
71
+ display: inline-block;
72
+ font-family: inherit;
73
+ font-size: 22px;
74
+ font-weight: bold;
75
+ text-decoration: none;
76
+ padding: 8px 15px;
77
+ margin-top: 5px;
78
+ margin-bottom: 5px;
79
+ text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.15);
80
+ }
81
+
82
+ .lp-sidebar-settings h2 {
83
+ font-size: 21px;
84
+ line-height: 24px;
85
+ margin: 0px 0px 5px;
86
+ text-shadow: 1px 1px 1px #fff;
87
+ }
88
+
89
+ .lp-sidebar-settings small {
90
+ display: block;
91
+ margin-top: 5px;
92
+ }
93
+
94
+ .lp-sidebar-settings input[type="image"] {
95
+ margin: auto;
96
+ margin-left: 90px;
97
+ }
98
+
99
+ #lp-additional-resources {
100
+ padding-top: 15px;
101
+ margin-left: 10px;
102
+ }
103
+
104
+ #lp-additional-resources hr {
105
+ margin-bottom: 15px;
106
+ margin-left: -29px;
107
+ color: rgb(233, 233, 233);
108
+ opacity: .7;
109
+ border: 1px solid;
110
+ }
111
+
112
+ #lp-wordpress-site-status {
113
+
114
+ color: #000;
115
+ }
116
+
117
+ #php-sql-lp-version h3 {
118
+ color: #000;
119
+ margin-bottom: 0px;
120
+ margin-top: 0px;
121
+ padding-top: 0px;
122
+ font-size: 1.5em;
123
+ }
124
+
125
+ #sys-inbound-form {
126
+ display: none;
127
+ }
128
+
129
+ #sys-inbound-form h2 {
130
+ display: inline-block;
131
+ }
132
+
133
+ #inbound-download-sysinfo {
134
+ margin-left: 12px;
135
+ }
136
+
137
+ .lp-tab-display #php-sql-lp-version th {
138
+ padding: 10px;
139
+ padding-left: 0px;
140
+ }
141
+
142
+ #lp-main {
143
+ padding-top: 0px;
144
+ }
145
+
146
+ #copy-inbound-info {
147
+ min-height: 400px;
148
+ }
149
+
150
+ .nav-tab-wrapper {
151
+ margin-left: -20px;
152
+ padding-left: 33px !important;
153
+ }
154
+
155
+ #lp-main h4, h3.lp_global_settings_header {
156
+ margin-top: 0px;
157
+ padding-top: 0px;
158
+ padding-top: 0px;
159
+ font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif;
160
+ font-weight: 400;
161
+ line-height: 1.6em;
162
+ font-size: 20px;
163
+ padding-bottom: 0px;
164
+ margin-bottom: 5px;
165
+ }
166
+
167
+ #htaccess-contents {
168
+ margin-top: 20px;
169
+ }
170
+
171
+ #more-templates, #more-addons, #custom-templates {
172
+ width: 29%;
173
+ display: inline-block;
174
+ background: #FCFDFE;
175
+ padding: 5px;
176
+ margin-right: 10px;
177
+ border: 1px solid #E0E0E0;
178
+ -moz-border-radius: 7px;
179
+ border-radius: 7px;
180
+ overflow: hidden;
181
+ position: relative;
182
+ }
183
+
184
+ #more-templates img, #more-addons img, #custom-templates img {
185
+ margin: auto;
186
+ }
187
+
188
+ #php-sql-lp-version {
189
+ display: block;
190
+ }
191
+
192
+ .lp-tab-display {
193
+ padding: 13px;
194
+ }
195
+
196
+ .lp-tab-display td {
197
+ padding: 10px;
198
+ }
199
+
200
+ .lp-tab-display th {
201
+ padding: 10px;
202
+ }
203
+
204
+ .lp-tab-display th, .lp-tab-display .lp-gs-th {
205
+ width: 300px;
206
+ font-size: 14px;
207
+ font-weight: 300px;
208
+ text-align: left;
209
+ }
210
+
211
+ .lp_license_status_invalid {
212
+ display: inline;
213
+ padding-left: 10px;
214
+ color: red;
215
+ font-style: italic;
216
+ }
217
+
218
+ .lp_license_status_valid {
219
+ display: inline;
220
+ padding-left: 10px;
221
+ color: green;
222
+ font-style: italic;
223
+ }
224
+
225
+ #php-sql-lp-version {
226
+ display: none;
227
+ }
228
+
229
+ .tooltip {
230
+ cursor: help;
231
+ }
trunk/assets/css/admin/install-plugins.css ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #the-list .inbound-install-notice, #the-list .inbound-install-notice-links, .click-to-activate, .click-to-activate-bulk {
2
+ display: none;
3
+ }
4
+ .click-to-activate, .click-to-activate-bulk {
5
+ vertical-align: top !important;
6
+ padding-top: 0px !important;
7
+ }
8
+ .click-to-activate span, .click-to-activate-bulk span {
9
+ color: #04A204;
10
+ padding-right: 10px;
11
+ font-size: 40px;
12
+ text-shadow: none;
13
+ }
trunk/assets/css/admin/landing-page-edit-style.css ADDED
@@ -0,0 +1,542 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .cat-block {
3
+ display: inline-table;
4
+ padding-right: 60px;
5
+ }
6
+
7
+ #main-title-area {
8
+ margin-top: 5px;
9
+ }
10
+
11
+ #main-title-area span {
12
+ margin-top: 30px;
13
+ z-index: 999999;
14
+ }
15
+
16
+ tr#leads {
17
+ display: table-row !important;
18
+ }
19
+
20
+ #add-landing-page.hide-if-js {
21
+ display: block !important;
22
+ }
23
+
24
+ #menu-posts-landing-page .wp-submenu.wp-submenu-wrap {
25
+ z-index: 99999;
26
+ }
27
+
28
+ @font-face {
29
+ font-family: 'FontAwesome';
30
+ src: url('../shared/assets/fonts/fontawesome/fontawesome-webfont.eot?v=3.0.2');
31
+ src: url('../shared/assets/fonts/fontawesome/fontawesome-webfont.eot?#iefix&v=3.0.2') format('embedded-opentype'),
32
+ url('../shared/assets/fonts/fontawesome/fontawesome-webfont.woff?v=3.0.2') format('woff'),
33
+ url('../shared/assets/fonts/fontawesome/fontawesome-webfont.ttf?v=3.0.2') format('truetype');
34
+ font-weight: normal;
35
+ font-style: normal;
36
+ }
37
+
38
+ #adminmenu .menu-icon-landing-page div.wp-menu-image:before {
39
+ font-family: "FontAwesome" !important;
40
+ content: "\f15c";
41
+
42
+ }
43
+
44
+ .branch-3-7 #adminmenu .menu-icon-landing-page div.wp-menu-image:before {
45
+ display: none;
46
+ }
47
+
48
+ #adminmenu .menu-icon-landing-page div.wp-menu-image img {
49
+ display: none;
50
+ }
51
+
52
+ .branch-3-7 #adminmenu .menu-icon-landing-page div.wp-menu-image img {
53
+ display: block;
54
+ }
55
+
56
+ .appearance_page_install-inbound-plugins .inbound-install-notice {
57
+ display: none;
58
+ }
59
+
60
+ .inbound-and {
61
+ display: block;
62
+ margin-top: 10px;
63
+ font-size: 15px;
64
+ }
65
+
66
+ #postexcerpt p {
67
+ display: none;
68
+ }
69
+
70
+ .metabox-holder .postbox-container .empty-container {
71
+ border: none;
72
+ }
73
+
74
+ #lp_templates_wrapper_inside {
75
+ padding-left: 15px;
76
+ width: 945px;
77
+ margin: 0;
78
+ }
79
+
80
+ .lp_template_wrapper ul li {
81
+ float: left;
82
+ position: relative;
83
+ list-style: none;
84
+ }
85
+
86
+ /*hudson*/
87
+ .lp_template_wrapper ul li label {
88
+ font-size: 14px;
89
+ font-weight: 300;
90
+ color: greytext;
91
+ text-decoration: none;
92
+
93
+ }
94
+
95
+ /*hudson*/
96
+ .lp_template_wrapper ul li .template {
97
+ font-size: 14px;
98
+ / / font-weight: bold;
99
+ color: #222222;
100
+ text-decoration: none;
101
+ / / text-shadow: 0 1 px 2 px black;
102
+ }
103
+
104
+ #lp-main-headline-wrap {
105
+ margin-top: 5px;
106
+ }
107
+
108
+ .lp_template_wrapper ul li:hover {
109
+ / / height: 43 px;
110
+ -webkit-box-shadow: 0 0px 2px black inset;
111
+
112
+ }
113
+
114
+ .lp_template_wrapper ul li ul li:hover {
115
+ background: none;
116
+ -webkit-box-shadow: none;
117
+ -moz-box-shadow: none;
118
+ height: auto;
119
+ border: none;
120
+ }
121
+
122
+ .lp_template_wrapper ul li .horizontal li {
123
+ padding: 14px 10px 0px 0px;
124
+ }
125
+
126
+ .lp_template_wrapper ul li .horizontal li:first-child {
127
+ margin-left: -10px;
128
+ }
129
+
130
+ .lp_template_wrapper ul li .horizontal li a {
131
+ font-size: 12px;
132
+ font-weight: normal;
133
+ color: #c7c7c7;
134
+ }
135
+
136
+ .arrow-up {
137
+ width: 0;
138
+ height: 0;
139
+ border-left: 10px solid transparent;
140
+ border-right: 10px solid transparent;
141
+ border-bottom: 15px solid #6a6a63;
142
+ position: absolute;
143
+ left: 20px;
144
+ top: -15px;
145
+ }
146
+
147
+ .lp_template_wrapper ul li ul li .extended {
148
+ position: absolute;
149
+ top: 45px;
150
+ left: 0;
151
+ width: 330px;
152
+ background: url(images/dropdownback.png);
153
+ z-index: 1000;
154
+ -moz-box-shadow: 0 0px 8px rgba(0, 0, 0, 0.8);
155
+ -webkit-box-shadow: 0 0px 8px rgba(0, 0, 0, 0.8);
156
+ box-shadow: 0 0 8px black;
157
+ -moz-border-radius: 5px;
158
+ -webkit-border-radius: 5px;
159
+ border-radius: 5px;
160
+ border: 1px solid white;
161
+ display: none;
162
+ color: white;
163
+ }
164
+
165
+ .lp_template_wrapper ul li ul li .extended .screenshot {
166
+ display: block;
167
+ margin: 5px auto -26px auto;
168
+ -webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.8, transparent), to(rgba(255, 255, 255, 0.5)));
169
+ }
170
+
171
+ .lp_template_wrapper ul li ul li .extended p {
172
+ padding: 10px;
173
+ font-size: 11px;
174
+ line-height: 17px;
175
+ text-shadow: 0 1px 1px black;
176
+ }
177
+
178
+ .lp_template_wrapper ul li ul li .extended h2, .lp_template_wrapper ul li .ultraNav h2 {
179
+ padding-top: 10px;
180
+ padding-left: 10px;
181
+ font-size: 16px;
182
+ text-shadow: 0 1px 2px black;
183
+ color: white;
184
+ background: url(images/headerback.png) repeat-x;
185
+ height: 20px;
186
+ border-radius: 3px;
187
+ -webkit-border-radius: 3px;
188
+ -moz-border-radius: 3px;
189
+ }
190
+
191
+ .lp_template_wrapper ul li ul li .extended span {
192
+ padding-left: 10px;
193
+ font-size: 11px;
194
+ }
195
+
196
+ .lp_template_wrapper ul li ul li .extended ul.smallNav {
197
+ border-top: 1px solid rgba(141, 141, 141, 0.50);
198
+ padding: 10px;
199
+ height: 100px;
200
+ }
201
+
202
+ .lp_template_wrapper ul li ul li .extended ul.smallNav li {
203
+ padding: 0;
204
+ line-height: 22px;
205
+ font-weight: bold;
206
+ background: url(images/linkback.png) no-repeat;
207
+ }
208
+
209
+ .lp_template_wrapper ul li ul li .extended ul.smallNav li a {
210
+ color: #fff;
211
+ text-shadow: none;
212
+ font-size: 12px;
213
+ }
214
+
215
+ .lp_template_wrapper ul li ul li .extended ul.smallNav li label {
216
+ color: #c7c7c7;
217
+ text-shadow: none;
218
+ font-size: 12px;
219
+ text-decoration: none;
220
+ }
221
+
222
+ .lp-feature-link {
223
+ float: none;
224
+ margin: 0px;
225
+ display: block;
226
+ padding: 2px;
227
+ }
228
+
229
+ .lp-feature-link .lp-feature-link-img {
230
+ padding: 2px;
231
+ display: inline-block;
232
+ }
233
+
234
+ /*david*/
235
+ th.landing-page-table-header {
236
+ width: 230px;
237
+ line-height: 22px;
238
+ }
239
+
240
+ .default_template_highlight {
241
+ -webkit-box-shadow: inset 0px 0px 12px 1px rgba(82, 168, 238, 1);
242
+ box-shadow: inset 0px 0px 12px 1px rgba(82, 168, 238, 1);
243
+ }
244
+
245
+ .lp-selection-heading {
246
+ width: 89%;
247
+ margin-top: 20px;
248
+ }
249
+
250
+ .lp-selection-heading h1 {
251
+ display: inline;
252
+ }
253
+
254
+ #lp-cancel-selection {
255
+ display: inline;
256
+ float: right;
257
+ }
258
+
259
+ .lp_template_wrapper ul li ul li .extended ul.smallNav li:first-child {
260
+ margin: 0;
261
+ }
262
+
263
+ .lp_template_wrapper ul li ul li .extended ul.smallNav li:last-child {
264
+ margin-bottom: 10px;
265
+ }
266
+
267
+ .lp_template_wrapper ul li ul li:hover .extended {
268
+ display: block;
269
+ }
270
+
271
+ .lp_template_wrapper ul li .ultraNav {
272
+ position: absolute;
273
+ top: 55px;
274
+ left: -100px;
275
+ width: 294px;
276
+ background: url(images/dropdownback.png);
277
+ border: 1px solid white;
278
+ -webkit-border-radius: 5px;
279
+ -moz-border-radius: 5px;
280
+ border-radius: 5px;
281
+ z-index: 500;
282
+ -moz-box-shadow: 0 3px 8px rgba(0, 0, 0, 0.6);
283
+ -webkit-box-shadow: 0 3px 8px rgba(0, 0, 0, 0.6)
284
+ box-shadow: 0 3px 8px black;
285
+ display: none;
286
+ }
287
+
288
+ .ultraNav h2 {
289
+ text-align: center;
290
+ padding-left: 10px;
291
+ padding-top: 10px;
292
+ }
293
+
294
+ .lp_template_wrapper ul li .ultra {
295
+ width: 130px;
296
+ float: left;
297
+ margin: 10px 0 10px 10px;
298
+ -moz-box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.6);
299
+ -webkit-box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.6);
300
+ -moz-border-radius: 5px;
301
+ -webkit-border-radius: 5px;
302
+ border-bottom: none;
303
+ }
304
+
305
+ .lp_template_wrapper ul li .ultra:first-child {
306
+ margin: 0;
307
+ }
308
+
309
+ .lp_template_wrapper ul li .ultraNav .arrow-up {
310
+ left: 130px;
311
+ }
312
+
313
+ .lp_template_wrapper ul li .ultra a {
314
+ font-weight: normal;
315
+ font-size: 12px;
316
+ color: #c7c7c7;
317
+ text-shadow: 0 1px 2px black;
318
+ }
319
+
320
+ .lp_template_wrapper ul li .ultra li {
321
+ width: 120px;
322
+ line-height: 20px;
323
+ padding: 3px 5px;
324
+ background: url(images/linkback.png) no-repeat;
325
+ }
326
+
327
+ .lp_template_wrapper ul li:hover .ultraNav {
328
+ display: block;
329
+ }
330
+
331
+ #lp_template_change h2 {
332
+ display: inline-block;
333
+ }
334
+
335
+ #lp_template_change {
336
+ margin-left: 17px;
337
+ margin-top: -20px;
338
+ float: right;
339
+ position: absolute;
340
+ top: 0px;
341
+ right: 10px;
342
+ }
343
+
344
+ /* Split Testing Splash */
345
+ .lp_tooltip, .lp_tooltip_templates {
346
+ background: url('/wp-content/plugins/landing-pages/assets/css/images/question-light.png');
347
+ width: 15px;
348
+ height: 15px;
349
+ display: inline-block;
350
+ margin-left: 5px;
351
+ vertical-align: middle;
352
+ cursor: help;
353
+ background-repeat: no-repeat;
354
+ }
355
+
356
+ .tool_date {
357
+ margin-left: 25px;
358
+ vertical-align: top;
359
+ }
360
+
361
+ .tool_textarea {
362
+ vertical-align: top;
363
+ }
364
+
365
+ .tool_color {
366
+ margin-top: 1px;
367
+ }
368
+
369
+ .tool_checkbox {
370
+ vertical-align: top;
371
+ margin-top: 4px;
372
+ }
373
+
374
+ .lp_check_box_table td {
375
+ padding: 0px;
376
+ }
377
+
378
+ .lp_check_box_table {
379
+ display: inline;
380
+ float: left;
381
+ }
382
+
383
+ /* Split Testing */
384
+ .lp_toggle_pause {
385
+ color: red;
386
+ }
387
+
388
+ .lp_toggle_play {
389
+ color: green;
390
+ }
391
+
392
+ /*store*/
393
+
394
+ /* iframe's parent node */
395
+ div#lp-store-iframe-container {
396
+ / / position: fixed;
397
+ width: 100%;
398
+ height: 100%;
399
+ overflow: hidden;
400
+ }
401
+
402
+ /* iframe itself */
403
+ div#lp-store-iframe-container > iframe {
404
+ display: block;
405
+ width: 100%;
406
+ height: 100%;
407
+ border: none;
408
+ margin-left: 0px;
409
+ }
410
+
411
+ .column-thumbnail {
412
+ height: 110px;
413
+ }
414
+
415
+ .wp-list-table .column-date {
416
+ width: 128px;
417
+ }
418
+
419
+ .wp-list-table .details {
420
+ text-align: left;
421
+ padding-left: 20px;
422
+ }
423
+
424
+ #leads-table-container-inside {
425
+ margin-top: -36px;
426
+ color: #388DBC;
427
+ }
428
+
429
+ #wp-leads-splash-header {
430
+ background: #f2f2f2;
431
+ border-bottom: 1px solid #EBEBEA;
432
+ -webkit-box-shadow: inset 1px 1px 1px rgba(255, 255, 255, 0.3);
433
+ -moz-box-shadow: inset 1px 1px 1px rgba(255, 255, 255, 0.3);
434
+ box-shadow: inset 1px 1px 1px rgba(255, 255, 255, 0.3);
435
+ padding: 20px;
436
+ text-shadow: 1px 1px 1px #fff;
437
+ }
438
+
439
+ #lead-details-container {
440
+ border: 1px solid #EBEBEA;
441
+ }
442
+
443
+ #wp-leads-splash-email, #wp-leads-splash-ip, #wp-leads-splash-city, #wp-leads-splash-state, #wp-leads-splash-name {
444
+ border-bottom: 1px solid #EBEBEA;
445
+ padding: 10px 20px;
446
+ }
447
+
448
+ #wp-leads-extra-data {
449
+ margin-left: 20px;
450
+ margin-top: 5px;
451
+ }
452
+
453
+ #wp-leads-extra-data td {
454
+ padding-right: 15px;
455
+ }
456
+
457
+ .wplp-green-button {
458
+ background: #94BA65;
459
+ border: 1px solid rgba(0, 0, 0, 0.15);
460
+ -webkit-border-radius: 2px;
461
+ -moz-border-radius: 2px;
462
+ border-radius: 2px;
463
+ -webkit-box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.15), inset 1px 1px 1px rgba(255, 255, 255, 0.2);
464
+ -moz-box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.15), inset 1px 1px 1px rgba(255, 255, 255, 0.2);
465
+ box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.15), inset 1px 1px 1px rgba(255, 255, 255, 0.2);
466
+ color: #fff;
467
+ cursor: pointer;
468
+ display: inline-block;
469
+ font-family: inherit;
470
+ font-size: 14px;
471
+ font-weight: bold;
472
+ padding: 4px 5px;
473
+ text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.15);
474
+ text-decoration: none;
475
+ }
476
+
477
+ .wplp-right {
478
+ float: right;
479
+ }
480
+
481
+ .lp-lead-splash-h3, .wp-lead-label {
482
+ display: inline;
483
+ }
484
+
485
+ .wp-lead-label {
486
+ font-weight: bold;
487
+ }
488
+
489
+ #leads-table-container-inside .wp-list-table .details {
490
+ padding-left: 0px;
491
+ }
492
+
493
+ #leads-table-container-inside .wp-list-table .column-date {
494
+ width: 150px;
495
+ }
496
+
497
+ .date-picker .new-save-lp {
498
+ display: none;
499
+ }
500
+
501
+ #lp-tour {
502
+ position: absolute;
503
+ font-size: 13px;
504
+ top: 0px;
505
+ right: 170px;
506
+ color: rgb(253, 3, 3);
507
+ cursor: pointer;
508
+ }
509
+
510
+ .lp-success-message {
511
+ background: #e2ffc9;
512
+ border: 1px solid #c5eda3;
513
+ padding: 4px 10px 4px 10px;
514
+ margin-left: 10px;
515
+ -webkit-border-radius: 3px;
516
+ -moz-border-radius: 3px;
517
+ border-radius: 3px;
518
+ position: relative;
519
+ margin-top: 10px;
520
+ text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.5);
521
+ }
522
+
523
+ tr.media-id p.description {
524
+ display: inline-block;
525
+ }
526
+
527
+ div.capty-caption {
528
+ background-color: #000000;
529
+ color: #FFFFFF;
530
+ font: bold 11px verdana;
531
+ padding-left: 10px;
532
+ padding-top: 7px;
533
+ text-shadow: 1px 1px 0 #222222;
534
+ }
535
+
536
+ div.capty-caption a {
537
+ color: #318DAD;
538
+ font: bold 11px verdana;
539
+ text-decoration: none;
540
+ text-shadow: none;
541
+ }
542
+
trunk/assets/css/admin/landing-page-list.css ADDED
@@ -0,0 +1,492 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* CSS for Landing Page List */
2
+ #stats {
3
+ width: 270px;
4
+ }
5
+
6
+ #thumbnail-lander {
7
+ width: 162px;
8
+ }
9
+ #lp-tour {
10
+ margin-left: 10px;
11
+ }
12
+ #title {
13
+ width: 255px;
14
+ }
15
+
16
+ #impressions, #cr, #actions {
17
+ width: 99px;
18
+ text-align: center;
19
+ }
20
+
21
+ #cr {
22
+ width: 120px;
23
+ }
24
+
25
+ #cb {
26
+ width: 20px;
27
+ }
28
+
29
+ .clear_stats {
30
+ color: red;
31
+ }
32
+
33
+ .hover-description {
34
+ display: block;
35
+ color: grey;
36
+ font-size: 10px;
37
+ font-style: italic;
38
+ }
39
+
40
+ .lp-pop-description {
41
+ padding: 10px;
42
+ padding-left: 4px;
43
+ padding-top: 6px;
44
+ }
45
+
46
+ .lp-bottom-controls {
47
+ margin-left: 12px;
48
+ color: red;
49
+ font-size: 12px;
50
+ margin-right: 8px;
51
+ }
52
+
53
+ .lp-delete-var-stats {
54
+ display: inline-block;
55
+ }
56
+
57
+ .lp-pop-description {
58
+ display: block;
59
+ max-width: 325px;
60
+ }
61
+
62
+ .lp-pop-close {
63
+ font-size: 11px;
64
+ position: absolute;
65
+ font-weight: 100;
66
+ right: 10px;
67
+ top: 3px;
68
+ }
69
+
70
+ .winner-lp {
71
+ background-color: #E2FFC9;
72
+ }
73
+
74
+ .lp-pop-edit a {
75
+ color: #fff;
76
+ }
77
+
78
+ .lp-extra {
79
+ margin-left: 10px;
80
+ }
81
+
82
+ .lp-win {
83
+ color: green;
84
+ font-size: 14px;
85
+ font-weight: bold;
86
+ text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.5);
87
+ }
88
+
89
+ .lp-paused {
90
+ color: red;
91
+ font-size: 12px;
92
+ }
93
+
94
+ .lp-pop-controls {
95
+ display: inline-block;
96
+ margin-top: 8px;
97
+ }
98
+
99
+ .lp-pop-edit {
100
+ display: inline-block !important;
101
+ margin-right: 11px !important;
102
+ margin-left: 5px !important;
103
+ }
104
+
105
+ .lp-pop-preview a, .lp-pop-edit a {
106
+ text-decoration: none;
107
+ }
108
+
109
+
110
+ .stats li {
111
+ border-bottom: 1px solid #EBEBEA;
112
+ padding: 6px 20px;
113
+ margin: 0;
114
+ font-size: 13px;
115
+ vertical-align: top;
116
+ padding-left: 5px;
117
+ padding-right: 5px;
118
+ }
119
+
120
+ .stats li:hover {
121
+ background: #e0e0e0;
122
+ }
123
+
124
+ .wp-list-table td.stats .show-stats, .show-stats, .variation-winner-is {
125
+ display: none;
126
+ }
127
+
128
+ .wp-list-table td.stats .show-stats {
129
+ margin-top: 10px;
130
+ padding-top: 0px;
131
+ margin-left: 4px;
132
+ position: absolute;
133
+ }
134
+
135
+ td.stats.column-stats {
136
+ border: 1px solid #EBEBEA;
137
+
138
+ }
139
+
140
+ .wp-list-table td.stats {
141
+ padding-left: 0px;
142
+ padding-right: 0px;
143
+ }
144
+
145
+ .lp-current-winner {
146
+ background-color: rgb(226, 255, 201);
147
+ }
148
+
149
+ #impressions span, #cr span, #actions span {
150
+ text-align: center;
151
+ float: none;
152
+ }
153
+
154
+ .lp-varation-stat-ul {
155
+ min-width: 270px;
156
+ }
157
+
158
+ .status-0 {
159
+ background-color: #F9DBDB !important;
160
+ font-weight: normal;
161
+ color: rgb(117, 117, 117) !important;
162
+ }
163
+
164
+ .wp-list-table td.impressions, .wp-list-table td.actions, .wp-list-table td.cr {
165
+ font-size: 18px;
166
+ color: #000;
167
+ margin: 0;
168
+ text-align: center;
169
+ padding-top: 15px;
170
+ border-right: 1px solid #EBEBEA;
171
+ }
172
+
173
+ .wp-list-table td.cr {
174
+ }
175
+
176
+ .row-title {
177
+ font-size: 15px !important;
178
+ margin-top: 2px !important;
179
+ display: inline-block;
180
+ }
181
+
182
+ .wp-list-table td.actions {
183
+ }
184
+
185
+ .post-state .states {
186
+ font-size: 10px;
187
+ padding: 3px 8px 3px 8px;
188
+ -moz-border-radius: 2px;
189
+ -webkit-border-radius: 2px;
190
+ border-radius: 2px;
191
+ }
192
+
193
+ .post-state .password {
194
+ background: #000;
195
+ color: #fff;
196
+ }
197
+
198
+ .post-state .pending {
199
+ background: #83CF21 !important;
200
+ color: #fff;
201
+ }
202
+
203
+ .post-state .private {
204
+ background: #E0A21B;
205
+ color: #fff;
206
+ }
207
+
208
+ .post-state .draft {
209
+ background: #006699;
210
+ color: #fff;
211
+ }
212
+
213
+ #hide-stats, .show-stats-top {
214
+ color: #21759b;
215
+ font-size: 9px;
216
+ padding-left: 10px;
217
+ }
218
+
219
+ .stats li:last-child {
220
+ //border-bottom: none;
221
+ }
222
+
223
+ .no-stats-yet {
224
+ padding-left: 7px;
225
+ padding-top: 6px;
226
+ color: #777;
227
+ font-size: 11px;
228
+ display: none;
229
+ }
230
+
231
+ .widefat td.stats {
232
+ border-top: none;
233
+ padding-top: 0px;
234
+ }
235
+
236
+ .widefat td.stats ul {
237
+ font-size: 12px;
238
+ border-top: none;
239
+ width: 100%;
240
+ border-bottom: none;
241
+ margin-bottom: 0px;
242
+ padding-bottom: 0px;
243
+ display: inline-block;
244
+ margin-top: 0px;
245
+ }
246
+
247
+ .lp-numbers {
248
+ font-size: 13px;
249
+ min-width: 199px;
250
+ display: inline-block;
251
+ }
252
+
253
+ .introjs-showElement .row-actions {
254
+ visibility: visible;
255
+ }
256
+
257
+ .stats li:last-child:not(:first-child) {
258
+ border-bottom: none;
259
+ }
260
+
261
+ .lp-impress-num {
262
+ display: inline-block;
263
+ text-align: center;
264
+ min-width: 30px;
265
+ padding-right: 5px;
266
+ padding-left: 5px;
267
+ }
268
+
269
+ .lp-no-stats {
270
+ display: inline-block;
271
+ padding-left: 10px;
272
+ color: #ccc;
273
+ }
274
+
275
+ .lp-impress-num, .lp-con-num, .cr-number {
276
+ font-weight: bold;
277
+ font-size: 19px;
278
+ }
279
+
280
+ .visit-text {
281
+ display: inline-block;
282
+ min-width: 60px;
283
+ }
284
+
285
+ .lp-con-num {
286
+ display: inline-block;
287
+ padding-left: 4px;
288
+ padding-right: 4px;
289
+ }
290
+
291
+ .lp-letter, .cr-number, .cr-number.cr-empty-0 {
292
+ display: inline-block;
293
+
294
+ font-size: 20px;
295
+ min-width: 16px;
296
+ min-height: 20px;
297
+ border-radius: 3px;
298
+ background: #f3f3f3;
299
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#f4f4f4));
300
+ background-image: -webkit-linear-gradient(top, #fefefe, #f4f4f4);
301
+ background-image: -moz-linear-gradient(top, #fefefe, #f4f4f4);
302
+ background-image: -o-linear-gradient(top, #fefefe, #f4f4f4);
303
+ background-image: linear-gradient(to bottom, #fefefe, #f4f4f4);
304
+ border-color: #bbb;
305
+ color: #333;
306
+ text-shadow: 0 1px 0 #fff;
307
+ font-family: sans-serif;
308
+ cursor: pointer;
309
+ border-width: 1px;
310
+ border-style: solid;
311
+ padding: 1px;
312
+ padding-left: 4px;
313
+ text-align: center;
314
+ padding-right: 5px;
315
+ padding-top: 6px;
316
+ margin-right: 5px;
317
+ }
318
+
319
+ .cr-number {
320
+ margin-left: 5px;
321
+ padding-left: 5px;
322
+ background-color: #21759b;
323
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#2a95c5), to(#21759b));
324
+ background-image: -webkit-linear-gradient(top, #2a95c5, #21759b);
325
+ background-image: -moz-linear-gradient(top, #2a95c5, #21759b);
326
+ background-image: -ms-linear-gradient(top, #2a95c5, #21759b);
327
+ background-image: -o-linear-gradient(top, #2a95c5, #21759b);
328
+ background-image: linear-gradient(to bottom, #2a95c5, #21759b);
329
+ border-color: #21759b;
330
+ border-bottom-color: #1e6a8d;
331
+ -webkit-box-shadow: inset 0 1px 0 rgba(120, 200, 230, 0.5);
332
+ box-shadow: inset 0 1px 0 rgba(120, 200, 230, 0.5);
333
+ color: #fff;
334
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
335
+ font-weight: normal;
336
+ margin-right: 0px !important;
337
+ }
338
+
339
+ .cr-number.cr-empty-0 {
340
+ font-weight: normal !important;
341
+ color: #ccc;
342
+ box-shadow: none;
343
+ -webkit-box-shadow: none;
344
+ }
345
+
346
+ a.cr-number:hover {
347
+ background-color: #278ab7;
348
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#2e9fd2), to(#21759b));
349
+ background-image: -webkit-linear-gradient(top, #2e9fd2, #21759b);
350
+ background-image: -moz-linear-gradient(top, #2e9fd2, #21759b);
351
+ background-image: -ms-linear-gradient(top, #2e9fd2, #21759b);
352
+ background-image: -o-linear-gradient(top, #2e9fd2, #21759b);
353
+ background-image: linear-gradient(to bottom, #2e9fd2, #21759b);
354
+ border-color: #1b607f;
355
+ -webkit-box-shadow: inset 0 1px 0 rgba(120, 200, 230, 0.6);
356
+ box-shadow: inset 0 1px 0 rgba(120, 200, 230, 0.6);
357
+ color: #fff;
358
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
359
+ }
360
+
361
+
362
+ /* New Variation Testing Stat Design by Ahmed Kaludi (AhmedKaludi.com) START */
363
+ .lp-varation-stat-ul{
364
+ font-family: "Open Sans",sans-serif;
365
+ }
366
+ .lp-varation-stat-ul li{
367
+ padding: 0;
368
+ }
369
+ .lp-varation-stat-ul li .lp-letter{
370
+ background: #fff;
371
+ border: 0;
372
+ border-radius: 0;
373
+ margin-right: 0;
374
+ font-weight: 300;
375
+ font-size: 20px;
376
+ padding: 22px 16px;
377
+ line-height: 1;
378
+ color: #666666
379
+ }
380
+ .column-stats{
381
+ padding: 0px !important
382
+ }
383
+ .lp-varation-stat-ul .winner-lp{
384
+ background: #F9FFF4 !important
385
+ }
386
+ .lp-varation-stat-ul .winner-lp .lp-letter{
387
+ background: #15dd6f;
388
+ color: #fff;
389
+ font-weight: 300
390
+ }
391
+ .lp-varation-stat-ul .visit-text,
392
+ .lp-varation-stat-ul .lp-conversion-txt{
393
+ width: 100%;
394
+ text-align: center;
395
+ display: inline-block;
396
+ color: #777;
397
+ }
398
+ .lp-varation-stat-ul .lp-impress-num,
399
+ .lp-varation-stat-ul .lp-con-num{
400
+ width: 100%;
401
+ text-align: center;
402
+ padding: 0;
403
+ }
404
+ .lp-varation-stat-ul .lp-visitors,
405
+ .lp-varation-stat-ul .lp-conversions{
406
+ width: 81px;
407
+ display: inline-block;
408
+ text-align: center;
409
+ }
410
+ .visit-text, .lp-conversion-txt{
411
+ text-transform: uppercase;
412
+ font-size: 10px;
413
+ color: #333333;
414
+ letter-spacing: 0.6px;
415
+ }
416
+ .lp-varation-stat-ul .lp-impress-num,
417
+ .lp-varation-stat-ul .lp-con-num{
418
+ font-size: 16px;
419
+ color: #000;
420
+ font-weight: normal;
421
+ }
422
+ .lp-varation-stat-ul .lp-numbers{
423
+ min-width: 140px;
424
+ position: absolute;
425
+ margin-top: 12px;
426
+ }
427
+ .lp-varation-stat-ul .cr-number.cr-empty-0,
428
+ .lp-varation-stat-ul .cr-number.cr-empty-0:hover{
429
+ text-align: center;
430
+ width: 42px;
431
+ float: right;
432
+ background: none;
433
+ border: 0;
434
+ box-shadow: none;
435
+ font-size: 14px;
436
+ font-weight: normal;
437
+ color: #999;
438
+ text-shadow: none;
439
+ padding: 0;
440
+ margin: 0;
441
+ margin-top: 16px;
442
+ padding-right: 10px;
443
+ }
444
+ .lp-varation-stat-ul .cr-number, .lp-varation-stat-ul .cr-number:hover{
445
+ background: none;
446
+ border: 0;
447
+ box-shadow: none;
448
+ font-size: 14px;
449
+ font-weight: 500;
450
+ color: #555555;
451
+ text-shadow: none;
452
+ padding: 0;
453
+ margin: 0;
454
+ margin-top: 16px;
455
+ padding-right: 10px;
456
+ }
457
+ .lp-varation-stat-ul .winner-lp .cr-number{
458
+ color: #333
459
+ }
460
+ .lp-varation-stat-ul .cr-number{
461
+ text-align: center;
462
+ width: 45px;
463
+ float: right;
464
+ margin-top: 16px;
465
+ padding-right: 10px;
466
+ }
467
+ .lp-varation-stat-ul .cr-number:before{
468
+ content: "";
469
+ background: url('../../images/variation-normal.png') no-repeat;
470
+ padding: 7px 15px 3px 8px;
471
+ display: inline-block;
472
+ text-align: center;
473
+ background-position: 0px 1px;
474
+ }
475
+ .lp-varation-stat-ul .winner-lp .cr-number:before{
476
+ background-position: 0px 1px;
477
+ padding: 7px 10px 8px 10px;
478
+ background: url('../../images/variation-up.png') no-repeat;
479
+ }
480
+ .column-stats{
481
+ padding: 0
482
+ }
483
+
484
+ body .alternate, .striped>tbody>:nth-child(odd), ul.striped>:nth-child(odd) {
485
+ background-color:#ffffff !important;
486
+ }
487
+ body #the-list td {
488
+ border-bottom: 1px solid #EBEBEA;
489
+ }
490
+ /* New Variation Testing Stat Design by Ahmed Kaludi (AhmedKaludi.com) END */
491
+
492
+
trunk/assets/css/customizer-load.css ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .lp-customizer-overlay
2
+ {
3
+ position: absolute;
4
+ z-index: 999999;
5
+ background-color: #000;
6
+ opacity: 0;
7
+ background: -moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
8
+ background: -webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9)));
9
+ background: -webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
10
+ background: -o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
11
+ background: -ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
12
+ background: radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
13
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1);
14
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
15
+ filter: alpha(opacity=50);
16
+ -webkit-transition: all 0.3s ease-out;
17
+ -moz-transition: all 0.3s ease-out;
18
+ -ms-transition: all 0.3s ease-out;
19
+ -o-transition: all 0.3s ease-out;
20
+ transition: all 0.3s ease-out;
21
+ }
22
+
23
+
24
+ #template-display-options .inbound-meta-box-label {
25
+ width:100%;
26
+ }
27
+
28
+
29
+ html {
30
+ margin-top: 0px !important;
31
+ }
32
+ .live-preview-active
33
+ {
34
+ background-color: gray;
35
+ background-image: repeating-linear-gradient(45deg, transparent, transparent 35px, rgba(255,255,255,.5) 35px, rgba(255,255,255,.5) 70px);
36
+ }
37
+ .live-preview-area-box {
38
+ display:inline-block;
39
+ }
40
+ .lp-see-this {
41
+ color:#000000 !important;
42
+ }
43
+ .live-preview-active {
44
+ background: rgba(253, 253, 252, 1);
45
+ border-radius: 0px;
46
+ padding: 0px;
47
+ outline: 2px dashed rgb(255, 0, 0);
48
+ -webkit-box-shadow: 0px 0px 35px rgba(50, 50, 50, 1);
49
+ -moz-box-shadow: 0px 0px 35px rgba(50, 50, 50, 1);
50
+ box-shadow: 0px 0px 35px rgba(50, 50, 50, 1);
51
+ z-index: 99999999;
52
+ }
53
+
54
+ .small-html {
55
+ height: 200%;
56
+ border: 0;
57
+ position: absolute;
58
+ top: 0;
59
+ left: 0;
60
+ background-color: #eee;
61
+
62
+ -webkit-transform: scale(.8);
63
+ -moz-transform: scale(0.8);
64
+ -ms-transform: scale(0.8);
65
+ -o-transform: scale(0.8);
66
+ transform: scale(0.8);
67
+ -webkit-transform-origin: top left;
68
+ -moz-transform-origin: top left;
69
+ -ms-transform-origin: top left;
70
+ -o-transform-origin: top left;
71
+ transform-origin: top left;
72
+ -webkit-transition: opacity 0.4s ease;
73
+ -moz-transition: opacity 0.4s ease;
74
+ -o-transition: opacity 0.4s ease;
75
+ transition: opacity 0.4s ease;
76
+ }
trunk/assets/css/customizer.frontend.css ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ html.wp-toolbar {
2
+ padding-top: 0px;
3
+ }
4
+ body {
5
+ min-width: 400px !important;
6
+ }
7
+ #wpadminbar, #adminmenuback, #current_variation_id, #post_ID {
8
+ display: none !important;
9
+ }
10
+
11
+ #adminmenuwrap {display: none !important;}
12
+ .auto-fold #wpcontent {
13
+ margin-left: 0px;
14
+ }
15
+ .jPicker .Icon {
16
+ height: 23px;}
17
+
18
+ #lp-options-controls {
19
+ position: absolute;
20
+ top: 13px;
21
+ right: 10px;
22
+ }
23
+ #lp-frontend-options-container {
24
+ padding-left: 8px;
25
+ padding-right: 8px;
26
+ z-index: 99999999998 !important;
27
+ }
28
+ #lp-top-box {
29
+ background: #eaeaea;
30
+ width: 100%;
31
+ height: 42px;
32
+ border-bottom: rgba(206, 206, 206, 0.5);
33
+ border-width: 1px;
34
+ border-style: solid;
35
+
36
+ }
37
+ .mceToolbar.mceToolbarRow1.Enabled td {
38
+ display: inline-block !important;
39
+ }
40
+ .media-modal {
41
+ position: fixed;
42
+ top: 45px !important;}
43
+
44
+ .mceStatusbar.mceFirst.mceLast div {
45
+ display: none !important;
46
+ }
47
+ .media-modal {
48
+ width: 473px !important;
49
+ left:10px !important;
50
+ position: absolute;
51
+ }
52
+ input[type="radio"] {
53
+ margin-left: 5px;
54
+ vertical-align: middle;
55
+ }
56
+ /* #wpcontent, body {
57
+ min-width: 470px !important;
58
+ } */
59
+ .click-this {
60
+ display: none;
61
+ }
62
+ .jPicker .Grid {
63
+ display: none;
64
+ }
65
+ .jPicker .Button {
66
+ text-align: center;
67
+ padding: 0 4px;
68
+ width: 264px;
69
+ position: absolute;
70
+ border-bottom: none;
71
+ left: 0px;
72
+ bottom: 3px;
73
+ }
74
+ .jPicker .Button input {
75
+ font-size: 18px !important;
76
+ }
77
+ .jPicker .Icon span.Color, .jPicker .Icon span.Alpha {
78
+ width: 97% !important;
79
+ }
80
+ .jPicker .Title {
81
+ width: 254px;
82
+ }
83
+ .landing-page-option-td {
84
+ position: relative;
85
+ }
86
+ .media-modal-backdrop, .media-modal {
87
+ position: fixed !important;
88
+ }
89
+ .upload_image_button {
90
+ background: #f3f3f3;
91
+ background-image: -webkit-gradient(linear,left top,left bottom,from(#fefefe),to(#f4f4f4));
92
+ background-image: -webkit-linear-gradient(top,#fefefe,#f4f4f4);
93
+ background-image: -moz-linear-gradient(top,#fefefe,#f4f4f4);
94
+ background-image: -o-linear-gradient(top,#fefefe,#f4f4f4);
95
+ background-image: linear-gradient(to bottom,#fefefe,#f4f4f4);
96
+ border-color: #bbb;
97
+ color: #333;
98
+ text-shadow: 0 1px 0 #fff;
99
+ display: inline-block;
100
+ text-decoration: none;
101
+ font-size: 12px;
102
+ line-height: 23px;
103
+ height: 24px;
104
+ margin: 0;
105
+ padding: 0 10px 1px;
106
+ cursor: pointer;
107
+ border-width: 1px;
108
+ border-style: solid;
109
+ -webkit-border-radius: 3px;
110
+ -webkit-appearance: none;
111
+ border-radius: 3px;
112
+ white-space: nowrap;
113
+ -webkit-box-sizing: border-box;
114
+ -moz-box-sizing: border-box;
115
+ box-sizing: border-box;
116
+ }
117
+ #media-items {
118
+ width: 311px !important;
119
+ }
120
+ .variation-letter-top {
121
+ border-radius: 3px;
122
+ border-style: solid;
123
+ border-width: 1px;
124
+ padding: 1px;
125
+ padding-left: 4px;
126
+ padding-right: 5px;
127
+ background: #fff;
128
+ display: inline-block;
129
+ margin-right: 10px;
130
+ }
131
+ .the-title input {
132
+ width: 78%;
133
+ }
134
+ table.jPicker {
135
+ width: 445px;}
136
+
137
+ html {
138
+ background: #f5f5f5;
139
+ border-right: 1px solid rgba(0,0,0,0.2);
140
+ }
141
+ .landing-page-option-row {
142
+ padding-top: 10px;
143
+ padding-left: 3px;
144
+ padding-bottom:0px;
145
+ padding-right: 0px;
146
+ clear: both;
147
+ }
148
+ .landing-page-table-header {
149
+ font-size: 17px;
150
+ padding-bottom: 5px;
151
+ padding-left: 2px;
152
+ }
153
+ h1 {
154
+ line-height: 28px;
155
+ margin-bottom: 0px;
156
+ margin-top: 10px;
157
+ }
trunk/assets/css/customizer.media-uploader.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .media-upload-form {
2
+ margin-top: 20px;
3
+ width: 376px;
4
+ }
5
+ #media-upload #filter {
6
+ width: 376px;
7
+ }
8
+ .post_title, .image_alt, .post_excerpt, .post_content, .url, .align, .upload-flash-bypass, .max-upload-size {
9
+ display: none;
10
+ }
11
+ .media-upload-form {
12
+ width: 60% !important;
13
+ }
14
+ .savesend input.button {
15
+ background-color: #21759b;
16
+ background-image: -webkit-gradient(linear,left top,left bottom,from(#2a95c5),to(#21759b));
17
+ background-image: -webkit-linear-gradient(top,#2a95c5,#21759b);
18
+ background-image: -moz-linear-gradient(top,#2a95c5,#21759b);
19
+ background-image: -ms-linear-gradient(top,#2a95c5,#21759b);
20
+ background-image: -o-linear-gradient(top,#2a95c5,#21759b);
21
+ background-image: linear-gradient(to bottom,#2a95c5,#21759b);
22
+ border-color: #21759b;
23
+ border-bottom-color: #1e6a8d;
24
+ -webkit-box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
25
+ box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
26
+ color: #fff;
27
+ text-decoration: none;
28
+ text-shadow: 0 1px 0 rgba(0,0,0,0.1);
29
+ height: 35px;
30
+ font-size: 20px;
31
+ }
32
+ .media-upload-form.type-form.validate, #image-form {
33
+ width: 60% !important;
34
+ }
trunk/assets/css/frontend/customizer-preview.css ADDED
@@ -0,0 +1 @@
 
1
+ #variation-list {
trunk/assets/css/frontend/global-landing-page-style.css ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .wp-caption {
3
+ background: #FBFBFB;
4
+ border: 1px solid #EEE;
5
+ padding: 10px;
6
+ max-width: 100%;
7
+ }
8
+
9
+ .wp-caption img {
10
+ display: block;
11
+ margin-bottom: 5px;
12
+ }
13
+
14
+ .wp-caption-text,
15
+ .gallery-caption {
16
+ margin: 0;
17
+ font-size: 12px;
18
+ font-style: italic
19
+ }
20
+
21
+ .alignright {
22
+ float: right;
23
+ margin: 10px 0px 10px 20px;
24
+ }
25
+
26
+ .alignleft {
27
+ float: left;
28
+ margin: 10px 20px 10px 0px;
29
+ }
30
+
31
+ .aligncenter {
32
+ display: block;
33
+ margin-left: auto;
34
+ margin-right: auto;
35
+ }
36
+
37
+ .alignnone {
38
+ display: block;
39
+ margin: 10px 0px;
40
+ }
41
+
42
+ .bypostauthor {
43
+ }
trunk/assets/css/frontend/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/css/iframe-preview.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ :root:root:root {
2
+ margin-top: 0px !important;
3
+ };
trunk/assets/css/images/dropdownback.png ADDED
Binary file
trunk/assets/css/images/headerback.png ADDED
Binary file
trunk/assets/css/images/hover.png ADDED
Binary file
trunk/assets/css/images/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/css/images/linkback.png ADDED
Binary file
trunk/assets/css/images/question-light.png ADDED
Binary file
trunk/assets/css/images/tooltip.png ADDED
Binary file
trunk/assets/css/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/images/ab-retina-icons.png ADDED
Binary file
trunk/assets/images/add-on-image.png ADDED
Binary file
trunk/assets/images/cta-install.png ADDED
Binary file
trunk/assets/images/custom-setup-image.png ADDED
Binary file
trunk/assets/images/get-custom-setup.png ADDED
Binary file
trunk/assets/images/get-wordpress-templates.png ADDED
Binary file
trunk/assets/images/github-help.jpg ADDED
Binary file
trunk/assets/images/image.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ if (!function_exists('inbound_sanitize_this')) {
5
+ function inbound_sanitize_this($color) {
6
+ if (!strstr($color,'#')) {
7
+ $color = '#'. $color;
8
+ }
9
+
10
+ // 3 or 6 hex digits, or the empty string.
11
+ if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) {
12
+
13
+
14
+ return $color;
15
+ }
16
+ }
17
+ }
18
+
19
+ // file: image.php
20
+ // Dynamically Create a clear png for css background opacities
21
+ header("Content-type: image/png");
22
+
23
+ $hex_value = inbound_sanitize_this($_GET['hex']);
24
+
25
+ if (isset($_GET['trans'])) {
26
+ $trans_value = intval($_GET['trans']);
27
+ } else {
28
+ $trans_value = 50;
29
+ }
30
+
31
+ if (!function_exists('_inbound_HexToRGB')) {
32
+ // Convert Hex to RGB Value
33
+ function _inbound_HexToRGB($hex) {
34
+ $hex = preg_replace("/#/", "", $hex);
35
+ $color = array();
36
+
37
+ if (strlen($hex) == 3) {
38
+ $color['r'] = hexdec(substr($hex, 0, 1) . $r);
39
+ $color['g'] = hexdec(substr($hex, 1, 1) . $g);
40
+ $color['b'] = hexdec(substr($hex, 2, 1) . $b);
41
+ } else if (strlen($hex) == 6) {
42
+ $color['r'] = hexdec(substr($hex, 0, 2));
43
+ $color['g'] = hexdec(substr($hex, 2, 2));
44
+ $color['b'] = hexdec(substr($hex, 4, 2));
45
+ }
46
+
47
+ return $color;
48
+
49
+ }
50
+ }
51
+ $RBG_array = _inbound_HexToRGB($hex_value);
52
+
53
+ if (isset($RBG_array)) {
54
+ $red = (isset($RBG_array['r'])) ? $RBG_array['r'] : '0';
55
+ $green = (isset($RBG_array['g'])) ? $RBG_array['g'] : '0';
56
+ $blue = (isset($RBG_array['b'])) ? $RBG_array['b'] : '0';
57
+
58
+ // Set the image
59
+ $img = imagecreatetruecolor(10, 10); // 10 x 10 px
60
+ imagesavealpha($img, true);
61
+
62
+ // Fill the image with transparent color
63
+ $color = imagecolorallocatealpha($img, $red, $green, $blue, $trans_value);
64
+ imagefill($img, 0, 0, $color);
65
+
66
+ // Return the image
67
+ imagepng($img);
68
+
69
+ // Destroy image
70
+ imagedestroy($img);
71
+
72
+ }
73
+
74
+ // usage in html: <image src="path-to-file/image.php?hex=HEXCOLOR">
75
+ // Make sure to add in the HEX GET Parameters with ?hex= and ?trans= for transparency
76
+ // example: <image src="path-to-file/image.php?hex=ffffff"> will call white transparent png
trunk/assets/images/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/images/leads-install.png ADDED
Binary file
trunk/assets/images/localhost.png ADDED
Binary file
trunk/assets/images/templates-image.png ADDED
Binary file
trunk/assets/images/variation-normal.png ADDED
Binary file
trunk/assets/images/variation-up.png ADDED
Binary file
trunk/assets/js/admin/admin.global-settings.js ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function getUrlVars() {
2
+ var vars = [], hash;
3
+ var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
4
+ for (var i = 0; i < hashes.length; i++) {
5
+ hash = hashes[i].split('=');
6
+ vars.push(hash[0]);
7
+ vars[hash[0]] = hash[1];
8
+ }
9
+ return vars;
10
+ };
11
+
12
+ function getUrlVar(name) {
13
+ return getUrlVars()[name];
14
+ };
15
+
16
+ jQuery(document).ready(function ($) {
17
+
18
+ jQuery(document).ready(function() {
19
+ jQuery('.tooltip').tooltipster({
20
+ contentAsHTML: true,
21
+ interactive: true,
22
+ maxWidth: 350,
23
+ position: "right",
24
+ theme: "tooltipster-noir"
25
+ });
26
+ });
27
+
28
+ // Getting URL var by its nam
29
+ var byName = getUrlVar('tab');
30
+
31
+ // Set setting Tab
32
+ setTimeout(function () {
33
+ jQuery("#" + byName).click();
34
+ }, 300);
35
+
36
+ /* Update Setting URL */
37
+ jQuery("body").on('click', '.nav-tab', function () {
38
+ var this_id = jQuery(this).attr('id');
39
+ if (history.pushState) {
40
+ var newurl = window.location.href.replace(/tab=([^"]*)/g, 'tab=' + this_id);
41
+ var current_tab = newurl.match(/tab=([^"]*)/g);
42
+ if (typeof (current_tab) != "undefined" && current_tab != null && current_tab != "") {
43
+ var current_tab = current_tab[0].replace("tab=", "");
44
+ window.history.pushState({path: newurl}, '', newurl);
45
+ } else {
46
+ var newurl = window.location.href + '&tab=' + this_id;
47
+ window.history.pushState({path: newurl}, '', newurl);
48
+ }
49
+
50
+ }
51
+ });
52
+
53
+ setTimeout(function() {
54
+ var getoption = document.URL.split('&option=')[1];
55
+ var showoption = "#" + getoption;
56
+ jQuery(showoption).click();
57
+ }, 100);
58
+
59
+ /* Navigate tabs */
60
+ jQuery('.lp-nav-tab').live('click', function() {
61
+ var this_id = this.id.replace('tabs-','');
62
+ jQuery('.lp-tab-display').css('display','none');
63
+ jQuery('#'+this_id).css('display','block');
64
+ jQuery('.lp-nav-tab').removeClass('nav-tab-special-active');
65
+ jQuery('.lp-nav-tab').addClass('nav-tab-special-inactive');
66
+ jQuery('#tabs-'+this_id).addClass('nav-tab-special-active');
67
+ jQuery('#id-open-tab').val(this_id);
68
+ });
69
+ var form_sys = jQuery("#sys-inbound-form");
70
+ jQuery("#in-sys-info").after(form_sys);
71
+ jQuery("#sys-inbound-form").show();
72
+
73
+ });
trunk/assets/js/admin/admin.install-plugins.js ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+ /* Loads on /themes.php?page=install-inbound-plugins */
3
+ var install_status = jQuery("#the-list td.status.column-status").text();
4
+ var click_apply = "<h2 class='click-to-activate'><span>←</span>Click Apply to Install</h2>";
5
+ var activate_apply = "<h2 class='click-to-activate-bulk'><span>←</span>Click Apply to Bulk Activate Plugins</h2>";
6
+ jQuery(".alignleft.actions.bulkactions").after(click_apply);
7
+ jQuery(".alignleft.actions.bulkactions").after(activate_apply);
8
+ console.log(install_status);
9
+ jQuery('#the-list td.status.column-status').each(function(){
10
+ var installed_on = $(this).text();
11
+ if (installed_on === "Not Installed") {
12
+ $(this).parent().find("input[type=checkbox]").attr("checked", "on");
13
+ if ( $(".click-to-activate-bulk").is(":hidden") ) {
14
+ jQuery('.click-to-activate').show();
15
+ jQuery(".alignleft.actions.bulkactions select").val('tgmpa-bulk-install');
16
+ }
17
+
18
+ }
19
+ if (installed_on === "Installed But Not Activated") {
20
+ $(this).parent().find("input[type=checkbox]").attr("checked", "on");
21
+ if ( $(".click-to-activate").is(":hidden") ) {
22
+ jQuery('.click-to-activate-bulk').show();
23
+ jQuery(".alignleft.actions.bulkactions select").val('tgmpa-bulk-activate');
24
+ }
25
+
26
+ }
27
+ });
28
+ jQuery("#cb-select-all-1, #cb-select-all-2").attr("checked", "on");
29
+
30
+ });
trunk/assets/js/admin/admin.landing-page-list.js ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+ // Code for landing page list view
3
+ var cats = jQuery("#landing_page_category option").length;
4
+ if ( cats === 0 ){
5
+ jQuery("#landing_page_category").hide();
6
+ }
7
+
8
+ jQuery('.lp-letter').each(function(){
9
+ var draft = jQuery(this).text();
10
+ if ( draft === "" ){
11
+ jQuery(this).parent().parent().hide();
12
+ }
13
+ });
14
+
15
+ /* List tour */
16
+ var tourbutton = '<a class="" id="lp-tour" style="font-size:13px;">Need help? Take the tour</a>';
17
+ jQuery(tourbutton).appendTo(".wrap h1");
18
+ jQuery("body").on('click', '#lp-tour', function () {
19
+ jQuery(this).hide();
20
+ var tour = jQuery("#lp-tour-style").length;
21
+ if ( tour === 0 ) {
22
+ jQuery('head').append("<link rel='stylesheet' id='lp-tour-style' href='/wp-content/plugins/landing-pages/assets/css/admin-tour.css' type='text/css' /><script type='text/javascript' src='/wp-content/plugins/landing-pages/assets/js/admin/tour/tour.post-list.js'></script><script type='text/javascript' src='/wp-content/plugins/landing-pages/assets/js/admin/intro.js'></script>");
23
+ }
24
+ setTimeout(function() {
25
+ introJs().start(); // start tour
26
+ }, 300);
27
+
28
+ });
29
+ /*jQuery(".lp-varation-stat-ul").each(function(){
30
+ var length = jQuery(this).find("li").length;
31
+ if ( length < 3 ){
32
+ jQuery(this).find("li").first().css("padding-top", "18px");
33
+ }
34
+ });
35
+ */
36
+ jQuery("body").on('mouseenter', 'tr.type-landing-page', function () {
37
+ jQuery(this).find(".no-stats-yet").show();
38
+ });
39
+ jQuery("body").on('mouseleave', 'tr.type-landing-page', function () {
40
+ jQuery(this).find(".no-stats-yet").hide();
41
+ });
42
+ jQuery(".variation-winner-is").each(function(){
43
+ var target = jQuery(this).text();
44
+ jQuery("." + target).addClass("winner-lp").attr("data-lp", "Current Winner");
45
+ });
46
+
47
+ var hidestats = "<span id='hide-stats'>(Hide Stats)</span><span class='show-stats show-stats-top'>Show Stats</span>";
48
+ jQuery("#stats").append(hidestats);
49
+
50
+ jQuery("body").on('click', '#hide-stats', function () {
51
+ jQuery(".lp-varation-stat-ul").each(function(){
52
+ jQuery(this).hide();
53
+ });
54
+ jQuery(".show-stats").show();
55
+ jQuery("#hide-stats").hide();
56
+ });
57
+
58
+ jQuery("body").on('click', '.show-stats-top', function () {
59
+ jQuery(".lp-varation-stat-ul").each(function(){
60
+ jQuery(this).show();
61
+ });
62
+ jQuery(".show-stats").hide();
63
+ jQuery("#hide-stats").show();
64
+ });
65
+
66
+ jQuery("body").on('click', '.show-stats', function () {
67
+ jQuery(this).hide();
68
+ jQuery(this).parent().find(".lp-varation-stat-ul").show();
69
+ });
70
+
71
+ jQuery("body").on("click", ".lp-pop-close", function(event) {
72
+ jQuery(this).parent().parent().parent().hide();
73
+ });
74
+
75
+ jQuery("body").on("click", ".lp-pop-preview a", function(event) {
76
+ jQuery(this).parent().parent().parent().parent().hide();
77
+ });
78
+
79
+ // Fix Thickbox width/hieght
80
+ jQuery(function($) {
81
+ tb_position = function() {
82
+ var tbWindow = $('#TB_window');
83
+ var width = $(window).width();
84
+ var H = $(window).height();
85
+ var W = ( 1720 < width ) ? 1720 : width;
86
+
87
+ if ( tbWindow.size() ) {
88
+ tbWindow.width( W - 50 ).height( H - 45 );
89
+ $('#TB_iframeContent').width( W - 50 ).height( H - 75 );
90
+ tbWindow.css({'margin-left': '-' + parseInt((( W - 50 ) / 2),10) + 'px'});
91
+ if ( typeof document.body.style.maxWidth != 'undefined' )
92
+ tbWindow.css({'top':'40px','margin-top':'0'});
93
+ //$('#TB_title').css({'background-color':'#fff','color':'#cfcfcf'});
94
+ };
95
+
96
+ return $('a.thickbox').each( function() {
97
+ var href = $(this).attr('href');
98
+ if ( ! href ) return;
99
+ href = href.replace(/&width=[0-9]+/g, '');
100
+ href = href.replace(/&height=[0-9]+/g, '');
101
+ $(this).attr( 'href', href + '&width=' + ( W - 80 ) + '&height=' + ( H - 85 ) );
102
+ });
103
+
104
+ };
105
+
106
+ jQuery('a.thickbox').click(function(){
107
+ if ( typeof tinyMCE != 'undefined' && tinyMCE.activeEditor ) {
108
+ tinyMCE.get('content').focus();
109
+ tinyMCE.activeEditor.windowManager.bookmark = tinyMCE.activeEditor.selection.getBookmark('simple');
110
+ }
111
+
112
+ });
113
+
114
+ $(window).resize( function() { tb_position() } );
115
+ });
116
+
117
+ });
trunk/assets/js/admin/admin.metaboxes.js ADDED
@@ -0,0 +1 @@
 
0
  jQuery( '.upload_image_button' ).on( 'click', function() {
1
  tb_show('test', 'media-upload.php?type=image&TB_iframe=1');
2
  var field_id = jQuery(this).data('field-id');
3
  window.send_to_editor = function( html ) {
4
  imgurl = jQuery( 'img', html ).attr( 'src' );
5
  jQuery( '#' + field_id ).val(imgurl);
6
  tb_remove();
7
  }
8
  return false;
9
  });
1
+
2
  jQuery( '.upload_image_button' ).on( 'click', function() {
3
  tb_show('test', 'media-upload.php?type=image&TB_iframe=1');
4
  var field_id = jQuery(this).data('field-id');
5
  window.send_to_editor = function( html ) {
6
  imgurl = jQuery( 'img', html ).attr( 'src' );
7
  jQuery( '#' + field_id ).val(imgurl);
8
  tb_remove();
9
  }
10
  return false;
11
  });
trunk/assets/js/admin/admin.post-edit-ab-testing.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function ($) {
2
+ var variations = new Array();
3
+ var has_variations = 0;
4
+ variations = variation.variations;
5
+
6
+
7
+ var replace_slash = '\\';
8
+
9
+ //variation.content_area = variation.content_area.replace(/\n/g, replace_slash);
10
+ //variation.content_area = variation.content_area.replace(/\r\n/g, "<br/>").replace(/\r/g, "<br/>").replace(/\n/g, "<br/>");
11
+
12
+ jQuery("#wp-content-editor-container textarea").val(variation.content_area);
13
+ jQuery("#content_ifr").contents().find("body").html(variation.content_area);
14
+
15
+
16
+ var html;
17
+ if (variation.vid>0&&variation.new_variation!=1)
18
+ {
19
+ html = '<a class="add-new-h2" href="?post='+variation.pid+'&action=edit&lp-variation-id='+variation.vid+'&ab-action=delete-variation">Delete This Variation</a>';
20
+ jQuery('.wrap h2:first').append(html);
21
+ }
22
+
23
+ if (variation.vid>0)
24
+ {
25
+ jQuery('#delete-action').remove();
26
+ }
27
+
28
+ //alter preview and customizer buttons based on open variation
29
+ var preview_href = jQuery('#post-preview').attr('href');
30
+ jQuery('#post-preview').attr('href',preview_href+'?lp-variation-id='+variation.vid);
31
+
32
+ //setup timer and and navigation change events
33
+ var input_change = jQuery("#switch-lp").text();
34
+ jQuery('.wrap').on('keyup change', jQuery('form').find('input[type=text],textarea,select'), function() {
35
+ jQuery("#switch-lp").text("1");
36
+ console.log("change");
37
+ });
38
+
39
+ /*setTimeout(function () {
40
+ input_change = 1;
41
+ }, 15000);
42
+ */
43
+ jQuery('.wrap').on('click', '.nav-tab-wrapper a', function(e) {
44
+ var this_id = this.id.replace('tabs-','');
45
+ if (input_change==1)
46
+ {
47
+ var answer = confirm('Do you want to change variations without saving the changes made here?');
48
+ if (answer){
49
+ // do the default action
50
+ } else {
51
+ e.preventDefault();
52
+ }
53
+ }
54
+
55
+ jQuery('.lp-tab-display').css('display','none');
56
+ jQuery('#'+this_id).css('display','block');
57
+ jQuery('.lp-nav-tab').removeClass('nav-tab-special-active');
58
+ jQuery('.lp-nav-tab').addClass('nav-tab-special-inactive');
59
+ jQuery('#tabs-'+this_id).addClass('nav-tab-special-active');
60
+ jQuery('#id-open-tab').val(this_id);
61
+
62
+ });
63
+
64
+ });
trunk/assets/js/admin/admin.post-edit.js ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function ($) {
2
+
3
+ var cookies = (typeof (jQuery.cookie) != "undefined" ? true : false); // Check for JQuery Cookie
4
+ function cookie_notice() {
5
+ alert('Oh no! jQuery Cookie not loaded. Your Server Might be Blocking this. Some functionality may be impaired');
6
+ }
7
+
8
+ jQuery('.button.button-small').each(function () {
9
+ var $this = jQuery(this);
10
+ var text = $this.text();
11
+ if (text === "Get Shortlink") {
12
+ $this.hide();
13
+ }
14
+ });
15
+
16
+ var width = jQuery("#lp-thumbnail-sidebar-preview").width();
17
+ jQuery('#zoomer').zoomer({width: width, height: 225, zoom: 0.27, tranformOrigin: '0px 40px 1px',});
18
+
19
+ // Filter Styling
20
+ jQuery('#template-filter li').first().addClass('button-primary');
21
+ // filter items when filter link is clicked
22
+ jQuery('#template-filter a').click(function () {
23
+ var selector = jQuery(this).attr('data-filter');
24
+ jQuery("ul#template-filter li").removeClass('button-primary');
25
+ jQuery(this).parent().addClass('button-primary');
26
+ $(".template-item-boxes").fadeOut(500);
27
+ setTimeout(function () {
28
+ $(selector).fadeIn(500);
29
+ }, 500);
30
+
31
+ return false;
32
+ });
33
+
34
+
35
+ jQuery("body").on('click', '#content-tmce, .wp-switch-editor.switch-tmce', function () {
36
+ if (cookies) {
37
+ $.cookie("lp-edit-view-choice", "editor", {path: '/', expires: 7});
38
+ } else {
39
+ cookie_notice();
40
+ }
41
+ });
42
+
43
+ jQuery("body").on('click', '#content-html, .wp-switch-editor.switch-html', function () {
44
+ if (cookies) {
45
+ $.cookie("lp-edit-view-choice", "html", {path: '/', expires: 7});
46
+ } else {
47
+ cookie_notice();
48
+ }
49
+ });
50
+
51
+ if (cookies) {
52
+ var which_editor = $.cookie("lp-edit-view-choice");
53
+ } else {
54
+ var which_editor = 'editor';
55
+ cookie_notice();
56
+ }
57
+ if (which_editor === null) {
58
+ setTimeout(function () {
59
+ //jQuery("#content-tmce").click();
60
+ //jQuery(".wp-switch-editor.switch-tmce").click();
61
+ }, 1000);
62
+
63
+ }
64
+
65
+ if (which_editor === 'editor') {
66
+ setTimeout(function () {
67
+
68
+ jQuery('.switch-tmce').each(function () {
69
+ jQuery(this).click();
70
+ });
71
+
72
+ }, 1000);
73
+ }
74
+
75
+ /* Tour Start JS */
76
+ var tourbutton = '<a class="" id="lp-tour" style="font-size:13px;position: absolute;bottom: 5px;">Need help? Take the tour</a>';
77
+ jQuery(tourbutton).appendTo("h2:eq(0)");
78
+ jQuery("body").on('click', '#lp-tour', function () {
79
+ jQuery(this).hide();
80
+ var tour = jQuery("#lp-tour-style").length;
81
+ if (tour === 0) {
82
+ jQuery('head').append("<link rel='stylesheet' id='lp-tour-style' href='/wp-content/plugins/landing-pages/assets/css/admin-tour.css' type='text/css' /><script type='text/javascript' src='/wp-content/plugins/landing-pages/assets/js/admin/tour/tour.post-edit.js'></script><script type='text/javascript' src='/wp-content/plugins/landing-pages/assets/js/admin/intro.js'></script>");
83
+ }
84
+ setTimeout(function () {
85
+ introJs().start(); // start tour
86
+ }, 300);
87
+
88
+ });
89
+
90
+ var current_a_tab = jQuery("#tabs-0").hasClass('nav-tab-special-active');
91
+ if (current_a_tab === true) {
92
+ var url_norm = jQuery("#view-post-btn a").attr('href');
93
+ var new_url = url_norm + "?lp-variation-id=0";
94
+ jQuery("#view-post-btn a").attr('href', new_url);
95
+ }
96
+
97
+ /* Fix inactivate theme display */
98
+ jQuery("#template-box a").live('click', function () {
99
+
100
+ setTimeout(function () {
101
+ jQuery('#TB_window iframe').contents().find("#customize-controls").hide();
102
+ jQuery('#TB_window iframe').contents().find(".wp-full-overlay.expanded").css("margin-left", "0px");
103
+ }, 600);
104
+
105
+ });
106
+
107
+ /* Fix Split testing iframe size */
108
+ jQuery("#lp-metabox-splittesting a.thickbox, #leads-table-container-inside .column-details a").live('click', function () {
109
+ jQuery('#TB_iframeContent, #TB_window').hide();
110
+ setTimeout(function () {
111
+
112
+ jQuery('#TB_iframeContent, #TB_window').width(640).height(800).css("margin-left", "0px").css("left", "35%");
113
+ jQuery('#TB_iframeContent, #TB_window').show();
114
+ }, 600);
115
+ });
116
+
117
+ /* Load meta box in correct position on page load */
118
+ var current_template = jQuery("input#lp_select_template ").val();
119
+ var current_template_meta = "#lp_" + current_template + "_custom_meta_box";
120
+ jQuery(current_template_meta).removeClass("postbox").appendTo("#template-display-options").addClass("Old-Template");
121
+ var current_template_h3 = "#lp_" + current_template + "_custom_meta_box h3";
122
+
123
+ /* jQuery(current_template_h3).css("background","#f8f8f8"); */
124
+ jQuery(current_template_meta + ' .handlediv').hide();
125
+ jQuery(current_template_meta + ' .hndle').css('cursor', 'default');
126
+
127
+
128
+ /* Fix Thickbox width/hieght */
129
+ jQuery(function ($) {
130
+ tb_position = function () {
131
+ var tbWindow = $('#TB_window');
132
+ var width = $(window).width();
133
+ var H = $(window).height();
134
+ var W = ( 1720 < width ) ? 1720 : width;
135
+
136
+ if (tbWindow.size()) {
137
+ tbWindow.width(W - 50).height(H - 45);
138
+ $('#TB_iframeContent').width(W - 50).height(H - 75);
139
+ tbWindow.css({'margin-left': '-' + parseInt((( W - 50 ) / 2), 10) + 'px'});
140
+ if (typeof document.body.style.maxWidth != 'undefined') {
141
+ tbWindow.css({'top': '40px', 'margin-top': '0'});
142
+ }
143
+
144
+ }
145
+ ;
146
+
147
+ return $('a.thickbox').each(function () {
148
+ var href = $(this).attr('href');
149
+ if (!href) return;
150
+ href = href.replace(/&width=[0-9]+/g, '');
151
+ href = href.replace(/&height=[0-9]+/g, '');
152
+ $(this).attr('href', href + '&width=' + ( W - 80 ) + '&height=' + ( H - 85 ));
153
+
154
+ });
155
+
156
+ };
157
+
158
+ jQuery('a.thickbox').click(function () {
159
+ if (typeof tinyMCE != 'undefined' && tinyMCE.activeEditor) {
160
+ tinyMCE.get('content').focus();
161
+ tinyMCE.activeEditor.windowManager.bookmark = tinyMCE.activeEditor.selection.getBookmark('simple');
162
+ }
163
+
164
+ });
165
+
166
+ $(window).resize(function () {
167
+ tb_position()
168
+ });
169
+ });
170
+
171
+ /* Colorpicker fix */
172
+ jQuery('.jpicker').one('mouseenter', function () {
173
+ jQuery(this).jPicker({
174
+ window: // used to define the position of the popup window only useful in binded mode
175
+ {
176
+ title: null, // any title for the jPicker window itself - displays "Drag Markers To Pick A Color" if left null
177
+ position: {
178
+ x: 'screenCenter', // acceptable values "left", "center", "right", "screenCenter", or relative px value
179
+ y: 'center', // acceptable values "top", "bottom", "center", or relative px value
180
+ },
181
+ expandable: false, // default to large static picker - set to true to make an expandable picker (small icon with popup) - set
182
+ // automatically when binded to input element
183
+ liveUpdate: true, // set false if you want the user to click "OK" before the binded input box updates values (always "true"
184
+ // for expandable picker)
185
+ alphaSupport: false, // set to true to enable alpha picking
186
+ alphaPrecision: 0, // set decimal precision for alpha percentage display - hex codes do not map directly to percentage
187
+ // integers - range 0-2
188
+ updateInputColor: true // set to false to prevent binded input colors from changing
189
+ }
190
+ },
191
+ function (color, context) {
192
+ var all = color.val('all');
193
+ // alert('Color chosen - hex: ' + (all && '#' + all.hex || 'none') + ' - alpha: ' + (all && all.a + '%' || 'none'));
194
+ //jQuery(this).attr('rel', all.hex);
195
+
196
+ jQuery(this).parent().find(".lp-success-message").remove();
197
+ //jQuery(this).parent().find(".new-save-lp").show();
198
+ //jQuery(this).parent().find(".new-save-lp-frontend").show();
199
+ //jQuery(this).attr('value', all.hex);
200
+ });
201
+ });
202
+
203
+
204
+ if (jQuery(".lp-template-selector-container").css("display") == "none") {
205
+ jQuery(".currently_selected").hide();
206
+ } else {
207
+ jQuery(".currently_selected").show();
208
+ }
209
+
210
+ /* Add current title of template to selector */
211
+ var selected_template = jQuery('#lp_select_template').val();
212
+ var selected_template_id = "#" + selected_template;
213
+ var clean_template_name = selected_template.replace(/-/g, ' ');
214
+
215
+ function capitaliseFirstLetter(string) {
216
+ return string.charAt(0).toUpperCase() + string.slice(1);
217
+ }
218
+
219
+ var currentlabel = jQuery(".currently_selected");
220
+ jQuery(selected_template_id).parent().addClass("default_template_highlight").prepend(currentlabel);
221
+
222
+ jQuery('#lp-change-template-button').live('click', function () {
223
+ jQuery('.acf-postbox').remove();
224
+ jQuery(".wrap").fadeOut(500, function () {
225
+
226
+ jQuery(".lp-template-selector-container").fadeIn(500, function () {
227
+ jQuery(".currently_selected").show();
228
+ jQuery('#lp-cancel-selection').show();
229
+ });
230
+
231
+ });
232
+ });
233
+
234
+
235
+ jQuery('.background-style').on('change', function () {
236
+ var input = jQuery(".background-style option:selected").val();
237
+ if (input == 'color') {
238
+ jQuery('.background-color').show();
239
+ jQuery('.background-image').hide();
240
+ jQuery('.background_tip').hide();
241
+ }
242
+ else if (input == 'default') {
243
+ jQuery('.background-color').hide();
244
+ jQuery('.background-image').hide();
245
+ jQuery('.background_tip').hide();
246
+ }
247
+ else if (input == 'custom') {
248
+ var obj = jQuery(".background-style .lp_tooltip");
249
+ obj.removeClass("lp_tooltip").addClass("background_tip").html("Use the custom css block at the bottom of this page to set up custom CSS rules");
250
+ jQuery('.background_tip').show();
251
+ }
252
+ else {
253
+ jQuery('.background-color').hide();
254
+ jQuery('.background-image').show();
255
+ jQuery('.background_tip').hide();
256
+ }
257
+
258
+ });
259
+
260
+ /* Check BG options on page load */
261
+ jQuery(document).ready(function () {
262
+ var input = jQuery(".background-style option:selected").val();
263
+ if (input == 'color') {
264
+ jQuery('.background-color').show();
265
+ jQuery('.background-image').hide();
266
+ jQuery('.background_tip').hide();
267
+ }
268
+ else if (input == 'default') {
269
+ jQuery('.background-color').hide();
270
+ jQuery('.background-image').hide();
271
+ jQuery('.background_tip').hide();
272
+ }
273
+ else if (input == 'custom') {
274
+ var obj = jQuery(".background-style .lp_tooltip");
275
+ obj.removeClass("lp_tooltip").addClass("background_tip").html("Use the custom css block at the bottom of this page to set up custom CSS rules");
276
+ jQuery('.background_tip').show();
277
+ }
278
+ else {
279
+ jQuery('.background-color').hide();
280
+ jQuery('.background-image').show();
281
+ jQuery('.background_tip').hide();
282
+ }
283
+ });
284
+
285
+ /* Stylize lead's wp-list-table */
286
+ var cnt = $("#leads-table-container").contents();
287
+ $("#lp_conversion_log_metabox").replaceWith(cnt);
288
+
289
+ /* remove inputs from wp-list-table */
290
+ jQuery('#leads-table-container-inside input').each(function () {
291
+ jQuery(this).remove();
292
+ });
293
+
294
+ var post_status = jQuery("#original_post_status").val();
295
+
296
+ if (post_status === "draft") {
297
+ jQuery(".new-save-lp-frontend").on("click", function (event) {
298
+ event.preventDefault();
299
+ alert("Must publish this page before you can use the visual editor!");
300
+ });
301
+ var subbox = jQuery("#submitdiv");
302
+ jQuery("#lp_ab_display_stats_metabox").before(subbox)
303
+ } else {
304
+ jQuery("#publish").val("Update All");
305
+ }
306
+
307
+
308
+ });
trunk/assets/js/admin/admin.post-new.js ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function ($) {
2
+
3
+ jQuery('#lp-template-selector-container').css('display','block');
4
+
5
+ //remove inputs from wp-list-table
6
+ jQuery('#leads-table-container-inside input').each(function(){
7
+ jQuery(this).remove();
8
+ });
9
+
10
+ jQuery("#submitdiv").siblings().hide();
11
+
12
+ jQuery("#title-prompt-text").text("Name Your New Landing Page");
13
+ jQuery("#title").attr("required","required");
14
+
15
+ var titledescription = jQuery("<span id='descriptor'>This will be the administrative title your landing page, the main headline is created in the next step</span>");
16
+ jQuery(titledescription).appendTo("#titlewrap");
17
+
18
+ jQuery("#save-action input").addClass("button-primary button-large").css("margin-bottom", "10px").attr("value", "Create Landing Page");
19
+
20
+ var sidebar = jQuery("#side-sortables");
21
+ jQuery(sidebar).appendTo("#titlediv");
22
+
23
+ var tempdiv = jQuery("<div id='templates' class='postbox'><h3 class='hndle'>Current Template: <span id='ctemp'></span></h3><div id='lp_the_image'><span id='timage'><img src='' id='c_temp'></span></div><div id='template_current'></div></div>");
24
+
25
+ jQuery(tempdiv).appendTo("#titlewrap");
26
+ var changebutton = jQuery("#lp_template_change");
27
+
28
+ jQuery(changebutton).appendTo("#templates");
29
+ jQuery("#lp_template_change a").removeClass("button-primary").addClass("button");
30
+
31
+ // New Sidebar
32
+ jQuery("#postbox-container-1").html("<div class='postbox'><center><h3>Download Additional Templates</h3><a target='_blank' href='http://www.inboundnow.com/market/?show=landing-pages'><img src='"+lp_post_new_ui.LANDINGPAGES_URLPATH+"assets/images/get-wordpress-templates.png'></a><a target='_blank' href='http://www.inboundnow.com/market/?show=landing-pages' class='button new-lp-button button-primary button-large'>Download Landing Page Templates</a></center></div><div class='postbox'><center><h3>Need Custom Template Design?</h3><a target='_blank' href='http://www.inboundnow.com/contact'><img src='"+lp_post_new_ui.LANDINGPAGES_URLPATH+"assets/images/get-custom-setup.png'></a><a target='_blank' href='http://docs.inboundnow.com/guide/default-wp-themes/' class='button new-lp-button button-primary button-large'>Get Custom Template Setup</a></center></div>");
33
+
34
+ jQuery('.lp_select_template').click(function(){
35
+ jQuery(".mceIframeContainer iframe#content_ifr").css("height", "100%");
36
+ jQuery("#wp-content-editor-container .mceStatusbar").css("display", "none");
37
+ });
38
+
39
+ jQuery('.lp_select_template').click(function(){
40
+
41
+ var template = jQuery(this).attr('id');
42
+ var selected_template_id = "#" + template;
43
+ var label = jQuery(this).attr('label');
44
+ var template_image = "#" + template + " .template-thumbnail";
45
+ var template_img_obj = jQuery(template_image).attr("src");
46
+
47
+ jQuery("#ctemp").text(label);
48
+ jQuery("#template_current").html('<input type="hidden" name="lp-selected-template" value="'+template+'"><input type="hidden" value="1" name="lp_post_new">');
49
+ jQuery("#timage #c_temp").attr("src", template_img_obj);
50
+ jQuery("#submitdiv .hndle span").text("Create Landing Page");
51
+
52
+ });
53
+
54
+ jQuery('#lp-change-template-button').live('click', function () {
55
+ jQuery(".wrap").fadeOut(500,function(){
56
+
57
+ jQuery(".lp-template-selector-container").fadeIn(500, function(){
58
+ jQuery('#lp-cancel-selection').show();
59
+ });
60
+ jQuery("#template-filter li a").first().click();
61
+ });
62
+ });
63
+
64
+ // filter items when filter link is clicked
65
+ jQuery('#template-filter a').click(function(){
66
+ var selector = jQuery(this).attr('data-filter');
67
+ jQuery("ul#template-filter li").removeClass('button-primary');
68
+ jQuery(this).parent().addClass('button-primary');
69
+ $(".template-item-boxes").fadeOut(500);
70
+ setTimeout(function() {
71
+ $(selector).fadeIn(500);
72
+ }, 500);
73
+
74
+ return false;
75
+ });
76
+
77
+ jQuery('.lp_select_template').click(function(){
78
+ var template = jQuery(this).attr('id');
79
+ var label = jQuery(this).attr('label');
80
+ jQuery(".lp-template-selector-container").fadeOut(500,function(){
81
+ jQuery(".wrap").fadeIn(500, function(){
82
+ });
83
+ });
84
+
85
+ jQuery('#lp_metabox_select_template h3').html('Current Active Template: '+label);
86
+ jQuery('#lp_select_template').val(template);
87
+ //alert(template);
88
+ //alert(label);
89
+ });
90
+
91
+
92
+ jQuery("#template-box a").live('click', function () {
93
+
94
+ setTimeout(function() {
95
+ jQuery('#TB_window iframe').contents().find("#customize-controls").hide();
96
+ jQuery('#TB_window iframe').contents().find(".wp-full-overlay.expanded").css("margin-left", "0px");
97
+ }, 1200);
98
+
99
+ });
100
+
101
+ // Fix Thickbox width
102
+ jQuery(function($) {
103
+ tb_position = function() {
104
+ var tbWindow = $('#TB_window');
105
+ var width = $(window).width();
106
+ var H = $(window).height();
107
+ var W = ( 1720 < width ) ? 1720 : width;
108
+
109
+ if ( tbWindow.size() ) {
110
+ tbWindow.width( W - 50 ).height( H - 45 );
111
+ $('#TB_iframeContent').width( W - 50 ).height( H - 75 );
112
+ tbWindow.css({'margin-left': '-' + parseInt((( W - 50 ) / 2),10) + 'px'});
113
+ if ( typeof document.body.style.maxWidth != 'undefined' )
114
+ tbWindow.css({'top':'40px','margin-top':'0'});
115
+ //$('#TB_title').css({'background-color':'#fff','color':'#cfcfcf'});
116
+ };
117
+
118
+ return $('a.thickbox').each( function() {
119
+ var href = $(this).attr('href');
120
+ if ( ! href ) return;
121
+ href = href.replace(/&width=[0-9]+/g, '');
122
+ href = href.replace(/&height=[0-9]+/g, '');
123
+ $(this).attr( 'href', href + '&width=' + ( W - 80 ) + '&height=' + ( H - 85 ) );
124
+ });
125
+ };
126
+
127
+ jQuery('a.thickbox').click(function(){
128
+ if ( typeof tinyMCE != 'undefined' && tinyMCE.activeEditor ) {
129
+ tinyMCE.get('content').focus();
130
+ tinyMCE.activeEditor.windowManager.bookmark = tinyMCE.activeEditor.selection.getBookmark('simple');
131
+ }
132
+
133
+ });
134
+
135
+ $(window).resize( function() { tb_position() } );
136
+ });
137
+
138
+ var nonce_val = lp_post_new_ui.wp_landing_page_meta_nonce; // NEED CORRECT NONCE
139
+
140
+ var nonce_html = '<input type="hidden" value="74910e3045" name="wp-landing-page-meta-nonce">';
141
+
142
+ jQuery('form').prepend(nonce_html);
143
+
144
+ });
trunk/assets/js/admin/admin.post.js ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function ($) {
2
+ jQuery('body').on( 'click' , '.lp_select_template' , function() {
3
+ var this_template = jQuery(this);
4
+ swal({
5
+ title: sweetalert.title,
6
+ text: sweetalert.text,
7
+ type: "info",
8
+ showCancelButton: true,
9
+ confirmButtonColor: "#2ea2cc",
10
+ confirmButtonText: sweetalert.confirmButtonText,
11
+ closeOnConfirm: false
12
+ }, function () {
13
+ swal({
14
+ title: sweetalert.waitTitle,
15
+ text: sweetalert.waitText,
16
+ imageUrl: sweetalert.waitImage
17
+ });
18
+
19
+ var template = this_template.attr('id');
20
+ jQuery('#lp_select_template').val(template);
21
+
22
+ /* save post */
23
+ jQuery('#publish').click();
24
+ });
25
+ });
26
+
27
+
28
+ jQuery('#lp-cancel-selection').click(function(){
29
+ jQuery(".lp-template-selector-container").fadeOut(500,function(){
30
+ jQuery(".wrap").fadeIn(500, function(){
31
+ });
32
+ });
33
+
34
+ });
35
+ });
trunk/assets/js/admin/admin.templates-upload.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+
3
+ jQuery('.subsubsub li a').live('click', function () {
4
+
5
+ var id = jQuery(this).attr('id');
6
+ //alert (id);
7
+ if (id == 'menu_upload') {
8
+ jQuery('.templates_search').hide();
9
+ jQuery('.templates_search').removeClass('current');
10
+
11
+ jQuery('.templates_upload').show();
12
+ jQuery('.templates_upload').addClass('current');
13
+ }
14
+ else if (id == 'menu_search')
15
+ {
16
+ jQuery('.templates_upload').hide();
17
+ jQuery('.templates_upload').removeClass('current');
18
+
19
+ jQuery('.templates_search').show();
20
+ jQuery('.templates_search').addClass('current');
21
+ }
22
+
23
+ });
24
+
25
+ });
trunk/assets/js/admin/admin.templates.js ADDED
@@ -0,0 +1 @@
 
0
 
1
+
2
 
trunk/assets/js/admin/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/js/admin/intro.js ADDED
@@ -0,0 +1,758 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Intro.js v0.4.0
3
+ * https://github.com/usablica/intro.js
4
+ * MIT licensed
5
+ *
6
+ * Copyright (C) 2013 usabli.ca - A weekend project by Afshin Mehrabani (@afshinmeh)
7
+ */
8
+
9
+ (function (root, factory) {
10
+ if (typeof exports === 'object') {
11
+ // CommonJS
12
+ factory(exports);
13
+ } else if (typeof define === 'function' && define.amd) {
14
+ // AMD. Register as an anonymous module.
15
+ define(['exports'], factory);
16
+ } else {
17
+ // Browser globals
18
+ factory(root);
19
+ }
20
+ } (this, function (exports) {
21
+ //Default config/variables
22
+ var VERSION = '0.4.0';
23
+
24
+ /**
25
+ * IntroJs main class
26
+ *
27
+ * @class IntroJs
28
+ */
29
+ function IntroJs(obj) {
30
+ this._targetElement = obj;
31
+
32
+ this._options = {
33
+ nextLabel: 'Next &rarr;',
34
+ prevLabel: '&larr; Back',
35
+ skipLabel: 'Skip',
36
+ doneLabel: 'Done',
37
+ tooltipPosition: 'bottom',
38
+ exitOnEsc: true,
39
+ exitOnOverlayClick: true,
40
+ showStepNumbers: true
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Initiate a new introduction/guide from an element in the page
46
+ *
47
+ * @api private
48
+ * @method _introForElement
49
+ * @param {Object} targetElm
50
+ * @returns {Boolean} Success or not?
51
+ */
52
+ function _introForElement(targetElm) {
53
+ var introItems = [],
54
+ self = this;
55
+
56
+ if (this._options.steps) {
57
+ //use steps passed programmatically
58
+ var allIntroSteps = [];
59
+
60
+ for (var i = 0, stepsLength = this._options.steps.length; i < stepsLength; i++) {
61
+ var currentItem = this._options.steps[i];
62
+ //set the step
63
+ currentItem.step = i + 1;
64
+ //grab the element with given selector from the page
65
+ currentItem.element = document.querySelector(currentItem.element);
66
+ introItems.push(currentItem);
67
+ }
68
+
69
+ } else {
70
+ //use steps from data-* annotations
71
+
72
+ var allIntroSteps = targetElm.querySelectorAll('*[data-intro]');
73
+ //if there's no element to intro
74
+ if (allIntroSteps.length < 1) {
75
+ return false;
76
+ }
77
+
78
+ for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
79
+ var currentElement = allIntroSteps[i];
80
+ introItems.push({
81
+ element: currentElement,
82
+ intro: currentElement.getAttribute('data-intro'),
83
+ step: parseInt(currentElement.getAttribute('data-step'), 10),
84
+ position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
85
+ });
86
+ }
87
+ }
88
+
89
+ //Ok, sort all items with given steps
90
+ introItems.sort(function (a, b) {
91
+ return a.step - b.step;
92
+ });
93
+
94
+ //set it to the introJs object
95
+ self._introItems = introItems;
96
+
97
+ //add overlay layer to the page
98
+ if(_addOverlayLayer.call(self, targetElm)) {
99
+ //then, start the show
100
+ _nextStep.call(self);
101
+
102
+ var skipButton = targetElm.querySelector('.introjs-skipbutton'),
103
+ nextStepButton = targetElm.querySelector('.introjs-nextbutton');
104
+
105
+ self._onKeyDown = function(e) {
106
+ if (e.keyCode === 27 && self._options.exitOnEsc == true) {
107
+ //escape key pressed, exit the intro
108
+ _exitIntro.call(self, targetElm);
109
+ //check if any callback is defined
110
+ if (self._introExitCallback != undefined) {
111
+ self._introExitCallback.call(self);
112
+ }
113
+ } else if(e.keyCode === 37) {
114
+ //left arrow
115
+ _previousStep.call(self);
116
+ } else if (e.keyCode === 39 || e.keyCode === 13) {
117
+ //right arrow or enter
118
+ _nextStep.call(self);
119
+ //prevent default behaviour on hitting Enter, to prevent steps being skipped in some browsers
120
+ if(e.preventDefault) {
121
+ e.preventDefault();
122
+ } else {
123
+ e.returnValue = false;
124
+ }
125
+ }
126
+ };
127
+
128
+ self._onResize = function(e) {
129
+ _setHelperLayerPosition.call(self, document.querySelector('.introjs-helperLayer'));
130
+ };
131
+
132
+ if (window.addEventListener) {
133
+ window.addEventListener('keydown', self._onKeyDown, true);
134
+ //for window resize
135
+ window.addEventListener("resize", self._onResize, true);
136
+ } else if (document.attachEvent) { //IE
137
+ document.attachEvent('onkeydown', self._onKeyDown);
138
+ //for window resize
139
+ document.attachEvent("onresize", self._onResize);
140
+ }
141
+ }
142
+ return false;
143
+ }
144
+
145
+ /**
146
+ * Go to specific step of introduction
147
+ *
148
+ * @api private
149
+ * @method _goToStep
150
+ */
151
+ function _goToStep(step) {
152
+ //because steps starts with zero
153
+ this._currentStep = step - 2;
154
+ if(typeof (this._introItems) !== 'undefined') {
155
+ _nextStep.call(this);
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Go to next step on intro
161
+ *
162
+ * @api private
163
+ * @method _nextStep
164
+ */
165
+ function _nextStep() {
166
+ if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
167
+ this._introBeforeChangeCallback.call(this, this._targetElement);
168
+ }
169
+
170
+ if (typeof (this._currentStep) === 'undefined') {
171
+ this._currentStep = 0;
172
+ } else {
173
+ ++this._currentStep;
174
+ }
175
+
176
+ if((this._introItems.length) <= this._currentStep) {
177
+ //end of the intro
178
+ //check if any callback is defined
179
+ if (typeof (this._introCompleteCallback) === 'function') {
180
+ this._introCompleteCallback.call(this);
181
+ }
182
+ _exitIntro.call(this, this._targetElement);
183
+ return;
184
+ }
185
+
186
+ _showElement.call(this, this._introItems[this._currentStep]);
187
+ }
188
+
189
+ /**
190
+ * Go to previous step on intro
191
+ *
192
+ * @api private
193
+ * @method _nextStep
194
+ */
195
+ function _previousStep() {
196
+ if (this._currentStep === 0) {
197
+ return false;
198
+ }
199
+
200
+ if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
201
+ this._introBeforeChangeCallback.call(this, this._targetElement);
202
+ }
203
+
204
+ _showElement.call(this, this._introItems[--this._currentStep]);
205
+ }
206
+
207
+ /**
208
+ * Exit from intro
209
+ *
210
+ * @api private
211
+ * @method _exitIntro
212
+ * @param {Object} targetElement
213
+ */
214
+ function _exitIntro(targetElement) {
215
+ //remove overlay layer from the page
216
+ var overlayLayer = targetElement.querySelector('.introjs-overlay');
217
+ //for fade-out animation
218
+ overlayLayer.style.opacity = 0;
219
+ setTimeout(function () {
220
+ if (overlayLayer.parentNode) {
221
+ overlayLayer.parentNode.removeChild(overlayLayer);
222
+ }
223
+ }, 500);
224
+ //remove all helper layers
225
+ var helperLayer = targetElement.querySelector('.introjs-helperLayer');
226
+ if (helperLayer) {
227
+ helperLayer.parentNode.removeChild(helperLayer);
228
+ }
229
+ //remove `introjs-showElement` class from the element
230
+ var showElement = document.querySelector('.introjs-showElement');
231
+ if (showElement) {
232
+ showElement.className = showElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, ''); // This is a manual trim.
233
+ }
234
+
235
+ //remove `introjs-fixParent` class from the elements
236
+ var fixParents = document.querySelectorAll('.introjs-fixParent');
237
+ if (fixParents && fixParents.length > 0) {
238
+ for (var i = fixParents.length - 1; i >= 0; i--) {
239
+ fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
240
+ };
241
+ }
242
+ //clean listeners
243
+ if (window.removeEventListener) {
244
+ window.removeEventListener('keydown', this._onKeyDown, true);
245
+ } else if (document.detachEvent) { //IE
246
+ document.detachEvent('onkeydown', this._onKeyDown);
247
+ }
248
+ //set the step to zero
249
+ this._currentStep = undefined;
250
+ }
251
+
252
+ /**
253
+ * Render tooltip box in the page
254
+ *
255
+ * @api private
256
+ * @method _placeTooltip
257
+ * @param {Object} targetElement
258
+ * @param {Object} tooltipLayer
259
+ * @param {Object} arrowLayer
260
+ */
261
+ function _placeTooltip(targetElement, tooltipLayer, arrowLayer) {
262
+ //reset the old style
263
+ tooltipLayer.style.top = null;
264
+ tooltipLayer.style.right = null;
265
+ tooltipLayer.style.bottom = null;
266
+ tooltipLayer.style.left = null;
267
+
268
+ //prevent error when `this._currentStep` is undefined
269
+ if(!this._introItems[this._currentStep]) return;
270
+
271
+ var currentTooltipPosition = this._introItems[this._currentStep].position;
272
+ switch (currentTooltipPosition) {
273
+ case 'top':
274
+ tooltipLayer.style.left = '15px';
275
+ tooltipLayer.style.top = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
276
+ arrowLayer.className = 'introjs-arrow bottom';
277
+ break;
278
+ case 'right':
279
+ tooltipLayer.style.left = (_getOffset(targetElement).width + 20) + 'px';
280
+ arrowLayer.className = 'introjs-arrow left';
281
+ break;
282
+ case 'left':
283
+ tooltipLayer.style.top = '15px';
284
+ tooltipLayer.style.right = (_getOffset(targetElement).width + 20) + 'px';
285
+ arrowLayer.className = 'introjs-arrow right';
286
+ break;
287
+ case 'bottom':
288
+ // Bottom going to follow the default behavior
289
+ default:
290
+ tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
291
+ arrowLayer.className = 'introjs-arrow top';
292
+ break;
293
+ }
294
+ }
295
+
296
+ /**
297
+ * Update the position of the helper layer on the screen
298
+ *
299
+ * @api private
300
+ * @method _setHelperLayerPosition
301
+ * @param {Object} helperLayer
302
+ */
303
+ function _setHelperLayerPosition(helperLayer) {
304
+ if(helperLayer) {
305
+ //prevent error when `this._currentStep` in undefined
306
+ if(!this._introItems[this._currentStep]) return;
307
+
308
+ var elementPosition = _getOffset(this._introItems[this._currentStep].element);
309
+ //set new position to helper layer
310
+ helperLayer.setAttribute('style', 'width: ' + (elementPosition.width + 10) + 'px; ' +
311
+ 'height:' + (elementPosition.height + 10) + 'px; ' +
312
+ 'top:' + (elementPosition.top - 5) + 'px;' +
313
+ 'left: ' + (elementPosition.left - 5) + 'px;');
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Show an element on the page
319
+ *
320
+ * @api private
321
+ * @method _showElement
322
+ * @param {Object} targetElement
323
+ */
324
+ function _showElement(targetElement) {
325
+
326
+ if (typeof (this._introChangeCallback) !== 'undefined') {
327
+ this._introChangeCallback.call(this, targetElement.element);
328
+ }
329
+
330
+ var self = this,
331
+ oldHelperLayer = document.querySelector('.introjs-helperLayer'),
332
+ elementPosition = _getOffset(targetElement.element);
333
+
334
+ if(oldHelperLayer != null) {
335
+ var oldHelperNumberLayer = oldHelperLayer.querySelector('.introjs-helperNumberLayer'),
336
+ oldtooltipLayer = oldHelperLayer.querySelector('.introjs-tooltiptext'),
337
+ oldArrowLayer = oldHelperLayer.querySelector('.introjs-arrow'),
338
+ oldtooltipContainer = oldHelperLayer.querySelector('.introjs-tooltip'),
339
+ skipTooltipButton = oldHelperLayer.querySelector('.introjs-skipbutton'),
340
+ prevTooltipButton = oldHelperLayer.querySelector('.introjs-prevbutton'),
341
+ nextTooltipButton = oldHelperLayer.querySelector('.introjs-nextbutton');
342
+
343
+ //hide the tooltip
344
+ oldtooltipContainer.style.opacity = 0;
345
+
346
+ //set new position to helper layer
347
+ _setHelperLayerPosition.call(self, oldHelperLayer);
348
+
349
+ //remove `introjs-fixParent` class from the elements
350
+ var fixParents = document.querySelectorAll('.introjs-fixParent');
351
+ if (fixParents && fixParents.length > 0) {
352
+ for (var i = fixParents.length - 1; i >= 0; i--) {
353
+ fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
354
+ };
355
+ }
356
+
357
+ //remove old classes
358
+ var oldShowElement = document.querySelector('.introjs-showElement');
359
+ oldShowElement.className = oldShowElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, '');
360
+ //we should wait until the CSS3 transition is competed (it's 0.3 sec) to prevent incorrect `height` and `width` calculation
361
+ if (self._lastShowElementTimer) {
362
+ clearTimeout(self._lastShowElementTimer);
363
+ }
364
+ self._lastShowElementTimer = setTimeout(function() {
365
+ //set current step to the label
366
+ if(oldHelperNumberLayer != null) {
367
+ oldHelperNumberLayer.innerHTML = targetElement.step;
368
+ }
369
+ //set current tooltip text
370
+ oldtooltipLayer.innerHTML = targetElement.intro;
371
+ //set the tooltip position
372
+ _placeTooltip.call(self, targetElement.element, oldtooltipContainer, oldArrowLayer);
373
+ //show the tooltip
374
+ oldtooltipContainer.style.opacity = 1;
375
+ }, 350);
376
+
377
+ } else {
378
+ var helperLayer = document.createElement('div'),
379
+ arrowLayer = document.createElement('div'),
380
+ tooltipLayer = document.createElement('div');
381
+
382
+ helperLayer.className = 'introjs-helperLayer';
383
+
384
+ //set new position to helper layer
385
+ _setHelperLayerPosition.call(self, helperLayer);
386
+
387
+ //add helper layer to target element
388
+ this._targetElement.appendChild(helperLayer);
389
+
390
+ arrowLayer.className = 'introjs-arrow';
391
+ tooltipLayer.className = 'introjs-tooltip';
392
+
393
+
394
+ tooltipLayer.innerHTML = '<div class="introjs-tooltiptext">' +
395
+ targetElement.intro +
396
+ '</div><div class="introjs-tooltipbuttons"></div>';
397
+
398
+ //add helper layer number
399
+ if (this._options.showStepNumbers) {
400
+ var helperNumberLayer = document.createElement('span');
401
+ helperNumberLayer.className = 'introjs-helperNumberLayer';
402
+ helperNumberLayer.innerHTML = targetElement.step;
403
+ helperLayer.appendChild(helperNumberLayer);
404
+ }
405
+ tooltipLayer.appendChild(arrowLayer);
406
+ helperLayer.appendChild(tooltipLayer);
407
+
408
+ //next button
409
+ var nextTooltipButton = document.createElement('a');
410
+
411
+ nextTooltipButton.onclick = function() {
412
+ if(self._introItems.length - 1 != self._currentStep) {
413
+ _nextStep.call(self);
414
+ }
415
+ };
416
+
417
+ nextTooltipButton.href = 'javascript:void(0);';
418
+ nextTooltipButton.innerHTML = this._options.nextLabel;
419
+
420
+ //previous button
421
+ var prevTooltipButton = document.createElement('a');
422
+
423
+ prevTooltipButton.onclick = function() {
424
+ if(self._currentStep != 0) {
425
+ _previousStep.call(self);
426
+ }
427
+ };
428
+
429
+ prevTooltipButton.href = 'javascript:void(0);';
430
+ prevTooltipButton.innerHTML = this._options.prevLabel;
431
+
432
+ //skip button
433
+ var skipTooltipButton = document.createElement('a');
434
+ skipTooltipButton.className = 'introjs-button introjs-skipbutton';
435
+ skipTooltipButton.href = 'javascript:void(0);';
436
+ skipTooltipButton.innerHTML = this._options.skipLabel;
437
+
438
+ skipTooltipButton.onclick = function() {
439
+ if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') {
440
+ self._introCompleteCallback.call(self);
441
+ }
442
+
443
+ if (self._introItems.length - 1 != self._currentStep && typeof (self._introExitCallback) === 'function') {
444
+ self._introExitCallback.call(self);
445
+ }
446
+
447
+ _exitIntro.call(self, self._targetElement);
448
+ };
449
+
450
+ var tooltipButtonsLayer = tooltipLayer.querySelector('.introjs-tooltipbuttons');
451
+ tooltipButtonsLayer.appendChild(skipTooltipButton);
452
+ tooltipButtonsLayer.appendChild(prevTooltipButton);
453
+ tooltipButtonsLayer.appendChild(nextTooltipButton);
454
+
455
+ //set proper position
456
+ _placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer);
457
+ }
458
+
459
+ if (this._currentStep == 0) {
460
+ prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-disabled';
461
+ nextTooltipButton.className = 'introjs-button introjs-nextbutton';
462
+ skipTooltipButton.innerHTML = this._options.skipLabel;
463
+ } else if (this._introItems.length - 1 == this._currentStep) {
464
+ skipTooltipButton.innerHTML = this._options.doneLabel;
465
+ prevTooltipButton.className = 'introjs-button introjs-prevbutton';
466
+ nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-disabled';
467
+ } else {
468
+ prevTooltipButton.className = 'introjs-button introjs-prevbutton';
469
+ nextTooltipButton.className = 'introjs-button introjs-nextbutton';
470
+ skipTooltipButton.innerHTML = this._options.skipLabel;
471
+ }
472
+
473
+ //Set focus on "next" button, so that hitting Enter always moves you onto the next step
474
+ nextTooltipButton.focus();
475
+
476
+ //add target element position style
477
+ targetElement.element.className += ' introjs-showElement';
478
+
479
+ var currentElementPosition = _getPropValue(targetElement.element, 'position');
480
+ if (currentElementPosition !== 'absolute' &&
481
+ currentElementPosition !== 'relative') {
482
+ //change to new intro item
483
+ targetElement.element.className += ' introjs-relativePosition';
484
+ }
485
+
486
+ var parentElm = targetElement.element.parentNode;
487
+ while(parentElm != null) {
488
+ if(parentElm.tagName.toLowerCase() === 'body') break;
489
+
490
+ var zIndex = _getPropValue(parentElm, 'z-index');
491
+ if(/[0-9]+/.test(zIndex)) {
492
+ parentElm.className += ' introjs-fixParent';
493
+ }
494
+ parentElm = parentElm.parentNode;
495
+ }
496
+
497
+ if (!_elementInViewport(targetElement.element)) {
498
+ var rect = targetElement.element.getBoundingClientRect(),
499
+ top = rect.bottom - (rect.bottom - rect.top),
500
+ bottom = rect.bottom - _getWinSize().height;
501
+
502
+ // Scroll up
503
+ if (top < 0) {
504
+ window.scrollBy(0, top - 30); // 30px padding from edge to look nice
505
+
506
+ // Scroll down
507
+ } else {
508
+ window.scrollBy(0, bottom + 100); // 70px + 30px padding from edge to look nice
509
+ }
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Get an element CSS property on the page
515
+ * Thanks to JavaScript Kit: http://www.javascriptkit.com/dhtmltutors/dhtmlcascade4.shtml
516
+ *
517
+ * @api private
518
+ * @method _getPropValue
519
+ * @param {Object} element
520
+ * @param {String} propName
521
+ * @returns Element's property value
522
+ */
523
+ function _getPropValue (element, propName) {
524
+ var propValue = '';
525
+ if (element.currentStyle) { //IE
526
+ propValue = element.currentStyle[propName];
527
+ } else if (document.defaultView && document.defaultView.getComputedStyle) { //Others
528
+ propValue = document.defaultView.getComputedStyle(element, null).getPropertyValue(propName);
529
+ }
530
+
531
+ //Prevent exception in IE
532
+ if(propValue.toLowerCase) {
533
+ return propValue.toLowerCase();
534
+ } else {
535
+ return propValue;
536
+ }
537
+ }
538
+
539
+ /**
540
+ * Provides a cross-browser way to get the screen dimensions
541
+ * via: http://stackoverflow.com/questions/5864467/internet-explorer-innerheight
542
+ *
543
+ * @api private
544
+ * @method _getWinSize
545
+ * @returns {Object} width and height attributes
546
+ */
547
+ function _getWinSize() {
548
+ if (window.innerWidth != undefined) {
549
+ return { width: window.innerWidth, height: window.innerHeight };
550
+ } else {
551
+ var D = document.documentElement;
552
+ return { width: D.clientWidth, height: D.clientHeight };
553
+ }
554
+ }
555
+
556
+ /**
557
+ * Add overlay layer to the page
558
+ * http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
559
+ *
560
+ * @api private
561
+ * @method _elementInViewport
562
+ * @param {Object} el
563
+ */
564
+ function _elementInViewport(el) {
565
+ var rect = el.getBoundingClientRect();
566
+
567
+ return (
568
+ rect.top >= 0 &&
569
+ rect.left >= 0 &&
570
+ (rect.bottom+80) <= window.innerHeight && // add 80 to get the text right
571
+ rect.right <= window.innerWidth
572
+ );
573
+ }
574
+
575
+ /**
576
+ * Add overlay layer to the page
577
+ *
578
+ * @api private
579
+ * @method _addOverlayLayer
580
+ * @param {Object} targetElm
581
+ */
582
+ function _addOverlayLayer(targetElm) {
583
+ var overlayLayer = document.createElement('div'),
584
+ styleText = '',
585
+ self = this;
586
+
587
+ //set css class name
588
+ overlayLayer.className = 'introjs-overlay';
589
+
590
+ //check if the target element is body, we should calculate the size of overlay layer in a better way
591
+ if (targetElm.tagName.toLowerCase() === 'body') {
592
+ styleText += 'top: 0;bottom: 0; left: 0;right: 0;position: fixed;';
593
+ overlayLayer.setAttribute('style', styleText);
594
+ } else {
595
+ //set overlay layer position
596
+ var elementPosition = _getOffset(targetElm);
597
+ if(elementPosition) {
598
+ styleText += 'width: ' + elementPosition.width + 'px; height:' + elementPosition.height + 'px; top:' + elementPosition.top + 'px;left: ' + elementPosition.left + 'px;';
599
+ overlayLayer.setAttribute('style', styleText);
600
+ }
601
+ }
602
+
603
+ targetElm.appendChild(overlayLayer);
604
+
605
+ overlayLayer.onclick = function() {
606
+ if(self._options.exitOnOverlayClick == true) {
607
+ _exitIntro.call(self, targetElm);
608
+ }
609
+ //check if any callback is defined
610
+ if (self._introExitCallback != undefined) {
611
+ self._introExitCallback.call(self);
612
+ }
613
+ };
614
+
615
+ setTimeout(function() {
616
+ styleText += 'opacity: .8;';
617
+ overlayLayer.setAttribute('style', styleText);
618
+ }, 10);
619
+ return true;
620
+ }
621
+
622
+ /**
623
+ * Get an element position on the page
624
+ * Thanks to `meouw`: http://stackoverflow.com/a/442474/375966
625
+ *
626
+ * @api private
627
+ * @method _getOffset
628
+ * @param {Object} element
629
+ * @returns Element's position info
630
+ */
631
+ function _getOffset(element) {
632
+ var elementPosition = {};
633
+
634
+ //set width
635
+ elementPosition.width = element.offsetWidth;
636
+
637
+ //set height
638
+ elementPosition.height = element.offsetHeight;
639
+
640
+ //calculate element top and left
641
+ var _x = 0;
642
+ var _y = 0;
643
+ while(element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) {
644
+ _x += element.offsetLeft;
645
+ _y += element.offsetTop;
646
+ element = element.offsetParent;
647
+ }
648
+ //set top
649
+ elementPosition.top = _y;
650
+ //set left
651
+ elementPosition.left = _x;
652
+
653
+ return elementPosition;
654
+ }
655
+
656
+ /**
657
+ * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
658
+ * via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically
659
+ *
660
+ * @param obj1
661
+ * @param obj2
662
+ * @returns obj3 a new object based on obj1 and obj2
663
+ */
664
+ function _mergeOptions(obj1,obj2) {
665
+ var obj3 = {};
666
+ for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
667
+ for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
668
+ return obj3;
669
+ }
670
+
671
+ var introJs = function (targetElm) {
672
+ if (typeof (targetElm) === 'object') {
673
+ //Ok, create a new instance
674
+ return new IntroJs(targetElm);
675
+
676
+ } else if (typeof (targetElm) === 'string') {
677
+ //select the target element with query selector
678
+ var targetElement = document.querySelector(targetElm);
679
+
680
+ if (targetElement) {
681
+ return new IntroJs(targetElement);
682
+ } else {
683
+ throw new Error('There is no element with given selector.');
684
+ }
685
+ } else {
686
+ return new IntroJs(document.body);
687
+ }
688
+ };
689
+
690
+ /**
691
+ * Current IntroJs version
692
+ *
693
+ * @property version
694
+ * @type String
695
+ */
696
+ introJs.version = VERSION;
697
+
698
+ //Prototype
699
+ introJs.fn = IntroJs.prototype = {
700
+ clone: function () {
701
+ return new IntroJs(this);
702
+ },
703
+ setOption: function(option, value) {
704
+ this._options[option] = value;
705
+ return this;
706
+ },
707
+ setOptions: function(options) {
708
+ this._options = _mergeOptions(this._options, options);
709
+ return this;
710
+ },
711
+ start: function () {
712
+ _introForElement.call(this, this._targetElement);
713
+ return this;
714
+ },
715
+ goToStep: function(step) {
716
+ _goToStep.call(this, step);
717
+ return this;
718
+ },
719
+ exit: function() {
720
+ _exitIntro.call(this, this._targetElement);
721
+ },
722
+ onbeforechange: function(providedCallback) {
723
+ if (typeof (providedCallback) === 'function') {
724
+ this._introBeforeChangeCallback = providedCallback;
725
+ } else {
726
+ throw new Error('Provided callback for onbeforechange was not a function');
727
+ }
728
+ return this;
729
+ },
730
+ onchange: function(providedCallback) {
731
+ if (typeof (providedCallback) === 'function') {
732
+ this._introChangeCallback = providedCallback;
733
+ } else {
734
+ throw new Error('Provided callback for onchange was not a function.');
735
+ }
736
+ return this;
737
+ },
738
+ oncomplete: function(providedCallback) {
739
+ if (typeof (providedCallback) === 'function') {
740
+ this._introCompleteCallback = providedCallback;
741
+ } else {
742
+ throw new Error('Provided callback for oncomplete was not a function.');
743
+ }
744
+ return this;
745
+ },
746
+ onexit: function(providedCallback) {
747
+ if (typeof (providedCallback) === 'function') {
748
+ this._introExitCallback = providedCallback;
749
+ } else {
750
+ throw new Error('Provided callback for onexit was not a function.');
751
+ }
752
+ return this;
753
+ }
754
+ };
755
+
756
+ exports.introJs = introJs;
757
+ return introJs;
758
+ }));
trunk/assets/js/admin/tour/tour.post-edit.js ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ // Post Edit Screen Tour
2
+ jQuery("#titlewrap").attr({"data-step": "1", "data-intro": 'This is the adminstrative title of your landing. <br>Visitors will not be able to see this. To edit this, simply click on the text.'});
3
+ jQuery(".nav-tab-wrapper").attr({"data-step": "2", "data-intro": 'This controls the A/B testing functionality of the page.<br>You can toggle back and forth between variations or click the add new variation to start an A/B test.'});
4
+ jQuery(".new-save-lp-frontend").attr({"data-step": "3", "data-intro": 'This lauches the frontend editor that will allow you to see live previews of your landing page variations and edit the settings on the same screen!'});
5
+ jQuery(".lp-notes").attr({"data-step": "4", "data-intro": 'Add notes to each of your A/B test variations to keep track of what you are testing.'});
6
+ jQuery("#main-title-area").attr({"data-step": "5", "data-intro": 'This is the main headline area of your landing page. Make sure your headlines are catchy and have a clear value proposition'});
7
+ jQuery("#content_InboundShortcodesButton_action").attr({"data-step": "6", "data-intro": '<p>This is the inbound shortcode tool. You can use it to <strong>build forms</strong> and do a number of other cool things!</p>'});
8
+ jQuery("#lp_ab_display_stats_metabox").attr({"data-step": "7", "data-intro": '<p>This is the main stats box for your landing page variations. Here you will find all of your page views, conversions, and conversion rate numbers.</p><p>A/B Variation controls are also available here.</p><p><strong>Pause:</strong> Paused the current variation from a/b testing</p><p><strong>Edit:</strong> Jump to edit screen of selected variation</p><p><strong>Preview:</strong> Pop open preview window</p><p><strong>Clone:</strong> Clones exact copy of landing page in a new variation</p><p><strong>Delete:</strong> Deletes the variation from landing page</p>'});
9
+ jQuery("#lp_metabox_select_template").attr({"data-step": "8", "data-intro": 'These are the main options that control the currently selected template.'});
trunk/assets/js/admin/tour/tour.post-list.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ // Post Edit Screen Tour
2
+ jQuery(".thumbnail-lander.column-thumbnail-lander:eq(0)").attr({"data-step": "1", "data-intro": 'This is a quick screenshot of your landing page.<br><br> Click on it to see the live version in a popup window here.<br><br> You can preview your a/b variations directly from this view.'});
3
+ jQuery(".post-title.page-title.column-title:eq(0)").attr({"data-step": "2", "data-intro": '<p>This is the admin title of the landing page. This isn\'t visible to visitors</p><p>You can delete, clone, or clears all of the page stats from here.</p><p><strong>Trash:</strong> Deletes this landing page and places it in the trash</p><p><strong>Edit:</strong> Jump to edit screen of this landing page</p><p><strong>Preview:</strong> Pop open preview window</p><p><strong>Clone:</strong> Clones exact copy of landing page. This includes all current variations.</p><p><strong>Clear Stats:</strong> This will clear all stats for each variation. This cannot be undone.</p>'});
4
+ jQuery(".stats.column-stats:eq(0)").attr({"data-step": "3", "data-intro": '<p>These are the current stats of your landing page variations.</p><p>Green boxes mean the variation is winning!</p>'});
5
+ jQuery("#impressions").attr({"data-step": "4", "data-intro": '<p>This column shows the total number of page views the landing page has. This include all current A/B testing variations.</p>'});
6
+ jQuery("#actions").attr({"data-step": "5", "data-intro": '<p>This column shows the total number of conversions the landing page has. This include all current A/B testing variations.</p>'});
7
+ jQuery("#cr").attr({"data-step": "6", "data-intro": '<p>This column shows the total aggregate conversion rate of the landing page. This include all current A/B testing variations.</p>'});
8
+ jQuery(".add-new-h2").attr({"data-step": "7", "data-intro": '<p>Thats all folks! Go ahead and create a new landing page and get started!</p>'});
trunk/assets/js/ajax.clearstats.js ADDED
@@ -0,0 +1 @@
 
0
  jQuery('.clear_stats').on('click', function () {
1
  // define the bulk edit row
2
  var post_id = this.id.replace('lp_clear_', '');
3
  var status = 0;
4
  if (confirm('Are you sure you want to delete the ALL of stats for this landing page? (There is no undo) Alternatively you can clear stats per version.')) {
5
  jQuery.ajax({
6
  type: 'POST',
7
  url: ajaxurl,
8
  context: this,
9
  data: {
10
  action: 'lp_clear_stats_action',
11
  j_rules: status,
12
  page_id: post_id
13
  },
14
  success: function (data) {
15
  var self = this;
16
  //alert(data);
17
  // jQuery('.lp-form').unbind('submit').submit();
18
  jQuery(self).hide();
19
  jQuery(self).parent().parent().parent().parent().find(".lp-impress-num, .lp-con-num").text("0");
20
  jQuery(self).parent().parent().parent().parent().find(".cr-number").addClass("cr-empty-0").text("0%");
21
  //alert("Changes Saved! Refresh the page to see your changes");
22
  },
23
  error: function (MLHttpRequest, textStatus, errorThrown) {
24
  alert("Ajax not enabled");
25
  }
26
  });
27
  return false;
28
  }
29
  });
30
  jQuery('body').on('click', '.lp-delete-var-stats', function () {
31
  var post_id = jQuery(this).attr("rel");
32
  var variation_id = jQuery(this).attr('data-vid');
33
  var variation_letter = jQuery(this).attr('data-letter');
34
  var selector = '#lp-variation-' + variation_letter;
35
  //console.log(selector);
36
  if (confirm('Are you sure you want to delete stats for variation ' + variation_letter + "?")) {
37
  jQuery.ajax({
38
  type: 'POST',
39
  url: ajaxurl,
40
  context: this,
41
  data: {
42
  action: 'lp_clear_stats_single',
43
  variation: variation_id,
44
  page_id: post_id
45
  },
46
  success: function (data) {
47
  var self = this;
48
  jQuery(self).text("Stats Removed!").css("color", "green").removeClass("lp-delete-var-stats").addClass('lp-clear-success');
49
  jQuery(selector).find(".stat-span-impressions, .stat-span-conversions").text("0");
50
  jQuery(selector).find(".stat-span-conversion_rate").addClass("cr-empty-0").text("0%");
51
  },
52
  error: function (MLHttpRequest, textStatus, errorThrown) {
53
  alert("Ajax not enabled");
54
  }
55
  });
56
  return false;
57
  }
58
  });
1
+ jQuery(document).ready(function ($) {
2
  jQuery('.clear_stats').on('click', function () {
3
  // define the bulk edit row
4
  var post_id = this.id.replace('lp_clear_', '');
5
  var status = 0;
6
  if (confirm('Are you sure you want to delete the ALL of stats for this landing page? (There is no undo) Alternatively you can clear stats per version.')) {
7
  jQuery.ajax({
8
  type: 'POST',
9
  url: ajaxurl,
10
  context: this,
11
  data: {
12
  action: 'lp_clear_stats_action',
13
  j_rules: status,
14
  page_id: post_id
15
  },
16
  success: function (data) {
17
  var self = this;
18
  //alert(data);
19
  // jQuery('.lp-form').unbind('submit').submit();
20
  jQuery(self).hide();
21
  jQuery(self).parent().parent().parent().parent().find(".lp-impress-num, .lp-con-num").text("0");
22
  jQuery(self).parent().parent().parent().parent().find(".cr-number").addClass("cr-empty-0").text("0%");
23
  //alert("Changes Saved! Refresh the page to see your changes");
24
  },
25
  error: function (MLHttpRequest, textStatus, errorThrown) {
26
  alert("Ajax not enabled");
27
  }
28
  });
29
  return false;
30
  }
31
  });
32
  jQuery('body').on('click', '.lp-delete-var-stats', function () {
33
  var post_id = jQuery(this).attr("rel");
34
  var variation_id = jQuery(this).attr('data-vid');
35
  var variation_letter = jQuery(this).attr('data-letter');
36
  var selector = '#lp-variation-' + variation_letter;
37
  //console.log(selector);
38
  if (confirm('Are you sure you want to delete stats for variation ' + variation_letter + "?")) {
39
  jQuery.ajax({
40
  type: 'POST',
41
  url: ajaxurl,
42
  context: this,
43
  data: {
44
  action: 'lp_clear_stats_single',
45
  variation: variation_id,
46
  page_id: post_id
47
  },
48
  success: function (data) {
49
  var self = this;
50
  jQuery(self).text("Stats Removed!").css("color", "green").removeClass("lp-delete-var-stats").addClass('lp-clear-success');
51
  jQuery(selector).find(".stat-span-impressions, .stat-span-conversions").text("0");
52
  jQuery(selector).find(".stat-span-conversion_rate").addClass("cr-empty-0").text("0%");
53
  },
54
  error: function (MLHttpRequest, textStatus, errorThrown) {
55
  alert("Ajax not enabled");
56
  }
57
  });
58
  return false;
59
  }
60
  });
trunk/assets/js/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/js/jquery.bindfirst.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery.fn.bindFirst = function(name, fn) {
2
+ // bind as you normally would
3
+ // don't want to miss out on any jQuery magic
4
+ this.on(name, fn);
5
+
6
+ // Thanks to a comment by @Martin, adding support for
7
+ // namespaced events too.
8
+ this.each(function() {
9
+ var handlers = jQuery._data(this, 'events')[name.split('.')[0]];
10
+ // take out the handler we just inserted from the end
11
+ var handler = handlers.pop();
12
+ // move it at the beginning
13
+ handlers.splice(0, 0, handler);
14
+ });
15
+ };
trunk/assets/js/jquery.cookie.js ADDED
@@ -0,0 +1 @@
 
1
+ /*!
trunk/assets/js/jquery.easing.min.js ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
3
+ *
4
+ * Uses the built in easing capabilities added In jQuery 1.1
5
+ * to offer multiple easing options
6
+ *
7
+ * TERMS OF USE - EASING EQUATIONS
8
+ *
9
+ * Open source under the BSD License.
10
+ *
11
+ * Copyright © 2001 Robert Penner
12
+ * All rights reserved.
13
+ *
14
+ * TERMS OF USE - jQuery Easing
15
+ *
16
+ * Open source under the BSD License.
17
+ *
18
+ * Copyright © 2008 George McGinley Smith
19
+ * All rights reserved.
20
+ *
21
+ * Redistribution and use in source and binary forms, with or without modification,
22
+ * are permitted provided that the following conditions are met:
23
+ *
24
+ * Redistributions of source code must retain the above copyright notice, this list of
25
+ * conditions and the following disclaimer.
26
+ * Redistributions in binary form must reproduce the above copyright notice, this list
27
+ * of conditions and the following disclaimer in the documentation and/or other materials
28
+ * provided with the distribution.
29
+ *
30
+ * Neither the name of the author nor the names of contributors may be used to endorse
31
+ * or promote products derived from this software without specific prior written permission.
32
+ *
33
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
34
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
35
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
36
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
39
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
42
+ *
43
+ */
44
+ jQuery.easing.jswing=jQuery.easing.swing;jQuery.extend(jQuery.easing,{def:"easeOutQuad",swing:function(e,f,a,h,g){return jQuery.easing[jQuery.easing.def](e,f,a,h,g)},easeInQuad:function(e,f,a,h,g){return h*(f/=g)*f+a},easeOutQuad:function(e,f,a,h,g){return -h*(f/=g)*(f-2)+a},easeInOutQuad:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f+a}return -h/2*((--f)*(f-2)-1)+a},easeInCubic:function(e,f,a,h,g){return h*(f/=g)*f*f+a},easeOutCubic:function(e,f,a,h,g){return h*((f=f/g-1)*f*f+1)+a},easeInOutCubic:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f+a}return h/2*((f-=2)*f*f+2)+a},easeInQuart:function(e,f,a,h,g){return h*(f/=g)*f*f*f+a},easeOutQuart:function(e,f,a,h,g){return -h*((f=f/g-1)*f*f*f-1)+a},easeInOutQuart:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f+a}return -h/2*((f-=2)*f*f*f-2)+a},easeInQuint:function(e,f,a,h,g){return h*(f/=g)*f*f*f*f+a},easeOutQuint:function(e,f,a,h,g){return h*((f=f/g-1)*f*f*f*f+1)+a},easeInOutQuint:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f*f+a}return h/2*((f-=2)*f*f*f*f+2)+a},easeInSine:function(e,f,a,h,g){return -h*Math.cos(f/g*(Math.PI/2))+h+a},easeOutSine:function(e,f,a,h,g){return h*Math.sin(f/g*(Math.PI/2))+a},easeInOutSine:function(e,f,a,h,g){return -h/2*(Math.cos(Math.PI*f/g)-1)+a},easeInExpo:function(e,f,a,h,g){return(f==0)?a:h*Math.pow(2,10*(f/g-1))+a},easeOutExpo:function(e,f,a,h,g){return(f==g)?a+h:h*(-Math.pow(2,-10*f/g)+1)+a},easeInOutExpo:function(e,f,a,h,g){if(f==0){return a}if(f==g){return a+h}if((f/=g/2)<1){return h/2*Math.pow(2,10*(f-1))+a}return h/2*(-Math.pow(2,-10*--f)+2)+a},easeInCirc:function(e,f,a,h,g){return -h*(Math.sqrt(1-(f/=g)*f)-1)+a},easeOutCirc:function(e,f,a,h,g){return h*Math.sqrt(1-(f=f/g-1)*f)+a},easeInOutCirc:function(e,f,a,h,g){if((f/=g/2)<1){return -h/2*(Math.sqrt(1-f*f)-1)+a}return h/2*(Math.sqrt(1-(f-=2)*f)+1)+a},easeInElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}return -(g*Math.pow(2,10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j))+e},easeOutElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}return g*Math.pow(2,-10*h)*Math.sin((h*k-i)*(2*Math.PI)/j)+l+e},easeInOutElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k/2)==2){return e+l}if(!j){j=k*(0.3*1.5)}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}if(h<1){return -0.5*(g*Math.pow(2,10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j))+e}return g*Math.pow(2,-10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j)*0.5+l+e},easeInBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}return i*(f/=h)*f*((g+1)*f-g)+a},easeOutBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}return i*((f=f/h-1)*f*((g+1)*f+g)+1)+a},easeInOutBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}if((f/=h/2)<1){return i/2*(f*f*(((g*=(1.525))+1)*f-g))+a}return i/2*((f-=2)*f*(((g*=(1.525))+1)*f+g)+2)+a},easeInBounce:function(e,f,a,h,g){return h-jQuery.easing.easeOutBounce(e,g-f,0,h,g)+a},easeOutBounce:function(e,f,a,h,g){if((f/=g)<(1/2.75)){return h*(7.5625*f*f)+a}else{if(f<(2/2.75)){return h*(7.5625*(f-=(1.5/2.75))*f+0.75)+a}else{if(f<(2.5/2.75)){return h*(7.5625*(f-=(2.25/2.75))*f+0.9375)+a}else{return h*(7.5625*(f-=(2.625/2.75))*f+0.984375)+a}}}},easeInOutBounce:function(e,f,a,h,g){if(f<g/2){return jQuery.easing.easeInBounce(e,f*2,0,h,g)*0.5+a}return jQuery.easing.easeOutBounce(e,f*2-g,0,h,g)*0.5+h*0.5+a}});
trunk/assets/js/jquery.form-population.js ADDED
@@ -0,0 +1 @@
 
0
  <input type="text" name="name" />
1
  <input type="email" name="email" />
2
  <input type="text" name="address[addr1]" />
3
  <input type="text" name="address[city]" />
4
  <input type="text" name="address[state]" />
5
  "email": "john@doe.com",
6
  "name": "John Doe",
7
  "address": {
8
  "addr1": "Street name",
9
  "city": "City name",
10
  "state": "State"
11
  }
12
  for(var key in data) {
13
  var name = key;
14
  var value = data[key];
15
  // no need to set empty values
16
  if(value == "") {
17
  continue;
18
  }
19
  // handle array name attributes
20
  if(typeof(basename) !== "undefined") {
21
  name = basename + "[" + key + "]";
22
  }
23
  if(value.constructor == Array) {
24
  name += '[]';
25
  } else if(typeof value == "object") {
26
  populateFields(container, value, name);
27
  continue;
28
  }
29
  // populate field
30
  var elements = container.querySelectorAll('input[name="'+ name +'"], select[name="'+ name +'"], textarea[name="'+ name +'"]');
31
  // Dirty: abandon if we did not find the element
32
  if(!elements) {
33
  return;
34
  }
35
  // loop through found elements to set their values
36
  for(var i = 0; i < elements.length; i++) {
37
  var element = elements[i];
38
  // check element type
39
  switch(element.type || element.tagName) {
40
  case 'text':
41
  case 'email':
42
  case 'date':
43
  case 'tel':
44
  element.value = value;
45
  break;
46
  case 'radio':
47
  element.checked = (element.value === value);
48
  break;
49
  case 'checkbox':
50
  for(var j = 0; j < value.length; j++) {
51
  element.checked = (element.value === value[j]);
52
  }
53
  break;
54
  case 'select-multiple':
55
  var values = value.constructor == Array ? value : [value];
56
  for(var k = 0; k < element.options.length; k++)
57
  {
58
  for(var l = 0; l < values.length; l++)
59
  {
60
  element.options[k].selected |= (element.options[k].value == values[l]);
61
  }
62
  }
63
  break;
64
  case 'select':
65
  case 'select-one':
66
  element.value = value.toString() || value;
67
  break;
68
  }
69
  }
70
  }
71
  var name = ( elements[i].name ) ? elements[i].name : '';
1
+ /*
2
  <input type="text" name="name" />
3
  <input type="email" name="email" />
4
  <input type="text" name="address[addr1]" />
5
  <input type="text" name="address[city]" />
6
  <input type="text" name="address[state]" />
7
  "email": "john@doe.com",
8
  "name": "John Doe",
9
  "address": {
10
  "addr1": "Street name",
11
  "city": "City name",
12
  "state": "State"
13
  }
14
  for(var key in data) {
15
  var name = key;
16
  var value = data[key];
17
  // no need to set empty values
18
  if(value == "") {
19
  continue;
20
  }
21
  // handle array name attributes
22
  if(typeof(basename) !== "undefined") {
23
  name = basename + "[" + key + "]";
24
  }
25
  if(value.constructor == Array) {
26
  name += '[]';
27
  } else if(typeof value == "object") {
28
  populateFields(container, value, name);
29
  continue;
30
  }
31
  // populate field
32
  var elements = container.querySelectorAll('input[name="'+ name +'"], select[name="'+ name +'"], textarea[name="'+ name +'"]');
33
  // Dirty: abandon if we did not find the element
34
  if(!elements) {
35
  return;
36
  }
37
  // loop through found elements to set their values
38
  for(var i = 0; i < elements.length; i++) {
39
  var element = elements[i];
40
  // check element type
41
  switch(element.type || element.tagName) {
42
  case 'text':
43
  case 'email':
44
  case 'date':
45
  case 'tel':
46
  element.value = value;
47
  break;
48
  case 'radio':
49
  element.checked = (element.value === value);
50
  break;
51
  case 'checkbox':
52
  for(var j = 0; j < value.length; j++) {
53
  element.checked = (element.value === value[j]);
54
  }
55
  break;
56
  case 'select-multiple':
57
  var values = value.constructor == Array ? value : [value];
58
  for(var k = 0; k < element.options.length; k++)
59
  {
60
  for(var l = 0; l < values.length; l++)
61
  {
62
  element.options[k].selected |= (element.options[k].value == values[l]);
63
  }
64
  }
65
  break;
66
  case 'select':
67
  case 'select-one':
68
  element.value = value.toString() || value;
69
  break;
70
  }
71
  }
72
  }
73
  var name = ( elements[i].name ) ? elements[i].name : '';
trunk/assets/js/jquery.lp.cookie.js ADDED
@@ -0,0 +1 @@
 
1
+ /*!
trunk/assets/js/jquery.tablesorter.js ADDED
@@ -0,0 +1,1031 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ *
3
+ * TableSorter 2.0 - Client-side table sorting with ease!
4
+ * Version 2.0.5b
5
+ * @requires jQuery v1.2.3
6
+ *
7
+ * Copyright (c) 2007 Christian Bach
8
+ * Examples and docs at: http://tablesorter.com
9
+ * Dual licensed under the MIT and GPL licenses:
10
+ * http://www.opensource.org/licenses/mit-license.php
11
+ * http://www.gnu.org/licenses/gpl.html
12
+ *
13
+ */
14
+ /**
15
+ *
16
+ * @description Create a sortable table with multi-column sorting capabilitys
17
+ *
18
+ * @example $('table').tablesorter();
19
+ * @desc Create a simple tablesorter interface.
20
+ *
21
+ * @example $('table').tablesorter({ sortList:[[0,0],[1,0]] });
22
+ * @desc Create a tablesorter interface and sort on the first and secound column column headers.
23
+ *
24
+ * @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } });
25
+ *
26
+ * @desc Create a tablesorter interface and disableing the first and second column headers.
27
+ *
28
+ *
29
+ * @example $('table').tablesorter({ headers: { 0: {sorter:"integer"}, 1: {sorter:"currency"} } });
30
+ *
31
+ * @desc Create a tablesorter interface and set a column parser for the first
32
+ * and second column.
33
+ *
34
+ *
35
+ * @param Object
36
+ * settings An object literal containing key/value pairs to provide
37
+ * optional settings.
38
+ *
39
+ *
40
+ * @option String cssHeader (optional) A string of the class name to be appended
41
+ * to sortable tr elements in the thead of the table. Default value:
42
+ * "header"
43
+ *
44
+ * @option String cssAsc (optional) A string of the class name to be appended to
45
+ * sortable tr elements in the thead on a ascending sort. Default value:
46
+ * "headerSortUp"
47
+ *
48
+ * @option String cssDesc (optional) A string of the class name to be appended
49
+ * to sortable tr elements in the thead on a descending sort. Default
50
+ * value: "headerSortDown"
51
+ *
52
+ * @option String sortInitialOrder (optional) A string of the inital sorting
53
+ * order can be asc or desc. Default value: "asc"
54
+ *
55
+ * @option String sortMultisortKey (optional) A string of the multi-column sort
56
+ * key. Default value: "shiftKey"
57
+ *
58
+ * @option String textExtraction (optional) A string of the text-extraction
59
+ * method to use. For complex html structures inside td cell set this
60
+ * option to "complex", on large tables the complex option can be slow.
61
+ * Default value: "simple"
62
+ *
63
+ * @option Object headers (optional) An array containing the forces sorting
64
+ * rules. This option let's you specify a default sorting rule. Default
65
+ * value: null
66
+ *
67
+ * @option Array sortList (optional) An array containing the forces sorting
68
+ * rules. This option let's you specify a default sorting rule. Default
69
+ * value: null
70
+ *
71
+ * @option Array sortForce (optional) An array containing forced sorting rules.
72
+ * This option let's you specify a default sorting rule, which is
73
+ * prepended to user-selected rules. Default value: null
74
+ *
75
+ * @option Boolean sortLocaleCompare (optional) Boolean flag indicating whatever
76
+ * to use String.localeCampare method or not. Default set to true.
77
+ *
78
+ *
79
+ * @option Array sortAppend (optional) An array containing forced sorting rules.
80
+ * This option let's you specify a default sorting rule, which is
81
+ * appended to user-selected rules. Default value: null
82
+ *
83
+ * @option Boolean widthFixed (optional) Boolean flag indicating if tablesorter
84
+ * should apply fixed widths to the table columns. This is usefull when
85
+ * using the pager companion plugin. This options requires the dimension
86
+ * jquery plugin. Default value: false
87
+ *
88
+ * @option Boolean cancelSelection (optional) Boolean flag indicating if
89
+ * tablesorter should cancel selection of the table headers text.
90
+ * Default value: true
91
+ *
92
+ * @option Boolean debug (optional) Boolean flag indicating if tablesorter
93
+ * should display debuging information usefull for development.
94
+ *
95
+ * @type jQuery
96
+ *
97
+ * @name tablesorter
98
+ *
99
+ * @cat Plugins/Tablesorter
100
+ *
101
+ * @author Christian Bach/christian.bach@polyester.se
102
+ */
103
+
104
+ (function ($) {
105
+ $.extend({
106
+ tablesorter: new
107
+ function () {
108
+
109
+ var parsers = [],
110
+ widgets = [];
111
+
112
+ this.defaults = {
113
+ cssHeader: "header",
114
+ cssAsc: "headerSortUp",
115
+ cssDesc: "headerSortDown",
116
+ cssChildRow: "expand-child",
117
+ sortInitialOrder: "asc",
118
+ sortMultiSortKey: "shiftKey",
119
+ sortForce: null,
120
+ sortAppend: null,
121
+ sortLocaleCompare: true,
122
+ textExtraction: "simple",
123
+ parsers: {}, widgets: [],
124
+ widgetZebra: {
125
+ css: ["even", "odd"]
126
+ }, headers: {}, widthFixed: false,
127
+ cancelSelection: true,
128
+ sortList: [],
129
+ headerList: [],
130
+ dateFormat: "us",
131
+ decimal: '/\.|\,/g',
132
+ onRenderHeader: null,
133
+ selectorHeaders: 'thead th',
134
+ debug: false
135
+ };
136
+
137
+ /* debuging utils */
138
+
139
+ function benchmark(s, d) {
140
+ log(s + "," + (new Date().getTime() - d.getTime()) + "ms");
141
+ }
142
+
143
+ this.benchmark = benchmark;
144
+
145
+ function log(s) {
146
+ if (typeof console != "undefined" && typeof console.debug != "undefined") {
147
+ console.log(s);
148
+ } else {
149
+ alert(s);
150
+ }
151
+ }
152
+
153
+ /* parsers utils */
154
+
155
+ function buildParserCache(table, $headers) {
156
+
157
+ if (table.config.debug) {
158
+ var parsersDebug = "";
159
+ }
160
+
161
+ if (table.tBodies.length == 0) return; // In the case of empty tables
162
+ var rows = table.tBodies[0].rows;
163
+
164
+ if (rows[0]) {
165
+
166
+ var list = [],
167
+ cells = rows[0].cells,
168
+ l = cells.length;
169
+
170
+ for (var i = 0; i < l; i++) {
171
+
172
+ var p = false;
173
+
174
+ if ($.metadata && ($($headers[i]).metadata() && $($headers[i]).metadata().sorter)) {
175
+
176
+ p = getParserById($($headers[i]).metadata().sorter);
177
+
178
+ } else if ((table.config.headers[i] && table.config.headers[i].sorter)) {
179
+
180
+ p = getParserById(table.config.headers[i].sorter);
181
+ }
182
+ if (!p) {
183
+
184
+ p = detectParserForColumn(table, rows, -1, i);
185
+ }
186
+
187
+ if (table.config.debug) {
188
+ parsersDebug += "column:" + i + " parser:" + p.id + "\n";
189
+ }
190
+
191
+ list.push(p);
192
+ }
193
+ }
194
+
195
+ if (table.config.debug) {
196
+ log(parsersDebug);
197
+ }
198
+
199
+ return list;
200
+ };
201
+
202
+ function detectParserForColumn(table, rows, rowIndex, cellIndex) {
203
+ var l = parsers.length,
204
+ node = false,
205
+ nodeValue = false,
206
+ keepLooking = true;
207
+ while (nodeValue == '' && keepLooking) {
208
+ rowIndex++;
209
+ if (rows[rowIndex]) {
210
+ node = getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex);
211
+ nodeValue = trimAndGetNodeText(table.config, node);
212
+ if (table.config.debug) {
213
+ log('Checking if value was empty on row:' + rowIndex);
214
+ }
215
+ } else {
216
+ keepLooking = false;
217
+ }
218
+ }
219
+ for (var i = 1; i < l; i++) {
220
+ if (parsers[i].is(nodeValue, table, node)) {
221
+ return parsers[i];
222
+ }
223
+ }
224
+ // 0 is always the generic parser (text)
225
+ return parsers[0];
226
+ }
227
+
228
+ function getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex) {
229
+ return rows[rowIndex].cells[cellIndex];
230
+ }
231
+
232
+ function trimAndGetNodeText(config, node) {
233
+ return $.trim(getElementText(config, node));
234
+ }
235
+
236
+ function getParserById(name) {
237
+ var l = parsers.length;
238
+ for (var i = 0; i < l; i++) {
239
+ if (parsers[i].id.toLowerCase() == name.toLowerCase()) {
240
+ return parsers[i];
241
+ }
242
+ }
243
+ return false;
244
+ }
245
+
246
+ /* utils */
247
+
248
+ function buildCache(table) {
249
+
250
+ if (table.config.debug) {
251
+ var cacheTime = new Date();
252
+ }
253
+
254
+ var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0,
255
+ totalCells = (table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length) || 0,
256
+ parsers = table.config.parsers,
257
+ cache = {
258
+ row: [],
259
+ normalized: []
260
+ };
261
+
262
+ for (var i = 0; i < totalRows; ++i) {
263
+
264
+ /** Add the table data to main data array */
265
+ var c = $(table.tBodies[0].rows[i]),
266
+ cols = [];
267
+
268
+ // if this is a child row, add it to the last row's children and
269
+ // continue to the next row
270
+ if (c.hasClass(table.config.cssChildRow)) {
271
+ cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add(c);
272
+ // go to the next for loop
273
+ continue;
274
+ }
275
+
276
+ cache.row.push(c);
277
+
278
+ for (var j = 0; j < totalCells; ++j) {
279
+ cols.push(parsers[j].format(getElementText(table.config, c[0].cells[j]), table, c[0].cells[j]));
280
+ }
281
+
282
+ cols.push(cache.normalized.length); // add position for rowCache
283
+ cache.normalized.push(cols);
284
+ cols = null;
285
+ };
286
+
287
+ if (table.config.debug) {
288
+ benchmark("Building cache for " + totalRows + " rows:", cacheTime);
289
+ }
290
+
291
+ return cache;
292
+ };
293
+
294
+ function getElementText(config, node) {
295
+
296
+ var text = "";
297
+
298
+ if (!node) return "";
299
+
300
+ if (!config.supportsTextContent) config.supportsTextContent = node.textContent || false;
301
+
302
+ if (config.textExtraction == "simple") {
303
+ if (config.supportsTextContent) {
304
+ text = node.textContent;
305
+ } else {
306
+ if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
307
+ text = node.childNodes[0].innerHTML;
308
+ } else {
309
+ text = node.innerHTML;
310
+ }
311
+ }
312
+ } else {
313
+ if (typeof(config.textExtraction) == "function") {
314
+ text = config.textExtraction(node);
315
+ } else {
316
+ text = $(node).text();
317
+ }
318
+ }
319
+ return text;
320
+ }
321
+
322
+ function appendToTable(table, cache) {
323
+
324
+ if (table.config.debug) {
325
+ var appendTime = new Date()
326
+ }
327
+
328
+ var c = cache,
329
+ r = c.row,
330
+ n = c.normalized,
331
+ totalRows = n.length,
332
+ checkCell = (n[0].length - 1),
333
+ tableBody = $(table.tBodies[0]),
334
+ rows = [];
335
+
336
+
337
+ for (var i = 0; i < totalRows; i++) {
338
+ var pos = n[i][checkCell];
339
+
340
+ rows.push(r[pos]);
341
+
342
+ if (!table.config.appender) {
343
+
344
+ //var o = ;
345
+ var l = r[pos].length;
346
+ for (var j = 0; j < l; j++) {
347
+ tableBody[0].appendChild(r[pos][j]);
348
+ }
349
+
350
+ //
351
+ }
352
+ }
353
+
354
+
355
+
356
+ if (table.config.appender) {
357
+
358
+ table.config.appender(table, rows);
359
+ }
360
+
361
+ rows = null;
362
+
363
+ if (table.config.debug) {
364
+ benchmark("Rebuilt table:", appendTime);
365
+ }
366
+
367
+ // apply table widgets
368
+ applyWidget(table);
369
+
370
+ // trigger sortend
371
+ setTimeout(function () {
372
+ $(table).trigger("sortEnd");
373
+ }, 0);
374
+
375
+ };
376
+
377
+ function buildHeaders(table) {
378
+
379
+ if (table.config.debug) {
380
+ var time = new Date();
381
+ }
382
+
383
+ var meta = ($.metadata) ? true : false;
384
+
385
+ var header_index = computeTableHeaderCellIndexes(table);
386
+
387
+ $tableHeaders = $(table.config.selectorHeaders, table).each(function (index) {
388
+
389
+ this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex];
390
+ // this.column = index;
391
+ this.order = formatSortingOrder(table.config.sortInitialOrder);
392
+
393
+
394
+ this.count = this.order;
395
+
396
+ if (checkHeaderMetadata(this) || checkHeaderOptions(table, index)) this.sortDisabled = true;
397
+ if (checkHeaderOptionsSortingLocked(table, index)) this.order = this.lockedOrder = checkHeaderOptionsSortingLocked(table, index);
398
+
399
+ if (!this.sortDisabled) {
400
+ var $th = $(this).addClass(table.config.cssHeader);
401
+ if (table.config.onRenderHeader) table.config.onRenderHeader.apply($th);
402
+ }
403
+
404
+ // add cell to headerList
405
+ table.config.headerList[index] = this;
406
+ });
407
+
408
+ if (table.config.debug) {
409
+ benchmark("Built headers:", time);
410
+ log($tableHeaders);
411
+ }
412
+
413
+ return $tableHeaders;
414
+
415
+ };
416
+
417
+ // from:
418
+ // http://www.javascripttoolbox.com/lib/table/examples.php
419
+ // http://www.javascripttoolbox.com/temp/table_cellindex.html
420
+
421
+
422
+ function computeTableHeaderCellIndexes(t) {
423
+ var matrix = [];
424
+ var lookup = {};
425
+ var thead = t.getElementsByTagName('THEAD')[0];
426
+ var trs = thead.getElementsByTagName('TR');
427
+
428
+ for (var i = 0; i < trs.length; i++) {
429
+ var cells = trs[i].cells;
430
+ for (var j = 0; j < cells.length; j++) {
431
+ var c = cells[j];
432
+
433
+ var rowIndex = c.parentNode.rowIndex;
434
+ var cellId = rowIndex + "-" + c.cellIndex;
435
+ var rowSpan = c.rowSpan || 1;
436
+ var colSpan = c.colSpan || 1
437
+ var firstAvailCol;
438
+ if (typeof(matrix[rowIndex]) == "undefined") {
439
+ matrix[rowIndex] = [];
440
+ }
441
+ // Find first available column in the first row
442
+ for (var k = 0; k < matrix[rowIndex].length + 1; k++) {
443
+ if (typeof(matrix[rowIndex][k]) == "undefined") {
444
+ firstAvailCol = k;
445
+ break;
446
+ }
447
+ }
448
+ lookup[cellId] = firstAvailCol;
449
+ for (var k = rowIndex; k < rowIndex + rowSpan; k++) {
450
+ if (typeof(matrix[k]) == "undefined") {
451
+ matrix[k] = [];
452
+ }
453
+ var matrixrow = matrix[k];
454
+ for (var l = firstAvailCol; l < firstAvailCol + colSpan; l++) {
455
+ matrixrow[l] = "x";
456
+ }
457
+ }
458
+ }
459
+ }
460
+ return lookup;
461
+ }
462
+
463
+ function checkCellColSpan(table, rows, row) {
464
+ var arr = [],
465
+ r = table.tHead.rows,
466
+ c = r[row].cells;
467
+
468
+ for (var i = 0; i < c.length; i++) {
469
+ var cell = c[i];
470
+
471
+ if (cell.colSpan > 1) {
472
+ arr = arr.concat(checkCellColSpan(table, headerArr, row++));
473
+ } else {
474
+ if (table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row + 1])) {
475
+ arr.push(cell);
476
+ }
477
+ // headerArr[row] = (i+row);
478
+ }
479
+ }
480
+ return arr;
481
+ };
482
+
483
+ function checkHeaderMetadata(cell) {
484
+ if (($.metadata) && ($(cell).metadata().sorter === false)) {
485
+ return true;
486
+ };
487
+ return false;
488
+ }
489
+
490
+ function checkHeaderOptions(table, i) {
491
+ if ((table.config.headers[i]) && (table.config.headers[i].sorter === false)) {
492
+ return true;
493
+ };
494
+ return false;
495
+ }
496
+
497
+ function checkHeaderOptionsSortingLocked(table, i) {
498
+ if ((table.config.headers[i]) && (table.config.headers[i].lockedOrder)) return table.config.headers[i].lockedOrder;
499
+ return false;
500
+ }
501
+
502
+ function applyWidget(table) {
503
+ var c = table.config.widgets;
504
+ var l = c.length;
505
+ for (var i = 0; i < l; i++) {
506
+
507
+ getWidgetById(c[i]).format(table);
508
+ }
509
+
510
+ }
511
+
512
+ function getWidgetById(name) {
513
+ var l = widgets.length;
514
+ for (var i = 0; i < l; i++) {
515
+ if (widgets[i].id.toLowerCase() == name.toLowerCase()) {
516
+ return widgets[i];
517
+ }
518
+ }
519
+ };
520
+
521
+ function formatSortingOrder(v) {
522
+ if (typeof(v) != "Number") {
523
+ return (v.toLowerCase() == "desc") ? 1 : 0;
524
+ } else {
525
+ return (v == 1) ? 1 : 0;
526
+ }
527
+ }
528
+
529
+ function isValueInArray(v, a) {
530
+ var l = a.length;
531
+ for (var i = 0; i < l; i++) {
532
+ if (a[i][0] == v) {
533
+ return true;
534
+ }
535
+ }
536
+ return false;
537
+ }
538
+
539
+ function setHeadersCss(table, $headers, list, css) {
540
+ // remove all header information
541
+ $headers.removeClass(css[0]).removeClass(css[1]);
542
+
543
+ var h = [];
544
+ $headers.each(function (offset) {
545
+ if (!this.sortDisabled) {
546
+ h[this.column] = $(this);
547
+ }
548
+ });
549
+
550
+ var l = list.length;
551
+ for (var i = 0; i < l; i++) {
552
+ h[list[i][0]].addClass(css[list[i][1]]);
553
+ }
554
+ }
555
+
556
+ function fixColumnWidth(table, $headers) {
557
+ var c = table.config;
558
+ if (c.widthFixed) {
559
+ var colgroup = $('<colgroup>');
560
+ $("tr:first td", table.tBodies[0]).each(function () {
561
+ colgroup.append($('<col>').css('width', $(this).width()));
562
+ });
563
+ $(table).prepend(colgroup);
564
+ };
565
+ }
566
+
567
+ function updateHeaderSortCount(table, sortList) {
568
+ var c = table.config,
569
+ l = sortList.length;
570
+ for (var i = 0; i < l; i++) {
571
+ var s = sortList[i],
572
+ o = c.headerList[s[0]];
573
+ o.count = s[1];
574
+ o.count++;
575
+ }
576
+ }
577
+
578
+ /* sorting methods */
579
+
580
+ function multisort(table, sortList, cache) {
581
+
582
+ if (table.config.debug) {
583
+ var sortTime = new Date();
584
+ }
585
+
586
+ var dynamicExp = "var sortWrapper = function(a,b) {",
587
+ l = sortList.length;
588
+
589
+ // TODO: inline functions.
590
+ for (var i = 0; i < l; i++) {
591
+
592
+ var c = sortList[i][0];
593
+ var order = sortList[i][1];
594
+ // var s = (getCachedSortType(table.config.parsers,c) == "text") ?
595
+ // ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ?
596
+ // "sortNumeric" : "sortNumericDesc");
597
+ // var s = (table.config.parsers[c].type == "text") ? ((order == 0)
598
+ // ? makeSortText(c) : makeSortTextDesc(c)) : ((order == 0) ?
599
+ // makeSortNumeric(c) : makeSortNumericDesc(c));
600
+ var s = (table.config.parsers[c].type == "text") ? ((order == 0) ? makeSortFunction("text", "asc", c) : makeSortFunction("text", "desc", c)) : ((order == 0) ? makeSortFunction("numeric", "asc", c) : makeSortFunction("numeric", "desc", c));
601
+ var e = "e" + i;
602
+
603
+ dynamicExp += "var " + e + " = " + s; // + "(a[" + c + "],b[" + c
604
+ // + "]); ";
605
+ dynamicExp += "if(" + e + ") { return " + e + "; } ";
606
+ dynamicExp += "else { ";
607
+
608
+ }
609
+
610
+ // if value is the same keep orignal order
611
+ var orgOrderCol = cache.normalized[0].length - 1;
612
+ dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];";
613
+
614
+ for (var i = 0; i < l; i++) {
615
+ dynamicExp += "}; ";
616
+ }
617
+
618
+ dynamicExp += "return 0; ";
619
+ dynamicExp += "}; ";
620
+
621
+ if (table.config.debug) {
622
+ benchmark("Evaling expression:" + dynamicExp, new Date());
623
+ }
624
+
625
+ eval(dynamicExp);
626
+
627
+ cache.normalized.sort(sortWrapper);
628
+
629
+ if (table.config.debug) {
630
+ benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time:", sortTime);
631
+ }
632
+
633
+ return cache;
634
+ };
635
+
636
+ function makeSortFunction(type, direction, index) {
637
+ var a = "a[" + index + "]",
638
+ b = "b[" + index + "]";
639
+ if (type == 'text' && direction == 'asc') {
640
+ return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + a + " < " + b + ") ? -1 : 1 )));";
641
+ } else if (type == 'text' && direction == 'desc') {
642
+ return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + b + " < " + a + ") ? -1 : 1 )));";
643
+ } else if (type == 'numeric' && direction == 'asc') {
644
+ return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + a + " - " + b + "));";
645
+ } else if (type == 'numeric' && direction == 'desc') {
646
+ return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + b + " - " + a + "));";
647
+ }
648
+ };
649
+
650
+ function makeSortText(i) {
651
+ return "((a[" + i + "] < b[" + i + "]) ? -1 : ((a[" + i + "] > b[" + i + "]) ? 1 : 0));";
652
+ };
653
+
654
+ function makeSortTextDesc(i) {
655
+ return "((b[" + i + "] < a[" + i + "]) ? -1 : ((b[" + i + "] > a[" + i + "]) ? 1 : 0));";
656
+ };
657
+
658
+ function makeSortNumeric(i) {
659
+ return "a[" + i + "]-b[" + i + "];";
660
+ };
661
+
662
+ function makeSortNumericDesc(i) {
663
+ return "b[" + i + "]-a[" + i + "];";
664
+ };
665
+
666
+ function sortText(a, b) {
667
+ if (table.config.sortLocaleCompare) return a.localeCompare(b);
668
+ return ((a < b) ? -1 : ((a > b) ? 1 : 0));
669
+ };
670
+
671
+ function sortTextDesc(a, b) {
672
+ if (table.config.sortLocaleCompare) return b.localeCompare(a);
673
+ return ((b < a) ? -1 : ((b > a) ? 1 : 0));
674
+ };
675
+
676
+ function sortNumeric(a, b) {
677
+ return a - b;
678
+ };
679
+
680
+ function sortNumericDesc(a, b) {
681
+ return b - a;
682
+ };
683
+
684
+ function getCachedSortType(parsers, i) {
685
+ return parsers[i].type;
686
+ }; /* public methods */
687
+ this.construct = function (settings) {
688
+ return this.each(function () {
689
+ // if no thead or tbody quit.
690
+ if (!this.tHead || !this.tBodies) return;
691
+ // declare
692
+ var $this, $document, $headers, cache, config, shiftDown = 0,
693
+ sortOrder;
694
+ // new blank config object
695
+ this.config = {};
696
+ // merge and extend.
697
+ config = $.extend(this.config, $.tablesorter.defaults, settings);
698
+ // store common expression for speed
699
+ $this = $(this);
700
+ // save the settings where they read
701
+ $.data(this, "tablesorter", config);
702
+ // build headers
703
+ $headers = buildHeaders(this);
704
+ // try to auto detect column type, and store in tables config
705
+ this.config.parsers = buildParserCache(this, $headers);
706
+ // build the cache for the tbody cells
707
+ cache = buildCache(this);
708
+ // get the css class names, could be done else where.
709
+ var sortCSS = [config.cssDesc, config.cssAsc];
710
+ // fixate columns if the users supplies the fixedWidth option
711
+ fixColumnWidth(this);
712
+ // apply event handling to headers
713
+ // this is to big, perhaps break it out?
714
+ $headers.click(
715
+
716
+ function (e) {
717
+ var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0;
718
+ if (!this.sortDisabled && totalRows > 0) {
719
+ // Only call sortStart if sorting is
720
+ // enabled.
721
+ $this.trigger("sortStart");
722
+ // store exp, for speed
723
+ var $cell = $(this);
724
+ // get current column index
725
+ var i = this.column;
726
+ // get current column sort order
727
+ this.order = this.count++ % 2;
728
+ // always sort on the locked order.
729
+ if(this.lockedOrder) this.order = this.lockedOrder;
730
+
731
+ // user only whants to sort on one
732
+ // column
733
+ if (!e[config.sortMultiSortKey]) {
734
+ // flush the sort list
735
+ config.sortList = [];
736
+ if (config.sortForce != null) {
737
+ var a = config.sortForce;
738
+ for (var j = 0; j < a.length; j++) {
739
+ if (a[j][0] != i) {
740
+ config.sortList.push(a[j]);
741
+ }
742
+ }
743
+ }
744
+ // add column to sort list
745
+ config.sortList.push([i, this.order]);
746
+ // multi column sorting
747
+ } else {
748
+ // the user has clicked on an all
749
+ // ready sortet column.
750
+ if (isValueInArray(i, config.sortList)) {
751
+ // revers the sorting direction
752
+ // for all tables.
753
+ for (var j = 0; j < config.sortList.length; j++) {
754
+ var s = config.sortList[j],
755
+ o = config.headerList[s[0]];
756
+ if (s[0] == i) {
757
+ o.count = s[1];
758
+ o.count++;
759
+ s[1] = o.count % 2;
760
+ }
761
+ }
762
+ } else {
763
+ // add column to sort list array
764
+ config.sortList.push([i, this.order]);
765
+ }
766
+ };
767
+ setTimeout(function () {
768
+ // set css for headers
769
+ setHeadersCss($this[0], $headers, config.sortList, sortCSS);
770
+ appendToTable(
771
+ $this[0], multisort(
772
+ $this[0], config.sortList, cache)
773
+ );
774
+ }, 1);
775
+ // stop normal event by returning false
776
+ return false;
777
+ }
778
+ // cancel selection
779
+ }).mousedown(function () {
780
+ if (config.cancelSelection) {
781
+ this.onselectstart = function () {
782
+ return false
783
+ };
784
+ return false;
785
+ }
786
+ });
787
+ // apply easy methods that trigger binded events
788
+ $this.bind("update", function () {
789
+ var me = this;
790
+ setTimeout(function () {
791
+ // rebuild parsers.
792
+ me.config.parsers = buildParserCache(
793
+ me, $headers);
794
+ // rebuild the cache map
795
+ cache = buildCache(me);
796
+ }, 1);
797
+ }).bind("updateCell", function (e, cell) {
798
+ var config = this.config;
799
+ // get position from the dom.
800
+ var pos = [(cell.parentNode.rowIndex - 1), cell.cellIndex];
801
+ // update cache
802
+ cache.normalized[pos[0]][pos[1]] = config.parsers[pos[1]].format(
803
+ getElementText(config, cell), cell);
804
+ }).bind("sorton", function (e, list) {
805
+ $(this).trigger("sortStart");
806
+ config.sortList = list;
807
+ // update and store the sortlist
808
+ var sortList = config.sortList;
809
+ // update header count index
810
+ updateHeaderSortCount(this, sortList);
811
+ // set css for headers
812
+ setHeadersCss(this, $headers, sortList, sortCSS);
813
+ // sort the table and append it to the dom
814
+ appendToTable(this, multisort(this, sortList, cache));
815
+ }).bind("appendCache", function () {
816
+ appendToTable(this, cache);
817
+ }).bind("applyWidgetId", function (e, id) {
818
+ getWidgetById(id).format(this);
819
+ }).bind("applyWidgets", function () {
820
+ // apply widgets
821
+ applyWidget(this);
822
+ });
823
+ if ($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) {
824
+ config.sortList = $(this).metadata().sortlist;
825
+ }
826
+ // if user has supplied a sort list to constructor.
827
+ if (config.sortList.length > 0) {
828
+ $this.trigger("sorton", [config.sortList]);
829
+ }
830
+ // apply widgets
831
+ applyWidget(this);
832
+ });
833
+ };
834
+ this.addParser = function (parser) {
835
+ var l = parsers.length,
836
+ a = true;
837
+ for (var i = 0; i < l; i++) {
838
+ if (parsers[i].id.toLowerCase() == parser.id.toLowerCase()) {
839
+ a = false;
840
+ }
841
+ }
842
+ if (a) {
843
+ parsers.push(parser);
844
+ };
845
+ };
846
+ this.addWidget = function (widget) {
847
+ widgets.push(widget);
848
+ };
849
+ this.formatFloat = function (s) {
850
+ var i = parseFloat(s);
851
+ return (isNaN(i)) ? 0 : i;
852
+ };
853
+ this.formatInt = function (s) {
854
+ var i = parseInt(s);
855
+ return (isNaN(i)) ? 0 : i;
856
+ };
857
+ this.isDigit = function (s, config) {
858
+ // replace all an wanted chars and match.
859
+ return /^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g, '')));
860
+ };
861
+ this.clearTableBody = function (table) {
862
+ if ($.browser.msie) {
863
+ function empty() {
864
+ while (this.firstChild)
865
+ this.removeChild(this.firstChild);
866
+ }
867
+ empty.apply(table.tBodies[0]);
868
+ } else {
869
+ table.tBodies[0].innerHTML = "";
870
+ }
871
+ };
872
+ }
873
+ });
874
+
875
+ // extend plugin scope
876
+ $.fn.extend({
877
+ tablesorter: $.tablesorter.construct
878
+ });
879
+
880
+ // make shortcut
881
+ var ts = $.tablesorter;
882
+
883
+ // add default parsers
884
+ ts.addParser({
885
+ id: "text",
886
+ is: function (s) {
887
+ return true;
888
+ }, format: function (s) {
889
+ return $.trim(s.toLocaleLowerCase());
890
+ }, type: "text"
891
+ });
892
+
893
+ ts.addParser({
894
+ id: "digit",
895
+ is: function (s, table) {
896
+ var c = table.config;
897
+ return $.tablesorter.isDigit(s, c);
898
+ }, format: function (s) {
899
+ return $.tablesorter.formatFloat(s);
900
+ }, type: "numeric"
901
+ });
902
+
903
+ ts.addParser({
904
+ id: "currency",
905
+ is: function (s) {
906
+ return /^[£$€?.]/.test(s);
907
+ }, format: function (s) {
908
+ return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g), ""));
909
+ }, type: "numeric"
910
+ });
911
+
912
+ ts.addParser({
913
+ id: "ipAddress",
914
+ is: function (s) {
915
+ return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);
916
+ }, format: function (s) {
917
+ var a = s.split("."),
918
+ r = "",
919
+ l = a.length;
920
+ for (var i = 0; i < l; i++) {
921
+ var item = a[i];
922
+ if (item.length == 2) {
923
+ r += "0" + item;
924
+ } else {
925
+ r += item;
926
+ }
927
+ }
928
+ return $.tablesorter.formatFloat(r);
929
+ }, type: "numeric"
930
+ });
931
+
932
+ ts.addParser({
933
+ id: "url",
934
+ is: function (s) {
935
+ return /^(https?|ftp|file):\/\/$/.test(s);
936
+ }, format: function (s) {
937
+ return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//), ''));
938
+ }, type: "text"
939
+ });
940
+
941
+ ts.addParser({
942
+ id: "isoDate",
943
+ is: function (s) {
944
+ return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);
945
+ }, format: function (s) {
946
+ return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(
947
+ new RegExp(/-/g), "/")).getTime() : "0");
948
+ }, type: "numeric"
949
+ });
950
+
951
+ ts.addParser({
952
+ id: "percent",
953
+ is: function (s) {
954
+ return /\%$/.test($.trim(s));
955
+ }, format: function (s) {
956
+ return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g), ""));
957
+ }, type: "numeric"
958
+ });
959
+
960
+ ts.addParser({
961
+ id: "usLongDate",
962
+ is: function (s) {
963
+ return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));
964
+ }, format: function (s) {
965
+ return $.tablesorter.formatFloat(new Date(s).getTime());
966
+ }, type: "numeric"
967
+ });
968
+
969
+ ts.addParser({
970
+ id: "shortDate",
971
+ is: function (s) {
972
+ return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);
973
+ }, format: function (s, table) {
974
+ var c = table.config;
975
+ s = s.replace(/\-/g, "/");
976
+ if (c.dateFormat == "us") {
977
+ // reformat the string in ISO format
978
+ s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2");
979
+ } else if (c.dateFormat == "uk") {
980
+ // reformat the string in ISO format
981
+ s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1");
982
+ } else if (c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") {
983
+ s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3");
984
+ }
985
+ return $.tablesorter.formatFloat(new Date(s).getTime());
986
+ }, type: "numeric"
987
+ });
988
+ ts.addParser({
989
+ id: "time",
990
+ is: function (s) {
991
+ return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);
992
+ }, format: function (s) {
993
+ return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime());
994
+ }, type: "numeric"
995
+ });
996
+ ts.addParser({
997
+ id: "metadata",
998
+ is: function (s) {
999
+ return false;
1000
+ }, format: function (s, table, cell) {
1001
+ var c = table.config,
1002
+ p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;
1003
+ return $(cell).metadata()[p];
1004
+ }, type: "numeric"
1005
+ });
1006
+ // add default widgets
1007
+ ts.addWidget({
1008
+ id: "zebra",
1009
+ format: function (table) {
1010
+ if (table.config.debug) {
1011
+ var time = new Date();
1012
+ }
1013
+ var $tr, row = -1,
1014
+ odd;
1015
+ // loop through the visible rows
1016
+ $("tr:visible", table.tBodies[0]).each(function (i) {
1017
+ $tr = $(this);
1018
+ // style children rows the same way the parent
1019
+ // row was styled
1020
+ if (!$tr.hasClass(table.config.cssChildRow)) row++;
1021
+ odd = (row % 2 == 0);
1022
+ $tr.removeClass(
1023
+ table.config.widgetZebra.css[odd ? 0 : 1]).addClass(
1024
+ table.config.widgetZebra.css[odd ? 1 : 0])
1025
+ });
1026
+ if (table.config.debug) {
1027
+ $.tablesorter.benchmark("Applying Zebra widget", time);
1028
+ }
1029
+ }
1030
+ });
1031
+ })(jQuery);
trunk/assets/js/jquery.total-storage.min.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TotalStorage
3
+ *
4
+ * Copyright (c) 2012 Jared Novack & Upstatement (upstatement.com)
5
+ * Dual licensed under the MIT and GPL licenses:
6
+ * http://www.opensource.org/licenses/mit-license.php
7
+ * http://www.gnu.org/licenses/gpl.html
8
+ *
9
+ * Total Storage is the conceptual the love child of jStorage by Andris Reinman,
10
+ * and Cookie by Klaus Hartl -- though this is not connected to either project.
11
+ *
12
+ * @name $.totalStorage
13
+ * @cat Plugins/Cookie
14
+ * @author Jared Novack/jared@upstatement.com
15
+ * @version 1.1.2
16
+ * @url http://upstatement.com/blog/2012/01/jquery-local-storage-done-right-and-easy/
17
+ */
18
+
19
+ (function(c,h){var e,d;if("localStorage"in window)try{d="undefined"===typeof window.localStorage?h:window.localStorage,e="undefined"==typeof d||"undefined"==typeof window.JSON?!1:!0}catch(j){e=!1}c.totalStorage=function(b,a){return c.totalStorage.impl.init(b,a)};c.totalStorage.setItem=function(b,a){return c.totalStorage.impl.setItem(b,a)};c.totalStorage.getItem=function(b){return c.totalStorage.impl.getItem(b)};c.totalStorage.getAll=function(){return c.totalStorage.impl.getAll()};c.totalStorage.deleteItem=
20
+ function(b){return c.totalStorage.impl.deleteItem(b)};c.totalStorage.impl={init:function(b,a){return"undefined"!=typeof a?this.setItem(b,a):this.getItem(b)},setItem:function(b,a){if(!e)try{return c.cookie(b,a),a}catch(g){console.log("Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie")}var f=JSON.stringify(a);d.setItem(b,f);return this.parseResult(f)},getItem:function(b){if(!e)try{return this.parseResult(c.cookie(b))}catch(a){return null}b=
21
+ d.getItem(b);return this.parseResult(b)},deleteItem:function(b){if(!e)try{return c.cookie(b,null),!0}catch(a){return!1}d.removeItem(b);return!0},getAll:function(){var b=[];if(e)for(var a in d)a.length&&b.push({key:a,value:this.parseResult(d.getItem(a))});else try{var g=document.cookie.split(";");for(a=0;a<g.length;a++){var f=g[a].split("=")[0];b.push({key:f,value:this.parseResult(c.cookie(f))})}}catch(h){return null}return b},parseResult:function(b){var a;try{a=JSON.parse(b),"undefined"==typeof a&&
22
+ (a=b),"true"==a&&(a=!0),"false"==a&&(a=!1),parseFloat(a)==a&&"object"!=typeof a&&(a=parseFloat(a))}catch(c){a=b}return a}}})(jQuery);
trunk/assets/js/stop_page_stats.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /* For Iframe previews to stop saving page views */
2
+
3
+ var dont_save_page_view = _inbound.Utils.getParameterVal('dont_save', window.location.href);
4
+ if (dont_save_page_view) {
5
+ console.log('turn off page tracking');
6
+ window.inbound_settings.page_tracking = 'off';
7
+ }
trunk/assets/js/wordpress/editor.min.js ADDED
@@ -0,0 +1 @@
 
1
+ var switchEditors={switchto:function(b){var c=b.id,a=c.length,e=c.substr(0,a-5),d=c.substr(a-4);this.go(e,d)},go:function(g,f){g=g||"content";f=f||"toggle";var c=this,b=tinyMCE.get(g),a,d,e=tinymce.DOM;a="wp-"+g+"-wrap";d=e.get(g);if("toggle"==f){if(b&&!b.isHidden()){f="html"}else{f="tmce"}}if("tmce"==f||"tinymce"==f){if(b&&!b.isHidden()){return false}if(typeof(QTags)!="undefined"){QTags.closeAllTags(g)}if(tinyMCEPreInit.mceInit[g]&&tinyMCEPreInit.mceInit[g].wpautop){d.value=c.wpautop(d.value)}if(b){b.show()}else{b=new tinymce.Editor(g,tinyMCEPreInit.mceInit[g]);b.render()}e.removeClass(a,"html-active");e.addClass(a,"tmce-active");setUserSetting("editor","tinymce")}else{if("html"==f){if(b&&b.isHidden()){return false}if(b){b.hide()}e.removeClass(a,"tmce-active");e.addClass(a,"html-active");setUserSetting("editor","html")}}return false},_wp_Nop:function(c){var d,b,e=false,a=false;if(c.indexOf("<pre")!=-1||c.indexOf("<script")!=-1){e=true;c=c.replace(/<(pre|script)[^>]*>[\s\S]+?<\/\1>/g,function(f){f=f.replace(/<br ?\/?>(\r\n|\n)?/g,"<wp-temp-lb>");return f.replace(/<\/?p( [^>]*)?>(\r\n|\n)?/g,"<wp-temp-lb>")})}if(c.indexOf("[caption")!=-1){a=true;c=c.replace(/\[caption[\s\S]+?\[\/caption\]/g,function(f){return f.replace(/<br([^>]*)>/g,"<wp-temp-br$1>").replace(/[\r\n\t]+/,"")})}d="blockquote|ul|ol|li|table|thead|tbody|tfoot|tr|th|td|div|h[1-6]|p|fieldset";c=c.replace(new RegExp("\\s*</("+d+")>\\s*","g"),"</$1>\n");c=c.replace(new RegExp("\\s*<((?:"+d+")(?: [^>]*)?)>","g"),"\n<$1>");c=c.replace(/(<p [^>]+>.*?)<\/p>/g,"$1</p#>");c=c.replace(/<div( [^>]*)?>\s*<p>/gi,"<div$1>\n\n");c=c.replace(/\s*<p>/gi,"");c=c.replace(/\s*<\/p>\s*/gi,"\n\n");c=c.replace(/\n[\s\u00a0]+\n/g,"\n\n");c=c.replace(/\s*<br ?\/?>\s*/gi,"\n");c=c.replace(/\s*<div/g,"\n<div");c=c.replace(/<\/div>\s*/g,"</div>\n");c=c.replace(/\s*\[caption([^\[]+)\[\/caption\]\s*/gi,"\n\n[caption$1[/caption]\n\n");c=c.replace(/caption\]\n\n+\[caption/g,"caption]\n\n[caption");b="blockquote|ul|ol|li|table|thead|tbody|tfoot|tr|th|td|h[1-6]|pre|fieldset";c=c.replace(new RegExp("\\s*<((?:"+b+")(?: [^>]*)?)\\s*>","g"),"\n<$1>");c=c.replace(new RegExp("\\s*</("+b+")>\\s*","g"),"</$1>\n");c=c.replace(/<li([^>]*)>/g,"\t<li$1>");if(c.indexOf("<hr")!=-1){c=c.replace(/\s*<hr( [^>]*)?>\s*/g,"\n\n<hr$1>\n\n")}if(c.indexOf("<object")!=-1){c=c.replace(/<object[\s\S]+?<\/object>/g,function(f){return f.replace(/[\r\n]+/g,"")})}c=c.replace(/<\/p#>/g,"</p>\n");c=c.replace(/\s*(<p [^>]+>[\s\S]*?<\/p>)/g,"\n$1");c=c.replace(/^\s+/,"");c=c.replace(/[\s\u00a0]+$/,"");if(e){c=c.replace(/<wp-temp-lb>/g,"\n")}if(a){c=c.replace(/<wp-temp-br([^>]*)>/g,"<br$1>")}return c},_wp_Autop:function(a){var c=false,b=false,d="table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|option|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|noscript|samp|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary";if(a.indexOf("<object")!=-1){a=a.replace(/<object[\s\S]+?<\/object>/g,function(e){return e.replace(/[\r\n]+/g,"")})}a=a.replace(/<[^<>]+>/g,function(e){return e.replace(/[\r\n]+/g," ")});if(a.indexOf("<pre")!=-1||a.indexOf("<script")!=-1){c=true;a=a.replace(/<(pre|script)[^>]*>[\s\S]+?<\/\1>/g,function(e){return e.replace(/(\r\n|\n)/g,"<wp-temp-lb>")})}if(a.indexOf("[caption")!=-1){b=true;a=a.replace(/\[caption[\s\S]+?\[\/caption\]/g,function(e){e=e.replace(/<br([^>]*)>/g,"<wp-temp-br$1>");e=e.replace(/<[a-zA-Z0-9]+( [^<>]+)?>/g,function(f){return f.replace(/[\r\n\t]+/," ")});return e.replace(/\s*\n\s*/g,"<wp-temp-br />")})}a=a+"\n\n";a=a.replace(/<br \/>\s*<br \/>/gi,"\n\n");a=a.replace(new RegExp("(<(?:"+d+")(?: [^>]*)?>)","gi"),"\n$1");a=a.replace(new RegExp("(</(?:"+d+")>)","gi"),"$1\n\n");a=a.replace(/<hr( [^>]*)?>/gi,"<hr$1>\n\n");a=a.replace(/\r\n|\r/g,"\n");a=a.replace(/\n\s*\n+/g,"\n\n");a=a.replace(/([\s\S]+?)\n\n/g,"<p>$1</p>\n");a=a.replace(/<p>\s*?<\/p>/gi,"");a=a.replace(new RegExp("<p>\\s*(</?(?:"+d+")(?: [^>]*)?>)\\s*</p>","gi"),"$1");a=a.replace(/<p>(<li.+?)<\/p>/gi,"$1");a=a.replace(/<p>\s*<blockquote([^>]*)>/gi,"<blockquote$1><p>");a=a.replace(/<\/blockquote>\s*<\/p>/gi,"</p></blockquote>");a=a.replace(new RegExp("<p>\\s*(</?(?:"+d+")(?: [^>]*)?>)","gi"),"$1");a=a.replace(new RegExp("(</?(?:"+d+")(?: [^>]*)?>)\\s*</p>","gi"),"$1");a=a.replace(/\s*\n/gi,"<br />\n");a=a.replace(new RegExp("(</?(?:"+d+")[^>]*>)\\s*<br />","gi"),"$1");a=a.replace(/<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)/gi,"$1");a=a.replace(/(?:<p>|<br ?\/?>)*\s*\[caption([^\[]+)\[\/caption\]\s*(?:<\/p>|<br ?\/?>)*/gi,"[caption$1[/caption]");a=a.replace(/(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g,function(f,e,g){if(g.match(/<p( [^>]*)?>/)){return f}return e+"<p>"+g+"</p>"});if(c){a=a.replace(/<wp-temp-lb>/g,"\n")}if(b){a=a.replace(/<wp-temp-br([^>]*)>/g,"<br$1>")}return a},pre_wpautop:function(b){var a=this,d={o:a,data:b,unfiltered:b},c=typeof(jQuery)!="undefined";if(c){jQuery("body").trigger("beforePreWpautop",[d])}d.data=a._wp_Nop(d.data);if(c){jQuery("body").trigger("afterPreWpautop",[d])}return d.data},wpautop:function(b){var a=this,d={o:a,data:b,unfiltered:b},c=typeof(jQuery)!="undefined";if(c){jQuery("body").trigger("beforeWpautop",[d])}d.data=a._wp_Autop(d.data);if(c){jQuery("body").trigger("afterWpautop",[d])}return d.data}};
trunk/assets/js/wordpress/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/lang/landing-pages-ach.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ady.mo ADDED
Binary file
trunk/assets/lang/landing-pages-af.mo ADDED
Binary file
trunk/assets/lang/landing-pages-af_ZA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ak.mo ADDED
Binary file
trunk/assets/lang/landing-pages-aln.mo ADDED
Binary file
trunk/assets/lang/landing-pages-am.mo ADDED
Binary file
trunk/assets/lang/landing-pages-am_ET.mo ADDED
Binary file
trunk/assets/lang/landing-pages-an.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ar.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ar_AA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ar_EG.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ar_SA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ar_SD.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ar_SY.mo ADDED
Binary file
trunk/assets/lang/landing-pages-arn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-as.mo ADDED
Binary file
trunk/assets/lang/landing-pages-as_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ast.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ast_ES.mo ADDED
Binary file
trunk/assets/lang/landing-pages-az.mo ADDED
Binary file
trunk/assets/lang/landing-pages-az@Arab.mo ADDED
Binary file
trunk/assets/lang/landing-pages-az@latin.mo ADDED
Binary file
trunk/assets/lang/landing-pages-az_AZ.mo ADDED
Binary file
trunk/assets/lang/landing-pages-az_IR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ba.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bal.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bar.mo ADDED
Binary file
trunk/assets/lang/landing-pages-be.mo ADDED
Binary file
trunk/assets/lang/landing-pages-be@tarask.mo ADDED
Binary file
trunk/assets/lang/landing-pages-be_BY.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bg.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bg_BG.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bn_BD.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bn_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bo_CN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-br.mo ADDED
Binary file
trunk/assets/lang/landing-pages-brx.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bs.mo ADDED
Binary file
trunk/assets/lang/landing-pages-bs_BA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ca.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ca@valencia.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ca_ES.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cdo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ceb.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cgg.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cjy.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cmn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-co.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cpx.mo ADDED
Binary file
trunk/assets/lang/landing-pages-crh.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cs.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cs_CZ.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cv.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cy.mo ADDED
Binary file
trunk/assets/lang/landing-pages-cy_GB.mo ADDED
Binary file
trunk/assets/lang/landing-pages-czh.mo ADDED
Binary file
trunk/assets/lang/landing-pages-czo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-da.mo ADDED
Binary file
trunk/assets/lang/landing-pages-da_DK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-de.mo ADDED
Binary file
trunk/assets/lang/landing-pages-de_AT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-de_CH.mo ADDED
Binary file
trunk/assets/lang/landing-pages-de_DE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-doi.mo ADDED
Binary file
trunk/assets/lang/landing-pages-dv.mo ADDED
Binary file
trunk/assets/lang/landing-pages-dz.mo ADDED
Binary file
trunk/assets/lang/landing-pages-dz_BT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-el.mo ADDED
Binary file
trunk/assets/lang/landing-pages-el_GR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en@pirate.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_AT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_AU.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_BD.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_BE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_CA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_CH.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_CL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_CZ.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_DE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_EG.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_ES.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_FI.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_GB.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_GH.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_GR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_HK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_HR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_HU.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_IE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_IT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_LK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_NG.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_NL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_NO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_NZ.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_PK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_PL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_PT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_RO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_SE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_SK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_ZA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_ee.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_lt.mo ADDED
Binary file
trunk/assets/lang/landing-pages-en_lv.mo ADDED
Binary file
trunk/assets/lang/landing-pages-eo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_419.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_AR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_BO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_CL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_CO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_CR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_DO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_EC.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_ES.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_GT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_HN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_MX.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_NI.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_PA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_PE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_PR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_PY.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_SV.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_US.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_UY.mo ADDED
Binary file
trunk/assets/lang/landing-pages-es_VE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-et.mo ADDED
Binary file
trunk/assets/lang/landing-pages-et_EE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-eu.mo ADDED
Binary file
trunk/assets/lang/landing-pages-eu_ES.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fa.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fa_AF.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fa_IR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ff.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ff_SN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fi.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fi_FI.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fil.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fo_FO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fr.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fr_BE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fr_CA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fr_CH.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fr_FR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-frp.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fur.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fy.mo ADDED
Binary file
trunk/assets/lang/landing-pages-fy_NL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ga.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ga_IE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-gan.mo ADDED
Binary file
trunk/assets/lang/landing-pages-gd.mo ADDED
Binary file
trunk/assets/lang/landing-pages-gl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-gl_ES.mo ADDED
Binary file
trunk/assets/lang/landing-pages-gu.mo ADDED
Binary file
trunk/assets/lang/landing-pages-gu_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-gun.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ha.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hak.mo ADDED
Binary file
trunk/assets/lang/landing-pages-haw.mo ADDED
Binary file
trunk/assets/lang/landing-pages-he.mo ADDED
Binary file
trunk/assets/lang/landing-pages-he_IL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hi.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hi_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hne.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hr.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hr_HR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hsb.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hsn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ht.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ht_HT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hu.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hu_HU.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hu_RO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hy.mo ADDED
Binary file
trunk/assets/lang/landing-pages-hy_AM.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ia.mo ADDED
Binary file
trunk/assets/lang/landing-pages-id.mo ADDED
Binary file
trunk/assets/lang/landing-pages-id_ID.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ig.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ilo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-io.mo ADDED
Binary file
trunk/assets/lang/landing-pages-is.mo ADDED
Binary file
trunk/assets/lang/landing-pages-is_IS.mo ADDED
Binary file
trunk/assets/lang/landing-pages-it.mo ADDED
Binary file
trunk/assets/lang/landing-pages-it_CH.mo ADDED
Binary file
trunk/assets/lang/landing-pages-it_IT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-iu.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ja.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ja_JP.mo ADDED
Binary file
trunk/assets/lang/landing-pages-jv.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ka.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ka_GE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-kab.mo ADDED
Binary file
trunk/assets/lang/landing-pages-kl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-kn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-kn_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ksh.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ku.mo ADDED
Binary file
trunk/assets/lang/landing-pages-kw.mo ADDED
Binary file
trunk/assets/lang/landing-pages-la.mo ADDED
Binary file
trunk/assets/lang/landing-pages-lg.mo ADDED
Binary file
trunk/assets/lang/landing-pages-lzh.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mh.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mi.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mn_MN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mni.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mnp.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mr.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mr_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ms.mo ADDED
Binary file
trunk/assets/lang/landing-pages-mw1.mo ADDED
Binary file
trunk/assets/lang/landing-pages-my.mo ADDED
Binary file
trunk/assets/lang/landing-pages-my_MM.mo ADDED
Binary file
trunk/assets/lang/landing-pages-myv.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nah.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nan.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nap.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nb.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nb_NO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ne.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ne_NP.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nia.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nl_BE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nl_NL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nn_NO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-no.mo ADDED
Binary file
trunk/assets/lang/landing-pages-no_NO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nqo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nr.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nso.mo ADDED
Binary file
trunk/assets/lang/landing-pages-nv.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ny.mo ADDED
Binary file
trunk/assets/lang/landing-pages-oc.mo ADDED
Binary file
trunk/assets/lang/landing-pages-om.mo ADDED
Binary file
trunk/assets/lang/landing-pages-or.mo ADDED
Binary file
trunk/assets/lang/landing-pages-or_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-os.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pa.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pa_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pam.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pap.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pfl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pl_PL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pms.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ps.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pt.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pt_BR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-pt_PT.mo ADDED
Binary file
trunk/assets/lang/landing-pages-rm.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ro.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ro_RO.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ru.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ru@petr1708.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ru_RU.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ru_ee.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ru_lt.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ru_lv.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sa.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sah.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sat.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sc.mo ADDED
Binary file
trunk/assets/lang/landing-pages-scn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sco.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sd.mo ADDED
Binary file
trunk/assets/lang/landing-pages-se.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sg.mo ADDED
Binary file
trunk/assets/lang/landing-pages-si.mo ADDED
Binary file
trunk/assets/lang/landing-pages-si_LK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sk.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sk_SK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sl_SI.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sm.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sma.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-so.mo ADDED
Binary file
trunk/assets/lang/landing-pages-son.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sq.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sq_AL.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sr.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sr@Ijekavian.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sr@ijekavianlatin.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sr@latin.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sr_RS.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sr_RS@latin.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ss.mo ADDED
Binary file
trunk/assets/lang/landing-pages-st.mo ADDED
Binary file
trunk/assets/lang/landing-pages-st_ZA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-su.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sv.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sv_FI.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sv_SE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sw.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sw_CD.mo ADDED
Binary file
trunk/assets/lang/landing-pages-sw_KE.mo ADDED
Binary file
trunk/assets/lang/landing-pages-szl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ta.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ta_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ta_LK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-te.mo ADDED
Binary file
trunk/assets/lang/landing-pages-te_IN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tet.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tg.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tg_TJ.mo ADDED
Binary file
trunk/assets/lang/landing-pages-th.mo ADDED
Binary file
trunk/assets/lang/landing-pages-th_TH.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ti.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tk.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tk_TM.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tl_PH.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-to.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tr.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tr_TR.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ts.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tt.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tzl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-tzm.mo ADDED
Binary file
trunk/assets/lang/landing-pages-udm.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ug.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ug@Arab.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ug@Cyrl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ug@Latin.mo ADDED
Binary file
trunk/assets/lang/landing-pages-uk.mo ADDED
Binary file
trunk/assets/lang/landing-pages-uk_UA.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ur.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ur_PK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-uz.mo ADDED
Binary file
trunk/assets/lang/landing-pages-uz@Arab.mo ADDED
Binary file
trunk/assets/lang/landing-pages-uz@Cyrl.mo ADDED
Binary file
trunk/assets/lang/landing-pages-uz@Latn.mo ADDED
Binary file
trunk/assets/lang/landing-pages-uz_UZ.mo ADDED
Binary file
trunk/assets/lang/landing-pages-ve.mo ADDED
Binary file
trunk/assets/lang/landing-pages-vec.mo ADDED
Binary file
trunk/assets/lang/landing-pages-vi.mo ADDED
Binary file
trunk/assets/lang/landing-pages-vi_VN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-vls.mo ADDED
Binary file
trunk/assets/lang/landing-pages-vmf.mo ADDED
Binary file
trunk/assets/lang/landing-pages-wa.mo ADDED
Binary file
trunk/assets/lang/landing-pages-war.mo ADDED
Binary file
trunk/assets/lang/landing-pages-wo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-wo_SN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-wuu.mo ADDED
Binary file
trunk/assets/lang/landing-pages-xh.mo ADDED
Binary file
trunk/assets/lang/landing-pages-yi.mo ADDED
Binary file
trunk/assets/lang/landing-pages-yo.mo ADDED
Binary file
trunk/assets/lang/landing-pages-yue.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zh-Hans.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zh-Hant.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zh.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zh_CN.GB2312.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zh_CN.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zh_HK.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zh_TW.Big5.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zh_TW.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zu.mo ADDED
Binary file
trunk/assets/lang/landing-pages-zu_ZA.mo ADDED
Binary file
trunk/assets/libraries/class-tgm-plugin-activation.php ADDED
@@ -0,0 +1,3541 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin installation and activation for WordPress themes.
4
+ *
5
+ * Please note that this is a drop-in library for a theme or plugin.
6
+ * The authors of this library (Thomas, Gary and Juliette) are NOT responsible
7
+ * for the support of your plugin or theme. Please contact the plugin
8
+ * or theme author for support.
9
+ *
10
+ * @package TGM-Plugin-Activation
11
+ * @version 2.5.0
12
+ * @link http://tgmpluginactivation.com/
13
+ * @author Thomas Griffin, Gary Jones, Juliette Reinders Folmer
14
+ * @copyright Copyright (c) 2011, Thomas Griffin
15
+ * @license GPL-2.0+
16
+ *
17
+ * @wordpress-plugin
18
+ * Plugin Name: TGM Plugin Activation
19
+ * Plugin URI:
20
+ * Description: Plugin installation and activation for WordPress themes.
21
+ * Version: 2.5.0
22
+ * Author: Thomas Griffin, Gary Jones, Juliette Reinders Folmer
23
+ * Author URI: http://tgmpluginactivation.com/
24
+ * Text Domain: tgmpa
25
+ * Domain Path: /languages/
26
+ * Copyright: 2011, Thomas Griffin
27
+ */
28
+
29
+ /*
30
+ Copyright 2011 Thomas Griffin (thomasgriffinmedia.com)
31
+
32
+ This program is free software; you can redistribute it and/or modify
33
+ it under the terms of the GNU General Public License, version 2, as
34
+ published by the Free Software Foundation.
35
+
36
+ This program is distributed in the hope that it will be useful,
37
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
38
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39
+ GNU General Public License for more details.
40
+
41
+ You should have received a copy of the GNU General Public License
42
+ along with this program; if not, write to the Free Software
43
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
44
+ */
45
+
46
+ if ( ! class_exists( 'INBOUND_Plugin_Activation' ) ) {
47
+
48
+ /**
49
+ * Automatic plugin installation and activation library.
50
+ *
51
+ * Creates a way to automatically install and activate plugins from within themes.
52
+ * The plugins can be either bundled, downloaded from the WordPress
53
+ * Plugin Repository or downloaded from another external source.
54
+ *
55
+ * @since 1.0.0
56
+ *
57
+ * @package TGM-Plugin-Activation
58
+ * @author Thomas Griffin
59
+ * @author Gary Jones
60
+ */
61
+ class INBOUND_Plugin_Activation {
62
+ /**
63
+ * TGMPA version number.
64
+ *
65
+ * @since 2.5.0
66
+ *
67
+ * @const string Version number.
68
+ */
69
+ const TGMPA_VERSION = '2.5.0';
70
+
71
+ /**
72
+ * Regular expression to test if a URL is a WP plugin repo URL.
73
+ *
74
+ * @const string Regex.
75
+ *
76
+ * @since 2.5.0
77
+ */
78
+ const WP_REPO_REGEX = '|^http[s]?://wordpress\.org/(?:extend/)?plugins/|';
79
+
80
+ /**
81
+ * Arbitrary regular expression to test if a string starts with a URL.
82
+ *
83
+ * @const string Regex.
84
+ *
85
+ * @since 2.5.0
86
+ */
87
+ const IS_URL_REGEX = '|^http[s]?://|';
88
+
89
+ /**
90
+ * Holds a copy of itself, so it can be referenced by the class name.
91
+ *
92
+ * @since 1.0.0
93
+ *
94
+ * @var INBOUND_Plugin_Activation
95
+ */
96
+ public static $instance;
97
+
98
+ /**
99
+ * Holds arrays of plugin details.
100
+ *
101
+ * @since 1.0.0
102
+ *
103
+ * @since 2.5.0 the array has the plugin slug as an associative key.
104
+ *
105
+ * @var array
106
+ */
107
+ public $plugins = array();
108
+
109
+ /**
110
+ * Holds arrays of plugin names to use to sort the plugins array.
111
+ *
112
+ * @since 2.5.0
113
+ *
114
+ * @var array
115
+ */
116
+ protected $sort_order = array();
117
+
118
+ /**
119
+ * Whether any plugins have the 'force_activation' setting set to true.
120
+ *
121
+ * @since 2.5.0
122
+ *
123
+ * @var bool
124
+ */
125
+ protected $has_forced_activation = false;
126
+
127
+ /**
128
+ * Whether any plugins have the 'force_deactivation' setting set to true.
129
+ *
130
+ * @since 2.5.0
131
+ *
132
+ * @var bool
133
+ */
134
+ protected $has_forced_deactivation = false;
135
+
136
+ /**
137
+ * Name of the unique ID to hash notices.
138
+ *
139
+ * @since 2.4.0
140
+ *
141
+ * @var string
142
+ */
143
+ public $id = 'tgmpa';
144
+
145
+ /**
146
+ * Name of the query-string argument for the admin page.
147
+ *
148
+ * @since 1.0.0
149
+ *
150
+ * @var string
151
+ */
152
+ public $menu = 'tgmpa-install-plugins';
153
+
154
+ /**
155
+ * Parent menu file slug.
156
+ *
157
+ * @since 2.5.0
158
+ *
159
+ * @var string
160
+ */
161
+ public $parent_slug = 'themes.php';
162
+
163
+ /**
164
+ * Capability needed to view the plugin installation menu item.
165
+ *
166
+ * @since 2.5.0
167
+ *
168
+ * @var string
169
+ */
170
+ public $capability = 'edit_theme_options';
171
+
172
+ /**
173
+ * Default absolute path to folder containing bundled plugin zip files.
174
+ *
175
+ * @since 2.0.0
176
+ *
177
+ * @var string Absolute path prefix to zip file location for bundled plugins. Default is empty string.
178
+ */
179
+ public $default_path = '';
180
+
181
+ /**
182
+ * Flag to show admin notices or not.
183
+ *
184
+ * @since 2.1.0
185
+ *
186
+ * @var boolean
187
+ */
188
+ public $has_notices = true;
189
+
190
+ /**
191
+ * Flag to determine if the user can dismiss the notice nag.
192
+ *
193
+ * @since 2.4.0
194
+ *
195
+ * @var boolean
196
+ */
197
+ public $dismissable = true;
198
+
199
+ /**
200
+ * Message to be output above nag notice if dismissable is false.
201
+ *
202
+ * @since 2.4.0
203
+ *
204
+ * @var string
205
+ */
206
+ public $dismiss_msg = '';
207
+
208
+ /**
209
+ * Flag to set automatic activation of plugins. Off by default.
210
+ *
211
+ * @since 2.2.0
212
+ *
213
+ * @var boolean
214
+ */
215
+ public $is_automatic = false;
216
+
217
+ /**
218
+ * Optional message to display before the plugins table.
219
+ *
220
+ * @since 2.2.0
221
+ *
222
+ * @var string Message filtered by wp_kses_post(). Default is empty string.
223
+ */
224
+ public $message = '';
225
+
226
+ /**
227
+ * Holds configurable array of strings.
228
+ *
229
+ * Default values are added in the constructor.
230
+ *
231
+ * @since 2.0.0
232
+ *
233
+ * @var array
234
+ */
235
+ public $strings = array();
236
+
237
+ /**
238
+ * Holds the version of WordPress.
239
+ *
240
+ * @since 2.4.0
241
+ *
242
+ * @var int
243
+ */
244
+ public $wp_version;
245
+
246
+ /**
247
+ * Holds the hook name for the admin page.
248
+ *
249
+ * @since 2.5.0
250
+ *
251
+ * @var string
252
+ */
253
+ public $page_hook;
254
+
255
+ /**
256
+ * Adds a reference of this object to $instance, populates default strings,
257
+ * does the tgmpa_init action hook, and hooks in the interactions to init.
258
+ *
259
+ * @since 1.0.0
260
+ *
261
+ * @see INBOUND_Plugin_Activation::init()
262
+ */
263
+ protected function __construct() {
264
+ // Set the current WordPress version.
265
+ $this->wp_version = $GLOBALS['wp_version'];
266
+
267
+ // Announce that the class is ready, and pass the object (for advanced use).
268
+ do_action_ref_array( 'tgmpa_init', array( $this ) );
269
+
270
+ // When the rest of WP has loaded, kick-start the rest of the class.
271
+ add_action( 'init', array( $this, 'init' ) );
272
+ }
273
+
274
+ /**
275
+ * Initialise the interactions between this class and WordPress.
276
+ *
277
+ * Hooks in three new methods for the class: admin_menu, notices and styles.
278
+ *
279
+ * @since 2.0.0
280
+ *
281
+ * @see INBOUND_Plugin_Activation::admin_menu()
282
+ * @see INBOUND_Plugin_Activation::notices()
283
+ * @see INBOUND_Plugin_Activation::styles()
284
+ */
285
+ public function init() {
286
+ /**
287
+ * By default TGMPA only loads on the WP back-end and not in an Ajax call. Using this filter
288
+ * you can overrule that behaviour.
289
+ *
290
+ * @since 2.5.0
291
+ *
292
+ * @param bool $load Whether or not TGMPA should load.
293
+ * Defaults to the return of `is_admin() && ! defined( 'DOING_AJAX' )`.
294
+ */
295
+ if ( true !== apply_filters( 'tgmpa_load', ( is_admin() && ! defined( 'DOING_AJAX' ) ) ) ) {
296
+ return;
297
+ }
298
+
299
+ // Load class strings.
300
+ $this->strings = array(
301
+ 'page_title' => __( 'Install Required Plugins', 'tgmpa' ),
302
+ 'menu_title' => __( 'Install Plugins', 'tgmpa' ),
303
+ 'installing' => __( 'Installing Plugin: %s', 'tgmpa' ),
304
+ 'oops' => __( 'Something went wrong with the plugin API.', 'tgmpa' ),
305
+ 'notice_can_install_required' => _n_noop(
306
+ 'This theme requires the following plugin: %1$s.',
307
+ 'This theme requires the following plugins: %1$s.',
308
+ 'tgmpa'
309
+ ),
310
+ 'notice_can_install_recommended' => _n_noop(
311
+ 'This theme recommends the following plugin: %1$s.',
312
+ 'This theme recommends the following plugins: %1$s.',
313
+ 'tgmpa'
314
+ ),
315
+ 'notice_cannot_install' => _n_noop(
316
+ 'Sorry, but you do not have the correct permissions to install the %1$s plugin.',
317
+ 'Sorry, but you do not have the correct permissions to install the %1$s plugins.',
318
+ 'tgmpa'
319
+ ),
320
+ 'notice_ask_to_update' => _n_noop(
321
+ 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.',
322
+ 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.',
323
+ 'tgmpa'
324
+ ),
325
+ 'notice_ask_to_update_maybe' => _n_noop(
326
+ 'There is an update available for: %1$s.',
327
+ 'There are updates available for the following plugins: %1$s.',
328
+ 'tgmpa'
329
+ ),
330
+ 'notice_cannot_update' => _n_noop(
331
+ 'Sorry, but you do not have the correct permissions to update the %1$s plugin.',
332
+ 'Sorry, but you do not have the correct permissions to update the %1$s plugins.',
333
+ 'tgmpa'
334
+ ),
335
+ 'notice_can_activate_required' => _n_noop(
336
+ 'The following required plugin is currently inactive: %1$s.',
337
+ 'The following required plugins are currently inactive: %1$s.',
338
+ 'tgmpa'
339
+ ),
340
+ 'notice_can_activate_recommended' => _n_noop(
341
+ 'The following recommended plugin is currently inactive: %1$s.',
342
+ 'The following recommended plugins are currently inactive: %1$s.',
343
+ 'tgmpa'
344
+ ),
345
+ 'notice_cannot_activate' => _n_noop(
346
+ 'Sorry, but you do not have the correct permissions to activate the %1$s plugin.',
347
+ 'Sorry, but you do not have the correct permissions to activate the %1$s plugins.',
348
+ 'tgmpa'
349
+ ),
350
+ 'install_link' => _n_noop(
351
+ 'Begin installing plugin',
352
+ 'Begin installing plugins',
353
+ 'tgmpa'
354
+ ),
355
+ 'update_link' => _n_noop(
356
+ 'Begin updating plugin',
357
+ 'Begin updating plugins',
358
+ 'tgmpa'
359
+ ),
360
+ 'activate_link' => _n_noop(
361
+ 'Begin activating plugin',
362
+ 'Begin activating plugins',
363
+ 'tgmpa'
364
+ ),
365
+ 'return' => __( 'Return to Required Plugins Installer', 'tgmpa' ),
366
+ 'dashboard' => __( 'Return to the dashboard', 'tgmpa' ),
367
+ 'plugin_activated' => __( 'Plugin activated successfully.', 'tgmpa' ),
368
+ 'activated_successfully' => __( 'The following plugin was activated successfully:', 'tgmpa' ),
369
+ 'plugin_already_active' => __( 'No action taken. Plugin %1$s was already active.', 'tgmpa' ),
370
+ 'plugin_needs_higher_version' => __( 'Plugin not activated. A higher version of %s is needed for this theme. Please update the plugin.', 'tgmpa' ),
371
+ 'complete' => __( 'All plugins installed and activated successfully. %1$s', 'tgmpa' ),
372
+ 'dismiss' => __( 'Dismiss this notice', 'tgmpa' ),
373
+ 'contact_admin' => __( 'Please contact the administrator of this site for help.', 'tgmpa' ),
374
+ );
375
+
376
+ do_action( 'tgmpa_register' );
377
+
378
+ /* After this point, the plugins should be registered and the configuration set. */
379
+
380
+ // Proceed only if we have plugins to handle.
381
+ if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) {
382
+ return;
383
+ }
384
+
385
+ // Set up the menu and notices if we still have outstanding actions.
386
+ if ( true !== $this->is_tgmpa_complete() ) {
387
+ // Sort the plugins.
388
+ array_multisort( $this->sort_order, SORT_ASC, $this->plugins );
389
+
390
+ add_action( 'admin_menu', array( $this, 'admin_menu' ) );
391
+ add_action( 'admin_head', array( $this, 'dismiss' ) );
392
+
393
+ // Prevent the normal links from showing underneath a single install/update page.
394
+ add_filter( 'install_plugin_complete_actions', array( $this, 'actions' ) );
395
+ add_filter( 'update_plugin_complete_actions', array( $this, 'actions' ) );
396
+
397
+ if ( $this->has_notices ) {
398
+ add_action( 'admin_notices', array( $this, 'notices' ) );
399
+ add_action( 'admin_init', array( $this, 'admin_init' ), 1 );
400
+ add_action( 'admin_enqueue_scripts', array( $this, 'thickbox' ) );
401
+ }
402
+
403
+ add_action( 'load-plugins.php', array( $this, 'add_plugin_action_link_filters' ), 1 );
404
+ }
405
+
406
+ // Make sure things get reset on switch theme.
407
+ add_action( 'switch_theme', array( $this, 'flush_plugins_cache' ) );
408
+
409
+ if ( $this->has_notices ) {
410
+ add_action( 'switch_theme', array( $this, 'update_dismiss' ) );
411
+ }
412
+
413
+ // Setup the force activation hook.
414
+ if ( true === $this->has_forced_activation ) {
415
+ add_action( 'admin_init', array( $this, 'force_activation' ) );
416
+ }
417
+
418
+ // Setup the force deactivation hook.
419
+ if ( true === $this->has_forced_deactivation ) {
420
+ add_action( 'switch_theme', array( $this, 'force_deactivation' ) );
421
+ }
422
+ }
423
+
424
+ /**
425
+ * Prevent activation of plugins which don't meet the minimum version requirement from the
426
+ * WP native plugins page.
427
+ *
428
+ * @since 2.5.0
429
+ */
430
+ public function add_plugin_action_link_filters() {
431
+ foreach ( $this->plugins as $slug => $plugin ) {
432
+ if ( false === $this->can_plugin_activate( $slug ) ) {
433
+ add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_activate' ), 20 );
434
+ }
435
+
436
+ if ( true === $plugin['force_activation'] ) {
437
+ add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_deactivate' ), 20 );
438
+ }
439
+
440
+ if ( false !== $this->does_plugin_require_update( $slug ) ) {
441
+ add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_update' ), 20 );
442
+ }
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Remove the 'Activate' link on the WP native plugins page if the plugin does not meet the
448
+ * minimum version requirements.
449
+ *
450
+ * @since 2.5.0
451
+ *
452
+ * @param array $actions Action links.
453
+ * @return array
454
+ */
455
+ public function filter_plugin_action_links_activate( $actions ) {
456
+ unset( $actions['activate'] );
457
+
458
+ return $actions;
459
+ }
460
+
461
+ /**
462
+ * Remove the 'Deactivate' link on the WP native plugins page if the plugin has been set to force activate.
463
+ *
464
+ * @since 2.5.0
465
+ *
466
+ * @param array $actions Action links.
467
+ * @return array
468
+ */
469
+ public function filter_plugin_action_links_deactivate( $actions ) {
470
+ unset( $actions['deactivate'] );
471
+
472
+ return $actions;
473
+ }
474
+
475
+ /**
476
+ * Add a 'Requires update' link on the WP native plugins page if the plugin does not meet the
477
+ * minimum version requirements.
478
+ *
479
+ * @since 2.5.0
480
+ *
481
+ * @param array $actions Action links.
482
+ * @return array
483
+ */
484
+ public function filter_plugin_action_links_update( $actions ) {
485
+ $actions['update'] = sprintf(
486
+ '<a href="%1$s" title="%2$s" class="edit">%3$s</a>',
487
+ esc_url( $this->get_tgmpa_status_url( 'update' ) ),
488
+ esc_attr__( 'This plugin needs to be updated to be compatible with your theme.', 'tgmpa' ),
489
+ esc_html__( 'Update Required', 'tgmpa' )
490
+ );
491
+
492
+ return $actions;
493
+ }
494
+
495
+ /**
496
+ * Handles calls to show plugin information via links in the notices.
497
+ *
498
+ * We get the links in the admin notices to point to the TGMPA page, rather
499
+ * than the typical plugin-install.php file, so we can prepare everything
500
+ * beforehand.
501
+ *
502
+ * WP does not make it easy to show the plugin information in the thickbox -
503
+ * here we have to require a file that includes a function that does the
504
+ * main work of displaying it, enqueue some styles, set up some globals and
505
+ * finally call that function before exiting.
506
+ *
507
+ * Down right easy once you know how...
508
+ *
509
+ * Returns early if not the TGMPA page.
510
+ *
511
+ * @since 2.1.0
512
+ *
513
+ * @global string $tab Used as iframe div class names, helps with styling
514
+ * @global string $body_id Used as the iframe body ID, helps with styling
515
+ *
516
+ * @return null Returns early if not the TGMPA page.
517
+ */
518
+ public function admin_init() {
519
+ if ( ! $this->is_tgmpa_page() ) {
520
+ return;
521
+ }
522
+
523
+ if ( isset( $_REQUEST['tab'] ) && 'plugin-information' === $_REQUEST['tab'] ) {
524
+ // Needed for install_plugin_information().
525
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
526
+
527
+ wp_enqueue_style( 'plugin-install' );
528
+
529
+ global $tab, $body_id;
530
+ $body_id = 'plugin-information';
531
+ // @codingStandardsIgnoreStart
532
+ $tab = 'plugin-information';
533
+ // @codingStandardsIgnoreEnd
534
+
535
+ install_plugin_information();
536
+
537
+ exit;
538
+ }
539
+ }
540
+
541
+ /**
542
+ * Enqueue thickbox scripts/styles for plugin info.
543
+ *
544
+ * Thickbox is not automatically included on all admin pages, so we must
545
+ * manually enqueue it for those pages.
546
+ *
547
+ * Thickbox is only loaded if the user has not dismissed the admin
548
+ * notice or if there are any plugins left to install and activate.
549
+ *
550
+ * @since 2.1.0
551
+ */
552
+ public function thickbox() {
553
+ if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) {
554
+ add_thickbox();
555
+ }
556
+ }
557
+
558
+ /**
559
+ * Adds submenu page if there are plugin actions to take.
560
+ *
561
+ * This method adds the submenu page letting users know that a required
562
+ * plugin needs to be installed.
563
+ *
564
+ * This page disappears once the plugin has been installed and activated.
565
+ *
566
+ * @since 1.0.0
567
+ *
568
+ * @see INBOUND_Plugin_Activation::init()
569
+ * @see INBOUND_Plugin_Activation::install_plugins_page()
570
+ *
571
+ * @return null Return early if user lacks capability to install a plugin.
572
+ */
573
+ public function admin_menu() {
574
+ // Make sure privileges are correct to see the page.
575
+ if ( ! current_user_can( 'install_plugins' ) ) {
576
+ return;
577
+ }
578
+
579
+ $args = apply_filters(
580
+ 'tgmpa_admin_menu_args',
581
+ array(
582
+ 'parent_slug' => $this->parent_slug, // Parent Menu slug.
583
+ 'page_title' => $this->strings['page_title'], // Page title.
584
+ 'menu_title' => $this->strings['menu_title'], // Menu title.
585
+ 'capability' => $this->capability, // Capability.
586
+ 'menu_slug' => $this->menu, // Menu slug.
587
+ 'function' => array( $this, 'install_plugins_page' ), // Callback.
588
+ )
589
+ );
590
+
591
+ $this->add_admin_menu( $args );
592
+ }
593
+
594
+ /**
595
+ * Add the menu item.
596
+ *
597
+ * @since 2.5.0
598
+ *
599
+ * @param array $args Menu item configuration.
600
+ */
601
+ protected function add_admin_menu( array $args ) {
602
+ if ( has_filter( 'tgmpa_admin_menu_use_add_theme_page' ) ) {
603
+ _deprecated_function( 'The "tgmpa_admin_menu_use_add_theme_page" filter', '2.5.0', esc_html__( 'Set the parent_slug config variable instead.', 'tgmpa' ) );
604
+ }
605
+
606
+ if ( 'themes.php' === $this->parent_slug ) {
607
+ $this->page_hook = call_user_func( 'add_theme_page', $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
608
+ } else {
609
+ $this->page_hook = call_user_func( 'add_submenu_page', $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
610
+ }
611
+ }
612
+
613
+ /**
614
+ * Echoes plugin installation form.
615
+ *
616
+ * This method is the callback for the admin_menu method function.
617
+ * This displays the admin page and form area where the user can select to install and activate the plugin.
618
+ * Aborts early if we're processing a plugin installation action.
619
+ *
620
+ * @since 1.0.0
621
+ *
622
+ * @return null Aborts early if we're processing a plugin installation action.
623
+ */
624
+ public function install_plugins_page() {
625
+ // Store new instance of plugin table in object.
626
+ $plugin_table = new INBOUND_TGMPA_List_Table;
627
+
628
+ // Return early if processing a plugin installation action.
629
+ if ( ( ( 'tgmpa-bulk-install' === $plugin_table->current_action() || 'tgmpa-bulk-update' === $plugin_table->current_action() ) && $plugin_table->process_bulk_actions() ) || $this->do_plugin_install() ) {
630
+ return;
631
+ }
632
+
633
+ // Force refresh of available plugin information so we'll know about manual updates/deletes.
634
+ wp_clean_plugins_cache( false );
635
+
636
+ ?>
637
+ <div class="tgmpa wrap">
638
+ <h2><?php echo esc_html( get_admin_page_title() ); ?></h2>
639
+ <?php $plugin_table->prepare_items(); ?>
640
+
641
+ <?php
642
+ if ( ! empty( $this->message ) && is_string( $this->message ) ) {
643
+ echo wp_kses_post( $this->message );
644
+ }
645
+ ?>
646
+ <?php $plugin_table->views(); ?>
647
+
648
+ <form id="tgmpa-plugins" action="" method="post">
649
+ <input type="hidden" name="tgmpa-page" value="<?php echo esc_attr( $this->menu ); ?>" />
650
+ <input type="hidden" name="plugin_status" value="<?php echo esc_attr( $plugin_table->view_context ); ?>" />
651
+ <?php $plugin_table->display(); ?>
652
+ </form>
653
+ </div>
654
+ <?php
655
+ }
656
+
657
+ /**
658
+ * Installs, updates or activates a plugin depending on the action link clicked by the user.
659
+ *
660
+ * Checks the $_GET variable to see which actions have been
661
+ * passed and responds with the appropriate method.
662
+ *
663
+ * Uses WP_Filesystem to process and handle the plugin installation
664
+ * method.
665
+ *
666
+ * @since 1.0.0
667
+ *
668
+ * @uses WP_Filesystem
669
+ * @uses WP_Error
670
+ * @uses WP_Upgrader
671
+ * @uses Plugin_Upgrader
672
+ * @uses Plugin_Installer_Skin
673
+ * @uses Plugin_Upgrader_Skin
674
+ *
675
+ * @return boolean True on success, false on failure.
676
+ */
677
+ protected function do_plugin_install() {
678
+ if ( empty( $_GET['plugin'] ) ) {
679
+ return false;
680
+ }
681
+
682
+ // All plugin information will be stored in an array for processing.
683
+ $slug = $this->sanitize_key( urldecode( $_GET['plugin'] ) );
684
+
685
+ if ( ! isset( $this->plugins[ $slug ] ) ) {
686
+ return false;
687
+ }
688
+
689
+ // Was an install or upgrade action link clicked?
690
+ if ( ( isset( $_GET['tgmpa-install'] ) && 'install-plugin' === $_GET['tgmpa-install'] ) || ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) ) {
691
+
692
+ $install_type = 'install';
693
+ if ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) {
694
+ $install_type = 'update';
695
+ }
696
+
697
+ check_admin_referer( 'tgmpa-' . $install_type, 'tgmpa-nonce' );
698
+
699
+ // Pass necessary information via URL if WP_Filesystem is needed.
700
+ $url = wp_nonce_url(
701
+ add_query_arg(
702
+ array(
703
+ 'plugin' => urlencode( $slug ),
704
+ 'tgmpa-' . $install_type => $install_type . '-plugin',
705
+ ),
706
+ $this->get_tgmpa_url()
707
+ ),
708
+ 'tgmpa-' . $install_type,
709
+ 'tgmpa-nonce'
710
+ );
711
+
712
+ $method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
713
+
714
+ if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, array() ) ) ) {
715
+ return true;
716
+ }
717
+
718
+ if ( ! WP_Filesystem( $creds ) ) {
719
+ request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, array() ); // Setup WP_Filesystem.
720
+ return true;
721
+ }
722
+
723
+ /* If we arrive here, we have the filesystem. */
724
+
725
+ // Prep variables for Plugin_Installer_Skin class.
726
+ $extra = array();
727
+ $extra['slug'] = $slug; // Needed for potentially renaming of directory name.
728
+ $source = $this->get_download_url( $slug );
729
+ $api = ( 'repo' === $this->plugins[ $slug ]['source_type'] ) ? $this->get_plugins_api( $slug ) : null;
730
+ $api = ( false !== $api ) ? $api : null;
731
+
732
+ $url = add_query_arg(
733
+ array(
734
+ 'action' => $install_type . '-plugin',
735
+ 'plugin' => urlencode( $slug ),
736
+ ),
737
+ 'update.php'
738
+ );
739
+
740
+ if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
741
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
742
+ }
743
+
744
+ $skin_args = array(
745
+ 'type' => ( 'bundled' !== $this->plugins[ $slug ]['source_type'] ) ? 'web' : 'upload',
746
+ 'title' => sprintf( $this->strings['installing'], $this->plugins[ $slug ]['name'] ),
747
+ 'url' => esc_url_raw( $url ),
748
+ 'nonce' => $install_type . '-plugin_' . $slug,
749
+ 'plugin' => '',
750
+ 'api' => $api,
751
+ 'extra' => $extra,
752
+ );
753
+
754
+ if ( 'update' === $install_type ) {
755
+ $skin_args['plugin'] = $this->plugins[ $slug ]['file_path'];
756
+ $skin = new Plugin_Upgrader_Skin( $skin_args );
757
+ } else {
758
+ $skin = new Plugin_Installer_Skin( $skin_args );
759
+ }
760
+
761
+ // Create a new instance of Plugin_Upgrader.
762
+ $upgrader = new Plugin_Upgrader( $skin );
763
+
764
+ // Perform the action and install the plugin from the $source urldecode().
765
+ add_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
766
+
767
+ if ( 'update' === $install_type ) {
768
+ // Inject our info into the update transient.
769
+ $to_inject = array( $slug => $this->plugins[ $slug ] );
770
+ $to_inject[ $slug ]['source'] = $source;
771
+ $this->inject_update_info( $to_inject );
772
+
773
+ $upgrader->upgrade( $this->plugins[ $slug ]['file_path'] );
774
+ } else {
775
+ $upgrader->install( $source );
776
+ }
777
+
778
+ remove_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
779
+
780
+ // Make sure we have the correct file path now the plugin is installed/updated.
781
+ $this->populate_file_path( $slug );
782
+
783
+ // Only activate plugins if the config option is set to true and the plugin isn't
784
+ // already active (upgrade).
785
+ if ( $this->is_automatic && ! $this->is_plugin_active( $slug ) ) {
786
+ $plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method.
787
+ if ( false === $this->activate_single_plugin( $plugin_activate, $slug, true ) ) {
788
+ return true; // Finish execution of the function early as we encountered an error.
789
+ }
790
+ }
791
+
792
+ $this->show_tgmpa_version();
793
+
794
+ // Display message based on if all plugins are now active or not.
795
+ if ( $this->is_tgmpa_complete() ) {
796
+ echo '<p>', sprintf( esc_html( $this->strings['complete'] ), '<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>' ), '</p>';
797
+ echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
798
+ } else {
799
+ echo '<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
800
+ }
801
+
802
+ return true;
803
+ } elseif ( isset( $this->plugins[ $slug ]['file_path'], $_GET['tgmpa-activate'] ) && 'activate-plugin' === $_GET['tgmpa-activate'] ) {
804
+ // Activate action link was clicked.
805
+ check_admin_referer( 'tgmpa-activate', 'tgmpa-nonce' );
806
+
807
+ if ( false === $this->activate_single_plugin( $this->plugins[ $slug ]['file_path'], $slug ) ) {
808
+ return true; // Finish execution of the function early as we encountered an error.
809
+ }
810
+ }
811
+
812
+ return false;
813
+ }
814
+
815
+ /**
816
+ * Inject information into the 'update_plugins' site transient as WP checks that before running an update.
817
+ *
818
+ * @since 2.5.0
819
+ *
820
+ * @param array $plugins The plugin information for the plugins which are to be updated.
821
+ */
822
+ public function inject_update_info( $plugins ) {
823
+ $repo_updates = get_site_transient( 'update_plugins' );
824
+
825
+ if ( ! is_object( $repo_updates ) ) {
826
+ $repo_updates = new stdClass;
827
+ }
828
+
829
+ foreach ( $plugins as $slug => $plugin ) {
830
+ $file_path = $plugin['file_path'];
831
+
832
+ if ( empty( $repo_updates->response[ $file_path ] ) ) {
833
+ $repo_updates->response[ $file_path ] = new stdClass;
834
+ }
835
+
836
+ // We only really need to set package, but let's do all we can in case WP changes something.
837
+ $repo_updates->response[ $file_path ]->slug = $slug;
838
+ $repo_updates->response[ $file_path ]->plugin = $file_path;
839
+ $repo_updates->response[ $file_path ]->new_version = $plugin['version'];
840
+ $repo_updates->response[ $file_path ]->package = $plugin['source'];
841
+ if ( empty( $repo_updates->response[ $file_path ]->url ) && ! empty( $plugin['external_url'] ) ) {
842
+ $repo_updates->response[ $file_path ]->url = $plugin['external_url'];
843
+ }
844
+ }
845
+
846
+ set_site_transient( 'update_plugins', $repo_updates );
847
+ }
848
+
849
+ /**
850
+ * Adjust the plugin directory name if necessary.
851
+ *
852
+ * The final destination directory of a plugin is based on the subdirectory name found in the
853
+ * (un)zipped source. In some cases - most notably GitHub repository plugin downloads -, this
854
+ * subdirectory name is not the same as the expected slug and the plugin will not be recognized
855
+ * as installed. This is fixed by adjusting the temporary unzipped source subdirectory name to
856
+ * the expected plugin slug.
857
+ *
858
+ * @since 2.5.0
859
+ *
860
+ * @param string $source Path to upgrade/zip-file-name.tmp/subdirectory/.
861
+ * @param string $remote_source Path to upgrade/zip-file-name.tmp.
862
+ * @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin.
863
+ * @return string $source
864
+ */
865
+ public function maybe_adjust_source_dir( $source, $remote_source, $upgrader ) {
866
+ if ( ! $this->is_tgmpa_page() || ! is_object( $GLOBALS['wp_filesystem'] ) ) {
867
+ return $source;
868
+ }
869
+
870
+ // Check for single file plugins.
871
+ $source_files = array_keys( $GLOBALS['wp_filesystem']->dirlist( $remote_source ) );
872
+ if ( 1 === count( $source_files ) && false === $GLOBALS['wp_filesystem']->is_dir( $source ) ) {
873
+ return $source;
874
+ }
875
+
876
+ // Multi-file plugin, let's see if the directory is correctly named.
877
+ $desired_slug = '';
878
+
879
+ // Figure out what the slug is supposed to be.
880
+ if ( false === $upgrader->bulk && ! empty( $upgrader->skin->options['extra']['slug'] ) ) {
881
+ $desired_slug = $upgrader->skin->options['extra']['slug'];
882
+ } else {
883
+ // Bulk installer contains less info, so fall back on the info registered here.
884
+ foreach ( $this->plugins as $slug => $plugin ) {
885
+ if ( ! empty( $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) && $plugin['name'] === $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) {
886
+ $desired_slug = $slug;
887
+ break;
888
+ }
889
+ }
890
+ unset( $slug, $plugin );
891
+ }
892
+
893
+ if ( ! empty( $desired_slug ) ) {
894
+ $subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) );
895
+
896
+ if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) {
897
+ $from = untrailingslashit( $source );
898
+ $to = trailingslashit( $remote_source ) . $desired_slug;
899
+
900
+ if ( true === $GLOBALS['wp_filesystem']->move( $from, $to ) ) {
901
+ return trailingslashit( $to );
902
+ } else {
903
+ return new WP_Error( 'rename_failed', esc_html__( 'The remote plugin package does not contain a folder with the desired slug and renaming did not work.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
904
+ }
905
+ } elseif ( empty( $subdir_name ) ) {
906
+ return new WP_Error( 'packaged_wrong', esc_html__( 'The remote plugin package consists of more than one file, but the files are not packaged in a folder.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
907
+ }
908
+ }
909
+
910
+ return $source;
911
+ }
912
+
913
+ /**
914
+ * Activate a single plugin and send feedback about the result to the screen.
915
+ *
916
+ * @since 2.5.0
917
+ *
918
+ * @param string $file_path Path within wp-plugins/ to main plugin file.
919
+ * @param string $slug Plugin slug.
920
+ * @param bool $automatic Whether this is an automatic activation after an install. Defaults to false.
921
+ * This determines the styling of the output messages.
922
+ * @return bool False if an error was encountered, true otherwise.
923
+ */
924
+ protected function activate_single_plugin( $file_path, $slug, $automatic = false ) {
925
+ if ( $this->can_plugin_activate( $slug ) ) {
926
+ $activate = activate_plugin( $file_path );
927
+
928
+ if ( is_wp_error( $activate ) ) {
929
+ echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>',
930
+ '<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
931
+
932
+ return false; // End it here if there is an error with activation.
933
+ } else {
934
+ if ( ! $automatic ) {
935
+ // Make sure message doesn't display again if bulk activation is performed
936
+ // immediately after a single activation.
937
+ if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
938
+ echo '<div id="message" class="updated"><p>', esc_html( $this->strings['activated_successfully'] ), ' <strong>', esc_html( $this->plugins[ $slug ]['name'] ), '.</strong></p></div>';
939
+ }
940
+ } else {
941
+ // Simpler message layout for use on the plugin install page.
942
+ echo '<p>', esc_html( $this->strings['plugin_activated'] ), '</p>';
943
+ }
944
+ }
945
+ } elseif ( $this->is_plugin_active( $slug ) ) {
946
+ // No simpler message format provided as this message should never be encountered
947
+ // on the plugin install page.
948
+ echo '<div id="message" class="error"><p>',
949
+ sprintf(
950
+ esc_html( $this->strings['plugin_already_active'] ),
951
+ '<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
952
+ ),
953
+ '</p></div>';
954
+ } elseif ( $this->does_plugin_require_update( $slug ) ) {
955
+ if ( ! $automatic ) {
956
+ // Make sure message doesn't display again if bulk activation is performed
957
+ // immediately after a single activation.
958
+ if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
959
+ echo '<div id="message" class="error"><p>',
960
+ sprintf(
961
+ esc_html( $this->strings['plugin_needs_higher_version'] ),
962
+ '<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
963
+ ),
964
+ '</p></div>';
965
+ }
966
+ } else {
967
+ // Simpler message layout for use on the plugin install page.
968
+ echo '<p>', sprintf( esc_html( $this->strings['plugin_needs_higher_version'] ), esc_html( $this->plugins[ $slug ]['name'] ) ), '</p>';
969
+ }
970
+ }
971
+
972
+ return true;
973
+ }
974
+
975
+ /**
976
+ * Echoes required plugin notice.
977
+ *
978
+ * Outputs a message telling users that a specific plugin is required for
979
+ * their theme. If appropriate, it includes a link to the form page where
980
+ * users can install and activate the plugin.
981
+ *
982
+ * Returns early if we're on the Install page.
983
+ *
984
+ * @since 1.0.0
985
+ *
986
+ * @global object $current_screen
987
+ *
988
+ * @return null Returns early if we're on the Install page.
989
+ */
990
+ public function notices() {
991
+ // Remove nag on the install page / Return early if the nag message has been dismissed.
992
+ if ( $this->is_tgmpa_page() || get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) {
993
+ return;
994
+ }
995
+
996
+ // Store for the plugin slugs by message type.
997
+ $message = array();
998
+
999
+ // Initialize counters used to determine plurality of action link texts.
1000
+ $install_link_count = 0;
1001
+ $update_link_count = 0;
1002
+ $activate_link_count = 0;
1003
+
1004
+ foreach ( $this->plugins as $slug => $plugin ) {
1005
+ if ( $this->is_plugin_active( $slug ) && false === $this->does_plugin_have_update( $slug ) ) {
1006
+ continue;
1007
+ }
1008
+
1009
+ if ( ! $this->is_plugin_installed( $slug ) ) {
1010
+ if ( current_user_can( 'install_plugins' ) ) {
1011
+ $install_link_count++;
1012
+
1013
+ if ( true === $plugin['required'] ) {
1014
+ $message['notice_can_install_required'][] = $slug;
1015
+ } else {
1016
+ $message['notice_can_install_recommended'][] = $slug;
1017
+ }
1018
+ } else {
1019
+ // Need higher privileges to install the plugin.
1020
+ $message['notice_cannot_install'][] = $slug;
1021
+ }
1022
+ } else {
1023
+ if ( ! $this->is_plugin_active( $slug ) && $this->can_plugin_activate( $slug ) ) {
1024
+ if ( current_user_can( 'activate_plugins' ) ) {
1025
+ $activate_link_count++;
1026
+
1027
+ if ( true === $plugin['required'] ) {
1028
+ $message['notice_can_activate_required'][] = $slug;
1029
+ } else {
1030
+ $message['notice_can_activate_recommended'][] = $slug;
1031
+ }
1032
+ } else {
1033
+ // Need higher privileges to activate the plugin.
1034
+ $message['notice_cannot_activate'][] = $slug;
1035
+ }
1036
+ }
1037
+
1038
+ if ( $this->does_plugin_require_update( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
1039
+
1040
+ if ( current_user_can( 'install_plugins' ) ) {
1041
+ $update_link_count++;
1042
+
1043
+ if ( $this->does_plugin_require_update( $slug ) ) {
1044
+ $message['notice_ask_to_update'][] = $slug;
1045
+ } elseif ( false !== $this->does_plugin_have_update( $slug ) ) {
1046
+ $message['notice_ask_to_update_maybe'][] = $slug;
1047
+ }
1048
+ } else {
1049
+ // Need higher privileges to update the plugin.
1050
+ $message['notice_cannot_update'][] = $slug;
1051
+ }
1052
+ }
1053
+ }
1054
+ }
1055
+ unset( $slug, $plugin );
1056
+
1057
+ // If we have notices to display, we move forward.
1058
+ if ( ! empty( $message ) ) {
1059
+ krsort( $message ); // Sort messages.
1060
+ $rendered = '';
1061
+
1062
+ // As add_settings_error() wraps the final message in a <p> and as the final message can't be
1063
+ // filtered, using <p>'s in our html would render invalid html output.
1064
+ $line_template = '<span style="display: block; margin: 0.5em 0.5em 0 0; clear: both;">%s</span>' . "\n";
1065
+
1066
+ // If dismissable is false and a message is set, output it now.
1067
+ if ( ! $this->dismissable && ! empty( $this->dismiss_msg ) ) {
1068
+ $rendered .= sprintf( $line_template, wp_kses_post( $this->dismiss_msg ) );
1069
+ }
1070
+
1071
+ // Render the individual message lines for the notice.
1072
+ foreach ( $message as $type => $plugin_group ) {
1073
+ $linked_plugins = array();
1074
+
1075
+ // Get the external info link for a plugin if one is available.
1076
+ foreach ( $plugin_group as $plugin_slug ) {
1077
+ $linked_plugins[] = $this->get_info_link( $plugin_slug );
1078
+ }
1079
+ unset( $plugin_slug );
1080
+
1081
+ $count = count( $plugin_group );
1082
+ $linked_plugins = array_map( array( 'INBOUND_TGM_Utils', 'wrap_in_em' ), $linked_plugins );
1083
+ $last_plugin = array_pop( $linked_plugins ); // Pop off last name to prep for readability.
1084
+
1085
+ $imploded = empty( $linked_plugins ) ? $last_plugin : ( implode( ', ', $linked_plugins ) . ' <span class="inbound-and">and</span>' . ' ' . $last_plugin );
1086
+
1087
+ $rendered .= sprintf(
1088
+ $line_template,
1089
+ sprintf(
1090
+ translate_nooped_plural( $this->strings[ $type ], $count, 'tgmpa' ),
1091
+ $imploded,
1092
+ $count
1093
+ )
1094
+ );
1095
+
1096
+ if ( 0 === strpos( $type, 'notice_cannot' ) ) {
1097
+ $rendered .= $this->strings['contact_admin'];
1098
+ }
1099
+ }
1100
+ unset( $type, $plugin_group, $linked_plugins, $count, $last_plugin, $imploded );
1101
+
1102
+ // Setup action links.
1103
+ $action_links = array(
1104
+ 'install' => '',
1105
+ 'update' => '',
1106
+ 'activate' => '',
1107
+ 'dismiss' => $this->dismissable ? '<a href="' . esc_url( add_query_arg( 'tgmpa-dismiss', 'dismiss_admin_notices' ) ) . '" class="dismiss-notice" target="_parent">' . esc_html( $this->strings['dismiss'] ) . '</a>' : '',
1108
+ );
1109
+
1110
+ $link_template = '<a href="%2$s">%1$s</a>';
1111
+
1112
+ if ( current_user_can( 'install_plugins' ) ) {
1113
+ if ( $install_link_count > 0 ) {
1114
+ $action_links['install'] = sprintf(
1115
+ $link_template,
1116
+ translate_nooped_plural( $this->strings['install_link'], $install_link_count, 'tgmpa' ),
1117
+ esc_url( $this->get_tgmpa_status_url( 'install' ) )
1118
+ );
1119
+ }
1120
+ if ( $update_link_count > 0 ) {
1121
+ $action_links['update'] = sprintf(
1122
+ $link_template,
1123
+ translate_nooped_plural( $this->strings['update_link'], $update_link_count, 'tgmpa' ),
1124
+ esc_url( $this->get_tgmpa_status_url( 'update' ) )
1125
+ );
1126
+ }
1127
+ }
1128
+
1129
+ if ( current_user_can( 'activate_plugins' ) && $activate_link_count > 0 ) {
1130
+ $action_links['activate'] = sprintf(
1131
+ $link_template,
1132
+ translate_nooped_plural( $this->strings['activate_link'], $activate_link_count, 'tgmpa' ),
1133
+ esc_url( $this->get_tgmpa_status_url( 'activate' ) )
1134
+ );
1135
+ }
1136
+
1137
+ $action_links = apply_filters( 'tgmpa_notice_action_links', $action_links );
1138
+
1139
+ $action_links = array_filter( (array) $action_links ); // Remove any empty array items.
1140
+
1141
+ if ( ! empty( $action_links ) && is_array( $action_links ) ) {
1142
+ $action_links = sprintf( $line_template, implode( ' | ', $action_links ) );
1143
+ $rendered .= apply_filters( 'tgmpa_notice_rendered_action_links', $action_links );
1144
+ }
1145
+
1146
+ // Register the nag messages and prepare them to be processed.
1147
+ if ( ! empty( $this->strings['nag_type'] ) ) {
1148
+ add_settings_error( 'tgmpa', 'tgmpa', $rendered, sanitize_html_class( strtolower( $this->strings['nag_type'] ) ) );
1149
+ } else {
1150
+ $nag_class = version_compare( $this->wp_version, '3.8', '<' ) ? 'updated' : 'update-nag';
1151
+ add_settings_error( 'tgmpa', 'tgmpa', $rendered, $nag_class );
1152
+ }
1153
+ }
1154
+
1155
+ // Admin options pages already output settings_errors, so this is to avoid duplication.
1156
+ if ( 'options-general' !== $GLOBALS['current_screen']->parent_base ) {
1157
+ $this->display_settings_errors();
1158
+ }
1159
+ }
1160
+
1161
+ /**
1162
+ * Display settings errors and remove those which have been displayed to avoid duplicate messages showing
1163
+ *
1164
+ * @since 2.5.0
1165
+ */
1166
+ protected function display_settings_errors() {
1167
+ global $wp_settings_errors;
1168
+
1169
+ settings_errors( 'tgmpa' );
1170
+
1171
+ foreach ( (array) $wp_settings_errors as $key => $details ) {
1172
+ if ( 'tgmpa' === $details['setting'] ) {
1173
+ unset( $wp_settings_errors[ $key ] );
1174
+ break;
1175
+ }
1176
+ }
1177
+ }
1178
+
1179
+ /**
1180
+ * Add dismissable admin notices.
1181
+ *
1182
+ * Appends a link to the admin nag messages. If clicked, the admin notice disappears and no longer is visible to users.
1183
+ *
1184
+ * @since 2.1.0
1185
+ */
1186
+ public function dismiss() {
1187
+ if ( isset( $_GET['tgmpa-dismiss'] ) ) {
1188
+ update_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, 1 );
1189
+ }
1190
+ }
1191
+
1192
+ /**
1193
+ * Add individual plugin to our collection of plugins.
1194
+ *
1195
+ * If the required keys are not set or the plugin has already
1196
+ * been registered, the plugin is not added.
1197
+ *
1198
+ * @since 2.0.0
1199
+ *
1200
+ * @param array|null $plugin Array of plugin arguments or null if invalid argument.
1201
+ * @return null Return early if incorrect argument.
1202
+ */
1203
+ public function register( $plugin ) {
1204
+ if ( empty( $plugin['slug'] ) || empty( $plugin['name'] ) ) {
1205
+ return;
1206
+ }
1207
+
1208
+ if ( empty( $plugin['slug'] ) || ! is_string( $plugin['slug'] ) || isset( $this->plugins[ $plugin['slug'] ] ) ) {
1209
+ return;
1210
+ }
1211
+
1212
+ $defaults = array(
1213
+ 'name' => '', // String
1214
+ 'slug' => '', // String
1215
+ 'source' => 'repo', // String
1216
+ 'required' => false, // Boolean
1217
+ 'version' => '', // String
1218
+ 'force_activation' => false, // Boolean
1219
+ 'force_deactivation' => false, // Boolean
1220
+ 'external_url' => '', // String
1221
+ 'is_callable' => '', // String|Array.
1222
+ );
1223
+
1224
+ // Prepare the received data.
1225
+ $plugin = wp_parse_args( $plugin, $defaults );
1226
+
1227
+ // Standardize the received slug.
1228
+ $plugin['slug'] = $this->sanitize_key( $plugin['slug'] );
1229
+
1230
+ // Forgive users for using string versions of booleans or floats for version number.
1231
+ $plugin['version'] = (string) $plugin['version'];
1232
+ $plugin['source'] = empty( $plugin['source'] ) ? 'repo' : $plugin['source'];
1233
+ $plugin['required'] = INBOUND_TGM_Utils::validate_bool( $plugin['required'] );
1234
+ $plugin['force_activation'] = INBOUND_TGM_Utils::validate_bool( $plugin['force_activation'] );
1235
+ $plugin['force_deactivation'] = INBOUND_TGM_Utils::validate_bool( $plugin['force_deactivation'] );
1236
+
1237
+ // Enrich the received data.
1238
+ $plugin['file_path'] = $this->_get_plugin_basename_from_slug( $plugin['slug'] );
1239
+ $plugin['source_type'] = $this->get_plugin_source_type( $plugin['source'] );
1240
+
1241
+ // Set the class properties.
1242
+ $this->plugins[ $plugin['slug'] ] = $plugin;
1243
+ $this->sort_order[ $plugin['slug'] ] = $plugin['name'];
1244
+
1245
+ // Should we add the force activation hook ?
1246
+ if ( true === $plugin['force_activation'] ) {
1247
+ $this->has_forced_activation = true;
1248
+ }
1249
+
1250
+ // Should we add the force deactivation hook ?
1251
+ if ( true === $plugin['force_deactivation'] ) {
1252
+ $this->has_forced_deactivation = true;
1253
+ }
1254
+ }
1255
+
1256
+ /**
1257
+ * Determine what type of source the plugin comes from.
1258
+ *
1259
+ * @since 2.5.0
1260
+ *
1261
+ * @param string $source The source of the plugin as provided, either empty (= WP repo), a file path
1262
+ * (= bundled) or an external URL.
1263
+ * @return string 'repo', 'external', or 'bundled'
1264
+ */
1265
+ protected function get_plugin_source_type( $source ) {
1266
+ if ( 'repo' === $source || preg_match( self::WP_REPO_REGEX, $source ) ) {
1267
+ return 'repo';
1268
+ } elseif ( preg_match( self::IS_URL_REGEX, $source ) ) {
1269
+ return 'external';
1270
+ } else {
1271
+ return 'bundled';
1272
+ }
1273
+ }
1274
+
1275
+ /**
1276
+ * Sanitizes a string key.
1277
+ *
1278
+ * Near duplicate of WP Core `sanitize_key()`. The difference is that uppercase characters *are*
1279
+ * allowed, so as not to break upgrade paths from non-standard bundled plugins using uppercase
1280
+ * characters in the plugin directory path/slug. Silly them.
1281
+ *
1282
+ * @see https://developer.wordpress.org/reference/hooks/sanitize_key/
1283
+ *
1284
+ * @since 2.5.0
1285
+ *
1286
+ * @param string $key String key.
1287
+ * @return string Sanitized key
1288
+ */
1289
+ public function sanitize_key( $key ) {
1290
+ $raw_key = $key;
1291
+ $key = preg_replace( '`[^A-Za-z0-9_-]`', '', $key );
1292
+
1293
+ /**
1294
+ * Filter a sanitized key string.
1295
+ *
1296
+ * @since 3.0.0
1297
+ *
1298
+ * @param string $key Sanitized key.
1299
+ * @param string $raw_key The key prior to sanitization.
1300
+ */
1301
+ return apply_filters( 'tgmpa_sanitize_key', $key, $raw_key );
1302
+ }
1303
+
1304
+ /**
1305
+ * Amend default configuration settings.
1306
+ *
1307
+ * @since 2.0.0
1308
+ *
1309
+ * @param array $config Array of config options to pass as class properties.
1310
+ */
1311
+ public function config( $config ) {
1312
+ $keys = array(
1313
+ 'id',
1314
+ 'default_path',
1315
+ 'has_notices',
1316
+ 'dismissable',
1317
+ 'dismiss_msg',
1318
+ 'menu',
1319
+ 'parent_slug',
1320
+ 'capability',
1321
+ 'is_automatic',
1322
+ 'message',
1323
+ 'strings',
1324
+ );
1325
+
1326
+ foreach ( $keys as $key ) {
1327
+ if ( isset( $config[ $key ] ) ) {
1328
+ if ( is_array( $config[ $key ] ) ) {
1329
+ $this->$key = array_merge( $this->$key, $config[ $key ] );
1330
+ } else {
1331
+ $this->$key = $config[ $key ];
1332
+ }
1333
+ }
1334
+ }
1335
+ }
1336
+
1337
+ /**
1338
+ * Amend action link after plugin installation.
1339
+ *
1340
+ * @since 2.0.0
1341
+ *
1342
+ * @param array $install_actions Existing array of actions.
1343
+ * @return array Amended array of actions.
1344
+ */
1345
+ public function actions( $install_actions ) {
1346
+ // Remove action links on the TGMPA install page.
1347
+ if ( $this->is_tgmpa_page() ) {
1348
+ return false;
1349
+ }
1350
+
1351
+ return $install_actions;
1352
+ }
1353
+
1354
+ /**
1355
+ * Flushes the plugins cache on theme switch to prevent stale entries
1356
+ * from remaining in the plugin table.
1357
+ *
1358
+ * @since 2.4.0
1359
+ *
1360
+ * @param bool $clear_update_cache Optional. Whether to clear the Plugin updates cache.
1361
+ * Parameter added in v2.5.0.
1362
+ */
1363
+ public function flush_plugins_cache( $clear_update_cache = true ) {
1364
+ wp_clean_plugins_cache( $clear_update_cache );
1365
+ }
1366
+
1367
+ /**
1368
+ * Set file_path key for each installed plugin.
1369
+ *
1370
+ * @since 2.1.0
1371
+ *
1372
+ * @param string $plugin_slug Optional. If set, only (re-)populates the file path for that specific plugin.
1373
+ * Parameter added in v2.5.0.
1374
+ */
1375
+ public function populate_file_path( $plugin_slug = '' ) {
1376
+ if ( ! empty( $plugin_slug ) && is_string( $plugin_slug ) && isset( $this->plugins[ $plugin_slug ] ) ) {
1377
+ $this->plugins[ $plugin_slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $plugin_slug );
1378
+ } else {
1379
+ // Add file_path key for all plugins.
1380
+ foreach ( $this->plugins as $slug => $values ) {
1381
+ $this->plugins[ $slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $slug );
1382
+ }
1383
+ }
1384
+ }
1385
+
1386
+ /**
1387
+ * Helper function to extract the file path of the plugin file from the
1388
+ * plugin slug, if the plugin is installed.
1389
+ *
1390
+ * @since 2.0.0
1391
+ *
1392
+ * @param string $slug Plugin slug (typically folder name) as provided by the developer.
1393
+ * @return string Either file path for plugin if installed, or just the plugin slug.
1394
+ */
1395
+ protected function _get_plugin_basename_from_slug( $slug ) {
1396
+ $keys = array_keys( $this->get_plugins() );
1397
+
1398
+ foreach ( $keys as $key ) {
1399
+ if ( preg_match( '|^' . $slug . '/|', $key ) ) {
1400
+ return $key;
1401
+ }
1402
+ }
1403
+
1404
+ return $slug;
1405
+ }
1406
+
1407
+ /**
1408
+ * Retrieve plugin data, given the plugin name.
1409
+ *
1410
+ * Loops through the registered plugins looking for $name. If it finds it,
1411
+ * it returns the $data from that plugin. Otherwise, returns false.
1412
+ *
1413
+ * @since 2.1.0
1414
+ *
1415
+ * @param string $name Name of the plugin, as it was registered.
1416
+ * @param string $data Optional. Array key of plugin data to return. Default is slug.
1417
+ * @return string|boolean Plugin slug if found, false otherwise.
1418
+ */
1419
+ public function _get_plugin_data_from_name( $name, $data = 'slug' ) {
1420
+ foreach ( $this->plugins as $values ) {
1421
+ if ( $name === $values['name'] && isset( $values[ $data ] ) ) {
1422
+ return $values[ $data ];
1423
+ }
1424
+ }
1425
+
1426
+ return false;
1427
+ }
1428
+
1429
+ /**
1430
+ * Retrieve the download URL for a package.
1431
+ *
1432
+ * @since 2.5.0
1433
+ *
1434
+ * @param string $slug Plugin slug.
1435
+ * @return string Plugin download URL or path to local file or empty string if undetermined.
1436
+ */
1437
+ public function get_download_url( $slug ) {
1438
+ $dl_source = '';
1439
+
1440
+ switch ( $this->plugins[ $slug ]['source_type'] ) {
1441
+ case 'repo':
1442
+ return $this->get_wp_repo_download_url( $slug );
1443
+ case 'external':
1444
+ return $this->plugins[ $slug ]['source'];
1445
+ case 'bundled':
1446
+ return $this->default_path . $this->plugins[ $slug ]['source'];
1447
+ }
1448
+
1449
+ return $dl_source; // Should never happen.
1450
+ }
1451
+
1452
+ /**
1453
+ * Retrieve the download URL for a WP repo package.
1454
+ *
1455
+ * @since 2.5.0
1456
+ *
1457
+ * @param string $slug Plugin slug.
1458
+ * @return string Plugin download URL.
1459
+ */
1460
+ protected function get_wp_repo_download_url( $slug ) {
1461
+ $source = '';
1462
+ $api = $this->get_plugins_api( $slug );
1463
+
1464
+ if ( false !== $api && isset( $api->download_link ) ) {
1465
+ $source = $api->download_link;
1466
+ }
1467
+
1468
+ return $source;
1469
+ }
1470
+
1471
+ /**
1472
+ * Try to grab information from WordPress API.
1473
+ *
1474
+ * @since 2.5.0
1475
+ *
1476
+ * @param string $slug Plugin slug.
1477
+ * @return object Plugins_api response object on success, WP_Error on failure.
1478
+ */
1479
+ protected function get_plugins_api( $slug ) {
1480
+ static $api = array(); // Cache received responses.
1481
+
1482
+ if ( ! isset( $api[ $slug ] ) ) {
1483
+ if ( ! function_exists( 'plugins_api' ) ) {
1484
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
1485
+ }
1486
+
1487
+ $response = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) );
1488
+
1489
+ $api[ $slug ] = false;
1490
+
1491
+ if ( is_wp_error( $response ) ) {
1492
+ wp_die( esc_html( $this->strings['oops'] ) );
1493
+ } else {
1494
+ $api[ $slug ] = $response;
1495
+ }
1496
+ }
1497
+
1498
+ return $api[ $slug ];
1499
+ }
1500
+
1501
+ /**
1502
+ * Retrieve a link to a plugin information page.
1503
+ *
1504
+ * @since 2.5.0
1505
+ *
1506
+ * @param string $slug Plugin slug.
1507
+ * @return string Fully formed html link to a plugin information page if available
1508
+ * or the plugin name if not.
1509
+ */
1510
+ public function get_info_link( $slug ) {
1511
+ if ( ! empty( $this->plugins[ $slug ]['external_url'] ) && preg_match( self::IS_URL_REGEX, $this->plugins[ $slug ]['external_url'] ) ) {
1512
+ $link = sprintf(
1513
+ '<a href="%1$s" target="_blank">%2$s</a>',
1514
+ esc_url( $this->plugins[ $slug ]['external_url'] ),
1515
+ esc_html( $this->plugins[ $slug ]['name'] )
1516
+ );
1517
+ } elseif ( 'repo' === $this->plugins[ $slug ]['source_type'] ) {
1518
+ $url = add_query_arg(
1519
+ array(
1520
+ 'tab' => 'plugin-information',
1521
+ 'plugin' => urlencode( $slug ),
1522
+ 'TB_iframe' => 'true',
1523
+ 'width' => '640',
1524
+ 'height' => '500',
1525
+ ),
1526
+ self_admin_url( 'plugin-install.php' )
1527
+ );
1528
+
1529
+ $link = sprintf(
1530
+ '<a href="%1$s" class="thickbox">%2$s</a>',
1531
+ esc_url( $url ),
1532
+ $this->plugins[ $slug ]['name']
1533
+ );
1534
+ } else {
1535
+ $link = esc_html( $this->plugins[ $slug ]['name'] ); // No hyperlink.
1536
+ }
1537
+
1538
+ return $link;
1539
+ }
1540
+
1541
+ /**
1542
+ * Determine if we're on the TGMPA Install page.
1543
+ *
1544
+ * @since 2.1.0
1545
+ *
1546
+ * @return boolean True when on the TGMPA page, false otherwise.
1547
+ */
1548
+ protected function is_tgmpa_page() {
1549
+ return isset( $_GET['page'] ) && $this->menu === $_GET['page'];
1550
+ }
1551
+
1552
+ /**
1553
+ * Retrieve the URL to the TGMPA Install page.
1554
+ *
1555
+ * I.e. depending on the config settings passed something along the lines of:
1556
+ * http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins
1557
+ *
1558
+ * @since 2.5.0
1559
+ *
1560
+ * @return string Properly encoded URL (not escaped).
1561
+ */
1562
+ public function get_tgmpa_url() {
1563
+ static $url;
1564
+
1565
+ if ( ! isset( $url ) ) {
1566
+ $parent = $this->parent_slug;
1567
+ if ( false === strpos( $parent, '.php' ) ) {
1568
+ $parent = 'admin.php';
1569
+ }
1570
+ $url = add_query_arg(
1571
+ array(
1572
+ 'page' => urlencode( $this->menu ),
1573
+ ),
1574
+ self_admin_url( $parent )
1575
+ );
1576
+ }
1577
+
1578
+ return $url;
1579
+ }
1580
+
1581
+ /**
1582
+ * Retrieve the URL to the TGMPA Install page for a specific plugin status (view).
1583
+ *
1584
+ * I.e. depending on the config settings passed something along the lines of:
1585
+ * http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins&plugin_status=install
1586
+ *
1587
+ * @since 2.5.0
1588
+ *
1589
+ * @param string $status Plugin status - either 'install', 'update' or 'activate'.
1590
+ * @return string Properly encoded URL (not escaped).
1591
+ */
1592
+ public function get_tgmpa_status_url( $status ) {
1593
+ return add_query_arg(
1594
+ array(
1595
+ 'plugin_status' => urlencode( $status ),
1596
+ ),
1597
+ $this->get_tgmpa_url()
1598
+ );
1599
+ }
1600
+
1601
+ /**
1602
+ * Determine whether there are open actions for plugins registered with TGMPA.
1603
+ *
1604
+ * @since 2.5.0
1605
+ *
1606
+ * @return bool True if complete, i.e. no outstanding actions. False otherwise.
1607
+ */
1608
+ public function is_tgmpa_complete() {
1609
+ $complete = true;
1610
+ foreach ( $this->plugins as $slug => $plugin ) {
1611
+ if ( ! $this->is_plugin_active( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
1612
+ $complete = false;
1613
+ break;
1614
+ }
1615
+ }
1616
+
1617
+ return $complete;
1618
+ }
1619
+
1620
+ /**
1621
+ * Check if a plugin is installed. Does not take must-use plugins into account.
1622
+ *
1623
+ * @since 2.5.0
1624
+ *
1625
+ * @param string $slug Plugin slug.
1626
+ * @return bool True if installed, false otherwise.
1627
+ */
1628
+ public function is_plugin_installed( $slug ) {
1629
+ $installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
1630
+
1631
+ return ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ] ) );
1632
+ }
1633
+
1634
+ /**
1635
+ * Check if a plugin is active.
1636
+ *
1637
+ * @since 2.5.0
1638
+ *
1639
+ * @param string $slug Plugin slug.
1640
+ * @return bool True if active, false otherwise.
1641
+ */
1642
+ public function is_plugin_active( $slug ) {
1643
+ return ( ( ! empty( $this->plugins[ $slug ]['is_callable'] ) && is_callable( $this->plugins[ $slug ]['is_callable'] ) ) || is_plugin_active( $this->plugins[ $slug ]['file_path'] ) );
1644
+ }
1645
+
1646
+ /**
1647
+ * Check if a plugin can be updated, i.e. if we have information on the minimum WP version required
1648
+ * available, check whether the current install meets them.
1649
+ *
1650
+ * @since 2.5.0
1651
+ *
1652
+ * @param string $slug Plugin slug.
1653
+ * @return bool True if OK to update, false otherwise.
1654
+ */
1655
+ public function can_plugin_update( $slug ) {
1656
+ // We currently can't get reliable info on non-WP-repo plugins - issue #380.
1657
+ if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
1658
+ return true;
1659
+ }
1660
+
1661
+ $api = $this->get_plugins_api( $slug );
1662
+
1663
+ if ( false !== $api && isset( $api->requires ) ) {
1664
+ return version_compare( $GLOBALS['wp_version'], $api->requires, '>=' );
1665
+ }
1666
+
1667
+ // No usable info received from the plugins API, presume we can update.
1668
+ return true;
1669
+ }
1670
+
1671
+ /**
1672
+ * Check if a plugin can be activated, i.e. is not currently active and meets the minimum
1673
+ * plugin version requirements set in TGMPA (if any).
1674
+ *
1675
+ * @since 2.5.0
1676
+ *
1677
+ * @param string $slug Plugin slug.
1678
+ * @return bool True if OK to activate, false otherwise.
1679
+ */
1680
+ public function can_plugin_activate( $slug ) {
1681
+ return ( ! $this->is_plugin_active( $slug ) && ! $this->does_plugin_require_update( $slug ) );
1682
+ }
1683
+
1684
+ /**
1685
+ * Retrieve the version number of an installed plugin.
1686
+ *
1687
+ * @since 2.5.0
1688
+ *
1689
+ * @param string $slug Plugin slug.
1690
+ * @return string Version number as string or an empty string if the plugin is not installed
1691
+ * or version unknown (plugins which don't comply with the plugin header standard).
1692
+ */
1693
+ public function get_installed_version( $slug ) {
1694
+ $installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
1695
+
1696
+ if ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'] ) ) {
1697
+ return $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'];
1698
+ }
1699
+
1700
+ return '';
1701
+ }
1702
+
1703
+ /**
1704
+ * Check whether a plugin complies with the minimum version requirements.
1705
+ *
1706
+ * @since 2.5.0
1707
+ *
1708
+ * @param string $slug Plugin slug.
1709
+ * @return bool True when a plugin needs to be updated, otherwise false.
1710
+ */
1711
+ public function does_plugin_require_update( $slug ) {
1712
+ $installed_version = $this->get_installed_version( $slug );
1713
+ $minimum_version = $this->plugins[ $slug ]['version'];
1714
+
1715
+ return version_compare( $minimum_version, $installed_version, '>' );
1716
+ }
1717
+
1718
+ /**
1719
+ * Check whether there is an update available for a plugin.
1720
+ *
1721
+ * @since 2.5.0
1722
+ *
1723
+ * @param string $slug Plugin slug.
1724
+ * @return false|string Version number string of the available update or false if no update available.
1725
+ */
1726
+ public function does_plugin_have_update( $slug ) {
1727
+ // Presume bundled and external plugins will point to a package which meets the minimum required version.
1728
+ if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
1729
+ if ( $this->does_plugin_require_update( $slug ) ) {
1730
+ return $this->plugins[ $slug ]['version'];
1731
+ }
1732
+
1733
+ return false;
1734
+ }
1735
+
1736
+ $repo_updates = get_site_transient( 'update_plugins' );
1737
+
1738
+ if ( isset( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version ) ) {
1739
+ return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version;
1740
+ }
1741
+
1742
+ return false;
1743
+ }
1744
+
1745
+ /**
1746
+ * Retrieve potential upgrade notice for a plugin.
1747
+ *
1748
+ * @since 2.5.0
1749
+ *
1750
+ * @param string $slug Plugin slug.
1751
+ * @return string The upgrade notice or an empty string if no message was available or provided.
1752
+ */
1753
+ public function get_upgrade_notice( $slug ) {
1754
+ // We currently can't get reliable info on non-WP-repo plugins - issue #380.
1755
+ if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
1756
+ return '';
1757
+ }
1758
+
1759
+ $repo_updates = get_site_transient( 'update_plugins' );
1760
+
1761
+ if ( ! empty( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice ) ) {
1762
+ return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice;
1763
+ }
1764
+
1765
+ return '';
1766
+ }
1767
+
1768
+ /**
1769
+ * Wrapper around the core WP get_plugins function, making sure it's actually available.
1770
+ *
1771
+ * @since 2.5.0
1772
+ *
1773
+ * @param string $plugin_folder Optional. Relative path to single plugin folder.
1774
+ * @return array Array of installed plugins with plugin information.
1775
+ */
1776
+ public function get_plugins( $plugin_folder = '' ) {
1777
+ if ( ! function_exists( 'get_plugins' ) ) {
1778
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
1779
+ }
1780
+
1781
+ return get_plugins( $plugin_folder );
1782
+ }
1783
+
1784
+ /**
1785
+ * Delete dismissable nag option when theme is switched.
1786
+ *
1787
+ * This ensures that the user(s) is/are again reminded via nag of required
1788
+ * and/or recommended plugins if they re-activate the theme.
1789
+ *
1790
+ * @since 2.1.1
1791
+ */
1792
+ public function update_dismiss() {
1793
+ delete_metadata( 'user', null, 'tgmpa_dismissed_notice_' . $this->id, null, true );
1794
+ }
1795
+
1796
+ /**
1797
+ * Forces plugin activation if the parameter 'force_activation' is
1798
+ * set to true.
1799
+ *
1800
+ * This allows theme authors to specify certain plugins that must be
1801
+ * active at all times while using the current theme.
1802
+ *
1803
+ * Please take special care when using this parameter as it has the
1804
+ * potential to be harmful if not used correctly. Setting this parameter
1805
+ * to true will not allow the specified plugin to be deactivated unless
1806
+ * the user switches themes.
1807
+ *
1808
+ * @since 2.2.0
1809
+ */
1810
+ public function force_activation() {
1811
+ foreach ( $this->plugins as $slug => $plugin ) {
1812
+ if ( true === $plugin['force_activation'] ) {
1813
+ if ( ! $this->is_plugin_installed( $slug ) ) {
1814
+ // Oops, plugin isn't there so iterate to next condition.
1815
+ continue;
1816
+ } elseif ( $this->can_plugin_activate( $slug ) ) {
1817
+ // There we go, activate the plugin.
1818
+ activate_plugin( $plugin['file_path'] );
1819
+ }
1820
+ }
1821
+ }
1822
+ }
1823
+
1824
+ /**
1825
+ * Forces plugin deactivation if the parameter 'force_deactivation'
1826
+ * is set to true.
1827
+ *
1828
+ * This allows theme authors to specify certain plugins that must be
1829
+ * deactivated upon switching from the current theme to another.
1830
+ *
1831
+ * Please take special care when using this parameter as it has the
1832
+ * potential to be harmful if not used correctly.
1833
+ *
1834
+ * @since 2.2.0
1835
+ */
1836
+ public function force_deactivation() {
1837
+ foreach ( $this->plugins as $slug => $plugin ) {
1838
+ // Only proceed forward if the parameter is set to true and plugin is active.
1839
+ if ( true === $plugin['force_deactivation'] && $this->is_plugin_active( $slug ) ) {
1840
+ deactivate_plugins( $plugin['file_path'] );
1841
+ }
1842
+ }
1843
+ }
1844
+
1845
+ /**
1846
+ * Echo the current TGMPA version number to the page.
1847
+ */
1848
+ public function show_tgmpa_version() {
1849
+ echo '<p style="float: right; padding: 0em 1.5em 0.5em 0;"><strong><small>',
1850
+ esc_html( sprintf( _x( 'TGMPA v%s', '%s = version number', 'tgmpa' ), self::TGMPA_VERSION ) ),
1851
+ '</small></strong></p>';
1852
+ }
1853
+
1854
+ /**
1855
+ * Returns the singleton instance of the class.
1856
+ *
1857
+ * @since 2.4.0
1858
+ *
1859
+ * @return object The INBOUND_Plugin_Activation object.
1860
+ */
1861
+ public static function get_instance() {
1862
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
1863
+ self::$instance = new self();
1864
+ }
1865
+
1866
+ return self::$instance;
1867
+ }
1868
+
1869
+ /**
1870
+ * Ensure only one instance of the class is ever invoked.
1871
+ */
1872
+ public static function load_tgm_plugin_activation() {
1873
+ if (!isset($GLOBALS['tgmpa'] )) {
1874
+ $GLOBALS['tgmpa'] = INBOUND_Plugin_Activation::get_instance();
1875
+ }
1876
+ }
1877
+ }
1878
+
1879
+ if ( did_action( 'after_setup_theme' ) ) {
1880
+ INBOUND_Plugin_Activation::load_tgm_plugin_activation();
1881
+ } else {
1882
+ add_action( 'after_setup_theme', array( 'INBOUND_Plugin_Activation', 'load_tgm_plugin_activation' ) );
1883
+ }
1884
+ }
1885
+
1886
+ if ( ! function_exists( 'inbound_activate' ) ) {
1887
+ /**
1888
+ * Helper function to register a collection of required plugins.
1889
+ *
1890
+ * @since 2.0.0
1891
+ * @api
1892
+ *
1893
+ * @param array $plugins An array of plugin arrays.
1894
+ * @param array $config Optional. An array of configuration values.
1895
+ */
1896
+ function inbound_activate( $plugins, $config = array() ) {
1897
+ $instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
1898
+
1899
+ foreach ( $plugins as $plugin ) {
1900
+ call_user_func( array( $instance, 'register' ), $plugin );
1901
+ }
1902
+
1903
+ if ( ! empty( $config ) && is_array( $config ) ) {
1904
+ call_user_func( array( $instance, 'config' ), $config );
1905
+ }
1906
+ }
1907
+ }
1908
+
1909
+ /**
1910
+ * WP_List_Table isn't always available. If it isn't available,
1911
+ * we load it here.
1912
+ *
1913
+ * @since 2.2.0
1914
+ */
1915
+ if ( ! class_exists( 'WP_List_Table' ) ) {
1916
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
1917
+ }
1918
+
1919
+ if ( ! class_exists( 'INBOUND_TGMPA_List_Table' ) ) {
1920
+
1921
+ /**
1922
+ * List table class for handling plugins.
1923
+ *
1924
+ * Extends the WP_List_Table class to provide a future-compatible
1925
+ * way of listing out all required/recommended plugins.
1926
+ *
1927
+ * Gives users an interface similar to the Plugin Administration
1928
+ * area with similar (albeit stripped down) capabilities.
1929
+ *
1930
+ * This class also allows for the bulk install of plugins.
1931
+ *
1932
+ * @since 2.2.0
1933
+ *
1934
+ * @package TGM-Plugin-Activation
1935
+ * @author Thomas Griffin
1936
+ * @author Gary Jones
1937
+ */
1938
+ class INBOUND_TGMPA_List_Table extends WP_List_Table {
1939
+ /**
1940
+ * TGMPA instance.
1941
+ *
1942
+ * @since 2.5.0
1943
+ *
1944
+ * @var object
1945
+ */
1946
+ protected $tgmpa;
1947
+
1948
+ /**
1949
+ * The currently chosen view.
1950
+ *
1951
+ * @since 2.5.0
1952
+ *
1953
+ * @var string One of: 'all', 'install', 'update', 'activate'
1954
+ */
1955
+ public $view_context = 'all';
1956
+
1957
+ /**
1958
+ * The plugin counts for the various views.
1959
+ *
1960
+ * @since 2.5.0
1961
+ *
1962
+ * @var array
1963
+ */
1964
+ protected $view_totals = array(
1965
+ 'all' => 0,
1966
+ 'install' => 0,
1967
+ 'update' => 0,
1968
+ 'activate' => 0,
1969
+ );
1970
+
1971
+ /**
1972
+ * References parent constructor and sets defaults for class.
1973
+ *
1974
+ * @since 2.2.0
1975
+ */
1976
+ public function __construct() {
1977
+ $this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
1978
+
1979
+ parent::__construct(
1980
+ array(
1981
+ 'singular' => 'plugin',
1982
+ 'plural' => 'plugins',
1983
+ 'ajax' => false,
1984
+ )
1985
+ );
1986
+
1987
+ if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'install', 'update', 'activate' ), true ) ) {
1988
+ $this->view_context = sanitize_key( $_REQUEST['plugin_status'] );
1989
+ }
1990
+
1991
+ add_filter( 'tgmpa_table_data_items', array( $this, 'sort_table_items' ) );
1992
+ }
1993
+
1994
+ /**
1995
+ * Get a list of CSS classes for the <table> tag.
1996
+ *
1997
+ * Overruled to prevent the 'plural' argument from being added.
1998
+ *
1999
+ * @since 2.5.0
2000
+ *
2001
+ * @return array CSS classnames.
2002
+ */
2003
+ public function get_table_classes() {
2004
+ return array( 'widefat', 'fixed' );
2005
+ }
2006
+
2007
+ /**
2008
+ * Gathers and renames all of our plugin information to be used by WP_List_Table to create our table.
2009
+ *
2010
+ * @since 2.2.0
2011
+ *
2012
+ * @return array $table_data Information for use in table.
2013
+ */
2014
+ protected function _gather_plugin_data() {
2015
+ // Load thickbox for plugin links.
2016
+ $this->tgmpa->admin_init();
2017
+ $this->tgmpa->thickbox();
2018
+
2019
+ // Categorize the plugins which have open actions.
2020
+ $plugins = $this->categorize_plugins_to_views();
2021
+
2022
+ // Set the counts for the view links.
2023
+ $this->set_view_totals( $plugins );
2024
+
2025
+ // Prep variables for use and grab list of all installed plugins.
2026
+ $table_data = array();
2027
+ $i = 0;
2028
+
2029
+ // Redirect to the 'all' view if no plugins where found for the selected view context.
2030
+ if ( empty( $plugins[ $this->view_context ] ) ) {
2031
+ $this->view_context = 'all';
2032
+ }
2033
+
2034
+ foreach ( $plugins[ $this->view_context ] as $slug => $plugin ) {
2035
+ $table_data[ $i ]['sanitized_plugin'] = $plugin['name'];
2036
+ $table_data[ $i ]['slug'] = $slug;
2037
+ $table_data[ $i ]['plugin'] = '<strong>' . $this->tgmpa->get_info_link( $slug ) . '</strong>';
2038
+ $table_data[ $i ]['source'] = $this->get_plugin_source_type_text( $plugin['source_type'] );
2039
+ $table_data[ $i ]['type'] = $this->get_plugin_advise_type_text( $plugin['required'] );
2040
+ $table_data[ $i ]['status'] = $this->get_plugin_status_text( $slug );
2041
+ $table_data[ $i ]['installed_version'] = $this->tgmpa->get_installed_version( $slug );
2042
+ $table_data[ $i ]['minimum_version'] = $plugin['version'];
2043
+ $table_data[ $i ]['available_version'] = $this->tgmpa->does_plugin_have_update( $slug );
2044
+
2045
+ // Prep the upgrade notice info.
2046
+ $upgrade_notice = $this->tgmpa->get_upgrade_notice( $slug );
2047
+ if ( ! empty( $upgrade_notice ) ) {
2048
+ $table_data[ $i ]['upgrade_notice'] = $upgrade_notice;
2049
+
2050
+ add_action( "tgmpa_after_plugin_row_$slug", array( $this, 'wp_plugin_update_row' ), 10, 2 );
2051
+ }
2052
+
2053
+ $table_data[ $i ] = apply_filters( 'tgmpa_table_data_item', $table_data[ $i ], $plugin );
2054
+
2055
+ $i++;
2056
+ }
2057
+
2058
+ return $table_data;
2059
+ }
2060
+
2061
+ /**
2062
+ * Categorize the plugins which have open actions into views for the TGMPA page.
2063
+ *
2064
+ * @since 2.5.0
2065
+ */
2066
+ protected function categorize_plugins_to_views() {
2067
+ $plugins = array(
2068
+ 'all' => array(), // Meaning: all plugins which still have open actions.
2069
+ 'install' => array(),
2070
+ 'update' => array(),
2071
+ 'activate' => array(),
2072
+ );
2073
+
2074
+ foreach ( $this->tgmpa->plugins as $slug => $plugin ) {
2075
+ if ( $this->tgmpa->is_plugin_active( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
2076
+ // No need to display plugins if they are installed, up-to-date and active.
2077
+ continue;
2078
+ } else {
2079
+ $plugins['all'][ $slug ] = $plugin;
2080
+
2081
+ if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
2082
+ $plugins['install'][ $slug ] = $plugin;
2083
+ } else {
2084
+ if ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
2085
+ $plugins['update'][ $slug ] = $plugin;
2086
+ }
2087
+
2088
+ if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
2089
+ $plugins['activate'][ $slug ] = $plugin;
2090
+ }
2091
+ }
2092
+ }
2093
+ }
2094
+
2095
+ return $plugins;
2096
+ }
2097
+
2098
+ /**
2099
+ * Set the counts for the view links.
2100
+ *
2101
+ * @since 2.5.0
2102
+ *
2103
+ * @param array $plugins Plugins order by view.
2104
+ */
2105
+ protected function set_view_totals( $plugins ) {
2106
+ foreach ( $plugins as $type => $list ) {
2107
+ $this->view_totals[ $type ] = count( $list );
2108
+ }
2109
+ }
2110
+
2111
+ /**
2112
+ * Get the plugin required/recommended text string.
2113
+ *
2114
+ * @since 2.5.0
2115
+ *
2116
+ * @param string $required Plugin required setting.
2117
+ * @return string
2118
+ */
2119
+ protected function get_plugin_advise_type_text( $required ) {
2120
+ if ( true === $required ) {
2121
+ return __( 'Required', 'tgmpa' );
2122
+ }
2123
+
2124
+ return __( 'Recommended', 'tgmpa' );
2125
+ }
2126
+
2127
+ /**
2128
+ * Get the plugin source type text string.
2129
+ *
2130
+ * @since 2.5.0
2131
+ *
2132
+ * @param string $type Plugin type.
2133
+ * @return string
2134
+ */
2135
+ protected function get_plugin_source_type_text( $type ) {
2136
+ $string = '';
2137
+
2138
+ switch ( $type ) {
2139
+ case 'repo':
2140
+ $string = __( 'WordPress Repository', 'tgmpa' );
2141
+ break;
2142
+ case 'external':
2143
+ $string = __( 'External Source', 'tgmpa' );
2144
+ break;
2145
+ case 'bundled':
2146
+ $string = __( 'Pre-Packaged', 'tgmpa' );
2147
+ break;
2148
+ }
2149
+
2150
+ return $string;
2151
+ }
2152
+
2153
+ /**
2154
+ * Determine the plugin status message.
2155
+ *
2156
+ * @since 2.5.0
2157
+ *
2158
+ * @param string $slug Plugin slug.
2159
+ * @return string
2160
+ */
2161
+ protected function get_plugin_status_text( $slug ) {
2162
+ if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
2163
+ return __( 'Not Installed', 'tgmpa' );
2164
+ }
2165
+
2166
+ if ( ! $this->tgmpa->is_plugin_active( $slug ) ) {
2167
+ $install_status = __( 'Installed But Not Activated', 'tgmpa' );
2168
+ } else {
2169
+ $install_status = __( 'Active', 'tgmpa' );
2170
+ }
2171
+
2172
+ $update_status = '';
2173
+
2174
+ if ( $this->tgmpa->does_plugin_require_update( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
2175
+ $update_status = __( 'Required Update not Available', 'tgmpa' );
2176
+
2177
+ } elseif ( $this->tgmpa->does_plugin_require_update( $slug ) ) {
2178
+ $update_status = __( 'Requires Update', 'tgmpa' );
2179
+
2180
+ } elseif ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
2181
+ $update_status = __( 'Update recommended', 'tgmpa' );
2182
+ }
2183
+
2184
+ if ( '' === $update_status ) {
2185
+ return $install_status;
2186
+ }
2187
+
2188
+ return sprintf(
2189
+ _x( '%1$s, %2$s', '%1$s = install status, %2$s = update status', 'tgmpa' ),
2190
+ $install_status,
2191
+ $update_status
2192
+ );
2193
+ }
2194
+
2195
+ /**
2196
+ * Sort plugins by Required/Recommended type and by alphabetical plugin name within each type.
2197
+ *
2198
+ * @since 2.5.0
2199
+ *
2200
+ * @param array $items Prepared table items.
2201
+ * @return array Sorted table items.
2202
+ */
2203
+ public function sort_table_items( $items ) {
2204
+ $type = array();
2205
+ $name = array();
2206
+
2207
+ foreach ( $items as $i => $plugin ) {
2208
+ $type[ $i ] = $plugin['type']; // Required / recommended.
2209
+ $name[ $i ] = $plugin['sanitized_plugin'];
2210
+ }
2211
+
2212
+ array_multisort( $type, SORT_DESC, $name, SORT_ASC, $items );
2213
+
2214
+ return $items;
2215
+ }
2216
+
2217
+ /**
2218
+ * Get an associative array ( id => link ) of the views available on this table.
2219
+ *
2220
+ * @since 2.5.0
2221
+ *
2222
+ * @return array
2223
+ */
2224
+ public function get_views() {
2225
+ $status_links = array();
2226
+
2227
+ foreach ( $this->view_totals as $type => $count ) {
2228
+ if ( $count < 1 ) {
2229
+ continue;
2230
+ }
2231
+
2232
+ switch ( $type ) {
2233
+ case 'all':
2234
+ $text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'plugins', 'tgmpa' );
2235
+ break;
2236
+ case 'install':
2237
+ $text = _n( 'To Install <span class="count">(%s)</span>', 'To Install <span class="count">(%s)</span>', $count, 'tgmpa' );
2238
+ break;
2239
+ case 'update':
2240
+ $text = _n( 'Update Available <span class="count">(%s)</span>', 'Update Available <span class="count">(%s)</span>', $count, 'tgmpa' );
2241
+ break;
2242
+ case 'activate':
2243
+ $text = _n( 'To Activate <span class="count">(%s)</span>', 'To Activate <span class="count">(%s)</span>', $count, 'tgmpa' );
2244
+ break;
2245
+ default:
2246
+ $text = '';
2247
+ break;
2248
+ }
2249
+
2250
+ if ( ! empty( $text ) ) {
2251
+
2252
+ $status_links[ $type ] = sprintf(
2253
+ '<a href="%s"%s>%s</a>',
2254
+ esc_url( $this->tgmpa->get_tgmpa_status_url( $type ) ),
2255
+ ( $type === $this->view_context ) ? ' class="current"' : '',
2256
+ sprintf( $text, number_format_i18n( $count ) )
2257
+ );
2258
+ }
2259
+ }
2260
+
2261
+ return $status_links;
2262
+ }
2263
+
2264
+ /**
2265
+ * Create default columns to display important plugin information
2266
+ * like type, action and status.
2267
+ *
2268
+ * @since 2.2.0
2269
+ *
2270
+ * @param array $item Array of item data.
2271
+ * @param string $column_name The name of the column.
2272
+ * @return string
2273
+ */
2274
+ public function column_default( $item, $column_name ) {
2275
+ return $item[ $column_name ];
2276
+ }
2277
+
2278
+ /**
2279
+ * Required for bulk installing.
2280
+ *
2281
+ * Adds a checkbox for each plugin.
2282
+ *
2283
+ * @since 2.2.0
2284
+ *
2285
+ * @param array $item Array of item data.
2286
+ * @return string The input checkbox with all necessary info.
2287
+ */
2288
+ public function column_cb( $item ) {
2289
+ return sprintf(
2290
+ '<input type="checkbox" name="%1$s[]" value="%2$s" id="%3$s" />',
2291
+ esc_attr( $this->_args['singular'] ),
2292
+ esc_attr( $item['slug'] ),
2293
+ esc_attr( $item['sanitized_plugin'] )
2294
+ );
2295
+ }
2296
+
2297
+ /**
2298
+ * Create default title column along with the action links.
2299
+ *
2300
+ * @since 2.2.0
2301
+ *
2302
+ * @param array $item Array of item data.
2303
+ * @return string The plugin name and action links.
2304
+ */
2305
+ public function column_plugin( $item ) {
2306
+ return sprintf(
2307
+ '%1$s %2$s',
2308
+ $item['plugin'],
2309
+ $this->row_actions( $this->get_row_actions( $item ), true )
2310
+ );
2311
+ }
2312
+
2313
+ /**
2314
+ * Create version information column.
2315
+ *
2316
+ * @since 2.5.0
2317
+ *
2318
+ * @param array $item Array of item data.
2319
+ * @return string HTML-formatted version information.
2320
+ */
2321
+ public function column_version( $item ) {
2322
+ $output = array();
2323
+
2324
+ if ( $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
2325
+ $installed = ! empty( $item['installed_version'] ) ? $item['installed_version'] : _x( 'unknown', 'as in: "version nr unknown"', 'tgmpa' );
2326
+
2327
+ $color = '';
2328
+ if ( ! empty( $item['minimum_version'] ) && $this->tgmpa->does_plugin_require_update( $item['slug'] ) ) {
2329
+ $color = ' color: #ff0000; font-weight: bold;';
2330
+ }
2331
+
2332
+ $output[] = sprintf(
2333
+ '<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Installed version:', 'tgmpa' ) . '</p>',
2334
+ $color,
2335
+ $installed
2336
+ );
2337
+ }
2338
+
2339
+ if ( ! empty( $item['minimum_version'] ) ) {
2340
+ $output[] = sprintf(
2341
+ '<p><span style="min-width: 32px; text-align: right; float: right;">%1$s</span>' . __( 'Minimum required version:', 'tgmpa' ) . '</p>',
2342
+ $item['minimum_version']
2343
+ );
2344
+ }
2345
+
2346
+ if ( ! empty( $item['available_version'] ) ) {
2347
+ $color = '';
2348
+ if ( ! empty( $item['minimum_version'] ) && version_compare( $item['available_version'], $item['minimum_version'], '>=' ) ) {
2349
+ $color = ' color: #71C671; font-weight: bold;';
2350
+ }
2351
+
2352
+ $output[] = sprintf(
2353
+ '<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Available version:', 'tgmpa' ) . '</p>',
2354
+ $color,
2355
+ $item['available_version']
2356
+ );
2357
+ }
2358
+
2359
+ if ( empty( $output ) ) {
2360
+ return '&nbsp;'; // Let's not break the table layout.
2361
+ } else {
2362
+ return implode( "\n", $output );
2363
+ }
2364
+ }
2365
+
2366
+ /**
2367
+ * Sets default message within the plugins table if no plugins
2368
+ * are left for interaction.
2369
+ *
2370
+ * Hides the menu item to prevent the user from clicking and
2371
+ * getting a permissions error.
2372
+ *
2373
+ * @since 2.2.0
2374
+ */
2375
+ public function no_items() {
2376
+ printf( wp_kses_post( __( 'No plugins to install, update or activate. <a href="%1$s">Return to the Dashboard</a>', 'tgmpa' ) ), esc_url( self_admin_url() ) );
2377
+ echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
2378
+ }
2379
+
2380
+ /**
2381
+ * Output all the column information within the table.
2382
+ *
2383
+ * @since 2.2.0
2384
+ *
2385
+ * @return array $columns The column names.
2386
+ */
2387
+ public function get_columns() {
2388
+ $columns = array(
2389
+ 'cb' => '<input type="checkbox" />',
2390
+ 'plugin' => __( 'Plugin', 'tgmpa' ),
2391
+ 'source' => __( 'Source', 'tgmpa' ),
2392
+ 'type' => __( 'Type', 'tgmpa' ),
2393
+ );
2394
+
2395
+ if ( 'all' === $this->view_context || 'update' === $this->view_context ) {
2396
+ $columns['version'] = __( 'Version', 'tgmpa' );
2397
+ $columns['status'] = __( 'Status', 'tgmpa' );
2398
+ }
2399
+
2400
+ return apply_filters( 'tgmpa_table_columns', $columns );
2401
+ }
2402
+
2403
+ /**
2404
+ * Get name of default primary column
2405
+ *
2406
+ * @since 2.5.0 / WP 4.3+ compatibility
2407
+ * @access protected
2408
+ *
2409
+ * @return string
2410
+ */
2411
+ protected function get_default_primary_column_name() {
2412
+ return 'plugin';
2413
+ }
2414
+
2415
+ /**
2416
+ * Get the name of the primary column.
2417
+ *
2418
+ * @since 2.5.0 / WP 4.3+ compatibility
2419
+ * @access protected
2420
+ *
2421
+ * @return string The name of the primary column.
2422
+ */
2423
+ protected function get_primary_column_name() {
2424
+ if ( method_exists( 'WP_List_Table', 'get_primary_column_name' ) ) {
2425
+ return parent::get_primary_column_name();
2426
+ } else {
2427
+ return $this->get_default_primary_column_name();
2428
+ }
2429
+ }
2430
+
2431
+ /**
2432
+ * Get the actions which are relevant for a specific plugin row.
2433
+ *
2434
+ * @since 2.5.0
2435
+ *
2436
+ * @param array $item Array of item data.
2437
+ * @return array Array with relevant action links.
2438
+ */
2439
+ protected function get_row_actions( $item ) {
2440
+ $actions = array();
2441
+ $action_links = array();
2442
+
2443
+ // Display the 'Install' action link if the plugin is not yet available.
2444
+ if ( ! $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
2445
+ $actions['install'] = _x( 'Install %2$s', '%2$s = plugin name in screen reader markup', 'tgmpa' );
2446
+ } else {
2447
+ // Display the 'Update' action link if an update is available and WP complies with plugin minimum.
2448
+ if ( false !== $this->tgmpa->does_plugin_have_update( $item['slug'] ) && $this->tgmpa->can_plugin_update( $item['slug'] ) ) {
2449
+ $actions['update'] = _x( 'Update %2$s', '%2$s = plugin name in screen reader markup', 'tgmpa' );
2450
+ }
2451
+
2452
+ // Display the 'Activate' action link, but only if the plugin meets the minimum version.
2453
+ if ( $this->tgmpa->can_plugin_activate( $item['slug'] ) ) {
2454
+ $actions['activate'] = _x( 'Activate %2$s', '%2$s = plugin name in screen reader markup', 'tgmpa' );
2455
+ }
2456
+ }
2457
+
2458
+ // Create the actual links.
2459
+ foreach ( $actions as $action => $text ) {
2460
+ $nonce_url = wp_nonce_url(
2461
+ add_query_arg(
2462
+ array(
2463
+ 'plugin' => urlencode( $item['slug'] ),
2464
+ 'tgmpa-' . $action => $action . '-plugin',
2465
+ ),
2466
+ $this->tgmpa->get_tgmpa_url()
2467
+ ),
2468
+ 'tgmpa-' . $action,
2469
+ 'tgmpa-nonce'
2470
+ );
2471
+
2472
+ $action_links[ $action ] = sprintf(
2473
+ '<a href="%1$s">' . esc_html( $text ) . '</a>',
2474
+ esc_url( $nonce_url ),
2475
+ '<span class="screen-reader-text">' . esc_html( $item['sanitized_plugin'] ) . '</span>'
2476
+ );
2477
+ }
2478
+
2479
+ $prefix = ( defined( 'WP_NETWORK_ADMIN' ) && WP_NETWORK_ADMIN ) ? 'network_admin_' : '';
2480
+ return apply_filters( "tgmpa_{$prefix}plugin_action_links", array_filter( $action_links ), $item['slug'], $item, $this->view_context );
2481
+ }
2482
+
2483
+ /**
2484
+ * Generates content for a single row of the table.
2485
+ *
2486
+ * @since 2.5.0
2487
+ *
2488
+ * @param object $item The current item.
2489
+ */
2490
+ public function single_row( $item ) {
2491
+ parent::single_row( $item );
2492
+
2493
+ /**
2494
+ * Fires after each specific row in the TGMPA Plugins list table.
2495
+ *
2496
+ * The dynamic portion of the hook name, `$item['slug']`, refers to the slug
2497
+ * for the plugin.
2498
+ *
2499
+ * @since 2.5.0
2500
+ */
2501
+ do_action( "tgmpa_after_plugin_row_{$item['slug']}", $item['slug'], $item, $this->view_context );
2502
+ }
2503
+
2504
+ /**
2505
+ * Show the upgrade notice below a plugin row if there is one.
2506
+ *
2507
+ * @since 2.5.0
2508
+ *
2509
+ * @see /wp-admin/includes/update.php
2510
+ *
2511
+ * @param string $slug Plugin slug.
2512
+ * @param array $item The information available in this table row.
2513
+ * @return null Return early if upgrade notice is empty.
2514
+ */
2515
+ public function wp_plugin_update_row( $slug, $item ) {
2516
+ if ( empty( $item['upgrade_notice'] ) ) {
2517
+ return;
2518
+ }
2519
+
2520
+ echo '
2521
+ <tr class="plugin-update-tr">
2522
+ <td colspan="', absint( $this->get_column_count() ), '" class="plugin-update colspanchange">
2523
+ <div class="update-message">',
2524
+ esc_html__( 'Upgrade message from the plugin author:', 'tgmpa' ),
2525
+ ' <strong>', wp_kses_data( $item['upgrade_notice'] ), '</strong>
2526
+ </div>
2527
+ </td>
2528
+ </tr>';
2529
+ }
2530
+
2531
+ /**
2532
+ * Extra controls to be displayed between bulk actions and pagination.
2533
+ *
2534
+ * @since 2.5.0
2535
+ *
2536
+ * @param string $which 'top' or 'bottom' table navigation.
2537
+ */
2538
+ public function extra_tablenav( $which ) {
2539
+ if ( 'bottom' === $which ) {
2540
+ $this->tgmpa->show_tgmpa_version();
2541
+ }
2542
+ }
2543
+
2544
+ /**
2545
+ * Defines the bulk actions for handling registered plugins.
2546
+ *
2547
+ * @since 2.2.0
2548
+ *
2549
+ * @return array $actions The bulk actions for the plugin install table.
2550
+ */
2551
+ public function get_bulk_actions() {
2552
+
2553
+ $actions = array();
2554
+
2555
+ if ( 'update' !== $this->view_context && 'activate' !== $this->view_context ) {
2556
+ if ( current_user_can( 'install_plugins' ) ) {
2557
+ $actions['tgmpa-bulk-install'] = __( 'Install', 'tgmpa' );
2558
+ }
2559
+ }
2560
+
2561
+ if ( 'install' !== $this->view_context ) {
2562
+ if ( current_user_can( 'update_plugins' ) ) {
2563
+ $actions['tgmpa-bulk-update'] = __( 'Update', 'tgmpa' );
2564
+ }
2565
+ if ( current_user_can( 'activate_plugins' ) ) {
2566
+ $actions['tgmpa-bulk-activate'] = __( 'Activate', 'tgmpa' );
2567
+ }
2568
+ }
2569
+
2570
+ return $actions;
2571
+ }
2572
+
2573
+ /**
2574
+ * Processes bulk installation and activation actions.
2575
+ *
2576
+ * The bulk installation process looks for the $_POST information and passes that
2577
+ * through if a user has to use WP_Filesystem to enter their credentials.
2578
+ *
2579
+ * @since 2.2.0
2580
+ */
2581
+ public function process_bulk_actions() {
2582
+ // Bulk installation process.
2583
+ if ( 'tgmpa-bulk-install' === $this->current_action() || 'tgmpa-bulk-update' === $this->current_action() ) {
2584
+
2585
+ check_admin_referer( 'bulk-' . $this->_args['plural'] );
2586
+
2587
+ $install_type = 'install';
2588
+ if ( 'tgmpa-bulk-update' === $this->current_action() ) {
2589
+ $install_type = 'update';
2590
+ }
2591
+
2592
+ $plugins_to_install = array();
2593
+
2594
+ // Did user actually select any plugins to install/update ?
2595
+ if ( empty( $_POST['plugin'] ) ) {
2596
+ if ( 'install' === $install_type ) {
2597
+ $message = __( 'No plugins were selected to be installed. No action taken.', 'tgmpa' );
2598
+ } else {
2599
+ $message = __( 'No plugins were selected to be updated. No action taken.', 'tgmpa' );
2600
+ }
2601
+
2602
+ echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
2603
+
2604
+ return false;
2605
+ }
2606
+
2607
+ if ( is_array( $_POST['plugin'] ) ) {
2608
+ $plugins_to_install = (array) $_POST['plugin'];
2609
+ } elseif ( is_string( $_POST['plugin'] ) ) {
2610
+ // Received via Filesystem page - un-flatten array (WP bug #19643).
2611
+ $plugins_to_install = explode( ',', $_POST['plugin'] );
2612
+ }
2613
+
2614
+ // Sanitize the received input.
2615
+ $plugins_to_install = array_map( 'urldecode', $plugins_to_install );
2616
+ $plugins_to_install = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins_to_install );
2617
+
2618
+ // Validate the received input.
2619
+ foreach ( $plugins_to_install as $key => $slug ) {
2620
+ // Check if the plugin was registered with TGMPA and remove if not.
2621
+ if ( ! isset( $this->tgmpa->plugins[ $slug ] ) ) {
2622
+ unset( $plugins_to_install[ $key ] );
2623
+ continue;
2624
+ }
2625
+
2626
+ // For updates: make sure this is a plugin we *can* update (update available and WP version ok).
2627
+ if ( 'update' === $install_type && ( $this->tgmpa->is_plugin_installed( $slug ) && ( false === $this->tgmpa->does_plugin_have_update( $slug ) || ! $this->tgmpa->can_plugin_update( $slug ) ) ) ) {
2628
+ unset( $plugins_to_install[ $key ] );
2629
+ }
2630
+ }
2631
+
2632
+ // No need to proceed further if we have no plugins to handle.
2633
+ if ( empty( $plugins_to_install ) ) {
2634
+ if ( 'install' === $install_type ) {
2635
+ $message = __( 'No plugins are available to be installed at this time.', 'tgmpa' );
2636
+ } else {
2637
+ $message = __( 'No plugins are available to be updated at this time.', 'tgmpa' );
2638
+ }
2639
+
2640
+ echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
2641
+
2642
+ return false;
2643
+ }
2644
+
2645
+ // Pass all necessary information if WP_Filesystem is needed.
2646
+ $url = wp_nonce_url(
2647
+ $this->tgmpa->get_tgmpa_url(),
2648
+ 'bulk-' . $this->_args['plural']
2649
+ );
2650
+
2651
+ // Give validated data back to $_POST which is the only place the filesystem looks for extra fields.
2652
+ $_POST['plugin'] = implode( ',', $plugins_to_install ); // Work around for WP bug #19643.
2653
+
2654
+ $method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
2655
+ $fields = array_keys( $_POST ); // Extra fields to pass to WP_Filesystem.
2656
+
2657
+ if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, $fields ) ) ) {
2658
+ return true; // Stop the normal page form from displaying, credential request form will be shown.
2659
+ }
2660
+
2661
+ // Now we have some credentials, setup WP_Filesystem.
2662
+ if ( ! WP_Filesystem( $creds ) ) {
2663
+ // Our credentials were no good, ask the user for them again.
2664
+ request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, $fields );
2665
+
2666
+ return true;
2667
+ }
2668
+
2669
+ /* If we arrive here, we have the filesystem */
2670
+
2671
+ // Store all information in arrays since we are processing a bulk installation.
2672
+ $names = array();
2673
+ $sources = array(); // Needed for installs.
2674
+ $file_paths = array(); // Needed for upgrades.
2675
+ $to_inject = array(); // Information to inject into the update_plugins transient.
2676
+
2677
+ // Prepare the data for validated plugins for the install/upgrade.
2678
+ foreach ( $plugins_to_install as $slug ) {
2679
+ $name = $this->tgmpa->plugins[ $slug ]['name'];
2680
+ $source = $this->tgmpa->get_download_url( $slug );
2681
+
2682
+ if ( ! empty( $name ) && ! empty( $source ) ) {
2683
+ $names[] = $name;
2684
+
2685
+ switch ( $install_type ) {
2686
+
2687
+ case 'install':
2688
+ $sources[] = $source;
2689
+ break;
2690
+
2691
+ case 'update':
2692
+ $file_paths[] = $this->tgmpa->plugins[ $slug ]['file_path'];
2693
+ $to_inject[ $slug ] = $this->tgmpa->plugins[ $slug ];
2694
+ $to_inject[ $slug ]['source'] = $source;
2695
+ break;
2696
+ }
2697
+ }
2698
+ }
2699
+ unset( $slug, $name, $source );
2700
+
2701
+ // Create a new instance of INBOUND_TGM_Bulk_Installer.
2702
+ $installer = new INBOUND_TGM_Bulk_Installer(
2703
+ new INBOUND_TGM_Bulk_Installer_Skin(
2704
+ array(
2705
+ 'url' => esc_url_raw( $this->tgmpa->get_tgmpa_url() ),
2706
+ 'nonce' => 'bulk-' . $this->_args['plural'],
2707
+ 'names' => $names,
2708
+ 'install_type' => $install_type,
2709
+ )
2710
+ )
2711
+ );
2712
+
2713
+ // Wrap the install process with the appropriate HTML.
2714
+ echo '<div class="tgmpa wrap">',
2715
+ '<h2>', esc_html( get_admin_page_title() ), '</h2>';
2716
+
2717
+ // Process the bulk installation submissions.
2718
+ add_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
2719
+
2720
+ if ( 'tgmpa-bulk-update' === $this->current_action() ) {
2721
+ // Inject our info into the update transient.
2722
+ $this->tgmpa->inject_update_info( $to_inject );
2723
+
2724
+ $installer->bulk_upgrade( $file_paths );
2725
+ } else {
2726
+ $installer->bulk_install( $sources );
2727
+ }
2728
+
2729
+ remove_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
2730
+
2731
+ echo '</div>';
2732
+
2733
+ return true;
2734
+ }
2735
+
2736
+ // Bulk activation process.
2737
+ if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
2738
+ check_admin_referer( 'bulk-' . $this->_args['plural'] );
2739
+
2740
+ // Did user actually select any plugins to activate ?
2741
+ if ( empty( $_POST['plugin'] ) ) {
2742
+ echo '<div id="message" class="error"><p>', esc_html__( 'No plugins were selected to be activated. No action taken.', 'tgmpa' ), '</p></div>';
2743
+
2744
+ return false;
2745
+ }
2746
+
2747
+ // Grab plugin data from $_POST.
2748
+ $plugins = array();
2749
+ if ( isset( $_POST['plugin'] ) ) {
2750
+ $plugins = array_map( 'urldecode', (array) $_POST['plugin'] );
2751
+ $plugins = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins );
2752
+ }
2753
+
2754
+ $plugins_to_activate = array();
2755
+ $plugin_names = array();
2756
+
2757
+ // Grab the file paths for the selected & inactive plugins from the registration array.
2758
+ foreach ( $plugins as $slug ) {
2759
+ if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
2760
+ $plugins_to_activate[] = $this->tgmpa->plugins[ $slug ]['file_path'];
2761
+ $plugin_names[] = $this->tgmpa->plugins[ $slug ]['name'];
2762
+ }
2763
+ }
2764
+ unset( $slug );
2765
+
2766
+ // Return early if there are no plugins to activate.
2767
+ if ( empty( $plugins_to_activate ) ) {
2768
+ echo '<div id="message" class="error"><p>', esc_html__( 'No plugins are available to be activated at this time.', 'tgmpa' ), '</p></div>';
2769
+
2770
+ return false;
2771
+ }
2772
+
2773
+ // Now we are good to go - let's start activating plugins.
2774
+ $activate = activate_plugins( $plugins_to_activate );
2775
+
2776
+ if ( is_wp_error( $activate ) ) {
2777
+ echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>';
2778
+ } else {
2779
+ $count = count( $plugin_names ); // Count so we can use _n function.
2780
+ $plugin_names = array_map( array( 'INBOUND_TGM_Utils', 'wrap_in_strong' ), $plugin_names );
2781
+ $last_plugin = array_pop( $plugin_names ); // Pop off last name to prep for readability.
2782
+ $imploded = empty( $plugin_names ) ? $last_plugin : ( implode( ', ', $plugin_names ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
2783
+
2784
+ printf( // WPCS: xss ok.
2785
+ '<div id="message" class="updated"><p>%1$s %2$s.</p></div>',
2786
+ esc_html( _n( 'The following plugin was activated successfully:', 'The following plugins were activated successfully:', $count, 'tgmpa' ) ),
2787
+ $imploded
2788
+ );
2789
+
2790
+ // Update recently activated plugins option.
2791
+ $recent = (array) get_option( 'recently_activated' );
2792
+ foreach ( $plugins_to_activate as $plugin => $time ) {
2793
+ if ( isset( $recent[ $plugin ] ) ) {
2794
+ unset( $recent[ $plugin ] );
2795
+ }
2796
+ }
2797
+ update_option( 'recently_activated', $recent );
2798
+ }
2799
+
2800
+ unset( $_POST ); // Reset the $_POST variable in case user wants to perform one action after another.
2801
+
2802
+ return true;
2803
+ }
2804
+
2805
+ return false;
2806
+ }
2807
+
2808
+ /**
2809
+ * Prepares all of our information to be outputted into a usable table.
2810
+ *
2811
+ * @since 2.2.0
2812
+ */
2813
+ public function prepare_items() {
2814
+ $columns = $this->get_columns(); // Get all necessary column information.
2815
+ $hidden = array(); // No columns to hide, but we must set as an array.
2816
+ $sortable = array(); // No reason to make sortable columns.
2817
+ $primary = $this->get_primary_column_name(); // Column which has the row actions.
2818
+ $this->_column_headers = array( $columns, $hidden, $sortable, $primary ); // Get all necessary column headers.
2819
+
2820
+ // Process our bulk activations here.
2821
+ if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
2822
+ $this->process_bulk_actions();
2823
+ }
2824
+
2825
+ // Store all of our plugin data into $items array so WP_List_Table can use it.
2826
+ $this->items = apply_filters( 'tgmpa_table_data_items', $this->_gather_plugin_data() );
2827
+ }
2828
+
2829
+ /* *********** DEPRECATED METHODS *********** */
2830
+
2831
+ /**
2832
+ * Retrieve plugin data, given the plugin name.
2833
+ *
2834
+ * @since 2.2.0
2835
+ * @deprecated 2.5.0 use {@see INBOUND_Plugin_Activation::_get_plugin_data_from_name()} instead.
2836
+ * @see INBOUND_Plugin_Activation::_get_plugin_data_from_name()
2837
+ *
2838
+ * @param string $name Name of the plugin, as it was registered.
2839
+ * @param string $data Optional. Array key of plugin data to return. Default is slug.
2840
+ * @return string|boolean Plugin slug if found, false otherwise.
2841
+ */
2842
+ protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
2843
+ _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'INBOUND_Plugin_Activation::_get_plugin_data_from_name()' );
2844
+
2845
+ return $this->tgmpa->_get_plugin_data_from_name( $name, $data );
2846
+ }
2847
+ }
2848
+ }
2849
+
2850
+ /**
2851
+ * The WP_Upgrader file isn't always available. If it isn't available,
2852
+ * we load it here.
2853
+ *
2854
+ * We check to make sure no action or activation keys are set so that WordPress
2855
+ * does not try to re-include the class when processing upgrades or installs outside
2856
+ * of the class.
2857
+ *
2858
+ * @since 2.2.0
2859
+ */
2860
+ add_action( 'admin_init', 'tgmpa_load_bulk_installer' );
2861
+ if ( ! function_exists( 'tgmpa_load_bulk_installer' ) ) {
2862
+ /**
2863
+ * Load bulk installer
2864
+ */
2865
+ function tgmpa_load_bulk_installer() {
2866
+ // Get TGMPA class instance.
2867
+ $tgmpa_instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
2868
+
2869
+ if ( isset( $_GET['page'] ) && $tgmpa_instance->menu === $_GET['page'] ) {
2870
+ if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
2871
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
2872
+ }
2873
+
2874
+ if ( ! class_exists( 'INBOUND_TGM_Bulk_Installer' ) ) {
2875
+
2876
+ /**
2877
+ * Installer class to handle bulk plugin installations.
2878
+ *
2879
+ * Extends WP_Upgrader and customizes to suit the installation of multiple
2880
+ * plugins.
2881
+ *
2882
+ * @since 2.2.0
2883
+ *
2884
+ * @internal Since 2.5.0 the class is an extension of Plugin_Upgrader rather than WP_Upgrader
2885
+ *
2886
+ * @package TGM-Plugin-Activation
2887
+ * @author Thomas Griffin
2888
+ * @author Gary Jones
2889
+ */
2890
+ class INBOUND_TGM_Bulk_Installer extends Plugin_Upgrader {
2891
+ /**
2892
+ * Holds result of bulk plugin installation.
2893
+ *
2894
+ * @since 2.2.0
2895
+ *
2896
+ * @var string
2897
+ */
2898
+ public $result;
2899
+
2900
+ /**
2901
+ * Flag to check if bulk installation is occurring or not.
2902
+ *
2903
+ * @since 2.2.0
2904
+ *
2905
+ * @var boolean
2906
+ */
2907
+ public $bulk = false;
2908
+
2909
+ /**
2910
+ * TGMPA instance
2911
+ *
2912
+ * @since 2.5.0
2913
+ *
2914
+ * @var object
2915
+ */
2916
+ protected $tgmpa;
2917
+
2918
+ /**
2919
+ * Whether or not the destination directory needs to be cleared ( = on update).
2920
+ *
2921
+ * @since 2.5.0
2922
+ *
2923
+ * @var bool
2924
+ */
2925
+ protected $clear_destination = false;
2926
+
2927
+ /**
2928
+ * References parent constructor and sets defaults for class.
2929
+ *
2930
+ * @since 2.2.0
2931
+ *
2932
+ * @param \Bulk_Upgrader_Skin|null $skin Installer skin.
2933
+ */
2934
+ public function __construct( $skin = null ) {
2935
+ // Get TGMPA class instance.
2936
+ $this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
2937
+
2938
+ parent::__construct( $skin );
2939
+
2940
+ if ( isset( $this->skin->options['install_type'] ) && 'update' === $this->skin->options['install_type'] ) {
2941
+ $this->clear_destination = true;
2942
+ }
2943
+
2944
+ if ( $this->tgmpa->is_automatic ) {
2945
+ $this->activate_strings();
2946
+ }
2947
+
2948
+ add_action( 'upgrader_process_complete', array( $this->tgmpa, 'populate_file_path' ) );
2949
+ }
2950
+
2951
+ /**
2952
+ * Sets the correct activation strings for the installer skin to use.
2953
+ *
2954
+ * @since 2.2.0
2955
+ */
2956
+ public function activate_strings() {
2957
+ $this->strings['activation_failed'] = __( 'Plugin activation failed.', 'tgmpa' );
2958
+ $this->strings['activation_success'] = __( 'Plugin activated successfully.', 'tgmpa' );
2959
+ }
2960
+
2961
+ /**
2962
+ * Performs the actual installation of each plugin.
2963
+ *
2964
+ * @since 2.2.0
2965
+ *
2966
+ * @see WP_Upgrader::run()
2967
+ *
2968
+ * @param array $options The installation config options.
2969
+ * @return null|array Return early if error, array of installation data on success.
2970
+ */
2971
+ public function run( $options ) {
2972
+ $result = parent::run( $options );
2973
+
2974
+ // Reset the strings in case we changed one during automatic activation.
2975
+ if ( $this->tgmpa->is_automatic ) {
2976
+ if ( 'update' === $this->skin->options['install_type'] ) {
2977
+ $this->upgrade_strings();
2978
+ } else {
2979
+ $this->install_strings();
2980
+ }
2981
+ }
2982
+
2983
+ return $result;
2984
+ }
2985
+
2986
+ /**
2987
+ * Processes the bulk installation of plugins.
2988
+ *
2989
+ * @since 2.2.0
2990
+ *
2991
+ * @internal This is basically a near identical copy of the WP Core Plugin_Upgrader::bulk_upgrade()
2992
+ * method, with minor adjustments to deal with new installs instead of upgrades.
2993
+ * For ease of future synchronizations, the adjustments are clearly commented, but no other
2994
+ * comments are added. Code style has been made to comply.
2995
+ *
2996
+ * @see Plugin_Upgrader::bulk_upgrade()
2997
+ * @see https://core.trac.wordpress.org/browser/tags/4.2.1/src/wp-admin/includes/class-wp-upgrader.php#L838
2998
+ *
2999
+ * @param array $plugins The plugin sources needed for installation.
3000
+ * @param array $args Arbitrary passed extra arguments.
3001
+ * @return string|bool Install confirmation messages on success, false on failure.
3002
+ */
3003
+ public function bulk_install( $plugins, $args = array() ) {
3004
+ // [TGMPA + ] Hook auto-activation in.
3005
+ add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
3006
+
3007
+ $defaults = array(
3008
+ 'clear_update_cache' => true,
3009
+ );
3010
+ $parsed_args = wp_parse_args( $args, $defaults );
3011
+
3012
+ $this->init();
3013
+ $this->bulk = true;
3014
+
3015
+ $this->install_strings(); // [TGMPA + ] adjusted.
3016
+
3017
+ /* [TGMPA - ] $current = get_site_transient( 'update_plugins' ); */
3018
+
3019
+ /* [TGMPA - ] add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4); */
3020
+
3021
+ $this->skin->header();
3022
+
3023
+ // Connect to the Filesystem first.
3024
+ $res = $this->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
3025
+ if ( ! $res ) {
3026
+ $this->skin->footer();
3027
+
3028
+ return false;
3029
+ }
3030
+
3031
+ $this->skin->bulk_header();
3032
+
3033
+ // Only start maintenance mode if:
3034
+ // - running Multisite and there are one or more plugins specified, OR
3035
+ // - a plugin with an update available is currently active.
3036
+ // @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
3037
+ $maintenance = ( is_multisite() && ! empty( $plugins ) );
3038
+
3039
+ /*
3040
+ [TGMPA - ]
3041
+ foreach ( $plugins as $plugin )
3042
+ $maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) );
3043
+ */
3044
+ if ( $maintenance ) {
3045
+ $this->maintenance_mode( true );
3046
+ }
3047
+
3048
+ $results = array();
3049
+
3050
+ $this->update_count = count( $plugins );
3051
+ $this->update_current = 0;
3052
+ foreach ( $plugins as $plugin ) {
3053
+ $this->update_current++;
3054
+
3055
+ /*
3056
+ [TGMPA - ]
3057
+ $this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
3058
+
3059
+ if ( !isset( $current->response[ $plugin ] ) ) {
3060
+ $this->skin->set_result('up_to_date');
3061
+ $this->skin->before();
3062
+ $this->skin->feedback('up_to_date');
3063
+ $this->skin->after();
3064
+ $results[$plugin] = true;
3065
+ continue;
3066
+ }
3067
+
3068
+ // Get the URL to the zip file
3069
+ $r = $current->response[ $plugin ];
3070
+
3071
+ $this->skin->plugin_active = is_plugin_active($plugin);
3072
+ */
3073
+
3074
+ $result = $this->run( array(
3075
+ 'package' => $plugin, // [TGMPA + ] adjusted.
3076
+ 'destination' => WP_PLUGIN_DIR,
3077
+ 'clear_destination' => false, // [TGMPA + ] adjusted.
3078
+ 'clear_working' => true,
3079
+ 'is_multi' => true,
3080
+ 'hook_extra' => array(
3081
+ 'plugin' => $plugin,
3082
+ ),
3083
+ ) );
3084
+
3085
+ $results[ $plugin ] = $this->result;
3086
+
3087
+ // Prevent credentials auth screen from displaying multiple times.
3088
+ if ( false === $result ) {
3089
+ break;
3090
+ }
3091
+ } //end foreach $plugins
3092
+
3093
+ $this->maintenance_mode( false );
3094
+
3095
+ /**
3096
+ * Fires when the bulk upgrader process is complete.
3097
+ *
3098
+ * @since WP 3.6.0 / TGMPA 2.5.0
3099
+ *
3100
+ * @param Plugin_Upgrader $this Plugin_Upgrader instance. In other contexts, $this, might
3101
+ * be a Theme_Upgrader or Core_Upgrade instance.
3102
+ * @param array $data {
3103
+ * Array of bulk item update data.
3104
+ *
3105
+ * @type string $action Type of action. Default 'update'.
3106
+ * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
3107
+ * @type bool $bulk Whether the update process is a bulk update. Default true.
3108
+ * @type array $packages Array of plugin, theme, or core packages to update.
3109
+ * }
3110
+ */
3111
+ do_action( 'upgrader_process_complete', $this, array(
3112
+ 'action' => 'install', // [TGMPA + ] adjusted.
3113
+ 'type' => 'plugin',
3114
+ 'bulk' => true,
3115
+ 'plugins' => $plugins,
3116
+ ) );
3117
+
3118
+ $this->skin->bulk_footer();
3119
+
3120
+ $this->skin->footer();
3121
+
3122
+ // Cleanup our hooks, in case something else does a upgrade on this connection.
3123
+ /* [TGMPA - ] remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin')); */
3124
+
3125
+ // [TGMPA + ] Remove our auto-activation hook.
3126
+ remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
3127
+
3128
+ // Force refresh of plugin update information.
3129
+ wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
3130
+
3131
+ return $results;
3132
+ }
3133
+
3134
+ /**
3135
+ * Handle a bulk upgrade request.
3136
+ *
3137
+ * @since 2.5.0
3138
+ *
3139
+ * @see Plugin_Upgrader::bulk_upgrade()
3140
+ *
3141
+ * @param array $plugins The local WP file_path's of the plugins which should be upgraded.
3142
+ * @param array $args Arbitrary passed extra arguments.
3143
+ * @return string|bool Install confirmation messages on success, false on failure.
3144
+ */
3145
+ public function bulk_upgrade( $plugins, $args = array() ) {
3146
+
3147
+ add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
3148
+
3149
+ $result = parent::bulk_upgrade( $plugins, $args );
3150
+
3151
+ remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
3152
+
3153
+ return $result;
3154
+ }
3155
+
3156
+ /**
3157
+ * Abuse a filter to auto-activate plugins after installation.
3158
+ *
3159
+ * Hooked into the 'upgrader_post_install' filter hook.
3160
+ *
3161
+ * @since 2.5.0
3162
+ *
3163
+ * @param bool $bool The value we need to give back (true).
3164
+ * @return bool
3165
+ */
3166
+ public function auto_activate( $bool ) {
3167
+ // Only process the activation of installed plugins if the automatic flag is set to true.
3168
+ if ( $this->tgmpa->is_automatic ) {
3169
+ // Flush plugins cache so the headers of the newly installed plugins will be read correctly.
3170
+ wp_clean_plugins_cache();
3171
+
3172
+ // Get the installed plugin file.
3173
+ $plugin_info = $this->plugin_info();
3174
+
3175
+ // Don't try to activate on upgrade of active plugin as WP will do this already.
3176
+ if ( ! is_plugin_active( $plugin_info ) ) {
3177
+ $activate = activate_plugin( $plugin_info );
3178
+
3179
+ // Adjust the success string based on the activation result.
3180
+ $this->strings['process_success'] = $this->strings['process_success'] . "<br />\n";
3181
+
3182
+ if ( is_wp_error( $activate ) ) {
3183
+ $this->skin->error( $activate );
3184
+ $this->strings['process_success'] .= $this->strings['activation_failed'];
3185
+ } else {
3186
+ $this->strings['process_success'] .= $this->strings['activation_success'];
3187
+ }
3188
+ }
3189
+ }
3190
+
3191
+ return $bool;
3192
+ }
3193
+ }
3194
+ }
3195
+
3196
+ if ( ! class_exists( 'INBOUND_TGM_Bulk_Installer_Skin' ) ) {
3197
+
3198
+ /**
3199
+ * Installer skin to set strings for the bulk plugin installations..
3200
+ *
3201
+ * Extends Bulk_Upgrader_Skin and customizes to suit the installation of multiple
3202
+ * plugins.
3203
+ *
3204
+ * @since 2.2.0
3205
+ *
3206
+ * @see https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/class-wp-upgrader-skins.php
3207
+ *
3208
+ * @package TGM-Plugin-Activation
3209
+ * @author Thomas Griffin
3210
+ * @author Gary Jones
3211
+ */
3212
+ class INBOUND_TGM_Bulk_Installer_Skin extends Bulk_Upgrader_Skin {
3213
+ /**
3214
+ * Holds plugin info for each individual plugin installation.
3215
+ *
3216
+ * @since 2.2.0
3217
+ *
3218
+ * @var array
3219
+ */
3220
+ public $plugin_info = array();
3221
+
3222
+ /**
3223
+ * Holds names of plugins that are undergoing bulk installations.
3224
+ *
3225
+ * @since 2.2.0
3226
+ *
3227
+ * @var array
3228
+ */
3229
+ public $plugin_names = array();
3230
+
3231
+ /**
3232
+ * Integer to use for iteration through each plugin installation.
3233
+ *
3234
+ * @since 2.2.0
3235
+ *
3236
+ * @var integer
3237
+ */
3238
+ public $i = 0;
3239
+
3240
+ /**
3241
+ * TGMPA instance
3242
+ *
3243
+ * @since 2.5.0
3244
+ *
3245
+ * @var object
3246
+ */
3247
+ protected $tgmpa;
3248
+
3249
+ /**
3250
+ * Constructor. Parses default args with new ones and extracts them for use.
3251
+ *
3252
+ * @since 2.2.0
3253
+ *
3254
+ * @param array $args Arguments to pass for use within the class.
3255
+ */
3256
+ public function __construct( $args = array() ) {
3257
+ // Get TGMPA class instance.
3258
+ $this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
3259
+
3260
+ // Parse default and new args.
3261
+ $defaults = array(
3262
+ 'url' => '',
3263
+ 'nonce' => '',
3264
+ 'names' => array(),
3265
+ 'install_type' => 'install',
3266
+ );
3267
+ $args = wp_parse_args( $args, $defaults );
3268
+
3269
+ // Set plugin names to $this->plugin_names property.
3270
+ $this->plugin_names = $args['names'];
3271
+
3272
+ // Extract the new args.
3273
+ parent::__construct( $args );
3274
+ }
3275
+
3276
+ /**
3277
+ * Sets install skin strings for each individual plugin.
3278
+ *
3279
+ * Checks to see if the automatic activation flag is set and uses the
3280
+ * the proper strings accordingly.
3281
+ *
3282
+ * @since 2.2.0
3283
+ */
3284
+ public function add_strings() {
3285
+ if ( 'update' === $this->options['install_type'] ) {
3286
+ parent::add_strings();
3287
+ $this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
3288
+ } else {
3289
+ $this->upgrader->strings['skin_update_failed_error'] = __( 'An error occurred while installing %1$s: <strong>%2$s</strong>.', 'tgmpa' );
3290
+ $this->upgrader->strings['skin_update_failed'] = __( 'The installation of %1$s failed.', 'tgmpa' );
3291
+
3292
+ if ( $this->tgmpa->is_automatic ) {
3293
+ // Automatic activation strings.
3294
+ $this->upgrader->strings['skin_upgrade_start'] = __( 'The installation and activation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
3295
+ $this->upgrader->strings['skin_update_successful'] = __( '%1$s installed and activated successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
3296
+ $this->upgrader->strings['skin_upgrade_end'] = __( 'All installations and activations have been completed.', 'tgmpa' );
3297
+ $this->upgrader->strings['skin_before_update_header'] = __( 'Installing and Activating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
3298
+ } else {
3299
+ // Default installation strings.
3300
+ $this->upgrader->strings['skin_upgrade_start'] = __( 'The installation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
3301
+ $this->upgrader->strings['skin_update_successful'] = esc_html__( '%1$s installed successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
3302
+ $this->upgrader->strings['skin_upgrade_end'] = __( 'All installations have been completed.', 'tgmpa' );
3303
+ $this->upgrader->strings['skin_before_update_header'] = __( 'Installing Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
3304
+ }
3305
+ }
3306
+ }
3307
+
3308
+ /**
3309
+ * Outputs the header strings and necessary JS before each plugin installation.
3310
+ *
3311
+ * @since 2.2.0
3312
+ *
3313
+ * @param string $title Unused in this implementation.
3314
+ */
3315
+ public function before( $title = '' ) {
3316
+ if ( empty( $title ) ) {
3317
+ $title = esc_html( $this->plugin_names[ $this->i ] );
3318
+ }
3319
+ parent::before( $title );
3320
+ }
3321
+
3322
+ /**
3323
+ * Outputs the footer strings and necessary JS after each plugin installation.
3324
+ *
3325
+ * Checks for any errors and outputs them if they exist, else output
3326
+ * success strings.
3327
+ *
3328
+ * @since 2.2.0
3329
+ *
3330
+ * @param string $title Unused in this implementation.
3331
+ */
3332
+ public function after( $title = '' ) {
3333
+ if ( empty( $title ) ) {
3334
+ $title = esc_html( $this->plugin_names[ $this->i ] );
3335
+ }
3336
+ parent::after( $title );
3337
+
3338
+ $this->i++;
3339
+ }
3340
+
3341
+ /**
3342
+ * Outputs links after bulk plugin installation is complete.
3343
+ *
3344
+ * @since 2.2.0
3345
+ */
3346
+ public function bulk_footer() {
3347
+ // Serve up the string to say installations (and possibly activations) are complete.
3348
+ parent::bulk_footer();
3349
+
3350
+ // Flush plugins cache so we can make sure that the installed plugins list is always up to date.
3351
+ wp_clean_plugins_cache();
3352
+
3353
+ $this->tgmpa->show_tgmpa_version();
3354
+
3355
+ // Display message based on if all plugins are now active or not.
3356
+ $update_actions = array();
3357
+
3358
+ if ( $this->tgmpa->is_tgmpa_complete() ) {
3359
+ // All plugins are active, so we display the complete string and hide the menu to protect users.
3360
+ echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
3361
+ $update_actions['dashboard'] = sprintf(
3362
+ esc_html( $this->tgmpa->strings['complete'] ),
3363
+ '<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>'
3364
+ );
3365
+ } else {
3366
+ $update_actions['tgmpa_page'] = '<a href="' . esc_url( $this->tgmpa->get_tgmpa_url() ) . '" target="_parent">' . esc_html( $this->tgmpa->strings['return'] ) . '</a>';
3367
+ }
3368
+
3369
+ /**
3370
+ * Filter the list of action links available following bulk plugin installs/updates.
3371
+ *
3372
+ * @since 2.5.0
3373
+ *
3374
+ * @param array $update_actions Array of plugin action links.
3375
+ * @param array $plugin_info Array of information for the last-handled plugin.
3376
+ */
3377
+ $update_actions = apply_filters( 'tgmpa_update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );
3378
+
3379
+ if ( ! empty( $update_actions ) ) {
3380
+ $this->feedback( implode( ' | ', (array) $update_actions ) );
3381
+ }
3382
+ }
3383
+
3384
+ /* *********** DEPRECATED METHODS *********** */
3385
+
3386
+ /**
3387
+ * Flush header output buffer.
3388
+ *
3389
+ * @since 2.2.0
3390
+ * @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
3391
+ * @see Bulk_Upgrader_Skin::flush_output()
3392
+ */
3393
+ public function before_flush_output() {
3394
+ _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
3395
+ $this->flush_output();
3396
+ }
3397
+
3398
+ /**
3399
+ * Flush footer output buffer and iterate $this->i to make sure the
3400
+ * installation strings reference the correct plugin.
3401
+ *
3402
+ * @since 2.2.0
3403
+ * @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
3404
+ * @see Bulk_Upgrader_Skin::flush_output()
3405
+ */
3406
+ public function after_flush_output() {
3407
+ _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
3408
+ $this->flush_output();
3409
+ $this->i++;
3410
+ }
3411
+ }
3412
+ }
3413
+ }
3414
+ }
3415
+ }
3416
+
3417
+ if ( ! class_exists( 'INBOUND_TGM_Utils' ) ) {
3418
+
3419
+ /**
3420
+ * Generic utilities for TGMPA.
3421
+ *
3422
+ * All methods are static, poor-dev name-spacing class wrapper.
3423
+ *
3424
+ * @since 2.5.0
3425
+ *
3426
+ * @package TGM-Plugin-Activation
3427
+ * @author Juliette Reinders Folmer
3428
+ */
3429
+ class INBOUND_TGM_Utils {
3430
+ /**
3431
+ * Whether the PHP filter extension is enabled.
3432
+ *
3433
+ * @see http://php.net/book.filter
3434
+ *
3435
+ * @since 2.5.0
3436
+ *
3437
+ * @static
3438
+ *
3439
+ * @var bool $has_filters True is the extension is enabled.
3440
+ */
3441
+ public static $has_filters;
3442
+
3443
+ /**
3444
+ * Wrap an arbitrary string in <em> tags. Meant to be used in combination with array_map().
3445
+ *
3446
+ * @since 2.5.0
3447
+ *
3448
+ * @static
3449
+ *
3450
+ * @param string $string Text to be wrapped.
3451
+ * @return string
3452
+ */
3453
+ public static function wrap_in_em( $string ) {
3454
+ return '<em>' . $string . '</em>';
3455
+ }
3456
+
3457
+ /**
3458
+ * Wrap an arbitrary string in <strong> tags. Meant to be used in combination with array_map().
3459
+ *
3460
+ * @since 2.5.0
3461
+ *
3462
+ * @static
3463
+ *
3464
+ * @param string $string Text to be wrapped.
3465
+ * @return string
3466
+ */
3467
+ public static function wrap_in_strong( $string ) {
3468
+ return '<strong>' . wp_kses_post( $string ) . '</strong>';
3469
+ }
3470
+
3471
+ /**
3472
+ * Helper function: Validate a value as boolean
3473
+ *
3474
+ * @since 2.5.0
3475
+ *
3476
+ * @static
3477
+ *
3478
+ * @param mixed $value Arbitrary value.
3479
+ * @return bool
3480
+ */
3481
+ public static function validate_bool( $value ) {
3482
+ if ( ! isset( self::$has_filters ) ) {
3483
+ self::$has_filters = extension_loaded( 'filter' );
3484
+ }
3485
+
3486
+ if ( self::$has_filters ) {
3487
+ return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
3488
+ } else {
3489
+ return self::emulate_filter_bool( $value );
3490
+ }
3491
+ }
3492
+
3493
+ /**
3494
+ * Helper function: Cast a value to bool
3495
+ *
3496
+ * @since 2.5.0
3497
+ *
3498
+ * @static
3499
+ *
3500
+ * @param mixed $value Value to cast.
3501
+ * @return bool
3502
+ */
3503
+ protected static function emulate_filter_bool( $value ) {
3504
+ // @codingStandardsIgnoreStart
3505
+ static $true = array(
3506
+ '1',
3507
+ 'true', 'True', 'TRUE',
3508
+ 'y', 'Y',
3509
+ 'yes', 'Yes', 'YES',
3510
+ 'on', 'On', 'ON',
3511
+ );
3512
+ static $false = array(
3513
+ '0',
3514
+ 'false', 'False', 'FALSE',
3515
+ 'n', 'N',
3516
+ 'no', 'No', 'NO',
3517
+ 'off', 'Off', 'OFF',
3518
+ );
3519
+ // @codingStandardsIgnoreEnd
3520
+
3521
+ if ( is_bool( $value ) ) {
3522
+ return $value;
3523
+ } else if ( is_int( $value ) && ( 0 === $value || 1 === $value ) ) {
3524
+ return (bool) $value;
3525
+ } else if ( ( is_float( $value ) && ! is_nan( $value ) ) && ( (float) 0 === $value || (float) 1 === $value ) ) {
3526
+ return (bool) $value;
3527
+ } else if ( is_string( $value ) ) {
3528
+ $value = trim( $value );
3529
+ if ( in_array( $value, $true, true ) ) {
3530
+ return true;
3531
+ } else if ( in_array( $value, $false, true ) ) {
3532
+ return false;
3533
+ } else {
3534
+ return false;
3535
+ }
3536
+ }
3537
+
3538
+ return false;
3539
+ }
3540
+ } // End of class INBOUND_TGM_Utils
3541
+ } // End of class_exists wrapper
trunk/assets/libraries/datetimepicker/MIT-LICENSE.txt ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2013 http://xdsoft.net
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
trunk/assets/libraries/datetimepicker/README.md ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ datetimepicker
2
+ ==============
3
+ [Documentation][doc]
4
+
5
+
6
+ jQuery Plugin Date and Time Picker
7
+
8
+ DateTimePicker
9
+
10
+ ![ScreenShot](https://raw.github.com/xdan/datetimepicker/master/screen/1.png)
11
+
12
+ DatePicker
13
+
14
+ ![ScreenShot](https://raw.github.com/xdan/datetimepicker/master/screen/2.png)
15
+
16
+ TimePicker
17
+
18
+ ![ScreenShot](https://raw.github.com/xdan/datetimepicker/master/screen/3.png)
19
+
20
+ Options to highlight individual dates or periods
21
+
22
+ ![ScreenShot](https://raw.github.com/Mingpao/datetimepicker/master/screen/4.png)
23
+
24
+ ![ScreenShot](https://raw.github.com/Mingpao/datetimepicker/master/screen/5.png)
25
+
26
+ ![ScreenShot](https://raw.github.com/Mingpao/datetimepicker/master/screen/6.png)
27
+
28
+ [doc]: http://xdsoft.net/jqplugins/datetimepicker/
trunk/assets/libraries/datetimepicker/bower.json ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "datetimepicker",
3
+ "version": "2.4.5",
4
+ "main": [
5
+ "jquery.datetimepicker.js",
6
+ "jquery.datetimepicker.css"
7
+ ],
8
+ "ignore": [
9
+ "**/screen",
10
+ "**/datetimepicker.jquery.json",
11
+ "**/*.png",
12
+ "**/*.txt",
13
+ "**/*.md",
14
+ "**/*.html",
15
+ "**/*.tpl",
16
+ "**/jquery.js"
17
+ ],
18
+ "keywords": [
19
+ "calendar",
20
+ "date",
21
+ "time",
22
+ "form",
23
+ "datetime",
24
+ "datepicker",
25
+ "timepicker",
26
+ "datetimepicker",
27
+ "validation",
28
+ "ui",
29
+ "scroller",
30
+ "picker",
31
+ "i18n",
32
+ "input",
33
+ "jquery",
34
+ "touch"
35
+ ],
36
+ "dependencies": {
37
+ "jquery": ">= 1.7.2"
38
+ },
39
+ "authors": [
40
+ {
41
+ "name": "Chupurnov Valeriy",
42
+ "email": "chupurnov@gmail.com",
43
+ "homepage": "http://xdsoft.net/contacts.html"
44
+ }
45
+ ],
46
+ "license": "MIT",
47
+ "homepage": "http://xdsoft.net/jqplugins/datetimepicker/",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git://github.com:xdan/datetimepicker.git"
51
+ }
52
+ }
trunk/assets/libraries/datetimepicker/datetimepicker.jquery.json ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "datetimepicker",
3
+ "version": "2.4.5",
4
+ "title": "jQuery Date and Time picker",
5
+ "description": "jQuery plugin for date, time, or datetime manipulation in form",
6
+ "keywords": [
7
+ "calendar",
8
+ "date",
9
+ "time",
10
+ "form",
11
+ "datetime",
12
+ "datepicker",
13
+ "timepicker",
14
+ "datetimepicker",
15
+ "validation",
16
+ "ui",
17
+ "scroller",
18
+ "picker",
19
+ "i18n",
20
+ "input",
21
+ "jquery",
22
+ "touch"
23
+ ],
24
+ "author": {
25
+ "name": "Chupurnov Valeriy",
26
+ "email": "chupurnov@gmail.com",
27
+ "url": "http://xdsoft.net/contacts.html"
28
+ },
29
+ "maintainers": [{
30
+ "name": "Chupurnov Valeriy",
31
+ "email": "chupurnov@gmail.com",
32
+ "url": "http://xdsoft.net"
33
+ }],
34
+ "licenses": [
35
+ {
36
+ "type": "MIT",
37
+ "url": "https://github.com/xdan/datetimepicker/blob/master/MIT-LICENSE.txt"
38
+ }
39
+ ],
40
+ "bugs": "https://github.com/xdan/datetimepicker/issues",
41
+ "homepage": "http://xdsoft.net/jqplugins/datetimepicker/",
42
+ "docs": "http://xdsoft.net/jqplugins/datetimepicker/",
43
+ "download": "https://github.com/xdan/datetimepicker/archive/master.zip",
44
+ "dependencies": {
45
+ "jquery": ">=1.7"
46
+ }
47
+ }
trunk/assets/libraries/datetimepicker/jquery.datetimepicker.css ADDED
@@ -0,0 +1,545 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .xdsoft_datetimepicker {
2
+ box-shadow: 0 5px 15px -5px rgba(0, 0, 0, 0.506);
3
+ background: #fff;
4
+ border-bottom: 1px solid #bbb;
5
+ border-left: 1px solid #ccc;
6
+ border-right: 1px solid #ccc;
7
+ border-top: 1px solid #ccc;
8
+ color: #333;
9
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
10
+ padding: 8px;
11
+ padding-left: 0;
12
+ padding-top: 2px;
13
+ position: absolute;
14
+ z-index: 9999;
15
+ -moz-box-sizing: border-box;
16
+ box-sizing: border-box;
17
+ display: none;
18
+ }
19
+
20
+ .xdsoft_datetimepicker iframe {
21
+ position: absolute;
22
+ left: 0;
23
+ top: 0;
24
+ width: 75px;
25
+ height: 210px;
26
+ background: transparent;
27
+ border: none;
28
+ }
29
+
30
+ /*For IE8 or lower*/
31
+ .xdsoft_datetimepicker button {
32
+ border: none !important;
33
+ }
34
+
35
+ .xdsoft_noselect {
36
+ -webkit-touch-callout: none;
37
+ -webkit-user-select: none;
38
+ -khtml-user-select: none;
39
+ -moz-user-select: none;
40
+ -ms-user-select: none;
41
+ -o-user-select: none;
42
+ user-select: none;
43
+ }
44
+
45
+ .xdsoft_noselect::selection { background: transparent }
46
+ .xdsoft_noselect::-moz-selection { background: transparent }
47
+
48
+ .xdsoft_datetimepicker.xdsoft_inline {
49
+ display: inline-block;
50
+ position: static;
51
+ box-shadow: none;
52
+ }
53
+
54
+ .xdsoft_datetimepicker * {
55
+ -moz-box-sizing: border-box;
56
+ box-sizing: border-box;
57
+ padding: 0;
58
+ margin: 0;
59
+ }
60
+
61
+ .xdsoft_datetimepicker .xdsoft_datepicker, .xdsoft_datetimepicker .xdsoft_timepicker {
62
+ display: none;
63
+ }
64
+
65
+ .xdsoft_datetimepicker .xdsoft_datepicker.active, .xdsoft_datetimepicker .xdsoft_timepicker.active {
66
+ display: block;
67
+ }
68
+
69
+ .xdsoft_datetimepicker .xdsoft_datepicker {
70
+ width: 224px;
71
+ float: left;
72
+ margin-left: 8px;
73
+ }
74
+
75
+ .xdsoft_datetimepicker.xdsoft_showweeks .xdsoft_datepicker {
76
+ width: 256px;
77
+ }
78
+
79
+ .xdsoft_datetimepicker .xdsoft_timepicker {
80
+ width: 58px;
81
+ float: left;
82
+ text-align: center;
83
+ margin-left: 8px;
84
+ margin-top: 0;
85
+ }
86
+
87
+ .xdsoft_datetimepicker .xdsoft_datepicker.active+.xdsoft_timepicker {
88
+ margin-top: 8px;
89
+ margin-bottom: 3px
90
+ }
91
+
92
+ .xdsoft_datetimepicker .xdsoft_mounthpicker {
93
+ position: relative;
94
+ text-align: center;
95
+ }
96
+
97
+ .xdsoft_datetimepicker .xdsoft_label i,
98
+ .xdsoft_datetimepicker .xdsoft_prev,
99
+ .xdsoft_datetimepicker .xdsoft_next,
100
+ .xdsoft_datetimepicker .xdsoft_today_button {
101
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAeCAYAAADaW7vzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0NBRjI1NjM0M0UwMTFFNDk4NkFGMzJFQkQzQjEwRUIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0NBRjI1NjQ0M0UwMTFFNDk4NkFGMzJFQkQzQjEwRUIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDQ0FGMjU2MTQzRTAxMUU0OTg2QUYzMkVCRDNCMTBFQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDQ0FGMjU2MjQzRTAxMUU0OTg2QUYzMkVCRDNCMTBFQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoNEP54AAAIOSURBVHja7Jq9TsMwEMcxrZD4WpBYeKUCe+kTMCACHZh4BFfHO/AAIHZGFhYkBBsSEqxsLCAgXKhbXYOTxh9pfJVP+qutnZ5s/5Lz2Y5I03QhWji2GIcgAokWgfCxNvcOCCGKqiSqhUp0laHOne05vdEyGMfkdxJDVjgwDlEQgYQBgx+ULJaWSXXS6r/ER5FBVR8VfGftTKcITNs+a1XpcFoExREIDF14AVIFxgQUS+h520cdud6wNkC0UBw6BCO/HoCYwBhD8QCkQ/x1mwDyD4plh4D6DDV0TAGyo4HcawLIBBSLDkHeH0Mg2yVP3l4TQMZQDDsEOl/MgHQqhMNuE0D+oBh0CIr8MAKyazBH9WyBuKxDWgbXfjNf32TZ1KWm/Ap1oSk/R53UtQ5xTh3LUlMmT8gt6g51Q9p+SobxgJQ/qmsfZhWywGFSl0yBjCLJCMgXail3b7+rumdVJ2YRss4cN+r6qAHDkPWjPjdJCF4n9RmAD/V9A/Wp4NQassDjwlB6XBiCxcJQWmZZb8THFilfy/lfrTvLghq2TqTHrRMTKNJ0sIhdo15RT+RpyWwFdY96UZ/LdQKBGjcXpcc1AlSFEfLmouD+1knuxBDUVrvOBmoOC/rEcN7OQxKVeJTCiAdUzUJhA2Oez9QTkp72OTVcxDcXY8iKNkxGAJXmJCOQwOa6dhyXsOa6XwEGAKdeb5ET3rQdAAAAAElFTkSuQmCC);
102
+ }
103
+
104
+ .xdsoft_datetimepicker .xdsoft_label i {
105
+ opacity: 0.5;
106
+ background-position: -92px -19px;
107
+ display: inline-block;
108
+ width: 9px;
109
+ height: 20px;
110
+ vertical-align: middle;
111
+ }
112
+
113
+ .xdsoft_datetimepicker .xdsoft_prev {
114
+ float: left;
115
+ background-position: -20px 0;
116
+ }
117
+ .xdsoft_datetimepicker .xdsoft_today_button {
118
+ float: left;
119
+ background-position: -70px 0;
120
+ margin-left: 5px;
121
+ }
122
+
123
+ .xdsoft_datetimepicker .xdsoft_next {
124
+ float: right;
125
+ background-position: 0 0;
126
+ }
127
+
128
+ .xdsoft_datetimepicker .xdsoft_next,
129
+ .xdsoft_datetimepicker .xdsoft_prev ,
130
+ .xdsoft_datetimepicker .xdsoft_today_button {
131
+ background-color: transparent;
132
+ background-repeat: no-repeat;
133
+ border: 0 none;
134
+ cursor: pointer;
135
+ display: block;
136
+ height: 30px;
137
+ opacity: 0.5;
138
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
139
+ outline: medium none;
140
+ overflow: hidden;
141
+ padding: 0;
142
+ position: relative;
143
+ text-indent: 100%;
144
+ white-space: nowrap;
145
+ width: 20px;
146
+ min-width: 0;
147
+ }
148
+
149
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_prev,
150
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_next {
151
+ float: none;
152
+ background-position: -40px -15px;
153
+ height: 15px;
154
+ width: 30px;
155
+ display: block;
156
+ margin-left: 14px;
157
+ margin-top: 7px;
158
+ }
159
+
160
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_prev {
161
+ background-position: -40px 0;
162
+ margin-bottom: 7px;
163
+ margin-top: 0;
164
+ }
165
+
166
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box {
167
+ height: 151px;
168
+ overflow: hidden;
169
+ border-bottom: 1px solid #ddd;
170
+ }
171
+
172
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div {
173
+ background: #f5f5f5;
174
+ border-top: 1px solid #ddd;
175
+ color: #666;
176
+ font-size: 12px;
177
+ text-align: center;
178
+ border-collapse: collapse;
179
+ cursor: pointer;
180
+ border-bottom-width: 0;
181
+ height: 25px;
182
+ line-height: 25px;
183
+ }
184
+
185
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div > div:first-child {
186
+ border-top-width: 0;
187
+ }
188
+
189
+ .xdsoft_datetimepicker .xdsoft_today_button:hover,
190
+ .xdsoft_datetimepicker .xdsoft_next:hover,
191
+ .xdsoft_datetimepicker .xdsoft_prev:hover {
192
+ opacity: 1;
193
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
194
+ }
195
+
196
+ .xdsoft_datetimepicker .xdsoft_label {
197
+ display: inline;
198
+ position: relative;
199
+ z-index: 9999;
200
+ margin: 0;
201
+ padding: 5px 3px;
202
+ font-size: 14px;
203
+ line-height: 20px;
204
+ font-weight: bold;
205
+ background-color: #fff;
206
+ float: left;
207
+ width: 182px;
208
+ text-align: center;
209
+ cursor: pointer;
210
+ }
211
+
212
+ .xdsoft_datetimepicker .xdsoft_label:hover>span {
213
+ text-decoration: underline;
214
+ }
215
+
216
+ .xdsoft_datetimepicker .xdsoft_label:hover i {
217
+ opacity: 1.0;
218
+ }
219
+
220
+ .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select {
221
+ border: 1px solid #ccc;
222
+ position: absolute;
223
+ right: 0;
224
+ top: 30px;
225
+ z-index: 101;
226
+ display: none;
227
+ background: #fff;
228
+ max-height: 160px;
229
+ overflow-y: hidden;
230
+ }
231
+
232
+ .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select.xdsoft_monthselect{ right: -7px }
233
+ .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select.xdsoft_yearselect{ right: 2px }
234
+ .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select > div > .xdsoft_option:hover {
235
+ color: #fff;
236
+ background: #ff8000;
237
+ }
238
+
239
+ .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select > div > .xdsoft_option {
240
+ padding: 2px 10px 2px 5px;
241
+ text-decoration: none !important;
242
+ }
243
+
244
+ .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select > div > .xdsoft_option.xdsoft_current {
245
+ background: #33aaff;
246
+ box-shadow: #178fe5 0 1px 3px 0 inset;
247
+ color: #fff;
248
+ font-weight: 700;
249
+ }
250
+
251
+ .xdsoft_datetimepicker .xdsoft_month {
252
+ width: 100px;
253
+ text-align: right;
254
+ }
255
+
256
+ .xdsoft_datetimepicker .xdsoft_calendar {
257
+ clear: both;
258
+ }
259
+
260
+ .xdsoft_datetimepicker .xdsoft_year{
261
+ width: 48px;
262
+ margin-left: 5px;
263
+ }
264
+
265
+ .xdsoft_datetimepicker .xdsoft_calendar table {
266
+ border-collapse: collapse;
267
+ width: 100%;
268
+
269
+ }
270
+
271
+ .xdsoft_datetimepicker .xdsoft_calendar td > div {
272
+ padding-right: 5px;
273
+ }
274
+
275
+ .xdsoft_datetimepicker .xdsoft_calendar th {
276
+ height: 25px;
277
+ }
278
+
279
+ .xdsoft_datetimepicker .xdsoft_calendar td,.xdsoft_datetimepicker .xdsoft_calendar th {
280
+ width: 14.2857142%;
281
+ background: #f5f5f5;
282
+ border: 1px solid #ddd;
283
+ color: #666;
284
+ font-size: 12px;
285
+ text-align: right;
286
+ vertical-align: middle;
287
+ padding: 0;
288
+ border-collapse: collapse;
289
+ cursor: pointer;
290
+ height: 25px;
291
+ }
292
+ .xdsoft_datetimepicker.xdsoft_showweeks .xdsoft_calendar td,.xdsoft_datetimepicker.xdsoft_showweeks .xdsoft_calendar th {
293
+ width: 12.5%;
294
+ }
295
+
296
+ .xdsoft_datetimepicker .xdsoft_calendar th {
297
+ background: #f1f1f1;
298
+ }
299
+
300
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_today {
301
+ color: #33aaff;
302
+ }
303
+
304
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_highlighted_default {
305
+ background: #ffe9d2;
306
+ box-shadow: #ffb871 0 1px 4px 0 inset;
307
+ color: #000;
308
+ }
309
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_highlighted_mint {
310
+ background: #c1ffc9;
311
+ box-shadow: #00dd1c 0 1px 4px 0 inset;
312
+ color: #000;
313
+ }
314
+
315
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_default,
316
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current,
317
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_current {
318
+ background: #33aaff;
319
+ box-shadow: #178fe5 0 1px 3px 0 inset;
320
+ color: #fff;
321
+ font-weight: 700;
322
+ }
323
+
324
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_other_month,
325
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_disabled,
326
+ .xdsoft_datetimepicker .xdsoft_time_box >div >div.xdsoft_disabled {
327
+ opacity: 0.5;
328
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
329
+ cursor: default;
330
+ }
331
+
332
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_other_month.xdsoft_disabled {
333
+ opacity: 0.2;
334
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
335
+ }
336
+
337
+ .xdsoft_datetimepicker .xdsoft_calendar td:hover,
338
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div:hover {
339
+ color: #fff !important;
340
+ background: #ff8000 !important;
341
+ box-shadow: none !important;
342
+ }
343
+
344
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current.xdsoft_disabled:hover,
345
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box>div>div.xdsoft_current.xdsoft_disabled:hover {
346
+ background: #33aaff !important;
347
+ box-shadow: #178fe5 0 1px 3px 0 inset !important;
348
+ color: #fff !important;
349
+ }
350
+
351
+ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_disabled:hover,
352
+ .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_disabled:hover {
353
+ color: inherit !important;
354
+ background: inherit !important;
355
+ box-shadow: inherit !important;
356
+ }
357
+
358
+ .xdsoft_datetimepicker .xdsoft_calendar th {
359
+ font-weight: 700;
360
+ text-align: center;
361
+ color: #999;
362
+ cursor: default;
363
+ }
364
+
365
+ .xdsoft_datetimepicker .xdsoft_copyright {
366
+ color: #ccc !important;
367
+ font-size: 10px;
368
+ clear: both;
369
+ float: none;
370
+ margin-left: 8px;
371
+ }
372
+
373
+ .xdsoft_datetimepicker .xdsoft_copyright a { color: #eee !important }
374
+ .xdsoft_datetimepicker .xdsoft_copyright a:hover { color: #aaa !important }
375
+
376
+ .xdsoft_time_box {
377
+ position: relative;
378
+ border: 1px solid #ccc;
379
+ }
380
+ .xdsoft_scrollbar >.xdsoft_scroller {
381
+ background: #ccc !important;
382
+ height: 20px;
383
+ border-radius: 3px;
384
+ }
385
+ .xdsoft_scrollbar {
386
+ position: absolute;
387
+ width: 7px;
388
+ right: 0;
389
+ top: 0;
390
+ bottom: 0;
391
+ cursor: pointer;
392
+ }
393
+ .xdsoft_scroller_box {
394
+ position: relative;
395
+ }
396
+
397
+ .xdsoft_datetimepicker.xdsoft_dark {
398
+ box-shadow: 0 5px 15px -5px rgba(255, 255, 255, 0.506);
399
+ background: #000;
400
+ border-bottom: 1px solid #444;
401
+ border-left: 1px solid #333;
402
+ border-right: 1px solid #333;
403
+ border-top: 1px solid #333;
404
+ color: #ccc;
405
+ }
406
+
407
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box {
408
+ border-bottom: 1px solid #222;
409
+ }
410
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div {
411
+ background: #0a0a0a;
412
+ border-top: 1px solid #222;
413
+ color: #999;
414
+ }
415
+
416
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_label {
417
+ background-color: #000;
418
+ }
419
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select {
420
+ border: 1px solid #333;
421
+ background: #000;
422
+ }
423
+
424
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select > div > .xdsoft_option:hover {
425
+ color: #000;
426
+ background: #007fff;
427
+ }
428
+
429
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select > div > .xdsoft_option.xdsoft_current {
430
+ background: #cc5500;
431
+ box-shadow: #b03e00 0 1px 3px 0 inset;
432
+ color: #000;
433
+ }
434
+
435
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_label i,
436
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_prev,
437
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_next,
438
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_today_button {
439
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAeCAYAAADaW7vzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUExQUUzOTA0M0UyMTFFNDlBM0FFQTJENTExRDVBODYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUExQUUzOTE0M0UyMTFFNDlBM0FFQTJENTExRDVBODYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQTFBRTM4RTQzRTIxMUU0OUEzQUVBMkQ1MTFENUE4NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQTFBRTM4RjQzRTIxMUU0OUEzQUVBMkQ1MTFENUE4NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pp0VxGEAAAIASURBVHja7JrNSgMxEMebtgh+3MSLr1T1Xn2CHoSKB08+QmR8Bx9A8e7RixdB9CKCoNdexIugxFlJa7rNZneTbLIpM/CnNLsdMvNjM8l0mRCiQ9Ye61IKCAgZAUnH+mU3MMZaHYChBnJUDzWOFZdVfc5+ZFLbrWDeXPwbxIqrLLfaeS0hEBVGIRQCEiZoHQwtlGSByCCdYBl8g8egTTAWoKQMRBRBcZxYlhzhKegqMOageErsCHVkk3hXIFooDgHB1KkHIHVgzKB4ADJQ/A1jAFmAYhkQqA5TOBtocrKrgXwQA8gcFIuAIO8sQSA7hidvPwaQGZSaAYHOUWJABhWWw2EMIH9QagQERU4SArJXo0ZZL18uvaxejXt/Em8xjVBXmvFr1KVm/AJ10tRe2XnraNqaJvKE3KHuUbfK1E+VHB0q40/y3sdQSxY4FHWeKJCunP8UyDdqJZenT3ntVV5jIYCAh20vT7ioP8tpf6E2lfEMwERe+whV1MHjwZB7PBiCxcGQWwKZKD62lfGNnP/1poFAA60T7rF1UgcKd2id3KDeUS+oLWV8DfWAepOfq00CgQabi9zjcgJVYVD7PVzQUAUGAQkbNJTBICDhgwYTjDYD6XeW08ZKh+A4pYkzenOxXUbvZcWz7E8ykRMnIHGX1XPl+1m2vPYpL+2qdb8CDAARlKFEz/ZVkAAAAABJRU5ErkJggg==);
440
+ }
441
+
442
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td,
443
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th {
444
+ background: #0a0a0a;
445
+ border: 1px solid #222;
446
+ color: #999;
447
+ }
448
+
449
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th {
450
+ background: #0e0e0e;
451
+ }
452
+
453
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_today {
454
+ color: #cc5500;
455
+ }
456
+
457
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_highlighted_default {
458
+ background: #ffe9d2;
459
+ box-shadow: #ffb871 0 1px 4px 0 inset;
460
+ color:#000;
461
+ }
462
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_highlighted_mint {
463
+ background: #c1ffc9;
464
+ box-shadow: #00dd1c 0 1px 4px 0 inset;
465
+ color:#000;
466
+ }
467
+
468
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_default,
469
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_current,
470
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_current {
471
+ background: #cc5500;
472
+ box-shadow: #b03e00 0 1px 3px 0 inset;
473
+ color: #000;
474
+ }
475
+
476
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td:hover,
477
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div:hover {
478
+ color: #000 !important;
479
+ background: #007fff !important;
480
+ }
481
+
482
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th {
483
+ color: #666;
484
+ }
485
+
486
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright { color: #333 !important }
487
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright a { color: #111 !important }
488
+ .xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright a:hover { color: #555 !important }
489
+
490
+ .xdsoft_dark .xdsoft_time_box {
491
+ border: 1px solid #333;
492
+ }
493
+
494
+ .xdsoft_dark .xdsoft_scrollbar >.xdsoft_scroller {
495
+ background: #333 !important;
496
+ }
497
+ .xdsoft_datetimepicker .xdsoft_save_selected {
498
+ display: block;
499
+ border: 1px solid #dddddd !important;
500
+ margin-top: 5px;
501
+ width: 100%;
502
+ color: #454551;
503
+ font-size: 13px;
504
+ }
505
+ .xdsoft_datetimepicker .blue-gradient-button {
506
+ font-family: "museo-sans", "Book Antiqua", sans-serif;
507
+ font-size: 12px;
508
+ font-weight: 300;
509
+ color: #82878c;
510
+ height: 28px;
511
+ position: relative;
512
+ padding: 4px 17px 4px 33px;
513
+ border: 1px solid #d7d8da;
514
+ background: -moz-linear-gradient(top, #fff 0%, #f4f8fa 73%);
515
+ /* FF3.6+ */
516
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fff), color-stop(73%, #f4f8fa));
517
+ /* Chrome,Safari4+ */
518
+ background: -webkit-linear-gradient(top, #fff 0%, #f4f8fa 73%);
519
+ /* Chrome10+,Safari5.1+ */
520
+ background: -o-linear-gradient(top, #fff 0%, #f4f8fa 73%);
521
+ /* Opera 11.10+ */
522
+ background: -ms-linear-gradient(top, #fff 0%, #f4f8fa 73%);
523
+ /* IE10+ */
524
+ background: linear-gradient(to bottom, #fff 0%, #f4f8fa 73%);
525
+ /* W3C */
526
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff', endColorstr='#f4f8fa',GradientType=0 );
527
+ /* IE6-9 */
528
+ }
529
+ .xdsoft_datetimepicker .blue-gradient-button:hover, .xdsoft_datetimepicker .blue-gradient-button:focus, .xdsoft_datetimepicker .blue-gradient-button:hover span, .xdsoft_datetimepicker .blue-gradient-button:focus span {
530
+ color: #454551;
531
+ background: -moz-linear-gradient(top, #f4f8fa 0%, #FFF 73%);
532
+ /* FF3.6+ */
533
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f4f8fa), color-stop(73%, #FFF));
534
+ /* Chrome,Safari4+ */
535
+ background: -webkit-linear-gradient(top, #f4f8fa 0%, #FFF 73%);
536
+ /* Chrome10+,Safari5.1+ */
537
+ background: -o-linear-gradient(top, #f4f8fa 0%, #FFF 73%);
538
+ /* Opera 11.10+ */
539
+ background: -ms-linear-gradient(top, #f4f8fa 0%, #FFF 73%);
540
+ /* IE10+ */
541
+ background: linear-gradient(to bottom, #f4f8fa 0%, #FFF 73%);
542
+ /* W3C */
543
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f8fa', endColorstr='#FFF',GradientType=0 );
544
+ /* IE6-9 */
545
+ }
trunk/assets/libraries/datetimepicker/jquery.datetimepicker.js ADDED
@@ -0,0 +1,2073 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @preserve jQuery DateTimePicker plugin v2.4.5
3
+ * @homepage http://xdsoft.net/jqplugins/datetimepicker/
4
+ * (c) 2014, Chupurnov Valeriy.
5
+ */
6
+ /*global document,window,jQuery,setTimeout,clearTimeout,HighlightedDate,getCurrentValue*/
7
+ (function ($) {
8
+ 'use strict';
9
+ var default_options = {
10
+ i18n: {
11
+ ar: { // Arabic
12
+ months: [
13
+ "كانون الثاني", "شباط", "آذار", "نيسان", "مايو", "حزيران", "تموز", "آب", "أيلول", "تشرين الأول", "تشرين الثاني", "كانون الأول"
14
+ ],
15
+ dayOfWeek: [
16
+ "ن", "ث", "ع", "خ", "ج", "س", "ح"
17
+ ]
18
+ },
19
+ ro: { // Romanian
20
+ months: [
21
+ "ianuarie", "februarie", "martie", "aprilie", "mai", "iunie", "iulie", "august", "septembrie", "octombrie", "noiembrie", "decembrie"
22
+ ],
23
+ dayOfWeek: [
24
+ "l", "ma", "mi", "j", "v", "s", "d"
25
+ ]
26
+ },
27
+ id: { // Indonesian
28
+ months: [
29
+ "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"
30
+ ],
31
+ dayOfWeek: [
32
+ "Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"
33
+ ]
34
+ },
35
+ is: { // Icelandic
36
+ months: [
37
+ "Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ágúst", "September", "Október", "Nóvember", "Desember"
38
+ ],
39
+ dayOfWeek: [
40
+ "Sun", "Mán", "Þrið", "Mið", "Fim", "Fös", "Lau"
41
+ ]
42
+ },
43
+ bg: { // Bulgarian
44
+ months: [
45
+ "Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"
46
+ ],
47
+ dayOfWeek: [
48
+ "Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"
49
+ ]
50
+ },
51
+ fa: { // Persian/Farsi
52
+ months: [
53
+ 'فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند'
54
+ ],
55
+ dayOfWeek: [
56
+ 'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'
57
+ ]
58
+ },
59
+ ru: { // Russian
60
+ months: [
61
+ 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'
62
+ ],
63
+ dayOfWeek: [
64
+ "Вск", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"
65
+ ]
66
+ },
67
+ uk: { // Ukrainian
68
+ months: [
69
+ 'Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень'
70
+ ],
71
+ dayOfWeek: [
72
+ "Ндл", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Сбт"
73
+ ]
74
+ },
75
+ en: { // English
76
+ months: [
77
+ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
78
+ ],
79
+ dayOfWeek: [
80
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
81
+ ]
82
+ },
83
+ el: { // Ελληνικά
84
+ months: [
85
+ "Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"
86
+ ],
87
+ dayOfWeek: [
88
+ "Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"
89
+ ]
90
+ },
91
+ de: { // German
92
+ months: [
93
+ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'
94
+ ],
95
+ dayOfWeek: [
96
+ "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"
97
+ ]
98
+ },
99
+ nl: { // Dutch
100
+ months: [
101
+ "januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"
102
+ ],
103
+ dayOfWeek: [
104
+ "zo", "ma", "di", "wo", "do", "vr", "za"
105
+ ]
106
+ },
107
+ tr: { // Turkish
108
+ months: [
109
+ "Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"
110
+ ],
111
+ dayOfWeek: [
112
+ "Paz", "Pts", "Sal", "Çar", "Per", "Cum", "Cts"
113
+ ]
114
+ },
115
+ fr: { //French
116
+ months: [
117
+ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"
118
+ ],
119
+ dayOfWeek: [
120
+ "Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"
121
+ ]
122
+ },
123
+ es: { // Spanish
124
+ months: [
125
+ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
126
+ ],
127
+ dayOfWeek: [
128
+ "Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"
129
+ ]
130
+ },
131
+ th: { // Thai
132
+ months: [
133
+ 'มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'
134
+ ],
135
+ dayOfWeek: [
136
+ 'อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'
137
+ ]
138
+ },
139
+ pl: { // Polish
140
+ months: [
141
+ "styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"
142
+ ],
143
+ dayOfWeek: [
144
+ "nd", "pn", "wt", "śr", "cz", "pt", "sb"
145
+ ]
146
+ },
147
+ pt: { // Portuguese
148
+ months: [
149
+ "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"
150
+ ],
151
+ dayOfWeek: [
152
+ "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"
153
+ ]
154
+ },
155
+ ch: { // Simplified Chinese
156
+ months: [
157
+ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
158
+ ],
159
+ dayOfWeek: [
160
+ "日", "一", "二", "三", "四", "五", "六"
161
+ ]
162
+ },
163
+ se: { // Swedish
164
+ months: [
165
+ "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"
166
+ ],
167
+ dayOfWeek: [
168
+ "Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"
169
+ ]
170
+ },
171
+ kr: { // Korean
172
+ months: [
173
+ "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"
174
+ ],
175
+ dayOfWeek: [
176
+ "일", "월", "화", "수", "목", "금", "토"
177
+ ]
178
+ },
179
+ it: { // Italian
180
+ months: [
181
+ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"
182
+ ],
183
+ dayOfWeek: [
184
+ "Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"
185
+ ]
186
+ },
187
+ da: { // Dansk
188
+ months: [
189
+ "January", "Februar", "Marts", "April", "Maj", "Juni", "July", "August", "September", "Oktober", "November", "December"
190
+ ],
191
+ dayOfWeek: [
192
+ "Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"
193
+ ]
194
+ },
195
+ no: { // Norwegian
196
+ months: [
197
+ "Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"
198
+ ],
199
+ dayOfWeek: [
200
+ "Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"
201
+ ]
202
+ },
203
+ ja: { // Japanese
204
+ months: [
205
+ "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"
206
+ ],
207
+ dayOfWeek: [
208
+ "日", "月", "火", "水", "木", "金", "土"
209
+ ]
210
+ },
211
+ vi: { // Vietnamese
212
+ months: [
213
+ "Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"
214
+ ],
215
+ dayOfWeek: [
216
+ "CN", "T2", "T3", "T4", "T5", "T6", "T7"
217
+ ]
218
+ },
219
+ sl: { // Slovenščina
220
+ months: [
221
+ "Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"
222
+ ],
223
+ dayOfWeek: [
224
+ "Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob"
225
+ ]
226
+ },
227
+ cs: { // Čeština
228
+ months: [
229
+ "Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"
230
+ ],
231
+ dayOfWeek: [
232
+ "Ne", "Po", "Út", "St", "Čt", "Pá", "So"
233
+ ]
234
+ },
235
+ hu: { // Hungarian
236
+ months: [
237
+ "Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"
238
+ ],
239
+ dayOfWeek: [
240
+ "Va", "Hé", "Ke", "Sze", "Cs", "Pé", "Szo"
241
+ ]
242
+ },
243
+ az: { //Azerbaijanian (Azeri)
244
+ months: [
245
+ "Yanvar", "Fevral", "Mart", "Aprel", "May", "Iyun", "Iyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"
246
+ ],
247
+ dayOfWeek: [
248
+ "B", "Be", "Ça", "Ç", "Ca", "C", "Ş"
249
+ ]
250
+ },
251
+ bs: { //Bosanski
252
+ months: [
253
+ "Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"
254
+ ],
255
+ dayOfWeek: [
256
+ "Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"
257
+ ]
258
+ },
259
+ ca: { //Català
260
+ months: [
261
+ "Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"
262
+ ],
263
+ dayOfWeek: [
264
+ "Dg", "Dl", "Dt", "Dc", "Dj", "Dv", "Ds"
265
+ ]
266
+ },
267
+ 'en-GB': { //English (British)
268
+ months: [
269
+ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
270
+ ],
271
+ dayOfWeek: [
272
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
273
+ ]
274
+ },
275
+ et: { //"Eesti"
276
+ months: [
277
+ "Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"
278
+ ],
279
+ dayOfWeek: [
280
+ "P", "E", "T", "K", "N", "R", "L"
281
+ ]
282
+ },
283
+ eu: { //Euskara
284
+ months: [
285
+ "Urtarrila", "Otsaila", "Martxoa", "Apirila", "Maiatza", "Ekaina", "Uztaila", "Abuztua", "Iraila", "Urria", "Azaroa", "Abendua"
286
+ ],
287
+ dayOfWeek: [
288
+ "Ig.", "Al.", "Ar.", "Az.", "Og.", "Or.", "La."
289
+ ]
290
+ },
291
+ fi: { //Finnish (Suomi)
292
+ months: [
293
+ "Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu", "Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu", "Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu"
294
+ ],
295
+ dayOfWeek: [
296
+ "Su", "Ma", "Ti", "Ke", "To", "Pe", "La"
297
+ ]
298
+ },
299
+ gl: { //Galego
300
+ months: [
301
+ "Xan", "Feb", "Maz", "Abr", "Mai", "Xun", "Xul", "Ago", "Set", "Out", "Nov", "Dec"
302
+ ],
303
+ dayOfWeek: [
304
+ "Dom", "Lun", "Mar", "Mer", "Xov", "Ven", "Sab"
305
+ ]
306
+ },
307
+ hr: { //Hrvatski
308
+ months: [
309
+ "Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"
310
+ ],
311
+ dayOfWeek: [
312
+ "Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"
313
+ ]
314
+ },
315
+ ko: { //Korean (한국어)
316
+ months: [
317
+ "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"
318
+ ],
319
+ dayOfWeek: [
320
+ "일", "월", "화", "수", "목", "금", "토"
321
+ ]
322
+ },
323
+ lt: { //Lithuanian (lietuvių)
324
+ months: [
325
+ "Sausio", "Vasario", "Kovo", "Balandžio", "Gegužės", "Birželio", "Liepos", "Rugpjūčio", "Rugsėjo", "Spalio", "Lapkričio", "Gruodžio"
326
+ ],
327
+ dayOfWeek: [
328
+ "Sek", "Pir", "Ant", "Tre", "Ket", "Pen", "Šeš"
329
+ ]
330
+ },
331
+ lv: { //Latvian (Latviešu)
332
+ months: [
333
+ "Janvāris", "Februāris", "Marts", "Aprīlis ", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"
334
+ ],
335
+ dayOfWeek: [
336
+ "Sv", "Pr", "Ot", "Tr", "Ct", "Pk", "St"
337
+ ]
338
+ },
339
+ mk: { //Macedonian (Македонски)
340
+ months: [
341
+ "јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"
342
+ ],
343
+ dayOfWeek: [
344
+ "нед", "пон", "вто", "сре", "чет", "пет", "саб"
345
+ ]
346
+ },
347
+ mn: { //Mongolian (Монгол)
348
+ months: [
349
+ "1-р сар", "2-р сар", "3-р сар", "4-р сар", "5-р сар", "6-р сар", "7-р сар", "8-р сар", "9-р сар", "10-р сар", "11-р сар", "12-р сар"
350
+ ],
351
+ dayOfWeek: [
352
+ "Дав", "Мяг", "Лха", "Пүр", "Бсн", "Бям", "Ням"
353
+ ]
354
+ },
355
+ 'pt-BR': { //Português(Brasil)
356
+ months: [
357
+ "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"
358
+ ],
359
+ dayOfWeek: [
360
+ "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"
361
+ ]
362
+ },
363
+ sk: { //Slovenčina
364
+ months: [
365
+ "Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"
366
+ ],
367
+ dayOfWeek: [
368
+ "Ne", "Po", "Ut", "St", "Št", "Pi", "So"
369
+ ]
370
+ },
371
+ sq: { //Albanian (Shqip)
372
+ months: [
373
+ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
374
+ ],
375
+ dayOfWeek: [
376
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
377
+ ]
378
+ },
379
+ 'sr-YU': { //Serbian (Srpski)
380
+ months: [
381
+ "Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"
382
+ ],
383
+ dayOfWeek: [
384
+ "Ned", "Pon", "Uto", "Sre", "čet", "Pet", "Sub"
385
+ ]
386
+ },
387
+ sr: { //Serbian Cyrillic (Српски)
388
+ months: [
389
+ "јануар", "фебруар", "март", "април", "мај", "јун", "јул", "август", "септембар", "октобар", "новембар", "децембар"
390
+ ],
391
+ dayOfWeek: [
392
+ "нед", "пон", "уто", "сре", "чет", "пет", "суб"
393
+ ]
394
+ },
395
+ sv: { //Svenska
396
+ months: [
397
+ "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"
398
+ ],
399
+ dayOfWeek: [
400
+ "Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"
401
+ ]
402
+ },
403
+ 'zh-TW': { //Traditional Chinese (繁體中文)
404
+ months: [
405
+ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
406
+ ],
407
+ dayOfWeek: [
408
+ "日", "一", "二", "三", "四", "五", "六"
409
+ ]
410
+ },
411
+ zh: { //Simplified Chinese (简体中文)
412
+ months: [
413
+ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
414
+ ],
415
+ dayOfWeek: [
416
+ "日", "一", "二", "三", "四", "五", "六"
417
+ ]
418
+ },
419
+ he: { //Hebrew (עברית)
420
+ months: [
421
+ 'ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'
422
+ ],
423
+ dayOfWeek: [
424
+ 'א\'', 'ב\'', 'ג\'', 'ד\'', 'ה\'', 'ו\'', 'שבת'
425
+ ]
426
+ },
427
+ hy: { // Armenian
428
+ months: [
429
+ "Հունվար", "Փետրվար", "Մարտ", "Ապրիլ", "Մայիս", "Հունիս", "Հուլիս", "Օգոստոս", "Սեպտեմբեր", "Հոկտեմբեր", "Նոյեմբեր", "Դեկտեմբեր"
430
+ ],
431
+ dayOfWeek: [
432
+ "Կի", "Երկ", "Երք", "Չոր", "Հնգ", "Ուրբ", "Շբթ"
433
+ ]
434
+ },
435
+ kg: { // Kyrgyz
436
+ months: [
437
+ 'Үчтүн айы', 'Бирдин айы', 'Жалган Куран', 'Чын Куран', 'Бугу', 'Кулжа', 'Теке', 'Баш Оона', 'Аяк Оона', 'Тогуздун айы', 'Жетинин айы', 'Бештин айы'
438
+ ],
439
+ dayOfWeek: [
440
+ "Жек", "Дүй", "Шей", "Шар", "Бей", "Жум", "Ише"
441
+ ]
442
+ }
443
+ },
444
+ value: '',
445
+ lang: 'en',
446
+
447
+ format: 'Y/m/d H:i',
448
+ formatTime: 'H:i',
449
+ formatDate: 'Y/m/d',
450
+
451
+ startDate: false, // new Date(), '1986/12/08', '-1970/01/05','-1970/01/05',
452
+ step: 60,
453
+ monthChangeSpinner: true,
454
+
455
+ closeOnDateSelect: false,
456
+ closeOnTimeSelect: true,
457
+ closeOnWithoutClick: true,
458
+ closeOnInputClick: true,
459
+
460
+ timepicker: true,
461
+ datepicker: true,
462
+ weeks: false,
463
+
464
+ defaultTime: false, // use formatTime format (ex. '10:00' for formatTime: 'H:i')
465
+ defaultDate: false, // use formatDate format (ex new Date() or '1986/12/08' or '-1970/01/05' or '-1970/01/05')
466
+
467
+ minDate: false,
468
+ maxDate: false,
469
+ minTime: false,
470
+ maxTime: false,
471
+ disabledMinTime: false,
472
+ disabledMaxTime: false,
473
+
474
+ allowTimes: [],
475
+ opened: false,
476
+ initTime: true,
477
+ inline: false,
478
+ theme: '',
479
+
480
+ onSelectDate: function () {},
481
+ onSelectTime: function () {},
482
+ onChangeMonth: function () {},
483
+ onChangeYear: function () {},
484
+ onChangeDateTime: function () {},
485
+ onShow: function () {},
486
+ onClose: function () {},
487
+ onGenerate: function () {},
488
+
489
+ withoutCopyright: true,
490
+ inverseButton: false,
491
+ hours12: false,
492
+ next: 'xdsoft_next',
493
+ prev : 'xdsoft_prev',
494
+ dayOfWeekStart: 0,
495
+ parentID: 'body',
496
+ timeHeightInTimePicker: 25,
497
+ timepickerScrollbar: true,
498
+ todayButton: true,
499
+ prevButton: true,
500
+ nextButton: true,
501
+ defaultSelect: true,
502
+
503
+ scrollMonth: true,
504
+ scrollTime: true,
505
+ scrollInput: true,
506
+
507
+ lazyInit: false,
508
+ mask: false,
509
+ validateOnBlur: true,
510
+ allowBlank: true,
511
+ yearStart: 1950,
512
+ yearEnd: 2050,
513
+ monthStart: 0,
514
+ monthEnd: 11,
515
+ style: '',
516
+ id: '',
517
+ fixed: false,
518
+ roundTime: 'round', // ceil, floor
519
+ className: '',
520
+ weekends: [],
521
+ highlightedDates: [],
522
+ highlightedPeriods: [],
523
+ disabledDates : [],
524
+ disabledWeekDays: [],
525
+ yearOffset: 0,
526
+ beforeShowDay: null,
527
+
528
+ enterLikeTab: true,
529
+ showApplyButton: false
530
+ };
531
+ // fix for ie8
532
+ if (!window.getComputedStyle) {
533
+ window.getComputedStyle = function (el, pseudo) {
534
+ this.el = el;
535
+ this.getPropertyValue = function (prop) {
536
+ var re = /(\-([a-z]){1})/g;
537
+ if (prop === 'float') {
538
+ prop = 'styleFloat';
539
+ }
540
+ if (re.test(prop)) {
541
+ prop = prop.replace(re, function (a, b, c) {
542
+ return c.toUpperCase();
543
+ });
544
+ }
545
+ return el.currentStyle[prop] || null;
546
+ };
547
+ return this;
548
+ };
549
+ }
550
+ if (!Array.prototype.indexOf) {
551
+ Array.prototype.indexOf = function (obj, start) {
552
+ var i, j;
553
+ for (i = (start || 0), j = this.length; i < j; i += 1) {
554
+ if (this[i] === obj) { return i; }
555
+ }
556
+ return -1;
557
+ };
558
+ }
559
+ Date.prototype.countDaysInMonth = function () {
560
+ return new Date(this.getFullYear(), this.getMonth() + 1, 0).getDate();
561
+ };
562
+ $.fn.xdsoftScroller = function (percent) {
563
+ return this.each(function () {
564
+ var timeboxparent = $(this),
565
+ pointerEventToXY = function (e) {
566
+ var out = {x: 0, y: 0},
567
+ touch;
568
+ if (e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend' || e.type === 'touchcancel') {
569
+ touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
570
+ out.x = touch.clientX;
571
+ out.y = touch.clientY;
572
+ } else if (e.type === 'mousedown' || e.type === 'mouseup' || e.type === 'mousemove' || e.type === 'mouseover' || e.type === 'mouseout' || e.type === 'mouseenter' || e.type === 'mouseleave') {
573
+ out.x = e.clientX;
574
+ out.y = e.clientY;
575
+ }
576
+ return out;
577
+ },
578
+ move = 0,
579
+ timebox,
580
+ parentHeight,
581
+ height,
582
+ scrollbar,
583
+ scroller,
584
+ maximumOffset = 100,
585
+ start = false,
586
+ startY = 0,
587
+ startTop = 0,
588
+ h1 = 0,
589
+ touchStart = false,
590
+ startTopScroll = 0,
591
+ calcOffset = function () {};
592
+ if (percent === 'hide') {
593
+ timeboxparent.find('.xdsoft_scrollbar').hide();
594
+ return;
595
+ }
596
+ if (!$(this).hasClass('xdsoft_scroller_box')) {
597
+ timebox = timeboxparent.children().eq(0);
598
+ parentHeight = timeboxparent[0].clientHeight;
599
+ height = timebox[0].offsetHeight;
600
+ scrollbar = $('<div class="xdsoft_scrollbar"></div>');
601
+ scroller = $('<div class="xdsoft_scroller"></div>');
602
+ scrollbar.append(scroller);
603
+
604
+ timeboxparent.addClass('xdsoft_scroller_box').append(scrollbar);
605
+ calcOffset = function calcOffset(event) {
606
+ var offset = pointerEventToXY(event).y - startY + startTopScroll;
607
+ if (offset < 0) {
608
+ offset = 0;
609
+ }
610
+ if (offset + scroller[0].offsetHeight > h1) {
611
+ offset = h1 - scroller[0].offsetHeight;
612
+ }
613
+ timeboxparent.trigger('scroll_element.xdsoft_scroller', [maximumOffset ? offset / maximumOffset : 0]);
614
+ };
615
+
616
+ scroller
617
+ .on('touchstart.xdsoft_scroller mousedown.xdsoft_scroller', function (event) {
618
+ if (!parentHeight) {
619
+ timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percent]);
620
+ }
621
+
622
+ startY = pointerEventToXY(event).y;
623
+ startTopScroll = parseInt(scroller.css('margin-top'), 10);
624
+ h1 = scrollbar[0].offsetHeight;
625
+
626
+ if (event.type === 'mousedown') {
627
+ if (document) {
628
+ $(document.body).addClass('xdsoft_noselect');
629
+ }
630
+ $([document.body, window]).on('mouseup.xdsoft_scroller', function arguments_callee() {
631
+ $([document.body, window]).off('mouseup.xdsoft_scroller', arguments_callee)
632
+ .off('mousemove.xdsoft_scroller', calcOffset)
633
+ .removeClass('xdsoft_noselect');
634
+ });
635
+ $(document.body).on('mousemove.xdsoft_scroller', calcOffset);
636
+ } else {
637
+ touchStart = true;
638
+ event.stopPropagation();
639
+ event.preventDefault();
640
+ }
641
+ })
642
+ .on('touchmove', function (event) {
643
+ if (touchStart) {
644
+ event.preventDefault();
645
+ calcOffset(event);
646
+ }
647
+ })
648
+ .on('touchend touchcancel', function (event) {
649
+ touchStart = false;
650
+ startTopScroll = 0;
651
+ });
652
+
653
+ timeboxparent
654
+ .on('scroll_element.xdsoft_scroller', function (event, percentage) {
655
+ if (!parentHeight) {
656
+ timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percentage, true]);
657
+ }
658
+ percentage = percentage > 1 ? 1 : (percentage < 0 || isNaN(percentage)) ? 0 : percentage;
659
+
660
+ scroller.css('margin-top', maximumOffset * percentage);
661
+
662
+ setTimeout(function () {
663
+ timebox.css('marginTop', -parseInt((timebox[0].offsetHeight - parentHeight) * percentage, 10));
664
+ }, 10);
665
+ })
666
+ .on('resize_scroll.xdsoft_scroller', function (event, percentage, noTriggerScroll) {
667
+ var percent, sh;
668
+ parentHeight = timeboxparent[0].clientHeight;
669
+ height = timebox[0].offsetHeight;
670
+ percent = parentHeight / height;
671
+ sh = percent * scrollbar[0].offsetHeight;
672
+ if (percent > 1) {
673
+ scroller.hide();
674
+ } else {
675
+ scroller.show();
676
+ scroller.css('height', parseInt(sh > 10 ? sh : 10, 10));
677
+ maximumOffset = scrollbar[0].offsetHeight - scroller[0].offsetHeight;
678
+ if (noTriggerScroll !== true) {
679
+ timeboxparent.trigger('scroll_element.xdsoft_scroller', [percentage || Math.abs(parseInt(timebox.css('marginTop'), 10)) / (height - parentHeight)]);
680
+ }
681
+ }
682
+ });
683
+
684
+ timeboxparent.on('mousewheel', function (event) {
685
+ var top = Math.abs(parseInt(timebox.css('marginTop'), 10));
686
+
687
+ top = top - (event.deltaY * 20);
688
+ if (top < 0) {
689
+ top = 0;
690
+ }
691
+
692
+ timeboxparent.trigger('scroll_element.xdsoft_scroller', [top / (height - parentHeight)]);
693
+ event.stopPropagation();
694
+ return false;
695
+ });
696
+
697
+ timeboxparent.on('touchstart', function (event) {
698
+ start = pointerEventToXY(event);
699
+ startTop = Math.abs(parseInt(timebox.css('marginTop'), 10));
700
+ });
701
+
702
+ timeboxparent.on('touchmove', function (event) {
703
+ if (start) {
704
+ event.preventDefault();
705
+ var coord = pointerEventToXY(event);
706
+ timeboxparent.trigger('scroll_element.xdsoft_scroller', [(startTop - (coord.y - start.y)) / (height - parentHeight)]);
707
+ }
708
+ });
709
+
710
+ timeboxparent.on('touchend touchcancel', function (event) {
711
+ start = false;
712
+ startTop = 0;
713
+ });
714
+ }
715
+ timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percent]);
716
+ });
717
+ };
718
+
719
+ $.fn.datetimepicker = function (opt) {
720
+ var KEY0 = 48,
721
+ KEY9 = 57,
722
+ _KEY0 = 96,
723
+ _KEY9 = 105,
724
+ CTRLKEY = 17,
725
+ DEL = 46,
726
+ ENTER = 13,
727
+ ESC = 27,
728
+ BACKSPACE = 8,
729
+ ARROWLEFT = 37,
730
+ ARROWUP = 38,
731
+ ARROWRIGHT = 39,
732
+ ARROWDOWN = 40,
733
+ TAB = 9,
734
+ F5 = 116,
735
+ AKEY = 65,
736
+ CKEY = 67,
737
+ VKEY = 86,
738
+ ZKEY = 90,
739
+ YKEY = 89,
740
+ ctrlDown = false,
741
+ options = ($.isPlainObject(opt) || !opt) ? $.extend(true, {}, default_options, opt) : $.extend(true, {}, default_options),
742
+
743
+ lazyInitTimer = 0,
744
+ createDateTimePicker,
745
+ destroyDateTimePicker,
746
+
747
+ lazyInit = function (input) {
748
+ input
749
+ .on('open.xdsoft focusin.xdsoft mousedown.xdsoft', function initOnActionCallback(event) {
750
+ if (input.is(':disabled') || input.data('xdsoft_datetimepicker')) {
751
+ return;
752
+ }
753
+ clearTimeout(lazyInitTimer);
754
+ lazyInitTimer = setTimeout(function () {
755
+
756
+ if (!input.data('xdsoft_datetimepicker')) {
757
+ createDateTimePicker(input);
758
+ }
759
+ input
760
+ .off('open.xdsoft focusin.xdsoft mousedown.xdsoft', initOnActionCallback)
761
+ .trigger('open.xdsoft');
762
+ }, 100);
763
+ });
764
+ };
765
+
766
+ createDateTimePicker = function (input) {
767
+ var datetimepicker = $('<div class="xdsoft_datetimepicker xdsoft_noselect"></div>'),
768
+ xdsoft_copyright = $('<div class="xdsoft_copyright"><a target="_blank" href="http://xdsoft.net/jqplugins/datetimepicker/">xdsoft.net</a></div>'),
769
+ datepicker = $('<div class="xdsoft_datepicker active"></div>'),
770
+ mounth_picker = $('<div class="xdsoft_mounthpicker"><button type="button" class="xdsoft_prev"></button><button type="button" class="xdsoft_today_button"></button>' +
771
+ '<div class="xdsoft_label xdsoft_month"><span></span><i></i></div>' +
772
+ '<div class="xdsoft_label xdsoft_year"><span></span><i></i></div>' +
773
+ '<button type="button" class="xdsoft_next"></button></div>'),
774
+ calendar = $('<div class="xdsoft_calendar"></div>'),
775
+ timepicker = $('<div class="xdsoft_timepicker active"><button type="button" class="xdsoft_prev"></button><div class="xdsoft_time_box"></div><button type="button" class="xdsoft_next"></button></div>'),
776
+ timeboxparent = timepicker.find('.xdsoft_time_box').eq(0),
777
+ timebox = $('<div class="xdsoft_time_variant"></div>'),
778
+ applyButton = $('<button type="button" class="xdsoft_save_selected blue-gradient-button">Save Selected</button>'),
779
+ /*scrollbar = $('<div class="xdsoft_scrollbar"></div>'),
780
+ scroller = $('<div class="xdsoft_scroller"></div>'),*/
781
+ monthselect = $('<div class="xdsoft_select xdsoft_monthselect"><div></div></div>'),
782
+ yearselect = $('<div class="xdsoft_select xdsoft_yearselect"><div></div></div>'),
783
+ triggerAfterOpen = false,
784
+ XDSoft_datetime,
785
+ //scroll_element,
786
+ xchangeTimer,
787
+ timerclick,
788
+ current_time_index,
789
+ setPos,
790
+ timer = 0,
791
+ timer1 = 0,
792
+ _xdsoft_datetime;
793
+
794
+ if (options.id) {
795
+ datetimepicker.attr('id', options.id);
796
+ }
797
+ if (options.style) {
798
+ datetimepicker.attr('style', options.style);
799
+ }
800
+ if (options.weeks) {
801
+ datetimepicker.addClass('xdsoft_showweeks');
802
+ }
803
+
804
+ datetimepicker.addClass('xdsoft_' + options.theme);
805
+ datetimepicker.addClass(options.className);
806
+
807
+ mounth_picker
808
+ .find('.xdsoft_month span')
809
+ .after(monthselect);
810
+ mounth_picker
811
+ .find('.xdsoft_year span')
812
+ .after(yearselect);
813
+
814
+ mounth_picker
815
+ .find('.xdsoft_month,.xdsoft_year')
816
+ .on('mousedown.xdsoft', function (event) {
817
+ var select = $(this).find('.xdsoft_select').eq(0),
818
+ val = 0,
819
+ top = 0,
820
+ visible = select.is(':visible'),
821
+ items,
822
+ i;
823
+
824
+ mounth_picker
825
+ .find('.xdsoft_select')
826
+ .hide();
827
+ if (_xdsoft_datetime.currentTime) {
828
+ val = _xdsoft_datetime.currentTime[$(this).hasClass('xdsoft_month') ? 'getMonth' : 'getFullYear']();
829
+ }
830
+
831
+ select[visible ? 'hide' : 'show']();
832
+ for (items = select.find('div.xdsoft_option'), i = 0; i < items.length; i += 1) {
833
+ if (items.eq(i).data('value') === val) {
834
+ break;
835
+ } else {
836
+ top += items[0].offsetHeight;
837
+ }
838
+ }
839
+
840
+ select.xdsoftScroller(top / (select.children()[0].offsetHeight - (select[0].clientHeight)));
841
+ event.stopPropagation();
842
+ return false;
843
+ });
844
+
845
+ mounth_picker
846
+ .find('.xdsoft_select')
847
+ .xdsoftScroller()
848
+ .on('mousedown.xdsoft', function (event) {
849
+ event.stopPropagation();
850
+ event.preventDefault();
851
+ })
852
+ .on('mousedown.xdsoft', '.xdsoft_option', function (event) {
853
+
854
+ if (_xdsoft_datetime.currentTime === undefined || _xdsoft_datetime.currentTime === null) {
855
+ _xdsoft_datetime.currentTime = _xdsoft_datetime.now();
856
+ }
857
+
858
+ var year = _xdsoft_datetime.currentTime.getFullYear();
859
+ if (_xdsoft_datetime && _xdsoft_datetime.currentTime) {
860
+ _xdsoft_datetime.currentTime[$(this).parent().parent().hasClass('xdsoft_monthselect') ? 'setMonth' : 'setFullYear']($(this).data('value'));
861
+ }
862
+
863
+ $(this).parent().parent().hide();
864
+
865
+ datetimepicker.trigger('xchange.xdsoft');
866
+ if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
867
+ options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
868
+ }
869
+
870
+ if (year !== _xdsoft_datetime.currentTime.getFullYear() && $.isFunction(options.onChangeYear)) {
871
+ options.onChangeYear.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
872
+ }
873
+ });
874
+
875
+ datetimepicker.setOptions = function (_options) {
876
+ var highlightedDates = {},
877
+ getCaretPos = function (input) {
878
+ try {
879
+ if (document.selection && document.selection.createRange) {
880
+ var range = document.selection.createRange();
881
+ return range.getBookmark().charCodeAt(2) - 2;
882
+ }
883
+ if (input.setSelectionRange) {
884
+ return input.selectionStart;
885
+ }
886
+ } catch (e) {
887
+ return 0;
888
+ }
889
+ },
890
+ setCaretPos = function (node, pos) {
891
+ node = (typeof node === "string" || node instanceof String) ? document.getElementById(node) : node;
892
+ if (!node) {
893
+ return false;
894
+ }
895
+ if (node.createTextRange) {
896
+ var textRange = node.createTextRange();
897
+ textRange.collapse(true);
898
+ textRange.moveEnd('character', pos);
899
+ textRange.moveStart('character', pos);
900
+ textRange.select();
901
+ return true;
902
+ }
903
+ if (node.setSelectionRange) {
904
+ node.setSelectionRange(pos, pos);
905
+ return true;
906
+ }
907
+ return false;
908
+ },
909
+ isValidValue = function (mask, value) {
910
+ var reg = mask
911
+ .replace(/([\[\]\/\{\}\(\)\-\.\+]{1})/g, '\\$1')
912
+ .replace(/_/g, '{digit+}')
913
+ .replace(/([0-9]{1})/g, '{digit$1}')
914
+ .replace(/\{digit([0-9]{1})\}/g, '[0-$1_]{1}')
915
+ .replace(/\{digit[\+]\}/g, '[0-9_]{1}');
916
+ return (new RegExp(reg)).test(value);
917
+ };
918
+ options = $.extend(true, {}, options, _options);
919
+
920
+ if (_options.allowTimes && $.isArray(_options.allowTimes) && _options.allowTimes.length) {
921
+ options.allowTimes = $.extend(true, [], _options.allowTimes);
922
+ }
923
+
924
+ if (_options.weekends && $.isArray(_options.weekends) && _options.weekends.length) {
925
+ options.weekends = $.extend(true, [], _options.weekends);
926
+ }
927
+
928
+ if (_options.highlightedDates && $.isArray(_options.highlightedDates) && _options.highlightedDates.length) {
929
+ $.each(_options.highlightedDates, function (index, value) {
930
+ var splitData = $.map(value.split(','), $.trim),
931
+ exDesc,
932
+ hDate = new HighlightedDate(Date.parseDate(splitData[0], options.formatDate), splitData[1], splitData[2]), // date, desc, style
933
+ keyDate = hDate.date.dateFormat(options.formatDate);
934
+ if (highlightedDates[keyDate] !== undefined) {
935
+ exDesc = highlightedDates[keyDate].desc;
936
+ if (exDesc && exDesc.length && hDate.desc && hDate.desc.length) {
937
+ highlightedDates[keyDate].desc = exDesc + "\n" + hDate.desc;
938
+ }
939
+ } else {
940
+ highlightedDates[keyDate] = hDate;
941
+ }
942
+ });
943
+
944
+ options.highlightedDates = $.extend(true, [], highlightedDates);
945
+ }
946
+
947
+ if (_options.highlightedPeriods && $.isArray(_options.highlightedPeriods) && _options.highlightedPeriods.length) {
948
+ highlightedDates = $.extend(true, [], options.highlightedDates);
949
+ $.each(_options.highlightedPeriods, function (index, value) {
950
+ var splitData = $.map(value.split(','), $.trim),
951
+ dateTest = Date.parseDate(splitData[0], options.formatDate), // start date
952
+ dateEnd = Date.parseDate(splitData[1], options.formatDate),
953
+ desc = splitData[2],
954
+ hDate,
955
+ keyDate,
956
+ exDesc,
957
+ style = splitData[3];
958
+
959
+ while (dateTest <= dateEnd) {
960
+ hDate = new HighlightedDate(dateTest, desc, style);
961
+ keyDate = dateTest.dateFormat(options.formatDate);
962
+ dateTest.setDate(dateTest.getDate() + 1);
963
+ if (highlightedDates[keyDate] !== undefined) {
964
+ exDesc = highlightedDates[keyDate].desc;
965
+ if (exDesc && exDesc.length && hDate.desc && hDate.desc.length) {
966
+ highlightedDates[keyDate].desc = exDesc + "\n" + hDate.desc;
967
+ }
968
+ } else {
969
+ highlightedDates[keyDate] = hDate;
970
+ }
971
+ }
972
+ });
973
+
974
+ options.highlightedDates = $.extend(true, [], highlightedDates);
975
+ }
976
+
977
+ if (_options.disabledDates && $.isArray(_options.disabledDates) && _options.disabledDates.length) {
978
+ options.disabledDates = $.extend(true, [], _options.disabledDates);
979
+ }
980
+
981
+ if (_options.disabledWeekDays && $.isArray(_options.disabledWeekDays) && _options.disabledWeekDays.length) {
982
+ options.disabledWeekDays = $.extend(true, [], _options.disabledWeekDays);
983
+ }
984
+
985
+ if ((options.open || options.opened) && (!options.inline)) {
986
+ input.trigger('open.xdsoft');
987
+ }
988
+
989
+ if (options.inline) {
990
+ triggerAfterOpen = true;
991
+ datetimepicker.addClass('xdsoft_inline');
992
+ input.after(datetimepicker).hide();
993
+ }
994
+
995
+ if (options.inverseButton) {
996
+ options.next = 'xdsoft_prev';
997
+ options.prev = 'xdsoft_next';
998
+ }
999
+
1000
+ if (options.datepicker) {
1001
+ datepicker.addClass('active');
1002
+ } else {
1003
+ datepicker.removeClass('active');
1004
+ }
1005
+
1006
+ if (options.timepicker) {
1007
+ timepicker.addClass('active');
1008
+ } else {
1009
+ timepicker.removeClass('active');
1010
+ }
1011
+
1012
+ if (options.value) {
1013
+ _xdsoft_datetime.setCurrentTime(options.value);
1014
+ if (input && input.val) {
1015
+ input.val(_xdsoft_datetime.str);
1016
+ }
1017
+ }
1018
+
1019
+ if (isNaN(options.dayOfWeekStart)) {
1020
+ options.dayOfWeekStart = 0;
1021
+ } else {
1022
+ options.dayOfWeekStart = parseInt(options.dayOfWeekStart, 10) % 7;
1023
+ }
1024
+
1025
+ if (!options.timepickerScrollbar) {
1026
+ timeboxparent.xdsoftScroller('hide');
1027
+ }
1028
+
1029
+ if (options.minDate && /^-(.*)$/.test(options.minDate)) {
1030
+ options.minDate = _xdsoft_datetime.strToDateTime(options.minDate).dateFormat(options.formatDate);
1031
+ }
1032
+
1033
+ if (options.maxDate && /^\+(.*)$/.test(options.maxDate)) {
1034
+ options.maxDate = _xdsoft_datetime.strToDateTime(options.maxDate).dateFormat(options.formatDate);
1035
+ }
1036
+
1037
+ applyButton.toggle(options.showApplyButton);
1038
+
1039
+ mounth_picker
1040
+ .find('.xdsoft_today_button')
1041
+ .css('visibility', !options.todayButton ? 'hidden' : 'visible');
1042
+
1043
+ mounth_picker
1044
+ .find('.' + options.prev)
1045
+ .css('visibility', !options.prevButton ? 'hidden' : 'visible');
1046
+
1047
+ mounth_picker
1048
+ .find('.' + options.next)
1049
+ .css('visibility', !options.nextButton ? 'hidden' : 'visible');
1050
+
1051
+ if (options.mask) {
1052
+ input.off('keydown.xdsoft');
1053
+
1054
+ if (options.mask === true) {
1055
+ options.mask = options.format
1056
+ .replace(/Y/g, '9999')
1057
+ .replace(/F/g, '9999')
1058
+ .replace(/m/g, '19')
1059
+ .replace(/d/g, '39')
1060
+ .replace(/H/g, '29')
1061
+ .replace(/i/g, '59')
1062
+ .replace(/s/g, '59');
1063
+ }
1064
+
1065
+ if ($.type(options.mask) === 'string') {
1066
+ if (!isValidValue(options.mask, input.val())) {
1067
+ input.val(options.mask.replace(/[0-9]/g, '_'));
1068
+ }
1069
+
1070
+ input.on('keydown.xdsoft', function (event) {
1071
+ var val = this.value,
1072
+ key = event.which,
1073
+ pos,
1074
+ digit;
1075
+
1076
+ if (((key >= KEY0 && key <= KEY9) || (key >= _KEY0 && key <= _KEY9)) || (key === BACKSPACE || key === DEL)) {
1077
+ pos = getCaretPos(this);
1078
+ digit = (key !== BACKSPACE && key !== DEL) ? String.fromCharCode((_KEY0 <= key && key <= _KEY9) ? key - KEY0 : key) : '_';
1079
+
1080
+ if ((key === BACKSPACE || key === DEL) && pos) {
1081
+ pos -= 1;
1082
+ digit = '_';
1083
+ }
1084
+
1085
+ while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
1086
+ pos += (key === BACKSPACE || key === DEL) ? -1 : 1;
1087
+ }
1088
+
1089
+ val = val.substr(0, pos) + digit + val.substr(pos + 1);
1090
+ if ($.trim(val) === '') {
1091
+ val = options.mask.replace(/[0-9]/g, '_');
1092
+ } else {
1093
+ if (pos === options.mask.length) {
1094
+ event.preventDefault();
1095
+ return false;
1096
+ }
1097
+ }
1098
+
1099
+ pos += (key === BACKSPACE || key === DEL) ? 0 : 1;
1100
+ while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
1101
+ pos += (key === BACKSPACE || key === DEL) ? -1 : 1;
1102
+ }
1103
+
1104
+ if (isValidValue(options.mask, val)) {
1105
+ this.value = val;
1106
+ setCaretPos(this, pos);
1107
+ } else if ($.trim(val) === '') {
1108
+ this.value = options.mask.replace(/[0-9]/g, '_');
1109
+ } else {
1110
+ input.trigger('error_input.xdsoft');
1111
+ }
1112
+ } else {
1113
+ if (([AKEY, CKEY, VKEY, ZKEY, YKEY].indexOf(key) !== -1 && ctrlDown) || [ESC, ARROWUP, ARROWDOWN, ARROWLEFT, ARROWRIGHT, F5, CTRLKEY, TAB, ENTER].indexOf(key) !== -1) {
1114
+ return true;
1115
+ }
1116
+ }
1117
+
1118
+ event.preventDefault();
1119
+ return false;
1120
+ });
1121
+ }
1122
+ }
1123
+ if (options.validateOnBlur) {
1124
+ input
1125
+ .off('blur.xdsoft')
1126
+ .on('blur.xdsoft', function () {
1127
+ if (options.allowBlank && !$.trim($(this).val()).length) {
1128
+ $(this).val(null);
1129
+ datetimepicker.data('xdsoft_datetime').empty();
1130
+ } else if (!Date.parseDate($(this).val(), options.format)) {
1131
+ var splittedHours = +([$(this).val()[0], $(this).val()[1]].join('')),
1132
+ splittedMinutes = +([$(this).val()[2], $(this).val()[3]].join(''));
1133
+
1134
+ // parse the numbers as 0312 => 03:12
1135
+ if (!options.datepicker && options.timepicker && splittedHours >= 0 && splittedHours < 24 && splittedMinutes >= 0 && splittedMinutes < 60) {
1136
+ $(this).val([splittedHours, splittedMinutes].map(function (item) {
1137
+ return item > 9 ? item : '0' + item;
1138
+ }).join(':'));
1139
+ } else {
1140
+ $(this).val((_xdsoft_datetime.now()).dateFormat(options.format));
1141
+ }
1142
+
1143
+ datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val());
1144
+ } else {
1145
+ datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val());
1146
+ }
1147
+
1148
+ datetimepicker.trigger('changedatetime.xdsoft');
1149
+ });
1150
+ }
1151
+ options.dayOfWeekStartPrev = (options.dayOfWeekStart === 0) ? 6 : options.dayOfWeekStart - 1;
1152
+
1153
+ datetimepicker
1154
+ .trigger('xchange.xdsoft')
1155
+ .trigger('afterOpen.xdsoft');
1156
+ };
1157
+
1158
+ datetimepicker
1159
+ .data('options', options)
1160
+ .on('mousedown.xdsoft', function (event) {
1161
+ event.stopPropagation();
1162
+ event.preventDefault();
1163
+ yearselect.hide();
1164
+ monthselect.hide();
1165
+ return false;
1166
+ });
1167
+
1168
+ //scroll_element = timepicker.find('.xdsoft_time_box');
1169
+ timeboxparent.append(timebox);
1170
+ timeboxparent.xdsoftScroller();
1171
+
1172
+ datetimepicker.on('afterOpen.xdsoft', function () {
1173
+ timeboxparent.xdsoftScroller();
1174
+ });
1175
+
1176
+ datetimepicker
1177
+ .append(datepicker)
1178
+ .append(timepicker);
1179
+
1180
+ if (options.withoutCopyright !== true) {
1181
+ datetimepicker
1182
+ .append(xdsoft_copyright);
1183
+ }
1184
+
1185
+ datepicker
1186
+ .append(mounth_picker)
1187
+ .append(calendar)
1188
+ .append(applyButton);
1189
+
1190
+ $(options.parentID)
1191
+ .append(datetimepicker);
1192
+
1193
+ XDSoft_datetime = function () {
1194
+ var _this = this;
1195
+ _this.now = function (norecursion) {
1196
+ var d = new Date(),
1197
+ date,
1198
+ time;
1199
+
1200
+ if (!norecursion && options.defaultDate) {
1201
+ date = _this.strToDateTime(options.defaultDate);
1202
+ d.setFullYear(date.getFullYear());
1203
+ d.setMonth(date.getMonth());
1204
+ d.setDate(date.getDate());
1205
+ }
1206
+
1207
+ if (options.yearOffset) {
1208
+ d.setFullYear(d.getFullYear() + options.yearOffset);
1209
+ }
1210
+
1211
+ if (!norecursion && options.defaultTime) {
1212
+ time = _this.strtotime(options.defaultTime);
1213
+ d.setHours(time.getHours());
1214
+ d.setMinutes(time.getMinutes());
1215
+ }
1216
+ return d;
1217
+ };
1218
+
1219
+ _this.isValidDate = function (d) {
1220
+ if (Object.prototype.toString.call(d) !== "[object Date]") {
1221
+ return false;
1222
+ }
1223
+ return !isNaN(d.getTime());
1224
+ };
1225
+
1226
+ _this.setCurrentTime = function (dTime) {
1227
+ _this.currentTime = (typeof dTime === 'string') ? _this.strToDateTime(dTime) : _this.isValidDate(dTime) ? dTime : _this.now();
1228
+ datetimepicker.trigger('xchange.xdsoft');
1229
+ };
1230
+
1231
+ _this.empty = function () {
1232
+ _this.currentTime = null;
1233
+ };
1234
+
1235
+ _this.getCurrentTime = function (dTime) {
1236
+ return _this.currentTime;
1237
+ };
1238
+
1239
+ _this.nextMonth = function () {
1240
+
1241
+ if (_this.currentTime === undefined || _this.currentTime === null) {
1242
+ _this.currentTime = _this.now();
1243
+ }
1244
+
1245
+ var month = _this.currentTime.getMonth() + 1,
1246
+ year;
1247
+ if (month === 12) {
1248
+ _this.currentTime.setFullYear(_this.currentTime.getFullYear() + 1);
1249
+ month = 0;
1250
+ }
1251
+
1252
+ year = _this.currentTime.getFullYear();
1253
+
1254
+ _this.currentTime.setDate(
1255
+ Math.min(
1256
+ new Date(_this.currentTime.getFullYear(), month + 1, 0).getDate(),
1257
+ _this.currentTime.getDate()
1258
+ )
1259
+ );
1260
+ _this.currentTime.setMonth(month);
1261
+
1262
+ if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
1263
+ options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
1264
+ }
1265
+
1266
+ if (year !== _this.currentTime.getFullYear() && $.isFunction(options.onChangeYear)) {
1267
+ options.onChangeYear.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
1268
+ }
1269
+
1270
+ datetimepicker.trigger('xchange.xdsoft');
1271
+ return month;
1272
+ };
1273
+
1274
+ _this.prevMonth = function () {
1275
+
1276
+ if (_this.currentTime === undefined || _this.currentTime === null) {
1277
+ _this.currentTime = _this.now();
1278
+ }
1279
+
1280
+ var month = _this.currentTime.getMonth() - 1;
1281
+ if (month === -1) {
1282
+ _this.currentTime.setFullYear(_this.currentTime.getFullYear() - 1);
1283
+ month = 11;
1284
+ }
1285
+ _this.currentTime.setDate(
1286
+ Math.min(
1287
+ new Date(_this.currentTime.getFullYear(), month + 1, 0).getDate(),
1288
+ _this.currentTime.getDate()
1289
+ )
1290
+ );
1291
+ _this.currentTime.setMonth(month);
1292
+ if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
1293
+ options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
1294
+ }
1295
+ datetimepicker.trigger('xchange.xdsoft');
1296
+ return month;
1297
+ };
1298
+
1299
+ _this.getWeekOfYear = function (datetime) {
1300
+ var onejan = new Date(datetime.getFullYear(), 0, 1);
1301
+ return Math.ceil((((datetime - onejan) / 86400000) + onejan.getDay() + 1) / 7);
1302
+ };
1303
+
1304
+ _this.strToDateTime = function (sDateTime) {
1305
+ var tmpDate = [], timeOffset, currentTime;
1306
+
1307
+ if (sDateTime && sDateTime instanceof Date && _this.isValidDate(sDateTime)) {
1308
+ return sDateTime;
1309
+ }
1310
+
1311
+ tmpDate = /^(\+|\-)(.*)$/.exec(sDateTime);
1312
+ if (tmpDate) {
1313
+ tmpDate[2] = Date.parseDate(tmpDate[2], options.formatDate);
1314
+ }
1315
+ if (tmpDate && tmpDate[2]) {
1316
+ timeOffset = tmpDate[2].getTime() - (tmpDate[2].getTimezoneOffset()) * 60000;
1317
+ currentTime = new Date((_this.now(true)).getTime() + parseInt(tmpDate[1] + '1', 10) * timeOffset);
1318
+ } else {
1319
+ currentTime = sDateTime ? Date.parseDate(sDateTime, options.format) : _this.now();
1320
+ }
1321
+
1322
+ if (!_this.isValidDate(currentTime)) {
1323
+ currentTime = _this.now();
1324
+ }
1325
+
1326
+ return currentTime;
1327
+ };
1328
+
1329
+ _this.strToDate = function (sDate) {
1330
+ if (sDate && sDate instanceof Date && _this.isValidDate(sDate)) {
1331
+ return sDate;
1332
+ }
1333
+
1334
+ var currentTime = sDate ? Date.parseDate(sDate, options.formatDate) : _this.now(true);
1335
+ if (!_this.isValidDate(currentTime)) {
1336
+ currentTime = _this.now(true);
1337
+ }
1338
+ return currentTime;
1339
+ };
1340
+
1341
+ _this.strtotime = function (sTime) {
1342
+ if (sTime && sTime instanceof Date && _this.isValidDate(sTime)) {
1343
+ return sTime;
1344
+ }
1345
+ var currentTime = sTime ? Date.parseDate(sTime, options.formatTime) : _this.now(true);
1346
+ if (!_this.isValidDate(currentTime)) {
1347
+ currentTime = _this.now(true);
1348
+ }
1349
+ return currentTime;
1350
+ };
1351
+
1352
+ _this.str = function () {
1353
+ return _this.currentTime.dateFormat(options.format);
1354
+ };
1355
+ _this.currentTime = this.now();
1356
+ };
1357
+
1358
+ _xdsoft_datetime = new XDSoft_datetime();
1359
+
1360
+ applyButton.on('click', function (e) {//pathbrite
1361
+ e.preventDefault();
1362
+ datetimepicker.data('changed', true);
1363
+ _xdsoft_datetime.setCurrentTime(getCurrentValue());
1364
+ input.val(_xdsoft_datetime.str());
1365
+ datetimepicker.trigger('close.xdsoft');
1366
+ });
1367
+ mounth_picker
1368
+ .find('.xdsoft_today_button')
1369
+ .on('mousedown.xdsoft', function () {
1370
+ datetimepicker.data('changed', true);
1371
+ _xdsoft_datetime.setCurrentTime(0);
1372
+ datetimepicker.trigger('afterOpen.xdsoft');
1373
+ }).on('dblclick.xdsoft', function () {
1374
+ var currentDate = _xdsoft_datetime.getCurrentTime(), minDate, maxDate;
1375
+ currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate());
1376
+ minDate = _xdsoft_datetime.strToDate(options.minDate);
1377
+ minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
1378
+ if (currentDate < minDate) {
1379
+ return;
1380
+ }
1381
+ maxDate = _xdsoft_datetime.strToDate(options.maxDate);
1382
+ maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate());
1383
+ if (currentDate > maxDate) {
1384
+ return;
1385
+ }
1386
+ input.val(_xdsoft_datetime.str());
1387
+ datetimepicker.trigger('close.xdsoft');
1388
+ });
1389
+ mounth_picker
1390
+ .find('.xdsoft_prev,.xdsoft_next')
1391
+ .on('mousedown.xdsoft', function () {
1392
+ var $this = $(this),
1393
+ timer = 0,
1394
+ stop = false;
1395
+
1396
+ (function arguments_callee1(v) {
1397
+ if ($this.hasClass(options.next)) {
1398
+ _xdsoft_datetime.nextMonth();
1399
+ } else if ($this.hasClass(options.prev)) {
1400
+ _xdsoft_datetime.prevMonth();
1401
+ }
1402
+ if (options.monthChangeSpinner) {
1403
+ if (!stop) {
1404
+ timer = setTimeout(arguments_callee1, v || 100);
1405
+ }
1406
+ }
1407
+ }(500));
1408
+
1409
+ $([document.body, window]).on('mouseup.xdsoft', function arguments_callee2() {
1410
+ clearTimeout(timer);
1411
+ stop = true;
1412
+ $([document.body, window]).off('mouseup.xdsoft', arguments_callee2);
1413
+ });
1414
+ });
1415
+
1416
+ timepicker
1417
+ .find('.xdsoft_prev,.xdsoft_next')
1418
+ .on('mousedown.xdsoft', function () {
1419
+ var $this = $(this),
1420
+ timer = 0,
1421
+ stop = false,
1422
+ period = 110;
1423
+ (function arguments_callee4(v) {
1424
+ var pheight = timeboxparent[0].clientHeight,
1425
+ height = timebox[0].offsetHeight,
1426
+ top = Math.abs(parseInt(timebox.css('marginTop'), 10));
1427
+ if ($this.hasClass(options.next) && (height - pheight) - options.timeHeightInTimePicker >= top) {
1428
+ timebox.css('marginTop', '-' + (top + options.timeHeightInTimePicker) + 'px');
1429
+ } else if ($this.hasClass(options.prev) && top - options.timeHeightInTimePicker >= 0) {
1430
+ timebox.css('marginTop', '-' + (top - options.timeHeightInTimePicker) + 'px');
1431
+ }
1432
+ timeboxparent.trigger('scroll_element.xdsoft_scroller', [Math.abs(parseInt(timebox.css('marginTop'), 10) / (height - pheight))]);
1433
+ period = (period > 10) ? 10 : period - 10;
1434
+ if (!stop) {
1435
+ timer = setTimeout(arguments_callee4, v || period);
1436
+ }
1437
+ }(500));
1438
+ $([document.body, window]).on('mouseup.xdsoft', function arguments_callee5() {
1439
+ clearTimeout(timer);
1440
+ stop = true;
1441
+ $([document.body, window])
1442
+ .off('mouseup.xdsoft', arguments_callee5);
1443
+ });
1444
+ });
1445
+
1446
+ xchangeTimer = 0;
1447
+ // base handler - generating a calendar and timepicker
1448
+ datetimepicker
1449
+ .on('xchange.xdsoft', function (event) {
1450
+ clearTimeout(xchangeTimer);
1451
+ xchangeTimer = setTimeout(function () {
1452
+
1453
+ if (_xdsoft_datetime.currentTime === undefined || _xdsoft_datetime.currentTime === null) {
1454
+ _xdsoft_datetime.currentTime = _xdsoft_datetime.now();
1455
+ }
1456
+
1457
+ var table = '',
1458
+ start = new Date(_xdsoft_datetime.currentTime.getFullYear(), _xdsoft_datetime.currentTime.getMonth(), 1, 12, 0, 0),
1459
+ i = 0,
1460
+ j,
1461
+ today = _xdsoft_datetime.now(),
1462
+ maxDate = false,
1463
+ minDate = false,
1464
+ hDate,
1465
+ day,
1466
+ d,
1467
+ y,
1468
+ m,
1469
+ w,
1470
+ classes = [],
1471
+ customDateSettings,
1472
+ newRow = true,
1473
+ time = '',
1474
+ h = '',
1475
+ line_time,
1476
+ description;
1477
+
1478
+ while (start.getDay() !== options.dayOfWeekStart) {
1479
+ start.setDate(start.getDate() - 1);
1480
+ }
1481
+
1482
+ table += '<table><thead><tr>';
1483
+
1484
+ if (options.weeks) {
1485
+ table += '<th></th>';
1486
+ }
1487
+
1488
+ for (j = 0; j < 7; j += 1) {
1489
+ table += '<th>' + options.i18n[options.lang].dayOfWeek[(j + options.dayOfWeekStart) % 7] + '</th>';
1490
+ }
1491
+
1492
+ table += '</tr></thead>';
1493
+ table += '<tbody>';
1494
+
1495
+ if (options.maxDate !== false) {
1496
+ maxDate = _xdsoft_datetime.strToDate(options.maxDate);
1497
+ maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 23, 59, 59, 999);
1498
+ }
1499
+
1500
+ if (options.minDate !== false) {
1501
+ minDate = _xdsoft_datetime.strToDate(options.minDate);
1502
+ minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
1503
+ }
1504
+
1505
+ while (i < _xdsoft_datetime.currentTime.countDaysInMonth() || start.getDay() !== options.dayOfWeekStart || _xdsoft_datetime.currentTime.getMonth() === start.getMonth()) {
1506
+ classes = [];
1507
+ i += 1;
1508
+
1509
+ day = start.getDay();
1510
+ d = start.getDate();
1511
+ y = start.getFullYear();
1512
+ m = start.getMonth();
1513
+ w = _xdsoft_datetime.getWeekOfYear(start);
1514
+ description = '';
1515
+
1516
+ classes.push('xdsoft_date');
1517
+
1518
+ if (options.beforeShowDay && $.isFunction(options.beforeShowDay.call)) {
1519
+ customDateSettings = options.beforeShowDay.call(datetimepicker, start);
1520
+ } else {
1521
+ customDateSettings = null;
1522
+ }
1523
+
1524
+ if ((maxDate !== false && start > maxDate) || (minDate !== false && start < minDate) || (customDateSettings && customDateSettings[0] === false)) {
1525
+ classes.push('xdsoft_disabled');
1526
+ } else if (options.disabledDates.indexOf(start.dateFormat(options.formatDate)) !== -1) {
1527
+ classes.push('xdsoft_disabled');
1528
+ } else if (options.disabledWeekDays.indexOf(day) !== -1) {
1529
+ classes.push('xdsoft_disabled');
1530
+ }
1531
+
1532
+ if (customDateSettings && customDateSettings[1] !== "") {
1533
+ classes.push(customDateSettings[1]);
1534
+ }
1535
+
1536
+ if (_xdsoft_datetime.currentTime.getMonth() !== m) {
1537
+ classes.push('xdsoft_other_month');
1538
+ }
1539
+
1540
+ if ((options.defaultSelect || datetimepicker.data('changed')) && _xdsoft_datetime.currentTime.dateFormat(options.formatDate) === start.dateFormat(options.formatDate)) {
1541
+ classes.push('xdsoft_current');
1542
+ }
1543
+
1544
+ if (today.dateFormat(options.formatDate) === start.dateFormat(options.formatDate)) {
1545
+ classes.push('xdsoft_today');
1546
+ }
1547
+
1548
+ if (start.getDay() === 0 || start.getDay() === 6 || options.weekends.indexOf(start.dateFormat(options.formatDate)) !== -1) {
1549
+ classes.push('xdsoft_weekend');
1550
+ }
1551
+
1552
+ if (options.highlightedDates[start.dateFormat(options.formatDate)] !== undefined) {
1553
+ hDate = options.highlightedDates[start.dateFormat(options.formatDate)];
1554
+ classes.push(hDate.style === undefined ? 'xdsoft_highlighted_default' : hDate.style);
1555
+ description = hDate.desc === undefined ? '' : hDate.desc;
1556
+ }
1557
+
1558
+ if (options.beforeShowDay && $.isFunction(options.beforeShowDay)) {
1559
+ classes.push(options.beforeShowDay(start));
1560
+ }
1561
+
1562
+ if (newRow) {
1563
+ table += '<tr>';
1564
+ newRow = false;
1565
+ if (options.weeks) {
1566
+ table += '<th>' + w + '</th>';
1567
+ }
1568
+ }
1569
+
1570
+ table += '<td data-date="' + d + '" data-month="' + m + '" data-year="' + y + '"' + ' class="xdsoft_date xdsoft_day_of_week' + start.getDay() + ' ' + classes.join(' ') + '" title="' + description + '">' +
1571
+ '<div>' + d + '</div>' +
1572
+ '</td>';
1573
+
1574
+ if (start.getDay() === options.dayOfWeekStartPrev) {
1575
+ table += '</tr>';
1576
+ newRow = true;
1577
+ }
1578
+
1579
+ start.setDate(d + 1);
1580
+ }
1581
+ table += '</tbody></table>';
1582
+
1583
+ calendar.html(table);
1584
+
1585
+ mounth_picker.find('.xdsoft_label span').eq(0).text(options.i18n[options.lang].months[_xdsoft_datetime.currentTime.getMonth()]);
1586
+ mounth_picker.find('.xdsoft_label span').eq(1).text(_xdsoft_datetime.currentTime.getFullYear());
1587
+
1588
+ // generate timebox
1589
+ time = '';
1590
+ h = '';
1591
+ m = '';
1592
+ line_time = function line_time(h, m) {
1593
+ var now = _xdsoft_datetime.now(), optionDateTime, current_time;
1594
+ now.setHours(h);
1595
+ h = parseInt(now.getHours(), 10);
1596
+ now.setMinutes(m);
1597
+ m = parseInt(now.getMinutes(), 10);
1598
+ optionDateTime = new Date(_xdsoft_datetime.currentTime);
1599
+ optionDateTime.setHours(h);
1600
+ optionDateTime.setMinutes(m);
1601
+ classes = [];
1602
+ if ((options.minDateTime !== false && options.minDateTime > optionDateTime) || (options.maxTime !== false && _xdsoft_datetime.strtotime(options.maxTime).getTime() < now.getTime()) || (options.minTime !== false && _xdsoft_datetime.strtotime(options.minTime).getTime() > now.getTime())) {
1603
+ classes.push('xdsoft_disabled');
1604
+ }
1605
+ if ((options.minDateTime !== false && options.minDateTime > optionDateTime) || ((options.disabledMinTime !== false && now.getTime() > _xdsoft_datetime.strtotime(options.disabledMinTime).getTime()) && (options.disabledMaxTime !== false && now.getTime() < _xdsoft_datetime.strtotime(options.disabledMaxTime).getTime()))) {
1606
+ classes.push('xdsoft_disabled');
1607
+ }
1608
+
1609
+ current_time = new Date(_xdsoft_datetime.currentTime);
1610
+ current_time.setHours(parseInt(_xdsoft_datetime.currentTime.getHours(), 10));
1611
+ current_time.setMinutes(Math[options.roundTime](_xdsoft_datetime.currentTime.getMinutes() / options.step) * options.step);
1612
+
1613
+ if ((options.initTime || options.defaultSelect || datetimepicker.data('changed')) && current_time.getHours() === parseInt(h, 10) && (options.step > 59 || current_time.getMinutes() === parseInt(m, 10))) {
1614
+ if (options.defaultSelect || datetimepicker.data('changed')) {
1615
+ classes.push('xdsoft_current');
1616
+ } else if (options.initTime) {
1617
+ classes.push('xdsoft_init_time');
1618
+ }
1619
+ }
1620
+ if (parseInt(today.getHours(), 10) === parseInt(h, 10) && parseInt(today.getMinutes(), 10) === parseInt(m, 10)) {
1621
+ classes.push('xdsoft_today');
1622
+ }
1623
+ time += '<div class="xdsoft_time ' + classes.join(' ') + '" data-hour="' + h + '" data-minute="' + m + '">' + now.dateFormat(options.formatTime) + '</div>';
1624
+ };
1625
+
1626
+ if (!options.allowTimes || !$.isArray(options.allowTimes) || !options.allowTimes.length) {
1627
+ for (i = 0, j = 0; i < (options.hours12 ? 12 : 24); i += 1) {
1628
+ for (j = 0; j < 60; j += options.step) {
1629
+ h = (i < 10 ? '0' : '') + i;
1630
+ m = (j < 10 ? '0' : '') + j;
1631
+ line_time(h, m);
1632
+ }
1633
+ }
1634
+ } else {
1635
+ for (i = 0; i < options.allowTimes.length; i += 1) {
1636
+ h = _xdsoft_datetime.strtotime(options.allowTimes[i]).getHours();
1637
+ m = _xdsoft_datetime.strtotime(options.allowTimes[i]).getMinutes();
1638
+ line_time(h, m);
1639
+ }
1640
+ }
1641
+
1642
+ timebox.html(time);
1643
+
1644
+ opt = '';
1645
+ i = 0;
1646
+
1647
+ for (i = parseInt(options.yearStart, 10) + options.yearOffset; i <= parseInt(options.yearEnd, 10) + options.yearOffset; i += 1) {
1648
+ opt += '<div class="xdsoft_option ' + (_xdsoft_datetime.currentTime.getFullYear() === i ? 'xdsoft_current' : '') + '" data-value="' + i + '">' + i + '</div>';
1649
+ }
1650
+ yearselect.children().eq(0)
1651
+ .html(opt);
1652
+
1653
+ for (i = parseInt(options.monthStart, 10), opt = ''; i <= parseInt(options.monthEnd, 10); i += 1) {
1654
+ opt += '<div class="xdsoft_option ' + (_xdsoft_datetime.currentTime.getMonth() === i ? 'xdsoft_current' : '') + '" data-value="' + i + '">' + options.i18n[options.lang].months[i] + '</div>';
1655
+ }
1656
+ monthselect.children().eq(0).html(opt);
1657
+ $(datetimepicker)
1658
+ .trigger('generate.xdsoft');
1659
+ }, 10);
1660
+ event.stopPropagation();
1661
+ })
1662
+ .on('afterOpen.xdsoft', function () {
1663
+ if (options.timepicker) {
1664
+ var classType, pheight, height, top;
1665
+ if (timebox.find('.xdsoft_current').length) {
1666
+ classType = '.xdsoft_current';
1667
+ } else if (timebox.find('.xdsoft_init_time').length) {
1668
+ classType = '.xdsoft_init_time';
1669
+ }
1670
+ if (classType) {
1671
+ pheight = timeboxparent[0].clientHeight;
1672
+ height = timebox[0].offsetHeight;
1673
+ top = timebox.find(classType).index() * options.timeHeightInTimePicker + 1;
1674
+ if ((height - pheight) < top) {
1675
+ top = height - pheight;
1676
+ }
1677
+ timeboxparent.trigger('scroll_element.xdsoft_scroller', [parseInt(top, 10) / (height - pheight)]);
1678
+ } else {
1679
+ timeboxparent.trigger('scroll_element.xdsoft_scroller', [0]);
1680
+ }
1681
+ }
1682
+ });
1683
+
1684
+ timerclick = 0;
1685
+ calendar
1686
+ .on('click.xdsoft', 'td', function (xdevent) {
1687
+ xdevent.stopPropagation(); // Prevents closing of Pop-ups, Modals and Flyouts in Bootstrap
1688
+ timerclick += 1;
1689
+ var $this = $(this),
1690
+ currentTime = _xdsoft_datetime.currentTime;
1691
+
1692
+ if (currentTime === undefined || currentTime === null) {
1693
+ _xdsoft_datetime.currentTime = _xdsoft_datetime.now();
1694
+ currentTime = _xdsoft_datetime.currentTime;
1695
+ }
1696
+
1697
+ if ($this.hasClass('xdsoft_disabled')) {
1698
+ return false;
1699
+ }
1700
+
1701
+ currentTime.setDate(1);
1702
+ currentTime.setFullYear($this.data('year'));
1703
+ currentTime.setMonth($this.data('month'));
1704
+ currentTime.setDate($this.data('date'));
1705
+
1706
+ datetimepicker.trigger('select.xdsoft', [currentTime]);
1707
+
1708
+ input.val(_xdsoft_datetime.str());
1709
+ if ((timerclick > 1 || (options.closeOnDateSelect === true || (options.closeOnDateSelect === false && !options.timepicker))) && !options.inline) {
1710
+ datetimepicker.trigger('close.xdsoft');
1711
+ }
1712
+
1713
+ if (options.onSelectDate && $.isFunction(options.onSelectDate)) {
1714
+ options.onSelectDate.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), xdevent);
1715
+ }
1716
+
1717
+ datetimepicker.data('changed', true);
1718
+ datetimepicker.trigger('xchange.xdsoft');
1719
+ datetimepicker.trigger('changedatetime.xdsoft');
1720
+ setTimeout(function () {
1721
+ timerclick = 0;
1722
+ }, 200);
1723
+ });
1724
+
1725
+ timebox
1726
+ .on('click.xdsoft', 'div', function (xdevent) {
1727
+ xdevent.stopPropagation();
1728
+ var $this = $(this),
1729
+ currentTime = _xdsoft_datetime.currentTime;
1730
+
1731
+ if (currentTime === undefined || currentTime === null) {
1732
+ _xdsoft_datetime.currentTime = _xdsoft_datetime.now();
1733
+ currentTime = _xdsoft_datetime.currentTime;
1734
+ }
1735
+
1736
+ if ($this.hasClass('xdsoft_disabled')) {
1737
+ return false;
1738
+ }
1739
+ currentTime.setHours($this.data('hour'));
1740
+ currentTime.setMinutes($this.data('minute'));
1741
+ datetimepicker.trigger('select.xdsoft', [currentTime]);
1742
+
1743
+ datetimepicker.data('input').val(_xdsoft_datetime.str());
1744
+
1745
+ if (options.inline !== true && options.closeOnTimeSelect === true) {
1746
+ datetimepicker.trigger('close.xdsoft');
1747
+ }
1748
+
1749
+ if (options.onSelectTime && $.isFunction(options.onSelectTime)) {
1750
+ options.onSelectTime.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), xdevent);
1751
+ }
1752
+ datetimepicker.data('changed', true);
1753
+ datetimepicker.trigger('xchange.xdsoft');
1754
+ datetimepicker.trigger('changedatetime.xdsoft');
1755
+ });
1756
+
1757
+
1758
+ datepicker
1759
+ .on('mousewheel.xdsoft', function (event) {
1760
+ if (!options.scrollMonth) {
1761
+ return true;
1762
+ }
1763
+ if (event.deltaY < 0) {
1764
+ _xdsoft_datetime.nextMonth();
1765
+ } else {
1766
+ _xdsoft_datetime.prevMonth();
1767
+ }
1768
+ return false;
1769
+ });
1770
+
1771
+ input
1772
+ .on('mousewheel.xdsoft', function (event) {
1773
+ if (!options.scrollInput) {
1774
+ return true;
1775
+ }
1776
+ if (!options.datepicker && options.timepicker) {
1777
+ current_time_index = timebox.find('.xdsoft_current').length ? timebox.find('.xdsoft_current').eq(0).index() : 0;
1778
+ if (current_time_index + event.deltaY >= 0 && current_time_index + event.deltaY < timebox.children().length) {
1779
+ current_time_index += event.deltaY;
1780
+ }
1781
+ if (timebox.children().eq(current_time_index).length) {
1782
+ timebox.children().eq(current_time_index).trigger('mousedown');
1783
+ }
1784
+ return false;
1785
+ }
1786
+ if (options.datepicker && !options.timepicker) {
1787
+ datepicker.trigger(event, [event.deltaY, event.deltaX, event.deltaY]);
1788
+ if (input.val) {
1789
+ input.val(_xdsoft_datetime.str());
1790
+ }
1791
+ datetimepicker.trigger('changedatetime.xdsoft');
1792
+ return false;
1793
+ }
1794
+ });
1795
+
1796
+ datetimepicker
1797
+ .on('changedatetime.xdsoft', function (event) {
1798
+ if (options.onChangeDateTime && $.isFunction(options.onChangeDateTime)) {
1799
+ var $input = datetimepicker.data('input');
1800
+ options.onChangeDateTime.call(datetimepicker, _xdsoft_datetime.currentTime, $input, event);
1801
+ delete options.value;
1802
+ $input.trigger('change');
1803
+ }
1804
+ })
1805
+ .on('generate.xdsoft', function () {
1806
+ if (options.onGenerate && $.isFunction(options.onGenerate)) {
1807
+ options.onGenerate.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
1808
+ }
1809
+ if (triggerAfterOpen) {
1810
+ datetimepicker.trigger('afterOpen.xdsoft');
1811
+ triggerAfterOpen = false;
1812
+ }
1813
+ })
1814
+ .on('click.xdsoft', function (xdevent) {
1815
+ xdevent.stopPropagation();
1816
+ });
1817
+
1818
+ current_time_index = 0;
1819
+
1820
+ setPos = function () {
1821
+ var offset = datetimepicker.data('input').offset(), top = offset.top + datetimepicker.data('input')[0].offsetHeight - 1, left = offset.left, position = "absolute", node;
1822
+ if (options.fixed) {
1823
+ top -= $(window).scrollTop();
1824
+ left -= $(window).scrollLeft();
1825
+ position = "fixed";
1826
+ } else {
1827
+ if (top + datetimepicker[0].offsetHeight > $(window).height() + $(window).scrollTop()) {
1828
+ top = offset.top - datetimepicker[0].offsetHeight + 1;
1829
+ }
1830
+ if (top < 0) {
1831
+ top = 0;
1832
+ }
1833
+ if (left + datetimepicker[0].offsetWidth > $(window).width()) {
1834
+ left = $(window).width() - datetimepicker[0].offsetWidth;
1835
+ }
1836
+ }
1837
+
1838
+ node = datetimepicker[0];
1839
+ do {
1840
+ node = node.parentNode;
1841
+ if (window.getComputedStyle(node).getPropertyValue('position') === 'relative' && $(window).width() >= node.offsetWidth) {
1842
+ left = left - (($(window).width() - node.offsetWidth) / 2);
1843
+ break;
1844
+ }
1845
+ } while (node.nodeName !== 'HTML');
1846
+ datetimepicker.css({
1847
+ left: left,
1848
+ top: top,
1849
+ position: position
1850
+ });
1851
+ };
1852
+ datetimepicker
1853
+ .on('open.xdsoft', function (event) {
1854
+ var onShow = true;
1855
+ if (options.onShow && $.isFunction(options.onShow)) {
1856
+ onShow = options.onShow.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), event);
1857
+ }
1858
+ if (onShow !== false) {
1859
+ datetimepicker.show();
1860
+ setPos();
1861
+ $(window)
1862
+ .off('resize.xdsoft', setPos)
1863
+ .on('resize.xdsoft', setPos);
1864
+
1865
+ if (options.closeOnWithoutClick) {
1866
+ $([document.body, window]).on('mousedown.xdsoft', function arguments_callee6() {
1867
+ datetimepicker.trigger('close.xdsoft');
1868
+ $([document.body, window]).off('mousedown.xdsoft', arguments_callee6);
1869
+ });
1870
+ }
1871
+ }
1872
+ })
1873
+ .on('close.xdsoft', function (event) {
1874
+ var onClose = true;
1875
+ mounth_picker
1876
+ .find('.xdsoft_month,.xdsoft_year')
1877
+ .find('.xdsoft_select')
1878
+ .hide();
1879
+ if (options.onClose && $.isFunction(options.onClose)) {
1880
+ onClose = options.onClose.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), event);
1881
+ }
1882
+ if (onClose !== false && !options.opened && !options.inline) {
1883
+ datetimepicker.hide();
1884
+ }
1885
+ event.stopPropagation();
1886
+ })
1887
+ .on('toggle.xdsoft', function (event) {
1888
+ if (datetimepicker.is(':visible')) {
1889
+ datetimepicker.trigger('close.xdsoft');
1890
+ } else {
1891
+ datetimepicker.trigger('open.xdsoft');
1892
+ }
1893
+ })
1894
+ .data('input', input);
1895
+
1896
+ timer = 0;
1897
+ timer1 = 0;
1898
+
1899
+ datetimepicker.data('xdsoft_datetime', _xdsoft_datetime);
1900
+ datetimepicker.setOptions(options);
1901
+
1902
+ function getCurrentValue() {
1903
+ var ct = false, time;
1904
+
1905
+ if (options.startDate) {
1906
+ ct = _xdsoft_datetime.strToDate(options.startDate);
1907
+ } else {
1908
+ ct = options.value || ((input && input.val && input.val()) ? input.val() : '');
1909
+ if (ct) {
1910
+ ct = _xdsoft_datetime.strToDateTime(ct);
1911
+ } else if (options.defaultDate) {
1912
+ ct = _xdsoft_datetime.strToDateTime(options.defaultDate);
1913
+ if (options.defaultTime) {
1914
+ time = _xdsoft_datetime.strtotime(options.defaultTime);
1915
+ ct.setHours(time.getHours());
1916
+ ct.setMinutes(time.getMinutes());
1917
+ }
1918
+ }
1919
+ }
1920
+
1921
+ if (ct && _xdsoft_datetime.isValidDate(ct)) {
1922
+ datetimepicker.data('changed', true);
1923
+ } else {
1924
+ ct = '';
1925
+ }
1926
+
1927
+ return ct || 0;
1928
+ }
1929
+
1930
+ _xdsoft_datetime.setCurrentTime(getCurrentValue());
1931
+
1932
+ input
1933
+ .data('xdsoft_datetimepicker', datetimepicker)
1934
+ .on('open.xdsoft focusin.xdsoft mousedown.xdsoft', function (event) {
1935
+ if (input.is(':disabled') || (input.data('xdsoft_datetimepicker').is(':visible') && options.closeOnInputClick)) {
1936
+ return;
1937
+ }
1938
+ clearTimeout(timer);
1939
+ timer = setTimeout(function () {
1940
+ if (input.is(':disabled')) {
1941
+ return;
1942
+ }
1943
+
1944
+ triggerAfterOpen = true;
1945
+ _xdsoft_datetime.setCurrentTime(getCurrentValue());
1946
+
1947
+ datetimepicker.trigger('open.xdsoft');
1948
+ }, 100);
1949
+ })
1950
+ .on('keydown.xdsoft', function (event) {
1951
+ var val = this.value, elementSelector,
1952
+ key = event.which;
1953
+ if ([ENTER].indexOf(key) !== -1 && options.enterLikeTab) {
1954
+ elementSelector = $("input:visible,textarea:visible");
1955
+ datetimepicker.trigger('close.xdsoft');
1956
+ elementSelector.eq(elementSelector.index(this) + 1).focus();
1957
+ return false;
1958
+ }
1959
+ if ([TAB].indexOf(key) !== -1) {
1960
+ datetimepicker.trigger('close.xdsoft');
1961
+ return true;
1962
+ }
1963
+ });
1964
+ };
1965
+ destroyDateTimePicker = function (input) {
1966
+ var datetimepicker = input.data('xdsoft_datetimepicker');
1967
+ if (datetimepicker) {
1968
+ datetimepicker.data('xdsoft_datetime', null);
1969
+ datetimepicker.remove();
1970
+ input
1971
+ .data('xdsoft_datetimepicker', null)
1972
+ .off('.xdsoft');
1973
+ $(window).off('resize.xdsoft');
1974
+ $([window, document.body]).off('mousedown.xdsoft');
1975
+ if (input.unmousewheel) {
1976
+ input.unmousewheel();
1977
+ }
1978
+ }
1979
+ };
1980
+ $(document)
1981
+ .off('keydown.xdsoftctrl keyup.xdsoftctrl')
1982
+ .on('keydown.xdsoftctrl', function (e) {
1983
+ if (e.keyCode === CTRLKEY) {
1984
+ ctrlDown = true;
1985
+ }
1986
+ })
1987
+ .on('keyup.xdsoftctrl', function (e) {
1988
+ if (e.keyCode === CTRLKEY) {
1989
+ ctrlDown = false;
1990
+ }
1991
+ });
1992
+ return this.each(function () {
1993
+ var datetimepicker = $(this).data('xdsoft_datetimepicker'), $input;
1994
+ if (datetimepicker) {
1995
+ if ($.type(opt) === 'string') {
1996
+ switch (opt) {
1997
+ case 'show':
1998
+ $(this).select().focus();
1999
+ datetimepicker.trigger('open.xdsoft');
2000
+ break;
2001
+ case 'hide':
2002
+ datetimepicker.trigger('close.xdsoft');
2003
+ break;
2004
+ case 'toggle':
2005
+ datetimepicker.trigger('toggle.xdsoft');
2006
+ break;
2007
+ case 'destroy':
2008
+ destroyDateTimePicker($(this));
2009
+ break;
2010
+ case 'reset':
2011
+ this.value = this.defaultValue;
2012
+ if (!this.value || !datetimepicker.data('xdsoft_datetime').isValidDate(Date.parseDate(this.value, options.format))) {
2013
+ datetimepicker.data('changed', false);
2014
+ }
2015
+ datetimepicker.data('xdsoft_datetime').setCurrentTime(this.value);
2016
+ break;
2017
+ case 'validate':
2018
+ $input = datetimepicker.data('input');
2019
+ $input.trigger('blur.xdsoft');
2020
+ break;
2021
+ }
2022
+ } else {
2023
+ datetimepicker
2024
+ .setOptions(opt);
2025
+ }
2026
+ return 0;
2027
+ }
2028
+ if ($.type(opt) !== 'string') {
2029
+ if (!options.lazyInit || options.open || options.inline) {
2030
+ createDateTimePicker($(this));
2031
+ } else {
2032
+ lazyInit($(this));
2033
+ }
2034
+ }
2035
+ });
2036
+ };
2037
+ $.fn.datetimepicker.defaults = default_options;
2038
+ }(jQuery));
2039
+
2040
+ function HighlightedDate(date, desc, style) {
2041
+ "use strict";
2042
+ this.date = date;
2043
+ this.desc = desc;
2044
+ this.style = style;
2045
+ }
2046
+
2047
+ (function () {
2048
+
2049
+ /*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
2050
+ * Licensed under the MIT License (LICENSE.txt).
2051
+ *
2052
+ * Version: 3.1.12
2053
+ *
2054
+ * Requires: jQuery 1.2.2+
2055
+ */
2056
+ !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
2057
+
2058
+ // Parse and Format Library
2059
+ //http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
2060
+ /*
2061
+ * Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
2062
+ *
2063
+ * This program is free software; you can redistribute it and/or modify it
2064
+ * under the terms of the GNU Lesser General Public License as published by the
2065
+ * Free Software Foundation, version 2.1.
2066
+ *
2067
+ * This program is distributed in the hope that it will be useful, but WITHOUT
2068
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2069
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2070
+ * details.
2071
+ */
2072
+ Date.parseFunctions={count:0};Date.parseRegexes=[];Date.formatFunctions={count:0};Date.prototype.dateFormat=function(b){if(b=="unixtime"){return parseInt(this.getTime()/1000);}if(Date.formatFunctions[b]==null){Date.createNewFormat(b);}var a=Date.formatFunctions[b];return this[a]();};Date.createNewFormat=function(format){var funcName="format"+Date.formatFunctions.count++;Date.formatFunctions[format]=funcName;var codePrefix="Date.prototype."+funcName+" = function() {return ";var code="";var special=false;var ch="";for(var i=0;i<format.length;++i){ch=format.charAt(i);if(!special&&ch=="\\"){special=true;}else{if(special){special=false;code+="'"+String.escape(ch)+"' + ";}else{code+=Date.getFormatCode(ch);}}}if(code.length==0){code="\"\"";}else{code=code.substring(0,code.length-3);}eval(codePrefix+code+";}");};Date.getFormatCode=function(a){switch(a){case"d":return"String.leftPad(this.getDate(), 2, '0') + ";case"D":return"Date.dayNames[this.getDay()].substring(0, 3) + ";case"j":return"this.getDate() + ";case"l":return"Date.dayNames[this.getDay()] + ";case"S":return"this.getSuffix() + ";case"w":return"this.getDay() + ";case"z":return"this.getDayOfYear() + ";case"W":return"this.getWeekOfYear() + ";case"F":return"Date.monthNames[this.getMonth()] + ";case"m":return"String.leftPad(this.getMonth() + 1, 2, '0') + ";case"M":return"Date.monthNames[this.getMonth()].substring(0, 3) + ";case"n":return"(this.getMonth() + 1) + ";case"t":return"this.getDaysInMonth() + ";case"L":return"(this.isLeapYear() ? 1 : 0) + ";case"Y":return"this.getFullYear() + ";case"y":return"('' + this.getFullYear()).substring(2, 4) + ";case"a":return"(this.getHours() < 12 ? 'am' : 'pm') + ";case"A":return"(this.getHours() < 12 ? 'AM' : 'PM') + ";case"g":return"((this.getHours() %12) ? this.getHours() % 12 : 12) + ";case"G":return"this.getHours() + ";case"h":return"String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";case"H":return"String.leftPad(this.getHours(), 2, '0') + ";case"i":return"String.leftPad(this.getMinutes(), 2, '0') + ";case"s":return"String.leftPad(this.getSeconds(), 2, '0') + ";case"O":return"this.getGMTOffset() + ";case"T":return"this.getTimezone() + ";case"Z":return"(this.getTimezoneOffset() * -60) + ";default:return"'"+String.escape(a)+"' + ";}};Date.parseDate=function(a,c){if(c=="unixtime"){return new Date(!isNaN(parseInt(a))?parseInt(a)*1000:0);}if(Date.parseFunctions[c]==null){Date.createParser(c);}var b=Date.parseFunctions[c];return Date[b](a);};Date.createParser=function(format){var funcName="parse"+Date.parseFunctions.count++;var regexNum=Date.parseRegexes.length;var currentGroup=1;Date.parseFunctions[format]=funcName;var code="Date."+funcName+" = function(input) {\nvar y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, z = -1;\nvar d = new Date();\ny = d.getFullYear();\nm = d.getMonth();\nd = d.getDate();\nvar results = input.match(Date.parseRegexes["+regexNum+"]);\nif (results && results.length > 0) {";var regex="";var special=false;var ch="";for(var i=0;i<format.length;++i){ch=format.charAt(i);if(!special&&ch=="\\"){special=true;}else{if(special){special=false;regex+=String.escape(ch);}else{obj=Date.formatCodeToRegex(ch,currentGroup);currentGroup+=obj.g;regex+=obj.s;if(obj.g&&obj.c){code+=obj.c;}}}}code+="if (y > 0 && z > 0){\nvar doyDate = new Date(y,0);\ndoyDate.setDate(z);\nm = doyDate.getMonth();\nd = doyDate.getDate();\n}";code+="if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n{return new Date(y, m, d, h, i, s);}\nelse if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n{return new Date(y, m, d, h, i);}\nelse if (y > 0 && m >= 0 && d > 0 && h >= 0)\n{return new Date(y, m, d, h);}\nelse if (y > 0 && m >= 0 && d > 0)\n{return new Date(y, m, d);}\nelse if (y > 0 && m >= 0)\n{return new Date(y, m);}\nelse if (y > 0)\n{return new Date(y);}\n}return null;}";Date.parseRegexes[regexNum]=new RegExp("^"+regex+"$",'i');eval(code);};Date.formatCodeToRegex=function(b,a){switch(b){case"D":return{g:0,c:null,s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};case"j":case"d":return{g:1,c:"d = parseInt(results["+a+"], 10);\n",s:"(\\d{1,2})"};case"l":return{g:0,c:null,s:"(?:"+Date.dayNames.join("|")+")"};case"S":return{g:0,c:null,s:"(?:st|nd|rd|th)"};case"w":return{g:0,c:null,s:"\\d"};case"z":return{g:1,c:"z = parseInt(results["+a+"], 10);\n",s:"(\\d{1,3})"};case"W":return{g:0,c:null,s:"(?:\\d{2})"};case"F":return{g:1,c:"m = parseInt(Date.monthNumbers[results["+a+"].substring(0, 3)], 10);\n",s:"("+Date.monthNames.join("|")+")"};case"M":return{g:1,c:"m = parseInt(Date.monthNumbers[results["+a+"]], 10);\n",s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};case"n":case"m":return{g:1,c:"m = parseInt(results["+a+"], 10) - 1;\n",s:"(\\d{1,2})"};case"t":return{g:0,c:null,s:"\\d{1,2}"};case"L":return{g:0,c:null,s:"(?:1|0)"};case"Y":return{g:1,c:"y = parseInt(results["+a+"], 10);\n",s:"(\\d{4})"};case"y":return{g:1,c:"var ty = parseInt(results["+a+"], 10);\ny = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",s:"(\\d{1,2})"};case"a":return{g:1,c:"if (results["+a+"] == 'am') {\nif (h == 12) { h = 0; }\n} else { if (h < 12) { h += 12; }}",s:"(am|pm)"};case"A":return{g:1,c:"if (results["+a+"] == 'AM') {\nif (h == 12) { h = 0; }\n} else { if (h < 12) { h += 12; }}",s:"(AM|PM)"};case"g":case"G":case"h":case"H":return{g:1,c:"h = parseInt(results["+a+"], 10);\n",s:"(\\d{1,2})"};case"i":return{g:1,c:"i = parseInt(results["+a+"], 10);\n",s:"(\\d{2})"};case"s":return{g:1,c:"s = parseInt(results["+a+"], 10);\n",s:"(\\d{2})"};case"O":return{g:0,c:null,s:"[+-]\\d{4}"};case"T":return{g:0,c:null,s:"[A-Z]{3}"};case"Z":return{g:0,c:null,s:"[+-]\\d{1,5}"};default:return{g:0,c:null,s:String.escape(b)};}};Date.prototype.getTimezone=function(){return this.toString().replace(/^.*? ([A-Z]{3}) [0-9]{4}.*$/,"$1").replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/,"$1$2$3");};Date.prototype.getGMTOffset=function(){return(this.getTimezoneOffset()>0?"-":"+")+String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset())/60),2,"0")+String.leftPad(Math.abs(this.getTimezoneOffset())%60,2,"0");};Date.prototype.getDayOfYear=function(){var a=0;Date.daysInMonth[1]=this.isLeapYear()?29:28;for(var b=0;b<this.getMonth();++b){a+=Date.daysInMonth[b];}return a+this.getDate();};Date.prototype.getWeekOfYear=function(){var b=this.getDayOfYear()+(4-this.getDay());var a=new Date(this.getFullYear(),0,1);var c=(7-a.getDay()+4);return String.leftPad(Math.ceil((b-c)/7)+1,2,"0");};Date.prototype.isLeapYear=function(){var a=this.getFullYear();return((a&3)==0&&(a%100||(a%400==0&&a)));};Date.prototype.getFirstDayOfMonth=function(){var a=(this.getDay()-(this.getDate()-1))%7;return(a<0)?(a+7):a;};Date.prototype.getLastDayOfMonth=function(){var a=(this.getDay()+(Date.daysInMonth[this.getMonth()]-this.getDate()))%7;return(a<0)?(a+7):a;};Date.prototype.getDaysInMonth=function(){Date.daysInMonth[1]=this.isLeapYear()?29:28;return Date.daysInMonth[this.getMonth()];};Date.prototype.getSuffix=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};String.escape=function(a){return a.replace(/('|\\)/g,"\\$1");};String.leftPad=function(d,b,c){var a=new String(d);if(c==null){c=" ";}while(a.length<b){a=c+a;}return a;};Date.daysInMonth=[31,28,31,30,31,30,31,31,30,31,30,31];Date.monthNames=["January","February","March","April","May","June","July","August","September","October","November","December"];Date.dayNames=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];Date.y2kYear=50;Date.monthNumbers={Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11};Date.patterns={ISO8601LongPattern:"Y-m-d H:i:s",ISO8601ShortPattern:"Y-m-d",ShortDatePattern:"n/j/Y",LongDatePattern:"l, F d, Y",FullDateTimePattern:"l, F d, Y g:i:s A",MonthDayPattern:"F d",ShortTimePattern:"g:i A",LongTimePattern:"g:i:s A",SortableDateTimePattern:"Y-m-d\\TH:i:s",UniversalSortableDateTimePattern:"Y-m-d H:i:sO",YearMonthPattern:"F, Y"};
2073
+ }());
trunk/assets/libraries/datetimepicker/package.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "jquery-datetimepicker",
3
+ "version": "2.4.5",
4
+ "description": "jQuery Plugin DateTimePicker it is DatePicker and TimePicker in one",
5
+ "main": "jquery.datetimepicker.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/xdan/datetimepicker.git"
12
+ },
13
+ "keywords": [
14
+ "jquery-plugin",
15
+ "calendar",
16
+ "date",
17
+ "time",
18
+ "datetime",
19
+ "datepicker",
20
+ "timepicker"
21
+ ],
22
+ "author": "Chupurnov <chupurnov@gmail.com> (http://xdsoft.net/)",
23
+ "license": "MIT",
24
+ "bugs": {
25
+ "url": "https://github.com/xdan/datetimepicker/issues"
26
+ },
27
+ "homepage": "https://github.com/xdan/datetimepicker"
28
+ }
trunk/assets/libraries/datetimepicker/picker_functions.js ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function ($) {
2
+
3
+ /* Populates date and timepicker values */
4
+
5
+ /* Activates the datetime picker widget */
6
+ jQuery('.start.date').datetimepicker({
7
+ timepicker:false,
8
+ format:'Y-m-d'
9
+ });
10
+ jQuery('.time-picker').datetimepicker({
11
+ datepicker:false,
12
+ format: 'H:i'
13
+ });
14
+
15
+ if ($('.current_lander .new-date').length) { // implies *not* zero
16
+ var current_val = jQuery(".current_lander .new-date").val();
17
+ } else {
18
+ var current_val = jQuery(".new-date").val();
19
+ }
20
+ // if no timepicker in options fix it
21
+ if (typeof (current_val) == "undefined" || current_val === null || current_val == "") {
22
+ var current_val = '';
23
+ }
24
+
25
+ jQuery('.new-date').each(function(){
26
+ var the_val = $(this).val();
27
+ if (typeof (the_val) == "undefined" || the_val === null || the_val == "") {
28
+ var the_val = '';
29
+ }
30
+ var ret = the_val.split(" ");
31
+ var current_date = ret[0];
32
+ var current_time = ret[1];
33
+ jQuery(this).parent().parent().find(".date.start").val(current_date);
34
+ jQuery(this).parent().parent().find(".time-picker").val(current_time);
35
+ });
36
+
37
+ jQuery("body").on('change', '.jquery-date-picker .date.start', function () {
38
+ var date_chosen = jQuery(this).val();
39
+ var time_chosen = jQuery(this).parent().parent().find(".jquery-date-picker .time-picker").val();
40
+ var total_time = date_chosen + " " + time_chosen;
41
+ jQuery(this).parent().parent().find(".new-date").val(total_time);
42
+
43
+ });
44
+
45
+ jQuery("body").on('change', '.jquery-date-picker .time-picker', function () {
46
+ var date_chosen = jQuery(this).parent().parent().find(".jquery-date-picker .date.start").val();
47
+ var time_chosen = jQuery(this).val();
48
+ if (typeof (time_chosen) === "undefined" && time_chosen == null && time_chosen === "") {
49
+ var time_chosen = "00:00";
50
+ }
51
+ var total_time = date_chosen + " " + time_chosen;
52
+ jQuery(this).parent().find(".new-date").val(total_time);
53
+
54
+ });
55
+
56
+ });
trunk/assets/libraries/easyXDM.debug.js ADDED
@@ -0,0 +1 @@
 
0
  var t = typeof object[property];
1
  return t == 'function' ||
2
  (!!(t == 'object' && object[property])) ||
3
  t == 'unknown';
4
  return !!(typeof(object[property]) == 'object' && object[property]);
5
  return Object.prototype.toString.call(o) === '[object Array]';
6
  var name = "Shockwave Flash", mimeType = "application/x-shockwave-flash";
7
  if (!undef(navigator.plugins) && typeof navigator.plugins[name] == "object") {
8
  // adapted from the swfobject code
9
  var description = navigator.plugins[name].description;
10
  if (description && !undef(navigator.mimeTypes) && navigator.mimeTypes[mimeType] && navigator.mimeTypes[mimeType].enabledPlugin) {
11
  flashVersion = description.match(/\d+/g);
12
  }
13
  }
14
  if (!flashVersion) {
15
  var flash;
16
  try {
17
  flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
18
  flashVersion = Array.prototype.slice.call(flash.GetVariable("$version").match(/(\d+),(\d+),(\d+),(\d+)/), 1);
19
  flash = null;
20
  }
21
  catch (notSupportedException) {
22
  }
23
  }
24
  if (!flashVersion) {
25
  return false;
26
  }
27
  var major = parseInt(flashVersion[0], 10), minor = parseInt(flashVersion[1], 10);
28
  HAS_FLASH_THROTTLED_BUG = major > 9 && minor > 0;
29
  return true;
30
  * Cross Browser implementation for adding and removing event listeners.
31
  */
32
  on = function(target, type, listener){
33
  target.addEventListener(type, listener, false);
34
  };
35
  un = function(target, type, listener){
36
  target.removeEventListener(type, listener, false);
37
  };
38
  on = function(object, sEvent, fpNotify){
39
  object.attachEvent("on" + sEvent, fpNotify);
40
  };
41
  un = function(object, sEvent, fpNotify){
42
  object.detachEvent("on" + sEvent, fpNotify);
43
  };
44
  throw new Error("Browser not supported");
45
  * Cross Browser implementation of DOMContentLoaded.
46
  */
47
  // If browser is WebKit-powered, check for both 'loaded' (legacy browsers) and
48
  // 'interactive' (HTML5 specs, recent WebKit builds) states.
49
  // https://bugs.webkit.org/show_bug.cgi?id=45119
50
  readyState = document.readyState;
51
  domIsReady = readyState == "complete" || (~ navigator.userAgent.indexOf('AppleWebKit/') && (readyState == "loaded" || readyState == "interactive"));
52
  // If readyState is not supported in the browser, then in order to be able to fire whenReady functions apropriately
53
  // when added dynamically _after_ DOM load, we have to deduce wether the DOM is ready or not.
54
  // We only need a body to add elements to, so the existence of document.body is enough for us.
55
  domIsReady = !!document.body;
56
  if (domIsReady) {
57
  return;
58
  }
59
  domIsReady = true;
60
  for (var i = 0; i < domReadyQueue.length; i++) {
61
  domReadyQueue[i]();
62
  }
63
  domReadyQueue.length = 0;
64
  if (isHostMethod(window, "addEventListener")) {
65
  on(document, "DOMContentLoaded", dom_onReady);
66
  }
67
  else {
68
  on(document, "readystatechange", function(){
69
  if (document.readyState == "complete") {
70
  dom_onReady();
71
  }
72
  });
73
  if (document.documentElement.doScroll && window === top) {
74
  var doScrollCheck = function(){
75
  if (domIsReady) {
76
  return;
77
  }
78
  // http://javascript.nwbox.com/IEContentLoaded/
79
  try {
80
  document.documentElement.doScroll("left");
81
  }
82
  catch (e) {
83
  setTimeout(doScrollCheck, 1);
84
  return;
85
  }
86
  dom_onReady();
87
  };
88
  doScrollCheck();
89
  }
90
  }
91
  // A fallback to window.onload, that will always work
92
  on(window, "load", dom_onReady);
93
  * This will add a function to the queue of functions to be run once the DOM reaches a ready state.
94
  * If functions are added after this event then they will be executed immediately.
95
  * @param {function} fn The function to add
96
  * @param {Object} scope An optional scope for the function to be called with.
97
  */
98
  if (domIsReady) {
99
  fn.call(scope);
100
  return;
101
  }
102
  domReadyQueue.push(function(){
103
  fn.call(scope);
104
  });
105
  * Returns an instance of easyXDM from the parent window with
106
  * respect to the namespace.
107
  *
108
  * @return An instance of easyXDM (in the parent window)
109
  */
110
  var obj = parent;
111
  if (namespace !== "") {
112
  for (var i = 0, ii = namespace.split("."); i < ii.length; i++) {
113
  obj = obj[ii[i]];
114
  }
115
  }
116
  return obj.easyXDM;
117
  * Removes easyXDM variable from the global scope. It also returns control
118
  * of the easyXDM variable to whatever code used it before.
119
  *
120
  * @param {String} ns A string representation of an object that will hold
121
  * an instance of easyXDM.
122
  * @return An instance of easyXDM
123
  */
124
  window.easyXDM = _easyXDM;
125
  namespace = ns;
126
  if (namespace) {
127
  IFRAME_PREFIX = "easyXDM_" + namespace.replace(".", "_") + "_";
128
  }
129
  return easyXDM;
130
  * Methods for working with URLs
131
  */
132
  * Get the domain name from a url.
133
  * @param {String} url The url to extract the domain from.
134
  * @return The domain part of the url.
135
  * @type {String}
136
  */
137
  return url.match(reURI)[3];
138
  * Get the port for a given URL, or "" if none
139
  * @param {String} url The url to extract the port from.
140
  * @return The port part of the url.
141
  * @type {String}
142
  */
143
  return url.match(reURI)[4] || "";
144
  * Returns a string containing the schema, domain and if present the port
145
  * @param {String} url The url to extract the location from
146
  * @return {String} The location part of the url
147
  */
148
  var m = url.toLowerCase().match(reURI);
149
  var proto = m[2], domain = m[3], port = m[4] || "";
150
  if ((proto == "http:" && port == ":80") || (proto == "https:" && port == ":443")) {
151
  port = "";
152
  }
153
  return proto + "//" + domain + port;
154
  * Resolves a relative url into an absolute one.
155
  * @param {String} url The path to resolve.
156
  * @return {String} The resolved url.
157
  */
158
  // replace all // except the one in proto with /
159
  url = url.replace(reDoubleSlash, "$1/");
160
  // If the url is a valid url we do nothing
161
  if (!url.match(/^(http||https):\/\//)) {
162
  // If this is a relative path
163
  var path = (url.substring(0, 1) === "/") ? "" : location.pathname;
164
  if (path.substring(path.length - 1) !== "/") {
165
  path = path.substring(0, path.lastIndexOf("/") + 1);
166
  }
167
  url = location.protocol + "//" + location.host + path + url;
168
  }
169
  // reduce all 'xyz/../' to just ''
170
  while (reParent.test(url)) {
171
  url = url.replace(reParent, "");
172
  }
173
  return url;
174
  * Appends the parameters to the given url.<br/>
175
  * The base url can contain existing query parameters.
176
  * @param {String} url The base url.
177
  * @param {Object} parameters The parameters to add.
178
  * @return {String} A new valid url with the parameters appended.
179
  */
180
  var hash = "", indexOf = url.indexOf("#");
181
  if (indexOf !== -1) {
182
  hash = url.substring(indexOf);
183
  url = url.substring(0, indexOf);
184
  }
185
  var q = [];
186
  for (var key in parameters) {
187
  if (parameters.hasOwnProperty(key)) {
188
  q.push(key + "=" + encodeURIComponent(parameters[key]));
189
  }
190
  }
191
  return url + (useHash ? "#" : (url.indexOf("?") == -1 ? "?" : "&")) + q.join("&") + hash;
192
  input = input.substring(1).split("&");
193
  var data = {}, pair, i = input.length;
194
  while (i--) {
195
  pair = input[i].split("=");
196
  data[pair[0]] = decodeURIComponent(pair[1]);
197
  }
198
  return data;
199
  * Helper methods
200
  */
201
  * Helper for checking if a variable/property is undefined
202
  * @param {Object} v The variable to test
203
  * @return {Boolean} True if the passed variable is undefined
204
  */
205
  return typeof v === "undefined";
206
  * A safe implementation of HTML5 JSON. Feature testing is used to make sure the implementation works.
207
  * @return {JSON} A valid JSON conforming object, or null if not found.
208
  */
209
  var cached = {};
210
  var obj = {
211
  a: [1, 2, 3]
212
  }, json = "{\"a\":[1,2,3]}";
213
  if (typeof JSON != "undefined" && typeof JSON.stringify === "function" && JSON.stringify(obj).replace((/\s/g), "") === json) {
214
  // this is a working JSON instance
215
  return JSON;
216
  }
217
  if (Object.toJSON) {
218
  if (Object.toJSON(obj).replace((/\s/g), "") === json) {
219
  // this is a working stringify method
220
  cached.stringify = Object.toJSON;
221
  }
222
  }
223
  if (typeof String.prototype.evalJSON === "function") {
224
  obj = json.evalJSON();
225
  if (obj.a && obj.a.length === 3 && obj.a[2] === 3) {
226
  // this is a working parse method
227
  cached.parse = function(str){
228
  return str.evalJSON();
229
  };
230
  }
231
  }
232
  if (cached.stringify && cached.parse) {
233
  // Only memoize the result if we have valid instance
234
  getJSON = function(){
235
  return cached;
236
  };
237
  return cached;
238
  }
239
  return null;
240
  * Applies properties from the source object to the target object.<br/>
241
  * @param {Object} target The target of the properties.
242
  * @param {Object} source The source of the properties.
243
  * @param {Boolean} noOverwrite Set to True to only set non-existing properties.
244
  */
245
  var member;
246
  for (var prop in source) {
247
  if (source.hasOwnProperty(prop)) {
248
  if (prop in destination) {
249
  member = source[prop];
250
  if (typeof member === "object") {
251
  apply(destination[prop], member, noOverwrite);
252
  }
253
  else if (!noOverwrite) {
254
  destination[prop] = source[prop];
255
  }
256
  }
257
  else {
258
  destination[prop] = source[prop];
259
  }
260
  }
261
  }
262
  return destination;
263
  var form = document.body.appendChild(document.createElement("form")), input = form.appendChild(document.createElement("input"));
264
  input.name = IFRAME_PREFIX + "TEST" + channelId; // append channelId in order to avoid caching issues
265
  HAS_NAME_PROPERTY_BUG = input !== form.elements[input.name];
266
  document.body.removeChild(form);
267
  * Creates a frame and appends it to the DOM.
268
  * @param config {object} This object can have the following properties
269
  * <ul>
270
  * <li> {object} prop The properties that should be set on the frame. This should include the 'src' property.</li>
271
  * <li> {object} attr The attributes that should be set on the frame.</li>
272
  * <li> {DOMElement} container Its parent element (Optional).</li>
273
  * <li> {function} onLoad A method that should be called with the frames contentWindow as argument when the frame is fully loaded. (Optional)</li>
274
  * </ul>
275
  * @return The frames DOMElement
276
  * @type DOMElement
277
  */
278
  if (undef(HAS_NAME_PROPERTY_BUG)) {
279
  testForNamePropertyBug();
280
  }
281
  var frame;
282
  // This is to work around the problems in IE6/7 with setting the name property.
283
  // Internally this is set as 'submitName' instead when using 'iframe.name = ...'
284
  // This is not required by easyXDM itself, but is to facilitate other use cases
285
  if (HAS_NAME_PROPERTY_BUG) {
286
  frame = document.createElement("<iframe name=\"" + config.props.name + "\"/>");
287
  }
288
  else {
289
  frame = document.createElement("IFRAME");
290
  frame.name = config.props.name;
291
  }
292
  frame.id = frame.name = config.props.name;
293
  delete config.props.name;
294
  if (typeof config.container == "string") {
295
  config.container = document.getElementById(config.container);
296
  }
297
  if (!config.container) {
298
  // This needs to be hidden like this, simply setting display:none and the like will cause failures in some browsers.
299
  apply(frame.style, {
300
  position: "absolute",
301
  top: "-2000px",
302
  // Avoid potential horizontal scrollbar
303
  left: "0px"
304
  });
305
  config.container = document.body;
306
  }
307
  // HACK: IE cannot have the src attribute set when the frame is appended
308
  // into the container, so we set it to "javascript:false" as a
309
  // placeholder for now. If we left the src undefined, it would
310
  // instead default to "about:blank", which causes SSL mixed-content
311
  // warnings in IE6 when on an SSL parent page.
312
  var src = config.props.src;
313
  config.props.src = "javascript:false";
314
  // transfer properties to the frame
315
  apply(frame, config.props);
316
  frame.border = frame.frameBorder = 0;
317
  frame.allowTransparency = true;
318
  config.container.appendChild(frame);
319
  if (config.onLoad) {
320
  on(frame, "load", config.onLoad);
321
  }
322
  // set the frame URL to the proper value (we previously set it to
323
  // "javascript:false" to work around the IE issue mentioned above)
324
  if(config.usePost) {
325
  var form = config.container.appendChild(document.createElement('form')), input;
326
  form.target = frame.name;
327
  form.action = src;
328
  form.method = 'POST';
329
  if (typeof(config.usePost) === 'object') {
330
  for (var i in config.usePost) {
331
  if (config.usePost.hasOwnProperty(i)) {
332
  if (HAS_NAME_PROPERTY_BUG) {
333
  input = document.createElement('<input name="' + i + '"/>');
334
  } else {
335
  input = document.createElement("INPUT");
336
  input.name = i;
337
  }
338
  input.value = config.usePost[i];
339
  form.appendChild(input);
340
  }
341
  }
342
  }
343
  form.submit();
344
  form.parentNode.removeChild(form);
345
  } else {
346
  frame.src = src;
347
  }
348
  config.props.src = src;
349
  return frame;
350
  * Check whether a domain is allowed using an Access Control List.
351
  * The ACL can contain * and ? as wildcards, or can be regular expressions.
352
  * If regular expressions they need to begin with ^ and end with $.
353
  * @param {Array/String} acl The list of allowed domains
354
  * @param {String} domain The domain to test.
355
  * @return {Boolean} True if the domain is allowed, false if not.
356
  */
357
  // normalize into an array
358
  if (typeof acl == "string") {
359
  acl = [acl];
360
  }
361
  var re, i = acl.length;
362
  while (i--) {
363
  re = acl[i];
364
  re = new RegExp(re.substr(0, 1) == "^" ? re : ("^" + re.replace(/(\*)/g, ".$1").replace(/\?/g, ".") + "$"));
365
  if (re.test(domain)) {
366
  return true;
367
  }
368
  }
369
  return false;
370
  * Functions related to stacks
371
  */
372
  * Prepares an array of stack-elements suitable for the current configuration
373
  * @param {Object} config The Transports configuration. See easyXDM.Socket for more.
374
  * @return {Array} An array of stack-elements with the TransportElement at index 0.
375
  */
376
  var protocol = config.protocol, stackEls;
377
  config.isHost = config.isHost || undef(query.xdm_p);
378
  useHash = config.hash || false;
379
  if (!config.props) {
380
  config.props = {};
381
  }
382
  if (!config.isHost) {
383
  config.channel = query.xdm_c.replace(/["'<>\\]/g, "");
384
  config.secret = query.xdm_s;
385
  config.remote = query.xdm_e.replace(/["'<>\\]/g, "");
386
  ;
387
  protocol = query.xdm_p;
388
  if (config.acl && !checkAcl(config.acl, config.remote)) {
389
  throw new Error("Access denied for " + config.remote);
390
  }
391
  }
392
  else {
393
  config.remote = resolveUrl(config.remote);
394
  config.channel = config.channel || "default" + channelId++;
395
  config.secret = Math.random().toString(16).substring(2);
396
  if (undef(protocol)) {
397
  if (getLocation(location.href) == getLocation(config.remote)) {
398
  /*
399
  * Both documents has the same origin, lets use direct access.
400
  */
401
  protocol = "4";
402
  }
403
  else if (isHostMethod(window, "postMessage") || isHostMethod(document, "postMessage")) {
404
  /*
405
  * This is supported in IE8+, Firefox 3+, Opera 9+, Chrome 2+ and Safari 4+
406
  */
407
  protocol = "1";
408
  }
409
  else if (config.swf && isHostMethod(window, "ActiveXObject") && hasFlash()) {
410
  /*
411
  * The Flash transport superseedes the NixTransport as the NixTransport has been blocked by MS
412
  */
413
  protocol = "6";
414
  }
415
  else if (navigator.product === "Gecko" && "frameElement" in window && navigator.userAgent.indexOf('WebKit') == -1) {
416
  /*
417
  * This is supported in Gecko (Firefox 1+)
418
  */
419
  protocol = "5";
420
  }
421
  else if (config.remoteHelper) {
422
  /*
423
  * This is supported in all browsers that retains the value of window.name when
424
  * navigating from one domain to another, and where parent.frames[foo] can be used
425
  * to get access to a frame from the same domain
426
  */
427
  protocol = "2";
428
  }
429
  else {
430
  /*
431
  * This is supported in all browsers where [window].location is writable for all
432
  * The resize event will be used if resize is supported and the iframe is not put
433
  * into a container, else polling will be used.
434
  */
435
  protocol = "0";
436
  }
437
  }
438
  }
439
  config.protocol = protocol; // for conditional branching
440
  switch (protocol) {
441
  case "0":// 0 = HashTransport
442
  apply(config, {
443
  interval: 100,
444
  delay: 2000,
445
  useResize: true,
446
  useParent: false,
447
  usePolling: false
448
  }, true);
449
  if (config.isHost) {
450
  if (!config.local) {
451
  // If no local is set then we need to find an image hosted on the current domain
452
  var domain = location.protocol + "//" + location.host, images = document.body.getElementsByTagName("img"), image;
453
  var i = images.length;
454
  while (i--) {
455
  image = images[i];
456
  if (image.src.substring(0, domain.length) === domain) {
457
  config.local = image.src;
458
  break;
459
  }
460
  }
461
  if (!config.local) {
462
  // If no local was set, and we are unable to find a suitable file, then we resort to using the current window
463
  config.local = window;
464
  }
465
  }
466
  var parameters = {
467
  xdm_c: config.channel,
468
  xdm_p: 0
469
  };
470
  if (config.local === window) {
471
  // We are using the current window to listen to
472
  config.usePolling = true;
473
  config.useParent = true;
474
  config.local = location.protocol + "//" + location.host + location.pathname + location.search;
475
  parameters.xdm_e = config.local;
476
  parameters.xdm_pa = 1; // use parent
477
  }
478
  else {
479
  parameters.xdm_e = resolveUrl(config.local);
480
  }
481
  if (config.container) {
482
  config.useResize = false;
483
  parameters.xdm_po = 1; // use polling
484
  }
485
  config.remote = appendQueryParameters(config.remote, parameters);
486
  }
487
  else {
488
  apply(config, {
489
  channel: query.xdm_c,
490
  remote: query.xdm_e,
491
  useParent: !undef(query.xdm_pa),
492
  usePolling: !undef(query.xdm_po),
493
  useResize: config.useParent ? false : config.useResize
494
  });
495
  }
496
  stackEls = [new easyXDM.stack.HashTransport(config), new easyXDM.stack.ReliableBehavior({}), new easyXDM.stack.QueueBehavior({
497
  encode: true,
498
  maxLength: 4000 - config.remote.length
499
  }), new easyXDM.stack.VerifyBehavior({
500
  initiate: config.isHost
501
  })];
502
  break;
503
  case "1":
504
  stackEls = [new easyXDM.stack.PostMessageTransport(config)];
505
  break;
506
  case "2":
507
  if (config.isHost) {
508
  config.remoteHelper = resolveUrl(config.remoteHelper);
509
  }
510
  stackEls = [new easyXDM.stack.NameTransport(config), new easyXDM.stack.QueueBehavior(), new easyXDM.stack.VerifyBehavior({
511
  initiate: config.isHost
512
  })];
513
  break;
514
  case "3":
515
  stackEls = [new easyXDM.stack.NixTransport(config)];
516
  break;
517
  case "4":
518
  stackEls = [new easyXDM.stack.SameOriginTransport(config)];
519
  break;
520
  case "5":
521
  stackEls = [new easyXDM.stack.FrameElementTransport(config)];
522
  break;
523
  case "6":
524
  if (!flashVersion) {
525
  hasFlash();
526
  }
527
  stackEls = [new easyXDM.stack.FlashTransport(config)];
528
  break;
529
  }
530
  // this behavior is responsible for buffering outgoing messages, and for performing lazy initialization
531
  stackEls.push(new easyXDM.stack.QueueBehavior({
532
  lazy: config.lazy,
533
  remove: true
534
  }));
535
  return stackEls;
536
  * Chains all the separate stack elements into a single usable stack.<br/>
537
  * If an element is missing a necessary method then it will have a pass-through method applied.
538
  * @param {Array} stackElements An array of stack elements to be linked.
539
  * @return {easyXDM.stack.StackElement} The last element in the chain.
540
  */
541
  var stackEl, defaults = {
542
  incoming: function(message, origin){
543
  this.up.incoming(message, origin);
544
  },
545
  outgoing: function(message, recipient){
546
  this.down.outgoing(message, recipient);
547
  },
548
  callback: function(success){
549
  this.up.callback(success);
550
  },
551
  init: function(){
552
  this.down.init();
553
  },
554
  destroy: function(){
555
  this.down.destroy();
556
  }
557
  };
558
  for (var i = 0, len = stackElements.length; i < len; i++) {
559
  stackEl = stackElements[i];
560
  apply(stackEl, defaults, true);
561
  if (i !== 0) {
562
  stackEl.down = stackElements[i - 1];
563
  }
564
  if (i !== len - 1) {
565
  stackEl.up = stackElements[i + 1];
566
  }
567
  }
568
  return stackEl;
569
  * This will remove a stackelement from its stack while leaving the stack functional.
570
  * @param {Object} element The elment to remove from the stack.
571
  */
572
  element.up.down = element.down;
573
  element.down.up = element.up;
574
  element.up = element.down = null;
575
  * Export the main object and any other methods applicable
576
  */
577
  * @class easyXDM
578
  * A javascript library providing cross-browser, cross-domain messaging/RPC.
579
  * @version 2.4.19.0
580
  * @singleton
581
  */
582
  /**
583
  * The version of the library
584
  * @type {string}
585
  */
586
  version: "2.4.19.0",
587
  /**
588
  * This is a map containing all the query parameters passed to the document.
589
  * All the values has been decoded using decodeURIComponent.
590
  * @type {object}
591
  */
592
  query: query,
593
  /**
594
  * @private
595
  */
596
  stack: {},
597
  /**
598
  * Applies properties from the source object to the target object.<br/>
599
  * @param {object} target The target of the properties.
600
  * @param {object} source The source of the properties.
601
  * @param {boolean} noOverwrite Set to True to only set non-existing properties.
602
  */
603
  apply: apply,
604
  /**
605
  * A safe implementation of HTML5 JSON. Feature testing is used to make sure the implementation works.
606
  * @return {JSON} A valid JSON conforming object, or null if not found.
607
  */
608
  getJSONObject: getJSON,
609
  /**
610
  * This will add a function to the queue of functions to be run once the DOM reaches a ready state.
611
  * If functions are added after this event then they will be executed immediately.
612
  * @param {function} fn The function to add
613
  * @param {object} scope An optional scope for the function to be called with.
614
  */
615
  whenReady: whenReady,
616
  /**
617
  * Removes easyXDM variable from the global scope. It also returns control
618
  * of the easyXDM variable to whatever code used it before.
619
  *
620
  * @param {String} ns A string representation of an object that will hold
621
  * an instance of easyXDM.
622
  * @return An instance of easyXDM
623
  */
624
  noConflict: noConflict
625
  * @class easyXDM.DomHelper
626
  * Contains methods for dealing with the DOM
627
  * @singleton
628
  */
629
  /**
630
  * Provides a consistent interface for adding eventhandlers
631
  * @param {Object} target The target to add the event to
632
  * @param {String} type The name of the event
633
  * @param {Function} listener The listener
634
  */
635
  on: on,
636
  /**
637
  * Provides a consistent interface for removing eventhandlers
638
  * @param {Object} target The target to remove the event from
639
  * @param {String} type The name of the event
640
  * @param {Function} listener The listener
641
  */
642
  un: un,
643
  /**
644
  * Checks for the presence of the JSON object.
645
  * If it is not present it will use the supplied path to load the JSON2 library.
646
  * This should be called in the documents head right after the easyXDM script tag.
647
  * http://json.org/json2.js
648
  * @param {String} path A valid path to json2.js
649
  */
650
  requiresJSON: function(path){
651
  if (!isHostObject(window, "JSON")) {
652
  // we need to encode the < in order to avoid an illegal token error
653
  // when the script is inlined in a document.
654
  document.write('<' + 'script type="text/javascript" src="' + path + '"><' + '/script>');
655
  }
656
  }
657
  // The map containing the stored functions
658
  var _map = {};
659
  /**
660
  * @class easyXDM.Fn
661
  * This contains methods related to function handling, such as storing callbacks.
662
  * @singleton
663
  * @namespace easyXDM
664
  */
665
  easyXDM.Fn = {
666
  /**
667
  * Stores a function using the given name for reference
668
  * @param {String} name The name that the function should be referred by
669
  * @param {Function} fn The function to store
670
  * @namespace easyXDM.fn
671
  */
672
  set: function(name, fn){
673
  _map[name] = fn;
674
  },
675
  /**
676
  * Retrieves the function referred to by the given name
677
  * @param {String} name The name of the function to retrieve
678
  * @param {Boolean} del If the function should be deleted after retrieval
679
  * @return {Function} The stored function
680
  * @namespace easyXDM.fn
681
  */
682
  get: function(name, del){
683
  if (!_map.hasOwnProperty(name)) {
684
  return;
685
  }
686
  var fn = _map[name];
687
  if (del) {
688
  delete _map[name];
689
  }
690
  return fn;
691
  }
692
  };
693
  * @class easyXDM.Socket
694
  * This class creates a transport channel between two domains that is usable for sending and receiving string-based messages.<br/>
695
  * The channel is reliable, supports queueing, and ensures that the message originates from the expected domain.<br/>
696
  * Internally different stacks will be used depending on the browsers features and the available parameters.
697
  * <h2>How to set up</h2>
698
  * Setting up the provider:
699
  * <pre><code>
700
  * var socket = new easyXDM.Socket({
701
  * &nbsp; local: "name.html",
702
  * &nbsp; onReady: function(){
703
  * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the socket
704
  * &nbsp; &nbsp; socket.postMessage("foo-message");
705
  * &nbsp; },
706
  * &nbsp; onMessage: function(message, origin) {
707
  * &nbsp;&nbsp; alert("received " + message + " from " + origin);
708
  * &nbsp; }
709
  * });
710
  * </code></pre>
711
  * Setting up the consumer:
712
  * <pre><code>
713
  * var socket = new easyXDM.Socket({
714
  * &nbsp; remote: "http:&#47;&#47;remotedomain/page.html",
715
  * &nbsp; remoteHelper: "http:&#47;&#47;remotedomain/name.html",
716
  * &nbsp; onReady: function(){
717
  * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the socket
718
  * &nbsp; &nbsp; socket.postMessage("foo-message");
719
  * &nbsp; },
720
  * &nbsp; onMessage: function(message, origin) {
721
  * &nbsp;&nbsp; alert("received " + message + " from " + origin);
722
  * &nbsp; }
723
  * });
724
  * </code></pre>
725
  * If you are unable to upload the <code>name.html</code> file to the consumers domain then remove the <code>remoteHelper</code> property
726
  * and easyXDM will fall back to using the HashTransport instead of the NameTransport when not able to use any of the primary transports.
727
  * @namespace easyXDM
728
  * @constructor
729
  * @cfg {String/Window} local The url to the local name.html document, a local static file, or a reference to the local window.
730
  * @cfg {Boolean} lazy (Consumer only) Set this to true if you want easyXDM to defer creating the transport until really needed.
731
  * @cfg {String} remote (Consumer only) The url to the providers document.
732
  * @cfg {String} remoteHelper (Consumer only) The url to the remote name.html file. This is to support NameTransport as a fallback. Optional.
733
  * @cfg {Number} delay The number of milliseconds easyXDM should try to get a reference to the local window. Optional, defaults to 2000.
734
  * @cfg {Number} interval The interval used when polling for messages. Optional, defaults to 300.
735
  * @cfg {String} channel (Consumer only) The name of the channel to use. Can be used to set consistent iframe names. Must be unique. Optional.
736
  * @cfg {Function} onMessage The method that should handle incoming messages.<br/> This method should accept two arguments, the message as a string, and the origin as a string. Optional.
737
  * @cfg {Function} onReady A method that should be called when the transport is ready. Optional.
738
  * @cfg {DOMElement|String} container (Consumer only) The element, or the id of the element that the primary iframe should be inserted into. If not set then the iframe will be positioned off-screen. Optional.
739
  * @cfg {Array/String} acl (Provider only) Here you can specify which '[protocol]://[domain]' patterns that should be allowed to act as the consumer towards this provider.<br/>
740
  * This can contain the wildcards ? and *. Examples are 'http://example.com', '*.foo.com' and '*dom?.com'. If you want to use reqular expressions then you pattern needs to start with ^ and end with $.
741
  * If none of the patterns match an Error will be thrown.
742
  * @cfg {Object} props (Consumer only) Additional properties that should be applied to the iframe. This can also contain nested objects e.g: <code>{style:{width:"100px", height:"100px"}}</code>.
743
  * Properties such as 'name' and 'src' will be overrided. Optional.
744
  */
745
  // create the stack
746
  var stack = chainStack(prepareTransportStack(config).concat([{
747
  incoming: function(message, origin){
748
  config.onMessage(message, origin);
749
  },
750
  callback: function(success){
751
  if (config.onReady) {
752
  config.onReady(success);
753
  }
754
  }
755
  }])), recipient = getLocation(config.remote);
756
  // set the origin
757
  this.origin = getLocation(config.remote);
758
  /**
759
  * Initiates the destruction of the stack.
760
  */
761
  this.destroy = function(){
762
  stack.destroy();
763
  };
764
  /**
765
  * Posts a message to the remote end of the channel
766
  * @param {String} message The message to send
767
  */
768
  this.postMessage = function(message){
769
  stack.outgoing(message, recipient);
770
  };
771
  stack.init();
772
  * @class easyXDM.Rpc
773
  * Creates a proxy object that can be used to call methods implemented on the remote end of the channel, and also to provide the implementation
774
  * of methods to be called from the remote end.<br/>
775
  * The instantiated object will have methods matching those specified in <code>config.remote</code>.<br/>
776
  * This requires the JSON object present in the document, either natively, using json.org's json2 or as a wrapper around library spesific methods.
777
  * <h2>How to set up</h2>
778
  * <pre><code>
779
  * var rpc = new easyXDM.Rpc({
780
  * &nbsp; &#47;&#47; this configuration is equal to that used by the Socket.
781
  * &nbsp; remote: "http:&#47;&#47;remotedomain/...",
782
  * &nbsp; onReady: function(){
783
  * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the proxy
784
  * &nbsp; &nbsp; rpc.foo(...
785
  * &nbsp; }
786
  * },{
787
  * &nbsp; local: {..},
788
  * &nbsp; remote: {..}
789
  * });
790
  * </code></pre>
791
  *
792
  * <h2>Exposing functions (procedures)</h2>
793
  * <pre><code>
794
  * var rpc = new easyXDM.Rpc({
795
  * &nbsp; ...
796
  * },{
797
  * &nbsp; local: {
798
  * &nbsp; &nbsp; nameOfMethod: {
799
  * &nbsp; &nbsp; &nbsp; method: function(arg1, arg2, success, error){
800
  * &nbsp; &nbsp; &nbsp; &nbsp; ...
801
  * &nbsp; &nbsp; &nbsp; }
802
  * &nbsp; &nbsp; },
803
  * &nbsp; &nbsp; &#47;&#47; with shorthand notation
804
  * &nbsp; &nbsp; nameOfAnotherMethod: function(arg1, arg2, success, error){
805
  * &nbsp; &nbsp; }
806
  * &nbsp; },
807
  * &nbsp; remote: {...}
808
  * });
809
  * </code></pre>
810
  * The function referenced by [method] will receive the passed arguments followed by the callback functions <code>success</code> and <code>error</code>.<br/>
811
  * To send a successfull result back you can use
812
  * <pre><code>
813
  * return foo;
814
  * </pre></code>
815
  * or
816
  * <pre><code>
817
  * success(foo);
818
  * </pre></code>
819
  * To return an error you can use
820
  * <pre><code>
821
  * throw new Error("foo error");
822
  * </code></pre>
823
  * or
824
  * <pre><code>
825
  * error("foo error");
826
  * </code></pre>
827
  *
828
  * <h2>Defining remotely exposed methods (procedures/notifications)</h2>
829
  * The definition of the remote end is quite similar:
830
  * <pre><code>
831
  * var rpc = new easyXDM.Rpc({
832
  * &nbsp; ...
833
  * },{
834
  * &nbsp; local: {...},
835
  * &nbsp; remote: {
836
  * &nbsp; &nbsp; nameOfMethod: {}
837
  * &nbsp; }
838
  * });
839
  * </code></pre>
840
  * To call a remote method use
841
  * <pre><code>
842
  * rpc.nameOfMethod("arg1", "arg2", function(value) {
843
  * &nbsp; alert("success: " + value);
844
  * }, function(message) {
845
  * &nbsp; alert("error: " + message + );
846
  * });
847
  * </code></pre>
848
  * Both the <code>success</code> and <code>errror</code> callbacks are optional.<br/>
849
  * When called with no callback a JSON-RPC 2.0 notification will be executed.
850
  * Be aware that you will not be notified of any errors with this method.
851
  * <br/>
852
  * <h2>Specifying a custom serializer</h2>
853
  * If you do not want to use the JSON2 library for non-native JSON support, but instead capabilities provided by some other library
854
  * then you can specify a custom serializer using <code>serializer: foo</code>
855
  * <pre><code>
856
  * var rpc = new easyXDM.Rpc({
857
  * &nbsp; ...
858
  * },{
859
  * &nbsp; local: {...},
860
  * &nbsp; remote: {...},
861
  * &nbsp; serializer : {
862
  * &nbsp; &nbsp; parse: function(string){ ... },
863
  * &nbsp; &nbsp; stringify: function(object) {...}
864
  * &nbsp; }
865
  * });
866
  * </code></pre>
867
  * If <code>serializer</code> is set then the class will not attempt to use the native implementation.
868
  * @namespace easyXDM
869
  * @constructor
870
  * @param {Object} config The underlying transports configuration. See easyXDM.Socket for available parameters.
871
  * @param {Object} jsonRpcConfig The description of the interface to implement.
872
  */
873
  // expand shorthand notation
874
  if (jsonRpcConfig.local) {
875
  for (var method in jsonRpcConfig.local) {
876
  if (jsonRpcConfig.local.hasOwnProperty(method)) {
877
  var member = jsonRpcConfig.local[method];
878
  if (typeof member === "function") {
879
  jsonRpcConfig.local[method] = {
880
  method: member
881
  };
882
  }
883
  }
884
  }
885
  }
886
  // create the stack
887
  var stack = chainStack(prepareTransportStack(config).concat([new easyXDM.stack.RpcBehavior(this, jsonRpcConfig), {
888
  callback: function(success){
889
  if (config.onReady) {
890
  config.onReady(success);
891
  }
892
  }
893
  }]));
894
  // set the origin
895
  this.origin = getLocation(config.remote);
896
  /**
897
  * Initiates the destruction of the stack.
898
  */
899
  this.destroy = function(){
900
  stack.destroy();
901
  };
902
  stack.init();
903
  * @class easyXDM.stack.SameOriginTransport
904
  * SameOriginTransport is a transport class that can be used when both domains have the same origin.<br/>
905
  * This can be useful for testing and for when the main application supports both internal and external sources.
906
  * @namespace easyXDM.stack
907
  * @constructor
908
  * @param {Object} config The transports configuration.
909
  * @cfg {String} remote The remote document to communicate with.
910
  */
911
  var pub, frame, send, targetOrigin;
912
  return (pub = {
913
  outgoing: function(message, domain, fn){
914
  send(message);
915
  if (fn) {
916
  fn();
917
  }
918
  },
919
  destroy: function(){
920
  if (frame) {
921
  frame.parentNode.removeChild(frame);
922
  frame = null;
923
  }
924
  },
925
  onDOMReady: function(){
926
  targetOrigin = getLocation(config.remote);
927
  if (config.isHost) {
928
  // set up the iframe
929
  apply(config.props, {
930
  src: appendQueryParameters(config.remote, {
931
  xdm_e: location.protocol + "//" + location.host + location.pathname,
932
  xdm_c: config.channel,
933
  xdm_p: 4 // 4 = SameOriginTransport
934
  }),
935
  name: IFRAME_PREFIX + config.channel + "_provider"
936
  });
937
  frame = createFrame(config);
938
  easyXDM.Fn.set(config.channel, function(sendFn){
939
  send = sendFn;
940
  setTimeout(function(){
941
  pub.up.callback(true);
942
  }, 0);
943
  return function(msg){
944
  pub.up.incoming(msg, targetOrigin);
945
  };
946
  });
947
  }
948
  else {
949
  send = getParentObject().Fn.get(config.channel, true)(function(msg){
950
  pub.up.incoming(msg, targetOrigin);
951
  });
952
  setTimeout(function(){
953
  pub.up.callback(true);
954
  }, 0);
955
  }
956
  },
957
  init: function(){
958
  whenReady(pub.onDOMReady, pub);
959
  }
960
  });
961
  * @class easyXDM.stack.FlashTransport
962
  * FlashTransport is a transport class that uses an SWF with LocalConnection to pass messages back and forth.
963
  * @namespace easyXDM.stack
964
  * @constructor
965
  * @param {Object} config The transports configuration.
966
  * @cfg {String} remote The remote domain to communicate with.
967
  * @cfg {String} secret the pre-shared secret used to secure the communication.
968
  * @cfg {String} swf The path to the swf file
969
  * @cfg {Boolean} swfNoThrottle Set this to true if you want to take steps to avoid beeing throttled when hidden.
970
  * @cfg {String || DOMElement} swfContainer Set this if you want to control where the swf is placed
971
  */
972
  var pub, // the public interface
973
  frame, send, targetOrigin, swf, swfContainer;
974
  function onMessage(message, origin){
975
  setTimeout(function(){
976
  pub.up.incoming(message, targetOrigin);
977
  }, 0);
978
  }
979
  /**
980
  * This method adds the SWF to the DOM and prepares the initialization of the channel
981
  */
982
  function addSwf(domain){
983
  // the differentiating query argument is needed in Flash9 to avoid a caching issue where LocalConnection would throw an error.
984
  var url = config.swf + "?host=" + config.isHost;
985
  var id = "easyXDM_swf_" + Math.floor(Math.random() * 10000);
986
  // prepare the init function that will fire once the swf is ready
987
  easyXDM.Fn.set("flash_loaded" + domain.replace(/[\-.]/g, "_"), function(){
988
  easyXDM.stack.FlashTransport[domain].swf = swf = swfContainer.firstChild;
989
  var queue = easyXDM.stack.FlashTransport[domain].queue;
990
  for (var i = 0; i < queue.length; i++) {
991
  queue[i]();
992
  }
993
  queue.length = 0;
994
  });
995
  if (config.swfContainer) {
996
  swfContainer = (typeof config.swfContainer == "string") ? document.getElementById(config.swfContainer) : config.swfContainer;
997
  }
998
  else {
999
  // create the container that will hold the swf
1000
  swfContainer = document.createElement('div');
1001
  // http://bugs.adobe.com/jira/browse/FP-4796
1002
  // http://tech.groups.yahoo.com/group/flexcoders/message/162365
1003
  // https://groups.google.com/forum/#!topic/easyxdm/mJZJhWagoLc
1004
  apply(swfContainer.style, HAS_FLASH_THROTTLED_BUG && config.swfNoThrottle ? {
1005
  height: "20px",
1006
  width: "20px",
1007
  position: "fixed",
1008
  right: 0,
1009
  top: 0
1010
  } : {
1011
  height: "1px",
1012
  width: "1px",
1013
  position: "absolute",
1014
  overflow: "hidden",
1015
  right: 0,
1016
  top: 0
1017
  });
1018
  document.body.appendChild(swfContainer);
1019
  }
1020
  // create the object/embed
1021
  var flashVars = "callback=flash_loaded" + encodeURIComponent(domain.replace(/[\-.]/g, "_"))
1022
  + "&proto=" + global.location.protocol
1023
  + "&domain=" + encodeURIComponent(getDomainName(global.location.href))
1024
  + "&port=" + encodeURIComponent(getPort(global.location.href))
1025
  + "&ns=" + encodeURIComponent(namespace);
1026
  swfContainer.innerHTML = "<object height='20' width='20' type='application/x-shockwave-flash' id='" + id + "' data='" + url + "'>" +
1027
  "<param name='allowScriptAccess' value='always'></param>" +
1028
  "<param name='wmode' value='transparent'>" +
1029
  "<param name='movie' value='" +
1030
  url +
1031
  "'></param>" +
1032
  "<param name='flashvars' value='" +
1033
  flashVars +
1034
  "'></param>" +
1035
  "<embed type='application/x-shockwave-flash' FlashVars='" +
1036
  flashVars +
1037
  "' allowScriptAccess='always' wmode='transparent' src='" +
1038
  url +
1039
  "' height='1' width='1'></embed>" +
1040
  "</object>";
1041
  }
1042
  return (pub = {
1043
  outgoing: function(message, domain, fn){
1044
  swf.postMessage(config.channel, message.toString());
1045
  if (fn) {
1046
  fn();
1047
  }
1048
  },
1049
  destroy: function(){
1050
  try {
1051
  swf.destroyChannel(config.channel);
1052
  }
1053
  catch (e) {
1054
  }
1055
  swf = null;
1056
  if (frame) {
1057
  frame.parentNode.removeChild(frame);
1058
  frame = null;
1059
  }
1060
  },
1061
  onDOMReady: function(){
1062
  targetOrigin = config.remote;
1063
  // Prepare the code that will be run after the swf has been intialized
1064
  easyXDM.Fn.set("flash_" + config.channel + "_init", function(){
1065
  setTimeout(function(){
1066
  pub.up.callback(true);
1067
  });
1068
  });
1069
  // set up the omMessage handler
1070
  easyXDM.Fn.set("flash_" + config.channel + "_onMessage", onMessage);
1071
  config.swf = resolveUrl(config.swf); // reports have been made of requests gone rogue when using relative paths
1072
  var swfdomain = getDomainName(config.swf);
1073
  var fn = function(){
1074
  // set init to true in case the fn was called was invoked from a separate instance
1075
  easyXDM.stack.FlashTransport[swfdomain].init = true;
1076
  swf = easyXDM.stack.FlashTransport[swfdomain].swf;
1077
  // create the channel
1078
  swf.createChannel(config.channel, config.secret, getLocation(config.remote), config.isHost);
1079
  if (config.isHost) {
1080
  // if Flash is going to be throttled and we want to avoid this
1081
  if (HAS_FLASH_THROTTLED_BUG && config.swfNoThrottle) {
1082
  apply(config.props, {
1083
  position: "fixed",
1084
  right: 0,
1085
  top: 0,
1086
  height: "20px",
1087
  width: "20px"
1088
  });
1089
  }
1090
  // set up the iframe
1091
  apply(config.props, {
1092
  src: appendQueryParameters(config.remote, {
1093
  xdm_e: getLocation(location.href),
1094
  xdm_c: config.channel,
1095
  xdm_p: 6, // 6 = FlashTransport
1096
  xdm_s: config.secret
1097
  }),
1098
  name: IFRAME_PREFIX + config.channel + "_provider"
1099
  });
1100
  frame = createFrame(config);
1101
  }
1102
  };
1103
  if (easyXDM.stack.FlashTransport[swfdomain] && easyXDM.stack.FlashTransport[swfdomain].init) {
1104
  // if the swf is in place and we are the consumer
1105
  fn();
1106
  }
1107
  else {
1108
  // if the swf does not yet exist
1109
  if (!easyXDM.stack.FlashTransport[swfdomain]) {
1110
  // add the queue to hold the init fn's
1111
  easyXDM.stack.FlashTransport[swfdomain] = {
1112
  queue: [fn]
1113
  };
1114
  addSwf(swfdomain);
1115
  }
1116
  else {
1117
  easyXDM.stack.FlashTransport[swfdomain].queue.push(fn);
1118
  }
1119
  }
1120
  },
1121
  init: function(){
1122
  whenReady(pub.onDOMReady, pub);
1123
  }
1124
  });
1125
  * @class easyXDM.stack.PostMessageTransport
1126
  * PostMessageTransport is a transport class that uses HTML5 postMessage for communication.<br/>
1127
  * <a href="http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx</a><br/>
1128
  * <a href="https://developer.mozilla.org/en/DOM/window.postMessage">https://developer.mozilla.org/en/DOM/window.postMessage</a>
1129
  * @namespace easyXDM.stack
1130
  * @constructor
1131
  * @param {Object} config The transports configuration.
1132
  * @cfg {String} remote The remote domain to communicate with.
1133
  */
1134
  var pub, // the public interface
1135
  frame, // the remote frame, if any
1136
  callerWindow, // the window that we will call with
1137
  targetOrigin; // the domain to communicate with
1138
  /**
1139
  * Resolves the origin from the event object
1140
  * @private
1141
  * @param {Object} event The messageevent
1142
  * @return {String} The scheme, host and port of the origin
1143
  */
1144
  function _getOrigin(event){
1145
  if (event.origin) {
1146
  // This is the HTML5 property
1147
  return getLocation(event.origin);
1148
  }
1149
  if (event.uri) {
1150
  // From earlier implementations
1151
  return getLocation(event.uri);
1152
  }
1153
  if (event.domain) {
1154
  // This is the last option and will fail if the
1155
  // origin is not using the same schema as we are
1156
  return location.protocol + "//" + event.domain;
1157
  }
1158
  throw "Unable to retrieve the origin of the event";
1159
  }
1160
  /**
1161
  * This is the main implementation for the onMessage event.<br/>
1162
  * It checks the validity of the origin and passes the message on if appropriate.
1163
  * @private
1164
  * @param {Object} event The messageevent
1165
  */
1166
  function _window_onMessage(event){
1167
  var origin = _getOrigin(event);
1168
  if (origin == targetOrigin && event.data.substring(0, config.channel.length + 1) == config.channel + " ") {
1169
  pub.up.incoming(event.data.substring(config.channel.length + 1), origin);
1170
  }
1171
  }
1172
  return (pub = {
1173
  outgoing: function(message, domain, fn){
1174
  callerWindow.postMessage(config.channel + " " + message, domain || targetOrigin);
1175
  if (fn) {
1176
  fn();
1177
  }
1178
  },
1179
  destroy: function(){
1180
  un(window, "message", _window_onMessage);
1181
  if (frame) {
1182
  callerWindow = null;
1183
  frame.parentNode.removeChild(frame);
1184
  frame = null;
1185
  }
1186
  },
1187
  onDOMReady: function(){
1188
  targetOrigin = getLocation(config.remote);
1189
  if (config.isHost) {
1190
  // add the event handler for listening
1191
  var waitForReady = function(event){
1192
  if (event.data == config.channel + "-ready") {
1193
  // replace the eventlistener
1194
  callerWindow = ("postMessage" in frame.contentWindow) ? frame.contentWindow : frame.contentWindow.document;
1195
  un(window, "message", waitForReady);
1196
  on(window, "message", _window_onMessage);
1197
  setTimeout(function(){
1198
  pub.up.callback(true);
1199
  }, 0);
1200
  }
1201
  };
1202
  on(window, "message", waitForReady);
1203
  // set up the iframe
1204
  apply(config.props, {
1205
  src: appendQueryParameters(config.remote, {
1206
  xdm_e: getLocation(location.href),
1207
  xdm_c: config.channel,
1208
  xdm_p: 1 // 1 = PostMessage
1209
  }),
1210
  name: IFRAME_PREFIX + config.channel + "_provider"
1211
  });
1212
  frame = createFrame(config);
1213
  }
1214
  else {
1215
  // add the event handler for listening
1216
  on(window, "message", _window_onMessage);
1217
  callerWindow = ("postMessage" in window.parent) ? window.parent : window.parent.document;
1218
  callerWindow.postMessage(config.channel + "-ready", targetOrigin);
1219
  setTimeout(function(){
1220
  pub.up.callback(true);
1221
  }, 0);
1222
  }
1223
  },
1224
  init: function(){
1225
  whenReady(pub.onDOMReady, pub);
1226
  }
1227
  });
1228
  * @class easyXDM.stack.FrameElementTransport
1229
  * FrameElementTransport is a transport class that can be used with Gecko-browser as these allow passing variables using the frameElement property.<br/>
1230
  * Security is maintained as Gecho uses Lexical Authorization to determine under which scope a function is running.
1231
  * @namespace easyXDM.stack
1232
  * @constructor
1233
  * @param {Object} config The transports configuration.
1234
  * @cfg {String} remote The remote document to communicate with.
1235
  */
1236
  var pub, frame, send, targetOrigin;
1237
  return (pub = {
1238
  outgoing: function(message, domain, fn){
1239
  send.call(this, message);
1240
  if (fn) {
1241
  fn();
1242
  }
1243
  },
1244
  destroy: function(){
1245
  if (frame) {
1246
  frame.parentNode.removeChild(frame);
1247
  frame = null;
1248
  }
1249
  },
1250
  onDOMReady: function(){
1251
  targetOrigin = getLocation(config.remote);
1252
  if (config.isHost) {
1253
  // set up the iframe
1254
  apply(config.props, {
1255
  src: appendQueryParameters(config.remote, {
1256
  xdm_e: getLocation(location.href),
1257
  xdm_c: config.channel,
1258
  xdm_p: 5 // 5 = FrameElementTransport
1259
  }),
1260
  name: IFRAME_PREFIX + config.channel + "_provider"
1261
  });
1262
  frame = createFrame(config);
1263
  frame.fn = function(sendFn){
1264
  delete frame.fn;
1265
  send = sendFn;
1266
  setTimeout(function(){
1267
  pub.up.callback(true);
1268
  }, 0);
1269
  // remove the function so that it cannot be used to overwrite the send function later on
1270
  return function(msg){
1271
  pub.up.incoming(msg, targetOrigin);
1272
  };
1273
  };
1274
  }
1275
  else {
1276
  // This is to mitigate origin-spoofing
1277
  if (document.referrer && getLocation(document.referrer) != query.xdm_e) {
1278
  window.top.location = query.xdm_e;
1279
  }
1280
  send = window.frameElement.fn(function(msg){
1281
  pub.up.incoming(msg, targetOrigin);
1282
  });
1283
  pub.up.callback(true);
1284
  }
1285
  },
1286
  init: function(){
1287
  whenReady(pub.onDOMReady, pub);
1288
  }
1289
  });
1290
  * @class easyXDM.stack.NameTransport
1291
  * NameTransport uses the window.name property to relay data.
1292
  * The <code>local</code> parameter needs to be set on both the consumer and provider,<br/>
1293
  * and the <code>remoteHelper</code> parameter needs to be set on the consumer.
1294
  * @constructor
1295
  * @param {Object} config The transports configuration.
1296
  * @cfg {String} remoteHelper The url to the remote instance of hash.html - this is only needed for the host.
1297
  * @namespace easyXDM.stack
1298
  */
1299
  var pub; // the public interface
1300
  var isHost, callerWindow, remoteWindow, readyCount, callback, remoteOrigin, remoteUrl;
1301
  function _sendMessage(message){
1302
  var url = config.remoteHelper + (isHost ? "#_3" : "#_2") + config.channel;
1303
  callerWindow.contentWindow.sendMessage(message, url);
1304
  }
1305
  function _onReady(){
1306
  if (isHost) {
1307
  if (++readyCount === 2 || !isHost) {
1308
  pub.up.callback(true);
1309
  }
1310
  }
1311
  else {
1312
  _sendMessage("ready");
1313
  pub.up.callback(true);
1314
  }
1315
  }
1316
  function _onMessage(message){
1317
  pub.up.incoming(message, remoteOrigin);
1318
  }
1319
  function _onLoad(){
1320
  if (callback) {
1321
  setTimeout(function(){
1322
  callback(true);
1323
  }, 0);
1324
  }
1325
  }
1326
  return (pub = {
1327
  outgoing: function(message, domain, fn){
1328
  callback = fn;
1329
  _sendMessage(message);
1330
  },
1331
  destroy: function(){
1332
  callerWindow.parentNode.removeChild(callerWindow);
1333
  callerWindow = null;
1334
  if (isHost) {
1335
  remoteWindow.parentNode.removeChild(remoteWindow);
1336
  remoteWindow = null;
1337
  }
1338
  },
1339
  onDOMReady: function(){
1340
  isHost = config.isHost;
1341
  readyCount = 0;
1342
  remoteOrigin = getLocation(config.remote);
1343
  config.local = resolveUrl(config.local);
1344
  if (isHost) {
1345
  // Register the callback
1346
  easyXDM.Fn.set(config.channel, function(message){
1347
  if (isHost && message === "ready") {
1348
  // Replace the handler
1349
  easyXDM.Fn.set(config.channel, _onMessage);
1350
  _onReady();
1351
  }
1352
  });
1353
  // Set up the frame that points to the remote instance
1354
  remoteUrl = appendQueryParameters(config.remote, {
1355
  xdm_e: config.local,
1356
  xdm_c: config.channel,
1357
  xdm_p: 2
1358
  });
1359
  apply(config.props, {
1360
  src: remoteUrl + '#' + config.channel,
1361
  name: IFRAME_PREFIX + config.channel + "_provider"
1362
  });
1363
  remoteWindow = createFrame(config);
1364
  }
1365
  else {
1366
  config.remoteHelper = config.remote;
1367
  easyXDM.Fn.set(config.channel, _onMessage);
1368
  }
1369
  // Set up the iframe that will be used for the transport
1370
  var onLoad = function(){
1371
  // Remove the handler
1372
  var w = callerWindow || this;
1373
  un(w, "load", onLoad);
1374
  easyXDM.Fn.set(config.channel + "_load", _onLoad);
1375
  (function test(){
1376
  if (typeof w.contentWindow.sendMessage == "function") {
1377
  _onReady();
1378
  }
1379
  else {
1380
  setTimeout(test, 50);
1381
  }
1382
  }());
1383
  };
1384
  callerWindow = createFrame({
1385
  props: {
1386
  src: config.local + "#_4" + config.channel
1387
  },
1388
  onLoad: onLoad
1389
  });
1390
  },
1391
  init: function(){
1392
  whenReady(pub.onDOMReady, pub);
1393
  }
1394
  });
1395
  * @class easyXDM.stack.HashTransport
1396
  * HashTransport is a transport class that uses the IFrame URL Technique for communication.<br/>
1397
  * <a href="http://msdn.microsoft.com/en-us/library/bb735305.aspx">http://msdn.microsoft.com/en-us/library/bb735305.aspx</a><br/>
1398
  * @namespace easyXDM.stack
1399
  * @constructor
1400
  * @param {Object} config The transports configuration.
1401
  * @cfg {String/Window} local The url to the local file used for proxying messages, or the local window.
1402
  * @cfg {Number} delay The number of milliseconds easyXDM should try to get a reference to the local window.
1403
  * @cfg {Number} interval The interval used when polling for messages.
1404
  */
1405
  var pub;
1406
  var me = this, isHost, _timer, pollInterval, _lastMsg, _msgNr, _listenerWindow, _callerWindow;
1407
  var useParent, _remoteOrigin;
1408
  function _sendMessage(message){
1409
  if (!_callerWindow) {
1410
  return;
1411
  }
1412
  var url = config.remote + "#" + (_msgNr++) + "_" + message;
1413
  ((isHost || !useParent) ? _callerWindow.contentWindow : _callerWindow).location = url;
1414
  }
1415
  function _handleHash(hash){
1416
  _lastMsg = hash;
1417
  pub.up.incoming(_lastMsg.substring(_lastMsg.indexOf("_") + 1), _remoteOrigin);
1418
  }
1419
  /**
1420
  * Checks location.hash for a new message and relays this to the receiver.
1421
  * @private
1422
  */
1423
  function _pollHash(){
1424
  if (!_listenerWindow) {
1425
  return;
1426
  }
1427
  var href = _listenerWindow.location.href, hash = "", indexOf = href.indexOf("#");
1428
  if (indexOf != -1) {
1429
  hash = href.substring(indexOf);
1430
  }
1431
  if (hash && hash != _lastMsg) {
1432
  _handleHash(hash);
1433
  }
1434
  }
1435
  function _attachListeners(){
1436
  _timer = setInterval(_pollHash, pollInterval);
1437
  }
1438
  return (pub = {
1439
  outgoing: function(message, domain){
1440
  _sendMessage(message);
1441
  },
1442
  destroy: function(){
1443
  window.clearInterval(_timer);
1444
  if (isHost || !useParent) {
1445
  _callerWindow.parentNode.removeChild(_callerWindow);
1446
  }
1447
  _callerWindow = null;
1448
  },
1449
  onDOMReady: function(){
1450
  isHost = config.isHost;
1451
  pollInterval = config.interval;
1452
  _lastMsg = "#" + config.channel;
1453
  _msgNr = 0;
1454
  useParent = config.useParent;
1455
  _remoteOrigin = getLocation(config.remote);
1456
  if (isHost) {
1457
  apply(config.props, {
1458
  src: config.remote,
1459
  name: IFRAME_PREFIX + config.channel + "_provider"
1460
  });
1461
  if (useParent) {
1462
  config.onLoad = function(){
1463
  _listenerWindow = window;
1464
  _attachListeners();
1465
  pub.up.callback(true);
1466
  };
1467
  }
1468
  else {
1469
  var tries = 0, max = config.delay / 50;
1470
  (function getRef(){
1471
  if (++tries > max) {
1472
  throw new Error("Unable to reference listenerwindow");
1473
  }
1474
  try {
1475
  _listenerWindow = _callerWindow.contentWindow.frames[IFRAME_PREFIX + config.channel + "_consumer"];
1476
  }
1477
  catch (ex) {
1478
  }
1479
  if (_listenerWindow) {
1480
  _attachListeners();
1481
  pub.up.callback(true);
1482
  }
1483
  else {
1484
  setTimeout(getRef, 50);
1485
  }
1486
  }());
1487
  }
1488
  _callerWindow = createFrame(config);
1489
  }
1490
  else {
1491
  _listenerWindow = window;
1492
  _attachListeners();
1493
  if (useParent) {
1494
  _callerWindow = parent;
1495
  pub.up.callback(true);
1496
  }
1497
  else {
1498
  apply(config, {
1499
  props: {
1500
  src: config.remote + "#" + config.channel + new Date(),
1501
  name: IFRAME_PREFIX + config.channel + "_consumer"
1502
  },
1503
  onLoad: function(){
1504
  pub.up.callback(true);
1505
  }
1506
  });
1507
  _callerWindow = createFrame(config);
1508
  }
1509
  }
1510
  },
1511
  init: function(){
1512
  whenReady(pub.onDOMReady, pub);
1513
  }
1514
  });
1515
  * @class easyXDM.stack.ReliableBehavior
1516
  * This is a behavior that tries to make the underlying transport reliable by using acknowledgements.
1517
  * @namespace easyXDM.stack
1518
  * @constructor
1519
  * @param {Object} config The behaviors configuration.
1520
  */
1521
  var pub, // the public interface
1522
  callback; // the callback to execute when we have a confirmed success/failure
1523
  var idOut = 0, idIn = 0, currentMessage = "";
1524
  return (pub = {
1525
  incoming: function(message, origin){
1526
  var indexOf = message.indexOf("_"), ack = message.substring(0, indexOf).split(",");
1527
  message = message.substring(indexOf + 1);
1528
  if (ack[0] == idOut) {
1529
  currentMessage = "";
1530
  if (callback) {
1531
  callback(true);
1532
  }
1533
  }
1534
  if (message.length > 0) {
1535
  pub.down.outgoing(ack[1] + "," + idOut + "_" + currentMessage, origin);
1536
  if (idIn != ack[1]) {
1537
  idIn = ack[1];
1538
  pub.up.incoming(message, origin);
1539
  }
1540
  }
1541
  },
1542
  outgoing: function(message, origin, fn){
1543
  currentMessage = message;
1544
  callback = fn;
1545
  pub.down.outgoing(idIn + "," + (++idOut) + "_" + message, origin);
1546
  }
1547
  });
1548
  * @class easyXDM.stack.QueueBehavior
1549
  * This is a behavior that enables queueing of messages. <br/>
1550
  * It will buffer incoming messages and dispach these as fast as the underlying transport allows.
1551
  * This will also fragment/defragment messages so that the outgoing message is never bigger than the
1552
  * set length.
1553
  * @namespace easyXDM.stack
1554
  * @constructor
1555
  * @param {Object} config The behaviors configuration. Optional.
1556
  * @cfg {Number} maxLength The maximum length of each outgoing message. Set this to enable fragmentation.
1557
  */
1558
  var pub, queue = [], waiting = true, incoming = "", destroying, maxLength = 0, lazy = false, doFragment = false;
1559
  function dispatch(){
1560
  if (config.remove && queue.length === 0) {
1561
  removeFromStack(pub);
1562
  return;
1563
  }
1564
  if (waiting || queue.length === 0 || destroying) {
1565
  return;
1566
  }
1567
  waiting = true;
1568
  var message = queue.shift();
1569
  pub.down.outgoing(message.data, message.origin, function(success){
1570
  waiting = false;
1571
  if (message.callback) {
1572
  setTimeout(function(){
1573
  message.callback(success);
1574
  }, 0);
1575
  }
1576
  dispatch();
1577
  });
1578
  }
1579
  return (pub = {
1580
  init: function(){
1581
  if (undef(config)) {
1582
  config = {};
1583
  }
1584
  if (config.maxLength) {
1585
  maxLength = config.maxLength;
1586
  doFragment = true;
1587
  }
1588
  if (config.lazy) {
1589
  lazy = true;
1590
  }
1591
  else {
1592
  pub.down.init();
1593
  }
1594
  },
1595
  callback: function(success){
1596
  waiting = false;
1597
  var up = pub.up; // in case dispatch calls removeFromStack
1598
  dispatch();
1599
  up.callback(success);
1600
  },
1601
  incoming: function(message, origin){
1602
  if (doFragment) {
1603
  var indexOf = message.indexOf("_"), seq = parseInt(message.substring(0, indexOf), 10);
1604
  incoming += message.substring(indexOf + 1);
1605
  if (seq === 0) {
1606
  if (config.encode) {
1607
  incoming = decodeURIComponent(incoming);
1608
  }
1609
  pub.up.incoming(incoming, origin);
1610
  incoming = "";
1611
  }
1612
  }
1613
  else {
1614
  pub.up.incoming(message, origin);
1615
  }
1616
  },
1617
  outgoing: function(message, origin, fn){
1618
  if (config.encode) {
1619
  message = encodeURIComponent(message);
1620
  }
1621
  var fragments = [], fragment;
1622
  if (doFragment) {
1623
  // fragment into chunks
1624
  while (message.length !== 0) {
1625
  fragment = message.substring(0, maxLength);
1626
  message = message.substring(fragment.length);
1627
  fragments.push(fragment);
1628
  }
1629
  // enqueue the chunks
1630
  while ((fragment = fragments.shift())) {
1631
  queue.push({
1632
  data: fragments.length + "_" + fragment,
1633
  origin: origin,
1634
  callback: fragments.length === 0 ? fn : null
1635
  });
1636
  }
1637
  }
1638
  else {
1639
  queue.push({
1640
  data: message,
1641
  origin: origin,
1642
  callback: fn
1643
  });
1644
  }
1645
  if (lazy) {
1646
  pub.down.init();
1647
  }
1648
  else {
1649
  dispatch();
1650
  }
1651
  },
1652
  destroy: function(){
1653
  destroying = true;
1654
  pub.down.destroy();
1655
  }
1656
  });
1657
  * @class easyXDM.stack.VerifyBehavior
1658
  * This behavior will verify that communication with the remote end is possible, and will also sign all outgoing,
1659
  * and verify all incoming messages. This removes the risk of someone hijacking the iframe to send malicious messages.
1660
  * @namespace easyXDM.stack
1661
  * @constructor
1662
  * @param {Object} config The behaviors configuration.
1663
  * @cfg {Boolean} initiate If the verification should be initiated from this end.
1664
  */
1665
  var pub, mySecret, theirSecret, verified = false;
1666
  function startVerification(){
1667
  mySecret = Math.random().toString(16).substring(2);
1668
  pub.down.outgoing(mySecret);
1669
  }
1670
  return (pub = {
1671
  incoming: function(message, origin){
1672
  var indexOf = message.indexOf("_");
1673
  if (indexOf === -1) {
1674
  if (message === mySecret) {
1675
  pub.up.callback(true);
1676
  }
1677
  else if (!theirSecret) {
1678
  theirSecret = message;
1679
  if (!config.initiate) {
1680
  startVerification();
1681
  }
1682
  pub.down.outgoing(message);
1683
  }
1684
  }
1685
  else {
1686
  if (message.substring(0, indexOf) === theirSecret) {
1687
  pub.up.incoming(message.substring(indexOf + 1), origin);
1688
  }
1689
  }
1690
  },
1691
  outgoing: function(message, origin, fn){
1692
  pub.down.outgoing(mySecret + "_" + message, origin, fn);
1693
  },
1694
  callback: function(success){
1695
  if (config.initiate) {
1696
  startVerification();
1697
  }
1698
  }
1699
  });
1700
  * @class easyXDM.stack.RpcBehavior
1701
  * This uses JSON-RPC 2.0 to expose local methods and to invoke remote methods and have responses returned over the the string based transport stack.<br/>
1702
  * Exposed methods can return values synchronous, asyncronous, or bet set up to not return anything.
1703
  * @namespace easyXDM.stack
1704
  * @constructor
1705
  * @param {Object} proxy The object to apply the methods to.
1706
  * @param {Object} config The definition of the local and remote interface to implement.
1707
  * @cfg {Object} local The local interface to expose.
1708
  * @cfg {Object} remote The remote methods to expose through the proxy.
1709
  * @cfg {Object} serializer The serializer to use for serializing and deserializing the JSON. Should be compatible with the HTML5 JSON object. Optional, will default to JSON.
1710
  */
1711
  var pub, serializer = config.serializer || getJSON();
1712
  var _callbackCounter = 0, _callbacks = {};
1713
  /**
1714
  * Serializes and sends the message
1715
  * @private
1716
  * @param {Object} data The JSON-RPC message to be sent. The jsonrpc property will be added.
1717
  */
1718
  function _send(data){
1719
  data.jsonrpc = "2.0";
1720
  pub.down.outgoing(serializer.stringify(data));
1721
  }
1722
  /**
1723
  * Creates a method that implements the given definition
1724
  * @private
1725
  * @param {Object} The method configuration
1726
  * @param {String} method The name of the method
1727
  * @return {Function} A stub capable of proxying the requested method call
1728
  */
1729
  function _createMethod(definition, method){
1730
  var slice = Array.prototype.slice;
1731
  return function(){
1732
  var l = arguments.length, callback, message = {
1733
  method: method
1734
  };
1735
  if (l > 0 && typeof arguments[l - 1] === "function") {
1736
  //with callback, procedure
1737
  if (l > 1 && typeof arguments[l - 2] === "function") {
1738
  // two callbacks, success and error
1739
  callback = {
1740
  success: arguments[l - 2],
1741
  error: arguments[l - 1]
1742
  };
1743
  message.params = slice.call(arguments, 0, l - 2);
1744
  }
1745
  else {
1746
  // single callback, success
1747
  callback = {
1748
  success: arguments[l - 1]
1749
  };
1750
  message.params = slice.call(arguments, 0, l - 1);
1751
  }
1752
  _callbacks["" + (++_callbackCounter)] = callback;
1753
  message.id = _callbackCounter;
1754
  }
1755
  else {
1756
  // no callbacks, a notification
1757
  message.params = slice.call(arguments, 0);
1758
  }
1759
  if (definition.namedParams && message.params.length === 1) {
1760
  message.params = message.params[0];
1761
  }
1762
  // Send the method request
1763
  _send(message);
1764
  };
1765
  }
1766
  /**
1767
  * Executes the exposed method
1768
  * @private
1769
  * @param {String} method The name of the method
1770
  * @param {Number} id The callback id to use
1771
  * @param {Function} method The exposed implementation
1772
  * @param {Array} params The parameters supplied by the remote end
1773
  */
1774
  function _executeMethod(method, id, fn, params){
1775
  if (!fn) {
1776
  if (id) {
1777
  _send({
1778
  id: id,
1779
  error: {
1780
  code: -32601,
1781
  message: "Procedure not found."
1782
  }
1783
  });
1784
  }
1785
  return;
1786
  }
1787
  var success, error;
1788
  if (id) {
1789
  success = function(result){
1790
  success = emptyFn;
1791
  _send({
1792
  id: id,
1793
  result: result
1794
  });
1795
  };
1796
  error = function(message, data){
1797
  error = emptyFn;
1798
  var msg = {
1799
  id: id,
1800
  error: {
1801
  code: -32099,
1802
  message: message
1803
  }
1804
  };
1805
  if (data) {
1806
  msg.error.data = data;
1807
  }
1808
  _send(msg);
1809
  };
1810
  }
1811
  else {
1812
  success = error = emptyFn;
1813
  }
1814
  // Call local method
1815
  if (!isArray(params)) {
1816
  params = [params];
1817
  }
1818
  try {
1819
  var result = fn.method.apply(fn.scope, params.concat([success, error]));
1820
  if (!undef(result)) {
1821
  success(result);
1822
  }
1823
  }
1824
  catch (ex1) {
1825
  error(ex1.message);
1826
  }
1827
  }
1828
  return (pub = {
1829
  incoming: function(message, origin){
1830
  var data = serializer.parse(message);
1831
  if (data.method) {
1832
  // A method call from the remote end
1833
  if (config.handle) {
1834
  config.handle(data, _send);
1835
  }
1836
  else {
1837
  _executeMethod(data.method, data.id, config.local[data.method], data.params);
1838
  }
1839
  }
1840
  else {
1841
  // A method response from the other end
1842
  var callback = _callbacks[data.id];
1843
  if (data.error) {
1844
  if (callback.error) {
1845
  callback.error(data.error);
1846
  }
1847
  }
1848
  else if (callback.success) {
1849
  callback.success(data.result);
1850
  }
1851
  delete _callbacks[data.id];
1852
  }
1853
  },
1854
  init: function(){
1855
  if (config.remote) {
1856
  // Implement the remote sides exposed methods
1857
  for (var method in config.remote) {
1858
  if (config.remote.hasOwnProperty(method)) {
1859
  proxy[method] = _createMethod(config.remote[method], method);
1860
  }
1861
  }
1862
  }
1863
  pub.down.init();
1864
  },
1865
  destroy: function(){
1866
  for (var method in config.remote) {
1867
  if (config.remote.hasOwnProperty(method) && proxy.hasOwnProperty(method)) {
1868
  delete proxy[method];
1869
  }
1870
  }
1871
  pub.down.destroy();
1872
  }
1873
  });
1
+ (function (window, document, location, setTimeout, decodeURIComponent, encodeURIComponent) {
2
  var t = typeof object[property];
3
  return t == 'function' ||
4
  (!!(t == 'object' && object[property])) ||
5
  t == 'unknown';
6
  return !!(typeof(object[property]) == 'object' && object[property]);
7
  return Object.prototype.toString.call(o) === '[object Array]';
8
  var name = "Shockwave Flash", mimeType = "application/x-shockwave-flash";
9
  if (!undef(navigator.plugins) && typeof navigator.plugins[name] == "object") {
10
  // adapted from the swfobject code
11
  var description = navigator.plugins[name].description;
12
  if (description && !undef(navigator.mimeTypes) && navigator.mimeTypes[mimeType] && navigator.mimeTypes[mimeType].enabledPlugin) {
13
  flashVersion = description.match(/\d+/g);
14
  }
15
  }
16
  if (!flashVersion) {
17
  var flash;
18
  try {
19
  flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
20
  flashVersion = Array.prototype.slice.call(flash.GetVariable("$version").match(/(\d+),(\d+),(\d+),(\d+)/), 1);
21
  flash = null;
22
  }
23
  catch (notSupportedException) {
24
  }
25
  }
26
  if (!flashVersion) {
27
  return false;
28
  }
29
  var major = parseInt(flashVersion[0], 10), minor = parseInt(flashVersion[1], 10);
30
  HAS_FLASH_THROTTLED_BUG = major > 9 && minor > 0;
31
  return true;
32
  * Cross Browser implementation for adding and removing event listeners.
33
  */
34
  on = function(target, type, listener){
35
  target.addEventListener(type, listener, false);
36
  };
37
  un = function(target, type, listener){
38
  target.removeEventListener(type, listener, false);
39
  };
40
  on = function(object, sEvent, fpNotify){
41
  object.attachEvent("on" + sEvent, fpNotify);
42
  };
43
  un = function(object, sEvent, fpNotify){
44
  object.detachEvent("on" + sEvent, fpNotify);
45
  };
46
  throw new Error("Browser not supported");
47
  * Cross Browser implementation of DOMContentLoaded.
48
  */
49
  // If browser is WebKit-powered, check for both 'loaded' (legacy browsers) and
50
  // 'interactive' (HTML5 specs, recent WebKit builds) states.
51
  // https://bugs.webkit.org/show_bug.cgi?id=45119
52
  readyState = document.readyState;
53
  domIsReady = readyState == "complete" || (~ navigator.userAgent.indexOf('AppleWebKit/') && (readyState == "loaded" || readyState == "interactive"));
54
  // If readyState is not supported in the browser, then in order to be able to fire whenReady functions apropriately
55
  // when added dynamically _after_ DOM load, we have to deduce wether the DOM is ready or not.
56
  // We only need a body to add elements to, so the existence of document.body is enough for us.
57
  domIsReady = !!document.body;
58
  if (domIsReady) {
59
  return;
60
  }
61
  domIsReady = true;
62
  for (var i = 0; i < domReadyQueue.length; i++) {
63
  domReadyQueue[i]();
64
  }
65
  domReadyQueue.length = 0;
66
  if (isHostMethod(window, "addEventListener")) {
67
  on(document, "DOMContentLoaded", dom_onReady);
68
  }
69
  else {
70
  on(document, "readystatechange", function(){
71
  if (document.readyState == "complete") {
72
  dom_onReady();
73
  }
74
  });
75
  if (document.documentElement.doScroll && window === top) {
76
  var doScrollCheck = function(){
77
  if (domIsReady) {
78
  return;
79
  }
80
  // http://javascript.nwbox.com/IEContentLoaded/
81
  try {
82
  document.documentElement.doScroll("left");
83
  }
84
  catch (e) {
85
  setTimeout(doScrollCheck, 1);
86
  return;
87
  }
88
  dom_onReady();
89
  };
90
  doScrollCheck();
91
  }
92
  }
93
  // A fallback to window.onload, that will always work
94
  on(window, "load", dom_onReady);
95
  * This will add a function to the queue of functions to be run once the DOM reaches a ready state.
96
  * If functions are added after this event then they will be executed immediately.
97
  * @param {function} fn The function to add
98
  * @param {Object} scope An optional scope for the function to be called with.
99
  */
100
  if (domIsReady) {
101
  fn.call(scope);
102
  return;
103
  }
104
  domReadyQueue.push(function(){
105
  fn.call(scope);
106
  });
107
  * Returns an instance of easyXDM from the parent window with
108
  * respect to the namespace.
109
  *
110
  * @return An instance of easyXDM (in the parent window)
111
  */
112
  var obj = parent;
113
  if (namespace !== "") {
114
  for (var i = 0, ii = namespace.split("."); i < ii.length; i++) {
115
  obj = obj[ii[i]];
116
  }
117
  }
118
  return obj.easyXDM;
119
  * Removes easyXDM variable from the global scope. It also returns control
120
  * of the easyXDM variable to whatever code used it before.
121
  *
122
  * @param {String} ns A string representation of an object that will hold
123
  * an instance of easyXDM.
124
  * @return An instance of easyXDM
125
  */
126
  window.easyXDM = _easyXDM;
127
  namespace = ns;
128
  if (namespace) {
129
  IFRAME_PREFIX = "easyXDM_" + namespace.replace(".", "_") + "_";
130
  }
131
  return easyXDM;
132
  * Methods for working with URLs
133
  */
134
  * Get the domain name from a url.
135
  * @param {String} url The url to extract the domain from.
136
  * @return The domain part of the url.
137
  * @type {String}
138
  */
139
  return url.match(reURI)[3];
140
  * Get the port for a given URL, or "" if none
141
  * @param {String} url The url to extract the port from.
142
  * @return The port part of the url.
143
  * @type {String}
144
  */
145
  return url.match(reURI)[4] || "";
146
  * Returns a string containing the schema, domain and if present the port
147
  * @param {String} url The url to extract the location from
148
  * @return {String} The location part of the url
149
  */
150
  var m = url.toLowerCase().match(reURI);
151
  var proto = m[2], domain = m[3], port = m[4] || "";
152
  if ((proto == "http:" && port == ":80") || (proto == "https:" && port == ":443")) {
153
  port = "";
154
  }
155
  return proto + "//" + domain + port;
156
  * Resolves a relative url into an absolute one.
157
  * @param {String} url The path to resolve.
158
  * @return {String} The resolved url.
159
  */
160
  // replace all // except the one in proto with /
161
  url = url.replace(reDoubleSlash, "$1/");
162
  // If the url is a valid url we do nothing
163
  if (!url.match(/^(http||https):\/\//)) {
164
  // If this is a relative path
165
  var path = (url.substring(0, 1) === "/") ? "" : location.pathname;
166
  if (path.substring(path.length - 1) !== "/") {
167
  path = path.substring(0, path.lastIndexOf("/") + 1);
168
  }
169
  url = location.protocol + "//" + location.host + path + url;
170
  }
171
  // reduce all 'xyz/../' to just ''
172
  while (reParent.test(url)) {
173
  url = url.replace(reParent, "");
174
  }
175
  return url;
176
  * Appends the parameters to the given url.<br/>
177
  * The base url can contain existing query parameters.
178
  * @param {String} url The base url.
179
  * @param {Object} parameters The parameters to add.
180
  * @return {String} A new valid url with the parameters appended.
181
  */
182
  var hash = "", indexOf = url.indexOf("#");
183
  if (indexOf !== -1) {
184
  hash = url.substring(indexOf);
185
  url = url.substring(0, indexOf);
186
  }
187
  var q = [];
188
  for (var key in parameters) {
189
  if (parameters.hasOwnProperty(key)) {
190
  q.push(key + "=" + encodeURIComponent(parameters[key]));
191
  }
192
  }
193
  return url + (useHash ? "#" : (url.indexOf("?") == -1 ? "?" : "&")) + q.join("&") + hash;
194
  input = input.substring(1).split("&");
195
  var data = {}, pair, i = input.length;
196
  while (i--) {
197
  pair = input[i].split("=");
198
  data[pair[0]] = decodeURIComponent(pair[1]);
199
  }
200
  return data;
201
  * Helper methods
202
  */
203
  * Helper for checking if a variable/property is undefined
204
  * @param {Object} v The variable to test
205
  * @return {Boolean} True if the passed variable is undefined
206
  */
207
  return typeof v === "undefined";
208
  * A safe implementation of HTML5 JSON. Feature testing is used to make sure the implementation works.
209
  * @return {JSON} A valid JSON conforming object, or null if not found.
210
  */
211
  var cached = {};
212
  var obj = {
213
  a: [1, 2, 3]
214
  }, json = "{\"a\":[1,2,3]}";
215
  if (typeof JSON != "undefined" && typeof JSON.stringify === "function" && JSON.stringify(obj).replace((/\s/g), "") === json) {
216
  // this is a working JSON instance
217
  return JSON;
218
  }
219
  if (Object.toJSON) {
220
  if (Object.toJSON(obj).replace((/\s/g), "") === json) {
221
  // this is a working stringify method
222
  cached.stringify = Object.toJSON;
223
  }
224
  }
225
  if (typeof String.prototype.evalJSON === "function") {
226
  obj = json.evalJSON();
227
  if (obj.a && obj.a.length === 3 && obj.a[2] === 3) {
228
  // this is a working parse method
229
  cached.parse = function(str){
230
  return str.evalJSON();
231
  };
232
  }
233
  }
234
  if (cached.stringify && cached.parse) {
235
  // Only memoize the result if we have valid instance
236
  getJSON = function(){
237
  return cached;
238
  };
239
  return cached;
240
  }
241
  return null;
242
  * Applies properties from the source object to the target object.<br/>
243
  * @param {Object} target The target of the properties.
244
  * @param {Object} source The source of the properties.
245
  * @param {Boolean} noOverwrite Set to True to only set non-existing properties.
246
  */
247
  var member;
248
  for (var prop in source) {
249
  if (source.hasOwnProperty(prop)) {
250
  if (prop in destination) {
251
  member = source[prop];
252
  if (typeof member === "object") {
253
  apply(destination[prop], member, noOverwrite);
254
  }
255
  else if (!noOverwrite) {
256
  destination[prop] = source[prop];
257
  }
258
  }
259
  else {
260
  destination[prop] = source[prop];
261
  }
262
  }
263
  }
264
  return destination;
265
  var form = document.body.appendChild(document.createElement("form")), input = form.appendChild(document.createElement("input"));
266
  input.name = IFRAME_PREFIX + "TEST" + channelId; // append channelId in order to avoid caching issues
267
  HAS_NAME_PROPERTY_BUG = input !== form.elements[input.name];
268
  document.body.removeChild(form);
269
  * Creates a frame and appends it to the DOM.
270
  * @param config {object} This object can have the following properties
271
  * <ul>
272
  * <li> {object} prop The properties that should be set on the frame. This should include the 'src' property.</li>
273
  * <li> {object} attr The attributes that should be set on the frame.</li>
274
  * <li> {DOMElement} container Its parent element (Optional).</li>
275
  * <li> {function} onLoad A method that should be called with the frames contentWindow as argument when the frame is fully loaded. (Optional)</li>
276
  * </ul>
277
  * @return The frames DOMElement
278
  * @type DOMElement
279
  */
280
  if (undef(HAS_NAME_PROPERTY_BUG)) {
281
  testForNamePropertyBug();
282
  }
283
  var frame;
284
  // This is to work around the problems in IE6/7 with setting the name property.
285
  // Internally this is set as 'submitName' instead when using 'iframe.name = ...'
286
  // This is not required by easyXDM itself, but is to facilitate other use cases
287
  if (HAS_NAME_PROPERTY_BUG) {
288
  frame = document.createElement("<iframe name=\"" + config.props.name + "\"/>");
289
  }
290
  else {
291
  frame = document.createElement("IFRAME");
292
  frame.name = config.props.name;
293
  }
294
  frame.id = frame.name = config.props.name;
295
  delete config.props.name;
296
  if (typeof config.container == "string") {
297
  config.container = document.getElementById(config.container);
298
  }
299
  if (!config.container) {
300
  // This needs to be hidden like this, simply setting display:none and the like will cause failures in some browsers.
301
  apply(frame.style, {
302
  position: "absolute",
303
  top: "-2000px",
304
  // Avoid potential horizontal scrollbar
305
  left: "0px"
306
  });
307
  config.container = document.body;
308
  }
309
  // HACK: IE cannot have the src attribute set when the frame is appended
310
  // into the container, so we set it to "javascript:false" as a
311
  // placeholder for now. If we left the src undefined, it would
312
  // instead default to "about:blank", which causes SSL mixed-content
313
  // warnings in IE6 when on an SSL parent page.
314
  var src = config.props.src;
315
  config.props.src = "javascript:false";
316
  // transfer properties to the frame
317
  apply(frame, config.props);
318
  frame.border = frame.frameBorder = 0;
319
  frame.allowTransparency = true;
320
  config.container.appendChild(frame);
321
  if (config.onLoad) {
322
  on(frame, "load", config.onLoad);
323
  }
324
  // set the frame URL to the proper value (we previously set it to
325
  // "javascript:false" to work around the IE issue mentioned above)
326
  if(config.usePost) {
327
  var form = config.container.appendChild(document.createElement('form')), input;
328
  form.target = frame.name;
329
  form.action = src;
330
  form.method = 'POST';
331
  if (typeof(config.usePost) === 'object') {
332
  for (var i in config.usePost) {
333
  if (config.usePost.hasOwnProperty(i)) {
334
  if (HAS_NAME_PROPERTY_BUG) {
335
  input = document.createElement('<input name="' + i + '"/>');
336
  } else {
337
  input = document.createElement("INPUT");
338
  input.name = i;
339
  }
340
  input.value = config.usePost[i];
341
  form.appendChild(input);
342
  }
343
  }
344
  }
345
  form.submit();
346
  form.parentNode.removeChild(form);
347
  } else {
348
  frame.src = src;
349
  }
350
  config.props.src = src;
351
  return frame;
352
  * Check whether a domain is allowed using an Access Control List.
353
  * The ACL can contain * and ? as wildcards, or can be regular expressions.
354
  * If regular expressions they need to begin with ^ and end with $.
355
  * @param {Array/String} acl The list of allowed domains
356
  * @param {String} domain The domain to test.
357
  * @return {Boolean} True if the domain is allowed, false if not.
358
  */
359
  // normalize into an array
360
  if (typeof acl == "string") {
361
  acl = [acl];
362
  }
363
  var re, i = acl.length;
364
  while (i--) {
365
  re = acl[i];
366
  re = new RegExp(re.substr(0, 1) == "^" ? re : ("^" + re.replace(/(\*)/g, ".$1").replace(/\?/g, ".") + "$"));
367
  if (re.test(domain)) {
368
  return true;
369
  }
370
  }
371
  return false;
372
  * Functions related to stacks
373
  */
374
  * Prepares an array of stack-elements suitable for the current configuration
375
  * @param {Object} config The Transports configuration. See easyXDM.Socket for more.
376
  * @return {Array} An array of stack-elements with the TransportElement at index 0.
377
  */
378
  var protocol = config.protocol, stackEls;
379
  config.isHost = config.isHost || undef(query.xdm_p);
380
  useHash = config.hash || false;
381
  if (!config.props) {
382
  config.props = {};
383
  }
384
  if (!config.isHost) {
385
  config.channel = query.xdm_c.replace(/["'<>\\]/g, "");
386
  config.secret = query.xdm_s;
387
  config.remote = query.xdm_e.replace(/["'<>\\]/g, "");
388
  ;
389
  protocol = query.xdm_p;
390
  if (config.acl && !checkAcl(config.acl, config.remote)) {
391
  throw new Error("Access denied for " + config.remote);
392
  }
393
  }
394
  else {
395
  config.remote = resolveUrl(config.remote);
396
  config.channel = config.channel || "default" + channelId++;
397
  config.secret = Math.random().toString(16).substring(2);
398
  if (undef(protocol)) {
399
  if (getLocation(location.href) == getLocation(config.remote)) {
400
  /*
401
  * Both documents has the same origin, lets use direct access.
402
  */
403
  protocol = "4";
404
  }
405
  else if (isHostMethod(window, "postMessage") || isHostMethod(document, "postMessage")) {
406
  /*
407
  * This is supported in IE8+, Firefox 3+, Opera 9+, Chrome 2+ and Safari 4+
408
  */
409
  protocol = "1";
410
  }
411
  else if (config.swf && isHostMethod(window, "ActiveXObject") && hasFlash()) {
412
  /*
413
  * The Flash transport superseedes the NixTransport as the NixTransport has been blocked by MS
414
  */
415
  protocol = "6";
416
  }
417
  else if (navigator.product === "Gecko" && "frameElement" in window && navigator.userAgent.indexOf('WebKit') == -1) {
418
  /*
419
  * This is supported in Gecko (Firefox 1+)
420
  */
421
  protocol = "5";
422
  }
423
  else if (config.remoteHelper) {
424
  /*
425
  * This is supported in all browsers that retains the value of window.name when
426
  * navigating from one domain to another, and where parent.frames[foo] can be used
427
  * to get access to a frame from the same domain
428
  */
429
  protocol = "2";
430
  }
431
  else {
432
  /*
433
  * This is supported in all browsers where [window].location is writable for all
434
  * The resize event will be used if resize is supported and the iframe is not put
435
  * into a container, else polling will be used.
436
  */
437
  protocol = "0";
438
  }
439
  }
440
  }
441
  config.protocol = protocol; // for conditional branching
442
  switch (protocol) {
443
  case "0":// 0 = HashTransport
444
  apply(config, {
445
  interval: 100,
446
  delay: 2000,
447
  useResize: true,
448
  useParent: false,
449
  usePolling: false
450
  }, true);
451
  if (config.isHost) {
452
  if (!config.local) {
453
  // If no local is set then we need to find an image hosted on the current domain
454
  var domain = location.protocol + "//" + location.host, images = document.body.getElementsByTagName("img"), image;
455
  var i = images.length;
456
  while (i--) {
457
  image = images[i];
458
  if (image.src.substring(0, domain.length) === domain) {
459
  config.local = image.src;
460
  break;
461
  }
462
  }
463
  if (!config.local) {
464
  // If no local was set, and we are unable to find a suitable file, then we resort to using the current window
465
  config.local = window;
466
  }
467
  }
468
  var parameters = {
469
  xdm_c: config.channel,
470
  xdm_p: 0
471
  };
472
  if (config.local === window) {
473
  // We are using the current window to listen to
474
  config.usePolling = true;
475
  config.useParent = true;
476
  config.local = location.protocol + "//" + location.host + location.pathname + location.search;
477
  parameters.xdm_e = config.local;
478
  parameters.xdm_pa = 1; // use parent
479
  }
480
  else {
481
  parameters.xdm_e = resolveUrl(config.local);
482
  }
483
  if (config.container) {
484
  config.useResize = false;
485
  parameters.xdm_po = 1; // use polling
486
  }
487
  config.remote = appendQueryParameters(config.remote, parameters);
488
  }
489
  else {
490
  apply(config, {
491
  channel: query.xdm_c,
492
  remote: query.xdm_e,
493
  useParent: !undef(query.xdm_pa),
494
  usePolling: !undef(query.xdm_po),
495
  useResize: config.useParent ? false : config.useResize
496
  });
497
  }
498
  stackEls = [new easyXDM.stack.HashTransport(config), new easyXDM.stack.ReliableBehavior({}), new easyXDM.stack.QueueBehavior({
499
  encode: true,
500
  maxLength: 4000 - config.remote.length
501
  }), new easyXDM.stack.VerifyBehavior({
502
  initiate: config.isHost
503
  })];
504
  break;
505
  case "1":
506
  stackEls = [new easyXDM.stack.PostMessageTransport(config)];
507
  break;
508
  case "2":
509
  if (config.isHost) {
510
  config.remoteHelper = resolveUrl(config.remoteHelper);
511
  }
512
  stackEls = [new easyXDM.stack.NameTransport(config), new easyXDM.stack.QueueBehavior(), new easyXDM.stack.VerifyBehavior({
513
  initiate: config.isHost
514
  })];
515
  break;
516
  case "3":
517
  stackEls = [new easyXDM.stack.NixTransport(config)];
518
  break;
519
  case "4":
520
  stackEls = [new easyXDM.stack.SameOriginTransport(config)];
521
  break;
522
  case "5":
523
  stackEls = [new easyXDM.stack.FrameElementTransport(config)];
524
  break;
525
  case "6":
526
  if (!flashVersion) {
527
  hasFlash();
528
  }
529
  stackEls = [new easyXDM.stack.FlashTransport(config)];
530
  break;
531
  }
532
  // this behavior is responsible for buffering outgoing messages, and for performing lazy initialization
533
  stackEls.push(new easyXDM.stack.QueueBehavior({
534
  lazy: config.lazy,
535
  remove: true
536
  }));
537
  return stackEls;
538
  * Chains all the separate stack elements into a single usable stack.<br/>
539
  * If an element is missing a necessary method then it will have a pass-through method applied.
540
  * @param {Array} stackElements An array of stack elements to be linked.
541
  * @return {easyXDM.stack.StackElement} The last element in the chain.
542
  */
543
  var stackEl, defaults = {
544
  incoming: function(message, origin){
545
  this.up.incoming(message, origin);
546
  },
547
  outgoing: function(message, recipient){
548
  this.down.outgoing(message, recipient);
549
  },
550
  callback: function(success){
551
  this.up.callback(success);
552
  },
553
  init: function(){
554
  this.down.init();
555
  },
556
  destroy: function(){
557
  this.down.destroy();
558
  }
559
  };
560
  for (var i = 0, len = stackElements.length; i < len; i++) {
561
  stackEl = stackElements[i];
562
  apply(stackEl, defaults, true);
563
  if (i !== 0) {
564
  stackEl.down = stackElements[i - 1];
565
  }
566
  if (i !== len - 1) {
567
  stackEl.up = stackElements[i + 1];
568
  }
569
  }
570
  return stackEl;
571
  * This will remove a stackelement from its stack while leaving the stack functional.
572
  * @param {Object} element The elment to remove from the stack.
573
  */
574
  element.up.down = element.down;
575
  element.down.up = element.up;
576
  element.up = element.down = null;
577
  * Export the main object and any other methods applicable
578
  */
579
  * @class easyXDM
580
  * A javascript library providing cross-browser, cross-domain messaging/RPC.
581
  * @version 2.4.19.0
582
  * @singleton
583
  */
584
  /**
585
  * The version of the library
586
  * @type {string}
587
  */
588
  version: "2.4.19.0",
589
  /**
590
  * This is a map containing all the query parameters passed to the document.
591
  * All the values has been decoded using decodeURIComponent.
592
  * @type {object}
593
  */
594
  query: query,
595
  /**
596
  * @private
597
  */
598
  stack: {},
599
  /**
600
  * Applies properties from the source object to the target object.<br/>
601
  * @param {object} target The target of the properties.
602
  * @param {object} source The source of the properties.
603
  * @param {boolean} noOverwrite Set to True to only set non-existing properties.
604
  */
605
  apply: apply,
606
  /**
607
  * A safe implementation of HTML5 JSON. Feature testing is used to make sure the implementation works.
608
  * @return {JSON} A valid JSON conforming object, or null if not found.
609
  */
610
  getJSONObject: getJSON,
611
  /**
612
  * This will add a function to the queue of functions to be run once the DOM reaches a ready state.
613
  * If functions are added after this event then they will be executed immediately.
614
  * @param {function} fn The function to add
615
  * @param {object} scope An optional scope for the function to be called with.
616
  */
617
  whenReady: whenReady,
618
  /**
619
  * Removes easyXDM variable from the global scope. It also returns control
620
  * of the easyXDM variable to whatever code used it before.
621
  *
622
  * @param {String} ns A string representation of an object that will hold
623
  * an instance of easyXDM.
624
  * @return An instance of easyXDM
625
  */
626
  noConflict: noConflict
627
  * @class easyXDM.DomHelper
628
  * Contains methods for dealing with the DOM
629
  * @singleton
630
  */
631
  /**
632
  * Provides a consistent interface for adding eventhandlers
633
  * @param {Object} target The target to add the event to
634
  * @param {String} type The name of the event
635
  * @param {Function} listener The listener
636
  */
637
  on: on,
638
  /**
639
  * Provides a consistent interface for removing eventhandlers
640
  * @param {Object} target The target to remove the event from
641
  * @param {String} type The name of the event
642
  * @param {Function} listener The listener
643
  */
644
  un: un,
645
  /**
646
  * Checks for the presence of the JSON object.
647
  * If it is not present it will use the supplied path to load the JSON2 library.
648
  * This should be called in the documents head right after the easyXDM script tag.
649
  * http://json.org/json2.js
650
  * @param {String} path A valid path to json2.js
651
  */
652
  requiresJSON: function(path){
653
  if (!isHostObject(window, "JSON")) {
654
  // we need to encode the < in order to avoid an illegal token error
655
  // when the script is inlined in a document.
656
  document.write('<' + 'script type="text/javascript" src="' + path + '"><' + '/script>');
657
  }
658
  }
659
  // The map containing the stored functions
660
  var _map = {};
661
  /**
662
  * @class easyXDM.Fn
663
  * This contains methods related to function handling, such as storing callbacks.
664
  * @singleton
665
  * @namespace easyXDM
666
  */
667
  easyXDM.Fn = {
668
  /**
669
  * Stores a function using the given name for reference
670
  * @param {String} name The name that the function should be referred by
671
  * @param {Function} fn The function to store
672
  * @namespace easyXDM.fn
673
  */
674
  set: function(name, fn){
675
  _map[name] = fn;
676
  },
677
  /**
678
  * Retrieves the function referred to by the given name
679
  * @param {String} name The name of the function to retrieve
680
  * @param {Boolean} del If the function should be deleted after retrieval
681
  * @return {Function} The stored function
682
  * @namespace easyXDM.fn
683
  */
684
  get: function(name, del){
685
  if (!_map.hasOwnProperty(name)) {
686
  return;
687
  }
688
  var fn = _map[name];
689
  if (del) {
690
  delete _map[name];
691
  }
692
  return fn;
693
  }
694
  };
695
  * @class easyXDM.Socket
696
  * This class creates a transport channel between two domains that is usable for sending and receiving string-based messages.<br/>
697
  * The channel is reliable, supports queueing, and ensures that the message originates from the expected domain.<br/>
698
  * Internally different stacks will be used depending on the browsers features and the available parameters.
699
  * <h2>How to set up</h2>
700
  * Setting up the provider:
701
  * <pre><code>
702
  * var socket = new easyXDM.Socket({
703
  * &nbsp; local: "name.html",
704
  * &nbsp; onReady: function(){
705
  * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the socket
706
  * &nbsp; &nbsp; socket.postMessage("foo-message");
707
  * &nbsp; },
708
  * &nbsp; onMessage: function(message, origin) {
709
  * &nbsp;&nbsp; alert("received " + message + " from " + origin);
710
  * &nbsp; }
711
  * });
712
  * </code></pre>
713
  * Setting up the consumer:
714
  * <pre><code>
715
  * var socket = new easyXDM.Socket({
716
  * &nbsp; remote: "http:&#47;&#47;remotedomain/page.html",
717
  * &nbsp; remoteHelper: "http:&#47;&#47;remotedomain/name.html",
718
  * &nbsp; onReady: function(){
719
  * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the socket
720
  * &nbsp; &nbsp; socket.postMessage("foo-message");
721
  * &nbsp; },
722
  * &nbsp; onMessage: function(message, origin) {
723
  * &nbsp;&nbsp; alert("received " + message + " from " + origin);
724
  * &nbsp; }
725
  * });
726
  * </code></pre>
727
  * If you are unable to upload the <code>name.html</code> file to the consumers domain then remove the <code>remoteHelper</code> property
728
  * and easyXDM will fall back to using the HashTransport instead of the NameTransport when not able to use any of the primary transports.
729
  * @namespace easyXDM
730
  * @constructor
731
  * @cfg {String/Window} local The url to the local name.html document, a local static file, or a reference to the local window.
732
  * @cfg {Boolean} lazy (Consumer only) Set this to true if you want easyXDM to defer creating the transport until really needed.
733
  * @cfg {String} remote (Consumer only) The url to the providers document.
734
  * @cfg {String} remoteHelper (Consumer only) The url to the remote name.html file. This is to support NameTransport as a fallback. Optional.
735
  * @cfg {Number} delay The number of milliseconds easyXDM should try to get a reference to the local window. Optional, defaults to 2000.
736
  * @cfg {Number} interval The interval used when polling for messages. Optional, defaults to 300.
737
  * @cfg {String} channel (Consumer only) The name of the channel to use. Can be used to set consistent iframe names. Must be unique. Optional.
738
  * @cfg {Function} onMessage The method that should handle incoming messages.<br/> This method should accept two arguments, the message as a string, and the origin as a string. Optional.
739
  * @cfg {Function} onReady A method that should be called when the transport is ready. Optional.
740
  * @cfg {DOMElement|String} container (Consumer only) The element, or the id of the element that the primary iframe should be inserted into. If not set then the iframe will be positioned off-screen. Optional.
741
  * @cfg {Array/String} acl (Provider only) Here you can specify which '[protocol]://[domain]' patterns that should be allowed to act as the consumer towards this provider.<br/>
742
  * This can contain the wildcards ? and *. Examples are 'http://example.com', '*.foo.com' and '*dom?.com'. If you want to use reqular expressions then you pattern needs to start with ^ and end with $.
743
  * If none of the patterns match an Error will be thrown.
744
  * @cfg {Object} props (Consumer only) Additional properties that should be applied to the iframe. This can also contain nested objects e.g: <code>{style:{width:"100px", height:"100px"}}</code>.
745
  * Properties such as 'name' and 'src' will be overrided. Optional.
746
  */
747
  // create the stack
748
  var stack = chainStack(prepareTransportStack(config).concat([{
749
  incoming: function(message, origin){
750
  config.onMessage(message, origin);
751
  },
752
  callback: function(success){
753
  if (config.onReady) {
754
  config.onReady(success);
755
  }
756
  }
757
  }])), recipient = getLocation(config.remote);
758
  // set the origin
759
  this.origin = getLocation(config.remote);
760
  /**
761
  * Initiates the destruction of the stack.
762
  */
763
  this.destroy = function(){
764
  stack.destroy();
765
  };
766
  /**
767
  * Posts a message to the remote end of the channel
768
  * @param {String} message The message to send
769
  */
770
  this.postMessage = function(message){
771
  stack.outgoing(message, recipient);
772
  };
773
  stack.init();
774
  * @class easyXDM.Rpc
775
  * Creates a proxy object that can be used to call methods implemented on the remote end of the channel, and also to provide the implementation
776
  * of methods to be called from the remote end.<br/>
777
  * The instantiated object will have methods matching those specified in <code>config.remote</code>.<br/>
778
  * This requires the JSON object present in the document, either natively, using json.org's json2 or as a wrapper around library spesific methods.
779
  * <h2>How to set up</h2>
780
  * <pre><code>
781
  * var rpc = new easyXDM.Rpc({
782
  * &nbsp; &#47;&#47; this configuration is equal to that used by the Socket.
783
  * &nbsp; remote: "http:&#47;&#47;remotedomain/...",
784
  * &nbsp; onReady: function(){
785
  * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the proxy
786
  * &nbsp; &nbsp; rpc.foo(...
787
  * &nbsp; }
788
  * },{
789
  * &nbsp; local: {..},
790
  * &nbsp; remote: {..}
791
  * });
792
  * </code></pre>
793
  *
794
  * <h2>Exposing functions (procedures)</h2>
795
  * <pre><code>
796
  * var rpc = new easyXDM.Rpc({
797
  * &nbsp; ...
798
  * },{
799
  * &nbsp; local: {
800
  * &nbsp; &nbsp; nameOfMethod: {
801
  * &nbsp; &nbsp; &nbsp; method: function(arg1, arg2, success, error){
802
  * &nbsp; &nbsp; &nbsp; &nbsp; ...
803
  * &nbsp; &nbsp; &nbsp; }
804
  * &nbsp; &nbsp; },
805
  * &nbsp; &nbsp; &#47;&#47; with shorthand notation
806
  * &nbsp; &nbsp; nameOfAnotherMethod: function(arg1, arg2, success, error){
807
  * &nbsp; &nbsp; }
808
  * &nbsp; },
809
  * &nbsp; remote: {...}
810
  * });
811
  * </code></pre>
812
  * The function referenced by [method] will receive the passed arguments followed by the callback functions <code>success</code> and <code>error</code>.<br/>
813
  * To send a successfull result back you can use
814
  * <pre><code>
815
  * return foo;
816
  * </pre></code>
817
  * or
818
  * <pre><code>
819
  * success(foo);
820
  * </pre></code>
821
  * To return an error you can use
822
  * <pre><code>
823
  * throw new Error("foo error");
824
  * </code></pre>
825
  * or
826
  * <pre><code>
827
  * error("foo error");
828
  * </code></pre>
829
  *
830
  * <h2>Defining remotely exposed methods (procedures/notifications)</h2>
831
  * The definition of the remote end is quite similar:
832
  * <pre><code>
833
  * var rpc = new easyXDM.Rpc({
834
  * &nbsp; ...
835
  * },{
836
  * &nbsp; local: {...},
837
  * &nbsp; remote: {
838
  * &nbsp; &nbsp; nameOfMethod: {}
839
  * &nbsp; }
840
  * });
841
  * </code></pre>
842
  * To call a remote method use
843
  * <pre><code>
844
  * rpc.nameOfMethod("arg1", "arg2", function(value) {
845
  * &nbsp; alert("success: " + value);
846
  * }, function(message) {
847
  * &nbsp; alert("error: " + message + );
848
  * });
849
  * </code></pre>
850
  * Both the <code>success</code> and <code>errror</code> callbacks are optional.<br/>
851
  * When called with no callback a JSON-RPC 2.0 notification will be executed.
852
  * Be aware that you will not be notified of any errors with this method.
853
  * <br/>
854
  * <h2>Specifying a custom serializer</h2>
855
  * If you do not want to use the JSON2 library for non-native JSON support, but instead capabilities provided by some other library
856
  * then you can specify a custom serializer using <code>serializer: foo</code>
857
  * <pre><code>
858
  * var rpc = new easyXDM.Rpc({
859
  * &nbsp; ...
860
  * },{
861
  * &nbsp; local: {...},
862
  * &nbsp; remote: {...},
863
  * &nbsp; serializer : {
864
  * &nbsp; &nbsp; parse: function(string){ ... },
865
  * &nbsp; &nbsp; stringify: function(object) {...}
866
  * &nbsp; }
867
  * });
868
  * </code></pre>
869
  * If <code>serializer</code> is set then the class will not attempt to use the native implementation.
870
  * @namespace easyXDM
871
  * @constructor
872
  * @param {Object} config The underlying transports configuration. See easyXDM.Socket for available parameters.
873
  * @param {Object} jsonRpcConfig The description of the interface to implement.
874
  */
875
  // expand shorthand notation
876
  if (jsonRpcConfig.local) {
877
  for (var method in jsonRpcConfig.local) {
878
  if (jsonRpcConfig.local.hasOwnProperty(method)) {
879
  var member = jsonRpcConfig.local[method];
880
  if (typeof member === "function") {
881
  jsonRpcConfig.local[method] = {
882
  method: member
883
  };
884
  }
885
  }
886
  }
887
  }
888
  // create the stack
889
  var stack = chainStack(prepareTransportStack(config).concat([new easyXDM.stack.RpcBehavior(this, jsonRpcConfig), {
890
  callback: function(success){
891
  if (config.onReady) {
892
  config.onReady(success);
893
  }
894
  }
895
  }]));
896
  // set the origin
897
  this.origin = getLocation(config.remote);
898
  /**
899
  * Initiates the destruction of the stack.
900
  */
901
  this.destroy = function(){
902
  stack.destroy();
903
  };
904
  stack.init();
905
  * @class easyXDM.stack.SameOriginTransport
906
  * SameOriginTransport is a transport class that can be used when both domains have the same origin.<br/>
907
  * This can be useful for testing and for when the main application supports both internal and external sources.
908
  * @namespace easyXDM.stack
909
  * @constructor
910
  * @param {Object} config The transports configuration.
911
  * @cfg {String} remote The remote document to communicate with.
912
  */
913
  var pub, frame, send, targetOrigin;
914
  return (pub = {
915
  outgoing: function(message, domain, fn){
916
  send(message);
917
  if (fn) {
918
  fn();
919
  }
920
  },
921
  destroy: function(){
922
  if (frame) {
923
  frame.parentNode.removeChild(frame);
924
  frame = null;
925
  }
926
  },
927
  onDOMReady: function(){
928
  targetOrigin = getLocation(config.remote);
929
  if (config.isHost) {
930
  // set up the iframe
931
  apply(config.props, {
932
  src: appendQueryParameters(config.remote, {
933
  xdm_e: location.protocol + "//" + location.host + location.pathname,
934
  xdm_c: config.channel,
935
  xdm_p: 4 // 4 = SameOriginTransport
936
  }),
937
  name: IFRAME_PREFIX + config.channel + "_provider"
938
  });
939
  frame = createFrame(config);
940
  easyXDM.Fn.set(config.channel, function(sendFn){
941
  send = sendFn;
942
  setTimeout(function(){
943
  pub.up.callback(true);
944
  }, 0);
945
  return function(msg){
946
  pub.up.incoming(msg, targetOrigin);
947
  };
948
  });
949
  }
950
  else {
951
  send = getParentObject().Fn.get(config.channel, true)(function(msg){
952
  pub.up.incoming(msg, targetOrigin);
953
  });
954
  setTimeout(function(){
955
  pub.up.callback(true);
956
  }, 0);
957
  }
958
  },
959
  init: function(){
960
  whenReady(pub.onDOMReady, pub);
961
  }
962
  });
963
  * @class easyXDM.stack.FlashTransport
964
  * FlashTransport is a transport class that uses an SWF with LocalConnection to pass messages back and forth.
965
  * @namespace easyXDM.stack
966
  * @constructor
967
  * @param {Object} config The transports configuration.
968
  * @cfg {String} remote The remote domain to communicate with.
969
  * @cfg {String} secret the pre-shared secret used to secure the communication.
970
  * @cfg {String} swf The path to the swf file
971
  * @cfg {Boolean} swfNoThrottle Set this to true if you want to take steps to avoid beeing throttled when hidden.
972
  * @cfg {String || DOMElement} swfContainer Set this if you want to control where the swf is placed
973
  */
974
  var pub, // the public interface
975
  frame, send, targetOrigin, swf, swfContainer;
976
  function onMessage(message, origin){
977
  setTimeout(function(){
978
  pub.up.incoming(message, targetOrigin);
979
  }, 0);
980
  }
981
  /**
982
  * This method adds the SWF to the DOM and prepares the initialization of the channel
983
  */
984
  function addSwf(domain){
985
  // the differentiating query argument is needed in Flash9 to avoid a caching issue where LocalConnection would throw an error.
986
  var url = config.swf + "?host=" + config.isHost;
987
  var id = "easyXDM_swf_" + Math.floor(Math.random() * 10000);
988
  // prepare the init function that will fire once the swf is ready
989
  easyXDM.Fn.set("flash_loaded" + domain.replace(/[\-.]/g, "_"), function(){
990
  easyXDM.stack.FlashTransport[domain].swf = swf = swfContainer.firstChild;
991
  var queue = easyXDM.stack.FlashTransport[domain].queue;
992
  for (var i = 0; i < queue.length; i++) {
993
  queue[i]();
994
  }
995
  queue.length = 0;
996
  });
997
  if (config.swfContainer) {
998
  swfContainer = (typeof config.swfContainer == "string") ? document.getElementById(config.swfContainer) : config.swfContainer;
999
  }
1000
  else {
1001
  // create the container that will hold the swf
1002
  swfContainer = document.createElement('div');
1003
  // http://bugs.adobe.com/jira/browse/FP-4796
1004
  // http://tech.groups.yahoo.com/group/flexcoders/message/162365
1005
  // https://groups.google.com/forum/#!topic/easyxdm/mJZJhWagoLc
1006
  apply(swfContainer.style, HAS_FLASH_THROTTLED_BUG && config.swfNoThrottle ? {
1007
  height: "20px",
1008
  width: "20px",
1009
  position: "fixed",
1010
  right: 0,
1011
  top: 0
1012
  } : {
1013
  height: "1px",
1014
  width: "1px",
1015
  position: "absolute",
1016
  overflow: "hidden",
1017
  right: 0,
1018
  top: 0
1019
  });
1020
  document.body.appendChild(swfContainer);
1021
  }
1022
  // create the object/embed
1023
  var flashVars = "callback=flash_loaded" + encodeURIComponent(domain.replace(/[\-.]/g, "_"))
1024
  + "&proto=" + global.location.protocol
1025
  + "&domain=" + encodeURIComponent(getDomainName(global.location.href))
1026
  + "&port=" + encodeURIComponent(getPort(global.location.href))
1027
  + "&ns=" + encodeURIComponent(namespace);
1028
  swfContainer.innerHTML = "<object height='20' width='20' type='application/x-shockwave-flash' id='" + id + "' data='" + url + "'>" +
1029
  "<param name='allowScriptAccess' value='always'></param>" +
1030
  "<param name='wmode' value='transparent'>" +
1031
  "<param name='movie' value='" +
1032
  url +
1033
  "'></param>" +
1034
  "<param name='flashvars' value='" +
1035
  flashVars +
1036
  "'></param>" +
1037
  "<embed type='application/x-shockwave-flash' FlashVars='" +
1038
  flashVars +
1039
  "' allowScriptAccess='always' wmode='transparent' src='" +
1040
  url +
1041
  "' height='1' width='1'></embed>" +
1042
  "</object>";
1043
  }
1044
  return (pub = {
1045
  outgoing: function(message, domain, fn){
1046
  swf.postMessage(config.channel, message.toString());
1047
  if (fn) {
1048
  fn();
1049
  }
1050
  },
1051
  destroy: function(){
1052
  try {
1053
  swf.destroyChannel(config.channel);
1054
  }
1055
  catch (e) {
1056
  }
1057
  swf = null;
1058
  if (frame) {
1059
  frame.parentNode.removeChild(frame);
1060
  frame = null;
1061
  }
1062
  },
1063
  onDOMReady: function(){
1064
  targetOrigin = config.remote;
1065
  // Prepare the code that will be run after the swf has been intialized
1066
  easyXDM.Fn.set("flash_" + config.channel + "_init", function(){
1067
  setTimeout(function(){
1068
  pub.up.callback(true);
1069
  });
1070
  });
1071
  // set up the omMessage handler
1072
  easyXDM.Fn.set("flash_" + config.channel + "_onMessage", onMessage);
1073
  config.swf = resolveUrl(config.swf); // reports have been made of requests gone rogue when using relative paths
1074
  var swfdomain = getDomainName(config.swf);
1075
  var fn = function(){
1076
  // set init to true in case the fn was called was invoked from a separate instance
1077
  easyXDM.stack.FlashTransport[swfdomain].init = true;
1078
  swf = easyXDM.stack.FlashTransport[swfdomain].swf;
1079
  // create the channel
1080
  swf.createChannel(config.channel, config.secret, getLocation(config.remote), config.isHost);
1081
  if (config.isHost) {
1082
  // if Flash is going to be throttled and we want to avoid this
1083
  if (HAS_FLASH_THROTTLED_BUG && config.swfNoThrottle) {
1084
  apply(config.props, {
1085
  position: "fixed",
1086
  right: 0,
1087
  top: 0,
1088
  height: "20px",
1089
  width: "20px"
1090
  });
1091
  }
1092
  // set up the iframe
1093
  apply(config.props, {
1094
  src: appendQueryParameters(config.remote, {
1095
  xdm_e: getLocation(location.href),
1096
  xdm_c: config.channel,
1097
  xdm_p: 6, // 6 = FlashTransport
1098
  xdm_s: config.secret
1099
  }),
1100
  name: IFRAME_PREFIX + config.channel + "_provider"
1101
  });
1102
  frame = createFrame(config);
1103
  }
1104
  };
1105
  if (easyXDM.stack.FlashTransport[swfdomain] && easyXDM.stack.FlashTransport[swfdomain].init) {
1106
  // if the swf is in place and we are the consumer
1107
  fn();
1108
  }
1109
  else {
1110
  // if the swf does not yet exist
1111
  if (!easyXDM.stack.FlashTransport[swfdomain]) {
1112
  // add the queue to hold the init fn's
1113
  easyXDM.stack.FlashTransport[swfdomain] = {
1114
  queue: [fn]
1115
  };
1116
  addSwf(swfdomain);
1117
  }
1118
  else {
1119
  easyXDM.stack.FlashTransport[swfdomain].queue.push(fn);
1120
  }
1121
  }
1122
  },
1123
  init: function(){
1124
  whenReady(pub.onDOMReady, pub);
1125
  }
1126
  });
1127
  * @class easyXDM.stack.PostMessageTransport
1128
  * PostMessageTransport is a transport class that uses HTML5 postMessage for communication.<br/>
1129
  * <a href="http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx</a><br/>
1130
  * <a href="https://developer.mozilla.org/en/DOM/window.postMessage">https://developer.mozilla.org/en/DOM/window.postMessage</a>
1131
  * @namespace easyXDM.stack
1132
  * @constructor
1133
  * @param {Object} config The transports configuration.
1134
  * @cfg {String} remote The remote domain to communicate with.
1135
  */
1136
  var pub, // the public interface
1137
  frame, // the remote frame, if any
1138
  callerWindow, // the window that we will call with
1139
  targetOrigin; // the domain to communicate with
1140
  /**
1141
  * Resolves the origin from the event object
1142
  * @private
1143
  * @param {Object} event The messageevent
1144
  * @return {String} The scheme, host and port of the origin
1145
  */
1146
  function _getOrigin(event){
1147
  if (event.origin) {
1148
  // This is the HTML5 property
1149
  return getLocation(event.origin);
1150
  }
1151
  if (event.uri) {
1152
  // From earlier implementations
1153
  return getLocation(event.uri);
1154
  }
1155
  if (event.domain) {
1156
  // This is the last option and will fail if the
1157
  // origin is not using the same schema as we are
1158
  return location.protocol + "//" + event.domain;
1159
  }
1160
  throw "Unable to retrieve the origin of the event";
1161
  }
1162
  /**
1163
  * This is the main implementation for the onMessage event.<br/>
1164
  * It checks the validity of the origin and passes the message on if appropriate.
1165
  * @private
1166
  * @param {Object} event The messageevent
1167
  */
1168
  function _window_onMessage(event){
1169
  var origin = _getOrigin(event);
1170
  if (origin == targetOrigin && event.data.substring(0, config.channel.length + 1) == config.channel + " ") {
1171
  pub.up.incoming(event.data.substring(config.channel.length + 1), origin);
1172
  }
1173
  }
1174
  return (pub = {
1175
  outgoing: function(message, domain, fn){
1176
  callerWindow.postMessage(config.channel + " " + message, domain || targetOrigin);
1177
  if (fn) {
1178
  fn();
1179
  }
1180
  },
1181
  destroy: function(){
1182
  un(window, "message", _window_onMessage);
1183
  if (frame) {
1184
  callerWindow = null;
1185
  frame.parentNode.removeChild(frame);
1186
  frame = null;
1187
  }
1188
  },
1189
  onDOMReady: function(){
1190
  targetOrigin = getLocation(config.remote);
1191
  if (config.isHost) {
1192
  // add the event handler for listening
1193
  var waitForReady = function(event){
1194
  if (event.data == config.channel + "-ready") {
1195
  // replace the eventlistener
1196
  callerWindow = ("postMessage" in frame.contentWindow) ? frame.contentWindow : frame.contentWindow.document;
1197
  un(window, "message", waitForReady);
1198
  on(window, "message", _window_onMessage);
1199
  setTimeout(function(){
1200
  pub.up.callback(true);
1201
  }, 0);
1202
  }
1203
  };
1204
  on(window, "message", waitForReady);
1205
  // set up the iframe
1206
  apply(config.props, {
1207
  src: appendQueryParameters(config.remote, {
1208
  xdm_e: getLocation(location.href),
1209
  xdm_c: config.channel,
1210
  xdm_p: 1 // 1 = PostMessage
1211
  }),
1212
  name: IFRAME_PREFIX + config.channel + "_provider"
1213
  });
1214
  frame = createFrame(config);
1215
  }
1216
  else {
1217
  // add the event handler for listening
1218
  on(window, "message", _window_onMessage);
1219
  callerWindow = ("postMessage" in window.parent) ? window.parent : window.parent.document;
1220
  callerWindow.postMessage(config.channel + "-ready", targetOrigin);
1221
  setTimeout(function(){
1222
  pub.up.callback(true);
1223
  }, 0);
1224
  }
1225
  },
1226
  init: function(){
1227
  whenReady(pub.onDOMReady, pub);
1228
  }
1229
  });
1230
  * @class easyXDM.stack.FrameElementTransport
1231
  * FrameElementTransport is a transport class that can be used with Gecko-browser as these allow passing variables using the frameElement property.<br/>
1232
  * Security is maintained as Gecho uses Lexical Authorization to determine under which scope a function is running.
1233
  * @namespace easyXDM.stack
1234
  * @constructor
1235
  * @param {Object} config The transports configuration.
1236
  * @cfg {String} remote The remote document to communicate with.
1237
  */
1238
  var pub, frame, send, targetOrigin;
1239
  return (pub = {
1240
  outgoing: function(message, domain, fn){
1241
  send.call(this, message);
1242
  if (fn) {
1243
  fn();
1244
  }
1245
  },
1246
  destroy: function(){
1247
  if (frame) {
1248
  frame.parentNode.removeChild(frame);
1249
  frame = null;
1250
  }
1251
  },
1252
  onDOMReady: function(){
1253
  targetOrigin = getLocation(config.remote);
1254
  if (config.isHost) {
1255
  // set up the iframe
1256
  apply(config.props, {
1257
  src: appendQueryParameters(config.remote, {
1258
  xdm_e: getLocation(location.href),
1259
  xdm_c: config.channel,
1260
  xdm_p: 5 // 5 = FrameElementTransport
1261
  }),
1262
  name: IFRAME_PREFIX + config.channel + "_provider"
1263
  });
1264
  frame = createFrame(config);
1265
  frame.fn = function(sendFn){
1266
  delete frame.fn;
1267
  send = sendFn;
1268
  setTimeout(function(){
1269
  pub.up.callback(true);
1270
  }, 0);
1271
  // remove the function so that it cannot be used to overwrite the send function later on
1272
  return function(msg){
1273
  pub.up.incoming(msg, targetOrigin);
1274
  };
1275
  };
1276
  }
1277
  else {
1278
  // This is to mitigate origin-spoofing
1279
  if (document.referrer && getLocation(document.referrer) != query.xdm_e) {
1280
  window.top.location = query.xdm_e;
1281
  }
1282
  send = window.frameElement.fn(function(msg){
1283
  pub.up.incoming(msg, targetOrigin);
1284
  });
1285
  pub.up.callback(true);
1286
  }
1287
  },
1288
  init: function(){
1289
  whenReady(pub.onDOMReady, pub);
1290
  }
1291
  });
1292
  * @class easyXDM.stack.NameTransport
1293
  * NameTransport uses the window.name property to relay data.
1294
  * The <code>local</code> parameter needs to be set on both the consumer and provider,<br/>
1295
  * and the <code>remoteHelper</code> parameter needs to be set on the consumer.
1296
  * @constructor
1297
  * @param {Object} config The transports configuration.
1298
  * @cfg {String} remoteHelper The url to the remote instance of hash.html - this is only needed for the host.
1299
  * @namespace easyXDM.stack
1300
  */
1301
  var pub; // the public interface
1302
  var isHost, callerWindow, remoteWindow, readyCount, callback, remoteOrigin, remoteUrl;
1303
  function _sendMessage(message){
1304
  var url = config.remoteHelper + (isHost ? "#_3" : "#_2") + config.channel;
1305
  callerWindow.contentWindow.sendMessage(message, url);
1306
  }
1307
  function _onReady(){
1308
  if (isHost) {
1309
  if (++readyCount === 2 || !isHost) {
1310
  pub.up.callback(true);
1311
  }
1312
  }
1313
  else {
1314
  _sendMessage("ready");
1315
  pub.up.callback(true);
1316
  }
1317
  }
1318
  function _onMessage(message){
1319
  pub.up.incoming(message, remoteOrigin);
1320
  }
1321
  function _onLoad(){
1322
  if (callback) {
1323
  setTimeout(function(){
1324
  callback(true);
1325
  }, 0);
1326
  }
1327
  }
1328
  return (pub = {
1329
  outgoing: function(message, domain, fn){
1330
  callback = fn;
1331
  _sendMessage(message);
1332
  },
1333
  destroy: function(){
1334
  callerWindow.parentNode.removeChild(callerWindow);
1335
  callerWindow = null;
1336
  if (isHost) {
1337
  remoteWindow.parentNode.removeChild(remoteWindow);
1338
  remoteWindow = null;
1339
  }
1340
  },
1341
  onDOMReady: function(){
1342
  isHost = config.isHost;
1343
  readyCount = 0;
1344
  remoteOrigin = getLocation(config.remote);
1345
  config.local = resolveUrl(config.local);
1346
  if (isHost) {
1347
  // Register the callback
1348
  easyXDM.Fn.set(config.channel, function(message){
1349
  if (isHost && message === "ready") {
1350
  // Replace the handler
1351
  easyXDM.Fn.set(config.channel, _onMessage);
1352
  _onReady();
1353
  }
1354
  });
1355
  // Set up the frame that points to the remote instance
1356
  remoteUrl = appendQueryParameters(config.remote, {
1357
  xdm_e: config.local,
1358
  xdm_c: config.channel,
1359
  xdm_p: 2
1360
  });
1361
  apply(config.props, {
1362
  src: remoteUrl + '#' + config.channel,
1363
  name: IFRAME_PREFIX + config.channel + "_provider"
1364
  });
1365
  remoteWindow = createFrame(config);
1366
  }
1367
  else {
1368
  config.remoteHelper = config.remote;
1369
  easyXDM.Fn.set(config.channel, _onMessage);
1370
  }
1371
  // Set up the iframe that will be used for the transport
1372
  var onLoad = function(){
1373
  // Remove the handler
1374
  var w = callerWindow || this;
1375
  un(w, "load", onLoad);
1376
  easyXDM.Fn.set(config.channel + "_load", _onLoad);
1377
  (function test(){
1378
  if (typeof w.contentWindow.sendMessage == "function") {
1379
  _onReady();
1380
  }
1381
  else {
1382
  setTimeout(test, 50);
1383
  }
1384
  }());
1385
  };
1386
  callerWindow = createFrame({
1387
  props: {
1388
  src: config.local + "#_4" + config.channel
1389
  },
1390
  onLoad: onLoad
1391
  });
1392
  },
1393
  init: function(){
1394
  whenReady(pub.onDOMReady, pub);
1395
  }
1396
  });
1397
  * @class easyXDM.stack.HashTransport
1398
  * HashTransport is a transport class that uses the IFrame URL Technique for communication.<br/>
1399
  * <a href="http://msdn.microsoft.com/en-us/library/bb735305.aspx">http://msdn.microsoft.com/en-us/library/bb735305.aspx</a><br/>
1400
  * @namespace easyXDM.stack
1401
  * @constructor
1402
  * @param {Object} config The transports configuration.
1403
  * @cfg {String/Window} local The url to the local file used for proxying messages, or the local window.
1404
  * @cfg {Number} delay The number of milliseconds easyXDM should try to get a reference to the local window.
1405
  * @cfg {Number} interval The interval used when polling for messages.
1406
  */
1407
  var pub;
1408
  var me = this, isHost, _timer, pollInterval, _lastMsg, _msgNr, _listenerWindow, _callerWindow;
1409
  var useParent, _remoteOrigin;
1410
  function _sendMessage(message){
1411
  if (!_callerWindow) {
1412
  return;
1413
  }
1414
  var url = config.remote + "#" + (_msgNr++) + "_" + message;
1415
  ((isHost || !useParent) ? _callerWindow.contentWindow : _callerWindow).location = url;
1416
  }
1417
  function _handleHash(hash){
1418
  _lastMsg = hash;
1419
  pub.up.incoming(_lastMsg.substring(_lastMsg.indexOf("_") + 1), _remoteOrigin);
1420
  }
1421
  /**
1422
  * Checks location.hash for a new message and relays this to the receiver.
1423
  * @private
1424
  */
1425
  function _pollHash(){
1426
  if (!_listenerWindow) {
1427
  return;
1428
  }
1429
  var href = _listenerWindow.location.href, hash = "", indexOf = href.indexOf("#");
1430
  if (indexOf != -1) {
1431
  hash = href.substring(indexOf);
1432
  }
1433
  if (hash && hash != _lastMsg) {
1434
  _handleHash(hash);
1435
  }
1436
  }
1437
  function _attachListeners(){
1438
  _timer = setInterval(_pollHash, pollInterval);
1439
  }
1440
  return (pub = {
1441
  outgoing: function(message, domain){
1442
  _sendMessage(message);
1443
  },
1444
  destroy: function(){
1445
  window.clearInterval(_timer);
1446
  if (isHost || !useParent) {
1447
  _callerWindow.parentNode.removeChild(_callerWindow);
1448
  }
1449
  _callerWindow = null;
1450
  },
1451
  onDOMReady: function(){
1452
  isHost = config.isHost;
1453
  pollInterval = config.interval;
1454
  _lastMsg = "#" + config.channel;
1455
  _msgNr = 0;
1456
  useParent = config.useParent;
1457
  _remoteOrigin = getLocation(config.remote);
1458
  if (isHost) {
1459
  apply(config.props, {
1460
  src: config.remote,
1461
  name: IFRAME_PREFIX + config.channel + "_provider"
1462
  });
1463
  if (useParent) {
1464
  config.onLoad = function(){
1465
  _listenerWindow = window;
1466
  _attachListeners();
1467
  pub.up.callback(true);
1468
  };
1469
  }
1470
  else {
1471
  var tries = 0, max = config.delay / 50;
1472
  (function getRef(){
1473
  if (++tries > max) {
1474
  throw new Error("Unable to reference listenerwindow");
1475
  }
1476
  try {
1477
  _listenerWindow = _callerWindow.contentWindow.frames[IFRAME_PREFIX + config.channel + "_consumer"];
1478
  }
1479
  catch (ex) {
1480
  }
1481
  if (_listenerWindow) {
1482
  _attachListeners();
1483
  pub.up.callback(true);
1484
  }
1485
  else {
1486
  setTimeout(getRef, 50);
1487
  }
1488
  }());
1489
  }
1490
  _callerWindow = createFrame(config);
1491
  }
1492
  else {
1493
  _listenerWindow = window;
1494
  _attachListeners();
1495
  if (useParent) {
1496
  _callerWindow = parent;
1497
  pub.up.callback(true);
1498
  }
1499
  else {
1500
  apply(config, {
1501
  props: {
1502
  src: config.remote + "#" + config.channel + new Date(),
1503
  name: IFRAME_PREFIX + config.channel + "_consumer"
1504
  },
1505
  onLoad: function(){
1506
  pub.up.callback(true);
1507
  }
1508
  });
1509
  _callerWindow = createFrame(config);
1510
  }
1511
  }
1512
  },
1513
  init: function(){
1514
  whenReady(pub.onDOMReady, pub);
1515
  }
1516
  });
1517
  * @class easyXDM.stack.ReliableBehavior
1518
  * This is a behavior that tries to make the underlying transport reliable by using acknowledgements.
1519
  * @namespace easyXDM.stack
1520
  * @constructor
1521
  * @param {Object} config The behaviors configuration.
1522
  */
1523
  var pub, // the public interface
1524
  callback; // the callback to execute when we have a confirmed success/failure
1525
  var idOut = 0, idIn = 0, currentMessage = "";
1526
  return (pub = {
1527
  incoming: function(message, origin){
1528
  var indexOf = message.indexOf("_"), ack = message.substring(0, indexOf).split(",");
1529
  message = message.substring(indexOf + 1);
1530
  if (ack[0] == idOut) {
1531
  currentMessage = "";
1532
  if (callback) {
1533
  callback(true);
1534
  }
1535
  }
1536
  if (message.length > 0) {
1537
  pub.down.outgoing(ack[1] + "," + idOut + "_" + currentMessage, origin);
1538
  if (idIn != ack[1]) {
1539
  idIn = ack[1];
1540
  pub.up.incoming(message, origin);
1541
  }
1542
  }
1543
  },
1544
  outgoing: function(message, origin, fn){
1545
  currentMessage = message;
1546
  callback = fn;
1547
  pub.down.outgoing(idIn + "," + (++idOut) + "_" + message, origin);
1548
  }
1549
  });
1550
  * @class easyXDM.stack.QueueBehavior
1551
  * This is a behavior that enables queueing of messages. <br/>
1552
  * It will buffer incoming messages and dispach these as fast as the underlying transport allows.
1553
  * This will also fragment/defragment messages so that the outgoing message is never bigger than the
1554
  * set length.
1555
  * @namespace easyXDM.stack
1556
  * @constructor
1557
  * @param {Object} config The behaviors configuration. Optional.
1558
  * @cfg {Number} maxLength The maximum length of each outgoing message. Set this to enable fragmentation.
1559
  */
1560
  var pub, queue = [], waiting = true, incoming = "", destroying, maxLength = 0, lazy = false, doFragment = false;
1561
  function dispatch(){
1562
  if (config.remove && queue.length === 0) {
1563
  removeFromStack(pub);
1564
  return;
1565
  }
1566
  if (waiting || queue.length === 0 || destroying) {
1567
  return;
1568
  }
1569
  waiting = true;
1570
  var message = queue.shift();
1571
  pub.down.outgoing(message.data, message.origin, function(success){
1572
  waiting = false;
1573
  if (message.callback) {
1574
  setTimeout(function(){
1575
  message.callback(success);
1576
  }, 0);
1577
  }
1578
  dispatch();
1579
  });
1580
  }
1581
  return (pub = {
1582
  init: function(){
1583
  if (undef(config)) {
1584
  config = {};
1585
  }
1586
  if (config.maxLength) {
1587
  maxLength = config.maxLength;
1588
  doFragment = true;
1589
  }
1590
  if (config.lazy) {
1591
  lazy = true;
1592
  }
1593
  else {
1594
  pub.down.init();
1595
  }
1596
  },
1597
  callback: function(success){
1598
  waiting = false;
1599
  var up = pub.up; // in case dispatch calls removeFromStack
1600
  dispatch();
1601
  up.callback(success);
1602
  },
1603
  incoming: function(message, origin){
1604
  if (doFragment) {
1605
  var indexOf = message.indexOf("_"), seq = parseInt(message.substring(0, indexOf), 10);
1606
  incoming += message.substring(indexOf + 1);
1607
  if (seq === 0) {
1608
  if (config.encode) {
1609
  incoming = decodeURIComponent(incoming);
1610
  }
1611
  pub.up.incoming(incoming, origin);
1612
  incoming = "";
1613
  }
1614
  }
1615
  else {
1616
  pub.up.incoming(message, origin);
1617
  }
1618
  },
1619
  outgoing: function(message, origin, fn){
1620
  if (config.encode) {
1621
  message = encodeURIComponent(message);
1622
  }
1623
  var fragments = [], fragment;
1624
  if (doFragment) {
1625
  // fragment into chunks
1626
  while (message.length !== 0) {
1627
  fragment = message.substring(0, maxLength);
1628
  message = message.substring(fragment.length);
1629
  fragments.push(fragment);
1630
  }
1631
  // enqueue the chunks
1632
  while ((fragment = fragments.shift())) {
1633
  queue.push({
1634
  data: fragments.length + "_" + fragment,
1635
  origin: origin,
1636
  callback: fragments.length === 0 ? fn : null
1637
  });
1638
  }
1639
  }
1640
  else {
1641
  queue.push({
1642
  data: message,
1643
  origin: origin,
1644
  callback: fn
1645
  });
1646
  }
1647
  if (lazy) {
1648
  pub.down.init();
1649
  }
1650
  else {
1651
  dispatch();
1652
  }
1653
  },
1654
  destroy: function(){
1655
  destroying = true;
1656
  pub.down.destroy();
1657
  }
1658
  });
1659
  * @class easyXDM.stack.VerifyBehavior
1660
  * This behavior will verify that communication with the remote end is possible, and will also sign all outgoing,
1661
  * and verify all incoming messages. This removes the risk of someone hijacking the iframe to send malicious messages.
1662
  * @namespace easyXDM.stack
1663
  * @constructor
1664
  * @param {Object} config The behaviors configuration.
1665
  * @cfg {Boolean} initiate If the verification should be initiated from this end.
1666
  */
1667
  var pub, mySecret, theirSecret, verified = false;
1668
  function startVerification(){
1669
  mySecret = Math.random().toString(16).substring(2);
1670
  pub.down.outgoing(mySecret);
1671
  }
1672
  return (pub = {
1673
  incoming: function(message, origin){
1674
  var indexOf = message.indexOf("_");
1675
  if (indexOf === -1) {
1676
  if (message === mySecret) {
1677
  pub.up.callback(true);
1678
  }
1679
  else if (!theirSecret) {
1680
  theirSecret = message;
1681
  if (!config.initiate) {
1682
  startVerification();
1683
  }
1684
  pub.down.outgoing(message);
1685
  }
1686
  }
1687
  else {
1688
  if (message.substring(0, indexOf) === theirSecret) {
1689
  pub.up.incoming(message.substring(indexOf + 1), origin);
1690
  }
1691
  }
1692
  },
1693
  outgoing: function(message, origin, fn){
1694
  pub.down.outgoing(mySecret + "_" + message, origin, fn);
1695
  },
1696
  callback: function(success){
1697
  if (config.initiate) {
1698
  startVerification();
1699
  }
1700
  }
1701
  });
1702
  * @class easyXDM.stack.RpcBehavior
1703
  * This uses JSON-RPC 2.0 to expose local methods and to invoke remote methods and have responses returned over the the string based transport stack.<br/>
1704
  * Exposed methods can return values synchronous, asyncronous, or bet set up to not return anything.
1705
  * @namespace easyXDM.stack
1706
  * @constructor
1707
  * @param {Object} proxy The object to apply the methods to.
1708
  * @param {Object} config The definition of the local and remote interface to implement.
1709
  * @cfg {Object} local The local interface to expose.
1710
  * @cfg {Object} remote The remote methods to expose through the proxy.
1711
  * @cfg {Object} serializer The serializer to use for serializing and deserializing the JSON. Should be compatible with the HTML5 JSON object. Optional, will default to JSON.
1712
  */
1713
  var pub, serializer = config.serializer || getJSON();
1714
  var _callbackCounter = 0, _callbacks = {};
1715
  /**
1716
  * Serializes and sends the message
1717
  * @private
1718
  * @param {Object} data The JSON-RPC message to be sent. The jsonrpc property will be added.
1719
  */
1720
  function _send(data){
1721
  data.jsonrpc = "2.0";
1722
  pub.down.outgoing(serializer.stringify(data));
1723
  }
1724
  /**
1725
  * Creates a method that implements the given definition
1726
  * @private
1727
  * @param {Object} The method configuration
1728
  * @param {String} method The name of the method
1729
  * @return {Function} A stub capable of proxying the requested method call
1730
  */
1731
  function _createMethod(definition, method){
1732
  var slice = Array.prototype.slice;
1733
  return function(){
1734
  var l = arguments.length, callback, message = {
1735
  method: method
1736
  };
1737
  if (l > 0 && typeof arguments[l - 1] === "function") {
1738
  //with callback, procedure
1739
  if (l > 1 && typeof arguments[l - 2] === "function") {
1740
  // two callbacks, success and error
1741
  callback = {
1742
  success: arguments[l - 2],
1743
  error: arguments[l - 1]
1744
  };
1745
  message.params = slice.call(arguments, 0, l - 2);
1746
  }
1747
  else {
1748
  // single callback, success
1749
  callback = {
1750
  success: arguments[l - 1]
1751
  };
1752
  message.params = slice.call(arguments, 0, l - 1);
1753
  }
1754
  _callbacks["" + (++_callbackCounter)] = callback;
1755
  message.id = _callbackCounter;
1756
  }
1757
  else {
1758
  // no callbacks, a notification
1759
  message.params = slice.call(arguments, 0);
1760
  }
1761
  if (definition.namedParams && message.params.length === 1) {
1762
  message.params = message.params[0];
1763
  }
1764
  // Send the method request
1765
  _send(message);
1766
  };
1767
  }
1768
  /**
1769
  * Executes the exposed method
1770
  * @private
1771
  * @param {String} method The name of the method
1772
  * @param {Number} id The callback id to use
1773
  * @param {Function} method The exposed implementation
1774
  * @param {Array} params The parameters supplied by the remote end
1775
  */
1776
  function _executeMethod(method, id, fn, params){
1777
  if (!fn) {
1778
  if (id) {
1779
  _send({
1780
  id: id,
1781
  error: {
1782
  code: -32601,
1783
  message: "Procedure not found."
1784
  }
1785
  });
1786
  }
1787
  return;
1788
  }
1789
  var success, error;
1790
  if (id) {
1791
  success = function(result){
1792
  success = emptyFn;
1793
  _send({
1794
  id: id,
1795
  result: result
1796
  });
1797
  };
1798
  error = function(message, data){
1799
  error = emptyFn;
1800
  var msg = {
1801
  id: id,
1802
  error: {
1803
  code: -32099,
1804
  message: message
1805
  }
1806
  };
1807
  if (data) {
1808
  msg.error.data = data;
1809
  }
1810
  _send(msg);
1811
  };
1812
  }
1813
  else {
1814
  success = error = emptyFn;
1815
  }
1816
  // Call local method
1817
  if (!isArray(params)) {
1818
  params = [params];
1819
  }
1820
  try {
1821
  var result = fn.method.apply(fn.scope, params.concat([success, error]));
1822
  if (!undef(result)) {
1823
  success(result);
1824
  }
1825
  }
1826
  catch (ex1) {
1827
  error(ex1.message);
1828
  }
1829
  }
1830
  return (pub = {
1831
  incoming: function(message, origin){
1832
  var data = serializer.parse(message);
1833
  if (data.method) {
1834
  // A method call from the remote end
1835
  if (config.handle) {
1836
  config.handle(data, _send);
1837
  }
1838
  else {
1839
  _executeMethod(data.method, data.id, config.local[data.method], data.params);
1840
  }
1841
  }
1842
  else {
1843
  // A method response from the other end
1844
  var callback = _callbacks[data.id];
1845
  if (data.error) {
1846
  if (callback.error) {
1847
  callback.error(data.error);
1848
  }
1849
  }
1850
  else if (callback.success) {
1851
  callback.success(data.result);
1852
  }
1853
  delete _callbacks[data.id];
1854
  }
1855
  },
1856
  init: function(){
1857
  if (config.remote) {
1858
  // Implement the remote sides exposed methods
1859
  for (var method in config.remote) {
1860
  if (config.remote.hasOwnProperty(method)) {
1861
  proxy[method] = _createMethod(config.remote[method], method);
1862
  }
1863
  }
1864
  }
1865
  pub.down.init();
1866
  },
1867
  destroy: function(){
1868
  for (var method in config.remote) {
1869
  if (config.remote.hasOwnProperty(method) && proxy.hasOwnProperty(method)) {
1870
  delete proxy[method];
1871
  }
1872
  }
1873
  pub.down.destroy();
1874
  }
1875
  });
trunk/assets/libraries/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/libraries/jpicker/css/jPicker-1.1.6.css ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .jPicker .Icon {
2
+ display: inline-block;
3
+ height: 24px; /* change this value if using a different sized color picker icon */
4
+ position: relative; /* make this element an absolute positioning container */
5
+ text-align: left; /* make the zero width children position to the left of container */
6
+ width: 25px; /* change this value if using a different sized color picker icon */
7
+ }
8
+ .jPicker .Icon span.Color, .jPicker .Icon span.Alpha {
9
+ background-position: 2px 2px;
10
+ display: block;
11
+ height: 100%;
12
+ left: 0px;
13
+ position: absolute;
14
+ top: 0px;
15
+ width: 100%;
16
+ }
17
+ .jPicker .Icon span.Image {
18
+ background-repeat: no-repeat;
19
+ cursor: pointer;
20
+ display: block;
21
+ height: 100%;
22
+ left: 0px;
23
+ position: absolute;
24
+ top: 0px;
25
+ width: 100%;
26
+ }
27
+ .jPicker.Container {
28
+ color: #000;
29
+ z-index: 10;
30
+ }
31
+ table.jPicker {
32
+ background-color: #efefef;
33
+ border: 1px outset #666;
34
+ font-family: Arial, Helvetica, Sans-Serif;
35
+ font-size: 12px !important;
36
+ margin: 0px;
37
+ padding: 5px;
38
+ width: 545px;
39
+ z-index: 20;
40
+ }
41
+ .jPicker .Move {
42
+ background-color: #dddddd;
43
+ border-color: #fff #666 #666 #fff;
44
+ border-style: solid;
45
+ border-width: 1px;
46
+ cursor: move;
47
+ height: 12px;
48
+ padding: 0px;
49
+ }
50
+ .jPicker .Title {
51
+ font-size: 11px !important;
52
+ font-weight: bold;
53
+ margin: -2px 0px 0px 0px;
54
+ padding: 10px 0px 0px 0px;
55
+ text-align: center;
56
+ width: 100%;
57
+ }
58
+ .jPicker div.Map {
59
+ border-bottom: 2px solid #fff;
60
+ border-left: 2px solid #9a9a9a;
61
+ border-right: 2px solid #fff;
62
+ border-top: 2px solid #9a9a9a;
63
+ cursor: crosshair;
64
+ height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
65
+ margin: 0px 10px 10px 10px;
66
+ overflow: hidden; /* hide the overdraw of the Color Map icon when at edge of viewing box */
67
+ padding: 0px;
68
+ position: relative; /* make this element an absolute positioning container */
69
+ width: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
70
+ }
71
+ .jPicker div[class="Map"] {
72
+ height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
73
+ width: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
74
+ }
75
+ .jPicker div.Bar {
76
+ border-bottom: 2px solid #fff;
77
+ border-left: 2px solid #9a9a9a;
78
+ border-right: 2px solid #fff;
79
+ border-top: 2px solid #9a9a9a;
80
+ cursor: n-resize;
81
+ height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
82
+ margin: 12px 10px 0px 5px;
83
+ overflow: hidden;
84
+ padding: 0px;
85
+ position: relative;
86
+ width: 24px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 20px later */
87
+ }
88
+ .jPicker div[class="Bar"] {
89
+ height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
90
+ width: 20px; /* correct to 20px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
91
+ }
92
+ .jPicker .Map .Map1, .jPicker .Map .Map2, .jPicker .Map .Map3, .jPicker .Bar .Map1, .jPicker .Bar .Map2, .jPicker .Bar .Map3, .jPicker .Bar .Map4, .jPicker .Bar .Map5, .jPicker .Bar .Map6 {
93
+ background-color: transparent;
94
+ background-image: none;
95
+ display: block;
96
+ left: 0px;
97
+ position: absolute;
98
+ top: 0px;
99
+ }
100
+ .jPicker .Map .Map1, .jPicker .Map .Map2, .jPicker .Map .Map3 {
101
+ height: 2596px;
102
+ width: 256px; /* must specify pixel width. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar
103
+ would not be drawn if its overflow is set to hidden. */
104
+ }
105
+ .jPicker .Bar .Map1, .jPicker .Bar .Map2, .jPicker .Bar .Map3, .jPicker .Bar .Map4 {
106
+ height: 3896px;
107
+ width: 20px; /* must specify pixel width. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar
108
+ would not be drawn if its overflow is set to hidden. */
109
+ }
110
+ .jPicker .Bar .Map5, .jPicker .Bar .Map6 {
111
+ height: 256px;
112
+ width: 20px; /* must specify pixel width. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar
113
+ would not be drawn if its overflow is set to hidden. */
114
+ }
115
+ .jPicker .Map .Map1, .jPicker .Map .Map2, .jPicker .Bar .Map6 {
116
+ background-repeat: no-repeat;
117
+ }
118
+ .jPicker .Map .Map3, .jPicker .Bar .Map5 {
119
+ background-repeat: repeat;
120
+ }
121
+ .jPicker .Bar .Map1, .jPicker .Bar .Map2, .jPicker .Bar .Map3, .jPicker .Bar .Map4 {
122
+ background-repeat: repeat-x;
123
+ }
124
+ .jPicker .Map .Arrow {
125
+ display: block;
126
+ position: absolute;
127
+ }
128
+ .jPicker .Bar .Arrow {
129
+ display: block;
130
+ left: 0px; /* (arrow width / 2) - (element width / 2) - position arrows' center in elements' center */
131
+ position: absolute;
132
+ }
133
+ .jPicker .Preview {
134
+ font-size: 9px;
135
+ padding: 5px 0px 0px 0px;
136
+ text-align: center;
137
+ }
138
+ .jPicker .Preview div {
139
+ border: 2px inset #eee;
140
+ height: 62px;
141
+ margin: 0px auto;
142
+ padding: 0px;
143
+ width: 62px;
144
+ }
145
+ .jPicker .Preview div span {
146
+ border: 1px solid #000;
147
+ display: block;
148
+ height: 30px;
149
+ margin: 0px auto;
150
+ padding: 0px;
151
+ width: 60px;
152
+ }
153
+ .jPicker .Preview .Active {
154
+ border-bottom-width: 0px;
155
+ }
156
+ .jPicker .Preview .Current {
157
+ border-top-width: 0px;
158
+ cursor: pointer;
159
+ }
160
+ .jPicker input {
161
+ font-size: 13px;
162
+ }
163
+ .jPicker .Button {
164
+ text-align: center;
165
+ padding: 0px 4px;
166
+ width: 115px;
167
+ }
168
+ .jPicker .Button input {
169
+ padding: 2px 0px;
170
+ width: 100px;
171
+ }
172
+ .jPicker .Button .Ok {
173
+ margin: 12px 0px 5px 0px;
174
+ }
175
+ .jPicker td {
176
+ margin: 0px;
177
+ padding: 0px;
178
+ }
179
+ .jPicker td.Radio {
180
+ margin: 0px;
181
+ padding: 0px;
182
+ width: 31px;
183
+ }
184
+ .jPicker td.Radio input {
185
+ margin: 0px 5px 0px 0px;
186
+ padding: 0px;
187
+ }
188
+ .jPicker td.Text {
189
+ font-size: 12px !important;
190
+ height: 22px;
191
+ margin: 0px;
192
+ padding: 0px;
193
+ text-align: left;
194
+ width: 70px;
195
+ }
196
+ .jPicker tr.Hex td.Text {
197
+ width: 100px;
198
+ }
199
+ .jPicker td.Text input {
200
+ background-color: #fff;
201
+ border: 1px inset #aaa;
202
+ height: 19px;
203
+ margin: 0px 0px 0px 5px;
204
+ text-align: left;
205
+ width: 30px;
206
+ }
207
+ .jPicker td[class="Text"] input {
208
+ height: 15px;
209
+ }
210
+ .jPicker tr.Hex td.Text input.Hex {
211
+ width: 50px;
212
+ }
213
+ .jPicker tr.Hex td.Text input.AHex {
214
+ width: 20px;
215
+ }
216
+ .jPicker .Grid {
217
+ text-align: center;
218
+ width: 114px;
219
+ }
220
+ .jPicker .Grid span.QuickColor {
221
+ border: 1px inset #aaa;
222
+ cursor: pointer;
223
+ display: inline-block;
224
+ height: 15px;
225
+ line-height: 15px;
226
+ margin: 0px;
227
+ padding: 0px;
228
+ width: 19px;
229
+ }
230
+ .jPicker .Grid span[class="QuickColor"] {
231
+ width: 17px;
232
+ }
trunk/assets/libraries/jpicker/css/jPicker-1.1.6.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .jPicker .Icon{display:inline-block;height:24px;position:relative;text-align:left;width:25px}.jPicker .Icon span.Color,.jPicker .Icon span.Alpha{background-position:2px 2px;display:block;height:100%;left:0;position:absolute;top:0;width:100%}.jPicker .Icon span.Image{background-repeat:no-repeat;cursor:pointer;display:block;height:100%;left:0;position:absolute;top:0;width:100%}.jPicker.Container{color:#000;z-index:10}table.jPicker{background-color:#efefef;border:1px outset #666;font-family:Arial,Helvetica,Sans-Serif;font-size:12px!important;margin:0;padding:5px;width:545px;z-index:20}.jPicker .Move{background-color:#ddd;border-color:#fff #666 #666 #fff;border-style:solid;border-width:1px;cursor:move;height:12px;padding:0}.jPicker .Title{font-size:11px!important;font-weight:bold;margin:-2px 0 0 0;padding:10px 0 0 0;text-align:center;width:100%}.jPicker div.Map{border-bottom:2px solid #fff;border-left:2px solid #9a9a9a;border-right:2px solid #fff;border-top:2px solid #9a9a9a;cursor:crosshair;height:260px;margin:0 10px 10px 10px;overflow:hidden;padding:0;position:relative;width:260px}.jPicker div[class="Map"]{height:256px;width:256px}.jPicker div.Bar{border-bottom:2px solid #fff;border-left:2px solid #9a9a9a;border-right:2px solid #fff;border-top:2px solid #9a9a9a;cursor:n-resize;height:260px;margin:12px 10px 0 5px;overflow:hidden;padding:0;position:relative;width:24px}.jPicker div[class="Bar"]{height:256px;width:20px}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Map .Map3,.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4,.jPicker .Bar .Map5,.jPicker .Bar .Map6{background-color:transparent;background-image:none;display:block;left:0;position:absolute;top:0}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Map .Map3{height:2596px;width:256px}.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4{height:3896px;width:20px}.jPicker .Bar .Map5,.jPicker .Bar .Map6{height:256px;width:20px}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Bar .Map6{background-repeat:no-repeat}.jPicker .Map .Map3,.jPicker .Bar .Map5{background-repeat:repeat}.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4{background-repeat:repeat-x}.jPicker .Map .Arrow{display:block;position:absolute}.jPicker .Bar .Arrow{display:block;left:0;position:absolute}.jPicker .Preview{font-size:9px;padding:5px 0 0 0;text-align:center}.jPicker .Preview div{border:2px inset #eee;height:62px;margin:0 auto;padding:0;width:62px}.jPicker .Preview div span{border:1px solid #000;display:block;height:30px;margin:0 auto;padding:0;width:60px}.jPicker .Preview .Active{border-bottom-width:0}.jPicker .Preview .Current{border-top-width:0;cursor:pointer}.jPicker input{font-size:13px}.jPicker .Button{text-align:center;padding:0 4px;width:115px}.jPicker .Button input{padding:2px 0;width:100px}.jPicker .Button .Ok{margin:12px 0 5px 0}.jPicker td{margin:0;padding:0}.jPicker td.Radio{margin:0;padding:0;width:31px}.jPicker td.Radio input{margin:0 5px 0 0;padding:0}.jPicker td.Text{font-size:12px!important;height:22px;margin:0;padding:0;text-align:left;width:70px}.jPicker tr.Hex td.Text{width:100px}.jPicker td.Text input{background-color:#fff;border:1px inset #aaa;height:28px;margin:0 0 0 5px;text-align:left;width:30px}.jPicker td[class="Text"] input{height:27px}.jPicker tr.Hex td.Text input.Hex{width:50px}.jPicker tr.Hex td.Text input.AHex{width:20px}.jPicker .Grid{text-align:center;width:114px}.jPicker .Grid span.QuickColor{border:1px inset #aaa;cursor:pointer;display:inline-block;height:15px;line-height:15px;margin:0;padding:0;width:19px}.jPicker .Grid span[class="QuickColor"]{width:17px}
trunk/assets/libraries/jpicker/css/jPicker.css ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @media all
2
+ {
3
+ #jPicker { margin: 0px 8px; text-align: left; }
4
+ #jPicker ul { font-size: 15px; margin: 0px 0px 0px 15px; padding: 0px; }
5
+ #jPicker ul li { list-style: disc; padding: 2px 0px; }
6
+ #jPicker ul li ul { margin-bottom: 10px; }
7
+ #jPicker ul li ul li { list-style: circle; }
8
+ #jPicker p { font-size: 13px; padding: 0px 10px; }
9
+ #jPicker hr { clear: both; }
10
+ #jPicker h2.jPicker { font-size: 16px; padding: 20px 10px; }
11
+ #jPicker code { color: #8bd; font-size: 14px; font-weight: bold; }
12
+ #jPicker pre { background: #eee; border: 1px solid #000; color: #000; display: block; font-size: 11px; margin: 10px 5px; padding: 5px; }
13
+ #jPicker span { font-size: 13px; text-align: center; }
14
+ #jPicker a { color: #ff8050; }
15
+ #jPicker input { font-size: 13px; padding: 2px 5px; }
16
+ #jPicker h2 { font-size: 16px; margin: 10px 0px; }
17
+ }
trunk/assets/libraries/jpicker/images/AlphaBar.png ADDED
Binary file
trunk/assets/libraries/jpicker/images/Bars.png ADDED
Binary file
trunk/assets/libraries/jpicker/images/Maps.png ADDED
Binary file
trunk/assets/libraries/jpicker/images/NoColor.png ADDED
Binary file
trunk/assets/libraries/jpicker/images/bar-opacity.png ADDED
Binary file
trunk/assets/libraries/jpicker/images/map-opacity.png ADDED
Binary file
trunk/assets/libraries/jpicker/images/mappoint.gif ADDED
Binary file
trunk/assets/libraries/jpicker/images/picker.gif ADDED
Binary file
trunk/assets/libraries/jpicker/images/preview-opacity.png ADDED
Binary file
trunk/assets/libraries/jpicker/images/rangearrows.gif ADDED
Binary file
trunk/assets/libraries/jpicker/jpicker-1.1.6.min.js ADDED
@@ -0,0 +1 @@
 
1
+ (function(e,a){Math.precision=function(j,h){if(h===undefined){h=0}return Math.round(j*Math.pow(10,h))/Math.pow(10,h)};var d=function(z,k){var o=this,j=z.find("img:first"),F=0,E=100,w=100,D=0,C=100,v=100,s=0,p=0,n,q,u=new Array(),l=function(y){for(var x=0;x<u.length;x++){u[x].call(o,o,y)}},H=function(x){var y=z.offset();n={l:y.left|0,t:y.top|0};clearTimeout(q);q=setTimeout(function(){A.call(o,x)},0);e(document).bind("mousemove",h).bind("mouseup",B);x.preventDefault()},h=function(x){clearTimeout(q);q=setTimeout(function(){A.call(o,x)},0);x.stopPropagation();x.preventDefault();return false},B=function(x){e(document).unbind("mouseup",B).unbind("mousemove",h);x.stopPropagation();x.preventDefault();return false},A=function(M){var K=M.pageX-n.l,x=M.pageY-n.t,L=z.w,y=z.h;if(K<0){K=0}else{if(K>L){K=L}}if(x<0){x=0}else{if(x>y){x=y}}J.call(o,"xy",{x:((K/L)*w)+F,y:((x/y)*v)+D})},r=function(){var L=0,x=0,N=z.w,K=z.h,M=j.w,y=j.h;setTimeout(function(){if(w>0){if(s==E){L=N}else{L=((s/w)*N)|0}}if(v>0){if(p==C){x=K}else{x=((p/v)*K)|0}}if(M>=N){L=(N>>1)-(M>>1)}else{L-=M>>1}if(y>=K){x=(K>>1)-(y>>1)}else{x-=y>>1}j.css({left:L+"px",top:x+"px"})},0)},J=function(x,K,y){var O=K!==undefined;if(!O){if(x===undefined||x==null){x="xy"}switch(x.toLowerCase()){case"x":return s;case"y":return p;case"xy":default:return{x:s,y:p}}}if(y!=null&&y==o){return}var N=false,M,L;if(x==null){x="xy"}switch(x.toLowerCase()){case"x":M=K&&(K.x&&K.x|0||K|0)||0;break;case"y":L=K&&(K.y&&K.y|0||K|0)||0;break;case"xy":default:M=K&&K.x&&K.x|0||0;L=K&&K.y&&K.y|0||0;break}if(M!=null){if(M<F){M=F}else{if(M>E){M=E}}if(s!=M){s=M;N=true}}if(L!=null){if(L<D){L=D}else{if(L>C){L=C}}if(p!=L){p=L;N=true}}N&&l.call(o,y||o)},t=function(x,L){var P=L!==undefined;if(!P){if(x===undefined||x==null){x="all"}switch(x.toLowerCase()){case"minx":return F;case"maxx":return E;case"rangex":return{minX:F,maxX:E,rangeX:w};case"miny":return D;case"maxy":return C;case"rangey":return{minY:D,maxY:C,rangeY:v};case"all":default:return{minX:F,maxX:E,rangeX:w,minY:D,maxY:C,rangeY:v}}}var O=false,N,K,M,y;if(x==null){x="all"}switch(x.toLowerCase()){case"minx":N=L&&(L.minX&&L.minX|0||L|0)||0;break;case"maxx":K=L&&(L.maxX&&L.maxX|0||L|0)||0;break;case"rangex":N=L&&L.minX&&L.minX|0||0;K=L&&L.maxX&&L.maxX|0||0;break;case"miny":M=L&&(L.minY&&L.minY|0||L|0)||0;break;case"maxy":y=L&&(L.maxY&&L.maxY|0||L|0)||0;break;case"rangey":M=L&&L.minY&&L.minY|0||0;y=L&&L.maxY&&L.maxY|0||0;break;case"all":default:N=L&&L.minX&&L.minX|0||0;K=L&&L.maxX&&L.maxX|0||0;M=L&&L.minY&&L.minY|0||0;y=L&&L.maxY&&L.maxY|0||0;break}if(N!=null&&F!=N){F=N;w=E-F}if(K!=null&&E!=K){E=K;w=E-F}if(M!=null&&D!=M){D=M;v=C-D}if(y!=null&&C!=y){C=y;v=C-D}},I=function(x){if(e.isFunction(x)){u.push(x)}},m=function(y){if(!e.isFunction(y)){return}var x;while((x=e.inArray(y,u))!=-1){u.splice(x,1)}},G=function(){e(document).unbind("mouseup",B).unbind("mousemove",h);z.unbind("mousedown",H);z=null;j=null;u=null};e.extend(true,o,{val:J,range:t,bind:I,unbind:m,destroy:G});j.src=k.arrow&&k.arrow.image;j.w=k.arrow&&k.arrow.width||j.width();j.h=k.arrow&&k.arrow.height||j.height();z.w=k.map&&k.map.width||z.width();z.h=k.map&&k.map.height||z.height();z.bind("mousedown",H);I.call(o,r)},b=function(u,z,k,y){var q=this,l=u.find("td.Text input"),r=l.eq(3),v=l.eq(4),h=l.eq(5),o=l.length>7?l.eq(6):null,n=l.eq(0),p=l.eq(1),x=l.eq(2),s=l.eq(l.length>7?7:6),B=l.length>7?l.eq(8):null,C=function(E){if(E.target.value==""&&E.target!=s.get(0)&&(k!=null&&E.target!=k.get(0)||k==null)){return}if(!t(E)){return E}switch(E.target){case r.get(0):switch(E.keyCode){case 38:r.val(j.call(q,(r.val()<<0)+1,0,255));z.val("r",r.val(),E.target);return false;case 40:r.val(j.call(q,(r.val()<<0)-1,0,255));z.val("r",r.val(),E.target);return false}break;case v.get(0):switch(E.keyCode){case 38:v.val(j.call(q,(v.val()<<0)+1,0,255));z.val("g",v.val(),E.target);return false;case 40:v.val(j.call(q,(v.val()<<0)-1,0,255));z.val("g",v.val(),E.target);return false}break;case h.get(0):switch(E.keyCode){case 38:h.val(j.call(q,(h.val()<<0)+1,0,255));z.val("b",h.val(),E.target);return false;case 40:h.val(j.call(q,(h.val()<<0)-1,0,255));z.val("b",h.val(),E.target);return false}break;case o&&o.get(0):switch(E.keyCode){case 38:o.val(j.call(q,parseFloat(o.val())+1,0,100));z.val("a",Math.precision((o.val()*255)/100,y),E.target);return false;case 40:o.val(j.call(q,parseFloat(o.val())-1,0,100));z.val("a",Math.precision((o.val()*255)/100,y),E.target);return false}break;case n.get(0):switch(E.keyCode){case 38:n.val(j.call(q,(n.val()<<0)+1,0,360));z.val("h",n.val(),E.target);return false;case 40:n.val(j.call(q,(n.val()<<0)-1,0,360));z.val("h",n.val(),E.target);return false}break;case p.get(0):switch(E.keyCode){case 38:p.val(j.call(q,(p.val()<<0)+1,0,100));z.val("s",p.val(),E.target);return false;case 40:p.val(j.call(q,(p.val()<<0)-1,0,100));z.val("s",p.val(),E.target);return false}break;case x.get(0):switch(E.keyCode){case 38:x.val(j.call(q,(x.val()<<0)+1,0,100));z.val("v",x.val(),E.target);return false;case 40:x.val(j.call(q,(x.val()<<0)-1,0,100));z.val("v",x.val(),E.target);return false}break}},w=function(E){if(E.target.value==""&&E.target!=s.get(0)&&(k!=null&&E.target!=k.get(0)||k==null)){return}if(!t(E)){return E}switch(E.target){case r.get(0):r.val(j.call(q,r.val(),0,255));z.val("r",r.val(),E.target);break;case v.get(0):v.val(j.call(q,v.val(),0,255));z.val("g",v.val(),E.target);break;case h.get(0):h.val(j.call(q,h.val(),0,255));z.val("b",h.val(),E.target);break;case o&&o.get(0):o.val(j.call(q,o.val(),0,100));z.val("a",Math.precision((o.val()*255)/100,y),E.target);break;case n.get(0):n.val(j.call(q,n.val(),0,360));z.val("h",n.val(),E.target);break;case p.get(0):p.val(j.call(q,p.val(),0,100));z.val("s",p.val(),E.target);break;case x.get(0):x.val(j.call(q,x.val(),0,100));z.val("v",x.val(),E.target);break;case s.get(0):s.val(s.val().replace(/[^a-fA-F0-9]/g,"").toLowerCase().substring(0,6));k&&k.val(s.val());z.val("hex",s.val()!=""?s.val():null,E.target);break;case k&&k.get(0):k.val(k.val().replace(/[^a-fA-F0-9]/g,"").toLowerCase().substring(0,6));s.val(k.val());z.val("hex",k.val()!=""?k.val():null,E.target);break;case B&&B.get(0):B.val(B.val().replace(/[^a-fA-F0-9]/g,"").toLowerCase().substring(0,2));z.val("a",B.val()!=null?parseInt(B.val(),16):null,E.target);break}},A=function(E){if(z.val()!=null){switch(E.target){case r.get(0):r.val(z.val("r"));break;case v.get(0):v.val(z.val("g"));break;case h.get(0):h.val(z.val("b"));break;case o&&o.get(0):o.val(Math.precision((z.val("a")*100)/255,y));break;case n.get(0):n.val(z.val("h"));break;case p.get(0):p.val(z.val("s"));break;case x.get(0):x.val(z.val("v"));break;case s.get(0):case k&&k.get(0):s.val(z.val("hex"));k&&k.val(z.val("hex"));break;case B&&B.get(0):B.val(z.val("ahex").substring(6));break}}},t=function(E){switch(E.keyCode){case 9:case 16:case 29:case 37:case 39:return false;case"c".charCodeAt():case"v".charCodeAt():if(E.ctrlKey){return false}}return true},j=function(G,F,E){if(G==""||isNaN(G)){return F}if(G>E){return E}if(G<F){return F}return G},m=function(G,E){var F=G.val("all");if(E!=r.get(0)){r.val(F!=null?F.r:"")}if(E!=v.get(0)){v.val(F!=null?F.g:"")}if(E!=h.get(0)){h.val(F!=null?F.b:"")}if(o&&E!=o.get(0)){o.val(F!=null?Math.precision((F.a*100)/255,y):"")}if(E!=n.get(0)){n.val(F!=null?F.h:"")}if(E!=p.get(0)){p.val(F!=null?F.s:"")}if(E!=x.get(0)){x.val(F!=null?F.v:"")}if(E!=s.get(0)&&(k&&E!=k.get(0)||!k)){s.val(F!=null?F.hex:"")}if(k&&E!=k.get(0)&&E!=s.get(0)){k.val(F!=null?F.hex:"")}if(B&&E!=B.get(0)){B.val(F!=null?F.ahex.substring(6):"")}},D=function(){r.add(v).add(h).add(o).add(n).add(p).add(x).add(s).add(k).add(B).unbind("keyup",w).unbind("blur",A);r.add(v).add(h).add(o).add(n).add(p).add(x).unbind("keydown",C);z.unbind(m);r=null;v=null;h=null;o=null;n=null;p=null;x=null;s=null;B=null};e.extend(true,q,{destroy:D});r.add(v).add(h).add(o).add(n).add(p).add(x).add(s).add(k).add(B).bind("keyup",w).bind("blur",A);r.add(v).add(h).add(o).add(n).add(p).add(x).bind("keydown",C);z.bind(m)};e.jPicker={List:[],Color:function(z){var q=this,j,o,t,u,n,A,x,k=new Array(),m=function(r){for(var h=0;h<k.length;h++){k[h].call(q,q,r)}},l=function(h,G,r){var F=G!==undefined;if(!F){if(h===undefined||h==null||h==""){h="all"}if(j==null){return null}switch(h.toLowerCase()){case"ahex":return g.rgbaToHex({r:j,g:o,b:t,a:u});case"hex":return l("ahex").substring(0,6);case"all":return{r:j,g:o,b:t,a:u,h:n,s:A,v:x,hex:l.call(q,"hex"),ahex:l.call(q,"ahex")};default:var D={};for(var B=0;B<h.length;B++){switch(h.charAt(B)){case"r":if(h.length==1){D=j}else{D.r=j}break;case"g":if(h.length==1){D=o}else{D.g=o}break;case"b":if(h.length==1){D=t}else{D.b=t}break;case"a":if(h.length==1){D=u}else{D.a=u}break;case"h":if(h.length==1){D=n}else{D.h=n}break;case"s":if(h.length==1){D=A}else{D.s=A}break;case"v":if(h.length==1){D=x}else{D.v=x}break}}return D=={}?l.call(q,"all"):D;break}}if(r!=null&&r==q){return}var v=false;if(h==null){h=""}if(G==null){if(j!=null){j=null;v=true}if(o!=null){o=null;v=true}if(t!=null){t=null;v=true}if(u!=null){u=null;v=true}if(n!=null){n=null;v=true}if(A!=null){A=null;v=true}if(x!=null){x=null;v=true}v&&m.call(q,r||q);return}switch(h.toLowerCase()){case"ahex":case"hex":var D=g.hexToRgba(G&&(G.ahex||G.hex)||G||"00000000");l.call(q,"rgba",{r:D.r,g:D.g,b:D.b,a:h=="ahex"?D.a:u!=null?u:255},r);break;default:if(G&&(G.ahex!=null||G.hex!=null)){l.call(q,"ahex",G.ahex||G.hex||"00000000",r);return}var s={},E=false,C=false;if(G.r!==undefined&&!h.indexOf("r")==-1){h+="r"}if(G.g!==undefined&&!h.indexOf("g")==-1){h+="g"}if(G.b!==undefined&&!h.indexOf("b")==-1){h+="b"}if(G.a!==undefined&&!h.indexOf("a")==-1){h+="a"}if(G.h!==undefined&&!h.indexOf("h")==-1){h+="h"}if(G.s!==undefined&&!h.indexOf("s")==-1){h+="s"}if(G.v!==undefined&&!h.indexOf("v")==-1){h+="v"}for(var B=0;B<h.length;B++){switch(h.charAt(B)){case"r":if(C){continue}E=true;s.r=G&&G.r&&G.r|0||G&&G|0||0;if(s.r<0){s.r=0}else{if(s.r>255){s.r=255}}if(j!=s.r){j=s.r;v=true}break;case"g":if(C){continue}E=true;s.g=G&&G.g&&G.g|0||G&&G|0||0;if(s.g<0){s.g=0}else{if(s.g>255){s.g=255}}if(o!=s.g){o=s.g;v=true}break;case"b":if(C){continue}E=true;s.b=G&&G.b&&G.b|0||G&&G|0||0;if(s.b<0){s.b=0}else{if(s.b>255){s.b=255}}if(t!=s.b){t=s.b;v=true}break;case"a":s.a=G&&G.a!=null?G.a|0:G!=null?G|0:255;if(s.a<0){s.a=0}else{if(s.a>255){s.a=255}}if(u!=s.a){u=s.a;v=true}break;case"h":if(E){continue}C=true;s.h=G&&G.h&&G.h|0||G&&G|0||0;if(s.h<0){s.h=0}else{if(s.h>360){s.h=360}}if(n!=s.h){n=s.h;v=true}break;case"s":if(E){continue}C=true;s.s=G&&G.s!=null?G.s|0:G!=null?G|0:100;if(s.s<0){s.s=0}else{if(s.s>100){s.s=100}}if(A!=s.s){A=s.s;v=true}break;case"v":if(E){continue}C=true;s.v=G&&G.v!=null?G.v|0:G!=null?G|0:100;if(s.v<0){s.v=0}else{if(s.v>100){s.v=100}}if(x!=s.v){x=s.v;v=true}break}}if(v){if(E){j=j||0;o=o||0;t=t||0;var D=g.rgbToHsv({r:j,g:o,b:t});n=D.h;A=D.s;x=D.v}else{if(C){n=n||0;A=A!=null?A:100;x=x!=null?x:100;var D=g.hsvToRgb({h:n,s:A,v:x});j=D.r;o=D.g;t=D.b}}u=u!=null?u:255;m.call(q,r||q)}break}},p=function(h){if(e.isFunction(h)){k.push(h)}},y=function(r){if(!e.isFunction(r)){return}var h;while((h=e.inArray(r,k))!=-1){k.splice(h,1)}},w=function(){k=null};e.extend(true,q,{val:l,bind:p,unbind:y,destroy:w});if(z){if(z.ahex!=null){l("ahex",z)}else{if(z.hex!=null){l((z.a!=null?"a":"")+"hex",z.a!=null?{ahex:z.hex+g.intToHex(z.a)}:z)}else{if(z.r!=null&&z.g!=null&&z.b!=null){l("rgb"+(z.a!=null?"a":""),z)}else{if(z.h!=null&&z.s!=null&&z.v!=null){l("hsv"+(z.a!=null?"a":""),z)}}}}}},ColorMethods:{hexToRgba:function(m){m=this.validateHex(m);if(m==""){return{r:null,g:null,b:null,a:null}}var l="00",k="00",h="00",j="255";if(m.length==6){m+="ff"}if(m.length>6){l=m.substring(0,2);k=m.substring(2,4);h=m.substring(4,6);j=m.substring(6,m.length)}else{if(m.length>4){l=m.substring(4,m.length);m=m.substring(0,4)}if(m.length>2){k=m.substring(2,m.length);m=m.substring(0,2)}if(m.length>0){h=m.substring(0,m.length)}}return{r:this.hexToInt(l),g:this.hexToInt(k),b:this.hexToInt(h),a:this.hexToInt(j)}},validateHex:function(h){h=h.toLowerCase().replace(/[^a-f0-9]/g,"");if(h.length>8){h=h.substring(0,8)}return h},rgbaToHex:function(h){return this.intToHex(h.r)+this.intToHex(h.g)+this.intToHex(h.b)+this.intToHex(h.a)},intToHex:function(j){var h=(j|0).toString(16);if(h.length==1){h=("0"+h)}return h.toLowerCase()},hexToInt:function(h){return parseInt(h,16)},rgbToHsv:function(l){var o=l.r/255,n=l.g/255,j=l.b/255,k={h:0,s:0,v:0},m=0,h=0,p;if(o>=n&&o>=j){h=o;m=n>j?j:n}else{if(n>=j&&n>=o){h=n;m=o>j?j:o}else{h=j;m=n>o?o:n}}k.v=h;k.s=h?(h-m)/h:0;if(!k.s){k.h=0}else{p=h-m;if(o==h){k.h=(n-j)/p}else{if(n==h){k.h=2+(j-o)/p}else{k.h=4+(o-n)/p}}k.h=parseInt(k.h*60);if(k.h<0){k.h+=360}}k.s=(k.s*100)|0;k.v=(k.v*100)|0;return k},hsvToRgb:function(n){var r={r:0,g:0,b:0,a:100},m=n.h,x=n.s,u=n.v;if(x==0){if(u==0){r.r=r.g=r.b=0}else{r.r=r.g=r.b=(u*255/100)|0}}else{if(m==360){m=0}m/=60;x=x/100;u=u/100;var l=m|0,o=m-l,k=u*(1-x),j=u*(1-(x*o)),w=u*(1-(x*(1-o)));switch(l){case 0:r.r=u;r.g=w;r.b=k;break;case 1:r.r=j;r.g=u;r.b=k;break;case 2:r.r=k;r.g=u;r.b=w;break;case 3:r.r=k;r.g=j;r.b=u;break;case 4:r.r=w;r.g=k;r.b=u;break;case 5:r.r=u;r.g=k;r.b=j;break}r.r=(r.r*255)|0;r.g=(r.g*255)|0;r.b=(r.b*255)|0}return r}}};var f=e.jPicker.Color,c=e.jPicker.List,g=e.jPicker.ColorMethods;e.fn.jPicker=function(j){var h=arguments;return this.each(function(){var w=this,av=e.extend(true,{},e.fn.jPicker.defaults,j);if(e(w).get(0).nodeName.toLowerCase()=="input"){e.extend(true,av,{window:{bindToInput:true,expandable:true,input:e(w)}});if(e(w).val()==""){av.color.active=new f({hex:null});av.color.current=new f({hex:null})}else{if(g.validateHex(e(w).val())){av.color.active=new f({hex:e(w).val(),a:av.color.active.val("a")});av.color.current=new f({hex:e(w).val(),a:av.color.active.val("a")})}}}if(av.window.expandable){e(w).after('<span class="jPicker"><span class="Icon"><span class="Color">&nbsp;</span><span class="Alpha">&nbsp;</span><span class="Image" title="Click To Open Color Picker">&nbsp;</span><span class="Container">&nbsp;</span></span></span>')}else{av.window.liveUpdate=false}var Q=parseFloat(navigator.appVersion.split("MSIE")[1])<7&&document.body.filters,R=null,l=null,s=null,au=null,at=null,ar=null,P=null,O=null,N=null,M=null,L=null,K=null,D=null,U=null,aw=null,J=null,I=null,am=null,ai=null,E=null,an=null,ah=null,X=null,ab=null,aq=null,r=null,C=null,u=null,ag=function(aB){var aD=G.active,aE=n.clientPath,aA=aD.val("hex"),aC,az;av.color.mode=aB;switch(aB){case"h":setTimeout(function(){y.call(w,l,"transparent");x.call(w,au,0);Y.call(w,au,100);x.call(w,at,260);Y.call(w,at,100);y.call(w,s,"transparent");x.call(w,P,0);Y.call(w,P,100);x.call(w,O,260);Y.call(w,O,100);x.call(w,N,260);Y.call(w,N,100);x.call(w,M,260);Y.call(w,M,100);x.call(w,K,260);Y.call(w,K,100)},0);D.range("all",{minX:0,maxX:100,minY:0,maxY:100});U.range("rangeY",{minY:0,maxY:360});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("s"),y:100-aD.val("v")},D);U.val("y",360-aD.val("h"),U);break;case"s":setTimeout(function(){y.call(w,l,"transparent");x.call(w,au,-260);x.call(w,at,-520);x.call(w,P,-260);x.call(w,O,-520);x.call(w,K,260);Y.call(w,K,100)},0);D.range("all",{minX:0,maxX:360,minY:0,maxY:100});U.range("rangeY",{minY:0,maxY:100});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("h"),y:100-aD.val("v")},D);U.val("y",100-aD.val("s"),U);break;case"v":setTimeout(function(){y.call(w,l,"000000");x.call(w,au,-780);x.call(w,at,260);y.call(w,s,aA);x.call(w,P,-520);x.call(w,O,260);Y.call(w,O,100);x.call(w,K,260);Y.call(w,K,100)},0);D.range("all",{minX:0,maxX:360,minY:0,maxY:100});U.range("rangeY",{minY:0,maxY:100});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("h"),y:100-aD.val("s")},D);U.val("y",100-aD.val("v"),U);break;case"r":aC=-1040;az=-780;D.range("all",{minX:0,maxX:255,minY:0,maxY:255});U.range("rangeY",{minY:0,maxY:255});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("b"),y:255-aD.val("g")},D);U.val("y",255-aD.val("r"),U);break;case"g":aC=-1560;az=-1820;D.range("all",{minX:0,maxX:255,minY:0,maxY:255});U.range("rangeY",{minY:0,maxY:255});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("b"),y:255-aD.val("r")},D);U.val("y",255-aD.val("g"),U);break;case"b":aC=-2080;az=-2860;D.range("all",{minX:0,maxX:255,minY:0,maxY:255});U.range("rangeY",{minY:0,maxY:255});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("r"),y:255-aD.val("g")},D);U.val("y",255-aD.val("b"),U);break;case"a":setTimeout(function(){y.call(w,l,"transparent");x.call(w,au,-260);x.call(w,at,-520);x.call(w,P,260);x.call(w,O,260);Y.call(w,O,100);x.call(w,K,0);Y.call(w,K,100)},0);D.range("all",{minX:0,maxX:360,minY:0,maxY:100});U.range("rangeY",{minY:0,maxY:255});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("h"),y:100-aD.val("v")},D);U.val("y",255-aD.val("a"),U);break;default:throw ("Invalid Mode");break}switch(aB){case"h":break;case"s":case"v":case"a":setTimeout(function(){Y.call(w,au,100);Y.call(w,P,100);x.call(w,N,260);Y.call(w,N,100);x.call(w,M,260);Y.call(w,M,100)},0);break;case"r":case"g":case"b":setTimeout(function(){y.call(w,l,"transparent");y.call(w,s,"transparent");Y.call(w,P,100);Y.call(w,au,100);x.call(w,au,aC);x.call(w,at,aC-260);x.call(w,P,az-780);x.call(w,O,az-520);x.call(w,N,az);x.call(w,M,az-260);x.call(w,K,260);Y.call(w,K,100)},0);break}if(aD.val("ahex")==null){return}aj.call(w,aD)},aj=function(aA,az){if(az==null||(az!=U&&az!=D)){v.call(w,aA,az)}setTimeout(function(){ay.call(w,aA);al.call(w,aA);W.call(w,aA)},0)},z=function(aA,az){var aC=G.active;if(az!=D&&aC.val()==null){return}var aB=aA.val("all");switch(av.color.mode){case"h":aC.val("sv",{s:aB.x,v:100-aB.y},az);break;case"s":case"a":aC.val("hv",{h:aB.x,v:100-aB.y},az);break;case"v":aC.val("hs",{h:aB.x,s:100-aB.y},az);break;case"r":aC.val("gb",{g:255-aB.y,b:aB.x},az);break;case"g":aC.val("rb",{r:255-aB.y,b:aB.x},az);break;case"b":aC.val("rg",{r:aB.x,g:255-aB.y},az);break}},ac=function(aA,az){var aB=G.active;if(az!=U&&aB.val()==null){return}switch(av.color.mode){case"h":aB.val("h",{h:360-aA.val("y")},az);break;case"s":aB.val("s",{s:100-aA.val("y")},az);break;case"v":aB.val("v",{v:100-aA.val("y")},az);break;case"r":aB.val("r",{r:255-aA.val("y")},az);break;case"g":aB.val("g",{g:255-aA.val("y")},az);break;case"b":aB.val("b",{b:255-aA.val("y")},az);break;case"a":aB.val("a",255-aA.val("y"),az);break}},v=function(aC,az){if(az!=D){switch(av.color.mode){case"h":var aH=aC.val("sv");D.val("xy",{x:aH!=null?aH.s:100,y:100-(aH!=null?aH.v:100)},az);break;case"s":case"a":var aB=aC.val("hv");D.val("xy",{x:aB&&aB.h||0,y:100-(aB!=null?aB.v:100)},az);break;case"v":var aE=aC.val("hs");D.val("xy",{x:aE&&aE.h||0,y:100-(aE!=null?aE.s:100)},az);break;case"r":var aA=aC.val("bg");D.val("xy",{x:aA&&aA.b||0,y:255-(aA&&aA.g||0)},az);break;case"g":var aI=aC.val("br");D.val("xy",{x:aI&&aI.b||0,y:255-(aI&&aI.r||0)},az);break;case"b":var aG=aC.val("rg");D.val("xy",{x:aG&&aG.r||0,y:255-(aG&&aG.g||0)},az);break}}if(az!=U){switch(av.color.mode){case"h":U.val("y",360-(aC.val("h")||0),az);break;case"s":var aJ=aC.val("s");U.val("y",100-(aJ!=null?aJ:100),az);break;case"v":var aF=aC.val("v");U.val("y",100-(aF!=null?aF:100),az);break;case"r":U.val("y",255-(aC.val("r")||0),az);break;case"g":U.val("y",255-(aC.val("g")||0),az);break;case"b":U.val("y",255-(aC.val("b")||0),az);break;case"a":var aD=aC.val("a");U.val("y",255-(aD!=null?aD:255),az);break}}},ay=function(aA){try{var az=aA.val("all");E.css({backgroundColor:az&&"#"+az.hex||"transparent"});Y.call(w,E,az&&Math.precision((az.a*100)/255,4)||0)}catch(aB){}},al=function(aC){switch(av.color.mode){case"h":y.call(w,l,new f({h:aC.val("h")||0,s:100,v:100}).val("hex"));break;case"s":case"a":var aB=aC.val("s");Y.call(w,at,100-(aB!=null?aB:100));break;case"v":var aA=aC.val("v");Y.call(w,au,aA!=null?aA:100);break;case"r":Y.call(w,at,Math.precision((aC.val("r")||0)/255*100,4));break;case"g":Y.call(w,at,Math.precision((aC.val("g")||0)/255*100,4));break;case"b":Y.call(w,at,Math.precision((aC.val("b")||0)/255*100));break}var az=aC.val("a");Y.call(w,ar,Math.precision(((255-(az||0))*100)/255,4))},W=function(aF){switch(av.color.mode){case"h":var aH=aF.val("a");Y.call(w,L,Math.precision(((255-(aH||0))*100)/255,4));break;case"s":var aA=aF.val("hva"),aB=new f({h:aA&&aA.h||0,s:100,v:aA!=null?aA.v:100});y.call(w,s,aB.val("hex"));Y.call(w,O,100-(aA!=null?aA.v:100));Y.call(w,L,Math.precision(((255-(aA&&aA.a||0))*100)/255,4));break;case"v":var aC=aF.val("hsa"),aE=new f({h:aC&&aC.h||0,s:aC!=null?aC.s:100,v:100});y.call(w,s,aE.val("hex"));Y.call(w,L,Math.precision(((255-(aC&&aC.a||0))*100)/255,4));break;case"r":case"g":case"b":var aD=0,aG=0,az=aF.val("rgba");if(av.color.mode=="r"){aD=az&&az.b||0;aG=az&&az.g||0}else{if(av.color.mode=="g"){aD=az&&az.b||0;aG=az&&az.r||0}else{if(av.color.mode=="b"){aD=az&&az.r||0;aG=az&&az.g||0}}}var aI=aG>aD?aD:aG;Y.call(w,O,aD>aG?Math.precision(((aD-aG)/(255-aG))*100,4):0);Y.call(w,N,aG>aD?Math.precision(((aG-aD)/(255-aD))*100,4):0);Y.call(w,M,Math.precision((aI/255)*100,4));Y.call(w,L,Math.precision(((255-(az&&az.a||0))*100)/255,4));break;case"a":var aH=aF.val("a");y.call(w,s,aF.val("hex")||"000000");Y.call(w,L,aH!=null?0:100);Y.call(w,K,aH!=null?100:0);break}},y=function(az,aA){az.css({backgroundColor:aA&&aA.length==6&&"#"+aA||"transparent"})},t=function(az,aA){if(Q&&(aA.indexOf("AlphaBar.png")!=-1||aA.indexOf("Bars.png")!=-1||aA.indexOf("Maps.png")!=-1)){az.attr("pngSrc",aA);az.css({backgroundImage:"none",filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aA+"', sizingMethod='scale')"})}else{az.css({backgroundImage:"url('"+aA+"')"})}},x=function(az,aA){az.css({top:aA+"px"})},Y=function(aA,az){aA.css({visibility:az>0?"visible":"hidden"});if(az>0&&az<100){if(Q){var aB=aA.attr("pngSrc");if(aB!=null&&(aB.indexOf("AlphaBar.png")!=-1||aB.indexOf("Bars.png")!=-1||aB.indexOf("Maps.png")!=-1)){aA.css({filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aB+"', sizingMethod='scale') progid:DXImageTransform.Microsoft.Alpha(opacity="+az+")"})}else{aA.css({opacity:Math.precision(az/100,4)})}}else{aA.css({opacity:Math.precision(az/100,4)})}}else{if(az==0||az==100){if(Q){var aB=aA.attr("pngSrc");if(aB!=null&&(aB.indexOf("AlphaBar.png")!=-1||aB.indexOf("Bars.png")!=-1||aB.indexOf("Maps.png")!=-1)){aA.css({filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aB+"', sizingMethod='scale')"})}else{aA.css({opacity:""})}}else{aA.css({opacity:""})}}}},B=function(){G.active.val("ahex",G.current.val("ahex"))},T=function(){G.current.val("ahex",G.active.val("ahex"))},A=function(az){e(this).parents("tbody:first").find('input:radio[value!="'+az.target.value+'"]').removeAttr("checked");ag.call(w,az.target.value)},Z=function(){B.call(w)},q=function(){B.call(w);av.window.expandable&&ao.call(w);e.isFunction(ax)&&ax.call(w,G.active,X)},m=function(){T.call(w);av.window.expandable&&ao.call(w);e.isFunction(ae)&&ae.call(w,G.active,ah)},af=function(){V.call(w)},ap=function(aB,az){var aA=aB.val("hex");an.css({backgroundColor:aA&&"#"+aA||"transparent"});Y.call(w,an,Math.precision(((aB.val("a")||0)*100)/255,4))},H=function(aC,az){var aB=aC.val("hex");var aA=aC.val("va");aq.css({backgroundColor:aB&&"#"+aB||"transparent"});Y.call(w,r,Math.precision(((255-(aA&&aA.a||0))*100)/255,4));if(av.window.bindToInput&&av.window.updateInputColor){av.window.input.css({backgroundColor:aB&&"#"+aB||"transparent",color:aA==null||aA.v>75?"#000000":"#ffffff"})}},S=function(aB){var az=av.window.element,aA=av.window.page;J=parseInt(R.css("left"));I=parseInt(R.css("top"));am=aB.pageX;ai=aB.pageY;e(document).bind("mousemove",k).bind("mouseup",p);aB.preventDefault()},k=function(az){R.css({left:J-(am-az.pageX)+"px",top:I-(ai-az.pageY)+"px"});if(av.window.expandable&&!e.support.boxModel){R.prev().css({left:R.css("left"),top:R.css("top")})}az.stopPropagation();az.preventDefault();return false},p=function(az){e(document).unbind("mousemove",k).unbind("mouseup",p);az.stopPropagation();az.preventDefault();return false},F=function(az){az.preventDefault();az.stopPropagation();G.active.val("ahex",e(this).attr("title")||null,az.target);return false},ae=e.isFunction(h[1])&&h[1]||null,ad=e.isFunction(h[2])&&h[2]||null,ax=e.isFunction(h[3])&&h[3]||null,V=function(){G.current.val("ahex",G.active.val("ahex"));var az=function(){if(!av.window.expandable||e.support.boxModel){return}var aA=R.find("table:first");R.before("<iframe/>");R.prev().css({width:aA.width(),height:R.height(),opacity:0,position:"absolute",left:R.css("left"),top:R.css("top")})};if(av.window.expandable){e(document.body).children("div.jPicker.Container").css({zIndex:10});R.css({zIndex:20})}switch(av.window.effects.type){case"fade":R.fadeIn(av.window.effects.speed.show,az);break;case"slide":R.slideDown(av.window.effects.speed.show,az);break;case"show":default:R.show(av.window.effects.speed.show,az);break}},ao=function(){var az=function(){if(av.window.expandable){R.css({zIndex:10})}if(!av.window.expandable||e.support.boxModel){return}R.prev().remove()};switch(av.window.effects.type){case"fade":R.fadeOut(av.window.effects.speed.hide,az);break;case"slide":R.slideUp(av.window.effects.speed.hide,az);break;case"show":default:R.hide(av.window.effects.speed.hide,az);break}},o=function(){var aG=av.window,az=aG.expandable?e(w).next().find(".Container:first"):null;R=aG.expandable?e("<div/>"):e(w);R.addClass("jPicker Container");if(aG.expandable){R.hide()}R.get(0).onselectstart=function(aN){if(aN.target.nodeName.toLowerCase()!=="input"){return false}};var aJ=G.active.val("all");if(aG.alphaPrecision<0){aG.alphaPrecision=0}else{if(aG.alphaPrecision>2){aG.alphaPrecision=2}}var aK='<table class="jPicker" cellpadding="0" cellspacing="0"><tbody>'+(aG.expandable?'<tr><td class="Move" colspan="5">&nbsp;</td></tr>':"")+'<tr><td rowspan="9"><h2 class="Title">'+(aG.title||aa.text.title)+'</h2><div class="Map"><span class="Map1">&nbsp;</span><span class="Map2">&nbsp;</span><span class="Map3">&nbsp;</span><img src="'+n.clientPath+n.colorMap.arrow.file+'" class="Arrow"/></div></td><td rowspan="9"><div class="Bar"><span class="Map1">&nbsp;</span><span class="Map2">&nbsp;</span><span class="Map3">&nbsp;</span><span class="Map4">&nbsp;</span><span class="Map5">&nbsp;</span><span class="Map6">&nbsp;</span><img src="'+n.clientPath+n.colorBar.arrow.file+'" class="Arrow"/></div></td><td colspan="2" class="Preview">'+aa.text.newColor+'<div><span class="Active" title="'+aa.tooltips.colors.newColor+'">&nbsp;</span><span class="Current" title="'+aa.tooltips.colors.currentColor+'">&nbsp;</span></div>'+aa.text.currentColor+'</td><td rowspan="9" class="Button"><input type="button" class="Ok" value="'+aa.text.ok+'" title="'+aa.tooltips.buttons.ok+'"/><input type="button" class="Cancel" value="'+aa.text.cancel+'" title="'+aa.tooltips.buttons.cancel+'"/><hr/><div class="Grid">&nbsp;</div></td></tr><tr class="Hue"><td class="Radio"><label title="'+aa.tooltips.hue.radio+'"><input type="radio" value="h"'+(av.color.mode=="h"?' checked="checked"':"")+'/>H:</label></td><td class="Text"><input type="text" maxlength="3" value="'+(aJ!=null?aJ.h:"")+'" title="'+aa.tooltips.hue.textbox+'"/>&nbsp;&deg;</td></tr><tr class="Saturation"><td class="Radio"><label title="'+aa.tooltips.saturation.radio+'"><input type="radio" value="s"'+(av.color.mode=="s"?' checked="checked"':"")+'/>S:</label></td><td class="Text"><input type="text" maxlength="3" value="'+(aJ!=null?aJ.s:"")+'" title="'+aa.tooltips.saturation.textbox+'"/>&nbsp;%</td></tr><tr class="Value"><td class="Radio"><label title="'+aa.tooltips.value.radio+'"><input type="radio" value="v"'+(av.color.mode=="v"?' checked="checked"':"")+'/>V:</label><br/><br/></td><td class="Text"><input type="text" maxlength="3" value="'+(aJ!=null?aJ.v:"")+'" title="'+aa.tooltips.value.textbox+'"/>&nbsp;%<br/><br/></td></tr><tr class="Red"><td class="Radio"><label title="'+aa.tooltips.red.radio+'"><input type="radio" value="r"'+(av.color.mode=="r"?' checked="checked"':"")+'/>R:</label></td><td class="Text"><input type="text" maxlength="3" value="'+(aJ!=null?aJ.r:"")+'" title="'+aa.tooltips.red.textbox+'"/></td></tr><tr class="Green"><td class="Radio"><label title="'+aa.tooltips.green.radio+'"><input type="radio" value="g"'+(av.color.mode=="g"?' checked="checked"':"")+'/>G:</label></td><td class="Text"><input type="text" maxlength="3" value="'+(aJ!=null?aJ.g:"")+'" title="'+aa.tooltips.green.textbox+'"/></td></tr><tr class="Blue"><td class="Radio"><label title="'+aa.tooltips.blue.radio+'"><input type="radio" value="b"'+(av.color.mode=="b"?' checked="checked"':"")+'/>B:</label></td><td class="Text"><input type="text" maxlength="3" value="'+(aJ!=null?aJ.b:"")+'" title="'+aa.tooltips.blue.textbox+'"/></td></tr><tr class="Alpha"><td class="Radio">'+(aG.alphaSupport?'<label title="'+aa.tooltips.alpha.radio+'"><input type="radio" value="a"'+(av.color.mode=="a"?' checked="checked"':"")+"/>A:</label>":"&nbsp;")+'</td><td class="Text">'+(aG.alphaSupport?'<input type="text" maxlength="'+(3+aG.alphaPrecision)+'" value="'+(aJ!=null?Math.precision((aJ.a*100)/255,aG.alphaPrecision):"")+'" title="'+aa.tooltips.alpha.textbox+'"/>&nbsp;%':"&nbsp;")+'</td></tr><tr class="Hex"><td colspan="2" class="Text"><label title="'+aa.tooltips.hex.textbox+'">#:<input type="text" maxlength="6" class="Hex" value="'+(aJ!=null?aJ.hex:"")+'"/></label>'+(aG.alphaSupport?'<input type="text" maxlength="2" class="AHex" value="'+(aJ!=null?aJ.ahex.substring(6):"")+'" title="'+aa.tooltips.hex.alpha+'"/></td>':"&nbsp;")+"</tr></tbody></table>";if(aG.expandable){R.html(aK);if(e(document.body).children("div.jPicker.Container").length==0){e(document.body).prepend(R)}else{e(document.body).children("div.jPicker.Container:last").after(R)}R.mousedown(function(){e(document.body).children("div.jPicker.Container").css({zIndex:10});R.css({zIndex:20})});R.css({left:aG.position.x=="left"?(az.offset().left-530-(aG.position.y=="center"?25:0))+"px":aG.position.x=="center"?(az.offset().left-260)+"px":aG.position.x=="right"?(az.offset().left-10+(aG.position.y=="center"?25:0))+"px":aG.position.x=="screenCenter"?((e(document).width()>>1)-260)+"px":(az.offset().left+parseInt(aG.position.x))+"px",position:"absolute",top:aG.position.y=="top"?(az.offset().top-312)+"px":aG.position.y=="center"?(az.offset().top-156)+"px":aG.position.y=="bottom"?(az.offset().top+25)+"px":(az.offset().top+parseInt(aG.position.y))+"px"})}else{R=e(w);R.html(aK)}var aD=R.find("tbody:first");l=aD.find("div.Map:first");s=aD.find("div.Bar:first");var aL=l.find("span"),aI=s.find("span");au=aL.filter(".Map1:first");at=aL.filter(".Map2:first");ar=aL.filter(".Map3:first");P=aI.filter(".Map1:first");O=aI.filter(".Map2:first");N=aI.filter(".Map3:first");M=aI.filter(".Map4:first");L=aI.filter(".Map5:first");K=aI.filter(".Map6:first");D=new d(l,{map:{width:n.colorMap.width,height:n.colorMap.height},arrow:{image:n.clientPath+n.colorMap.arrow.file,width:n.colorMap.arrow.width,height:n.colorMap.arrow.height}});D.bind(z);U=new d(s,{map:{width:n.colorBar.width,height:n.colorBar.height},arrow:{image:n.clientPath+n.colorBar.arrow.file,width:n.colorBar.arrow.width,height:n.colorBar.arrow.height}});U.bind(ac);aw=new b(aD,G.active,aG.expandable&&aG.bindToInput?aG.input:null,aG.alphaPrecision);var aB=aJ!=null?aJ.hex:null,aH=aD.find(".Preview"),aF=aD.find(".Button");E=aH.find(".Active:first").css({backgroundColor:aB&&"#"+aB||"transparent"});an=aH.find(".Current:first").css({backgroundColor:aB&&"#"+aB||"transparent"}).bind("click",Z);Y.call(w,an,Math.precision(G.current.val("a")*100)/255,4);ah=aF.find(".Ok:first").bind("click",m);X=aF.find(".Cancel:first").bind("click",q);ab=aF.find(".Grid:first");setTimeout(function(){t.call(w,au,n.clientPath+"Maps.png");t.call(w,at,n.clientPath+"Maps.png");t.call(w,ar,n.clientPath+"map-opacity.png");t.call(w,P,n.clientPath+"Bars.png");t.call(w,O,n.clientPath+"Bars.png");t.call(w,N,n.clientPath+"Bars.png");t.call(w,M,n.clientPath+"Bars.png");t.call(w,L,n.clientPath+"bar-opacity.png");t.call(w,K,n.clientPath+"AlphaBar.png");t.call(w,aH.find("div:first"),n.clientPath+"preview-opacity.png")},0);aD.find("td.Radio input").bind("click",A);if(G.quickList&&G.quickList.length>0){var aE="";for(i=0;i<G.quickList.length;i++){if((typeof(G.quickList[i])).toString().toLowerCase()=="string"){G.quickList[i]=new f({hex:G.quickList[i]})}var aC=G.quickList[i].val("a");var aM=G.quickList[i].val("ahex");if(!aG.alphaSupport&&aM){aM=aM.substring(0,6)+"ff"}var aA=G.quickList[i].val("hex");aE+='<span class="QuickColor"'+(aM&&' title="#'+aM+'"'||"")+' style="background-color:'+(aA&&"#"+aA||"")+";"+(aA?"":"background-image:url("+n.clientPath+"NoColor.png)")+(aG.alphaSupport&&aC&&aC<255?";opacity:"+Math.precision(aC/255,4)+";filter:Alpha(opacity="+Math.precision(aC/2.55,4)+")":"")+'">&nbsp;</span>'}t.call(w,ab,n.clientPath+"bar-opacity.png");ab.html(aE);ab.find(".QuickColor").click(F)}ag.call(w,av.color.mode);G.active.bind(aj);e.isFunction(ad)&&G.active.bind(ad);G.current.bind(ap);if(aG.expandable){w.icon=az.parents(".Icon:first");aq=w.icon.find(".Color:first").css({backgroundColor:aB&&"#"+aB||"transparent"});r=w.icon.find(".Alpha:first");t.call(w,r,n.clientPath+"bar-opacity.png");Y.call(w,r,Math.precision(((255-(aJ!=null?aJ.a:0))*100)/255,4));C=w.icon.find(".Image:first").css({backgroundImage:"url('"+n.clientPath+n.picker.file+"')"}).bind("click",af);if(aG.bindToInput&&aG.updateInputColor){aG.input.css({backgroundColor:aB&&"#"+aB||"transparent",color:aJ==null||aJ.v>75?"#000000":"#ffffff"})}u=aD.find(".Move:first").bind("mousedown",S);G.active.bind(H)}else{V.call(w)}},ak=function(){R.find("td.Radio input").unbind("click",A);an.unbind("click",Z);X.unbind("click",q);ah.unbind("click",m);if(av.window.expandable){C.unbind("click",af);u.unbind("mousedown",S);w.icon=null}R.find(".QuickColor").unbind("click",F);l=null;s=null;au=null;at=null;ar=null;P=null;O=null;N=null;M=null;L=null;K=null;D.destroy();D=null;U.destroy();U=null;aw.destroy();aw=null;E=null;an=null;ah=null;X=null;ab=null;ae=null;ax=null;ad=null;R.html("");for(i=0;i<c.length;i++){if(c[i]==w){c.splice(i,1)}}},n=av.images,aa=av.localization,G={active:(typeof(av.color.active)).toString().toLowerCase()=="string"?new f({ahex:!av.window.alphaSupport&&av.color.active?av.color.active.substring(0,6)+"ff":av.color.active}):new f({ahex:!av.window.alphaSupport&&av.color.active.val("ahex")?av.color.active.val("ahex").substring(0,6)+"ff":av.color.active.val("ahex")}),current:(typeof(av.color.active)).toString().toLowerCase()=="string"?new f({ahex:!av.window.alphaSupport&&av.color.active?av.color.active.substring(0,6)+"ff":av.color.active}):new f({ahex:!av.window.alphaSupport&&av.color.active.val("ahex")?av.color.active.val("ahex").substring(0,6)+"ff":av.color.active.val("ahex")}),quickList:av.color.quickList};e.extend(true,w,{commitCallback:ae,liveCallback:ad,cancelCallback:ax,color:G,show:V,hide:ao,destroy:ak});c.push(w);setTimeout(function(){o.call(w)},0)})};e.fn.jPicker.defaults={window:{title:null,effects:{type:"slide",speed:{show:"fast",hide:"fast"}},position:{x:"screenCenter",y:"top"},expandable:false,liveUpdate:true,alphaSupport:false,alphaPrecision:0,updateInputColor:true},color:{mode:"h",active:new f({ahex:"#ffcc00ff"}),quickList:[new f({h:360,s:33,v:100}),new f({h:360,s:66,v:100}),new f({h:360,s:100,v:100}),new f({h:360,s:100,v:75}),new f({h:360,s:100,v:50}),new f({h:180,s:0,v:100}),new f({h:30,s:33,v:100}),new f({h:30,s:66,v:100}),new f({h:30,s:100,v:100}),new f({h:30,s:100,v:75}),new f({h:30,s:100,v:50}),new f({h:180,s:0,v:90}),new f({h:60,s:33,v:100}),new f({h:60,s:66,v:100}),new f({h:60,s:100,v:100}),new f({h:60,s:100,v:75}),new f({h:60,s:100,v:50}),new f({h:180,s:0,v:80}),new f({h:90,s:33,v:100}),new f({h:90,s:66,v:100}),new f({h:90,s:100,v:100}),new f({h:90,s:100,v:75}),new f({h:90,s:100,v:50}),new f({h:180,s:0,v:70}),new f({h:120,s:33,v:100}),new f({h:120,s:66,v:100}),new f({h:120,s:100,v:100}),new f({h:120,s:100,v:75}),new f({h:120,s:100,v:50}),new f({h:180,s:0,v:60}),new f({h:150,s:33,v:100}),new f({h:150,s:66,v:100}),new f({h:150,s:100,v:100}),new f({h:150,s:100,v:75}),new f({h:150,s:100,v:50}),new f({h:180,s:0,v:50}),new f({h:180,s:33,v:100}),new f({h:180,s:66,v:100}),new f({h:180,s:100,v:100}),new f({h:180,s:100,v:75}),new f({h:180,s:100,v:50}),new f({h:180,s:0,v:40}),new f({h:210,s:33,v:100}),new f({h:210,s:66,v:100}),new f({h:210,s:100,v:100}),new f({h:210,s:100,v:75}),new f({h:210,s:100,v:50}),new f({h:180,s:0,v:30}),new f({h:240,s:33,v:100}),new f({h:240,s:66,v:100}),new f({h:240,s:100,v:100}),new f({h:240,s:100,v:75}),new f({h:240,s:100,v:50}),new f({h:180,s:0,v:20}),new f({h:270,s:33,v:100}),new f({h:270,s:66,v:100}),new f({h:270,s:100,v:100}),new f({h:270,s:100,v:75}),new f({h:270,s:100,v:50}),new f({h:180,s:0,v:10}),new f({h:300,s:33,v:100}),new f({h:300,s:66,v:100}),new f({h:300,s:100,v:100}),new f({h:300,s:100,v:75}),new f({h:300,s:100,v:50}),new f({h:180,s:0,v:0}),new f({h:330,s:33,v:100}),new f({h:330,s:66,v:100}),new f({h:330,s:100,v:100}),new f({h:330,s:100,v:75}),new f({h:330,s:100,v:50}),new f()]},images:{clientPath:jpicker.thispath,colorMap:{width:256,height:256,arrow:{file:"mappoint.gif",width:15,height:15}},colorBar:{width:20,height:256,arrow:{file:"rangearrows.gif",width:20,height:7}},picker:{file:"picker.gif",width:25,height:24}},localization:{text:{title:"Drag Markers To Pick A Color",newColor:"new",currentColor:"current",ok:"OK",cancel:"Cancel"},tooltips:{colors:{newColor:"New Color - Press &ldquo;OK&rdquo; To Commit",currentColor:"Click To Revert To Original Color"},buttons:{ok:"Commit To This Color Selection",cancel:"Cancel And Revert To Original Color"},hue:{radio:"Set To &ldquo;Hue&rdquo; Color Mode",textbox:"Enter A &ldquo;Hue&rdquo; Value (0-360&deg;)"},saturation:{radio:"Set To &ldquo;Saturation&rdquo; Color Mode",textbox:"Enter A &ldquo;Saturation&rdquo; Value (0-100%)"},value:{radio:"Set To &ldquo;Value&rdquo; Color Mode",textbox:"Enter A &ldquo;Value&rdquo; Value (0-100%)"},red:{radio:"Set To &ldquo;Red&rdquo; Color Mode",textbox:"Enter A &ldquo;Red&rdquo; Value (0-255)"},green:{radio:"Set To &ldquo;Green&rdquo; Color Mode",textbox:"Enter A &ldquo;Green&rdquo; Value (0-255)"},blue:{radio:"Set To &ldquo;Blue&rdquo; Color Mode",textbox:"Enter A &ldquo;Blue&rdquo; Value (0-255)"},alpha:{radio:"Set To &ldquo;Alpha&rdquo; Color Mode",textbox:"Enter A &ldquo;Alpha&rdquo; Value (0-100)"},hex:{textbox:"Enter A &ldquo;Hex&rdquo; Color Value (#000000-#ffffff)",alpha:"Enter A &ldquo;Alpha&rdquo; Value (#00-#ff)"}}}}})(jQuery,"1.1.6");
trunk/assets/libraries/jquery.zoomer.js ADDED
@@ -0,0 +1,441 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery Zoomer v1.1
3
+ *
4
+ * By HubSpot >('_')<
5
+ *
6
+ * Licensed under the MIT license:
7
+ * http://www.opensource.org/licenses/mit-license.php
8
+ *
9
+ * Example usage:
10
+
11
+ $('iframe').zoomer({ width: 200, zoom: 0.5 });
12
+
13
+ *
14
+ */
15
+
16
+ (function($){
17
+
18
+ var methods,
19
+ pluginName = 'zoomer',
20
+ defaults = {
21
+ width: 'auto',
22
+ height: 'auto',
23
+ zoom: 0.4,
24
+ tranformOrigin: '0 0',
25
+ //loading
26
+ loadingType: 'message', // other type: 'spinner'
27
+ loadingMessage: 'Generating preview...',
28
+ spinnerURL: 'http://oi46.tinypic.com/6y375z.jpg', // requires loadingType: 'spinner'
29
+ //hover
30
+ message: 'Open Page',
31
+ ieMessageButtonClass: 'btn btn-secondary', // used in IE only
32
+ messageURL: false,
33
+ onComplete: function() {}
34
+ },
35
+ visible = {
36
+ visibility: 'visible'
37
+ },
38
+ invisible = {
39
+ visibility: 'hidden'
40
+ },
41
+ unselectable = {
42
+ '-webkit-user-select': 'none',
43
+ '-khtml-user-select': 'none',
44
+ '-moz-user-select': 'none',
45
+ '-o-user-select': 'none',
46
+ 'user-select': 'none',
47
+ 'overflow': 'hidden'
48
+ },
49
+ absolute = {
50
+ top: 0,
51
+ position: 'absolute'
52
+ },
53
+ relative = {
54
+ position: 'relative'
55
+ },
56
+ isMSIE = navigator.userAgent.match(/MSIE/),
57
+ MSIEVersion = navigator.userAgent.match(/MSIE (\d\.\d+)/) ? parseInt(RegExp.$1, 10) : null
58
+ ;
59
+
60
+ methods = {
61
+
62
+ init: function(opts) {
63
+ return this.each(function(){
64
+ var $el = $(this),
65
+ options = $.extend({}, defaults, opts)
66
+ ;
67
+
68
+ options.src = $el.attr('src');
69
+
70
+ $el.data(pluginName, options);
71
+
72
+ $el[pluginName]('zoomer');
73
+ });
74
+ },
75
+
76
+ zoomer: function() {
77
+ var $el = $(this), options = $el.data(pluginName);
78
+
79
+ $el
80
+ .css(invisible)
81
+ .css(unselectable)
82
+ ;
83
+
84
+ if (options.zoom === 'auto') {
85
+ if (options.width === 'auto' && options.height === 'auto') {
86
+ $.error('jQuery.zoomer: You must set either zoom or height and width.');
87
+ return;
88
+ }
89
+ options.zoom = options.width / $(window).width();
90
+ }
91
+
92
+ if (options.width === 'auto') {
93
+ options.width = $(window).height() * options.zoom;
94
+ }
95
+
96
+ if (options.height === 'auto') {
97
+ options.height = $(window).height() * options.zoom;
98
+ }
99
+
100
+ if (options.loadingType === 'spinner') {
101
+ options.loadingMessage = '<img style="padding: ' + parseInt((options.height - 17) / 2, 10) + 'px 0" src="' + options.spinnerURL + '" />';
102
+ }
103
+
104
+ //fix bug in older version of chrome:
105
+ //http://stackoverflow.com/questions/5159713/
106
+ if (navigator.userAgent.indexOf('Chrome/10.0.648') > -1) {
107
+ options.zoom = Math.sqrt(1 / options.zoom);
108
+ }
109
+
110
+ options.externalSrc = true;
111
+
112
+ try {
113
+ if ($el.get(0).contentWindow.document) {
114
+ options.externalSrc = false;
115
+ }
116
+ } catch (e) {}
117
+
118
+ $el[pluginName]('setUpWrapper');
119
+
120
+ $el[pluginName]('zoom');
121
+
122
+ return $el;
123
+ },
124
+
125
+ setUpWrapper: function() {
126
+ var $el = $(this), options = $el.data(pluginName);
127
+
128
+ if (!$el.parents('.zoomer-wrapper').length) {
129
+ $el
130
+ .wrap(
131
+ $('<div/>')
132
+ .addClass('zoomer-wrapper')
133
+ .css(unselectable)
134
+ .css(relative)
135
+ )
136
+ .wrap(
137
+ $('<div/>')
138
+ .addClass('zoomer-small')
139
+ .css(invisible)
140
+ .css(unselectable)
141
+ )
142
+ ;
143
+ }
144
+
145
+ options.zoomerWrapper = $el.parents('.zoomer-wrapper');
146
+
147
+ options.zoomerSmall = $el.parents('.zoomer-small');
148
+
149
+ options.zoomerCover = $('<div/>')
150
+ .addClass('zoomer-cover')
151
+ .css(unselectable)
152
+ .css(absolute)
153
+ .css({
154
+ textAlign: 'center',
155
+ fontSize: '15px'
156
+ })
157
+ ;
158
+
159
+ options.zoomerLink = $('<a/>')
160
+ .attr('target', '_blank')
161
+ .html("View Page<span style='line-height:12px;position:absolute; bottom:10px;left:0%;width:100%; text-align: center;'>(preview not always to scale)</span>")
162
+ .css({
163
+ height: options.height,
164
+ width: options.width,
165
+ color: '#444',
166
+ display: 'block',
167
+ lineHeight: (parseInt(options.height, 10) - parseInt((options.height - 80) / 10, 10)) + 'px',
168
+ textDecoration: 'none'
169
+ })
170
+ .css('background', '-moz-radial-gradient(center center, circle farthest-corner, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.4) 100%) repeat scroll 0 0 transparent')
171
+ .css('background-image', '-webkit-gradient(radial, center center, 0, center center, ' + parseInt(options.width, 10) + ', from(rgba(255, 255, 255, 0.95)), to(rgba(255, 255, 255, 0.4)))')
172
+ .mousedown(function(){
173
+ $(this).css('box-shadow', 'inset 0px 2px 8px rgba(100, 100, 100, 0.4)');
174
+ })
175
+ .bind('mouseout mouseup', function(){
176
+ $(this).css('box-shadow', 'none');
177
+ })
178
+ .hide()
179
+ ;
180
+
181
+ if (isMSIE) {
182
+ options.zoomerLink.css({
183
+ backgroundColor: 'rgba(255, 255, 255, 0.5)'
184
+ });
185
+ }
186
+
187
+ if (options.click) {
188
+ options.zoomerLink
189
+ .attr('href', options.messageURL || options.src || '#')
190
+ .unbind('click').bind('click', options.click)
191
+ ;
192
+ } else {
193
+ options.zoomerLink.attr('href', options.messageURL || options.src);
194
+ }
195
+
196
+ options.zoomerCover
197
+ .append(options.zoomerLink)
198
+ .hover(function(){
199
+ options.zoomerLink.show();
200
+ $(this).css('box-shadow', 'inset 2px 2px ' + (parseInt(options.width, 10) * 2) + 'px rgba(255, 255, 255, 0.2)');
201
+ }, function(){
202
+ options.zoomerLink.hide();
203
+ $(this).css('box-shadow', 'none');
204
+ })
205
+ .mousedown(function(){
206
+ $(this).css('box-shadow', 'inset 2px 2px ' + (parseInt(options.width, 10) * 2) + 'px rgba(200, 200, 200, 0.8)');
207
+ })
208
+ .bind('mouseout mouseup', function(){
209
+ $(this).css('box-shadow', 'none');
210
+ })
211
+ ;
212
+
213
+ options.zoomerLoader = $('<div/>')
214
+ .addClass('zoomer-loader')
215
+ .css(invisible)
216
+ .css(unselectable)
217
+ .css(absolute)
218
+ .css({
219
+ textAlign: 'center',
220
+ fontSize: '15px',
221
+ lineHeight: (parseInt(options.height, 10) - parseInt((options.height - 80) / 10, 10)) + 'px',
222
+ background: '#fff'
223
+ })
224
+ .html(options.loadingMessage)
225
+ ;
226
+
227
+ options.zoomerWrapper
228
+ .append(options.zoomerCover)
229
+ .append(options.zoomerLoader)
230
+ ;
231
+
232
+ if (isMSIE) { options.zoomerLoader.css(invisible); }
233
+
234
+ return $el[pluginName]('updateWrapper')[pluginName]('fadeOut');
235
+ },
236
+
237
+ updateWrapper: function() {
238
+ var $el = $(this), options = $el.data(pluginName);
239
+
240
+ $.each([options.zoomerWrapper.get(0), options.zoomerCover.get(0), options.zoomerLoader.get(0), options.zoomerSmall.get(0)], function(){
241
+ $(this).css({
242
+ height: options.height,
243
+ width: options.width
244
+ });
245
+ });
246
+
247
+ return $el;
248
+ },
249
+
250
+ fadeIn: function() {
251
+ var $el = $(this), options = $el.data(pluginName);
252
+
253
+ if (isMSIE) { return $el; }
254
+
255
+ $el.css(invisible);
256
+
257
+ options.zoomerSmall
258
+ .stop()
259
+ .css('opacity', 0)
260
+ .css(visible)
261
+ .animate({ 'opacity': 1 }, 150, function(){
262
+ $el
263
+ .css(visible)
264
+ .css('opacity', 0)
265
+ .animate({ 'opacity': 1 }, 500)
266
+ ;
267
+ })
268
+ ;
269
+
270
+ options.zoomerLoader
271
+ .show()
272
+ .animate({ 'opacity': 0 }, 300, function(){
273
+ $(this).hide();
274
+ })
275
+ ;
276
+
277
+ return $el;
278
+ },
279
+
280
+ fadeOut: function() {
281
+ var $el = $(this), options = $el.data(pluginName);
282
+
283
+ if (isMSIE) { return $el; }
284
+
285
+ options.zoomerSmall
286
+ .stop()
287
+ .animate({ 'opacity': 0 }, 300, function(){
288
+ $(this).css('visibility', 'hidden');
289
+ })
290
+ ;
291
+
292
+ options.zoomerLoader
293
+ .css('opacity', 0)
294
+ .css(visible)
295
+ .show()
296
+ .animate({ opacity: 1 }, 100)
297
+ ;
298
+
299
+ return $el;
300
+ },
301
+
302
+ zoom: function() {
303
+ var $el = $(this), options = $el.data(pluginName);
304
+
305
+ if (isMSIE) {
306
+ setTimeout(function(){
307
+ $el
308
+ .css({
309
+ zoom: options.zoom,
310
+ height: parseInt((options.height / options.zoom) * (1 / (MSIEVersion >= 9 ? 1 : options.zoom)), 10),
311
+ width: parseInt((options.width / options.zoom) * (1 / (MSIEVersion >= 9 ? 1 : options.zoom)), 10)
312
+ })
313
+ .css(visible)
314
+ ;
315
+
316
+ options.zoomerLink.remove();
317
+
318
+ options.zoomerCover
319
+ .unbind('hover mouseover mouseout')
320
+ .addClass(options.ieMessageButtonClass)
321
+ .html(options.message)
322
+ .css({
323
+ width: 94,
324
+ height: 14,
325
+ fontSize: 12,
326
+ padding: '6px 18px 6px 18px',
327
+ top: parseInt(options.height - (12 + (2 * 6) + 2 + 10), 10),
328
+ left: parseInt((options.width - (94 + (2 * 18))) / 2, 10)
329
+ })
330
+ .show()
331
+ ;
332
+
333
+ if (!options.click) {
334
+ options.click = function() {
335
+ location.href = options.messageURL || options.src;
336
+ };
337
+ }
338
+
339
+ options.zoomerCover.unbind('click').bind('click', options.click);
340
+
341
+ options.onComplete($el);
342
+ }, 1000);
343
+
344
+ return $el;
345
+ }
346
+
347
+ if (options.externalSrc) {
348
+ $el
349
+ .css({
350
+ height: options.height / options.zoom,
351
+ width: options.width / options.zoom,
352
+ 'transform-origin': options.tranformOrigin,
353
+ '-webkit-transform-origin': options.tranformOrigin,
354
+ '-moz-transform-origin': options.tranformOrigin,
355
+ '-o-transform-origin': options.tranformOrigin,
356
+ 'transform': 'scale(' + options.zoom + ')',
357
+ '-webkit-transform': 'scale(' + options.zoom + ')',
358
+ '-moz-transform': 'scale(' + options.zoom + ')',
359
+ '-o-transform': 'scale(' + options.zoom + ')'
360
+ })
361
+ .css(visible)
362
+ ;
363
+
364
+ $el[pluginName]('fadeIn');
365
+
366
+ options.onComplete($el);
367
+
368
+ return $el;
369
+ }
370
+
371
+ $el
372
+ .css({
373
+ height: options.height / options.zoom,
374
+ width: options.width / options.zoom
375
+ })
376
+ .load(function(){
377
+ $el.contents().find("meta[name=viewport]").remove();
378
+ console.log('remove viewport');
379
+ $el.contents().find('html').css({
380
+ 'transform-origin': options.tranformOrigin,
381
+ '-webkit-transform-origin': options.tranformOrigin,
382
+ '-moz-transform-origin': options.tranformOrigin,
383
+ '-o-transform-origin': options.tranformOrigin,
384
+ 'transform': 'scale(' + options.zoom + ')',
385
+ '-webkit-transform': 'scale(' + options.zoom + ')',
386
+ '-moz-transform': 'scale(' + options.zoom + ')',
387
+ '-o-transform': 'scale(' + options.zoom + ')',
388
+ 'width': '100%',
389
+ });
390
+
391
+
392
+
393
+ $el[pluginName]('fadeIn');
394
+
395
+ options.onComplete($el);
396
+ })
397
+ ;
398
+
399
+ return $el;
400
+ },
401
+
402
+ src: function(src) {
403
+ var $el = $(this),
404
+ options = $el.data(pluginName)
405
+ ;
406
+
407
+ options.src = src;
408
+
409
+ $el[pluginName]('fadeOut').attr('src', src);
410
+
411
+ return $el;
412
+ },
413
+
414
+ refresh: function() {
415
+ var $el = $(this), options = $el.data(pluginName);
416
+
417
+ return $el[pluginName]('src', options.src);
418
+ },
419
+
420
+ zoomedBodyHeight: function() {
421
+ var $el = $(this), options = $el.data(pluginName);
422
+
423
+ if (options.externalSrc) {
424
+ return $.error('jQuery.zoomer: cannot access bodyHeight of an external iFrame');
425
+ }
426
+
427
+ return options.zoom * $($el.get(0).contentWindow.document).height();
428
+ }
429
+ };
430
+
431
+ $.fn[pluginName] = function(options) {
432
+ if (methods[options]) {
433
+ return methods[options].apply(this, Array.prototype.slice.call(arguments, 1));
434
+ } else if (typeof options === 'object' || ! options) {
435
+ return methods.init.apply(this, arguments);
436
+ } else {
437
+ $.error('jQuery.' + pluginName + ': Method ' + options + ' does not exist');
438
+ }
439
+ };
440
+
441
+ })(jQuery);
trunk/assets/libraries/script.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ $(function(){
2
+
3
+ var note = $('#note'),
4
+ ts = new Date(2012, 0, 1),
5
+ newYear = true;
6
+
7
+ if((new Date()) > ts){
8
+ // The new year is here! Count towards something else.
9
+ // Notice the *1000 at the end - time must be in milliseconds
10
+ ts = (new Date()).getTime() + 10*24*60*60*1000;
11
+ newYear = false;
12
+ }
13
+
14
+ $('#countdown').countdown({
15
+ timestamp : ts,
16
+ callback : function(days, hours, minutes, seconds){
17
+
18
+ var message = "";
19
+
20
+ message += days + " day" + ( days==1 ? '':'s' ) + ", ";
21
+ message += hours + " hour" + ( hours==1 ? '':'s' ) + ", ";
22
+ message += minutes + " minute" + ( minutes==1 ? '':'s' ) + " and ";
23
+ message += seconds + " second" + ( seconds==1 ? '':'s' ) + " <br />";
24
+
25
+ if(newYear){
26
+ message += "left until the new year!";
27
+ }
28
+ else {
29
+ message += "left to 10 days from now!";
30
+ }
31
+
32
+ note.html(message);
33
+ }
34
+ });
35
+
36
+ });
trunk/assets/libraries/shareme/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/libraries/shareme/library.shareme.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php
trunk/assets/libraries/shareme/sharrre/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ # Silence is golden.
trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.js ADDED
@@ -0,0 +1,584 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Sharrre.com - Make your sharing widget!
3
+ * Version: beta 1.3.3
4
+ * Author: Julien Hany
5
+ * License: MIT http://en.wikipedia.org/wiki/MIT_License or GPLv2 http://en.wikipedia.org/wiki/GNU_General_Public_License
6
+ */
7
+
8
+ ;(function ( $, window, document, undefined ) {
9
+
10
+ /* Defaults
11
+ ================================================== */
12
+ var pluginName = 'sharrre',
13
+ defaults = {
14
+ className: 'sharrre',
15
+ share: {
16
+ googlePlus: false,
17
+ facebook: false,
18
+ twitter: false,
19
+ digg: false,
20
+ delicious: false,
21
+ stumbleupon: false,
22
+ linkedin: false,
23
+ pinterest: false
24
+ },
25
+ shareTotal: 0,
26
+ template: '',
27
+ title: '',
28
+ url: document.location.href,
29
+ text: document.title,
30
+ urlCurl: 'sharrre.php', //PHP script for google plus...
31
+ count: {}, //counter by social network
32
+ total: 0, //total of sharing
33
+ shorterTotal: true, //show total by k or M when number is to big
34
+ enableHover: true, //disable if you want to personalize hover event with callback
35
+ enableCounter: true, //disable if you just want use buttons
36
+ enableTracking: false, //tracking with google analitycs
37
+ hover: function(){}, //personalize hover event with this callback function
38
+ hide: function(){}, //personalize hide event with this callback function
39
+ click: function(){}, //personalize click event with this callback function
40
+ render: function(){}, //personalize render event with this callback function
41
+ buttons: { //settings for buttons
42
+ googlePlus : { //http://www.google.com/webmasters/+1/button/
43
+ url: '', //if you need to personnalize button url
44
+ urlCount: false, //if you want to use personnalize button url on global counter
45
+ size: 'medium',
46
+ lang: 'en-US',
47
+ annotation: ''
48
+ },
49
+ facebook: { //http://developers.facebook.com/docs/reference/plugins/like/
50
+ url: '', //if you need to personalize url button
51
+ urlCount: false, //if you want to use personnalize button url on global counter
52
+ action: 'like',
53
+ layout: 'button_count',
54
+ width: '',
55
+ send: 'false',
56
+ faces: 'false',
57
+ colorscheme: '',
58
+ font: '',
59
+ lang: 'en_US'
60
+ },
61
+ twitter: { //http://twitter.com/about/resources/tweetbutton
62
+ url: '', //if you need to personalize url button
63
+ urlCount: false, //if you want to use personnalize button url on global counter
64
+ count: 'horizontal',
65
+ hashtags: '',
66
+ via: '',
67
+ related: '',
68
+ lang: 'en'
69
+ },
70
+ digg: { //http://about.digg.com/downloads/button/smart
71
+ url: '', //if you need to personalize url button
72
+ urlCount: false, //if you want to use personnalize button url on global counter
73
+ type: 'DiggCompact'
74
+ },
75
+ delicious: {
76
+ url: '', //if you need to personalize url button
77
+ urlCount: false, //if you want to use personnalize button url on global counter
78
+ size: 'medium' //medium or tall
79
+ },
80
+ stumbleupon: { //http://www.stumbleupon.com/badges/
81
+ url: '', //if you need to personalize url button
82
+ urlCount: false, //if you want to use personnalize button url on global counter
83
+ layout: '1'
84
+ },
85
+ linkedin: { //http://developer.linkedin.com/plugins/share-button
86
+ url: '', //if you need to personalize url button
87
+ urlCount: false, //if you want to use personnalize button url on global counter
88
+ counter: ''
89
+ },
90
+ pinterest: { //http://pinterest.com/about/goodies/
91
+ url: '', //if you need to personalize url button
92
+ media: '',
93
+ description: '',
94
+ layout: 'horizontal'
95
+ }
96
+ }
97
+ },
98
+ /* Json URL to get count number
99
+ ================================================== */
100
+ urlJson = {
101
+ googlePlus: "",
102
+ facebook: "http://graph.facebook.com/?id={url}&callback=?",
103
+ //facebook : "http://api.ak.facebook.com/restserver.php?v=1.0&method=links.getStats&urls={url}&format=json"
104
+ twitter: "http://cdn.api.twitter.com/1/urls/count.json?url={url}&callback=?",
105
+ digg: "http://services.digg.com/2.0/story.getInfo?links={url}&type=javascript&callback=?",
106
+ delicious: 'http://feeds.delicious.com/v2/json/urlinfo/data?url={url}&callback=?',
107
+ //stumbleupon: "http://www.stumbleupon.com/services/1.01/badge.getinfo?url={url}&format=jsonp&callback=?",
108
+ stumbleupon: "",
109
+ linkedin: "http://www.linkedin.com/countserv/count/share?format=jsonp&url={url}&callback=?",
110
+ pinterest: ""
111
+ },
112
+ /* Load share buttons asynchronously
113
+ ================================================== */
114
+ loadButton = {
115
+ googlePlus : function(self){
116
+ var sett = self.options.buttons.googlePlus;
117
+ //$(self.element).find('.buttons').append('<div class="button googleplus"><g:plusone size="'+self.options.buttons.googlePlus.size+'" href="'+self.options.url+'"></g:plusone></div>');
118
+ $(self.element).find('.buttons').append('<div class="button googleplus"><div class="g-plusone" data-size="'+sett.size+'" data-href="'+(sett.url !== '' ? sett.url : self.options.url)+'" data-annotation="'+sett.annotation+'"></div></div>');
119
+ window.___gcfg = {
120
+ lang: self.options.buttons.googlePlus.lang
121
+ };
122
+ var loading = 0;
123
+ if(typeof gapi === 'undefined' && loading == 0){
124
+ loading = 1;
125
+ (function() {
126
+ var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
127
+ po.src = '//apis.google.com/js/plusone.js';
128
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
129
+ })();
130
+ }
131
+ else{
132
+ gapi.plusone.go();
133
+ }
134
+ },
135
+ facebook : function(self){
136
+ var sett = self.options.buttons.facebook;
137
+ $(self.element).find('.buttons').append('<div class="button facebook"><div id="fb-root"></div><div class="fb-like" data-href="'+(sett.url !== '' ? sett.url : self.options.url)+'" data-send="'+sett.send+'" data-layout="'+sett.layout+'" data-width="'+sett.width+'" data-show-faces="'+sett.faces+'" data-action="'+sett.action+'" data-colorscheme="'+sett.colorscheme+'" data-font="'+sett.font+'" data-via="'+sett.via+'"></div></div>');
138
+ var loading = 0;
139
+ if(typeof FB === 'undefined' && loading == 0){
140
+ loading = 1;
141
+ (function(d, s, id) {
142
+ var js, fjs = d.getElementsByTagName(s)[0];
143
+ if (d.getElementById(id)) {return;}
144
+ js = d.createElement(s); js.id = id;
145
+ js.src = '//connect.facebook.net/'+sett.lang+'/all.js#xfbml=1';
146
+ fjs.parentNode.insertBefore(js, fjs);
147
+ }(document, 'script', 'facebook-jssdk'));
148
+ }
149
+ else{
150
+ FB.XFBML.parse();
151
+ }
152
+ },
153
+ twitter : function(self){
154
+ var sett = self.options.buttons.twitter;
155
+ $(self.element).find('.buttons').append('<div class="button twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-url="'+(sett.url !== '' ? sett.url : self.options.url)+'" data-count="'+sett.count+'" data-text="'+self.options.text+'" data-via="'+sett.via+'" data-hashtags="'+sett.hashtags+'" data-related="'+sett.related+'" data-lang="'+sett.lang+'">Tweet</a></div>');
156
+ var loading = 0;
157
+ if(typeof twttr === 'undefined' && loading == 0){
158
+ loading = 1;
159
+ (function() {
160
+ var twitterScriptTag = document.createElement('script');
161
+ twitterScriptTag.type = 'text/javascript';
162
+ twitterScriptTag.async = true;
163
+ twitterScriptTag.src = '//platform.twitter.com/widgets.js';
164
+ var s = document.getElementsByTagName('script')[0];
165
+ s.parentNode.insertBefore(twitterScriptTag, s);
166
+ })();
167
+ }
168
+ else{
169
+ $.ajax({ url: '//platform.twitter.com/widgets.js', dataType: 'script', cache:true}); //http://stackoverflow.com/q/6536108
170
+ }
171
+ },
172
+ digg : function(self){
173
+ var sett = self.options.buttons.digg;
174
+ $(self.element).find('.buttons').append('<div class="button digg"><a class="DiggThisButton '+sett.type+'" rel="nofollow external" href="http://digg.com/submit?url='+encodeURIComponent((sett.url !== '' ? sett.url : self.options.url))+'"></a></div>');
175
+ var loading = 0;
176
+ if(typeof __DBW === 'undefined' && loading == 0){
177
+ loading = 1;
178
+ (function() {
179
+ var s = document.createElement('SCRIPT'), s1 = document.getElementsByTagName('SCRIPT')[0];
180
+ s.type = 'text/javascript';
181
+ s.async = true;
182
+ s.src = '//widgets.digg.com/buttons.js';
183
+ s1.parentNode.insertBefore(s, s1);
184
+ })();
185
+ }
186
+ },
187
+ delicious : function(self){
188
+ if(self.options.buttons.delicious.size == 'tall'){//tall
189
+ var css = 'width:50px;',
190
+ cssCount = 'height:35px;width:50px;font-size:15px;line-height:35px;',
191
+ cssShare = 'height:18px;line-height:18px;margin-top:3px;';
192
+ }
193
+ else{//medium
194
+ var css = 'width:93px;',
195
+ cssCount = 'float:right;padding:0 3px;height:20px;width:26px;line-height:20px;',
196
+ cssShare = 'float:left;height:20px;line-height:20px;';
197
+ }
198
+ var count = self.shorterTotal(self.options.count.delicious);
199
+ if(typeof count === "undefined"){
200
+ count = 0;
201
+ }
202
+ $(self.element).find('.buttons').append(
203
+ '<div class="button delicious"><div style="'+css+'font:12px Arial,Helvetica,sans-serif;cursor:pointer;color:#666666;display:inline-block;float:none;height:20px;line-height:normal;margin:0;padding:0;text-indent:0;vertical-align:baseline;">'+
204
+ '<div style="'+cssCount+'background-color:#fff;margin-bottom:5px;overflow:hidden;text-align:center;border:1px solid #ccc;border-radius:3px;">'+count+'</div>'+
205
+ '<div style="'+cssShare+'display:block;padding:0;text-align:center;text-decoration:none;width:50px;background-color:#7EACEE;border:1px solid #40679C;border-radius:3px;color:#fff;">'+
206
+ '<img src="http://www.delicious.com/static/img/delicious.small.gif" height="10" width="10" alt="Delicious" /> Add</div></div></div>');
207
+
208
+ $(self.element).find('.delicious').on('click', function(){
209
+ self.openPopup('delicious');
210
+ });
211
+ },
212
+ stumbleupon : function(self){
213
+ var sett = self.options.buttons.stumbleupon;
214
+ $(self.element).find('.buttons').append('<div class="button stumbleupon"><su:badge layout="'+sett.layout+'" location="'+(sett.url !== '' ? sett.url : self.options.url)+'"></su:badge></div>');
215
+ var loading = 0;
216
+ if(typeof STMBLPN === 'undefined' && loading == 0){
217
+ loading = 1;
218
+ (function() {
219
+ var li = document.createElement('script');li.type = 'text/javascript';li.async = true;
220
+ li.src = '//platform.stumbleupon.com/1/widgets.js';
221
+ var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(li, s);
222
+ })();
223
+ s = window.setTimeout(function(){
224
+ if(typeof STMBLPN !== 'undefined'){
225
+ STMBLPN.processWidgets();
226
+ clearInterval(s);
227
+ }
228
+ },500);
229
+ }
230
+ else{
231
+ STMBLPN.processWidgets();
232
+ }
233
+ },
234
+ linkedin : function(self){
235
+ var sett = self.options.buttons.linkedin;
236
+ $(self.element).find('.buttons').append('<div class="button linkedin"><script type="in/share" data-url="'+(sett.url !== '' ? sett.url : self.options.url)+'" data-counter="'+sett.counter+'"></script></div>');
237
+ var loading = 0;
238
+ if(typeof window.IN === 'undefined' && loading == 0){
239
+ loading = 1;
240
+ (function() {
241
+ var li = document.createElement('script');li.type = 'text/javascript';li.async = true;
242
+ li.src = '//platform.linkedin.com/in.js';
243
+ var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(li, s);
244
+ })();
245
+ }
246
+ else{
247
+ window.IN.init();
248
+ }
249
+ },
250
+ pinterest : function(self){
251
+ var sett = self.options.buttons.pinterest;
252
+ $(self.element).find('.buttons').append('<div class="button pinterest"><a href="http://pinterest.com/pin/create/button/?url='+(sett.url !== '' ? sett.url : self.options.url)+'&media='+sett.media+'&description='+sett.description+'" class="pin-it-button" count-layout="'+sett.layout+'">Pin It</a></div>');
253
+
254
+ (function() {
255
+ var li = document.createElement('script');li.type = 'text/javascript';li.async = true;
256
+ li.src = '//assets.pinterest.com/js/pinit.js';
257
+ var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(li, s);
258
+ })();
259
+ }
260
+ },
261
+ /* Tracking for Google Analytics
262
+ ================================================== */
263
+ tracking = {
264
+ googlePlus: function(){},
265
+ facebook: function(){
266
+ //console.log('facebook');
267
+ fb = window.setInterval(function(){
268
+ if (typeof FB !== 'undefined') {
269
+ FB.Event.subscribe('edge.create', function(targetUrl) {
270
+ _gaq.push(['_trackSocial', 'facebook', 'like', targetUrl]);
271
+ });
272
+ FB.Event.subscribe('edge.remove', function(targetUrl) {
273
+ _gaq.push(['_trackSocial', 'facebook', 'unlike', targetUrl]);
274
+ });
275
+ FB.Event.subscribe('message.send', function(targetUrl) {
276
+ _gaq.push(['_trackSocial', 'facebook', 'send', targetUrl]);
277
+ });
278
+ //console.log('ok');
279
+ clearInterval(fb);
280
+ }
281
+ },1000);
282
+ },
283
+ twitter: function(){
284
+ //console.log('twitter');
285
+ tw = window.setInterval(function(){
286
+ if (typeof twttr !== 'undefined') {
287
+ twttr.events.bind('tweet', function(event) {
288
+ if (event) {
289
+ _gaq.push(['_trackSocial', 'twitter', 'tweet']);
290
+ }
291
+ });
292
+ //console.log('ok');
293
+ clearInterval(tw);
294
+ }
295
+ },1000);
296
+ },
297
+ digg: function(){
298
+ //if somenone find a solution, mail me !
299
+ /*$(this.element).find('.digg').on('click', function(){
300
+ _gaq.push(['_trackSocial', 'digg', 'add']);
301
+ });*/
302
+ },
303
+ delicious: function(){},
304
+ stumbleupon: function(){},
305
+ linkedin: function(){
306
+ function LinkedInShare() {
307
+ _gaq.push(['_trackSocial', 'linkedin', 'share']);
308
+ }
309
+ },
310
+ pinterest: function(){
311
+ //if somenone find a solution, mail me !
312
+ }
313
+ },
314
+ /* Popup for each social network
315
+ ================================================== */
316
+ popup = {
317
+ googlePlus: function(opt){
318
+ window.open("https://plus.google.com/share?hl="+opt.buttons.googlePlus.lang+"&url="+encodeURIComponent((opt.buttons.googlePlus.url !== '' ? opt.buttons.googlePlus.url : opt.url)), "", "toolbar=0, status=0, width=900, height=500");
319
+ },
320
+ facebook: function(opt){
321
+ window.open("http://www.facebook.com/sharer.php?u="+encodeURIComponent((opt.buttons.facebook.url !== '' ? opt.buttons.facebook.url : opt.url))+"&t="+opt.text+"", "", "toolbar=0, status=0, width=900, height=500");
322
+ },
323
+ twitter: function(opt){
324
+ window.open("https://twitter.com/intent/tweet?text="+encodeURIComponent(opt.text)+"&url="+encodeURIComponent((opt.buttons.twitter.url !== '' ? opt.buttons.twitter.url : opt.url))+(opt.buttons.twitter.via !== '' ? '&via='+opt.buttons.twitter.via : ''), "", "toolbar=0, status=0, width=650, height=360");
325
+ },
326
+ digg: function(opt){
327
+ window.open("http://digg.com/tools/diggthis/submit?url="+encodeURIComponent((opt.buttons.digg.url !== '' ? opt.buttons.digg.url : opt.url))+"&title="+opt.text+"&related=true&style=true", "", "toolbar=0, status=0, width=650, height=360");
328
+ },
329
+ delicious: function(opt){
330
+ window.open('http://www.delicious.com/save?v=5&noui&jump=close&url='+encodeURIComponent((opt.buttons.delicious.url !== '' ? opt.buttons.delicious.url : opt.url))+'&title='+opt.text, 'delicious', 'toolbar=no,width=550,height=550');
331
+ },
332
+ stumbleupon: function(opt){
333
+ window.open('http://www.stumbleupon.com/badge/?url='+encodeURIComponent((opt.buttons.delicious.url !== '' ? opt.buttons.delicious.url : opt.url)), 'stumbleupon', 'toolbar=no,width=550,height=550');
334
+ },
335
+ linkedin: function(opt){
336
+ window.open('https://www.linkedin.com/cws/share?url='+encodeURIComponent((opt.buttons.delicious.url !== '' ? opt.buttons.delicious.url : opt.url))+'&token=&isFramed=true', 'linkedin', 'toolbar=no,width=550,height=550');
337
+ },
338
+ pinterest: function(opt){
339
+ window.open('http://pinterest.com/pin/create/button/?url='+encodeURIComponent((opt.buttons.pinterest.url !== '' ? opt.buttons.pinterest.url : opt.url))+'&media='+encodeURIComponent(opt.buttons.pinterest.media)+'&description='+opt.buttons.pinterest.description, 'pinterest', 'toolbar=no,width=700,height=300');
340
+ }
341
+ };
342
+
343
+ /* Plugin constructor
344
+ ================================================== */
345
+ function Plugin( element, options ) {
346
+ this.element = element;
347
+
348
+ this.options = $.extend( true, {}, defaults, options);
349
+ this.options.share = options.share; //simple solution to allow order of buttons
350
+
351
+ this._defaults = defaults;
352
+ this._name = pluginName;
353
+
354
+ this.init();
355
+ };
356
+
357
+ /* Initialization method
358
+ ================================================== */
359
+ Plugin.prototype.init = function () {
360
+ var self = this;
361
+ if(this.options.urlCurl !== ''){
362
+ urlJson.googlePlus = this.options.urlCurl + '?url={url}&type=googlePlus'; // PHP script for GooglePlus...
363
+ urlJson.stumbleupon = this.options.urlCurl + '?url={url}&type=stumbleupon'; // PHP script for Stumbleupon...
364
+ urlJson.pinterest = this.options.urlCurl + '?url={url}&type=pinterest'; // PHP script for Pinterest...
365
+ }
366
+ $(this.element).addClass(this.options.className); //add class
367
+
368
+ //HTML5 Custom data
369
+ if(typeof $(this.element).data('title') !== 'undefined'){
370
+ this.options.title = $(this.element).attr('data-title');
371
+ }
372
+ if(typeof $(this.element).data('url') !== 'undefined'){
373
+ this.options.url = $(this.element).data('url');
374
+ }
375
+ if(typeof $(this.element).data('text') !== 'undefined'){
376
+ this.options.text = $(this.element).data('text');
377
+ }
378
+
379
+ //how many social website have been selected
380
+ $.each(this.options.share, function(name, val) {
381
+ if(val === true){
382
+ self.options.shareTotal ++;
383
+ }
384
+ });
385
+
386
+ if(self.options.enableCounter === true){ //if for some reason you don't need counter
387
+ //get count of social share that have been selected
388
+ $.each(this.options.share, function(name, val) {
389
+ if(val === true){
390
+ //self.getSocialJson(name);
391
+ try {
392
+ self.getSocialJson(name);
393
+ } catch(e){
394
+ }
395
+ }
396
+ });
397
+ }
398
+ else if(self.options.template !== ''){ //for personalized button (with template)
399
+ this.options.render(this, this.options);
400
+ }
401
+ else{ // if you want to use official button like example 3 or 5
402
+ this.loadButtons();
403
+ }
404
+
405
+ //add hover event
406
+ $(this.element).hover(function(){
407
+ //load social button if enable and 1 time
408
+ if($(this).find('.buttons').length === 0 && self.options.enableHover === true){
409
+ self.loadButtons();
410
+ }
411
+ self.options.hover(self, self.options);
412
+ }, function(){
413
+ self.options.hide(self, self.options);
414
+ });
415
+
416
+ //click event
417
+ $(this.element).click(function(){
418
+ self.options.click(self, self.options);
419
+ return false;
420
+ });
421
+ };
422
+
423
+ /* loadButtons methode
424
+ ================================================== */
425
+ Plugin.prototype.loadButtons = function () {
426
+ var self = this;
427
+ $(this.element).append('<div class="buttons"></div>');
428
+ $.each(self.options.share, function(name, val) {
429
+ if(val == true){
430
+ loadButton[name](self);
431
+ if(self.options.enableTracking === true){ //add tracking
432
+ tracking[name]();
433
+ }
434
+ }
435
+ });
436
+ };
437
+
438
+ /* getSocialJson methode
439
+ ================================================== */
440
+ Plugin.prototype.getSocialJson = function (name) {
441
+ var self = this,
442
+ count = 0,
443
+ url = urlJson[name].replace('{url}', encodeURIComponent(this.options.url));
444
+ if(this.options.buttons[name].urlCount === true && this.options.buttons[name].url !== ''){
445
+ url = urlJson[name].replace('{url}', this.options.buttons[name].url);
446
+ }
447
+ //console.log('name : ' + name + ' - url : '+url); //debug
448
+ if(url != '' && self.options.urlCurl !== ''){ //urlCurl = '' if you don't want to used PHP script but used social button
449
+ $.getJSON(url, function(json){
450
+ if(typeof json.count !== "undefined"){ //GooglePlus, Stumbleupon, Twitter and Digg
451
+ var temp = json.count + '';
452
+ temp = temp.replace('\u00c2\u00a0', ''); //remove google plus special chars
453
+ count += parseInt(temp, 10);
454
+ }
455
+ else if(typeof json.likes !== "undefined"){ //Facebook Fan page
456
+ count += parseInt(json.likes, 10); //changed shares to likes to use with fanPage url
457
+ }
458
+ else if(typeof json.shares !== "undefined"){ //Facebook
459
+ count += parseInt(json.shares, 10);
460
+ }
461
+ else if(typeof json[0] !== "undefined"){ //Delicious
462
+ count += parseInt(json[0].total_posts, 10);
463
+ }
464
+ else if(typeof json[0] !== "undefined"){ //Stumbleupon
465
+ }
466
+ self.options.count[name] = count;
467
+ self.options.total += count;
468
+ self.renderer();
469
+ self.rendererPerso();
470
+ //console.log(json); //debug
471
+ })
472
+ .error(function() {
473
+ self.options.count[name] = 0;
474
+ self.rendererPerso();
475
+ });
476
+ }
477
+ else{
478
+ self.renderer();
479
+ self.options.count[name] = 0;
480
+ self.rendererPerso();
481
+ }
482
+ };
483
+
484
+ /* launch render methode
485
+ ================================================== */
486
+ Plugin.prototype.rendererPerso = function () {
487
+ //check if this is the last social website to launch render
488
+ var shareCount = 0;
489
+ for (e in this.options.count) { shareCount++; }
490
+ if(shareCount === this.options.shareTotal){
491
+ this.options.render(this, this.options);
492
+ }
493
+ };
494
+
495
+ /* render methode
496
+ ================================================== */
497
+ Plugin.prototype.renderer = function () {
498
+ var total = this.options.total,
499
+ template = this.options.template;
500
+ if(this.options.shorterTotal === true){ //format number like 1.2k or 5M
501
+ total = this.shorterTotal(total);
502
+ }
503
+
504
+ if(template !== ''){ //if there is a template
505
+ template = template.replace('{total}', total);
506
+ $(this.element).html(template);
507
+ }
508
+ else{ //template by defaults
509
+ $(this.element).html(
510
+ '<div class="box"><a class="count" href="#">' + total + '</a>' +
511
+ (this.options.title !== '' ? '<a class="share" href="#">' + this.options.title + '</a>' : '') +
512
+ '</div>'
513
+ );
514
+ }
515
+ };
516
+
517
+ /* format total numbers like 1.2k or 5M
518
+ ================================================== */
519
+ Plugin.prototype.shorterTotal = function (num) {
520
+ if (num >= 1e6){
521
+ num = (num / 1e6).toFixed(2) + "M"
522
+ } else if (num >= 1e3){
523
+ num = (num / 1e3).toFixed(1) + "k"
524
+ }
525
+ return num;
526
+ };
527
+
528
+ /* Methode for open popup
529
+ ================================================== */
530
+ Plugin.prototype.openPopup = function (site) {
531
+ popup[site](this.options); //open
532
+ if(this.options.enableTracking === true){ //tracking!
533
+ var tracking = {
534
+ googlePlus: {site: 'Google', action: '+1'},
535
+ facebook: {site: 'facebook', action: 'like'},
536
+ twitter: {site: 'twitter', action: 'tweet'},
537
+ digg: {site: 'digg', action: 'add'},
538
+ delicious: {site: 'delicious', action: 'add'},
539
+ stumbleupon: {site: 'stumbleupon', action: 'add'},
540
+ linkedin: {site: 'linkedin', action: 'share'},
541
+ pinterest: {site: 'pinterest', action: 'pin'}
542
+ };
543
+ _gaq.push(['_trackSocial', tracking[site].site, tracking[site].action]);
544
+ }
545
+ };
546
+
547
+ /* Methode for add +1 to a counter
548
+ ================================================== */
549
+ Plugin.prototype.simulateClick = function () {
550
+ var html = $(this.element).html();
551
+ $(this.element).html(html.replace(this.options.total, this.options.total+1));
552
+ };
553
+
554
+ /* Methode for add +1 to a counter
555
+ ================================================== */
556
+ Plugin.prototype.update = function (url, text) {
557
+ if(url !== ''){
558
+ this.options.url = url;
559
+ }
560
+ if(text !== ''){
561
+ this.options.text = text;
562
+ }
563
+ };
564
+
565
+ /* A really lightweight plugin wrapper around the constructor, preventing against multiple instantiations
566
+ ================================================== */
567
+ $.fn[pluginName] = function ( options ) {
568
+ var args = arguments;
569
+ if (options === undefined || typeof options === 'object') {
570
+ return this.each(function () {
571
+ if (!$.data(this, 'plugin_' + pluginName)) {
572
+ $.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
573
+ }
574
+ });
575
+ } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
576
+ return this.each(function () {
577
+ var instance = $.data(this, 'plugin_' + pluginName);
578
+ if (instance instanceof Plugin && typeof instance[options] === 'function') {
579
+ instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) );
580
+ }
581
+ });
582
+ }
583
+ };
584
+ })(jQuery, window, document);
trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t,o,n,i){function r(e,o){this.element=e,this.options=t.extend(!0,{},l,o),this.options.share=o.share,this._defaults=l,this._name=a,this.init()}var a="sharrre",l={className:"sharrre",share:{googlePlus:!1,facebook:!1,twitter:!1,digg:!1,delicious:!1,stumbleupon:!1,linkedin:!1,pinterest:!1},shareTotal:0,template:"",title:"",url:n.location.href,text:n.title,urlCurl:"sharrre.php",count:{},total:0,shorterTotal:!0,enableHover:!0,enableCounter:!0,enableTracking:!1,hover:function(){},hide:function(){},click:function(){},render:function(){},buttons:{googlePlus:{url:"",urlCount:!1,size:"medium",lang:"en-US",annotation:""},facebook:{url:"",urlCount:!1,action:"like",layout:"button_count",width:"",send:"false",faces:"false",colorscheme:"",font:"",lang:"en_US"},twitter:{url:"",urlCount:!1,count:"horizontal",hashtags:"",via:"",related:"",lang:"en"},digg:{url:"",urlCount:!1,type:"DiggCompact"},delicious:{url:"",urlCount:!1,size:"medium"},stumbleupon:{url:"",urlCount:!1,layout:"1"},linkedin:{url:"",urlCount:!1,counter:""},pinterest:{url:"",media:"",description:"",layout:"horizontal"}}},u={googlePlus:"",facebook:"http://graph.facebook.com/?id={url}&callback=?",twitter:"http://cdn.api.twitter.com/1/urls/count.json?url={url}&callback=?",digg:"http://services.digg.com/2.0/story.getInfo?links={url}&type=javascript&callback=?",delicious:"http://feeds.delicious.com/v2/json/urlinfo/data?url={url}&callback=?",stumbleupon:"",linkedin:"http://www.linkedin.com/countserv/count/share?format=jsonp&url={url}&callback=?",pinterest:""},c={googlePlus:function(e){var i=e.options.buttons.googlePlus;t(e.element).find(".buttons").append('<div class="button googleplus"><div class="g-plusone" data-size="'+i.size+'" data-href="'+(""!==i.url?i.url:e.options.url)+'" data-annotation="'+i.annotation+'"></div></div>'),o.___gcfg={lang:e.options.buttons.googlePlus.lang};var s=0;"undefined"==typeof gapi&&0==s?(s=1,function(){var t=n.createElement("script");t.type="text/javascript",t.async=!0,t.src="//apis.google.com/js/plusone.js";var e=n.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}()):gapi.plusone.go()},facebook:function(e){var o=e.options.buttons.facebook;t(e.element).find(".buttons").append('<div class="button facebook"><div id="fb-root"></div><div class="fb-like" data-href="'+(""!==o.url?o.url:e.options.url)+'" data-send="'+o.send+'" data-layout="'+o.layout+'" data-width="'+o.width+'" data-show-faces="'+o.faces+'" data-action="'+o.action+'" data-colorscheme="'+o.colorscheme+'" data-font="'+o.font+'" data-via="'+o.via+'"></div></div>');var i=0;"undefined"==typeof FB&&0==i?(i=1,function(t,e,n){var i,s=t.getElementsByTagName(e)[0];t.getElementById(n)||(i=t.createElement(e),i.id=n,i.src="//connect.facebook.net/"+o.lang+"/all.js#xfbml=1",s.parentNode.insertBefore(i,s))}(n,"script","facebook-jssdk")):FB.XFBML.parse()},twitter:function(e){var o=e.options.buttons.twitter;t(e.element).find(".buttons").append('<div class="button twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-url="'+(""!==o.url?o.url:e.options.url)+'" data-count="'+o.count+'" data-text="'+e.options.text+'" data-via="'+o.via+'" data-hashtags="'+o.hashtags+'" data-related="'+o.related+'" data-lang="'+o.lang+'">Tweet</a></div>');var i=0;"undefined"==typeof twttr&&0==i?(i=1,function(){var t=n.createElement("script");t.type="text/javascript",t.async=!0,t.src="//platform.twitter.com/widgets.js";var e=n.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}()):t.ajax({url:"//platform.twitter.com/widgets.js",dataType:"script",cache:!0})},digg:function(e){var o=e.options.buttons.digg;t(e.element).find(".buttons").append('<div class="button digg"><a class="DiggThisButton '+o.type+'" rel="nofollow external" href="http://digg.com/submit?url='+encodeURIComponent(""!==o.url?o.url:e.options.url)+'"></a></div>');var i=0;"undefined"==typeof __DBW&&0==i&&(i=1,function(){var t=n.createElement("SCRIPT"),e=n.getElementsByTagName("SCRIPT")[0];t.type="text/javascript",t.async=!0,t.src="//widgets.digg.com/buttons.js",e.parentNode.insertBefore(t,e)}())},delicious:function(e){if("tall"==e.options.buttons.delicious.size)var o="width:50px;",n="height:35px;width:50px;font-size:15px;line-height:35px;",i="height:18px;line-height:18px;margin-top:3px;";else var o="width:93px;",n="float:right;padding:0 3px;height:20px;width:26px;line-height:20px;",i="float:left;height:20px;line-height:20px;";var s=e.shorterTotal(e.options.count.delicious);"undefined"==typeof s&&(s=0),t(e.element).find(".buttons").append('<div class="button delicious"><div style="'+o+'font:12px Arial,Helvetica,sans-serif;cursor:pointer;color:#666666;display:inline-block;float:none;height:20px;line-height:normal;margin:0;padding:0;text-indent:0;vertical-align:baseline;"><div style="'+n+'background-color:#fff;margin-bottom:5px;overflow:hidden;text-align:center;border:1px solid #ccc;border-radius:3px;">'+s+'</div><div style="'+i+'display:block;padding:0;text-align:center;text-decoration:none;width:50px;background-color:#7EACEE;border:1px solid #40679C;border-radius:3px;color:#fff;"><img src="http://www.delicious.com/static/img/delicious.small.gif" height="10" width="10" alt="Delicious" /> Add</div></div></div>'),t(e.element).find(".delicious").on("click",function(){e.openPopup("delicious")})},stumbleupon:function(e){var i=e.options.buttons.stumbleupon;t(e.element).find(".buttons").append('<div class="button stumbleupon"><su:badge layout="'+i.layout+'" location="'+(""!==i.url?i.url:e.options.url)+'"></su:badge></div>');var r=0;"undefined"==typeof STMBLPN&&0==r?(r=1,function(){var t=n.createElement("script");t.type="text/javascript",t.async=!0,t.src="//platform.stumbleupon.com/1/widgets.js";var e=n.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}(),s=o.setTimeout(function(){"undefined"!=typeof STMBLPN&&(STMBLPN.processWidgets(),clearInterval(s))},500)):STMBLPN.processWidgets()},linkedin:function(e){var i=e.options.buttons.linkedin;t(e.element).find(".buttons").append('<div class="button linkedin"><script type="in/share" data-url="'+(""!==i.url?i.url:e.options.url)+'" data-counter="'+i.counter+'"></script></div>');var s=0;"undefined"==typeof o.IN&&0==s?(s=1,function(){var t=n.createElement("script");t.type="text/javascript",t.async=!0,t.src="//platform.linkedin.com/in.js";var e=n.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}()):o.IN.init()},pinterest:function(e){var o=e.options.buttons.pinterest;t(e.element).find(".buttons").append('<div class="button pinterest"><a href="http://pinterest.com/pin/create/button/?url='+(""!==o.url?o.url:e.options.url)+"&media="+o.media+"&description="+o.description+'" class="pin-it-button" count-layout="'+o.layout+'">Pin It</a></div>'),function(){var t=n.createElement("script");t.type="text/javascript",t.async=!0,t.src="//assets.pinterest.com/js/pinit.js";var e=n.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}()}},p={googlePlus:function(){},facebook:function(){fb=o.setInterval(function(){"undefined"!=typeof FB&&(FB.Event.subscribe("edge.create",function(t){_gaq.push(["_trackSocial","facebook","like",t])}),FB.Event.subscribe("edge.remove",function(t){_gaq.push(["_trackSocial","facebook","unlike",t])}),FB.Event.subscribe("message.send",function(t){_gaq.push(["_trackSocial","facebook","send",t])}),clearInterval(fb))},1e3)},twitter:function(){tw=o.setInterval(function(){"undefined"!=typeof twttr&&(twttr.events.bind("tweet",function(t){t&&_gaq.push(["_trackSocial","twitter","tweet"])}),clearInterval(tw))},1e3)},digg:function(){},delicious:function(){},stumbleupon:function(){},linkedin:function(){},pinterest:function(){}},d={googlePlus:function(t){o.open("https://plus.google.com/share?hl="+t.buttons.googlePlus.lang+"&url="+encodeURIComponent(""!==t.buttons.googlePlus.url?t.buttons.googlePlus.url:t.url),"","toolbar=0, status=0, width=900, height=500")},facebook:function(t){o.open("http://www.facebook.com/sharer.php?u="+encodeURIComponent(""!==t.buttons.facebook.url?t.buttons.facebook.url:t.url)+"&t="+t.text,"","toolbar=0, status=0, width=900, height=500")},twitter:function(t){o.open("https://twitter.com/intent/tweet?text="+encodeURIComponent(t.text)+"&url="+encodeURIComponent(""!==t.buttons.twitter.url?t.buttons.twitter.url:t.url)+(""!==t.buttons.twitter.via?"&via="+t.buttons.twitter.via:""),"","toolbar=0, status=0, width=650, height=360")},digg:function(t){o.open("http://digg.com/tools/diggthis/submit?url="+encodeURIComponent(""!==t.buttons.digg.url?t.buttons.digg.url:t.url)+"&title="+t.text+"&related=true&style=true","","toolbar=0, status=0, width=650, height=360")},delicious:function(t){o.open("http://www.delicious.com/save?v=5&noui&jump=close&url="+encodeURIComponent(""!==t.buttons.delicious.url?t.buttons.delicious.url:t.url)+"&title="+t.text,"delicious","toolbar=no,width=550,height=550")},stumbleupon:function(t){o.open("http://www.stumbleupon.com/badge/?url="+encodeURIComponent(""!==t.buttons.delicious.url?t.buttons.delicious.url:t.url),"stumbleupon","toolbar=no,width=550,height=550")},linkedin:function(t){o.open("https://www.linkedin.com/cws/share?url="+encodeURIComponent(""!==t.buttons.delicious.url?t.buttons.delicious.url:t.url)+"&token=&isFramed=true","linkedin","toolbar=no,width=550,height=550")},pinterest:function(t){o.open("http://pinterest.com/pin/create/button/?url="+encodeURIComponent(""!==t.buttons.pinterest.url?t.buttons.pinterest.url:t.url)+"&media="+encodeURIComponent(t.buttons.pinterest.media)+"&description="+t.buttons.pinterest.description,"pinterest","toolbar=no,width=700,height=300")}};r.prototype.init=function(){var e=this;""!==this.options.urlCurl&&(u.googlePlus=this.options.urlCurl+"?url={url}&type=googlePlus",u.stumbleupon=this.options.urlCurl+"?url={url}&type=stumbleupon",u.pinterest=this.options.urlCurl+"?url={url}&type=pinterest"),t(this.element).addClass(this.options.className),"undefined"!=typeof t(this.element).data("title")&&(this.options.title=t(this.element).attr("data-title")),"undefined"!=typeof t(this.element).data("url")&&(this.options.url=t(this.element).data("url")),"undefined"!=typeof t(this.element).data("text")&&(this.options.text=t(this.element).data("text")),t.each(this.options.share,function(t,o){o===!0&&e.options.shareTotal++}),e.options.enableCounter===!0?t.each(this.options.share,function(t,o){if(o===!0)try{e.getSocialJson(t)}catch(n){}}):""!==e.options.template?this.options.render(this,this.options):this.loadButtons(),t(this.element).hover(function(){0===t(this).find(".buttons").length&&e.options.enableHover===!0&&e.loadButtons(),e.options.hover(e,e.options)},function(){e.options.hide(e,e.options)}),t(this.element).click(function(){return e.options.click(e,e.options),!1})},r.prototype.loadButtons=function(){var e=this;t(this.element).append('<div class="buttons"></div>'),t.each(e.options.share,function(t,o){1==o&&(c[t](e),e.options.enableTracking===!0&&p[t]())})},r.prototype.getSocialJson=function(e){var o=this,n=0,i=u[e].replace("{url}",encodeURIComponent(this.options.url));this.options.buttons[e].urlCount===!0&&""!==this.options.buttons[e].url&&(i=u[e].replace("{url}",this.options.buttons[e].url)),""!=i&&""!==o.options.urlCurl?t.getJSON(i,function(t){if("undefined"!=typeof t.count){var i=t.count+"";i=i.replace(" ",""),n+=parseInt(i,10)}else"undefined"!=typeof t.likes?n+=parseInt(t.likes,10):"undefined"!=typeof t.shares?n+=parseInt(t.shares,10):"undefined"!=typeof t[0]?n+=parseInt(t[0].total_posts,10):"undefined"!=typeof t[0];o.options.count[e]=n,o.options.total+=n,o.renderer(),o.rendererPerso()}).error(function(){o.options.count[e]=0,o.rendererPerso()}):(o.renderer(),o.options.count[e]=0,o.rendererPerso())},r.prototype.rendererPerso=function(){var t=0;for(e in this.options.count)t++;t===this.options.shareTotal&&this.options.render(this,this.options)},r.prototype.renderer=function(){var e=this.options.total,o=this.options.template;this.options.shorterTotal===!0&&(e=this.shorterTotal(e)),""!==o?(o=o.replace("{total}",e),t(this.element).html(o)):t(this.element).html('<div class="box"><a class="count" href="#">'+e+"</a>"+(""!==this.options.title?'<a class="share" href="#">'+this.options.title+"</a>":"")+"</div>")},r.prototype.shorterTotal=function(t){return t>=1e6?t=(t/1e6).toFixed(2)+"M":t>=1e3&&(t=(t/1e3).toFixed(1)+"k"),t},r.prototype.openPopup=function(t){if(d[t](this.options),this.options.enableTracking===!0){var e={googlePlus:{site:"Google",action:"+1"},facebook:{site:"facebook",action:"like"},twitter:{site:"twitter",action:"tweet"},digg:{site:"digg",action:"add"},delicious:{site:"delicious",action:"add"},stumbleupon:{site:"stumbleupon",action:"add"},linkedin:{site:"linkedin",action:"share"},pinterest:{site:"pinterest",action:"pin"}};_gaq.push(["_trackSocial",e[t].site,e[t].action])}},r.prototype.simulateClick=function(){var e=t(this.element).html();t(this.element).html(e.replace(this.options.total,this.options.total+1))},r.prototype.update=function(t,e){""!==t&&(this.options.url=t),""!==e&&(this.options.text=e)},t.fn[a]=function(e){var o=arguments;return e===i||"object"==typeof e?this.each(function(){t.data(this,"plugin_"+a)||t.data(this,"plugin_"+a,new r(this,e))}):"string"==typeof e&&"_"!==e[0]&&"init"!==e?this.each(function(){var n=t.data(this,"plugin_"+a);n instanceof r&&"function"==typeof n[e]&&n[e].apply(n,Array.prototype.slice.call(o,1))}):void 0}}(jQuery,window,document);
trunk/classes/class.acf-integration.php ADDED
@@ -0,0 +1,740 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class ifor integrating landingpage CPT with ACF4 & ACF5
5
+ * @package ACF
6
+ */
7
+
8
+ class Landing_Pages_ACF {
9
+
10
+ /**
11
+ * Name under which the transient for the current tab will be saved.
12
+ * @var string
13
+ */
14
+ static $_transient_name = 'acf_current_tab';
15
+ /**
16
+ * Number of minutes the transient will be saved.
17
+ * @var int
18
+ */
19
+ static $_transient_minutes = 5;
20
+
21
+
22
+ /**
23
+ * Initialize Landing_Pages_ACF Class
24
+ */
25
+ public function __construct() {
26
+ self::load_hooks();
27
+ }
28
+
29
+
30
+ /**
31
+ * Load Hooks & Filters
32
+ */
33
+ public static function load_hooks() {
34
+
35
+ /* Load ACF Fields On ACF powered Email Template */
36
+ add_filter( 'acf/location/rule_match/template_id' , array( __CLASS__ , 'load_acf_on_template' ) , 10 , 3 );
37
+
38
+ /* make sure fields are placed in the correct location */
39
+ add_action( 'save_post', array( __CLASS__ , 'save_acf_fields' ) );
40
+
41
+ /* make sure fields are placed in the correct location */
42
+ add_action( 'wp_restore_post_revision', array( __CLASS__ , 'restore_acf_values' ) , 10 , 2 );
43
+
44
+ /* Adds revision fields to the revisions screen */
45
+
46
+ /* Adds revision fields value for Inbound Settings to the revisions screen */
47
+ add_filter( '_wp_post_revision_fields', array( __CLASS__ , 'add_revision_fields' ) );
48
+ add_filter( '_wp_post_revision_field_inbound_settings', array( __CLASS__ , 'add_revision_field_values' ) , 10 , 3 );
49
+
50
+ /* Intercept load custom field value request and hijack it */
51
+ add_filter( 'acf/load_value' , array( __CLASS__ , 'load_value' ) , 11 , 3 );
52
+
53
+ /* extra field formatting
54
+ add_filter( 'acf/format_value' , array( __CLASS__ , 'format_value' ) , 11 , 3 ); */
55
+
56
+ /* make sure fields are placed in the correct location */
57
+ add_action( 'admin_print_footer_scripts', array( __CLASS__ , 'reposition_acf_fields' ) );
58
+
59
+ /* add new location rule to ACF Field UI */
60
+ add_filter('acf/location/rule_types', array( __CLASS__ , 'define_location_rule_types' ) );
61
+
62
+ /* add new location rule values to ACF Field UI */
63
+ add_filter('acf/location/rule_values/template_id', array( __CLASS__ , 'define_location_rule_values' ) );
64
+
65
+ add_action( 'acf/input/admin_footer', array( __CLASS__ , 'handle_tab' ) );
66
+ add_action( 'wp_ajax_acf_save_current_tab', array( __CLASS__ , 'ajax_acf_save_current_tab' ) );
67
+
68
+ }
69
+
70
+ /**
71
+ * @param $choices
72
+ * @return mixed
73
+ */
74
+ public static function define_location_rule_types( $choices ) {
75
+
76
+ if (!isset($choices['Basic']['template_id'])) {
77
+ $choices['Basic']['template_id'] = __('Template ID', 'landing-page');
78
+ }
79
+
80
+ return $choices;
81
+ }
82
+
83
+ public static function define_location_rule_values( $choices ) {
84
+ $template_ids = Landing_Pages_Load_Extensions::get_uploaded_template_ids();
85
+
86
+ if (!isset($choices['default'])) {
87
+ $choices[ 'default' ] = 'default';
88
+ }
89
+
90
+ if( $template_ids ) {
91
+ foreach( $template_ids as $template_id ) {
92
+
93
+ /* template ID by template name here */
94
+ $choices[ $template_id ] = $template_id;
95
+
96
+ }
97
+ }
98
+
99
+ return $choices;
100
+ }
101
+
102
+ /**
103
+ * Adds javascript to make sure ACF fields load inside template container
104
+ */
105
+ public static function reposition_acf_fields() {
106
+ global $post;
107
+
108
+ if ( !defined('ACF_FREE') || ( !isset($post) || $post->post_type != 'landing-page' ) ) {
109
+ return;
110
+ }
111
+
112
+ ?>
113
+ <script type='text/javascript'>
114
+ jQuery('.acf_postbox').each(function(){
115
+ jQuery('#template-display-options').append(jQuery(this));
116
+ });
117
+ </script>
118
+ <?php
119
+ }
120
+
121
+
122
+ /**
123
+ * Compiles ACF Meta Data into a singular json pair for variation support
124
+ * @param $landing_page_id
125
+ */
126
+ public static function save_acf_fields( $landing_page_id ) {
127
+
128
+
129
+ if ( !isset($_POST['post_type']) || $_POST['post_type'] != 'landing-page' ) {
130
+ return;
131
+ }
132
+
133
+ if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
134
+ return;
135
+ }
136
+
137
+ /* save acf settings - uses our future data array - eventually we will migrate all post meta into this data object */
138
+ $fields = (isset($_POST['fields'])) ? $_POST['fields'] : null;
139
+ $fields = (isset($_POST['acf'])) ? $_POST['acf'] : $fields;
140
+
141
+ if ( $fields ) {
142
+
143
+ $settings = Landing_Pages_Meta::get_settings( $landing_page_id );
144
+ $variation_id = (isset($_REQUEST['lp-variation-id'])) ? intval($_REQUEST['lp-variation-id']) : '0';
145
+
146
+ if (!isset($settings['variations'])) {
147
+ $settings['variations'] = array();
148
+ }
149
+
150
+ $settings['variations'][$variation_id]['acf'] = $fields;
151
+ Landing_Pages_Meta::update_settings( $landing_page_id , $settings );
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Restore landing page ACF values from revision
157
+ * @param $post_id
158
+ * @param $revision_id
159
+ */
160
+ public static function restore_acf_values( $post_id , $revision_id ) {
161
+
162
+ $post = get_post($post_id);
163
+ if($post->post_type!='landing-page' ) {
164
+ return;
165
+ }
166
+
167
+ $revision_settings = Landing_Pages_Meta::get_settings( $revision_id );
168
+
169
+ Landing_Pages_Meta::update_settings( $post_id , $revision_settings );
170
+
171
+ }
172
+
173
+ /**
174
+ * Adds revision fields to revisions screen
175
+ * @param $fields
176
+ * @return mixed
177
+ */
178
+ public static function add_revision_fields( $fields ) {
179
+ global $post;
180
+ $fields['inbound_settings'] = __('Landing Page Settings' , 'inbound-pro');
181
+ return $fields;
182
+ }
183
+
184
+ public static function add_revision_field_values( $value , $field , $revision) {
185
+
186
+ if (!isset($revision->ID)) {
187
+ return $value;
188
+ }
189
+
190
+ $settings = Landing_Pages_Meta::get_settings( $revision->ID );
191
+
192
+ return json_encode($settings);
193
+ }
194
+
195
+ /**
196
+ * Although unused at the moment, this method can be used for filtering the return value with ACF5 fields
197
+ * @param $value
198
+ * @param $post_id
199
+ * @param $field
200
+ * @return mixed
201
+ */
202
+ public static function format_value( $value, $post_id, $field ) {
203
+ return $value;
204
+ }
205
+
206
+ /**
207
+ * Finds the correct value given the variation
208
+ *
209
+ * @param MIXED $value contains the non-variation value
210
+ * @param INT $post_id ID of landing page being loaded
211
+ * @param ARRAY $field wide array of data belonging to custom field (not leveraged in this method)
212
+ *
213
+ * @returns MIXED $new_value value mapped to variation.
214
+ */
215
+ public static function load_value( $value, $post_id, $field ) {
216
+ global $post;
217
+
218
+ if ( !isset($post) || $post->post_type != 'landing-page' ) {
219
+ return $value;
220
+ }
221
+
222
+ $vid = Landing_Pages_Variations::get_new_variation_reference_id(