WordPress Landing Pages - Version 2.3.2

Version Description

  • Adding support for Inbound Forms without redirect URLs (no ajax)
Download this release

Release Info

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

Code changes from version 2.2.9 to 2.3.2

Files changed (289) hide show
  1. {trunk/assets → assets}/tests/build/php.conf +0 -0
  2. {trunk/assets → assets}/tests/build/php.load +0 -0
  3. {trunk/assets → assets}/tests/build/travis-ci-apache +0 -0
  4. {trunk/assets → assets}/tests/codeception/_bootstrap.php +0 -0
  5. {trunk/assets → assets}/tests/codeception/_data/dump.sql +0 -0
  6. {trunk/assets → assets}/tests/codeception/_support/AcceptanceHelper.php +0 -0
  7. {trunk/assets → assets}/tests/codeception/_support/FunctionalHelper.php +0 -0
  8. {trunk/assets → assets}/tests/codeception/_support/UnitHelper.php +0 -0
  9. {trunk/assets → assets}/tests/codeception/acceptance/AcceptanceTester.php +0 -0
  10. {trunk/assets → assets}/tests/codeception/acceptance/LoginCept.php +0 -0
  11. {trunk/assets → assets}/tests/codeception/acceptance/StatisticsCept.php +0 -0
  12. {trunk/assets → assets}/tests/codeception/acceptance/WelcomeCept.php +0 -0
  13. {trunk/assets → assets}/tests/codeception/acceptance/_bootstrap.php +0 -0
  14. {trunk/assets → assets}/tests/codeception/functional/FunctionalTester.php +0 -0
  15. {trunk/assets → assets}/tests/codeception/functional/_bootstrap.php +0 -0
  16. {trunk/assets → assets}/tests/codeception/unit/UnitTester.php +0 -0
  17. {trunk/assets → assets}/tests/codeception/unit/_bootstrap.php +0 -0
  18. {trunk/assets → assets}/tests/phpunit/bootstrap.php +0 -0
  19. {trunk/assets → assets}/tests/phpunit/test.activations.php +0 -0
  20. {trunk/assets → assets}/tests/travis-ci/test.statistics.php +0 -0
  21. classes/class.activation.upgrade-routines.php +114 -34
  22. classes/class.admin-menus.php +18 -3
  23. classes/class.load-extensions.php +0 -46
  24. classes/class.post-type.landing-page.php +9 -5
  25. classes/{class.cloning.php → class.row-actions.php} +25 -2
  26. classes/class.settings.php +88 -33
  27. classes/class.welcome.php +1 -1
  28. classes/class.wp-list-table.templates.php +9 -5
  29. landing-pages.php +6 -5
  30. modules/module.redirect-ab-testing.php +147 -155
  31. readme.txt +4 -1
  32. shared/assets/js/frontend/analytics-src/analytics.events.js +61 -1
  33. shared/assets/js/frontend/analytics-src/analytics.forms.js +20 -3
  34. shared/assets/js/frontend/analytics/inboundAnalytics.js +82 -4
  35. shared/assets/js/frontend/analytics/inboundAnalytics.min.js +2 -2
  36. shared/assets/plugins/acf-field-date-time-picker/acf-date-time-picker.php +62 -0
  37. shared/assets/plugins/acf-field-date-time-picker/date-time-picker-v3.php +514 -0
  38. shared/assets/plugins/acf-field-date-time-picker/date-time-picker-v4.php +472 -0
  39. shared/assets/plugins/acf-field-date-time-picker/js/timepicker.js +131 -148
  40. shared/classes/class.acf-bootstrap.php +1 -1
  41. shared/classes/class.compatibility.php +0 -134
  42. shared/classes/class.events.php +78 -8
  43. shared/classes/class.form.php +92 -45
  44. shared/classes/class.inbound-api.php +23 -4
  45. shared/classes/class.lead-storage.php +16 -18
  46. shared/classes/class.licensing.php +1 -188
  47. shared/classes/class.load-shared.php +0 -1
  48. shared/docs/analytics.events.md +14 -0
  49. shared/shortcodes/inbound-shortcodes.php +2 -0
  50. shared/shortcodes/js/shortcodes.js +20 -3
  51. shared/shortcodes/js/spin.min.js +2 -0
  52. shared/shortcodes/shortcodes-fields.php +6 -4
  53. shared/shortcodes/shortcodes/button.php +1 -1
  54. shared/shortcodes/shortcodes/forms.php +2 -2
  55. trunk/.gitignore +0 -59
  56. trunk/Gruntfile.js +0 -19
  57. trunk/LICENSE +0 -339
  58. trunk/README.md +0 -359
  59. trunk/assets/css/admin-ab-testing.css +0 -311
  60. trunk/assets/css/admin-post-edit.css +0 -212
  61. trunk/assets/css/admin-post-new.css +0 -110
  62. trunk/assets/css/admin-templates.css +0 -48
  63. trunk/assets/css/admin-tour.css +0 -216
  64. trunk/assets/css/admin/acf-hide-wp-elements.css +0 -1
  65. trunk/assets/css/admin/content-stats.css +0 -87
  66. trunk/assets/css/admin/customizer-edit.css +0 -247
  67. trunk/assets/css/admin/edit-landing-page.css +0 -108
  68. trunk/assets/css/admin/global-settings.css +0 -231
  69. trunk/assets/css/admin/install-plugins.css +0 -13
  70. trunk/assets/css/admin/landing-page-edit-style.css +0 -542
  71. trunk/assets/css/admin/landing-page-list.css +0 -492
  72. trunk/assets/css/customizer-load.css +0 -76
  73. trunk/assets/css/customizer.frontend.css +0 -157
  74. trunk/assets/css/customizer.media-uploader.css +0 -34
  75. trunk/assets/css/frontend/customizer-preview.css +0 -1
  76. trunk/assets/css/frontend/global-landing-page-style.css +0 -43
  77. trunk/assets/css/frontend/index.php +0 -2
  78. trunk/assets/css/iframe-preview.css +0 -3
  79. trunk/assets/css/images/dropdownback.png +0 -0
  80. trunk/assets/css/images/headerback.png +0 -0
  81. trunk/assets/css/images/hover.png +0 -0
  82. trunk/assets/css/images/index.php +0 -2
  83. trunk/assets/css/images/linkback.png +0 -0
  84. trunk/assets/css/images/question-light.png +0 -0
  85. trunk/assets/css/images/tooltip.png +0 -0
  86. trunk/assets/css/index.php +0 -2
  87. trunk/assets/images/ab-retina-icons.png +0 -0
  88. trunk/assets/images/add-on-image.png +0 -0
  89. trunk/assets/images/cta-install.png +0 -0
  90. trunk/assets/images/custom-setup-image.png +0 -0
  91. trunk/assets/images/get-custom-setup.png +0 -0
  92. trunk/assets/images/get-wordpress-templates.png +0 -0
  93. trunk/assets/images/github-help.jpg +0 -0
  94. trunk/assets/images/image.php +0 -76
  95. trunk/assets/images/index.php +0 -2
  96. trunk/assets/images/leads-install.png +0 -0
  97. trunk/assets/images/localhost.png +0 -0
  98. trunk/assets/images/templates-image.png +0 -0
  99. trunk/assets/images/variation-normal.png +0 -0
  100. trunk/assets/images/variation-up.png +0 -0
  101. trunk/assets/js/admin/admin.global-settings.js +0 -73
  102. trunk/assets/js/admin/admin.install-plugins.js +0 -30
  103. trunk/assets/js/admin/admin.landing-page-list.js +0 -117
  104. trunk/assets/js/admin/admin.metaboxes.js +0 -1
  105. trunk/assets/js/admin/admin.post-edit-ab-testing.js +0 -64
  106. trunk/assets/js/admin/admin.post-edit.js +0 -322
  107. trunk/assets/js/admin/admin.post-new.js +0 -144
  108. trunk/assets/js/admin/admin.post.js +0 -35
  109. trunk/assets/js/admin/admin.templates-upload.js +0 -25
  110. trunk/assets/js/admin/admin.templates.js +0 -1
  111. trunk/assets/js/admin/index.php +0 -2
  112. trunk/assets/js/admin/intro.js +0 -758
  113. trunk/assets/js/admin/tour/tour.post-edit.js +0 -9
  114. trunk/assets/js/admin/tour/tour.post-list.js +0 -8
  115. trunk/assets/js/ajax.clearstats.js +0 -1
  116. trunk/assets/js/index.php +0 -2
  117. trunk/assets/js/jquery.bindfirst.js +0 -15
  118. trunk/assets/js/jquery.cookie.js +0 -1
  119. trunk/assets/js/jquery.easing.min.js +0 -44
  120. trunk/assets/js/jquery.form-population.js +0 -1
  121. trunk/assets/js/jquery.lp.cookie.js +0 -1
  122. trunk/assets/js/jquery.tablesorter.js +0 -1031
  123. trunk/assets/js/jquery.total-storage.min.js +0 -22
  124. trunk/assets/js/stop_page_stats.js +0 -7
  125. trunk/assets/js/wordpress/editor.min.js +0 -1
  126. trunk/assets/js/wordpress/index.php +0 -2
  127. trunk/assets/lang/.tx/config +0 -7
  128. trunk/assets/lang/landing-pages-ach.mo +0 -0
  129. trunk/assets/lang/landing-pages-af.mo +0 -0
  130. trunk/assets/lang/landing-pages-an.mo +0 -0
  131. trunk/assets/lang/landing-pages-ar.mo +0 -0
  132. trunk/assets/lang/landing-pages-as.mo +0 -0
  133. trunk/assets/lang/landing-pages-az.mo +0 -0
  134. trunk/assets/lang/landing-pages-be.mo +0 -0
  135. trunk/assets/lang/landing-pages-be_BY.mo +0 -0
  136. trunk/assets/lang/landing-pages-bg.mo +0 -0
  137. trunk/assets/lang/landing-pages-bg_BG.mo +0 -0
  138. trunk/assets/lang/landing-pages-bn_BD.mo +0 -0
  139. trunk/assets/lang/landing-pages-br.mo +0 -0
  140. trunk/assets/lang/landing-pages-bs.mo +0 -0
  141. trunk/assets/lang/landing-pages-bs_BA.mo +0 -0
  142. trunk/assets/lang/landing-pages-ca.mo +0 -0
  143. trunk/assets/lang/landing-pages-co.mo +0 -0
  144. trunk/assets/lang/landing-pages-cs_CZ.mo +0 -0
  145. trunk/assets/lang/landing-pages-cy.mo +0 -0
  146. trunk/assets/lang/landing-pages-da_DK.mo +0 -0
  147. trunk/assets/lang/landing-pages-de_AT.mo +0 -0
  148. trunk/assets/lang/landing-pages-de_CH.mo +0 -0
  149. trunk/assets/lang/landing-pages-de_DE.mo +0 -0
  150. trunk/assets/lang/landing-pages-dv.mo +0 -0
  151. trunk/assets/lang/landing-pages-el.mo +0 -0
  152. trunk/assets/lang/landing-pages-en@pirate.mo +0 -0
  153. trunk/assets/lang/landing-pages-en_AU.mo +0 -0
  154. trunk/assets/lang/landing-pages-en_CA.mo +0 -0
  155. trunk/assets/lang/landing-pages-en_GB.mo +0 -0
  156. trunk/assets/lang/landing-pages-eo.mo +0 -0
  157. trunk/assets/lang/landing-pages-es_AR.mo +0 -0
  158. trunk/assets/lang/landing-pages-es_CL.mo +0 -0
  159. trunk/assets/lang/landing-pages-es_ES.mo +0 -0
  160. trunk/assets/lang/landing-pages-es_MX.mo +0 -0
  161. trunk/assets/lang/landing-pages-es_PE.mo +0 -0
  162. trunk/assets/lang/landing-pages-es_US.mo +0 -0
  163. trunk/assets/lang/landing-pages-es_VE.mo +0 -0
  164. trunk/assets/lang/landing-pages-et.mo +0 -0
  165. trunk/assets/lang/landing-pages-eu.mo +0 -0
  166. trunk/assets/lang/landing-pages-fa.mo +0 -0
  167. trunk/assets/lang/landing-pages-fa_IR.mo +0 -0
  168. trunk/assets/lang/landing-pages-fi.mo +0 -0
  169. trunk/assets/lang/landing-pages-fil.mo +0 -0
  170. trunk/assets/lang/landing-pages-fo.mo +0 -0
  171. trunk/assets/lang/landing-pages-fr_BE.mo +0 -0
  172. trunk/assets/lang/landing-pages-fr_FR.mo +0 -0
  173. trunk/assets/lang/landing-pages-fy.mo +0 -0
  174. trunk/assets/lang/landing-pages-ga.mo +0 -0
  175. trunk/assets/lang/landing-pages-gd.mo +0 -0
  176. trunk/assets/lang/landing-pages-gl_ES.mo +0 -0
  177. trunk/assets/lang/landing-pages-gu_IN.mo +0 -0
  178. trunk/assets/lang/landing-pages-he_IL.mo +0 -0
  179. trunk/assets/lang/landing-pages-hi_IN.mo +0 -0
  180. trunk/assets/lang/landing-pages-hr.mo +0 -0
  181. trunk/assets/lang/landing-pages-hu_HU.mo +0 -0
  182. trunk/assets/lang/landing-pages-hy.mo +0 -0
  183. trunk/assets/lang/landing-pages-id.mo +0 -0
  184. trunk/assets/lang/landing-pages-id_ID.mo +0 -0
  185. trunk/assets/lang/landing-pages-is_IS.mo +0 -0
  186. trunk/assets/lang/landing-pages-it_CH.mo +0 -0
  187. trunk/assets/lang/landing-pages-it_IT.mo +0 -0
  188. trunk/assets/lang/landing-pages-ja.mo +0 -0
  189. trunk/assets/lang/landing-pages-jv.mo +0 -0
  190. trunk/assets/lang/landing-pages-ka.mo +0 -0
  191. trunk/assets/lang/landing-pages-ka_GE.mo +0 -0
  192. trunk/assets/lang/landing-pages-kk.mo +0 -0
  193. trunk/assets/lang/landing-pages-km.mo +0 -0
  194. trunk/assets/lang/landing-pages-kn.mo +0 -0
  195. trunk/assets/lang/landing-pages-ko_KR.mo +0 -0
  196. trunk/assets/lang/landing-pages-ku.mo +0 -0
  197. trunk/assets/lang/landing-pages-ky.mo +0 -0
  198. trunk/assets/lang/landing-pages-landing-pages - Copy.mo +0 -0
  199. trunk/assets/lang/landing-pages-landing-pages.mo +0 -0
  200. trunk/assets/lang/landing-pages-lo.mo +0 -0
  201. trunk/assets/lang/landing-pages-lt_LT.mo +0 -0
  202. trunk/assets/lang/landing-pages-lv.mo +0 -0
  203. trunk/assets/lang/landing-pages-mg.mo +0 -0
  204. trunk/assets/lang/landing-pages-mk_MK.mo +0 -0
  205. trunk/assets/lang/landing-pages-mn.mo +0 -0
  206. trunk/assets/lang/landing-pages-mr.mo +0 -0
  207. trunk/assets/lang/landing-pages-ms_MY.mo +0 -0
  208. trunk/assets/lang/landing-pages-my_MM.mo +0 -0
  209. trunk/assets/lang/landing-pages-nb_NO.mo +0 -0
  210. trunk/assets/lang/landing-pages-nds.mo +0 -0
  211. trunk/assets/lang/landing-pages-ne_NP.mo +0 -0
  212. trunk/assets/lang/landing-pages-nl.mo +0 -0
  213. trunk/assets/lang/landing-pages-nl_NL.mo +0 -0
  214. trunk/assets/lang/landing-pages-nn_NO.mo +0 -0
  215. trunk/assets/lang/landing-pages-oc.mo +0 -0
  216. trunk/assets/lang/landing-pages-os.mo +0 -0
  217. trunk/assets/lang/landing-pages-pap.mo +0 -0
  218. trunk/assets/lang/landing-pages-pl_PL.mo +0 -0
  219. trunk/assets/lang/landing-pages-ps.mo +0 -0
  220. trunk/assets/lang/landing-pages-pt_BR.mo +0 -0
  221. trunk/assets/lang/landing-pages-pt_PT.mo +0 -0
  222. trunk/assets/lang/landing-pages-ro_RO.mo +0 -0
  223. trunk/assets/lang/landing-pages-ru_RU.mo +0 -0
  224. trunk/assets/lang/landing-pages-sah.mo +0 -0
  225. trunk/assets/lang/landing-pages-si_LK.mo +0 -0
  226. trunk/assets/lang/landing-pages-sk_SK.mo +0 -0
  227. trunk/assets/lang/landing-pages-sl_SI.mo +0 -0
  228. trunk/assets/lang/landing-pages-so.mo +0 -0
  229. trunk/assets/lang/landing-pages-sq.mo +0 -0
  230. trunk/assets/lang/landing-pages-sr_RS.mo +0 -0
  231. trunk/assets/lang/landing-pages-su.mo +0 -0
  232. trunk/assets/lang/landing-pages-sv_SE.mo +0 -0
  233. trunk/assets/lang/landing-pages-sw.mo +0 -0
  234. trunk/assets/lang/landing-pages-ta_IN.mo +0 -0
  235. trunk/assets/lang/landing-pages-ta_LK.mo +0 -0
  236. trunk/assets/lang/landing-pages-te.mo +0 -0
  237. trunk/assets/lang/landing-pages-tg.mo +0 -0
  238. trunk/assets/lang/landing-pages-th.mo +0 -0
  239. trunk/assets/lang/landing-pages-tk_TM.mo +0 -0
  240. trunk/assets/lang/landing-pages-tl.mo +0 -0
  241. trunk/assets/lang/landing-pages-tr_TR.mo +0 -0
  242. trunk/assets/lang/landing-pages-tzm.mo +0 -0
  243. trunk/assets/lang/landing-pages-ug.mo +0 -0
  244. trunk/assets/lang/landing-pages-uk.mo +0 -0
  245. trunk/assets/lang/landing-pages-ur.mo +0 -0
  246. trunk/assets/lang/landing-pages-ur_PK.mo +0 -0
  247. trunk/assets/lang/landing-pages-uz.mo +0 -0
  248. trunk/assets/lang/landing-pages-vi.mo +0 -0
  249. trunk/assets/lang/landing-pages-zh_CN.GB2312.mo +0 -0
  250. trunk/assets/lang/landing-pages-zh_CN.mo +0 -0
  251. trunk/assets/lang/landing-pages-zh_HK.mo +0 -0
  252. trunk/assets/lang/landing-pages-zh_TW.mo +0 -0
  253. trunk/assets/lang/landing-pages.mo +0 -0
  254. trunk/assets/lang/landing-pages.po +0 -22
  255. trunk/assets/libraries/class-tgm-plugin-activation.php +0 -3541
  256. trunk/assets/libraries/datetimepicker/MIT-LICENSE.txt +0 -19
  257. trunk/assets/libraries/datetimepicker/README.md +0 -28
  258. trunk/assets/libraries/datetimepicker/bower.json +0 -52
  259. trunk/assets/libraries/datetimepicker/datetimepicker.jquery.json +0 -47
  260. trunk/assets/libraries/datetimepicker/jquery.datetimepicker.css +0 -545
  261. trunk/assets/libraries/datetimepicker/jquery.datetimepicker.js +0 -2073
  262. trunk/assets/libraries/datetimepicker/package.json +0 -28
  263. trunk/assets/libraries/datetimepicker/picker_functions.js +0 -56
  264. trunk/assets/libraries/easyXDM.debug.js +0 -1
  265. trunk/assets/libraries/index.php +0 -2
  266. trunk/assets/libraries/jpicker/css/jPicker-1.1.6.css +0 -232
  267. trunk/assets/libraries/jpicker/css/jPicker-1.1.6.min.css +0 -1
  268. trunk/assets/libraries/jpicker/css/jPicker.css +0 -17
  269. trunk/assets/libraries/jpicker/images/AlphaBar.png +0 -0
  270. trunk/assets/libraries/jpicker/images/Bars.png +0 -0
  271. trunk/assets/libraries/jpicker/images/Maps.png +0 -0
  272. trunk/assets/libraries/jpicker/images/NoColor.png +0 -0
  273. trunk/assets/libraries/jpicker/images/bar-opacity.png +0 -0
  274. trunk/assets/libraries/jpicker/images/map-opacity.png +0 -0
  275. trunk/assets/libraries/jpicker/images/mappoint.gif +0 -0
  276. trunk/assets/libraries/jpicker/images/picker.gif +0 -0
  277. trunk/assets/libraries/jpicker/images/preview-opacity.png +0 -0
  278. trunk/assets/libraries/jpicker/images/rangearrows.gif +0 -0
  279. trunk/assets/libraries/jpicker/jpicker-1.1.6.min.js +0 -1
  280. trunk/assets/libraries/jquery.zoomer.js +0 -441
  281. trunk/assets/libraries/script.js +0 -36
  282. trunk/assets/libraries/shareme/index.php +0 -2
  283. trunk/assets/libraries/shareme/library.shareme.php +0 -1
  284. trunk/assets/libraries/shareme/sharrre/index.php +0 -2
  285. trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.js +0 -584
  286. trunk/assets/libraries/shareme/sharrre/jquery.sharrre-1.3.3.min.js +0 -1
  287. trunk/classes/class.acf-integration.php +0 -654
  288. trunk/classes/class.activation.php +0 -293
  289. trunk/classes/class.activation.upgrade-routines.php +0 -100
{trunk/assets → assets}/tests/build/php.conf RENAMED
File without changes
{trunk/assets → assets}/tests/build/php.load RENAMED
File without changes
{trunk/assets → assets}/tests/build/travis-ci-apache RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/_bootstrap.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/_data/dump.sql RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/_support/AcceptanceHelper.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/_support/FunctionalHelper.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/_support/UnitHelper.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/acceptance/AcceptanceTester.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/acceptance/LoginCept.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/acceptance/StatisticsCept.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/acceptance/WelcomeCept.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/acceptance/_bootstrap.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/functional/FunctionalTester.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/functional/_bootstrap.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/unit/UnitTester.php RENAMED
File without changes
{trunk/assets → assets}/tests/codeception/unit/_bootstrap.php RENAMED
File without changes
{trunk/assets → assets}/tests/phpunit/bootstrap.php RENAMED
File without changes
{trunk/assets → assets}/tests/phpunit/test.activations.php RENAMED
File without changes
{trunk/assets → assets}/tests/travis-ci/test.statistics.php RENAMED
File without changes
classes/class.activation.upgrade-routines.php CHANGED
@@ -7,27 +7,6 @@ if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
7
 
8
  class Landing_Pages_Activation_Update_Routines {
9
 
10
- /*
11
- * @introduced: 1.8.9
12
- * @migration-type: Meta pair migragtion
13
- * @migration: Make a meta pair copy of wp_content into 'content' meta key for variation 0 to use (refactor session)
14
- * @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. *
15
- */
16
- public static function prepare_content_meta_key_for_variation_0() {
17
-
18
- /* for all landing pages load variations */
19
- $landing_pages = get_posts( array (
20
- 'post_type' => 'landing-page',
21
- 'posts_per_page' => -1
22
- ));
23
-
24
- /* loop through landing pages and copy post content into meta object */
25
- foreach ($landing_pages as $post) {
26
- $content = $post->post_content;
27
- update_post_meta( $post->ID , 'content' , $content);
28
- }
29
- }
30
-
31
 
32
  /*
33
  * @introduced: 1.5.7
@@ -36,6 +15,13 @@ if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
36
  */
37
  public static function migrate_legacy_conversion_area_contents() {
38
 
 
 
 
 
 
 
 
39
  /* for all landing pages load variations */
40
  $landing_pages = get_posts( array (
41
  'post_type' => 'landing-page',
@@ -75,17 +61,6 @@ if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
75
  }
76
  }
77
 
78
- /*
79
- * @introduced: 1.7.5
80
- * @migration-type: Meta key rename
81
- * @migration: renames all instances of inbound_conversion_data to _inbound_conversion_data
82
-
83
- */
84
- public static function meta_key_change_conversion_object() {
85
- global $wpdb;
86
-
87
- $wpdb->query("UPDATE $wpdb->postmeta SET `meta_key` = REPLACE (`meta_key` , 'inbound_conversion_data', '_inbound_conversion_data')");
88
- }
89
 
90
  /*
91
  * @introduced: 1.5.7
@@ -95,6 +70,13 @@ if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
95
  */
96
  public static function migrate_legacy_main_content() {
97
 
 
 
 
 
 
 
 
98
  /* for all landing pages load variations */
99
  $landing_pages = get_posts( array (
100
  'post_type' => 'landing-page',
@@ -134,11 +116,20 @@ if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
134
  }
135
 
136
  /*
137
- * UPDATE METHOD
138
- * Moves legacy templates to uploads folder
 
 
139
  */
140
  public static function updater_move_legacy_templates() {
141
 
 
 
 
 
 
 
 
142
  /* move copy of legacy core templates to the uploads folder and delete from core templates directory */
143
  $templates_to_move = array('rsvp-envelope','super-slick');
144
  chmod(LANDINGPAGES_UPLOADS_PATH, 0755);
@@ -213,6 +204,54 @@ if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
213
  }
214
  }
215
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  /*
217
  * @introduced: 2.0.4
218
  * @migration-type: Meta pair migragtion
@@ -222,6 +261,13 @@ if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
222
  */
223
  public static function migrate_variation_status_metapair() {
224
 
 
 
 
 
 
 
 
225
  /* for all landing pages load variations */
226
  $landing_pages = get_posts( array (
227
  'post_type' => 'landing-page',
@@ -241,6 +287,40 @@ if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
241
  }
242
  }
243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  }
245
 
246
  }
7
 
8
  class Landing_Pages_Activation_Update_Routines {
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  /*
12
  * @introduced: 1.5.7
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',
61
  }
62
  }
63
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  /*
66
  * @introduced: 1.5.7
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',
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);
204
  }
205
  }
206
 
207
+
208
+ /*
209
+ * @introduced: 1.7.5
210
+ * @migration-type: Meta key rename
211
+ * @migration: renames all instances of inbound_conversion_data to _inbound_conversion_data
212
+
213
+ */
214
+ public static function meta_key_change_conversion_object() {
215
+ global $wpdb;
216
+
217
+ /* ignore if not applicable */
218
+ $previous_installed_version = get_transient('lp_current_version');
219
+
220
+ if ( version_compare($previous_installed_version , "1.7.5") === 1 ) {
221
+ return;
222
+ }
223
+
224
+ $wpdb->query("UPDATE $wpdb->postmeta SET `meta_key` = REPLACE (`meta_key` , 'inbound_conversion_data', '_inbound_conversion_data')");
225
+ }
226
+
227
+ /*
228
+ * @introduced: 1.8.9
229
+ * @migration-type: Meta pair migragtion
230
+ * @migration: Make a meta pair copy of wp_content into 'content' meta key for variation 0 to use (refactor session)
231
+ * @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. *
232
+ */
233
+ public static function prepare_content_meta_key_for_variation_0() {
234
+
235
+ /* ignore if not applicable */
236
+ $previous_installed_version = get_transient('lp_current_version');
237
+
238
+ if ( version_compare($previous_installed_version , "1.8.9") === 1 ) {
239
+ return;
240
+ }
241
+
242
+ /* for all landing pages load variations */
243
+ $landing_pages = get_posts( array (
244
+ 'post_type' => 'landing-page',
245
+ 'posts_per_page' => -1
246
+ ));
247
+
248
+ /* loop through landing pages and copy post content into meta object */
249
+ foreach ($landing_pages as $post) {
250
+ $content = $post->post_content;
251
+ update_post_meta( $post->ID , 'content' , $content);
252
+ }
253
+ }
254
+
255
  /*
256
  * @introduced: 2.0.4
257
  * @migration-type: Meta pair migragtion
261
  */
262
  public static function migrate_variation_status_metapair() {
263
 
264
+ /* ignore if not applicable */
265
+ $previous_installed_version = get_transient('lp_current_version');
266
+
267
+ if ( version_compare($previous_installed_version , "2.0.4") === 1 ) {
268
+ return;
269
+ }
270
+
271
  /* for all landing pages load variations */
272
  $landing_pages = get_posts( array (
273
  'post_type' => 'landing-page',
287
  }
288
  }
289
 
290
+
291
+ /*
292
+ * @introduced: 2.3.1
293
+ * @migration-type: Inbound Pro Setting Migration
294
+ * @migration: mirgrates option lp-main-landing-page-permalink-prefix to $inbound_settings['landing-pages']['landing-page-permalink-prefix']
295
+ * @migration: mirgrates option lp-main-landing-page-rotation-halt to $inbound_settings['landing-pages']['landing-page-rotation-halt']
296
+ * @migration: mirgrates option lp-main-landing-page-disable-turn-off-ab to $inbound_settings['landing-pages']['landing-page-disable-turn-off-ab']
297
+ */
298
+ public static function migrate_landing_page_settings_to_pro_settings() {
299
+
300
+ /* ignore if not applicable */
301
+ $previous_installed_version = get_transient('lp_current_version');
302
+
303
+ if ( version_compare($previous_installed_version , "2.3.1") === 1 ) {
304
+ return;
305
+ }
306
+
307
+ if (!defined('INBOUND_PRO_CURRENT_VERSION')) {
308
+ return;
309
+ }
310
+
311
+ global $inbound_settings;
312
+
313
+ $landing_page_permalink_prefix = get_option( 'lp-main-landing-page-permalink-prefix', 'go' );
314
+ $sticky_variations = get_option( 'lp-main-landing-page-rotation-halt', '0' );
315
+ $disable_variant_testing = get_option( 'lp-main-landing-page-disable-turn-off-ab', '0' );
316
+
317
+ $inbound_settings['landing-pages']['landing-page-permalink-prefix'] = $landing_page_permalink_prefix;
318
+ $inbound_settings['landing-pages']['landing-page-rotation-halt'] = $sticky_variations;
319
+ $inbound_settings['landing-pages']['landing-page-disable-turn-off-ab'] = $disable_variant_testing;
320
+
321
+ Inbound_Options_API::update_option( 'inbound-pro' , 'settings' , $inbound_settings );
322
+ }
323
+
324
  }
325
 
326
  }
classes/class.admin-menus.php CHANGED
@@ -18,6 +18,7 @@ class Landing_Pages_Admin_Menus {
18
  */
19
  public static function add_hooks() {
20
  add_action('admin_menu', array(__CLASS__, 'add_sub_menus') );
 
21
  }
22
 
23
  /**
@@ -26,16 +27,30 @@ class Landing_Pages_Admin_Menus {
26
  public static function add_sub_menus() {
27
 
28
  /* add_submenu_page('edit.php?post_type=landing-page', __('Forms', 'landing-pages'), __('Forms', 'landing-pages'), 'edit_landing_pages', 'inbound-forms-redirect', 100); */
29
-
30
- 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'));
31
-
32
  if ( !class_exists('Inbound_Pro_Plugin') ) {
 
33
  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);
 
 
34
  }
35
 
36
  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);
37
 
38
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
40
 
41
  new Landing_Pages_Admin_Menus;
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
  /**
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;
classes/class.load-extensions.php CHANGED
@@ -26,8 +26,6 @@ class Landing_Pages_Load_Extensions {
26
  /* Modifies legacy template data key names for old, un-updated legacy templates */
27
  add_filter('lp_extension_data', array(__CLASS__, 'add_legacy_data_support'), 10, 1);
28
 
29
- /* Add license key inputs to all uploaded templates */
30
- add_filter('lp_define_global_settings', array(__CLASS__, 'prepare_license_keys'), 99, 1);
31
  }
32
 
33
  /**
@@ -74,50 +72,6 @@ class Landing_Pages_Load_Extensions {
74
  return $data;
75
  }
76
 
77
- /**
78
- * Adds licensing & automatic updates to uploaded templates
79
- *
80
- * @param ARRAY $global_settings contains all global setting data
81
- *
82
- * @retuns ARRAY $global_settings contains modified global setting data
83
- */
84
- public static function prepare_license_keys($global_settings) {
85
-
86
- if (!is_admin()) {
87
- return;
88
- }
89
-
90
- $lp_data = self::get_extended_data();
91
-
92
- $global_settings['lp-license-keys']['settings'][] = array('id' => 'template-license-keys-header', 'description' => __("Head to http://www.inboundnow.com/ to retrieve your license key for this template.", 'landing-pages'), 'type' => 'header', 'default' => '<h3 class="lp_global_settings_header">' . __('Template Licensing', 'landing-pages') . '</h3>');
93
-
94
- /* get master license key */
95
- $inboundnow_master_key = get_option('inboundnow_master_license_key', '');
96
-
97
- /* Loop through all setting data and add licensing for uploaded templates only */
98
- foreach ($lp_data as $key => $data) {
99
-
100
- $array_core_templates = array('simple-solid-lite', 'countdown-lander', 'default', 'demo', 'dropcap', 'half-and-half', 'simple-two-column', 'super-slick', 'svtle', 'tubelar', 'rsvp-envelope', 'three-column-lander');
101
-
102
- if ($key == 'lp' || substr($key, 0, 4) == 'ext-') {
103
- continue;
104
- }
105
-
106
- if (isset($data['info']['data_type']) && $data['info']['data_type'] == 'metabox') {
107
- continue;
108
- }
109
-
110
- if (in_array($key, $array_core_templates)) {
111
- continue;
112
- }
113
-
114
- $template_name = $lp_data[$key]['info']['label'];
115
- $global_settings['lp-license-keys']['settings'][$key] = array('id' => $key, 'label' => $template_name, 'slug' => $key, 'description' => __("Head to http://www.inboundnow.com/ to retrieve your license key for this template.", 'landing-pages'), 'type' => 'inboundnow-license-key');
116
- }
117
-
118
- return $global_settings;
119
- }
120
-
121
  /**
122
  * Loads core template config.php files
123
  *
26
  /* Modifies legacy template data key names for old, un-updated legacy templates */
27
  add_filter('lp_extension_data', array(__CLASS__, 'add_legacy_data_support'), 10, 1);
28
 
 
 
29
  }
30
 
31
  /**
72
  return $data;
73
  }
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  /**
76
  * Loads core template config.php files
77
  *
classes/class.post-type.landing-page.php CHANGED
@@ -65,7 +65,8 @@ if ( !class_exists('Landing_Pages_Post_Type') ) {
65
  */
66
  public static function register_post_type() {
67
 
68
- $slug = get_option( 'lp-main-landing-page-permalink-prefix', 'go' );
 
69
  $labels = array(
70
  'name' => __('Landing Pages', 'inbound-pro' ),
71
  'singular_name' => __('Landing Page', 'inbound-pro' ),
@@ -360,9 +361,12 @@ if ( !class_exists('Landing_Pages_Post_Type') ) {
360
  $this_path = "wp-content" . $this_path[1] . "core/landing-pages/";
361
  }
362
 
363
- $slug = get_option('lp-main-landing-page-permalink-prefix', 'go');
364
- /*echo $slug;exit; */
365
- $ab_testing = get_option('lp-main-landing-page-disable-turn-off-ab', "0");
 
 
 
366
  if ($ab_testing === "0") {
367
  add_rewrite_rule("$slug/([^/]*)/([0-9]+)/", "$slug/$1?lp-variation-id=$2", 'top');
368
  add_rewrite_rule("$slug/([^/]*)?", $this_path . "modules/module.redirect-ab-testing.php?permalink_name=$1 ", 'top');
@@ -391,7 +395,7 @@ if ( !class_exists('Landing_Pages_Post_Type') ) {
391
  /* print_r($rules_array);exit; */
392
 
393
 
394
- $slug = get_option('lp-main-landing-page-permalink-prefix', 'go');
395
 
396
  $i = 0;
397
  foreach ($rules_array as $key => $val) {
65
  */
66
  public static function register_post_type() {
67
 
68
+ $slug = Landing_Pages_Settings::get_setting( 'lp-main-landing-page-permalink-prefix', 'go' );
69
+
70
  $labels = array(
71
  'name' => __('Landing Pages', 'inbound-pro' ),
72
  'singular_name' => __('Landing Page', 'inbound-pro' ),
361
  $this_path = "wp-content" . $this_path[1] . "core/landing-pages/";
362
  }
363
 
364
+ /* handles local environment */
365
+ $this_path = str_replace("\\" , "/" , $this_path);
366
+
367
+ $slug = Landing_Pages_Settings::get_setting( 'lp-main-landing-page-permalink-prefix', 'go' );
368
+
369
+ $ab_testing = Landing_Pages_Settings::get_setting('lp-main-landing-page-disable-turn-off-ab', "0");
370
  if ($ab_testing === "0") {
371
  add_rewrite_rule("$slug/([^/]*)/([0-9]+)/", "$slug/$1?lp-variation-id=$2", 'top');
372
  add_rewrite_rule("$slug/([^/]*)?", $this_path . "modules/module.redirect-ab-testing.php?permalink_name=$1 ", 'top');
395
  /* print_r($rules_array);exit; */
396
 
397
 
398
+ $slug = Landing_Pages_Settings::get_setting( 'lp-main-landing-page-permalink-prefix', 'go' );
399
 
400
  $i = 0;
401
  foreach ($rules_array as $key => $val) {
classes/{class.cloning.php → class.row-actions.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class Landing_Pages_Cloning {
4
 
5
  /**
6
  * Initiate class
@@ -18,6 +18,9 @@ class Landing_Pages_Cloning {
18
 
19
  /* adds 'clone' links to posts */
20
  add_filter('post_row_actions', array( __CLASS__ ,'add_clone_link' ), 10, 2);
 
 
 
21
  }
22
 
23
  /**
@@ -164,6 +167,26 @@ class Landing_Pages_Cloning {
164
  };
165
  return $data;
166
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
168
 
169
- new Landing_Pages_Cloning;
1
  <?php
2
 
3
+ class Landing_Pages_Row_Actions {
4
 
5
  /**
6
  * Initiate class
18
 
19
  /* adds 'clone' links to posts */
20
  add_filter('post_row_actions', array( __CLASS__ ,'add_clone_link' ), 10, 2);
21
+
22
+ /* adds 'clear stats' links to posts */
23
+ add_filter('post_row_actions', array( __CLASS__ ,'add_clear_stats_link' ), 10, 2);
24
  }
25
 
26
  /**
167
  };
168
  return $data;
169
  }
170
+
171
+ /**
172
+ * Adds clear stats link to quick actions in a post types listing area
173
+ * @param $actions
174
+ * @param $post
175
+ * @return mixed
176
+ */
177
+ public static function add_clear_stats_link($actions, $post) {
178
+
179
+ if ($post->post_type != 'landing-page' ) {
180
+ return $actions;
181
+ }
182
+ // .clear_stats is listened to by ajax.clearstats.js
183
+ $actions['clear_the_stats'] = '<a id="'.$post->ID.'" title="'
184
+ . esc_attr(__("Clear the stats?", 'landing-pages'))
185
+ . '"class="clear_stats"'
186
+ . 'style="cursor:pointer;">' . __('Clear Stats', 'landing-pages') . '</a>';
187
+
188
+ return $actions;
189
+ }
190
  }
191
 
192
+ new Landing_Pages_Row_Actions;
classes/class.settings.php CHANGED
@@ -22,6 +22,56 @@ class Landing_Pages_Settings {
22
 
23
  /* download system info */
24
  add_action( 'admin_init', array( __CLASS__ , 'download_system_info' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  }
26
 
27
  /**
@@ -39,37 +89,29 @@ class Landing_Pages_Settings {
39
  array(
40
  'id' => 'lp_global_settings_main_header',
41
  'type' => 'header',
42
- 'default' => __('Landing Pages Core Settings' , 'landing-pages') ,
43
  'options' => null
44
  ),
45
  array(
46
  'id' => 'landing-page-permalink-prefix',
47
- 'label' => __( 'Default Landing Page Permalink Prefix' , 'landing-pages'),
48
- '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'" , 'landing-pages') ,
49
  'type' => 'text',
50
  'default' => 'go',
51
  'options' => null
52
  ),
53
  array(
54
  'id' => 'landing-page-rotation-halt',
55
- 'label' => __('Sticky Variations' , 'landing-pages'),
56
- '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." , 'landing-pages'),
57
  'type' => 'radio',
58
  'default' => '0',
59
  'options' => array('1'=>'on','0'=>'off')
60
  ),
61
- array(
62
- 'id' => 'inbound_compatibility_mode',
63
- 'label' => 'Turn on compability mode',
64
- 'description' => "<p>This option turns on compability mode for the inbound now plugins. This is typically used if you are experiencing bugs caused by third party plugin conflicts.</p>",
65
- 'type' => 'radio',
66
- 'default' => '0',
67
- 'options' => array('1'=>'On','0'=>'Off')
68
- ),
69
  array(
70
  'id' => 'landing-page-disable-turn-off-ab',
71
- 'label' => __('Turn Off AB Testing?' , 'landing-pages') ,
72
- '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>" , 'landing-pages'),
73
  'type' => 'radio',
74
  'default' => '0',
75
  'options' => array('0'=>'No Keep it on','1'=>'Yes turn AB testing Off')
@@ -83,18 +125,18 @@ class Landing_Pages_Settings {
83
  ( defined('INBOUND_ACCESS_LEVEL') && INBOUND_ACCESS_LEVEL < 1 )
84
  ) {
85
  /* Setup License Keys Tab */
86
- $lp_global_settings['lp-license-keys']['label'] = __('License Keys', 'landing-pages');
87
  $lp_global_settings['lp-license-keys']['settings'][] = array(
88
  'id' => 'extensions-license-keys-header',
89
- 'description' => __("Head to http://www.inboundnow.com/ to retrieve your license key for this template.", 'landing-pages'),
90
  'type' => 'header',
91
- 'default' => '<h3 class="lp_global_settings_header">' . __('Extension Licensing', 'landing-pages') . '</h3>'
92
  );
93
  }
94
 
95
  if (!defined('INBOUND_ACCESS_LEVEL') ) {
96
  /* Setup Extensions Tab */
97
- $lp_global_settings['lp-extensions']['label'] = __( 'Extensions' , 'landing-pages');
98
  $lp_global_settings['lp-extensions']['settings'] = array(
99
  array(
100
  'id' => 'lp-ext-header',
@@ -106,7 +148,7 @@ class Landing_Pages_Settings {
106
  }
107
 
108
  /* Setup Debug Tab */
109
- $lp_global_settings['lp-debug']['label'] = __( 'Debug' , 'landing-pages');
110
  $lp_global_settings['lp-debug']['settings'] = array(
111
  array(
112
  'id' => 'lp-debug-header',
@@ -121,6 +163,20 @@ class Landing_Pages_Settings {
121
  return $lp_global_settings;
122
  }
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
  /**
126
  * Enqueue scripts and styles for settings page
@@ -171,7 +227,7 @@ class Landing_Pages_Settings {
171
  $contentht = esc_textarea($contentht);
172
 
173
  if (!is_writable($htaccess_file)) {
174
- $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.", 'landing-pages') . "</h3></div>";
175
  echo $content;
176
  } else {
177
  $htaccess = '<textarea readonly="readonly" onclick="this.focus();this.select()" style="width: 90%;" rows="15" name="robotsnew">' . $contentht . '</textarea><br/>';
@@ -248,11 +304,11 @@ class Landing_Pages_Settings {
248
  </script>
249
  <div id="php-sql-lp-version" style="display:none;">
250
  <div id="inbound-install-status">
251
- <h3><?php _e('Installation Status', 'landing-pages'); ?></h3>
252
  <table id="lp-wordpress-site-status">
253
 
254
  <tr valign="top">
255
- <th scope="row"><label><?php _e('PHP Version', 'landing-pages'); ?></label></th>
256
  <td class="installation_item_cell">
257
  <strong><?php echo phpversion(); ?></strong>
258
  </td>
@@ -273,7 +329,7 @@ class Landing_Pages_Settings {
273
  </td>
274
  </tr>
275
  <tr valign="top">
276
- <th scope="row"><label><?php _e('MySQL Version', 'landing-pages'); ?></label></th>
277
  <td class="installation_item_cell">
278
  <strong><?php echo $wpdb->db_version(); ?></strong>
279
  </td>
@@ -294,7 +350,7 @@ class Landing_Pages_Settings {
294
  </td>
295
  </tr>
296
  <tr valign="top">
297
- <th scope="row"><label><?php _e('WordPress Version', 'landing-pages'); ?></label></th>
298
  <td class="installation_item_cell">
299
  <strong><?php echo get_bloginfo("version"); ?></strong>
300
  </td>
@@ -308,16 +364,16 @@ class Landing_Pages_Settings {
308
  ?>
309
  &times;
310
  <span
311
- class="installation_item_message"><?php _e('landing pages requires version X or higher', 'landing-pages'); ?></span>
312
  <?php
313
  }
314
  ?>
315
  </td>
316
  </tr>
317
  <tr valign="top">
318
- <th scope="row"><label><?php _e('Landing Page Version', 'landing-pages'); ?></label></th>
319
  <td class="installation_item_cell">
320
- <strong><?php _e('Version', 'landing-pages'); ?><?php echo LANDINGPAGES_CURRENT_VERSION; ?></strong>
321
  </td>
322
  <td>
323
 
@@ -331,7 +387,7 @@ class Landing_Pages_Settings {
331
  <div id="htaccess-contents">
332
 
333
  <?php if ($htaccess != "") {
334
- echo "<h3>" . __('The contents of your .htaccess file', 'landing-pages') . ":</h3>";
335
  echo $htaccess;
336
  } ?>
337
  </div>
@@ -534,7 +590,7 @@ class Landing_Pages_Settings {
534
  $field['id'] = $field['option_name'];
535
  }
536
 
537
- if ($field['id'] == 'main-landing-page-permalink-prefix') {
538
  /*echo "here"; */
539
  global $wp_rewrite;
540
  $wp_rewrite->flush_rules();
@@ -550,11 +606,9 @@ class Landing_Pages_Settings {
550
  'license' => sanitize_text_field($_POST['inboundnow_master_license_key']),
551
  'item_name' => $slug
552
  );
553
- /* error_log(print_r($api_params, true)); */
554
 
555
  /* Call the edd API */
556
  $response = wp_remote_get(add_query_arg($api_params, INBOUNDNOW_STORE_URL ), array('timeout' => 30, 'sslverify' => false));
557
- /* error_log(print_r($response, true)); */
558
 
559
  /* make sure the response came back okay */
560
  if (is_wp_error($response)) {
@@ -563,7 +617,7 @@ class Landing_Pages_Settings {
563
 
564
  /* decode the license data */
565
  $license_data = json_decode(wp_remote_retrieve_body($response));
566
- /* error_log(print_r($license_data, true)); */
567
 
568
  /* $license_data->license will be either "active" or "inactive" */
569
  update_option('lp_license_status-' . $field['slug'], $license_data->license);
@@ -655,6 +709,7 @@ class Landing_Pages_Settings {
655
  $input_type = 'text';
656
  }
657
 
 
658
  $license_status = self::check_license_status($field);
659
 
660
  echo '<input type="' . $input_type . '" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . $field['value'] . '" size="30" />';
22
 
23
  /* download system info */
24
  add_action( 'admin_init', array( __CLASS__ , 'download_system_info' ) );
25
+
26
+ /* Add settings to inbound pro */
27
+ add_filter('inbound_settings/extend', array( __CLASS__ , 'define_pro_settings' ) );
28
+ }
29
+
30
+ /**
31
+ * Adds pro admin settings
32
+ */
33
+ public static function define_pro_settings( $settings ) {
34
+ global $inbound_settings;
35
+
36
+ $settings['inbound-pro-setup'][] = array(
37
+ 'group_name' => LANDINGPAGES_PLUGIN_SLUG ,
38
+ 'keywords' => __('landing pages, landers, permalinks,sticky,ab testing' , 'inbound-pro'),
39
+ 'fields' => array (
40
+ array(
41
+ 'id' => 'header-landing-page',
42
+ 'type' => 'header',
43
+ 'default' => __('Landing Pages Settings', 'inbound-pro' ),
44
+ 'options' => null
45
+ ),
46
+ array(
47
+ 'id' => 'landing-page-permalink-prefix',
48
+ 'label' => __('Permalink Prefix', 'inbound-pro' ),
49
+ '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') ,
50
+ 'type' => 'text',
51
+ 'default' => 'go',
52
+ ),
53
+ array(
54
+ 'id' => 'landing-page-rotation-halt',
55
+ 'label' => __('Sticky Variations' , 'inbound-pro'),
56
+ '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'),
57
+ 'type' => 'radio',
58
+ 'default' => '0',
59
+ 'options' => array('1'=>'on','0'=>'off')
60
+ ),
61
+ array(
62
+ 'id' => 'landing-page-disable-turn-off-ab',
63
+ 'label' => __('Turn Off AB Testing?' , 'inbound-pro') ,
64
+ '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'),
65
+ 'type' => 'radio',
66
+ 'default' => '0',
67
+ 'options' => array('0'=>'No Keep it on','1'=>'Yes turn AB testing Off')
68
+ )
69
+ )
70
+
71
+ );
72
+
73
+
74
+ return $settings;
75
  }
76
 
77
  /**
89
  array(
90
  'id' => 'lp_global_settings_main_header',
91
  'type' => 'header',
92
+ 'default' => __('Landing Pages Core Settings' , 'inbound-pro') ,
93
  'options' => null
94
  ),
95
  array(
96
  'id' => 'landing-page-permalink-prefix',
97
+ 'label' => __( 'Default Landing Page Permalink Prefix' , 'inbound-pro'),
98
+ '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') ,
99
  'type' => 'text',
100
  'default' => 'go',
101
  'options' => null
102
  ),
103
  array(
104
  'id' => 'landing-page-rotation-halt',
105
+ 'label' => __('Sticky Variations' , 'inbound-pro'),
106
+ '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'),
107
  'type' => 'radio',
108
  'default' => '0',
109
  'options' => array('1'=>'on','0'=>'off')
110
  ),
 
 
 
 
 
 
 
 
111
  array(
112
  'id' => 'landing-page-disable-turn-off-ab',
113
+ 'label' => __('Turn Off AB Testing?' , 'inbound-pro') ,
114
+ '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'),
115
  'type' => 'radio',
116
  'default' => '0',
117
  'options' => array('0'=>'No Keep it on','1'=>'Yes turn AB testing Off')
125
  ( defined('INBOUND_ACCESS_LEVEL') && INBOUND_ACCESS_LEVEL < 1 )
126
  ) {
127
  /* Setup License Keys Tab */
128
+ $lp_global_settings['lp-license-keys']['label'] = __('API Key Setup', 'inbound-pro');
129
  $lp_global_settings['lp-license-keys']['settings'][] = array(
130
  'id' => 'extensions-license-keys-header',
131
+ 'description' => __("Head to http://www.inboundnow.com/account to retrieve your API key for this template.", 'inbound-pro'),
132
  'type' => 'header',
133
+ 'default' => '<h3 class="lp_global_settings_header">' . __('Inbound API Key', 'inbound-pro') . '</h3>'
134
  );
135
  }
136
 
137
  if (!defined('INBOUND_ACCESS_LEVEL') ) {
138
  /* Setup Extensions Tab */
139
+ $lp_global_settings['lp-extensions']['label'] = __( 'Extensions' , 'inbound-pro');
140
  $lp_global_settings['lp-extensions']['settings'] = array(
141
  array(
142
  'id' => 'lp-ext-header',
148
  }
149
 
150
  /* Setup Debug Tab */
151
+ $lp_global_settings['lp-debug']['label'] = __( 'Debug' , 'inbound-pro');
152
  $lp_global_settings['lp-debug']['settings'] = array(
153
  array(
154
  'id' => 'lp-debug-header',
163
  return $lp_global_settings;
164
  }
165
 
166
+ public static function get_setting( $field_id , $default ) {
167
+ global $inbound_settings;
168
+ $value = $default;
169
+
170
+ if (defined('INBOUND_PRO_CURRENT_VERSION')) {
171
+ $field_id = str_replace('lp-main-' , '', $field_id );
172
+ $value = (isset($inbound_settings['landing-pages'][$field_id])) ? $inbound_settings['landing-pages'][$field_id] : $default;
173
+ } else {
174
+ $value = get_option( $field_id, $default );
175
+ }
176
+
177
+ return $value;
178
+ }
179
+
180
 
181
  /**
182
  * Enqueue scripts and styles for settings page
227
  $contentht = esc_textarea($contentht);
228
 
229
  if (!is_writable($htaccess_file)) {
230
+ $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>";
231
  echo $content;
232
  } else {
233
  $htaccess = '<textarea readonly="readonly" onclick="this.focus();this.select()" style="width: 90%;" rows="15" name="robotsnew">' . $contentht . '</textarea><br/>';
304
  </script>
305
  <div id="php-sql-lp-version" style="display:none;">
306
  <div id="inbound-install-status">
307
+ <h3><?php _e('Installation Status', 'inbound-pro'); ?></h3>
308
  <table id="lp-wordpress-site-status">
309
 
310
  <tr valign="top">
311
+ <th scope="row"><label><?php _e('PHP Version', 'inbound-pro'); ?></label></th>
312
  <td class="installation_item_cell">
313
  <strong><?php echo phpversion(); ?></strong>
314
  </td>
329
  </td>
330
  </tr>
331
  <tr valign="top">
332
+ <th scope="row"><label><?php _e('MySQL Version', 'inbound-pro'); ?></label></th>
333
  <td class="installation_item_cell">
334
  <strong><?php echo $wpdb->db_version(); ?></strong>
335
  </td>
350
  </td>
351
  </tr>
352
  <tr valign="top">
353
+ <th scope="row"><label><?php _e('WordPress Version', 'inbound-pro'); ?></label></th>
354
  <td class="installation_item_cell">
355
  <strong><?php echo get_bloginfo("version"); ?></strong>
356
  </td>
364
  ?>
365
  &times;
366
  <span
367
+ class="installation_item_message"><?php _e('landing pages requires version X or higher', 'inbound-pro'); ?></span>
368
  <?php
369
  }
370
  ?>
371
  </td>
372
  </tr>
373
  <tr valign="top">
374
+ <th scope="row"><label><?php _e('Landing Page Version', 'inbound-pro'); ?></label></th>
375
  <td class="installation_item_cell">
376
+ <strong><?php _e('Version', 'inbound-pro'); ?><?php echo LANDINGPAGES_CURRENT_VERSION; ?></strong>
377
  </td>
378
  <td>
379
 
387
  <div id="htaccess-contents">
388
 
389
  <?php if ($htaccess != "") {
390
+ echo "<h3>" . __('The contents of your .htaccess file', 'inbound-pro') . ":</h3>";
391
  echo $htaccess;
392
  } ?>
393
  </div>
590
  $field['id'] = $field['option_name'];
591
  }
592
 
593
+ if ($field['id'] == 'lp-main-landing-page-permalink-prefix') {
594
  /*echo "here"; */
595
  global $wp_rewrite;
596
  $wp_rewrite->flush_rules();
606
  'license' => sanitize_text_field($_POST['inboundnow_master_license_key']),
607
  'item_name' => $slug
608
  );
 
609
 
610
  /* Call the edd API */
611
  $response = wp_remote_get(add_query_arg($api_params, INBOUNDNOW_STORE_URL ), array('timeout' => 30, 'sslverify' => false));
 
612
 
613
  /* make sure the response came back okay */
614
  if (is_wp_error($response)) {
617
 
618
  /* decode the license data */
619
  $license_data = json_decode(wp_remote_retrieve_body($response));
620
+
621
 
622
  /* $license_data->license will be either "active" or "inactive" */
623
  update_option('lp_license_status-' . $field['slug'], $license_data->license);
709
  $input_type = 'text';
710
  }
711
 
712
+
713
  $license_status = self::check_license_status($field);
714
 
715
  echo '<input type="' . $input_type . '" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . $field['value'] . '" size="30" />';
classes/class.welcome.php CHANGED
@@ -575,7 +575,7 @@ class LandingPages_Welcome {
575
 
576
  <h1 style="text-decoration: none; text-align: center;"><a target="_blank" id="create-templates" class='button' href="http://docs.inboundnow.com/guide/creating-landing-page-templates/">Create Your Own Templates</a></h1>
577
 
578
- <p class="about-description">WordPress Landing Pages is third party extendable. We have a variety of <a href="http://docs.inboundnow.com/landing-pages/dev/core-hooks-filters/hooks">hooks</a>, actions, and filters to add your own functionality</p>
579
  </div>
580
  <div class='grid one-third' id="inbound-contribute" style="text-align: center;">
581
  <p class="about-description" style=""><a href="https://github.com/inboundnow/landing-pages" target="_blank"><b>Contribute Code</b> + <span style="font-size:21px"><b>Submit Feature Requests</b></span></a></p>
575
 
576
  <h1 style="text-decoration: none; text-align: center;"><a target="_blank" id="create-templates" class='button' href="http://docs.inboundnow.com/guide/creating-landing-page-templates/">Create Your Own Templates</a></h1>
577
 
578
+ <p class="about-description">WordPress Landing Pages is third party extendable. We have a variety of <a href="#documentation-pending">hooks</a>, actions, and filters to add your own functionality</p>
579
  </div>
580
  <div class='grid one-third' id="inbound-contribute" style="text-align: center;">
581
  <p class="about-description" style=""><a href="https://github.com/inboundnow/landing-pages" target="_blank"><b>Contribute Code</b> + <span style="font-size:21px"><b>Submit Feature Requests</b></span></a></p>
classes/class.wp-list-table.templates.php CHANGED
@@ -10,6 +10,7 @@ class Landing_Pages_Templates_List_Table extends WP_List_Table {
10
  private $found_data;
11
  private $singular;
12
  private $plural;
 
13
 
14
  function __construct() {
15
 
@@ -76,6 +77,7 @@ class Landing_Pages_Templates_List_Table extends WP_List_Table {
76
  $args['singular'] = sanitize_key('');
77
 
78
  $this->_args = $args;
 
79
  }
80
 
81
  function get_columns() {
@@ -119,7 +121,7 @@ class Landing_Pages_Templates_List_Table extends WP_List_Table {
119
  usort($this->template_data, array(&$this, 'usort_reorder'));
120
  }
121
 
122
- $per_page = 25;
123
  $current_page = $this->get_pagenum();
124
 
125
 
@@ -145,7 +147,7 @@ class Landing_Pages_Templates_List_Table extends WP_List_Table {
145
  switch ($column_name) {
146
  case 'template':
147
  return '<div class="capty-wrapper" style="overflow: hidden; position: relative; "><div class="capty-image"><img src="' . $item['thumbnail'] . '" class="template-thumbnail" alt="' . $item['name'] . '" id="id_' . $item['ID'] . '" title="' . $item['name'] . '">
148
- </div><div class="capty-caption" style="text-align:center;width:158px;margin-left:-6px;height: 20px; opacity: 0.7; top:-82px;position: relative;">' . $item['name'] . '</div></div>';
149
  case 'category':
150
  return '<span class="post-state">
151
  <span class="pending states">' . $item[$column_name] . '</span>
@@ -206,9 +208,10 @@ class Landing_Pages_Templates_List_Table extends WP_List_Table {
206
  if (defined('INBOUND_PRO_PATH') && Inbound_Pro_Plugin::get_customer_status() > 0 ) {
207
  return $version;
208
  }
 
209
  $api_response = self::poll_api($item);
210
 
211
- if (false !== $api_response) {
212
  if (version_compare($version, $api_response['new_version'], '<')) {
213
  $template_page = LANDINGPAGES_STORE_URL . "/downloads/" . $item['ID'] . "/";
214
  $html = '<div class="update-message">' . $item['version'] . ' &nbsp;&nbsp; <font class="update-available">Version ' . $api_response['new_version'] . __( 'available' , 'inbound-pro' ). '</font><br> <a title="' . $item['name'] . '" class="thickbox" href="' . $template_page . '" target="_blank">'. __( 'View template details' , 'inbound-pro' ) .'</a> ';
@@ -228,12 +231,13 @@ class Landing_Pages_Templates_List_Table extends WP_List_Table {
228
  * @return bool
229
  */
230
  function poll_api( $item ) {
231
- $api_params = array('edd_action' => 'get_version', 'license' => get_option('lp-license-keys-' . $item['ID']), 'name' => $item['name'], 'slug' => $item['ID'], 'nature' => 'template',);
232
 
233
- $request = wp_remote_post(LANDINGPAGES_STORE_URL, array('timeout' => 15, 'sslverify' => false, 'body' => $api_params));
234
 
235
  if (!is_wp_error($request)) {
236
  $request = json_decode(wp_remote_retrieve_body($request), true);
 
237
  if ($request) $request['sections'] = maybe_unserialize($request['sections']);
238
  return $request;
239
  } else {
10
  private $found_data;
11
  private $singular;
12
  private $plural;
13
+ private $api_key;
14
 
15
  function __construct() {
16
 
77
  $args['singular'] = sanitize_key('');
78
 
79
  $this->_args = $args;
80
+ $this->api_key = get_option('inboundnow_master_license_key', '');
81
  }
82
 
83
  function get_columns() {
121
  usort($this->template_data, array(&$this, 'usort_reorder'));
122
  }
123
 
124
+ $per_page = 10;
125
  $current_page = $this->get_pagenum();
126
 
127
 
147
  switch ($column_name) {
148
  case 'template':
149
  return '<div class="capty-wrapper" style="overflow: hidden; position: relative; "><div class="capty-image"><img src="' . $item['thumbnail'] . '" class="template-thumbnail" alt="' . $item['name'] . '" id="id_' . $item['ID'] . '" title="' . $item['name'] . '">
150
+ </div><div class="capty-caption" style="text-align:center;width:158px;margin-left:0px;color:#ffffff;background:#000;height: 20px; opacity: 0.7; top:-82px;position: relative;">' . $item['name'] . '</div></div>';
151
  case 'category':
152
  return '<span class="post-state">
153
  <span class="pending states">' . $item[$column_name] . '</span>
208
  if (defined('INBOUND_PRO_PATH') && Inbound_Pro_Plugin::get_customer_status() > 0 ) {
209
  return $version;
210
  }
211
+
212
  $api_response = self::poll_api($item);
213
 
214
+ if ($api_response) {
215
  if (version_compare($version, $api_response['new_version'], '<')) {
216
  $template_page = LANDINGPAGES_STORE_URL . "/downloads/" . $item['ID'] . "/";
217
  $html = '<div class="update-message">' . $item['version'] . ' &nbsp;&nbsp; <font class="update-available">Version ' . $api_response['new_version'] . __( 'available' , 'inbound-pro' ). '</font><br> <a title="' . $item['name'] . '" class="thickbox" href="' . $template_page . '" target="_blank">'. __( 'View template details' , 'inbound-pro' ) .'</a> ';
231
  * @return bool
232
  */
233
  function poll_api( $item ) {
234
+ $api_params = array('edd_action' => 'inbound_get_version', 'license' => $this->api_key, 'name' => $item['name'], 'slug' => $item['ID'], 'nature' => 'template',);
235
 
236
+ $request = wp_remote_post('https://www.inboundnow.com', array('timeout' => 15, 'sslverify' => false, 'body' => $api_params));
237
 
238
  if (!is_wp_error($request)) {
239
  $request = json_decode(wp_remote_retrieve_body($request), true);
240
+
241
  if ($request) $request['sections'] = maybe_unserialize($request['sections']);
242
  return $request;
243
  } else {
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.2.9
7
  Author: Inbound Now
8
  Author URI: http://www.inboundnow.com/
9
 
@@ -37,10 +37,10 @@ if (!class_exists('Inbound_Landing_Pages_Plugin')) {
37
  */
38
  private static function load_constants() {
39
 
40
- define('LANDINGPAGES_CURRENT_VERSION', '2.2.9' );
41
  define('LANDINGPAGES_URLPATH', plugins_url( '/' , __FILE__ ) );
42
  define('LANDINGPAGES_PATH', WP_PLUGIN_DIR.'/'.plugin_basename( dirname(__FILE__) ).'/' );
43
- define('LANDINGPAGES_PLUGIN_SLUG', plugin_basename( dirname(__FILE__) ) );
44
  define('LANDINGPAGES_FILE', __FILE__ );
45
  define('LANDINGPAGES_STORE_URL', 'http://www.inboundnow.com/market' );
46
  $uploads = wp_upload_dir();
@@ -58,6 +58,7 @@ if (!class_exists('Inbound_Landing_Pages_Plugin')) {
58
  switch (is_admin()) :
59
  case true :
60
  /* loads admin files */
 
61
  include_once( LANDINGPAGES_PATH . 'classes/class.activation.php');
62
  include_once( LANDINGPAGES_PATH . 'classes/class.activation.upgrade-routines.php');
63
  include_once( LANDINGPAGES_PATH . 'classes/class.variations.php');
@@ -69,8 +70,7 @@ if (!class_exists('Inbound_Landing_Pages_Plugin')) {
69
  include_once( LANDINGPAGES_PATH . 'classes/class.admin-menus.php');
70
  include_once( LANDINGPAGES_PATH . 'classes/class.statistics.php');
71
  include_once( LANDINGPAGES_PATH . 'classes/class.admin-notices.php');
72
- include_once( LANDINGPAGES_PATH . 'classes/class.cloning.php');
73
- include_once( LANDINGPAGES_PATH . 'classes/class.settings.php');
74
  include_once( LANDINGPAGES_PATH . 'classes/class.welcome.php');
75
  include_once( LANDINGPAGES_PATH . 'classes/class.install.php');
76
  include_once( LANDINGPAGES_PATH . 'classes/class.landing-pages.php');
@@ -88,6 +88,7 @@ if (!class_exists('Inbound_Landing_Pages_Plugin')) {
88
 
89
  case false :
90
  /* load front-end files */
 
91
  include_once( LANDINGPAGES_PATH . 'classes/class.variations.php');
92
  include_once( LANDINGPAGES_PATH . 'classes/class.acf-integration.php');
93
  include_once( LANDINGPAGES_PATH . 'classes/class.postmeta.php');
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.3.2
7
  Author: Inbound Now
8
  Author URI: http://www.inboundnow.com/
9
 
37
  */
38
  private static function load_constants() {
39
 
40
+ define('LANDINGPAGES_CURRENT_VERSION', '2.3.2' );
41
  define('LANDINGPAGES_URLPATH', plugins_url( '/' , __FILE__ ) );
42
  define('LANDINGPAGES_PATH', WP_PLUGIN_DIR.'/'.plugin_basename( dirname(__FILE__) ).'/' );
43
+ define('LANDINGPAGES_PLUGIN_SLUG', 'landing-pages' );
44
  define('LANDINGPAGES_FILE', __FILE__ );
45
  define('LANDINGPAGES_STORE_URL', 'http://www.inboundnow.com/market' );
46
  $uploads = wp_upload_dir();
58
  switch (is_admin()) :
59
  case true :
60
  /* loads admin files */
61
+ include_once( LANDINGPAGES_PATH . 'classes/class.settings.php');
62
  include_once( LANDINGPAGES_PATH . 'classes/class.activation.php');
63
  include_once( LANDINGPAGES_PATH . 'classes/class.activation.upgrade-routines.php');
64
  include_once( LANDINGPAGES_PATH . 'classes/class.variations.php');
70
  include_once( LANDINGPAGES_PATH . 'classes/class.admin-menus.php');
71
  include_once( LANDINGPAGES_PATH . 'classes/class.statistics.php');
72
  include_once( LANDINGPAGES_PATH . 'classes/class.admin-notices.php');
73
+ include_once( LANDINGPAGES_PATH . 'classes/class.row-actions.php');
 
74
  include_once( LANDINGPAGES_PATH . 'classes/class.welcome.php');
75
  include_once( LANDINGPAGES_PATH . 'classes/class.install.php');
76
  include_once( LANDINGPAGES_PATH . 'classes/class.landing-pages.php');
88
 
89
  case false :
90
  /* load front-end files */
91
+ include_once( LANDINGPAGES_PATH . 'classes/class.settings.php');
92
  include_once( LANDINGPAGES_PATH . 'classes/class.variations.php');
93
  include_once( LANDINGPAGES_PATH . 'classes/class.acf-integration.php');
94
  include_once( LANDINGPAGES_PATH . 'classes/class.postmeta.php');
modules/module.redirect-ab-testing.php CHANGED
@@ -5,212 +5,204 @@ define("DONOTCACHEPAGE", true);
5
  define('DONOTCACHCEOBJECT', true);
6
  define('DONOTCDN', true);
7
 
8
- if ( file_exists ( './../../../../wp-load.php' ) )
9
- {
10
- include_once ( './../../../../wp-load.php' );
11
- }
12
- else if ( file_exists ( './../../../../../wp-load.php' ) )
13
- {
14
- include_once ( './../../../../../wp-load.php' );
15
- }
16
- else if ( file_exists ( './../../../../../../wp-load.php' ) )
17
- {
18
- include_once ( './../../../../../../wp-load.php' );
19
- }
20
-
21
- else if ( file_exists ( './../../../../../../../wp-load.php' ) )
22
- {
23
- include_once ( './../../../../../../../wp-load.php' );
24
  }
25
 
26
  class LP_Variation_Rotation {
27
 
28
- static $permalink_name;
29
- static $post_id;
30
- static $sticky_variations;
31
- static $last_loaded_variation;
32
- static $variations;
33
- static $marker;
34
- static $next_marker;
35
- static $destination_url;
36
 
37
- /**
38
- * Executes Class
39
- */
40
- public function __construct() {
41
 
42
- self::load_variables();
43
- /*self::run_debug(); */
44
- self::redirect();
45
 
46
- }
 
 
 
 
 
47
 
48
- /**
49
- * Loads Static Variables
50
- */
51
- private static function load_variables()
52
- {
53
- self::$permalink_name = (isset($_GET['permalink_name'])) ? sanitize_text_field($_GET['permalink_name']) : null;
54
  self::$post_id = self::load_post_id();
55
- self::$sticky_variations = get_option( 'lp-main-landing-page-rotation-halt' , false );
56
- self::$last_loaded_variation = ( isset( $_COOKIE['lp-loaded-variation-'.self::$permalink_name] ) ) ? intval($_COOKIE['lp-loaded-variation-'.self::$permalink_name]) : null;
57
 
58
- if ( self::$sticky_variations && self::$last_loaded_variation ) {
59
 
60
- self::$destination_url = self::$last_loaded_variation;
61
 
62
- if (!isset($_GET)) {
63
- return;
64
- }
65
 
66
- $begin = (strstr(self::$destination_url, '?')) ? '' : '?';
67
 
68
- /* Keep GET Params */
69
- foreach ($_GET as $key=>$value) {
70
- if ($key != "permalink_name"){
71
- $old_params .= "&$key=" . $value;
72
- }
73
- }
74
 
75
- self::$destination_url = self::$destination_url.$begin.$old_params;
76
 
77
- } else {
78
- self::$variations = self::load_variations();
79
- self::$marker = self::load_marker();
80
- self::$next_marker = self::discover_next_variation();
81
- self::$destination_url = self::build_destination_url();
82
- }
83
 
84
  }
85
 
86
- /**
87
- * Debug Information - Prints Class Variable Data
88
- */
89
- static function run_debug() {
90
- echo self::$variations. '<br>';
91
- echo self::$marker. '<br>';
92
- echo self::$next_marker. '<br>';
93
- echo self::$destination_url. '<br>';
94
- exit;
95
- }
96
 
97
- /**
98
- * Loads the ID of the Landing Page
99
- */
100
- static function load_post_id() {
101
- global $wpdb;
102
 
103
- $post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type='landing-page'", self::$permalink_name ));
104
 
105
- return $post_id;
106
 
107
- }
108
 
109
- /**
110
- * Loads an Array of Active Variations Associated with Landing Page
111
- */
112
- static function load_variations() {
113
 
114
- $live_variations = array();
115
 
116
- $variations_string = get_post_meta( self::$post_id , 'lp-ab-variations' , true );
117
- $variations = explode(',',$variations_string);
118
- $variations = array_filter($variations,'is_numeric');
119
 
120
- /* Check the Status of Each Variation and Keep Live Ones */
121
- foreach ($variations as $key=>$vid) {
122
 
123
 
124
- $variation_status = get_post_meta( self::$post_id , 'lp_ab_variation_status-'.$vid , true );
125
 
126
- if (!is_numeric($variation_status) || $variation_status==1) {
127
- $live_variations[] = $vid;
128
- }
129
 
130
- }
131
 
132
- return $live_variations;
133
- }
134
 
135
- /**
136
- * Loads Variation ID of Last Variation Loaded
137
- */
138
- static function load_marker() {
139
 
140
- $marker = get_post_meta( self::$post_id , 'lp-ab-variations-marker' , true );
141
 
142
- if ( !is_numeric($marker) || !in_array( $marker , self::$variations ) ) {
143
 
144
- $marker = current(self::$variations);
145
- }
146
 
147
- return $marker;
148
- }
149
 
150
- /**
151
- * Discovers Next Variation in Line
152
- */
153
- static function discover_next_variation() {
154
 
155
- /* Set Pointer to Correct Location in Variations Array */
156
- while ( self::$marker != current( self::$variations) ) {
157
- next(self::$variations);
158
- }
159
 
160
- /* Discover the next variation in the array */
161
- next(self::$variations);
162
 
163
- /* If the pointer is empty then reset array */
164
- if ( !is_numeric(current( self::$variations ) ) ) {
165
- reset( self::$variations );
166
- }
167
 
168
- /* Save as Historical Data */
169
- update_post_meta( self::$post_id , 'lp-ab-variations-marker' , current( self::$variations ) );
170
 
171
- return current( self::$variations );
172
 
173
- }
174
 
175
- /**
176
- * Builds Redirect URL & Stores Cookie Data
177
- */
178
- static function build_destination_url() {
179
 
180
- /* Load Base URL */
181
- $url = get_permalink(self::$post_id);
182
- $old_params = null;
183
 
184
- /* Keep GET Params */
185
- foreach ($_GET as $key=>$value) {
186
- if ($key != "permalink_name"){
187
- $old_params .= "&$key=" . $value;
188
- }
189
- }
190
 
191
- /* Build Final URL and Set Memory Cookies */
192
- $url = $url."?lp-variation-id=".self::$next_marker.$old_params;
193
 
194
- /* Set Memory Cookies */
195
- setcookie('lp-loaded-variation-'.self::$permalink_name , $url , time()+ 60 * 60 * 24 * 30 , "/" );
196
- setcookie( 'lp-variation-id' , self::$next_marker , time()+3600 , "/" );
197
 
198
- return $url;
199
- }
200
 
201
- /**
202
- * Redirects to Correct Variation
203
- */
204
- static function redirect() {
205
- if (count(self::$variations) > 1) {
206
- header("HTTP/1.1 302 Temporary Redirect");
207
- } else {
208
- header("HTTP/1.1 301 Moved Permanently");
209
- }
210
-
211
- header("Location: ".self::$destination_url);
212
- exit;
213
- }
214
  }
215
 
216
  $VariationRoation = new LP_Variation_Rotation;
5
  define('DONOTCACHCEOBJECT', true);
6
  define('DONOTCDN', true);
7
 
8
+ if (file_exists('./../../../../wp-load.php')) {
9
+ include_once('./../../../../wp-load.php');
10
+ } else if (file_exists('./../../../../../wp-load.php')) {
11
+ include_once('./../../../../../wp-load.php');
12
+ } else if (file_exists('./../../../../../../wp-load.php')) {
13
+ include_once('./../../../../../../wp-load.php');
14
+ } else if (file_exists('./../../../../../../../wp-load.php')) {
15
+ include_once('./../../../../../../../wp-load.php');
 
 
 
 
 
 
 
 
16
  }
17
 
18
  class LP_Variation_Rotation {
19
 
20
+ static $permalink_name;
21
+ static $post_id;
22
+ static $sticky_variations;
23
+ static $last_loaded_variation;
24
+ static $variations;
25
+ static $marker;
26
+ static $next_marker;
27
+ static $destination_url;
28
 
29
+ /**
30
+ * Executes Class
31
+ */
32
+ public function __construct() {
33
 
34
+ self::load_variables();
35
+ /*self::run_debug(); */
36
+ self::redirect();
37
 
38
+ }
39
+
40
+ /**
41
+ * Loads Static Variables
42
+ */
43
+ private static function load_variables() {
44
 
45
+ self::$permalink_name = (isset($_GET['permalink_name'])) ? sanitize_text_field($_GET['permalink_name']) : null;
 
 
 
 
 
46
  self::$post_id = self::load_post_id();
47
+ self::$sticky_variations = Landing_Pages_Settings::get_setting('lp-main-landing-page-rotation-halt', false);
48
+ self::$last_loaded_variation = (isset($_COOKIE['lp-loaded-variation-' . self::$permalink_name])) ? intval($_COOKIE['lp-loaded-variation-' . self::$permalink_name]) : null;
49
 
50
+ if (self::$sticky_variations && self::$last_loaded_variation) {
51
 
52
+ self::$destination_url = self::$last_loaded_variation;
53
 
54
+ if (!isset($_GET)) {
55
+ return;
56
+ }
57
 
58
+ $begin = (strstr(self::$destination_url, '?')) ? '' : '?';
59
 
60
+ /* Keep GET Params */
61
+ foreach ($_GET as $key => $value) {
62
+ if ($key != "permalink_name") {
63
+ $old_params .= "&$key=" . $value;
64
+ }
65
+ }
66
 
67
+ self::$destination_url = self::$destination_url . $begin . $old_params;
68
 
69
+ } else {
70
+ self::$variations = self::load_variations();
71
+ self::$marker = self::load_marker();
72
+ self::$next_marker = self::discover_next_variation();
73
+ self::$destination_url = self::build_destination_url();
74
+ }
75
 
76
  }
77
 
78
+ /**
79
+ * Debug Information - Prints Class Variable Data
80
+ */
81
+ static function run_debug() {
82
+ echo self::$variations . '<br>';
83
+ echo self::$marker . '<br>';
84
+ echo self::$next_marker . '<br>';
85
+ echo self::$destination_url . '<br>';
86
+ exit;
87
+ }
88
 
89
+ /**
90
+ * Loads the ID of the Landing Page
91
+ */
92
+ static function load_post_id() {
93
+ global $wpdb;
94
 
95
+ $post_id = $wpdb->get_var($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type='landing-page'", self::$permalink_name));
96
 
97
+ return $post_id;
98
 
99
+ }
100
 
101
+ /**
102
+ * Loads an Array of Active Variations Associated with Landing Page
103
+ */
104
+ static function load_variations() {
105
 
106
+ $live_variations = array();
107
 
108
+ $variations_string = get_post_meta(self::$post_id, 'lp-ab-variations', true);
109
+ $variations = explode(',', $variations_string);
110
+ $variations = array_filter($variations, 'is_numeric');
111
 
112
+ /* Check the Status of Each Variation and Keep Live Ones */
113
+ foreach ($variations as $key => $vid) {
114
 
115
 
116
+ $variation_status = get_post_meta(self::$post_id, 'lp_ab_variation_status-' . $vid, true);
117
 
118
+ if (!is_numeric($variation_status) || $variation_status == 1) {
119
+ $live_variations[] = $vid;
120
+ }
121
 
122
+ }
123
 
124
+ return $live_variations;
125
+ }
126
 
127
+ /**
128
+ * Loads Variation ID of Last Variation Loaded
129
+ */
130
+ static function load_marker() {
131
 
132
+ $marker = get_post_meta(self::$post_id, 'lp-ab-variations-marker', true);
133
 
134
+ if (!is_numeric($marker) || !in_array($marker, self::$variations)) {
135
 
136
+ $marker = current(self::$variations);
137
+ }
138
 
139
+ return $marker;
140
+ }
141
 
142
+ /**
143
+ * Discovers Next Variation in Line
144
+ */
145
+ static function discover_next_variation() {
146
 
147
+ /* Set Pointer to Correct Location in Variations Array */
148
+ while (self::$marker != current(self::$variations)) {
149
+ next(self::$variations);
150
+ }
151
 
152
+ /* Discover the next variation in the array */
153
+ next(self::$variations);
154
 
155
+ /* If the pointer is empty then reset array */
156
+ if (!is_numeric(current(self::$variations))) {
157
+ reset(self::$variations);
158
+ }
159
 
160
+ /* Save as Historical Data */
161
+ update_post_meta(self::$post_id, 'lp-ab-variations-marker', current(self::$variations));
162
 
163
+ return current(self::$variations);
164
 
165
+ }
166
 
167
+ /**
168
+ * Builds Redirect URL & Stores Cookie Data
169
+ */
170
+ static function build_destination_url() {
171
 
172
+ /* Load Base URL */
173
+ $url = get_permalink(self::$post_id);
174
+ $old_params = null;
175
 
176
+ /* Keep GET Params */
177
+ foreach ($_GET as $key => $value) {
178
+ if ($key != "permalink_name") {
179
+ $old_params .= "&$key=" . $value;
180
+ }
181
+ }
182
 
183
+ /* Build Final URL and Set Memory Cookies */
184
+ $url = $url . "?lp-variation-id=" . self::$next_marker . $old_params;
185
 
186
+ /* Set Memory Cookies */
187
+ setcookie('lp-loaded-variation-' . self::$permalink_name, $url, time() + 60 * 60 * 24 * 30, "/");
188
+ setcookie('lp-variation-id', self::$next_marker, time() + 3600, "/");
189
 
190
+ return $url;
191
+ }
192
 
193
+ /**
194
+ * Redirects to Correct Variation
195
+ */
196
+ static function redirect() {
197
+ if (count(self::$variations) > 1) {
198
+ header("HTTP/1.1 302 Temporary Redirect");
199
+ } else {
200
+ header("HTTP/1.1 301 Moved Permanently");
201
+ }
202
+
203
+ header("Location: " . self::$destination_url);
204
+ exit;
205
+ }
206
  }
207
 
208
  $VariationRoation = new LP_Variation_Rotation;
readme.txt CHANGED
@@ -7,7 +7,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
7
  Tags: landing pages, inbound marketing, conversion pages, split testing, a b test, a b testing, a/b test, a/b testing, coming soon page, email list, landing page, list building, maintenance page, squeeze page, inbound now, landing-pages, splash pages, cpa, click tracking, goal tracking, analytics, free landing page templates
8
  Requires at least: 3.8
9
  Tested up to: 4.6.0
10
- Stable Tag: 2.2.9
11
 
12
  Create landing pages for your WordPress site. Monitor and improve conversion rates, run A/B split tests, customize your own templates and more.
13
 
@@ -70,6 +70,9 @@ The plugin is also fully extendable and has a number of actions, filters, and ho
70
 
71
  == Changelog ==
72
 
 
 
 
73
  = 2.2.9 =
74
  * Fixing sanitation in image generation script.
75
 
7
  Tags: landing pages, inbound marketing, conversion pages, split testing, a b test, a b testing, a/b test, a/b testing, coming soon page, email list, landing page, list building, maintenance page, squeeze page, inbound now, landing-pages, splash pages, cpa, click tracking, goal tracking, analytics, free landing page templates
8
  Requires at least: 3.8
9
  Tested up to: 4.6.0
10
+ Stable Tag: 2.3.2
11
 
12
  Create landing pages for your WordPress site. Monitor and improve conversion rates, run A/B split tests, customize your own templates and more.
13
 
70
 
71
  == Changelog ==
72
 
73
+ = 2.3.2 =
74
+ * Adding support for Inbound Forms without redirect URLs (no ajax)
75
+
76
  = 2.2.9 =
77
  * Fixing sanitation in image generation script.
78
 
shared/assets/js/frontend/analytics-src/analytics.events.js CHANGED
@@ -526,4 +526,64 @@ var _inboundEvents = (function(_inbound) {
526
 
527
  return _inbound;
528
 
529
- })(_inbound || {});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
 
527
  return _inbound;
528
 
529
+ })(_inbound || {});
530
+
531
+
532
+ function inboundFormNoRedirect(){
533
+ /*button == the button that was clicked, form == the form that button belongs to, formRedirectUrl == the link that the form redirects to, if set*/
534
+
535
+ /*Get the button...*/
536
+ /*If not an iframe*/
537
+ if(window.frames.frameElement == null){
538
+ var button = document.querySelectorAll('button.inbound-button-submit[disabled]')[0];
539
+ }
540
+ /*If it is an iframe*/
541
+ else if(window.frames.frameElement.tagName.toLowerCase() == "iframe"){
542
+ var button = window.frames.frameElement.contentWindow.document.querySelectorAll('button.inbound-button-submit')[0];
543
+ }
544
+
545
+ if ( typeof button == 'undefined' ) {
546
+ return;
547
+ }
548
+
549
+ var form = button.form,
550
+ formRedirectUrl = form.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])');
551
+
552
+ /*If the redirect link is not set, or there is a single space in it, the form isn't supposed to redirect. So set the action for void*/
553
+ if(formRedirectUrl.length == 0 || formRedirectUrl[0]['value'] == 'IA=='){
554
+ form.action = 'javascript:void(0)';
555
+ }
556
+ }
557
+
558
+ _inbound.add_action( 'form_before_submission', inboundFormNoRedirect, 10 );
559
+
560
+ function inboundFormNoRedirectContent(){
561
+
562
+ /*If not an iframe*/
563
+ if(window.frames.frameElement == null){
564
+ var button = document.querySelectorAll('button.inbound-button-submit[disabled]')[0];
565
+ }
566
+ /*If it is an iframe*/
567
+ else if(window.frames.frameElement.tagName.toLowerCase() == "iframe"){
568
+ var button = window.frames.frameElement.contentWindow.document.querySelectorAll('button.inbound-button-submit')[0];
569
+ }
570
+
571
+
572
+ if ( typeof button == 'undefined' ) {
573
+ return;
574
+ }
575
+
576
+ var form = button.form,
577
+ formRedirectUrl = form.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])'),
578
+ btnBackground = jQuery(button).css('background'),
579
+ btnFontColor = jQuery(button).css('color'),
580
+ btnHeight = jQuery(button).css('height'),
581
+ spinner = button.getElementsByClassName('inbound-form-spinner');
582
+
583
+ if(formRedirectUrl.length == 0 || formRedirectUrl[0]['value'] == 'IA=='){
584
+ jQuery(spinner).remove();
585
+ jQuery(button).prepend('<div id="redir-check"><i class="fa fa-check-square" aria-hidden="true" style="background='+ btnBackground +'; color='+ btnFontColor +'; font-size:calc('+ btnHeight +' * .42);"></i></div>');
586
+ }
587
+ }
588
+
589
+ _inbound.add_action( 'form_after_submission', inboundFormNoRedirectContent, 10 );
shared/assets/js/frontend/analytics-src/analytics.forms.js CHANGED
@@ -206,6 +206,7 @@ var InboundForms = (function(_inbound) {
206
  return false;
207
  }
208
  }
 
209
  /* Loop through all match possiblities */
210
  for (i = 0; i < FieldMapArray.length; i++) {
211
  //for (var i = FieldMapArray.length - 1; i >= 0; i--) {
@@ -225,7 +226,6 @@ var InboundForms = (function(_inbound) {
225
 
226
  /* look for name attribute match */
227
  if (input_name && input_name.toLowerCase().indexOf(lookingFor) > -1) {
228
-
229
  found = true;
230
  _inbound.deBugger('forms', 'Found matching name attribute for -> ' + lookingFor);
231
 
@@ -261,7 +261,7 @@ var InboundForms = (function(_inbound) {
261
  }
262
 
263
  }
264
-
265
  return inbound_data;
266
 
267
  },
@@ -533,6 +533,21 @@ var InboundForms = (function(_inbound) {
533
  var page_views = _inbound.totalStorage('page_views') || {};
534
  var urlParams = _inbound.totalStorage('inbound_url_params') || {};
535
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
  var inboundDATA = {
537
  'email': email
538
  };
@@ -582,7 +597,9 @@ var InboundForms = (function(_inbound) {
582
  'post_type': post_type,
583
  'page_id': page_id,
584
  'variation': variation,
585
- 'source': utils.readCookie("inbound_referral_site")
 
 
586
  };
587
 
588
  callback = function(leadID) {
206
  return false;
207
  }
208
  }
209
+
210
  /* Loop through all match possiblities */
211
  for (i = 0; i < FieldMapArray.length; i++) {
212
  //for (var i = FieldMapArray.length - 1; i >= 0; i--) {
226
 
227
  /* look for name attribute match */
228
  if (input_name && input_name.toLowerCase().indexOf(lookingFor) > -1) {
 
229
  found = true;
230
  _inbound.deBugger('forms', 'Found matching name attribute for -> ' + lookingFor);
231
 
261
  }
262
 
263
  }
264
+
265
  return inbound_data;
266
 
267
  },
533
  var page_views = _inbound.totalStorage('page_views') || {};
534
  var urlParams = _inbound.totalStorage('inbound_url_params') || {};
535
 
536
+ /* check if redirect url is empty */
537
+ var formRedirectUrl = form.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])');
538
+ var inbound_form_is_ajax = false;
539
+ if(formRedirectUrl.length == 0 || formRedirectUrl[0]['value'] == 'IA=='){
540
+ var inbound_form_is_ajax = true;
541
+ }
542
+
543
+ /* get form id */
544
+ var inbound_form_id = form.querySelectorAll('input[value][type="hidden"][name="inbound_form_id"]');
545
+ if(inbound_form_id.length > 0 ){
546
+ inbound_form_id = inbound_form_id[0]['value'];
547
+ } else {
548
+ inbound_form_id = 0;
549
+ }
550
+
551
  var inboundDATA = {
552
  'email': email
553
  };
597
  'post_type': post_type,
598
  'page_id': page_id,
599
  'variation': variation,
600
+ 'source': utils.readCookie("inbound_referral_site"),
601
+ 'inbound_submitted': inbound_form_is_ajax,
602
+ 'inbound_form_id': inbound_form_id,
603
  };
604
 
605
  callback = function(leadID) {
shared/assets/js/frontend/analytics/inboundAnalytics.js CHANGED
@@ -857,7 +857,7 @@ var _inboundUtils = (function(_inbound) {
857
 
858
  /* Set Param Cookies */
859
  for (var k in urlParams) {
860
-
861
  if (k == 'action') {
862
  continue;
863
  }
@@ -1510,6 +1510,7 @@ var InboundForms = (function(_inbound) {
1510
  return false;
1511
  }
1512
  }
 
1513
  /* Loop through all match possiblities */
1514
  for (i = 0; i < FieldMapArray.length; i++) {
1515
  //for (var i = FieldMapArray.length - 1; i >= 0; i--) {
@@ -1529,7 +1530,6 @@ var InboundForms = (function(_inbound) {
1529
 
1530
  /* look for name attribute match */
1531
  if (input_name && input_name.toLowerCase().indexOf(lookingFor) > -1) {
1532
-
1533
  found = true;
1534
  _inbound.deBugger('forms', 'Found matching name attribute for -> ' + lookingFor);
1535
 
@@ -1565,7 +1565,7 @@ var InboundForms = (function(_inbound) {
1565
  }
1566
 
1567
  }
1568
-
1569
  return inbound_data;
1570
 
1571
  },
@@ -1837,6 +1837,21 @@ var InboundForms = (function(_inbound) {
1837
  var page_views = _inbound.totalStorage('page_views') || {};
1838
  var urlParams = _inbound.totalStorage('inbound_url_params') || {};
1839
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1840
  var inboundDATA = {
1841
  'email': email
1842
  };
@@ -1886,7 +1901,9 @@ var InboundForms = (function(_inbound) {
1886
  'post_type': post_type,
1887
  'page_id': page_id,
1888
  'variation': variation,
1889
- 'source': utils.readCookie("inbound_referral_site")
 
 
1890
  };
1891
 
1892
  callback = function(leadID) {
@@ -2841,6 +2858,67 @@ var _inboundEvents = (function(_inbound) {
2841
  return _inbound;
2842
 
2843
  })(_inbound || {});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2844
  /* LocalStorage Component */
2845
  var InboundTotalStorage = (function (_inbound){
2846
 
857
 
858
  /* Set Param Cookies */
859
  for (var k in urlParams) {
860
+ /* account for wordpress media uploader bug */
861
  if (k == 'action') {
862
  continue;
863
  }
1510
  return false;
1511
  }
1512
  }
1513
+
1514
  /* Loop through all match possiblities */
1515
  for (i = 0; i < FieldMapArray.length; i++) {
1516
  //for (var i = FieldMapArray.length - 1; i >= 0; i--) {
1530
 
1531
  /* look for name attribute match */
1532
  if (input_name && input_name.toLowerCase().indexOf(lookingFor) > -1) {
 
1533
  found = true;
1534
  _inbound.deBugger('forms', 'Found matching name attribute for -> ' + lookingFor);
1535
 
1565
  }
1566
 
1567
  }
1568
+
1569
  return inbound_data;
1570
 
1571
  },
1837
  var page_views = _inbound.totalStorage('page_views') || {};
1838
  var urlParams = _inbound.totalStorage('inbound_url_params') || {};
1839
 
1840
+ /* check if redirect url is empty */
1841
+ var formRedirectUrl = form.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])');
1842
+ var inbound_form_is_ajax = false;
1843
+ if(formRedirectUrl.length == 0 || formRedirectUrl[0]['value'] == 'IA=='){
1844
+ var inbound_form_is_ajax = true;
1845
+ }
1846
+
1847
+ /* get form id */
1848
+ var inbound_form_id = form.querySelectorAll('input[value][type="hidden"][name="inbound_form_id"]');
1849
+ if(inbound_form_id.length > 0 ){
1850
+ inbound_form_id = inbound_form_id[0]['value'];
1851
+ } else {
1852
+ inbound_form_id = 0;
1853
+ }
1854
+
1855
  var inboundDATA = {
1856
  'email': email
1857
  };
1901
  'post_type': post_type,
1902
  'page_id': page_id,
1903
  'variation': variation,
1904
+ 'source': utils.readCookie("inbound_referral_site"),
1905
+ 'inbound_submitted': inbound_form_is_ajax,
1906
+ 'inbound_form_id': inbound_form_id,
1907
  };
1908
 
1909
  callback = function(leadID) {
2858
  return _inbound;
2859
 
2860
  })(_inbound || {});
2861
+
2862
+
2863
+ function inboundFormNoRedirect(){
2864
+ /*button == the button that was clicked, form == the form that button belongs to, formRedirectUrl == the link that the form redirects to, if set*/
2865
+
2866
+ /*Get the button...*/
2867
+ /*If not an iframe*/
2868
+ if(window.frames.frameElement == null){
2869
+ var button = document.querySelectorAll('button.inbound-button-submit[disabled]')[0];
2870
+ }
2871
+ /*If it is an iframe*/
2872
+ else if(window.frames.frameElement.tagName.toLowerCase() == "iframe"){
2873
+ var button = window.frames.frameElement.contentWindow.document.querySelectorAll('button.inbound-button-submit')[0];
2874
+ }
2875
+
2876
+ if ( typeof button == 'undefined' ) {
2877
+ return;
2878
+ }
2879
+
2880
+ var form = button.form,
2881
+ formRedirectUrl = form.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])');
2882
+
2883
+ /*If the redirect link is not set, or there is a single space in it, the form isn't supposed to redirect. So set the action for void*/
2884
+ if(formRedirectUrl.length == 0 || formRedirectUrl[0]['value'] == 'IA=='){
2885
+ form.action = 'javascript:void(0)';
2886
+ }
2887
+ }
2888
+
2889
+ _inbound.add_action( 'form_before_submission', inboundFormNoRedirect, 10 );
2890
+
2891
+ function inboundFormNoRedirectContent(){
2892
+
2893
+ /*If not an iframe*/
2894
+ if(window.frames.frameElement == null){
2895
+ var button = document.querySelectorAll('button.inbound-button-submit[disabled]')[0];
2896
+ }
2897
+ /*If it is an iframe*/
2898
+ else if(window.frames.frameElement.tagName.toLowerCase() == "iframe"){
2899
+ var button = window.frames.frameElement.contentWindow.document.querySelectorAll('button.inbound-button-submit')[0];
2900
+ }
2901
+
2902
+
2903
+ if ( typeof button == 'undefined' ) {
2904
+ return;
2905
+ }
2906
+
2907
+ var form = button.form,
2908
+ formRedirectUrl = form.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])'),
2909
+ btnBackground = jQuery(button).css('background'),
2910
+ btnFontColor = jQuery(button).css('color'),
2911
+ btnHeight = jQuery(button).css('height'),
2912
+ spinner = button.getElementsByClassName('inbound-form-spinner');
2913
+
2914
+ if(formRedirectUrl.length == 0 || formRedirectUrl[0]['value'] == 'IA=='){
2915
+ jQuery(spinner).remove();
2916
+ jQuery(button).prepend('<div id="redir-check"><i class="fa fa-check-square" aria-hidden="true" style="background='+ btnBackground +'; color='+ btnFontColor +'; font-size:calc('+ btnHeight +' * .42);"></i></div>');
2917
+ }
2918
+ }
2919
+
2920
+ _inbound.add_action( 'form_after_submission', inboundFormNoRedirectContent, 10 );
2921
+
2922
  /* LocalStorage Component */
2923
  var InboundTotalStorage = (function (_inbound){
2924
 
shared/assets/js/frontend/analytics/inboundAnalytics.min.js CHANGED
@@ -1,3 +1,3 @@
1
  /*! Inbound Analyticsv1.0.0 | (c) 2016 Inbound Now | https://github.com/inboundnow/cta */
2
- var inbound_data=inbound_data||{},_inboundOptions=_inboundOptions||{},_gaq=_gaq||[],_inbound=function(e){var t={timeout:inbound_settings.is_admin?500:1e4,formAutoTracking:!0,formAutoPopulation:!0},n={init:function(){_inbound.Utils.init(),_inbound.Utils.domReady(window,function(){_inbound.DomLoaded()})},DomLoaded:function(){_inbound.PageTracking.init(),_inbound.Forms.init(),_inbound.Utils.setUrlParams(),_inbound.LeadsAPI.init(),setTimeout(function(){_inbound.Forms.init()},2e3),_inbound.trigger("analytics_ready")},extend:function(e,t){var n,i={};for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(i[n]=e[n]);for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(i[n]=t[n]);return i},debug:function(){},deBugger:function(e,t,n){if(console){var i,o,a,r=document.location.hash?document.location.hash:"",s=r.indexOf("#debug")>-1,t=t||!1;r&&r.match(/debug/)&&(r=r.split("-"),a=r[1]),o="true"===_inbound.Utils.readCookie("inbound_debug")?!0:!1,i="true"===_inbound.Utils.readCookie("inbound_debug_"+e)?!0:!1,(i||s||o)&&(t&&"string"==typeof t&&(o||"all"===a?console.log('logAll "'+e+'" =>',t):i?console.log('log "'+e+'" =>',t):e===a&&console.log('#log "'+e+'" =>',t)),n&&n instanceof Function&&n())}}},i=n.extend(t,e);return n.Settings=i||{},n}(_inboundOptions),_inboundHooks=function(e){var t=function(){function e(e,t,n,i){return"string"==typeof e&&"function"==typeof t&&(n=parseInt(n||10,10),s("actions",e,t,n,i)),d}function t(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t&&u("actions",t,e),d}function n(e,t){return"string"==typeof e&&r("actions",e,t),d}function i(e,t,n){return"string"==typeof e&&"function"==typeof t&&(n=parseInt(n||10,10),s("filters",e,t,n)),d}function o(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t?u("filters",t,e):d}function a(e,t){return"string"==typeof e&&r("filters",e,t),d}function r(e,t,n,i){if(c[e][t])if(n){var o,a=c[e][t];if(i)for(o=a.length;o--;){var r=a[o];r.callback===n&&r.context===i&&a.splice(o,1)}else for(o=a.length;o--;)a[o].callback===n&&a.splice(o,1)}else c[e][t]=[]}function s(e,t,n,i,o){var a={callback:n,priority:i,context:o},r=c[e][t];r?(r.push(a),r=l(r)):r=[a],c[e][t]=r}function l(e){for(var t,n,i,o=1,a=e.length;a>o;o++){for(t=e[o],n=o;(i=e[n-1])&&i.priority>t.priority;)e[n]=e[n-1],--n;e[n]=t}return e}function u(e,t,n){var i=c[e][t];if(!i)return"filters"===e?n[0]:!1;var o=0,a=i.length;if("filters"===e)for(;a>o;o++)n[0]=i[o].callback.apply(i[o].context,n);else for(;a>o;o++)i[o].callback.apply(i[o].context,n);return"filters"===e?n[0]:!0}var d={removeFilter:a,applyFilters:o,addFilter:i,removeAction:n,doAction:t,addAction:e},c={actions:{},filters:{}};return d};return e.hooks=new t,e.add_action=function(){var t=arguments[0].split(" ");for(k in t)arguments[0]="inbound."+t[k],e.hooks.addAction.apply(this,arguments);return this},e.remove_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeAction.apply(this,arguments),this},e.do_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.doAction.apply(this,arguments),this},e.add_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.addFilter.apply(this,arguments),this},e.remove_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeFilter.apply(this,arguments),this},e.apply_filters=function(){return arguments[0]="inbound."+arguments[0],e.hooks.applyFilters.apply(this,arguments)},e}(_inbound||{}),_inboundUtils=function(e){var t,n=window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest,i=(Object.prototype.toString,("https:"==location.protocol?"https://":"http://")+location.hostname+location.pathname.replace(/\/$/,"")),o={api_host:i,track_pageview:!0,track_links_timeout:300,cookie_name:"_sp",cookie_expiration:365,cookie_domain:(host=location.hostname.match(/[a-z0-9][a-z0-9\-]+\.[a-z\.]{2,6}$/i))?host[0]:""};return e.Utils={init:function(){this.polyFills(),this.checkLocalStorage(),this.SetUID(),this.storeReferralData()},polyFills:function(){window.console||(window.console={});for(var e=["log","info","warn","error","debug","trace","dir","group","groupCollapsed","groupEnd","time","timeEnd","profile","profileEnd","dirxml","assert","count","markTimeline","timeStamp","clear"],t=0;t<e.length;t++)window.console[e[t]]||(window.console[e[t]]=function(){});Date.prototype.toISOString||!function(){function e(e){var t=String(e);return 1===t.length&&(t="0"+t),t}Date.prototype.toISOString=function(){return this.getUTCFullYear()+"-"+e(this.getUTCMonth()+1)+"-"+e(this.getUTCDate())+"T"+e(this.getUTCHours())+":"+e(this.getUTCMinutes())+":"+e(this.getUTCSeconds())+"."+String((this.getUTCMilliseconds()/1e3).toFixed(3)).slice(2,5)+"Z"}}();try{new CustomEvent("?")}catch(n){this.CustomEvent=function(e,t){function n(n,o){var a=document.createEvent(e);return null!==n?i.call(a,n,(o||(o=t)).bubbles,o.cancelable,o.detail):a.initCustomEvent=i,a}function i(t,n,i,o){this["init"+e](t,n,i,o),"detail"in this||(this.detail=o)}return n}(this.CustomEvent?"CustomEvent":"Event",{bubbles:!1,cancelable:!1,detail:null})}document.querySelectorAll||(document.querySelectorAll=function(e){var t,n=document.createElement("style"),i=[];for(document.documentElement.firstChild.appendChild(n),document._qsa=[],n.styleSheet.cssText=e+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",window.scrollBy(0,0),n.parentNode.removeChild(n);document._qsa.length;)t=document._qsa.shift(),t.style.removeAttribute("x-qsa"),i.push(t);return document._qsa=null,i}),document.querySelector||(document.querySelector=function(e){var t=document.querySelectorAll(e);return t.length?t[0]:null}),!("innerText"in document.createElement("a"))&&"getSelection"in window&&HTMLElement.prototype.__defineGetter__("innerText",function(){for(var e,t=window.getSelection(),n=[],i=0;i<t.rangeCount;i++)n[i]=t.getRangeAt(i);t.removeAllRanges(),t.selectAllChildren(this),e=t.toString(),t.removeAllRanges();for(var i=0;i<n.length;i++)t.addRange(n[i]);return e})},createCookie:function(e,t,n){var i="";if(n){var o=new Date;o.setTime(o.getTime()+24*n*60*60*1e3),i="; expires="+o.toGMTString()}document.cookie=e+"="+t+i+"; path=/"},readCookie:function(e){for(var t=e+"=",n=document.cookie.split(";"),i=0;i<n.length;i++){for(var o=n[i];" "===o.charAt(0);)o=o.substring(1,o.length);if(0===o.indexOf(t))return o.substring(t.length,o.length)}return null},eraseCookie:function(e){this.createCookie(e,"",-1)},getAllCookies:function(){var t={};if(document.cookie&&""!==document.cookie)for(var n=document.cookie.split(";"),i=0;i<n.length;i++){var o=n[i].split("=");o[0]=o[0].replace(/^ /,""),t[decodeURIComponent(o[0])]=decodeURIComponent(o[1])}return e.totalStorage("inbound_cookies",t),t},setUrlParams:function(){var n={};!function(){for(var e,t=function(e){return decodeURIComponent(e).replace(/\+/g," ")},i=window.location.search.substring(1),o=/([^&=]+)=?([^&]*)/g;e=o.exec(i);)if("-1"==e[1].indexOf("["))n[t(e[1])]=t(e[2]);else{var a=e[1].indexOf("["),r=e[1].slice(a+1,e[1].indexOf("]",a)),s=t(e[1].slice(0,a));"object"!=typeof n[s]&&(n[t(s)]={},n[t(s)].length=0),r?n[t(s)][t(r)]=t(e[2]):Array.prototype.push.call(n[t(s)],t(e[2]))}}();for(var i in n)if("action"!=i)if("object"==typeof n[i])for(var o in n[i])this.createCookie(o,n[i][o],30);else this.createCookie(i,n[i],30);if(t){var a=e.totalStorage("inbound_url_params")||{},r=this.mergeObjs(a,n);e.totalStorage("inbound_url_params",r)}var s={option1:"yo",option2:"woooo"};e.trigger("url_parameters",n,s)},getAllUrlParams:function(){var n={};if(t)var n=e.totalStorage("inbound_url_params");return n},getParameterVal:function(e,t){return(RegExp(e+"=(.+?)(&|$)").exec(t)||[,!1])[1]},checkLocalStorage:function(){if("localStorage"in window)try{ls="undefined"==typeof window.localStorage?void 0:window.localStorage,t="undefined"==typeof ls||"undefined"==typeof window.JSON?!1:!0}catch(e){t=!1}return t},showLocalStorageSize:function(){function e(e){return 2*e.length}function t(e){return e/1024/1024}function n(t){return{name:t,size:e(localStorage[t])}}function i(e){return e.size=t(e.size).toFixed(2)+" MB",e}var o=Object.keys(localStorage).map(n).map(i);console.table(o)},addDays:function(e,t){return new Date(e.getTime()+24*t*60*60*1e3)},GetDate:function(){var e=new Date,t=e.getDate(),n=10>t?"0":"",i=e.getFullYear(),o=e.getHours(),a=10>o?"0":"",r=e.getMinutes(),s=10>r?"0":"",l=e.getSeconds(),u=10>l?"0":"",d=e.getMonth()+1,c=10>d?"0":"",m=i+"/"+c+d+"/"+n+t+" "+a+o+":"+s+r+":"+u+l;return m},SetSessionTimeout:function(){var e=(this.readCookie("lead_session_expire"),new Date);e.setTime(e.getTime()+18e5),this.createCookie("lead_session_expire",!0,e)},storeReferralData:function(){var t=new Date,n=document.referrer||"Direct Traffic",i=e.Utils.readCookie("inbound_referral_site"),o=e.totalStorage("inbound_original_referral");t.setTime(t.getTime()+18e5),i||this.createCookie("inbound_referral_site",n,t),o||e.totalStorage("inbound_original_referral",o)},CreateUID:function(e){var t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".split(""),n="";e||(e=Math.floor(Math.random()*t.length));for(var i=0;e>i;i++)n+=t[Math.floor(Math.random()*t.length)];return n},generateGUID:function(e){return e?(e^16*Math.random()>>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,guid)},SetUID:function(e){if(!this.readCookie("wp_lead_uid")){var t=e||this.CreateUID(35);this.createCookie("wp_lead_uid",t)}},countProperties:function(e){var t=0;for(var n in e)e.hasOwnProperty(n)&&++t;return t},mergeObjs:function(e,t){var n={};for(var i in e)n[i]=e[i];for(var i in t)n[i]=t[i];return n},hasClass:function(e,t){var n;if("classList"in document.documentElement)var n=t.classList.contains(e);else var n=new RegExp("(^|\\s)"+e+"(\\s|$)").test(t.className);return n},addClass:function(e,t){"classList"in document.documentElement?t.classList.add(e):this.hasClass(t,e)||(t.className+=(t.className?" ":"")+e)},removeClass:function(e,t){"classList"in document.documentElement?t.classList.remove(e):this.hasClass(t,e)&&(t.className=t.className.replace(new RegExp("(^|\\s)*"+e+"(\\s|$)*","g"),""))},removeElement:function(e){e.parentNode.removeChild(e)},trim:function(e){return e=e.replace(/(^\s*)|(\s*$)/gi,""),e=e.replace(/[ ]{2,}/gi," "),e=e.replace(/\n /,"\n")},ajaxPolyFill:function(){if("undefined"!=typeof XMLHttpRequest)return new XMLHttpRequest;for(var e,t=["MSXML2.XmlHttp.5.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp.2.0","Microsoft.XmlHttp"],n=0;n<t.length;n++)try{e=new ActiveXObject(t[n]);break}catch(i){}return e},ajaxSendData:function(e,t,n,i){var o=this.ajaxPolyFill();setTimeout(function(){o.open(n,e,!0),o.onreadystatechange=function(){4==o.readyState&&t(o.responseText)},"POST"==n&&o.setRequestHeader("Content-type","application/x-www-form-urlencoded"),o.send(i)},100)},ajaxGet:function(e,t,n,i){var o=[];for(var a in t)o.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e+"?"+o.join("&"),n,"GET",null,i)},ajaxPost:function(e,t,n,i){var o=[];for(var a in t)o.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e,n,"POST",o.join("&"),i)},sendEvent:function(e,t,i){t=t||{},async=!0;var a=getCookie();if(a){var r;for(r in a)t[r]=a[r]}t.id||(t.id=getId());var s={e:e,t:(new Date).toISOString(),kv:t},l=o.api_host+"/track?data="+encodeURIComponent(JSON.stringify(s));if(n){var u=new XMLHttpRequest;u.open("GET",l,async),u.withCredentials=async,u.send(null)}else{var d=document.createElement("script");d.type="text/javascript",d.async=async,d.defer=async,d.src=l;var c=document.getElementsByTagName("script")[0];c.parentNode.insertBefore(d,c)}return action(i),self},domReady:function(e,t){var n=!1,i=!0,o=e.document,a=o.documentElement,r=o.addEventListener?"addEventListener":"attachEvent",s=o.addEventListener?"removeEventListener":"detachEvent",l=o.addEventListener?"":"on",u=function(i){("readystatechange"!=i.type||"complete"==o.readyState)&&(("load"==i.type?e:o)[s](l+i.type,u,!1),!n&&(n=!0)&&t.call(e,i.type||i))},d=function(){try{a.doScroll("left")}catch(e){return setTimeout(d,50),void 0}u("poll")};if("complete"==o.readyState)t.call(e,"lazy");else{if(o.createEventObject&&a.doScroll){try{i=!e.frameElement}catch(c){}i&&d()}o[r](l+"DOMContentLoaded",u,!1),o[r](l+"readystatechange",u,!1),e[r](l+"load",u,!1)}},addListener:function(e,t,n){e&&(e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):e["on"+t]=n)},removeListener:function(e,t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):e["on"+t]=null},throttle:function(e,t){var n,i,o,a=null,r=0,s=function(){r=new Date,a=null,o=e.apply(n,i)};return function(){var l=new Date;r||(r=l);var u=t-(l-r);return n=this,i=arguments,0>=u?(clearTimeout(a),a=null,r=l,o=e.apply(n,i)):a||(a=setTimeout(s,u)),o}},checkTypeofGA:function(){"function"==typeof ga&&(universalGA=!0),"undefined"!=typeof _gaq&&"function"==typeof _gaq.push&&(classicGA=!0),"undefined"!=typeof dataLayer&&"function"==typeof dataLayer.push&&(googleTagManager=!0)}},e}(_inbound||{}),InboundForms=function(e){var t=!1,n=e.Utils,o=[],a=[],r=[],s=e.Settings,l=["first name","last name","name","email","e-mail","phone","website","job title","your favorite food","company","tele","address","comment"];if(e.Forms={init:function(){e.Forms.runFieldMappingFilters(),e.Forms.assignTrackClass(),e.Forms.formTrackInit()},runFieldMappingFilters:function(){l=e.hooks.applyFilters("forms.field_map",l)},debug:function(e,n){if(t&&console){var e=e||!1;e&&"string"==typeof e&&console.log(e),n&&n instanceof Function&&n()}},formTrackInit:function(){for(var e=0;e<window.document.forms.length;e++){var t=!1,n=window.document.forms[e];n.dataset.formProcessed||(n.dataset.formProcessed=!0,t=this.checkTrackStatus(n),t&&(this.attachFormSubmitEvent(n),this.initFormMapping(n)))}},checkTrackStatus:function(t){var n=t.getAttribute("class");return""!==n&&null!==n?n.toLowerCase().indexOf("wpl-track-me")>-1?!0:n.toLowerCase().indexOf("inbound-track")>-1?!0:(cb=function(){console.log(t)},e.deBugger("forms","This form not tracked. Please assign on in settings...",cb),!1):void 0},assignTrackClass:function(){if(window.inbound_settings){if(inbound_settings.inbound_track_include){var t=inbound_settings.inbound_track_include.split(","),n="add selectors "+inbound_settings.inbound_track_include;e.deBugger("forms",n),this.loopClassSelectors(t,"add")}if(inbound_settings.inbound_track_exclude){var t=inbound_settings.inbound_track_exclude.split(","),n="remove selectors "+inbound_settings.inbound_track_exclude;e.deBugger("forms",n),this.loopClassSelectors(t,"remove")}}},loopClassSelectors:function(t,i){for(var o=t.length-1;o>=0;o--){var a=n.trim(t[o]);-1===a.indexOf("#")&&-1===a.indexOf(".")&&(a="#"+a),a=document.querySelector(a),a&&("add"===i?(e.Utils.addClass("wpl-track-me",a),e.Utils.addClass("inbound-track",a)):(e.Utils.removeClass("wpl-track-me",a),e.Utils.removeClass("inbound-track",a)))}},initFormMapping:function(t){for(var n=[],i=0;i<t.elements.length;i++)formInput=t.elements[i],"hidden"!==formInput.type?(this.mapField(formInput),this.rememberInputValues(formInput),s.formAutoPopulation&&!e.Utils.hasClass("nopopulate",t)&&this.fillInputValues(formInput)):n.push(formInput);for(var o=n.length-1;o>=0;o--)formInput=n[o],this.mapField(formInput)},mapField:function(t){var a=t.id||!1,r=t.name||!1,s=this.getInputLabel(t);if(s){var u=this.ignoreFieldByLabel(s[0].innerText);if(u)return t.dataset.ignoreFormField=!0,!1}for(i=0;i<l.length;i++){var d=!1,c=l[i],m=n.trim(c),f=m.replace(/ /g,"_");r&&r.toLowerCase().indexOf(m)>-1?(d=!0,e.deBugger("forms","Found matching name attribute for -> "+m)):a&&a.toLowerCase().indexOf(m)>-1?(d=!0,e.deBugger("forms","Found matching ID attribute for ->"+m)):s?s[0].innerText.toLowerCase().indexOf(m)>-1&&(d=!0,e.deBugger("forms","Found matching sibling label for -> "+m)):o.push(m),d&&(this.addDataAttr(t,f),this.removeArrayItem(l,m),i--)}return inbound_data},formListener:function(t){t.preventDefault(),e.Forms.saveFormData(t.target),document.body.style.cursor="wait"},attachFormSubmitEvent:function(e){n.addListener(e,"submit",this.formListener);document.querySelector(".inbound-email")},ignoreFieldByLabel:function(t){var n=!1;return t?((-1!=t.toLowerCase().indexOf("credit card")||-1!=t.toLowerCase().indexOf("card number"))&&(n=!0),(-1!=t.toLowerCase().indexOf("expiration")||-1!=t.toLowerCase().indexOf("expiry"))&&(n=!0),("month"==t.toLowerCase()||"mm"==t.toLowerCase()||"yy"==t.toLowerCase()||"yyyy"==t.toLowerCase()||"year"==t.toLowerCase())&&(n=!0),(-1!=t.toLowerCase().indexOf("cvv")||-1!=t.toLowerCase().indexOf("cvc")||-1!=t.toLowerCase().indexOf("secure code")||-1!=t.toLowerCase().indexOf("security code"))&&(n=!0),n&&e.deBugger("forms","ignore "+t),n):!1},ignoreFieldByValue:function(e){var t=!1;if(!e)return!1;("visa"==e.toLowerCase()||"mastercard"==e.toLowerCase()||"american express"==e.toLowerCase()||"amex"==e.toLowerCase()||"discover"==e.toLowerCase())&&(t=!0);var n=new RegExp("/^[0-9]+$/");if(n.test(e)){var i=e.replace(" ","");this.isInt(i)&&i.length>=16&&(t=!0)}return t},isInt:function(e){return"number"==typeof e&&isFinite(e)&&e%1===0},releaseFormSubmit:function(e){document.body.style.cursor="default",n.removeClass("wpl-track-me",e),n.removeListener(e,"submit",this.formListener);var t=e.getAttribute("class");return""!==t&&null!==t&&-1!=t.toLowerCase().indexOf("wpcf7-form")?(setTimeout(function(){document.body.style.cursor="default"},300),!0):(e.submit(),setTimeout(function(){for(var t=0;t<e.elements.length;t++)formInput=e.elements[t],type=formInput.type||!1,"submit"===type&&"submit"===formInput.name&&e.elements[t].click()},2e3),void 0)},saveFormData:function(t){for(var i=i||{},o=0;o<t.elements.length;o++)if(formInput=t.elements[o],multiple=!1,formInput.name){if(formInput.dataset.ignoreFormField){e.deBugger("forms","ignore "+formInput.name);continue}switch(inputName=formInput.name.replace(/\[([^\[]*)\]/g,"%5B%5D$1"),i[inputName]||(i[inputName]={}),formInput.type&&(i[inputName].type=formInput.type),i[inputName].name||(i[inputName].name=formInput.name),formInput.dataset.mapFormField&&(i[inputName].map=formInput.dataset.mapFormField),formInput.nodeName){case"INPUT":if(l=this.getInputValue(formInput),l===!1)continue;break;case"TEXTAREA":l=formInput.value;break;case"SELECT":if(formInput.multiple){values=[],multiple=!0;for(var s=0;s<formInput.length;s++)formInput[s].selected&&values.push(encodeURIComponent(formInput[s].value))}else l=formInput.value}if(e.deBugger("forms","Input Value = "+l),l){i[inputName].value||(i[inputName].value=[]),i[inputName].value.push(multiple?values.join(","):encodeURIComponent(l));var l=multiple?values.join(","):encodeURIComponent(l)}}e.deBugger("forms",i);for(var u in i){var d=i[u].value,c=i[u].map;if("undefined"!=typeof d&&null!=d&&""!=d&&a.push(u+"="+i[u].value.join(",")),"undefined"!=typeof c&&null!=c&&i[u].value&&(r.push(c+"="+i[u].value.join(",")),"email"===u))var m=i[u].value.join(",")}var f=a.join("&");e.deBugger("forms","Stringified Raw Form PARAMS: "+f);var g=r.join("&");e.deBugger("forms","Stringified Mapped PARAMS"+g);var m=n.getParameterVal("email",g)||n.readCookie("wp_lead_email");m||(m=n.getParameterVal("wpleads_email_address",g));var p=n.getParameterVal("name",g),v=n.getParameterVal("first_name",g),h=n.getParameterVal("last_name",g);if(!h&&v){var _=decodeURI(v).split(" ");_.length>0&&(v=_[0],h=_[1])}if(p&&!h&&!v){var _=decodeURI(p).split(" ");_.length>0&&(v=_[0],h=_[1])}p=v&&h?v+" "+h:p,v||(v=""),h||(h=""),e.deBugger("forms","fName = "+v),e.deBugger("forms","lName = "+h),e.deBugger("forms","fullName = "+p);var b=e.totalStorage("page_views")||{},y=e.totalStorage("inbound_url_params")||{};if("undefined"!=typeof landing_path_info)var w=landing_path_info.variation;else if("undefined"!=typeof cta_path_info)var w=cta_path_info.variation;else var w=inbound_settings.variation_id;var k=inbound_settings.post_type||"page",C=inbound_settings.post_id||0;search_data={},formData={action:"inbound_lead_store",email:m,full_name:p,first_name:v,last_name:h,raw_params:f,mapped_params:g,url_params:JSON.stringify(y),search_data:"test",page_views:JSON.stringify(b),post_type:k,page_id:C,variation:w,source:n.readCookie("inbound_referral_site")},callback=function(i){e.deBugger("forms","Lead Created with ID: "+i),i=parseInt(i,10),formData.leadID=i,i&&(n.createCookie("wp_lead_id",i),e.totalStorage.deleteItem("page_views"),e.totalStorage.deleteItem("tracking_events")),e.trigger("form_after_submission",formData),e.Forms.releaseFormSubmit(t)},e.trigger("form_before_submission",formData),n.ajaxPost(inbound_settings.admin_url,formData,callback)},rememberInputValues:function(t){var i=(t.name?"inbound_"+t.name:"",t.type?t.type:"text");return"submit"===i||"hidden"===i||"file"===i||"password"===i||t.dataset.ignoreFormField?!1:(n.addListener(t,"change",function(t){if(t.target.name){if("checkbox"!==i)var o=t.target.value;else for(var a=[],r=document.querySelectorAll('input[name="'+t.target.name+'"]'),s=0;s<r.length;s++){var l=r[s].checked;l&&a.push(r[s].value),o=a.join(",")}inputData={name:t.target.name,node:t.target.nodeName.toLowerCase(),type:i,value:o,mapping:t.target.dataset.mapFormField},e.trigger("form_input_change",inputData),n.createCookie("inbound_"+t.target.name,encodeURIComponent(o))}}),void 0)},fillInputValues:function(e){var t=e.name?"inbound_"+e.name:"",i=e.type?e.type:"text";if("submit"===i||"hidden"===i||"file"===i||"password"===i)return!1;if(n.readCookie(t)&&"comment"!=t)if(value=decodeURIComponent(n.readCookie(t)),"checkbox"===i||"radio"===i)for(var o=value.split(","),a=0;a<o.length;a++)e.value.indexOf(o[a])>-1&&(e.checked=!0);else"undefined"!==value&&(e.value=value)},getInputLabel:function(e){var t;return(t=this.siblingsIsLabel(e))?t:(t=this.CheckParentForLabel(e))?t:!1},getInputValue:function(e){var t=!1;switch(e.type){case"radio":case"checkbox":e.checked&&(t=e.value);break;case"text":case"hidden":default:t=e.value}return t},addDataAttr:function(e,t){for(var n=document.getElementsByName(e.name),i=n.length-1;i>=0;i--)e.dataset.mapFormField||(n[i].dataset.mapFormField=t)},removeArrayItem:function(e,t){if(e.indexOf)index=e.indexOf(t);else for(index=e.length-1;index>=0&&e[index]!==t;--index);index>=0&&e.splice(index,1)},siblingsIsLabel:function(e){for(var t=this.getSiblings(e),n=[],i=t.length-1;i>=0;i--)"label"===t[i].nodeName.toLowerCase()&&n.push(t[i]);return n.length>0&&n.length<2?n:!1},getChildren:function(e,t){for(var n=[];e;e=e.nextSibling)1==e.nodeType&&e!=t&&n.push(e);return n},getSiblings:function(e){return this.getChildren(e.parentNode.firstChild,e)},CheckParentForLabel:function(e){if("FORM"===e.nodeName)return null;do{var t=e.getElementsByTagName("label");if(t.length>0&&t.length<2)return e.getElementsByTagName("label")}while(e=e.parentNode);return null},mailCheck:function(){var e=document.querySelector(".inbound-email");e&&(n.addListener(e,"blur",this.mailCheck),u.run({email:document.querySelector(".inbound-email").value,suggested:function(t){var i=document.querySelector(".email_suggestion");i&&n.removeElement(i);var o=document.createElement("span");o.innerHTML="<span class=\"email_suggestion\">Did youu mean <b><i id='email_correction' style='cursor: pointer;' title=\"click to update\">"+t.full+"</b></i>?</span>",e.parentNode.insertBefore(o,e.nextSibling);var a=document.getElementById("email_correction");n.addListener(a,"click",function(){e.value=a.innerHTML,a.parentNode.parentNode.innerHTML="Fixed!"})},empty:function(){}}))}},"undefined"==typeof u)var u={domainThreshold:1,topLevelThreshold:3,defaultDomains:["yahoo.com","google.com","hotmail.com","gmail.com","me.com","aol.com","mac.com","live.com","comcast.net","googlemail.com","msn.com","hotmail.co.uk","yahoo.co.uk","facebook.com","verizon.net","sbcglobal.net","att.net","gmx.com","mail.com","outlook.com","icloud.com"],defaultTopLevelDomains:["co.jp","co.uk","com","net","org","info","edu","gov","mil","ca","de"],run:function(e){e.domains=e.domains||u.defaultDomains,e.topLevelDomains=e.topLevelDomains||u.defaultTopLevelDomains,e.distanceFunction=e.distanceFunction||u.sift3Distance;var t=function(e){return e},n=e.suggested||t,i=e.empty||t,o=u.suggest(u.encodeEmail(e.email),e.domains,e.topLevelDomains,e.distanceFunction);return o?n(o):i()},suggest:function(e,t,n,i){e=e.toLowerCase();var o=this.splitEmail(e),a=this.findClosestDomain(o.domain,t,i,this.domainThreshold);if(a){if(a!=o.domain)return{address:o.address,domain:a,full:o.address+"@"+a}}else{var r=this.findClosestDomain(o.topLevelDomain,n,i,this.topLevelThreshold);if(o.domain&&r&&r!=o.topLevelDomain){var s=o.domain;return a=s.substring(0,s.lastIndexOf(o.topLevelDomain))+r,{address:o.address,domain:a,full:o.address+"@"+a}}}return!1},findClosestDomain:function(e,t,n,i){i=i||this.topLevelThreshold;var o,a=99,r=null;if(!e||!t)return!1;n||(n=this.sift3Distance);for(var s=0;s<t.length;s++){if(e===t[s])return e;o=n(e,t[s]),a>o&&(a=o,r=t[s])}return i>=a&&null!==r?r:!1},sift3Distance:function(e,t){if(null===e||0===e.length)return null===t||0===t.length?0:t.length;if(null===t||0===t.length)return e.length;for(var n=0,i=0,o=0,a=0,r=5;n+i<e.length&&n+o<t.length;){if(e.charAt(n+i)==t.charAt(n+o))a++;else{i=0,o=0;for(var s=0;r>s;s++){if(n+s<e.length&&e.charAt(n+s)==t.charAt(n)){i=s;break}if(n+s<t.length&&e.charAt(n)==t.charAt(n+s)){o=s;break}}}n++}return(e.length+t.length)/2-a},splitEmail:function(e){var t=e.trim().split("@");if(t.length<2)return!1;for(var n=0;n<t.length;n++)if(""===t[n])return!1;var i=t.pop(),o=i.split("."),a="";if(0===o.length)return!1;if(1==o.length)a=o[0];else{for(var n=1;n<o.length;n++)a+=o[n]+".";o.length>=2&&(a=a.substring(0,a.length-1))}return{topLevelDomain:a,domain:i,address:t.join("@")}},encodeEmail:function(e){var t=encodeURI(e);return t=t.replace("%20"," ").replace("%25","%").replace("%5E","^").replace("%60","`").replace("%7B","{").replace("%7C","|").replace("%7D","}")}};return e}(_inbound||{}),_inboundEvents=function(e){function t(t,i,o){var i=i||{};o=o||{},o.bubbles=o.bubbles||!0,o.cancelable=o.cancelable||!0,i=e.apply_filters("filter_"+t,i);!window.ActiveXObject&&"ActiveXObject"in window;if("function"==typeof CustomEvent)var a=new CustomEvent(t,{detail:i,bubbles:o.bubbles,cancelable:o.cancelable});else{var a=document.createEvent("Event");a.initEvent(t,!0,!0)}window.dispatchEvent(a),e.do_action(t,i),n(t,i)}function n(e,t){if(window.jQuery){var t=t||{};jQuery(document).trigger(e,t)}}e.trigger=function(t,n){e.Events[t](n)};return e.Events={analytics_ready:function(){var e={opt1:!0},n={data:"xyxy"};t("analytics_ready",n,e)},url_parameters:function(e){t("url_parameters",e)},session_start:function(){console.log(""),t("session_start")},session_end:function(e){t("session_end",e),console.log("Session End")},session_active:function(){t("session_active")},session_idle:function(e){t("session_idle",e)},session_resume:function(){t("session_resume")},session_heartbeat:function(e){var n={clock:e,leadData:InboundLeadData};t("session_heartbeat",n)},page_visit:function(e){t("page_view",e)},page_first_visit:function(){t("page_first_visit"),e.deBugger("pages","First Ever Page View of this Page")},page_revisit:function(n){t("page_revisit",n);var i=function(){console.log("pageData",n),console.log("Page Revisit viewed "+n+" times")};e.deBugger("pages",status,i)},tab_hidden:function(){e.deBugger("pages","Tab Hidden"),t("tab_hidden")},tab_visible:function(){e.deBugger("pages","Tab Visible"),t("tab_visible")},tab_mouseout:function(){e.deBugger("pages","Tab Mouseout"),t("tab_mouseout")},form_input_change:function(n){var i=function(){console.log(n)};e.deBugger("forms","inputData change. Data=",i),t("form_input_change",n)},form_before_submission:function(e){t("form_before_submission",e)},form_after_submission:function(e){t("form_after_submission",e)},analyticsError:function(e,t,n){var i=new CustomEvent("inbound_analytics_error",{detail:{MLHttpRequest:e,textStatus:t,errorThrown:n}});window.dispatchEvent(i),console.log("Page Save Error")}},e}(_inbound||{}),InboundTotalStorage=function(e){var t,n,i="_inbound";if("localStorage"in window)try{n="undefined"==typeof window.localStorage?void 0:window.localStorage,t="undefined"==typeof n||"undefined"==typeof window.JSON?!1:!0,window.localStorage.setItem(i,"1"),window.localStorage.removeItem(i)}catch(o){t=!1}e.totalStorage=function(t,n){return e.totalStorage.impl.init(t,n)},e.totalStorage.setItem=function(t,n){return e.totalStorage.impl.setItem(t,n)},e.totalStorage.getItem=function(t){return e.totalStorage.impl.getItem(t)},e.totalStorage.getAll=function(){return e.totalStorage.impl.getAll()},e.totalStorage.deleteItem=function(t){return e.totalStorage.impl.deleteItem(t)},e.totalStorage.impl={init:function(e,t){return"undefined"!=typeof t?this.setItem(e,t):this.getItem(e)},setItem:function(i,o){if(!t)try{return e.Utils.createCookie(i,o),o}catch(a){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 r=JSON.stringify(o);return n.setItem(i,r),this.parseResult(r)},getItem:function(i){if(!t)try{return this.parseResult(e.Utils.readCookie(i))}catch(o){return null}var a=n.getItem(i);return this.parseResult(a)},deleteItem:function(i){if(!t)try{return e.Utils.eraseCookie(i,null),!0}catch(o){return!1}return n.removeItem(i),!0},getAll:function(){var i=[];if(t)for(var o in n)o.length&&i.push({key:o,value:this.parseResult(n.getItem(o))});else try{for(var a=document.cookie.split(";"),r=0;r<a.length;r++){var s=a[r].split("="),l=s[0];i.push({key:l,value:this.parseResult(e.Utils.readCookie(l))})}}catch(u){return null}return i},parseResult:function(e){var t;try{t=JSON.parse(e),"undefined"==typeof t&&(t=e),"true"==t&&(t=!0),"false"==t&&(t=!1),parseFloat(t)==t&&"object"!=typeof t&&(t=parseFloat(t))}catch(n){t=e}return t}}}(_inbound||{}),_inboundLeadsAPI=function(e){return e.LeadsAPI={init:function(){var t=e.Utils,n=(t.readCookie("wp_lead_uid"),t.readCookie("wp_lead_id")),i=t.readCookie("lead_session_expire");i||(e.deBugger("leads","expired vistor. Run Processes"),n&&e.LeadsAPI.getAllLeadData())},setGlobalLeadData:function(e){InboundLeadData=e},getAllLeadData:function(){var t=e.Utils.readCookie("wp_lead_id"),n=e.totalStorage("inbound_lead_data"),i=e.Utils.readCookie("lead_data_expire");data={action:"inbound_get_all_lead_data",wp_lead_id:t},success=function(t){var n=JSON.parse(t);e.LeadsAPI.setGlobalLeadData(n),e.totalStorage("inbound_lead_data",n);var i=new Date;i.setTime(i.getTime()+18e5);var o=e.Utils.addDays(i,3);e.Utils.createCookie("lead_data_expire",!0,o)},n?(e.LeadsAPI.setGlobalLeadData(n),e.deBugger("lead","Set Global Lead Data from Localstorage"),i||(e.Utils.ajaxPost(inbound_settings.admin_url,data,success),e.deBugger("lead","localized data old. Pull new from DB"))):e.Utils.ajaxPost(inbound_settings.admin_url,data,success)},getLeadLists:function(){var t=e.Utils.readCookie("wp_lead_id"),n={action:"wpl_check_lists",wp_lead_id:t},i=function(){e.Utils.createCookie("lead_session_list_check",!0,{path:"/",expires:1}),e.deBugger("lead","Lists checked")};e.Utils.ajaxPost(inbound_settings.admin_url,n,i)}},e}(_inbound||{}),_inboundPageTracking=function(e){var t,n,i=!1,o=!1,a=!1,r=parseInt(e.Utils.readCookie("lead_session"),10)||0,s=0,l=(new Date,null),u=null,d=null,c=e.Utils,m=e.Utils.GetDate(),f="page_views",g=e.totalStorage(f)||{},p=inbound_settings.post_id||window.location.pathname,v=e.Settings.timeout||1e4;return e.PageTracking={init:function(i){return"page_views"!==f?!1:(this.CheckTimeOut(),i=i||{},t=parseInt(i.reportInterval,10)||10,n=parseInt(i.idleTimeout,10)||3,c.addListener(document,"keydown",c.throttle(e.PageTracking.pingSession,1e3)),c.addListener(document,"click",c.throttle(e.PageTracking.pingSession,1e3)),c.addListener(window,"mousemove",c.throttle(e.PageTracking.pingSession,1e3)),e.PageTracking.checkVisibility(),this.startSession(),void 0)},setIdle:function(t){var t=t||"No Movement",n="Session IDLE. Activity Timeout due to "+t;
3
- e.deBugger("pages",n),clearTimeout(e.PageTracking.idleTimer),e.PageTracking.stopClock(),e.trigger("session_idle")},checkVisibility:function(){var t,n,i;"undefined"!=typeof document.hidden?(t="hidden",i="visibilitychange",n="visibilityState"):"undefined"!=typeof document.mozHidden?(t="mozHidden",i="mozvisibilitychange",n="mozVisibilityState"):"undefined"!=typeof document.msHidden?(t="msHidden",i="msvisibilitychange",n="msVisibilityState"):"undefined"!=typeof document.webkitHidden&&(t="webkitHidden",i="webkitvisibilitychange",n="webkitVisibilityState");var o=document[t];e.Utils.addListener(document,i,function(){o!=document[t]&&(document[t]?(e.trigger("tab_hidden"),e.PageTracking.setIdle("browser tab switch")):(e.trigger("tab_visible"),e.PageTracking.pingSession()),o=document[t])})},clock:function(){r+=1;var n=r/60,i="Total time spent on Page in this Session: "+n.toFixed(2)+" min";if(e.deBugger("pages",i),r>0&&r%t===0){var o=new Date;o.setTime(o.getTime()+18e5),c.createCookie("lead_session",r,o),e.trigger("session_heartbeat",r)}},inactiveClock:function(){s+=1;var t=(1800-s)/60,n="Time until Session Timeout: "+t.toFixed(2)+" min";e.deBugger("pages",n),s>1800&&(e.trigger("session_end",InboundLeadData),e.Utils.eraseCookie("lead_session"),s=0,clearTimeout(u))},stopClock:function(){o=!0,clearTimeout(l),clearTimeout(u),u=setInterval(e.PageTracking.inactiveClock,1e3)},restartClock:function(){o=!1,e.trigger("session_resume"),e.deBugger("pages","Activity resumed. Session Active"),clearTimeout(l),s=0,clearTimeout(u),l=setInterval(e.PageTracking.clock,1e3)},turnOff:function(){e.PageTracking.setIdle(),a=!0},turnOn:function(){a=!1},startSession:function(){new Date;i=!0,l=setInterval(e.PageTracking.clock,1e3);var t=c.readCookie("lead_session");if(t)e.trigger("session_active");else{e.trigger("session_start");var n=new Date;n.setTime(n.getTime()+18e5),e.Utils.createCookie("lead_session",1,n)}this.pingSession()},resetInactiveFunc:function(){s=0,clearTimeout(u)},pingSession:function(t){a||(i||e.PageTracking.startSession(),o&&e.PageTracking.restartClock(),clearTimeout(d),d=setTimeout(e.PageTracking.setIdle,1e3*n+100),"undefined"!=typeof t&&"mousemove"===t.type&&e.PageTracking.mouseEvents(t))},mouseEvents:function(t){t.pageY<=5&&e.trigger("tab_mouseout")},getPageViews:function(){var t=e.Utils.checkLocalStorage();if(t){var n=localStorage.getItem(f),i=JSON.parse(n);return i}},isRevisit:function(e){var t=!1,e=e||{},n=e[p];return"undefined"!=typeof n&&null!==n&&(t=!0),t},triggerPageView:function(t){var n={title:document.title,url:document.location.href,path:document.location.pathname,count:1};t?(g[p].push(m),n.count=g[p].length,e.trigger("page_revisit",n)):(g[p]=[],g[p].push(m),e.trigger("page_first_visit",n)),e.trigger("page_visit",n),e.totalStorage(f,g),this.storePageView()},CheckTimeOut:function(){var t,n,i=this.isRevisit(g);if(i){var o=g[p].length-1,a=g[p][o],r=Math.abs(new Date(a).getTime()-new Date(m).getTime());n=r>v,n?(t="Timeout Happened. Page view fired",this.triggerPageView(i)):(time_left=.001*Math.abs(v-r),t=v/1e3+" sec timeout not done: "+time_left+" seconds left")}else this.triggerPageView(i);e.deBugger("pages",t)},storePageView:function(){if("off"!=inbound_settings.page_tracking){var t=e.Utils.readCookie("wp_lead_id")?e.Utils.readCookie("wp_lead_id"):"",n=e.Utils.readCookie("wp_lead_uid")?e.Utils.readCookie("wp_lead_uid"):"",i={action:"inbound_track_lead",wp_lead_uid:n,wp_lead_id:t,page_id:inbound_settings.post_id,variation_id:inbound_settings.variation_id,post_type:inbound_settings.post_type,current_url:window.location.href,page_views:JSON.stringify(e.PageTracking.getPageViews()),json:"0"},o=function(){};e.Utils.ajaxPost(inbound_settings.admin_url,i,o)}}},e}(_inbound||{});_inbound.init(),InboundLeadData=_inbound.totalStorage("inbound_lead_data")||null;
1
  /*! Inbound Analyticsv1.0.0 | (c) 2016 Inbound Now | https://github.com/inboundnow/cta */
2
+ function inboundFormNoRedirect(){if(null==window.frames.frameElement)var e=document.querySelectorAll("button.inbound-button-submit[disabled]")[0];else if("iframe"==window.frames.frameElement.tagName.toLowerCase())var e=window.frames.frameElement.contentWindow.document.querySelectorAll("button.inbound-button-submit")[0];if("undefined"!=typeof e){var t=e.form,n=t.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])');(0==n.length||"IA=="==n[0].value)&&(t.action="javascript:void(0)")}}function inboundFormNoRedirectContent(){if(null==window.frames.frameElement)var e=document.querySelectorAll("button.inbound-button-submit[disabled]")[0];else if("iframe"==window.frames.frameElement.tagName.toLowerCase())var e=window.frames.frameElement.contentWindow.document.querySelectorAll("button.inbound-button-submit")[0];if("undefined"!=typeof e){var t=e.form,n=t.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])'),i=jQuery(e).css("background"),o=jQuery(e).css("color"),a=jQuery(e).css("height"),r=e.getElementsByClassName("inbound-form-spinner");(0==n.length||"IA=="==n[0].value)&&(jQuery(r).remove(),jQuery(e).prepend('<div id="redir-check"><i class="fa fa-check-square" aria-hidden="true" style="background='+i+"; color="+o+"; font-size:calc("+a+' * .42);"></i></div>'))}}var inbound_data=inbound_data||{},_inboundOptions=_inboundOptions||{},_gaq=_gaq||[],_inbound=function(e){var t={timeout:inbound_settings.is_admin?500:1e4,formAutoTracking:!0,formAutoPopulation:!0},n={init:function(){_inbound.Utils.init(),_inbound.Utils.domReady(window,function(){_inbound.DomLoaded()})},DomLoaded:function(){_inbound.PageTracking.init(),_inbound.Forms.init(),_inbound.Utils.setUrlParams(),_inbound.LeadsAPI.init(),setTimeout(function(){_inbound.Forms.init()},2e3),_inbound.trigger("analytics_ready")},extend:function(e,t){var n,i={};for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(i[n]=e[n]);for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(i[n]=t[n]);return i},debug:function(){},deBugger:function(e,t,n){if(console){var i,o,a,r=document.location.hash?document.location.hash:"",s=r.indexOf("#debug")>-1,t=t||!1;r&&r.match(/debug/)&&(r=r.split("-"),a=r[1]),o="true"===_inbound.Utils.readCookie("inbound_debug")?!0:!1,i="true"===_inbound.Utils.readCookie("inbound_debug_"+e)?!0:!1,(i||s||o)&&(t&&"string"==typeof t&&(o||"all"===a?console.log('logAll "'+e+'" =>',t):i?console.log('log "'+e+'" =>',t):e===a&&console.log('#log "'+e+'" =>',t)),n&&n instanceof Function&&n())}}},i=n.extend(t,e);return n.Settings=i||{},n}(_inboundOptions),_inboundHooks=function(e){var t=function(){function e(e,t,n,i){return"string"==typeof e&&"function"==typeof t&&(n=parseInt(n||10,10),s("actions",e,t,n,i)),d}function t(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t&&u("actions",t,e),d}function n(e,t){return"string"==typeof e&&r("actions",e,t),d}function i(e,t,n){return"string"==typeof e&&"function"==typeof t&&(n=parseInt(n||10,10),s("filters",e,t,n)),d}function o(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t?u("filters",t,e):d}function a(e,t){return"string"==typeof e&&r("filters",e,t),d}function r(e,t,n,i){if(c[e][t])if(n){var o,a=c[e][t];if(i)for(o=a.length;o--;){var r=a[o];r.callback===n&&r.context===i&&a.splice(o,1)}else for(o=a.length;o--;)a[o].callback===n&&a.splice(o,1)}else c[e][t]=[]}function s(e,t,n,i,o){var a={callback:n,priority:i,context:o},r=c[e][t];r?(r.push(a),r=l(r)):r=[a],c[e][t]=r}function l(e){for(var t,n,i,o=1,a=e.length;a>o;o++){for(t=e[o],n=o;(i=e[n-1])&&i.priority>t.priority;)e[n]=e[n-1],--n;e[n]=t}return e}function u(e,t,n){var i=c[e][t];if(!i)return"filters"===e?n[0]:!1;var o=0,a=i.length;if("filters"===e)for(;a>o;o++)n[0]=i[o].callback.apply(i[o].context,n);else for(;a>o;o++)i[o].callback.apply(i[o].context,n);return"filters"===e?n[0]:!0}var d={removeFilter:a,applyFilters:o,addFilter:i,removeAction:n,doAction:t,addAction:e},c={actions:{},filters:{}};return d};return e.hooks=new t,e.add_action=function(){var t=arguments[0].split(" ");for(k in t)arguments[0]="inbound."+t[k],e.hooks.addAction.apply(this,arguments);return this},e.remove_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeAction.apply(this,arguments),this},e.do_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.doAction.apply(this,arguments),this},e.add_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.addFilter.apply(this,arguments),this},e.remove_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeFilter.apply(this,arguments),this},e.apply_filters=function(){return arguments[0]="inbound."+arguments[0],e.hooks.applyFilters.apply(this,arguments)},e}(_inbound||{}),_inboundUtils=function(e){var t,n=window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest,i=(Object.prototype.toString,("https:"==location.protocol?"https://":"http://")+location.hostname+location.pathname.replace(/\/$/,"")),o={api_host:i,track_pageview:!0,track_links_timeout:300,cookie_name:"_sp",cookie_expiration:365,cookie_domain:(host=location.hostname.match(/[a-z0-9][a-z0-9\-]+\.[a-z\.]{2,6}$/i))?host[0]:""};return e.Utils={init:function(){this.polyFills(),this.checkLocalStorage(),this.SetUID(),this.storeReferralData()},polyFills:function(){window.console||(window.console={});for(var e=["log","info","warn","error","debug","trace","dir","group","groupCollapsed","groupEnd","time","timeEnd","profile","profileEnd","dirxml","assert","count","markTimeline","timeStamp","clear"],t=0;t<e.length;t++)window.console[e[t]]||(window.console[e[t]]=function(){});Date.prototype.toISOString||!function(){function e(e){var t=String(e);return 1===t.length&&(t="0"+t),t}Date.prototype.toISOString=function(){return this.getUTCFullYear()+"-"+e(this.getUTCMonth()+1)+"-"+e(this.getUTCDate())+"T"+e(this.getUTCHours())+":"+e(this.getUTCMinutes())+":"+e(this.getUTCSeconds())+"."+String((this.getUTCMilliseconds()/1e3).toFixed(3)).slice(2,5)+"Z"}}();try{new CustomEvent("?")}catch(n){this.CustomEvent=function(e,t){function n(n,o){var a=document.createEvent(e);return null!==n?i.call(a,n,(o||(o=t)).bubbles,o.cancelable,o.detail):a.initCustomEvent=i,a}function i(t,n,i,o){this["init"+e](t,n,i,o),"detail"in this||(this.detail=o)}return n}(this.CustomEvent?"CustomEvent":"Event",{bubbles:!1,cancelable:!1,detail:null})}document.querySelectorAll||(document.querySelectorAll=function(e){var t,n=document.createElement("style"),i=[];for(document.documentElement.firstChild.appendChild(n),document._qsa=[],n.styleSheet.cssText=e+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",window.scrollBy(0,0),n.parentNode.removeChild(n);document._qsa.length;)t=document._qsa.shift(),t.style.removeAttribute("x-qsa"),i.push(t);return document._qsa=null,i}),document.querySelector||(document.querySelector=function(e){var t=document.querySelectorAll(e);return t.length?t[0]:null}),!("innerText"in document.createElement("a"))&&"getSelection"in window&&HTMLElement.prototype.__defineGetter__("innerText",function(){for(var e,t=window.getSelection(),n=[],i=0;i<t.rangeCount;i++)n[i]=t.getRangeAt(i);t.removeAllRanges(),t.selectAllChildren(this),e=t.toString(),t.removeAllRanges();for(var i=0;i<n.length;i++)t.addRange(n[i]);return e})},createCookie:function(e,t,n){var i="";if(n){var o=new Date;o.setTime(o.getTime()+24*n*60*60*1e3),i="; expires="+o.toGMTString()}document.cookie=e+"="+t+i+"; path=/"},readCookie:function(e){for(var t=e+"=",n=document.cookie.split(";"),i=0;i<n.length;i++){for(var o=n[i];" "===o.charAt(0);)o=o.substring(1,o.length);if(0===o.indexOf(t))return o.substring(t.length,o.length)}return null},eraseCookie:function(e){this.createCookie(e,"",-1)},getAllCookies:function(){var t={};if(document.cookie&&""!==document.cookie)for(var n=document.cookie.split(";"),i=0;i<n.length;i++){var o=n[i].split("=");o[0]=o[0].replace(/^ /,""),t[decodeURIComponent(o[0])]=decodeURIComponent(o[1])}return e.totalStorage("inbound_cookies",t),t},setUrlParams:function(){var n={};!function(){for(var e,t=function(e){return decodeURIComponent(e).replace(/\+/g," ")},i=window.location.search.substring(1),o=/([^&=]+)=?([^&]*)/g;e=o.exec(i);)if("-1"==e[1].indexOf("["))n[t(e[1])]=t(e[2]);else{var a=e[1].indexOf("["),r=e[1].slice(a+1,e[1].indexOf("]",a)),s=t(e[1].slice(0,a));"object"!=typeof n[s]&&(n[t(s)]={},n[t(s)].length=0),r?n[t(s)][t(r)]=t(e[2]):Array.prototype.push.call(n[t(s)],t(e[2]))}}();for(var i in n)if("action"!=i)if("object"==typeof n[i])for(var o in n[i])this.createCookie(o,n[i][o],30);else this.createCookie(i,n[i],30);if(t){var a=e.totalStorage("inbound_url_params")||{},r=this.mergeObjs(a,n);e.totalStorage("inbound_url_params",r)}var s={option1:"yo",option2:"woooo"};e.trigger("url_parameters",n,s)},getAllUrlParams:function(){var n={};if(t)var n=e.totalStorage("inbound_url_params");return n},getParameterVal:function(e,t){return(RegExp(e+"=(.+?)(&|$)").exec(t)||[,!1])[1]},checkLocalStorage:function(){if("localStorage"in window)try{ls="undefined"==typeof window.localStorage?void 0:window.localStorage,t="undefined"==typeof ls||"undefined"==typeof window.JSON?!1:!0}catch(e){t=!1}return t},showLocalStorageSize:function(){function e(e){return 2*e.length}function t(e){return e/1024/1024}function n(t){return{name:t,size:e(localStorage[t])}}function i(e){return e.size=t(e.size).toFixed(2)+" MB",e}var o=Object.keys(localStorage).map(n).map(i);console.table(o)},addDays:function(e,t){return new Date(e.getTime()+24*t*60*60*1e3)},GetDate:function(){var e=new Date,t=e.getDate(),n=10>t?"0":"",i=e.getFullYear(),o=e.getHours(),a=10>o?"0":"",r=e.getMinutes(),s=10>r?"0":"",l=e.getSeconds(),u=10>l?"0":"",d=e.getMonth()+1,c=10>d?"0":"",m=i+"/"+c+d+"/"+n+t+" "+a+o+":"+s+r+":"+u+l;return m},SetSessionTimeout:function(){var e=(this.readCookie("lead_session_expire"),new Date);e.setTime(e.getTime()+18e5),this.createCookie("lead_session_expire",!0,e)},storeReferralData:function(){var t=new Date,n=document.referrer||"Direct Traffic",i=e.Utils.readCookie("inbound_referral_site"),o=e.totalStorage("inbound_original_referral");t.setTime(t.getTime()+18e5),i||this.createCookie("inbound_referral_site",n,t),o||e.totalStorage("inbound_original_referral",o)},CreateUID:function(e){var t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".split(""),n="";e||(e=Math.floor(Math.random()*t.length));for(var i=0;e>i;i++)n+=t[Math.floor(Math.random()*t.length)];return n},generateGUID:function(e){return e?(e^16*Math.random()>>e/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,guid)},SetUID:function(e){if(!this.readCookie("wp_lead_uid")){var t=e||this.CreateUID(35);this.createCookie("wp_lead_uid",t)}},countProperties:function(e){var t=0;for(var n in e)e.hasOwnProperty(n)&&++t;return t},mergeObjs:function(e,t){var n={};for(var i in e)n[i]=e[i];for(var i in t)n[i]=t[i];return n},hasClass:function(e,t){var n;if("classList"in document.documentElement)var n=t.classList.contains(e);else var n=new RegExp("(^|\\s)"+e+"(\\s|$)").test(t.className);return n},addClass:function(e,t){"classList"in document.documentElement?t.classList.add(e):this.hasClass(t,e)||(t.className+=(t.className?" ":"")+e)},removeClass:function(e,t){"classList"in document.documentElement?t.classList.remove(e):this.hasClass(t,e)&&(t.className=t.className.replace(new RegExp("(^|\\s)*"+e+"(\\s|$)*","g"),""))},removeElement:function(e){e.parentNode.removeChild(e)},trim:function(e){return e=e.replace(/(^\s*)|(\s*$)/gi,""),e=e.replace(/[ ]{2,}/gi," "),e=e.replace(/\n /,"\n")},ajaxPolyFill:function(){if("undefined"!=typeof XMLHttpRequest)return new XMLHttpRequest;for(var e,t=["MSXML2.XmlHttp.5.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp.2.0","Microsoft.XmlHttp"],n=0;n<t.length;n++)try{e=new ActiveXObject(t[n]);break}catch(i){}return e},ajaxSendData:function(e,t,n,i){var o=this.ajaxPolyFill();setTimeout(function(){o.open(n,e,!0),o.onreadystatechange=function(){4==o.readyState&&t(o.responseText)},"POST"==n&&o.setRequestHeader("Content-type","application/x-www-form-urlencoded"),o.send(i)},100)},ajaxGet:function(e,t,n,i){var o=[];for(var a in t)o.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e+"?"+o.join("&"),n,"GET",null,i)},ajaxPost:function(e,t,n,i){var o=[];for(var a in t)o.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e,n,"POST",o.join("&"),i)},sendEvent:function(e,t,i){t=t||{},async=!0;var a=getCookie();if(a){var r;for(r in a)t[r]=a[r]}t.id||(t.id=getId());var s={e:e,t:(new Date).toISOString(),kv:t},l=o.api_host+"/track?data="+encodeURIComponent(JSON.stringify(s));if(n){var u=new XMLHttpRequest;u.open("GET",l,async),u.withCredentials=async,u.send(null)}else{var d=document.createElement("script");d.type="text/javascript",d.async=async,d.defer=async,d.src=l;var c=document.getElementsByTagName("script")[0];c.parentNode.insertBefore(d,c)}return action(i),self},domReady:function(e,t){var n=!1,i=!0,o=e.document,a=o.documentElement,r=o.addEventListener?"addEventListener":"attachEvent",s=o.addEventListener?"removeEventListener":"detachEvent",l=o.addEventListener?"":"on",u=function(i){("readystatechange"!=i.type||"complete"==o.readyState)&&(("load"==i.type?e:o)[s](l+i.type,u,!1),!n&&(n=!0)&&t.call(e,i.type||i))},d=function(){try{a.doScroll("left")}catch(e){return setTimeout(d,50),void 0}u("poll")};if("complete"==o.readyState)t.call(e,"lazy");else{if(o.createEventObject&&a.doScroll){try{i=!e.frameElement}catch(c){}i&&d()}o[r](l+"DOMContentLoaded",u,!1),o[r](l+"readystatechange",u,!1),e[r](l+"load",u,!1)}},addListener:function(e,t,n){e&&(e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):e["on"+t]=n)},removeListener:function(e,t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):e["on"+t]=null},throttle:function(e,t){var n,i,o,a=null,r=0,s=function(){r=new Date,a=null,o=e.apply(n,i)};return function(){var l=new Date;r||(r=l);var u=t-(l-r);return n=this,i=arguments,0>=u?(clearTimeout(a),a=null,r=l,o=e.apply(n,i)):a||(a=setTimeout(s,u)),o}},checkTypeofGA:function(){"function"==typeof ga&&(universalGA=!0),"undefined"!=typeof _gaq&&"function"==typeof _gaq.push&&(classicGA=!0),"undefined"!=typeof dataLayer&&"function"==typeof dataLayer.push&&(googleTagManager=!0)}},e}(_inbound||{}),InboundForms=function(e){var t=!1,n=e.Utils,o=[],a=[],r=[],s=e.Settings,l=["first name","last name","name","email","e-mail","phone","website","job title","your favorite food","company","tele","address","comment"];if(e.Forms={init:function(){e.Forms.runFieldMappingFilters(),e.Forms.assignTrackClass(),e.Forms.formTrackInit()},runFieldMappingFilters:function(){l=e.hooks.applyFilters("forms.field_map",l)},debug:function(e,n){if(t&&console){var e=e||!1;e&&"string"==typeof e&&console.log(e),n&&n instanceof Function&&n()}},formTrackInit:function(){for(var e=0;e<window.document.forms.length;e++){var t=!1,n=window.document.forms[e];n.dataset.formProcessed||(n.dataset.formProcessed=!0,t=this.checkTrackStatus(n),t&&(this.attachFormSubmitEvent(n),this.initFormMapping(n)))}},checkTrackStatus:function(t){var n=t.getAttribute("class");return""!==n&&null!==n?n.toLowerCase().indexOf("wpl-track-me")>-1?!0:n.toLowerCase().indexOf("inbound-track")>-1?!0:(cb=function(){console.log(t)},e.deBugger("forms","This form not tracked. Please assign on in settings...",cb),!1):void 0},assignTrackClass:function(){if(window.inbound_settings){if(inbound_settings.inbound_track_include){var t=inbound_settings.inbound_track_include.split(","),n="add selectors "+inbound_settings.inbound_track_include;e.deBugger("forms",n),this.loopClassSelectors(t,"add")}if(inbound_settings.inbound_track_exclude){var t=inbound_settings.inbound_track_exclude.split(","),n="remove selectors "+inbound_settings.inbound_track_exclude;e.deBugger("forms",n),this.loopClassSelectors(t,"remove")}}},loopClassSelectors:function(t,i){for(var o=t.length-1;o>=0;o--){var a=n.trim(t[o]);-1===a.indexOf("#")&&-1===a.indexOf(".")&&(a="#"+a),a=document.querySelector(a),a&&("add"===i?(e.Utils.addClass("wpl-track-me",a),e.Utils.addClass("inbound-track",a)):(e.Utils.removeClass("wpl-track-me",a),e.Utils.removeClass("inbound-track",a)))}},initFormMapping:function(t){for(var n=[],i=0;i<t.elements.length;i++)formInput=t.elements[i],"hidden"!==formInput.type?(this.mapField(formInput),this.rememberInputValues(formInput),s.formAutoPopulation&&!e.Utils.hasClass("nopopulate",t)&&this.fillInputValues(formInput)):n.push(formInput);for(var o=n.length-1;o>=0;o--)formInput=n[o],this.mapField(formInput)},mapField:function(t){var a=t.id||!1,r=t.name||!1,s=this.getInputLabel(t);if(s){var u=this.ignoreFieldByLabel(s[0].innerText);if(u)return t.dataset.ignoreFormField=!0,!1}for(i=0;i<l.length;i++){var d=!1,c=l[i],m=n.trim(c),f=m.replace(/ /g,"_");r&&r.toLowerCase().indexOf(m)>-1?(d=!0,e.deBugger("forms","Found matching name attribute for -> "+m)):a&&a.toLowerCase().indexOf(m)>-1?(d=!0,e.deBugger("forms","Found matching ID attribute for ->"+m)):s?s[0].innerText.toLowerCase().indexOf(m)>-1&&(d=!0,e.deBugger("forms","Found matching sibling label for -> "+m)):o.push(m),d&&(this.addDataAttr(t,f),this.removeArrayItem(l,m),i--)}return inbound_data},formListener:function(t){t.preventDefault(),e.Forms.saveFormData(t.target),document.body.style.cursor="wait"},attachFormSubmitEvent:function(e){n.addListener(e,"submit",this.formListener);document.querySelector(".inbound-email")},ignoreFieldByLabel:function(t){var n=!1;return t?((-1!=t.toLowerCase().indexOf("credit card")||-1!=t.toLowerCase().indexOf("card number"))&&(n=!0),(-1!=t.toLowerCase().indexOf("expiration")||-1!=t.toLowerCase().indexOf("expiry"))&&(n=!0),("month"==t.toLowerCase()||"mm"==t.toLowerCase()||"yy"==t.toLowerCase()||"yyyy"==t.toLowerCase()||"year"==t.toLowerCase())&&(n=!0),(-1!=t.toLowerCase().indexOf("cvv")||-1!=t.toLowerCase().indexOf("cvc")||-1!=t.toLowerCase().indexOf("secure code")||-1!=t.toLowerCase().indexOf("security code"))&&(n=!0),n&&e.deBugger("forms","ignore "+t),n):!1},ignoreFieldByValue:function(e){var t=!1;if(!e)return!1;("visa"==e.toLowerCase()||"mastercard"==e.toLowerCase()||"american express"==e.toLowerCase()||"amex"==e.toLowerCase()||"discover"==e.toLowerCase())&&(t=!0);var n=new RegExp("/^[0-9]+$/");if(n.test(e)){var i=e.replace(" ","");this.isInt(i)&&i.length>=16&&(t=!0)}return t},isInt:function(e){return"number"==typeof e&&isFinite(e)&&e%1===0},releaseFormSubmit:function(e){document.body.style.cursor="default",n.removeClass("wpl-track-me",e),n.removeListener(e,"submit",this.formListener);var t=e.getAttribute("class");return""!==t&&null!==t&&-1!=t.toLowerCase().indexOf("wpcf7-form")?(setTimeout(function(){document.body.style.cursor="default"},300),!0):(e.submit(),setTimeout(function(){for(var t=0;t<e.elements.length;t++)formInput=e.elements[t],type=formInput.type||!1,"submit"===type&&"submit"===formInput.name&&e.elements[t].click()},2e3),void 0)},saveFormData:function(t){for(var i=i||{},o=0;o<t.elements.length;o++)if(formInput=t.elements[o],multiple=!1,formInput.name){if(formInput.dataset.ignoreFormField){e.deBugger("forms","ignore "+formInput.name);continue}switch(inputName=formInput.name.replace(/\[([^\[]*)\]/g,"%5B%5D$1"),i[inputName]||(i[inputName]={}),formInput.type&&(i[inputName].type=formInput.type),i[inputName].name||(i[inputName].name=formInput.name),formInput.dataset.mapFormField&&(i[inputName].map=formInput.dataset.mapFormField),formInput.nodeName){case"INPUT":if(l=this.getInputValue(formInput),l===!1)continue;break;case"TEXTAREA":l=formInput.value;break;case"SELECT":if(formInput.multiple){values=[],multiple=!0;for(var s=0;s<formInput.length;s++)formInput[s].selected&&values.push(encodeURIComponent(formInput[s].value))}else l=formInput.value}if(e.deBugger("forms","Input Value = "+l),l){i[inputName].value||(i[inputName].value=[]),i[inputName].value.push(multiple?values.join(","):encodeURIComponent(l));var l=multiple?values.join(","):encodeURIComponent(l)}}e.deBugger("forms",i);for(var u in i){var d=i[u].value,c=i[u].map;if("undefined"!=typeof d&&null!=d&&""!=d&&a.push(u+"="+i[u].value.join(",")),"undefined"!=typeof c&&null!=c&&i[u].value&&(r.push(c+"="+i[u].value.join(",")),"email"===u))var m=i[u].value.join(",")}var f=a.join("&");e.deBugger("forms","Stringified Raw Form PARAMS: "+f);var g=r.join("&");e.deBugger("forms","Stringified Mapped PARAMS"+g);var m=n.getParameterVal("email",g)||n.readCookie("wp_lead_email");m||(m=n.getParameterVal("wpleads_email_address",g));var p=n.getParameterVal("name",g),v=n.getParameterVal("first_name",g),h=n.getParameterVal("last_name",g);if(!h&&v){var _=decodeURI(v).split(" ");_.length>0&&(v=_[0],h=_[1])}if(p&&!h&&!v){var _=decodeURI(p).split(" ");_.length>0&&(v=_[0],h=_[1])}p=v&&h?v+" "+h:p,v||(v=""),h||(h=""),e.deBugger("forms","fName = "+v),e.deBugger("forms","lName = "+h),e.deBugger("forms","fullName = "+p);var b=e.totalStorage("page_views")||{},y=e.totalStorage("inbound_url_params")||{},w=t.querySelectorAll('input[value][type="hidden"][name="inbound_furl"]:not([value=""])'),k=!1;if(0==w.length||"IA=="==w[0].value)var k=!0;var C=t.querySelectorAll('input[value][type="hidden"][name="inbound_form_id"]');C=C.length>0?C[0].value:0;if("undefined"!=typeof landing_path_info)var S=landing_path_info.variation;else if("undefined"!=typeof cta_path_info)var S=cta_path_info.variation;else var S=inbound_settings.variation_id;var I=inbound_settings.post_type||"page",L=inbound_settings.post_id||0;search_data={},formData={action:"inbound_lead_store",email:m,full_name:p,first_name:v,last_name:h,raw_params:f,mapped_params:g,url_params:JSON.stringify(y),search_data:"test",page_views:JSON.stringify(b),post_type:I,page_id:L,variation:S,source:n.readCookie("inbound_referral_site"),inbound_submitted:k,inbound_form_id:C},callback=function(i){e.deBugger("forms","Lead Created with ID: "+i),i=parseInt(i,10),formData.leadID=i,i&&(n.createCookie("wp_lead_id",i),e.totalStorage.deleteItem("page_views"),e.totalStorage.deleteItem("tracking_events")),e.trigger("form_after_submission",formData),e.Forms.releaseFormSubmit(t)},e.trigger("form_before_submission",formData),n.ajaxPost(inbound_settings.admin_url,formData,callback)},rememberInputValues:function(t){var i=(t.name?"inbound_"+t.name:"",t.type?t.type:"text");return"submit"===i||"hidden"===i||"file"===i||"password"===i||t.dataset.ignoreFormField?!1:(n.addListener(t,"change",function(t){if(t.target.name){if("checkbox"!==i)var o=t.target.value;else for(var a=[],r=document.querySelectorAll('input[name="'+t.target.name+'"]'),s=0;s<r.length;s++){var l=r[s].checked;l&&a.push(r[s].value),o=a.join(",")}inputData={name:t.target.name,node:t.target.nodeName.toLowerCase(),type:i,value:o,mapping:t.target.dataset.mapFormField},e.trigger("form_input_change",inputData),n.createCookie("inbound_"+t.target.name,encodeURIComponent(o))}}),void 0)},fillInputValues:function(e){var t=e.name?"inbound_"+e.name:"",i=e.type?e.type:"text";if("submit"===i||"hidden"===i||"file"===i||"password"===i)return!1;if(n.readCookie(t)&&"comment"!=t)if(value=decodeURIComponent(n.readCookie(t)),"checkbox"===i||"radio"===i)for(var o=value.split(","),a=0;a<o.length;a++)e.value.indexOf(o[a])>-1&&(e.checked=!0);else"undefined"!==value&&(e.value=value)},getInputLabel:function(e){var t;return(t=this.siblingsIsLabel(e))?t:(t=this.CheckParentForLabel(e))?t:!1},getInputValue:function(e){var t=!1;switch(e.type){case"radio":case"checkbox":e.checked&&(t=e.value);break;case"text":case"hidden":default:t=e.value}return t},addDataAttr:function(e,t){for(var n=document.getElementsByName(e.name),i=n.length-1;i>=0;i--)e.dataset.mapFormField||(n[i].dataset.mapFormField=t)},removeArrayItem:function(e,t){if(e.indexOf)index=e.indexOf(t);else for(index=e.length-1;index>=0&&e[index]!==t;--index);index>=0&&e.splice(index,1)},siblingsIsLabel:function(e){for(var t=this.getSiblings(e),n=[],i=t.length-1;i>=0;i--)"label"===t[i].nodeName.toLowerCase()&&n.push(t[i]);return n.length>0&&n.length<2?n:!1},getChildren:function(e,t){for(var n=[];e;e=e.nextSibling)1==e.nodeType&&e!=t&&n.push(e);return n},getSiblings:function(e){return this.getChildren(e.parentNode.firstChild,e)},CheckParentForLabel:function(e){if("FORM"===e.nodeName)return null;do{var t=e.getElementsByTagName("label");if(t.length>0&&t.length<2)return e.getElementsByTagName("label")}while(e=e.parentNode);return null},mailCheck:function(){var e=document.querySelector(".inbound-email");e&&(n.addListener(e,"blur",this.mailCheck),u.run({email:document.querySelector(".inbound-email").value,suggested:function(t){var i=document.querySelector(".email_suggestion");i&&n.removeElement(i);var o=document.createElement("span");o.innerHTML="<span class=\"email_suggestion\">Did youu mean <b><i id='email_correction' style='cursor: pointer;' title=\"click to update\">"+t.full+"</b></i>?</span>",e.parentNode.insertBefore(o,e.nextSibling);var a=document.getElementById("email_correction");n.addListener(a,"click",function(){e.value=a.innerHTML,a.parentNode.parentNode.innerHTML="Fixed!"})},empty:function(){}}))}},"undefined"==typeof u)var u={domainThreshold:1,topLevelThreshold:3,defaultDomains:["yahoo.com","google.com","hotmail.com","gmail.com","me.com","aol.com","mac.com","live.com","comcast.net","googlemail.com","msn.com","hotmail.co.uk","yahoo.co.uk","facebook.com","verizon.net","sbcglobal.net","att.net","gmx.com","mail.com","outlook.com","icloud.com"],defaultTopLevelDomains:["co.jp","co.uk","com","net","org","info","edu","gov","mil","ca","de"],run:function(e){e.domains=e.domains||u.defaultDomains,e.topLevelDomains=e.topLevelDomains||u.defaultTopLevelDomains,e.distanceFunction=e.distanceFunction||u.sift3Distance;var t=function(e){return e},n=e.suggested||t,i=e.empty||t,o=u.suggest(u.encodeEmail(e.email),e.domains,e.topLevelDomains,e.distanceFunction);return o?n(o):i()},suggest:function(e,t,n,i){e=e.toLowerCase();var o=this.splitEmail(e),a=this.findClosestDomain(o.domain,t,i,this.domainThreshold);if(a){if(a!=o.domain)return{address:o.address,domain:a,full:o.address+"@"+a}}else{var r=this.findClosestDomain(o.topLevelDomain,n,i,this.topLevelThreshold);if(o.domain&&r&&r!=o.topLevelDomain){var s=o.domain;return a=s.substring(0,s.lastIndexOf(o.topLevelDomain))+r,{address:o.address,domain:a,full:o.address+"@"+a}}}return!1},findClosestDomain:function(e,t,n,i){i=i||this.topLevelThreshold;var o,a=99,r=null;if(!e||!t)return!1;n||(n=this.sift3Distance);for(var s=0;s<t.length;s++){if(e===t[s])return e;o=n(e,t[s]),a>o&&(a=o,r=t[s])}return i>=a&&null!==r?r:!1},sift3Distance:function(e,t){if(null===e||0===e.length)return null===t||0===t.length?0:t.length;if(null===t||0===t.length)return e.length;for(var n=0,i=0,o=0,a=0,r=5;n+i<e.length&&n+o<t.length;){if(e.charAt(n+i)==t.charAt(n+o))a++;else{i=0,o=0;for(var s=0;r>s;s++){if(n+s<e.length&&e.charAt(n+s)==t.charAt(n)){i=s;break}if(n+s<t.length&&e.charAt(n)==t.charAt(n+s)){o=s;break}}}n++}return(e.length+t.length)/2-a},splitEmail:function(e){var t=e.trim().split("@");if(t.length<2)return!1;for(var n=0;n<t.length;n++)if(""===t[n])return!1;var i=t.pop(),o=i.split("."),a="";if(0===o.length)return!1;if(1==o.length)a=o[0];else{for(var n=1;n<o.length;n++)a+=o[n]+".";o.length>=2&&(a=a.substring(0,a.length-1))}return{topLevelDomain:a,domain:i,address:t.join("@")}},encodeEmail:function(e){var t=encodeURI(e);return t=t.replace("%20"," ").replace("%25","%").replace("%5E","^").replace("%60","`").replace("%7B","{").replace("%7C","|").replace("%7D","}")}};return e}(_inbound||{}),_inboundEvents=function(e){function t(t,i,o){var i=i||{};o=o||{},o.bubbles=o.bubbles||!0,o.cancelable=o.cancelable||!0,i=e.apply_filters("filter_"+t,i);!window.ActiveXObject&&"ActiveXObject"in window;if("function"==typeof CustomEvent)var a=new CustomEvent(t,{detail:i,bubbles:o.bubbles,cancelable:o.cancelable});else{var a=document.createEvent("Event");a.initEvent(t,!0,!0)}window.dispatchEvent(a),e.do_action(t,i),n(t,i)}function n(e,t){if(window.jQuery){var t=t||{};jQuery(document).trigger(e,t)}}e.trigger=function(t,n){e.Events[t](n)};return e.Events={analytics_ready:function(){var e={opt1:!0},n={data:"xyxy"};t("analytics_ready",n,e)},url_parameters:function(e){t("url_parameters",e)},session_start:function(){console.log(""),t("session_start")},session_end:function(e){t("session_end",e),console.log("Session End")},session_active:function(){t("session_active")},session_idle:function(e){t("session_idle",e)},session_resume:function(){t("session_resume")},session_heartbeat:function(e){var n={clock:e,leadData:InboundLeadData};t("session_heartbeat",n)},page_visit:function(e){t("page_view",e)},page_first_visit:function(){t("page_first_visit"),e.deBugger("pages","First Ever Page View of this Page")},page_revisit:function(n){t("page_revisit",n);var i=function(){console.log("pageData",n),console.log("Page Revisit viewed "+n+" times")};e.deBugger("pages",status,i)},tab_hidden:function(){e.deBugger("pages","Tab Hidden"),t("tab_hidden")},tab_visible:function(){e.deBugger("pages","Tab Visible"),t("tab_visible")},tab_mouseout:function(){e.deBugger("pages","Tab Mouseout"),t("tab_mouseout")},form_input_change:function(n){var i=function(){console.log(n)};e.deBugger("forms","inputData change. Data=",i),t("form_input_change",n)},form_before_submission:function(e){t("form_before_submission",e)},form_after_submission:function(e){t("form_after_submission",e)},analyticsError:function(e,t,n){var i=new CustomEvent("inbound_analytics_error",{detail:{MLHttpRequest:e,textStatus:t,errorThrown:n}});window.dispatchEvent(i),console.log("Page Save Error")}},e}(_inbound||{});_inbound.add_action("form_before_submission",inboundFormNoRedirect,10),_inbound.add_action("form_after_submission",inboundFormNoRedirectContent,10);var InboundTotalStorage=function(e){var t,n,i="_inbound";if("localStorage"in window)try{n="undefined"==typeof window.localStorage?void 0:window.localStorage,t="undefined"==typeof n||"undefined"==typeof window.JSON?!1:!0,window.localStorage.setItem(i,"1"),window.localStorage.removeItem(i)}catch(o){t=!1}e.totalStorage=function(t,n){return e.totalStorage.impl.init(t,n)},e.totalStorage.setItem=function(t,n){return e.totalStorage.impl.setItem(t,n)},e.totalStorage.getItem=function(t){return e.totalStorage.impl.getItem(t)},e.totalStorage.getAll=function(){return e.totalStorage.impl.getAll()},e.totalStorage.deleteItem=function(t){return e.totalStorage.impl.deleteItem(t)},e.totalStorage.impl={init:function(e,t){return"undefined"!=typeof t?this.setItem(e,t):this.getItem(e)},setItem:function(i,o){if(!t)try{return e.Utils.createCookie(i,o),o}catch(a){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 r=JSON.stringify(o);return n.setItem(i,r),this.parseResult(r)},getItem:function(i){if(!t)try{return this.parseResult(e.Utils.readCookie(i))}catch(o){return null}var a=n.getItem(i);return this.parseResult(a)},deleteItem:function(i){if(!t)try{return e.Utils.eraseCookie(i,null),!0}catch(o){return!1}return n.removeItem(i),!0},getAll:function(){var i=[];if(t)for(var o in n)o.length&&i.push({key:o,value:this.parseResult(n.getItem(o))});else try{for(var a=document.cookie.split(";"),r=0;r<a.length;r++){var s=a[r].split("="),l=s[0];i.push({key:l,value:this.parseResult(e.Utils.readCookie(l))})}}catch(u){return null}return i},parseResult:function(e){var t;try{t=JSON.parse(e),"undefined"==typeof t&&(t=e),"true"==t&&(t=!0),"false"==t&&(t=!1),parseFloat(t)==t&&"object"!=typeof t&&(t=parseFloat(t))}catch(n){t=e}return t}}}(_inbound||{}),_inboundLeadsAPI=function(e){return e.LeadsAPI={init:function(){var t=e.Utils,n=(t.readCookie("wp_lead_uid"),t.readCookie("wp_lead_id")),i=t.readCookie("lead_session_expire");i||(e.deBugger("leads","expired vistor. Run Processes"),n&&e.LeadsAPI.getAllLeadData())},setGlobalLeadData:function(e){InboundLeadData=e},getAllLeadData:function(){var t=e.Utils.readCookie("wp_lead_id"),n=e.totalStorage("inbound_lead_data"),i=e.Utils.readCookie("lead_data_expire");
3
+ data={action:"inbound_get_all_lead_data",wp_lead_id:t},success=function(t){var n=JSON.parse(t);e.LeadsAPI.setGlobalLeadData(n),e.totalStorage("inbound_lead_data",n);var i=new Date;i.setTime(i.getTime()+18e5);var o=e.Utils.addDays(i,3);e.Utils.createCookie("lead_data_expire",!0,o)},n?(e.LeadsAPI.setGlobalLeadData(n),e.deBugger("lead","Set Global Lead Data from Localstorage"),i||(e.Utils.ajaxPost(inbound_settings.admin_url,data,success),e.deBugger("lead","localized data old. Pull new from DB"))):e.Utils.ajaxPost(inbound_settings.admin_url,data,success)},getLeadLists:function(){var t=e.Utils.readCookie("wp_lead_id"),n={action:"wpl_check_lists",wp_lead_id:t},i=function(){e.Utils.createCookie("lead_session_list_check",!0,{path:"/",expires:1}),e.deBugger("lead","Lists checked")};e.Utils.ajaxPost(inbound_settings.admin_url,n,i)}},e}(_inbound||{}),_inboundPageTracking=function(e){var t,n,i=!1,o=!1,a=!1,r=parseInt(e.Utils.readCookie("lead_session"),10)||0,s=0,l=(new Date,null),u=null,d=null,c=e.Utils,m=e.Utils.GetDate(),f="page_views",g=e.totalStorage(f)||{},p=inbound_settings.post_id||window.location.pathname,v=e.Settings.timeout||1e4;return e.PageTracking={init:function(i){return"page_views"!==f?!1:(this.CheckTimeOut(),i=i||{},t=parseInt(i.reportInterval,10)||10,n=parseInt(i.idleTimeout,10)||3,c.addListener(document,"keydown",c.throttle(e.PageTracking.pingSession,1e3)),c.addListener(document,"click",c.throttle(e.PageTracking.pingSession,1e3)),c.addListener(window,"mousemove",c.throttle(e.PageTracking.pingSession,1e3)),e.PageTracking.checkVisibility(),this.startSession(),void 0)},setIdle:function(t){var t=t||"No Movement",n="Session IDLE. Activity Timeout due to "+t;e.deBugger("pages",n),clearTimeout(e.PageTracking.idleTimer),e.PageTracking.stopClock(),e.trigger("session_idle")},checkVisibility:function(){var t,n,i;"undefined"!=typeof document.hidden?(t="hidden",i="visibilitychange",n="visibilityState"):"undefined"!=typeof document.mozHidden?(t="mozHidden",i="mozvisibilitychange",n="mozVisibilityState"):"undefined"!=typeof document.msHidden?(t="msHidden",i="msvisibilitychange",n="msVisibilityState"):"undefined"!=typeof document.webkitHidden&&(t="webkitHidden",i="webkitvisibilitychange",n="webkitVisibilityState");var o=document[t];e.Utils.addListener(document,i,function(){o!=document[t]&&(document[t]?(e.trigger("tab_hidden"),e.PageTracking.setIdle("browser tab switch")):(e.trigger("tab_visible"),e.PageTracking.pingSession()),o=document[t])})},clock:function(){r+=1;var n=r/60,i="Total time spent on Page in this Session: "+n.toFixed(2)+" min";if(e.deBugger("pages",i),r>0&&r%t===0){var o=new Date;o.setTime(o.getTime()+18e5),c.createCookie("lead_session",r,o),e.trigger("session_heartbeat",r)}},inactiveClock:function(){s+=1;var t=(1800-s)/60,n="Time until Session Timeout: "+t.toFixed(2)+" min";e.deBugger("pages",n),s>1800&&(e.trigger("session_end",InboundLeadData),e.Utils.eraseCookie("lead_session"),s=0,clearTimeout(u))},stopClock:function(){o=!0,clearTimeout(l),clearTimeout(u),u=setInterval(e.PageTracking.inactiveClock,1e3)},restartClock:function(){o=!1,e.trigger("session_resume"),e.deBugger("pages","Activity resumed. Session Active"),clearTimeout(l),s=0,clearTimeout(u),l=setInterval(e.PageTracking.clock,1e3)},turnOff:function(){e.PageTracking.setIdle(),a=!0},turnOn:function(){a=!1},startSession:function(){new Date;i=!0,l=setInterval(e.PageTracking.clock,1e3);var t=c.readCookie("lead_session");if(t)e.trigger("session_active");else{e.trigger("session_start");var n=new Date;n.setTime(n.getTime()+18e5),e.Utils.createCookie("lead_session",1,n)}this.pingSession()},resetInactiveFunc:function(){s=0,clearTimeout(u)},pingSession:function(t){a||(i||e.PageTracking.startSession(),o&&e.PageTracking.restartClock(),clearTimeout(d),d=setTimeout(e.PageTracking.setIdle,1e3*n+100),"undefined"!=typeof t&&"mousemove"===t.type&&e.PageTracking.mouseEvents(t))},mouseEvents:function(t){t.pageY<=5&&e.trigger("tab_mouseout")},getPageViews:function(){var t=e.Utils.checkLocalStorage();if(t){var n=localStorage.getItem(f),i=JSON.parse(n);return i}},isRevisit:function(e){var t=!1,e=e||{},n=e[p];return"undefined"!=typeof n&&null!==n&&(t=!0),t},triggerPageView:function(t){var n={title:document.title,url:document.location.href,path:document.location.pathname,count:1};t?(g[p].push(m),n.count=g[p].length,e.trigger("page_revisit",n)):(g[p]=[],g[p].push(m),e.trigger("page_first_visit",n)),e.trigger("page_visit",n),e.totalStorage(f,g),this.storePageView()},CheckTimeOut:function(){var t,n,i=this.isRevisit(g);if(i){var o=g[p].length-1,a=g[p][o],r=Math.abs(new Date(a).getTime()-new Date(m).getTime());n=r>v,n?(t="Timeout Happened. Page view fired",this.triggerPageView(i)):(time_left=.001*Math.abs(v-r),t=v/1e3+" sec timeout not done: "+time_left+" seconds left")}else this.triggerPageView(i);e.deBugger("pages",t)},storePageView:function(){if("off"!=inbound_settings.page_tracking){var t=e.Utils.readCookie("wp_lead_id")?e.Utils.readCookie("wp_lead_id"):"",n=e.Utils.readCookie("wp_lead_uid")?e.Utils.readCookie("wp_lead_uid"):"",i={action:"inbound_track_lead",wp_lead_uid:n,wp_lead_id:t,page_id:inbound_settings.post_id,variation_id:inbound_settings.variation_id,post_type:inbound_settings.post_type,current_url:window.location.href,page_views:JSON.stringify(e.PageTracking.getPageViews()),json:"0"},o=function(){};e.Utils.ajaxPost(inbound_settings.admin_url,i,o)}}},e}(_inbound||{});_inbound.init(),InboundLeadData=_inbound.totalStorage("inbound_lead_data")||null;
shared/assets/plugins/acf-field-date-time-picker/acf-date-time-picker.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Name: Advanced Custom Fields: Date and Time Picker
4
+ * Plugin URI: https://github.com/soderlind/acf-field-date-time-picker
5
+ * Description: Date and Time Picker field for Advanced Custom Fields
6
+ * Version: 2.1.1
7
+ * Author: Per Soderlind
8
+ * Author URI: http://soderlind.no
9
+ * License: GPLv2 or later
10
+ * License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
+ * Text Domain: acf-field-date-time-picker
12
+ * Domain Path: /languages
13
+ */
14
+ define( 'ACFFIELDDATETIMEPICKER_VERSION', '2.1.1' );
15
+ /**
16
+ * Class acfFieldDateTimePickerPlugin
17
+ */
18
+ if ( ! class_exists( 'ACFFieldDateTimePickerPlugin' ) ) :
19
+ class ACFFieldDateTimePickerPlugin {
20
+ /**
21
+ * Construct
22
+ *
23
+ * @description:
24
+ * @since: 3.6
25
+ * @created: 1/04/13
26
+ */
27
+ function __construct() {
28
+
29
+ load_plugin_textdomain( 'acf-field-date-time-picker', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
30
+ // version 4+
31
+ add_action( 'acf/register_fields', array( $this, 'register_fields' ) );
32
+ // version 3-
33
+ add_action( 'init', array( $this, 'init' ) );
34
+ }
35
+
36
+ /**
37
+ * Init
38
+ *
39
+ * @description:
40
+ * @since: 3.6
41
+ * @created: 1/04/13
42
+ */
43
+ function init() {
44
+ if ( function_exists( 'register_field' ) ) {
45
+ register_field( 'acf_field_date_time_picker', dirname( __File__ ) . '/date-time-picker-v3.php' );
46
+ }
47
+ }
48
+
49
+ /**
50
+ * register_fields
51
+ *
52
+ * @description:
53
+ * @since: 3.6
54
+ * @created: 1/04/13
55
+ */
56
+ function register_fields() {
57
+ require_once( 'date-time-picker-v4.php' );
58
+ }
59
+ }
60
+
61
+ new ACFFieldDateTimePickerPlugin();
62
+ endif;
shared/assets/plugins/acf-field-date-time-picker/date-time-picker-v3.php ADDED
@@ -0,0 +1,514 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ACFFieldDateTimePicker extends acf_Field {
4
+ // vars
5
+ var $settings // will hold info such as dir / path
6
+ , $defaults // will hold default field options
7
+ , $domain; // holds the language domain
8
+
9
+
10
+ /*--------------------------------------------------------------------------------------
11
+ *
12
+ * Constructor
13
+ * - This function is called when the field class is initalized on each page.
14
+ * - Here you can add filters / actions and setup any other functionality for your field
15
+ *
16
+ * @author Elliot Condon
17
+ * @since 2.2.0
18
+ *
19
+ *-------------------------------------------------------------------------------------*/
20
+
21
+ function __construct( $parent ) {
22
+ // do not delete!
23
+ parent::__construct( $parent );
24
+
25
+ // set name / title
26
+ $this->name = 'date_time_picker';
27
+ $this->title = __( 'Date and Time Picker' );
28
+ $this->domain = 'acf-field-date-time-picker';
29
+ $this->defaults = array(
30
+ 'label' => __( 'Choose Time', $this->domain ),
31
+ 'time_format' => 'hh:mm',
32
+ 'show_date' => 'true',
33
+ 'date_format' => 'yy-mm-dd',
34
+ 'show_week_number' => 'false',
35
+ 'picker' => 'slider',
36
+ 'save_as_timestamp' => 'true',
37
+ 'get_as_timestamp' => 'false',
38
+ );
39
+
40
+ $this->settings = array(
41
+ 'path' => $this->helpers_get_path( __FILE__ ),
42
+ 'dir' => $this->helpers_get_dir( __FILE__ ),
43
+ 'version' => ACFFIELDDATETIMEPICKER_VERSION,
44
+ );
45
+ }
46
+
47
+ /*
48
+ * helpers_get_path
49
+ *
50
+ * @description: calculates the path (works for plugin / theme folders)
51
+ * @since: 3.6
52
+ * @created: 30/01/13
53
+ */
54
+
55
+ function helpers_get_path( $file ) {
56
+
57
+ return trailingslashit( dirname( $file ) );
58
+ }
59
+
60
+ /*
61
+ * helpers_get_dir
62
+ *
63
+ * @description: calculates the directory (works for plugin / theme folders)
64
+ * @since: 3.6
65
+ * @created: 30/01/13
66
+ */
67
+
68
+ function helpers_get_dir( $file ) {
69
+
70
+ $dir = trailingslashit( dirname( $file ) );
71
+ $count = 0;
72
+
73
+ // sanitize for Win32 installs
74
+ $dir = str_replace( '\\', '/', $dir );
75
+
76
+ // if file is in plugins folder
77
+ $wp_plugin_dir = str_replace( '\\', '/', WP_PLUGIN_DIR );
78
+ $dir = str_replace( $wp_plugin_dir, WP_PLUGIN_URL, $dir, $count );
79
+
80
+ if ( $count < 1 ) {
81
+ // if file is in wp-content folder
82
+ $wp_content_dir = str_replace( '\\', '/', WP_CONTENT_DIR );
83
+ $dir = str_replace( $wp_content_dir, WP_CONTENT_URL, $dir, $count );
84
+ }
85
+
86
+ if ( $count < 1 ) {
87
+ // if file is in ??? folder
88
+ $wp_dir = str_replace( '\\', '/', ABSPATH );
89
+ $dir = str_replace( $wp_dir, site_url( '/' ), $dir );
90
+ }
91
+
92
+ return $dir;
93
+ }
94
+
95
+ /*--------------------------------------------------------------------------------------
96
+ *
97
+ * create_options
98
+ * - this function is called from core/field_meta_box.php to create extra options
99
+ * for your field
100
+ *
101
+ * @params
102
+ * - $key (int) - the $_POST obejct key required to save the options to the field
103
+ * - $field (array) - the field object
104
+ *
105
+ * @author Elliot Condon
106
+ * @since 2.2.0
107
+ *
108
+ *-------------------------------------------------------------------------------------*/
109
+
110
+ function create_options( $key, $field ) {
111
+
112
+ $field = array_merge( $this->defaults, $field );
113
+ ?>
114
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_choice">
115
+ <td class="label">
116
+ <label for=""><?php _e( 'Date and Time Picker?', $this->domain ); ?></label>
117
+ </td>
118
+ <td>
119
+ <?php
120
+ $this->parent->create_field(array(
121
+ 'type' => 'radio',
122
+ 'name' => 'fields[' . $key . '][show_date]',
123
+ 'value' => $field['show_date'],
124
+ 'layout' => 'horizontal',
125
+ 'choices' => array(
126
+ 'true' => __( 'Date and Time Picker', $this->domain ),
127
+ 'false' => __( 'Time Picker', $this->domain ),
128
+ ),
129
+ ));
130
+ ?>
131
+ </td>
132
+ </tr>
133
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_dateformat">
134
+ <td class="label">
135
+ <label><?php _e( 'Date Format', $this->domain ); ?></label>
136
+ <p class="description"><?php _e( 'eg. mm/dd/yy. read more about', $this->domain ); ?> <a href="http://docs.jquery.com/UI/Datepicker/formatDate">formatDate</a></p>
137
+ </td>
138
+ <td>
139
+ <?php
140
+ $this->parent->create_field(array(
141
+ 'type' => 'text',
142
+ 'name' => 'fields[' . $key . '][date_format]',
143
+ 'value' => $field['date_format'],
144
+ ));
145
+ ?>
146
+ </td>
147
+ </tr>
148
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_timeformat">
149
+ <td class="label">
150
+ <label><?php _e( 'Time Format', $this->domain ); ?></label>
151
+ <p class="description"><?php printf( __( 'eg. hh:mm. read more about <a href="%s" target="_blank">formatting time</a>', $this->domain ), 'http://trentrichardson.com/examples/timepicker/#tp-formatting' ); ?></p>
152
+ </td>
153
+ <td>
154
+ <?php
155
+ $this->parent->create_field(array(
156
+ 'type' => 'text',
157
+ 'name' => 'fields[' . $key . '][time_format]',
158
+ 'value' => $field['time_format'],
159
+ ));
160
+ ?>
161
+ </td>
162
+ </tr>
163
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_week_number">
164
+ <td class="label">
165
+ <label for=""><?php _e( 'Display Week Number?', $this->domain ); ?></label>
166
+ </td>
167
+ <td>
168
+ <?php
169
+ $this->parent->create_field(array(
170
+ 'type' => 'radio',
171
+ 'name' => 'fields[' . $key . '][show_week_number]',
172
+ 'value' => $field['show_week_number'],
173
+ 'layout' => 'horizontal',
174
+ 'choices' => array(
175
+ 'true' => __( 'Yes', $this->domain ),
176
+ 'false' => __( 'No', $this->domain ),
177
+ ),
178
+ ));
179
+ ?>
180
+ </td>
181
+ </tr>
182
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_week_number">
183
+ <td class="label">
184
+ <label for=""><?php _e( 'Time Picker Style?', $this->domain ); ?></label>
185
+ </td>
186
+ <td>
187
+ <?php
188
+ $this->parent->create_field(array(
189
+ 'type' => 'radio',
190
+ 'name' => 'fields[' . $key . '][picker]',
191
+ 'value' => $field['picker'],
192
+ 'layout' => 'horizontal',
193
+ 'choices' => array(
194
+ 'slider' => __( 'Slider', $this->domain ),
195
+ 'select' => __( 'Dropdown', $this->domain ),
196
+ ),
197
+ ));
198
+ ?>
199
+ </td>
200
+ </tr>
201
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_week_number">
202
+ <td class="label">
203
+ <label for=""><?php _e( 'Save as timestamp?', $this->domain ); ?></label>
204
+ <p class="description"><?php printf( __( 'Most users should leave this untouched, only set it to "No" if you need a date and time format not supported by <a href="%s" target="_blank">strtotime</a>', $this->domain ), 'http://php.net/manual/en/function.strtotime.php' ); ?></p>
205
+ </td>
206
+ <td>
207
+ <?php
208
+ $this->parent->create_field(array(
209
+ 'type' => 'radio',
210
+ 'name' => 'fields[' . $key . '][save_as_timestamp]',
211
+ 'value' => $field['save_as_timestamp'],
212
+ 'layout' => 'horizontal',
213
+ 'choices' => array(
214
+ 'true' => __( 'Yes', $this->domain ),
215
+ 'false' => __( 'No', $this->domain ),
216
+ ),
217
+ ));
218
+ ?>
219
+ </td>
220
+ </tr>
221
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_week_number">
222
+ <td class="label">
223
+ <label for=""><?php _e( 'Get field as a timestamp?', $this->domain ); ?></label>
224
+ <p class="description"><?php printf(__( 'Most users should leave this untouched, only set it to "Yes" if you need get the date and time field as a timestamp using <a href="%s" target="_blank">the_field()</a> or <a href="%s" target="_blank">get_field()</a> ', $this->domain ), 'http://www.advancedcustomfields.com/resources/functions/the_field/',
225
+ 'http://www.advancedcustomfields.com/resources/functions/get_field/'); ?></p>
226
+ </td>
227
+ <td>
228
+ <?php
229
+ $this->parent->create_field(array(
230
+ 'type' => 'radio',
231
+ 'name' => 'fields[' . $key . '][get_as_timestamp]',
232
+ 'value' => $field['get_as_timestamp'],
233
+ 'layout' => 'horizontal',
234
+ 'choices' => array(
235
+ 'true' => __( 'Yes', $this->domain ),
236
+ 'false' => __( 'No', $this->domain ),
237
+ ),
238
+ ));
239
+ ?>
240
+ </td>
241
+ </tr>
242
+ <?php
243
+
244
+ }
245
+
246
+ /*--------------------------------------------------------------------------------------
247
+ *
248
+ * create_field
249
+ * - this function is called on edit screens to produce the html for this field
250
+ *
251
+ * @author Elliot Condon
252
+ * @since 2.2.0
253
+ *
254
+ *-------------------------------------------------------------------------------------*/
255
+
256
+ function create_field( $field ) {
257
+
258
+ $field = array_merge( $this->defaults, $field );
259
+
260
+ if ( true != $field['show_date'] ) {
261
+ echo '<input type="text" value="' . $field['value'] . '" name="' . $field['name'] . '" class="ps_timepicker" value="" data-picker="' . $field['picker'] . '" data-time_format="' . $field['time_format'] . '" title="' . $field['label'] . '" />';
262
+ } else {
263
+ echo '<input type="text" value="' . $field['value'] . '" name="' . $field['name'] . '" class="ps_timepicker" value="" data-picker="' . $field['picker'] . '" data-date_format="' . $field['date_format'] . '" data-time_format="' . $field['time_format'] . '" data-show_week_number="' . $field['show_week_number'] . '" title="' . $field['label'] . '" />';
264
+ }
265
+ }
266
+
267
+ /*--------------------------------------------------------------------------------------
268
+ *
269
+ * update_value
270
+ * - this function is called when saving a post object that your field is assigned to.
271
+ * the function will pass through the 3 parameters for you to use.
272
+ *
273
+ * @params
274
+ * - $post_id (int) - usefull if you need to save extra data or manipulate the current
275
+ * post object
276
+ * - $field (array) - usefull if you need to manipulate the $value based on a field option
277
+ * - $value (mixed) - the new value of your field.
278
+ *
279
+ * @author Elliot Condon
280
+ * @since 2.2.0
281
+ *
282
+ *-------------------------------------------------------------------------------------*/
283
+
284
+ function update_value( $post_id, $field, $value ) {
285
+
286
+ $field = array_merge( $this->defaults, $field );
287
+ if ( '' != $value && 'true' == $field['save_as_timestamp'] ) {
288
+ if ( preg_match( '/^dd?\//', $field['date_format'] ) ) { //if start with dd/ or d/ (not supported by strtotime())
289
+ $value = str_replace( '/', '-', $value );
290
+ }
291
+ $value = strtotime( $value );
292
+ }
293
+
294
+ parent::update_value( $post_id, $field, $value );
295
+ }
296
+
297
+ /*--------------------------------------------------------------------------------------
298
+ *
299
+ * get_value
300
+ * - called from the edit page to get the value of your field. This function is useful
301
+ * if your field needs to collect extra data for your create_field() function.
302
+ *
303
+ * @params
304
+ * - $post_id (int) - the post ID which your value is attached to
305
+ * - $field (array) - the field object.
306
+ *
307
+ * @author Elliot Condon
308
+ * @since 2.2.0
309
+ *
310
+ *-------------------------------------------------------------------------------------*/
311
+
312
+ function get_value( $post_id, $field ) {
313
+
314
+ $field = array_merge( $this->defaults, $field );
315
+ $value = parent::get_value( $post_id, $field );
316
+
317
+ if ( '' != $value && 'true' == $field['save_as_timestamp'] && $this->isValidTimeStamp( $value ) ) {
318
+ if ( 'true' == $field['show_date'] ) {
319
+ $value = date( sprintf( '%s %s', $this->js_to_php_dateformat( $field['date_format'] ), $this->js_to_php_timeformat( $field['time_format'] ) ), $value );
320
+ } else {
321
+ $value = date( sprintf( '%s', $this->js_to_php_timeformat( $field['time_format'] ) ), $value );
322
+ }
323
+ }
324
+
325
+ return $value;
326
+ }
327
+
328
+ function get_value_for_api( $post_id, $field ) {
329
+
330
+ $field = array_merge( $this->defaults, $field );
331
+ $value = parent::get_value( $post_id, $field );
332
+
333
+ if ( '' != $value && 'true' == $field['save_as_timestamp'] && 'true' != $field['get_as_timestamp'] && $this->isValidTimeStamp( $value ) ) {
334
+ if ( 'true' == $field['show_date'] ) {
335
+ $value = date( sprintf( '%s %s', $this->js_to_php_dateformat( $field['date_format'] ), $this->js_to_php_timeformat( $field['time_format'] ) ), $value );
336
+ } else {
337
+ $value = date( sprintf( '%s', $this->js_to_php_timeformat( $field['time_format'] ) ), $value );
338
+ }
339
+ }
340
+
341
+ return $value;
342
+ }
343
+
344
+ function js_to_php_dateformat( $date_format ) {
345
+
346
+ $chars = array(
347
+ // Day
348
+ 'dd' => 'd',
349
+ 'd' => 'j',
350
+ 'DD' => 'l',
351
+ 'D' => 'D',
352
+ 'o' => 'z',
353
+ // Month
354
+ 'mm' => 'm',
355
+ 'm' => 'n',
356
+ 'MM' => 'F',
357
+ 'M' => 'M',
358
+ // Year
359
+ 'yy' => 'Y',
360
+ 'y' => 'y',
361
+ );
362
+
363
+ return strtr( (string) $date_format, $chars );
364
+ }
365
+
366
+ function js_to_php_timeformat( $time_format ) {
367
+
368
+ $chars = array(
369
+ //hour
370
+ 'HH' => 'H',
371
+ 'H' => 'G',
372
+ 'hh' => 'h',
373
+ 'h' => 'g',
374
+ //minute
375
+ 'mm' => 'i',
376
+ 'm' => 'i',
377
+ //second
378
+ 'ss' => 's',
379
+ 's' => 's',
380
+ //am/pm
381
+ 'TT' => 'A',
382
+ 'T' => 'A',
383
+ 'tt' => 'a',
384
+ 't' => 'a',
385
+ );
386
+
387
+ return strtr( (string) $time_format, $chars );
388
+ }
389
+
390
+ function isValidTimeStamp( $timestamp ) {
391
+
392
+ return ( (string) (int) $timestamp === (string) $timestamp );
393
+ }
394
+
395
+ /*--------------------------------------------------------------------------------------
396
+ *
397
+ * admin_print_scripts / admin_print_styles
398
+ * - this function is called in the admin_print_scripts / admin_print_styles where
399
+ * your field is created. Use this function to register css and javascript to assist
400
+ * your create_field() function.
401
+ *
402
+ * @author Elliot Condon
403
+ * @since 3.0.0
404
+ *
405
+ *-------------------------------------------------------------------------------------*/
406
+
407
+ function admin_print_scripts() {
408
+
409
+ global $wp_locale;
410
+
411
+ $has_locale = false;
412
+ $js_locale = $this->get_js_locale( get_locale() );
413
+ wp_enqueue_script('jquery-ui-timepicker', $this->settings['dir'] . 'js/jquery-ui-timepicker-addon.js', array(
414
+ 'acf-datepicker',
415
+ 'jquery-ui-slider',
416
+ ), $this->settings['version'], true);
417
+
418
+ if ( file_exists( dirname( __FILE__ ) . '/js/localization/jquery-ui-timepicker-' . $js_locale . '.js' ) ) {
419
+ wp_enqueue_script('timepicker-localization', $this->settings['dir'] . 'js/localization/jquery-ui-timepicker-' . $js_locale . '.js', array(
420
+ 'jquery-ui-timepicker'
421
+ ), $this->settings['version'], true);
422
+ wp_enqueue_script('timepicker', $this->settings['dir'] . 'js/timepicker.js', array(
423
+ 'timepicker-localization'
424
+ ), $this->settings['version'], true);
425
+ $has_locale = true;
426
+ } else {
427
+ wp_enqueue_script('timepicker', $this->settings['dir'] . 'js/timepicker.js', array(
428
+ 'jquery-ui-timepicker'
429
+ ), $this->settings['version'], true);
430
+ }
431
+
432
+ if ( ! $has_locale && 'en' != $js_locale ) {
433
+ $timepicker_locale = array(
434
+ 'closeText' => __( 'Done', $this->domain ),
435
+ 'currentText' => __( 'Today', $this->domain ),
436
+ 'prevText' => __( 'Prev', $this->domain ),
437
+ 'nextText' => __( 'Next', $this->domain ),
438
+ 'monthStatus' => __( 'Show a different month', $this->domain ),
439
+ 'weekHeader' => __( 'Wk', $this->domain ),
440
+ 'timeText' => __( 'Time', $this->domain ),
441
+ 'hourText' => __( 'Hour', $this->domain ),
442
+ 'minuteText' => __( 'Minute', $this->domain ),
443
+ 'secondText' => __( 'Second', $this->domain ),
444
+ 'millisecText' => __( 'Millisecond', $this->domain ),
445
+ 'timezoneText' => __( 'Time Zone', $this->domain ),
446
+ 'isRTL' => $wp_locale->is_rtl(),
447
+ );
448
+ }
449
+ $timepicker_wp_locale = array(
450
+ 'monthNames' => $this->strip_array_indices( $wp_locale->month ),
451
+ 'monthNamesShort' => $this->strip_array_indices( $wp_locale->month_abbrev ),
452
+ 'dayNames' => $this->strip_array_indices( $wp_locale->weekday ),
453
+ 'dayNamesShort' => $this->strip_array_indices( $wp_locale->weekday_abbrev ),
454
+ 'dayNamesMin' => $this->strip_array_indices( $wp_locale->weekday_initial ),
455
+ 'showMonthAfterYear' => false,
456
+ 'showWeek' => false,
457
+ 'firstDay' => get_option( 'start_of_week' ),
458
+ );
459
+
460
+ $l10n = (isset( $timepicker_locale )) ? array_merge( $timepicker_wp_locale, $timepicker_locale ) : $timepicker_wp_locale;
461
+ wp_localize_script( 'timepicker', 'timepicker_objectL10n', $l10n );
462
+
463
+ }
464
+
465
+ /**
466
+ * helper function, see: http://www.renegadetechconsulting.com/tutorials/jquery-datepicker-and-wordpress-i18n
467
+ * @param array $ArrayToStrip
468
+ * @return array
469
+ */
470
+ function strip_array_indices( $array_to_strip ) {
471
+
472
+ foreach ( $array_to_strip as $obj_array_item ) {
473
+ $new_array[] = $obj_array_item;
474
+ }
475
+
476
+ return $new_array;
477
+ }
478
+
479
+ function get_js_locale( $locale ) {
480
+
481
+ $dir_path = $this->settings['path'] . 'js/localization/';
482
+ $exclude_list = array( '.', '..' );
483
+ $languages = $this->ps_preg_filter( '/jquery-ui-timepicker-(.*?)\.js/', '$1', array_diff( scandir( $dir_path ), $exclude_list ) );
484
+
485
+ $locale = strtolower( str_replace( '_', '-', $locale ) );
486
+
487
+ if ( false !== strpos( $locale, '-' ) ) {
488
+ $l = explode( '-', $locale );
489
+ $pattern = array( '/' . $locale . '/', '/' . $l[0] . '/', '/' . $l[1] . '/' );
490
+ } else {
491
+ $pattern = array( '/' . $locale . '/' );
492
+ }
493
+ $res = $this->ps_preg_filter( $pattern, '$0', $languages, -1, $count );
494
+
495
+ return ($count) ? implode( '', $res ) : 'en';
496
+ }
497
+
498
+ function ps_preg_filter( $pattern, $replace, $subject, $limit = -1, &$count = 0 ) {
499
+
500
+ if ( function_exists( 'preg_filter' ) ) {
501
+ return preg_filter( $pattern, $replace, $subject, $limit, $count );
502
+ } else {
503
+ return array_diff( preg_replace( $pattern, $replace, $subject, $limit, $count ), $subject );
504
+ }
505
+ }
506
+
507
+ function admin_print_styles() {
508
+
509
+ wp_enqueue_style( 'jquery-style', $this->settings['dir'] . 'css/jquery-ui.css' );
510
+ wp_enqueue_style('timepicker', $this->settings['dir'] . 'css/jquery-ui-timepicker-addon.css', array(
511
+ 'jquery-style'
512
+ ), $this->settings['version']);
513
+ }
514
+ }
shared/assets/plugins/acf-field-date-time-picker/date-time-picker-v4.php ADDED
@@ -0,0 +1,472 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( 'ACFFieldDateTimePicker' ) ) :
4
+ class ACFFieldDateTimePicker extends acf_field
5
+ {
6
+ // vars
7
+ var $settings // will hold info such as dir / path
8
+ , $defaults // will hold default field options
9
+ , $domain // holds the language domain
10
+ , $lang;
11
+
12
+ /**
13
+ * __construct
14
+ *
15
+ * Set name / label needed for actions / filters
16
+ *
17
+ * @since 3.6
18
+ * @date 23/01/13
19
+ */
20
+ function __construct() {
21
+ // vars
22
+ $this->name = 'date_time_picker';
23
+ $this->label = __( 'Date and Time Picker' );
24
+ $this->category = __( 'jQuery', $this->domain ); // Basic, Content, Choice, etc
25
+ $this->domain = 'acf-field-date-time-picker';
26
+ $this->defaults = array(
27
+ 'label' => __( 'Choose Time', $this->domain ),
28
+ 'time_format' => 'h:mm tt',
29
+ 'show_date' => 'true',
30
+ 'date_format' => 'm/d/y',
31
+ 'show_week_number' => 'false',
32
+ 'picker' => 'slider',
33
+ 'save_as_timestamp' => 'true',
34
+ 'get_as_timestamp' => 'false',
35
+ );
36
+
37
+ // do not delete!
38
+ parent::__construct();
39
+
40
+ // settings
41
+ $this->settings = array(
42
+ 'path' => apply_filters( 'acf/helpers/get_path', __FILE__ ),
43
+ 'dir' => apply_filters( 'acf/helpers/get_dir', __FILE__ ),
44
+ 'version' => ACFFIELDDATETIMEPICKER_VERSION,
45
+ );
46
+ }
47
+
48
+ /**
49
+ * create_options()
50
+ *
51
+ * Create extra options for your field. This is rendered when editing a field.
52
+ * The value of $field['name'] can be used (like bellow) to save extra data to the $field
53
+ *
54
+ * @type action
55
+ * @since 3.6
56
+ * @date 23/01/13
57
+ *
58
+ * @param $field - an array holding all the field's data
59
+ */
60
+ function create_options( $field ) {
61
+
62
+ $field = array_merge( $this->defaults, $field );
63
+ $key = $field['name'];
64
+ ?>
65
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_choice">
66
+ <td class="label">
67
+ <label for=""><?php _e( 'Date and Time Picker?', $this->domain ); ?></label>
68
+ </td>
69
+ <td>
70
+ <?php
71
+ do_action('acf/create_field', array(
72
+ 'type' => 'radio',
73
+ 'name' => 'fields[' . $key . '][show_date]',
74
+ 'value' => $field['show_date'],
75
+ 'layout' => 'horizontal',
76
+ 'choices' => array(
77
+ 'true' => __( 'Date and Time Picker', $this->domain ),
78
+ 'false' => __( 'Time Picker', $this->domain ),
79
+ ),
80
+ ));
81
+ ?>
82
+ </td>
83
+ </tr>
84
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_dateformat">
85
+ <td class="label">
86
+ <label><?php _e( 'Date Format', $this->domain ); ?></label>
87
+ <p class="description"><?php printf( __( 'eg. mm/dd/yy. read more about <a href="%s" target="_blank">formatting date</a>', $this->domain ), 'http://docs.jquery.com/UI/Datepicker/formatDate' ); ?></p>
88
+ </td>
89
+ <td>
90
+ <?php
91
+ do_action('acf/create_field', array(
92
+ 'type' => 'text',
93
+ 'name' => 'fields[' . $key . '][date_format]',
94
+ 'value' => $field['date_format'],
95
+ ));
96
+ /*
97
+ do_action('acf/create_field', array(
98
+ 'type' => 'select',
99
+ 'name' => 'fields['.$key.'][date_format]',
100
+ 'value' => $field['date_format'],
101
+ 'choices' => array(
102
+ 'm/d/y' => 'm/d/y (5/27/13)'
103
+ , 'mm/dd/yy' => 'mm/dd/yy (05/27/2013)'
104
+ , 'yy/mm/dd' => 'yy/mm/dd (2013/05/27)'
105
+ , 'yy-mm-dd' => 'yy-mm-dd (2013-05-27)'
106
+ , 'dd.mm.yy' => 'dd.mm.yy (27.05.2013)'
107
+ , 'dd-mm-yy' => 'dd-mm-yy (27-05-2013)'
108
+ , 'yy-M-dd' => 'yy-M-dd (2013-May-27)'
109
+ )
110
+ ));
111
+ */
112
+ ?>
113
+ </td>
114
+ </tr>
115
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_timeformat">
116
+ <td class="label">
117
+ <label><?php _e( 'Time Format', $this->domain ); ?></label>
118
+ <p class="description"><?php printf( __( 'eg. hh:mm. read more about <a href="%s" target="_blank">formatting time</a>', $this->domain ), 'http://trentrichardson.com/examples/timepicker/#tp-formatting' ); ?></p>
119
+ </td>
120
+ <td>
121
+ <?php
122
+ do_action('acf/create_field', array(
123
+ 'type' => 'text',
124
+ 'name' => 'fields[' . $key . '][time_format]',
125
+ 'value' => $field['time_format'],
126
+ ));
127
+ /*
128
+ do_action('acf/create_field', array(
129
+ 'type' => 'select',
130
+ 'name' => 'fields['.$key.'][time_format]',
131
+ 'value' => $field['time_format'],
132
+ 'choices' => array(
133
+ 'h:mm tt' => 'h:mm tt (9:59 am)'
134
+ , 'hh:mm tt' => 'hh:mm tt (09:59 am)'
135
+ , 'H:mm' => 'H:mm (9:59)'
136
+ , 'HH:mm' => 'HH:mm (09:59)'
137
+ )
138
+ ));
139
+ */
140
+ ?>
141
+ </td>
142
+ </tr>
143
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_week_number">
144
+ <td class="label">
145
+ <label for=""><?php _e( 'Display Week Number?', $this->domain ); ?></label>
146
+ </td>
147
+ <td>
148
+ <?php
149
+ do_action('acf/create_field', array(
150
+ 'type' => 'radio',
151
+ 'name' => 'fields[' . $key . '][show_week_number]',
152
+ 'value' => $field['show_week_number'],
153
+ 'layout' => 'horizontal',
154
+ 'choices' => array(
155
+ 'true' => __( 'Yes', $this->domain ),
156
+ 'false' => __( 'No', $this->domain ),
157
+ ),
158
+ ));
159
+ ?>
160
+ </td>
161
+ </tr>
162
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_week_number">
163
+ <td class="label">
164
+ <label for=""><?php _e( 'Time Picker style?', $this->domain ); ?></label>
165
+ </td>
166
+ <td>
167
+ <?php
168
+ do_action('acf/create_field', array(
169
+ 'type' => 'radio',
170
+ 'name' => 'fields[' . $key . '][picker]',
171
+ 'value' => $field['picker'],
172
+ 'layout' => 'horizontal',
173
+ 'choices' => array(
174
+ 'slider' => __( 'Slider', $this->domain ),
175
+ 'select' => __( 'Dropdown', $this->domain ),
176
+ ),
177
+ ));
178
+ ?>
179
+ </td>
180
+ </tr>
181
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_week_number">
182
+ <td class="label">
183
+ <label for=""><?php _e( 'Save as timestamp?', $this->domain ); ?></label>
184
+ <p class="description"><?php printf( __( 'Most users should leave this untouched, only set it to "No" if you need a date and time format not supported by <a href="%s" target="_blank">strtotime</a>', $this->domain ), 'http://php.net/manual/en/function.strtotime.php' ); ?></p>
185
+ </td>
186
+ <td>
187
+ <?php
188
+ do_action('acf/create_field', array(
189
+ 'type' => 'radio',
190
+ 'name' => 'fields[' . $key . '][save_as_timestamp]',
191
+ 'value' => $field['save_as_timestamp'],
192
+ 'layout' => 'horizontal',
193
+ 'choices' => array(
194
+ 'true' => __( 'Yes', $this->domain ),
195
+ 'false' => __( 'No', $this->domain ),
196
+ ),
197
+ ));
198
+ ?>
199
+ </td>
200
+ </tr>
201
+ <tr class="field_option field_option_<?php echo $this->name; ?> timepicker_week_number">
202
+ <td class="label">
203
+ <label for=""><?php _e( 'Get field as timestamp?', $this->domain ); ?></label>
204
+ <p class="description"><?php printf(__( 'Most users should leave this untouched, only set it to "Yes" if you need get the date and time field as a timestamp using <a href="%s" target="_blank">the_field()</a> or <a href="%s" target="_blank">get_field()</a> ', $this->domain ), 'http://www.advancedcustomfields.com/resources/functions/the_field/',
205
+ 'http://www.advancedcustomfields.com/resources/functions/get_field/'); ?></p>
206
+ </td>
207
+ <td>
208
+ <?php
209
+ do_action('acf/create_field', array(
210
+ 'type' => 'radio',
211
+ 'name' => 'fields[' . $key . '][get_as_timestamp]',
212
+ 'value' => $field['get_as_timestamp'],
213
+ 'layout' => 'horizontal',
214
+ 'choices' => array(
215
+ 'true' => __( 'Yes', $this->domain ),
216
+ 'false' => __( 'No', $this->domain ),
217
+ ),
218
+ ));
219
+ ?>
220
+ </td>
221
+ </tr>
222
+ <?php
223
+ }
224
+
225
+ /**
226
+ * create_field()
227
+ *
228
+ * Create the HTML interface for your field
229
+ *
230
+ * @param $field - an array holding all the field's data
231
+ *
232
+ * @type action
233
+ * @since 3.6
234
+ * @date 23/01/13
235
+ */
236
+ function create_field( $field ) {
237
+
238
+ if ( 'true' !== $field['show_date'] ) {
239
+ echo '<input type="text" value="' . $field['value'] . '" name="' . $field['name'] . '" class="ps_timepicker" value="" data-picker="' . $field['picker'] . '" data-time_format="' . $field['time_format'] . '" title="' . $field['label'] . '" />';
240
+ } else {
241
+ echo '<input type="text" value="' . $field['value'] . '" name="' . $field['name'] . '" class="ps_timepicker" value="" data-picker="' . $field['picker'] . '" data-date_format="' . $field['date_format'] . '" data-time_format="' . $field['time_format'] . '" data-show_week_number="' . $field['show_week_number'] . '" title="' . $field['label'] . '" />';
242
+ }
243
+ }
244
+
245
+ //function load_field_defaults( $field ) { return $field; }
246
+
247
+ function format_value( $value, $post_id, $field ) {
248
+
249
+ $field = array_merge( $this->defaults, $field );
250
+ if ( '' != $value && 'true' == $field['save_as_timestamp'] && $this->isValidTimeStamp( $value ) ) {
251
+ if ( 'true' == $field['show_date'] ) {
252
+ $value = date_i18n( sprintf( '%s %s', $this->js_to_php_dateformat( $field['date_format'] ), $this->js_to_php_timeformat( $field['time_format'] ) ), $value );
253
+ } else {
254
+ $value = date_i18n( sprintf( '%s', $this->js_to_php_timeformat( $field['time_format'] ) ), $value );
255
+ }
256
+ }
257
+ return $value;
258
+ }
259
+
260
+ function format_value_for_api( $value, $post_id, $field ) {
261
+
262
+ $field = array_merge( $this->defaults, $field );
263
+ if ( '' != $value && 'true' == $field['save_as_timestamp'] && 'true' != $field['get_as_timestamp'] && $this->isValidTimeStamp( $value ) ) {
264
+ if ( 'true' == $field['show_date'] ) {
265
+ $value = date_i18n( sprintf( '%s %s', $this->js_to_php_dateformat( $field['date_format'] ), $this->js_to_php_timeformat( $field['time_format'] ) ), $value );
266
+ } else {
267
+ $value = date_i18n( sprintf( '%s', $this->js_to_php_timeformat( $field['time_format'] ) ), $value );
268
+ }
269
+ }
270
+ return $value;
271
+ }
272
+
273
+ function js_to_php_dateformat( $date_format ) {
274
+
275
+ $chars = array(
276
+ // Day
277
+ 'dd' => 'd',
278
+ 'd' => 'j',
279
+ 'DD' => 'l',
280
+ 'D' => 'D',
281
+ 'o' => 'z',
282
+ // Month
283
+ 'mm' => 'm',
284
+ 'm' => 'n',
285
+ 'MM' => 'F',
286
+ 'M' => 'M',
287
+ // Year
288
+ 'yy' => 'Y',
289
+ 'y' => 'y',
290
+ );
291
+
292
+ return strtr( (string) $date_format, $chars );
293
+ }
294
+
295
+ function js_to_php_timeformat( $time_format ) {
296
+
297
+ $chars = array(
298
+ //hour
299
+ 'HH' => 'H',
300
+ 'H' => 'G',
301
+ 'hh' => 'h',
302
+ 'h' => 'g',
303
+ //minute
304
+ 'mm' => 'i',
305
+ 'm' => 'i',
306
+ //second
307
+ 'ss' => 's',
308
+ 's' => 's',
309
+ //am/pm
310
+ 'TT' => 'A',
311
+ 'T' => 'A',
312
+ 'tt' => 'a',
313
+ 't' => 'a',
314
+ );
315
+
316
+ return strtr( (string) $time_format, $chars );
317
+ }
318
+
319
+ function isValidTimeStamp( $timestamp ) {
320
+
321
+ return ( (string) (int) $timestamp === (string) $timestamp );
322
+ }
323
+
324
+ /**
325
+ * update_value()
326
+ *
327
+ * This filter is appied to the $value before it is updated in the db
328
+ *
329
+ * @type filter
330
+ * @since 3.6
331
+ * @date 23/01/13
332
+ *
333
+ * @param $value - the value which will be saved in the database
334
+ * @param $post_id - the $post_id of which the value will be saved
335
+ * @param $field - the field array holding all the field options
336
+ *
337
+ * @return $value - the modified value
338
+ */
339
+ function update_value( $value, $post_id, $field ) {
340
+
341
+ $field = array_merge( $this->defaults, $field );
342
+ if ( '' != $value && 'true' == $field['save_as_timestamp'] ) {
343
+ if ( preg_match( '/^dd?\//', $field['date_format'] ) ) { //if start with dd/ or d/ (not supported by strtotime())
344
+ $value = str_replace( '/', '-', $value );
345
+ }
346
+ $value = strtotime( $value );
347
+ }
348
+
349
+ return $value;
350
+ }
351
+
352
+ /**
353
+ * input_admin_enqueue_scripts()
354
+ *
355
+ * This action is called in the admin_enqueue_scripts action on the edit screen where your field is created.
356
+ * Use this action to add css + javascript to assist your create_field() action.
357
+ *
358
+ * $info http://codex.wordpress.org/Plugin_API/Action_Reference/admin_enqueue_scripts
359
+ * @type action
360
+ * @since 3.6
361
+ * @date 23/01/13
362
+ */
363
+ function input_admin_enqueue_scripts() {
364
+ global $wp_locale;
365
+
366
+ $has_locale = false;
367
+ $js_locale = $this->get_js_locale( get_locale() );
368
+
369
+ wp_enqueue_script('jquery-ui-timepicker', $this->settings['dir'] . 'js/jquery-ui-timepicker-addon.js', array(
370
+ 'acf-input',
371
+ 'jquery-ui-slider',
372
+ ), $this->settings['version'], true);
373
+
374
+ if ( file_exists( $this->settings['path'] . '/js/localization/jquery-ui-timepicker-' . $js_locale . '.js' ) ) {
375
+ wp_enqueue_script('timepicker-localization', $this->settings['dir'] . 'js/localization/jquery-ui-timepicker-' . $js_locale . '.js', array(
376
+ 'jquery-ui-timepicker'
377
+ ), $this->settings['version'], true);
378
+ wp_enqueue_script('timepicker', $this->settings['dir'] . 'js/timepicker.js', array(
379
+ 'timepicker-localization'
380
+ ), $this->settings['version'], true);
381
+ $has_locale = true;
382
+ } else {
383
+ wp_enqueue_script('timepicker', $this->settings['dir'] . 'js/timepicker.js', array(
384
+ 'jquery-ui-timepicker'
385
+ ), $this->settings['version'], true);
386
+ }
387
+
388
+ if ( ! $has_locale && 'en' != $js_locale ) {
389
+ $timepicker_locale = array(
390
+ 'closeText' => __( 'Done', $this->domain ),
391
+ 'currentText' => __( 'Today', $this->domain ),
392
+ 'prevText' => __( 'Prev', $this->domain ),
393
+ 'nextText' => __( 'Next', $this->domain ),
394
+ 'monthStatus' => __( 'Show a different month', $this->domain ),
395
+ 'weekHeader' => __( 'Wk', $this->domain ),
396
+ 'timeText' => __( 'Time', $this->domain ),
397
+ 'hourText' => __( 'Hour', $this->domain ),
398
+ 'minuteText' => __( 'Minute', $this->domain ),
399
+ 'secondText' => __( 'Second', $this->domain ),
400
+ 'millisecText' => __( 'Millisecond', $this->domain ),
401
+ 'timezoneText' => __( 'Time Zone', $this->domain ),
402
+ 'isRTL' => $wp_locale->is_rtl(),
403
+ );
404
+ }
405
+ $timepicker_wp_locale = array(
406
+ 'monthNames' => $this->strip_array_indices( $wp_locale->month ),
407
+ 'monthNamesShort' => $this->strip_array_indices( $wp_locale->month_abbrev ),
408
+ 'dayNames' => $this->strip_array_indices( $wp_locale->weekday ),
409
+ 'dayNamesShort' => $this->strip_array_indices( $wp_locale->weekday_abbrev ),
410
+ 'dayNamesMin' => $this->strip_array_indices( $wp_locale->weekday_initial ),
411
+ 'showMonthAfterYear' => false,
412
+ 'showWeek' => false,
413
+ 'firstDay' => get_option( 'start_of_week' ),
414
+ );
415
+
416
+ $l10n = (isset( $timepicker_locale )) ? array_merge( $timepicker_wp_locale, $timepicker_locale ) : $timepicker_wp_locale;
417
+ wp_localize_script( 'timepicker', 'timepicker_objectL10n', $l10n );
418
+
419
+ wp_enqueue_style('jquery-style', $this->settings['dir'] . 'css/jquery-ui.css', array(
420
+ 'acf-datepicker'
421
+ ), $this->settings['version']);
422
+ wp_enqueue_style('timepicker', $this->settings['dir'] . 'css/jquery-ui-timepicker-addon.css', array(
423
+ 'jquery-style'
424
+ ), $this->settings['version']);
425
+ }
426
+
427
+ /**
428
+ * helper function, see: http://www.renegadetechconsulting.com/tutorials/jquery-datepicker-and-wordpress-i18n
429
+ * @param array $ArrayToStrip
430
+ * @return array
431
+ */
432
+ function strip_array_indices( $array_to_strip ) {
433
+
434
+ foreach ( $array_to_strip as $obj_array_item ) {
435
+ $new_array[] = $obj_array_item;
436
+ }
437
+
438
+ return $new_array;
439
+ }
440
+
441
+ function get_js_locale( $locale ) {
442
+
443
+ $dir_path = $this->settings['path'] . 'js/localization/';
444
+ $exclude_list = array( '.', '..' );
445
+ $languages = $this->ps_preg_filter( '/jquery-ui-timepicker-(.*?)\.js/', '$1', array_diff( scandir( $dir_path ), $exclude_list ) );
446
+
447
+ $locale = strtolower( str_replace( '_', '-', $locale ) );
448
+
449
+ if ( false !== strpos( $locale, '-' ) ) {
450
+ $l = explode( '-', $locale );
451
+ $pattern = array( '/' . $locale . '/', '/' . $l[0] . '/', '/' . $l[1] . '/' );
452
+ } else {
453
+ $pattern = array( '/' . $locale . '/' );
454
+ }
455
+ $res = $this->ps_preg_filter( $pattern, '$0', $languages, -1, $count );
456
+
457
+ return ($count) ? implode( '', $res ) : 'en';
458
+ }
459
+
460
+ function ps_preg_filter( $pattern, $replace, $subject, $limit = -1, &$count = 0 ) {
461
+
462
+ if ( function_exists( 'preg_filter' ) ) {
463
+ return preg_filter( $pattern, $replace, $subject, $limit, $count );
464
+ } else {
465
+ return array_diff( preg_replace( $pattern, $replace, $subject, $limit, $count ), $subject );
466
+ }
467
+ }
468
+ }
469
+
470
+ // create field
471
+ new ACFFieldDateTimePicker();
472
+ endif;
shared/assets/plugins/acf-field-date-time-picker/js/timepicker.js CHANGED
@@ -1,153 +1,136 @@
1
  /**
2
  * Date and Time Picker
3
  */
4
- (function($){
5
 
6
- function initialize_field( $el ) {
7
-
8
- //$el.doStuff();
9
-
10
- }
11
-
12
-
13
- if( typeof acf.add_action !== 'undefined' ) {
14
-
15
- /*
16
- * ready append (ACF5)
17
- *
18
- * These are 2 events which are fired during the page load
19
- * ready = on page load similar to $(document).ready()
20
- * append = on new DOM elements appended via repeater field
21
- *
22
- * @type event
23
- * @date 20/07/13
24
- *
25
- * @param $el (jQuery selection) the jQuery element which contains the ACF fields
26
- * @return n/a
27
- */
28
-
29
- acf.add_action('ready append', function( $el ){
30
-
31
- $el.find('input.ps_timepicker').each(function(){
32
- var input = $(this)
33
- , is_timeonly = (input.attr('data-date_format') == undefined)
34
- , date_format = (input.attr('data-date_format') != undefined) ? input.attr('data-date_format') : 'mm/dd/yy'
35
- , time_format = input.attr('data-time_format')
36
- , has_ampm = (input.attr('data-time_format').search(/t/i) != -1);
37
-
38
- //don't apply datepicker to clone field
39
- if (input.parents('.acf-row.clone').length) {
40
- return;
41
- }
42
-
43
-
44
- input.addClass('active').attr("placeholder", (is_timeonly) ? time_format : date_format + ' ' + time_format).datetimepicker({
45
- changeYear: true
46
- , yearRange: "-100:+100"
47
- , changeMonth: true
48
- , timeOnly: is_timeonly
49
- , timeFormat: time_format
50
- , dateFormat: date_format
51
- , showWeek: (input.attr('data-show_week_number') != "true") ? 0 : 1
52
- , ampm: has_ampm
53
- , controlType: input.attr('data-picker')
54
- , timeOnlyTitle: input.attr('title')
55
- , monthNames: timepicker_objectL10n.monthNames
56
- , monthNamesShort: timepicker_objectL10n.monthNamesShort
57
- , dayNames: timepicker_objectL10n.dayNames
58
- , dayNamesShort: timepicker_objectL10n.dayNamesShort
59
- , dayNamesMin: timepicker_objectL10n.dayNamesMin
60
- , firstDay: timepicker_objectL10n.firstDay
61
- });
62
-
63
-
64
- if($('body > #ui-datepicker-div').length > 0)
65
- {
66
- $('#ui-datepicker-div').wrap('<div class="ui-acf" />');
67
- }
68
-
69
- // allow null
70
- input.blur(function(){
71
-
72
- if( !input.val() )
73
- {
74
- input.val('');
75
- }
76
- });
77
- });
78
-
79
-
80
-
81
- });
82
-
83
-
84
- } else {
85
-
86
-
87
- /*
88
- * acf/setup_fields (ACF4)
89
- *
90
- * This event is triggered when ACF adds any new elements to the DOM.
91
- *
92
- * @type function
93
- * @since 1.0.0
94
- * @date 01/01/12
95
- *
96
- * @param event e: an event object. This can be ignored
97
- * @param Element postbox: An element which contains the new HTML
98
- *
99
- * @return n/a
100
- */
101
-
102
- $(document).live('acf/setup_fields', function(e, postbox){
103
-
104
- $(postbox).find('input.ps_timepicker').each(function(){
105
- var input = $(this)
106
- , is_timeonly = (input.attr('data-date_format') == undefined)
107
- , date_format = (input.attr('data-date_format') != undefined) ? input.attr('data-date_format') : 'mm/dd/yy'
108
- , time_format = input.attr('data-time_format')
109
- , has_ampm = (input.attr('data-time_format').search(/t/i) != -1);
110
-
111
- if( acf.helpers.is_clone_field(input) )
112
- {
113
- return;
114
- }
115
-
116
-
117
- input.addClass('active').attr("placeholder", (is_timeonly) ? time_format : date_format + ' ' + time_format).datetimepicker({
118
- changeYear: true
119
- , yearRange: "-100:+100"
120
- , changeMonth: true
121
- , timeOnly: is_timeonly
122
- , timeFormat: time_format
123
- , dateFormat: date_format
124
- , showWeek: (input.attr('data-show_week_number') != "true") ? 0 : 1
125
- , ampm: has_ampm
126
- , controlType: input.attr('data-picker')
127
- , timeOnlyTitle: input.attr('title')
128
- , monthNames: timepicker_objectL10n.monthNames
129
- , monthNamesShort: timepicker_objectL10n.monthNamesShort
130
- , dayNames: timepicker_objectL10n.dayNames
131
- , dayNamesShort: timepicker_objectL10n.dayNamesShort
132
- , dayNamesMin: timepicker_objectL10n.dayNamesMin
133
- , firstDay: timepicker_objectL10n.firstDay
134
- });
135
-
136
-
137
- if($('body > #ui-datepicker-div').length > 0)
138
- {
139
- $('#ui-datepicker-div').wrap('<div class="ui-acf" />');
140
- }
141
-
142
- // allow null
143
- input.blur(function(){
144
-
145
- if( !input.val() )
146
- {
147
- input.val('');
148
- }
149
- });
150
- });
151
- });
152
- }
153
  })(jQuery);
1
  /**
2
  * Date and Time Picker
3
  */
 
4
 
5
+ acf = acf || {};
6
+
7
+ (function ($) {
8
+
9
+ function initialize_field($el) {
10
+ //$el.doStuff();
11
+ }
12
+
13
+ if (typeof acf.add_action !== 'undefined') {
14
+
15
+ /**
16
+ * ready append (ACF5)
17
+ *
18
+ * These are 2 events which are fired during the page load
19
+ * ready = on page load similar to $(document).ready()
20
+ * append = on new DOM elements appended via repeater field
21
+ *
22
+ * @type event
23
+ * @date 20/07/13
24
+ *
25
+ * @param $el (jQuery selection) the jQuery element which contains the ACF fields
26
+ * @return n/a
27
+ */
28
+ acf.add_action('ready append', function ($el) {
29
+
30
+ acf.get_fields({ type : 'date_time_picker'}, $el).each(function () {
31
+ // var input = $('input', $(this)),
32
+ var input = $(this).find('input'),
33
+ is_timeonly = (input.attr('data-date_format') == undefined),
34
+ date_format = (input.attr('data-date_format') != undefined) ? input.attr('data-date_format') : 'mm/dd/yy',
35
+ time_format = input.attr('data-time_format'),
36
+ has_ampm = (input.attr('data-date_format') != undefined) ? (input.attr('data-time_format').search(/t/i) != -1) : false;
37
+
38
+ //don't apply datepicker to clone field (check for different class names to enhance compatibility with older acf versions)
39
+ if (input.parents('.acf-row.acf-clone').length || input.parents('.acf-row.clone, .acf-clone').length) {
40
+ return;
41
+ }
42
+
43
+ input
44
+ .addClass('active')
45
+ .attr("placeholder", (is_timeonly) ? time_format : date_format + ' ' + time_format)
46
+ .datetimepicker({
47
+ changeYear: true,
48
+ yearRange: "-100:+100",
49
+ changeMonth: true,
50
+ timeOnly: is_timeonly,
51
+ timeFormat: time_format,
52
+ dateFormat: date_format,
53
+ showWeek: (input.attr('data-show_week_number') != "true") ? 0 : 1,
54
+ ampm: has_ampm,
55
+ controlType: input.attr('data-picker'),
56
+ timeOnlyTitle: input.attr('title'),
57
+ monthNames: timepicker_objectL10n.monthNames,
58
+ monthNamesShort: timepicker_objectL10n.monthNamesShort,
59
+ dayNames: timepicker_objectL10n.dayNames,
60
+ dayNamesShort: timepicker_objectL10n.dayNamesShort,
61
+ dayNamesMin: timepicker_objectL10n.dayNamesMin,
62
+ firstDay: timepicker_objectL10n.firstDay
63
+ });
64
+
65
+ if ($('body > #ui-datepicker-div').length > 0) {
66
+ $('#ui-datepicker-div').wrap('<div class="ui-acf" />');
67
+ }
68
+
69
+ // allow null
70
+ input.blur(function () {
71
+ if (!input.val()) {
72
+ input.val('');
73
+ }
74
+ });
75
+ });
76
+ });
77
+ } else {
78
+ /**
79
+ * acf/setup_fields (ACF4)
80
+ *
81
+ * This event is triggered when ACF adds any new elements to the DOM.
82
+ *
83
+ * @type function
84
+ * @since 1.0.0
85
+ * @date 01/01/12
86
+ *
87
+ * @param event e: an event object. This can be ignored
88
+ * @param Element postbox: An element which contains the new HTML
89
+ *
90
+ * @return n/a
91
+ */
92
+ $(document).live('acf/setup_fields', function (e, postbox) {
93
+ $(postbox).find('input.ps_timepicker').each(function () {
94
+ var input = $(this),
95
+ is_timeonly = (input.attr('data-date_format') == undefined),
96
+ date_format = (input.attr('data-date_format') != undefined) ? input.attr('data-date_format') : 'mm/dd/yy',
97
+ time_format = input.attr('data-time_format'),
98
+ has_ampm = (input.attr('data-time_format').search(/t/i) != -1);
99
+
100
+ if (acf.helpers.is_clone_field(input)) {
101
+ return;
102
+ }
103
+
104
+ input.addClass('active').attr("placeholder", (is_timeonly) ? time_format : date_format + ' ' + time_format).datetimepicker({
105
+ changeYear: true,
106
+ yearRange: "-100:+100",
107
+ changeMonth: true,
108
+ timeOnly: is_timeonly,
109
+ timeFormat: time_format,
110
+ dateFormat: date_format,
111
+ showWeek: (input.attr('data-show_week_number') != "true") ? 0 : 1,
112
+ ampm: has_ampm,
113
+ controlType: input.attr('data-picker'),
114
+ timeOnlyTitle: input.attr('title'),
115
+ monthNames: timepicker_objectL10n.monthNames,
116
+ monthNamesShort: timepicker_objectL10n.monthNamesShort,
117
+ dayNames: timepicker_objectL10n.dayNames,
118
+ dayNamesShort: timepicker_objectL10n.dayNamesShort,
119
+ dayNamesMin: timepicker_objectL10n.dayNamesMin,
120
+ firstDay: timepicker_objectL10n.firstDay
121
+ });
122
+
123
+ if ($('body > #ui-datepicker-div').length > 0) {
124
+ $('#ui-datepicker-div').wrap('<div class="ui-acf" />');
125
+ }
126
+
127
+ // allow null
128
+ input.blur(function () {
129
+ if (!input.val()) {
130
+ input.val('');
131
+ }
132
+ });
133
+ });
134
+ });
135
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  })(jQuery);
shared/classes/class.acf-bootstrap.php CHANGED
@@ -45,7 +45,7 @@ class Inbound_Shared_ACF_BootStrap {
45
  public static function load_acf_extended_fields() {
46
  if (!function_exists('register_fields_font_awesome')) {
47
  include_once( INBOUNDNOW_SHARED_PATH . 'assets/plugins/advanced-custom-fields-font-awesome/acf-font-awesome.php');
48
- include_once( INBOUNDNOW_SHARED_PATH . 'assets/plugins/acf-field-date-time-picker/acf-date_time_picker.php');
49
  }
50
  }
51
 
45
  public static function load_acf_extended_fields() {
46
  if (!function_exists('register_fields_font_awesome')) {
47
  include_once( INBOUNDNOW_SHARED_PATH . 'assets/plugins/advanced-custom-fields-font-awesome/acf-font-awesome.php');
48
+ include_once( INBOUNDNOW_SHARED_PATH . 'assets/plugins/acf-field-date-time-picker/acf-date-time-picker.php');
49
  }
50
  }
51
 
shared/classes/class.compatibility.php DELETED
@@ -1,134 +0,0 @@
1
- <?php
2
- /**
3
- * Compability Mode Deregisters All Third party scripts not in the whitelist
4
- * - The class was made to cut down on third party support requests
5
- *
6
- * Call the dequeue manually Inbound_Compatibility::inbound_compatibilities_mode();
7
- */
8
-
9
- /* From Global Settings if compat mode toggled on turn off third party scripts */
10
- add_action('admin_enqueue_scripts', 'inbound_turn_on_compatiblity', 110);
11
- if (!function_exists('inbound_turn_on_compatiblity')) {
12
- function inbound_turn_on_compatiblity() {
13
- $screen = get_current_screen();
14
-
15
- /* Add all Plugin Screens to Array */
16
- $inbound_screens = Inbound_Compatibility::return_inbound_now_screens(); /* grabs our plugin screen ids */
17
-
18
- /* If Not Inbound Now Screen Exit function */
19
- if (!in_array($screen->id, $inbound_screens)) {
20
- return;
21
- }
22
-
23
- $lead_compatiblity = get_option( 'wpl-main-inbound_compatibility_mode', $default = false );
24
- $cta_compatiblity = get_option( 'wp-cta-main-inbound_compatibility_mode', $default = false );
25
- $lp_compatiblity = get_option( 'lp-main-inbound_compatibility_mode', $default = false );
26
- if ( $lead_compatiblity || $cta_compatiblity || $lp_compatiblity ) {
27
- Inbound_Compatibility::inbound_compatibilities_mode(); /* kill third party scripts */
28
- }
29
- }
30
- }
31
-
32
- add_action('admin_notices', 'inbound_compability_admin_notice'); /* disable compat notice */
33
- if (!function_exists('inbound_compability_admin_notice')) {
34
- function inbound_compability_admin_notice(){
35
- $lead_compatiblity = get_option( 'wpl-main-inbound_compatibility_mode', $default = false );
36
- $cta_compatiblity = get_option( 'wp-cta-main-inbound_compatibility_mode', $default = false );
37
- $lp_compatiblity = get_option( 'lp-main-inbound_compatibility_mode', $default = false );
38
- if ($lead_compatiblity) {
39
- $link = admin_url( 'edit.php?post_type=wp-lead&page=wpleads_global_settings' );
40
- } elseif ($cta_compatiblity) {
41
- $link = admin_url( 'edit.php?post_type=wp-call-to-action&page=wp_cta_global_settings' );
42
- } elseif ($lp_compatiblity) {
43
- $link = admin_url( 'edit.php?post_type=landing-page&page=lp_global_settings' );
44
- }
45
-
46
- if ( $lead_compatiblity || $cta_compatiblity || $lp_compatiblity ) {
47
- echo '<div class="updated">
48
- <p>Inbound Now Compatibility Mode is currently activated. To turn off go to <a href="'.$link.'">global settings</a> and toggle off</p>
49
- </div>';
50
- }
51
- }
52
- }
53
-
54
- if (!class_exists('Inbound_Compatibility')) {
55
- class Inbound_Compatibility {
56
- static $add_inbound_compatibility;
57
-
58
- /**
59
- * Dequeue all third party scripts on page
60
- * @return [type] [description]
61
- */
62
- static function inbound_compatibilities_mode() {
63
-
64
- if (is_admin()){
65
- $screen = get_current_screen();
66
- } else {
67
- $screen = '';
68
- }
69
- global $wp_scripts;
70
-
71
- /* Match our plugins and whitelist them */
72
- $registered_scripts = $wp_scripts->registered;
73
- $inbound_white_list = array();
74
- foreach ($registered_scripts as $handle) {
75
- if(preg_match("/\/plugins\/leads\//", $handle->src)) {
76
- /*echo $handle->handle; */
77
- $inbound_white_list[] = $handle->handle;
78
- }
79
- if(preg_match("/\/plugins\/cta\//", $handle->src)) {
80
- /*echo $handle->handle; */
81
- $inbound_white_list[]= $handle->handle;
82
- }
83
- if(preg_match("/\/plugins\/landing-pages\//", $handle->src)) {
84
- /*echo $handle->handle; */
85
- $inbound_white_list[]= $handle->handle;
86
- }
87
- }
88
- /*print_r($inbound_white_list); */
89
-
90
- /* NEED Filter for ADDONs */
91
-
92
-
93
- $scripts_queued = $wp_scripts->queue; /* All Queued Scripts */ /*print_r($wp_scripts->queue); */
94
-
95
- /* Wordpress Core Scripts List */
96
- $wp_core_scripts = array("jcrop", "swfobject", "swfupload", "swfupload-degrade", "swfupload-queue", "swfupload-handlers", "jquery", "jquery-form", "jquery-color", "jquery-masonry", "jquery-ui-core", "jquery-ui-widget", "jquery-ui-mouse", "jquery-ui-accordion", "jquery-ui-autocomplete", "jquery-ui-slider", "jquery-ui-progressbar", "jquery-ui-tabs", "jquery-ui-sortable", "jquery-ui-draggable", "jquery-ui-droppable", "jquery-ui-selectable", "jquery-ui-position", "jquery-ui-datepicker", "jquery-ui-tooltip", "jquery-ui-resizable", "jquery-ui-dialog", "jquery-ui-button", "jquery-effects-core", "jquery-effects-blind", "jquery-effects-bounce", "jquery-effects-clip", "jquery-effects-drop", "jquery-effects-explode", "jquery-effects-fade", "jquery-effects-fold", "jquery-effects-highlight", "jquery-effects-pulsate", "jquery-effects-scale", "jquery-effects-shake", "jquery-effects-slide", "jquery-effects-transfer", "wp-mediaelement", "schedule", "suggest", "thickbox", "hoverIntent", "jquery-hotkeys", "sack", "quicktags", "iris", "farbtastic", "colorpicker", "tiny_mce", "autosave", "wp-ajax-response", "wp-lists", "common", "editorremov", "editor-functions", "ajaxcat", "admin-categories", "admin-tags", "admin-custom-fields", "password-strength-meter", "admin-comments", "admin-users", "admin-forms", "xfn", "upload", "postbox", "slug", "post", "page", "link", "comment", "comment-reply", "admin-gallery", "media-upload", "admin-widgets", "word-count", "theme-preview", "json2", "plupload", "plupload-all", "plupload-html4", "plupload-html5", "plupload-flash", "plupload-silverlight", "underscore", "backbone");
97
-
98
-
99
- foreach ($scripts_queued as $key => $value) {
100
- /*echo $key . $value; */
101
- if (!in_array($value, $inbound_white_list) && !in_array($value, $wp_core_scripts)){
102
- wp_dequeue_script( $value );
103
- /*echo $key . $value; */
104
- }
105
- }
106
- }
107
-
108
- static function return_inbound_now_screens(){
109
- $inbound_screens = array(
110
- 'wp-lead_page_wpleads_global_settings',
111
- 'wp-lead_page_lead_management',
112
- 'edit-list',
113
- 'edit-wp-lead',
114
- 'wp-lead',
115
- 'edit-wplead_list_category',
116
- 'edit-inbound-forms',
117
- 'inbound-forms',
118
- 'edit-landing-page',
119
- 'landing-page',
120
- 'edit-landing_page_category',
121
- 'landing-page_page_lp_manage_templates',
122
- 'landing-page_page_lp_global_settings',
123
- 'landing-page_page_lp_store',
124
- 'edit-wp-call-to-action',
125
- 'edit-wp_call_to_action_category',
126
- 'wp-call-to-action',
127
- 'wp-call-to-action_page_wp_cta_manage_templates',
128
- 'wp-call-to-action_page_wp_cta_global_settings',
129
- );
130
- /* add filter */
131
- return $inbound_screens;
132
- }
133
- }
134
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
shared/classes/class.events.php CHANGED
@@ -110,6 +110,7 @@ class Inbound_Events {
110
  `variation_id` mediumint(9) NOT NULL,
111
  `lead_id` mediumint(20) NOT NULL,
112
  `lead_uid` varchar(255) NOT NULL,
 
113
  `session_id` varchar(255) NOT NULL,
114
  `source` text NOT NULL,
115
  `datetime` datetime NOT NULL,
@@ -128,18 +129,31 @@ class Inbound_Events {
128
  */
129
  public static function store_form_submission( $lead ){
130
 
131
- if (! isset($lead['raw_params']) ) {
132
  return;
133
  }
134
 
135
  parse_str($lead['raw_params'] , $raw_params );
136
  $details = array_merge($raw_params,$lead);
 
 
 
 
 
 
 
 
 
 
 
 
137
  $args = array(
138
  'event_name' => 'inbound_form_submission',
139
  'page_id' => $lead['page_id'],
140
  'variation_id' => $lead['variation'],
141
  'form_id' => (isset($raw_params['inbound_form_id'])) ? $raw_params['inbound_form_id'] : '',
142
  'lead_id' => $lead['id'],
 
143
  'lead_uid' => ( isset($_COOKIE['wp_lead_uid']) ? $_COOKIE['wp_lead_uid'] : '' ),
144
  'event_details' => json_encode($details),
145
  'datetime' => $lead['wordpress_date_time']
@@ -379,7 +393,7 @@ class Inbound_Events {
379
 
380
  }
381
 
382
- public static function delete_related_events( $post_id ) {
383
  global $wpdb;
384
 
385
  $post = get_post($post_id);
@@ -397,6 +411,11 @@ class Inbound_Events {
397
  'lead_id' => $post_id
398
  );
399
  break;
 
 
 
 
 
400
  default:
401
  $where = array(
402
  'page_id' => $post_id
@@ -404,6 +423,10 @@ class Inbound_Events {
404
  break;
405
  }
406
 
 
 
 
 
407
  $wpdb->delete( $table_name, $where, $where_format = null );
408
 
409
  }
@@ -467,16 +490,30 @@ class Inbound_Events {
467
  global $wpdb;
468
 
469
  $table_name = $wpdb->prefix . "inbound_events";
 
470
 
471
  switch ($nature) {
472
  case 'lead_id':
473
- $query = 'SELECT * FROM '.$table_name.' WHERE datetime >= "'.$params['start_date'].'" AND datetime <= "'.$params['end_date'].'" AND `lead_id` = "'.$params['lead_id'].'" AND `event_name` = "inbound_form_submission" ORDER BY `datetime` DESC';
474
  break;
475
  case 'page_id':
476
- $query = 'SELECT * FROM '.$table_name.' WHERE datetime >= "'.$params['start_date'].'" AND datetime <= "'.$params['end_date'].'" AND `page_id` = "'.$params['page_id'].'" AND `event_name` = "inbound_form_submission" ORDER BY `datetime` DESC';
 
 
 
477
  break;
478
  }
479
 
 
 
 
 
 
 
 
 
 
 
480
 
481
  $results = $wpdb->get_results( $query , ARRAY_A );
482
 
@@ -489,9 +526,9 @@ class Inbound_Events {
489
  public static function get_page_views( $lead_id ){
490
  global $wpdb;
491
 
492
- $table_name = $wpdb->prefix . "inbound_events";
493
 
494
- $query = 'SELECT * FROM '.$table_name.' WHERE `lead_id` = "'.$lead_id.'" AND `event_name` = "inbound_page_view" ORDER BY `datetime` DESC';
495
  $results = $wpdb->get_results( $query , ARRAY_A );
496
 
497
  return $results;
@@ -520,6 +557,24 @@ class Inbound_Events {
520
  return $results;
521
  }
522
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  /**
524
  * Get all cta click events related to lead ID
525
  */
@@ -573,16 +628,31 @@ class Inbound_Events {
573
  global $wpdb;
574
 
575
  $table_name = $wpdb->prefix . "inbound_events";
 
576
 
577
  switch ($nature) {
578
  case 'lead_id':
579
- $query = 'SELECT * FROM '.$table_name.' WHERE datetime >= "'.$params['start_date'].'" AND datetime <= "'.$params['end_date'].'" AND `lead_id` = "'.$params['lead_id'].'" AND `event_name` = "inbound_cta_click" ORDER BY `datetime` DESC';
580
  break;
581
  case 'page_id':
582
- $query = 'SELECT * FROM '.$table_name.' WHERE datetime >= "'.$params['start_date'].'" AND datetime <= "'.$params['end_date'].'" AND `page_id` = "'.$params['page_id'].'" AND `event_name` = "inbound_cta_click" ORDER BY `datetime` DESC';
 
 
 
583
  break;
584
  }
585
 
 
 
 
 
 
 
 
 
 
 
 
586
  $results = $wpdb->get_results( $query , ARRAY_A );
587
 
588
  return $results;
110
  `variation_id` mediumint(9) NOT NULL,
111
  `lead_id` mediumint(20) NOT NULL,
112
  `lead_uid` varchar(255) NOT NULL,
113
+ `list_id` mediumint(20) NOT NULL,
114
  `session_id` varchar(255) NOT NULL,
115
  `source` text NOT NULL,
116
  `datetime` datetime NOT NULL,
129
  */
130
  public static function store_form_submission( $lead ){
131
 
132
+ if (!isset($lead['raw_params']) ) {
133
  return;
134
  }
135
 
136
  parse_str($lead['raw_params'] , $raw_params );
137
  $details = array_merge($raw_params,$lead);
138
+
139
+ if (!isset($raw_params['inbound_form_id'])) {
140
+ return;
141
+ }
142
+
143
+ if (isset($raw_params['wp_cta_id'])) {
144
+ $lead['cta_id'] = $raw_params['wp_cta_id'];
145
+ $lead['variation'] = $raw_params['wp_cta_vid'];
146
+ } else {
147
+ $lead['cta_id'] = 0;
148
+ }
149
+
150
  $args = array(
151
  'event_name' => 'inbound_form_submission',
152
  'page_id' => $lead['page_id'],
153
  'variation_id' => $lead['variation'],
154
  'form_id' => (isset($raw_params['inbound_form_id'])) ? $raw_params['inbound_form_id'] : '',
155
  'lead_id' => $lead['id'],
156
+ 'cta_id' => $lead['cta_id'],
157
  'lead_uid' => ( isset($_COOKIE['wp_lead_uid']) ? $_COOKIE['wp_lead_uid'] : '' ),
158
  'event_details' => json_encode($details),
159
  'datetime' => $lead['wordpress_date_time']
393
 
394
  }
395
 
396
+ public static function delete_related_events( $post_id , $vid = 'all' ) {
397
  global $wpdb;
398
 
399
  $post = get_post($post_id);
411
  'lead_id' => $post_id
412
  );
413
  break;
414
+ case 'wp-call-to-action':
415
+ $where = array(
416
+ 'cta_id' => $post_id
417
+ );
418
+ break;
419
  default:
420
  $where = array(
421
  'page_id' => $post_id
423
  break;
424
  }
425
 
426
+ if ($vid != 'all'){
427
+ $where['variation_id'] = $vid;
428
+ }
429
+
430
  $wpdb->delete( $table_name, $where, $where_format = null );
431
 
432
  }
490
  global $wpdb;
491
 
492
  $table_name = $wpdb->prefix . "inbound_events";
493
+ $query = 'SELECT * FROM '.$table_name.' WHERE ';
494
 
495
  switch ($nature) {
496
  case 'lead_id':
497
+ $query .= '`lead_id` = "'.$params['lead_id'].'" ';
498
  break;
499
  case 'page_id':
500
+ $query .= '`page_id` = "'.$params['page_id'].'" ';
501
+ break;
502
+ case 'cta_id':
503
+ $query .= '`cta_id` = "'.$params['cta_id'].'" ';
504
  break;
505
  }
506
 
507
+ /* add date constraints if applicable */
508
+ if (isset($params['start_date'])) {
509
+ $query .= 'AND datetime >= "'.$params['start_date'].'" AND datetime <= "'.$params['end_date'].'" ';
510
+ }
511
+
512
+ if (isset($params['variation_id'])) {
513
+ $query .= 'AND variation_id = "'.$params['variation_id'].'" ';
514
+ }
515
+
516
+ $query .= 'AND `event_name` LIKE "%form_submission" ORDER BY `datetime` DESC';
517
 
518
  $results = $wpdb->get_results( $query , ARRAY_A );
519
 
526
  public static function get_page_views( $lead_id ){
527
  global $wpdb;
528
 
529
+ $table_name = $wpdb->prefix . "inbound_page_views";
530
 
531
+ $query = 'SELECT * FROM '.$table_name.' WHERE `lead_id` = "'.$lead_id.'" ORDER BY `datetime` DESC';
532
  $results = $wpdb->get_results( $query , ARRAY_A );
533
 
534
  return $results;
557
  return $results;
558
  }
559
 
560
+ /**
561
+ * Get page view count given lead_id
562
+ *
563
+ */
564
+ public static function get_page_views_count( $lead_id ){
565
+ global $wpdb;
566
+
567
+ $table_name = $wpdb->prefix . "inbound_page_views";
568
+
569
+ $query = 'SELECT count(*) FROM '.$table_name.' WHERE `lead_id` = "'.$lead_id.'"';
570
+
571
+ $count = $wpdb->get_var( $query , 0, 0 );
572
+
573
+ /* return null if nothing there */
574
+ return ($count) ? $count : 0;
575
+
576
+ }
577
+
578
  /**
579
  * Get all cta click events related to lead ID
580
  */
628
  global $wpdb;
629
 
630
  $table_name = $wpdb->prefix . "inbound_events";
631
+ $query = 'SELECT * FROM '.$table_name.' WHERE ';
632
 
633
  switch ($nature) {
634
  case 'lead_id':
635
+ $query .= '`lead_id` = "'.$params['lead_id'].'" ';
636
  break;
637
  case 'page_id':
638
+ $query .= '`page_id` = "'.$params['page_id'].'" ';
639
+ break;
640
+ case 'cta_id':
641
+ $query .= '`cta_id` = "'.$params['cta_id'].'" ';
642
  break;
643
  }
644
 
645
+ /* add date constraints if applicable */
646
+ if (isset($params['start_date'])) {
647
+ $query .= 'AND datetime >= "'.$params['start_date'].'" AND datetime <= "'.$params['end_date'].'" ';
648
+ }
649
+
650
+ if (isset($params['variation_id'])) {
651
+ $query .= 'AND variation_id = "'.$params['variation_id'].'" ';
652
+ }
653
+
654
+ $query .= 'AND `event_name` = "inbound_cta_click" ORDER BY `datetime` DESC';
655
+
656
  $results = $wpdb->get_results( $query , ARRAY_A );
657
 
658
  return $results;
shared/classes/class.form.php CHANGED
@@ -47,7 +47,6 @@ if (!class_exists('Inbound_Forms')) {
47
  'submit_bg_color' => ''
48
  ), $atts));
49
 
50
-
51
  if (!$id && isset($_GET['post'])) {
52
  $id = intval($_GET['post']);
53
  }
@@ -448,10 +447,10 @@ if (!class_exists('Inbound_Forms')) {
448
  /* End Loop */
449
 
450
  $current_page = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
451
- $form .= '<div class="inbound-field ' . $main_layout . ' inbound-submit-area"><button type="submit" class="inbound-button-submit inbound-submit-action" value="' . $submit_button . '" name="send" id="inbound_form_submit" data-ignore-form-field="true" style="' . $submit_bg . $submit_color . $image_button . '">' . $icon_insert . '' . $submit_button . $inner_button . '</button></div><input data-ignore-form-field="true" type="hidden" name="inbound_submitted" value="1">';
452
  /* <!--<input type="submit" '.$submit_button_type.' class="button" value="'.$submit_button.'" name="send" id="inbound_form_submit" />--> */
453
 
454
- $form .= '<input type="hidden" name="inbound_form_n" class="inbound_form_n" value="' . $form_name . '"><input type="hidden" name="inbound_form_lists" id="inbound_form_lists" value="' . $lists . '" data-map-form-field="inbound_form_lists"><input type="hidden" name="inbound_form_id" class="inbound_form_id" value="' . $id . '"><input type="hidden" name="inbound_current_page_url" value="' . $current_page . '"><input type="hidden" name="page_id" value="' . (isset($post->ID) ? $post->ID : '0') . '"><input type="hidden" name="inbound_furl" value="' . base64_encode($redirect) . '"><input type="hidden" name="inbound_notify" value="' . base64_encode($notify) . '"><input type="hidden" class="inbound_params" name="inbound_params" value=""></form></div>';
455
  $form .= "<style type='text/css'>.inbound-button-submit{ {$font_size} }</style>";
456
  $form = preg_replace('/<br class="inbr".\/>/', '', $form); /* remove editor br tags */
457
 
@@ -529,6 +528,7 @@ if (!class_exists('Inbound_Forms')) {
529
  */
530
  static function register_script() {
531
  wp_enqueue_style('inbound-shortcodes');
 
532
  }
533
 
534
  /**
@@ -553,7 +553,7 @@ if (!class_exists('Inbound_Forms')) {
553
 
554
  jQuery(document).ready(function($){
555
 
556
- jQuery("form").submit(function(e) {
557
 
558
  /* added below condition for check any of checkbox checked or not by kirit dholakiya */
559
  if( jQuery(\'.checkbox-required\')[0] && jQuery(\'.checkbox-required input[type=checkbox]:checked\').length==0)
@@ -573,6 +573,47 @@ if (!class_exists('Inbound_Forms')) {
573
  return false;
574
  }
575
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
576
  });
577
 
578
  jQuery("#inbound_form_submit br").remove(); /* remove br tags */
@@ -683,64 +724,70 @@ if (!class_exists('Inbound_Forms')) {
683
  */
684
  static function do_actions() {
685
 
686
- if (isset($_POST['inbound_submitted']) && $_POST['inbound_submitted'] === '1') {
687
- $form_post_data = array();
688
- if (isset($_POST['phone_xoxo']) && $_POST['phone_xoxo'] != "") {
689
- wp_die($message = 'Die You spam bastard');
690
- return false;
691
- }
692
- /* get form submitted form's meta data */
693
- $form_meta_data = get_post_meta($_POST['inbound_form_id']);
694
 
695
- if (isset($_POST['inbound_furl']) && $_POST['inbound_furl'] != "") {
696
- $redirect = base64_decode($_POST['inbound_furl']);
697
- } else if (isset($_POST['inbound_current_page_url'])) {
698
- $redirect = $_POST['inbound_current_page_url'];
699
- }
 
 
700
 
 
 
 
 
 
 
 
701
 
702
- /*print_r($_POST); */
703
- foreach ($_POST as $field => $value) {
704
 
705
- if (get_magic_quotes_gpc() && is_string($value)) {
706
- $value = stripslashes($value);
707
- }
 
 
 
708
 
709
- $field = strtolower($field);
710
 
711
- if (preg_match('/Email|e-mail|email/i', $field)) {
712
- $field = "wpleads_email_address";
713
- if (isset($_POST['inbound_form_id']) && $_POST['inbound_form_id'] != "") {
714
- self::store_form_stats($_POST['inbound_form_id'], $value);
715
- }
716
  }
 
717
 
718
 
719
- $form_post_data[$field] = (!is_array($value)) ? strip_tags($value) : $value;
720
 
721
- }
722
 
723
- $form_meta_data['post_id'] = $_POST['inbound_form_id']; /* pass in form id */
724
 
725
- /* Send emails if passes spam check returns false */
726
- if (!apply_filters('inbound_check_if_spam', false, $form_post_data)) {
727
- self::send_conversion_admin_notification($form_post_data, $form_meta_data);
728
- self::send_conversion_lead_notification($form_post_data, $form_meta_data);
729
-
730
- /* hook runs after form actions are completed and before page redirect */
731
- do_action('inboundnow_form_submit_actions', $form_post_data, $form_meta_data);
732
- }
733
 
 
 
 
734
 
735
- /* redirect now */
736
- if ($redirect != "") {
737
- $redirect = str_replace('%3F', '/', html_entity_decode($redirect));
738
- wp_redirect($redirect);
739
- exit();
740
- }
741
 
 
 
 
 
 
742
  }
743
 
 
 
744
  }
745
 
746
  /**
47
  'submit_bg_color' => ''
48
  ), $atts));
49
 
 
50
  if (!$id && isset($_GET['post'])) {
51
  $id = intval($_GET['post']);
52
  }
447
  /* End Loop */
448
 
449
  $current_page = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
450
+ $form .= '<div class="inbound-field ' . $main_layout . ' inbound-submit-area"><button type="submit" class="inbound-button-submit inbound-submit-action" value="' . $submit_button . '" name="send" id="inbound_form_submit" data-ignore-form-field="true" style="' . $submit_bg . $submit_color . $image_button . 'position:relative;">' . $icon_insert . '' . $submit_button . $inner_button . '</button></div><input data-ignore-form-field="true" type="hidden" name="inbound_submitted" value="1">';
451
  /* <!--<input type="submit" '.$submit_button_type.' class="button" value="'.$submit_button.'" name="send" id="inbound_form_submit" />--> */
452
 
453
+ $form .= '<input type="hidden" name="inbound_form_n" class="inbound_form_n" value="' . $form_name . '"><input type="hidden" name="inbound_form_lists" id="inbound_form_lists" value="' . $lists . '" data-map-form-field="inbound_form_lists"><input type="hidden" name="inbound_form_id" class="inbound_form_id" value="' . $id . '"><input type="hidden" name="inbound_current_page_url" value="' . $current_page . '"><input type="hidden" name="page_id" value="' . (isset($post->ID) ? $post->ID : '0') . '"><input type="hidden" name="inbound_furl" value="' . base64_encode(trim($redirect)) . '"><input type="hidden" name="inbound_notify" value="' . base64_encode($notify) . '"><input type="hidden" class="inbound_params" name="inbound_params" value=""></form></div>';
454
  $form .= "<style type='text/css'>.inbound-button-submit{ {$font_size} }</style>";
455
  $form = preg_replace('/<br class="inbr".\/>/', '', $form); /* remove editor br tags */
456
 
528
  */
529
  static function register_script() {
530
  wp_enqueue_style('inbound-shortcodes');
531
+ wp_enqueue_script('spin.min', INBOUNDNOW_SHARED_URLPATH . '/shortcodes/js/spin.min.js', null, null, true);
532
  }
533
 
534
  /**
553
 
554
  jQuery(document).ready(function($){
555
 
556
+ jQuery(".inbound-now-form").submit(function(e) {
557
 
558
  /* added below condition for check any of checkbox checked or not by kirit dholakiya */
559
  if( jQuery(\'.checkbox-required\')[0] && jQuery(\'.checkbox-required input[type=checkbox]:checked\').length==0)
573
  return false;
574
  }
575
  });
576
+
577
+ /*Disable button and add spinner to form*/
578
+
579
+ var target = jQuery(this).find("#inbound_form_submit"),
580
+ spinnerColor = jQuery(target).css("color"),
581
+ buttonWidth = jQuery(target).css("width"),
582
+ buttonHeight = jQuery(target).css("height"),
583
+ scale = jQuery(target).css("font-size");
584
+ scale = scale.replace("px", "");
585
+ scale = scale / 40;
586
+
587
+
588
+ //spinner
589
+ var opts = {
590
+ lines: 8 // The number of lines to draw
591
+ , length: 0 // The length of each line
592
+ , width: 7 // The line thickness
593
+ , radius: 25 // The radius of the inner circle
594
+ , scale: scale // Scales overall size of the spinner
595
+ , corners: 1 // Corner roundness (0..1)
596
+ , color: spinnerColor // #rgb or #rrggbb or array of colors
597
+ , opacity: 0.25 // Opacity of the lines
598
+ , rotate: 0 // The rotation offset
599
+ , direction: 1 // 1: clockwise, -1: counterclockwise
600
+ , speed: 1 // Rounds per second
601
+ , trail: 60 // Afterglow percentage
602
+ , fps: 20 // Frames per second when using setTimeout() as a fallback for CSS
603
+ , zIndex: 2e9 // The z-index (defaults to 2000000000)
604
+ , className: "inbound-form-spinner" // The CSS class to assign to the spinner
605
+ , top: "50%" // Top position relative to parent
606
+ , left: "50%" // Left position relative to parent
607
+ , shadow: false // Whether to render a shadow
608
+ , hwaccel: false // Whether to use hardware acceleration
609
+ , position: "absolute" // Element positioning
610
+ }
611
+
612
+ jQuery(target).prop("disabled",true).html("").css({"width" : buttonWidth, "height" : buttonHeight});
613
+
614
+ var spinner = new Spinner(opts).spin(target[0]);
615
+
616
+
617
  });
618
 
619
  jQuery("#inbound_form_submit br").remove(); /* remove br tags */
724
  */
725
  static function do_actions() {
726
 
727
+ /* only process actions when told to */
728
+ if (!isset($_POST['inbound_submitted']) || !$_POST['inbound_submitted']) {
729
+ return;
730
+ }
 
 
 
 
731
 
732
+ $form_post_data = array();
733
+ if (isset($_POST['phone_xoxo']) && $_POST['phone_xoxo'] != "") {
734
+ wp_die($message = 'Die Die Die');
735
+ return false;
736
+ }
737
+ /* get form submitted form's meta data */
738
+ $form_meta_data = get_post_meta($_POST['inbound_form_id']);
739
 
740
+ if (isset($_POST['inbound_furl']) && $_POST['inbound_furl'] != "") {
741
+ $redirect = base64_decode($_POST['inbound_furl']);
742
+ } else if (isset($_POST['inbound_current_page_url'])) {
743
+ $redirect = $_POST['inbound_current_page_url'];
744
+ } else {
745
+ $redirect = "";
746
+ }
747
 
 
 
748
 
749
+ /*print_r($_POST); */
750
+ foreach ($_POST as $field => $value) {
751
+
752
+ if (get_magic_quotes_gpc() && is_string($value)) {
753
+ $value = stripslashes($value);
754
+ }
755
 
756
+ $field = strtolower($field);
757
 
758
+ if (preg_match('/Email|e-mail|email/i', $field)) {
759
+ $field = "wpleads_email_address";
760
+ if (isset($_POST['inbound_form_id']) && $_POST['inbound_form_id'] != "") {
761
+ self::store_form_stats($_POST['inbound_form_id'], $value);
 
762
  }
763
+ }
764
 
765
 
766
+ $form_post_data[$field] = (!is_array($value)) ? strip_tags($value) : $value;
767
 
768
+ }
769
 
770
+ $form_meta_data['post_id'] = $_POST['inbound_form_id']; /* pass in form id */
771
 
772
+ /* Send emails if passes spam check returns false */
773
+ if (!apply_filters('inbound_check_if_spam', false, $form_post_data)) {
774
+ self::send_conversion_admin_notification($form_post_data, $form_meta_data);
775
+ self::send_conversion_lead_notification($form_post_data, $form_meta_data);
 
 
 
 
776
 
777
+ /* hook runs after form actions are completed and before page redirect */
778
+ do_action('inboundnow_form_submit_actions', $form_post_data, $form_meta_data);
779
+ }
780
 
 
 
 
 
 
 
781
 
782
+ /* redirect now */
783
+ if ($redirect != "") {
784
+ $redirect = str_replace('%3F', '/', html_entity_decode($redirect));
785
+ wp_redirect($redirect);
786
+ exit();
787
  }
788
 
789
+
790
+
791
  }
792
 
793
  /**
shared/classes/class.inbound-api.php CHANGED
@@ -896,6 +896,16 @@ if (!class_exists('Inbound_API')) {
896
  /* Merge POST & GET & @param vars into array variable */
897
  $params = array_merge( $params, $_REQUEST );
898
 
 
 
 
 
 
 
 
 
 
 
899
  /* Make sure our meta_data field is setup correctly */
900
  self::validate_parameter( $params['meta_data'], 'meta_data', 'array' );
901
 
@@ -929,14 +939,21 @@ if (!class_exists('Inbound_API')) {
929
  }
930
 
931
  /* Add lead to lists */
932
- if (isset($params['lead_lists']) && self::validate_parameter( $params['lead_lists'], 'lead_lists', 'array' ) ) {
 
 
933
 
 
934
  foreach ( $params['lead_lists'] as $list_id ) {
935
  $Inbound_Leads->add_lead_to_list( $lead_id, $list_id );
936
  }
937
  }
938
 
939
  /* Add tag to leads */
 
 
 
 
940
  if (isset($params['tags']) && self::validate_parameter( $params['tags'], 'tags', 'array' ) ) {
941
  foreach ( $params['tags'] as $tag ) {
942
  $Inbound_Leads->add_tag_to_lead( $lead_id, $tag );
@@ -1361,7 +1378,8 @@ if (!class_exists('Inbound_API')) {
1361
  $profile = $profiles[0];
1362
  $args = unserialize($profile->args);
1363
 
1364
- $args['id'] = (isset( $args['id']) && $args['id'] ) ? $args['id'] : $_COOKIE['wp_lead_id'];
 
1365
 
1366
  /* process extra lead events */
1367
  if ($args['id']) {
@@ -1394,10 +1412,11 @@ if (!class_exists('Inbound_API')) {
1394
  }
1395
  }
1396
 
1397
- /* Add link click event to lead profile */
1398
- do_action('inbound_track_link', $args);
1399
  }
1400
 
 
 
 
1401
  /* redirect to url */
1402
  header('Location: '. $args['url'] );
1403
  exit;
896
  /* Merge POST & GET & @param vars into array variable */
897
  $params = array_merge( $params, $_REQUEST );
898
 
899
+ /* Account for Zapier */
900
+ if (!isset($params['meta_data']) && file_get_contents('php://input')) {
901
+ $params = json_decode(file_get_contents('php://input'), true);
902
+ }
903
+
904
+ /* check if meta_data is http query */
905
+ if (!is_array($params['meta_data']) && strstr($params['meta_data'] , '=')) {
906
+ parse_str($params['meta_data'],$params['meta_data']);
907
+ }
908
+
909
  /* Make sure our meta_data field is setup correctly */
910
  self::validate_parameter( $params['meta_data'], 'meta_data', 'array' );
911
 
939
  }
940
 
941
  /* Add lead to lists */
942
+ if (isset($params['lead_lists']) && !is_array($params['lead_lists']) ){
943
+ $params['lead_lists'] = explode(',',$params['lead_lists']);
944
+ }
945
 
946
+ if (isset($params['lead_lists']) && self::validate_parameter( $params['lead_lists'], 'lead_lists', 'array' ) ) {
947
  foreach ( $params['lead_lists'] as $list_id ) {
948
  $Inbound_Leads->add_lead_to_list( $lead_id, $list_id );
949
  }
950
  }
951
 
952
  /* Add tag to leads */
953
+ if (isset($params['tags']) && !is_array($params['tags']) && $params['tags']){
954
+ $params['tags'] = explode(',',$params['tags']);
955
+ }
956
+
957
  if (isset($params['tags']) && self::validate_parameter( $params['tags'], 'tags', 'array' ) ) {
958
  foreach ( $params['tags'] as $tag ) {
959
  $Inbound_Leads->add_tag_to_lead( $lead_id, $tag );
1378
  $profile = $profiles[0];
1379
  $args = unserialize($profile->args);
1380
 
1381
+ $lead_id_cookie = (isset($_COOKIE['wp_lead_id'])) ? $_COOKIE['wp_lead_id'] : 0;
1382
+ $args['id'] = (isset( $args['id']) && $args['id'] ) ? $args['id'] : $lead_id_cookie;
1383
 
1384
  /* process extra lead events */
1385
  if ($args['id']) {
1412
  }
1413
  }
1414
 
 
 
1415
  }
1416
 
1417
+ /* Process tracked link extras */
1418
+ do_action('inbound_track_link', $args);
1419
+
1420
  /* redirect to url */
1421
  header('Location: '. $args['url'] );
1422
  exit;
shared/classes/class.lead-storage.php CHANGED
@@ -77,11 +77,7 @@ if (!class_exists('LeadStorage')) {
77
  $lead['source'] = self::check_val('source', $args);
78
  $lead['ip_address'] = self::lookup_ip_address();
79
 
80
- if($lead['mapped_params']){
81
- parse_str($lead['mapped_params'], $mappedData);
82
- } else {
83
- $mappedData = array();
84
- }
85
 
86
  if($lead['raw_params']){
87
  parse_str($lead['raw_params'], $raw_params);
@@ -89,7 +85,14 @@ if (!class_exists('LeadStorage')) {
89
  $raw_params = array();
90
  }
91
 
92
- $mappedData = self::improve_mapping($mappedData, $lead);
 
 
 
 
 
 
 
93
 
94
  /* prepate lead lists */
95
  $lead['lead_lists'] = (isset($args['lead_lists'])) ? $args['lead_lists'] : null;
@@ -129,7 +132,9 @@ if (!class_exists('LeadStorage')) {
129
  $Inbound_Leads->add_lead_to_list($lead['id'], $lead['lead_lists']);
130
 
131
  /* store lead list cookie */
132
- Leads_Tracking::cookie_lead_lists($lead['id']);
 
 
133
  }
134
 
135
 
@@ -575,14 +580,14 @@ if (!class_exists('LeadStorage')) {
575
  /**
576
  * Uses mapped data if not programatically set
577
  */
578
- static function improve_mapping($mappedData, $lead) {
579
 
580
  /* check to see if there are any mapped values arriving through inbound_store_lead */
581
  $fields = Leads_Field_Map::build_map_array();
582
 
583
  foreach ($fields as $key => $label ) {
584
- if( isset( $lead[ $key ]) && !isset($mappedData[$key]) ) {
585
- $mappedData[$key] = $lead[ $key ];
586
  }
587
  }
588
 
@@ -696,13 +701,6 @@ if (!function_exists('inbound_store_lead')) {
696
  /* wpleads_email_address becomes wpleads_email */
697
  $args['email'] = $args['wpleads_email_address'];
698
 
699
- /* loop through and remove wpleads_ (we will add them back in the new method ) */
700
- foreach ($args as $key => $value) {
701
- $newkey = str_replace( 'wpleads_', '', $key );
702
- unset($args[$key]);
703
- $args[$newkey] = $value;
704
- }
705
-
706
  /* Send data through new method */
707
  $Leads = new LeadStorage();
708
  if ($return) {
@@ -739,7 +737,7 @@ if (!function_exists('inbound_add_conversion_to_lead')) {
739
  $lead_data['wordpress_date_time'] = date("Y-m-d G:i:s T", $time);
740
  $conversion_data = get_post_meta( $lead_id, 'wpleads_conversion_data', TRUE );
741
  $conversion_data = json_decode($conversion_data,true);
742
- $variation = $lead_data['variation'];
743
 
744
  if ( is_array($conversion_data)) {
745
  $c_count = count($conversion_data) + 1;
77
  $lead['source'] = self::check_val('source', $args);
78
  $lead['ip_address'] = self::lookup_ip_address();
79
 
80
+
 
 
 
 
81
 
82
  if($lead['raw_params']){
83
  parse_str($lead['raw_params'], $raw_params);
85
  $raw_params = array();
86
  }
87
 
88
+ if($lead['mapped_params']){
89
+ parse_str($lead['mapped_params'], $mappedData);
90
+ } else {
91
+ $mappedData = array();
92
+ }
93
+
94
+
95
+ $mappedData = self::improve_mapping($mappedData, $lead , $args);
96
 
97
  /* prepate lead lists */
98
  $lead['lead_lists'] = (isset($args['lead_lists'])) ? $args['lead_lists'] : null;
132
  $Inbound_Leads->add_lead_to_list($lead['id'], $lead['lead_lists']);
133
 
134
  /* store lead list cookie */
135
+ if (class_exists('Leads_Tracking')) {
136
+ Leads_Tracking::cookie_lead_lists($lead['id']);
137
+ }
138
  }
139
 
140
 
580
  /**
581
  * Uses mapped data if not programatically set
582
  */
583
+ static function improve_mapping($mappedData, $lead , $args) {
584
 
585
  /* check to see if there are any mapped values arriving through inbound_store_lead */
586
  $fields = Leads_Field_Map::build_map_array();
587
 
588
  foreach ($fields as $key => $label ) {
589
+ if( isset( $args[ $key ]) && !isset($mappedData[$key]) ) {
590
+ $mappedData[$key] = $args[ $key ];
591
  }
592
  }
593
 
701
  /* wpleads_email_address becomes wpleads_email */
702
  $args['email'] = $args['wpleads_email_address'];
703
 
 
 
 
 
 
 
 
704
  /* Send data through new method */
705
  $Leads = new LeadStorage();
706
  if ($return) {
737
  $lead_data['wordpress_date_time'] = date("Y-m-d G:i:s T", $time);
738
  $conversion_data = get_post_meta( $lead_id, 'wpleads_conversion_data', TRUE );
739
  $conversion_data = json_decode($conversion_data,true);
740
+ $variation = (isset($lead_data['variation'])) ? $lead_data['variation']:0;
741
 
742
  if ( is_array($conversion_data)) {
743
  $c_count = count($conversion_data) + 1;
shared/classes/class.licensing.php CHANGED
@@ -57,120 +57,9 @@ if ( ! class_exists( 'Inbound_License' ) )
57
  return;
58
  }
59
 
60
- /* Add licenses key to global settings array */
61
- add_filter( 'lp_define_global_settings', array( $this, 'lp_settings' ), 2 );
62
- add_filter( 'wp_cta_define_global_settings', array( $this, 'wp_cta_settings' ), 2 );
63
- add_filter( 'wpleads_define_global_settings', array( $this, 'wpleads_settings' ), 2 );
64
-
65
- /* save license key data / activate license keys */
66
- if (is_admin()) {
67
- $this->save_license_field();
68
- }
69
-
70
-
71
- add_action('lp_render_global_settings', array($this, 'display_license_field'));
72
- add_action('wpleads_render_global_settings', array($this, 'display_license_field'));
73
- add_action('wp_cta_render_global_settings', array($this, 'display_license_field'));
74
-
75
-
76
-
77
- }
78
-
79
- public function lp_settings( $lp_global_settings ) {
80
- $lp_global_settings['lp-license-keys']['settings'][$this->plugin_slug] = array(
81
- 'id' => $this->plugin_slug,
82
- 'slug' => $this->plugin_slug,
83
- 'remote_download_slug' => $this->remote_download_slug,
84
- 'label' => sprintf( '%1$s', $this->plugin_label ),
85
- 'description' => 'Head to http://www.inboundnow.com/ to retrieve your license key for '.$this->plugin_label,
86
- 'type' => 'inboundnow-license-key',
87
- 'default' => $this->master_license_key
88
- );
89
-
90
- return $lp_global_settings;
91
- }
92
-
93
- public function wp_cta_settings( $wp_cta_global_settings ) {
94
-
95
- $wp_cta_global_settings['wp-cta-license-keys']['settings'][$this->plugin_slug] = array(
96
- 'id' => $this->plugin_slug,
97
- 'slug' => $this->plugin_slug,
98
- 'remote_download_slug' => $this->remote_download_slug,
99
- 'label' => sprintf( '%1$s', $this->plugin_label ),
100
- 'description' => 'Head to http://www.inboundnow.com/ to retrieve your license key for '.$this->plugin_label,
101
- 'type' => 'inboundnow-license-key',
102
- 'default' => ''
103
- );
104
-
105
- return $wp_cta_global_settings;
106
- }
107
-
108
-
109
- public function wpleads_settings( $wpleads_global_settings ) {
110
- $wpleads_global_settings['wpleads-license-keys']['label'] = 'License Keys';
111
- $wpleads_global_settings['wpleads-license-keys']['settings'][$this->plugin_slug] = array(
112
- 'id' => $this->plugin_slug,
113
- 'slug' => $this->plugin_slug,
114
- 'remote_download_slug' => $this->remote_download_slug,
115
- 'label' => sprintf( '%1$s', $this->plugin_label ),
116
- 'description' => 'Head to http://www.inboundnow.com/ to retrieve your license key for '.$this->plugin_label,
117
- 'type' => 'inboundnow-license-key',
118
- 'default' => $this->master_license_key
119
- );
120
-
121
- /*print_r($lp_global_settings);exit; */
122
- return $wpleads_global_settings;
123
  }
124
 
125
-
126
-
127
- function display_license_field($field)
128
- {
129
- if ( $field['type']=='inboundnow-license-key' && ($field['slug']==$this->plugin_slug) )
130
- {
131
-
132
- $field['id'] = "inboundnow-license-keys-".$field['slug'];
133
- $field['value'] = get_option('inboundnow_master_license_key', '');
134
-
135
- echo '<input type="hidden" name="'.$field['id'].'" id="'.$field['id'].'" value="'.$field['value'].'" size="30" />';
136
-
137
-
138
- switch ($_GET['post_type']){
139
-
140
- case "landing-page":
141
- $prefix = "lp_";
142
- break;
143
- case "wp-lead":
144
- $prefix = "wpleads_";
145
- break;
146
- case "wp-call-to-action":
147
- $prefix = "wp_cta_";
148
- break;
149
-
150
- }
151
- /*echo here;exit; */
152
- $license_status = $this->check_license_status($field);
153
-
154
- echo '<input type="hidden" name="inboundnow_license_status-'.$field['slug'].'" id="'.$field['id'].'" value="'.$license_status.'" size="30" />';
155
-
156
-
157
- if ($license_status=='valid')
158
- {
159
- echo '<div class="'.$prefix.'license_status_valid">Enabled</div>';
160
- }
161
- else
162
- {
163
- echo '<div class="'.$prefix.'license_status_invalid">Disabled</div>';
164
- }
165
-
166
- echo '<div class="'.$prefix.'tooltip tool_text" title="'.$field['description'].'"></div>';
167
- }
168
- }
169
-
170
-
171
-
172
- public function check_license_status($field)
173
- {
174
 
175
  $date = date("Y-m-d");
176
  $cache_date = get_transient($field['id']."-expire");
@@ -197,7 +86,6 @@ if ( ! class_exists( 'Inbound_License' ) )
197
 
198
  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
199
 
200
-
201
  if( $license_data->license == 'active' ) {
202
  $newDate = date('Y-m-d', strtotime($license_data->expires));
203
  set_transient($field['id']."-expire", true, YEAR_IN_SECONDS / 2 );
@@ -208,81 +96,6 @@ if ( ! class_exists( 'Inbound_License' ) )
208
  }
209
  }
210
 
211
-
212
-
213
- /* SAVE & ACTIVATE LICENSE & CHECK STATUS OF KEYS */
214
-
215
-
216
- public function save_license_field()
217
- {
218
-
219
- if (!isset($_POST['inboundnow_master_license_key'])) {
220
- return;
221
- }
222
-
223
- $field_id = "inboundnow-license-keys-".$this->plugin_slug;
224
-
225
- $license_status = get_option('inboundnow_license_status_'.$this->plugin_slug );
226
-
227
- $master_license_key = $_POST['inboundnow_master_license_key'];
228
-
229
- /*
230
- echo "license status:".$license_status;
231
- echo "<br>";
232
- echo "new_key:".$master_license_key;
233
- echo "<br>";
234
- echo "old_key:".$this->master_license_key;
235
- echo "<br>";
236
- echo "plugin_slug:".$this->plugin_slug;
237
- echo "<hr>";
238
- */
239
-
240
- if ($license_status=='valid' && $master_license_key == $this->master_license_key )
241
- return;
242
-
243
- if ( $master_license_key ) {
244
- update_option($field_id ,$master_license_key);
245
-
246
- /* data to send in our API request */
247
- $api_params = array(
248
- 'edd_action'=> 'inbound_check_license',
249
- 'license' => $master_license_key,
250
- 'item_name' => $this->remote_download_slug ,
251
- 'cache_bust'=> substr(md5(rand()),0,7)
252
- );
253
- /*print_r($api_params); */
254
-
255
-
256
- /* Call the custom API. */
257
- $response = wp_remote_get( add_query_arg( $api_params, $this->remote_api_url ), array( 'timeout' => 30, 'sslverify' => false ) );
258
-
259
- /* decode the license data */
260
- $license_data = json_decode( wp_remote_retrieve_body( $response ) );
261
-
262
- /* $license_data->license will be either "active" or "inactive" */
263
- $license_status = update_option('inboundnow_license_status_'.$this->plugin_slug, $license_data->license);
264
-
265
- }
266
- elseif ( empty($master_license_key) )
267
- {
268
- update_option($field_id, '' );
269
- update_option('inboundnow_license_status_'.$this->plugin_slug, 'inactive');
270
- }
271
- }
272
- /**
273
- * Check for Updates at the defined API endpoint and modify the update array.
274
- *
275
- * This function dives into the update api just when Wordpress creates its update array,
276
- * then adds a custom API call and injects the custom plugin data retrieved from the API.
277
- * It is reassembled from parts of the native Wordpress plugin update code.
278
- * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
279
- *
280
- * @uses api_request()
281
- *
282
- * @param array $_transient_data Update array build by Wordpress.
283
- * @return array Modified update array with custom plugin data.
284
- */
285
-
286
  public function pre_set_site_transient_update_plugins_filter( $_transient_data )
287
  {
288
 
57
  return;
58
  }
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  }
61
 
62
+ public function check_license_status($field){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
  $date = date("Y-m-d");
65
  $cache_date = get_transient($field['id']."-expire");
86
 
87
  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
88
 
 
89
  if( $license_data->license == 'active' ) {
90
  $newDate = date('Y-m-d', strtotime($license_data->expires));
91
  set_transient($field['id']."-expire", true, YEAR_IN_SECONDS / 2 );
96
  }
97
  }
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  public function pre_set_site_transient_update_plugins_filter( $_transient_data )
100
  {
101
 
shared/classes/class.load-shared.php CHANGED
@@ -55,7 +55,6 @@ if (!class_exists('Inbound_Load_Shared')) {
55
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.form.php');
56
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.menus.adminbar.php');
57
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.debug.php');
58
- include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.compatibility.php');
59
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.templating-engine.php');
60
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.shortcodes.email-template.php');
61
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.shortcodes.cookie-values.php');
55
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.form.php');
56
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.menus.adminbar.php');
57
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.debug.php');
 
58
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.templating-engine.php');
59
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.shortcodes.email-template.php');
60
  include_once( INBOUNDNOW_SHARED_PATH . 'classes/class.shortcodes.cookie-values.php');
shared/docs/analytics.events.md CHANGED
@@ -348,5 +348,19 @@ function form_after_submission_function( data ) {
348
  _inbound.add_action( 'form_after_submission', form_after_submission_function, 10 );
349
  ```
350
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  <!-- End shared\assets\js\frontend\analytics-src\analytics.events.js -->
352
 
348
  _inbound.add_action( 'form_after_submission', form_after_submission_function, 10 );
349
  ```
350
 
351
+ button == the button that was clicked, form == the form that button belongs to, formRedirectUrl == the link that the form redirects to, if set
352
+
353
+ Get the button...
354
+
355
+ If not an iframe
356
+
357
+ If it is an iframe
358
+
359
+ If the redirect link is not set, or there is a single space in it, the form isn't supposed to redirect. So set the action for void
360
+
361
+ If not an iframe
362
+
363
+ If it is an iframe
364
+
365
  <!-- End shared\assets\js\frontend\analytics-src\analytics.events.js -->
366
 
shared/shortcodes/inbound-shortcodes.php CHANGED
@@ -39,7 +39,9 @@ class Inbound_Shortcodes {
39
 
40
  add_action( 'wp_enqueue_scripts', array(__CLASS__, 'frontend_loads')); // load styles
41
  add_shortcode('list', array(__CLASS__, 'inbound_shortcode_list'));
 
42
  add_shortcode('button', array(__CLASS__, 'inbound_shortcode_button'));
 
43
  add_shortcode('social_share', array(__CLASS__, 'inbound_shortcode_social_links'));
44
  //add_action('admin_notices', array(__CLASS__, 'inbound_shortcode_prompt'));
45
  //add_action('admin_init', array(__CLASS__, 'inbound_shortcode_prompt_ignore'));
39
 
40
  add_action( 'wp_enqueue_scripts', array(__CLASS__, 'frontend_loads')); // load styles
41
  add_shortcode('list', array(__CLASS__, 'inbound_shortcode_list'));
42
+ add_shortcode('inbound_list', array(__CLASS__, 'inbound_shortcode_list'));
43
  add_shortcode('button', array(__CLASS__, 'inbound_shortcode_button'));
44
+ add_shortcode('inbound_button', array(__CLASS__, 'inbound_shortcode_button'));
45
  add_shortcode('social_share', array(__CLASS__, 'inbound_shortcode_social_links'));
46
  //add_action('admin_notices', array(__CLASS__, 'inbound_shortcode_prompt'));
47
  //add_action('admin_init', array(__CLASS__, 'inbound_shortcode_prompt_ignore'));
shared/shortcodes/js/shortcodes.js CHANGED
@@ -510,15 +510,15 @@ var InboundShortcodes = {
510
  jQuery("body").on('mousedown', '#inbound_save_form', function () {
511
 
512
  var post_id = jQuery("#post_ID").val();
513
- var form_settings = jQuery(".child-clone-rows.ui-sortable").html();
514
  var shortcode_name = jQuery("#inbound_current_shortcode").val();
515
- var shortcode_value = jQuery('#_inbound_shortcodes_newoutput').html();
516
  var form_name = jQuery("#inbound_shortcode_form_name").val();
517
  var form_values = jQuery("#inbound-shortcodes-form").serialize();
518
  var notify_email = jQuery("#inbound_shortcode_notify").val();
519
  var notify_email_subject = jQuery("#inbound_shortcode_notify_subject").val();
520
  var field_count = jQuery('.child-clone-row').length;
521
- var redirect_value = jQuery('#inbound_shortcode_redirect').val();
522
 
523
  if (typeof (inbound_forms) != "undefined" && inbound_forms !== null) {
524
  var post_type = 'inbound-forms';
@@ -551,6 +551,23 @@ var InboundShortcodes = {
551
  return false;
552
  }
553
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  if (shortcode_name === "insert_inbound_form_shortcode" && form_name == "") {
555
  jQuery(".step-item.first").click();
556
 
510
  jQuery("body").on('mousedown', '#inbound_save_form', function () {
511
 
512
  var post_id = jQuery("#post_ID").val();
513
+ var form_settings = jQuery(".child-clone-rows.ui-sortable").html().trim();
514
  var shortcode_name = jQuery("#inbound_current_shortcode").val();
515
+ var shortcode_value = jQuery('#_inbound_shortcodes_newoutput').html().trim();
516
  var form_name = jQuery("#inbound_shortcode_form_name").val();
517
  var form_values = jQuery("#inbound-shortcodes-form").serialize();
518
  var notify_email = jQuery("#inbound_shortcode_notify").val();
519
  var notify_email_subject = jQuery("#inbound_shortcode_notify_subject").val();
520
  var field_count = jQuery('.child-clone-row').length;
521
+ var redirect_value = jQuery('#inbound_shortcode_redirect').val().trim();
522
 
523
  if (typeof (inbound_forms) != "undefined" && inbound_forms !== null) {
524
  var post_type = 'inbound-forms';
551
  return false;
552
  }
553
  }
554
+
555
+ /*Redirect whitespace cleaning*/
556
+ if(form_values.indexOf("&inbound_shortcode_redirect_2=+")){
557
+ var form_values2 = form_values.substring(form_values.indexOf("&inbound_shortcode_redirect_2=") + 30, form_values.indexOf("inbound_shortcode_notify"));
558
+ var saveString = form_values2;
559
+ var length = form_values2.length;
560
+
561
+ for(i = 0; i < length; i++){
562
+ if(form_values2.charAt(0) == '+'){
563
+ form_values2 = form_values2.replace('+', '');
564
+ }else{
565
+ break;
566
+ }
567
+ }
568
+ form_values = form_values.replace(saveString, form_values2);
569
+ }
570
+
571
  if (shortcode_name === "insert_inbound_form_shortcode" && form_name == "") {
572
  jQuery(".step-item.first").click();
573
 
shared/shortcodes/js/spin.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // http://spin.js.org/#v2.3.2
2
+ !function(a,b){"object"==typeof module&&module.exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.Spinner=b()}(this,function(){"use strict";function a(a,b){var c,d=document.createElement(a||"div");for(c in b)d[c]=b[c];return d}function b(a){for(var b=1,c=arguments.length;c>b;b++)a.appendChild(arguments[b]);return a}function c(a,b,c,d){var e=["opacity",b,~~(100*a),c,d].join("-"),f=.01+c/d*100,g=Math.max(1-(1-a)/b*(100-f),a),h=j.substring(0,j.indexOf("Animation")).toLowerCase(),i=h&&"-"+h+"-"||"";return m[e]||(k.insertRule("@"+i+"keyframes "+e+"{0%{opacity:"+g+"}"+f+"%{opacity:"+a+"}"+(f+.01)+"%{opacity:1}"+(f+b)%100+"%{opacity:"+a+"}100%{opacity:"+g+"}}",k.cssRules.length),m[e]=1),e}function d(a,b){var c,d,e=a.style;if(b=b.charAt(0).toUpperCase()+b.slice(1),void 0!==e[b])return b;for(d=0;d<l.length;d++)if(c=l[d]+b,void 0!==e[c])return c}function e(a,b){for(var c in b)a.style[d(a,c)||c]=b[c];return a}function f(a){for(var b=1;b<arguments.length;b++){var c=arguments[b];for(var d in c)void 0===a[d]&&(a[d]=c[d])}return a}function g(a,b){return"string"==typeof a?a:a[b%a.length]}function h(a){this.opts=f(a||{},h.defaults,n)}function i(){function c(b,c){return a("<"+b+' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">',c)}k.addRule(".spin-vml","behavior:url(#default#VML)"),h.prototype.lines=function(a,d){function f(){return e(c("group",{coordsize:k+" "+k,coordorigin:-j+" "+-j}),{width:k,height:k})}function h(a,h,i){b(m,b(e(f(),{rotation:360/d.lines*a+"deg",left:~~h}),b(e(c("roundrect",{arcsize:d.corners}),{width:j,height:d.scale*d.width,left:d.scale*d.radius,top:-d.scale*d.width>>1,filter:i}),c("fill",{color:g(d.color,a),opacity:d.opacity}),c("stroke",{opacity:0}))))}var i,j=d.scale*(d.length+d.width),k=2*d.scale*j,l=-(d.width+d.length)*d.scale*2+"px",m=e(f(),{position:"absolute",top:l,left:l});if(d.shadow)for(i=1;i<=d.lines;i++)h(i,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(i=1;i<=d.lines;i++)h(i);return b(a,m)},h.prototype.opacity=function(a,b,c,d){var e=a.firstChild;d=d.shadow&&d.lines||0,e&&b+d<e.childNodes.length&&(e=e.childNodes[b+d],e=e&&e.firstChild,e=e&&e.firstChild,e&&(e.opacity=c))}}var j,k,l=["webkit","Moz","ms","O"],m={},n={lines:12,length:7,width:5,radius:10,scale:1,corners:1,color:"#000",opacity:.25,rotate:0,direction:1,speed:1,trail:100,fps:20,zIndex:2e9,className:"spinner",top:"50%",left:"50%",shadow:!1,hwaccel:!1,position:"absolute"};if(h.defaults={},f(h.prototype,{spin:function(b){this.stop();var c=this,d=c.opts,f=c.el=a(null,{className:d.className});if(e(f,{position:d.position,width:0,zIndex:d.zIndex,left:d.left,top:d.top}),b&&b.insertBefore(f,b.firstChild||null),f.setAttribute("role","progressbar"),c.lines(f,c.opts),!j){var g,h=0,i=(d.lines-1)*(1-d.direction)/2,k=d.fps,l=k/d.speed,m=(1-d.opacity)/(l*d.trail/100),n=l/d.lines;!function o(){h++;for(var a=0;a<d.lines;a++)g=Math.max(1-(h+(d.lines-a)*n)%l*m,d.opacity),c.opacity(f,a*d.direction+i,g,d);c.timeout=c.el&&setTimeout(o,~~(1e3/k))}()}return c},stop:function(){var a=this.el;return a&&(clearTimeout(this.timeout),a.parentNode&&a.parentNode.removeChild(a),this.el=void 0),this},lines:function(d,f){function h(b,c){return e(a(),{position:"absolute",width:f.scale*(f.length+f.width)+"px",height:f.scale*f.width+"px",background:b,boxShadow:c,transformOrigin:"left",transform:"rotate("+~~(360/f.lines*k+f.rotate)+"deg) translate("+f.scale*f.radius+"px,0)",borderRadius:(f.corners*f.scale*f.width>>1)+"px"})}for(var i,k=0,l=(f.lines-1)*(1-f.direction)/2;k<f.lines;k++)i=e(a(),{position:"absolute",top:1+~(f.scale*f.width/2)+"px",transform:f.hwaccel?"translate3d(0,0,0)":"",opacity:f.opacity,animation:j&&c(f.opacity,f.trail,l+k*f.direction,f.lines)+" "+1/f.speed+"s linear infinite"}),f.shadow&&b(i,e(h("#000","0 0 4px #000"),{top:"2px"})),b(d,b(i,h(g(f.color,k),"0 0 1px rgba(0,0,0,.1)")));return d},opacity:function(a,b,c){b<a.childNodes.length&&(a.childNodes[b].style.opacity=c)}}),"undefined"!=typeof document){k=function(){var c=a("style",{type:"text/css"});return b(document.getElementsByTagName("head")[0],c),c.sheet||c.styleSheet}();var o=e(a("group"),{behavior:"url(#default#VML)"});!d(o,"transform")&&o.adj?i():j=d(o,"animation")}return h});
shared/shortcodes/shortcodes-fields.php CHANGED
@@ -4,10 +4,12 @@ if ( !class_exists('Inbound_Shortcodes_Fields') ) {
4
 
5
  /* Include wp-load
6
  * ----------------------------------------------------- */
7
- /* Include wp-load
8
- * ----------------------------------------------------- */
9
- $path_to_file = explode( 'wp-content', __FILE__ );
10
- $path_to_wp = $path_to_file[0];
 
 
11
  require_once( $path_to_wp . '/wp-load.php' );
12
 
13
  /* The Class
4
 
5
  /* Include wp-load
6
  * ----------------------------------------------------- */
7
+ if (function_exists('get_home_path')) {
8
+ $path_to_wp = get_home_path();
9
+ } else {
10
+ $path_to_file = explode( 'wp-content', __FILE__ );
11
+ $path_to_wp = $path_to_file[0];
12
+ }
13
  require_once( $path_to_wp . '/wp-load.php' );
14
 
15
  /* The Class
shared/shortcodes/shortcodes/button.php CHANGED
@@ -101,7 +101,7 @@
101
  ),
102
  ),
103
  // style="{{style}}"
104
- 'shortcode' => '[button font_size="{{font-size}}" color="{{color}}" text_color="{{text-color}}" icon="{{icon}}" url="{{url}}" width="{{width}}" target="{{target}}"]{{content}}[/button]',
105
  'popup_title' =>'Insert Button Shortcode'
106
  );
107
 
101
  ),
102
  ),
103
  // style="{{style}}"
104
+ 'shortcode' => '[inbound_button font_size="{{font-size}}" color="{{color}}" text_color="{{text-color}}" icon="{{icon}}" url="{{url}}" width="{{width}}" target="{{target}}"]{{content}}[/button]',
105
  'popup_title' =>'Insert Button Shortcode'
106
  );
107
 
shared/shortcodes/shortcodes/forms.php CHANGED
@@ -43,8 +43,8 @@ $shortcodes_config['forms'] = array(
43
  'std' => 'redirect'
44
  ),*/
45
  'redirect' => array(
46
- 'name' => __('Redirect URL<span class="small-required-text">*</span>', 'inbound-pro' ),
47
- 'desc' => __('Where do you want to send people after they fill out the form? Please note: http:// is required.', 'inbound-pro' ),
48
  'type' => 'text',
49
  'placeholder' => "http://www.yoursite.com/thank-you",
50
  'std' => '',
43
  'std' => 'redirect'
44
  ),*/
45
  'redirect' => array(
46
+ 'name' => __('Redirect URL', 'inbound-pro' ),
47
+ 'desc' => __('Where do you want to send people after they fill out the form? Please note: http:// is required. Leave blank to prevent redirection.', 'inbound-pro' ),
48
  'type' => 'text',
49
  'placeholder' => "http://www.yoursite.com/thank-you",
50
  'std' => '',
trunk/.gitignore DELETED
@@ -1,59 +0,0 @@
1
- .DS_Store
2
- /shared/_DelSyncFiles/
3
-
4
- shared/languages/landing-pages/.tx/CONFIG
5
- shared/languages/landing-pages/get-translations.bat
6
- shared/languages/leads/_get-translations.bat
7
- shared/languages/calls-to-action/_get-translations.bat
8
-
9
- #filetypes
10
-
11
-
12
- # OS generated files #
13
- ######################
14
- *~
15
- .SyncIgnore
16
- .svn
17
- .cvs
18
- .DS_Store
19
- .DS_Store?
20
- ._*
21
- .Spotlight-V100
22
- .Trashes
23
- Icon?
24
- ehthumbs.db
25
- Thumbs.db
26
- .cache
27
- .project
28
- .settings
29
- .tmproj
30
- *.esproj
31
- nbproject
32
- *.sublime-project
33
- *.sublime-workspace
34
- *.exe
35
- *.bat
36
- *.sh
37
-
38
- # Grunt
39
- node_modules
40
- Desktop.ini
41
-
42
- #codeception
43
- tests/codeception/_output
44
- tests/codeception/_support
45
- tests/codeception/_data
46
-
47
- #composer
48
- composer.lock
49
- vendor
50
- bin
51
-
52
- #phpstorm
53
- .idea
54
- /shared/assets/plugins/advanced-custom-fields/**.png
55
- /shared/assets/plugins/advanced-custom-fields/images/add-ons/**.jpg
56
- /shared/assets/plugins/advanced-custom-fields/lang/**.pot
57
- /shared/assets/plugins/advanced-custom-fields/lang/**.po
58
- /shared/assets/plugins/advanced-custom-fields/lang/**.mo
59
- /svn
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/Gruntfile.js DELETED
@@ -1,19 +0,0 @@
1
- /* for main build processes we use gulp see gulpfile.js */
2
- module.exports = function(grunt) {
3
-
4
- grunt.initConfig({
5
- pkg: grunt.file.readJSON('package.json'),
6
- wp_readme_to_markdown: {
7
- cta: {
8
- files: {
9
- 'readme.md': 'readme.txt'
10
- },
11
- },
12
- },
13
- });
14
-
15
- grunt.loadNpmTasks('grunt-wp-readme-to-markdown');
16
-
17
- grunt.registerTask('default', ['wp_readme_to_markdown']);
18
-
19
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/LICENSE DELETED
@@ -1,339 +0,0 @@
1
- GNU GENERAL PUBLIC LICENSE
2
- Version 2, June 1991
3
-
4
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
- Everyone is permitted to copy and distribute verbatim copies
7
- of this license document, but changing it is not allowed.
8
-
9
- Preamble
10
-
11
- The licenses for most software are designed to take away your
12
- freedom to share and change it. By contrast, the GNU General Public
13
- License is intended to guarantee your freedom to share and change free
14
- software--to make sure the software is free for all its users. This
15
- General Public License applies to most of the Free Software
16
- Foundation's software and to any other program whose authors commit to
17
- using it. (Some other Free Software Foundation software is covered by
18
- the GNU Lesser General Public License instead.) You can apply it to
19
- your programs, too.
20
-
21
- When we speak of free software, we are referring to freedom, not
22
- price. Our General Public Licenses are designed to make sure that you
23
- have the freedom to distribute copies of free software (and charge for
24
- this service if you wish), that you receive source code or can get it
25
- if you want it, that you can change the software or use pieces of it
26
- in new free programs; and that you know you can do these things.
27
-
28
- To protect your rights, we need to make restrictions that forbid
29
- anyone to deny you these rights or to ask you to surrender the rights.
30
- These restrictions translate to certain responsibilities for you if you
31
- distribute copies of the software, or if you modify it.
32
-
33
- For example, if you distribute copies of such a program, whether
34
- gratis or for a fee, you must give the recipients all the rights that
35
- you have. You must make sure that they, too, receive or can get the
36
- source code. And you must show them these terms so they know their
37
- rights.
38
-
39
- We protect your rights with two steps: (1) copyright the software, and
40
- (2) offer you this license which gives you legal permission to copy,
41
- distribute and/or modify the software.
42
-
43
- Also, for each author's protection and ours, we want to make certain
44
- that everyone understands that there is no warranty for this free
45
- software. If the software is modified by someone else and passed on, we
46
- want its recipients to know that what they have is not the original, so
47
- that any problems introduced by others will not reflect on the original
48
- authors' reputations.
49
-
50
- Finally, any free program is threatened constantly by software
51
- patents. We wish to avoid the danger that redistributors of a free
52
- program will individually obtain patent licenses, in effect making the
53
- program proprietary. To prevent this, we have made it clear that any
54
- patent must be licensed for everyone's free use or not licensed at all.
55
-
56
- The precise terms and conditions for copying, distribution and
57
- modification follow.
58
-
59
- GNU GENERAL PUBLIC LICENSE
60
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
-
62
- 0. This License applies to any program or other work which contains
63
- a notice placed by the copyright holder saying it may be distributed
64
- under the terms of this General Public License. The "Program", below,
65
- refers to any such program or work, and a "work based on the Program"
66
- means either the Program or any derivative work under copyright law:
67
- that is to say, a work containing the Program or a portion of it,
68
- either verbatim or with modifications and/or translated into another
69
- language. (Hereinafter, translation is included without limitation in
70
- the term "modification".) Each licensee is addressed as "you".
71
-
72
- Activities other than copying, distribution and modification are not
73
- covered by this License; they are outside its scope. The act of
74
- running the Program is not restricted, and the output from the Program
75
- is covered only if its contents constitute a work based on the
76
- Program (independent of having been made by running the Program).
77
- Whether that is true depends on what the Program does.
78
-
79
- 1. You may copy and distribute verbatim copies of the Program's
80
- source code as you receive it, in any medium, provided that you
81
- conspicuously and appropriately publish on each copy an appropriate
82
- copyright notice and disclaimer of warranty; keep intact all the
83
- notices that refer to this License and to the absence of any warranty;
84
- and give any other recipients of the Program a copy of this License
85
- along with the Program.
86
-
87
- You may charge a fee for the physical act of transferring a copy, and
88
- you may at your option offer warranty protection in exchange for a fee.
89
-
90
- 2. You may modify your copy or copies of the Program or any portion
91
- of it, thus forming a work based on the Program, and copy and
92
- distribute such modifications or work under the terms of Section 1
93
- above, provided that you also meet all of these conditions:
94
-
95
- a) You must cause the modified files to carry prominent notices
96
- stating that you changed the files and the date of any change.
97
-
98
- b) You must cause any work that you distribute or publish, that in
99
- whole or in part contains or is derived from the Program or any
100
- part thereof, to be licensed as a whole at no charge to all third
101
- parties under the terms of this License.
102
-
103
- c) If the modified program normally reads commands interactively
104
- when run, you must cause it, when started running for such
105
- interactive use in the most ordinary way, to print or display an
106
- announcement including an appropriate copyright notice and a
107
- notice that there is no warranty (or else, saying that you provide
108
- a warranty) and that users may redistribute the program under
109
- these conditions, and telling the user how to view a copy of this
110
- License. (Exception: if the Program itself is interactive but
111
- does not normally print such an announcement, your work based on
112
- the Program is not required to print an announcement.)
113
-
114
- These requirements apply to the modified work as a whole. If
115
- identifiable sections of that work are not derived from the Program,
116
- and can be reasonably considered independent and separate works in
117
- themselves, then this License, and its terms, do not apply to those
118
- sections when you distribute them as separate works. But when you
119
- distribute the same sections as part of a whole which is a work based
120
- on the Program, the distribution of the whole must be on the terms of
121
- this License, whose permissions for other licensees extend to the
122
- entire whole, and thus to each and every part regardless of who wrote it.
123
-
124
- Thus, it is not the intent of this section to claim rights or contest
125
- your rights to work written entirely by you; rather, the intent is to
126
- exercise the right to control the distribution of derivative or
127
- collective works based on the Program.
128
-
129
- In addition, mere aggregation of another work not based on the Program
130
- with the Program (or with a work based on the Program) on a volume of
131
- a storage or distribution medium does not bring the other work under
132
- the scope of this License.
133
-
134
- 3. You may copy and distribute the Program (or a work based on it,
135
- under Section 2) in object code or executable form under the terms of
136
- Sections 1 and 2 above provided that you also do one of the following:
137
-
138
- a) Accompany it with the complete corresponding machine-readable
139
- source code, which must be distributed under the terms of Sections
140
- 1 and 2 above on a medium customarily used for software interchange; or,
141
-
142
- b) Accompany it with a written offer, valid for at least three
143
- years, to give any third party, for a charge no more than your
144
- cost of physically performing source distribution, a complete
145
- machine-readable copy of the corresponding source code, to be
146
- distributed under the terms of Sections 1 and 2 above on a medium
147
- customarily used for software interchange; or,
148
-
149
- c) Accompany it with the information you received as to the offer
150
- to distribute corresponding source code. (This alternative is
151
- allowed only for noncommercial distribution and only if you
152
- received the program in object code or executable form with such
153
- an offer, in accord with Subsection b above.)
154
-
155
- The source code for a work means the preferred form of the work for
156
- making modifications to it. For an executable work, complete source
157
- code means all the source code for all modules it contains, plus any
158
- associated interface definition files, plus the scripts used to
159
- control compilation and installation of the executable. However, as a
160
- special exception, the source code distributed need not include
161
- anything that is normally distributed (in either source or binary
162
- form) with the major components (compiler, kernel, and so on) of the
163
- operating system on which the executable runs, unless that component
164
- itself accompanies the executable.
165
-
166
- If distribution of executable or object code is made by offering
167
- access to copy from a designated place, then offering equivalent
168
- access to copy the source code from the same place counts as
169
- distribution of the source code, even though third parties are not
170
- compelled to copy the source along with the object code.
171
-
172
- 4. You may not copy, modify, sublicense, or distribute the Program
173
- except as expressly provided under this License. Any attempt
174
- otherwise to copy, modify, sublicense or distribute the Program is
175
- void, and will automatically terminate your rights under this License.
176
- However, parties who have received copies, or rights, from you under
177
- this License will not have their licenses terminated so long as such
178
- parties remain in full compliance.
179
-
180
- 5. You are not required to accept this License, since you have not
181
- signed it. However, nothing else grants you permission to modify or
182
- distribute the Program or its derivative works. These actions are
183
- prohibited by law if you do not accept this License. Therefore, by
184
- modifying or distributing the Program (or any work based on the
185
- Program), you indicate your acceptance of this License to do so, and
186
- all its terms and conditions for copying, distributing or modifying
187
- the Program or works based on it.
188
-
189
- 6. Each time you redistribute the Program (or any work based on the
190
- Program), the recipient automatically receives a license from the
191
- original licensor to copy, distribute or modify the Program subject to
192
- these terms and conditions. You may not impose any further
193
- restrictions on the recipients' exercise of the rights granted herein.
194
- You are not responsible for enforcing compliance by third parties to
195
- this License.
196
-
197
- 7. If, as a consequence of a court judgment or allegation of patent
198
- infringement or for any other reason (not limited to patent issues),
199
- conditions are imposed on you (whether by court order, agreement or
200
- otherwise) that contradict the conditions of this License, they do not
201
- excuse you from the conditions of this License. If you cannot
202
- distribute so as to satisfy simultaneously your obligations under this
203
- License and any other pertinent obligations, then as a consequence you
204
- may not distribute the Program at all. For example, if a patent
205
- license would not permit royalty-free redistribution of the Program by
206
- all those who receive copies directly or indirectly through you, then
207
- the only way you could satisfy both it and this License would be to
208
- refrain entirely from distribution of the Program.
209
-
210
- If any portion of this section is held invalid or unenforceable under
211
- any particular circumstance, the balance of the section is intended to
212
- apply and the section as a whole is intended to apply in other
213
- circumstances.
214
-
215
- It is not the purpose of this section to induce you to infringe any
216
- patents or other property right claims or to contest validity of any
217
- such claims; this section has the sole purpose of protecting the
218
- integrity of the free software distribution system, which is
219
- implemented by public license practices. Many people have made
220
- generous contributions to the wide range of software distributed
221
- through that system in reliance on consistent application of that
222
- system; it is up to the author/donor to decide if he or she is willing
223
- to distribute software through any other system and a licensee cannot
224
- impose that choice.
225
-
226
- This section is intended to make thoroughly clear what is believed to
227
- be a consequence of the rest of this License.
228
-
229
- 8. If the distribution and/or use of the Program is restricted in
230
- certain countries either by patents or by copyrighted interfaces, the
231
- original copyright holder who places the Program under this License
232
- may add an explicit geographical distribution limitation excluding
233
- those countries, so that distribution is permitted only in or among
234
- countries not thus excluded. In such case, this License incorporates
235
- the limitation as if written in the body of this License.
236
-
237
- 9. The Free Software Foundation may publish revised and/or new versions
238
- of the General Public License from time to time. Such new versions will
239
- be similar in spirit to the present version, but may differ in detail to
240
- address new problems or concerns.
241
-
242
- Each version is given a distinguishing version number. If the Program
243
- specifies a version number of this License which applies to it and "any
244
- later version", you have the option of following the terms and conditions
245
- either of that version or of any later version published by the Free
246
- Software Foundation. If the Program does not specify a version number of
247
- this License, you may choose any version ever published by the Free Software
248
- Foundation.
249
-
250
- 10. If you wish to incorporate parts of the Program into other free
251
- programs whose distribution conditions are different, write to the author
252
- to ask for permission. For software which is copyrighted by the Free
253
- Software Foundation, write to the Free Software Foundation; we sometimes
254
- make exceptions for this. Our decision will be guided by the two goals
255
- of preserving the free status of all derivatives of our free software and
256
- of promoting the sharing and reuse of software generally.
257
-
258
- NO WARRANTY
259
-
260
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
- FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
- OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
- PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
- OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
- TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
- PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
- REPAIR OR CORRECTION.
269
-
270
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
- WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
- REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
- INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
- OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
- TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
- YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
- PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
- POSSIBILITY OF SUCH DAMAGES.
279
-
280
- END OF TERMS AND CONDITIONS
281
-
282
- How to Apply These Terms to Your New Programs
283
-
284
- If you develop a new program, and you want it to be of the greatest
285
- possible use to the public, the best way to achieve this is to make it
286
- free software which everyone can redistribute and change under these terms.
287
-
288
- To do so, attach the following notices to the program. It is safest
289
- to attach them to the start of each source file to most effectively
290
- convey the exclusion of warranty; and each file should have at least
291
- the "copyright" line and a pointer to where the full notice is found.
292
-
293
- WordPress Landing Pages
294
- Copyright (C) 2013 Inbound Now
295
-
296
- This program is free software; you can redistribute it and/or modify
297
- it under the terms of the GNU General Public License as published by
298
- the Free Software Foundation; either version 2 of the License, or
299
- (at your option) any later version.
300
-
301
- This program is distributed in the hope that it will be useful,
302
- but WITHOUT ANY WARRANTY; without even the implied warranty of
303
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
- GNU General Public License for more details.
305
-
306
- You should have received a copy of the GNU General Public License along
307
- with this program; if not, write to the Free Software Foundation, Inc.,
308
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
-
310
- Also add information on how to contact you by electronic and paper mail.
311
-
312
- If the program is interactive, make it output a short notice like this
313
- when it starts in an interactive mode:
314
-
315
- Gnomovision version 69, Copyright (C) year name of author
316
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
- This is free software, and you are welcome to redistribute it
318
- under certain conditions; type `show c' for details.
319
-
320
- The hypothetical commands `show w' and `show c' should show the appropriate
321
- parts of the General Public License. Of course, the commands you use may
322
- be called something other than `show w' and `show c'; they could even be
323
- mouse-clicks or menu items--whatever suits your program.
324
-
325
- You should also get your employer (if you work as a programmer) or your
326
- school, if any, to sign a "copyright disclaimer" for the program, if
327
- necessary. Here is a sample; alter the names:
328
-
329
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
-
332
- {signature of Ty Coon}, 1 April 1989
333
- Ty Coon, President of Vice
334
-
335
- This General Public License does not permit incorporating your program into
336
- proprietary programs. If your program is a subroutine library, you may
337
- consider it more useful to permit linking proprietary applications with the
338
- library. If this is what you want to do, use the GNU Lesser General
339
- Public License instead of this License.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/README.md DELETED
@@ -1,359 +0,0 @@
1
- ![](https://travis-ci.org/inboundnow/landing-pages.svg?branch=master)
2
-
3
- # WordPress Landing Pages #
4
-
5
- **Contributors:** David Wells, Hudson Atwell
6
- **Donate link:** mailto:marketplace@inboundnow.com
7
- **License:** GPLv2 or later
8
- **License URI:** http://www.gnu.org/licenses/gpl-2.0.html
9
- **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
10
- **Requires at least:** 3.8
11
- **Tested up to:** 4.1
12
- **Stable Tag:** 1.8.0
13
-
14
- Create landing pages for your WordPress site. Monitor and improve conversion rates, run A/B split tests, customize your own templates and more.
15
-
16
- ## Description ##
17
-
18
- > 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.
19
-
20
- 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!
21
-
22
- 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.
23
-
24
- Landing pages are an ideal way to convert more of your passive website visitors into active leads or email list subscribers.
25
-
26
- ### Highlights ###
27
-
28
- * Create beautiful Landing Pages on your WordPress site.
29
- * Visual Editor to view changes being made on the fly!
30
- * Track conversion rates on your landing pages for continual optimization.
31
- * Easily clone existing landing pages and run A/B Split tests on variations.
32
- * Use your current WordPress theme or choose from our library of custom landing page designs.
33
- * Pre-populate Forms with visitor information to increase conversion rates
34
- * Gather lead intelligence and track lead activity with <a href="http://wordpress.org/plugins/leads/screenshots/">WordPress Leads</a>
35
- * Extend functionality with our growing repository of <a href="http://www.inboundnow.com/market/category/landing-pages/extensions/">third party add ons</a>.
36
- * Easily implement your own custom landing page design.
37
-
38
- This plugin is form agnostic meaning it will work with any form system you use.
39
-
40
- Recommended form plugins (Gravity forms, Ninja Forms or Contact form 7)
41
-
42
- ### About the Plugin ###
43
-
44
- http://www.youtube.com/watch?v=flEd0sRTFUo
45
-
46
- ### Developers & Designers ###
47
-
48
- 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.
49
-
50
- You can quickly take your existing designs and implement them using our <a href="http://docs.inboundnow.com/section/developer/">templating framework</a>.
51
-
52
- 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.
53
-
54
-
55
- [Follow Development on GitHub ](https://github.com/inboundnow/landing-pages "Follow & Contribute to core development on GitHub")
56
- |
57
- [Follow Development on Twitter ](https://twitter.com/gitlandingpages "See our latest development commits on Twitter")
58
-
59
-
60
- ## Installation ##
61
-
62
- 1. Upload `landing-pages` folder to the `/wp-content/plugins/` directory
63
- 1. Activate the plugin through the 'Plugins' menu in WordPress
64
-
65
- ## Frequently Asked Questions ##
66
- *Can I create my own landing page designs?,
67
- *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>.
68
-
69
- ## Screenshots ##
70
-
71
- ### 1. Landing Page Custom Post Type ###
72
- ![Landing Page Custom Post Type](screenshot-1.jpg)
73
-
74
- ### 2. Track conversion rates and continuously improve your landing pages ###
75
- ![Track conversion rates and continuously improve your landing pages](screenshot-2.jpg)
76
-
77
- ### 3. Manage Split Testing Page ###
78
- ![Manage Split Testing Page](screenshot-3.jpg)
79
-
80
- ### 4. Choose from a ton of pre-made templates, use your existing design, or design your own theme! ###
81
- ![Choose from a ton of pre-made templates, use your existing design, or design your own theme!](screenshot-4.jpg)
82
-
83
-
84
- ## Changelog ##
85
- ### 1.8.0 ###
86
- * Fixing addon store
87
-
88
- ### 1.7.9 ###
89
- * Even more security updates! Security for the win!
90
-
91
- ### 1.7.8 ###
92
- * Security Patch
93
-
94
- ### 1.7.7 ###
95
- * Fix double lead notification email
96
-
97
- ### 1.7.6 ###
98
- * Fixed double email submission on contact form 7
99
-
100
- ### 1.7.5 ###
101
- * Added form field exclusions to ignore sensitive data
102
-
103
- ### 1.7.3 ###
104
- * See changelog here: https://github.com/inboundnow/landing-pages/issues?q=is%3Aissue+is%3Aclosed+label%3Av1.7.3
105
-
106
- ### 1.7.2 ###
107
- * Improved form email typo detection
108
- * Improved Template Styles
109
- * Fixed content wysiwyg scroll freezing bug
110
-
111
- ### 1.7.1 ###
112
- * removed iframe of inbound now addon store. For addons please visit: http://inboundnow.com/market
113
-
114
- ### 1.7.0 ###
115
- * Removed anonymous PHP functions for PHP 5.2 support
116
- * Updated template creation standards
117
- * Converted varition modules to CLASS based system & documented
118
- * Move /lang/ file outside of shared
119
-
120
- ### 1.6.2 ###
121
- * Bug Fix: Fix with lead email notifications
122
-
123
- ### 1.5.9 ###
124
- * Various bug fixes.
125
- * Refactored main plugin file to class loader.
126
- * Improved localization systems.
127
-
128
- ### 1.5.8 ###
129
- * Bug Fix: Check all required fields
130
-
131
- ### 1.5.7 ###
132
- * Improvement: All core template now use new consolidated settings system.
133
- * Improvement: Leads Dashboard styling & stats
134
- * Improvement: Screenshots on local installation replaced with template thumbnails.
135
-
136
-
137
- ### 1.5.6 ###
138
- * Fix to insert marketing shortcode popup
139
-
140
- ### 1.5.5 ###
141
- * Added events to lead tracking
142
- * Bug Fix: Marketing Button
143
- * Optimized CTA Tracking JS.
144
- * Expanded impression/conversion analytics to all post types.
145
-
146
- ### 1.5.4 ###
147
- * Impression tracking bug fix.
148
- * Bringing Inbound Tracking to All Posts/Pages
149
-
150
- ### 1.5.3 ###
151
- * Temporary fix for shortcodes disappearing from wordpress 3.8 to 3.9
152
- * Performance improvements on analytics and lead tracking
153
-
154
- ### 1.5.1 ###
155
- * Misc bug fixes
156
-
157
- ### 1.5.0 ###
158
- * fixed field mapping bug
159
- * Added better compability for js conflicts
160
- * Prepping for marketing automation
161
-
162
- ### 1.4.9 ###
163
- * Fixed and improved default landing page templates
164
- * Updates to work with V2 of the CTA plugins
165
- * Improved form compatibilty with contact form 7, gravity forms, and ninja forms
166
- * Numerous bug files and code improvements
167
-
168
- ### 1.4.8 ###
169
- * Added Google Analytics Custom Event Tracking for form submissions
170
- * Added Ability: automatically sort leads into lists on form completions
171
- * Added Ability: Send lead notification emails to multiple people. Use comma separated values
172
- * Improved Social Media Buttons called with lp_social_media() function
173
- * Fixed qTranslate plugin bug
174
- * Fixed Genesis Title tag conflict
175
- * Added improved asset loader
176
- * Updated main docs.inboundnow.com site. Check it out!
177
-
178
- ### 1.4.7 ###
179
- * GPL fix with js library
180
-
181
- ### 1.4.6 ###
182
- * New Feature: Bulk Lead management with leads plugin wordpress.org/plugins/leads/
183
- * Added tags to lead profiles for improved management/categorization
184
- * Added new compatibility options to fix third party plugin conflicts!
185
- * Added new debugging javascript debugging tools for users
186
- * Fixed Email Sending Error on forms
187
- * Improved support for master license keys
188
-
189
- ### 1.4.5 ###
190
- * Added New HTML Lead Email Template with clickable links for faster lead management
191
- * Added Button Shortcodes!
192
- * Added HTML field option to form tool
193
- * Added Divider Option to Form tool
194
- * Added multi column support to icon list shortcode
195
- * Added Font Awesome Icons option to Inbound Form Submit buttons
196
- * Added Social Sharing Shortcode
197
- * Bug fix - emails not sending after form conversion fixed
198
-
199
- ### 1.4.1 ###
200
- * Bug fix - missing trackingObj
201
-
202
- ### 1.4.0 ###
203
- * Added feature request form to all plugin admin pages. Submit your feature requests today! =)
204
-
205
- ### 1.3.9 ###
206
- * Bug fixes for form creation issues
207
- * Bug fixes for safari page tracking not firing
208
- * Added quick menu to WP admin bar for quicker marketing!
209
-
210
- ### 1.3.8 ###
211
- * Updated styles to 3.8 wordpress
212
- * Streamlined form creation
213
- * fixed rogue PHP errors
214
-
215
- ### 1.3.7 ###
216
- * Added: Shortcode now automatically render in landing page option echos in templates
217
- * Updated: Visual Editor tool
218
- * Updated: Template selection interface
219
- * Updated: Major updates to core templates, CSS tweaks and fixes
220
- * Fixed: Shortcode insert into correct editor box
221
- * Fixed: editor always on HTML view
222
-
223
- ### 1.3.6 ###
224
-
225
- * Added: New Shortcodes! Fancy List and Column shortcodes
226
- * Added: Added email confirmation support to Inbound Forms tool
227
- * Added: Added New Welcome Page with Tutorial Video on Getting Started
228
- * Added: New Debug Tab for faster support requests/debugging
229
- * Fixed: CSS conflicts with button classes
230
-
231
- ### 1.3.1 ###
232
-
233
- * Added: Added InboundNow form creation and management system (beta)
234
- * Added: Support for InboundNow cross plugin extensions
235
- * Added: 'Sticky Variations' to global settings.
236
- * Added: Easier way for extension developers to license their extensions.
237
- * Added: 'header' setting component to global settings.
238
- * Fixed: Security issues
239
- * Improvement: Improved data management for global settings, metaboxes, and extensions.
240
-
241
- ### 1.2.3 ###
242
-
243
- * Fixed: Security issue with vulnerability to sql injection.
244
-
245
- ### 1.2.1 ###
246
-
247
- * Fixed: Issues with shortcodes rendering in wp-admin for variations.
248
-
249
- ### 1.1.9 ###
250
-
251
- * Fixed: Issues with navigation menu items breaking on landing pages with the default template selected.
252
-
253
- ### 1.1.8 ###
254
-
255
- * Fixed: Issue with post_content not saving for variations.
256
- * Added: [lp_conversion_area] Shortcode. It renders form conversion area anywhere on landing page
257
- * Fixed: Restored the ability to delete custom templates from 'Templates' section.
258
-
259
- ### 1.1.7 ###
260
-
261
- * Fixed: Issue with extension license keys not validating
262
- * Fixed: Issue with shortcodes not firing on select core templates
263
- * Improvement: Converted global settings data array to new easier to read format for development, added in legacy support.
264
-
265
- ### 1.1.0.1 ###
266
-
267
- * Fixed: Variation saves for custom css and custom js.
268
- * Fixed: jQuery error related to wysiwyg content formatting.
269
-
270
- ### 1.0.9.9 ###
271
- * Improved extension metabox loading for quicker load times and optimized meta data storage.
272
- * Phased out more 'old method' split testing components.
273
- * Improved .htaccess parsing.
274
- * Addressed issue with line breaks being removed from WYSIWYG editors.
275
-
276
- ### 1.0.9.4 ###
277
- * Added in tours for the edit screen and the list of landing page screen for new users to learn how to use the tool quickly and easily
278
- * Updated conversion tracking for wp-leads addon plugin
279
- * Added in option for default templates to toggle on/off navigation
280
-
281
- ### 1.0.9.3 ###
282
-
283
- * Removed old A/B split testing and the new system is fully in place!
284
-
285
- ### 1.0.9.0 ###
286
-
287
- * Added in A/B stats to the main landing page list view
288
-
289
- ### 1.0.8.6 ###
290
-
291
- * Release new and improved version of A/B testing!
292
- * Ajax saving on landing page options for faster page edits
293
- * Frontend Visual Editor to see what you are editing/changing
294
- * Enabled frontend editor for use on normal pages and posts
295
-
296
- ### 1.0.8.5 ###
297
-
298
- Providing better conversion and impression tracking for landing pages that are set as homepage.
299
-
300
- ### 1.0.8.4 ###
301
-
302
- Fixing activation bug
303
-
304
- ### 1.0.8.1 ###
305
-
306
- Fixing issue with jquery submission errors.
307
-
308
- ### 1.0.7.9 ###
309
-
310
- Added capability to activate and update license keys for premium extensions. Added ability to define white listed HTML elements for Form Standardization process.
311
-
312
- ### 1.0.7.3 ###
313
-
314
- Fixed issue with WP_List_table causing posts to to save or edit propperly Attempt 001
315
-
316
- ### 1.0.7.1 ###
317
-
318
- Added cookie based auto-field population & lead data collection to core.
319
-
320
- ### 1.0.5.6 ###
321
-
322
- Fixed issue with global setting's radio buttons not holding new set values.
323
-
324
- ### 1.0.5.3 ###
325
-
326
- Solutions for custom post type wp rewrite issue on activation.
327
-
328
- ### 1.0.5.1 ###
329
-
330
- Introducing version control system for extensions.
331
-
332
- ### 1.0.4.4 ###
333
-
334
- Migrating store to new location. Updating version control systems
335
-
336
- ### 1.0.4.2 ###
337
-
338
- Added new defitions to form standardization parser. Limited .htaccess rewrites to plugin activation to try and mitigate .htaccess corruptions.
339
-
340
- ### 1.0.4.1 ###
341
-
342
- Fixed issue with conversions not recording on some servers by forcing form submittal to wait until ajax has completely finnished loading before continuing to process form.
343
-
344
- ### 1.0.3.9 ###
345
-
346
- Fixed issue with plugins and wp core refusing to update on some installations when landing page plugin is activated.
347
-
348
- ### 1.0.3.8 ###
349
-
350
- Debugging cross browser impressions and conversion tracking. Implemented soltion for url-to-postid conversions that's compatible with the /slug/ removal extension for landing pages plugin.
351
- Added email validation check to prevent false positives when form standardization is turned on.
352
-
353
- ### 1.0.3.7 ###
354
-
355
- **Bug Fix:** 'Clear Stats' button.
356
-
357
- ### 1.1 ###
358
-
359
- Released
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 .bab-stat-control-pause, .variation-on .bab-stat-control-play, .variation-off .pause-sep,.variation-on .play-sep, .variation-on .is-paused{
48
- display: none;
49
- }
50
- .bab-stat-control-container {
51
-
52
- bottom: 0px;
53
- left: 0px;
54
- }
55
- .bab-stat-control-container:hover {
56
-
57
- bottom: 0px;
58
- left: 0px;
59
- display: block;
60
- }
61
- .bab-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
- .bab-variation-row:last-child {
71
- margin-bottom: 0px;
72
- }
73
- .bab-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
- .bab-stat-control-container span {
82
- vertical-align: bottom;
83
- display: inline-block;
84
- }
85
- .bab-stat-seperator {
86
- padding-left: 3px;
87
- padding-right: 3px;
88
- font-size: 0px;
89
- }
90
- .variation-on .bab-stat-control-pause a {
91
- color: red;
92
- font-weight: bold;
93
- }
94
- .variation-off .bab-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 .bab-stat-control-play a {
104
- color: green;
105
- font-weight: bold;
106
- }
107
- .variation-off .bab-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
- .bab-stat-letter {
136
- border-radius: 3px;
137
- border-style:solid;
138
- border-width:1px;
139
- padding:2px;
140
- }
141
-
142
- .bab-stat-container-conversions, .bab-stat-container-impressions, .bab-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 .bab-varation-header{
255
- font-size: 14px;
256
- font-weight: normal;
257
- color: #000;
258
- padding-left: 18px !important;
259
- }
260
- .bab-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
- .bab-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
- .bab-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
- .bab-stat-control-play a:before{
302
- }
303
- #wpbody .bab-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
- #bab-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
- #bab-stat-box:last-child {
18
- margin-bottom: 0px;
19
- }
20
- .bab-number-box
21
- {
22
- background: transparent;
23
- display: inline-block;
24
- width: 31%;
25
- padding-top: 15px
26
- }
27
- .bab-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
- .bab-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
- .bab-stat-control-container
50
- {
51
- text-align: center;
52
- padding: 5px;
53
- }
54
-
55
- .bab-variation-row
56
- {
57
- display: block;
58
- }
59
-
60
- .bab-stat-letter
61
- {
62
- background: #fff;
63
- padding-top: 0px;
64
- padding-bottom: 0px;
65
- }
66
-
67
- .bab-notes
68
- {
69
- float: right;
70
- font-size: 12px;
71
- font-weight: normal;
72
- }
73
-
74
- .bab-number-box span.bab-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
- .bab-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, #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,108 +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
- #post-body-content, .edit-form-section {
8
- margin-bottom: 0px;
9
- }
10
-
11
- #main-title-header h3 {
12
- display: inline-block;
13
- padding-left: 0px;
14
- }
15
- #titlediv {
16
- margin-bottom: 0px;
17
- }
18
- #TB_window {
19
- z-index: 999999999999;
20
- }
21
- .currently_selected{
22
- position: absolute;
23
- top: 72px;
24
- left: 16px;
25
- font-size: 19px;
26
- line-height: 21px;
27
- padding-top: 15px;
28
- text-align: center;
29
- background: black;
30
- width: 90%;
31
- height: 36px;
32
- color: white;
33
- opacity: 0.5;
34
- border-radius: 7px;
35
- }
36
- .lp-template-selector-container ul#template-filter li {
37
- display: inline-block;
38
-
39
- margin-right: 5px;
40
- text-align: center;
41
- margin-bottom: 10px;
42
- }
43
- .lp-template-selector-container ul#template-filter {
44
- margin-bottom: 10px;
45
- }
46
- .lp-template-selector-container ul#template-filter {
47
- line-height: 30px;
48
- margin-top: 10px;
49
- margin-bottom: 0px;
50
- }
51
- .lp-template-selector-container ul#template-filter a {
52
- margin-right: 0px;
53
- padding: 0px;
54
- font-weight: bold;
55
- text-decoration: none;
56
- }
57
- ul#template-filter .button-primary a {
58
- color:#fff;
59
- }
60
- #more-templates-button {
61
- display: inline-block;
62
- vertical-align: middle;
63
- float: none !important;
64
- font-weight: normal;
65
- font-size: 20px;
66
- }
67
- #more-templates-button a {
68
- font-size: 15px;
69
- }
70
- #lp_2_form_content {
71
- margin-top:20px;
72
- }
73
- #lp_2_form_content .hndle em {
74
- font-size: 13px;
75
- }
76
- .template-thumbnail
77
- {
78
- width:100%;
79
- height:190px;
80
- -webkit-border-radius: 4px;
81
- -khtml-border-radius: 4px;
82
- -moz-border-radius: 4px;
83
- border-radius: 4px;
84
- background-color: #A9A9A9;
85
- -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 0 0 1px,rgba(0, 0, 0, 0.3) 0 2px 5px;
86
- -moz-box-shadow: rgba(0,0,0,0.2) 0 0 0 1px,rgba(0,0,0,0.3) 0 2px 5px;
87
- box-shadow: rgba(0, 0, 0, 0.2) 0 0 0 1px,rgba(0, 0, 0, 0.3) 0 2px 5px;
88
- }
89
-
90
- ul#template-filter{ margin: 0px 0; padding: 0; padding-left: 0px; line-height: 64px; }
91
- ul#template-filter li{ display: inline; }
92
- ul#template-filter a{ margin-right: 0.5em; padding: 0em 1em; font-weight: bold; text-decoration: none; }
93
- ul#template-filter .button-primary a:hover { color:#fff;}
94
- ul#template-filter a.current{ background-color: #DDD; }
95
-
96
- #template-item{ float: left; margin-right: 18px; overflow: hidden; margin: 0px 0 0 0; padding: 0; list-style: none; width: 300px; margin-bottom: 10px; }
97
- #template-item div{ display: block; }
98
- /* #template-item div a{ display: block; width: 163px; height: 120px; overflow: hidden; border: 1px solid #CDCDCD; background: #eee; }*/
99
- #template-item li p{ font-size: 11px; line-height: 15px; color: #AAA; margin: 5px 0; }
100
- #template-box .lp_tooltip_templates{
101
- bottom: 6px;
102
- position: absolute;
103
- right: 8px;
104
- }
105
-
106
- .lp_tooltip {
107
- display:inline;
108
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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,322 +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
-
172
- /* the_content default overwrite */
173
- jQuery('body').on('click', '#overwrite-content', function () {
174
- if (confirm('Are you sure you want to overwrite what is currently in the main edit box above?')) {
175
- var ctmce = jQuery('#content-tmce');
176
- switchEditors.switchto(ctmce[0]); // switch to tinymce
177
- setTimeout(function () {
178
- var default_content = jQuery(".inbound-default-content-option textarea").first().text();
179
- jQuery("#content_ifr").contents().find("body").html(default_content);
180
- }, 500);
181
-
182
- }
183
- });
184
-
185
- /* Colorpicker fix */
186
- jQuery('.jpicker').one('mouseenter', function () {
187
- jQuery(this).jPicker({
188
- window: // used to define the position of the popup window only useful in binded mode
189
- {
190
- title: null, // any title for the jPicker window itself - displays "Drag Markers To Pick A Color" if left null
191
- position: {
192
- x: 'screenCenter', // acceptable values "left", "center", "right", "screenCenter", or relative px value
193
- y: 'center', // acceptable values "top", "bottom", "center", or relative px value
194
- },
195
- expandable: false, // default to large static picker - set to true to make an expandable picker (small icon with popup) - set
196
- // automatically when binded to input element
197
- liveUpdate: true, // set false if you want the user to click "OK" before the binded input box updates values (always "true"
198
- // for expandable picker)
199
- alphaSupport: false, // set to true to enable alpha picking
200
- alphaPrecision: 0, // set decimal precision for alpha percentage display - hex codes do not map directly to percentage
201
- // integers - range 0-2
202
- updateInputColor: true // set to false to prevent binded input colors from changing
203
- }
204
- },
205
- function (color, context) {
206
- var all = color.val('all');
207
- // alert('Color chosen - hex: ' + (all && '#' + all.hex || 'none') + ' - alpha: ' + (all && all.a + '%' || 'none'));
208
- //jQuery(this).attr('rel', all.hex);
209
-
210
- jQuery(this).parent().find(".lp-success-message").remove();
211
- //jQuery(this).parent().find(".new-save-lp").show();
212
- //jQuery(this).parent().find(".new-save-lp-frontend").show();
213
- //jQuery(this).attr('value', all.hex);
214
- });
215
- });
216
-
217
-
218
- if (jQuery(".lp-template-selector-container").css("display") == "none") {
219
- jQuery(".currently_selected").hide();
220
- } else {
221
- jQuery(".currently_selected").show();
222
- }
223
-
224
- /* Add current title of template to selector */
225
- var selected_template = jQuery('#lp_select_template').val();
226
- var selected_template_id = "#" + selected_template;
227
- var clean_template_name = selected_template.replace(/-/g, ' ');
228
-
229
- function capitaliseFirstLetter(string) {
230
- return string.charAt(0).toUpperCase() + string.slice(1);
231
- }
232
-
233
- var currentlabel = jQuery(".currently_selected");
234
- jQuery(selected_template_id).parent().addClass("default_template_highlight").prepend(currentlabel);
235
-
236
- jQuery('#lp-change-template-button').live('click', function () {
237
- jQuery('.acf-postbox').remove();
238
- jQuery(".wrap").fadeOut(500, function () {
239
-
240
- jQuery(".lp-template-selector-container").fadeIn(500, function () {
241
- jQuery(".currently_selected").show();
242
- jQuery('#lp-cancel-selection').show();
243
- });
244
-
245
- });
246
- });
247
-
248
-
249
- jQuery('.background-style').on('change', function () {
250
- var input = jQuery(".background-style option:selected").val();
251
- if (input == 'color') {
252
- jQuery('.background-color').show();
253
- jQuery('.background-image').hide();
254
- jQuery('.background_tip').hide();
255
- }
256
- else if (input == 'default') {
257
- jQuery('.background-color').hide();
258
- jQuery('.background-image').hide();
259
- jQuery('.background_tip').hide();
260
- }
261
- else if (input == 'custom') {
262
- var obj = jQuery(".background-style .lp_tooltip");
263
- 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");
264
- jQuery('.background_tip').show();
265
- }
266
- else {
267
- jQuery('.background-color').hide();
268
- jQuery('.background-image').show();
269
- jQuery('.background_tip').hide();
270
- }
271
-
272
- });
273
-
274
- /* Check BG options on page load */
275
- jQuery(document).ready(function () {
276
- var input = jQuery(".background-style option:selected").val();
277
- if (input == 'color') {
278
- jQuery('.background-color').show();
279
- jQuery('.background-image').hide();
280
- jQuery('.background_tip').hide();
281
- }
282
- else if (input == 'default') {
283
- jQuery('.background-color').hide();
284
- jQuery('.background-image').hide();
285
- jQuery('.background_tip').hide();
286
- }
287
- else if (input == 'custom') {
288
- var obj = jQuery(".background-style .lp_tooltip");
289
- 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");
290
- jQuery('.background_tip').show();
291
- }
292
- else {
293
- jQuery('.background-color').hide();
294
- jQuery('.background-image').show();
295
- jQuery('.background_tip').hide();
296
- }
297
- });
298
-
299
- /* Stylize lead's wp-list-table */
300
- var cnt = $("#leads-table-container").contents();
301
- $("#lp_conversion_log_metabox").replaceWith(cnt);
302
-
303
- /* remove inputs from wp-list-table */
304
- jQuery('#leads-table-container-inside input').each(function () {
305
- jQuery(this).remove();
306
- });
307
-
308
- var post_status = jQuery("#original_post_status").val();
309
-
310
- if (post_status === "draft") {
311
- jQuery(".new-save-lp-frontend").on("click", function (event) {
312
- event.preventDefault();
313
- alert("Must publish this page before you can use the visual editor!");
314
- });
315
- var subbox = jQuery("#submitdiv");
316
- jQuery("#lp_ab_display_stats_metabox").before(subbox)
317
- } else {
318
- jQuery("#publish").val("Update All");
319
- }
320
-
321
-
322
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Additional Templates</h3><a target='_blank' href='http://www.inboundnow.com/market/?show=landing-pages'><img src='"+lp_post_new_ui.LANDINGPAGES_URLPATH+"assets/images/get-wordpress-templates.png'></a><a target='_blank' href='http://www.inboundnow.com/market/?show=landing-pages' class='button new-lp-button button-primary button-large'>Download Landing Page Templates</a></center></div><div class='postbox'><center><h3>Need Custom Template Design?</h3><a target='_blank' href='http://www.inboundnow.com/contact'><img src='"+lp_post_new_ui.LANDINGPAGES_URLPATH+"assets/images/get-custom-setup.png'></a><a target='_blank' href='http://docs.inboundnow.com/guide/default-wp-themes/' class='button new-lp-button button-primary button-large'>Get Custom Template Setup</a></center></div>");
33
-
34
- jQuery('.lp_select_template').click(function(){
35
- jQuery(".mceIframeContainer iframe#content_ifr").css("height", "100%");
36
- jQuery("#wp-content-editor-container .mceStatusbar").css("display", "none");
37
- });
38
-
39
- jQuery('.lp_select_template').click(function(){
40
-
41
- var template = jQuery(this).attr('id');
42
- var selected_template_id = "#" + template;
43
- var label = jQuery(this).attr('label');
44
- var template_image = "#" + template + " .template-thumbnail";
45
- var template_img_obj = jQuery(template_image).attr("src");
46
-
47
- jQuery("#ctemp").text(label);
48
- jQuery("#template_current").html('<input type="hidden" name="lp-selected-template" value="'+template+'"><input type="hidden" value="1" name="lp_post_new">');
49
- jQuery("#timage #c_temp").attr("src", template_img_obj);
50
- jQuery("#submitdiv .hndle span").text("Create Landing Page");
51
-
52
- });
53
-
54
- jQuery('#lp-change-template-button').live('click', function () {
55
- jQuery(".wrap").fadeOut(500,function(){
56
-
57
- jQuery(".lp-template-selector-container").fadeIn(500, function(){
58
- jQuery('#lp-cancel-selection').show();
59
- });
60
- jQuery("#template-filter li a").first().click();
61
- });
62
- });
63
-
64
- // filter items when filter link is clicked
65
- jQuery('#template-filter a').click(function(){
66
- var selector = jQuery(this).attr('data-filter');
67
- jQuery("ul#template-filter li").removeClass('button-primary');
68
- jQuery(this).parent().addClass('button-primary');
69
- $(".template-item-boxes").fadeOut(500);
70
- setTimeout(function() {
71
- $(selector).fadeIn(500);
72
- }, 500);
73
-
74
- return false;
75
- });
76
-
77
- jQuery('.lp_select_template').click(function(){
78
- var template = jQuery(this).attr('id');
79
- var label = jQuery(this).attr('label');
80
- jQuery(".lp-template-selector-container").fadeOut(500,function(){
81
- jQuery(".wrap").fadeIn(500, function(){
82
- });
83
- });
84
-
85
- jQuery('#lp_metabox_select_template h3').html('Current Active Template: '+label);
86
- jQuery('#lp_select_template').val(template);
87
- //alert(template);
88
- //alert(label);
89
- });
90
-
91
-
92
- jQuery("#template-box a").live('click', function () {
93
-
94
- setTimeout(function() {
95
- jQuery('#TB_window iframe').contents().find("#customize-controls").hide();
96
- jQuery('#TB_window iframe').contents().find(".wp-full-overlay.expanded").css("margin-left", "0px");
97
- }, 1200);
98
-
99
- });
100
-
101
- // Fix Thickbox width
102
- jQuery(function($) {
103
- tb_position = function() {
104
- var tbWindow = $('#TB_window');
105
- var width = $(window).width();
106
- var H = $(window).height();
107
- var W = ( 1720 < width ) ? 1720 : width;
108
-
109
- if ( tbWindow.size() ) {
110
- tbWindow.width( W - 50 ).height( H - 45 );
111
- $('#TB_iframeContent').width( W - 50 ).height( H - 75 );
112
- tbWindow.css({'margin-left': '-' + parseInt((( W - 50 ) / 2),10) + 'px'});
113
- if ( typeof document.body.style.maxWidth != 'undefined' )
114
- tbWindow.css({'top':'40px','margin-top':'0'});
115
- //$('#TB_title').css({'background-color':'#fff','color':'#cfcfcf'});
116
- };
117
-
118
- return $('a.thickbox').each( function() {
119
- var href = $(this).attr('href');
120
- if ( ! href ) return;
121
- href = href.replace(/&width=[0-9]+/g, '');
122
- href = href.replace(/&height=[0-9]+/g, '');
123
- $(this).attr( 'href', href + '&width=' + ( W - 80 ) + '&height=' + ( H - 85 ) );
124
- });
125
- };
126
-
127
- jQuery('a.thickbox').click(function(){
128
- if ( typeof tinyMCE != 'undefined' && tinyMCE.activeEditor ) {
129
- tinyMCE.get('content').focus();
130
- tinyMCE.activeEditor.windowManager.bookmark = tinyMCE.activeEditor.selection.getBookmark('simple');
131
- }
132
-
133
- });
134
-
135
- $(window).resize( function() { tb_position() } );
136
- });
137
-
138
- var nonce_val = lp_post_new_ui.wp_landing_page_meta_nonce; // NEED CORRECT NONCE
139
-
140
- var nonce_html = '<input type="hidden" value="74910e3045" name="wp-landing-page-meta-nonce">';
141
-
142
- jQuery('form').prepend(nonce_html);
143
-
144
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/assets/js/admin/admin.post.js 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>If you <strong>hover over the letter</strong> you will be able to preview or jump directly to the edit screen of that particular variation.</p><p>You can also clear indiviudal variation stats from there.</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 = 'li[data-postid=' + post_id + '][data-letter=' + 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(".lp-impress-num, .lp-con-num").text("0");
52
  jQuery(selector).find(".cr-number").addClass("cr-empty-0").text("0%");
53
  jQuery(self).parent().parent().find('.bab-stat-span-impressions, .bab-stat-span-conversions').text("0");
54
  jQuery(self).parent().parent().find('.bab-stat-span-conversion_rate').text("0%");
55
  },
56
  error: function (MLHttpRequest, textStatus, errorThrown) {
57
  alert("Ajax not enabled");
58
  }
59
  });
60
  return false;
61
  }
62
  });
 
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 = 'li[data-postid=' + post_id + '][data-letter=' + 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(".lp-impress-num, .lp-con-num").text("0");
50
  jQuery(selector).find(".cr-number").addClass("cr-empty-0").text("0%");
51
  jQuery(self).parent().parent().find('.bab-stat-span-impressions, .bab-stat-span-conversions').text("0");
52
  jQuery(self).parent().parent().find('.bab-stat-span-conversion_rate').text("0%");
53
  },
54
  error: function (MLHttpRequest, textStatus, errorThrown) {
55
  alert("Ajax not enabled");
56
  }
57
  });
58
  return false;
59
  }
60
  });
trunk/assets/js/index.php 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/.tx/config DELETED
@@ -1,7 +0,0 @@
1
- [main]
2
- host = https://www.transifex.com
3
-
4
- [landing-pages.landing-pages]
5
- file_filter = <lang>.po
6
- source_lang = en_US
7
-
 
 
 
 
 
 
 
trunk/assets/lang/landing-pages-ach.mo DELETED
Binary file
trunk/assets/lang/landing-pages-af.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-as.mo DELETED
Binary file
trunk/assets/lang/landing-pages-az.mo DELETED
Binary file
trunk/assets/lang/landing-pages-be.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_BD.mo DELETED
Binary file
trunk/assets/lang/landing-pages-br.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-co.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cs_CZ.mo DELETED
Binary file
trunk/assets/lang/landing-pages-cy.mo DELETED
Binary file
trunk/assets/lang/landing-pages-da_DK.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-dv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-el.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en@pirate.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_AU.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_CA.mo DELETED
Binary file
trunk/assets/lang/landing-pages-en_GB.mo DELETED
Binary file
trunk/assets/lang/landing-pages-eo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_AR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_CL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_ES.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_MX.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_PE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-es_US.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-eu.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fa.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fa_IR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-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-fr_BE.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fr_FR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-fy.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ga.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gd.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gl_ES.mo DELETED
Binary file
trunk/assets/lang/landing-pages-gu_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-he_IL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hi_IN.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hr.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hu_HU.mo DELETED
Binary file
trunk/assets/lang/landing-pages-hy.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-is_IS.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-ja.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-kk.mo DELETED
Binary file
trunk/assets/lang/landing-pages-km.mo DELETED
Binary file
trunk/assets/lang/landing-pages-kn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ko_KR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ku.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ky.mo DELETED
Binary file
trunk/assets/lang/landing-pages-landing-pages - Copy.mo DELETED
Binary file
trunk/assets/lang/landing-pages-landing-pages.mo DELETED
Binary file
trunk/assets/lang/landing-pages-lo.mo DELETED
Binary file
trunk/assets/lang/landing-pages-lt_LT.mo DELETED
Binary file
trunk/assets/lang/landing-pages-lv.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mg.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mk_MK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mn.mo DELETED
Binary file
trunk/assets/lang/landing-pages-mr.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ms_MY.mo DELETED
Binary file
trunk/assets/lang/landing-pages-my_MM.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nb_NO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nds.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ne_NP.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nl.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nl_NL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-nn_NO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-oc.mo DELETED
Binary file
trunk/assets/lang/landing-pages-os.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pap.mo DELETED
Binary file
trunk/assets/lang/landing-pages-pl_PL.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ps.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-ro_RO.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ru_RU.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sah.mo DELETED
Binary file
trunk/assets/lang/landing-pages-si_LK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sk_SK.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sl_SI.mo DELETED
Binary file
trunk/assets/lang/landing-pages-so.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sq.mo DELETED
Binary file
trunk/assets/lang/landing-pages-sr_RS.mo DELETED
Binary file
trunk/assets/lang/landing-pages-su.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-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-tg.mo DELETED
Binary file
trunk/assets/lang/landing-pages-th.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-tr_TR.mo DELETED
Binary file
trunk/assets/lang/landing-pages-tzm.mo DELETED
Binary file
trunk/assets/lang/landing-pages-ug.mo DELETED
Binary file
trunk/assets/lang/landing-pages-uk.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-vi.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.mo DELETED
Binary file
trunk/assets/lang/landing-pages.mo DELETED
Binary file
trunk/assets/lang/landing-pages.po DELETED
@@ -1,22 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: Landing Pages\n"
4
- "POT-Creation-Date: 2016-03-10 17:59-0600\n"
5
- "PO-Revision-Date: 2016-03-10 18:07-0600\n"
6
- "Last-Translator: \n"
7
- "Language-Team: InboundNow <support@inboundnow.com>\n"
8
- "Language: en_US\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.7\n"
13
- "X-Poedit-KeywordsList: __;_e\n"
14
- "X-Poedit-Basepath: ..\n"
15
- "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
- "X-Poedit-SearchPath-0: .\n"
17
- "X-Poedit-SearchPathExcluded-0: js\n"
18
- "X-Poedit-SearchPathExcluded-1: shared/docs\n"
19
- "X-Poedit-SearchPathExcluded-2: ../templates/*.js\n"
20
- "X-Poedit-SearchPathExcluded-3: .\n"
21
- "X-Poedit-SearchPathExcluded-4: ../shared/assets\n"
22
- "X-Poedit-SearchPathExcluded-5: libraries\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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,654 +0,0 @@
1
- <?php
2
-
3
- if (!class_exists('Landing_Pages_ACF')) {
4
-
5
- class Landing_Pages_ACF {
6
-
7
- /**
8
- * Name under which the transient for the current tab will be saved.
9
- * @var string
10
- */
11
- static $_transient_name = 'acf_current_tab';
12
- /**
13
- * Number of minutes the transient will be saved.
14
- * @var int
15
- */
16
- static $_transient_minutes = 5;
17
-
18
-
19
- /**
20
- * Initialize Landing_Pages_ACF Class
21
- */
22
- public function __construct() {
23
- self::load_hooks();
24
- }
25
-
26
-
27
- /**
28
- * Load Hooks & Filters
29
- */
30
- public static function load_hooks() {
31
-
32
- /* Load ACF Fields On ACF powered Email Template */
33
- add_filter( 'acf/location/rule_match/template_id' , array( __CLASS__ , 'load_acf_on_template' ) , 10 , 3 );
34
-
35
- /* make sure fields are placed in the correct location */
36
- add_action( 'save_post', array( __CLASS__ , 'save_acf_fields' ) );
37
-
38
- /* Intercept load custom field value request and hijack it */
39
- add_filter( 'acf/load_value' , array( __CLASS__ , 'load_value' ) , 11 , 3 );
40
-
41
- /* extra field formatting
42
- add_filter( 'acf/format_value' , array( __CLASS__ , 'format_value' ) , 11 , 3 ); */
43
-
44
- /* make sure fields are placed in the correct location */
45
- add_action( 'admin_print_footer_scripts', array( __CLASS__ , 'reposition_acf_fields' ) );
46
-
47
- /* add new location rule to ACF Field UI */
48
- add_filter('acf/location/rule_types', array( __CLASS__ , 'define_location_rule_types' ) );
49
-
50
- /* add new location rule values to ACF Field UI */
51
- add_filter('acf/location/rule_values/template_id', array( __CLASS__ , 'define_location_rule_values' ) );
52
-
53
- add_action( 'acf/input/admin_footer', array( __CLASS__ , 'handle_tab' ) );
54
- add_action( 'wp_ajax_acf_save_current_tab', array( __CLASS__ , 'ajax_acf_save_current_tab' ) );
55
-
56
- }
57
-
58
- /**
59
- * @param $choices
60
- * @return mixed
61
- */
62
- public static function define_location_rule_types( $choices ) {
63
-
64
- if (!isset($choices['Basic']['template_id'])) {
65
- $choices['Basic']['template_id'] = __('Template ID', 'landing-page');
66
- }
67
-
68
- return $choices;
69
- }
70
-
71
- public static function define_location_rule_values( $choices ) {
72
- $template_ids = Landing_Pages_Load_Extensions::get_uploaded_template_ids();
73
-
74
- if (!isset($choices['default'])) {
75
- $choices[ 'default' ] = 'default';
76
- }
77
-
78
- if( $template_ids ) {
79
- foreach( $template_ids as $template_id ) {
80
-
81
- /* template ID by template name here */
82
- $choices[ $template_id ] = $template_id;
83
-
84
- }
85
- }
86
-
87
- return $choices;
88
- }
89
-
90
- /**
91
- * Adds javascript to make sure ACF fields load inside template container
92
- */
93
- public static function reposition_acf_fields() {
94
- global $post;
95
-
96
- if ( !defined('ACF_FREE') || ( !isset($post) || $post->post_type != 'landing-page' ) ) {
97
- return;
98
- }
99
-
100
- ?>
101
- <script type='text/javascript'>
102
- jQuery('.acf_postbox').each(function(){
103
- jQuery('#template-display-options').append(jQuery(this));
104
- });
105
- </script>
106
- <?php
107
- }
108
-
109
- public static function save_acf_fields( $landing_page_id ) {
110
-
111
- if ( wp_is_post_revision( $landing_page_id ) ) {
112
- return;
113
- }
114
-
115
- if ( !isset($_POST['post_type']) || $_POST['post_type'] != 'landing-page' ) {
116
- return;
117
- }
118
-
119
- if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
120
- return;
121
- }
122
-
123
- /* save acf settings - uses our future data array - eventually we will migrate all post meta into this data object */
124
- $fields = (isset($_POST['fields'])) ? $_POST['fields'] : null;
125
- $fields = (isset($_POST['acf'])) ? $_POST['acf'] : $fields;
126
-
127
- if ( $fields ) {
128
-
129
- $settings = Landing_Pages_Meta::get_settings( $landing_page_id );
130
- $variation_id = (isset($_REQUEST['lp-variation-id'])) ? intval($_REQUEST['lp-variation-id']) : '0';
131
-
132
- if (!isset($settings['variations'])) {
133
- $settings['variations'] = array();
134
- }
135
-
136
- $settings['variations'][$variation_id]['acf'] = $fields;
137
- Landing_Pages_Meta::update_settings( $landing_page_id , $settings );
138
- }
139
- }
140
-
141
- /**
142
- * Although unused at the moment, this method can be used for filtering the return value with ACF5 fields
143
- * @param $value
144
- * @param $post_id
145
- * @param $field
146
- * @return mixed
147
- */
148
- public static function format_value( $value, $post_id, $field ) {
149
- return $value;
150
- }
151
-
152
- /**
153
- * Finds the correct value given the variation
154
- *
155
- * @param MIXED $value contains the non-variation value
156
- * @param INT $post_id ID of landing page being loaded
157
- * @param ARRAY $field wide array of data belonging to custom field (not leveraged in this method)
158
- *
159
- * @returns MIXED $new_value value mapped to variation.
160
- */
161
- public static function load_value( $value, $post_id, $field ) {
162
- global $post;
163
-
164
- if ( !isset($post) || $post->post_type != 'landing-page' ) {
165
- return $value;
166
- }
167
-
168
- $vid = Landing_Pages_Variations::get_new_variation_reference_id( $post->ID );
169
-
170
- $settings = Landing_Pages_Meta::get_settings( $post->ID );
171
-
172
- $variations = ( isset($settings['variations']) ) ? $settings['variations'] : null;
173
-
174
- /* If there is no ACF data for this template attempt to pull values from the legacy postmeta values */
175
-
176
- if ( !isset( $variations[ $vid ][ 'acf' ] ) || !$variations[ $vid ][ 'acf' ]) {
177
- return self::load_legacy_value( $value, $post_id, $field );
178
- }
179
-
180
-
181
- if ( isset( $variations[ $vid ][ 'acf' ] ) ) {
182
- $new_value = self::search_field_array( $variations[ $vid ][ 'acf' ] , $field );
183
-
184
- /* sometimes value is an array count when new_value believes it should be an array in this case get new count */
185
- if (!is_array($value) && is_array($new_value)) {
186
- $value = count($new_value);
187
- } else if($new_value) {
188
- if ($new_value =='_empty') {
189
- $new_value = '';
190
- }
191
- $value = $new_value;
192
- }
193
-
194
- /* acf lite isn't processing return values correctly - ignore repeater subfields */
195
- if ( !is_admin() && defined('ACF_FREE') ) {
196
- $value = self::acf_free_value_formatting( $value , $field );
197
-
198
- }
199
-
200
- if ( !is_admin() && is_string($value) && !defined('INBOUND_DEBUG_GF_AJAX') ) {
201
- $value = do_shortcode($value);
202
- }
203
-
204
- /* handle non acf5 template return formatting */
205
- if (defined('ACF_PRO')) {
206
- $value = self::acf_check_if_acf4( $value , $field );
207
- }
208
-
209
- }
210
-
211
- return $value;
212
-
213
- }
214
- /**
215
- * Finds the correct value given the variation - uses legacy meta system
216
- *
217
- * @param MIXED $value contains the non-variation value
218
- * @param INT $post_id ID of landing page being loaded
219
- * @param ARRAY $field wide array of data belonging to custom field (not leveraged in this method)
220
- *
221
- * @returns MIXED $new_value value mapped to variation.
222
- */
223
- public static function load_legacy_value( $value, $post_id, $field ) {
224
- global $post;
225
-
226
- /* get registered field object data */
227
- $field = self::acf_get_registered_field( $field );
228
-
229
- /* if a brand new post ignore return default value */
230
- if ( $post->post_status != 'publish' ) {
231
- return ( isset($field['default_value']) ) ? do_shortcode($field['default_value']) : '' ;
232
- }
233
-
234
- $vid = Landing_Pages_Variations::get_new_variation_reference_id( $post->ID );
235
-
236
- if ( $vid ) {
237
- $value = get_post_meta( $post_id , $field['name'] . '-' . $vid , true );
238
- } else {
239
- $value = get_post_meta( $post_id , $field['name'] , true );
240
- }
241
-
242
-
243
- if ($field['type']=='image' && is_admin() ) {
244
- $value = self::get_image_id_from_url( $value );
245
- }
246
-
247
- if ($field['type']=='date_picker') {
248
- $value = str_replace('-' , '', $value);
249
- $value = explode(' ' , $value);
250
- $value = $value[0];
251
- }
252
-
253
- if ($field['type']=='color_picker') {
254
- if (!strstr( $value , '#' ) && $value ) {
255
- $value = '#'.$value;
256
- }
257
- }
258
-
259
- if (!is_array($value) && !is_admin() ) {
260
- $value = do_shortcode($value);
261
- }
262
-
263
- return $value;
264
-
265
- }
266
-
267
-
268
- /**
269
- * Searches ACF variation array and returns the correct field value given the field key
270
- *
271
- * @param ARRAY $array of custom field keys and values stored for variation
272
- * @param STRING $needle acf form field key
273
- *
274
- * @return $feild value
275
- */
276
- public static function search_field_array( $array , $field ) {
277
-
278
- $needle = $field['key'];
279
-
280
- foreach ($array as $key => $value ){
281
-
282
-
283
- if ($key === $needle && !is_array($value) ) {
284
- $value = ($value) ? $value : '_empty' ;
285
- return $value;
286
- }
287
-
288
- /* Arrays could be repeaters or any custom field with sets of multiple values */
289
- if ( is_array($value) ) {
290
-
291
- /* 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 */
292
- if ( $key === $needle ) {
293
-
294
- $repeater_array = self::get_repeater_layouts( $value );
295
- if ($repeater_array) {
296
- return $repeater_array;
297
- } else {
298
- return $value;
299
- }
300
-
301
- }
302
-
303
- /* Check if array is repeater fields and determine correct value given a parsed field name with field key */
304
- $repeater_value = self::get_repeater_values( $value , $field , $needle );
305
-
306
- /* If target key is not in these repeater fields, or this array is not determined to be a repeater field then move on. */
307
- if ($repeater_value) {
308
- return $repeater_value;
309
- }
310
-
311
-
312
- }
313
-
314
- }
315
-
316
- return false;
317
- }
318
-
319
- /**
320
- * Searches an array assumed to be a repeater field dataset and returns an array of repeater field layout definitions
321
- *
322
- * @retuns ARRAY $fields this array will either be empty of contain repeater field layout definitions.
323
- */
324
- public static function get_repeater_layouts( $array ) {
325
-
326
- $fields = array();
327
-
328
- foreach ($array as $key => $value) {
329
- if ( isset( $value['acf_fc_layout'] ) ) {
330
- $fields[] = $value['acf_fc_layout'];
331
- }
332
- }
333
-
334
- return $fields;
335
- }
336
-
337
-
338
- /**
339
- * Searches an array assumed to be a repeater field dataset and returns an array of repeater field layout definitions
340
- *
341
- * @retuns ARRAY $fields this array will either be empty of contain repeater field layout definitions.
342
- */
343
- public static function get_repeater_values( $array , $field , $needle ) {
344
-
345
- /* Discover correct repeater pointer by parsing field name */
346
- preg_match('/(_\d_)/', $field['name'], $matches, 0);
347
-
348
- /* if not a repeater subfield then bail */
349
- if (!$matches) {
350
- return false;
351
- }
352
-
353
- $pointer = str_replace('_' , '' , $matches[0]);
354
- $repeater_key = self::key_search($array, $field , true ); /* returns parent flexible content field key using sub field key */
355
-
356
-
357
- /* */
358
- if ( $repeater_key && $repeater_key !== '0' && isset($array[$repeater_key][$pointer][$field['key']])){
359
- return $array[$repeater_key][$pointer][$field['key']];
360
- }
361
-
362
- /* repeater field comes after the pointer???? */
363
- if (isset($array[$pointer][$needle])){
364
- return $array[$pointer][$needle];
365
- }
366
-
367
-
368
-
369
- return '';
370
-
371
- }
372
-
373
- /**
374
- * Check if current post is a landing page using an ACF powered template
375
- *
376
- * @filter acf/location/rule_match/template_id
377
- *
378
- * @returns BOOL declaring if current page is a landing page with an ACF template loaded or not
379
- */
380
- public static function load_acf_on_template( $allow , $rule, $args ) {
381
- global $post;
382
-
383
- if ( !isset($post) || $post->post_type != 'landing-page' ) {
384
- return $allow;
385
- }
386
-
387
- $template = Landing_Pages_Variations::get_current_template( $args['post_id'] );
388
-
389
- if ($template == $rule['value']) {
390
- return true;
391
- } else {
392
- return false;
393
- }
394
- }
395
-
396
- /**
397
- *
398
- * @param $image_url
399
- * @return mixed
400
- */
401
- public static function get_image_id_from_url($url) {
402
- $dir = wp_upload_dir();
403
-
404
- // baseurl never has a trailing slash
405
- if ( false === strpos( $url, $dir['baseurl'] . '/' ) ) {
406
- // URL points to a place outside of upload directory
407
- return false;
408
- }
409
-
410
- $file = basename( $url );
411
- $query = array(
412
- 'post_type' => 'attachment',
413
- 'fields' => 'ids',
414
- 'meta_query' => array(
415
- array(
416
- 'value' => $file,
417
- 'compare' => 'LIKE',
418
- ),
419
- )
420
- );
421
-
422
- $query['meta_query'][0]['key'] = '_wp_attached_file';
423
-
424
- // query attachments
425
- $ids = get_posts( $query );
426
-
427
- if ( ! empty( $ids ) ) {
428
-
429
- foreach ( $ids as $id ) {
430
-
431
- // first entry of returned array is the URL
432
- if ( $url === array_shift( wp_get_attachment_image_src( $id, 'full' ) ) )
433
- return $id;
434
- }
435
- }
436
-
437
- $query['meta_query'][0]['key'] = '_wp_attachment_metadata';
438
-
439
- // query attachments again
440
- $ids = get_posts( $query );
441
-
442
- if ( empty( $ids) )
443
- return false;
444
-
445
- foreach ( $ids as $id ) {
446
-
447
- $meta = wp_get_attachment_metadata( $id );
448
-
449
- foreach ( $meta['sizes'] as $size => $values ) {
450
-
451
- if ( $values['file'] === $file && $url === array_shift( wp_get_attachment_image_src( $id, $size ) ) )
452
- return $id;
453
- }
454
- }
455
-
456
- return false;
457
- }
458
-
459
- public static function acf_get_registered_field( $field ) {
460
- global $acf_register_field_group;
461
-
462
- if (!$acf_register_field_group) {
463
- return $field;
464
- }
465
-
466
- foreach ($acf_register_field_group as $key => $group) {
467
- foreach ( $group['fields'] as $this_field ) {
468
- if ( $this_field['name'] == $field['name'] ){
469
- return $this_field;
470
- }
471
- }
472
- }
473
- }
474
-
475
-
476
- /**
477
- * Correct return value formatting when Pro is NOT installed
478
- */
479
- public static function acf_free_value_formatting( $value , $field ) {
480
-
481
- if ($field['type'] == 'image' && $field['return_format'] == 'url' && !strstr($value , 'http' ) ) {
482
- $image_array = wp_get_attachment_image_src( $value , 'full' );
483
- return $image_array[0];
484
- }
485
-
486
- if ($field['type'] == 'file' && $field['return_format'] == 'url' && !strstr($value , 'http' ) ) {
487
- return wp_get_attachment_url( $value );
488
- }
489
-
490
- if ($field['type'] == 'wysiwyg') {
491
- $vaue = wpautop($value);
492
- $vaue = do_shortcode($value);
493
- }
494
-
495
- return $value;
496
- }
497
-
498
- /**
499
- * checks template data type
500
- * @param $value
501
- * @param $field
502
- * @return mixed
503
- */
504
- public static function acf_check_if_acf4( $value , $field ) {
505
- global $key, $lp_data;
506
-
507
- if (!isset($lp_data[$key])) {
508
- return $value;
509
- }
510
-
511
- if ( $lp_data[$key]['info']['data_type'] == 'acf4' ) {
512
- return self::acf_free_value_formatting($value , $field);
513
- } else {
514
- return $value;
515
- }
516
- }
517
-
518
-
519
- /**
520
- * This is a complicated array search method for working with ACF repeater fields.
521
- * @param $array
522
- * @param $field
523
- * @param bool|false $get_parent if get_parent is set to true to will return the parent field group key of the repeater fields
524
- * @param mixed $last_key placeholder for storing the last key...
525
- * @return bool|int|string
526
- */
527
- public static function key_search($array, $field , $get_parent = false , $last_key = false) {
528
- $value = false;
529
-
530
- foreach ($array as $key => $item) {
531
- if ($key === $field['key'] ) {
532
- $value = $item;
533
- } else {
534
- if (is_array($item)) {
535
- $last_key = ( !is_numeric($key)) ? $key : $last_key;
536
- $value = self::key_search($item, $field , $get_parent , $last_key );
537
- }
538
- }
539
-
540
- if ($value) {
541
- if (!$get_parent) {
542
- return $value;
543
- } else {
544
- return $last_key;
545
- }
546
-
547
- }
548
- }
549
-
550
- return false;
551
- }
552
-
553
- /**
554
- * Select tab that was selected in last edit session of the post.
555
- *
556
- * - If the time the same post that was last edited lies within the time the
557
- * transient exists, the last selected tab will be selected via JavaScript.
558
- * - If a new post is opened for editing, the current tab will be overwritten.
559
- */
560
- public static function handle_tab() {
561
- // Run only when post_id is present
562
- if ( ! isset( $_GET['post'] ) || ! is_numeric( $_GET['post'] ) ) {
563
- return;
564
- }
565
- $post_id = sanitize_key( $_GET['post'] );
566
- // Check for existing transient
567
- $current_tab = get_transient( self::$_transient_name );
568
- // Use value only once, delete transient right away
569
- delete_transient( self::$_transient_name );
570
- // The first tab is selected by default
571
- $tab_index = 0;
572
- // Get tab index for current post
573
- if ( $current_tab['post_id'] === $post_id ) {
574
- $tab_index = $current_tab['tab_index'];
575
- }
576
- ?>
577
- <script type="text/javascript">
578
- (function($) {
579
- /**
580
- * Global to save the current index of selected tab
581
- * @type int
582
- */
583
- window.acf_current_tab_index = null;
584
- acf.add_action('ready', function( $el ){
585
- var tabIndex = <?php echo $tab_index; ?>
586
- // Get tab element by index
587
- var $li = $('.acf-tab-group').find('li:eq(<?php echo $tab_index; ?>)');
588
- // Select tab only when it’s not the first tab, which is selected by default
589
- if (0 !== tabIndex) {
590
- $li.find('a').click();
591
- }
592
- window.acf_current_tab_index = tabIndex;
593
- });
594
- acf.add_action('refresh', function($tabGroup) {
595
- var $currentTab;
596
- var currentTabIndex = window.acf_current_tab_index;
597
- var newTabIndex;
598
- // Bail out if we have no jQuery object
599
- if (false === $tabGroup instanceof jQuery) {
600
- return;
601
- }
602
- $currentTab = $tabGroup.find('li.active');
603
- // Bail out if no active tab was found
604
- if ($currentTab.length === 0) {
605
- return;
606
- }
607
- // Get index of active tab
608
- newTabIndex = $currentTab.index();
609
- // Bail out if index is initial or previously selected tab is the same
610
- if (null === currentTabIndex || newTabIndex === currentTabIndex) {
611
- return;
612
- }
613
- window.acf_current_tab_index = newTabIndex;
614
- // Send tabIndex to backend to save transient
615
- $.ajax(ajaxurl, {
616
- method: 'post',
617
- data: {
618
- action: 'acf_save_current_tab',
619
- tab_index: newTabIndex,
620
- post_id: <?php echo $post_id; ?>
621
- }
622
- });
623
- });
624
- })(jQuery);
625
- </script>
626
- <?php
627
- }
628
- public static function ajax_acf_save_current_tab() {
629
- if ( ! isset( $_POST['tab_index'] ) || ! is_numeric( $_POST['tab_index'] ) ) {
630
- return;
631
- }
632
- $tab_index = sanitize_text_field($_POST['tab_index']);
633
- $post_id = $_POST['post_id'];
634
- $transient_value = array(
635
- 'tab_index' => $tab_index,
636
- 'post_id' => $post_id,
637
- );
638
- $result = set_transient( self::$_transient_name, $transient_value, self::$_transient_minutes * 60 );
639
- if ( $result ) {
640
- wp_send_json_success();
641
- }
642
- wp_die();
643
- }
644
-
645
- }
646
-
647
- /**
648
- * Initialize ACF Integrations
649
- */
650
-
651
- new Landing_Pages_ACF();
652
-
653
-
654
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.activation.php DELETED
@@ -1,293 +0,0 @@
1
- <?php
2
-
3
- if ( !class_exists('Landing_Pages_Activation') ) {
4
-
5
- class Landing_Pages_Activation {
6
-
7
- static $version_wp;
8
- static $version_php;
9
- static $version_cta;
10
- static $version_leads;
11
- static $version_lpah;
12
-
13
- /**
14
- * Initiate class
15
- */
16
- public function __construct() {
17
- self::load_hooks();
18
- }
19
-
20
- /**
21
- * load supporting hooks and filters
22
- */
23
- public static function load_hooks() {
24
- if (!is_admin()) {
25
- return;
26
- }
27
-
28
- /* Add listener for unset permalinks */
29
- add_action('admin_notices', array( __CLASS__ , 'permastruct_check' ) );
30
-
31
- /** add listener for permlaink flush command */
32
- add_action('admin_init', array( __CLASS__ , 'flush_permalinks' ) , 11 );
33
-
34
- /* Add listener for uncompleted upgrade routines */
35
- add_action( 'admin_init' , array( 'Landing_Pages_Activation' , 'run_upgrade_routine_checks' ) );
36
-
37
- }
38
-
39
- public static function activate() {
40
- self::load_static_vars();
41
- self::run_version_checks();
42
- self::activate_plugin();
43
- self::run_updates();
44
- }
45
-
46
- public static function deactivate() {
47
- global $wp_rewrite;
48
- $wp_rewrite->flush_rules();
49
- }
50
-
51
- public static function load_static_vars() {
52
-
53
- self::$version_wp = '3.6';
54
- self::$version_php = '5.2';
55
- self::$version_cta = '1.2.1';
56
- self::$version_leads = '1.2.1';
57
- self::$version_lpah = '1.0.8';
58
- }
59
-
60
- public static function activate_plugin() {
61
-
62
- /* Update DB Markers for Plugin */
63
- self::store_version_data();
64
-
65
- /* Set Default Settings */
66
- self::set_default_settings();
67
-
68
- /* Activate shared components */
69
- self::activate_shared();
70
-
71
- /* Run additional actions */
72
- do_action( 'activate_landing_pages' );
73
-
74
- }
75
-
76
- /* This method loads public methods from the Landing_Pages_Activation_Update_Routines class and automatically runs them if they have not been run yet.
77
- * 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
78
- */
79
-
80
- public static function run_updates() {
81
-
82
- /* Get list of updaters from Landing_Pages_Activation_Update_Routines class */
83
- $updaters = get_class_methods('Landing_Pages_Activation_Update_Routines');
84
-
85
- /* Get transient list of completed update processes */
86
- $completed = ( get_option( 'lp_completed_upgrade_routines' ) ) ? get_option( 'lp_completed_upgrade_routines' ) : array();
87
-
88
- /* Get the difference between the two arrays */
89
- $remaining = array_diff( $updaters , $completed );
90
-
91
- /* Loop through updaters and run updaters that have not been ran */
92
- foreach ( $remaining as $updater ) {
93
-
94
- Landing_Pages_Activation_Update_Routines::$updater();
95
- $completed[] = $updater;
96
-
97
- }
98
-
99
- /* Update this transient value with list of completed upgrade processes */
100
- update_option( 'lp_completed_upgrade_routines' , $completed );
101
-
102
- }
103
-
104
- /**
105
- * This method checks if there are upgrade routines that have not been executed yet and notifies the administror if there are
106
- *
107
- */
108
- public static function run_upgrade_routine_checks() {
109
-
110
- /* Listen for a manual upgrade call */
111
- if (isset($_GET['plugin_action']) && $_GET['plugin_action'] == 'upgrade_routines' && $_GET['plugin'] =='landing-pages' ) {
112
- self::run_updates();
113
- wp_redirect(admin_url('edit.php?post_type=landing-page'));
114
- exit;
115
- }
116
-
117
- /* Get list of updaters from Landing_Pages_Activation_Update_Routines class */
118
- $updaters = get_class_methods('Landing_Pages_Activation_Update_Routines');
119
-
120
- /* Get transient list of completed update processes */
121
- $completed = ( get_option( 'lp_completed_upgrade_routines' ) ) ? get_option( 'lp_completed_upgrade_routines' ) : array();
122
-
123
- /* Get the difference between the two arrays */
124
- $remaining = array_diff( $updaters , $completed );
125
-
126
- if (count($remaining)>0) {
127
- add_action( 'admin_notices', array( __CLASS__ , 'display_upgrade_routine_notice' ) );
128
- }
129
- }
130
-
131
- public static function display_upgrade_routine_notice() {
132
- ?>
133
- <div class="error">
134
- <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>
135
- </div>
136
- <?php
137
- }
138
-
139
-
140
- /* Creates transient records of past and current version data */
141
- public static function store_version_data() {
142
-
143
- $old = get_transient('lp_current_version');
144
- set_transient( 'lp_previous_version' , $old );
145
- set_transient( 'lp_current_version' , LANDINGPAGES_CURRENT_VERSION );
146
-
147
- }
148
-
149
- public static function set_default_settings() {
150
- add_option( 'lp_global_css', '', '', 'no' );
151
- add_option( 'lp_global_js', '', '', 'no' );
152
- add_option( 'lp_global_lp_slug', 'go', '', 'no' );
153
- update_option( 'lp_activate_rewrite_check', '1');
154
-
155
- /* Set's welcome page redirect transient */
156
- set_transient( '_landing_page_activation_redirect', true, 30 );
157
- }
158
-
159
- /**
160
- * Tells Inbound Shared to run activation commands
161
- */
162
- public static function activate_shared() {
163
- update_option( 'Inbound_Activate', true );
164
- }
165
-
166
- /* Aborts activation and details
167
- * @param args ARRAY of message details
168
- */
169
- public static function abort_activation( $args ) {
170
- echo $args['title'] . '<br>';
171
- echo $args['message'] . '<br>';
172
- echo 'Details:<br>';
173
- print_r ($args['details']);
174
- echo '<br>';
175
- echo $args['solution'];
176
-
177
- deactivate_plugins( LANDINGPAGES_FILE );
178
- exit;
179
- }
180
-
181
-
182
- /* Checks if plugin is compatible with current server PHP version */
183
- public static function run_version_checks() {
184
-
185
- global $wp_version;
186
-
187
- /* Check PHP Version */
188
- if ( version_compare( phpversion(), self::$version_php, '<' ) ) {
189
- self::abort_activation(
190
- array(
191
- 'title' => 'Installation aborted',
192
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
193
- 'details' => array(
194
- __( 'Server PHP Version' , 'inbound-pro' ) => phpversion(),
195
- __( 'Required PHP Version' , 'inbound-pro' ) => self::$version_php
196
- ),
197
- 'solution' => sprintf( __( 'Please contact your hosting provider to upgrade PHP to %s or greater' , 'inbound-pro' ) , self::$version_php )
198
- )
199
- );
200
- }
201
-
202
- /* Check WP Version */
203
- if ( version_compare( $wp_version , self::$version_wp, '<' ) ) {
204
- self::abort_activation( array(
205
- 'title' => 'Installation aborted',
206
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
207
- 'details' => array(
208
- __( 'WordPress Version' , 'inbound-pro' ) => $wp_version,
209
- __( 'Required WordPress Version' , 'inbound-pro' ) => self::$version_wp
210
- ),
211
- 'solution' => sprintf( __( 'Please update landing pages to version %s or greater.' , 'inbound-pro' ) , self::$version_wp )
212
- )
213
- );
214
- }
215
-
216
- /* Check CTA Version */
217
- if ( defined('WP_CTA_CURRENT_VERSION') && version_compare( WP_CTA_CURRENT_VERSION , self::$version_cta , '<' ) ) {
218
- self::abort_activation( array(
219
- 'title' => 'Installation aborted',
220
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
221
- 'details' => array(
222
- __( 'Calls to Action Version' , 'inbound-pro' ) => WP_CTA_CURRENT_VERSION,
223
- __( 'Required Calls to Action Version' , 'inbound-pro' ) => self::$version_cta
224
- ),
225
- 'solution' => sprintf( __( 'Please update Calls to Action to version %s or greater.' , 'inbound-pro' ) , self::$version_cta )
226
- )
227
- );
228
- }
229
-
230
- /* Check Leads Version */
231
- if ( defined('WPL_CURRENT_VERSION') && version_compare( WPL_CURRENT_VERSION , self::$version_leads , '<' ) ) {
232
- self::abort_activation( array(
233
- 'title' => 'Installation aborted',
234
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
235
- 'details' => array(
236
- __( 'Leads Version' , 'inbound-pro' ) => WPL_CURRENT_VERSION,
237
- __( 'Required Leads Version' , 'inbound-pro' ) => self::$version_leads
238
- ),
239
- 'solution' => sprintf( __( 'Please update Leads to version %s or greater.' , 'inbound-pro' ) , self::$version_leads )
240
- )
241
- );
242
- }
243
-
244
- /* Check Extension Version */
245
- if ( defined('LP_HOMEPAGE_CURRENT_VERSION') && version_compare( LP_HOMEPAGE_CURRENT_VERSION , self::$version_lpah , '<' ) ) {
246
- self::abort_activation( array(
247
- 'title' => 'Installation aborted',
248
- 'message' => __('Landing Plugin could not be installed' , 'landing-pages'),
249
- 'details' => array(
250
- __( 'Extension: Landing Page as Homepage' , 'inbound-pro' ) => LP_HOMEPAGE_CURRENT_VERSION,
251
- __( 'Required extension version' , 'inbound-pro' ) => self::$version_lpah
252
- ),
253
- 'solution' => sprintf( __( 'Please update extension to version %s or greater.' , 'inbound-pro' ) , self::$version_lpah )
254
- )
255
- );
256
- }
257
-
258
- }
259
-
260
- /**
261
- * flush permalinks
262
- */
263
- public static function flush_permalinks() {
264
-
265
- if ( !get_option( 'lp_activate_rewrite_check' ) ) {
266
- return;
267
- }
268
-
269
- flush_rewrite_rules( true );
270
- delete_option( 'lp_activate_rewrite_check' );
271
- }
272
-
273
- /**
274
- * check for 'default' permalinks and warn
275
- */
276
- public static function permastruct_check() {
277
- if ( '' == get_option( 'permalink_structure' ) ) {
278
- ?>
279
- <div class="error">
280
- <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>
281
- </div>
282
- <?php
283
- }
284
- }
285
- }
286
-
287
- /* Add Activation Hook */
288
- register_activation_hook( LANDINGPAGES_FILE , array( 'Landing_Pages_Activation' , 'activate' ) );
289
- register_deactivation_hook( LANDINGPAGES_FILE , array( 'Landing_Pages_Activation' , 'deactivate' ) );
290
-
291
- new Landing_Pages_Activation;
292
-
293
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/classes/class.activation.upgrade-routines.php DELETED
@@ -1,255 +0,0 @@
1
- <?php
2
-
3
- /* Public methods in this class will be run at least once during plugin activation script. */
4
- /* Updater methods fired are stored in transient to prevent repeat processing */
5
-
6
- if ( !class_exists('Landing_Pages_Activation_Update_Routines') ) {
7
-
8
- class Landing_Pages_Activation_Update_Routines {
9
-
10
- /*
11
- * @introduced: 1.8.9
12
- * @migration-type: Meta pair migragtion
13
- * @migration: Make a meta pair copy of wp_content into 'content' meta key for variation 0 to use (refactor session)
14
- * @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. *
15
- */
16
- public static function prepare_content_meta_key_for_variation_0() {
17
-
18
- /* for all landing pages load variations */
19
- $landing_pages = get_posts( array (
20
- 'post_type' => 'landing-page',
21
- 'posts_per_page' => -1
22
- ));
23
-
24
- /* loop through landing pages and copy post content into meta object */
25
- foreach ($landing_pages as $post) {
26
- $content = $post->post_content;
27
- update_post_meta( $post->ID , 'content' , $content);
28
- }
29
- }
30
-
31
-
32
- /*
33
- * @introduced: 1.5.7
34
- * @migration-type: Meta pair migragtion
35
- * @migration: convert meta key lp-conversion-area to template-name-conversion-area-content-{vid}
36
- */
37
- public static function migrate_legacy_conversion_area_contents() {
38
-
39
- /* for all landing pages load variations */
40
- $landing_pages = get_posts( array (
41
- 'post_type' => 'landing-page',
42
- 'posts_per_page' => -1
43
- ));
44
-
45
- foreach ($landing_pages as $post) {
46
-
47
- /* for all variations loop through and migrate_data */
48
- ( get_post_meta($post->ID,'lp-ab-variations', true) ) ? $variations = get_post_meta($post->ID,'lp-ab-variations', true) : $variations = array( '0' => '0' );
49
-
50
- if (!is_array($variations) && strlen($variations) > 1 ) {
51
- $variations = explode(',',$variations);
52
- }
53
-
54
- foreach ($variations as $key=>$vid) {
55
-
56
- ($vid) ? $suffix = '-' . $vid : $suffix = '';
57
-
58
- $selected_template = get_post_meta( $post->ID , 'lp-selected-template' . $suffix , true );
59
-
60
- if ( !$selected_template ) {
61
- continue;
62
- }
63
-
64
- /* discover legacy main content */
65
- ( $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 );
66
-
67
- /* Now if the new key is not already poplated, copy the content to the new key */
68
- $check = get_post_meta( $post->ID , $selected_template .'-conversion-area-content' . $suffix , true );
69
- if (!$check) {
70
- update_post_meta( $post->ID , $selected_template .'-conversion-area-content' . $suffix , $conversion_area_content );
71
- }
72
-
73
- }
74
-
75
- }
76
- }
77
-
78
- /*
79
- * @introduced: 1.7.5
80
- * @migration-type: Meta key rename
81
- * @migration: renames all instances of inbound_conversion_data to _inbound_conversion_data
82
-
83
- */
84
- public static function meta_key_change_conversion_object() {
85
- global $wpdb;
86
-
87
- $wpdb->query("UPDATE $wpdb->postmeta SET `meta_key` = REPLACE (`meta_key` , 'inbound_conversion_data', '_inbound_conversion_data')");
88
- }
89
-
90
- /*
91
- * @introduced: 1.5.7
92
- * @migration-type: Meta pair migragtion
93
- * @migration: mirgrates post_content and content-{vid} values to template-name-main-content-{vid}
94
-
95
- */
96
- public static function migrate_legacy_main_content() {
97
-
98
- /* for all landing pages load variations */
99
- $landing_pages = get_posts( array (
100
-