From 7b4b6c9961fe21803c4757cefd6788edd3c35206 Mon Sep 17 00:00:00 2001 From: cristianraiber Date: Wed, 25 Apr 2018 20:38:30 +0300 Subject: [PATCH 01/12] turn textareas into WYSIWYG editors; minor customizer UI CSS fixes --- assets/css/admin.css | 43 +++-- assets/js/previewer.js | 4 + assets/js/widget.js | 166 +++++++++++------- inc/widgets/class-shapely-categories.php | 2 +- .../class-shapely-home-call-for-action.php | 8 +- inc/widgets/class-shapely-home-contact.php | 89 +++++----- inc/widgets/class-shapely-home-parallax.php | 7 +- inc/widgets/class-shapely-home-portfolio.php | 6 +- inc/widgets/class-shapely-video.php | 6 +- 9 files changed, 194 insertions(+), 137 deletions(-) diff --git a/assets/css/admin.css b/assets/css/admin.css index 71558e4..3eb7a88 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -1,42 +1,51 @@ .shapely-media-control img { - width: 100%; - height: auto; + width: 100%; + height: auto; } .logo_heading { - display: block; - width: 100%; + display: block; + width: 100%; } #setting-error-tgmpa.notice { - display: block; + display: block; } .client-sortable .logo_heading { - background: #f3f3f3; - border: 1px dotted; - cursor: move; - display: block; - font-size: 14px; - padding: 8px 0; - text-align: center; - width: 100%; + background: #f3f3f3; + border: 1px dotted; + cursor: move; + display: block; + font-size: 14px; + padding: 8px 0; + text-align: center; + width: 100%; } .client-sortable .logo_heading:hover { - border: 1px solid; + border: 1px solid; } .client-sortable .cloneya a.clone, .client-sortable .cloneya a.delete { - display: none; + display: none; } .client-sortable .cloneya:last-child a.clone, .client-sortable .cloneya:last-child a.delete { - display: inline-block; + display: inline-block; } .shapely-media-control img { - width: 100%; + width: 100%; +} + +.shapely-editor-container label { + position: relative; + top: 30px; +} + +.checkbox_switch { + margin: 10px auto; } \ No newline at end of file diff --git a/assets/js/previewer.js b/assets/js/previewer.js index 056d01d..7a5c5bc 100644 --- a/assets/js/previewer.js +++ b/assets/js/previewer.js @@ -4,6 +4,8 @@ return; } + var illdyCompanion = {}; + wp.customize.selectiveRefresh.bind( 'widget-updated', function( placement ) { var maxHeight, container, msnry, element; $( '.logo-carousel' ).flexslider({ @@ -22,6 +24,7 @@ if ( 'function' === typeof $( '.parallax-window' ).parallax ) { $( '.parallax-window' ).parallax(); } + if ( $( '.masonry' ).length && 'undefined' !== typeof Masonry ) { container = document.querySelector( '.masonry' ); msnry = new Masonry( container, { @@ -52,6 +55,7 @@ }, 3000 ); } + $( '.slider-arrow-controls' ).flexslider({ controlNav: false }); diff --git a/assets/js/widget.js b/assets/js/widget.js index d358d2d..85d0313 100644 --- a/assets/js/widget.js +++ b/assets/js/widget.js @@ -1,70 +1,104 @@ jQuery( document ).ready( function() {// jscs:ignore validateLineBreaks - /* Clonning of Logo Client Widgets */ - jQuery( document ).on( 'widget-added', function() { - shapelySort(); - shapelyCreateColorPicker(); - } ); - jQuery( document ).on( 'widget-updated', function() { - shapelySort(); - shapelyCreateColorPicker(); - } ); - - shapelySort(); - shapelyCreateColorPicker(); - - /* Client widget sorting and cloning*/ - /* Font awsome selector */ - jQuery( 'select.shapely-icon' ).change( function() { - jQuery( this ).siblings( 'span' ).removeClass().addClass( 'fa ' + jQuery( this ).val() ); - } ); - - /* - * Function for sorting - */ - function shapelySort() { - jQuery( '.client-sortable' ).sortable( { - handle: '.logo_heading' - } ).bind( 'sortupdate', function() { - var index = 0, img; - var attrname = jQuery( this ).find( 'input:first' ).attr( 'name' ); - var attrbase = attrname.substring( 0, attrname.indexOf( '][' ) + 1 ); - var attrid = jQuery( this ).find( 'input:first' ).attr( 'id' ); - var attrbaseid = attrid.substring( 0, attrid.indexOf( '-client_logo' ) + 13 ); - - jQuery( this ).find( 'li' ).each( function() { - jQuery( this ).find( '.count' ).html( index + 1 ); - jQuery( this ).find( '.image-id' ).attr( 'id', attrbaseid + index ).attr( 'name', attrbase + '[client_logo][img]' + '[' + index + ']' ); - jQuery( this ).find( '.shapely-media-control' ).attr( 'data-delegate-container', attrbaseid + index ); - jQuery( this ).find( 'img' ).attr( 'id', 'link-' + index ).attr( 'name', attrbase + '[client_logo][link]' + '[' + index + ']' ).trigger( 'change' ); - index++; - } ); - } ); - - /* Cloning */ - jQuery( '.clone-wrapper' ).cloneya().on( 'after_append.cloneya after_delete.cloneya', function( toClone, newClone ) { - var img = jQuery( newClone ).next( 'li' ).find( 'img' ); - jQuery( '.client-sortable' ).trigger( 'sortupdate' ); - img.attr( 'src', img.attr( 'data-default' ) ); - } ); - - } - - function shapelyCreateColorPicker() { - var context = jQuery( '#widgets-right' ); - var colorPickers = context.find( '.shapely-color-picker' ); - if ( colorPickers.length > 0 ) { - jQuery.each( colorPickers, function() { - if ( ! jQuery( this ).hasClass( 'wp-color-picker' ) ) { - jQuery( this ).wpColorPicker( { - change: function( $this, ui ) { - var color = jQuery( $this.target ).wpColorPicker( 'color' ); - jQuery( $this.target ).val( color ).trigger( 'change' ); - } - } ); - } - } ); - } - } + 'use strict'; + + /* Clonning of Logo Client Widgets */ + jQuery( document ).on( 'widget-added widget-updated', function( e, widget ) { + shapelySort(); + shapelyCreateColorPicker(); + var context = jQuery( widget ).find( '.shapely-editor-container' ); + jQuery( context ).each( function() { + shapelyCompanion.textEditor.init( jQuery( this ) ); + } ); + } ); + + shapelySort(); + shapelyCreateColorPicker(); + + /* Client widget sorting and cloning*/ + /* Font awsome selector */ + jQuery( 'select.shapely-icon' ).change( function() { + jQuery( this ).siblings( 'span' ).removeClass().addClass( 'fa ' + jQuery( this ).val() ); + } ); + + /* + * Function for sorting + */ + function shapelySort() { + jQuery( '.client-sortable' ).sortable( { + handle: '.logo_heading' + } ).bind( 'sortupdate', function() { + var index = 0, img; + var attrname = jQuery( this ).find( 'input:first' ).attr( 'name' ); + var attrbase = attrname.substring( 0, attrname.indexOf( '][' ) + 1 ); + var attrid = jQuery( this ).find( 'input:first' ).attr( 'id' ); + var attrbaseid = attrid.substring( 0, attrid.indexOf( '-client_logo' ) + 13 ); + + jQuery( this ).find( 'li' ).each( function() { + jQuery( this ).find( '.count' ).html( index + 1 ); + jQuery( this ).find( '.image-id' ).attr( 'id', attrbaseid + index ).attr( 'name', attrbase + '[client_logo][img]' + '[' + index + ']' ); + jQuery( this ).find( '.shapely-media-control' ).attr( 'data-delegate-container', attrbaseid + index ); + jQuery( this ).find( 'img' ).attr( 'id', 'link-' + index ).attr( 'name', attrbase + '[client_logo][link]' + '[' + index + ']' ).trigger( 'change' ); + index++; + } ); + } ); + + /* Cloning */ + jQuery( '.clone-wrapper' ).cloneya().on( 'after_append.cloneya after_delete.cloneya', function( toClone, newClone ) { + var img = jQuery( newClone ).next( 'li' ).find( 'img' ); + jQuery( '.client-sortable' ).trigger( 'sortupdate' ); + img.attr( 'src', img.attr( 'data-default' ) ); + } ); + + } + + function shapelyCreateColorPicker() { + var context = jQuery( '#widgets-right' ); + var colorPickers = context.find( '.shapely-color-picker' ); + if ( colorPickers.length > 0 ) { + jQuery.each( colorPickers, function() { + if ( !jQuery( this ).hasClass( 'wp-color-picker' ) ) { + jQuery( this ).wpColorPicker( { + change: function( $this, ui ) { + var color = jQuery( $this.target ).wpColorPicker( 'color' ); + jQuery( $this.target ).val( color ).trigger( 'change' ); + } + } ); + } + } ); + } + } + + var shapelyCompanion = {}; + shapelyCompanion.textEditor = { + init: function( selector ) { + var context = jQuery( selector ), + editorId = jQuery( context.find( 'textarea' ) ).attr( 'id' ); + + if ( tinymce.get( editorId ) ) { + wp.editor.remove( editorId ); + } + + wp.editor.initialize( editorId, { + tinymce: { + wpautop: true, + rows: 7, + setup: function( editor ) { + editor.on( 'change', function() { + editor.save(); + jQuery( editor.getElement() ).trigger( 'change' ); + } ); + } + }, + quicktags: true + } ); + } + }; + + jQuery( '.shapely-editor-container' ).each( function() { + shapelyCompanion.textEditor.init( jQuery( this ) ); + } ); } ); + + diff --git a/inc/widgets/class-shapely-categories.php b/inc/widgets/class-shapely-categories.php index 72e8459..4c4767a 100644 --- a/inc/widgets/class-shapely-categories.php +++ b/inc/widgets/class-shapely-categories.php @@ -108,7 +108,7 @@ class="widefat"/>

-
+
diff --git a/inc/widgets/class-shapely-home-call-for-action.php b/inc/widgets/class-shapely-home-call-for-action.php index 48d4142..c4a788c 100644 --- a/inc/widgets/class-shapely-home-call-for-action.php +++ b/inc/widgets/class-shapely-home-call-for-action.php @@ -66,13 +66,15 @@ function form( $instance ) { } ?> -

- ' . wp_kses_post( $title ) . ''; - } + if ( '' != $title ) { + echo '

' . wp_kses_post( $title ) . '

'; + } - if ( '' != $body_content ) { - echo '

' . wp_kses_post( $body_content ) . '

'; - } + if ( '' != $body_content ) { + echo '

' . wp_kses_post( $body_content ) . '

'; + } - ?> + ?>
@@ -147,31 +147,33 @@ function form( $instance ) { ?> -

+

+ + name="get_field_name( 'title' ) ); ?>" + id="get_field_id( 'title' ) ); ?>" + class="widefat" />

-

+

+ + id="get_field_id( 'body_content' ) ); ?>" + class="widefat">

- + + name="get_field_name( 'image_src' ) ); ?>" + id="get_field_id( 'image_src' ) ); ?>" + value="" + class="image-id blazersix-media-control-target"> @@ -190,7 +192,7 @@ class="image-id blazersix-media-control-target"> $forms_args = array( 'post_type' => 'wpcf7_contact_form', 'post_status' => 'publish', - 'posts_per_page' => -1, + 'posts_per_page' => - 1, ); $forms = get_posts( $forms_args ); @@ -204,41 +206,46 @@ class="image-id blazersix-media-control-target"> ?>

-

+

+ + name="get_field_name( 'phone' ) ); ?>" + id="get_field_id( 'phone' ) ); ?>" + class="widefat" />

-

+

+ + name="get_field_name( 'email' ) ); ?>" + id="get_field_id( 'email' ) ); ?>" + class="widefat" />

-

+

+ - +

-
+
> + for="get_field_name( 'socialicons' ) ); ?>">
@@ -261,7 +268,7 @@ public function update( $new_instance, $old_instance ) { $instance['image_src'] = ( ! empty( $new_instance['image_src'] ) ) ? esc_url_raw( $new_instance['image_src'] ) : ''; $instance['body_content'] = ( ! empty( $new_instance['body_content'] ) ) ? wp_kses_post( $new_instance['body_content'] ) : ''; $instance['phone'] = ( ! empty( $new_instance['phone'] ) ) ? esc_html( $new_instance['phone'] ) : ''; - $instance['address'] = ( ! empty( $new_instance['address'] ) ) ? esc_html( $new_instance['address'] ) : ''; + $instance['address'] = ( ! empty( $new_instance['address'] ) ) ? wp_kses_post( $new_instance['address'] ) : ''; $instance['email'] = ( ! empty( $new_instance['email'] ) ) ? esc_html( $new_instance['email'] ) : ''; $instance['contactform'] = ( ! empty( $new_instance['contactform'] ) ) ? absint( $new_instance['contactform'] ) : ''; $instance['socialicons'] = ( ! empty( $new_instance['socialicons'] ) ) ? esc_html( $new_instance['socialicons'] ) : ''; @@ -270,4 +277,4 @@ public function update( $new_instance, $old_instance ) { } } -?> +?> \ No newline at end of file diff --git a/inc/widgets/class-shapely-home-parallax.php b/inc/widgets/class-shapely-home-parallax.php index 5207d9a..db848cb 100644 --- a/inc/widgets/class-shapely-home-parallax.php +++ b/inc/widgets/class-shapely-home-parallax.php @@ -200,12 +200,13 @@ class="image-id blazersix-media-control-target">

-

-
+
diff --git a/inc/widgets/class-shapely-home-portfolio.php b/inc/widgets/class-shapely-home-portfolio.php index 0cee0c1..b7999f5 100644 --- a/inc/widgets/class-shapely-home-portfolio.php +++ b/inc/widgets/class-shapely-home-portfolio.php @@ -161,7 +161,7 @@ function form( $instance ) {

-

+

+ id="get_field_id( 'body_content' ) ); ?>" + class="widefat">

-
@@ -145,21 +144,21 @@ class="widefat"> for="get_field_id( 'title' . $i ) ); ?>"> + name="get_field_name( 'title' . $i ) ); ?>" + id="get_field_id( 'title' . $i ) ); ?>" + class="widefat" />

- get_fontawesome_icons(); - $icon = ( isset( $instance[ 'icon' . $i ] ) && '' != $instance[ 'icon' . $i ] ) ? esc_html( $instance[ 'icon' . $i ] ) : ''; - ?> + $get_fontawesome_icons = $this->get_fontawesome_icons(); + $icon = ( isset( $instance[ 'icon' . $i ] ) && '' != $instance[ 'icon' . $i ] ) ? esc_html( $instance[ 'icon' . $i ] ) : ''; + ?> + style="font-size: 24px;vertical-align: middle;margin-left: 10px;">

-

+

+ + id="get_field_id( 'body_content' . $i ) ); ?>" + class="widefat"> + +

Date: Wed, 25 Apr 2018 21:10:44 +0300 Subject: [PATCH 03/12] version bump --- shapely-companion.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shapely-companion.php b/shapely-companion.php index ea364b7..77b480c 100644 --- a/shapely-companion.php +++ b/shapely-companion.php @@ -3,7 +3,7 @@ * Plugin Name: Shapely Companion * Plugin URI: https://colorlib.com/wp/themes/shapely/ * Description: Shapely Companion is a companion plugin for Shapely theme. - * Version: 1.2.1 + * Version: 1.2.2 * Author: Colorlib * Author URI: https://colorlib.com * License: GPL-2.0+ From ad9f732232da0eb0d752a125d4416b1904d9bd82 Mon Sep 17 00:00:00 2001 From: cristianraiber Date: Wed, 25 Apr 2018 21:11:21 +0300 Subject: [PATCH 04/12] readme.txt verison bump as well --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index a2d074b..e18c02a 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: colorlibplugins, silkalns Tags: woocommerce, widgets, plugin, demo, companion, home page, one page, parallax, social, portfolio, projects Requires at least: 3.8 Tested up to: 4.8 -Stable tag: 1.2.1 +Stable tag: 1.2.2 License: GPLv3 or later License URI: http://www.gnu.org/licenses/gpl-3.0.html From c87dd7f98587c90bff2e337600cb426f97e58bfa Mon Sep 17 00:00:00 2001 From: cristianraiber Date: Fri, 27 Apr 2018 13:43:43 +0300 Subject: [PATCH 05/12] PHPCS fixes --- .jshintrc | 5 +- assets/js/previewer.js | 39 +- assets/js/vendor/jquery-cloneya.js | 268 +++++++------- assets/js/vendor/player.js | 336 ++++++++++-------- assets/js/vendor/player.min.js | 4 +- assets/js/widget.js | 172 ++++----- inc/shapely-widgets.php | 12 +- inc/widgets/class-shapely-categories.php | 74 ++-- .../class-shapely-home-call-for-action.php | 109 +++--- inc/widgets/class-shapely-home-clients.php | 164 ++++----- inc/widgets/class-shapely-home-contact.php | 158 ++++---- inc/widgets/class-shapely-home-features.php | 188 +++++----- inc/widgets/class-shapely-home-parallax.php | 240 ++++++------- inc/widgets/class-shapely-home-portfolio.php | 203 ++++++----- .../class-shapely-home-testimonials.php | 171 +++++---- inc/widgets/class-shapely-page-content.php | 35 +- inc/widgets/class-shapely-page-title.php | 7 +- inc/widgets/class-shapely-recent-posts.php | 87 +++-- inc/widgets/class-shapely-social.php | 43 ++- inc/widgets/class-shapely-video.php | 226 +++++------- readme.txt | 8 +- 21 files changed, 1278 insertions(+), 1271 deletions(-) mode change 100644 => 100755 assets/js/vendor/player.js mode change 100644 => 100755 assets/js/vendor/player.min.js diff --git a/.jshintrc b/.jshintrc index ab424ea..363ec09 100644 --- a/.jshintrc +++ b/.jshintrc @@ -15,10 +15,11 @@ "unused": false, "browser": true, "globals": { + "$": false, "jQuery": false, "wp": false, "shapelyCompanion": false, - "wpNavMenu" : false, - "Masonry" : false + "wpNavMenu": false, + "Masonry": false } } diff --git a/assets/js/previewer.js b/assets/js/previewer.js index 7a5c5bc..3301e31 100644 --- a/assets/js/previewer.js +++ b/assets/js/previewer.js @@ -1,14 +1,15 @@ (function( $ ) {// jscs:ignore validateLineBreaks - $( document ).ready(function() { - if ( 'undefined' === typeof wp || ! wp.customize || ! wp.customize.selectiveRefresh ) { + + 'use strict'; + + $( document ).ready( function() { + if ( 'undefined' === typeof wp || !wp.customize || !wp.customize.selectiveRefresh ) { return; } - var illdyCompanion = {}; - wp.customize.selectiveRefresh.bind( 'widget-updated', function( placement ) { - var maxHeight, container, msnry, element; - $( '.logo-carousel' ).flexslider({ + var maxHeight, container, msnry, element; + $( '.logo-carousel' ).flexslider( { minItems: 1, maxItems: 4, move: 1, @@ -19,7 +20,7 @@ slideshowSpeed: 3000, directionNav: false, controlNav: false - }); + } ); if ( 'function' === typeof $( '.parallax-window' ).parallax ) { $( '.parallax-window' ).parallax(); @@ -29,18 +30,18 @@ container = document.querySelector( '.masonry' ); msnry = new Masonry( container, { itemSelector: '.masonry-item' - }); + } ); maxHeight = -1; msnry.on( 'layoutComplete', function() { var element = jQuery( msnry.element ), - cols = element.find( '.masonry-item img' ); + cols = element.find( '.masonry-item img' ); jQuery.each( cols, function() { if ( parseInt( jQuery( this ).attr( 'height' ), 10 ) > maxHeight ) { maxHeight = parseInt( jQuery( this ).attr( 'height' ), 10 ); } - }); + } ); - }); + } ); msnry.layout(); element = jQuery( msnry.element ); @@ -48,26 +49,26 @@ jQuery( element ).css( 'height', maxHeight + 'px' ); } - if ( 0 !== jQuery( '.testimonial-section' ).length ) { + if ( 0 !== jQuery( '.testimonial-section' ).length ) { testimonialHeight(); - setTimeout(function() { + setTimeout( function() { testimonialHeight(); }, 3000 ); } - - $( '.slider-arrow-controls' ).flexslider({ + $( '.slider-arrow-controls' ).flexslider( { controlNav: false - }); + } ); + /* * Resetting testimonial parallax height */ function testimonialHeight() { - var testimonialHeight = jQuery( '.testimonial-section .parallax-window .container' ).outerHeight() + 150; + var testimonialHeight = jQuery( '.testimonial-section .parallax-window .container' ).outerHeight() + 150; jQuery( '.testimonial-section .parallax-window' ).css( 'height', testimonialHeight ); jQuery( window ).trigger( 'resize' ).trigger( 'scroll' ); } - }); - }); + } ); + } ); })( jQuery ); diff --git a/assets/js/vendor/jquery-cloneya.js b/assets/js/vendor/jquery-cloneya.js index 854d65c..39f6a95 100644 --- a/assets/js/vendor/jquery-cloneya.js +++ b/assets/js/vendor/jquery-cloneya.js @@ -5,26 +5,26 @@ * License GNU/GPL & MIT */ -(function ($) { +(function( $ ) { "use strict"; var name = "cloneya", defaults = { - cloneThis : '.toclone', - cloneButton : '.clone', - deleteButton : '.delete', + cloneThis: '.toclone', + cloneButton: '.clone', + deleteButton: '.delete', clonePosition: 'after', - minimum : 1, + minimum: 1, // renaming limit - maximum : 999, //setting it to a high number, by default + maximum: 999, //setting it to a high number, by default //limit: 999, - valueClone : false, - dataClone : false, - deepClone : false, - serializeID : true, - ignore : 'label.error', + valueClone: false, + dataClone: false, + deepClone: false, + serializeID: true, + ignore: 'label.error', preserveChildCount: false }; @@ -53,12 +53,11 @@ * @param {Boolean} options.serializeID - Whether to serialize the IDs, automatically * @param {String} options.ignore - Selectors for clonables' elements that should not be cloned * @param {Boolean} options.defaultRender - Start with this number of clones, by default - * @param {Boolean} options.preserveChildCount - whether to preserve the initial number of clone's child clones, - * works with nesting as well. + * @param {Boolean} options.preserveChildCount - whether to preserve the initial number of clone's child clones, works with nesting as well. * * @returns {_L13.CloneYa} */ - function CloneYa(element, options) { + function CloneYa( element, options ) { /** * regex for recalculating the ids * @@ -66,10 +65,9 @@ */ this.regex = /^(.*)(\d)+$/i; - this.elem = element; - this.$elem = $(element); + this.$elem = $( element ); this.elemClass = name + '-wrap'; @@ -80,7 +78,6 @@ */ //var elem = $(element); - /** * Support deprecated parameters */ @@ -95,124 +92,119 @@ * * @type @exp;$@call;extend */ - this.config = $.extend({}, defaults, options); - + this.config = $.extend( {}, defaults, options ); /** * * @type @exp;elem@call;closestChild */ - this.clones = this.$elem.closestChild(this.config.cloneThis); + this.clones = this.$elem.closestChild( this.config.cloneThis ); this.init(); } CloneYa.prototype = { - init : function () { + init: function() { var $this = this; - // add our classes - $this.$elem.addClass($this.elemClass); - $this.clones.addClass(name); + $this.$elem.addClass( $this.elemClass ); + $this.clones.addClass( name ); // save the sibling count into data attr - $this.clones.data('initialCount', $this.clones.length); + $this.clones.data( 'initialCount', $this.clones.length ); //Now, what if the clone button and delete button are not contained in //the clonable? // add a click handler for the clone buttons - $this.$elem.on('click.' + name, $this.config.cloneThis + '>' + $this.config.cloneButton, function (event) { + $this.$elem.on( 'click.' + name, $this.config.cloneThis + '>' + $this.config.cloneButton, function( event ) { event.preventDefault(); event.stopPropagation(); - var toClone = $(this).closest($this.config.cloneThis); + var toClone = $( this ).closest( $this.config.cloneThis ); // this is just a wrapper for the custom clone event - $this.$elem.triggerAll('clone_clone clone.' + name, [ toClone ]); - }); - + $this.$elem.triggerAll( 'clone_clone clone.' + name, [ toClone ] ); + } ); // the custom clone event - $this.$elem.on('clone.' + name, function (event, toClone) { - - $this._cloneAndAppend(toClone); - - }); + $this.$elem.on( 'clone.' + name, function( event, toClone ) { + if ( event.namespace === name ) { + $this._cloneAndAppend( toClone ); + } + } ); // click handler for delete button - $this.$elem.on('click.' + name, $this.config.cloneThis + '>' + $this.config.deleteButton, function (event) { + $this.$elem.on( 'click.' + name, $this.config.cloneThis + '>' + $this.config.deleteButton, function( event ) { event.preventDefault(); event.stopPropagation(); - var toDelete = $(this).closest($this.config.cloneThis); + var toDelete = $( this ).closest( $this.config.cloneThis ); // just a wrapper for delclone event - $this.$elem.triggerAll('clone_delete delete.' + name, [ toDelete ]); - }); + $this.$elem.triggerAll( 'clone_delete delete.' + name, [ toDelete ] ); + } ); // the delete clone event - $this.$elem.on('delete.' + name, function (event, toDelete) { + $this.$elem.on( 'delete.' + name, function( event, toDelete ) { // get the count of all the sibling clones /** * * @type @exp;$todelete@call;closest@call;closestChild@pro;length */ - var cloneCount = toDelete.closest('.' + $this.elemClass).closestChild($this.config.cloneThis).length; + var cloneCount = toDelete.closest( '.' + $this.elemClass ).closestChild( $this.config.cloneThis ).length; if ( cloneCount > $this.config.minimum ) { // trigger hook - $this.$elem.triggerAll('clone_before_delete before_delete.' + name, [ toDelete, cloneCount ]); - $this.$elem.triggerHandler('remove.' + name, [ toDelete ]); - $this.$elem.triggerAll('clone_after_delete after_delete.' + name); + $this.$elem.triggerAll( 'clone_before_delete before_delete.' + name, [ toDelete, cloneCount ] ); + $this.$elem.triggerHandler( 'remove.' + name, [ toDelete ] ); + $this.$elem.triggerAll( 'clone_after_delete after_delete.' + name ); } else { - $this.$elem.triggerHandler('minimum.' + name, $this.config.minimum, [ toDelete ]); - + $this.$elem.triggerHandler( 'minimum.' + name, $this.config.minimum, [ toDelete ] ); // First clone form can't be deleted, but the values should be removed from first form // is this expected behaviour? especially since we use minimum? - toDelete.find('input, textarea, select').each(function () { - $this._clearForm($(this)); - }); + toDelete.find( 'input, textarea, select' ).each( function() { + $this._clearForm( $( this ) ); + } ); } - }); + } ); + $this.$elem.on( 'remove.' + name, function( event, toDelete ) { + $( toDelete ).remove(); - $this.$elem.on('remove.' + name, function (event, toDelete) { - $(toDelete).remove(); - - }); + } ); }, - _clean : function () { + _clean: function() { var $this = this; - $this.$elem.removeClass(name + '-wrap'); - $this.clones.removeClass(name); - $this.$elem.off('click.' + name, $this.config.cloneThis + '>' + $this.config.cloneButton); - $this.$elem.off('click.' + name, $this.config.cloneThis + '>' + $this.config.deleteButton); - $this.$elem.off('clone_clone clone_delete clone_before_delete clone.' + name + ' delete.' + name + ' before_delete.' + name); + $this.$elem.removeClass( name + '-wrap' ); + $this.clones.removeClass( name ); + $this.$elem.off( 'click.' + name, $this.config.cloneThis + '>' + $this.config.cloneButton ); + $this.$elem.off( 'click.' + name, $this.config.cloneThis + '>' + $this.config.deleteButton ); + $this.$elem.off( 'clone_clone clone_delete clone_before_delete clone.' + name + ' delete.' + name + ' before_delete.' + name ); }, - destroy : function () { + destroy: function() { this._clean(); - this.$elem.removeData(name); + this.$elem.removeData( name ); }, - getOption : function () { + getOption: function() { return this.config; }, - setOption : function (lateOptions) { - $.extend(this.config, lateOptions || {}); + setOption: function( lateOptions ) { + $.extend( this.config, lateOptions || {} ); this._clean(); this.init(); }, - _cloneAndAppend: function (toClone) { + _cloneAndAppend: function( toClone ) { // get the count of all the sibling clones @@ -220,52 +212,50 @@ * * @type @exp;$toclone@call;closest@call;closestChild@pro;length */ - var cloneCount = toClone.closest('.' + this.elemClass).closestChild(this.config.cloneThis).length; - + var cloneCount = toClone.closest( '.' + this.elemClass ).closestChild( this.config.cloneThis ).length; // check if we've reached the maximum limit if ( cloneCount < this.config.maximum ) { // trigger a custom event for hooking in - this.$elem.triggerAll('clone_before_clone before_clone.' + name, [ toClone ]); - - var newClone = this._cloneItem(toClone); + this.$elem.triggerAll( 'clone_before_clone before_clone.' + name, [ toClone ] ); + var newClone = this._cloneItem( toClone ); // trigger custom event on the original element - this.$elem.triggerAll('clone_after_clone after_clone.' + name, [ toClone, newClone ]); + this.$elem.triggerAll( 'clone_after_clone after_clone.' + name, [ toClone, newClone ] ); // add to our clones object - this.clones.add(newClone); + this.clones.add( newClone ); // trigger custom event on the new clone - this.$elem.triggerAll('clone_before_append before_append.' + name, [ toClone, newClone ]); + this.$elem.triggerAll( 'clone_before_append before_append.' + name, [ toClone, newClone ] ); // get the position where the clone has to be added // and add the newclone if ( this.config.clonePosition !== 'after' ) { - toClone.before(newClone); + toClone.before( newClone ); } else { - toClone.after(newClone); + toClone.after( newClone ); } if ( this.config.ignore ) { - newClone.find(this.config.ignore).remove(); + newClone.find( this.config.ignore ).remove(); } // reformat the id attributes this._redoIDs(); // trigger custom event for hooking - this.$elem.triggerAll('clone_after_append after_append.' + name, [ toClone, newClone ]); + this.$elem.triggerAll( 'clone_after_append after_append.' + name, [ toClone, newClone ] ); } else { // trigger a custom event for hooking - this.$elem.triggerAll('clone_limit maximum.' + name, this.config.maximum, [ toClone ]); + this.$elem.triggerAll( 'clone_limit maximum.' + name, this.config.maximum, [ toClone ] ); } }, - _cloneItem : function (toClone) { + _cloneItem: function( toClone ) { var $this = this; // clone it @@ -273,56 +263,56 @@ * * @type @exp;$toclone@call;clone */ - var newClone = toClone.clone($this.config.dataClone, $this.config.deepClone); + var newClone = toClone.clone( $this.config.dataClone, $this.config.deepClone ); // we want to preserve the initial child count if ( $this.config.preserveChildCount !== false ) { // the child count only needs preservation if they are clonable. - var originalChildren = toClone.find('.' + name + '-wrap'); + var originalChildren = toClone.find( '.' + name + '-wrap' ); // for each wrapper - newClone.find('.' + name + '-wrap').each(function (index) { + newClone.find( '.' + name + '-wrap' ).each( function( index ) { /** * * @type @call;jquery-cloneya_L8.$@call;closestChild */ - var inNewClone = $(this).closestChild('.' + name); + var inNewClone = $( this ).closestChild( '.' + name ); - var inOriginal = $(originalChildren[ index ]).closestChild('.' + name); + var inOriginal = $( originalChildren[ index ] ).closestChild( '.' + name ); /** * * @type @exp;inOriginal@call;data */ - var originalCount = inOriginal.data('initialCount'); + var originalCount = inOriginal.data( 'initialCount' ); /** * * @type @exp;inNewClone@call;slice */ - var $extra = inNewClone.slice(originalCount, inNewClone.length); + var $extra = inNewClone.slice( originalCount, inNewClone.length ); $extra.remove(); - inNewClone.data('initial-count', originalCount); - }); + inNewClone.data( 'initial-count', originalCount ); + } ); } // get the form input - newClone.find('input, textarea, select').each(function () { + newClone.find( 'input, textarea, select' ).each( function() { // check if the values need to be copied, if not empty them - $this._clearForm($(this)); + $this._clearForm( $( this ) ); // removed the portion taking care of the index // each case is specific and I'd rather leave it to the developer // custom event hook for index handling - $this.$elem.triggerAll('clone_form_input form_input.' + name, [ $(this), toClone, newClone ]); - }); + $this.$elem.triggerAll( 'clone_form_input form_input.' + name, [ $( this ), toClone, newClone ] ); + } ); return newClone; @@ -335,16 +325,16 @@ * @param {type} $el * @returns {undefined} */ - _clearForm : function ($el) { + _clearForm: function( $el ) { - if ( !this.config.valueClone && !$el.hasClass('noEmpty') ) { + if ( !this.config.valueClone && !$el.hasClass( 'noEmpty' ) ) { - if ( $el.is(':checkbox') || $el.is(':radio') ) { + if ( $el.is( ':checkbox' ) || $el.is( ':radio' ) ) { - $el.prop('checked', false); + $el.prop( 'checked', false ); } else { - $el.val(''); + $el.val( '' ); } } @@ -357,7 +347,7 @@ * * @returns {undefined} */ - _redoIDs : function () { + _redoIDs: function() { var $this = this; @@ -371,9 +361,9 @@ * * @type @exp;elem@call;find@call;first@call;attr */ - var mainid = $this.$elem.find($this.config.cloneThis).first().attr('id'); + var mainid = $this.$elem.find( $this.config.cloneThis ).first().attr( 'id' ); - $this.$elem.find($this.config.cloneThis).each(function (i) { + $this.$elem.find( $this.config.cloneThis ).each( function( i ) { var j; // assign the index to a string var for appending to the ids @@ -385,63 +375,60 @@ } // first modify the clone id - if ( $(this).attr('id') ) { - $(this).attr('id', mainid + j); + if ( $( this ).attr( 'id' ) ) { + $( this ).attr( 'id', mainid + j ); } var id, nId; // take all the elements inside the clone - $(this).find('*').each(function () { + $( this ).find( '*' ).each( function() { - id = $(this).attr('id'); + id = $( this ).attr( 'id' ); if ( id ) { // match the id with the regex to get the string part // separate from the number part - var match = id.match($this.regex); + var match = id.match( $this.regex ); // if there was a number if ( match && match.length === 3 ) { // just take the string part // add the new number to it - nId = id.replace(/\d+$/, "") + j; + nId = id.replace( /\d+$/, "" ) + j; - $(this).attr('id', nId); + $( this ).attr( 'id', nId ); } else { // else there was no number, // this was earlier the first element // just add the number to its id nId = id + j; - $(this).attr('id', nId); + $( this ).attr( 'id', nId ); } } //update label - $(this).closest($this.config.cloneThis).find("label[for='" + id + "']").attr('for', nId); + $( this ).closest( $this.config.cloneThis ).find( "label[for='" + id + "']" ).attr( 'for', nId ); if ( $this.config.serializeIndex ) { - var name = $(this).attr('name'); + var name = $( this ).attr( 'name' ); // This will increment the numeric array index for cloned field names if ( name ) { - var matches = name.match(/\[([^}]+)\]/); + var matches = name.match( /\[([0-9}]+)\]/ ); if ( matches && matches.length >= 1 ) { var st = name; - name = [].map.call(st, function (s, n) { - return (!isNaN(+s) && st[ n - 1 ] === '[' && st[ n + 1 ] === ']') ? i : s; - }).join(''); + var name = st.replace( matches[ 0 ], "[" + i + "]" ); - $(this).attr('name', name); + $( this ).attr( 'name', name ); } } } - }); - }); + } ); + } ); } - }; // add the cloneya to the global object @@ -450,41 +437,40 @@ * @param {type} options * @returns {jquery-cloneya_L8.$.fn@call;each} */ - $.fn[ name ] = function (options) { + $.fn[ name ] = function( options ) { var args = arguments; if ( options === undefined || typeof options === 'object' ) { // Creates a new plugin instance, for each selected element, and // stores a reference withint the element's data - return this.each(function () { - if ( !$.data(this, name) ) { - $.data(this, name, new CloneYa(this, options)); + return this.each( function() { + if ( !$.data( this, name ) ) { + $.data( this, name, new CloneYa( this, options ) ); } - }); + } ); } else if ( typeof options === 'string' && options[ 0 ] !== '_' && options !== 'init' ) { // Call a public pluguin method (not starting with an underscore) for each // selected element. - if ( Array.prototype.slice.call(args, 1).length === 0 && $.inArray(options, $.fn[ name ].getters) !== -1 ) { + if ( Array.prototype.slice.call( args, 1 ).length === 0 && $.inArray( options, $.fn[ name ].getters ) !== -1 ) { // If the user does not pass any arguments and the method allows to // work as a getter then break the chainability so we can return a value // instead the element reference. - var instance = $.data(this[ 0 ], name); - return instance[ options ].apply(instance, Array.prototype.slice.call(args, 1)); + var instance = $.data( this[ 0 ], name ); + return instance[ options ].apply( instance, Array.prototype.slice.call( args, 1 ) ); } else { // Invoke the speficied method on each selected element - return this.each(function () { - var instance = $.data(this, name); + return this.each( function() { + var instance = $.data( this, name ); if ( instance instanceof CloneYa && typeof instance[ options ] === 'function' ) { - instance[ options ].apply(instance, Array.prototype.slice.call(args, 1)); + instance[ options ].apply( instance, Array.prototype.slice.call( args, 1 ) ); } - }); + } ); } } }; $.fn[ name ].getters = [ 'getOption' ]; - /* * jquery.closestchild 0.1.1 * @@ -497,7 +483,7 @@ * @param {type} selector * @returns {$} */ - $.fn.closestChild = function (selector) { + $.fn.closestChild = function( selector ) { var $children, $results; $children = this.children(); @@ -506,12 +492,12 @@ return $(); } - $results = $children.filter(selector); + $results = $children.filter( selector ); if ( $results.length > 0 ) { return $results; } else { - return $children.closestChild(selector); + return $children.closestChild( selector ); } }; @@ -519,14 +505,14 @@ * TriggerAll, modified from stackoverflow * http://stackoverflow.com/questions/11850625/jquery-trigger-multiple-events */ - $.fn.extend({ - triggerAll: function (events, params) { - var el = this, i, evts = events.split(' '); + $.fn.extend( { + triggerAll: function( events, params ) { + var el = this, i, evts = events.split( ' ' ); for ( i = 0; i < evts.length; i += 1 ) { - el.triggerHandler(evts[ i ], params); + el.triggerHandler( evts[ i ], params ); } return el; } - }); + } ); -})(jQuery); +})( jQuery ); \ No newline at end of file diff --git a/assets/js/vendor/player.js b/assets/js/vendor/player.js old mode 100644 new mode 100755 index 3c836bf..a90d95f --- a/assets/js/vendor/player.js +++ b/assets/js/vendor/player.js @@ -1,14 +1,107 @@ -/*! @vimeo/player v2.1.0 | (c) 2017 Vimeo | MIT License | https://github.com/vimeo/player.js */ +/*! @vimeo/player v2.6.1 | (c) 2018 Vimeo | MIT License | https://github.com/vimeo/player.js */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.Vimeo = global.Vimeo || {}, global.Vimeo.Player = factory()); }(this, (function () { 'use strict'; +/** + * @module lib/functions + */ + +/** + * Check to see this is a node environment. + * @type {Boolean} + */ +/* global global */ +var isNode = typeof global !== 'undefined' && {}.toString.call(global) === '[object global]'; + +/** + * Get the name of the method for a given getter or setter. + * + * @param {string} prop The name of the property. + * @param {string} type Either “get” or “set”. + * @return {string} + */ +function getMethodName(prop, type) { + if (prop.indexOf(type.toLowerCase()) === 0) { + return prop; + } + + return '' + type.toLowerCase() + prop.substr(0, 1).toUpperCase() + prop.substr(1); +} + +/** + * Check to see if the object is a DOM Element. + * + * @param {*} element The object to check. + * @return {boolean} + */ +function isDomElement(element) { + return element instanceof window.HTMLElement; +} + +/** + * Check to see whether the value is a number. + * + * @see http://dl.dropboxusercontent.com/u/35146/js/tests/isNumber.html + * @param {*} value The value to check. + * @param {boolean} integer Check if the value is an integer. + * @return {boolean} + */ +function isInteger(value) { + // eslint-disable-next-line eqeqeq + return !isNaN(parseFloat(value)) && isFinite(value) && Math.floor(value) == value; +} + +/** + * Check to see if the URL is a Vimeo url. + * + * @param {string} url The url string. + * @return {boolean} + */ +function isVimeoUrl(url) { + return (/^(https?:)?\/\/((player|www).)?vimeo.com(?=$|\/)/.test(url) + ); +} + +/** + * Get the Vimeo URL from an element. + * The element must have either a data-vimeo-id or data-vimeo-url attribute. + * + * @param {object} oEmbedParameters The oEmbed parameters. + * @return {string} + */ +function getVimeoUrl() { + var oEmbedParameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var id = oEmbedParameters.id; + var url = oEmbedParameters.url; + var idOrUrl = id || url; + + if (!idOrUrl) { + throw new Error('An id or url must be passed, either in an options object or as a data-vimeo-id or data-vimeo-url attribute.'); + } + + if (isInteger(idOrUrl)) { + return 'https://vimeo.com/' + idOrUrl; + } + + if (isVimeoUrl(idOrUrl)) { + return idOrUrl.replace('http:', 'https:'); + } + + if (id) { + throw new TypeError('\u201C' + id + '\u201D is not a valid video id.'); + } + + throw new TypeError('\u201C' + idOrUrl + '\u201D is not a vimeo.com url.'); +} + var arrayIndexOfSupport = typeof Array.prototype.indexOf !== 'undefined'; -var postMessageSupport = typeof window.postMessage !== 'undefined'; +var postMessageSupport = typeof window !== 'undefined' && typeof window.postMessage !== 'undefined'; -if (!arrayIndexOfSupport || !postMessageSupport) { +if (!isNode && (!arrayIndexOfSupport || !postMessageSupport)) { throw new Error('Sorry, the Vimeo Player API is not available in this browser.'); } @@ -623,7 +716,6 @@ var callbackMap = new WeakMap(); /** * Store a callback for a method or event for a player. * - * @author Brad Dougherty * @param {Player} player The player object. * @param {string} name The method or event name. * @param {(function(this:Player, *): void|{resolve: function, reject: function})} callback @@ -644,7 +736,6 @@ function storeCallback(player, name, callback) { /** * Get the callbacks for a player and event or method. * - * @author Brad Dougherty * @param {Player} player The player object. * @param {string} name The method or event name * @return {function[]} @@ -657,7 +748,6 @@ function getCallbacks(player, name) { /** * Remove a stored callback for a method or event for a player. * - * @author Brad Dougherty * @param {Player} player The player object. * @param {string} name The method or event name * @param {function} [callback] The specific callback to remove. @@ -710,7 +800,6 @@ function shiftCallbacks(player, name) { /** * Move callbacks associated with an element to another element. * - * @author Brad Dougherty * @param {HTMLElement} oldElement The old element. * @param {HTMLElement} newElement The new element. * @return {void} @@ -722,107 +811,15 @@ function swapCallbacks(oldElement, newElement) { callbackMap.delete(oldElement); } -/** - * @module lib/functions - */ - -/** - * Get the name of the method for a given getter or setter. - * - * @author Brad Dougherty - * @param {string} prop The name of the property. - * @param {string} type Either “get” or “set”. - * @return {string} - */ -function getMethodName(prop, type) { - if (prop.indexOf(type.toLowerCase()) === 0) { - return prop; - } - - return '' + type.toLowerCase() + prop.substr(0, 1).toUpperCase() + prop.substr(1); -} - -/** - * Check to see if the object is a DOM Element. - * - * @author Brad Dougherty - * @param {*} element The object to check. - * @return {boolean} - */ -function isDomElement(element) { - return element instanceof window.HTMLElement; -} - -/** - * Check to see whether the value is a number. - * - * @author Brad Dougherty - * @see http://dl.dropboxusercontent.com/u/35146/js/tests/isNumber.html - * @param {*} value The value to check. - * @param {boolean} integer Check if the value is an integer. - * @return {boolean} - */ -function isInteger(value) { - // eslint-disable-next-line eqeqeq - return !isNaN(parseFloat(value)) && isFinite(value) && Math.floor(value) == value; -} - -/** - * Check to see if the URL is a Vimeo url. - * - * @author Brad Dougherty - * @param {string} url The url string. - * @return {boolean} - */ -function isVimeoUrl(url) { - return (/^(https?:)?\/\/((player|www).)?vimeo.com(?=$|\/)/.test(url) - ); -} - -/** - * Get the Vimeo URL from an element. - * The element must have either a data-vimeo-id or data-vimeo-url attribute. - * - * @author Brad Dougherty - * @param {object} oEmbedParameters The oEmbed parameters. - * @return {string} - */ -function getVimeoUrl() { - var oEmbedParameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - var id = oEmbedParameters.id; - var url = oEmbedParameters.url; - var idOrUrl = id || url; - - if (!idOrUrl) { - throw new Error('An id or url must be passed, either in an options object or as a data-vimeo-id or data-vimeo-url attribute.'); - } - - if (isInteger(idOrUrl)) { - return 'https://vimeo.com/' + idOrUrl; - } - - if (isVimeoUrl(idOrUrl)) { - return idOrUrl.replace('http:', 'https:'); - } - - if (id) { - throw new TypeError('\u201C' + id + '\u201D is not a valid video id.'); - } - - throw new TypeError('\u201C' + idOrUrl + '\u201D is not a vimeo.com url.'); -} - /** * @module lib/embed */ -var oEmbedParameters = ['id', 'url', 'width', 'maxwidth', 'height', 'maxheight', 'portrait', 'title', 'byline', 'color', 'autoplay', 'autopause', 'loop', 'responsive']; +var oEmbedParameters = ['autopause', 'autoplay', 'background', 'byline', 'color', 'height', 'id', 'loop', 'maxheight', 'maxwidth', 'muted', 'playsinline', 'portrait', 'responsive', 'speed', 'title', 'transparent', 'url', 'width']; /** * Get the 'data-vimeo'-prefixed attributes from an element as an object. * - * @author Brad Dougherty * @param {HTMLElement} element The element. * @param {Object} [defaults={}] The default values to use. * @return {Object} @@ -844,7 +841,6 @@ function getOEmbedParameters(element) { /** * Make an oEmbed call for the specified URL. * - * @author Brad Dougherty * @param {string} videoUrl The vimeo.com url for the video. * @param {Object} [params] Parameters to pass to oEmbed. * @return {Promise} @@ -899,7 +895,6 @@ function getOEmbedData(videoUrl) { /** * Create an embed from oEmbed data inside an element. * - * @author Brad Dougherty * @param {object} data The oEmbed data. * @param {HTMLElement} element The element to put the iframe in. * @return {HTMLIFrameElement} The iframe embed. @@ -927,7 +922,6 @@ function createEmbed(_ref, element) { /** * Initialize all embeds within a specific element * - * @author Brad Dougherty * @param {HTMLElement} [parent=document] The parent element. * @return {void} */ @@ -964,7 +958,6 @@ function initializeEmbeds() { /** * Resize embeds when messaged by the player. * - * @author Brad Dougherty * @param {HTMLElement} [parent=document] The parent element. * @return {void} */ @@ -976,6 +969,7 @@ function resizeEmbeds() { return; } + // 'spacechange' is fired only on embeds with cards if (!event.data || event.data.event !== 'spacechange') { return; } @@ -987,11 +981,10 @@ function resizeEmbeds() { continue; } + // Change padding-bottom of the enclosing div to accommodate + // card carousel without distorting aspect ratio var space = iframes[i].parentElement; - - if (space && space.className.indexOf('vimeo-space') !== -1) { - space.style.paddingBottom = event.data.data[0].bottom + 'px'; - } + space.style.paddingBottom = event.data.data[0].bottom + 'px'; break; } @@ -1025,7 +1018,6 @@ function parseMessageData(data) { /** * Post a message to the specified target. * - * @author Brad Dougherty * @param {Player} player The player object to use. * @param {string} method The API method to call. * @param {object} params The parameters to send to the player. @@ -1056,7 +1048,6 @@ function postMessage(player, method, params) { /** * Parse the data received from a message event. * - * @author Brad Dougherty * @param {Player} player The player that received the message. * @param {(Object|string)} data The message data. Strings will be parsed into JSON. * @return {void} @@ -1115,7 +1106,6 @@ var Player = function () { /** * Create a Player. * - * @author Brad Dougherty * @param {(HTMLIFrameElement|HTMLElement|string|jQuery)} element A reference to the Vimeo * player iframe, and id, or a jQuery object. * @param {object} [options] oEmbed parameters to use when creating an embed in the element. @@ -1138,7 +1128,7 @@ var Player = function () { } // Find an element by ID - if (typeof element === 'string') { + if (typeof document !== 'undefined' && typeof element === 'string') { element = document.getElementById(element); } @@ -1204,7 +1194,10 @@ var Player = function () { getOEmbedData(url, params).then(function (data) { var iframe = createEmbed(data, element); + // Overwrite element with the new iframe, + // but store reference to the original element _this.element = iframe; + _this._originalElement = element; swapCallbacks(element, iframe); playerMap.set(_this.element, _this); @@ -1232,7 +1225,6 @@ var Player = function () { /** * Get a promise for a method. * - * @author Brad Dougherty * @param {string} name The API method to call. * @param {Object} [args={}] Arguments to send via postMessage. * @return {Promise} @@ -1257,6 +1249,8 @@ var Player = function () { }); postMessage(_this2, name, args); + }).catch(function (error) { + reject(error); }); }); } @@ -1264,7 +1258,6 @@ var Player = function () { /** * Get a promise for the value of a player property. * - * @author Brad Dougherty * @param {string} name The property name * @return {Promise} */ @@ -1294,7 +1287,6 @@ var Player = function () { /** * Get a promise for setting the value of a player property. * - * @author Brad Dougherty * @param {string} name The API method to call. * @param {mixed} value The value to set. * @return {Promise} @@ -1330,7 +1322,6 @@ var Player = function () { * callback with a single parameter, `data`, that contains the data for * that event. * - * @author Brad Dougherty * @param {string} eventName The name of the event. * @param {function(*)} callback The function to call when the event fires. * @return {void} @@ -1367,7 +1358,6 @@ var Player = function () { * listeners for that event if a `callback` isn’t passed, or only that * specific callback if it is passed. * - * @author Brad Dougherty * @param {string} eventName The name of the event. * @param {function} [callback] The specific callback to remove. * @return {void} @@ -1407,7 +1397,6 @@ var Player = function () { * the video is successfully loaded, or it will be rejected if it could * not be loaded. * - * @author Brad Dougherty * @param {number} id The id of the video. * @return {LoadVideoPromise} */ @@ -1430,14 +1419,15 @@ var Player = function () { * need to wait for `ready` to trigger to begin adding event listeners * or calling other methods. * - * @author Brad Dougherty * @return {ReadyPromise} */ }, { key: 'ready', value: function ready() { - var readyPromise = readyMap.get(this); + var readyPromise = readyMap.get(this) || new npo_src(function (resolve, reject) { + reject('Unknown player. Probably unloaded.'); + }); return npo_src.resolve(readyPromise); } @@ -1454,7 +1444,6 @@ var Player = function () { /** * Add a cue point to the player. * - * @author Brad Dougherty * @param {number} time The time for the cue point. * @param {object} [data] Arbitrary data to be returned with the cue point. * @return {AddCuePointPromise} @@ -1481,7 +1470,6 @@ var Player = function () { /** * Remove a cue point from the video. * - * @author Brad Dougherty * @param {string} id The id of the cue point to remove. * @return {RemoveCuePointPromise} */ @@ -1517,7 +1505,6 @@ var Player = function () { * When set via the API, the track language will not change the viewer’s * stored preference. * - * @author Brad Dougherty * @param {string} language The two‐letter language code. * @param {string} [kind] The kind of track to enable (captions or subtitles). * @return {EnableTextTrackPromise} @@ -1545,7 +1532,6 @@ var Player = function () { /** * Disable the currently-active text track. * - * @author Brad Dougherty * @return {DisableTextTrackPromise} */ @@ -1564,7 +1550,6 @@ var Player = function () { /** * Pause the video if it’s playing. * - * @author Brad Dougherty * @return {PausePromise} */ @@ -1586,7 +1571,6 @@ var Player = function () { * viewer has tapped on the play button in the player, however, you * will be able to use this function. * - * @author Brad Dougherty * @return {PlayPromise} */ @@ -1605,7 +1589,6 @@ var Player = function () { /** * Return the player to its initial state. * - * @author Brad Dougherty * @return {UnloadPromise} */ @@ -1615,6 +1598,34 @@ var Player = function () { return this.callMethod('unload'); } + /** + * Cleanup the player and remove it from the DOM + * + * It won't be usable and a new one should be constructed + * in order to do any operations. + * + * @return {Promise} + */ + + }, { + key: 'destroy', + value: function destroy() { + var _this5 = this; + + return new npo_src(function (resolve) { + readyMap.delete(_this5); + playerMap.delete(_this5.element); + if (_this5._originalElement) { + playerMap.delete(_this5._originalElement); + _this5._originalElement.removeAttribute('data-vimeo-initialized'); + } + if (_this5.element && _this5.element.nodeName === 'IFRAME') { + _this5.element.remove(); + } + resolve(); + }); + } + /** * A promise to get the autopause behavior of the video. * @@ -1626,7 +1637,6 @@ var Player = function () { /** * Get the autopause behavior for this player. * - * @author Brad Dougherty * @return {GetAutopausePromise} */ @@ -1652,7 +1662,6 @@ var Player = function () { * for doing so, we recommend that you leave autopause set to the * default (`true`). * - * @author Brad Dougherty * @param {boolean} autopause * @return {SetAutopausePromise} */ @@ -1672,7 +1681,6 @@ var Player = function () { /** * Get the color for this player. * - * @author Brad Dougherty * @return {GetColorPromise} */ @@ -1698,7 +1706,6 @@ var Player = function () { * color may fail if the owner of the video has set their embed * preferences to force a specific color. * - * @author Brad Dougherty * @param {string} color The hex or rgb color string to set. * @return {SetColorPromise} */ @@ -1728,7 +1735,6 @@ var Player = function () { /** * Get an array of the cue points added to the video. * - * @author Brad Dougherty * @return {GetCuePointsPromise} */ @@ -1747,7 +1753,6 @@ var Player = function () { /** * Get the current playback position in seconds. * - * @author Brad Dougherty * @return {GetCurrentTimePromise} */ @@ -1774,7 +1779,6 @@ var Player = function () { * to as close to that time as possible. The exact time will be the * fulfilled value of the promise. * - * @author Brad Dougherty * @param {number} currentTime * @return {SetCurrentTimePromise} */ @@ -1796,7 +1800,6 @@ var Player = function () { * nearest second before playback begins, and to the nearest thousandth * of a second after playback begins. * - * @author Brad Dougherty * @return {GetDurationPromise} */ @@ -1816,7 +1819,6 @@ var Player = function () { * Get the ended state of the video. The video has ended if * `currentTime === duration`. * - * @author Brad Dougherty * @return {GetEndedPromise} */ @@ -1835,7 +1837,6 @@ var Player = function () { /** * Get the loop state of the player. * - * @author Brad Dougherty * @return {GetLoopPromise} */ @@ -1855,7 +1856,6 @@ var Player = function () { * Set the loop state of the player. When set to `true`, the player * will start over immediately once playback ends. * - * @author Brad Dougherty * @param {boolean} loop * @return {SetLoopPromise} */ @@ -1875,7 +1875,6 @@ var Player = function () { /** * Get the paused state of the player. * - * @author Brad Dougherty * @return {GetLoopPromise} */ @@ -1885,6 +1884,46 @@ var Player = function () { return this.get('paused'); } + /** + * A promise to get the playback rate of the player. + * + * @promise GetPlaybackRatePromise + * @fulfill {number} The playback rate of the player on a scale from 0.5 to 2. + */ + /** + * Get the playback rate of the player on a scale from `0.5` to `2`. + * + * @return {GetPlaybackRatePromise} + */ + + }, { + key: 'getPlaybackRate', + value: function getPlaybackRate() { + return this.get('playbackRate'); + } + + /** + * A promise to set the playbackrate of the player. + * + * @promise SetPlaybackRatePromise + * @fulfill {number} The playback rate was set. + * @reject {RangeError} The playback rate was less than 0.5 or greater than 2. + */ + /** + * Set the playback rate of the player on a scale from `0.5` to `2`. When set + * via the API, the playback rate will not be synchronized to other + * players or stored as the viewer's preference. + * + * @param {number} playbackRate + * @return {SetPlaybackRatePromise} + */ + + }, { + key: 'setPlaybackRate', + value: function setPlaybackRate(playbackRate) { + return this.set('playbackRate', playbackRate); + } + /** * A promise to get the text tracks of a video. * @@ -1894,7 +1933,6 @@ var Player = function () { /** * Get an array of the text tracks that exist for the video. * - * @author Brad Dougherty * @return {GetTextTracksPromise} */ @@ -1913,7 +1951,6 @@ var Player = function () { /** * Get the `