PageRenderTime 44ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/jetpack/modules/shortcodes/presentations.php

https://gitlab.com/Gashler/sg
PHP | 431 lines | 245 code | 69 blank | 117 comment | 65 complexity | f47769d02199d82e6e71232933529495 MD5 | raw file
  1. <?php
  2. /*
  3. Plugin Name: Presentations
  4. Plugin URI: http://automattic.com/wordpress-plugins/
  5. Description: Presentations plugin based on the work done by <a href="http://darylkoop.com/">Daryl Koopersmith</a>. Powered by jmpress.js
  6. Version: 0.2
  7. Author: Automattic
  8. Author URI: http://automattic.com/wordpress-plugins/
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * Known issues:
  23. *
  24. * - IE 7/8 are not supported by jmpress and presentations will not work
  25. * - IE 9 will not animate transitions at all, though it's possible to at least
  26. * switch between slides.
  27. * - Infinite Scroll themes will not load presentations properly unless the post
  28. * happens to be on the first loaded page. The permalink page will function
  29. * properly, however.
  30. * - Exiting fullscreen mode will not properly reset the scroll locations in Safari
  31. */
  32. /*
  33. HOW TO: How the plugin settings are organized and which features are supported.
  34. The entire presentation should be wrapped with a [presentation] shortcode, and every
  35. individual slide should be wrapped with a [slide] shortcode. Any settings supported
  36. by [slide] can be set into [presentation], which will apply that setting for the entire
  37. presentation unless overridden by individual slides.
  38. - [presentation] only settings:
  39. - duration: transition durations, default is one second.
  40. - height: content height, default is 400px
  41. - width: content width, default is 550px
  42. - autoplay: delay between transitions in seconds, default 3s
  43. when set the presentation will automatically transition between slides
  44. as long as the presentation remains in focus
  45. - [slide] settings:
  46. - transition: specifies where the next slide will be placed relative
  47. to the last one before it. Supported values are "up", "down"
  48. "left", "right", or "none". Default value is "down".
  49. - scale: scales the content relative to other slides, default value is one
  50. - rotate: rotates the content by the specified degrees, default is zero
  51. - fade: slides will fade in and out during transition. Values of "on" or
  52. "true" will enable fading, while values of "no" or "false" will
  53. disable it. Default value is "on"
  54. - bgcolor: specifies a background color for the slides. Any CSS valid value
  55. is permitted. Default color is transparent.
  56. - bgimg: specifies an image url which will fill the background. Image is
  57. set to fill the background 100% width and height
  58. - fadebullets: any html <li> tags will start out with an opacity of 0 and any
  59. subsequent slide transitions will show the bullets one by one
  60. */
  61. if ( ! class_exists( 'Presentations' ) ) :
  62. class Presentations {
  63. private $presentation_settings;
  64. private $presentation_initialized;
  65. private $scripts_and_style_included;
  66. /**
  67. * Constructor
  68. */
  69. function __construct() {
  70. // Bail without 3.0.
  71. if ( ! function_exists( '__return_false' ) )
  72. return;
  73. $this->presentation_initialized = false;
  74. $this->scripts_and_style_included = false;
  75. // Registers shortcodes
  76. add_action( 'wp_head', array( &$this, 'add_scripts' ), 1 );
  77. add_shortcode( 'presentation', array( &$this, 'presentation_shortcode' ) );
  78. add_shortcode( 'slide', array( &$this, 'slide_shortcode' ) );
  79. }
  80. function add_scripts() {
  81. $this->scripts_and_style_included = false;
  82. if ( empty( $GLOBALS['posts'] ) || !is_array( $GLOBALS['posts'] ) ) {
  83. return;
  84. }
  85. foreach ( $GLOBALS['posts'] as $p ) {
  86. if ( has_shortcode( $p->post_content, 'presentation' ) ) {
  87. $this->scripts_and_style_included = true;
  88. break;
  89. }
  90. }
  91. if ( ! $this->scripts_and_style_included )
  92. return;
  93. $plugin = plugin_dir_url( __FILE__ );
  94. // Add CSS
  95. wp_enqueue_style('presentations', $plugin . 'css/style.css');
  96. // Add JavaScript
  97. wp_enqueue_script('jquery');
  98. wp_enqueue_script('jmpress',
  99. $plugin . 'js/jmpress.min.js',
  100. array('jquery'),
  101. '0.4.5',
  102. true);
  103. wp_enqueue_script('presentations',
  104. $plugin . 'js/main.js',
  105. array('jquery', 'jmpress'),
  106. false,
  107. true);
  108. }
  109. function presentation_shortcode( $atts, $content='' ) {
  110. // Mark that we've found a valid [presentation] shortcode
  111. $this->presentation_initialized = true;
  112. $atts = shortcode_atts( array(
  113. 'duration' => '',
  114. 'height' => '',
  115. 'width' => '',
  116. 'bgcolor' => '',
  117. 'bgimg' => '',
  118. 'autoplay' => '',
  119. // Settings
  120. 'transition' => '',
  121. 'scale' => '',
  122. 'rotate' => '',
  123. 'fade' => '',
  124. 'fadebullets' => '',
  125. ), $atts, 'presentation' );
  126. $this->presentation_settings = array(
  127. 'transition' => 'down',
  128. 'scale' => 1,
  129. 'rotate' => 0,
  130. 'fade' => 'on',
  131. 'fadebullets' => 0,
  132. 'last' => array(
  133. 'x' => 0,
  134. 'y' => 0,
  135. 'scale' => 1,
  136. 'rotate' => 0,
  137. ),
  138. );
  139. // Set the presentation-wide settings
  140. if ( '' != trim( $atts['transition'] ) )
  141. $this->presentation_settings['transition'] = $atts['transition'];
  142. if ( '' != trim( $atts['scale'] ) )
  143. $this->presentation_settings['scale'] = floatval( $atts['scale'] );
  144. if ( '' != trim( $atts['rotate'] ) )
  145. $this->presentation_settings['rotate'] = floatval( $atts['rotate'] );
  146. if ( '' != trim( $atts['fade'] ) )
  147. $this->presentation_settings['fade'] = $atts['fade'];
  148. if ( '' != trim( $atts['fadebullets'] ) )
  149. $this->presentation_settings['fadebullets'] = $atts['fadebullets'];
  150. // Set any settings the slides don't care about
  151. if ( '' != trim( $atts['duration'] ) )
  152. $duration = floatval( $atts['duration'] ) . 's';
  153. else
  154. $duration = '1s';
  155. // Autoplay durations are set in milliseconds
  156. if ( '' != trim( $atts['autoplay'] ) )
  157. $autoplay = floatval( $atts['autoplay'] ) * 1000;
  158. else
  159. $autoplay = 0; // No autoplay
  160. // Set the presentation size as specified or with some nicely sized dimensions
  161. if ( '' != trim( $atts['width'] ) )
  162. $this->presentation_settings['width'] = intval( $atts['width'] );
  163. else
  164. $this->presentation_settings['width'] = 480;
  165. if ( '' != trim( $atts['height'] ) )
  166. $this->presentation_settings['height'] = intval( $atts['height'] );
  167. else
  168. $this->presentation_settings['height'] = 370;
  169. // Hide the content by default in case the scripts fail
  170. $style = 'display: none; width: ' . $this->presentation_settings['width'] . 'px; height: ' . $this->presentation_settings['height'] . 'px;';
  171. // Check for background color XOR background image
  172. // Use a white background if nothing specified
  173. if ( preg_match( '/https?\:\/\/[^\'"\s]*/', $atts['bgimg'], $matches ) ) {
  174. $style .= ' background-image: url("' . esc_url( $matches[0] ) . '");';
  175. } else if ( '' != trim( $atts['bgcolor'] ) ) {
  176. $style .= ' background-color: ' . esc_attr( $atts['bgcolor'] ) . ';';
  177. } else {
  178. $style .= ' background-color: #fff;';
  179. }
  180. // Not supported message style is inlined incase the style sheet doesn't get included
  181. $out = "<section class='presentation-wrapper'>";
  182. $out.= "<p class='not-supported-msg' style='display: inherit; padding: 25%; text-align: center;'>";
  183. $out.= __( 'This slideshow could not be started. Try refreshing the page or viewing it in another browser.' , 'jetpack' ) . '</p>';
  184. // Bail out unless the scripts were added
  185. if ( $this->scripts_and_style_included ) {
  186. $out.= sprintf(
  187. '<div class="presentation" duration="%s" data-autoplay="%s" style="%s">',
  188. esc_attr( $duration ),
  189. esc_attr( $autoplay ),
  190. esc_attr( $style )
  191. );
  192. $out.= "<div class='nav-arrow-left'></div>";
  193. $out.= "<div class='nav-arrow-right'></div>";
  194. $out.= "<div class='nav-fullscreen-button'></div>";
  195. if ( $autoplay ) {
  196. $out.= "<div class='autoplay-overlay' style='display: none'><p class='overlay-msg'>";
  197. $out.= __( 'Click to autoplay the presentation!' , 'jetpack' );
  198. $out.= "</p></div>";
  199. }
  200. $out.= do_shortcode( $content );
  201. }
  202. $out.= "</section>";
  203. $this->presentation_initialized = false;
  204. return $out;
  205. }
  206. function slide_shortcode( $atts, $content = '' ) {
  207. // Bail out unless wrapped by a [presentation] shortcode
  208. if ( ! $this->presentation_initialized )
  209. return $content;
  210. $atts = shortcode_atts( array(
  211. 'transition' => '',
  212. 'scale' => '',
  213. 'rotate' => '',
  214. 'fade' => '',
  215. 'fadebullets'=> '',
  216. 'bgcolor' => '',
  217. 'bgimg' => '',
  218. ), $atts, 'slide' );
  219. // Determine positioning based on transition
  220. if ( '' == trim( $atts['transition'] ) )
  221. $atts['transition'] = $this->presentation_settings['transition'];
  222. // Setting the content scale
  223. if ( '' == trim( $atts['scale'] ) )
  224. $atts['scale'] = $this->presentation_settings['scale'];
  225. if( '' == trim( $atts['scale'] ) )
  226. $scale = 1;
  227. else
  228. $scale = floatval( $atts['scale'] );
  229. if ( $scale < 0 )
  230. $scale *= -1;
  231. // Setting the content rotation
  232. if ( '' == trim( $atts['rotate'] ) )
  233. $atts['rotate'] = $this->presentation_settings['rotate'];
  234. if( '' == trim( $atts['rotate'] ) )
  235. $rotate = 0;
  236. else
  237. $rotate = floatval( $atts['rotate'] );
  238. // Setting if the content should fade
  239. if ( '' == trim( $atts['fade'] ) )
  240. $atts['fade'] = $this->presentation_settings['fade'];
  241. if ( 'on' == $atts['fade'] || 'true' == $atts['fade'] )
  242. $fade = 'fade';
  243. else
  244. $fade = '';
  245. // Setting if bullets should fade on step changes
  246. if ( '' == trim( $atts['fadebullets'] ) )
  247. $atts['fadebullets'] = $this->presentation_settings['fadebullets'];
  248. if ( 'on' == $atts['fadebullets'] || 'true' == $atts['fadebullets'] )
  249. $fadebullets = 'fadebullets';
  250. else
  251. $fadebullets = '';
  252. $coords = $this->get_coords( array(
  253. 'transition' => $atts['transition'],
  254. 'scale' => $scale,
  255. 'rotate' => $rotate,
  256. ));
  257. $x = $coords['x'];
  258. $y = $coords['y'];
  259. // Check for background color XOR background image
  260. // Use a white background if nothing specified
  261. if ( preg_match( '/https?\:\/\/[^\'"\s]*/', $atts['bgimg'], $matches ) ) {
  262. $style = 'background-image: url("' . esc_url( $matches[0] ) . '");';
  263. } else if ( '' != trim( $atts['bgcolor'] ) ) {
  264. $style = 'background-color: ' . esc_attr( $atts['bgcolor'] ) . ';';
  265. } else {
  266. $style = '';
  267. }
  268. // Put everything together and let jmpress do the magic!
  269. $out = sprintf(
  270. '<div class="step %s %s" data-x="%s" data-y="%s" data-scale="%s" data-rotate="%s" style="%s">',
  271. esc_attr( $fade ),
  272. esc_attr( $fadebullets ),
  273. esc_attr( $x ),
  274. esc_attr( $y ),
  275. esc_attr( $scale ),
  276. esc_attr( $rotate ),
  277. esc_attr( $style )
  278. );
  279. $out.= "<div class='slide-content'>";
  280. $out.= do_shortcode( $content );
  281. $out.= "</div></div>";
  282. return $out;
  283. }
  284. /**
  285. * Determines the position of the next slide based on the position and scaling of the previous slide.
  286. *
  287. * @param array $args: an array with the following key-value pairs
  288. * string $transition: the transition name, "up", "down", "left", or "right"
  289. * float $scale: the scale of the next slide (used to determine the position of the slide after that)
  290. *
  291. * @return array with the 'x' and 'y' coordinates of the slide
  292. */
  293. function get_coords( $args ) {
  294. if ( 0 == $args['scale'] )
  295. $args['scale'] = 1;
  296. $width = $this->presentation_settings['width'];
  297. $height = $this->presentation_settings['height'];
  298. $last = $this->presentation_settings['last'];
  299. $scale = $last['scale'];
  300. $next = array(
  301. 'x' => $last['x'],
  302. 'y' => $last['y'],
  303. 'scale' => $args['scale'],
  304. 'rotate' => $args['rotate'],
  305. );
  306. // All angles are measured from the vertical axis, so everything is backwards!
  307. $diagAngle = atan2( $width, $height );
  308. $diagonal = sqrt( pow( $width, 2 ) + pow( $height, 2 ) );
  309. // We offset the angles by the angle formed by the diagonal so that
  310. // we can multiply the sines directly against the diagonal length
  311. $theta = deg2rad( $last['rotate'] ) - $diagAngle;
  312. $phi = deg2rad( $next['rotate'] ) - $diagAngle;
  313. // We start by displacing by the slide dimensions
  314. $totalHorizDisp = $width * $scale;
  315. $totalVertDisp = $height * $scale;
  316. // If the previous slide was rotated, we add the incremental offset from the rotation
  317. // Namely the difference between the regular dimension (no rotation) and the component
  318. // of the diagonal for that angle
  319. $totalHorizDisp += ( ( ( abs( sin( $theta ) ) * $diagonal) - $width ) / 2) * $scale;
  320. $totalVertDisp += ( ( ( abs( cos( $theta ) ) * $diagonal) - $height) / 2) * $scale;
  321. // Similarly, we check if the current slide has been rotated and add whatever additional
  322. // offset has been added. This is so that two rotated corners don't clash with each other.
  323. // Note: we are checking the raw angle relative to the vertical axis, NOT the diagonal angle.
  324. if ( $next['rotate'] % 180 != 0 ){
  325. $totalHorizDisp += ( abs( ( sin( $phi ) * $diagonal ) - $width ) / 2) * $next['scale'];
  326. $totalVertDisp += ( abs( ( cos( $phi ) * $diagonal ) - $height ) / 2) * $next['scale'];
  327. }
  328. switch ( trim( $args['transition'] ) ) {
  329. case 'none':
  330. break;
  331. case 'left':
  332. $next['x'] -= $totalHorizDisp;
  333. break;
  334. case 'right':
  335. $next['x'] += $totalHorizDisp;
  336. break;
  337. case 'up':
  338. $next['y'] -= $totalVertDisp;
  339. break;
  340. case 'down':
  341. default:
  342. $next['y'] += $totalVertDisp;
  343. break;
  344. }
  345. $this->presentation_settings['last'] = $next;
  346. return $next;
  347. }
  348. }
  349. $GLOBALS['presentations'] = new Presentations();
  350. endif;