- Platinum Partners
+
- Representing Magento's highest level of partner engagement,
- Magento Platinum Partners have established themselves as
- leaders and innovators of key products and services designed
- to help merchants and brands grow their business. Magento
- reserves the Platinum level for select trusted partners that
- are committed to offering integrations of commerce features,
- functions, and tools, as well as back-end systems and operations,
- to extend and enhance the power of the Magento commerce platform.
+
- Featured Platinum Partners
+
@@ -30,19 +29,18 @@
-
Magento Marketplace
+
- Extensions and Themes are an essential component of the Magento
- Ecosystem. Please visit the Magento Marketplace
- to see the latest innovations that developers
- have created to enhance your Magento Store.
+
- Visit Magento Marketplaces
+
diff --git a/app/code/Magento/Marketplace/view/adminhtml/templates/partners.phtml b/app/code/Magento/Marketplace/view/adminhtml/templates/partners.phtml
index ae31e3005513a..7787b9d33a47d 100644
--- a/app/code/Magento/Marketplace/view/adminhtml/templates/partners.phtml
+++ b/app/code/Magento/Marketplace/view/adminhtml/templates/partners.phtml
@@ -23,11 +23,11 @@ $partners = $block->getPartners();
escapeHtml($partner['description']);?>
- Read More
+
- Partner Page
+
@@ -35,6 +35,6 @@ $partners = $block->getPartners();
- No partners were found
+
diff --git a/app/code/Magento/Multishipping/view/frontend/layout/multishipping_checkout.xml b/app/code/Magento/Multishipping/view/frontend/layout/multishipping_checkout.xml
index 097574d310747..46ec2dcccadd7 100644
--- a/app/code/Magento/Multishipping/view/frontend/layout/multishipping_checkout.xml
+++ b/app/code/Magento/Multishipping/view/frontend/layout/multishipping_checkout.xml
@@ -7,6 +7,24 @@
-->
+
+
+
+ -
+
-
+
-
+
-
+
- Magento_Captcha/js/view/checkout/loginCaptcha
+ - additional-login-form-fields
+ - user_login
+ - authenticationPopup
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Payment/view/frontend/web/transparent.js b/app/code/Magento/Payment/view/frontend/web/transparent.js
index 66b3203d7bc51..bbbd6ce1b3aa2 100644
--- a/app/code/Magento/Payment/view/frontend/web/transparent.js
+++ b/app/code/Magento/Payment/view/frontend/web/transparent.js
@@ -46,6 +46,11 @@ define([
.off('click')
.on('click', $.proxy(this._placeOrderHandler, this));
}
+
+ this.element.validation();
+ $('[data-container="' + this.options.gateway + '-cc-number"]').on('focusout', function () {
+ $(this).valid();
+ });
},
/**
diff --git a/app/code/Magento/ProductVideo/Block/Adminhtml/Product/Edit/NewVideo.php b/app/code/Magento/ProductVideo/Block/Adminhtml/Product/Edit/NewVideo.php
index fbc2132db4999..473e44373b7ed 100644
--- a/app/code/Magento/ProductVideo/Block/Adminhtml/Product/Edit/NewVideo.php
+++ b/app/code/Magento/ProductVideo/Block/Adminhtml/Product/Edit/NewVideo.php
@@ -12,11 +12,21 @@
*/
class NewVideo extends \Magento\Backend\Block\Widget\Form\Generic
{
+ /**
+ * Anchor is product video
+ */
+ const PATH_ANCHOR_PRODUCT_VIDEO = 'catalog_product_video-link';
+
/**
* @var \Magento\ProductVideo\Helper\Media
*/
protected $mediaHelper;
+ /**
+ * @var \Magento\Framework\UrlInterface
+ */
+ protected $urlBuilder;
+
/**
* @var \Magento\Framework\Json\EncoderInterface
*/
@@ -24,22 +34,23 @@ class NewVideo extends \Magento\Backend\Block\Widget\Form\Generic
/**
* @param \Magento\Backend\Block\Template\Context $context
- * @param \Magento\ProductVideo\Helper\Media $mediaHelper
- * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\Data\FormFactory $formFactory
+ * @param \Magento\ProductVideo\Helper\Media $mediaHelper
+ * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Data\FormFactory $formFactory,
- \Magento\Framework\Json\EncoderInterface $jsonEncoder,
\Magento\ProductVideo\Helper\Media $mediaHelper,
+ \Magento\Framework\Json\EncoderInterface $jsonEncoder,
array $data = []
) {
parent::__construct($context, $registry, $formFactory, $data);
$this->mediaHelper = $mediaHelper;
+ $this->urlBuilder = $context->getUrlBuilder();
$this->jsonEncoder = $jsonEncoder;
$this->setUseContainer(true);
}
@@ -104,7 +115,8 @@ protected function _prepareForm()
'title' => __('Url'),
'required' => true,
'name' => 'video_url',
- 'note' => 'Youtube or Vimeo supported',
+ 'note' => $this->getNoteVideoUrl(),
+
]
);
@@ -158,7 +170,7 @@ protected function _prepareForm()
'label' => '',
'title' => __('Get Video Information'),
'name' => 'new_video_get',
- 'value' => 'Get Video Information',
+ 'value' => __('Get Video Information'),
'class' => 'action-default'
]
);
@@ -248,4 +260,38 @@ protected function addMediaRoleAttributes(Fieldset $fieldset)
}
return $this;
}
+
+ /**
+ * Get note for video url
+ *
+ * @return \Magento\Framework\Phrase
+ */
+ protected function getNoteVideoUrl()
+ {
+ $result = __('YouTube and Vimeo supported.');
+ if ($this->mediaHelper->getYouTubeApiKey() === null) {
+ $result = __(
+ 'Vimeo supported. '
+ . 'To add YouTube video, please enter YouTube API Key first.',
+ $this->getConfigApiKeyUrl()
+ );
+ }
+ return $result;
+ }
+
+ /**
+ * Get url for config params
+ *
+ * @return string
+ */
+ protected function getConfigApiKeyUrl()
+ {
+ return $this->urlBuilder->getUrl(
+ 'adminhtml/system_config/edit',
+ [
+ 'section' => 'catalog',
+ '_fragment' => self::PATH_ANCHOR_PRODUCT_VIDEO
+ ]
+ );
+ }
}
diff --git a/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php b/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php
index 623c82edbcb25..cf5f42da71cf4 100644
--- a/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php
+++ b/app/code/Magento/ProductVideo/Controller/Adminhtml/Product/Gallery/RetrieveImage.php
@@ -8,6 +8,9 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\File\Uploader;
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
class RetrieveImage extends \Magento\Backend\App\Action
{
/**
@@ -72,12 +75,13 @@ public function __construct(
*/
public function executeInternal()
{
+ $baseTmpMediaPath = $this->mediaConfig->getBaseTmpMediaPath();
try {
$remoteFileUrl = $this->getRequest()->getParam('remote_image');
- $originalFileName = $this->parseOriginalFileName($remoteFileUrl);
- $localFileName = $this->localFileName($originalFileName);
- $localTmpFileName = $this->generateTmpFileName($localFileName);
- $localFileMediaPath = $this->appendFileSystemPath($localTmpFileName);
+ $originalFileName = basename($remoteFileUrl);
+ $localFileName = Uploader::getCorrectFileName($originalFileName);
+ $localTmpFileName = Uploader::getDispretionPath($localFileName) . DIRECTORY_SEPARATOR . $localFileName;
+ $localFileMediaPath = $baseTmpMediaPath . ($localTmpFileName);
$localUniqueFileMediaPath = $this->appendNewFileName($localFileMediaPath);
$this->retrieveRemoteImage($remoteFileUrl, $localUniqueFileMediaPath);
$localFileFullPath = $this->appendAbsoluteFileSystemPath($localUniqueFileMediaPath);
@@ -101,7 +105,7 @@ public function executeInternal()
protected function appendResultSaveRemoteImage($fileName)
{
$fileInfo = pathinfo($fileName);
- $tmpFileName = $this->generateTmpFileName($fileInfo['basename']);
+ $tmpFileName = Uploader::getDispretionPath($fileInfo['basename']) . DIRECTORY_SEPARATOR . $fileInfo['basename'];
$result['name'] = $fileInfo['basename'];
$result['type'] = $this->imageAdapter->getMimeType();
$result['error'] = 0;
@@ -111,26 +115,22 @@ protected function appendResultSaveRemoteImage($fileName)
return $result;
}
- /**
- * @param string $fileName
- * @return string
- */
- protected function localFileName($fileName)
- {
- $fileName = Uploader::getCorrectFileName($fileName);
- return $fileName;
- }
-
/**
* @param string $fileUrl
* @param string $localFilePath
- * @return bool|void
+ * @return void
+ * @throws \Magento\Framework\Exception\LocalizedException
*/
protected function retrieveRemoteImage($fileUrl, $localFilePath)
{
$this->curl->setConfig(['header' => false]);
$this->curl->write('GET', $fileUrl);
$image = $this->curl->read();
+ if (empty($image)) {
+ throw new \Magento\Framework\Exception\LocalizedException(
+ __('Could not get video information. Please check your connection and try again.')
+ );
+ }
$this->fileUtility->saveFile($localFilePath, $image);
}
@@ -146,43 +146,6 @@ protected function appendNewFileName($localFilePath)
return $fileInfo['dirname'] . DIRECTORY_SEPARATOR . $fileName;
}
- /**
- * @param string $fileUrl
- * @return string
- */
- protected function parseOriginalFileName($fileUrl)
- {
- return basename($fileUrl);
- }
-
- /**
- * @param string $fileName
- * @return string
- */
- protected function generateTmpFileName($fileName)
- {
- return Uploader::getDispretionPath($fileName) . DIRECTORY_SEPARATOR . $fileName;
- }
-
- /**
- * @param string $fileName
- * @return string
- */
- protected function generateFileNameWithPath($fileName)
- {
- return Uploader::getDispretionPath($fileName) . DIRECTORY_SEPARATOR . $fileName;
- }
-
- /**
- * @param string $localTmpFile
- * @return string
- */
- protected function appendFileSystemPath($localTmpFile)
- {
- $pathToSave = $this->mediaConfig->getBaseTmpMediaPath();
- return $pathToSave . $localTmpFile;
- }
-
/**
* @param string $localTmpFile
* @return string
diff --git a/app/code/Magento/ProductVideo/Model/Plugin/BaseImage.php b/app/code/Magento/ProductVideo/Model/Plugin/BaseImage.php
index 809da5a9c6b3d..f9342074f99d8 100644
--- a/app/code/Magento/ProductVideo/Model/Plugin/BaseImage.php
+++ b/app/code/Magento/ProductVideo/Model/Plugin/BaseImage.php
@@ -6,7 +6,7 @@
namespace Magento\ProductVideo\Model\Plugin;
-use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\BaseImage as OriginalBloc;
+use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\BaseImage as OriginalBlock;
use Magento\Framework\View\Element\Template;
/**
@@ -20,13 +20,13 @@ class BaseImage
const ELEMENT_OUTPUT_TEMPLATE = 'Magento_ProductVideo::product/edit/base_image.phtml';
/**
- * @param OriginalBloc $baseImage
+ * @param OriginalBlock $baseImage
* @param Template $block
* @return Template
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
- public function afterAssignBlockVariables(OriginalBloc $baseImage, Template $block)
+ public function afterAssignBlockVariables(OriginalBlock $baseImage, Template $block)
{
$block->assign([
'videoPlaceholderText' => __('Click here to add videos.'),
@@ -37,13 +37,13 @@ public function afterAssignBlockVariables(OriginalBloc $baseImage, Template $blo
}
/**
- * @param OriginalBloc $baseImage
+ * @param OriginalBlock $baseImage
* @param Template $block
* @return Template
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
- public function afterCreateElementHtmlOutputBlock(OriginalBloc $baseImage, Template $block)
+ public function afterCreateElementHtmlOutputBlock(OriginalBlock $baseImage, Template $block)
{
$block->setTemplate(self::ELEMENT_OUTPUT_TEMPLATE);
return $block;
diff --git a/app/code/Magento/ProductVideo/Model/Plugin/ExternalVideoEntryProcessor.php b/app/code/Magento/ProductVideo/Model/Plugin/ExternalVideoEntryProcessor.php
index 935e84de05c13..1ec18643158d2 100644
--- a/app/code/Magento/ProductVideo/Model/Plugin/ExternalVideoEntryProcessor.php
+++ b/app/code/Magento/ProductVideo/Model/Plugin/ExternalVideoEntryProcessor.php
@@ -41,13 +41,21 @@ class ExternalVideoEntryProcessor
*/
protected $resourceEntryMediaGallery;
+ /**
+ * @var \Magento\ProductVideo\Model\ResourceModel\Video
+ */
+ protected $videoResourceModel;
+
/**
* @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Media $resourceEntryMediaGallery
+ * @param \Magento\ProductVideo\Model\ResourceModel\Video $videoResourceModel
*/
public function __construct(
- \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Media $resourceEntryMediaGallery
+ \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Media $resourceEntryMediaGallery,
+ \Magento\ProductVideo\Model\ResourceModel\Video $videoResourceModel
) {
$this->resourceEntryMediaGallery = $resourceEntryMediaGallery;
+ $this->videoResourceModel = $videoResourceModel;
}
/**
@@ -141,8 +149,7 @@ protected function saveAdditionalStoreData(array $videoDataCollection)
*/
protected function saveVideoValuesItem(array $item)
{
- $this->resourceEntryMediaGallery->saveDataRow(
- InstallSchema::GALLERY_VALUE_VIDEO_TABLE,
+ $this->videoResourceModel->insertOnDuplicate(
$this->prepareVideoRowDataForSave($item)
);
}
diff --git a/app/code/Magento/ProductVideo/Model/Plugin/ExternalVideoResourceBackend.php b/app/code/Magento/ProductVideo/Model/Plugin/ExternalVideoResourceBackend.php
new file mode 100644
index 0000000000000..e29ce8831c954
--- /dev/null
+++ b/app/code/Magento/ProductVideo/Model/Plugin/ExternalVideoResourceBackend.php
@@ -0,0 +1,46 @@
+videoResourceModel = $videoResourceModel;
+ }
+
+ /**
+ * @param Media $originalResourceModel
+ * @param array $valueIdMap
+ * @return array
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterDuplicate(Media $originalResourceModel, array $valueIdMap)
+ {
+ $mediaGalleryEntitiesData = $this->videoResourceModel->loadByIds(array_keys($valueIdMap));
+ foreach ($mediaGalleryEntitiesData as $row) {
+ $row['value_id'] = $valueIdMap[$row['value_id']];
+ $this->videoResourceModel->insertOnDuplicate($row);
+ }
+
+ return $valueIdMap;
+ }
+}
diff --git a/app/code/Magento/ProductVideo/Model/ResourceModel/Video.php b/app/code/Magento/ProductVideo/Model/ResourceModel/Video.php
new file mode 100644
index 0000000000000..3a242f71eb42a
--- /dev/null
+++ b/app/code/Magento/ProductVideo/Model/ResourceModel/Video.php
@@ -0,0 +1,47 @@
+_init(\Magento\ProductVideo\Setup\InstallSchema::GALLERY_VALUE_VIDEO_TABLE, 'value_id');
+ }
+
+ /**
+ * @param array $data
+ * @param array $fields
+ * @return int
+ * @throws \Magento\Framework\Exception\LocalizedException
+ */
+ public function insertOnDuplicate(array $data, array $fields = [])
+ {
+ return $this->getConnection()->insertOnDuplicate($this->getMainTable(), $data, $fields);
+ }
+
+ /**
+ * @param array $ids
+ * @return array
+ * @throws \Magento\Framework\Exception\LocalizedException
+ */
+ public function loadByIds(array $ids)
+ {
+ $select = $this->getConnection()->select()->from(
+ $this->getMainTable()
+ )->where(
+ 'value_id IN(?)',
+ $ids
+ );
+
+ return $this->getConnection()->fetchAll($select);
+ }
+}
diff --git a/app/code/Magento/ProductVideo/Model/VideoExtractor.php b/app/code/Magento/ProductVideo/Model/VideoExtractor.php
index be97959b6df52..aa9267e5a324e 100644
--- a/app/code/Magento/ProductVideo/Model/VideoExtractor.php
+++ b/app/code/Magento/ProductVideo/Model/VideoExtractor.php
@@ -12,7 +12,7 @@ class VideoExtractor implements \Magento\Framework\View\Xsd\Media\TypeDataExtrac
/**
* Media Entry type code
*/
- const MEDIA_TYPE_CODE = 'image';
+ const MEDIA_TYPE_CODE = 'video';
/**
* Extract configuration data of videos from the DOM structure
diff --git a/app/code/Magento/ProductVideo/Setup/UpgradeData.php b/app/code/Magento/ProductVideo/Setup/UpgradeData.php
new file mode 100644
index 0000000000000..b1e418c0f39df
--- /dev/null
+++ b/app/code/Magento/ProductVideo/Setup/UpgradeData.php
@@ -0,0 +1,73 @@
+categorySetupFactory = $categorySetupFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ */
+ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
+ {
+ $setup->startSetup();
+ if (version_compare($context->getVersion(), '2.0.0.2') < 0) {
+ /** @var \Magento\Catalog\Setup\CategorySetup $categorySetup */
+ $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);
+
+ $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);
+ $attributeSetId = $categorySetup->getDefaultAttributeSetId($entityTypeId);
+
+ $attributeGroup = $categorySetup->getAttributeGroup(
+ $entityTypeId,
+ $attributeSetId,
+ 'Image Management'
+ );
+ if (isset($attributeGroup['attribute_group_name'])
+ && $attributeGroup['attribute_group_name'] == 'Image Management'
+ ) {
+ // update General Group
+ $categorySetup->updateAttributeGroup(
+ $entityTypeId,
+ $attributeSetId,
+ $attributeGroup['attribute_group_id'],
+ 'attribute_group_name',
+ 'Images and Videos'
+ );
+ }
+
+ }
+
+ $setup->endSetup();
+ }
+}
diff --git a/app/code/Magento/ProductVideo/Test/Unit/Block/Adminhtml/Product/Edit/NewVideoTest.php b/app/code/Magento/ProductVideo/Test/Unit/Block/Adminhtml/Product/Edit/NewVideoTest.php
index e07d3144baa89..9da5b71dd4d5f 100644
--- a/app/code/Magento/ProductVideo/Test/Unit/Block/Adminhtml/Product/Edit/NewVideoTest.php
+++ b/app/code/Magento/ProductVideo/Test/Unit/Block/Adminhtml/Product/Edit/NewVideoTest.php
@@ -37,6 +37,11 @@ class NewVideoTest extends \PHPUnit_Framework_TestCase
*/
protected $jsonEncoderMock;
+ /**
+ * @var \Magento\ProductVideo\Helper\Media|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $mediaHelper;
+
/**
* @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
* |\Magento\ProductVideo\Block\Adminhtml\Product\Edit\NewVideo
@@ -46,6 +51,7 @@ class NewVideoTest extends \PHPUnit_Framework_TestCase
public function setUp()
{
$this->contextMock = $this->getMock('\Magento\Backend\Block\Template\Context', [], [], '', false);
+ $this->mediaHelper = $this->getMock('\Magento\ProductVideo\Helper\Media', [], [], '', false);
$this->mathRandom = $this->getMock('\Magento\Framework\Math\Random', [], [], '', false);
$this->urlBuilder = $this->getMock('\Magento\Framework\UrlInterface', [], [], '', false);
$this->contextMock->expects($this->any())->method('getMathRandom')->willReturn($this->mathRandom);
@@ -60,9 +66,11 @@ public function setUp()
'\Magento\ProductVideo\Block\Adminhtml\Product\Edit\NewVideo',
[
'context' => $this->contextMock,
+ 'mediaHelper' => $this->mediaHelper,
+ 'urlBuilder' => $this->urlBuilder,
+ 'jsonEncoder' => $this->jsonEncoderMock,
'registry' => $this->registryMock,
'formFactory' => $this->formFactoryMock,
- 'jsonEncoder' => $this->jsonEncoderMock
]
);
}
diff --git a/app/code/Magento/ProductVideo/etc/adminhtml/system.xml b/app/code/Magento/ProductVideo/etc/adminhtml/system.xml
index f475ab5b70d54..d00f9a78e6b65 100644
--- a/app/code/Magento/ProductVideo/etc/adminhtml/system.xml
+++ b/app/code/Magento/ProductVideo/etc/adminhtml/system.xml
@@ -8,10 +8,10 @@
-
+
Product Video
-
- YouTube API key
+
+ YouTube API Key
diff --git a/app/code/Magento/ProductVideo/etc/di.xml b/app/code/Magento/ProductVideo/etc/di.xml
index 99aeef0a7251e..7f27e06492a15 100644
--- a/app/code/Magento/ProductVideo/etc/di.xml
+++ b/app/code/Magento/ProductVideo/etc/di.xml
@@ -39,6 +39,9 @@
+
+
+
diff --git a/app/code/Magento/ProductVideo/etc/module.xml b/app/code/Magento/ProductVideo/etc/module.xml
index a6bc6bab40b5a..16107ae938e40 100644
--- a/app/code/Magento/ProductVideo/etc/module.xml
+++ b/app/code/Magento/ProductVideo/etc/module.xml
@@ -6,7 +6,7 @@
*/
-->
-
+
diff --git a/app/code/Magento/ProductVideo/etc/view.xml b/app/code/Magento/ProductVideo/etc/view.xml
index 3a09480fc4c57..f5ce5d81d6ff7 100644
--- a/app/code/Magento/ProductVideo/etc/view.xml
+++ b/app/code/Magento/ProductVideo/etc/view.xml
@@ -5,7 +5,7 @@
* See COPYING.txt for license details.
*/
-->
-
+
diff --git a/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js b/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js
index 52171f1537a25..e52368166270e 100644
--- a/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js
+++ b/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js
@@ -1,595 +1,588 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-require([
- 'jquery',
- 'Magento_Ui/js/modal/alert',
- 'jquery/ui'
- ],
- function ($, alert) {
- 'use strict';
-
- var videoRegister = {
- _register: {},
-
- /**
- * Checks, if api is already registered
- *
- * @param {String} api
- * @returns {bool}
- */
- isRegistered: function (api) {
- return this._register[api] !== undefined;
- },
-
- /**
- * Checks, if api is loaded
- *
- * @param {String} api
- * @returns {bool}
- */
- isLoaded: function (api) {
- return this._register[api] !== undefined && this._register[api] === true;
- },
-
- /**
- * Register new video api
- * @param {String} api
- * @param {bool} loaded
- */
- register: function (api, loaded) {
- loaded = loaded || false;
- this._register[api] = loaded;
- }
- };
-
- $.widget('mage.productVideoLoader', {
-
- /**
- * @private
- */
- _create: function () {
- switch (this.element.data('type')) {
- case 'youtube':
- this.element.videoYoutube();
- this._player = this.element.data('mageVideoYoutube');
- break;
-
- case 'vimeo':
- this.element.videoVimeo();
- this._player = this.element.data('mageVideoVimeo');
- break;
- default:
- throw {
- name: 'Video Error',
- message: 'Unknown video type',
-
- /**
- * Return string
- */
- toString: function () {
- return this.name + ': ' + this.message;
- }
- };
- }
- },
-
- /**
- * Initializes variables
- * @private
- */
- _initialize: function () {
- this._params = this.element.data('params') || {};
- this._code = this.element.data('code');
- this._width = this.element.data('width');
- this._height = this.element.data('height');
- this._autoplay = !!this.element.data('autoplay');
- this._playing = this._autoplay || false;
-
- this._responsive = this.element.data('responsive') !== false;
-
- if (this._responsive === true) {
- this.element.addClass('responsive');
- }
-
- this._calculateRatio();
- },
-
- /**
- * Abstract play command
- */
- play: function () {
- this._player.play();
- },
-
- /**
- * Abstract pause command
- */
- pause: function () {
- this._player.pause();
- },
-
- /**
- * Abstract stop command
- */
- stop: function () {
- this._player.stop();
- },
-
- /**
- * Abstract playing command
- */
- playing: function () {
- return this._player.playing();
- },
-
- /**
- * Abstract destroying command
- */
- destroy: function () {
- this._player.destroy();
- },
-
- /**
- * Calculates ratio for responsive videos
- * @private
- */
- _calculateRatio: function () {
- if (!this._responsive) {
- return;
- }
- this.element.css('paddingBottom', this._height / this._width * 100 + '%');
- }
- });
-
- $.widget('mage.videoYoutube', $.mage.productVideoLoader, {
-
- /**
- * Initialization of the Youtube widget
- * @private
- */
- _create: function () {
- var self = this;
-
- this._initialize();
-
- this.element.append('
');
-
- this._on(window, {
-
- /**
- * Youtube state check
- * @private
- */
- 'youtubeapiready': function () {
- if (self._player !== undefined) {
- return;
- }
-
- if (self._autoplay) {
- self._params.autoplay = 1;
- }
- self._params.rel = 0;
-
- self._player = new window.YT.Player(self.element.children(':first')[0], {
- height: self._height,
- width: self._width,
- videoId: self._code,
- playerVars: self._params,
- events: {
-
- /**
- * @private
- */
- 'onReady': function onPlayerReady() {
- self._player.getDuration();
- },
-
- /**
- * State change flag init
- */
- onStateChange: function (data) {
- switch (window.parseInt(data.data, 10)) {
- case 1:
- self._playing = true;
- break;
- default:
- self._playing = false;
- break;
- }
-
- self._trigger('statechange', {}, data);
- }
- }
-
- });
- }
- });
-
- this._loadApi();
- },
-
- /**
- * Loads Youtube API and triggers event, when loaded
- * @private
- */
- _loadApi: function () {
- var element,
- scriptTag;
-
- if (videoRegister.isRegistered('youtube')) {
- if (videoRegister.isLoaded('youtube')) {
- $(window).trigger('youtubeapiready');
- }
-
- return;
- }
- videoRegister.register('youtube');
-
- element = document.createElement('script');
- scriptTag = document.getElementsByTagName('script')[0];
-
- element.async = true;
- element.src = 'https://www.youtube.com/iframe_api';
- scriptTag.parentNode.insertBefore(element, scriptTag);
-
- /**
- * Trigger youtube api ready event
- */
- window.onYouTubeIframeAPIReady = function () {
- $(window).trigger('youtubeapiready');
- videoRegister.register('youtube', true);
- };
- },
-
- /**
- * Play command for Youtube
- */
- play: function () {
- this._player.playVideo();
- this._playing = true;
- },
-
- /**
- * Pause command for Youtube
- */
- pause: function () {
- this._player.pauseVideo();
- this._playing = false;
- },
-
- /**
- * Stop command for Youtube
- */
- stop: function () {
- this._player.stopVideo();
- this._playing = false;
- },
-
- /**
- * Playing command for Youtube
- */
- playing: function () {
- return this._playing;
- },
-
- /**
- * stops and unloads player
- * @private
- */
- destroy: function () {
- this.stop();
- this._player.destroy();
- }
- });
-
- $.widget('mage.videoVimeo', $.mage.productVideoLoader, {
-
- /**
- * Initialize the Vimeo widget
- * @private
- */
- _create: function () {
- var timestamp,
- src,
- additionalParams;
-
- this._initialize();
- timestamp = new Date().getTime();
-
- if (this._autoplay) {
- additionalParams += '&autoplay=1';
- }
-
- src = 'http://player.vimeo.com/video/' +
- this._code + '?api=1&player_id=vimeo' +
- this._code +
- timestamp +
- additionalParams;
- this.element.append(
- $('')
- .attr('frameborder', 0)
- .attr('id', 'vimeo' + this._code + timestamp)
- .attr('width', this._width)
- .attr('height', this._height)
- .attr('src', src)
- );
-
- }
- });
-
- $.widget('mage.videoData', {
- options: {
- youtubeKey: '',
- noKeyErrorTxt: 'You have not entered youtube API key. ' +
- 'No information about youtube video will be retrieved.',
- eventSource: '' //where is data going from - focus out or click on button
- },
-
- _REQUEST_VIDEO_INFORMATION_TRIGGER: 'update_video_information',
-
- _UPDATE_VIDEO_INFORMATION_TRIGGER: 'updated_video_information',
-
- _ERROR_UPDATE_INFORMATION_TRIGGER: 'error_updated_information',
-
- _videoInformation: null,
-
- /**
- * @private
- */
- _init: function () {
- if (!this.options.youtubeKey && this.options.eventSource === 'click') {
- alert({
- content: this.options.noKeyErrorTxt
- });
- }
- this._onRequestHandler();
- },
-
- /**
- * @private
- */
- _onRequestHandler: function () {
- var url = this.element.val(),
- self = this,
- videoInfo,
- type,
- id,
- googleapisUrl;
-
- if (!url) {
- //this._onRequestError("Video url is undefined");
- return;
- }
-
- videoInfo = this._validateURL(url);
-
- if (!videoInfo) {
- this._onRequestError('Invalid video url');
-
- return;
- }
-
- /**
- *
- * @param {Object} data
- * @private
- */
- function _onYouTubeLoaded(data) {
- var tmp,
- uploadedFormatted,
- respData,
- createErrorMessage;
-
- /**
- * Create errors message
- *
- * @returns {String}
- */
- createErrorMessage = function () {
- var error = data.error,
- errors = error.errors,
- i,
- errLength = errors.length,
- tmpError,
- errReason,
- errorsMessage = [];
-
- for (i = 0; i < errLength; i++) {
- tmpError = errors[i];
- errReason = tmpError.reason;
-
- if (['keyInvalid'].indexOf(errReason) !== -1) {
- errorsMessage.push('Youtube API key is an invalid');
-
- break;
- }
-
- errorsMessage.push(tmpError.message);
- }
-
- return 'Video can\'t be shown by reason: ' + $.unique(errorsMessage).join(', ');
- };
-
- if (data.error && data.error.code === 400) {
- this._onRequestError(createErrorMessage());
-
- return;
- }
-
- if (!data.items || data.items.length < 1) {
- this._onRequestError('Video not found');
-
- return;
- }
-
- tmp = data.items[0];
- uploadedFormatted = tmp.snippet.publishedAt.replace('T', ' ').replace(/\..+/g, '');
- respData = {
- duration: this._formatYoutubeDuration(tmp.contentDetails.duration),
- channel: tmp.snippet.channelTitle,
- channelId: tmp.snippet.channelId,
- uploaded: uploadedFormatted,
- title: tmp.snippet.localized.title,
- description: tmp.snippet.description,
- thumbnail: tmp.snippet.thumbnails.high.url,
- videoId: videoInfo.id,
- videoProvider: videoInfo.type
- };
- this._videoInformation = respData;
- this.element.trigger(this._UPDATE_VIDEO_INFORMATION_TRIGGER, respData);
- }
-
- /**
- * @private
- */
- function _onVimeoLoaded(data) {
- var tmp = data[0],
- respData;
-
- if (data.length < 1) {
- this._onRequestError('Video not found');
-
- return null;
- }
- tmp = data[0];
- respData = {
- duration: this._formatVimeoDuration(tmp.duration),
- channel: tmp['user_name'],
- channelId: tmp['user_url'],
- uploaded: tmp['upload_date'],
- title: tmp.title,
- description: tmp.description.replace(/( |<([^>]+)>)/ig, ''),
- thumbnail: tmp['thumbnail_large'],
- videoId: videoInfo.id,
- videoProvider: videoInfo.type
- };
- this._videoInformation = respData;
- this.element.trigger(this._UPDATE_VIDEO_INFORMATION_TRIGGER, respData);
- }
-
- type = videoInfo.type;
- id = videoInfo.id;
-
- if (type === 'youtube') {
- googleapisUrl = 'https://www.googleapis.com/youtube/v3/videos?id=' +
- id +
- '&part=snippet,contentDetails,statistics,status&key=' +
- this.options.youtubeKey + '&alt=json&callback=?';
- $.getJSON(googleapisUrl,
- {
- format: 'json'
- },
- $.proxy(_onYouTubeLoaded, self)
- ).fail(
- function () {
- self._onRequestError('Video not found');
- }
- );
- } else if (type === 'vimeo') {
- $.getJSON('http://www.vimeo.com/api/v2/video/' + id + '.json?callback=?',
- {
- format: 'json'
- },
- $.proxy(_onVimeoLoaded, self)
- ).fail(
- function () {
- self._onRequestError('Video not found');
- }
- );
- }
- },
-
- /**
- * @private
- */
- _onRequestError: function (error) {
- this._videoInformation = null;
- this.element.trigger(this._ERROR_UPDATE_INFORMATION_TRIGGER, error);
- this.element.val('');
- alert({
- content: 'Error: "' + error + '"'
- });
- },
-
- /**
- * @private
- */
- _formatYoutubeDuration: function (duration) {
- var match = duration.match(/PT(\d+H)?(\d+M)?(\d+S)?/),
- hours = parseInt(match[1], 10) || 0,
- minutes = parseInt(match[2], 10) || 0,
- seconds = parseInt(match[3], 10) || 0;
-
- return this._formatVimeoDuration(hours * 3600 + minutes * 60 + seconds);
- },
-
- /**
- * @private
- */
- _formatVimeoDuration: function (seconds) {
- return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0];
- },
-
- /**
- * @private
- */
- _parseHref: function (href) {
- var a = document.createElement('a');
-
- a.href = href;
-
- return a;
- },
-
- /**
- * @private
- */
- _validateURL: function (href, forceVideo) {
- var id,
- type,
- ampersandPosition,
- vimeoRegex;
-
- if (typeof href !== 'string') {
- return href;
- }
- href = this._parseHref(href);
-
- if (href.host.match(/youtube\.com/) && href.search) {
-
- id = href.search.split('v=')[1];
-
- if (id) {
- ampersandPosition = id.indexOf('&');
- type = 'youtube';
- }
-
- if (id && ampersandPosition !== -1) {
- id = id.substring(0, ampersandPosition);
- }
-
- } else if (href.host.match(/youtube\.com|youtu\.be/)) {
- id = href.pathname.replace(/^\/(embed\/|v\/)?/, '').replace(/\/.*/, '');
- type = 'youtube';
- } else if (href.host.match(/vimeo\.com/)) {
- type = 'vimeo';
- vimeoRegex = new RegExp(['https?:\\/\\/(?:www\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)',
- '?|groups\\/([^\\/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|)(\\d+)(?:$|\\/|\\?)'
- ].join(''));
- id = href.href.match(vimeoRegex)[3];
- }
-
- if ((!id || !type) && forceVideo) {
- id = href.href;
- type = 'custom';
- }
-
- return id ? {
- id: id, type: type, s: href.search.replace(/^\?/, '')
- } : false;
- }
- });
- });
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*jshint browser:true jquery:true*/
+require([
+ 'jquery',
+ 'Magento_Ui/js/modal/alert',
+ 'jquery/ui'
+ ],
+ function ($, alert) {
+ 'use strict';
+
+ var videoRegister = {
+ _register: {},
+
+ /**
+ * Checks, if api is already registered
+ *
+ * @param {String} api
+ * @returns {bool}
+ */
+ isRegistered: function (api) {
+ return this._register[api] !== undefined;
+ },
+
+ /**
+ * Checks, if api is loaded
+ *
+ * @param {String} api
+ * @returns {bool}
+ */
+ isLoaded: function (api) {
+ return this._register[api] !== undefined && this._register[api] === true;
+ },
+
+ /**
+ * Register new video api
+ * @param {String} api
+ * @param {bool} loaded
+ */
+ register: function (api, loaded) {
+ loaded = loaded || false;
+ this._register[api] = loaded;
+ }
+ };
+
+ $.widget('mage.productVideoLoader', {
+
+ /**
+ * @private
+ */
+ _create: function () {
+ switch (this.element.data('type')) {
+ case 'youtube':
+ this.element.videoYoutube();
+ this._player = this.element.data('mageVideoYoutube');
+ break;
+
+ case 'vimeo':
+ this.element.videoVimeo();
+ this._player = this.element.data('mageVideoVimeo');
+ break;
+ default:
+ throw {
+ name: 'Video Error',
+ message: 'Unknown video type',
+
+ /**
+ * Return string
+ */
+ toString: function () {
+ return this.name + ': ' + this.message;
+ }
+ };
+ }
+ },
+
+ /**
+ * Initializes variables
+ * @private
+ */
+ _initialize: function () {
+ this._params = this.element.data('params') || {};
+ this._code = this.element.data('code');
+ this._width = this.element.data('width');
+ this._height = this.element.data('height');
+ this._autoplay = !!this.element.data('autoplay');
+ this._playing = this._autoplay || false;
+
+ this._responsive = this.element.data('responsive') !== false;
+
+ if (this._responsive === true) {
+ this.element.addClass('responsive');
+ }
+
+ this._calculateRatio();
+ },
+
+ /**
+ * Abstract play command
+ */
+ play: function () {
+ this._player.play();
+ },
+
+ /**
+ * Abstract pause command
+ */
+ pause: function () {
+ this._player.pause();
+ },
+
+ /**
+ * Abstract stop command
+ */
+ stop: function () {
+ this._player.stop();
+ },
+
+ /**
+ * Abstract playing command
+ */
+ playing: function () {
+ return this._player.playing();
+ },
+
+ /**
+ * Abstract destroying command
+ */
+ destroy: function () {
+ this._player.destroy();
+ },
+
+ /**
+ * Calculates ratio for responsive videos
+ * @private
+ */
+ _calculateRatio: function () {
+ if (!this._responsive) {
+ return;
+ }
+ this.element.css('paddingBottom', this._height / this._width * 100 + '%');
+ }
+ });
+
+ $.widget('mage.videoYoutube', $.mage.productVideoLoader, {
+
+ /**
+ * Initialization of the Youtube widget
+ * @private
+ */
+ _create: function () {
+ var self = this;
+
+ this._initialize();
+
+ this.element.append('
');
+
+ this._on(window, {
+
+ /**
+ * Youtube state check
+ * @private
+ */
+ 'youtubeapiready': function () {
+ if (self._player !== undefined) {
+ return;
+ }
+
+ if (self._autoplay) {
+ self._params.autoplay = 1;
+ }
+ self._params.rel = 0;
+
+ self._player = new window.YT.Player(self.element.children(':first')[0], {
+ height: self._height,
+ width: self._width,
+ videoId: self._code,
+ playerVars: self._params,
+ events: {
+
+ /**
+ * @private
+ */
+ 'onReady': function onPlayerReady() {
+ self._player.getDuration();
+ },
+
+ /**
+ * State change flag init
+ */
+ onStateChange: function (data) {
+ switch (window.parseInt(data.data, 10)) {
+ case 1:
+ self._playing = true;
+ break;
+ default:
+ self._playing = false;
+ break;
+ }
+
+ self._trigger('statechange', {}, data);
+ }
+ }
+
+ });
+ }
+ });
+
+ this._loadApi();
+ },
+
+ /**
+ * Loads Youtube API and triggers event, when loaded
+ * @private
+ */
+ _loadApi: function () {
+ var element,
+ scriptTag;
+
+ if (videoRegister.isRegistered('youtube')) {
+ if (videoRegister.isLoaded('youtube')) {
+ $(window).trigger('youtubeapiready');
+ }
+
+ return;
+ }
+ videoRegister.register('youtube');
+
+ element = document.createElement('script');
+ scriptTag = document.getElementsByTagName('script')[0];
+
+ element.async = true;
+ element.src = 'https://www.youtube.com/iframe_api';
+ scriptTag.parentNode.insertBefore(element, scriptTag);
+
+ /**
+ * Trigger youtube api ready event
+ */
+ window.onYouTubeIframeAPIReady = function () {
+ $(window).trigger('youtubeapiready');
+ videoRegister.register('youtube', true);
+ };
+ },
+
+ /**
+ * Play command for Youtube
+ */
+ play: function () {
+ this._player.playVideo();
+ this._playing = true;
+ },
+
+ /**
+ * Pause command for Youtube
+ */
+ pause: function () {
+ this._player.pauseVideo();
+ this._playing = false;
+ },
+
+ /**
+ * Stop command for Youtube
+ */
+ stop: function () {
+ this._player.stopVideo();
+ this._playing = false;
+ },
+
+ /**
+ * Playing command for Youtube
+ */
+ playing: function () {
+ return this._playing;
+ },
+
+ /**
+ * stops and unloads player
+ * @private
+ */
+ destroy: function () {
+ this.stop();
+ this._player.destroy();
+ }
+ });
+
+ $.widget('mage.videoVimeo', $.mage.productVideoLoader, {
+
+ /**
+ * Initialize the Vimeo widget
+ * @private
+ */
+ _create: function () {
+ var timestamp,
+ src,
+ additionalParams;
+
+ this._initialize();
+ timestamp = new Date().getTime();
+
+ if (this._autoplay) {
+ additionalParams += '&autoplay=1';
+ }
+
+ src = 'http://player.vimeo.com/video/' +
+ this._code + '?api=1&player_id=vimeo' +
+ this._code +
+ timestamp +
+ additionalParams;
+ this.element.append(
+ $('')
+ .attr('frameborder', 0)
+ .attr('id', 'vimeo' + this._code + timestamp)
+ .attr('width', this._width)
+ .attr('height', this._height)
+ .attr('src', src)
+ );
+
+ }
+ });
+
+ $.widget('mage.videoData', {
+ options: {
+ youtubeKey: '',
+ eventSource: '' //where is data going from - focus out or click on button
+ },
+
+ _REQUEST_VIDEO_INFORMATION_TRIGGER: 'update_video_information',
+
+ _UPDATE_VIDEO_INFORMATION_TRIGGER: 'updated_video_information',
+
+ _ERROR_UPDATE_INFORMATION_TRIGGER: 'error_updated_information',
+
+ _videoInformation: null,
+
+ /**
+ * @private
+ */
+ _init: function () {
+ this._onRequestHandler();
+ },
+
+ /**
+ * @private
+ */
+ _onRequestHandler: function () {
+ var url = this.element.val(),
+ self = this,
+ videoInfo,
+ type,
+ id,
+ googleapisUrl;
+
+ if (!url) {
+ //this._onRequestError("Video url is undefined");
+ return;
+ }
+
+ videoInfo = this._validateURL(url);
+
+ if (!videoInfo) {
+ this._onRequestError('Invalid video url');
+
+ return;
+ }
+
+ /**
+ *
+ * @param {Object} data
+ * @private
+ */
+ function _onYouTubeLoaded(data) {
+ var tmp,
+ uploadedFormatted,
+ respData,
+ createErrorMessage;
+
+ /**
+ * Create errors message
+ *
+ * @returns {String}
+ */
+ createErrorMessage = function () {
+ var error = data.error,
+ errors = error.errors,
+ i,
+ errLength = errors.length,
+ tmpError,
+ errReason,
+ errorsMessage = [];
+
+ for (i = 0; i < errLength; i++) {
+ tmpError = errors[i];
+ errReason = tmpError.reason;
+
+ if (['keyInvalid'].indexOf(errReason) !== -1) {
+ errorsMessage.push('Youtube API key is invalid');
+
+ break;
+ }
+
+ errorsMessage.push(tmpError.message);
+ }
+
+ return 'Video cant be shown due to the following reason: ' + $.unique(errorsMessage).join(', ');
+ };
+
+ if (data.error && data.error.code === 400) {
+ this._onRequestError(createErrorMessage());
+
+ return;
+ }
+
+ if (!data.items || data.items.length < 1) {
+ this._onRequestError('Video not found');
+
+ return;
+ }
+
+ tmp = data.items[0];
+ uploadedFormatted = tmp.snippet.publishedAt.replace('T', ' ').replace(/\..+/g, '');
+ respData = {
+ duration: this._formatYoutubeDuration(tmp.contentDetails.duration),
+ channel: tmp.snippet.channelTitle,
+ channelId: tmp.snippet.channelId,
+ uploaded: uploadedFormatted,
+ title: tmp.snippet.localized.title,
+ description: tmp.snippet.description,
+ thumbnail: tmp.snippet.thumbnails.high.url,
+ videoId: videoInfo.id,
+ videoProvider: videoInfo.type
+ };
+ this._videoInformation = respData;
+ this.element.trigger(this._UPDATE_VIDEO_INFORMATION_TRIGGER, respData);
+ }
+
+ /**
+ * @private
+ */
+ function _onVimeoLoaded(data) {
+ var tmp = data[0],
+ respData;
+
+ if (data.length < 1) {
+ this._onRequestError('Video not found');
+
+ return null;
+ }
+ tmp = data[0];
+ respData = {
+ duration: this._formatVimeoDuration(tmp.duration),
+ channel: tmp['user_name'],
+ channelId: tmp['user_url'],
+ uploaded: tmp['upload_date'],
+ title: tmp.title,
+ description: tmp.description.replace(/( |<([^>]+)>)/ig, ''),
+ thumbnail: tmp['thumbnail_large'],
+ videoId: videoInfo.id,
+ videoProvider: videoInfo.type
+ };
+ this._videoInformation = respData;
+ this.element.trigger(this._UPDATE_VIDEO_INFORMATION_TRIGGER, respData);
+ }
+
+ type = videoInfo.type;
+ id = videoInfo.id;
+
+ if (type === 'youtube') {
+ googleapisUrl = 'https://www.googleapis.com/youtube/v3/videos?id=' +
+ id +
+ '&part=snippet,contentDetails,statistics,status&key=' +
+ this.options.youtubeKey + '&alt=json&callback=?';
+ $.getJSON(googleapisUrl,
+ {
+ format: 'json'
+ },
+ $.proxy(_onYouTubeLoaded, self)
+ ).fail(
+ function () {
+ self._onRequestError('Video not found');
+ }
+ );
+ } else if (type === 'vimeo') {
+ $.getJSON('http://www.vimeo.com/api/v2/video/' + id + '.json?callback=?',
+ {
+ format: 'json'
+ },
+ $.proxy(_onVimeoLoaded, self)
+ ).fail(
+ function () {
+ self._onRequestError('Video not found');
+ }
+ );
+ }
+ },
+
+ /**
+ * @private
+ */
+ _onRequestError: function (error) {
+ this._videoInformation = null;
+ this.element.trigger(this._ERROR_UPDATE_INFORMATION_TRIGGER, error);
+ this.element.val('');
+ alert({
+ content: 'Error: "' + error + '"'
+ });
+ },
+
+ /**
+ * @private
+ */
+ _formatYoutubeDuration: function (duration) {
+ var match = duration.match(/PT(\d+H)?(\d+M)?(\d+S)?/),
+ hours = parseInt(match[1], 10) || 0,
+ minutes = parseInt(match[2], 10) || 0,
+ seconds = parseInt(match[3], 10) || 0;
+
+ return this._formatVimeoDuration(hours * 3600 + minutes * 60 + seconds);
+ },
+
+ /**
+ * @private
+ */
+ _formatVimeoDuration: function (seconds) {
+ return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0];
+ },
+
+ /**
+ * @private
+ */
+ _parseHref: function (href) {
+ var a = document.createElement('a');
+
+ a.href = href;
+
+ return a;
+ },
+
+ /**
+ * @private
+ */
+ _validateURL: function (href, forceVideo) {
+ var id,
+ type,
+ ampersandPosition,
+ vimeoRegex;
+
+ if (typeof href !== 'string') {
+ return href;
+ }
+ href = this._parseHref(href);
+
+ if (href.host.match(/youtube\.com/) && href.search) {
+
+ id = href.search.split('v=')[1];
+
+ if (id) {
+ ampersandPosition = id.indexOf('&');
+ type = 'youtube';
+ }
+
+ if (id && ampersandPosition !== -1) {
+ id = id.substring(0, ampersandPosition);
+ }
+
+ } else if (href.host.match(/youtube\.com|youtu\.be/)) {
+ id = href.pathname.replace(/^\/(embed\/|v\/)?/, '').replace(/\/.*/, '');
+ type = 'youtube';
+ } else if (href.host.match(/vimeo\.com/)) {
+ type = 'vimeo';
+ vimeoRegex = new RegExp(['https?:\\/\\/(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)',
+ '?|groups\\/([^\\/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|video\\/|)(\\d+)(?:$|\\/|\\?)'
+ ].join(''));
+ id = href.href.match(vimeoRegex)[3];
+ }
+
+ if ((!id || !type) && forceVideo) {
+ id = href.href;
+ type = 'custom';
+ }
+
+ return id ? {
+ id: id, type: type, s: href.search.replace(/^\?/, '')
+ } : false;
+ }
+ });
+ });
diff --git a/app/code/Magento/ProductVideo/view/adminhtml/web/js/new-video-dialog.js b/app/code/Magento/ProductVideo/view/adminhtml/web/js/new-video-dialog.js
index e5efb668b51e9..fe8e76ded235d 100644
--- a/app/code/Magento/ProductVideo/view/adminhtml/web/js/new-video-dialog.js
+++ b/app/code/Magento/ProductVideo/view/adminhtml/web/js/new-video-dialog.js
@@ -4,14 +4,13 @@
*/
define([
'jquery',
- 'Magento_Ui/js/modal/alert',
'jquery/ui',
'Magento_Ui/js/modal/modal',
'mage/translate',
'mage/backend/tree-suggest',
'mage/backend/validation',
'Magento_ProductVideo/js/get-video-information'
-], function ($, alert) {
+], function ($) {
'use strict';
$.widget('mage.createVideoPlayer', {
@@ -62,11 +61,9 @@ define([
if (checkVideoID && checkVideoID !== this.options.videoId) {
this._doUpdate();
- } else
- if (checkVideoID && checkVideoID === this.options.videoId) {
+ } else if (checkVideoID && checkVideoID === this.options.videoId) {
return false;
- } else
- if (!checkVideoID) {
+ } else if (!checkVideoID) {
this._doUpdate();
}
@@ -97,8 +94,7 @@ define([
this.options.metaData.data.uploader +
''
);
- } else
- if (this.options.videoProvider === 'vimeo') {
+ } else if (this.options.videoProvider === 'vimeo') {
$(this.options.metaData.DOM.uploader).html(
' 0) {
+ $('.image-upload-error').remove();
+ }
+
if (data.errorcode || data.error) {
- alert({
- content: data.error
- });
+ $('#video_url').parent().append('' +
+ '
' + data.error + ' ');
return;
}
@@ -647,7 +659,7 @@ define([
roles.prop('disabled', false);
file = $('#file_name').val();
widget._onGetVideoInformationEditClick();
- modalTitleElement = $('.modal-title');
+ modalTitleElement = $('.mage-new-video-dialog .modal-title');
if (!file) {
widget._blockActionButtons(true);
@@ -870,9 +882,8 @@ define([
if (
ext.length < 2 ||
this._imageTypes.indexOf(ext.toLowerCase()) === -1 ||
- !file.files ||
+ !file.files ||
!file.files.length
-
) {
prev.remove();
this._previewImage = null;
@@ -968,7 +979,9 @@ define([
try {
newVideoForm.validation('clearError');
- } catch (e) {}
+ } catch (e) {
+
+ }
newVideoForm.trigger('reset');
},
diff --git a/app/code/Magento/ProductVideo/view/frontend/requirejs-config.js b/app/code/Magento/ProductVideo/view/frontend/requirejs-config.js
index e19b89135b441..7f488a2fa2f80 100644
--- a/app/code/Magento/ProductVideo/view/frontend/requirejs-config.js
+++ b/app/code/Magento/ProductVideo/view/frontend/requirejs-config.js
@@ -6,7 +6,8 @@
var config = {
map: {
'*': {
- loadPlayer: 'Magento_ProductVideo/js/load-player'
+ loadPlayer: 'Magento_ProductVideo/js/load-player',
+ fotoramaVideoEvents: 'Magento_ProductVideo/js/fotorama-add-video-events'
}
}
};
diff --git a/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js b/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js
index 3fa62c44903df..16f3aa9f922ae 100644
--- a/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js
+++ b/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js
@@ -11,6 +11,11 @@ define([
], function ($) {
'use strict';
+ /**
+ * @private
+ */
+ var allowBase = true; //global var is needed because fotorama always fully reloads events in case of fullscreen
+
/**
* @private
*/
@@ -68,8 +73,8 @@ define([
type = 'youtube';
} else if (href.host.match(/vimeo\.com/)) {
type = 'vimeo';
- vimeoRegex = new RegExp(['https?:\\/\\/(?:www\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)',
- '?|groups\\/([^\\/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|)(\\d+)(?:$|\\/|\\?)'
+ vimeoRegex = new RegExp(['https?:\\/\\/(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)',
+ '?|groups\\/([^\\/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|video\\/|)(\\d+)(?:$|\\/|\\?)'
].join(''));
id = href.href.match(vimeoRegex)[3];
}
@@ -96,6 +101,7 @@ define([
VI: 'vimeo', // [CONST]
FTVC: 'fotorama__video-close',
FTAR: 'fotorama__arr',
+ isFullscreen: 0,
Base: 0, //on check for video is base this setting become true if there is any video with base role
MobileMaxWidth: 767,
GP: 'gallery-placeholder', //gallery placeholder class is needed to find and erase