WordPress Landing Pages - Version 2.7.7

Version Description

  • Fixing issue with category filter on landing pages CPT listing page
Download this release

Release Info

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

Code changes from version 2.7.6 to 2.7.7

Files changed (496) hide show
  1. classes/class.acf-integration.php +18 -4
  2. classes/class.post-type.landing-page.php +6 -1
  3. landing-pages.php +2 -2
  4. readme.txt +7 -3
  5. shared/classes/class.acf-bootstrap.php +3 -3
  6. shared/classes/class.events.php +5 -1
  7. shared/classes/class.lead-storage.php +16 -6
  8. trunk/README.md +0 -53
  9. trunk/assets/css/admin-ab-testing.css +0 -311
  10. trunk/assets/css/admin-post-edit.css +0 -212
  11. trunk/assets/css/admin-post-new.css +0 -110
  12. trunk/assets/css/admin-templates.css +0 -48
  13. trunk/assets/css/admin-tour.css +0 -216
  14. trunk/assets/css/admin/acf-hide-wp-elements.css +0 -1
  15. trunk/assets/css/admin/content-stats.css +0 -87
  16. trunk/assets/css/admin/customizer-edit.css +0 -247
  17. trunk/assets/css/admin/edit-landing-page.css +0 -167
  18. trunk/assets/css/admin/global-settings.css +0 -231
  19. trunk/assets/css/admin/install-plugins.css +0 -13
  20. trunk/assets/css/admin/landing-page-edit-style.css +0 -542
  21. trunk/assets/css/admin/landing-page-list.css +0 -492
  22. trunk/assets/css/customizer-load.css +0 -76
  23. trunk/assets/css/customizer.frontend.css +0 -157
  24. trunk/assets/css/customizer.media-uploader.css +0 -34
  25. trunk/assets/css/frontend/customizer-preview.css +0 -1
  26. trunk/assets/css/frontend/global-landing-page-style.css +0 -43
  27. trunk/assets/css/frontend/index.php +0 -2
  28. trunk/assets/css/iframe-preview.css +0 -3
  29. trunk/assets/css/images/dropdownback.png +0 -0
  30. trunk/assets/css/images/headerback.png +0 -0
  31. trunk/assets/css/images/hover.png +0 -0
  32. trunk/assets/css/images/index.php +0 -2
  33. trunk/assets/css/images/linkback.png +0 -0
  34. trunk/assets/css/images/question-light.png +0 -0
  35. trunk/assets/css/images/tooltip.png +0 -0
  36. trunk/assets/css/index.php +0 -2
  37. trunk/assets/images/ab-retina-icons.png +0 -0
  38. trunk/assets/images/add-on-image.png +0 -0
  39. trunk/assets/images/cta-install.png +0 -0
  40. trunk/assets/images/custom-setup-image.png +0 -0
  41. trunk/assets/images/get-custom-setup.png +0 -0
  42. trunk/assets/images/get-wordpress-templates.png +0 -0
  43. trunk/assets/images/github-help.jpg +0 -0
  44. trunk/assets/images/image.php +0 -76
  45. trunk/assets/images/index.php +0 -2
  46. trunk/assets/images/leads-install.png +0 -0
  47. trunk/assets/images/localhost.png +0 -0
  48. trunk/assets/images/templates-image.png +0 -0
  49. trunk/assets/images/variation-normal.png +0 -0
  50. trunk/assets/images/variation-up.png +0 -0
  51. trunk/assets/js/admin/admin.global-settings.js +0 -73
  52. trunk/assets/js/admin/admin.install-plugins.js +0 -30
  53. trunk/assets/js/admin/admin.landing-page-list.js +0 -117
  54. trunk/assets/js/admin/admin.metaboxes.js +0 -1
  55. trunk/assets/js/admin/admin.post-edit-ab-testing.js +0 -64
  56. trunk/assets/js/admin/admin.post-edit.js +0 -308
  57. trunk/assets/js/admin/admin.post-new.js +0 -144
  58. trunk/assets/js/admin/admin.post.js +0 -35
  59. trunk/assets/js/admin/admin.templates-upload.js +0 -25
  60. trunk/assets/js/admin/admin.templates.js +0 -1
  61. trunk/assets/js/admin/index.php +0 -2
  62. trunk/assets/js/admin/intro.js +0 -758
  63. trunk/assets/js/admin/tour/tour.post-edit.js +0 -9
  64. trunk/assets/js/admin/tour/tour.post-list.js +0 -8
  65. trunk/assets/js/ajax.clearstats.js +0 -1
  66. trunk/assets/js/index.php +0 -2
  67. trunk/assets/js/jquery.bindfirst.js +0 -15
  68. trunk/assets/js/jquery.cookie.js +0 -1
  69. trunk/assets/js/jquery.easing.min.js +0 -44
  70. trunk/assets/js/jquery.form-population.js +0 -1
  71. trunk/assets/js/jquery.lp.cookie.js +0 -1
  72. trunk/assets/js/jquery.tablesorter.js +0 -1031
  73. trunk/assets/js/jquery.total-storage.min.js +0 -22
  74. trunk/assets/js/stop_page_stats.js +0 -7
  75. trunk/assets/js/wordpress/editor.min.js +0 -1
  76. trunk/assets/js/wordpress/index.php +0 -2
  77. trunk/assets/lang/landing-pages-ach.mo +0 -0
  78. trunk/assets/lang/landing-pages-ady.mo +0 -0
  79. trunk/assets/lang/landing-pages-af.mo +0 -0
  80. trunk/assets/lang/landing-pages-af_ZA.mo +0 -0
  81. trunk/assets/lang/landing-pages-ak.mo +0 -0
  82. trunk/assets/lang/landing-pages-aln.mo +0 -0
  83. trunk/assets/lang/landing-pages-am.mo +0 -0
  84. trunk/assets/lang/landing-pages-am_ET.mo +0 -0
  85. trunk/assets/lang/landing-pages-an.mo +0 -0
  86. trunk/assets/lang/landing-pages-ar.mo +0 -0
  87. trunk/assets/lang/landing-pages-ar_AA.mo +0 -0
  88. trunk/assets/lang/landing-pages-ar_EG.mo +0 -0
  89. trunk/assets/lang/landing-pages-ar_SA.mo +0 -0
  90. trunk/assets/lang/landing-pages-ar_SD.mo +0 -0
  91. trunk/assets/lang/landing-pages-ar_SY.mo +0 -0
  92. trunk/assets/lang/landing-pages-arn.mo +0 -0
  93. trunk/assets/lang/landing-pages-as.mo +0 -0
  94. trunk/assets/lang/landing-pages-as_IN.mo +0 -0
  95. trunk/assets/lang/landing-pages-ast.mo +0 -0
  96. trunk/assets/lang/landing-pages-ast_ES.mo +0 -0
  97. trunk/assets/lang/landing-pages-az.mo +0 -0
  98. trunk/assets/lang/landing-pages-az@Arab.mo +0 -0
  99. trunk/assets/lang/landing-pages-az@latin.mo +0 -0
  100. trunk/assets/lang/landing-pages-az_AZ.mo +0 -0
  101. trunk/assets/lang/landing-pages-az_IR.mo +0 -0
  102. trunk/assets/lang/landing-pages-ba.mo +0 -0
  103. trunk/assets/lang/landing-pages-bal.mo +0 -0
  104. trunk/assets/lang/landing-pages-bar.mo +0 -0
  105. trunk/assets/lang/landing-pages-be.mo +0 -0
  106. trunk/assets/lang/landing-pages-be@tarask.mo +0 -0
  107. trunk/assets/lang/landing-pages-be_BY.mo +0 -0
  108. trunk/assets/lang/landing-pages-bg.mo +0 -0
  109. trunk/assets/lang/landing-pages-bg_BG.mo +0 -0
  110. trunk/assets/lang/landing-pages-bn.mo +0 -0
  111. trunk/assets/lang/landing-pages-bn_BD.mo +0 -0
  112. trunk/assets/lang/landing-pages-bn_IN.mo +0 -0
  113. trunk/assets/lang/landing-pages-bo.mo +0 -0
  114. trunk/assets/lang/landing-pages-bo_CN.mo +0 -0
  115. trunk/assets/lang/landing-pages-br.mo +0 -0
  116. trunk/assets/lang/landing-pages-brx.mo +0 -0
  117. trunk/assets/lang/landing-pages-bs.mo +0 -0
  118. trunk/assets/lang/landing-pages-bs_BA.mo +0 -0
  119. trunk/assets/lang/landing-pages-ca.mo +0 -0
  120. trunk/assets/lang/landing-pages-ca@valencia.mo +0 -0
  121. trunk/assets/lang/landing-pages-ca_ES.mo +0 -0
  122. trunk/assets/lang/landing-pages-cdo.mo +0 -0
  123. trunk/assets/lang/landing-pages-ceb.mo +0 -0
  124. trunk/assets/lang/landing-pages-cgg.mo +0 -0
  125. trunk/assets/lang/landing-pages-cjy.mo +0 -0
  126. trunk/assets/lang/landing-pages-cmn.mo +0 -0
  127. trunk/assets/lang/landing-pages-co.mo +0 -0
  128. trunk/assets/lang/landing-pages-cpx.mo +0 -0
  129. trunk/assets/lang/landing-pages-crh.mo +0 -0
  130. trunk/assets/lang/landing-pages-cs.mo +0 -0
  131. trunk/assets/lang/landing-pages-cs_CZ.mo +0 -0
  132. trunk/assets/lang/landing-pages-cv.mo +0 -0
  133. trunk/assets/lang/landing-pages-cy.mo +0 -0
  134. trunk/assets/lang/landing-pages-cy_GB.mo +0 -0
  135. trunk/assets/lang/landing-pages-czh.mo +0 -0
  136. trunk/assets/lang/landing-pages-czo.mo +0 -0
  137. trunk/assets/lang/landing-pages-da.mo +0 -0
  138. trunk/assets/lang/landing-pages-da_DK.mo +0 -0
  139. trunk/assets/lang/landing-pages-de.mo +0 -0
  140. trunk/assets/lang/landing-pages-de_AT.mo +0 -0
  141. trunk/assets/lang/landing-pages-de_CH.mo +0 -0
  142. trunk/assets/lang/landing-pages-de_DE.mo +0 -0
  143. trunk/assets/lang/landing-pages-doi.mo +0 -0
  144. trunk/assets/lang/landing-pages-dv.mo +0 -0
  145. trunk/assets/lang/landing-pages-dz.mo +0 -0
  146. trunk/assets/lang/landing-pages-dz_BT.mo +0 -0
  147. trunk/assets/lang/landing-pages-el.mo +0 -0
  148. trunk/assets/lang/landing-pages-el_GR.mo +0 -0
  149. trunk/assets/lang/landing-pages-en.mo +0 -0
  150. trunk/assets/lang/landing-pages-en@pirate.mo +0 -0
  151. trunk/assets/lang/landing-pages-en_AT.mo +0 -0
  152. trunk/assets/lang/landing-pages-en_AU.mo +0 -0
  153. trunk/assets/lang/landing-pages-en_BD.mo +0 -0
  154. trunk/assets/lang/landing-pages-en_BE.mo +0 -0
  155. trunk/assets/lang/landing-pages-en_CA.mo +0 -0
  156. trunk/assets/lang/landing-pages-en_CH.mo +0 -0
  157. trunk/assets/lang/landing-pages-en_CL.mo +0 -0
  158. trunk/assets/lang/landing-pages-en_CZ.mo +0 -0
  159. trunk/assets/lang/landing-pages-en_DE.mo +0 -0
  160. trunk/assets/lang/landing-pages-en_EG.mo +0 -0
  161. trunk/assets/lang/landing-pages-en_ES.mo +0 -0
  162. trunk/assets/lang/landing-pages-en_FI.mo +0 -0
  163. trunk/assets/lang/landing-pages-en_GB.mo +0 -0
  164. trunk/assets/lang/landing-pages-en_GH.mo +0 -0
  165. trunk/assets/lang/landing-pages-en_GR.mo +0 -0
  166. trunk/assets/lang/landing-pages-en_HK.mo +0 -0
  167. trunk/assets/lang/landing-pages-en_HR.mo +0 -0
  168. trunk/assets/lang/landing-pages-en_HU.mo +0 -0
  169. trunk/assets/lang/landing-pages-en_IE.mo +0 -0
  170. trunk/assets/lang/landing-pages-en_IN.mo +0 -0
  171. trunk/assets/lang/landing-pages-en_IT.mo +0 -0
  172. trunk/assets/lang/landing-pages-en_LK.mo +0 -0
  173. trunk/assets/lang/landing-pages-en_NG.mo +0 -0
  174. trunk/assets/lang/landing-pages-en_NL.mo +0 -0
  175. trunk/assets/lang/landing-pages-en_NO.mo +0 -0
  176. trunk/assets/lang/landing-pages-en_NZ.mo +0 -0
  177. trunk/assets/lang/landing-pages-en_PK.mo +0 -0
  178. trunk/assets/lang/landing-pages-en_PL.mo +0 -0
  179. trunk/assets/lang/landing-pages-en_PT.mo +0 -0
  180. trunk/assets/lang/landing-pages-en_RO.mo +0 -0
  181. trunk/assets/lang/landing-pages-en_SE.mo +0 -0
  182. trunk/assets/lang/landing-pages-en_SK.mo +0 -0
  183. trunk/assets/lang/landing-pages-en_ZA.mo +0 -0
  184. trunk/assets/lang/landing-pages-en_ee.mo +0 -0
  185. trunk/assets/lang/landing-pages-en_lt.mo +0 -0
  186. trunk/assets/lang/landing-pages-en_lv.mo +0 -0
  187. trunk/assets/lang/landing-pages-eo.mo +0 -0
  188. trunk/assets/lang/landing-pages-es.mo +0 -0
  189. trunk/assets/lang/landing-pages-es_419.mo +0 -0
  190. trunk/assets/lang/landing-pages-es_AR.mo +0 -0
  191. trunk/assets/lang/landing-pages-es_BO.mo +0 -0
  192. trunk/assets/lang/landing-pages-es_CL.mo +0 -0
  193. trunk/assets/lang/landing-pages-es_CO.mo +0 -0
  194. trunk/assets/lang/landing-pages-es_CR.mo +0 -0
  195. trunk/assets/lang/landing-pages-es_DO.mo +0 -0
  196. trunk/assets/lang/landing-pages-es_EC.mo +0 -0
  197. trunk/assets/lang/landing-pages-es_ES.mo +0 -0
  198. trunk/assets/lang/landing-pages-es_GT.mo +0 -0
  199. trunk/assets/lang/landing-pages-es_HN.mo +0 -0
  200. trunk/assets/lang/landing-pages-es_MX.mo +0 -0
  201. trunk/assets/lang/landing-pages-es_NI.mo +0 -0
  202. trunk/assets/lang/landing-pages-es_PA.mo +0 -0
  203. trunk/assets/lang/landing-pages-es_PE.mo +0 -0
  204. trunk/assets/lang/landing-pages-es_PR.mo +0 -0
  205. trunk/assets/lang/landing-pages-es_PY.mo +0 -0
  206. trunk/assets/lang/landing-pages-es_SV.mo +0 -0
  207. trunk/assets/lang/landing-pages-es_US.mo +0 -0
  208. trunk/assets/lang/landing-pages-es_UY.mo +0 -0
  209. trunk/assets/lang/landing-pages-es_VE.mo +0 -0
  210. trunk/assets/lang/landing-pages-et.mo +0 -0
  211. trunk/assets/lang/landing-pages-et_EE.mo +0 -0
  212. trunk/assets/lang/landing-pages-eu.mo +0 -0
  213. trunk/assets/lang/landing-pages-eu_ES.mo +0 -0
  214. trunk/assets/lang/landing-pages-fa.mo +0 -0
  215. trunk/assets/lang/landing-pages-fa_AF.mo +0 -0
  216. trunk/assets/lang/landing-pages-fa_IR.mo +0 -0
  217. trunk/assets/lang/landing-pages-ff.mo +0 -0
  218. trunk/assets/lang/landing-pages-ff_SN.mo +0 -0
  219. trunk/assets/lang/landing-pages-fi.mo +0 -0
  220. trunk/assets/lang/landing-pages-fi_FI.mo +0 -0
  221. trunk/assets/lang/landing-pages-fil.mo +0 -0
  222. trunk/assets/lang/landing-pages-fo.mo +0 -0
  223. trunk/assets/lang/landing-pages-fo_FO.mo +0 -0
  224. trunk/assets/lang/landing-pages-fr.mo +0 -0
  225. trunk/assets/lang/landing-pages-fr_BE.mo +0 -0
  226. trunk/assets/lang/landing-pages-fr_CA.mo +0 -0
  227. trunk/assets/lang/landing-pages-fr_CH.mo +0 -0
  228. trunk/assets/lang/landing-pages-fr_FR.mo +0 -0
  229. trunk/assets/lang/landing-pages-frp.mo +0 -0
  230. trunk/assets/lang/landing-pages-fur.mo +0 -0
  231. trunk/assets/lang/landing-pages-fy.mo +0 -0
  232. trunk/assets/lang/landing-pages-fy_NL.mo +0 -0
  233. trunk/assets/lang/landing-pages-ga.mo +0 -0
  234. trunk/assets/lang/landing-pages-ga_IE.mo +0 -0
  235. trunk/assets/lang/landing-pages-gan.mo +0 -0
  236. trunk/assets/lang/landing-pages-gd.mo +0 -0
  237. trunk/assets/lang/landing-pages-gl.mo +0 -0
  238. trunk/assets/lang/landing-pages-gl_ES.mo +0 -0
  239. trunk/assets/lang/landing-pages-gu.mo +0 -0
  240. trunk/assets/lang/landing-pages-gu_IN.mo +0 -0
  241. trunk/assets/lang/landing-pages-gun.mo +0 -0
  242. trunk/assets/lang/landing-pages-ha.mo +0 -0
  243. trunk/assets/lang/landing-pages-hak.mo +0 -0
  244. trunk/assets/lang/landing-pages-haw.mo +0 -0
  245. trunk/assets/lang/landing-pages-he.mo +0 -0
  246. trunk/assets/lang/landing-pages-he_IL.mo +0 -0
  247. trunk/assets/lang/landing-pages-hi.mo +0 -0
  248. trunk/assets/lang/landing-pages-hi_IN.mo +0 -0
  249. trunk/assets/lang/landing-pages-hne.mo +0 -0
  250. trunk/assets/lang/landing-pages-hr.mo +0 -0
  251. trunk/assets/lang/landing-pages-hr_HR.mo +0 -0
  252. trunk/assets/lang/landing-pages-hsb.mo +0 -0
  253. trunk/assets/lang/landing-pages-hsn.mo +0 -0
  254. trunk/assets/lang/landing-pages-ht.mo +0 -0
  255. trunk/assets/lang/landing-pages-ht_HT.mo +0 -0
  256. trunk/assets/lang/landing-pages-hu.mo +0 -0
  257. trunk/assets/lang/landing-pages-hu_HU.mo +0 -0
  258. trunk/assets/lang/landing-pages-hu_RO.mo +0 -0
  259. trunk/assets/lang/landing-pages-hy.mo +0 -0
  260. trunk/assets/lang/landing-pages-hy_AM.mo +0 -0
  261. trunk/assets/lang/landing-pages-ia.mo +0 -0
  262. trunk/assets/lang/landing-pages-id.mo +0 -0
  263. trunk/assets/lang/landing-pages-id_ID.mo +0 -0
  264. trunk/assets/lang/landing-pages-ig.mo +0 -0
  265. trunk/assets/lang/landing-pages-ilo.mo +0 -0
  266. trunk/assets/lang/landing-pages-io.mo +0 -0
  267. trunk/assets/lang/landing-pages-is.mo +0 -0
  268. trunk/assets/lang/landing-pages-is_IS.mo +0 -0
  269. trunk/assets/lang/landing-pages-it.mo +0 -0
  270. trunk/assets/lang/landing-pages-it_CH.mo +0 -0
  271. trunk/assets/lang/landing-pages-it_IT.mo +0 -0
  272. trunk/assets/lang/landing-pages-iu.mo +0 -0
  273. trunk/assets/lang/landing-pages-ja.mo +0 -0
  274. trunk/assets/lang/landing-pages-ja_JP.mo +0 -0
  275. trunk/assets/lang/landing-pages-jv.mo +0 -0
  276. trunk/assets/lang/landing-pages-ka.mo +0 -0
  277. trunk/assets/lang/landing-pages-ka_GE.mo +0 -0
  278. trunk/assets/lang/landing-pages-kab.mo +0 -0
  279. trunk/assets/lang/landing-pages-kl.mo +0 -0
  280. trunk/assets/lang/landing-pages-kn.mo +0 -0
  281. trunk/assets/lang/landing-pages-kn_IN.mo +0 -0
  282. trunk/assets/lang/landing-pages-ksh.mo +0 -0
  283. trunk/assets/lang/landing-pages-ku.mo +0 -0
  284. trunk/assets/lang/landing-pages-kw.mo +0 -0
  285. trunk/assets/lang/landing-pages-la.mo +0 -0
  286. trunk/assets/lang/landing-pages-lg.mo +0 -0
  287. trunk/assets/lang/landing-pages-lzh.mo +0 -0
  288. trunk/assets/lang/landing-pages-mh.mo +0 -0
  289. trunk/assets/lang/landing-pages-mi.mo +0 -0
  290. trunk/assets/lang/landing-pages-mn.mo +0 -0
  291. trunk/assets/lang/landing-pages-mn_MN.mo +0 -0
  292. trunk/assets/lang/landing-pages-mni.mo +0 -0
  293. trunk/assets/lang/landing-pages-mnp.mo +0 -0
  294. trunk/assets/lang/landing-pages-mr.mo +0 -0
  295. trunk/assets/lang/landing-pages-mr_IN.mo +0 -0
  296. trunk/assets/lang/landing-pages-ms.mo +0 -0
  297. trunk/assets/lang/landing-pages-mw1.mo +0 -0
  298. trunk/assets/lang/landing-pages-my.mo +0 -0
  299. trunk/assets/lang/landing-pages-my_MM.mo +0 -0
  300. trunk/assets/lang/landing-pages-myv.mo +0 -0
  301. trunk/assets/lang/landing-pages-nah.mo +0 -0
  302. trunk/assets/lang/landing-pages-nan.mo +0 -0
  303. trunk/assets/lang/landing-pages-nap.mo +0 -0
  304. trunk/assets/lang/landing-pages-nb.mo +0 -0
  305. trunk/assets/lang/landing-pages-nb_NO.mo +0 -0
  306. trunk/assets/lang/landing-pages-ne.mo +0 -0
  307. trunk/assets/lang/landing-pages-ne_NP.mo +0 -0
  308. trunk/assets/lang/landing-pages-nia.mo +0 -0
  309. trunk/assets/lang/landing-pages-nl.mo +0 -0
  310. trunk/assets/lang/landing-pages-nl_BE.mo +0 -0
  311. trunk/assets/lang/landing-pages-nl_NL.mo +0 -0
  312. trunk/assets/lang/landing-pages-nn.mo +0 -0
  313. trunk/assets/lang/landing-pages-nn_NO.mo +0 -0
  314. trunk/assets/lang/landing-pages-no.mo +0 -0
  315. trunk/assets/lang/landing-pages-no_NO.mo +0 -0
  316. trunk/assets/lang/landing-pages-nqo.mo +0 -0
  317. trunk/assets/lang/landing-pages-nr.mo +0 -0
  318. trunk/assets/lang/landing-pages-nso.mo +0 -0
  319. trunk/assets/lang/landing-pages-nv.mo +0 -0
  320. trunk/assets/lang/landing-pages-ny.mo +0 -0
  321. trunk/assets/lang/landing-pages-oc.mo +0 -0
  322. trunk/assets/lang/landing-pages-om.mo +0 -0
  323. trunk/assets/lang/landing-pages-or.mo +0 -0
  324. trunk/assets/lang/landing-pages-or_IN.mo +0 -0
  325. trunk/assets/lang/landing-pages-os.mo +0 -0
  326. trunk/assets/lang/landing-pages-pa.mo +0 -0
  327. trunk/assets/lang/landing-pages-pa_IN.mo +0 -0
  328. trunk/assets/lang/landing-pages-pam.mo +0 -0
  329. trunk/assets/lang/landing-pages-pap.mo +0 -0
  330. trunk/assets/lang/landing-pages-pfl.mo +0 -0
  331. trunk/assets/lang/landing-pages-pl.mo +0 -0
  332. trunk/assets/lang/landing-pages-pl_PL.mo +0 -0
  333. trunk/assets/lang/landing-pages-pms.mo +0 -0
  334. trunk/assets/lang/landing-pages-ps.mo +0 -0
  335. trunk/assets/lang/landing-pages-pt.mo +0 -0
  336. trunk/assets/lang/landing-pages-pt_BR.mo +0 -0
  337. trunk/assets/lang/landing-pages-pt_PT.mo +0 -0
  338. trunk/assets/lang/landing-pages-rm.mo +0 -0
  339. trunk/assets/lang/landing-pages-ro.mo +0 -0
  340. trunk/assets/lang/landing-pages-ro_RO.mo +0 -0
  341. trunk/assets/lang/landing-pages-ru.mo +0 -0
  342. trunk/assets/lang/landing-pages-ru@petr1708.mo +0 -0
  343. trunk/assets/lang/landing-pages-ru_RU.mo +0 -0
  344. trunk/assets/lang/landing-pages-ru_ee.mo +0 -0
  345. trunk/assets/lang/landing-pages-ru_lt.mo +0 -0
  346. trunk/assets/lang/landing-pages-ru_lv.mo +0 -0
  347. trunk/assets/lang/landing-pages-sa.mo +0 -0
  348. trunk/assets/lang/landing-pages-sah.mo +0 -0
  349. trunk/assets/lang/landing-pages-sat.mo +0 -0
  350. trunk/assets/lang/landing-pages-sc.mo +0 -0
  351. trunk/assets/lang/landing-pages-scn.mo +0 -0
  352. trunk/assets/lang/landing-pages-sco.mo +0 -0
  353. trunk/assets/lang/landing-pages-sd.mo +0 -0
  354. trunk/assets/lang/landing-pages-se.mo +0 -0
  355. trunk/assets/lang/landing-pages-sg.mo +0 -0
  356. trunk/assets/lang/landing-pages-si.mo +0 -0
  357. trunk/assets/lang/landing-pages-si_LK.mo +0 -0
  358. trunk/assets/lang/landing-pages-sk.mo +0 -0
  359. trunk/assets/lang/landing-pages-sk_SK.mo +0 -0
  360. trunk/assets/lang/landing-pages-sl.mo +0 -0
  361. trunk/assets/lang/landing-pages-sl_SI.mo +0 -0
  362. trunk/assets/lang/landing-pages-sm.mo +0 -0
  363. trunk/assets/lang/landing-pages-sma.mo +0 -0
  364. trunk/assets/lang/landing-pages-sn.mo +0 -0
  365. trunk/assets/lang/landing-pages-so.mo +0 -0
  366. trunk/assets/lang/landing-pages-son.mo +0 -0
  367. trunk/assets/lang/landing-pages-sq.mo +0 -0
  368. trunk/assets/lang/landing-pages-sq_AL.mo +0 -0
  369. trunk/assets/lang/landing-pages-sr.mo +0 -0
  370. trunk/assets/lang/landing-pages-sr@Ijekavian.mo +0 -0
  371. trunk/assets/lang/landing-pages-sr@ijekavianlatin.mo +0 -0
  372. trunk/assets/lang/landing-pages-sr@latin.mo +0 -0
  373. trunk/assets/lang/landing-pages-sr_RS.mo +0 -0
  374. trunk/assets/lang/landing-pages-sr_RS@latin.mo +0 -0
  375. trunk/assets/lang/landing-pages-ss.mo +0 -0
  376. trunk/assets/lang/landing-pages-st.mo +0 -0
  377. trunk/assets/lang/landing-pages-st_ZA.mo +0 -0
  378. trunk/assets/lang/landing-pages-su.mo +0 -0
  379. trunk/assets/lang/landing-pages-sv.mo +0 -0
  380. trunk/assets/lang/landing-pages-sv_FI.mo +0 -0
  381. trunk/assets/lang/landing-pages-sv_SE.mo +0 -0
  382. trunk/assets/lang/landing-pages-sw.mo +0 -0
  383. trunk/assets/lang/landing-pages-sw_CD.mo +0 -0
  384. trunk/assets/lang/landing-pages-sw_KE.mo +0 -0
  385. trunk/assets/lang/landing-pages-szl.mo +0 -0
  386. trunk/assets/lang/landing-pages-ta.mo +0 -0
  387. trunk/assets/lang/landing-pages-ta_IN.mo +0 -0
  388. trunk/assets/lang/landing-pages-ta_LK.mo +0 -0
  389. trunk/assets/lang/landing-pages-te.mo +0 -0
  390. trunk/assets/lang/landing-pages-te_IN.mo +0 -0
  391. trunk/assets/lang/landing-pages-tet.mo +0 -0
  392. trunk/assets/lang/landing-pages-tg.mo +0 -0
  393. trunk/assets/lang/landing-pages-tg_TJ.mo +0 -0
  394. trunk/assets/lang/landing-pages-th.mo +0 -0
  395. trunk/assets/lang/landing-pages-th_TH.mo +0 -0
  396. trunk/assets/lang/landing-pages-ti.mo +0 -0
  397. trunk/assets/lang/landing-pages-tk.mo +0 -0
  398. trunk/assets/lang/landing-pages-tk_TM.mo +0 -0
  399. trunk/assets/lang/landing-pages-tl.mo +0 -0
  400. trunk/assets/lang/landing-pages-tl_PH.mo +0 -0
  401. trunk/assets/lang/landing-pages-tn.mo +0 -0
  402. trunk/assets/lang/landing-pages-to.mo +0 -0
  403. trunk/assets/lang/landing-pages-tr.mo +0 -0
  404. trunk/assets/lang/landing-pages-tr_TR.mo +0 -0
  405. trunk/assets/lang/landing-pages-ts.mo +0 -0
  406. trunk/assets/lang/landing-pages-tt.mo +0 -0
  407. trunk/assets/lang/landing-pages-tzl.mo +0 -0
  408. trunk/assets/lang/landing-pages-tzm.mo +0 -0
  409. trunk/assets/lang/landing-pages-udm.mo +0 -0
  410. trunk/assets/lang/landing-pages-ug.mo +0 -0
  411. trunk/assets/lang/landing-pages-ug@Arab.mo +0 -0
  412. trunk/assets/lang/landing-pages-ug@Cyrl.mo +0 -0
  413. trunk/assets/lang/landing-pages-ug@Latin.mo +0 -0
  414. trunk/assets/lang/landing-pages-uk.mo +0 -0
  415. trunk/assets/lang/landing-pages-uk_UA.mo +0 -0
  416. trunk/assets/lang/landing-pages-ur.mo +0 -0
  417. trunk/assets/lang/landing-pages-ur_PK.mo +0 -0
  418. trunk/assets/lang/landing-pages-uz.mo +0 -0
  419. trunk/assets/lang/landing-pages-uz@Arab.mo +0 -0
  420. trunk/assets/lang/landing-pages-uz@Cyrl.mo +0 -0
  421. trunk/assets/lang/landing-pages-uz@Latn.mo +0 -0
  422. trunk/assets/lang/landing-pages-uz_UZ.mo +0 -0
  423. trunk/assets/lang/landing-pages-ve.mo +0 -0
  424. trunk/assets/lang/landing-pages-vec.mo +0 -0
  425. trunk/assets/lang/landing-pages-vi.mo +0 -0
  426. trunk/assets/lang/landing-pages-vi_VN.mo +0 -0
  427. trunk/assets/lang/landing-pages-vls.mo +0 -0
  428. trunk/assets/lang/landing-pages-vmf.mo +0 -0
  429. trunk/assets/lang/landing-pages-wa.mo +0 -0
  430. trunk/assets/lang/landing-pages-war.mo +0 -0
  431. trunk/assets/lang/landing-pages-wo.mo +0 -0
  432. trunk/assets/lang/landing-pages-wo_SN.mo +0 -0
  433. trunk/assets/lang/landing-pages-wuu.mo +0 -0
  434. trunk/assets/lang/landing-pages-xh.mo +0 -0
  435. trunk/assets/lang/landing-pages-yi.mo +0 -0
  436. trunk/assets/lang/landing-pages-yo.mo +0 -0
  437. trunk/assets/lang/landing-pages-yue.mo +0 -0
  438. trunk/assets/lang/landing-pages-zh-Hans.mo +0 -0
  439. trunk/assets/lang/landing-pages-zh-Hant.mo +0 -0
  440. trunk/assets/lang/landing-pages-zh.mo +0 -0
  441. trunk/assets/lang/landing-pages-zh_CN.GB2312.mo +0 -0
  442. trunk/assets/lang/landing-pages-zh_CN.mo +0 -0
  443. trunk/assets/lang/landing-pages-zh_HK.mo +0 -0
  444. trunk/assets/lang/landing-pages-zh_TW.Big5.mo +0 -0
  445. trunk/assets/lang/landing-pages-zh_TW.mo +0 -0
  446. trunk/assets/lang/landing-pages-zu.mo +0 -0
  447. trunk/assets/lang/landing-pages-zu_ZA.mo +0 -0
  448. trunk/assets/libraries/class-tgm-plugin-activation.php +0 -3541
  449. trunk/assets/libraries/datetimepicker/MIT-LICENSE.txt +0 -19
  450. trunk/assets/libraries/datetimepicker/README.md +0 -28
  451. trunk/assets/libraries/datetimepicker/bower.json +0 -52
  452. trunk/assets/libraries/datetimepicker/datetimepicker.jquery.json +0 -47
  453. trunk/assets/libraries/datetimepicker/jquery.datetimepicker.css +0 -545
  454. trunk/assets/libraries/datetimepicker/jquery.datetimepicker.js +0 -2073
  455. trunk/assets/libraries/datetimepicker/package.json +0 -28
  456. trunk/assets/libraries/datetimepicker/picker_functions.js +0 -56
  457. trunk/assets/libraries/easyXDM.debug.js +0 -1
  458. trunk/assets/libraries/index.php +0 -2
  459. trunk/assets/libraries/jpicker/css/jPicker-1.1.6.css +0 -232
  460. trunk/assets/libraries/jpicker/css/jPicker-1.1.6.min.css +0 -1
  461. trunk/assets/libraries/jpicker/css/jPicker.css +0 -17
  462. trunk/assets/libraries/jpicker/images/AlphaBar.png +0 -0
  463. trunk/assets/libraries/jpicker/images/Bars.png +0 -0
  464. trunk/assets/libraries/jpicker/images/Maps.png +0 -0
  465. trunk/assets/libraries/jpicker/images/NoColor.png +0 -0
  466. trunk/assets/libraries/jpicker/images/bar-opacity.png +0 -0
  467. trunk/assets/libraries/jpicker/images/map-opacity.png +0 -0
  468. trunk/assets/libraries/jpicker/images/mappoint.gif +0 -0
  469. trunk/assets/libraries/jpicker/images/picker.gif +0 -0
  470. trunk/assets/libraries/jpicker/images/preview-opacity.png +0 -0
  471. trunk/assets/libraries/jpicker/images/rangearrows.gif +0 -0
  472. trunk/assets/libraries/jpicker/jpicker-1.1.6.min.js +0 -1
  473. trunk/assets/libraries/jquery.zoomer.js +0 -441
  474. trunk/assets/libraries/script.js +0 -36
  475. trunk/assets/libraries/shareme/index.php +0 -2
  476. trunk/assets/libraries/shareme/library.shareme.php +0 -1
  477. trunk/assets/libraries/shareme/sharrre/index.php +0 -2
  478. trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.js +0 -584
  479. trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.min.js +0 -1
  480. trunk/classes/class.acf-integration.php +0 -740
  481. trunk/classes/class.activation.php +0 -296
  482. trunk/classes/class.activation.upgrade-routines.php +0 -294
  483. trunk/classes/class.admin-menus.php +0 -56
  484. trunk/classes/class.admin-notices.php +0 -185
  485. trunk/classes/class.install.php +0 -129
  486. trunk/classes/class.landing-pages.php +0 -722
  487. trunk/classes/class.load-templates.php +0 -278
  488. trunk/classes/class.metaboxes.php +0 -1210
  489. trunk/classes/class.post-type.landing-page.php +0 -667
  490. trunk/classes/class.postmeta.php +0 -37
  491. trunk/classes/class.row-actions.php +0 -198
  492. trunk/classes/class.settings.php +0 -870
  493. trunk/classes/class.sidebars.php +0 -102
  494. trunk/classes/class.split-testing-stats.php +0 -217
  495. trunk/classes/class.store.php +0 -33
  496. trunk/classes/class.template-management.php +0 -379
classes/class.acf-integration.php CHANGED
@@ -233,6 +233,7 @@ class Landing_Pages_ACF {
233
 
234
 
235
  if ( isset( $variations[ $vid ][ 'acf' ] ) ) {
 
236
  $new_value = self::search_field_array( $variations[ $vid ][ 'acf' ] , $field );
237
 
238
  /* sometimes value is an array count when new_value believes it should be an array in this case get new count */
@@ -248,7 +249,6 @@ class Landing_Pages_ACF {
248
  /* acf lite isn't processing return values correctly - ignore repeater subfields */
249
  if ( !is_admin() && defined('ACF_FREE') ) {
250
  $value = self::acf_free_value_formatting( $value , $field );
251
-
252
  }
253
 
254
  if ( !is_admin() && is_string($value) && !defined('INBOUND_DEBUG_GF_AJAX') ) {
@@ -331,6 +331,7 @@ class Landing_Pages_ACF {
331
 
332
  $needle = $field['key'];
333
 
 
334
  foreach ($array as $key => $value ){
335
 
336
 
@@ -345,7 +346,7 @@ class Landing_Pages_ACF {
345
  /* Check if this array contains a repeater field layouts. If it does then return layouts, else this array is a non-repeater value set so return it */
346
  if ( $key === $needle ) {
347
 
348
- $repeater_array = self::get_repeater_layouts( $value );
349
  if ($repeater_array) {
350
  return $repeater_array;
351
  } else {
@@ -375,10 +376,23 @@ class Landing_Pages_ACF {
375
  *
376
  * @retuns ARRAY $fields this array will either be empty of contain repeater field layout definitions.
377
  */
378
- public static function get_repeater_layouts( $array ) {
379
-
380
  $fields = array();
381
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  foreach ($array as $key => $value) {
383
  if ( isset( $value['acf_fc_layout'] ) ) {
384
  $fields[] = $value['acf_fc_layout'];
233
 
234
 
235
  if ( isset( $variations[ $vid ][ 'acf' ] ) ) {
236
+
237
  $new_value = self::search_field_array( $variations[ $vid ][ 'acf' ] , $field );
238
 
239
  /* sometimes value is an array count when new_value believes it should be an array in this case get new count */
249
  /* acf lite isn't processing return values correctly - ignore repeater subfields */
250
  if ( !is_admin() && defined('ACF_FREE') ) {
251
  $value = self::acf_free_value_formatting( $value , $field );
 
252
  }
253
 
254
  if ( !is_admin() && is_string($value) && !defined('INBOUND_DEBUG_GF_AJAX') ) {
331
 
332
  $needle = $field['key'];
333
 
334
+
335
  foreach ($array as $key => $value ){
336
 
337
 
346
  /* Check if this array contains a repeater field layouts. If it does then return layouts, else this array is a non-repeater value set so return it */
347
  if ( $key === $needle ) {
348
 
349
+ $repeater_array = self::get_repeater_layouts( $value , $field );
350
  if ($repeater_array) {
351
  return $repeater_array;
352
  } else {
376
  *
377
  * @retuns ARRAY $fields this array will either be empty of contain repeater field layout definitions.
378
  */
379
+ public static function get_repeater_layouts( $array , $field ) {
 
380
  $fields = array();
381
 
382
+ if ($field['type'] == 'flexible_content') {
383
+ foreach($array as $key=>$value) {
384
+ if (is_array($value)) {
385
+ $fields[] = $value;
386
+ }
387
+ }
388
+
389
+ $fields = ($fields) ? $fields : $array;
390
+
391
+ return $fields;
392
+ }
393
+
394
+
395
+
396
  foreach ($array as $key => $value) {
397
  if ( isset( $value['acf_fc_layout'] ) ) {
398
  $fields[] = $value['acf_fc_layout'];
classes/class.post-type.landing-page.php CHANGED
@@ -517,7 +517,7 @@ class Landing_Pages_Post_Type {
517
  /**
518
  * Convert the category id to the taxonomy id during a query
519
  */
520
- public static function sort_by_category_prepare_query() {
521
  global $pagenow;
522
  $qv = &$query->query_vars;
523
  if ($pagenow == 'edit.php' && isset($qv['landing_page_category']) && is_numeric($qv['landing_page_category'])) {
@@ -530,6 +530,11 @@ class Landing_Pages_Post_Type {
530
  * Add styling handlers to custom post states
531
  */
532
  public static function filter_custom_post_states($post_states) {
 
 
 
 
 
533
  foreach ($post_states as &$state) {
534
  $state = '<span class="' . strtolower($state) . ' states">' . str_replace(' ', '-', $state) . '</span>';
535
  }
517
  /**
518
  * Convert the category id to the taxonomy id during a query
519
  */
520
+ public static function sort_by_category_prepare_query( $query ) {
521
  global $pagenow;
522
  $qv = &$query->query_vars;
523
  if ($pagenow == 'edit.php' && isset($qv['landing_page_category']) && is_numeric($qv['landing_page_category'])) {
530
  * Add styling handlers to custom post states
531
  */
532
  public static function filter_custom_post_states($post_states) {
533
+
534
+ if (!$post_states) {
535
+ return array();
536
+ }
537
+
538
  foreach ($post_states as &$state) {
539
  $state = '<span class="' . strtolower($state) . ' states">' . str_replace(' ', '-', $state) . '</span>';
540
  }
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.7.6
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.7.6' );
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' );
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.7.7
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.7.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' );
readme.txt CHANGED
@@ -6,8 +6,8 @@ License: GPLv2 or later
6
  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: 5.0.3
10
- Stable Tag: 2.7.6
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,10 @@ We also offer a guide for using <a href="https://github.com/inboundnow/inbound-p
85
 
86
  == Changelog ==
87
 
 
 
 
 
88
  = 2.7.6 =
89
  * Updating Inbound PRO upgrade links, removing a few CTAs for a cleaner design.
90
 
@@ -336,7 +340,7 @@ We also offer a guide for using <a href="https://github.com/inboundnow/inbound-p
336
  = 1.7.0 =
337
  * Removed anonymous PHP functions for PHP 5.2 support
338
  * Updated template creation standards
339
- * Converted varition modules to CLASS based system & documented
340
  * Move /lang/ file outside of shared
341
 
342
  = 1.6.2 =
6
  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: 5.2.1
10
+ Stable Tag: 2.7.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
 
86
  == Changelog ==
87
 
88
+
89
+ = 2.7.7 =
90
+ * Fixing issue with category filter on landing pages CPT listing page
91
+
92
  = 2.7.6 =
93
  * Updating Inbound PRO upgrade links, removing a few CTAs for a cleaner design.
94
 
340
  = 1.7.0 =
341
  * Removed anonymous PHP functions for PHP 5.2 support
342
  * Updated template creation standards
343
+ * Converted variation modules to CLASS based system & documented
344
  * Move /lang/ file outside of shared
345
 
346
  = 1.6.2 =
shared/classes/class.acf-bootstrap.php CHANGED
@@ -58,9 +58,9 @@ class Inbound_Shared_ACF_BootStrap {
58
  * If ACF Pro is active then register a global for active fields - this provides legacy support to Landing Pages
59
  */
60
  public static function acf_register_global( $field_group ) {
61
- $GLOBALS['acf_register_field_group'][] = array(
62
- 'fields' => acf_local()->fields
63
- );
64
  }
65
  /**
66
  * define custom ACF path
58
  * If ACF Pro is active then register a global for active fields - this provides legacy support to Landing Pages
59
  */
60
  public static function acf_register_global( $field_group ) {
61
+ //$GLOBALS['acf_register_field_group'][] = array(
62
+ // 'fields' => acf_local()->fields
63
+ // );
64
  }
65
  /**
66
  * define custom ACF path
shared/classes/class.events.php CHANGED
@@ -836,6 +836,10 @@ class Inbound_Events {
836
  break;
837
  }
838
 
 
 
 
 
839
 
840
  $query .=' AND `page_id` != "0" ';
841
 
@@ -1160,7 +1164,7 @@ class Inbound_Events {
1160
  $query .= ' AND list_id = "'.$params['list_id'].'" ';
1161
  }
1162
 
1163
- if (isset($params['variation_id']) && $params['variation_id'] ) {
1164
  $query .= ' AND variation_id = "'.$params['variation_id'].'" ';
1165
  }
1166
 
836
  break;
837
  }
838
 
839
+ if (isset($params['variation_id']) ) {
840
+ $query .= ' AND variation_id = "'.$params['variation_id'].'" ';
841
+ }
842
+
843
 
844
  $query .=' AND `page_id` != "0" ';
845
 
1164
  $query .= ' AND list_id = "'.$params['list_id'].'" ';
1165
  }
1166
 
1167
+ if (isset($params['variation_id']) ) {
1168
  $query .= ' AND variation_id = "'.$params['variation_id'].'" ';
1169
  }
1170
 
shared/classes/class.lead-storage.php CHANGED
@@ -120,17 +120,19 @@ if (!class_exists('LeadStorage')) {
120
  if ($leadExists) {
121
  $lead['id'] = $leadExists;
122
  do_action('wpleads_existing_lead_update', $lead);
 
 
 
 
 
 
123
  }
124
  /* else create new lead */
125
  else {
126
- $lead['id'] = self::store_new_lead($lead);
127
  }
128
 
129
 
130
- /* Store Mapped Form Data */
131
- if(!empty($mappedData)){
132
- self::store_mapped_data($lead, $mappedData);
133
- }
134
 
135
  /* if status is included in lead array then set status */
136
  if (isset($lead['wp_lead_status']) && !empty($lead['wp_lead_status'])) {
@@ -303,7 +305,7 @@ if (!class_exists('LeadStorage')) {
303
  /**
304
  * Creates new lead in wp-lead post type
305
  */
306
- static function store_new_lead($lead){
307
  /* Create New Lead */
308
  $post = array(
309
  'post_title' => $lead['email'],
@@ -322,6 +324,14 @@ if (!class_exists('LeadStorage')) {
322
  /* set lead save count */
323
  update_post_meta( $id , 'inbound_update_count' , 1 );
324
 
 
 
 
 
 
 
 
 
325
  do_action('wpleads_new_lead_insert', $lead ); /* action hook on new leads only */
326
  return $id;
327
  }
120
  if ($leadExists) {
121
  $lead['id'] = $leadExists;
122
  do_action('wpleads_existing_lead_update', $lead);
123
+
124
+ /* Update mapped data */
125
+ if(!empty($mappedData)){
126
+ self::store_mapped_data($lead, $mappedData);
127
+ }
128
+
129
  }
130
  /* else create new lead */
131
  else {
132
+ $lead['id'] = self::store_new_lead($lead , $mappedData);
133
  }
134
 
135
 
 
 
 
 
136
 
137
  /* if status is included in lead array then set status */
138
  if (isset($lead['wp_lead_status']) && !empty($lead['wp_lead_status'])) {
305
  /**
306
  * Creates new lead in wp-lead post type
307
  */
308
+ static function store_new_lead($lead , $mappedData){
309
  /* Create New Lead */
310
  $post = array(
311
  'post_title' => $lead['email'],
324
  /* set lead save count */
325
  update_post_meta( $id , 'inbound_update_count' , 1 );
326
 
327
+ $lead['lead_id'] = $id;
328
+ $lead['id'] = $id;
329
+
330
+ /* Store Mapped Form Data */
331
+ if(!empty($mappedData)){
332
+ self::store_mapped_data($lead, $mappedData);
333
+ }
334
+
335
  do_action('wpleads_new_lead_insert', $lead ); /* action hook on new leads only */
336
  return $id;
337
  }
trunk/README.md DELETED
@@ -1,53 +0,0 @@
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 DELETED
@@ -1,311 +0,0 @@
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 DELETED
@@ -1,212 +0,0 @@
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 DELETED
@@ -1,110 +0,0 @@
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 DELETED
@@ -1,48 +0,0 @@
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 DELETED
@@ -1,216 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
1
- #postdivrich, #lp_2_form_content, #main-title-area {display:none !important;}
 
trunk/assets/css/admin/content-stats.css DELETED
@@ -1,87 +0,0 @@
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 DELETED
@@ -1,247 +0,0 @@
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 DELETED
@@ -1,167 +0,0 @@
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 DELETED
@@ -1,231 +0,0 @@
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 DELETED
@@ -1,13 +0,0 @@
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 DELETED
@@ -1,542 +0,0 @@
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 DELETED
@@ -1,492 +0,0 @@
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 DELETED
@@ -1,76 +0,0 @@
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 DELETED
@@ -1,157 +0,0 @@
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 DELETED
@@ -1,34 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
1
- #variation-list {
 
trunk/assets/css/frontend/global-landing-page-style.css DELETED
@@ -1,43 +0,0 @@
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 DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/css/iframe-preview.css DELETED
@@ -1,3 +0,0 @@
1
- :root:root:root {
2
- margin-top: 0px !important;
3
- };
 
 
 
trunk/assets/css/images/dropdownback.png DELETED
Binary file
trunk/assets/css/images/headerback.png DELETED
Binary file
trunk/assets/css/images/hover.png DELETED
Binary file
trunk/assets/css/images/index.php DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/css/images/linkback.png DELETED
Binary file
trunk/assets/css/images/question-light.png DELETED
Binary file
trunk/assets/css/images/tooltip.png DELETED
Binary file
trunk/assets/css/index.php DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/images/ab-retina-icons.png DELETED
Binary file
trunk/assets/images/add-on-image.png DELETED
Binary file
trunk/assets/images/cta-install.png DELETED
Binary file
trunk/assets/images/custom-setup-image.png DELETED
Binary file
trunk/assets/images/get-custom-setup.png DELETED
Binary file
trunk/assets/images/get-wordpress-templates.png DELETED
Binary file
trunk/assets/images/github-help.jpg DELETED
Binary file
trunk/assets/images/image.php DELETED
@@ -1,76 +0,0 @@
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 DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/images/leads-install.png DELETED
Binary file
trunk/assets/images/localhost.png DELETED
Binary file
trunk/assets/images/templates-image.png DELETED
Binary file
trunk/assets/images/variation-normal.png DELETED
Binary file
trunk/assets/images/variation-up.png DELETED
Binary file
trunk/assets/js/admin/admin.global-settings.js DELETED
@@ -1,73 +0,0 @@
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 DELETED
@@ -1,30 +0,0 @@
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 DELETED
@@ -1,117 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
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
  });
 
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
  });
trunk/assets/js/admin/admin.post-edit-ab-testing.js DELETED
@@ -1,64 +0,0 @@
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 DELETED
@@ -1,308 +0,0 @@
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 DELETED
@@ -1,144 +0,0 @@
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 Inbound PRO and join Inbound Now's membership plan for access to premium 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 DELETED
@@ -1,35 +0,0 @@
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 DELETED
@@ -1,25 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
1
-
2
 
 
0
 
trunk/assets/js/admin/index.php DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/js/admin/intro.js DELETED
@@ -1,758 +0,0 @@
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 DELETED
@@ -1,9 +0,0 @@
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 DELETED
@@ -1,8 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
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
  });
 
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
  });
trunk/assets/js/index.php DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/js/jquery.bindfirst.js DELETED
@@ -1,15 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
1
- /*!
 
trunk/assets/js/jquery.easing.min.js DELETED
@@ -1,44 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
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 : '';
 
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 : '';
trunk/assets/js/jquery.lp.cookie.js DELETED
@@ -1 +0,0 @@
1
- /*!
 
trunk/assets/js/jquery.tablesorter.js DELETED
@@ -1,1031 +0,0 @@
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 DELETED
@@ -1,22 +0,0 @@
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 DELETED
@@ -1,7 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
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 DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/lang/landing-pages-ach.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ady.mo DELETED
Binary file
trunk/assets/lang/landing-pages-af.mo DELETED
Binary file
trunk/assets/lang/landing-pages-af_ZA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ak.mo DELETED
Binary file
trunk/assets/lang/landing-pages-aln.mo DELETED
Binary file
trunk/assets/lang/landing-pages-am.mo DELETED
Binary file
trunk/assets/lang/landing-pages-am_ET.mo DELETED
Binary file
trunk/assets/lang/landing-pages-an.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ar.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ar_AA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ar_EG.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ar_SA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ar_SD.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ar_SY.mo DELETED
Binary file
trunk/assets/lang/landing-pages-arn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-as.mo DELETED
Binary file
trunk/assets/lang/landing-pages-as_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ast.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ast_ES.mo DELETED
Binary file
trunk/assets/lang/landing-pages-az.mo DELETED
Binary file
trunk/assets/lang/landing-pages-az@Arab.mo DELETED
Binary file
trunk/assets/lang/landing-pages-az@latin.mo DELETED
Binary file
trunk/assets/lang/landing-pages-az_AZ.mo DELETED
Binary file
trunk/assets/lang/landing-pages-az_IR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ba.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bal.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bar.mo DELETED
Binary file
trunk/assets/lang/landing-pages-be.mo DELETED
Binary file
trunk/assets/lang/landing-pages-be@tarask.mo DELETED
Binary file
trunk/assets/lang/landing-pages-be_BY.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bg.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bg_BG.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bn_BD.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bn_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bo_CN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-br.mo DELETED
Binary file
trunk/assets/lang/landing-pages-brx.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bs.mo DELETED
Binary file
trunk/assets/lang/landing-pages-bs_BA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ca.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ca@valencia.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ca_ES.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cdo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ceb.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cgg.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cjy.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cmn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-co.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cpx.mo DELETED
Binary file
trunk/assets/lang/landing-pages-crh.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cs.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cs_CZ.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cy.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cy_GB.mo DELETED
Binary file
trunk/assets/lang/landing-pages-czh.mo DELETED
Binary file
trunk/assets/lang/landing-pages-czo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-da.mo DELETED
Binary file
trunk/assets/lang/landing-pages-da_DK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-de.mo DELETED
Binary file
trunk/assets/lang/landing-pages-de_AT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-de_CH.mo DELETED
Binary file
trunk/assets/lang/landing-pages-de_DE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-doi.mo DELETED
Binary file
trunk/assets/lang/landing-pages-dv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-dz.mo DELETED
Binary file
trunk/assets/lang/landing-pages-dz_BT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-el.mo DELETED
Binary file
trunk/assets/lang/landing-pages-el_GR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en@pirate.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_AT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_AU.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_BD.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_BE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_CA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_CH.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_CL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_CZ.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_DE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_EG.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_ES.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_FI.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_GB.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_GH.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_GR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_HK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_HR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_HU.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_IE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_IT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_LK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_NG.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_NL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_NO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_NZ.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_PK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_PL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_PT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_RO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_SE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_SK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_ZA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_ee.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_lt.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_lv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-eo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_419.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_AR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_BO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_CL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_CO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_CR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_DO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_EC.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_ES.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_GT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_HN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_MX.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_NI.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_PA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_PE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_PR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_PY.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_SV.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_US.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_UY.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_VE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-et.mo DELETED
Binary file
trunk/assets/lang/landing-pages-et_EE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-eu.mo DELETED
Binary file
trunk/assets/lang/landing-pages-eu_ES.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fa.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fa_AF.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fa_IR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ff.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ff_SN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fi.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fi_FI.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fil.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fo_FO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fr.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fr_BE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fr_CA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fr_CH.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fr_FR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-frp.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fur.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fy.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fy_NL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ga.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ga_IE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gan.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gd.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gl_ES.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gu.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gu_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gun.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ha.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hak.mo DELETED
Binary file
trunk/assets/lang/landing-pages-haw.mo DELETED
Binary file
trunk/assets/lang/landing-pages-he.mo DELETED
Binary file
trunk/assets/lang/landing-pages-he_IL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hi.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hi_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hne.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hr.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hr_HR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hsb.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hsn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ht.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ht_HT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hu.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hu_HU.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hu_RO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hy.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hy_AM.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ia.mo DELETED
Binary file
trunk/assets/lang/landing-pages-id.mo DELETED
Binary file
trunk/assets/lang/landing-pages-id_ID.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ig.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ilo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-io.mo DELETED
Binary file
trunk/assets/lang/landing-pages-is.mo DELETED
Binary file
trunk/assets/lang/landing-pages-is_IS.mo DELETED
Binary file
trunk/assets/lang/landing-pages-it.mo DELETED
Binary file
trunk/assets/lang/landing-pages-it_CH.mo DELETED
Binary file
trunk/assets/lang/landing-pages-it_IT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-iu.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ja.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ja_JP.mo DELETED
Binary file
trunk/assets/lang/landing-pages-jv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ka.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ka_GE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-kab.mo DELETED
Binary file
trunk/assets/lang/landing-pages-kl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-kn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-kn_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ksh.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ku.mo DELETED
Binary file
trunk/assets/lang/landing-pages-kw.mo DELETED
Binary file
trunk/assets/lang/landing-pages-la.mo DELETED
Binary file
trunk/assets/lang/landing-pages-lg.mo DELETED
Binary file
trunk/assets/lang/landing-pages-lzh.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mh.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mi.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mn_MN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mni.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mnp.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mr.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mr_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ms.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mw1.mo DELETED
Binary file
trunk/assets/lang/landing-pages-my.mo DELETED
Binary file
trunk/assets/lang/landing-pages-my_MM.mo DELETED
Binary file
trunk/assets/lang/landing-pages-myv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nah.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nan.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nap.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nb.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nb_NO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ne.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ne_NP.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nia.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nl_BE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nl_NL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nn_NO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-no.mo DELETED
Binary file
trunk/assets/lang/landing-pages-no_NO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nqo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nr.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nso.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ny.mo DELETED
Binary file
trunk/assets/lang/landing-pages-oc.mo DELETED
Binary file
trunk/assets/lang/landing-pages-om.mo DELETED
Binary file
trunk/assets/lang/landing-pages-or.mo DELETED
Binary file
trunk/assets/lang/landing-pages-or_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-os.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pa.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pa_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pam.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pap.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pfl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pl_PL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pms.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ps.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pt.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pt_BR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pt_PT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-rm.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ro.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ro_RO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ru.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ru@petr1708.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ru_RU.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ru_ee.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ru_lt.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ru_lv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sa.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sah.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sat.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sc.mo DELETED
Binary file
trunk/assets/lang/landing-pages-scn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sco.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sd.mo DELETED
Binary file
trunk/assets/lang/landing-pages-se.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sg.mo DELETED
Binary file
trunk/assets/lang/landing-pages-si.mo DELETED
Binary file
trunk/assets/lang/landing-pages-si_LK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sk.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sk_SK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sl_SI.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sm.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sma.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-so.mo DELETED
Binary file
trunk/assets/lang/landing-pages-son.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sq.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sq_AL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sr.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sr@Ijekavian.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sr@ijekavianlatin.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sr@latin.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sr_RS.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sr_RS@latin.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ss.mo DELETED
Binary file
trunk/assets/lang/landing-pages-st.mo DELETED
Binary file
trunk/assets/lang/landing-pages-st_ZA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-su.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sv_FI.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sv_SE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sw.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sw_CD.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sw_KE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-szl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ta.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ta_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ta_LK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-te.mo DELETED
Binary file
trunk/assets/lang/landing-pages-te_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tet.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tg.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tg_TJ.mo DELETED
Binary file
trunk/assets/lang/landing-pages-th.mo DELETED
Binary file
trunk/assets/lang/landing-pages-th_TH.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ti.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tk.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tk_TM.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tl_PH.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-to.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tr.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tr_TR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ts.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tt.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tzl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tzm.mo DELETED
Binary file
trunk/assets/lang/landing-pages-udm.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ug.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ug@Arab.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ug@Cyrl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ug@Latin.mo DELETED
Binary file
trunk/assets/lang/landing-pages-uk.mo DELETED
Binary file
trunk/assets/lang/landing-pages-uk_UA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ur.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ur_PK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-uz.mo DELETED
Binary file
trunk/assets/lang/landing-pages-uz@Arab.mo DELETED
Binary file
trunk/assets/lang/landing-pages-uz@Cyrl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-uz@Latn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-uz_UZ.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ve.mo DELETED
Binary file
trunk/assets/lang/landing-pages-vec.mo DELETED
Binary file
trunk/assets/lang/landing-pages-vi.mo DELETED
Binary file
trunk/assets/lang/landing-pages-vi_VN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-vls.mo DELETED
Binary file
trunk/assets/lang/landing-pages-vmf.mo DELETED
Binary file
trunk/assets/lang/landing-pages-wa.mo DELETED
Binary file
trunk/assets/lang/landing-pages-war.mo DELETED
Binary file
trunk/assets/lang/landing-pages-wo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-wo_SN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-wuu.mo DELETED
Binary file
trunk/assets/lang/landing-pages-xh.mo DELETED
Binary file
trunk/assets/lang/landing-pages-yi.mo DELETED
Binary file
trunk/assets/lang/landing-pages-yo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-yue.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zh-Hans.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zh-Hant.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zh.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zh_CN.GB2312.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zh_CN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zh_HK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zh_TW.Big5.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zh_TW.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zu.mo DELETED
Binary file
trunk/assets/lang/landing-pages-zu_ZA.mo DELETED
Binary file
trunk/assets/libraries/class-tgm-plugin-activation.php DELETED
@@ -1,3541 +0,0 @@
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 DELETED
@@ -1,19 +0,0 @@
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 DELETED
@@ -1,28 +0,0 @@
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 DELETED
@@ -1,52 +0,0 @@
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 DELETED
@@ -1,47 +0,0 @@
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 DELETED
@@ -1,545 +0,0 @@
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 DELETED
@@ -1,2073 +0,0 @@
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 DELETED
@@ -1,28 +0,0 @@
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 DELETED
@@ -1,56 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
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
  });
 
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
  });
trunk/assets/libraries/index.php DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/libraries/jpicker/css/jPicker-1.1.6.css DELETED
@@ -1,232 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
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 DELETED
@@ -1,17 +0,0 @@
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 DELETED
Binary file
trunk/assets/libraries/jpicker/images/Bars.png DELETED
Binary file
trunk/assets/libraries/jpicker/images/Maps.png DELETED
Binary file
trunk/assets/libraries/jpicker/images/NoColor.png DELETED
Binary file
trunk/assets/libraries/jpicker/images/bar-opacity.png DELETED
Binary file
trunk/assets/libraries/jpicker/images/map-opacity.png DELETED
Binary file
trunk/assets/libraries/jpicker/images/mappoint.gif DELETED
Binary file
trunk/assets/libraries/jpicker/images/picker.gif DELETED
Binary file
trunk/assets/libraries/jpicker/images/preview-opacity.png DELETED
Binary file
trunk/assets/libraries/jpicker/images/rangearrows.gif DELETED
Binary file
trunk/assets/libraries/jpicker/jpicker-1.1.6.min.js DELETED
@@ -1 +0,0 @@
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 DELETED
@@ -1,441 +0,0 @@
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 DELETED
@@ -1,36 +0,0 @@
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 DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/libraries/shareme/library.shareme.php DELETED
@@ -1 +0,0 @@
1
- <?php
 
trunk/assets/libraries/shareme/sharrre/index.php DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- # Silence is golden.
 
 
trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.js DELETED
@@ -1,584 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
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 DELETED
@@ -1,740 +0,0 @@
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( $post->ID );
223
-
224
- $settings = Landing_Pages_Meta::get_settings( $post->ID );
225
-
226
- $variations = ( isset($settings['variations']) ) ? $settings['variations'] : null;
227
-
228
- /* If there is no ACF data for this template attempt to pull values from the legacy postmeta values */
229
-
230
- if ( !isset( $variations[ $vid ][ 'acf' ] ) || !$variations[ $vid ][ 'acf' ]) {
231
- return self::load_legacy_value( $value, $post_id, $field );
232
- }
233
-
234
-
235
- if ( isset( $variations[ $vid ][ 'acf' ] ) ) {
236
- $new_value = self::search_field_array( $variations[ $vid ][ 'acf' ] , $field );
237
-
238
- /* sometimes value is an array count when new_value believes it should be an array in this case get new count */
239
- if (!is_array($value) && is_array($new_value)) {
240
- $value = count($new_value);
241
- } else if($new_value) {
242
- if ($new_value =='_empty') {
243
- $new_value = '';
244
- }
245
- $value = $new_value;
246
- }
247
-
248
- /* acf lite isn't processing return values correctly - ignore repeater subfields */
249
- if ( !is_admin() && defined('ACF_FREE') ) {
250
- $value = self::acf_free_value_formatting( $value , $field );
251
-
252
- }
253
-
254
- if ( !is_admin() && is_string($value) && !defined('INBOUND_DEBUG_GF_AJAX') ) {
255
- $value = do_shortcode($value);
256
- }
257
-
258
- /* handle non acf5 template return formatting */
259
- if (defined('ACF_PRO')) {
260
- $value = self::acf_check_if_acf4( $value , $field );
261
- }
262
-
263
- }
264
-
265
- return $value;
266
-
267
- }
268
- /**
269
- * Finds the correct value given the variation - uses legacy meta system
270
- *
271
- * @param MIXED $value contains the non-variation value
272
- * @param INT $post_id ID of landing page being loaded
273
- * @param ARRAY $field wide array of data belonging to custom field (not leveraged in this method)
274
- *
275
- * @returns MIXED $new_value value mapped to variation.
276
- */
277
- public static function load_legacy_value( $value, $post_id, $field ) {
278
- global $post;
279
-
280
- /* get registered field object data */
281
- $field = self::acf_get_registered_field( $field );
282
-
283
- /* if a brand new post ignore return default value */
284
- if ( $post->post_status != 'publish' ) {
285
- return ( isset($field['default_value']) ) ? do_shortcode($field['default_value']) : '' ;
286
- }
287
-
288
- $vid = Landing_Pages_Variations::get_new_variation_reference_id( $post->ID );
289
-
290
- if ( $vid ) {
291
- $value = get_post_meta( $post_id , $field['name'] . '-' . $vid , true );
292
- } else {
293
- $value = get_post_meta( $post_id , $field['name'] , true );
294
- }
295
-
296
-
297
- if ($field['type']=='image' && is_admin() ) {
298
- $value = self::get_image_id_from_url( $value );
299
- }
300
-
301
- if ($field['type']=='date_picker') {
302
- $value = str_replace('-' , '', $value);
303
- $value = explode(' ' , $value);
304
- $value = $value[0];
305
- }
306
-
307
- if ($field['type']=='color_picker') {
308
- if (!strstr( $value , '#' ) && $value ) {
309
- $value = '#'.$value;
310
- }
311
- }
312
-
313
- if (!is_array($value) && !is_admin() ) {
314
- $value = do_shortcode($value);
315
- }
316
-
317
- return $value;
318
-
319
- }
320
-
321
-
322
- /**
323
- * Searches ACF variation array and returns the correct field value given the field key
324
- *
325
- * @param ARRAY $array of custom field keys and values stored for variation
326
- * @param STRING $needle acf form field key
327
- *
328
- * @return $feild value
329
- */
330
- public static function search_field_array( $array , $field ) {
331
-
332
- $needle = $field['key'];
333
-
334
- foreach ($array as $key => $value ){
335
-
336
-
337
- if ($key === $needle && !is_array($value) ) {
338
- $value = ($value) ? $value : '_empty' ;
339
- return $value;
340
- }
341
-
342
- /* Arrays could be repeaters or any custom field with sets of multiple values */
343
- if ( is_array($value) ) {
344
-
345
- /* Check if this array contains a repeater field layouts. If it does then return layouts, else this array is a non-repeater value set so return it */
346
- if ( $key === $needle ) {
347
-
348
- $repeater_array = self::get_repeater_layouts( $value );
349
- if ($repeater_array) {
350
- return $repeater_array;
351
- } else {
352
- return $value;
353
- }
354
-
355
- }
356
-
357
- /* Check if array is repeater fields and determine correct value given a parsed field name with field key */
358
- $repeater_value = self::get_repeater_values( $value , $field , $needle );
359
-
360
- /* If target key is not in these repeater fields, or this array is not determined to be a repeater field then move on. */
361
- if ($repeater_value) {
362
- return $repeater_value;
363
- }
364
-
365
-
366
- }
367
-
368
- }
369
-
370
- return false;
371
- }
372
-
373
- /**
374
- * Searches an array assumed to be a repeater field dataset and returns an array of repeater field layout definitions
375
- *
376
- * @retuns ARRAY $fields this array will either be empty of contain repeater field layout definitions.
377
- */
378
- public static function get_repeater_layouts( $array ) {
379
-
380
- $fields = array();
381
-
382
- foreach ($array as $key => $value) {
383
- if ( isset( $value['acf_fc_layout'] ) ) {
384
- $fields[] = $value['acf_fc_layout'];
385
- }
386
- }
387
-
388
- return $fields;
389
- }
390
-
391
-
392
- /**
393
- * Searches an array assumed to be a repeater field dataset and returns an array of repeater field layout definitions
394
- *
395
- * @retuns ARRAY $fields this array will either be empty of contain repeater field layout definitions.
396
- */
397
- public static function get_repeater_values( $array , $field , $needle ) {
398
-
399
- /* Discover correct repeater pointer by parsing field name */
400
- preg_match_all('/(_\d_)/', $field['name'], $matches, PREG_PATTERN_ORDER, 0);
401
-
402
- /* if not a repeater subfield then bail */
403
- if (!$matches || !$matches[0]) {
404
- return false;
405
- }
406
-
407
- $pointer = str_replace('_' , '' , $matches[0][0]);
408
- $repeater_key = self::key_search($array, $field , true ); /* returns parent flexible content field key using sub field key */
409
-
410
-
411
- /* */
412
- if ( $repeater_key && $repeater_key !== '0' && isset($array[$repeater_key][$pointer][$field['key']])){
413
- /* if the value is empty, mark as empty */
414
- if($array[$repeater_key][$pointer][$field['key']] === ''){$array[$repeater_key][$pointer][$field['key']] = '_empty';}
415
-
416
- return $array[$repeater_key][$pointer][$field['key']];
417
- }
418
-
419
- /* repeater field comes after the pointer???? */
420
- if (isset($array[$pointer][$needle])){
421
- if($array[$pointer][$needle] === ''){$array[$pointer][$needle] = '_empty';}
422
-
423
- return $array[$pointer][$needle];
424
- }
425
-
426
-
427
-
428
- /* if the repeater is nested in a flexible content field */
429
- if(isset($matches[0][1])){
430
- $nested_value = null;
431
- $parent_field = $field['parent'];
432
- $sub_pointer = str_replace('_' , '' , $matches[0][1]);
433
-
434
- if(isset($array[$pointer][$parent_field][$sub_pointer][$field['key']])){
435
- $nested_value = $array[$pointer][$parent_field][$sub_pointer][$field['key']];
436
- }
437
-
438
- /* if the nested repeater's indexes are field keys instead of numbers */
439
- if( isset($array[$repeater_key][$parent_field]) &&
440
- is_array($array[$repeater_key][$parent_field]) &&
441
- !isset($array[$repeater_key][$parent_field][0]))
442
- {
443
- /* get the numerical indexes of the keys */
444
- $keys = array_keys($array[$repeater_key][$parent_field]);
445
-
446
- $nested_value = $array[$repeater_key][$parent_field][$keys[$sub_pointer]][$field['key']];
447
-
448
- }
449
-
450
- /* if the value is empty, mark it as empty */
451
- if($nested_value === ''){$nested_value = '_empty';}
452
-
453
- if(isset($nested_value)){
454
- return $nested_value;
455
- }
456
- }
457
-
458
- return '';
459
-
460
- }
461
-
462
- /**
463
- * Check if current post is a landing page using an ACF powered template
464
- *
465
- * @filter acf/location/rule_match/template_id
466
- *
467
- * @returns BOOL declaring if current page is a landing page with an ACF template loaded or not
468
- */
469
- public static function load_acf_on_template( $allow , $rule, $args ) {
470
- global $post;
471
-
472
- if ( !isset($post) || $post->post_type != 'landing-page' ) {
473
- return $allow;
474
- }
475
-
476
- $template = Landing_Pages_Variations::get_current_template( $args['post_id'] );
477
-
478
- if ($template == $rule['value']) {
479
- return true;
480
- } else {
481
- return false;
482
- }
483
- }
484
-
485
- /**
486
- *
487
- * @param $image_url
488
- * @return mixed
489
- */
490
- public static function get_image_id_from_url($url) {
491
- $dir = wp_upload_dir();
492
-
493
- // baseurl never has a trailing slash
494
- if ( false === strpos( $url, $dir['baseurl'] . '/' ) ) {
495
- // URL points to a place outside of upload directory
496
- return false;
497
- }
498
-
499
- $file = basename( $url );
500
- $query = array(
501
- 'post_type' => 'attachment',
502
- 'fields' => 'ids',
503
- 'meta_query' => array(
504
- array(
505
- 'value' => $file,
506
- 'compare' => 'LIKE',
507
- ),
508
- )
509
- );
510
-
511
- $query['meta_query'][0]['key'] = '_wp_attached_file';
512
-
513
- // query attachments
514
- $ids = get_posts( $query );
515
-
516
- if ( ! empty( $ids ) ) {
517
-
518
- foreach ( $ids as $id ) {
519
-
520
- // first entry of returned array is the URL
521
- if ( $url === array_shift( wp_get_attachment_image_src( $id, 'full' ) ) )
522
- return $id;
523
- }
524
- }
525
-
526
- $query['meta_query'][0]['key'] = '_wp_attachment_metadata';
527
-
528
- // query attachments again
529
- $ids = get_posts( $query );
530
-
531
- if ( empty( $ids) )
532
- return false;
533
-
534
- foreach ( $ids as $id ) {
535
-
536
- $meta = wp_get_attachment_metadata( $id );
537
-
538
- foreach ( $meta['sizes'] as $size => $values ) {
539
-
540
- if ( $values['file'] === $file && $url === array_shift( wp_get_attachment_image_src( $id, $size ) ) )
541
- return $id;
542
- }
543
- }
544
-
545
- return false;
546
- }
547
-
548
- public static function acf_get_registered_field( $field ) {
549
- global $acf_register_field_group;
550
-
551
- if (!$acf_register_field_group) {
552
- return $field;
553
- }
554
-
555
- foreach ($acf_register_field_group as $key => $group) {
556
- foreach ( $group['fields'] as $this_field ) {
557
- if ( $this_field['name'] == $field['name'] ){
558
- return $this_field;
559
- }
560
- }
561
- }
562
- }
563
-
564
-
565
- /**
566
- * Correct return value formatting when Pro is NOT installed
567
- */
568
- public static function acf_free_value_formatting( $value , $field ) {
569
-
570
- if ($field['type'] == 'image' && $field['return_format'] == 'url' && !strstr($value , 'http' ) ) {
571
- $image_array = wp_get_attachment_image_src( $value , 'full' );
572
- return $image_array[0];
573
- }
574
-
575
- if ($field['type'] == 'file' && $field['return_format'] == 'url' && !strstr($value , 'http' ) ) {
576
- return wp_get_attachment_url( $value );
577
- }
578
-
579
- if ($field['type'] == 'wysiwyg') {
580
- $vaue = wpautop($value);
581
- $vaue = do_shortcode($value);
582
- }
583
-
584
- return $value;
585
- }
586
-
587
- /**
588
- * checks template data type
589
- * @param $value
590
- * @param $field
591
- * @return mixed
592
- */
593
- public static function acf_check_if_acf4( $value , $field ) {
594
- global $key, $lp_data;
595
-
596
- if (!isset($lp_data[$key])) {
597
- return $value;
598
- }
599
-
600
- if ( $lp_data[$key]['info']['data_type'] == 'acf4' ) {
601
- return self::acf_free_value_formatting($value , $field);
602
- } else {
603
- return $value;
604
- }
605
- }
606
-
607
-
608
- /**
609
- * This is a complicated array search method for working with ACF repeater fields.
610
- * @param $array
611
- * @param $field
612
- * @param bool|false $get_parent if get_parent is set to true to will return the parent field group key of the repeater fields
613
- * @param mixed $last_key placeholder for storing the last key...
614
- * @return bool|int|string
615
- */
616
- public static function key_search($array, $field , $get_parent = false , $last_key = false) {
617
- $value = false;
618
-
619
- foreach ($array as $key => $item) {
620
- if ($key === $field['key'] ) {
621
- $value = $item;
622
- } else {
623
- if (is_array($item)) {
624
- $last_key = ( !is_numeric($key)) ? $key : $last_key;
625
- $value = self::key_search($item, $field , $get_parent , $last_key );
626
- }
627
- }
628
-
629
- if ($value) {
630
- if (!$get_parent) {
631
- return $value;
632
- } else {
633
- return $last_key;
634
- }
635
-
636
- }
637
- }
638
-
639
- return false;
640
- }
641
-
642
- /**
643
- * Select tab that was selected in last edit session of the post.
644
- *
645
- * - If the time the same post that was last edited lies within the time the
646
- * transient exists, the last selected tab will be selected via JavaScript.
647
- * - If a new post is opened for editing, the current tab will be overwritten.
648
- */
649
- public static function handle_tab() {
650
- // Run only when post_id is present
651
- if ( ! isset( $_GET['post'] ) || ! is_numeric( $_GET['post'] ) ) {
652
- return;
653
- }
654
- $post_id = sanitize_key( $_GET['post'] );
655
- // Check for existing transient
656
- $current_tab = get_transient( self::$_transient_name );
657
- // Use value only once, delete transient right away
658
- delete_transient( self::$_transient_name );
659
- // The first tab is selected by default
660
- $tab_index = 0;
661
- // Get tab index for current post
662
- if ( $current_tab['post_id'] === $post_id ) {
663
- $tab_index = $current_tab['tab_index'];
664
- }
665
- ?>
666
- <script type="text/javascript">
667
- (function($) {
668
- /**
669
- * Global to save the current index of selected tab
670
- * @type int
671
- */
672
- window.acf_current_tab_index = null;
673
- acf.add_action('ready', function( $el ){
674
- var tabIndex = <?php echo $tab_index; ?>
675
- // Get tab element by index
676
- var $li = $('.acf-tab-group').find('li:eq(<?php echo $tab_index; ?>)');
677
- // Select tab only when it’s not the first tab, which is selected by default
678
- if (0 !== tabIndex) {
679
- $li.find('a').click();
680
- }
681
- window.acf_current_tab_index = tabIndex;
682
- });
683
- acf.add_action('refresh', function($tabGroup) {
684
- var $currentTab;
685
- var currentTabIndex = window.acf_current_tab_index;
686
- var newTabIndex;
687
- // Bail out if we have no jQuery object
688
- if (false === $tabGroup instanceof jQuery) {
689
- return;
690
- }
691
- $currentTab = $tabGroup.find('li.active');
692
- // Bail out if no active tab was found
693
- if ($currentTab.length === 0) {
694
- return;
695
- }
696
- // Get index of active tab
697
- newTabIndex = $currentTab.index();
698
- // Bail out if index is initial or previously selected tab is the same
699
- if (null === currentTabIndex || newTabIndex === currentTabIndex) {
700
- return;
701
- }
702
- window.acf_current_tab_index = newTabIndex;
703
- // Send tabIndex to backend to save transient
704
- $.ajax(ajaxurl, {
705
- method: 'post',
706
- data: {
707
- action: 'acf_save_current_tab',
708
- tab_index: newTabIndex,
709
- post_id: <?php echo $post_id; ?>
710
- }
711
- });
712
- });
713
- })(jQuery);
714
- </script>
715
- <?php
716
- }
717
- public static function ajax_acf_save_current_tab() {
718
- if ( ! isset( $_POST['tab_index'] ) || ! is_numeric( $_POST['tab_index'] ) ) {
719
- return;
720
- }
721
- $tab_index = sanitize_text_field($_POST['tab_index']);
722
- $post_id = $_POST['post_id'];
723
- $transient_value = array(
724
- 'tab_index' => $tab_index,
725
- 'post_id' => $post_id,
726
- );
727
- $result = set_transient( self::$_transient_name, $transient_value, self::$_transient_minutes * 60 );
728
- if ( $result ) {
729
- wp_send_json_success();
730
- }
731
- wp_die();
732
- }
733
-
734
- }
735
-
736
- /**
737
- * Initialize ACF Integrations
738
- */
739
-
740
- new Landing_Pages_ACF();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.activation.php DELETED
@@ -1,296 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class for managing landing page activation routines
5
- * @package LandingPages
6
- * @subpackage Activation
7
- */
8
-
9
- class Landing_Pages_Activation {
10
-
11
- static $version_wp;
12
- static $version_php;
13
- static $version_cta;
14
- static $version_leads;
15
- static $version_lpah;
16
-
17
- /**
18
- * Initiate class
19
- */
20
- public function __construct() {
21
- self::load_hooks();
22
- }
23
-
24
- /**
25
- * load supporting hooks and filters
26
- */
27
- public static function load_hooks() {
28
- if (!is_admin()) {
29
- return;
30
- }
31
-
32
- /* Add listener for unset permalinks */
33
- add_action('admin_notices', array( __CLASS__ , 'permastruct_check' ) );
34
-
35
- /** add listener for permlaink flush command */
36
- add_action('admin_init', array( __CLASS__ , 'flush_permalinks' ) , 11 );
37
-
38
- /* Add listener for uncompleted upgrade routines */
39
- add_action( 'admin_init' , array( 'Landing_Pages_Activation' , 'run_upgrade_routine_checks' ) );
40
-
41
- }
42
-
43
- public static function activate() {
44
- self::load_static_vars();
45
- self::run_version_checks();
46
- self::activate_plugin();
47
- self::run_updates();
48
- }
49
-
50
- public static function deactivate() {
51
- global $wp_rewrite;
52
- $wp_rewrite->flush_rules();
53
- }
54
-
55
- public static function load_static_vars() {
56
-
57
- self::$version_wp = '3.6';
58
- self::$version_php = '5.2';
59
- self::$version_cta = '1.2.1';
60
- self::$version_leads = '1.2.1';
61
- self::$version_lpah = '1.0.8';
62
- }
63
-
64
- public static function activate_plugin() {
65
-
66
- /* Update DB Markers for Plugin */
67
- self::store_version_data();
68
-
69
- /* Set Default Settings */
70
- self::set_default_settings();
71
-
72
- /* Activate shared components */
73
- self::activate_shared();
74
-
75
- /* Run additional actions */
76
- do_action( 'activate_landing_pages' );
77
-
78
- }
79
-
80
- /* This method loads public methods from the Landing_Pages_Activation_Update_Routines class and automatically runs them if they have not been run yet.
81
- * We use transients to store the data, which may not be the best way but I don't have to worry about save/update/create option and the auto load process
82
- */
83
-
84
- public static function run_updates() {
85
-
86
- /* Get list of updaters from Landing_Pages_Activation_Update_Routines class */
87
- $updaters = get_class_methods('Landing_Pages_Activation_Update_Routines');
88
-
89
- /* Get transient list of completed update processes */
90
- $completed = ( get_option( 'lp_completed_upgrade_routines' ) ) ? get_option( 'lp_completed_upgrade_routines' ) : array();
91
-
92
- /* Get the difference between the two arrays */
93
- $remaining = array_diff( $updaters , $completed );
94
-
95
- /* Loop through updaters and run updaters that have not been ran */
96
- foreach ( $remaining as $updater ) {
97
-
98
- Landing_Pages_Activation_Update_Routines::$updater();
99
- $completed[] = $updater;
100
-
101
- }
102
-
103
- /* Update this transient value with list of completed upgrade processes */
104
- update_option( 'lp_completed_upgrade_routines' , $completed );
105
-
106
- }
107
-
108
- /**
109
- * This method checks if there are upgrade routines that have not been executed yet and notifies the administror if there are
110
- *
111
- */
112
- public static function run_upgrade_routine_checks() {
113
-
114
- /* Listen for a manual upgrade call */
115
- if (isset($_GET['plugin_action']) && $_GET['plugin_action'] == 'upgrade_routines' && $_GET['plugin'] =='landing-pages' ) {
116
- self::run_updates();
117
- wp_redirect(wp_get_referer());
118
- exit;
119
- }
120
-
121
- /* Get list of updaters from Landing_Pages_Activation_Update_Routines class */
122
- $updaters = get_class_methods('Landing_Pages_Activation_Update_Routines');
123
-
124
- /* Get transient list of completed update processes */
125
- $completed = ( get_option( 'lp_completed_upgrade_routines' ) ) ? get_option( 'lp_completed_upgrade_routines' ) : array();
126
-
127
- /* Get the difference between the two arrays */
128
- $remaining = array_diff( $updaters , $completed );
129
-
130
- if (count($remaining)>0) {
131
- add_action( 'admin_notices', array( __CLASS__ , 'display_upgrade_routine_notice' ) );
132
- }
133
- }
134
-
135
- public static function display_upgrade_routine_notice() {
136
- ?>
137
- <div class="error">
138
- <p><?php _e( 'Landing Pages plugin requires a database upgrade:', 'inbound-pro' ); ?> <a href='?plugin=landing-pages&plugin_action=upgrade_routines'><?php _e('Upgrade database now' , 'inbound-pro' ); ?></a></p>
139
- </div>
140
- <?php
141
- }
142
-
143
-
144
- /* Creates transient records of past and current version data */
145
- public static function store_version_data() {
146
-
147
- $old = get_transient('lp_current_version');
148
- set_transient( 'lp_previous_version' , $old );
149
- set_transient( 'lp_current_version' , LANDINGPAGES_CURRENT_VERSION );
150
-
151
- }
152
-
153
- public static function set_default_settings() {
154
- add_option( 'lp_global_css', '', '', 'no' );
155
- add_option( 'lp_global_js', '', '', 'no' );
156
- add_option( 'lp_global_lp_slug', 'go', '', 'no' );
157
- update_option( 'lp_activate_rewrite_check', '1');
158
-
159
- /* Set's welcome page redirect transient */
160
- set_transient( '_landing_page_activation_redirect', true, 30 );
161
- }
162
-
163
- /**
164
- * Tells Inbound Shared to run activation commands
165
- */
166
- public static function activate_shared() {
167
- update_option( 'Inbound_Activate', true );
168
- }
169
-
170
- /* Aborts activation and details
171
- * @param args ARRAY of message details
172
- */
173
- public static function abort_activation( $args ) {
174
- echo $args['title'] . '<br>';
175
- echo $args['message'] . '<br>';
176
- echo 'Details:<br>';
177
- print_r ($args['details']);
178
- echo '<br>';
179
- echo $args['solution'];
180
-
181
- deactivate_plugins( LANDINGPAGES_FILE );
182
- exit;
183
- }
184
-
185
-
186
- /* Checks if plugin is compatible with current server PHP version */
187
- public static function run_version_checks() {
188
-
189
- global $wp_version;
190
-
191
- /* Check PHP Version */
192
- if ( version_compare( phpversion(), self::$version_php, '<' ) ) {
193
- self::abort_activation(
194
- array(
195
- 'title' => 'Installation aborted',
196
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
197
- 'details' => array(
198
- __( 'Server PHP Version' , 'inbound-pro' ) => phpversion(),
199
- __( 'Required PHP Version' , 'inbound-pro' ) => self::$version_php
200
- ),
201
- 'solution' => sprintf( __( 'Please contact your hosting provider to upgrade PHP to %s or greater' , 'inbound-pro' ) , self::$version_php )
202
- )
203
- );
204
- }
205
-
206
- /* Check WP Version */
207
- if ( version_compare( $wp_version , self::$version_wp, '<' ) ) {
208
- self::abort_activation( array(
209
- 'title' => 'Installation aborted',
210
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
211
- 'details' => array(
212
- __( 'WordPress Version' , 'inbound-pro' ) => $wp_version,
213
- __( 'Required WordPress Version' , 'inbound-pro' ) => self::$version_wp
214
- ),
215
- 'solution' => sprintf( __( 'Please update landing pages to version %s or greater.' , 'inbound-pro' ) , self::$version_wp )
216
- )
217
- );
218
- }
219
-
220
- /* Check CTA Version */
221
- if ( defined('WP_CTA_CURRENT_VERSION') && version_compare( WP_CTA_CURRENT_VERSION , self::$version_cta , '<' ) ) {
222
- self::abort_activation( array(
223
- 'title' => 'Installation aborted',
224
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
225
- 'details' => array(
226
- __( 'Calls to Action Version' , 'inbound-pro' ) => WP_CTA_CURRENT_VERSION,
227
- __( 'Required Calls to Action Version' , 'inbound-pro' ) => self::$version_cta
228
- ),
229
- 'solution' => sprintf( __( 'Please update Calls to Action to version %s or greater.' , 'inbound-pro' ) , self::$version_cta )
230
- )
231
- );
232
- }
233
-
234
- /* Check Leads Version */
235
- if ( defined('WPL_CURRENT_VERSION') && version_compare( WPL_CURRENT_VERSION , self::$version_leads , '<' ) ) {
236
- self::abort_activation( array(
237
- 'title' => 'Installation aborted',
238
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
239
- 'details' => array(
240
- __( 'Leads Version' , 'inbound-pro' ) => WPL_CURRENT_VERSION,
241
- __( 'Required Leads Version' , 'inbound-pro' ) => self::$version_leads
242
- ),
243
- 'solution' => sprintf( __( 'Please update Leads to version %s or greater.' , 'inbound-pro' ) , self::$version_leads )
244
- )
245
- );
246
- }
247
-
248
- /* Check Extension Version */
249
- if ( defined('LP_HOMEPAGE_CURRENT_VERSION') && version_compare( LP_HOMEPAGE_CURRENT_VERSION , self::$version_lpah , '<' ) ) {
250
- self::abort_activation( array(
251
- 'title' => 'Installation aborted',
252
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
253
- 'details' => array(
254
- __( 'Extension: Landing Page as Homepage' , 'inbound-pro' ) => LP_HOMEPAGE_CURRENT_VERSION,
255
- __( 'Required extension version' , 'inbound-pro' ) => self::$version_lpah
256
- ),
257
- 'solution' => sprintf( __( 'Please update extension to version %s or greater.' , 'inbound-pro' ) , self::$version_lpah )
258
- )
259
- );
260
- }
261
-
262
- }
263
-
264
- /**
265
- * flush permalinks
266
- */
267
- public static function flush_permalinks() {
268
-
269
- if ( !get_option( 'lp_activate_rewrite_check' ) ) {
270
- return;
271
- }
272
-
273
- flush_rewrite_rules( true );
274
- delete_option( 'lp_activate_rewrite_check' );
275
- }
276
-
277
- /**
278
- * check for 'default' permalinks and warn
279
- */
280
- public static function permastruct_check() {
281
- if ( '' == get_option( 'permalink_structure' ) ) {
282
- ?>
283
- <div class="error">
284
- <p><?php _e( 'Landing Pages plugin requires you to use a non default permlaink structure. Please head into your pemalink settings and choose an option besides \'default\'.' , 'landing-pages'); ?></p>
285
- </div>
286
- <?php
287
- }
288
- }
289
- }
290
-
291
- /* Add Activation Hook */
292
- register_activation_hook( LANDINGPAGES_FILE , array( 'Landing_Pages_Activation' , 'activate' ) );
293
- register_deactivation_hook( LANDINGPAGES_FILE , array( 'Landing_Pages_Activation' , 'deactivate' ) );
294
-
295
- new Landing_Pages_Activation;
296
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.activation.upgrade-routines.php DELETED
@@ -1,294 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class for defining and executing database routines. Updater methods fired are stored in transient to prevent repeat processing
5
- * @package LandingPages
6
- * @subpackage Activation
7
- */
8
- class Landing_Pages_Activation_Update_Routines {
9
-
10
-
11
- /*
12
- * @introduced: 1.5.7
13
- * @migration-type: Meta pair migragtion
14
- * @migration: convert meta key lp-conversion-area to template-name-conversion-area-content-{vid}
15
- */
16
- public static function migrate_legacy_conversion_area_contents() {
17
-
18
- /* ignore if not applicable */
19
- $previous_installed_version = get_transient('lp_current_version');
20
-
21
- if (version_compare($previous_installed_version, "1.5.7") === 1) {
22
- return;
23
- }
24
-
25
- /* for all landing pages load variations */
26
- $landing_pages = get_posts(array(
27
- 'post_type' => 'landing-page',
28
- 'posts_per_page' => -1
29
- ));
30
-
31
- foreach ($landing_pages as $post) {
32
-
33
- /* for all variations loop through and migrate_data */
34
- (get_post_meta($post->ID, 'lp-ab-variations', true)) ? $variations = get_post_meta($post->ID, 'lp-ab-variations', true) : $variations = array('0' => '0');
35
-
36
- if (!is_array($variations) && strlen($variations) > 1) {
37
- $variations = explode(',', $variations);
38
- }
39
-
40
- foreach ($variations as $key => $vid) {
41
-
42
- ($vid) ? $suffix = '-' . $vid : $suffix = '';
43
-
44
- $selected_template = get_post_meta($post->ID, 'lp-selected-template' . $suffix, true);
45
-
46
- if (!$selected_template) {
47
- continue;
48
- }
49
-
50
- /* discover legacy main content */
51
- ($vid) ? $conversion_area_content = get_post_meta($post->ID, 'conversion-area-content' . $suffix, true) : $conversion_area_content = get_post_meta($post->ID, 'lp-conversion-area', true);
52
-
53
- /* Now if the new key is not already poplated, copy the content to the new key */
54
- $check = get_post_meta($post->ID, $selected_template . '-conversion-area-content' . $suffix, true);
55
- if (!$check) {
56
- update_post_meta($post->ID, $selected_template . '-conversion-area-content' . $suffix, $conversion_area_content);
57
- }
58
-
59
- }
60
-
61
- }
62
- }
63
-
64
-
65
- /*
66
- * @introduced: 1.5.7
67
- * @migration-type: Meta pair migragtion
68
- * @migration: mirgrates post_content and content-{vid} values to template-name-main-content-{vid}
69
-
70
- */
71
- public static function migrate_legacy_main_content() {
72
-
73
- /* ignore if not applicable */
74
- $previous_installed_version = get_transient('lp_current_version');
75
-
76
- if (version_compare($previous_installed_version, "1.5.8") === 1) {
77
- return;
78
- }
79
-
80
- /* for all landing pages load variations */
81
- $landing_pages = get_posts(array(
82
- 'post_type' => 'landing-page',
83
- 'posts_per_page' => -1
84
- ));
85
-
86
- foreach ($landing_pages as $post) {
87
-
88
- /* for all variations loop through and migrate_data */
89
- (get_post_meta($post->ID, 'lp-ab-variations', true)) ? $variations = get_post_meta($post->ID, 'lp-ab-variations', true) : $variations = array('0' => '0');
90
-
91
- if (!is_array($variations) && strlen($variations) > 1) {
92
- $variations = explode(',', $variations);
93
- }
94
-
95
- foreach ($variations as $key => $vid) {
96
-
97
- ($vid) ? $suffix = '-' . $vid : $suffix = '';
98
-
99
- $selected_template = get_post_meta($post->ID, 'lp-selected-template' . $suffix, true);
100
- if (!$selected_template) {
101
- continue;
102
- }
103
-
104
- /* discover legacy main content */
105
- ($vid) ? $content = get_post_meta($post->ID, 'content' . $suffix, true) : $content = $post->post_content;
106
-
107
- /* Now if the new key is not already poplated, copy the content to the new key */
108
- $check = get_post_meta($post->ID, $selected_template . '-main-content' . $suffix, true);
109
- if (!$check) {
110
- update_post_meta($post->ID, $selected_template . '-main-content' . $suffix, $content);
111
- }
112
-
113
- }
114
-
115
- }
116
- }
117
-
118
- /*
119
- * @introduced: 1.5.8
120
- * @migration-type: template migragtion
121
- * @migration: Moves legacy templates to uploads folder
122
- *
123
- */
124
- public static function updater_move_legacy_templates() {
125
-
126
- /* ignore if not applicable */
127
- $previous_installed_version = get_transient('lp_current_version');
128
-
129
- if (version_compare($previous_installed_version, "1.5.8") === 1) {
130
- return;
131
- }
132
-
133
- /* move copy of legacy core templates to the uploads folder and delete from core templates directory */
134
- $templates_to_move = array('rsvp-envelope', 'super-slick');
135
- chmod(LANDINGPAGES_UPLOADS_PATH, 0755);
136
-
137
- $template_paths = Landing_Pages_Load_Extensions::get_core_template_ids();
138
- if (count($template_paths) > 0) {
139
- foreach ($template_paths as $name) {
140
- if (in_array($name, $templates_to_move)) {
141
- $old_path = LANDINGPAGES_PATH . "templates/$name/";
142
- $new_path = LANDINGPAGES_UPLOADS_PATH . "$name/";
143
-
144
- /*
145
- echo "oldpath: $old_path<br>";
146
- echo "newpath: $new_path<br>";
147
- */
148
-
149
- @mkdir($new_path, 0775);
150
- chmod($old_path, 0775);
151
-
152
- self::move_files($old_path, $new_path);
153
-
154
- rmdir($old_path);
155
- }
156
- }
157
- }
158
- }
159
-
160
- /* Private Method - Moves files from one folder the older. This is not an updater process */
161
- private static function move_files($old_path, $new_path) {
162
-
163
- $files = scandir($old_path);
164
-
165
- if (!$files) {
166
- return;
167
- }
168
-
169
- foreach ($files as $file) {
170
- if (in_array($file, array(".", ".."))) {
171
- continue;
172
- }
173
-
174
- if ($file == ".DS_Store") {
175
- unlink($old_path . $file);
176
- continue;
177
- }
178
-
179
- if (is_dir($old_path . $file)) {
180
- @mkdir($new_path . $file . '/', 0775);
181
- chmod($old_path . $file . '/', 0775);
182
- lp_move_template_files($old_path . $file . '/', $new_path . $file . '/');
183
- rmdir($old_path . $file);
184
- continue;
185
- }
186
-
187
- /*
188
- echo "oldfile:".$old_path.$file."<br>";
189
- echo "newfile:".$new_path.$file."<br>";
190
- */
191
-
192
- if (copy($old_path . $file, $new_path . $file)) {
193
- unlink($old_path . $file);
194
- }
195
- }
196
-
197
- $delete = (isset($delete)) ? $delete : false;
198
-
199
- if (!$delete) {
200
- return;
201
- }
202
- }
203
-
204
-
205
- /*
206
- * @introduced: 1.7.5
207
- * @migration-type: Meta key rename
208
- * @migration: renames all instances of inbound_conversion_data to _inbound_conversion_data
209
-
210
- */
211
- public static function meta_key_change_conversion_object() {
212
- global $wpdb;
213
-
214
- /* ignore if not applicable */
215
- $previous_installed_version = get_transient('lp_current_version');
216
-
217
- if (version_compare($previous_installed_version, "1.7.5") === 1) {
218
- return;
219
- }
220
-
221
- $wpdb->query("UPDATE $wpdb->postmeta SET `meta_key` = REPLACE (`meta_key` , 'inbound_conversion_data', '_inbound_conversion_data')");
222
- }
223
-
224
- /*
225
- * @introduced: 1.8.9
226
- * @migration-type: Meta pair migragtion
227
- * @migration: Make a meta pair copy of wp_content into 'content' meta key for variation 0 to use (refactor session)
228
- * @moredetails: Before 1.8.9 we did not source post_content from a meta pair when variation 0 was served. In a step to refactor and normalize we now pull post_content from the meta pair with key 'content'. For now (subject to further improvements in the future), variation id 0 pulls from 'content' meta key while varation 1+ pulls from 'content-{varation_id}' meta key. *
229
- */
230
- public static function prepare_content_meta_key_for_variation_0() {
231
-
232
- /* ignore if not applicable */
233
- $previous_installed_version = get_transient('lp_current_version');
234
-
235
- if (version_compare($previous_installed_version, "1.8.9") === 1) {
236
- return;
237
- }
238
-
239
- /* for all landing pages load variations */
240
- $landing_pages = get_posts(array(
241
- 'post_type' => 'landing-page',
242
- 'posts_per_page' => -1
243
- ));
244
-
245
- /* loop through landing pages and copy post content into meta object */
246
- foreach ($landing_pages as $post) {
247
- $content = $post->post_content;
248
- update_post_meta($post->ID, 'content', $content);
249
- }
250
- }
251
-
252
- /*
253
- * @introduced: 2.0.4
254
- * @migration-type: Meta pair migragtion
255
- * @migration: mirgrates lp_ab_variation_status to lp_ab_variation_status-0
256
- * @migration: mirgrates lp-variation-notes to lp-variation-notes-0
257
-
258
- */
259
- public static function migrate_variation_status_metapair() {
260
-
261
- /* ignore if not applicable */
262
- $previous_installed_version = get_transient('lp_current_version');
263
-
264
- if (version_compare($previous_installed_version, "2.0.4") === 1) {
265
- return;
266
- }
267
-
268
- /* for all landing pages load variations */
269
- $landing_pages = get_posts(array(
270
- 'post_type' => 'landing-page',
271
- 'posts_per_page' => -1
272
- ));
273
-
274
- foreach ($landing_pages as $post) {
275
-
276
- /* mirgrates lp_ab_variation_status to lp_ab_variation_status-0 */
277
- $status = get_post_meta($post->ID, 'lp_ab_variation_status', true);
278
- update_post_meta($post->ID, 'lp_ab_variation_status-0', $status);
279
-
280
- /* mirgrates lp_ab_variation_status to lp_ab_variation_status-0 */
281
- $status = get_post_meta($post->ID, 'lp-variation-notes', true);
282
- update_post_meta($post->ID, 'lp-variation-notes-0', $status);
283
-
284
- }
285
- }
286
-
287
- }
288
-
289
-
290
- /* Declare Helper Functions here */
291
- function lp_move_template_files($old_path, $new_path) {
292
-
293
-
294
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.admin-menus.php DELETED
@@ -1,56 +0,0 @@
1
- <?php
2
- /**
3
- * Class for adding Landing Pages menu items to left wp-admin menu
4
- * @package LandingPages
5
- * @subpackage Menus
6
- */
7
- class Landing_Pages_Admin_Menus {
8
-
9
- /**
10
- * Initiate class
11
- */
12
- public function __construct() {
13
- self::add_hooks();
14
- }
15
-
16
- /**
17
- * Load hooks and filters
18
- */
19
- public static function add_hooks() {
20
- add_action('admin_menu', array(__CLASS__, 'add_sub_menus') );
21
- add_action('admin_init', array(__CLASS__, 'redirect_inbound_pro_settings') );
22
- }
23
-
24
- /**
25
- * Add sub menu items to Landing Pages
26
- */
27
- public static function add_sub_menus() {
28
-
29
- /* add_submenu_page('edit.php?post_type=landing-page', __('Forms', 'landing-pages'), __('Forms', 'landing-pages'), 'edit_landing_pages', 'inbound-forms-redirect', 100); */
30
- if ( !class_exists('Inbound_Pro_Plugin') ) {
31
- add_submenu_page('edit.php?post_type=landing-page', __('Settings', 'landing-pages'), __('Settings', 'landing-pages'), 'edit_landing_pages', 'lp_global_settings', array('Landing_Pages_Settings' , 'display_settings'));
32
- add_submenu_page('edit.php?post_type=landing-page', __('Upgrade to Pro' , 'landing-pages'),__('Upgrade to Pro' , 'landing-pages'), 'edit_landing_pages', 'lp_store', array( 'Inbound_Now_Store' , 'store_display' ),100);
33
- } else {
34
- add_submenu_page('edit.php?post_type=landing-page', __('Settings', 'landing-pages'), __('Settings', 'landing-pages'), 'edit_landing_pages', 'inbound-pro-landing-pages', array( 'Landing_Pages_Settings' , 'redirect_settings' ));
35
- }
36
-
37
- add_submenu_page('edit.php?post_type=landing-page', __('Upload Templates', 'landing-pages'), __('Upload Templates', 'landing-pages'), 'edit_landing_pages', 'lp_manage_templates', 'lp_manage_templates', 100);
38
-
39
- }
40
-
41
- /**
42
- * redirects settings link to Inbound Pro settings page with Landing Pages settings pre-loaded
43
- */
44
- public static function redirect_inbound_pro_settings() {
45
-
46
- if ( !isset($_GET['page']) || $_GET['page'] != 'inbound-pro-landing-pages') {
47
- return;
48
- }
49
-
50
- header('Location: ' . admin_url('admin.php?page=inbound-pro&setting=Landing+Pages'));
51
- exit;
52
-
53
- }
54
- }
55
-
56
- new Landing_Pages_Admin_Menus;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.admin-notices.php DELETED
@@ -1,185 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class for defining and displaying admin notices to users. Only displays notices in areas related to Landing Pages plugin.
5
- * @package LandingPages
6
- * @subpackage Notices
7
- */
8
-
9
- class Landing_Pages_Admin_Notices {
10
-
11
- public function __construct() {
12
- self::add_hooks();
13
- }
14
-
15
-
16
- public static function add_hooks() {
17
- add_action('admin_notices', array( __CLASS__, 'dont_install_landing_page_templates_here'));
18
- add_action('admin_notices', array( __CLASS__, 'permalink_structure_notice' ) );
19
- }
20
-
21
- /**
22
- * Persistant message to not install landing page themes at templates.
23
- */
24
- public static function dont_install_landing_page_templates_here() {
25
-
26
- $screen = get_current_screen();
27
-
28
- if( $screen->id === 'themes' ||
29
- $screen->id === 'theme-install' ||
30
- $screen->id === 'update' && isset($_GET['action']) && $_GET['action'] === "upload-theme"
31
- ) {
32
- /* only show administrators */
33
- if( !current_user_can('activate_plugins') ) {
34
- return;
35
- }
36
-
37
- $message_id = 'landing-page-installation';
38
-
39
- if (is_plugin_active('landing-pages/landing-pages.php')) {
40
- $lp = true;
41
- $message_id = 'landing-page-installation';
42
- }
43
-
44
- if (is_plugin_active('cta/calls-to-action.php')) {
45
- $cta = true;
46
- $message_id = 'cta-installation';
47
- }
48
-
49
- /* check if user viewed message already */
50
- if (self::check_if_viewed($message_id)) {
51
- return;
52
- }
53
-
54
- $doc = 'http://docs.inboundnow.com/guide/installing-new-templates/';
55
- $link = admin_url( 'edit.php?post_type=landing-page&page=lp_templates_upload' );
56
-
57
-
58
- ?>
59
- <div class="error" style="margin-bottom:10px;" id="inbound_notice_<?php echo $message_id; ?>">
60
- <h3 style='font-weight:normal; margin-bottom:0px;padding-bottom:0px;'>
61
- <strong>
62
- <?php _e( 'Attention Landing Page Users:' , 'inbound-pro' ); ?>
63
- </strong>
64
- </h3>
65
- <p style='font-weight:normal; margin-top:0px;margin-bottom:0px;'><?php _e( sprintf( 'If you are trying to install a <strong>landing page template</strong> from Inbound Now, %s Please Follow these instructions%s' , '<a href=\'http://docs.inboundnow.com/guide/installing-new-templates/\' target=\'_blank\'>' , '</a>' ) , 'inbound-pro' ); ?>
66
- <br>
67
- <?php echo "Landing page templates need to be installed <a href='".$link."'>here</a> in the <strong><a href='".$link."'>Landing pages</a> > <a href='".$link."'>Manage templates area</a></strong>"; ?>
68
- </p>
69
- <a class="button button-large inbound_dismiss" href="#" id="<?php echo $message_id; ?>" data-notification-id="<?php echo $message_id; ?>" ><?php _e('Dismiss','inbound-pro'); ?></a>
70
- <br><br>
71
- </div>
72
- <?php
73
-
74
- /* echo javascript used to listen for notice closing */
75
- self::javascript_dismiss_notice();
76
- }
77
- }
78
-
79
- /**
80
- * Notice to tell people that a permalink structure besides default must be selected to enable split testing
81
- */
82
- public static function permalink_structure_notice(){
83
- global $pagenow;
84
-
85
- if ( !get_option('permalink_structure') ) {
86
-
87
- /* only show administrators */
88
- if( !current_user_can('activate_plugins') ) {
89
- return;
90
- }
91
- ?>
92
- <div class="error">
93
- <p>
94
- <?php _e( 'We\'ve noticed that your permalink settings are set to the default setting. Landing Page varation roation is not possible on this setting. To enable roation please go into Settings->Permalinks and update them to a different format.' , 'inbound-pro' ); ?>
95
- </p>
96
- </div>
97
- <?php
98
- }
99
- }
100
-
101
- /**
102
- * Notice to tell people that variation A needs to be save first
103
- */
104
- public static function acf5_required(){
105
- global $post;
106
-
107
- $screen = get_current_screen();
108
-
109
- if ( !isset($post) || $screen->id == 'landing-pages' ||$screen->id == 'edit-landing-page' || $post->post_status !='publish' ) {
110
- return;
111
- }
112
-
113
- $extension_data = Landing_Pages_Load_Extensions::get_extended_data();;
114
- $current_template = Landing_Pages_Variations::get_current_template($post->ID);
115
-
116
- if ( defined('ACF_PRO') || !isset($extension_data[$current_template]['info']['data_type']) || $extension_data[$current_template]['info']['data_type'] != 'acf5' ) {
117
- return;
118
- }
119
-
120
- ?>
121
-
122
- <div class="error">
123
- <p>
124
- <?php echo sprintf(__('This landing page template requires %sInbound Pro Plugin + active subscription%s or the %sInbound Premium Template Support Extension%s to operate. Please download the best available option and activate it as a plugin to continue working with this template.', 'landing-pages'), '<a href="https://www.inboundnow.com/pricing/">', '</a>', '<a href="https://www.inboundnow.com/account/">', '</a>'); ?>
125
- </p>
126
- </div>
127
- <?php
128
-
129
- }
130
-
131
-
132
- /**
133
- * check if user has viewed and dismissed cta
134
- * @param $notificaiton_id
135
- */
136
- public static function check_if_viewed( $notificaiton_id ) {
137
- global $current_user;
138
-
139
- $user_id = $current_user->ID;
140
-
141
- return get_user_meta($user_id, 'inbound_notification_' . $notificaiton_id ) ;
142
- }
143
-
144
-
145
- public static function javascript_dismiss_notice() {
146
- global $current_user;
147
-
148
- $user_id = $current_user->ID;
149
- ?>
150
- <script type="text/javascript">
151
- jQuery( document ).ready(function() {
152
-
153
- jQuery('body').on('click' , '.inbound_dismiss' , function() {
154
-
155
- var notification_id = jQuery( this ).data('notification-id');
156
-
157
- jQuery('#inbound_notice_' + notification_id).hide();
158
-
159
- jQuery.ajax({
160
- type: 'POST',
161
- url: ajaxurl,
162
- context: this,
163
- data: {
164
- action: 'inbound_dismiss_ajax',
165
- notification_id: notification_id,
166
- user_id: '<?php echo $user_id; ?>'
167
- },
168
-
169
- success: function (data) {
170
- },
171
-
172
- error: function (MLHttpRequest, textStatus, errorThrown) {
173
- alert("Ajax not enabled");
174
- }
175
- });
176
- })
177
-
178
- });
179
- </script>
180
- <?php
181
- }
182
-
183
- }
184
-
185
- new Landing_Pages_Admin_Notices;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.install.php DELETED
@@ -1,129 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class for creating example landing page on first install and prompting Leads and CTA GPL plugin downloads when Landing Pages GPL installed.
5
- * @package LandingPages
6
- * @subpackage Activation
7
- */
8
-
9
- class Landing_Pages_Install {
10
-
11
- /**
12
- * Initiate class
13
- */
14
- public function __construct() {
15
- self::add_hooks();
16
- }
17
-
18
- /**
19
- * Load hooks and filters
20
- */
21
- public static function add_hooks() {
22
- add_action( 'admin_init', array( __CLASS__ , 'install_example_landing_page_check') );
23
-
24
- /* load styles and scripts */
25
- add_action('admin_enqueue_scripts', array( __CLASS__ , 'enqueue_scripts' ) );
26
-
27
- }
28
-
29
- /**
30
- * Enqueue scripts and styles
31
- */
32
- public static function enqueue_scripts() {
33
- global $plugin_page;
34
- if ( $plugin_page != 'install-inbound-plugins' ) {
35
- return;
36
- }
37
-
38
- wp_enqueue_script('inbound-install-plugins', LANDINGPAGES_URLPATH . 'assets/js/admin/install-plugins.js' , array() , null);
39
- wp_enqueue_style('inbound-install-plugins-css', LANDINGPAGES_URLPATH . 'assets/css/admin/install-plugins.css', array() , null);
40
- }
41
-
42
- /**
43
- * Creates example landing page if needs creating else returns the lp id on record
44
- * @returns INT
45
- */
46
- public static function install_example_landing_page_check() {
47
- $lp_default_options = get_option( 'lp_settings_general' );
48
-
49
- if ( isset( $lp_default_options["default_landing_page"] ) ) {
50
- return $lp_default_options["default_landing_page"];
51
- }
52
-
53
- return self::install_example_landing_page();
54
- }
55
-
56
-
57
- /**
58
- * Install example landing page and return landing page id
59
- * @returns INT $landing_page_id
60
- */
61
- public static function install_example_landing_page() {
62
-
63
-
64
- $landing_page_id = wp_insert_post(
65
- array(
66
- 'post_title' => __( 'A/B Testing Landing Page Example' , 'landing-pages'),
67
- 'post_content' => __( '<p>This is the first paragraph of your landing page where you want to draw the viewers in and quickly explain your value proposition.</p><p><strong>Use Bullet Points to:</strong><ul><li>Explain why they should fill out the form</li><li>What they will learn if they download</li><li>A problem this form will solve for them</li></ul></p><p>Short ending paragraph reiterating the value behind the form</p>' , 'post'),
68
- 'post_status' => 'publish',
69
- 'post_type' => 'landing-page',
70
- ) , true
71
- );
72
-
73
- /* Variation A */
74
- add_post_meta($landing_page_id, 'lp-main-headline', __( 'Main Catchy Headline (A)' , 'landing-pages') );
75
- add_post_meta($landing_page_id, 'lp-selected-template', 'svtle');
76
- add_post_meta($landing_page_id, 'svtle-conversion-area-content', '<h2>'.__( 'Form a' , 'landing-pages') .'</h2>[inbound_forms id="default_1" name="First, Last, Email Form"]' );
77
- add_post_meta($landing_page_id, 'svtle-main-content', __( '<p>This is the first paragraph of your landing page where you want to draw the viewers in and quickly explain your value proposition.</p><p><strong>Use Bullet Points to:</strong><ul><li>Explain why they should fill out the form</li><li>What they will learn if they download</li><li>A problem this form will solve for them</li></ul></p><p>Short ending paragraph reiterating the value behind the form</p>' , 'landing-pages') );
78
-
79
- /* variation B */
80
- add_post_meta($landing_page_id, 'lp-main-headline-1', __('Main Catchy Headline Two (B)' , 'landing-pages') );
81
- add_post_meta($landing_page_id, 'lp-selected-template-1', 'svtle');
82
- add_post_meta($landing_page_id, 'svtle-conversion-area-content-1', '<h2>'.__( 'Form B' , 'landing-pages') .'</h2>[inbound_forms id="default_1" name="First, Last, Email Form"]');
83
- add_post_meta($landing_page_id, 'svtle-main-content-1', '<p>(Version B) This is the first paragraph of your landing page where you want to draw the viewers in and quickly explain your value proposition.</p><p><strong>Use Bullet Points to:</strong><ul><li>Explain why they should fill out the form</li><li>What they will learn if they download</li><li>A problem this form will solve for them</li></ul></p><p>Short ending paragraph reiterating the value behind the form</p>');
84
-
85
- /* Add A/B Testing meta */
86
- add_post_meta($landing_page_id, 'lp-ab-variations', '0,1');
87
- add_post_meta($landing_page_id, 'lp-ab-variation-impressions-0', 30);
88
- add_post_meta($landing_page_id, 'lp-ab-variation-impressions-1', 35);
89
- add_post_meta($landing_page_id, 'lp-ab-variation-conversions-0', 10);
90
- add_post_meta($landing_page_id, 'lp-ab-variation-conversions-1', 15);
91
-
92
- /* Add template meta A */
93
- add_post_meta($landing_page_id, 'svtle-submit-button-color', '5baa1e');
94
- add_post_meta($landing_page_id, 'svtle-display-social', '0');
95
- add_post_meta($landing_page_id, 'svtle-logo', '/wp-content/plugins/landing-pages/templates/svtle/assets/images/inbound-logo.png');
96
- add_post_meta($landing_page_id, 'svtle-body-color', 'ffffff');
97
- add_post_meta($landing_page_id, 'svtle-sidebar', 'left');
98
- add_post_meta($landing_page_id, 'svtle-page-text-color', '4d4d4d');
99
- add_post_meta($landing_page_id, 'svtle-sidebar-color', 'ffffff');
100
- add_post_meta($landing_page_id, 'svtle-sidebar-text-color', '000000');
101
- add_post_meta($landing_page_id, 'svtle-header-color', 'ffffff');
102
-
103
- /* Add template meta B */
104
- add_post_meta($landing_page_id, 'svtle-submit-button-color-1', 'ff0c00');
105
- add_post_meta($landing_page_id, 'svtle-display-social-1', '0');
106
- add_post_meta($landing_page_id, 'svtle-logo-1', '/wp-content/plugins/landing-pages/templates/svtle/assets/images/inbound-logo.png');
107
- add_post_meta($landing_page_id, 'svtle-body-color-1', '51b0ef');
108
- add_post_meta($landing_page_id, 'svtle-sidebar-1', 'left');
109
- add_post_meta($landing_page_id, 'svtle-page-text-color-1', '000000');
110
- add_post_meta($landing_page_id, 'svtle-sidebar-color-1', '51b0ef');
111
- add_post_meta($landing_page_id, 'svtle-sidebar-text-color-1', '000000');
112
- add_post_meta($landing_page_id, 'svtle-header-color-1', '51b0ef');
113
-
114
- /* Store our page IDs */
115
- $options = array(
116
- "default_landing_page" => $landing_page_id
117
- );
118
-
119
-
120
- update_option( "lp_settings_general" , $options );
121
-
122
- return $landing_page_id;
123
- }
124
-
125
-
126
- }
127
-
128
-
129
- new Landing_Pages_Install;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.landing-pages.php DELETED
@@ -1,722 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class for loading landing page templates when landing page is called on the frontend.
5
- * @package LandingPages
6
- * @subpackage Templates
7
- */
8
-
9
- class Landing_Pages_Template_Switcher {
10
-
11
- /**
12
- * Initiate class
13
- */
14
- public function __construct() {
15
- self::add_hooks();
16
- }
17
-
18
- /**
19
- * Load hook and filters
20
- */
21
- public static function add_hooks() {
22
- /* Alter the title for landing page to it's administrative title */
23
- add_filter('wp_title', array( __CLASS__ , 'display_landing_page_title' ), 9, 2);
24
- add_filter('the_title', array( __CLASS__ , 'display_landing_page_title' ) , 10, 2);
25
- add_filter('get_the_title', array( __CLASS__ , 'display_landing_page_title' ), 10, 2);
26
-
27
- /* prepare and display landing page content */
28
- add_filter('the_content', array( __CLASS__ , 'display_landing_page_content' ) , 10, 2);
29
- add_filter('get_the_content', array( __CLASS__ , 'display_landing_page_content' ) , 10, 2);
30
-
31
- /* prepare conversion area if default template */
32
- add_filter('the_content', array( __CLASS__ , 'display_conversion_area' ) , 20);
33
- add_filter('get_the_content', array( __CLASS__ , 'display_conversion_area' ), 20);
34
-
35
- /* Switch to correct landing page template */
36
- add_filter('template_include', array( __CLASS__ , 'switch_template' ), 13);
37
-
38
- /* Load custom CSS and load custom JS */
39
- add_action('wp_head', array( __CLASS__ , 'load_custom_js_css' ) );
40
-
41
- /* add conversion area shortcode */
42
- add_shortcode('lp_conversion_area', array( __CLASS__ , 'process_conversion_area_shortcode') );
43
- add_shortcode('landing-page-conversion', array( __CLASS__ , 'process_conversion_shortcode') );
44
-
45
- /* listen for postback URL conversions */
46
- add_action( 'init' , array( __CLASS__ , 'process_postback_conversion' ));
47
-
48
- /* Add Custom Class to Landing Page Nav Menu to hide/remove */
49
- add_filter('wp_nav_menu_args', array( __CLASS__ , 'hide_nav_menu' ) );
50
-
51
- /* strips active theme styling from non default landing pages */
52
- add_action('wp_print_styles', array( __CLASS__ , 'strip_styles' ), 100);
53
- }
54
-
55
- /**
56
- * Return custom Landing Page headline
57
- */
58
- public static function display_landing_page_title( $content, $id = null ) {
59
- global $post;
60
-
61
- if (!isset($post)) {
62
- return $content;
63
- }
64
-
65
- if ( ($post->post_type != 'landing-page' || is_admin()) || $id != $post->ID ) {
66
- return $content;
67
- }
68
-
69
- return lp_main_headline($post, null, true);
70
- }
71
-
72
- /**
73
- * Displays landing page content
74
- * @param $content
75
- * @return string
76
- */
77
- public static function display_landing_page_content($content) {
78
- global $post;
79
-
80
- if (!isset($post) || $post->post_type != 'landing-page') {
81
- return $content;
82
- }
83
-
84
- $content = Landing_Pages_Variations::get_post_content( $post->ID );
85
- $content = do_shortcode( $content );
86
- if (!defined('LANDING_PAGES_WPAUTOP') || LANDING_PAGES_WPAUTOP === TRUE) {
87
- $content = wpautop($content);
88
- }
89
- return $content;
90
- }
91
-
92
- /**
93
- * display conversion area
94
- */
95
- public static function display_conversion_area($content) {
96
-
97
- if ('landing-page' != get_post_type() || is_admin()) {
98
- return $content;
99
- }
100
-
101
- global $post;
102
-
103
- remove_action('the_content', array( __CLASS__ , 'display_conversion_area' ) , 20 );
104
-
105
- $template = Landing_Pages_Variations::get_current_template( $post->ID );
106
-
107
- $my_theme = wp_get_theme($template);
108
-
109
- if ( !$my_theme->exists() && $template != 'default') {
110
- return $content;
111
- }
112
-
113
- $wrapper_class = "";
114
-
115
- $position = Landing_Pages_Variations::get_conversion_area_placement( $post->ID );
116
- $conversion_area = lp_conversion_area(null, null, true, true);
117
- $conversion_area = "<div id='lp_container' class='$wrapper_class'>" . $conversion_area . "</div>";
118
-
119
- if ($position == 'top') {
120
- $content = $conversion_area . $content;
121
- } else if ($position == 'bottom') {
122
- $content = $content . $conversion_area;
123
- } else if ($position == 'widget') {
124
- $content = $content;
125
- } else {
126
- $conversion_area = str_replace("id='lp_container'", "id='lp_container' class='lp_form_$position' style='float:$position'", $conversion_area);
127
- $content = $conversion_area . $content;
128
-
129
- }
130
-
131
- return $content;
132
- }
133
-
134
- /**
135
- * Detects if landing page & issues the correct template
136
- */
137
- public static function switch_template( $template ) {
138
- global $wp_query, $post, $query_string;
139
-
140
- if (!isset($post) || $post->post_type != "landing-page" || !is_singular("landing-page")) {
141
- return $template;
142
- }
143
-
144
- if (post_password_required()) {
145
- $password = apply_filters('landing-pages/password-template' , get_the_password_form());
146
-
147
- /* This is for developers who'd like to create their own custom password protection template isntead of using the bland one */
148
- if (file_exists($password)) {
149
- return $password;
150
- } else {
151
- echo $password;
152
- exit;
153
- }
154
- }
155
-
156
- /* nextgen gallery support */
157
- if (!defined('NGG_DISABLE_FILTER_THE_CONTENT')) {
158
- define( 'NGG_DISABLE_FILTER_THE_CONTENT' , true );
159
- }
160
-
161
- $selected_template = Landing_Pages_Variations::get_current_template( $post->ID );
162
-
163
- if (!isset($selected_template) || $selected_template === 'default' ) {
164
- return $template;
165
- }
166
-
167
- /* check if inactive theme */
168
- $my_theme = wp_get_theme( $selected_template );
169
- if ($my_theme->exists()) {
170
- return $template;
171
- }
172
-
173
- /* check if core template first */
174
- if (file_exists(LANDINGPAGES_PATH . 'templates/' . $selected_template . '/index.php')) {
175
- return LANDINGPAGES_PATH . 'templates/' . $selected_template . '/index.php';
176
- }
177
- /* next check if it is an uploaded template */
178
- else if (file_exists(LANDINGPAGES_UPLOADS_PATH . $selected_template . '/index.php')) {
179
- return LANDINGPAGES_UPLOADS_PATH . $selected_template . '/index.php';
180
- }
181
- /* next check if it is included with a WordPress theme */
182
- else if (file_exists(LANDINGPAGES_THEME_TEMPLATES_PATH . $selected_template . '/index.php')) {
183
- return LANDINGPAGES_THEME_TEMPLATES_PATH . $selected_template . '/index.php';
184
- }
185
-
186
- return $template;
187
- }
188
-
189
- /**
190
- * load custom CSS & JS
191
- */
192
- public static function load_custom_js_css() {
193
- global $post;
194
-
195
- if ( !isset($post) || 'landing-page' != $post->post_type) {
196
- return;
197
- }
198
-
199
- $custom_css_name = Landing_Pages_Variations::prepare_input_id('lp-custom-css');
200
- $custom_js_name =Landing_Pages_Variations::prepare_input_id('lp-custom-js');
201
- $custom_css = Landing_Pages_Variations::get_custom_css( $post->ID );
202
- $custom_js = Landing_Pages_Variations::get_custom_js( $post->ID );
203
- echo "<!-- This site landing page was built with the WordPress Landing Pages plugin - https://www.inboundnow.com/landing-pages/ -->";
204
-
205
- if (!stristr($custom_css, '<style')) {
206
- echo '<style type="text/css" id="lp_css_custom">' . $custom_css . '</style>';
207
- } else {
208
- echo $custom_css;
209
- }
210
-
211
- if (!stristr($custom_js, '<script') && ( stristr($custom_js, '$.') || stristr($custom_js, 'jQuery') ) ) {
212
- echo '<script type="text/javascript" id="lp_js_custom">jQuery(document).ready(function($) {
213
- ' . $custom_js . ' });</script>';
214
- } else if (!stristr($custom_js, '<script')) {
215
- echo '<script type="text/javascript" id="lp_js_custom">' . $custom_js . '</script>';
216
- } else {
217
- echo $custom_js;
218
- }
219
- }
220
-
221
-
222
- /**
223
- *
224
- * [lp_conversion_area] shortcode support
225
- *
226
- */
227
- public static function process_conversion_area_shortcode($atts, $content = null) {
228
- extract(shortcode_atts(array('id' => '', 'align' => '' /*'style' => ''*/
229
- ), $atts));
230
-
231
-
232
- $conversion_area = lp_conversion_area($post = null, $content = null, $return = true, $doshortcode = true, $rebuild_attributes = true);
233
-
234
- return $conversion_area;
235
- }
236
-
237
- /**
238
- *
239
- * [landing-page-conversion] shortcode support
240
- *
241
- */
242
- public static function process_conversion_shortcode($atts, $content = null) {
243
- extract(shortcode_atts(array(
244
- 'id' => '',
245
- 'vid' => '0'
246
- ), $atts));
247
-
248
-
249
- /* check do not track flag */
250
- $do_not_track = apply_filters('inbound_analytics_stop_track' , false );
251
- if ( $do_not_track || isset($_SESSION['landing_page_conversions']) && in_array( $id , $_SESSION['landing_page_conversions'] ) ) {
252
- return;
253
- }
254
-
255
- Landing_Pages_Variations::record_conversion($id , $vid);
256
-
257
- $_SESSION['landing_page_conversions'][] = $id;
258
-
259
- }
260
-
261
- /**
262
- * Use postback URL to record conversion for landing pages
263
- */
264
- public static function process_postback_conversion($atts, $content = null) {
265
-
266
- if ( !isset($_GET['postback']) ) {
267
- return;
268
- }
269
-
270
- if ( !isset($_GET['event']) || $_GET['event'] != 'lp_conversion' ) {
271
- return;
272
- }
273
-
274
- $id = $_GET['id'];
275
- $vid = $_GET['vid'];
276
-
277
- $salt = md5( $id . AUTH_KEY );
278
-
279
- if ( $_GET['salt'] != $salt ) {
280
- return;
281
- }
282
-
283
- Landing_Pages_Variations::record_conversion($id , $vid);
284
-
285
- _e('success','landing-pages');
286
- exit;
287
-
288
- }
289
-
290
-
291
- /**
292
- * Hides navigation menu on default landing page tempaltes
293
- * @param string $args
294
- * @return string
295
- */
296
- public static function hide_nav_menu($args = '') {
297
- global $post;
298
-
299
- if ( !isset($post) || $post->post_type != 'landing-page') {
300
- return $args;
301
- }
302
-
303
-
304
- $template_name = Landing_Pages_Variations::get_current_template( $post->ID );
305
- if ($template_name != 'default') {
306
- return $args;
307
- }
308
-
309
- $nav_status = get_post_meta($post->ID, 'default-lp_hide_nav', true);
310
-
311
- if ($nav_status != 'off' ) {
312
- return $args;
313
- }
314
-
315
- if (isset($args['container_class'])) {
316
- $current_class = " " . $args['container_class'];
317
- }
318
-
319
- $args['container_class'] = "custom_landing_page_nav{$current_class}";
320
-
321
- $args['echo'] = false;
322
-
323
- return $args;
324
- }
325
-
326
- /**
327
- * Utility method for loading popular 3rd party assets into Landing Page
328
- */
329
- public static function load_misc_plugin_support() {
330
- /* WP Featherlight */
331
- if (class_exists('WP_Featherlight_Scripts')) {
332
- $wpfl = new WP_Featherlight_Scripts(plugin_dir_url( 'wp-featherlight' ) , '');
333
- $wpfl->load_css();
334
- }
335
-
336
- /* easy way for 3rd parties to hook into */
337
- do_action('load_misc_plugin_support');
338
- }
339
-
340
- /**
341
- * Remove all base css from the current active wordpress theme in landing pages
342
- * currently removes all css from wp_head and re-enqueues the admin bar css.
343
- */
344
- public static function strip_styles() {
345
-
346
- if (is_admin() || 'landing-page' != get_post_type() || !is_singular('landing-page')) {
347
- return;
348
- }
349
-
350
- global $post;
351
- $template = Landing_Pages_Variations::get_current_template( $post->ID );
352
-
353
- $my_theme = wp_get_theme($template);
354
-
355
- if ($my_theme->exists() || $template == 'default') {
356
- return;
357
- }
358
-
359
- global $wp_styles;
360
-
361
- $registered_scripts = $wp_styles->registered;
362
- $inbound_white_list = array();
363
- foreach ($registered_scripts as $handle) {
364
- if (preg_match("/\/plugins\/leads\//", $handle->src)) {
365
- /*echo $handle->handle; */
366
- $inbound_white_list[] = $handle->handle;
367
- }
368
- if (preg_match("/\/plugins\/cta\//", $handle->src)) {
369
- /*echo $handle->handle; */
370
- $inbound_white_list[] = $handle->handle;
371
- }
372
- if (preg_match("/\/plugins\/landing-pages\//", $handle->src)) {
373
- /*echo $handle->handle; */
374
- $inbound_white_list[] = $handle->handle;
375
- }
376
- }
377
-
378
- $wp_styles->queue = $inbound_white_list;
379
-
380
- wp_enqueue_style('admin-bar');
381
-
382
-
383
- }
384
- }
385
-
386
-
387
- new Landing_Pages_Template_Switcher;
388
-
389
-
390
- /**
391
- * Echos or returns main headline
392
- * @param OBJECT $post
393
- * @param STRING $headline depreciated
394
- * @param bool $return
395
- */
396
- function lp_main_headline($post = null, $headline = null, $return = false) {
397
- if (!isset($post)) {
398
- global $post;
399
- }
400
-
401
- $main_headline = Landing_Pages_Variations::get_main_headline( $post->ID );
402
-
403
- if (!$return) {
404
- echo $main_headline;
405
- } else {
406
- return $main_headline;
407
- }
408
- }
409
-
410
-
411
- /**
412
- * Display conversion area for default template
413
- * @param OBJECT $post
414
- * @param STRING $content
415
- * @param bool $return
416
- * @param bool $doshortcode
417
- * @return null
418
- */
419
- function lp_conversion_area($post = null, $content = null, $return = false, $doshortcode = true) {
420
- if (!isset($post)) {
421
- global $post;
422
- }
423
-
424
- $content = Landing_Pages_Variations::get_conversion_area( $post->ID );
425
- $wrapper_class = lp_discover_important_wrappers($content);
426
-
427
- if ($doshortcode) {
428
- $content = do_shortcode($content);
429
- }
430
-
431
- $content = apply_filters('lp_conversion_area_post', $content, $post);
432
-
433
- if (!$return) {
434
- $content = str_replace('<p><div id="inbound-form-wrapper"', '<div id="inbound-form-wrapper"', $content);
435
- $content = preg_replace('/<p[^>]*><\/p[^>]*>/', '', $content); /* remove empty p tags */
436
- $content = preg_replace('/<\/p>/', '', $content); /* remove last empty p tag */
437
- echo do_shortcode($content);
438
- } else {
439
- return $content;
440
- }
441
-
442
- }
443
-
444
-
445
- /**
446
- * Echo or return content area content for default template
447
- * @param OBJECT $post
448
- * @param STRING $content depreciated
449
- * @param bool $return
450
- *
451
- */
452
- function lp_content_area($post = null, $content = null, $return = false) {
453
- if (!isset($post)) {
454
- global $post;
455
- }
456
-
457
- if (!isset($post) && isset($_REQUEST['post'])) {
458
- $post = get_post(intval($_REQUEST['post']));
459
- } else if (!isset($post) && isset($_REQUEST['lp_id'])) {
460
- $post = get_post(intval($_REQUEST['lp_id']));
461
- }
462
-
463
-
464
- $content_area = Landing_Pages_Variations::get_post_content( $post->ID );
465
-
466
- if (!is_admin()) {
467
- $content_area = apply_filters('the_content', $content_area);
468
- }
469
-
470
- if (!$return) {
471
- echo $content_area;
472
- } else {
473
- return $content_area;
474
- }
475
-
476
- }
477
-
478
-
479
- /**
480
- * Get parent directory of calling template - used by templates
481
- * @param $path
482
- * @return mixed
483
- */
484
- function lp_get_parent_directory($path) {
485
- return basename($path);
486
- }
487
-
488
-
489
-
490
- /**
491
- * Improve body class for landing page template
492
- * @return string
493
- */
494
- function lp_body_class() {
495
- global $post;
496
- global $lp_data;
497
-
498
- $template = Landing_Pages_Variations::get_current_template( $post->ID );
499
- if ($template) {
500
- $lp_body_class = "template-" . $template;
501
- $postid = "page-id-" . get_the_ID();
502
- echo 'class="';
503
- echo $lp_body_class . " " . $postid . " wordpress-landing-page";
504
- echo '"';
505
- }
506
- return $lp_body_class;
507
- }
508
-
509
-
510
- /**
511
- * Shorthand function for getting a settings value from a landing page variation
512
- * @param $post
513
- * @param $key
514
- * @param $variation_id
515
- * @return string
516
- */
517
- function lp_get_value($post, $key, $field_id) {
518
-
519
- if (!isset($post)) {
520
- return '';
521
- }
522
-
523
- $return = Landing_Pages_Variations::get_setting_value( $key . '-'. $field_id , $post->ID );
524
-
525
- return do_shortcode($return);
526
-
527
- }
528
-
529
- /**
530
- * Generate a dropdown of available landing pages - May be unused
531
- * @param $select_id
532
- * @param $post_type
533
- * @param int $selected
534
- * @param int $width
535
- * @param int $height
536
- * @param int $font_size
537
- * @param bool $multiple
538
- */
539
- function lp_generate_drowndown($select_id, $post_type, $selected = 0, $width = 400, $height = 230, $font_size = 13, $multiple = true) {
540
- $post_type_object = get_post_type_object($post_type);
541
- $label = $post_type_object->label;
542
-
543
- if ($multiple == true) {
544
- $multiple = "multiple='multiple'";
545
- } else {
546
- $multiple = "";
547
- }
548
-
549
- $posts = get_posts(array('post_type' => $post_type, 'post_status' => 'publish', 'suppress_filters' => false, 'posts_per_page' => -1));
550
- echo '<select name="' . $select_id . '" id="' . $select_id . '" class="lp-multiple-select" style="width:' . $width . 'px;height:' . $height . 'px;font-size:' . $font_size . 'px;" ' . $multiple . '>';
551
- foreach ($posts as $post) {
552
- echo '<option value="', $post->ID, '"', $selected == $post->ID ? ' selected="selected"' : '', '>', $post->post_title, '</option>';
553
- }
554
- echo '</select>';
555
- }
556
-
557
- /**
558
- * Remove custom fields metaboxes from Landing Pages post type
559
- */
560
- function lp_in_admin_header() {
561
- global $post, $wp_meta_boxes;
562
-
563
- if ( !isset($post) || $post->post_type != 'landing-page') {
564
- return;
565
- }
566
-
567
- unset($wp_meta_boxes[get_current_screen()->id]['normal']['core']['postcustom']);
568
- }
569
- add_action('in_admin_header', 'lp_in_admin_header');
570
-
571
- /**
572
- * detect gravity forms class names
573
- * @param $content
574
- * @return string
575
- */
576
- function lp_discover_important_wrappers($content) {
577
- $wrapper_class = "";
578
- if (strstr($content, 'gform_wrapper')) {
579
- $wrapper_class = 'gform_wrapper';
580
- }
581
- return $wrapper_class;
582
- }
583
-
584
- /**
585
- * If no forms are found in conversion area add tracking class to links
586
- * @param null $content
587
- * @param null $wrapper_class
588
- * @return null|string
589
- */
590
- function lp_rebuild_attributes($content = null, $wrapper_class = null) {
591
- if (strstr($content, '<form')) {
592
- return $content;
593
- }
594
-
595
- /* Standardize all links */
596
- $inputs = preg_match_all('/\<a(.*?)\>/s', $content, $matches);
597
- if (!empty($matches[0])) {
598
- foreach ($matches[0] as $key => $value) {
599
- if ($key == 0) {
600
- $new_value = $value;
601
- $new_value = preg_replace('/ class=(["\'])(.*?)(["\'])/', 'class="$2 inbound-track-link"', $new_value);
602
-
603
-
604
- $content = str_replace($value, $new_value, $content);
605
- break;
606
- }
607
- }
608
- }
609
-
610
- $check_wrap = preg_match_all('/lp_container_noform/s', $content, $check);
611
- if (empty($check[0])) {
612
- $content = "<div id='lp_container_noform' class='$wrapper_class link-click-tracking'>{$content}</div>";
613
- }
614
-
615
- return $content;
616
- }
617
-
618
- /* LEGACY CODE FOR ADDING LANDING PAGE TEMPLATE METABOX SETTINGS TO TEMPLATE METABOX */
619
- function lp_add_option($key, $type, $id, $default = null, $label = null, $description = null, $options = null) {
620
- switch ($type) {
621
- case "colorpicker":
622
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'colorpicker', 'default' => $default);
623
- break;
624
- case "text":
625
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'text', 'default' => $default);
626
- break;
627
- case "license-key":
628
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'inbound-license-key', 'default' => $default, 'slug' => $id);
629
- break;
630
- case "textarea":
631
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'textarea', 'default' => $default);
632
- break;
633
- case "wysiwyg":
634
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'wysiwyg', 'default' => $default);
635
- break;
636
- case "media":
637
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'media', 'default' => $default);
638
- break;
639
- case "checkbox":
640
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'checkbox', 'default' => $default, 'options' => $options);
641
- break;
642
- case "radio":
643
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'radio', 'default' => $default, 'options' => $options);
644
- break;
645
- case "dropdown":
646
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'dropdown', 'default' => $default, 'options' => $options);
647
- break;
648
- case "datepicker":
649
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'datepicker', 'default' => $default);
650
- break;
651
- case "html":
652
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'html', 'default' => $default);
653
- break;
654
- case "custom-css":
655
- return array('label' => $label, 'description' => $description, 'id' => $id, 'type' => 'turn-off-editor', 'default' => $default /* inline css */
656
- );
657
- break;
658
- case "description-block":
659
- return array('label' => $label, 'description' => $description, 'id' => $key . '-' . $id, 'type' => 'description-block', 'default' => $default);
660
- break;
661
- }
662
- }
663
-
664
- /**
665
- * legacy function to discover current landing page id. Please use Landing_Pages_Variations::get_current_variation_id();
666
- * @return int
667
- */
668
- function lp_ab_testing_get_current_variation_id() {
669
- if (isset($_GET['ab-action']) && is_admin()) {
670
- return $_SESSION['lp_ab_test_open_variation'];
671
- }
672
-
673
- if (!isset($_SESSION['lp_ab_test_open_variation']) && !isset($_REQUEST['lp-variation-id'])) {
674
- $current_variation_id = 0;
675
- }
676
- /*echo $_REQUEST['lp-variation-id']; */
677
- if (isset($_REQUEST['lp-variation-id'])) {
678
- $_SESSION['lp_ab_test_open_variation'] = intval($_REQUEST['lp-variation-id']);
679
- $current_variation_id = intval($_REQUEST['lp-variation-id']);
680
- /*echo "setting session $current_variation_id"; */
681
- }
682
-
683
- if (isset($_GET['message']) && $_GET['message'] == 1 && isset($_SESSION['lp_ab_test_open_variation'])) {
684
- $current_variation_id = $_SESSION['lp_ab_test_open_variation'];
685
-
686
- /*echo "here:".$_SESSION['lp_ab_test_open_variation']; */
687
- }
688
-
689
- if (isset($_GET['ab-action']) && $_GET['ab-action'] == 'delete-variation') {
690
- $current_variation_id = 0;
691
- $_SESSION['lp_ab_test_open_variation'] = 0;
692
- }
693
-
694
- if (!isset($current_variation_id)) $current_variation_id = 0;
695
-
696
- return $current_variation_id;
697
- }
698
-
699
-
700
- /* LEGACY CALLBACKS -- STILL USED BY SOME OLDER EXTENSIONS AND TEMPLATES */
701
- function lp_list_feature() {
702
- return null;
703
- }
704
-
705
-
706
- function lp_global_config() {
707
- do_action('lp_global_config');
708
- }
709
-
710
- if (!function_exists('lp_init')) {
711
- function lp_init() {
712
- do_action('lp_init');
713
- }
714
- }
715
-
716
- function lp_head() {
717
- do_action('lp_head');
718
- }
719
-
720
- function lp_footer() {
721
- do_action('lp_footer');
722
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.load-templates.php DELETED
@@ -1,278 +0,0 @@
1
- <?php
2
- /**
3
- * Class for loading extensions and templates. Mostly templates. No extensions use this class anymore.
4
- * @package LandingPages
5
- * @subpackage Templates
6
- */
7
-
8
- class Landing_Pages_Load_Extensions {
9
-
10
- /**
11
- * Initializes Landing_Pages_Load_Extensions
12
- */
13
- public function __construct() {
14
- /* load hooks & filters */
15
- self::load_hooks();
16
- }
17
-
18
- /**
19
- * Loads hooks and filiters
20
- */
21
- public static function load_hooks() {
22
-
23
- /*load core & uploaded templates */
24
- add_action('admin_init',array(__CLASS__,'load_core_template_configurations') , 5 );
25
- add_action('admin_init',array(__CLASS__,'load_uploaded_template_configurations') , 5 );
26
- add_action('admin_init',array(__CLASS__,'load_theme_privided_template_configurations') , 5 );
27
-
28
- /* Adds core metabox settings to extension data array */
29
- add_filter('lp_extension_data', array(__CLASS__, 'add_core_setting_data'), 1, 1);
30
-
31
- /* Modifies legacy template data key names for old, un-updated legacy templates */
32
- add_filter('lp_extension_data', array(__CLASS__, 'add_legacy_data_support'), 10, 1);
33
-
34
- }
35
-
36
- /**
37
- * Adds core metaboxes setting data using lp_extension_data filter
38
- */
39
- public static function add_core_setting_data($data) {
40
-
41
- $data['lp']['settings'] = array(array('id' => 'selected-template', 'label' => __('Select Template', 'landing-pages'), 'description' => __("This option provides a placeholder for the selected template data.", 'landing-pages'), 'type' => 'radio', /* this is not honored. Template selection setting is handled uniquely by core. */
42
- 'default' => 'default', 'options' => null /* this is not honored. Template selection setting is handled uniquely by core. */), array('id' => 'main-headline', 'label' => __('Set Main Headline', 'landing-pages'), 'description' => __("Set Main Headline", 'landing-pages'), 'type' => 'text', /* this is not honored. Main Headline Input setting is handled uniquely by core. */
43
- 'default' => '', 'options' => null),);
44
-
45
- return $data;
46
- }
47
-
48
- /**
49
- * Looks for occurances of 'options' in template & extension data arrays and replaces key with 'settings'
50
- */
51
- public static function add_legacy_data_support($data) {
52
-
53
- foreach ($data as $parent_key => $subarray) {
54
- if (is_array($subarray)) {
55
- foreach ($subarray as $k => $subsubarray) {
56
- /* change 'options' key to 'settings' */
57
- if ($k == 'options') $data[$parent_key]['settings'] = $subsubarray;
58
-
59
- if ($k == 'category') $data[$parent_key]['info']['category'] = $subsubarray;
60
-
61
- if ($k == 'version') $data[$parent_key]['info']['version'] = $subsubarray;
62
-
63
- if ($k == 'label') $data[$parent_key]['info']['label'] = $subsubarray;
64
-
65
- if ($k == 'description') $data[$parent_key]['info']['description'] = $subsubarray;
66
- }
67
- }
68
- }
69
-
70
- return $data;
71
- }
72
-
73
- /**
74
- * Loads core template config.php files
75
- *
76
- * @returns ARRAY contains template setting data
77
- */
78
- public static function load_core_template_configurations() {
79
- global $lp_data;
80
-
81
- $template_ids = self::get_core_template_ids();
82
-
83
- /*Now load all config.php files with their custom meta data */
84
- if (count($template_ids) > 0) {
85
- foreach ($template_ids as $name) {
86
- if ($name != ".svn" && $name != ".git") {
87
- include_once(LANDINGPAGES_PATH . "/templates/$name/config.php");
88
- }
89
- }
90
- }
91
-
92
- }
93
-
94
- /**
95
- * Loads uploaded template config.php files
96
- *
97
- */
98
- public static function load_uploaded_template_configurations() {
99
- global $lp_data;
100
-
101
- $template_ids = self::get_uploaded_template_ids();
102
-
103
- /* loop through template ids and include their config file */
104
- foreach ($template_ids as $name) {
105
- $match = FALSE;
106
- if (strpos($name, 'tmp') !== FALSE || strpos($name, 'template-generator') !== FALSE) {
107
- $match = TRUE;
108
- }
109
- if ($name != ".svn" && $name != ".git" && $name != 'template-generator' && $match === FALSE) {
110
- if (file_exists(LANDINGPAGES_UPLOADS_PATH . "$name/config.php")) {
111
- include_once(LANDINGPAGES_UPLOADS_PATH . "$name/config.php");
112
- }
113
- }
114
- }
115
-
116
- }
117
-
118
- /**
119
- * Loads landing pages found in theme forlder
120
- *
121
- */
122
- public static function load_theme_privided_template_configurations() {
123
- global $lp_data;
124
-
125
- $template_ids = self::get_theme_provided_template_ids();
126
-
127
- /* loop through template ids and include their config file */
128
- foreach ($template_ids as $name) {
129
- if (file_exists(LANDINGPAGES_THEME_TEMPLATES_PATH . "$name/config.php")) {
130
- include_once(LANDINGPAGES_THEME_TEMPLATES_PATH . "$name/config.php");
131
- }
132
- }
133
-
134
- }
135
-
136
- /**
137
- * Gets array of landing page templates provided by WordPress theme
138
- *
139
- * @returns ARRAY $template_ids array of uploaded template ids
140
- */
141
- public static function get_theme_provided_template_ids() {
142
-
143
- $template_ids = array();
144
-
145
-
146
- if (!is_dir( LANDINGPAGES_THEME_TEMPLATES_PATH )) {
147
- return $template_ids;
148
- }
149
-
150
- $results = scandir(LANDINGPAGES_THEME_TEMPLATES_PATH);
151
-
152
- foreach ($results as $name) {
153
- if ($name === '.' or $name === '..' or $name === '__MACOSX') {
154
- continue;
155
- }
156
-
157
- if (is_dir(LANDINGPAGES_THEME_TEMPLATES_PATH . '/' . $name)) {
158
- $template_ids[] = $name;
159
- }
160
- }
161
-
162
- return $template_ids;
163
- }
164
-
165
- /**
166
- * Gets array of uploaded template paths
167
- *
168
- * @returns ARRAY $template_ids array of uploaded template ids
169
- */
170
- public static function get_uploaded_template_ids() {
171
- $template_ids = array();
172
-
173
- if (!is_dir(LANDINGPAGES_UPLOADS_PATH)) {
174
- wp_mkdir_p(LANDINGPAGES_UPLOADS_PATH);
175
- }
176
-
177
- $results = scandir(LANDINGPAGES_UPLOADS_PATH);
178
-
179
- foreach ($results as $name) {
180
- if ($name === '.' or $name === '..' or $name === '__MACOSX') {
181
- continue;
182
- }
183
-
184
- if (is_dir(LANDINGPAGES_UPLOADS_PATH . '/' . $name)) {
185
- $template_ids[] = $name;
186
- }
187
- }
188
-
189
- return $template_ids;
190
- }
191
-
192
- /**
193
- * Gets array of uploaded template paths
194
- *
195
- * @returns ARRAY $template_ids array of uploaded template ids
196
- */
197
- public static function get_core_template_ids() {
198
- $template_ids = array();
199
-
200
- $template_path = LANDINGPAGES_PATH . "/templates/";
201
- $results = scandir($template_path);
202
-
203
- /*scan through templates directory and pull in name paths */
204
- foreach ($results as $name) {
205
- if ($name === '.' or $name === '..' or $name === '__MACOSX') {
206
- continue;
207
- }
208
-
209
- if (is_dir($template_path . '/' . $name)) {
210
- $template_ids[] = $name;
211
- }
212
- }
213
-
214
- return $template_ids;
215
- }
216
-
217
- /**
218
- * Get's array of template categories from loaded templates
219
- *
220
- * @returns ARRAY $template_cats array if template categories
221
- */
222
- public static function get_template_categories() {
223
- $template_settings = self::get_extended_data();
224
-
225
- foreach ($template_settings as $key => $val) {
226
- if ($key == 'lp' || substr($key, 0, 4) == 'ext-' || isset($val['info']['data_type']) && $val['info']['data_type'] == 'metabox') {
227
- continue;
228
- }
229
-
230
- /* account for legacy data models */
231
- if (isset($val['category'])) {
232
- $cats = $val['category'];
233
- } else {
234
- if (isset($val['info']['category'])) {
235
- $cats = $val['info']['category'];
236
- }
237
- }
238
-
239
- $cats = explode(',', $cats);
240
-
241
- foreach ($cats as $cat_value) {
242
- $cat_value = trim($cat_value);
243
- $name = str_replace(array('-', '_'), ' ', $cat_value);
244
- $name = ucwords($name);
245
-
246
- if (!isset($template_cats[$cat_value])) {
247
- $template_cats[$cat_value]['count'] = 1;
248
- } else {
249
- $template_cats[$cat_value]['count']++;
250
- }
251
-
252
- $template_cats[$cat_value]['value'] = $cat_value;
253
- $template_cats[$cat_value]['label'] = "$name";
254
- }
255
- }
256
-
257
- return $template_cats;
258
- }
259
-
260
- /**
261
- * Get's template and extension setting data
262
- *
263
- * @retuns ARRAY of template & extension data
264
- */
265
- public static function get_extended_data() {
266
- global $lp_data;
267
-
268
- $lp_data = apply_filters('lp_extension_data', $lp_data);
269
-
270
- return $lp_data;
271
- }
272
-
273
-
274
- }
275
-
276
- /* Initialize Landing_Pages_Load_Extensions */
277
- new Landing_Pages_Load_Extensions;
278
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.metaboxes.php DELETED
@@ -1,1210 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class for rendering and storing data related to the landing-page CPT edit screen
5
- * @package LandingPages
6
- * @subpackage Management
7
- */
8
-
9
- class Landing_Pages_Metaboxes {
10
-
11
- static $current_vid;
12
- static $current_template;
13
- static $variations;
14
- static $is_new;
15
- static $is_clone;
16
- static $content_area;
17
-
18
- /**
19
- * initiate class
20
- */
21
- public function __construct() {
22
- self::add_hooks();
23
- }
24
-
25
- /**
26
- * load hooks and filters
27
- */
28
- public static function add_hooks() {
29
- add_action( 'admin_init' , array( __CLASS__ , 'run_actions' ) );
30
- add_action( 'admin_enqueue_scripts' , array( __CLASS__ , 'enqueue_scripts' ) );
31
- add_action( 'add_meta_boxes' , array( __CLASS__ , 'register_metaboxes' ) );
32
- add_action( 'edit_form_after_title', array( __CLASS__ , 'display_variations_nav_metabox' ) );
33
- add_action( 'edit_form_after_title', array( __CLASS__ , 'display_main_headline' ) );
34
- add_filter( 'enter_title_here', array( __CLASS__, 'filter_default_title_text' ) , 10, 2 );
35
- add_filter( 'wp_default_editor', array( __CLASS__ , 'filter_default_wysiwyg_view' ) );
36
-
37
- /* get selected template metabox html */
38
- add_action( 'wp_ajax_lp_get_template_meta' , array( __CLASS__ , 'ajax_get_template_metabox_html' ));
39
-
40
- /* hidden select template container */
41
- add_action('admin_notices', array( __CLASS__ , 'display_select_template_container' ) );
42
-
43
- /* save landing page */
44
- add_action('save_post', array( __CLASS__ , 'save_landing_page' ) );
45
-
46
- /* set wpseo priority to low */
47
- add_filter('wpseo_metabox_prio', array( __CLASS__ , 'set_wpseo_priority' ));
48
-
49
- }
50
-
51
- /**
52
- * Register metaboxes
53
- */
54
- public static function register_metaboxes() {
55
-
56
- global $post;
57
-
58
- if ( !isset($post) || $post->post_type!='landing-page') {
59
- return;
60
- }
61
-
62
-
63
- if($post->post_status !== 'draft') {
64
- add_meta_box(
65
- 'lp-thumbnail-sidebar-preview',
66
- __( 'Template Preview', 'landing-pages'),
67
- array( __CLASS__ , 'display_template_preview_metabox' ),
68
- 'landing-page' ,
69
- 'side',
70
- 'high'
71
- );
72
- }
73
-
74
-
75
- /* Add conversion area for default template */
76
- add_meta_box(
77
- 'lp_2_form_content',
78
- __('Insert Form / Conversion Content', 'landing-pages'),
79
- array( __CLASS__ , 'display_conversion_area_metabox' ),
80
- 'landing-page',
81
- 'normal',
82
- 'high'
83
- );
84
-
85
- /* Select Template Metbox */
86
- add_meta_box(
87
- 'lp_metabox_select_template', /* $id */
88
- __( 'Template Selection', 'landing-pages'),
89
- array( __CLASS__ , 'display_select_template' ),
90
- 'landing-page',
91
- 'normal',
92
- 'high'
93
- );
94
-
95
- /* Load Template Settings */
96
- $extension_data = Landing_Pages_Load_Extensions::get_extended_data();;
97
- $current_template = Landing_Pages_Variations::get_current_template($post->ID);
98
- foreach ($extension_data as $key => $data) {
99
-
100
- if ( $key != $current_template || ( isset($data['info']['data_type']) && strstr( $data['info']['data_type'] , 'acf') ) ) {
101
- continue;
102
- }
103
-
104
- $template_name = ucwords(str_replace('-', ' ', $key));
105
- $id = strtolower(str_replace(' ', '-', $key));
106
-
107
- add_meta_box(
108
- "lp_{$id}_custom_meta_box", /* $id */
109
- "<small>$template_name</small>",
110
- array( __CLASS__ , 'display_extended_metabox' ),
111
- 'landing-page', /* post-type */
112
- 'normal', /* $context */
113
- 'default',/* $priority */
114
- array('key' => $key)
115
- );
116
-
117
- }
118
-
119
-
120
- /* add custom css */
121
- add_meta_box(
122
- 'lp_3_custom_css',
123
- __( 'Custom CSS' , 'landing-pages') ,
124
- array( __CLASS__ , 'display_custom_css_metabox' ),
125
- 'landing-page',
126
- 'normal',
127
- 'low'
128
- );
129
-
130
- /* add custom js */
131
- add_meta_box(
132
- 'lp_3_custom_js',
133
- __('Custom JS' , 'landing-pages') ,
134
- array( __CLASS__ , 'display_custom_js_metabox' ),
135
- 'landing-page',
136
- 'normal',
137
- 'low'
138
- );
139
-
140
- /* add custom variation notes */
141
- add_meta_box(
142
- 'lp_4_variation_notes',
143
- __('Variation Notes' , 'landing-pages') ,
144
- array( __CLASS__ , 'display_variation_notes' ),
145
- 'landing-page',
146
- 'normal',
147
- 'low'
148
- );
149
-
150
- /* Add AB Testing Stats Box */
151
- add_meta_box(
152
- 'lp_ab_display_stats_metabox',
153
- __( 'A/B Testing', 'landing-pages'),
154
- array( __CLASS__ , 'display_quick_stats_metabox' ) ,
155
- 'landing-page' ,
156
- 'side',
157
- 'high'
158
- );
159
-
160
- /* discover extended metaboxes and render them */
161
- foreach ($extension_data as $key => $data) {
162
-
163
- if ( !isset( $data['info']['data_type']) || $data['info']['data_type'] != 'metabox') {
164
- continue;
165
- }
166
-
167
- $id = "metabox-" . $key;
168
-
169
- (isset($data['info']['label'])) ? $name = $data['info']['label'] : $name = ucwords(str_replace(array('-', 'ext '), ' ', $key) . " Extension Options");
170
- (isset($data['info']['position'])) ? $position = $data['info']['position'] : $position = "normal";
171
- (isset($data['info']['priority'])) ? $priority = $data['info']['priority'] : $priority = "default";
172
-
173
- add_meta_box(
174
- "lp_{$id}_custom_meta_box",
175
- $name,
176
- array( __CLASS__ , 'display_extended_metabox' ),
177
- 'landing-page',
178
- $position,
179
- $priority,
180
- array('key' => $key)
181
- );
182
- }
183
-
184
- /* Display short description */
185
- add_meta_box(
186
- 'postexcerpt',
187
- __('Short Description', 'landing-pages'),
188
- 'post_excerpt_meta_box',
189
- 'landing-page',
190
- 'normal',
191
- 'core'
192
- );
193
-
194
- /* Display conversion tracking helper */
195
- add_meta_box(
196
- 'lp_conversion_tracking',
197
- __('Additional Resources', 'landing-pages'),
198
- array( __CLASS__ , 'display_additional_resources' ),
199
- 'landing-page',
200
- 'normal',
201
- 'low'
202
- );
203
- }
204
-
205
- /**
206
- * Run administrative actions on landing page
207
- */
208
- public static function run_actions() {
209
-
210
- if (!isset($_GET['post'])) {
211
- return;
212
- }
213
-
214
- $post = get_post( $_GET['post'] );
215
-
216
- if ( !isset($post) || $post->post_type != 'landing-page') {
217
- return;
218
- }
219
-
220
-
221
- self::$current_vid = Landing_Pages_Variations::get_current_variation_id( $post->ID );
222
- self::$variations =Landing_Pages_Variations::get_variations( $post->ID );
223
-
224
- /*check for delete command */
225
- if (isset($_GET['ab-action']) && $_GET['ab-action'] == 'delete-variation') {
226
- Landing_Pages_Variations::delete_variation( $post->ID , intval($_REQUEST['action-variation-id']) );
227
- }
228
-
229
- /*check for pause command */
230
- if (isset($_GET['ab-action']) && $_GET['ab-action'] == 'pause-variation') {
231
- Landing_Pages_Variations::pause_variation( $post->ID , intval($_REQUEST['action-variation-id']) );
232
-
233
- }
234
-
235
- /*check for pause command */
236
- if (isset($_GET['ab-action']) && $_GET['ab-action'] == 'play-variation') {
237
- Landing_Pages_Variations::play_variation( $post->ID , intval($_REQUEST['action-variation-id']) );
238
- }
239
-
240
- self::$is_new = (isset($_GET['new-variation'])) ? 1 : 0;
241
- self::$is_clone = (isset($_GET['clone'])) ? $_GET['clone'] : null;
242
- self::$content_area = Landing_Pages_Variations::get_post_content( $post->ID );
243
-
244
- (isset($_GET['new-variation']) && $_GET['new-variation'] == 1) ? $new_variation = 1 : $new_variation = 0;
245
-
246
- /*if new variation and cloning then programatically prepare the next variation id */
247
- if (self::$is_new ) {
248
- $_SESSION['lp_ab_test_open_variation'] = Landing_Pages_Variations::prepare_new_variation_id( $post->ID );
249
- }
250
- }
251
-
252
-
253
- /**
254
- * Enqueue scripts
255
- */
256
- public static function enqueue_scripts( $hook ) {
257
-
258
- global $post;
259
- $screen = get_current_screen();
260
-
261
- if ( !isset($screen) || $screen->id != 'landing-page') {
262
- return;
263
- }
264
-
265
- wp_enqueue_script(array('jquery', 'jqueryui', 'editor', 'thickbox', 'media-upload'));
266
- wp_enqueue_style('edit-landing-page', LANDINGPAGES_URLPATH . 'assets/css/admin/edit-landing-page.css', array() , null);
267
- wp_enqueue_script('lp-js-metaboxes', LANDINGPAGES_URLPATH . 'assets/js/admin/admin.metaboxes.js', array() , null);
268
- wp_enqueue_script('jpicker', LANDINGPAGES_URLPATH . 'assets/libraries/jpicker/jpicker-1.1.6.min.js', array() , null);
269
- wp_localize_script( 'jpicker', 'jpicker', array( 'thispath' => LANDINGPAGES_URLPATH.'assets/libraries/jpicker/images/' ));
270
- wp_enqueue_style('jpicker-css', LANDINGPAGES_URLPATH . 'assets/libraries/jpicker/css/jPicker-1.1.6.min.css', array() , null);
271
-
272
- $template_data = Landing_Pages_Load_Extensions::get_extended_data();;
273
- $template_data_json = json_encode($template_data);
274
- $template = Landing_Pages_Variations::get_current_template( $post->ID );
275
- $params = array('selected_template'=>$template, 'templates'=>$template_data_json);
276
- wp_localize_script('lp-js-metaboxes', 'data', $params);
277
-
278
- /* if ACF load CSS to hide WordPress core elements */
279
- if ( isset($template_data[$template]['info']['data_type']) && strstr( $template_data[$template]['info']['data_type'] , 'acf')){
280
- wp_enqueue_style('lp-acf-template', LANDINGPAGES_URLPATH . 'assets/css/admin/acf-hide-wp-elements.css' , array() , null );
281
- }
282
-
283
- wp_enqueue_style('inbound-metaboxes', INBOUNDNOW_SHARED_URLPATH . 'assets/css/admin/inbound-metaboxes.css' , array() , null);
284
- wp_enqueue_script( 'lp-admin-clear-stats-ajax-request', LANDINGPAGES_URLPATH . 'assets/js/ajax.clearstats.js', array( 'jquery' ) , null );
285
- wp_localize_script( 'lp-admin-clear-stats-ajax-request', 'ajaxadmin', array( 'ajaxurl' => admin_url('admin-ajax.php'), 'lp_clear_nonce' => wp_create_nonce('lp-clear-nonce') ) );
286
-
287
- wp_enqueue_script('jquery-zoomer', LANDINGPAGES_URLPATH . 'assets/libraries/jquery.zoomer.js', array() , null);
288
- wp_enqueue_script('lp-post-edit-ui', LANDINGPAGES_URLPATH . 'assets/js/admin/admin.post-edit.js', array() , null);
289
- wp_localize_script( 'lp-post-edit-ui', 'lp_post_edit_ui', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'post_id' => $post->ID , 'wp_landing_page_meta_nonce' => wp_create_nonce('wp-landing-page-meta-nonce'), 'lp_template_nonce' => wp_create_nonce('lp-nonce') ) );
290
- wp_enqueue_style('admin-post-edit-css', LANDINGPAGES_URLPATH . 'assets/css/admin-post-edit.css', array() , null);
291
-
292
- /* Load FontAwesome */
293
- wp_register_style('font-awesome', INBOUNDNOW_SHARED_URLPATH.'assets/fonts/fontawesome/css/font-awesome.min.css', array() , null);
294
- wp_enqueue_style('font-awesome');
295
-
296
- /* Load Sweet Alert */
297
- wp_enqueue_script('sweet-alert', INBOUNDNOW_SHARED_URLPATH.'assets/includes/SweetAlert/sweetalert.min.js', array() , null);
298
- $localized = array(
299
- 'title' => __("Are you sure?","landing-pages"),
300
- 'text' => __("Are you sure you want to select this template?","landing-pages"),
301
- 'confirmButtonText' => __("Yes","landing-pages"),
302
- 'confirmTextTitle' => __("Deleted!","landing-pages"),
303
- 'confirmText' => __("Your imaginary file has been deleted.","landing-pages"),
304
- 'waitTitle' => __("Please wait","landing-pages"),
305
- 'waitText' => __("We are peparing your template now.","landing-pages"),
306
- 'waitImage' => INBOUNDNOW_SHARED_URLPATH .'assets/includes/SweetAlert/loading_colorful.gif'
307
- );
308
- wp_localize_script('sweet-alert', 'sweetalert', $localized );
309
- wp_enqueue_style('sweet-alert', INBOUNDNOW_SHARED_URLPATH.'assets/includes/SweetAlert/sweetalert.css', array() , null);
310
-
311
- wp_enqueue_style('lp-ab-testing-admin', LANDINGPAGES_URLPATH . 'assets/css/admin-ab-testing.css', array() , null);
312
- wp_enqueue_script('lp-ab-testing-admin', LANDINGPAGES_URLPATH . 'assets/js/admin/admin.post-edit-ab-testing.js', array('jquery') , null );
313
- wp_localize_script('lp-ab-testing-admin', 'variation', array('pid' => $post->ID , 'vid' => self::$current_vid, 'new_variation' => self::$is_new , 'variations' => self::$variations, 'content_area' => self::$content_area));
314
-
315
- /* enqueue supportive scripts */
316
- wp_enqueue_script( 'jquery-time-picker', LANDINGPAGES_URLPATH . 'assets/libraries/datetimepicker/jquery.datetimepicker.js', array('jquery') , null );
317
- wp_enqueue_style( 'jquery-time-picker', LANDINGPAGES_URLPATH . 'assets/libraries/datetimepicker/jquery.datetimepicker.css' , array() , null );
318
- wp_enqueue_script( 'jquery-date-picker', LANDINGPAGES_URLPATH . 'assets/libraries/datetimepicker/picker_functions.js', array('jquery') , null );
319
-
320
- /* only load these scripts and styles when creatng a new landing page */
321
- if ( $hook == 'post-new.php' ) {
322
- wp_enqueue_script('lp-js-create-new-lander', LANDINGPAGES_URLPATH . 'assets/js/admin/admin.post-new.js', array('jquery'), null, true );
323
- wp_localize_script( 'lp-js-create-new-lander', 'lp_post_new_ui', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'post_id' => $post->ID , 'wp_landing_page_meta_nonce' => wp_create_nonce('lp_nonce') , 'LANDINGPAGES_URLPATH' => LANDINGPAGES_URLPATH ) );
324
- wp_enqueue_style('lp-css-post-new', LANDINGPAGES_URLPATH . 'assets/css/admin-post-new.css' , array() , null);
325
- }
326
-
327
- if ( $hook == 'post.php' ) {
328
- /* change template sweet alert support */
329
- wp_enqueue_script('lp-change-template', LANDINGPAGES_URLPATH . 'assets/js/admin/admin.post.js', array('jquery'), null, true );
330
- }
331
- }
332
-
333
- /**
334
- * force wysiwyg eeditor to open in html mode
335
- * @return string
336
- */
337
- public static function filter_default_wysiwyg_view( $default ) {
338
- global $post;
339
- if ( !isset($post) || $post->post_type != 'landing-page' ) {
340
- return $default;
341
- }
342
-
343
- return 'html';
344
- }
345
-
346
-
347
- /**
348
- * change the default title placeholder text for landing pages
349
- * @param $text
350
- * @param $post
351
- * @return mixed
352
- */
353
- public static function filter_default_title_text( $text , $post ) {
354
- if ($post->post_type == 'landing-page') {
355
- return __( 'Enter Landing Page Description' , 'landing-pages');
356
- } else {
357
- return $text;
358
- }
359
- }
360
-
361
-
362
- /**
363
- * Display main headline
364
- */
365
- public static function display_main_headline() {
366
- global $post;
367
-
368
- if (!isset($post) || $post->post_type !='landing-page' ) {
369
- return;
370
- }
371
-
372
- $variation_id = Landing_Pages_Variations::get_current_variation_id( );
373
- $main_headline = Landing_Pages_Variations::get_main_headline( $post->ID , $variation_id );
374
-
375
- ?>
376
- <div id="main-title-area">
377
- <input type="text" name="<?php echo Landing_Pages_Variations::prepare_input_id( 'lp-main-headline'); ?>" placeholder="<?php _e('Enter Headline' , 'landing-pages'); ?>" id="lp-main-headline" value="<?php echo $main_headline; ?>" title="'. __('This headline will appear in the landing page template.' , 'landing-pages') .'">
378
- </div>
379
- <div id="switch-lp">0</div>
380
-
381
- <?php
382
- /* Frontend params */
383
- if(isset($_REQUEST['frontend']) && $_REQUEST['frontend'] == 'true') {
384
- echo('<input type="hidden" name="frontend" id="frontend-on" value="true" />');
385
- }
386
-
387
- }
388
- /**
389
- * dipslay select template metabox
390
- */
391
- public static function display_select_template() {
392
- global $post;
393
-
394
- $template = Landing_Pages_Variations::get_current_template( $post->ID );
395
-
396
- $name = Landing_Pages_Variations::prepare_input_id( 'lp-selected-template' );
397
-
398
- /* Use nonce for verification */
399
- echo "<input type='hidden' name='lp_lp_custom_fields_nonce' value='".wp_create_nonce('lp-nonce')."' />";
400
- ?>
401
-
402
- <div id="lp_template_change"><h2>
403
- <a class="button" id="lp-change-template-button"><?php _e( 'Choose Another Template' , 'landing-pages'); ?></a>
404
- </div>
405
- <input type='hidden' id='lp_select_template' name='<?php echo $name; ?>' value='<?php echo $template; ?>'>
406
- <div id="template-display-options">
407
-
408
- </div>
409
-
410
- <?php
411
- }
412
-
413
- /**
414
- * Display variation tabs
415
- */
416
- public static function display_variations_nav_metabox() {
417
- global $post;
418
-
419
- global $post;
420
-
421
- if ( !isset($post) || $post->post_type!='landing-page') {
422
- return;
423
- }
424
-
425
- $current_variation_id = Landing_Pages_Variations::get_current_variation_id($post->ID);
426
-
427
- echo "<input type='hidden' id='open_variation' value='{$current_variation_id}'>";
428
- echo "<input type='hidden' name='lp-variation-id' id='lp-variation-id' value='{$current_variation_id}'>";
429
-
430
- $variations = Landing_Pages_Variations::get_variations($post->ID);
431
- $new_variation_id = Landing_Pages_Variations::prepare_new_variation_id($post->ID);
432
-
433
- if ($current_variation_id > 0 || self::$is_new ) {
434
- $first_class = 'inactive';
435
- } else {
436
- $first_class = 'active';
437
- }
438
-
439
- echo '<h2 class="nav-tab-wrapper a_b_tabs">';
440
-
441
- foreach ($variations as $i => $vid) {
442
- $letter = Landing_Pages_Variations::vid_to_letter( $post->ID , $i);
443
- $pre = ($i < 1) ? __('Version ', 'landing-pages') : '';
444
-
445
- if ($current_variation_id == $vid && !isset($_GET['new-variation'])) {
446
- $cur_class = 'active';
447
- } else {
448
- $cur_class = 'inactive';
449
- }
450
- $permalink = get_permalink($post->ID) . '?' . '&lp-variation-id=' . $vid ;
451
- echo '<a href="?post=' . $post->ID . '&lp-variation-id=' . $vid . '&action=edit" class="lp-nav-tab nav-tab nav-tab-special-' . $cur_class . '" data-permalink="'.$permalink.'" id="tabs-add-variation" target="_parent">' . $pre . $letter . '</a>';
452
- }
453
-
454
- if (!isset($_GET['new-variation'])) {
455
- echo '<a href="?post=' . $post->ID . '&lp-variation-id=' . $new_variation_id . '&action=edit&new-variation=1" class="lp-nav-tab nav-tab nav-tab-special-inactive nav-tab-add-new-variation" id="tabs-add-variation">' . __('Add New Variation', 'landing-pages') . '</a>';
456
- } else {
457
- $variation_count = $i + 1;
458
- $letter = Landing_Pages_Variations::vid_to_letter( $post->ID, $variation_count);
459
- echo '<a href="?post=' . $post->ID . '&lp-variation-id=' . $new_variation_id . '&action=edit" class="lp-nav-tab nav-tab nav-tab-special-active" id="tabs-add-variation">' . $letter . '</a>';
460
- }
461
- $edit_link = (isset($_GET['lp-variation-id'])) ? '?lp-variation-id=' . $_GET['lp-variation-id'] . '' : '?lp-variation-id=0';
462
- $post_link = get_permalink($post->ID);
463
- $post_link = preg_replace('/\?.*/', '', $post_link);
464
- echo "<a rel='" . $post_link . "' id='launch-visual-editer' class='button-primary new-save-lp-frontend' href='$post_link$edit_link&inbound-customizer=on'>" . __('Launch Visual Editor', 'landing-pages') . "</a>";
465
- echo '</h2>';
466
-
467
-
468
- }
469
-
470
- /**
471
- * Displays quick stats metabox
472
- */
473
- public static function display_quick_stats_metabox() {
474
- global $post;
475
- $variations = Landing_Pages_Variations::get_variations($post->ID);
476
-
477
- ?>
478
- <div>
479
-
480
- <style type="text/css">
481
-
482
- </style>
483
- <div class="inside" id="a-b-testing">
484
-
485
- <div id="stat-box">
486
- <?php
487
-
488
- if (isset($_GET['new_meta_key']) && is_numeric($_GET['new_meta_key']) ) {
489
- ?>
490
- <script type="text/javascript">
491
- jQuery(document).ready(function($) {
492
- /* This fixes meta data saves for cloned pages */
493
- function isNumber (o) {
494
- return ! isNaN (o-0) && o !== null && o !== "" && o !== false;
495
- }
496
- var new_meta_key = "<?php echo $_GET['new_meta_key'];?>";
497
- jQuery('#template-display-options input[type=text], #template-display-options select, #template-display-options input[type=radio], #template-display-options textarea').each(function(){
498
- var this_id = jQuery(this).attr("id");
499
- var final_number = this_id.match(/[^-]+$/g);
500
- var new_id = this_id.replace(/[^-]+$/g, new_meta_key);
501
- var is_number = isNumber(final_number);
502
-
503
- if (is_number === false) {
504
- jQuery(this).attr("id", this_id + "-" + new_meta_key);
505
- jQuery(this).attr("name", this_id + "-" + new_meta_key);
506
- } else {
507
- jQuery(this).attr("id", new_id);
508
- jQuery(this).attr("name", new_id);
509
- }
510
- });
511
- });
512
- </script>
513
- <?php
514
- }
515
-
516
- $howmany = count($variations);
517
-
518
- foreach ($variations as $key => $vid) {
519
-
520
-
521
- $variation_status = Landing_Pages_Variations::get_variation_status($post->ID, $vid);
522
- $variation_status_class = ($variation_status == 1) ? "variation-on" : 'variation-off';
523
-
524
- $permalink = Landing_Pages_Variations::get_variation_permalink($post->ID, $vid);
525
-
526
- $impressions = Landing_Pages_Variations::get_impressions($post->ID, $vid);
527
- $conversions = Landing_Pages_Variations::get_conversions($post->ID, $vid);
528
- $conversion_rate = Landing_Pages_Variations::get_conversion_rate($post->ID, $vid);
529
- $title = Landing_Pages_Variations::get_main_headline($post->ID, $vid);
530
-
531
- ?>
532
-
533
- <div id="lp-variation-<?php echo Landing_Pages_Variations::vid_to_letter( $post->ID , $key); ?>"
534
- class="variation-row <?php echo $variation_status_class; ?>">
535
- <div class='varation-header'>
536
- <span class='variation-name'><?php _e('Variation', 'landing-pages'); ?> <span
537
- class='stat-letter'><?php echo Landing_Pages_Variations::vid_to_letter( $post->ID , $key); ?></span>
538
- <?php
539
- if ($variation_status != 1) {
540
- ?>
541
- <span class='is-paused'>(<?php _e('Paused', 'landing-pages') ?>)</span>
542
- <?php
543
- }
544
- ?>
545
- </span>
546
-
547
- <span class="settings_icon"> </span>
548
- <span class="settings_wrapper">
549
- <span class="settings_wrapper_heading">Variation Settings</span>
550
- <ul class="settings_list_li">
551
- <li class="settings_edit">
552
- <span class='stat-menu-edit'>
553
- <a title="<?php _e('Edit this variation', 'landing-pages'); ?>" href='?post=<?php echo $post->ID; ?>&action=edit&action-variation-id=<?php echo $vid; ?>'>
554
- <?php _e('Edit', 'landing-pages'); ?>
555
- </a>
556
- </span>
557
- </li>
558
- <li class="settings_preview">
559
- <span class='stat-menu-preview'>
560
- <a title="<?php _e('Preview this variation', 'landing-pages'); ?>" class='thickbox' href='<?php echo $permalink; ?>&iframe_window=on&post_id=<?php echo $post->ID; ?>&TB_iframe=true&width=1503&height=467' target='_blank'>
561
- <?php _e('Preview', 'landing-pages'); ?>
562
- </a>
563
- </span>
564
- </li>
565
- <li class="settings_clone">
566
- <span class='stat-menu-clone'>
567
- <a title="<?php _e('Clone this variation', 'landing-pages'); ?>" href='?post=<?php echo $post->ID; ?>&action=edit&new-variation=1&clone=<?php echo $vid; ?>&new_meta_key=<?php echo $howmany; ?>'>
568
- <?php _e('Clone', 'landing-pages'); ?>
569
- </a>
570
- </span>
571
- </li>
572
- <li class="settings_delete">
573
- <span class='stat-control-delete'>
574
- <a title="<?php _e('Delete this variation', 'landing-pages'); ?>" href='?post=<?php echo $post->ID; ?>&action=edit&action-variation-id=<?php echo $vid; ?>&ab-action=delete-variation'>
575
- <?php _e('Delete', 'landing-pages'); ?>
576
- </a>
577
- </span>
578
- </li>
579
- <li class="settings_clearstat">
580
- <!-- CLEAR STATS START -->
581
- <span class="lp-delete-var-stats" data-letter='<?php echo Landing_Pages_Variations::vid_to_letter( $post->ID , $key); ?>' data-vid='<?php echo $vid; ?>' rel='<?php echo $post->ID; ?>' title="<?php _e('Delete this variations stats', 'landing-pages'); ?>">
582
- <?php _e('Clear Stats', 'landing-pages'); ?>
583
- </span>
584
- <!-- CLEAR STAT END --></li>
585
- </ul>
586
- </span>
587
-
588
-
589
-
590
- <!-- PAUSE START -->
591
- <span class='stat-control-pause'><a title="<?php _e('Pause this variation', 'landing-pages'); ?>"
592
- href='?post=<?php echo $post->ID; ?>&action=edit&action-variation-id=<?php echo $vid; ?>&ab-action=pause-variation'> </a></span>
593
- <!-- PAUSE END -->
594
-
595
- <!-- PLAY START -->
596
- <span class='stat-seperator pause-sep'>|</span>
597
- <span class='stat-control-play'><a
598
- title="<?php _e('Turn this variation on', 'landing-pages'); ?>"
599
- href='?post=<?php echo $post->ID; ?>&action=edit&action-variation-id=<?php echo $vid; ?>&ab-action=play-variation'> </a></span>
600
- <!-- PLAY END -->
601
-
602
-
603
-
604
- </div>
605
- <div class="stat-row">
606
- <div class='stat-stats' colspan='2'>
607
- <div class='stat-container-impressions number-box'>
608
- <span class="stat-id"><?php _e('Views', 'landing-pages'); ?> </span>
609
- <span class='stat-span-impressions'><?php echo $impressions; ?></span>
610
- </div>
611
- <div class='stat-container-conversions number-box'>
612
- <span class="stat-id"><?php _e('Conversions', 'landing-pages'); ?></span> <span class='stat-span-conversions'><?php echo $conversions; ?></span>
613
- </span>
614
- </div>
615
- <div class='stat-container-conversion_rate number-box'>
616
- <span class="stat-id rate"><?php _e('Conversion Rate', 'landing-pages'); ?></span>
617
- <span class='stat-span-conversion_rate'><?php echo $conversion_rate; ?></span>
618
- </div>
619
-
620
- </div>
621
- </div>
622
- <div class="stat-row">
623
-
624
- <div class='stat-menu-container'>
625
-
626
- <?php do_action('lp_ab_testing_stats_menu_post'); ?>
627
-
628
- </div>
629
- </div>
630
- </div>
631
- <?php
632
-
633
- }
634
- ?>
635
- </div>
636
-
637
- </div>
638
- </div>
639
- <?php
640
- }
641
-
642
- /**
643
- * Display conversion area metabox
644
- */
645
- public static function display_conversion_area_metabox(){
646
-
647
- global $post;
648
-
649
- $meta_box_id = 'lp_2_form_content';
650
- $editor_id = 'landing-page-myeditor';
651
-
652
- /* Add CSS & jQuery to make this work like the original WYSIWYG */
653
- echo "
654
- <style type='text/css'>
655
- #$meta_box_id #edButtonHTML, #$meta_box_id #edButtonPreview {background-color: #F1F1F1; border-color: #DFDFDF #DFDFDF #CCC; color: #999;}
656
- #$editor_id{width:100%;}
657
- #$meta_box_id #editorcontainer{background:#fff !important;}
658
- #$meta_box_id #editor_id_fullscreen{display:none;}
659
- </style>
660
-
661
- <script type='text/javascript'>
662
- jQuery(function($){
663
- jQuery('#lp_2_form_content #editor-toolbar > a').click(function(){
664
- jQuery('#$meta_box_id #editor-toolbar > a').removeClass('active');
665
- jQuery(this).addClass('active');
666
- });
667
-
668
- if(jQuery('#lp_2_form_content #edButtonPreview').hasClass('active')){
669
- jQuery('#$meta_box_id #ed_toolbar').hide();
670
- }
671
-
672
- jQuery('#lp_2_form_content #edButtonPreview').click(function(){
673
- jQuery('#$meta_box_id #ed_toolbar').hide();
674
- });
675
-
676
- jQuery('#lp_2_form_content #edButtonHTML').click(function(){
677
- jQuery('#$meta_box_id #ed_toolbar').show();
678
- });
679
-
680
- /*Tell the uploader to insert content into the correct WYSIWYG editor */
681
- jQuery('#media-buttons a').bind('click', function(){
682
- var customEditor = jQuery(this).parents('#$meta_box_id');
683
- if(customEditor.length > 0){
684
- edCanvas = document.getElementById('$editor_id');
685
- }
686
- else{
687
- edCanvas = document.getElementById('content');
688
- }
689
- });
690
- });
691
- </script>
692
- ";
693
-
694
- /*Create The Editor */
695
- $conversion_area = Landing_Pages_Variations::get_conversion_area( $post->ID );
696
- wp_editor($conversion_area, $editor_id);
697
-
698
- /*Clear The Room! */
699
- echo "<div style='clear:both; display:block;'></div>";
700
- echo "<div style='width:100%;text-align:right;margin-top:11px;'><div class='lp_tooltip' title=\"". __('To help track conversions Landing Pages Plugin will automatically add a tracking class to forms. If you would like to track a link add this class to it' , 'landing-pages') ." class='inbound-track-link'\" ></div></div>";
701
-
702
- }
703
-
704
- /**
705
- * Display custom CSS metabox
706
- */
707
- public static function display_custom_css_metabox() {
708
- global $post;
709
-
710
- echo sprintf(
711
- __('%sCustom CSS may be required to customize this landing page.%s%s %sFormat%s: #element-id { display:none !important; }%s' , 'landing-pages') ,
712
- '<em>' , '</em>' , '<strong>' , '<u>' , '</u>' ,'</strong>'
713
- );
714
-
715
- $custom_css_name = Landing_Pages_Variations::prepare_input_id( 'lp-custom-css' );
716
- $custom_css = Landing_Pages_Variations::get_custom_css( $post->ID );
717
- echo '<textarea name="'.$custom_css_name.'" id="lp-custom-css" rows="5" cols="30" style="width:100%;">'. $custom_css .'</textarea>';
718
- }
719
-
720
- /**
721
- * Display custom JS metabox
722
- */
723
- public static function display_custom_js_metabox() {
724
- global $post;
725
-
726
- $custom_js_name = Landing_Pages_Variations::prepare_input_id( 'lp-custom-js' );
727
- $custom_js = Landing_Pages_Variations::get_custom_js( $post->ID );
728
-
729
- echo '<textarea name="'.$custom_js_name.'" id="lp_custom_js" rows="5" cols="30" style="width:100%;">'.$custom_js.'</textarea>';
730
- }
731
-
732
- /**
733
- * Display variation notes metabox
734
- */
735
- public static function display_variation_notes() {
736
- global $post;
737
-
738
- $variation_id = Landing_Pages_Variations::get_current_variation_id( );
739
- $variation_notes = Landing_Pages_Variations::get_variation_notes( $post->ID , $variation_id );
740
- $variation_notes_id = Landing_Pages_Variations::prepare_input_id( 'lp-variation-notes');
741
-
742
- echo '<textarea name="'.$variation_notes_id.'" id="lp_variation_notes" rows="5" cols="30" style="width:100%;">'.$variation_notes.'</textarea>';
743
- }
744
-
745
- /**
746
- * Display select template container
747
- */
748
- public static function display_select_template_container() {
749
- global $post;
750
-
751
-
752
- if (!isset($post) || $post->post_type != 'landing-page') {
753
- return false;
754
- }
755
-
756
- $screen = get_current_screen();
757
-
758
- $toggle = ($screen->parent_file != 'edit.php?post_type=landing-page' || $screen->action != 'add') ? "display:none" : "";
759
-
760
- $extension_data = Landing_Pages_Load_Extensions::get_extended_data();;
761
- $extension_data_cats = Landing_Pages_Load_Extensions::get_template_categories();
762
-
763
- unset($extension_data['lp']);
764
-
765
- ksort($extension_data_cats);
766
- $uploads = wp_upload_dir();
767
- $uploads_path = $uploads['basedir'];
768
- $extended_path = $uploads_path . '/landing-pages/templates/';
769
-
770
- self::$current_template = Landing_Pages_Variations::get_current_template($post->ID);
771
-
772
- echo "<div class='lp-template-selector-container' style='{$toggle}'>";
773
- echo "<div class='lp-selection-heading'>";
774
- echo "<h1>" . __('Select Your Landing Page Template!', 'landing-pages') . "</h1>";
775
- echo '<a class="button-secondary" style="display:none;" id="lp-cancel-selection">' . __('Cancel Template Change', 'landing-pages') . '</a>';
776
- echo "</div>";
777
- echo '<ul id="template-filter" >';
778
- echo '<li class="button-primary button"><a href="#" data-filter=".template-item-boxes">' . __('All', 'landing-pages') . '</a></li>';
779
- echo '<li class="button-primary button"><a href="#" data-filter=".theme">' . __('Theme', 'landing-pages') . '</a></li>';
780
- $categories = array('Theme');
781
- foreach ($extension_data_cats as $cat) {
782
-
783
- $slug = str_replace(' ', '-', $cat['value']);
784
- $slug = strtolower($slug);
785
- $cat['value'] = ucwords($cat['value']);
786
- if (!in_array($cat['value'], $categories)) {
787
- echo '<li class="button"><a href="#" data-filter=".' . $slug . '">' . $cat['value'] . '</a></li>';
788
- $categories[] = $cat['value'];
789
- }
790
-
791
- }
792
- echo "</ul>";
793
- echo '<div id="templates-container" >';
794
-
795
- foreach ($extension_data as $this_extension => $data) {
796
-
797
- if (substr($this_extension, 0, 4) == 'ext-') {
798
- continue;
799
- }
800
-
801
- if (isset($data['info']['data_type']) && $data['info']['data_type'] == 'metabox') {
802
- continue;
803
- }
804
-
805
-
806
- $cats = explode(',', $data['info']['category']);
807
- foreach ($cats as $key => $cat) {
808
- $cat = (is_array($cat)) ? implode(',',$cat) : $cat;
809
- $cat = ($cat) ? trim($cat) : '';
810
- $cat = str_replace(' ', '-', $cat);
811
- $cats[$key] = trim(strtolower($cat));
812
- }
813
-
814
- $cat_slug = implode(' ', $cats);
815
-
816
- $thumb = false;
817
- /* Get Thumbnail */
818
- if (file_exists(LANDINGPAGES_PATH . 'templates/' . $this_extension . "/thumbnail.png")) {
819
- if ($this_extension == 'default') {
820
- $thumbnail = get_template_directory() . "/screenshot.png";
821
- if (file_exists($thumbnail)) {
822
- $thumbnail = get_bloginfo('template_directory') . "/screenshot.png";
823
- $thumb = true;
824
- }
825
- } else {
826
- $thumbnail = LANDINGPAGES_URLPATH . 'templates/' . $this_extension . "/thumbnail.png";
827
- $thumb = true;
828
- }
829
-
830
- }
831
-
832
- if (file_exists(LANDINGPAGES_UPLOADS_PATH . $this_extension . "/thumbnail.png")) {
833
- $thumbnail = LANDINGPAGES_UPLOADS_URLPATH . $this_extension . "/thumbnail.png";
834
- $thumb = true;
835
- }
836
-
837
- if (file_exists(LANDINGPAGES_UPLOADS_PATH . $this_extension . "/thumbnail.jpg")) {
838
- $thumbnail = LANDINGPAGES_UPLOADS_URLPATH . $this_extension . "/thumbnail.jpg";
839
- $thumb = true;
840
- }
841
-
842
- if (!$thumb) {
843
- $thumbnail = LANDINGPAGES_URLPATH . 'templates/default/thumbnail.png';
844
- }
845
-
846
- $demo_link = (isset($data['info']['demo'])) ? $data['info']['demo'] : '';
847
- ?>
848
- <div id='template-item' class="<?php echo $cat_slug; ?> template-item-boxes">
849
- <div id="template-box">
850
- <div class="lp_tooltip_templates" title="<?php echo $data['info']['description']; ?>"></div>
851
- <a class='lp_select_template' href='#' label='<?php echo $data['info']['label']; ?>'
852
- id='<?php echo $this_extension; ?>'>
853
- <img src="<?php echo $thumbnail; ?>" class='template-thumbnail'
854
- alt="<?php echo $data['info']['label']; ?>" id='lp_<?php echo $this_extension; ?>'>
855
- </a>
856
-
857
- <p>
858
-
859
- <div id="template-title"><?php echo $data['info']['label']; ?></div>
860
- <a href='#' label='<?php echo $data['info']['label']; ?>' id='<?php echo $this_extension; ?>'
861
- class='lp_select_template'><?php _e('Select', 'landing-pages'); ?></a> |
862
- <a class='<?php echo $cat_slug;?>' target="_blank" href='<?php echo $demo_link;?>'
863
- id='lp_preview_this_template'><?php _e('Preview', 'landing-pages'); ?></a>
864
- </p>
865
- </div>
866
- </div>
867
- <?php
868
- }
869
- echo '</div>';
870
- echo "<div class='clear'></div>";
871
- echo "</div>";
872
- echo "<div style='display:none;' class='currently_selected'>" . __('This is Currently Selected', 'landing-pages') . "</a></div>";
873
- }
874
-
875
- /**
876
- * Display template preview metabox
877
- */
878
- public static function display_template_preview_metabox() {
879
- global $post;
880
-
881
- $template = Landing_Pages_Variations::get_current_template( $post->ID );
882
- $permalink = Landing_Pages_Variations::get_variation_permalink( $post->ID );
883
-
884
- $datetime = the_modified_date('YmjH',null,null,false);
885
- $permalink = add_query_arg( array( 'dt' => $datetime , 'dont_save' => true ) , $permalink );
886
- ?>
887
-
888
- <style type="text/css">
889
- <?php
890
- /* hide featured image slot if not default template */
891
- if ($template != 'default' ) {
892
- echo '#postimagediv {display:none;}';
893
- }
894
-
895
- ?>
896
- #lp-thumbnail-sidebar-preview {
897
- background: transparent !important;
898
- }
899
- #lp-thumbnail-sidebar-preview .handlediv, #lp-thumbnail-sidebar-preview .hndle {
900
- display: none !important;
901
- }
902
- #lp-thumbnail-sidebar-preview .inside {
903
- padding: 0px !important;
904
-
905
- border: none !important;
906
- margin-top: -33px !important;
907
- margin-bottom: -10px;
908
- overflow:hidden;
909
- }
910
- #lp-thumbnail-sidebar-preview .zoomer-wrapper {
911
- vertical-align: top;
912
- margin-top:33px !important;
913
- }
914
- #lp-thumbnail-sidebar-preview iframe#zoomer {
915
- margin-top: -30px;
916
- }
917
- </style>
918
- <?php
919
-
920
- if (isset($_GET['new-variation'])) {
921
- return;
922
- }
923
- if( isset($_GET['inbound-editor']) && $_GET['inbound-editor'] !== true ) {
924
- return;
925
- }
926
- // default
927
- echo "<iframe src='$permalink' id='zoomer'></iframe>";
928
-
929
- }
930
-
931
-
932
- /**
933
- * generate metabox html from extended dataset
934
- */
935
- public static function display_extended_metabox( $post , $args) {
936
-
937
- $extension_data = Landing_Pages_Load_Extensions::get_extended_data();;
938
-
939
- $key = $args['args']['key'];
940
-
941
- if (!isset( $extension_data[$key]['settings'] ) ) {
942
- return;
943
- }
944
-
945
- self::render_fields($key , $extension_data[$key]['settings'] , $post);
946
- }
947
-
948
-
949
- /**
950
- * Display additional documentaiton metabox
951
- */
952
- public static function display_additional_resources() {
953
- global $post;
954
-
955
- $variation_id = Landing_Pages_Variations::get_current_variation_id();
956
- $salt = md5( $post->ID . AUTH_KEY );
957
- ?>
958
- <div>
959
- <table style='width:100%'>
960
- <tr>
961
- <td style='width:22%'>
962
- <?php _e( 'Conversion Shortcode' , 'inbound-pro' ); ?>
963
- </td>
964
- <td>
965
- <input type='text' style='width:95%;display:inline;' readonly='readonly' value="[landing-page-conversion id='<?php echo $post->ID; ?>' vid='<?php echo $variation_id; ?>']">
966
- <div class="lp_tooltip" title="<?php _e( 'Instead of depending on Inbound Forms or tracked clicks for conversion tracking, enter this shortcode into your final destination page to manually increment this variation\'s conversion count' , 'landing-page' ); ?>" ><i class="fa fa-question-circle"></i></div>
967
- </td>
968
- </tr>
969
- <tr>
970
- <td>
971
- <?php _e( 'Conversion Callback URL' , 'inbound-pro' ); ?>
972
- </td>
973
- <td>
974
- <input type='text' style='width:95%;display:inline;' readonly='readonly' value="<?php echo add_query_arg( array( 'postback'=>'true' , 'event' => 'lp_conversion' , 'id' => $post->ID , 'vid' => $variation_id , 'salt' => $salt ) , site_url()) ?>">
975
- <div class="lp_tooltip" title="<?php _e( 'If you would like to use a thrid party event to record a conversion you can use this cusomized callback URL.' , 'landing-page' ); ?>" ><i class="fa fa-question-circle"></i></div>
976
- </td>
977
- </tr>
978
- </table>
979
- </div>
980
- <?php
981
- }
982
-
983
-
984
- /**
985
- * Renders metabox html
986
- * @param STRING $key data key
987
- * @param ARRAY $custom_fields field data
988
- */
989
- public static function render_fields($key, $custom_fields, $post) {
990
-
991
- /* Use nonce for verification */
992
- echo "<input type='hidden' name='lp_{$key}_custom_fields_nonce' value='" . wp_create_nonce('lp-nonce') . "' />";
993
-
994
- /* Begin the field table and loop */
995
- echo '<div class="form-table" id="inbound-meta">';
996
-
997
- foreach ($custom_fields as $field) {
998
-
999
- $field_id = Landing_Pages_Variations::prepare_input_id( $key . "-" . $field['id'] );
1000
- $field_name = $field['id'];
1001
- $label_class = $field['id'] . "-label";
1002
- $type_class = " inbound-" . $field['type'];
1003
- $type_class_row = " inbound-" . $field['type'] . "-row";
1004
- $type_class_option = " inbound-" . $field['type'] . "-option";
1005
- $option_class = (isset($field['class'])) ? $field['class'] : '';
1006
-
1007
- $ink = get_option('lp-license-keys-' . $key);
1008
- $status = get_option('lp_license_status-' . $key);
1009
- $status_test = (isset($status) && $status != "") ? $status : 'inactive';
1010
-
1011
- $meta = Landing_Pages_Variations::get_setting_value( $key . "-" . $field['id'] , $post->ID , null, $field['default'] );
1012
-
1013
- /* Remove prefixes on global => true template options */
1014
- if (isset($field['global']) && $field['global'] === true) {
1015
- $field_id = $field_name;
1016
- $meta = get_post_meta($post->ID, $field_name, true);
1017
- }
1018
-
1019
- /* begin a table row with */
1020
- echo '<div class="' . $field['id'] . $type_class_row . ' div-' . $option_class . ' wp-call-to-action-option-row inbound-meta-box-row">';
1021
-
1022
- if ($field['type'] != "description-block" && $field['type'] != "custom-css") {
1023
- echo '<div id="inbound-' . $field_id . '" data-actual="' . $field_id . '" class="inbound-meta-box-label wp-call-to-action-table-header ' . $label_class . $type_class . '"><label for="' . $field_id . '">' . $field['label'] . '</label></div>';
1024
- }
1025
-
1026
- echo '<div class="wp-call-to-action-option-td inbound-meta-box-option ' . $type_class_option . '" data-field-type="' . $field['type'] . '">';
1027
- switch ($field['type']) {
1028
- case 'description-block':
1029
- echo '<div id="' . $field_id . '" class="description-block">' . $field['description'] . '</div>';
1030
- break;
1031
- case 'custom-css':
1032
- echo '<style type="text/css">' . $field['default'] . '</style>';
1033
- break;
1034
- /* text */
1035
- case 'colorpicker':
1036
- if (!$meta) {
1037
- $meta = $field['default'];
1038
- }
1039
- $var_id = (isset($_GET['new_meta_key'])) ? "-" . $_GET['new_meta_key'] : '';
1040
- echo '<input type="text" class="jpicker" style="background-color:#' . $meta . '" name="' . $field_id . '" id="' . $field_id . '" value="' . $meta . '" size="5" /><span class="button-primary new-save-lp" data-field-type="text" id="' . $field_id . $var_id . '" style="margin-left:10px; display:none;">Update</span>
1041
- <div class="lp_tooltip tool_color" title="' . $field['description'] . '"></div>';
1042
- break;
1043
- case 'datepicker':
1044
- echo '<div class="jquery-date-picker inbound-datepicker" id="date-picking" data-field-type="text">
1045
- <span class="datepair" data-language="javascript">
1046
- Date: <input type="text" id="date-picker-' . $key . '" class="date start" /></span>
1047
- Time: <input id="time-picker-' . $key . '" type="text" class="time time-picker" />
1048
- <input type="hidden" name="' . $field_id . '" id="' . $field_id . '" value="' . $meta . '" class="new-date" value="" >
1049
- <p class="description">' . $field['description'] . '</p>
1050
- </div>';
1051
- break;
1052
- case 'text':
1053
- echo '<input type="text" name="' . $field_id . '" id="' . $field_id . '" value="' . $meta . '" size="30" />
1054
- <div class="lp_tooltip" title="' . $field['description'] . '"></div>';
1055
- break;
1056
- case 'number':
1057
-
1058
- echo '<input type="number" class="' . $option_class . '" name="' . $field_id . '" id="' . $field_id . '" value="' . $meta . '" size="20" ' . (isset($field['min']) ? 'min="'.$field['min'].'"' : '' ) . ' ' . (isset($field['max']) ? 'max="'.$field['max'].'"' : '' ) . ' ' . (isset($field['step']) ? 'step="'.$field['step'].'"' : '' ) . '/>
1059
- <div class="lp_tooltip" title="' . $field['description'] . '"></div>';
1060
-
1061
- break;
1062
- /* textarea */
1063
- case 'textarea':
1064
- echo '<textarea name="' . $field_id . '" id="' . $field_id . '" cols="106" rows="6" style="width: 75%;">' . $meta . '</textarea>
1065
- <div class="lp_tooltip tool_textarea" title="' . $field['description'] . '"></div>';
1066
- break;
1067
- /* wysiwyg */
1068
- case 'wysiwyg':
1069
- echo "<div class='iframe-options iframe-options-" . $field_id . "' id='" . $field['id'] . "'>";
1070
- wp_editor($meta, $field_id, $settings = array('editor_class' => $field_name));
1071
- echo '<p class="description">' . $field['description'] . '</p></div>';
1072
- break;
1073
- /* media */
1074
- case 'media':
1075
- /*echo 1; exit; */
1076
- echo '<label for="upload_image" data-field-type="text">';
1077
- echo '<input name="' . $field_id . '" id="' . $field_id . '" type="text" size="36" name="upload_image" value="' . $meta . '" />';
1078
- echo '<input data-field-id="' . $field_id . '" class="upload_image_button" id="uploader_' . $field_id . '" type="button" value="'.__('Upload Image' , 'inbound-pro' ) .'" />';
1079
- echo '<p class="description">' . $field['description'] . '</p>';
1080
- break;
1081
- /* checkbox */
1082
- case 'checkbox':
1083
- $i = 1;
1084
- echo "<table class='lp_check_box_table'>";
1085
- if (!isset($meta)) {
1086
- $meta = array();
1087
- } elseif (!is_array($meta)) {
1088
- $meta = array($meta);
1089
- }
1090
- foreach ($field['options'] as $value => $label) {
1091
- if ($i == 5 || $i == 1) {
1092
- echo "<tr>";
1093
- $i = 1;
1094
- }
1095
- echo '<td data-field-type="checkbox"><input type="checkbox" name="' . $field_id . '[]" id="' . $field_id . '" value="' . $value . '" ', in_array($value, $meta) ? ' checked="checked"' : '', '/>';
1096
- echo '<label for="' . $value . '">&nbsp;&nbsp;' . $label . '</label></td>';
1097
- if ($i == 4) {
1098
- echo "</tr>";
1099
- }
1100
- $i++;
1101
- }
1102
- echo "</table>";
1103
- echo '<div class="lp_tooltip tool_checkbox" title="' . $field['description'] . '"></div>';
1104
- break;
1105
- /* radio */
1106
- case 'radio':
1107
- foreach ($field['options'] as $value => $label) {
1108
- /*echo $meta.":".$field_id; */
1109
- /*echo "<br>"; */
1110
- echo '<input type="radio" name="' . $field_id . '" id="' . $field_id . '" value="' . $value . '" ', $meta == $value ? ' checked="checked"' : '', '/>';
1111
- echo '<label for="' . $value . '">&nbsp;&nbsp;' . $label . '</label> &nbsp;&nbsp;&nbsp;&nbsp;';
1112
- }
1113
- echo '<div class="lp_tooltip" title="' . $field['description'] . '"></div>';
1114
- break;
1115
- /* select */
1116
- case 'dropdown':
1117
- echo '<select name="' . $field_id . '" id="' . $field_id . '" class="' . $field['id'] . '">';
1118
- foreach ($field['options'] as $value => $label) {
1119
- echo '<option', $meta == $value ? ' selected="selected"' : '', ' value="' . $value . '">' . $label . '</option>';
1120
- }
1121
- echo '</select><div class="lp_tooltip" title="' . $field['description'] . '"></div>';
1122
- break;
1123
-
1124
-
1125
- }
1126
- echo '</div></div>';
1127
- } /* end foreach */
1128
- echo '</div>'; /* end table */
1129
- /*exit; */
1130
- }
1131
-
1132
-
1133
- /**
1134
- * Ajax listener to get template settings html
1135
- */
1136
- public static function ajax_get_template_metabox_html() {
1137
- global $wpdb;
1138
-
1139
- $current_template = sanitize_text_field($_POST['selected_template']);
1140
-
1141
- $post_id = intval($_POST['post_id']);
1142
- $post = get_post($post_id);
1143
-
1144
- $args['args']['key'] = $current_template;
1145
-
1146
- self::display_extended_metabox($post, $args);
1147
- die();
1148
- }
1149
-
1150
-
1151
- /**
1152
- * Save Landing Page
1153
- */
1154
- public static function save_landing_page( $landing_page_id ) {
1155
- global $post;
1156
-
1157
-
1158
- if ( !isset($post) || $post->post_type !='landing-page' || wp_is_post_revision( $landing_page_id ) ) {
1159
- return;
1160
- }
1161
-
1162
-
1163
- if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
1164
- return;
1165
- }
1166
-
1167
- $variations = Landing_Pages_Variations::get_variations( $landing_page_id );
1168
- $variation_id = (isset($_REQUEST['lp-variation-id'])) ? intval($_REQUEST['lp-variation-id']) : '0';
1169
- $_SESSION['lp_ab_test_open_variation'] = $variation_id;
1170
- if (!in_array( $variation_id , $variations) ) {
1171
- $variations[] = $variation_id;
1172
- }
1173
- Landing_Pages_Variations::update_variations( $landing_page_id , $variations );
1174
-
1175
- /* save all post data */
1176
- $ignore_list = array( 'acf' , 'post_status', 'post_type', 'tax_input', 'post_author', 'user_ID', 'post_ID', 'landing-page-myeditor', 'catslist', 'post_title', 'samplepermalinknonce', 'autosavenonce', 'action', 'autosave', 'mm', 'jj', 'aa', 'hh', 'mn', 'ss', '_wp_http_referer', 'lp-variation-id', '_wpnonce', 'originalaction', 'original_post_status', 'referredby', '_wp_original_http_referer', 'meta-box-order-nonce', 'closedpostboxesnonce', 'hidden_post_status', 'hidden_post_password', 'hidden_post_visibility', 'visibility', 'post_password', 'hidden_mm', 'cur_mm', 'hidden_jj', 'cur_jj', 'hidden_aa', 'cur_aa', 'hidden_hh', 'cur_hh', 'hidden_mn', 'cur_mn', 'original_publish', 'save', 'newlanding_page_category', 'newlanding_page_category_parent', '_ajax_nonce-add-landing_page_category', 'lp_lp_custom_fields_nonce', 'post_mime_type', 'ID', 'comment_status', 'ping_status');
1177
- foreach ($_REQUEST as $key => $value) {
1178
-
1179
- if (in_array( $key , $ignore_list) ) {
1180
- continue;
1181
- }
1182
-
1183
- if ( $variation_id > 0 && !strstr( $key, "-{$variation_id}")) {
1184
- $key = $key . '-' . $variation_id;
1185
- }
1186
-
1187
- update_post_meta( $landing_page_id , $key , $value );
1188
- }
1189
-
1190
- /* save conversion area */
1191
- if(isset($_REQUEST['landing-page-myeditor'])) {
1192
- $conversion_area = wpautop($_REQUEST['landing-page-myeditor']);
1193
- $conversion_area_key = Landing_Pages_Variations::prepare_input_id( 'lp-conversion-area' , $variation_id );
1194
- update_post_meta( $landing_page_id , $conversion_area_key , $conversion_area);
1195
- }
1196
-
1197
- }
1198
-
1199
- /**
1200
- * Sets WPSEO metabox priority to low
1201
- * @return string
1202
- */
1203
- public static function set_wpseo_priority() {
1204
- return 'low';
1205
- }
1206
-
1207
- }
1208
-
1209
-
1210
- new Landing_Pages_Metaboxes;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.post-type.landing-page.php DELETED
@@ -1,667 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class for registering the landing page CPT and expanding the CPT's listing page with additional data
5
- * @package LandingPages
6
- * @subpackage Management
7
- */
8
-
9
-
10
- class Landing_Pages_Post_Type {
11
-
12
- function __construct() {
13
- self::load_hooks();
14
- }
15
-
16
- /**
17
- * setup hooks and filters
18
- */
19
- private function load_hooks() {
20
- add_action('init', array( __CLASS__ , 'register_post_type' ) );
21
- add_action( 'admin_init' , array( __CLASS__ , 'register_role_capabilities' ) ,999);
22
- add_action('init', array( __CLASS__ , 'register_taxonomies' ) );
23
- add_action('init', array( __CLASS__ , 'add_rewrite_rules') );
24
- add_filter('mod_rewrite_rules', array( __CLASS__ , 'filter_rewrite_rules' ) , 1);
25
-
26
- /* adds & managed collumns */
27
- add_filter("manage_edit-landing-page_columns", array( __CLASS__ , 'register_columns' ) );
28
- add_action("manage_posts_custom_column", array( __CLASS__ , "display_columns" ) );
29
- add_filter('landing-page_orderby', 'lp_column_orderby', 10, 2);
30
-
31
- /* disable SEO Filter */
32
- if ((isset($_GET['post_type']) && ($_GET['post_type'] == 'landing-page'))) {
33
- add_filter('wpseo_use_page_analysis', '__return_false');
34
- }
35
-
36
- /* adds category to landing page sorting filter */
37
- add_action('restrict_manage_posts', array( __CLASS__, 'sort_by_category' ) );
38
- add_filter('parse_query', array( __CLASS__ , 'sort_by_category_prepare_query' ));
39
-
40
- /* make columns sortable */
41
- add_filter('manage_edit-landing-page_sortable_columns', array( __CLASS__ , 'define_sortable_columns' ));
42
-
43
- /* add styling handlers to custom post states */
44
- add_filter('display_post_states', array( __CLASS__ , 'filter_custom_post_states' ) );
45
-
46
- /* enqueue scripts for landing page listings */
47
- add_action( 'admin_enqueue_scripts' , array(__CLASS__, 'enqueue_admin_scripts' ) );
48
-
49
-
50
- /* enqueue scripts for landing page listings */
51
- if (isset($_GET['dont_save'])
52
- || isset($_GET['iframe_window'])
53
- || isset($_GET['inbound-preview']) ) {
54
- add_action('wp_enqueue_scripts', array(__CLASS__, 'stop_stat_tracking') , 20);
55
- }
56
-
57
- /* load iframed preview page when preview is clicked from AB stats box */
58
- if (isset($_GET['iframe_window'])) {
59
- /*add_action('wp_head', array( __CLASS__ , 'load_preview_iframe' ) );*/
60
- add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts_iframe') );
61
- }
62
-
63
- /* Miscelanous wp_head - Should probably be refactored into enqueue - h */
64
- add_action('wp_head', array(__CLASS__, 'wp_head' ));
65
-
66
- }
67
-
68
- /**
69
- * register post type
70
- */
71
- public static function register_post_type() {
72
-
73
- $slug = Landing_Pages_Settings::get_setting( 'lp-main-landing-page-permalink-prefix', 'go' );
74
- $featured_images = Landing_Pages_Settings::get_setting( 'lp-main-landing-page-enable-featured-image', false );
75
-
76
- $capabilities = array('title','custom-fields','editor', 'revisions');
77
-
78
- if ($featured_images) {
79
- array_push($capabilities , 'thumbnail');
80
- }
81
-
82
- $labels = array(
83
- 'name' => __('Landing Pages', 'inbound-pro' ),
84
- 'singular_name' => __('Landing Page', 'inbound-pro' ),
85
- 'add_new' => __('Add New', 'inbound-pro' ),
86
- 'add_new_item' => __('Add New Landing Page' , 'inbound-pro' ),
87
- 'edit_item' => __('Edit Landing Page' , 'inbound-pro' ),
88
- 'new_item' => __('New Landing Page' , 'inbound-pro' ),
89
- 'view_item' => __('View Landing Page' , 'inbound-pro' ),
90
- 'search_items' => __('Search Landing Page' , 'inbound-pro' ),
91
- 'not_found' => __('Nothing found' , 'inbound-pro' ),
92
- 'not_found_in_trash' => __('Nothing found in Trash' , 'inbound-pro' ),
93
- 'parent_item_colon' => ''
94
- );
95
-
96
- $args = array(
97
- 'labels' => $labels,
98
- 'public' => true,
99
- 'publicly_queryable' => true,
100
- 'show_ui' => true,
101
- 'query_var' => true,
102
- 'menu_icon' => '',
103
- 'rewrite' => array("slug" => "$slug",'with_front' => false),
104
- 'capability_type' => array('landing_page','landing_pages'),
105
- 'map_meta_cap' => true,
106
- 'hierarchical' => false,
107
- 'menu_position' => 32,
108
- 'supports' => $capabilities
109
- );
110
-
111
- register_post_type( 'landing-page' , $args );
112
- }
113
-
114
- /**
115
- * Register Role Capabilities
116
- */
117
- public static function register_role_capabilities() {
118
- // Add the roles you'd like to administer the custom post types
119
- $roles = array('inbound_marketer','administrator');
120
-
121
- // Loop through each role and assign capabilities
122
- foreach($roles as $the_role) {
123
-
124
- $role = get_role($the_role);
125
- if (!$role) {
126
- continue;
127
- }
128
-
129
- $role->add_cap( 'read' );
130
- $role->add_cap( 'read_landing_page');
131
- $role->add_cap( 'read_private_landing_pages' );
132
- $role->add_cap( 'edit_landing_page' );
133
- $role->add_cap( 'edit_landing_pages' );
134
- $role->add_cap( 'edit_others_landing_pages' );
135
- $role->add_cap( 'edit_published_landing_pages' );
136
- $role->add_cap( 'publish_landing_pages' );
137
- $role->add_cap( 'delete_landing_pages' );
138
- $role->add_cap( 'delete_others_landing_pages' );
139
- $role->add_cap( 'delete_private_landing_pages' );
140
- $role->add_cap( 'delete_published_landing_pages' );
141
- }
142
- }
143
-
144
- /**
145
- * Register landing page taxonomies
146
- */
147
- public static function register_taxonomies() {
148
-
149
- $args = array(
150
- 'hierarchical' => true,
151
- 'label' => __("Categories", 'inbound-pro'),
152
- 'singular_label' => __("Landing Page Category",
153
- 'landing-pages'),
154
- 'show_ui' => true,
155
- 'query_var' => true,
156
- "rewrite" => true
157
- );
158
-
159
- register_taxonomy( 'landing_page_category', array('landing-page'), $args);
160
- }
161
-
162
-
163
-
164
- /**
165
- * Register columns
166
- *
167
- * @param $columns
168
- * @return array
169
- */
170
- public static function register_columns($columns) {
171
- $columns = array(
172
- "cb" => "<input type=\"checkbox\" />",
173
- "thumbnail-lander" => __("Preview", 'inbound-pro'),
174
- "title" => __("Landing Page Title", 'inbound-pro'),
175
- "stats" => __("Split Testing Results", 'inbound-pro'),
176
- "impressions" => __("Total<br>Visits", 'inbound-pro'),
177
- "actions" => __("Total<br>Conversions", 'inbound-pro'),
178
- "cr" => __("Total<br>Conversion Rate", 'inbound-pro')
179
- );
180
- return $columns;
181
- }
182
-
183
- /**
184
- * Enqueue admin scripts
185
- */
186
- public static function enqueue_admin_scripts( $hook ) {
187
- global $post;
188
- $screen = get_current_screen();
189
-
190
- if (!isset($post) ||$post->post_type != 'landing-page') {
191
- return;
192
- }
193
-
194
- wp_enqueue_style('lp-content-stats', LANDINGPAGES_URLPATH . 'assets/css/admin/content-stats.css', array() , null);
195
-
196
- /* listing page only */
197
- if ($screen->id == 'edit-landing-page' ) {
198
- /* load stat clear handlers */
199
- wp_enqueue_script( 'lp-admin-clear-stats-ajax-request', LANDINGPAGES_URLPATH . 'assets/js/ajax.clearstats.js', array( 'jquery' ) , null );
200
- wp_localize_script( 'lp-admin-clear-stats-ajax-request', 'ajaxadmin', array( 'ajaxurl' => admin_url('admin-ajax.php'), 'lp_clear_nonce' => wp_create_nonce('lp-clear-nonce') ) );
201
-
202
- wp_enqueue_script('landing-page-list', LANDINGPAGES_URLPATH . 'assets/js/admin/admin.landing-page-list.js', array() , null);
203
- wp_enqueue_style('landing-page-list-css', LANDINGPAGES_URLPATH.'assets/css/admin/landing-page-list.css', array() , null);
204
- wp_enqueue_script('jqueryui');
205
-
206
- }
207
-
208
-
209
-
210
- /* load css when landing page iframe preview is being loaded from within wp-admin */
211
- if (isset($_GET['iframe_window'])) {
212
- wp_enqueue_style('lp_ab_testing_customizer_css', LANDINGPAGES_URLPATH . 'assets/css/frontend/customizer-preview.css', array() , null);
213
- }
214
- }
215
-
216
- /**
217
- * Enqueue frontend scripts
218
- */
219
- public static function enqueue_frontend_scripts() {
220
- global $post;
221
- if ( !isset($post) && $post->post_type=='landing-page') {
222
- return;
223
- }
224
-
225
- wp_enqueue_style('inbound-wordpress-base', LANDINGPAGES_URLPATH . 'assets/css/frontend/global-landing-page-style.css', array() , null);
226
- wp_enqueue_style('inbound-shortcodes', INBOUND_FORMS.'css/frontend-render.css', array() , null);
227
-
228
-
229
- }
230
-
231
- /**
232
- * Display column data
233
- * @param $columns
234
- * @return array
235
- */
236
- public static function display_columns($column) {
237
- global $post;
238
-
239
- if ($post->post_type != 'landing-page') return;
240
-
241
- switch ($column) {
242
- case 'ID':
243
- echo $post->ID;
244
- BREAK;
245
- case 'thumbnail-lander':
246
-
247
- $template = get_post_meta($post->ID, 'lp-selected-template', true);
248
- $permalink = get_permalink($post->ID);
249
- $datetime = the_modified_date('YmjH', null, null, false);
250
- $permalink = $permalink = $permalink . '?dt=' . $datetime;
251
-
252
- if (in_array($_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1'))) {
253
-
254
- if(file_exists(LANDINGPAGES_UPLOADS_PATH . $template . '/thumbnail.png')) {
255
- $thumbnail = LANDINGPAGES_UPLOADS_URLPATH . $template . '/thumbnail.png';
256
- } else if(file_exists(LANDINGPAGES_UPLOADS_PATH . $template . '/thumbnail.jpg')) {
257
-
258
- $thumbnail = LANDINGPAGES_UPLOADS_URLPATH . $template . '/thumbnail.jpg';
259
-
260
- } else {
261
- $thumbnail = LANDINGPAGES_URLPATH . 'templates/' . $template . '/thumbnail.png';
262
- }
263
-
264
- } else {
265
- $thumbnail = 'http://s.wordpress.com/mshots/v1/' . urlencode(esc_url($permalink)) . '?w=140';
266
- }
267
-
268
- echo "<a title='" . __('Click to Preview this variation', 'inbound-pro') . "' class='thickbox' href='" . $permalink . "?lp-variation-id=0&iframe_window=on&post_id=" . $post->ID . "&TB_iframe=true&width=640&height=703' target='_blank'><img src='" . $thumbnail . "' style='width:155px;height:110px;' title='Click to Preview'></a>";
269
- BREAK;
270
- case "stats":
271
- self::show_stats();
272
- BREAK;
273
- case "impressions" :
274
- echo self::show_aggregated_stats("impressions");
275
- BREAK;
276
- case "actions":
277
- echo self::show_aggregated_stats("actions");
278
- BREAK;
279
- case "cr":
280
- echo self::show_aggregated_stats("cr") . "%";
281
- BREAK;
282
- case "template":
283
- $template_used = Landing_Pages_Variations::get_current_template( $post->ID );
284
- echo $template_used;
285
- BREAK;
286
- }
287
- }
288
-
289
-
290
- /**
291
- * Define Sortable Columns
292
- */
293
- public static function define_sortable_columns($columns) {
294
-
295
- return array(
296
- 'title' => 'title',
297
- 'impressions' => 'impressions',
298
- 'actions' => 'actions',
299
- 'cr' => 'cr'
300
- );
301
-
302
- }
303
-
304
- /**
305
- * Define Row Actions
306
- */
307
- public static function filter_row_actions( $actions , $post ) {
308
-
309
- if ($post->post_type=='wp-call-to-action') {
310
- $actions['clear'] = '<a href="#clear-stats" id="wp_cta_clear_'.$post->ID.'" class="clear_stats" title="'
311
- . __( 'Clear impression and conversion records', 'cta' )
312
- . '" >' . __( 'Clear All Stats' , 'cta') . '</a>';
313
-
314
- /* show shortcode */
315
- $actions['clear'] .= '<br><span style="color:#000;">' . __( 'Shortcode:' , 'cta' ) .'</span> <input type="text" style="width: 60%; text-align: center;" class="regular-text code short-shortcode-input" readonly="readonly" id="shortcode" name="shortcode" value="[cta id=\''.$post->ID.'\']">';
316
- }
317
-
318
- return $actions;
319
-
320
- }
321
-
322
-
323
- /**
324
- * Needs further refactoring & documentation
325
- * @param $type_of_stat
326
- * @return float|int
327
- */
328
- public static function show_aggregated_stats($type_of_stat) {
329
- global $post;
330
-
331
- $variations = get_post_meta($post->ID, 'lp-ab-variations', true);
332
- $variations = explode(",", $variations);
333
-
334
- $impressions = 0;
335
- $conversions = 0;
336
-
337
- foreach ($variations as $vid) {
338
- $each_impression = (int) get_post_meta($post->ID, 'lp-ab-variation-impressions-' . $vid, true);
339
- $each_conversion = (int) get_post_meta($post->ID, 'lp-ab-variation-conversions-' . $vid, true);
340
- (($each_conversion === "")) ? $final_conversion = 0 : $final_conversion = $each_conversion;
341
- $impressions += (int) get_post_meta($post->ID, 'lp-ab-variation-impressions-' . $vid, true);
342
- $conversions += (int) get_post_meta($post->ID, 'lp-ab-variation-conversions-' . $vid, true);
343
- }
344
-
345
- if ($type_of_stat === "actions") {
346
- return $conversions;
347
- }
348
- if ($type_of_stat === "impressions") {
349
- return $impressions;
350
- }
351
- if ($type_of_stat === "cr") {
352
- if ($impressions != 0) {
353
- $conversion_rate = $conversions / $impressions;
354
- } else {
355
- $conversion_rate = 0;
356
- }
357
- $conversion_rate = round($conversion_rate, 2) * 100;
358
- return $conversion_rate;
359
- }
360
-
361
- }
362
-
363
- /**
364
- * Adds rewrite rules
365
- */
366
- public static function add_rewrite_rules() {
367
- if ( !class_exists('Inbound_Pro_Plugin')){
368
- $this_path = LANDINGPAGES_PATH;
369
- $this_path = explode('wp-content', $this_path);
370
- $this_path = "wp-content" . $this_path[1];
371
- } else {
372
- $this_path = INBOUND_PRO_PATH;
373
- $this_path = explode('wp-content', $this_path);
374
- $this_path = "wp-content" . $this_path[1] . "core/landing-pages/";
375
- }
376
-
377
- /* handles local environment */
378
- $this_path = str_replace("\\" , "/" , $this_path);
379
-
380
- $slug = Landing_Pages_Settings::get_setting( 'lp-main-landing-page-permalink-prefix', 'go' );
381
-
382
- $ab_testing = Landing_Pages_Settings::get_setting('lp-main-landing-page-disable-turn-off-ab', "0");
383
- if ($ab_testing === "0") {
384
- add_rewrite_rule("$slug/([^/]*)/([0-9]+)/", "$slug/$1?lp-variation-id=$2", 'top');
385
- add_rewrite_rule("$slug/([^/]*)?", $this_path . "modules/module.redirect-ab-testing.php?permalink_name=$1 ", 'top');
386
- add_rewrite_rule("landing-page=([^/]*)?", $this_path . 'modules/module.redirect-ab-testing.php?permalink_name=$1', 'top');
387
- }
388
-
389
- }
390
-
391
- /**
392
- * Adds conditions to rewrite rules
393
- * @param $rules
394
- * @return string
395
- */
396
- public static function filter_rewrite_rules( $rules ) {
397
- if (stristr($rules, 'RewriteCond %{QUERY_STRING} !lp-variation-id')) {
398
- return $rules;
399
- }
400
-
401
- $rules_array = preg_split('/$\R?^/m', $rules);
402
-
403
- if (count($rules_array) < 3) {
404
- $rules_array = explode("\n", $rules);
405
- $rules_array = array_filter($rules_array);
406
- }
407
-
408
- /* print_r($rules_array);exit; */
409
-
410
-
411
- $slug = Landing_Pages_Settings::get_setting( 'lp-main-landing-page-permalink-prefix', 'go' );
412
-
413
- $i = 0;
414
- foreach ($rules_array as $key => $val) {
415
-
416
- if (stristr($val, "RewriteRule ^{$slug}/([^/]*)? ") || stristr($val, "RewriteRule ^{$slug}/([^/]*)/([0-9]+)/ ")) {
417
- $new_val = "RewriteCond %{QUERY_STRING} !lp-variation-id";
418
- $rules_array[$i] = $new_val;
419
- $i++;
420
- $rules_array[$i] = $val;
421
- $i++;
422
- } else {
423
- $rules_array[$i] = $val;
424
- $i++;
425
- }
426
- }
427
-
428
- $rules = implode("\r\n", $rules_array);
429
-
430
-
431
- return $rules;
432
- }
433
-
434
-
435
- /**
436
- * Show stats container on Landing Page lists page
437
- */
438
- public static function show_stats() {
439
-
440
- global $post;
441
- $permalink = get_permalink($post->ID);
442
- $variations = Landing_Pages_Variations::get_variations($post->ID);
443
-
444
- echo "<span class='show-stats button'> " . __('Show Variation Stats', 'inbound-pro') . "</span>";
445
- echo "<ul class='lp-varation-stat-ul'>";
446
- $cr_array = array();
447
- $i = 0;
448
-
449
- foreach ($variations as $key => $vid) {
450
- $letter = Landing_Pages_Variations::vid_to_letter($post->ID, $key); /* convert to letter */
451
- $impressions = Landing_Pages_Variations::get_impressions($post->ID, $vid);
452
- $conversions = Landing_Pages_Variations::get_conversions($post->ID, $vid);
453
-
454
- /* get variation status */
455
- $status = Landing_Pages_Variations::get_variation_status( $post->ID, $vid ); /* Current status */
456
-
457
- /* Get variation notes */
458
- $each_notes = Landing_Pages_Variations::get_variation_notes( $post->ID, $vid );
459
-
460
- if ($impressions) {
461
- $conversion_rate = $conversions / $impressions;
462
- } else {
463
- $conversion_rate = 0;
464
- }
465
- $conversion_rate = round($conversion_rate, 2) * 100;
466
-
467
- $cr_array[] = $conversion_rate;
468
-
469
- $data_letter = "data-letter=\"" . $letter . "\"";
470
- $edit_link = admin_url('post.php?post=' . $post->ID . '&lp-variation-id=' . $vid . '&action=edit');
471
- echo "<li rel='" . $status . "' data-postid='" . $post->ID . "' data-letter='" . $letter . "' data-lp='' class='lp-stat-row-" . $vid . " " . $post->ID . '-' . $conversion_rate . " status-" . $status . "'><a class='lp-letter' title='click to edit this variation' href='" . $edit_link . "'>" . $letter . "</a><span class='lp-numbers'><span class='lp-visitors'><span class='visit-text'>" . __( 'Impressions' , 'inbound-pro' ) . "</span><span class='lp-impress-num'>" . $impressions . "</span></span> <span class='lp-conversions'> <span class='lp-conversion-txt'>" . __( 'Conversions' , 'inbound-pro' ) . "</span> <span class='lp-con-num'>" . $conversions . "</span> </span> </span><a ". $data_letter . " class='cr-number cr-empty-" . $conversion_rate . "' href='" . $edit_link . "'>" . $conversion_rate . "%</a></li>";
472
- $i++;
473
- }
474
- echo "</ul>";
475
- $winning_cr = max($cr_array); /* best conversion rate */
476
- if ($winning_cr != 0) {
477
- echo "<span class='variation-winner-is'>" . $post->ID . "-" . $winning_cr . "</span>";
478
- }
479
- /*echo "Total Visits: " . $impressions; */
480
- /*echo "Total Conversions: " . $conversions; */
481
-
482
- }
483
-
484
-
485
- /**
486
- * Show dropdown of landing page categories
487
- */
488
- public static function sort_by_category() {
489
- global $typenow;
490
-
491
- if ($typenow != "landing-page") {
492
- return;
493
- }
494
-
495
-
496
- $filters = get_object_taxonomies($typenow);
497
-
498
- foreach ($filters as $tax_slug) {
499
-
500
- $tax_obj = get_taxonomy($tax_slug);
501
- (isset($_GET[$tax_slug])) ? $current = $_GET[$tax_slug] : $current = 0;
502
- wp_dropdown_categories(
503
- array(
504
- 'show_option_all' => __('Show All ' . $tax_obj->label),
505
- 'taxonomy' => $tax_slug,
506
- 'name' => $tax_obj->name,
507
- 'orderby' => 'name',
508
- 'selected' => $current,
509
- 'hierarchical' => $tax_obj->hierarchical,
510
- 'show_count' => false,
511
- 'hide_empty' => true
512
- )
513
- );
514
- }
515
- }
516
-
517
- /**
518
- * Convert the category id to the taxonomy id during a query
519
- */
520
- public static function sort_by_category_prepare_query() {
521
- global $pagenow;
522
- $qv = &$query->query_vars;
523
- if ($pagenow == 'edit.php' && isset($qv['landing_page_category']) && is_numeric($qv['landing_page_category'])) {
524
- $term = get_term_by('id', $qv['landing_page_category'], 'landing_page_category');
525
- $qv['landing_page_category'] = $term->slug;
526
- }
527
- }
528
-
529
- /**
530
- * Add styling handlers to custom post states
531
- */
532
- public static function filter_custom_post_states($post_states) {
533
- foreach ($post_states as &$state) {
534
- $state = '<span class="' . strtolower($state) . ' states">' . str_replace(' ', '-', $state) . '</span>';
535
- }
536
- return $post_states;
537
- }
538
-
539
- /**
540
- * Loads preview iframe. Currently disabled. Plans to update @DavidWells
541
- */
542
- public static function load_preview_iframe() {
543
-
544
- $variation_id = Landing_Pages_Variations::get_current_variation_id();
545
- $landing_page_id = $_GET['post_id'];
546
-
547
- $variations = Landing_Pages_Variations::get_variations( $landing_page_id );
548
- ?>
549
- <link rel="stylesheet" href="<?php echo LANDINGPAGES_URLPATH . 'assets/css/customizer-ab-testing.css';?>"/>
550
- <style type="text/css">
551
-
552
- #variation-list {
553
- position: absolute;
554
- top: 0px;
555
- left: 0px;
556
- padding-left: 5px;
557
- }
558
-
559
- #variation-list h3 {
560
- text-decoration: none;
561
- border-bottom: none;
562
- }
563
-
564
- #variation-list div {
565
- display: inline-block;
566
- }
567
-
568
- #current_variation_id, #current-post-id {
569
- display: none !important;
570
- }
571
-
572
- </style>
573
- <script type="text/javascript">
574
- jQuery(document).ready(function ($) {
575
- var current_page = jQuery("#current_variation_id").text();
576
- /* reload the iframe preview page (for option toggles) */
577
- jQuery('.variation-lp').on('click', function (event) {
578
- variation_is = jQuery(this).attr("id");
579
- var original_url = jQuery(parent.document).find("#TB_iframeContent").attr("src");
580
- var current_id = jQuery("#current-post-id").text();
581
- someURL = original_url;
582
-
583
- splitURL = someURL.split('?');
584
- someURL = splitURL[0];
585
- new_url = someURL + "?lp-variation-id=" + variation_is + "&iframe_window=on&post_id=" + current_id;
586
- jQuery(parent.document).find("#TB_iframeContent").attr("src", new_url);
587
- });
588
- });
589
- </script>
590
- <?php
591
- }
592
-
593
- /**
594
- * Load JS to disable stats from working for preview windows
595
- */
596
- public static function stop_stat_tracking() {
597
- show_admin_bar(false);
598
- wp_enqueue_script('stop-inbound-stats-js', LANDINGPAGES_URLPATH . 'assets/js/stop_page_stats.js' , array('inbound-analytics') , null );
599
- wp_enqueue_style('inbound-preview-window-css', LANDINGPAGES_URLPATH . 'assets/css/iframe-preview.css' , array() , null);
600
- }
601
-
602
- /**
603
- * Load misc wp_head
604
- */
605
- public static function wp_head() {
606
- global $post;
607
-
608
- if (isset($post) && $post->post_type !=='landing-page') {
609
- return;
610
- }
611
- /* if is tiny iframe preview window force these styles */
612
- if (isset($_GET['dont_save'])) { ?>
613
- <style type="text/css">
614
- :root:root:root #wpadminbar {
615
- display:none !important;
616
- }
617
- :root:root:root {
618
- margin-top: 0px !important;
619
- min-height: 714px !important;
620
- }
621
- </style>
622
- <?php }
623
-
624
- if (isset($_GET['lp-variation-id']) && !isset($_GET['inbound-customizer']) && !isset($_GET['iframe_window']) && !isset($_GET['live-preview-area'])) {
625
- ?>
626
-
627
- <?php
628
- if(!defined('Inbound_Now_Disable_URL_CLEAN')) {
629
- ?>
630
- <script type="text/javascript">
631
- /* Then strip params if pushstate exists */
632
- if (typeof window.history.pushState == 'function') {
633
- var cleanparams=window.location.href.split("?");
634
- var clean_url= landing_pages_remove_variation_param();
635
- history.replaceState({},"landing page",clean_url);
636
- }
637
- function landing_pages_remove_variation_param() {
638
- var urlparts= window.location.href.split('?');
639
- if (urlparts.length>=2) {
640
-
641
- var prefix= encodeURIComponent('lp-variation-id')+'=';
642
- var pars= urlparts[1].split(/[&;]/g);
643
-
644
- /* reverse iteration as may be destructive */
645
- for (var i= pars.length; i-- > 0;) {
646
- //idiom for string.startsWith
647
- if (pars[i].lastIndexOf(prefix, 0) !== -1) {
648
- pars.splice(i, 1);
649
- }
650
- }
651
-
652
- url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
653
- return url;
654
- } else {
655
- return url;
656
- }
657
- }
658
- </script>
659
- <?php
660
- }
661
- }
662
-
663
- }
664
- }
665
-
666
- /* Load Post Type Pre Init */
667
- new Landing_Pages_Post_Type();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.postmeta.php DELETED
@@ -1,37 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class provides a data interface for interacting with landing page meta data. Used by Landing_Pages_ACF class
5
- * @package LandingPages
6
- * @subpackage DataInterfaces
7
- */
8
-
9
- class Landing_Pages_Meta {
10
-
11
- /**
12
- * Gets email settings
13
- * @param INT $email_id
14
- * @return ARRAY $landing_page_settings
15
- */
16
- public static function get_settings( $landing_pages_id ) {
17
-
18
- $landing_page_settings = maybe_unserialize(get_post_meta( $landing_pages_id , 'inbound_settings' , true ));
19
-
20
- if (!$landing_page_settings) {
21
- $landing_page_settings = array();
22
- }
23
-
24
-
25
- return $landing_page_settings;
26
- }
27
-
28
- /**
29
- * Updates inbound_settings post meta
30
- * @param INT $landing_pages_id
31
- * @param ARRAY $settings
32
- */
33
- public static function update_settings( $landing_pages_id , $settings ) {
34
- update_metadata('post', $landing_pages_id, 'inbound_settings', $settings, '');
35
- }
36
-
37
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.row-actions.php DELETED
@@ -1,198 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class adds row actions to landing-page CPT listing page. Should be moved into class.post-type.landing-pages.php
5
- * @package LandingPages
6
- * @subpackage Management
7
- */
8
-
9
- class Landing_Pages_Row_Actions {
10
-
11
- /**
12
- * Initiate class
13
- */
14
- public function __construct() {
15
- self::load_hooks();
16
- }
17
-
18
- /**
19
- * Loads hooks and filters
20
- */
21
- public static function load_hooks() {
22
- /* add admin action to clone post */
23
- add_action('admin_action_clone_landing_page', array( __CLASS__ , 'clone_landing_page' ) );
24
-
25
- /* adds 'clone' links to posts */
26
- add_filter('post_row_actions', array( __CLASS__ ,'add_clone_link' ), 10, 2);
27
-
28
- /* adds 'clear stats' links to posts */
29
- add_filter('post_row_actions', array( __CLASS__ ,'add_clear_stats_link' ), 10, 2);
30
- }
31
-
32
- /**
33
- * Adds close links to quick actions in a post types listing area
34
- * @param $actions
35
- * @param $post
36
- * @return mixed
37
- */
38
- public static function add_clone_link($actions, $post) {
39
-
40
- if ($post->post_type != 'landing-page' ) {
41
- return $actions;
42
- }
43
-
44
- $actions['clone'] = '<a href="'.self::get_clone_link( $post->ID ).'" title="'
45
- . esc_attr(__("Clone this item", 'landing-pages'))
46
- . '">' . __('Clone', 'landing-pages') . '</a>';
47
-
48
- return $actions;
49
- }
50
-
51
- /**
52
- * Builds the clone action link
53
- * @param int $id
54
- * @param bool|true $draft
55
- */
56
- public static function get_clone_link( $id = 0 ) {
57
-
58
- if ( !$post = get_post( $id ) ) {
59
- return;
60
- }
61
-
62
-
63
- $link = add_query_arg( array('action'=>'clone_landing_page' , 'post' => $post->ID ) , admin_url("admin.php"));
64
-
65
- return $link;
66
- }
67
-
68
-
69
- /**
70
- * Creates cloned landing page and opens it for user
71
- * @param string $status
72
- */
73
- public static function clone_landing_page($status = 'pending') {
74
-
75
- /* Get the original post */
76
- $id = (isset($_GET['post']) ? intval($_GET['post']) : intval($_POST['post']) );
77
- $post = get_post($id);
78
-
79
- /* Copy the post and insert it */
80
- if (!isset($post) || !$post) {
81
- $post_type_obj = get_post_type_object( $post->post_type );
82
- wp_die(esc_attr(__('Copy creation failed, could not find original:', 'landing-pages')) . ' ' . $id);
83
- }
84
-
85
- if (!is_object($post)&&is_numeric($post)) {
86
- $post = get_post($post);
87
- }
88
-
89
- $status = $post->post_status;
90
-
91
- /* We don't want to clone revisions */
92
- if ($post->post_type == 'revision') {
93
- return;
94
- }
95
-
96
-
97
- $prefix = "Copy of ";
98
- $suffix = "";
99
- $status = 'pending';
100
-
101
-
102
- $new_post_author = self::get_current_user();
103
-
104
-
105
- $new_post = array(
106
- 'menu_order' => $post->menu_order,
107
- 'comment_status' => $post->comment_status,
108
- 'ping_status' => $post->ping_status,
109
- 'post_author' => $new_post_author->ID,
110
- 'post_content' => $post->post_content,
111
- 'post_excerpt' => $post->post_excerpt ,
112
- 'post_mime_type' => $post->post_mime_type,
113
- 'post_parent' => $new_post_parent = empty($parent_id)? $post->post_parent : $parent_id,
114
- 'post_password' => $post->post_password,
115
- 'post_status' => $status,
116
- 'post_title' => $prefix.$post->post_title.$suffix,
117
- 'post_type' => $post->post_type,
118
- );
119
-
120
- $new_post['post_date'] = $new_post_date = $post->post_date;
121
- $new_post['post_date_gmt'] = get_gmt_from_date($new_post_date);
122
-
123
- $new_post_id = wp_insert_post($new_post);
124
-
125
- $meta_data = self::get_meta($post->ID);
126
- foreach ($meta_data as $key => $value) {
127
- update_post_meta($new_post_id, $key, $value);
128
- }
129
-
130
-
131
- wp_redirect(admin_url('edit.php?post_type=' . $post->post_type));
132
-
133
- exit;
134
- }
135
-
136
- /**
137
- * Get current user
138
- * @return OBJECT $user
139
- */
140
- public static function get_current_user() {
141
-
142
- if (function_exists('wp_get_current_user')) {
143
- return wp_get_current_user();
144
- } else if (function_exists('wp_get_current_user')) {
145
- global $userdata;
146
- $userdata = wp_get_current_user();
147
- return $userdata;
148
- } else {
149
- $user_login = $_COOKIE[USER_COOKIE];
150
- $current_user = $wpdb->get_results("SELECT * FROM $wpdb->users WHERE user_login='$user_login'");
151
- return $current_user;
152
- }
153
-
154
- }
155
-
156
- /**
157
- * Gets meta data of landing page from landing page id
158
- * @param $post_id
159
- * @return array
160
- */
161
- public static function get_meta($landing_page_id) {
162
-
163
-
164
- global $wpdb;
165
- $data = array();
166
- $wpdb->query("
167
- SELECT `meta_key`, `meta_value`
168
- FROM $wpdb->postmeta
169
- WHERE `post_id` = $landing_page_id
170
- ");
171
- foreach ($wpdb->last_result as $k => $v) {
172
- $data[$v->meta_key] = $v->meta_value;
173
- };
174
- return $data;
175
- }
176
-
177
- /**
178
- * Adds clear stats link to quick actions in a post types listing area
179
- * @param $actions
180
- * @param $post
181
- * @return mixed
182
- */
183
- public static function add_clear_stats_link($actions, $post) {
184
-
185
- if ($post->post_type != 'landing-page' ) {
186
- return $actions;
187
- }
188
- // .clear_stats is listened to by ajax.clearstats.js
189
- $actions['clear_the_stats'] = '<a id="'.$post->ID.'" title="'
190
- . esc_attr(__("Clear the stats?", 'landing-pages'))
191
- . '"class="clear_stats"'
192
- . 'style="cursor:pointer;">' . __('Clear Stats', 'landing-pages') . '</a>';
193
-
194
- return $actions;
195
- }
196
- }
197
-
198
- new Landing_Pages_Row_Actions;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.settings.php DELETED
@@ -1,870 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class provides a data interface for retrieving and storing landing page settings into the GPL legacy setting system or the Inbound Pro settings system.
5
- * @package LandingPages
6
- * @subpackage DataInterfaces
7
- */
8
-
9
- class Landing_Pages_Settings {
10
-
11
- /**
12
- * initiate class
13
- */
14
- public function __construct() {
15
- self::load_hooks();
16
- }
17
-
18
- /**
19
- * Load hooks and filters
20
- */
21
- public static function load_hooks() {
22
-
23
- /* load settings scripts and styles */
24
- add_action('admin_enqueue_scripts', array( __CLASS__ , 'enqueue_settings_scripts' ) );
25
-
26
- /* display system info */
27
- add_action('admin_footer', array( __CLASS__ , 'display_system_info' ) );
28
-
29
- /* download system info */
30
- add_action( 'admin_init', array( __CLASS__ , 'download_system_info' ) );
31
-
32
- /* Add settings to inbound pro */
33
- add_filter('inbound_settings/extend', array( __CLASS__ , 'define_pro_settings' ) );
34
- }
35
-
36
- /**
37
- * Adds pro admin settings
38
- */
39
- public static function define_pro_settings( $settings ) {
40
- global $inbound_settings;
41
-
42
- $settings['inbound-pro-setup'][] = array(
43
- 'group_name' => LANDINGPAGES_PLUGIN_SLUG ,
44
- 'keywords' => __('landing pages, landers, permalinks,sticky,ab testing' , 'inbound-pro'),
45
- 'fields' => array (
46
- array(
47
- 'id' => 'header-landing-page',
48
- 'type' => 'header',
49
- 'default' => __('Landing Pages Settings', 'inbound-pro' ),
50
- 'options' => null
51
- ),
52
- array(
53
- 'id' => 'landing-page-permalink-prefix',
54
- 'label' => __('Permalink Prefix', 'inbound-pro' ),
55
- 'description' => __("The prefix for landing page URL permalink. Example: http://www.yoursite.com/PREFIX/landing-page. Inbound Now also provides an extension that will remove the prefix if desired in the extensions area." , 'inbound-pro') ,
56
- 'type' => 'text',
57
- 'default' => 'go',
58
- ),
59
- array(
60
- 'id' => 'landing-page-rotation-halt',
61
- 'label' => __('Sticky Variations' , 'inbound-pro'),
62
- 'description' => __("With this setting enabled the landing pages plugin will prevent landing page version a/b rotation for a specific visitor that has viewed the page for 30 days." , 'inbound-pro'),
63
- 'type' => 'radio',
64
- 'default' => '0',
65
- 'options' => array('1'=>'on','0'=>'off')
66
- ),
67
- array(
68
- 'id' => 'landing-page-disable-turn-off-ab',
69
- 'label' => __('Turn Off AB Testing?' , 'inbound-pro') ,
70
- 'description' => __("This will disable the AB testing functionality of your landing pages. This is to comply with Googles new PPC regulations with redirects. After saving this option <a href='/wp-admin/options-permalink.php'>visit this page to flush/reset your permalinks</a>" , 'inbound-pro'),
71
- 'type' => 'radio',
72
- 'default' => '0',
73
- 'options' => array('0'=>'No Keep it on','1'=>'Yes turn AB testing Off')
74
- ),
75
- array(
76
- 'id' => 'landing-page-enable-featured-image',
77
- 'label' => __('Enable Featured Images' , 'inbound-pro') ,
78
- 'description' => __("Enable this setting if you plan to include the landing-page post type in any frontend post archives that leverages the featured image system." , 'inbound-pro'),
79
- 'type' => 'radio',
80
- 'default' => '0',
81
- 'options' => array('0'=>__('Off','inbound-pro'), '1'=> __('On' , 'inbound-pro') )
82
- )
83
- )
84
-
85
- );
86
-
87
-
88
- return $settings;
89
- }
90
-
91
- /**
92
- * Loads default global settings & extends them
93
- */
94
- public static function get_stand_alone_settings() {
95
- global $lp_global_settings;
96
-
97
- /* Setup Main Navigation Tab and Settings */
98
- $tab_slug = 'lp-main';
99
- $lp_global_settings[$tab_slug]['label'] = __( 'Global Settings' , 'inbound-pro' );
100
-
101
-
102
- $lp_global_settings[$tab_slug]['settings'] = array(
103
- array(
104
- 'id' => 'lp_global_settings_main_header',
105
- 'type' => 'header',
106
- 'default' => __('Core Settings' , 'inbound-pro') ,
107
- 'options' => null
108
- ),
109
- array(
110
- 'id' => 'landing-page-permalink-prefix',
111
- 'label' => __( 'Default Landing Page Permalink Prefix' , 'inbound-pro'),
112
- 'description' => __("Enter in the <span style='color:red;'>prefix</span> for landing page URLs (aka permalinks).<br><br>This is the URL Slug that will be in the landing page URL.<br><br> Example: http://www.yoursite.com/<span style='color:red;'>PREFIX</span>/landing-page . Enter in a single word like 'go'" , 'inbound-pro') ,
113
- 'type' => 'text',
114
- 'default' => 'go',
115
- 'options' => null
116
- ),
117
- array(
118
- 'id' => 'landing-page-rotation-halt',
119
- 'label' => __('Sticky Variations' , 'inbound-pro'),
120
- 'description' => __("With this setting enabled the landing pages plugin will prevent landing page version a/b rotation for a specific visitor that has viewed the page.<br><br>This pause on the a/b rotation will automatically expire after 30 days." , 'inbound-pro'),
121
- 'type' => 'radio',
122
- 'default' => '0',
123
- 'options' => array('1'=>'on','0'=>'off')
124
- ),
125
- array(
126
- 'id' => 'landing-page-disable-turn-off-ab',
127
- 'label' => __('Turn Off AB Testing?' , 'inbound-pro') ,
128
- 'description' => __("This will disable the AB testing functionality of your landing pages. This is to comply with Googles new PPC regulations with redirects. After saving this option <a href='/wp-admin/options-permalink.php'>visit this page to flush/reset your permalinks</a>" , 'inbound-pro'),
129
- 'type' => 'radio',
130
- 'default' => '0',
131
- 'options' => array('0'=>'No Keep it on','1'=>'Yes turn AB testing Off')
132
- ),
133
- array(
134
- 'id' => 'landing-page-enable-featured-image',
135
- 'label' => __('Enable Featured Images' , 'inbound-pro') ,
136
- 'description' => __("Enable this setting if you plan to include the landing-page post type in any frontend post archives that leverages the featured image system." , 'inbound-pro'),
137
- 'type' => 'radio',
138
- 'default' => '0',
139
- 'options' => array('0'=>__('Off','inbound-pro'), '1'=> __('On' , 'inbound-pro') )
140
- )
141
- );
142
-
143
-
144
- if (
145
- !defined('INBOUND_ACCESS_LEVEL')
146
- ||
147
- ( defined('INBOUND_ACCESS_LEVEL') && INBOUND_ACCESS_LEVEL < 1 )
148
- ) {
149
- /* Setup License Keys Tab */
150
- $lp_global_settings['lp-license-keys']['label'] = __('API Key Setup', 'inbound-pro');
151
- $lp_global_settings['lp-license-keys']['settings'][] = array(
152
- 'id' => 'extensions-license-keys-header',
153
- 'description' => __("Head to http://www.inboundnow.com/account to retrieve your API key for this template.", 'inbound-pro'),
154
- 'type' => 'header',
155
- 'default' => '<h3 class="lp_global_settings_header">' . __('Inbound API Key', 'inbound-pro') . '</h3>'
156
- );
157
- }
158
-
159
- if (!defined('INBOUND_ACCESS_LEVEL') ) {
160
- /* Setup Extensions Tab */
161
- $lp_global_settings['lp-extensions']['label'] = __( 'Extensions' , 'inbound-pro');
162
- $lp_global_settings['lp-extensions']['settings'] = array(
163
- array(
164
- 'id' => 'lp-ext-header',
165
- 'type' => 'header',
166
- 'default' => '',
167
- 'options' => null
168
- )
169
- );
170
- }
171
-
172
- /* Setup Debug Tab */
173
- $lp_global_settings['lp-debug']['label'] = __( 'Debug' , 'inbound-pro');
174
- $lp_global_settings['lp-debug']['settings'] = array(
175
- array(
176
- 'id' => 'lp-debug-header',
177
- 'type' => 'header',
178
- 'default' => '',
179
- 'options' => null
180
- )
181
- );
182
-
183
- $lp_global_settings = apply_filters('lp_define_global_settings',$lp_global_settings);
184
-
185
- return $lp_global_settings;
186
- }
187
-
188
- /**
189
- * Get setting value from DB. Handles stand alone landing pages plugin differently from Inbound Pro included landing pages plugin
190
- * @param $field_id
191
- * @param $default
192
- * @return mixed
193
- */
194
- public static function get_setting( $field_id , $default ) {
195
- global $inbound_settings;
196
- $value = $default;
197
-
198
- if (defined('INBOUND_PRO_CURRENT_VERSION')) {
199
- $field_id = str_replace('lp-main-' , '', $field_id );
200
- $value = (isset($inbound_settings['landing-pages'][$field_id])) ? $inbound_settings['landing-pages'][$field_id] : $default;
201
- } else {
202
- $value = get_option( $field_id, $default );
203
- }
204
-
205
- return $value;
206
- }
207
-
208
-
209
- /**
210
- * Enqueue scripts and styles for settings page
211
- */
212
- public static function enqueue_settings_scripts() {
213
-
214
- if ( !isset($_GET['page']) || $_GET['page']!='lp_global_settings' ) {
215
- return;
216
- }
217
-
218
- wp_enqueue_style('lp-css-global-settings-here', LANDINGPAGES_URLPATH . 'assets/css/admin/global-settings.css', array() , null);
219
- wp_enqueue_script('lp-settings-js', LANDINGPAGES_URLPATH . 'assets/js/admin/admin.global-settings.js', array() , null);
220
-
221
- /* load ToolTipster */
222
- wp_enqueue_style('tooltipster', INBOUNDNOW_SHARED_URLPATH . 'assets/includes/ToolTipster/css/tooltipster.css', array() , null);
223
- wp_enqueue_style('tooltipster-theme', INBOUNDNOW_SHARED_URLPATH . 'assets/includes/ToolTipster/css/themes/tooltipster-noir.css', array() , null);
224
- wp_enqueue_script('tooltipster', INBOUNDNOW_SHARED_URLPATH . 'assets/includes/ToolTipster/js/jquery.tooltipster.min.js', array() , null);
225
- }
226
-
227
- /**
228
- * Add action links in Plugins table
229
- */
230
- public static function extend_plugin_quicklinks( $links ) {
231
-
232
- return array_merge(
233
- array(
234
- 'settings' => '<a href="' . admin_url( 'edit.php?post_type=landing-page&page=lp_global_settings' ) . '">' . __( 'Settings', 'ts-fab' ) . '</a>'
235
- ),
236
- $links
237
- );
238
- }
239
-
240
-
241
- /**
242
- * Displays global settings container
243
- */
244
- public static function display_settings() {
245
- global $wpdb;
246
-
247
-
248
- $lp_global_settings = self::get_stand_alone_settings();
249
-
250
- $htaccess = "";
251
- if ((isset($_SERVER['SERVER_SOFTWARE']) && stristr($_SERVER['SERVER_SOFTWARE'], 'nginx') === false) && file_exists(get_home_path() . ".htaccess")) {
252
- $htaccess_file = get_home_path() . "/.htaccess";
253
- $f = fopen($htaccess_file, 'r');
254
- $contentht = fread($f, filesize($htaccess_file));
255
- $contentht = esc_textarea($contentht);
256
-
257
- if (!is_writable($htaccess_file)) {
258
- $content = " <div class=\"error\"><h3>" . __("Oh no! Your .htaccess is not writable and A/B testing won't work unless you make your .htaccess file writable.", 'inbound-pro') . "</h3></div>";
259
- echo $content;
260
- } else {
261
- $htaccess = '<textarea readonly="readonly" onclick="this.focus();this.select()" style="width: 90%;" rows="15" name="robotsnew">' . $contentht . '</textarea><br/>';
262
- }
263
- }
264
-
265
-
266
- $active_tab = 'lp-main';
267
- if (isset($_REQUEST['open-tab'])) {
268
- $active_tab = sanitize_title($_REQUEST['open-tab']);
269
- }
270
-
271
- do_action('lp_pre_display_global_settings');
272
-
273
- self::save_stand_alone_settings();
274
-
275
- echo '<h2 class="nav-tab-wrapper">';
276
-
277
- foreach ($lp_global_settings as $key => $data) {
278
- if (!isset($data['label'])) {
279
- continue;
280
- }
281
- ?>
282
- <a id='tabs-<?php echo $key; ?>'
283
- class="lp-nav-tab nav-tab nav-tab-special<?php echo $active_tab == $key ? '-active' : '-inactive'; ?>"><?php echo $data['label']; ?></a>
284
- <?php
285
- }
286
-
287
- echo "</h2><div class='lp-settings-tab-sidebar'>";
288
-
289
- echo "<div style=''></div>";
290
- echo "</div>";
291
- echo "<form action='edit.php?post_type=landing-page&page=lp_global_settings' method='POST'>
292
- <input type='hidden' name='nature' value='lp-global-settings-save'>
293
- <input type='hidden' name='open-tab' id='id-open-tab' value='{$active_tab}'>";
294
-
295
-
296
- foreach ($lp_global_settings as $key => $data) {
297
- self::render_stand_alone_settings($key, $data['settings'], $active_tab);
298
- }
299
-
300
- echo '<div style="float:left;padding-left:9px;padding-top:20px;">
301
- <input type="submit" value="Save Settings" tabindex="5" id="lp-button-create-new-group-open" class="button-primary" >
302
- </div>';
303
- echo "</form>";
304
- ?>
305
- <div id="lp-additional-resources" class="clear">
306
- <hr>
307
- <?php
308
- $rand = rand(0,3);
309
- switch ($rand) {
310
- case 0:
311
- echo ' <div class="" style="margin-left:auto;margin-right:auto;">
312
- <h4><b>Sponsored Moment: Need to hire WordPress assistance? Agents at Codeable are ready to help.</b></h4>
313
- <a href="https://codeable.io/?ref=WwUol">
314
- <img src=\'https://referoo.co/creatives/21/asset.png\' />
315
- </a>
316
- </div>';
317
- echo ' </div>';
318
- break;
319
- case 1:
320
- echo ' <div class="" style="margin-left:auto;margin-right:auto;">
321
- <h4><b>This plugin works great on WPEngine! Use our special offer below to receive 20% off the first annual payment.</b></h4>
322
- <a target="_blank" href="http://www.shareasale.com/r.cfm?B=1255604&U=1220301&M=41388"><img src="https://www.inboundnow.com/wp-content/uploads/2016/12/Inbound-Now-728x90.png" border="0" /></a>
323
- </div>';
324
- echo ' </div>';
325
- break;
326
- case 2:
327
- echo '<div class="" style="margin-left:auto;margin-right:auto;">
328
- <h4>Did you know we offer an enhanced version of this plugin? - <a target="_blank" href="https://www.inboundnow.com/upgrade/?ref=356">Read more about our Inbound Now PRO plugin.</a></b></h4>
329
- </div>';
330
- echo ' </div>';
331
- break;
332
- case 3:
333
- echo '<div class="" style="margin-left:auto;margin-right:auto;">
334
- <h4><b>Thanks for using our free plugin! - <a target="_blank" href="https://wordpress.org/support/plugin/landing-pages/reviews/?filter=5">Rate us 5 stars to help us grow!</a></b></h4>
335
- </div>';
336
- echo ' </div>';
337
- break;
338
- }
339
- ?>
340
- </div>
341
- <script type="text/javascript">
342
- jQuery(document).ready(function ($) {
343
- var debug = jQuery("#php-sql-lp-version");
344
- jQuery(debug).prependTo("#lp-debug");
345
- jQuery("#php-sql-lp-version").show();
346
- });
347
-
348
- </script>
349
- <div id="php-sql-lp-version" style="display:none;">
350
- <div id="inbound-install-status">
351
- <h3><?php _e('Installation Status', 'inbound-pro'); ?></h3>
352
- <table id="lp-wordpress-site-status">
353
-
354
- <tr valign="top">
355
- <th scope="row"><label><?php _e('PHP Version', 'inbound-pro'); ?></label></th>
356
- <td class="installation_item_cell">
357
- <strong><?php echo phpversion(); ?></strong>
358
- </td>
359
- <td>
360
- <?php
361
- if (version_compare(phpversion(), '5.3.3', '>')) {
362
- ?>
363
-
364
- <?php
365
- } else {
366
- ?>
367
- &times;
368
- <span
369
- class="installation_item_message"><?php _e("Landing Pages requires PHP 5 or above.", "gravityforms"); ?></span>
370
- <?php
371
- }
372
- ?>
373
- </td>
374
- </tr>
375
- <tr valign="top">
376
- <th scope="row"><label><?php _e('MySQL Version', 'inbound-pro'); ?></label></th>
377
- <td class="installation_item_cell">
378
- <strong><?php echo $wpdb->db_version(); ?></strong>
379
- </td>
380
- <td>
381
- <?php
382
- if (version_compare($wpdb->db_version(), '5.0.0', '>')) {
383
- ?>
384
-
385
- <?php
386
- } else {
387
- ?>
388
- &times;
389
- <span
390
- class="installation_item_message"><?php _e("Gravity Forms requires MySQL 5 or above.", "gravityforms"); ?></span>
391
- <?php
392
- }
393
- ?>
394
- </td>
395
- </tr>
396
- <tr valign="top">
397
- <th scope="row"><label><?php _e('WordPress Version', 'inbound-pro'); ?></label></th>
398
- <td class="installation_item_cell">
399
- <strong><?php echo get_bloginfo("version"); ?></strong>
400
- </td>
401
- <td>
402
- <?php
403
- if (version_compare(get_bloginfo("version"), '3.6', '>')) {
404
- ?>
405
-
406
- <?php
407
- } else {
408
- ?>
409
- &times;
410
- <span
411
- class="installation_item_message"><?php _e('landing pages requires version X or higher', 'inbound-pro'); ?></span>
412
- <?php
413
- }
414
- ?>
415
- </td>
416
- </tr>
417
- <tr valign="top">
418
- <th scope="row"><label><?php _e('Landing Page Version', 'inbound-pro'); ?></label></th>
419
- <td class="installation_item_cell">
420
- <strong><?php _e('Version', 'inbound-pro'); ?><?php echo LANDINGPAGES_CURRENT_VERSION; ?></strong>
421
- </td>
422
- <td>
423
-
424
- </td>
425
- </tr>
426
- </table>
427
- </div>
428
- <div id="inbound-sys-info">
429
- <span id="in-sys-info"></span>
430
- </div>
431
- <div id="htaccess-contents">
432
-
433
- <?php if ($htaccess != "") {
434
- echo "<h3>" . __('The contents of your .htaccess file', 'inbound-pro') . ":</h3>";
435
- echo $htaccess;
436
- } ?>
437
- </div>
438
- </div>
439
- <?php
440
- }
441
-
442
- public static function display_system_info($hook) {
443
- global $wpdb;
444
- $screen = get_current_screen();
445
-
446
- if ($screen->id != 'landing-page_page_lp_global_settings') {
447
- return;
448
- }
449
-
450
- if (get_bloginfo('version') < '3.4') {
451
- $theme_data = get_theme_data(get_stylesheet_directory() . '/style.css');
452
- $theme = $theme_data['Name'] . ' ' . $theme_data['Version'];
453
- } else {
454
- $theme_data = wp_get_theme();
455
- $theme = $theme_data->Name . ' ' . $theme_data->Version;
456
- }
457
-
458
- /* Try to identifty the hosting provider */
459
- $host = false;
460
- if (defined('WPE_APIKEY')) {
461
- $host = 'WP Engine';
462
- } elseif (defined('PAGELYBIN')) {
463
- $host = 'Pagely';
464
- }
465
-
466
- ?>
467
-
468
- <form id="sys-inbound-form"
469
- action="<?php echo esc_url(admin_url('edit.php?post_type=landing-page&page=lp_global_settings')); ?>"
470
- method="post" dir="ltr">
471
- <h2><?php _e('System Information', 'inboundnow') ?></h2>
472
- <input type="hidden" name="inbound-action" value="inbound-download-sysinfo"/>
473
- <style type="text/css">#inbound-download-sysinfo {
474
- display: none;
475
- }</style>
476
- <?php submit_button(__('Download System Info File for Support Requests', 'inboundnow'), 'primary', 'inbound-download-sysinfo', false); ?>
477
- <textarea readonly="readonly" onclick="this.focus();this.select()" id="copy-inbound-info"
478
- name="landing_pages_sysinfo"
479
- title="<?php _e('To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac).', 'edd'); ?>">
480
- ### Begin System Info ###
481
-
482
- ## Please include this information when posting support requests ##
483
-
484
- Multisite: <?php echo is_multisite() ? 'Yes' . "\n" : 'No' . "\n" ?>
485
-
486
- SITE_URL: <?php echo site_url() . "\n"; ?>
487
- HOME_URL: <?php echo home_url() . "\n"; ?>
488
-
489
- Landing Page Version: <?php echo LANDINGPAGES_CURRENT_VERSION . "\n"; ?>
490
- Upgraded From: <?php echo get_option('lp_version_upgraded_from', 'None') . "\n"; ?>
491
- WordPress Version: <?php echo get_bloginfo('version') . "\n"; ?>
492
- Permalink Structure: <?php echo get_option('permalink_structure') . "\n"; ?>
493
- Active Theme: <?php echo $theme . "\n"; ?>
494
- <?php if ($host) : ?>
495
- Host: <?php echo $host . "\n"; ?>
496
- <?php endif; ?>
497
-
498
- Registered Post Stati: <?php echo implode(', ', get_post_stati()) . "\n\n"; ?>
499
-
500
- PHP Version: <?php echo PHP_VERSION . "\n"; ?>
501
- MySQL Version: <?php
502
- $con=mysqli_connect("localhost","my_user","my_password","my_db");
503
-
504
- if (mysqli_connect_errno()) {
505
- echo "Failed to connect to MySQL: " . mysqli_connect_error(). "\n";
506
- }
507
-
508
- echo mysqli_get_server_info($con). "\n";
509
-
510
- ?>
511
- Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
512
-
513
- PHP Safe Mode: <?php echo ini_get('safe_mode') ? "Yes" : "No\n"; ?>
514
- PHP Memory Limit: <?php echo ini_get('memory_limit') . "\n"; ?>
515
- PHP Upload Max Size: <?php echo ini_get('upload_max_filesize') . "\n"; ?>
516
- PHP Post Max Size: <?php echo ini_get('post_max_size') . "\n"; ?>
517
- PHP Upload Max Filesize: <?php echo ini_get('upload_max_filesize') . "\n"; ?>
518
- PHP Time Limit: <?php echo ini_get('max_execution_time') . "\n"; ?>
519
- PHP Max Input Vars: <?php echo ini_get('max_input_vars') . "\n"; ?>
520
-
521
- WP_DEBUG: <?php echo defined('WP_DEBUG') ? WP_DEBUG ? 'Enabled' . "\n" : 'Disabled' . "\n" : 'Not set' . "\n" ?>
522
-
523
- WP Table Prefix: <?php echo "Length: " . strlen($wpdb->prefix);
524
- echo " Status:";
525
- if (strlen($wpdb->prefix) > 16) {
526
- echo " ERROR: Too Long";
527
- } else {
528
- echo " Acceptable";
529
- }
530
- echo "\n"; ?>
531
-
532
- Show On Front: <?php echo get_option('show_on_front') . "\n" ?>
533
- Page On Front: <?php $id = get_option('page_on_front');
534
- echo get_the_title($id) . ' (#' . $id . ')' . "\n" ?>
535
- Page For Posts: <?php $id = get_option('page_for_posts');
536
- echo get_the_title($id) . ' (#' . $id . ')' . "\n" ?>
537
-
538
- Session: <?php echo isset($_SESSION) ? 'Enabled' : 'Disabled'; ?><?php echo "\n"; ?>
539
- Session Name: <?php echo esc_html(ini_get('session.name')); ?><?php echo "\n"; ?>
540
- Cookie Path: <?php echo esc_html(ini_get('session.cookie_path')); ?><?php echo "\n"; ?>
541
- Save Path: <?php echo esc_html(ini_get('session.save_path')); ?><?php echo "\n"; ?>
542
- Use Cookies: <?php echo ini_get('session.use_cookies') ? 'On' : 'Off'; ?><?php echo "\n"; ?>
543
- Use Only Cookies: <?php echo ini_get('session.use_only_cookies') ? 'On' : 'Off'; ?><?php echo "\n"; ?>
544
-
545
- WordPress Memory Limit: NA
546
- DISPLAY ERRORS: <?php echo (ini_get('display_errors')) ? 'On (' . ini_get('display_errors') . ')' : 'N/A'; ?><?php echo "\n"; ?>
547
- FSOCKOPEN: <?php echo (function_exists('fsockopen')) ? __('Your server supports fsockopen.', 'edd') : __('Your server does not support fsockopen.', 'edd'); ?><?php echo "\n"; ?>
548
- cURL: <?php echo (function_exists('curl_init')) ? __('Your server supports cURL.', 'edd') : __('Your server does not support cURL.', 'edd'); ?><?php echo "\n"; ?>
549
- SOAP Client: <?php echo (class_exists('SoapClient')) ? __('Your server has the SOAP Client enabled.', 'edd') : __('Your server does not have the SOAP Client enabled.', 'edd'); ?><?php echo "\n"; ?>
550
- SUHOSIN: <?php echo (extension_loaded('suhosin')) ? __('Your server has SUHOSIN installed.', 'edd') : __('Your server does not have SUHOSIN installed.', 'edd'); ?><?php echo "\n"; ?>
551
-
552
- - INSTALLED LP TEMPLATES:
553
- <?php
554
- /* Show templates that have been copied to the theme's edd_templates dir */
555
- $dir = LANDINGPAGES_UPLOADS_PATH . '/*';
556
- if (!empty($dir)) {
557
- foreach (glob($dir) as $file) {
558
- echo "Template: " . basename($file) . "\n";
559
- }
560
- } else {
561
- echo 'No overrides found';
562
- }
563
- ?>
564
-
565
- - ACTIVE PLUGINS:
566
- <?php
567
- $plugins = get_plugins();
568
- $active_plugins = get_option('active_plugins', array());
569
-
570
- foreach ($plugins as $plugin_path => $plugin) {
571
- /* If the plugin isn't active, don't show it. */
572
- if (!in_array($plugin_path, $active_plugins)) continue;
573
-
574
- echo $plugin['Name'] . ': ' . $plugin['Version'] . "\n";
575
- }
576
-
577
- if (is_multisite()) {
578
- ?>
579
-
580
- - NETWORK ACTIVE PLUGINS:
581
-
582
- <?php
583
- $plugins = wp_get_active_network_plugins();
584
- $active_plugins = get_site_option('active_sitewide_plugins', array());
585
-
586
- foreach ($plugins as $plugin_path) {
587
- $plugin_base = plugin_basename($plugin_path);
588
-
589
- /* If the plugin isn't active, don't show it. */
590
- if (!array_key_exists($plugin_base, $active_plugins)) continue;
591
-
592
- $plugin = get_plugin_data($plugin_path);
593
-
594
- echo $plugin['Name'] . ' :' . $plugin['Version'] . "\n";
595
- }
596
-
597
- }
598
-
599
-
600
- ?>
601
-
602
- ### End System Info ###</textarea>
603
- </form>
604
- <?php
605
- }
606
-
607
- /**
608
- * download sytem info - Not sure this is hooked into anything
609
- */
610
- public static function download_system_info() {
611
-
612
- if (isset($_POST['inbound-action']) && $_POST['inbound-action'] === 'inbound-download-sysinfo') {
613
- nocache_headers();
614
- header( "Content-type: text/plain" );
615
- header( 'Content-Disposition: attachment; filename="inbound-system-info.txt"' );
616
-
617
- echo wp_strip_all_tags( $_POST['landing_pages_sysinfo'] );
618
- wp_die('');
619
- }
620
-
621
- }
622
-
623
- /**
624
- * Saves global settings
625
- */
626
- public static function save_stand_alone_settings() {
627
-
628
- $lp_global_settings = self::get_stand_alone_settings();
629
-
630
- if (!isset($_POST['nature'])) {
631
- return;
632
- }
633
-
634
- foreach ($lp_global_settings as $key => $data) {
635
- $tab_settings = $lp_global_settings[$key]['settings'];
636
-
637
- /* loop through fields and save the data */
638
- foreach ($tab_settings as $field) {
639
-
640
- $field['id'] = $key . "-" . $field['id'];
641
-
642
- if (array_key_exists('option_name', $field) && $field['option_name']) {
643
- $field['id'] = $field['option_name'];
644
- }
645
-
646
- if ($field['id'] == 'lp-main-landing-page-permalink-prefix') {
647
- /*echo "here"; */
648
- global $wp_rewrite;
649
- $wp_rewrite->flush_rules();
650
- }
651
- if ($field['type']=='inboundnow-license-key') {
652
- if (defined('INBOUND_ACCESS_LEVEL') ) {
653
- return;
654
- }
655
- /* error_log(print_r($field, true)); */
656
- $slug = (isset($field['remote_download_slug'])) ? $field['remote_download_slug'] : $field['slug'];
657
- $api_params = array(
658
- 'edd_action' => 'inbound_check_license',
659
- 'license' => sanitize_text_field($_POST['inboundnow_master_license_key']),
660
- 'item_name' => $slug
661
- );
662
-
663
- /* Call the edd API */
664
- $response = wp_remote_get(add_query_arg($api_params, INBOUNDNOW_STORE_URL ), array('timeout' => 30, 'sslverify' => false));
665
-
666
- /* make sure the response came back okay */
667
- if (is_wp_error($response)) {
668
- break;
669
- }
670
-
671
- /* decode the license data */
672
- $license_data = json_decode(wp_remote_retrieve_body($response));
673
-
674
-
675
- /* $license_data->license will be either "active" or "inactive" */
676
- update_option('lp_license_status-' . $field['slug'], $license_data->license);
677
- } else {
678
- if (isset($_POST[$field['id']])) {
679
- update_option($field['id'], sanitize_text_field($_POST[$field['id']]));
680
- }
681
- }
682
-
683
-
684
- do_action('lp_save_global_settings', $field);
685
- }
686
- }
687
- }
688
-
689
- /**
690
- * Render Settings
691
- * @param $key
692
- * @param $custom_fields
693
- * @param $active_tab
694
- */
695
- public static function render_stand_alone_settings($key, $custom_fields, $active_tab) {
696
- if (!$custom_fields) {
697
- return;
698
- }
699
-
700
- $master_license_key = get_option('inboundnow_master_license_key', '');
701
-
702
- if ($key == $active_tab) {
703
- $display = 'block';
704
- } else {
705
- $display = 'none';
706
- }
707
-
708
- /*echo $display; */
709
-
710
- /* Use nonce for verification */
711
- echo "<input type='hidden' name='lp_{$key}_custom_fields_nonce' value='" . wp_create_nonce('lp-nonce') . "' />";
712
-
713
- /* Begin the field table and loop */
714
- echo '<table class="lp-tab-display" id="' . $key . '" style="display:' . $display . '">';
715
- /*print_r($custom_fields);exit; */
716
- foreach ($custom_fields as $field) {
717
-
718
- /* get value of this field if it exists for this post */
719
- if (isset($field['default'])) {
720
- $default = $field['default'];
721
- } else {
722
- $default = null;
723
-
724
- }
725
-
726
- $field['id'] = $key . "-" . $field['id'];
727
-
728
- if (array_key_exists('option_name', $field) && $field['option_name']) $field['id'] = $field['option_name'];
729
-
730
- $field['value'] = get_option($field['id'], $default);
731
-
732
- /* begin a table row with */
733
- echo '<tr><th class="lp-gs-th" valign="top" style="font-weight:300;">';
734
- if ($field['type'] == 'header') {
735
- echo '<h4>' . $field['default'] . '</h4>';
736
- } else {
737
- echo '<div class="inbound-setting-label tooltip" title="' . $field['description'] . '">' . $field['label'] . '</div>';
738
- }
739
- echo '</th><td>';
740
-
741
- switch ($field['type']) {
742
- /* text */
743
- case 'colorpicker':
744
- if (!$field['value']) {
745
- $field['value'] = $field['default'];
746
- }
747
- echo '<input type="text" class="jpicker" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . $field['value'] . '" size="5" />';
748
- continue 2;
749
- case 'datepicker':
750
- echo '<input id="datepicker-example2" class="Zebra_DatePicker_Icon" type="text" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . $field['value'] . '" size="8" />';
751
- continue 2;
752
- case 'inboundnow-license-key':
753
-
754
- if (defined('INBOUND_PRO_PATH')) {
755
- continue;
756
- }
757
-
758
- if ($master_license_key) {
759
- $field['value'] = $master_license_key;
760
- $input_type = 'hidden';
761
- } else {
762
- $input_type = 'text';
763
- }
764
-
765
-
766
- $license_status = self::check_license_status($field);
767
-
768
- echo '<input type="' . $input_type . '" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . $field['value'] . '" size="30" />';
769
-
770
-
771
- echo '<input type="hidden" name="lp_license_status-' . $field['slug'] . '" id="' . $field['id'] . '" value="' . $license_status . '" size="30" />';
772
-
773
- if ($license_status == 'valid') {
774
- echo '<div class="lp_license_status_valid">Enabled</div>';
775
- } else {
776
- echo '<div class="lp_license_status_invalid">Disabled</div>';
777
- }
778
-
779
- continue 2;
780
- case 'text':
781
- echo '<input type="text" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . $field['value'] . '" size="30" class="" />';
782
- continue 2;
783
- /* textarea */
784
- case 'textarea':
785
- echo '<textarea name="' . $field['id'] . '" id="' . $field['id'] . '" cols="106" rows="6"></textarea>';
786
- continue 2;
787
- /* wysiwyg */
788
- case 'wysiwyg':
789
- wp_editor($field['value'], $field['id'], $settings = array());
790
- echo '<span class="description">' . $field['description'] . '</span><br><br>';
791
- continue 2;
792
- /* media */
793
- case 'media':
794
- /*echo 1; exit; */
795
- echo '<label for="upload_image">';
796
- echo '<input name="' . $field['id'] . '" id="' . $field['id'] . '" type="text" size="36" name="upload_image" value="' . $field['value'] . '" />';
797
- echo '<input data-field-id="' . $field['id'] . '" class="upload_image_button" id="uploader_' . $field['id'] . '" type="button" value="'. __( 'Upload Image' , 'inbound-pro' ) .'"/>';
798
- continue 2;
799
- /* checkbox */
800
- case 'checkbox':
801
- $i = 1;
802
- echo "<table>";
803
- if (!isset($field['value'])) {
804
- $field['value'] = array();
805
- } elseif (!is_array($field['value'])) {
806
- $field['value'] = array($field['value']);
807
- }
808
- foreach ($field['options'] as $value => $label) {
809
- if ($i == 5 || $i == 1) {
810
- echo "<tr>";
811
- $i = 1;
812
- }
813
- echo '<td><input type="checkbox" name="' . $field['id'] . '[]" id="' . $field['id'] . '" value="' . $value . '" ', in_array($value, $field['value']) ? ' checked="checked"' : '', ' class="tooltip tool_text" title="' . $field['description'] . '" />';
814
- echo '<label for="' . $value . '">&nbsp;&nbsp;' . $label . '</label></td>';
815
- if ($i == 4) {
816
- echo "</tr>";
817
- }
818
- $i++;
819
- }
820
- echo "</table>";
821
- continue 2;
822
- /* radio */
823
- case 'radio':
824
- foreach ($field['options'] as $value => $label) {
825
- /*echo $meta.":".$field['id'] ; */
826
- /*echo "<br>"; */
827
- echo '<input type="radio" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . $value . '" ', $field['value'] == $value ? ' checked="checked"' : '', ' class="tooltip tool_radio" title="' . $field['description'] . '" />';
828
- echo '<label for="' . $value . '">&nbsp;&nbsp;' . $label . '</label> &nbsp;&nbsp;&nbsp;&nbsp;';
829
- }
830
- continue 2;
831
- /* select */
832
- case 'dropdown':
833
- echo '<select name="' . $field['id'] . '" id="' . $field['id'] . '">';
834
- foreach ($field['options'] as $value => $label) {
835
- echo '<option', $field['value'] == $value ? ' selected="selected"' : '', ' value="' . $value . '">' . $label . '</option>';
836
- }
837
- echo '</select>';
838
- continue 2;
839
- case 'html':
840
- echo $field['default'];
841
- continue 2;
842
-
843
-
844
- } /*end switch */
845
-
846
- do_action('lp_render_global_settings', $field);
847
-
848
- echo '</td></tr>';
849
- } /* end foreach */
850
- echo '</table>'; /* end table */
851
- }
852
-
853
- /**
854
- * Check license status
855
- * @param $field
856
- * @return bool|string
857
- */
858
- public static function check_license_status($field) {
859
-
860
- $license_status = get_option('lp_license_status-' . $field['slug']);
861
-
862
- if ( $license_status == 'valid') {
863
- return "valid";
864
- } else {
865
- return "invalid";
866
- }
867
- }
868
- }
869
-
870
- new Landing_Pages_Settings;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.sidebars.php DELETED
@@ -1,102 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class sets up landing page sidebar for holding conversion areas when 'default' template is selected.
5
- * @package LandingPages
6
- * @subpackage Sidebars
7
- */
8
-
9
- class Landing_Pages_Sidebars {
10
-
11
- /**
12
- * initiate class
13
- */
14
- public function __construct() {
15
- self::add_hooks();
16
- }
17
-
18
- /**
19
- * load hooks and filters
20
- */
21
- public static function add_hooks() {
22
- add_action('init', array( __CLASS__ , 'register_sidebars' ) , 100 );
23
- add_action('wp_head', array( __CLASS__ , 'replace_sidebars' ) );
24
- }
25
-
26
- /**
27
- * Register sidebars
28
- */
29
- public static function register_sidebars() {
30
- if (function_exists('register_sidebar')) {
31
- register_sidebar( array(
32
- 'id' => 'lp_sidebar',
33
- 'name' => __('Landing Pages Sidebar', 'landing-pages'),
34
- 'description' => __('Landing Pages Sidebar Area: For default and native theme templates only.', 'landing-pages'),
35
- 'before_widget' => '<div id="%1$s" class="widget %2$s">',
36
- 'after_widget' => '</div>',
37
- 'before_title' => '<h3 class="widget-title">',
38
- 'after_title' => '</h3>',
39
- 'priority' => 10
40
- ));
41
- }
42
- }
43
-
44
- /**
45
- * Replaces default template's side bar with landing page sidebar
46
- */
47
- public static function replace_sidebars() {
48
-
49
- global $_wp_sidebars_widgets, $post, $wp_registered_sidebars, $wp_registered_widgets;
50
-
51
- if ( !isset($post) || $post->post_type != 'landing-page') {
52
- return;
53
- }
54
-
55
- $whitelist = array('sidebar-1','sidebar-left','primary','default','blog','sidebar-right','blog-sidebar','left-sidebar','right-sidebar');
56
-
57
- /* get correct registered widget */
58
- $registered_widget_id = 'id_lp_conversion_area_widget-1';
59
- foreach ($wp_registered_widgets as $key => $array ) {
60
- if (strstr($key , 'id_lp_conversion_area_widget')) {
61
- $registered_widget_id = $key;
62
- break;
63
- }
64
- }
65
-
66
- if (!is_active_sidebar('lp_sidebar')) {
67
- $active_widgets = get_option('sidebars_widgets');
68
-
69
- if (!isset($active_widgets['lp_sidebar']) || !$active_widgets['lp_sidebar'] ) {
70
- $active_widgets['lp_sidebar'] = array($registered_widget_id);
71
- $_wp_sidebars_widgets['lp_sidebar'] = $active_widgets['lp_sidebar'];
72
- update_option('sidebars_widgets', $active_widgets);
73
- }
74
- }
75
-
76
-
77
- $count = 0;
78
- $found = 0;
79
- foreach ($_wp_sidebars_widgets as $key => $val) {
80
-
81
- foreach ($whitelist as $item) {
82
-
83
- if (strpos($key, $item) !== FALSE || $key == 'sidebar') {
84
- $_wp_sidebars_widgets['wp_inactive_widgets'] = array();
85
- $_wp_sidebars_widgets[$key] = $_wp_sidebars_widgets['lp_sidebar'];
86
- $found = 1;
87
- }
88
- }
89
- if (!$found && $count===0) {
90
- $_wp_sidebars_widgets[$key] = $_wp_sidebars_widgets['lp_sidebar'];
91
- }
92
- $count++;
93
- }
94
-
95
- /* error_log(print_r($wp_registered_widgets,true)); */
96
- /* error_log(print_r($_wp_sidebars_widgets,true)); */
97
-
98
-
99
- }
100
- }
101
-
102
- new Landing_Pages_Sidebars;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.split-testing-stats.php DELETED
@@ -1,217 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class contains methods related to split testing statistics
5
- * @package LandingPages
6
- * @subpackage Tracking
7
- */
8
-
9
- class Landing_Pages_Split_Testing_Stats {
10
-
11
- /**
12
- * Initiate class
13
- */
14
- public function __construct() {
15
- self::load_hooks();
16
- }
17
-
18
- /**
19
- * load hooks and filters
20
- */
21
- public static function load_hooks() {
22
-
23
- /* adds page impression to split testing statistics */
24
- add_action( 'lp_record_impression' , array( __CLASS__ , 'record_impression' ) , 10, 3);
25
-
26
- /* adds landing page conversion to split testing statistics */
27
- add_action( 'inbound_track_link', array(__CLASS__, 'record_conversion'));
28
-
29
- /* adds landing page conversion to split testing statistics */
30
- add_filter( 'inboundnow_store_lead_pre_filter_data' , array( __CLASS__ , 'record_conversion' ) ,10,1);
31
-
32
- }
33
-
34
- /**
35
- * Records landing page & non landing page impression
36
- * @param $post_id
37
- * @param string $post_type
38
- * @param int $variation_id
39
- */
40
- public static function record_impression($post_id, $post_type , $variation_id = 0) {
41
-
42
- /* ignore mshots and previews from admin area */
43
- if (strstr( $_SERVER['HTTP_REFERER'] , 'edit.php?post_type=landing-page' )) {
44
- return;
45
- }
46
- if (strstr( $_SERVER['HTTP_REFERER'] , 'post.php' )) {
47
- return;
48
- }
49
- if (strstr( $_SERVER['HTTP_REFERER'] , 'edit.php' )) {
50
- return;
51
- }
52
-
53
- /* If Landing Page Post Type */
54
- if ( $post_type == 'landing-page' ) {
55
- $impressions = Landing_Pages_Variations::get_impressions( $post_id, $variation_id );
56
- $impressions++;
57
- Landing_Pages_Variations::set_impressions_count( $post_id, $variation_id, $impressions );
58
- }
59
- /* If Non Landing Page Post Type */
60
- else {
61
- $impressions = Landing_Pages_Split_Testing_Stats::get_impressions_count( $post_id );
62
- $impressions++;
63
- Landing_Pages_Split_Testing_Stats::set_impressions_count( $post_id, $impressions );
64
- }
65
- }
66
-
67
- /**
68
- * Records lead creation events and link click events as split testing conversion
69
- * @param $data
70
- */
71
- public static function record_conversion($data) {
72
-
73
- if (!isset( $data['page_id'] ) ) {
74
- return $data;
75
- }
76
-
77
- /* this filter is used by Inbound Pro to check if visitor's ip is on a not track list */
78
- $do_not_track = apply_filters('inbound_analytics_stop_track' , false );
79
-
80
- if ( $do_not_track ) {
81
- return $data;
82
- }
83
-
84
- $post_type = get_post_type($data['page_id']);
85
- $data['vid'] = (isset($data['vid'])) ? $data['vid'] : 0;
86
- $data['vid'] = (isset($data['variation'])) ? $data['variation'] : $data['vid'];
87
-
88
- if (current_filter() == 'inbound_track_link' && $post_type != 'landing-page' ) {
89
- return;
90
- } else if ($post_type === 'landing-page' ) {
91
- $data['vid'] = (isset($data['lp-variation-id'])) ? $data['lp-variation-id'] : $data['vid']; $data['vid'];
92
- $conversions = Landing_Pages_Variations::get_conversions( $data['page_id'] , $data['vid'] );
93
- $conversions++;
94
- Landing_Pages_Variations::set_conversions_count( $data['page_id'] , $data['vid'] , $conversions );
95
- }
96
- /* increment conversions for non landing pages */
97
- else {
98
- $conversions = Landing_Pages_Split_Testing_Stats::get_conversions_count( $data['page_id'] );
99
- $conversions++;
100
- Landing_Pages_Split_Testing_Stats::set_conversions_count( $data['page_id'] , $conversions );
101
- }
102
-
103
- return $data;
104
- }
105
-
106
- /**
107
- * Register Columns
108
- */
109
- public static function register_columns( $cols ) {
110
-
111
- $cols['inbound_impressions'] = __( 'Impressions' , 'inbound-email' );
112
- $cols['inbound_conversions'] = __( 'Conversions' , 'inbound-email' );
113
- $cols['inbound_conversion_rate'] = __( 'Conversion Rate' , 'inbound-email' );
114
-
115
- return $cols;
116
- }
117
-
118
- /**
119
- * Prepare Column Data
120
- */
121
- public static function prepare_column_data( $column , $post_id ) {
122
- global $post;
123
-
124
- switch ($column) {
125
- case "inbound_impressions":
126
- echo self::get_impressions_count( $post->ID );
127
- break;
128
- case "inbound_conversions":
129
- echo self::get_conversions_count( $post->ID );
130
- break;
131
- case "inbound_conversion_rate":
132
- echo self::get_conversion_rate( $post->ID);
133
- break;
134
- }
135
- }
136
-
137
-
138
- /**
139
- * Returns impression count for non landing pages. See Landing_Pages_Variations class for retrieving landing page statistics
140
- *
141
- * @param INT $post_id id of call to action
142
- *
143
- * @return INT impression count
144
- */
145
- public static function get_impressions_count( $post_id ) {
146
-
147
- $impressions = get_post_meta( $post_id , '_inbound_impressions_count' , true);
148
-
149
- if (!is_numeric($impressions)) {
150
- $impressions = 0;
151
- }
152
-
153
- return $impressions;
154
- }
155
-
156
- /**
157
- * Returns conversion count for non landing page. See Landing_Pages_Variations class for retrieving landing page statistics
158
- *
159
- * @param INT $post_id id
160
- *
161
- * @return INT impression count
162
- */
163
- public static function get_conversions_count( $post_id ) {
164
-
165
-
166
- $conversions = get_post_meta( $post_id , '_inbound_conversions_count' , true);
167
-
168
- if (!is_numeric($conversions)) {
169
- $conversions = 0;
170
- }
171
-
172
- return $conversions;
173
- }
174
-
175
- /**
176
- * Returns conversion count for non landing page. See Landing_Pages_Variations class for retrieving landing page statistics
177
- *
178
- * @param INT $post_id id
179
- *
180
- * @return INT
181
- */
182
- public static function get_conversion_rate( $post_id ) {
183
-
184
- $impressions = Landing_Pages_Split_Testing_Stats::get_impressions_count( $post_id );
185
- $conversions = Landing_Pages_Split_Testing_Stats::get_conversions_count( $post_id );
186
-
187
- if ($impressions > 0) {
188
- $conversion_rate = $conversions / $impressions;
189
- $conversion_rate_number = $conversion_rate * 100;
190
- $conversion_rate_number = round($conversion_rate_number, 2);
191
- $conversion_rate = $conversion_rate_number;
192
- } else {
193
- $conversion_rate = 0;
194
- }
195
-
196
- return $conversion_rate;
197
- }
198
-
199
-
200
- /**
201
- * Set impression count
202
- */
203
- public static function set_impressions_count( $post_id , $count ) {
204
- update_post_meta( $post_id, '_inbound_impressions_count', $count );
205
- }
206
-
207
- /**
208
- * Set conversion count
209
- */
210
- public static function set_conversions_count( $post_id , $count ) {
211
- update_post_meta( $post_id, '_inbound_conversions_count', $count );
212
- }
213
-
214
- }
215
-
216
-
217
- new Landing_Pages_Split_Testing_Stats;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.store.php DELETED
@@ -1,33 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class adds prompts to upgrade to Inbound Pro when user is using GPL Landing Pages. Also will be foundation for template installation engine once we phase out all free templates from core.
5
- * @package LandingPages
6
- * @subpackage NeedsAttention
7
- */
8
- class Inbound_Now_Store {
9
-
10
- /**
11
- *
12
- */
13
- public static function store_display() {
14
-
15
- /* normal display here */
16
- self::store_redirect();
17
-
18
- }
19
-
20
- /**
21
- *
22
- */
23
- public static function store_redirect() { ?>
24
- <script>
25
-
26
- window.location = "https://www.inboundnow.com/upgrade";
27
-
28
- </script>
29
- <?php
30
- }
31
- }
32
-
33
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.template-management.php DELETED
@@ -1,413 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class for managing and installing landing page templates manually. This feature is redundant for Inbound Pro subscribers using 1-click-installations.
5
- * @package LandingPages
6
- * @subpackage Templates
7
- */
8
-
9
- class Landing_Pages_Template_Management {
10
-
11
- public function __construct() {
12
- self::load_hooks();
13
- self::load_views();
14
- }
15
-
16
- /**
17
- * Loads hooks and filters
18
- */
19
- public static function load_hooks() {
20
- add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_admin_scripts_manage'));
21
- add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_admin_scripts_upload'));
22
-
23
- /* create hidden pages for template upload management */
24
- add_action('admin_menu', array( __CLASS__ , 'create_pages' ) );
25
- }
26
-
27
-
28
- /**
29
- * Add support for additional pages
30
- */
31
- public static function create_pages() {
32
-
33
- if ( !current_user_can('manage_options') ) {
34
- return;
35
- }
36
-
37
- global $_registered_pages;
38
-
39
- $hookname = get_plugin_page_hookname('lp_templates_upload', 'edit.php?post_type=landing-page');
40
- if (!empty($hookname)) {
41
- add_action($hookname, 'lp_templates_upload');
42
- }
43
- $_registered_pages[$hookname] = true;
44
-
45
- $hookname = get_plugin_page_hookname('lp_templates_search', 'edit.php?post_type=landing-page');
46
- /*echo $hookname;exit; */
47
- if (!empty($hookname)) {
48
- add_action($hookname, 'lp_templates_search');
49
- }
50
- $_registered_pages[$hookname] = true;
51
-
52
- }
53
-
54
- /**
55
- * Enqueue admin scripts for Template Manager
56
- */
57
- public static function enqueue_admin_scripts_manage() {
58
- $screen = get_current_screen();
59
-
60
- if ($screen->base != 'landing-page_page_lp_manage_templates') {
61
- return;
62
- }
63
-
64
- wp_enqueue_style( 'lp-css-templates' , LANDINGPAGES_URLPATH . 'assets/css/admin-templates.css', array() , null);
65
- wp_enqueue_script( 'lp-js-templates' , LANDINGPAGES_URLPATH . 'assets/js/admin/admin.templates.js', array() , null);
66
- }
67
-
68
- /**
69
- * Enqueue admin scripts for Template Uploader
70
- */
71
- public static function enqueue_admin_scripts_upload() {
72
- $screen = get_current_screen();
73
-
74
- if ($screen->base != 'landing-landing-page_page_lp_templates_upload') {
75
- return;
76
- }
77
-
78
- wp_enqueue_script( 'lp-js-templates-upload' , LANDINGPAGES_URLPATH . 'assets/js/admin/admin.templates-upload.js', array() , null);
79
- }
80
-
81
- /**
82
- * Renders the correct views
83
- */
84
- public static function load_views() {
85
-
86
- }
87
-
88
- /**
89
- * Display Template List Table
90
- */
91
- public static function display_template_management_view() {
92
- self::run_management_actions();
93
-
94
- echo '<div class="wrap">';
95
- ?>
96
-
97
- <h2><?php _e( 'Manage Templates' , 'inbound-pro' ); ?>
98
- <a href="edit.php?post_type=landing-page&page=lp_templates_upload"
99
- class="add-new-h2"><?php echo esc_html_x('Add New Template', 'landing-pages'); ?></a>
100
- </h2>
101
- <?php
102
-
103
- $myListTable = new Landing_Pages_Templates_List_Table();
104
- $myListTable->prepare_items();
105
- ?>
106
- <form method="post">
107
- <input type="hidden" name="page" value="my_list_test"/>
108
- <?php $myListTable->search_box('search', 'search_id'); ?>
109
- </form>
110
- <form method="post" id='bulk_actions'>
111
-
112
- <?php
113
- $myListTable->display();
114
-
115
- echo '</div></form>';
116
- }
117
-
118
- /**
119
- * Displays template upload view
120
- */
121
- public static function display_upload_view() {
122
- self::run_upload_actions();
123
- self::display_upload_prompt();
124
- self::display_template_search();
125
- }
126
-
127
- /**
128
- * Performs template management actions
129
- */
130
- public static function run_management_actions() {
131
- if (!isset($_REQUEST['action'])) {
132
- return;
133
- }
134
-
135
- switch ($_REQUEST['action']):
136
- case 'upgrade':
137
- if (count($_REQUEST['template']) > 0) {
138
- foreach ($_REQUEST['template'] as $key => $slug) {
139
- self::action_upgrade_template( $slug );
140
- }
141
- }
142
- break;
143
- case 'delete':
144
- if (count($_REQUEST['template']) > 0) {
145
-
146
- foreach ($_REQUEST['template'] as $key => $slug) {
147
- self::delete_template(LANDINGPAGES_UPLOADS_PATH . $slug, $slug);
148
- }
149
- }
150
- break;
151
- endswitch;
152
-
153
-
154
- echo('<meta http-equiv="refresh" content="0;url=edit.php?post_type=landing-page&page=lp_manage_templates">');
155
- exit;
156
- }
157
-
158
- /**
159
- * Performs template upload action
160
- */
161
- public static function run_upload_actions() {
162
-
163
- if (!$_FILES || !wp_verify_nonce($_POST["lp_wpnonce"], 'lp-nonce')) {
164
- return;
165
- }
166
-
167
- $name = $_FILES['templatezip']['name'];
168
- $name = preg_replace('/\((.*?)\)/', '', $name);
169
- $name = str_replace(array(' ', '.zip'), '', $name);
170
- $name = trim($name);
171
-
172
- include_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
173
-
174
- $zip = new PclZip($_FILES['templatezip']["tmp_name"]);
175
-
176
- $uploads = wp_upload_dir();
177
- $uploads_path = $uploads['basedir'];
178
- $extended_path = $uploads_path . '/landing-pages/templates/';
179
- if (!is_dir($extended_path)) {
180
- wp_mkdir_p($extended_path);
181
- }
182
-
183
- if (($list = $zip->listContent()) == 0) {
184
- die("There was a problem. Please try again!");
185
- }
186
-
187
- $is_template = false;
188
- foreach ($list as $key => $val) {
189
- foreach ($val as $k => $v) {
190
- if (strstr($v, '/config.php')) {
191
- $is_template = true;
192
- break;
193
- } else if (strstr($v, 'config.php')) {
194
- $misconfig = 1;
195
- }else if ($is_template == true) {
196
- break;
197
- }
198
- }
199
- }
200
-
201
- if (!$is_template) {
202
- echo '<br><br><br><br>';
203
- if ($misconfig) {
204
- die( __('We\'ve detected that this is a landing page template, but the files need to be zipped inside the parent folder. Please restructure your zip file so that it\'s contents are inside a parent directory with your template\'s name.' , 'inbound-pro' ));
205
-
206
- } else {
207
- die( __('WARNING! This zip file does not seem to be a template file! If you are trying to install a Landing Page extension please use the Plugin\'s upload section! Please press the back button and try again!' , 'inbound-pro' ));
208
- }
209
- }
210
-
211
-
212
- if ($result = $zip->extract(PCLZIP_OPT_PATH, $extended_path, PCLZIP_OPT_REPLACE_NEWER) == 0) {
213
- die( __( 'There was a problem. Please try again!' , 'inbound-pro' ) );
214
- } else {
215
- unlink($_FILES['templatezip']["tmp_name"]);
216
- echo '<div class="updated"><p>' . __( 'Template uploaded successfully!' , 'inbound-pro' ) . '</div>';
217
- }
218
- }
219
-
220
- /**
221
- * Display upload prompt
222
- */
223
- public static function display_upload_prompt() {
224
- require_once (ABSPATH .'wp-includes/pluggable.php');
225
- ?>
226
- <div class="wrap templates_upload">
227
- <div class="icon32" id="icon-plugins"><br></div><h2><?php _e( 'Install Templates' , 'landing-pages'); ?></h2>
228
-
229
- <ul class="subsubsub">
230
- <li class="plugin-install-manager"><a href="<?php echo admin_url('edit.php?post_type=landing-page&page=lp_manage_templates' ); ?>" id='manage'><?php _e( 'Back' ,'landing-pages'); ?></a> |</li>
231
- <li class="plugin-install-dashboard"><a target="_blank" href="https://www.inboundnow.com/market/?show=landing-pages" id='menu_search'><?php _e( 'Find New Templates' ,'landing-pages'); ?></a> |</li>
232
- <li class="plugin-install-upload"><a class="current" href="#upload" id='menu_upload'><?php _e( 'Upload' , 'landing-pages'); ?></a> </li>
233
- </ul>
234
-
235
- <br class="clear">
236
- <h4><?php _e('Install Landing Pages template by uploading them here in .zip format' , 'inbound-pro'); ?></h4>
237
-
238
- <p class="install-help"><?php _e( 'Warning: Do not upload landing page extensions here or you will break the plugin! <br>Extensions are uploaded in the WordPress plugins section.' , 'inbound-pro'); ?></p>
239
- <form action="" class="wp-upload-form" enctype="multipart/form-data" method="post">
240
- <input type="hidden" value="<?php echo wp_create_nonce('lp-nonce'); ?>" name="lp_wpnonce" id="_wpnonce">
241
- <input type="hidden" value="/wp-admin/plugin-install.php?tab=upload" name="_wp_http_referer">
242
- <label for="pluginzip" class="screen-reader-text"><?php _e( 'Template zip file' , 'inbound-pro'); ?></label>
243
- <input type="file" name="templatezip" id="templatezip">
244
- <input type="submit" value="Install Now" class="button" id="install-template-submit" name="install-template-submit" disabled="">
245
- </form>
246
- </div>
247
- <?php
248
- }
249
-
250
- /**
251
- * Display template search input
252
- */
253
- public static function display_template_search() {
254
- ?>
255
-
256
- <div class="wrap templates_search" style='display:none'>
257
- <div class="icon32" id="icon-plugins"><br></div><h2><?php _e( 'Search Templates' , 'inbound-pro'); ?></h2>
258
-
259
- <ul class="subsubsub">
260
- <li class="plugin-install-dashboard"><a href="#search" id='menu_search'><?php _e( 'Search' , 'inbound-pro'); ?></a> |</li>
261
- <li class="plugin-install-upload"><a class="current" href="#upload" id='menu_upload'><?php _e( 'Upload' , 'inbound-pro'); ?></a> </li>
262
- </ul>
263
-
264
- <br class="clear">
265
- <p class="install-help"><?php _e( 'Search the Inboundnow marketplace for free and premium templates.' , 'inbound-pro'); ?></p>
266
- <form action="edit.php?post_type=landing-page&page=lp_store" method="POST" id="">
267
- <input type="search" autofocus="autofocus" value="" name="search">
268
- <label for="plugin-search-input" class="screen-reader-text"><?php _e( 'Search Templates' , 'inbound-pro'); ?></label>
269
- <input type="submit" value="Search Templates" class="button" id="plugin-search-input" name="plugin-search-input">
270
- </form>
271
- </div>
272
-
273
- <?php
274
- }
275
-
276
- /**
277
- * Perform action: upgrade ticket
278
- * @param $slug
279
- */
280
- public static function action_upgrade_template( $slug ) {
281
- global $lp_data;
282
- $data = $lp_data[$slug]['info'];
283
- $item['ID'] = $slug;
284
- $item['template'] = $slug;
285
- $item['name'] = $data['label'];
286
- $item['category'] = $data['category'];
287
- $item['description'] = $data['description'];
288
-
289
- $response = self::poll_api($item);
290
- $package = $response['package'];
291
- IF (!isset($package) || empty($package)) return;
292
-
293
- $zip_array = wp_remote_get( $package , array( 'timeout' => 60 , 'sslverify' => false ) );
294
-
295
- ($zip_array['response']['code'] == 200) ? $zip = $zip_array['body'] : die("<div class='error'><p>{$slug}: Invalid download location (Version control not provided).</p></div>");
296
-
297
- $uploads = wp_upload_dir();
298
- $uploads_dir = $uploads['path'];
299
-
300
- $temp = ini_get('upload_tmp_dir');
301
- if (empty($temp)) {
302
- $temp = "/tmp";
303
- }
304
-
305
- $file_path = $temp . "/" . $slug . ".zip";
306
-
307
-
308
- file_put_contents($file_path, $zip);
309
-
310
- include_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
311
-
312
- $zip = new PclZip($file_path);
313
- $uploads = wp_upload_dir();
314
- $uploads_path = $uploads['basedir'];
315
- $extended_path = $uploads_path . '/landing-pages/templates/';
316
-
317
-
318
- if (!is_dir($extended_path)) {
319
- wp_mkdir_p($extended_path);
320
- }
321
-
322
- $result = $zip->extract(PCLZIP_OPT_PATH, $extended_path, PCLZIP_OPT_REPLACE_NEWER);
323
-
324
- if (!$result) {
325
- die("There was a problem. Please try again!");
326
- } else {
327
- /*print_r($result);exit; */
328
- unlink($file_path);
329
- echo '<div class="updated"><p>' . $data['label'] . ' upgraded successfully!</div>';
330
- }
331
- }
332
-
333
- /**
334
- * Action: delete template
335
- */
336
- public static function delete_template($dir, $slug) {
337
- global $lp_data;
338
- $data = $lp_data[$slug];
339
-
340
- if (!file_exists($dir)) {
341
- return true;
342
- }
343
-
344
- if (!is_dir($dir) || is_link($dir)) {
345
- return unlink($dir);
346
- }
347
-
348
- foreach (scandir($dir) as $item) {
349
- if ($item == '.' || $item == '..') {
350
- continue;
351
- }
352
-
353
- if (!self::delete_template($dir . "/" . $item, $slug)) {
354
-
355
- chmod($dir . "/" . $item, 0777);
356
-
357
- if (!self::delete_template($dir . "/" . $item, $slug)) {
358
- return false;
359
- }
360
- };
361
- }
362
- return rmdir($dir);
363
-
364
-
365
- echo '<div class="updated"><p>' . $data['label'] . ' deleted successfully!</div>';
366
- }
367
-
368
- /**
369
- * Check Inbound Now API to see if template is ready for an update
370
- * @param $item
371
- * @return bool
372
- */
373
- public static function poll_api( $item ) {
374
- $api_params = array('edd_action' => 'get_version', 'license' => get_option('lp-license-keys-' . $item['ID']), 'name' => $item['name'], 'slug' => $item['ID'], 'nature' => 'template',);
375
-
376
- $request = wp_remote_post(LANDINGPAGES_STORE_URL, array('timeout' => 15, 'sslverify' => false, 'body' => $api_params));
377
-
378
- if (!is_wp_error($request)) {
379
-