diff --git a/admin-dev/ajax.php b/admin-dev/ajax.php
index a3a387c3e..d58755762 100644
--- a/admin-dev/ajax.php
+++ b/admin-dev/ajax.php
@@ -678,17 +678,6 @@ if (Tools::isSubmit('getChildrenCategories') && Tools::getValue('id_category_par
die(Tools::jsonEncode($children_categories));
}
-if (Tools::isSubmit('updateProductImageShopAsso'))
-{
- if ($id_image = (int)Tools::getValue('id_image') AND $id_shop = (int)Tools::getValue('id_shop'))
- {
- if ((int)Tools::getValue('active'))
- Db::getInstance()->Execute('INSERT INTO '._DB_PREFIX_.'image_shop (`id_image`, `id_shop`) VALUES('.(int)$id_image.', '.(int)$id_shop.')');
- else
- Db::getInstance()->Execute('DELETE FROM '._DB_PREFIX_.'image_shop WHERE `id_image`='.(int)$id_image.' AND `id_shop`='.(int)$id_shop);
- }
-}
-
if (Tools::isSubmit('getNotifications'))
{
$notification = new Notification;
diff --git a/admin-dev/tabs/AdminCatalog.php b/admin-dev/tabs/AdminCatalog.php
index 2a914c49d..ab0b59475 100644
--- a/admin-dev/tabs/AdminCatalog.php
+++ b/admin-dev/tabs/AdminCatalog.php
@@ -68,7 +68,6 @@ class AdminCatalog extends AdminTab
$id_category = $shop->getCategory();
}
}
-
self::$_category = new Category($id_category);
if (!Validate::isLoadedObject(self::$_category))
die('Category cannot be loaded');
@@ -113,6 +112,16 @@ class AdminCatalog extends AdminTab
}
$this->adminProducts->postProcess($this->token);
}
+ public function ajaxProcess()
+ {
+ if (Tools::getValue('addImage') !== false)
+ $this->adminProducts->ajaxProcess();
+ if (Tools::getValue('updateProductImageShopAsso'))
+ $this->adminProducts->ajaxProcess();
+ if (Tools::getValue('deleteImage'))
+ $this->adminProducts->ajaxProcess();
+
+ }
public function displayErrors()
{
diff --git a/admin-dev/tabs/AdminProducts.php b/admin-dev/tabs/AdminProducts.php
index 863944407..46a9292ed 100644
--- a/admin-dev/tabs/AdminProducts.php
+++ b/admin-dev/tabs/AdminProducts.php
@@ -28,13 +28,13 @@ include_once(PS_ADMIN_DIR.'/tabs/AdminProfiles.php');
class AdminProducts extends AdminTab
{
- protected $maxFileSize = 20000000;
+ protected $maxFileSize = 20000000;
private $_category;
public function __construct()
{
-
+
$this->table = 'product';
$this->className = 'Product';
$this->lang = true;
@@ -68,7 +68,6 @@ class AdminProducts extends AdminTab
parent::__construct();
}
-
private function _cleanMetaKeywords($keywords)
{
if (!empty($keywords) && $keywords != '')
@@ -416,28 +415,8 @@ class AdminProducts extends AdminTab
{
if ($this->tabAccess['edit'] === '1')
{
- /* Delete product image */
- if (isset($_GET['deleteImage']))
- {
- $image->delete();
-
- if (!Image::getCover($image->id_product))
- {
- $first_img = Db::getInstance()->getRow('
- SELECT `id_image` FROM `'._DB_PREFIX_.'image`
- WHERE `id_product` = '.(int)($image->id_product));
- Db::getInstance()->Execute('
- UPDATE `'._DB_PREFIX_.'image`
- SET `cover` = 1
- WHERE `id_image` = '.(int)($first_img['id_image']));
- }
- @unlink(_PS_TMP_IMG_DIR_.'/product_'.$image->id_product.'.jpg');
- @unlink(_PS_TMP_IMG_DIR_.'/product_mini_'.$image->id_product.'.jpg');
- Tools::redirectAdmin(self::$currentIndex.'&id_product='.$image->id_product.'&id_category='.(!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1').'&add'.$this->table.'&tabs=1'.'&token='.($token ? $token : $this->token));
- }
-
/* Update product image/legend */
- elseif (isset($_GET['editImage']))
+ if (isset($_GET['editImage']))
{
if ($image->cover)
$_POST['cover'] = 1;
@@ -856,6 +835,61 @@ class AdminProducts extends AdminTab
parent::postProcess(true);
}
+ public function ajaxProcess()
+ {
+ if (Tools::getValue('addImage') !== false)
+ {
+ self::$currentIndex = 'index.php?tab=AdminCatalog';
+ $allowedExtensions = array("jpeg", "gif", "png", "jpg");
+ // max file size in bytes
+ $sizeLimit = $this->maxFileSize;
+ $uploader = new FileUploader($allowedExtensions, $sizeLimit);
+ $result = $uploader->handleUpload();
+ if (isset($result['success']))
+ {
+ $shops = false;
+ if (Shop::isMultiShopActivated())
+ $shops = Shop::getShops();
+ $obj = new Product((int)Tools::getValue('id_product'));
+ $countImages = (int)Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'image WHERE id_product = '.(int)$obj->id);
+ $images = Image::getImages($this->context->language->id, $obj->id);
+ $imagesTotal = Image::getImagesTotal($obj->id);
+ $html = $this->getLineTableImage($result['success'], $imagesTotal + 1, $this->token, $shops);
+ die(Tools::jsonEncode(array("success" => $html)));
+ }
+ else
+ die(Tools::jsonEncode($result));
+ }
+
+ if (Tools::getValue('updateProductImageShopAsso'))
+ {
+ if ($id_image = (int)Tools::getValue('id_image') AND $id_shop = (int)Tools::getValue('id_shop'))
+ if (Tools::getValue('active') == "true")
+ die(Db::getInstance()->Execute('INSERT INTO '._DB_PREFIX_.'image_shop (`id_image`, `id_shop`) VALUES('.(int)$id_image.', '.(int)$id_shop.')'));
+ else
+ die(Db::getInstance()->Execute('DELETE FROM '._DB_PREFIX_.'image_shop WHERE `id_image`='.(int)$id_image.' AND `id_shop`='.(int)$id_shop));
+ }
+
+ if (Tools::getValue('deleteImage'))
+ {
+ $image = new Image((int)Tools::getValue('id_image'));
+ $image->delete();
+ if (!Image::getCover($image->id_product))
+ {
+ $first_img = Db::getInstance()->getRow('
+ SELECT `id_image` FROM `'._DB_PREFIX_.'image`
+ WHERE `id_product` = '.(int)($image->id_product));
+ Db::getInstance()->Execute('
+ UPDATE `'._DB_PREFIX_.'image`
+ SET `cover` = 1
+ WHERE `id_image` = '.(int)($first_img['id_image']));
+ }
+ @unlink(_PS_TMP_IMG_DIR_.'/product_'.$image->id_product.'.jpg');
+ @unlink(_PS_TMP_IMG_DIR_.'/product_mini_'.$image->id_product.'.jpg');
+ die(true);
+ }
+
+ }
protected function _validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $price, $from_quantity, $reduction, $reduction_type, $from, $to)
{
if (!Validate::isUnsignedId($id_shop) OR !Validate::isUnsignedId($id_currency) OR !Validate::isUnsignedId($id_country) OR !Validate::isUnsignedId($id_group))
@@ -923,41 +957,6 @@ class AdminProducts extends AdminTab
$this->copyImage($product->id, $image->id, $method);
}
}
-
- /* Adding a new product image */
- elseif (isset($_FILES['image_product']['name']) && $_FILES['image_product']['name'] != NULL )
- {
- if ($error = checkImageUploadError($_FILES['image_product']))
- $this->_errors[] = $error;
-
- if (!sizeof($this->_errors) AND isset($_FILES['image_product']['tmp_name']) AND $_FILES['image_product']['tmp_name'] != NULL)
- {
- if (!Validate::isLoadedObject($product))
- $this->_errors[] = Tools::displayError('Cannot add image because product add failed.');
- elseif (substr($_FILES['image_product']['name'], -4) == '.zip')
- return $this->uploadImageZip($product);
- else
- {
- $image = new Image();
- $image->id_product = (int)($product->id);
- $_POST['id_product'] = $image->id_product;
- $image->position = Image::getHighestPosition($product->id) + 1;
- if (($cover = Tools::getValue('cover')) == 1)
- Image::deleteCover($product->id);
- $image->cover = !$cover ? !sizeof($product->getImages(Configuration::get('PS_LANG_DEFAULT'))) : true;
- $this->validateRules('Image', 'image');
- $this->copyFromPost($image, 'image');
- if (!sizeof($this->_errors))
- {
- if (!$image->add())
- $this->_errors[] = Tools::displayError('Error while creating additional image');
- else
- $this->copyImage($product->id, $image->id, $method);
- $id_image = $image->id;
- }
- }
- }
- }
if (isset($image) AND Validate::isLoadedObject($image) AND !file_exists(_PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format))
$image->delete();
if (sizeof($this->_errors))
@@ -966,86 +965,6 @@ class AdminProducts extends AdminTab
@unlink(_PS_TMP_IMG_DIR_.'/product_mini_'.$product->id.'.jpg');
return ((isset($id_image) AND is_int($id_image) AND $id_image) ? $id_image : true);
}
-
- public function uploadImageZip($product)
- {
- // Move the ZIP file to the img/tmp directory
- if (!$zipfile = tempnam(_PS_TMP_IMG_DIR_, 'PS') OR !move_uploaded_file($_FILES['image_product']['tmp_name'], $zipfile))
- {
- $this->_errors[] = Tools::displayError('An error occurred during the ZIP file upload.');
- return false;
- }
-
- // Unzip the file to a subdirectory
- $subdir = _PS_TMP_IMG_DIR_.uniqid().'/';
- try
- {
- if (!Tools::ZipExtract($zipfile, $subdir))
- throw new Exception(Tools::displayError('An error occurred while unzipping your file.'));
-
- $types = array('.gif' => 'image/gif', '.jpeg' => 'image/jpeg', '.jpg' => 'image/jpg', '.png' => 'image/png');
- $_POST['id_product'] = (int)$product->id;
- $imagesTypes = ImageType::getImagesTypes('products');
- $highestPosition = Image::getHighestPosition($product->id);
- foreach (scandir($subdir) as $file)
- {
- if ($file[0] == '.')
- continue;
-
- // Create image object
- $image = new Image();
- $image->id_product = (int)$product->id;
- $image->position = ++$highestPosition;
- $image->cover = ($highestPosition == 1 ? true : false);
-
- // Call automated copy function
- $this->validateRules('Image', 'image');
- $this->copyFromPost($image, 'image');
-
- if (sizeof($this->_errors))
- throw new Exception('');
-
- if (!$image->add())
- throw new Exception(Tools::displayError('Error while creating additional image'));
-
- $ext = substr($file, -4);
- $type = (isset($types[$ext]) ? $types[$ext] : '');
- if (!isPicture(array('tmp_name' => $subdir.$file, 'type' => $type)))
- {
- $image->delete();
- throw new Exception(Tools::displayError('Image format not recognized, allowed formats are: .gif, .jpg, .png'));
- }
-
- if (!$new_path = $image->getPathForCreation())
- throw new Exception(Tools::displayError('An error occurred during new folder creation'));
- if (!imageResize($subdir.$file, $new_path.'.'.$image->image_format))
- {
- $image->delete();
- throw new Exception(Tools::displayError('An error occurred while resizing image.'));
- }
-
- foreach ($imagesTypes AS $k => $imageType)
- if (!imageResize($subdir.$file, _PS_PROD_IMG_DIR_.$image->getImgPath().'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height']))
- {
- $image->delete();
- throw new Exception(Tools::displayError('An error occurred while copying image.').' '.stripslashes($imageType['name']));
- }
-
- Module::hookExec('watermark', array('id_image' => $image->id, 'id_product' => $image->id_product));
- }
- }
- catch (Exception $e)
- {
- if ($error = $e->getMessage());
- $this->_errors[] = $error;
- Tools::deleteDirectory($subdir);
- return false;
- }
-
- Tools::deleteDirectory($subdir);
- return true;
- }
-
/**
* Copy a product image
*
@@ -1118,7 +1037,7 @@ class AdminProducts extends AdminTab
/* Check description short size without html */
$limit = (int)Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT');
- if ($limit <= 0) $limit = 800;
+ if ($limit <= 0) $limit = 400;
foreach ($languages AS $language)
if ($value = Tools::getValue('description_short_'.$language['id_lang']))
if (Tools::strlen(strip_tags($value)) > $limit)
@@ -2967,11 +2886,20 @@ class AdminProducts extends AdminTab
function displayFormImages($obj, $token = NULL)
{
+ if(!Tools::getValue('id_product'))
+ return '';
global $attributeJs, $images;
+ $shops = false;
+ if (Shop::isMultiShopActivated())
+ $shops = Shop::getShops();
+
$countImages = (int)Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'image WHERE id_product = '.(int)$obj->id);
+ $images = Image::getImages($this->context->language->id, $obj->id);
+ $imagesTotal = Image::getImagesTotal($obj->id);
+
echo '
-
2. '.$this->l('Images').' ('.$countImages.')
+
2. '.$this->l('Images').' ('.$countImages.')
'.(Tools::getValue('id_image')?$this->l('Edit this product image'):$this->l('Add a new image to this product')).'
@@ -2982,92 +2910,152 @@ class AdminProducts extends AdminTab
'.$this->l('File:').'
-
-
- '.$this->l('Format:').' JPG, GIF, PNG. '.$this->l('Filesize:').' '.(Tools::getMaxUploadSize() / 1024).''.$this->l('Kb max.').'
- '.$this->l('You can also upload a ZIP file containing several images. Thumbnails will be resized automatically.').'
+
',
+
+ classes: {
+ // used to get elements from templates
+ button: 'qq-upload-button',
+ list: 'qq-upload-list',
+
+ file: 'qq-upload-file',
+ spinner: 'qq-upload-spinner',
+ size: 'qq-upload-size',
+ cancel: 'qq-upload-cancel',
+
+ // added to list item when upload completes
+ // used in css to hide progress spinner
+ success: 'qq-upload-success',
+ fail: 'qq-upload-fail'
+ }
+ });
+ // overwrite options with user supplied
+ qq.extend(this._options, o);
+
+ this._element = this._options.element;
+ this._element.innerHTML = this._options.template;
+ this._listElement = this._options.listElement || this._find(this._element, 'list');
+
+ this._classes = this._options.classes;
+
+ this._button = this._createUploadButton(this._find(this._element, 'button'));
+
+ this._bindCancelEvent();
+};
+
+// inherit from Basic Uploader
+qq.extend(qq.FileUploader.prototype, qq.FileUploaderBasic.prototype);
+
+qq.extend(qq.FileUploader.prototype, {
+ /**
+ * Gets one of the elements listed in this._options.classes
+ **/
+ _find: function(parent, type){
+ var element = qq.getByClass(parent, this._options.classes[type])[0];
+ if (!element){
+ throw new Error('element not found ' + type);
+ }
+
+ return element;
+ },
+
+ _onSubmit: function(id, fileName){
+ qq.FileUploaderBasic.prototype._onSubmit.apply(this, arguments);
+ this._addToList(id, fileName);
+ },
+ _onProgress: function(id, fileName, loaded, total){
+ qq.FileUploaderBasic.prototype._onProgress.apply(this, arguments);
+
+ var item = this._getItemByFileId(id);
+ var size = this._find(item, 'size');
+ size.style.display = 'inline';
+
+ var text;
+ if (loaded != total){
+ text = Math.round(loaded / total * 100) + '% from ' + this._formatSize(total);
+ } else {
+ text = this._formatSize(total);
+ }
+
+ qq.setText(size, text);
+ },
+ _onComplete: function(id, fileName, result){
+ qq.FileUploaderBasic.prototype._onComplete.apply(this, arguments);
+
+ // mark completed
+ var item = this._getItemByFileId(id);
+ qq.remove(this._find(item, 'cancel'));
+ qq.remove(this._find(item, 'spinner'));
+
+ if (result.success){
+ qq.addClass(item, this._classes.success);
+ } else {
+ qq.addClass(item, this._classes.fail);
+ }
+ },
+ _addToList: function(id, fileName){
+ var item = qq.toElement(this._options.fileTemplate);
+ item.qqFileId = id;
+
+ var fileElement = this._find(item, 'file');
+ qq.setText(fileElement, this._formatFileName(fileName));
+ this._find(item, 'size').style.display = 'none';
+
+ this._listElement.appendChild(item);
+ },
+ _getItemByFileId: function(id){
+ var item = this._listElement.firstChild;
+
+ // there can't be txt nodes in dynamically created list
+ // and we can use nextSibling
+ while (item){
+ if (item.qqFileId == id) return item;
+ item = item.nextSibling;
+ }
+ },
+ /**
+ * delegate click event for cancel link
+ **/
+ _bindCancelEvent: function(){
+ var self = this,
+ list = this._listElement;
+
+ qq.attach(list, 'click', function(e){
+ e = e || window.event;
+ var target = e.target || e.srcElement;
+
+ if (qq.hasClass(target, self._classes.cancel)){
+ qq.preventDefault(e);
+
+ var item = target.parentNode;
+ self._handler.cancel(item.qqFileId);
+ qq.remove(item);
+ }
+ });
+ }
+});
+
+
+qq.UploadButton = function(o){
+ this._options = {
+ element: null,
+ // if set to true adds multiple attribute to file input
+ multiple: false,
+ // name attribute of file input
+ name: 'file',
+ onChange: function(input){},
+ hoverClass: 'qq-upload-button-hover',
+ focusClass: 'qq-upload-button-focus'
+ };
+
+ qq.extend(this._options, o);
+
+ this._element = this._options.element;
+
+ // make button suitable container for input
+ qq.css(this._element, {
+ position: 'relative',
+ overflow: 'hidden',
+ // Make sure browse button is in the right side
+ // in Internet Explorer
+ direction: 'ltr'
+ });
+
+ this._input = this._createInput();
+};
+
+qq.UploadButton.prototype = {
+ /* returns file input element */
+ getInput: function(){
+ return this._input;
+ },
+ /* cleans/recreates the file input */
+ reset: function(){
+ if (this._input.parentNode){
+ qq.remove(this._input);
+ }
+
+ qq.removeClass(this._element, this._options.focusClass);
+ this._input = this._createInput();
+ },
+ _createInput: function(){
+ var input = document.createElement("input");
+
+ if (this._options.multiple){
+ input.setAttribute("multiple", "multiple");
+ }
+
+ input.setAttribute("type", "file");
+ input.setAttribute("name", this._options.name);
+
+ qq.css(input, {
+ position: 'absolute',
+ // in Opera only 'browse' button
+ // is clickable and it is located at
+ // the right side of the input
+ right: 0,
+ top: 0,
+ fontFamily: 'Arial',
+ // 4 persons reported this, the max values that worked for them were 243, 236, 236, 118
+ fontSize: '118px',
+ margin: 0,
+ padding: 0,
+ cursor: 'pointer',
+ opacity: 0
+ });
+
+ this._element.appendChild(input);
+
+ var self = this;
+ qq.attach(input, 'change', function(){
+ self._options.onChange(input);
+ });
+
+ qq.attach(input, 'mouseover', function(){
+ qq.addClass(self._element, self._options.hoverClass);
+ });
+ qq.attach(input, 'mouseout', function(){
+ qq.removeClass(self._element, self._options.hoverClass);
+ });
+ qq.attach(input, 'focus', function(){
+ qq.addClass(self._element, self._options.focusClass);
+ });
+ qq.attach(input, 'blur', function(){
+ qq.removeClass(self._element, self._options.focusClass);
+ });
+
+ // IE and Opera, unfortunately have 2 tab stops on file input
+ // which is unacceptable in our case, disable keyboard access
+ if (window.attachEvent){
+ // it is IE or Opera
+ input.setAttribute('tabIndex', "-1");
+ }
+
+ return input;
+ }
+};
+
+/**
+ * Class for uploading files, uploading itself is handled by child classes
+ */
+qq.UploadHandlerAbstract = function(o){
+ this._options = {
+ debug: false,
+ action: '/upload.php',
+ // maximum number of concurrent uploads
+ maxConnections: 999,
+ onProgress: function(id, fileName, loaded, total){},
+ onComplete: function(id, fileName, response){},
+ onCancel: function(id, fileName){}
+ };
+ qq.extend(this._options, o);
+
+ this._queue = [];
+ // params for files in queue
+ this._params = [];
+};
+qq.UploadHandlerAbstract.prototype = {
+ log: function(str){
+ if (this._options.debug && window.console) console.log('[uploader] ' + str);
+ },
+ /**
+ * Adds file or file input to the queue
+ * @returns id
+ **/
+ add: function(file){},
+ /**
+ * Sends the file identified by id and additional query params to the server
+ */
+ upload: function(id, params){
+ var len = this._queue.push(id);
+
+ var copy = {};
+ qq.extend(copy, params);
+ this._params[id] = copy;
+
+ // if too many active uploads, wait...
+ if (len <= this._options.maxConnections){
+ this._upload(id, this._params[id]);
+ }
+ },
+ /**
+ * Cancels file upload by id
+ */
+ cancel: function(id){
+ this._cancel(id);
+ this._dequeue(id);
+ },
+ /**
+ * Cancells all uploads
+ */
+ cancelAll: function(){
+ for (var i=0; i= max && i < max){
+ var nextId = this._queue[max-1];
+ this._upload(nextId, this._params[nextId]);
+ }
+ }
+};
+
+/**
+ * Class for uploading files using form and iframe
+ * @inherits qq.UploadHandlerAbstract
+ */
+qq.UploadHandlerForm = function(o){
+ qq.UploadHandlerAbstract.apply(this, arguments);
+
+ this._inputs = {};
+};
+// @inherits qq.UploadHandlerAbstract
+qq.extend(qq.UploadHandlerForm.prototype, qq.UploadHandlerAbstract.prototype);
+
+qq.extend(qq.UploadHandlerForm.prototype, {
+ add: function(fileInput){
+ fileInput.setAttribute('name', 'qqfile');
+ var id = 'qq-upload-handler-iframe' + qq.getUniqueId();
+
+ this._inputs[id] = fileInput;
+
+ // remove file input from DOM
+ if (fileInput.parentNode){
+ qq.remove(fileInput);
+ }
+
+ return id;
+ },
+ getName: function(id){
+ // get input value and remove path to normalize
+ return this._inputs[id].value.replace(/.*(\/|\\)/, "");
+ },
+ _cancel: function(id){
+ this._options.onCancel(id, this.getName(id));
+
+ delete this._inputs[id];
+
+ var iframe = document.getElementById(id);
+ if (iframe){
+ // to cancel request set src to something else
+ // we use src="javascript:false;" because it doesn't
+ // trigger ie6 prompt on https
+ iframe.setAttribute('src', 'javascript:false;');
+
+ qq.remove(iframe);
+ }
+ },
+ _upload: function(id, params){
+ var input = this._inputs[id];
+
+ if (!input){
+ throw new Error('file with passed id was not added, or already uploaded or cancelled');
+ }
+
+ var fileName = this.getName(id);
+
+ var iframe = this._createIframe(id);
+ var form = this._createForm(iframe, params);
+ form.appendChild(input);
+
+ var self = this;
+ this._attachLoadEvent(iframe, function(){
+ self.log('iframe loaded');
+
+ var response = self._getIframeContentJSON(iframe);
+
+ self._options.onComplete(id, fileName, response);
+ self._dequeue(id);
+
+ delete self._inputs[id];
+ // timeout added to fix busy state in FF3.6
+ setTimeout(function(){
+ qq.remove(iframe);
+ }, 1);
+ });
+
+ form.submit();
+ qq.remove(form);
+
+ return id;
+ },
+ _attachLoadEvent: function(iframe, callback){
+ qq.attach(iframe, 'load', function(){
+ // when we remove iframe from dom
+ // the request stops, but in IE load
+ // event fires
+ if (!iframe.parentNode){
+ return;
+ }
+
+ // fixing Opera 10.53
+ if (iframe.contentDocument &&
+ iframe.contentDocument.body &&
+ iframe.contentDocument.body.innerHTML == "false"){
+ // In Opera event is fired second time
+ // when body.innerHTML changed from false
+ // to server response approx. after 1 sec
+ // when we upload file with iframe
+ return;
+ }
+
+ callback();
+ });
+ },
+ /**
+ * Returns json object received by iframe from server.
+ */
+ _getIframeContentJSON: function(iframe){
+ // iframe.contentWindow.document - for IE<7
+ var doc = iframe.contentDocument ? iframe.contentDocument: iframe.contentWindow.document,
+ response;
+
+ this.log("converting iframe's innerHTML to JSON");
+ this.log("innerHTML = " + doc.body.innerHTML);
+
+ try {
+ response = eval("(" + doc.body.innerHTML + ")");
+ } catch(err){
+ response = {};
+ }
+
+ return response;
+ },
+ /**
+ * Creates iframe with unique name
+ */
+ _createIframe: function(id){
+ // We can't use following code as the name attribute
+ // won't be properly registered in IE6, and new window
+ // on form submit will open
+ // var iframe = document.createElement('iframe');
+ // iframe.setAttribute('name', id);
+
+ var iframe = qq.toElement('');
+ // src="javascript:false;" removes ie6 prompt on https
+
+ iframe.setAttribute('id', id);
+
+ iframe.style.display = 'none';
+ document.body.appendChild(iframe);
+
+ return iframe;
+ },
+ /**
+ * Creates form, that will be submitted to iframe
+ */
+ _createForm: function(iframe, params){
+ // We can't use the following code in IE6
+ // var form = document.createElement('form');
+ // form.setAttribute('method', 'post');
+ // form.setAttribute('enctype', 'multipart/form-data');
+ // Because in this case file won't be attached to request
+ var form = qq.toElement('');
+
+ var queryString = qq.obj2url(params, this._options.action);
+
+ form.setAttribute('action', queryString);
+ form.setAttribute('target', iframe.name);
+ form.style.display = 'none';
+ document.body.appendChild(form);
+
+ return form;
+ }
+});
+
+/**
+ * Class for uploading files using xhr
+ * @inherits qq.UploadHandlerAbstract
+ */
+qq.UploadHandlerXhr = function(o){
+ qq.UploadHandlerAbstract.apply(this, arguments);
+
+ this._files = [];
+ this._xhrs = [];
+
+ // current loaded size in bytes for each file
+ this._loaded = [];
+};
+
+// static method
+qq.UploadHandlerXhr.isSupported = function(){
+ var input = document.createElement('input');
+ input.type = 'file';
+
+ return (
+ 'multiple' in input &&
+ typeof File != "undefined" &&
+ typeof (new XMLHttpRequest()).upload != "undefined" );
+};
+
+// @inherits qq.UploadHandlerAbstract
+qq.extend(qq.UploadHandlerXhr.prototype, qq.UploadHandlerAbstract.prototype)
+
+qq.extend(qq.UploadHandlerXhr.prototype, {
+ /**
+ * Adds file to the queue
+ * Returns id to use with upload, cancel
+ **/
+ add: function(file){
+ if (!(file instanceof File)){
+ throw new Error('Passed obj in not a File (in qq.UploadHandlerXhr)');
+ }
+ return this._files.push(file) - 1;
+ },
+ getName: function(id){
+ var file = this._files[id];
+ // fix missing name in Safari 4
+ return file.fileName != null ? file.fileName : file.name;
+ },
+ getSize: function(id){
+ var file = this._files[id];
+ return file.fileSize != null ? file.fileSize : file.size;
+ },
+ /**
+ * Returns uploaded bytes for file identified by id
+ */
+ getLoaded: function(id){
+ return this._loaded[id] || 0;
+ },
+ /**
+ * Sends the file identified by id and additional query params to the server
+ * @param {Object} params name-value string pairs
+ */
+ _upload: function(id, params){
+ var file = this._files[id],
+ name = this.getName(id),
+ size = this.getSize(id);
+
+ this._loaded[id] = 0;
+
+ var xhr = this._xhrs[id] = new XMLHttpRequest();
+ var self = this;
+
+ xhr.upload.onprogress = function(e){
+ if (e.lengthComputable){
+ self._loaded[id] = e.loaded;
+ self._options.onProgress(id, name, e.loaded, e.total);
+ }
+ };
+
+ xhr.onreadystatechange = function(){
+ if (xhr.readyState == 4){
+ self._onComplete(id, xhr);
+ }
+ };
+
+ // build query string
+ params = params || {};
+ params['qqfile'] = name;
+ var queryString = qq.obj2url(params, this._options.action);
+
+ xhr.open("POST", queryString, true);
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
+ xhr.setRequestHeader("Content-Type", "application/octet-stream");
+ xhr.send(file);
+ },
+ _onComplete: function(id, xhr){
+ // the request was aborted/cancelled
+ if (!this._files[id]) return;
+
+ var name = this.getName(id);
+ var size = this.getSize(id);
+
+ this._options.onProgress(id, name, size, size);
+
+ if (xhr.status == 200){
+ this.log("xhr - server response received");
+ this.log("responseText = " + xhr.responseText);
+
+ var response;
+
+ try {
+ response = jQuery.parseJSON(xhr.responseText);
+ } catch(err){
+ console.log(err);
+ response = {};
+ }
+
+ this._options.onComplete(id, name, response);
+
+ } else {
+ this._options.onComplete(id, name, {});
+ }
+
+ this._files[id] = null;
+ this._xhrs[id] = null;
+ this._dequeue(id);
+ },
+ _cancel: function(id){
+ this._options.onCancel(id, this.getName(id));
+
+ this._files[id] = null;
+
+ if (this._xhrs[id]){
+ this._xhrs[id].abort();
+ this._xhrs[id] = null;
+ }
+ }
+});
\ No newline at end of file
diff --git a/translations/fr/errors.php b/translations/fr/errors.php
index 1a6fb4f11..521780913 100644
--- a/translations/fr/errors.php
+++ b/translations/fr/errors.php
@@ -19,8 +19,6 @@ $_ERRORS['82d6830fc99545242c1333aee42d5a17'] = 'Une erreur est survenue pendant
$_ERRORS['b464b4391b0ed5cc6d35dee9a62c3244'] = 'Une erreur est survenue pendant l\'installation du module :';
$_ERRORS['6b9b69ab9178ef91715387ca776ce2b5'] = 'Une erreur est survenue pendant la désinstallation du module :';
$_ERRORS['2ff0db4e2462e54ee9e4d345d9e3f4d7'] = 'Une erreure est survenue, ce module n\'existe pas :';
-$_ERRORS['c8d29e2bc52b6c92a1560990874aa565'] = 'Une erreur s\'est produite lors de l\'ajout du comté';
-$_ERRORS['920ecfc0507c000f2ae996465a9a3b16'] = 'Une erreur s\'est produite lors de l\'ajout des codes postaux';
$_ERRORS['d8f4f69d48a199f1c406d3e821b7828a'] = 'une erreur est survenue avant d\'envoyer le message';
$_ERRORS['200cb26c2479e770241b1c62ccfb8e08'] = 'une erreur est survenue lors de la suppression du produit personnalisé';
$_ERRORS['8eccd648c123a09bcf8520fea052861d'] = 'une erreur est survenue lors de la suppression du produit';
@@ -59,7 +57,6 @@ $_ERRORS['dea9b328f904f025e4031bf8dfb7b392'] = 'une erreur s\'est produite penda
$_ERRORS['2d97cc6ccfbff56dd7fa8a135970e964'] = 'Une erreur est survenue lors de la suppression d\'une réduction de groupe';
$_ERRORS['d5b9eddfad35e1cd6c97eff40c8301e6'] = 'Une erreur est survenue pendant la suppression de l\'image';
$_ERRORS['54bff0a0282d2be7fe5ee14aa4628291'] = 'Une erreur est survenue lors de la suppression d\'un prix spécifique';
-$_ERRORS['fdebc7ba5328f22535df315e9f52b2f5'] = 'Une erreur est survenue pendant la récupération d\'un comté';
$_ERRORS['28c39342f22a394f233ec0cba0ecfa02'] = 'Une erreur est survenue pendant la récupération d\'un état';
$_ERRORS['bdc3ce1a2e9e6d8ab5bd0dd31c1a03fe'] = 'Une erreur est survenue lors de l\'import d\'une devise';
$_ERRORS['42a8c33bd3e937c419378c5a965e65ac'] = 'Une erreur est survenue lors de l\'import d\'une taxe';
@@ -95,6 +92,7 @@ $_ERRORS['5636dd80d3968f9b1ce4400bd71c5a7a'] = 'une erreur est apparue lors de l
$_ERRORS['26e6e2aef679da0451f05fb535ac40d7'] = 'une erreur s\'est produite pendant l\'envoi du fichier';
$_ERRORS['c791e58067fc99ef9fdb95bace661815'] = 'une erreur s\'est produite et votre nouveau mot de passe n\'a pas pu vous être envoyé : merci de signaler ce problème en utilisant le formulaire de contact';
$_ERRORS['420530ab27ece9fef8cc0b6835e65d31'] = 'Une erreur s\'est produite, votre message n\'a pas été envoyé s\'il vous plaît contactez votre administrateur système';
+$_ERRORS['9475177df74030214d1e6cf3ee642a9a'] = 'Une erreur s\'est produite.';
$_ERRORS['8572b5d5a2dd8a7558363713a2e353da'] = 'Un article de votre panier n\'est plus disponible pour cette quantité, vous ne pouvez continuer votre commande';
$_ERRORS['099788460b01d1cfe9997d4c577f7f56'] = 'Un article de votre panier n\'est plus disponible, vous ne pouvez continuer votre commande';
$_ERRORS['b9c1228a8e8c3412befae5d854508114'] = 'Une commande a déjà été passée avec ce panier';
@@ -109,7 +107,6 @@ $_ERRORS['8243462d21cc70da864e92c31c29486a'] = 'Requête SQL pour les sous-domai
$_ERRORS['d1a9295d276a65933e0a7334a12e6f41'] = 'Mauvaise extension de fichier';
$_ERRORS['2d4aab5065e4f7b78be97f9a6de62a1d'] = 'La categorie CMS ne peut être déplacée ici';
$_ERRORS['f55449d53d91aff67bad843f9ab47aee'] = 'Système de cache manquant ';
-$_ERRORS['c8e61b851c4a858374ad46b1171b16ec'] = 'fichier de configuration inaccessible';
$_ERRORS['a855995ec17e0c80d5985a885f3d4d84'] = 'Impossible d\'ajouter un serveur Memcache';
$_ERRORS['3d35aa7e75c2f7467f45b4fa1c8bf8a9'] = 'impossible d\'ajouter d\'image car l\'ajout du produit a échoué';
$_ERRORS['18ed633d86ed8181bded16b1876a3b5a'] = 'impossible d\'ajouter ce produit car votre bon de réduction n\'est pas valable sur les produits soldés';
@@ -177,6 +174,7 @@ $_ERRORS['869507b317c3e475fc0ca9f3551e3760'] = 'Une erreur s\'est produite lors
$_ERRORS['9ec9207929cd361ca5e264548f411e16'] = 'Erreur lors de la mise à jour de la base de données de PayPal';
$_ERRORS['c200140aea36e1efbf655fabf3f3b59e'] = 'erreur lors de la création de l\'image supplémentaire';
$_ERRORS['1a80f28eca93f30e2e333b6432890c10'] = 'une erreur est survenue pendant l\'extraction du module (le fichier peut être corrompu)';
+$_ERRORS['efccf3b0fd1b65f88bd6dfa2821060c8'] = 'uen erreur est survenue pendant la mise à jour du statut';
$_ERRORS['1391c1ff3846b38862bbfc43938b8270'] = 'une erreur s\'est produite pendant le chargement de l\'image ; vous devez changer votre configuration serveur';
$_ERRORS['76f643ec10f812dbaccd1250fc1a4d15'] = 'Erreur : panier vide';
$_ERRORS['1769b5ab48b8e2ce733fb38663ec853a'] = 'Erreur : Serveur ou port SMTP invalides';
@@ -203,8 +201,11 @@ $_ERRORS['d194b022bc5a1a01657823aaccd45e9b'] = 'Erreur fatale: l\'iso code n\'es
$_ERRORS['9b3261577a34cd7c48ad83d80295ff09'] = 'Erreur fatale : pas de transporteur par défaut';
$_ERRORS['411ec6016c7845e0c49fb51160a12677'] = 'Erreur fatale : le répertoire contenant les modules n\'est pas présent';
$_ERRORS['6f268ac84ce6195ecf4e3dfe437e2aee'] = 'Erreur fatale: Aucun client';
+$_ERRORS['847b0a793110ff20927e76269328e582'] = 'Extension invalide, je fichier doit avoir l\'extension suivante';
$_ERRORS['42e7b89a369899d8c0c4f0631bd1c921'] = 'Fichier install.sql est manquant ';
$_ERRORS['058dcec46037cb9f9c8b7d2b76799834'] = 'Fichier install.sql n\'est pas lisible ';
+$_ERRORS['3ca396a7b899e8d1a593e5d7896d0d1e'] = 'Le fichier est vide';
+$_ERRORS['ec89c7fa06f1df12a2b43c7159e21119'] = 'Le fichier est trop lourd';
$_ERRORS['4eeb89c9c7ae218f3d9cb4faaf8f1e38'] = 'Taille de nom de fichier trop long';
$_ERRORS['1b921ec32b4bac52d8801f4e196f79c6'] = 'Le drapeau et l\'image de \"Aucune image\" sont requis';
$_ERRORS['71754079aaeefc5c6e745ddd59f8a35f'] = 'Commande gratuite';
@@ -225,7 +226,6 @@ $_ERRORS['8b978fa2ad857b185bc61dc5acb10927'] = 'Object réduction incorrect';
$_ERRORS['da393a0fcc28b1678ba1f8f59ea94b50'] = 'Object commande incorrect';
$_ERRORS['c99348e30ef9822b53fce9b9f0c198c9'] = 'Valeur incorrecte pour une qualité d\'image JPEG.';
$_ERRORS['75e3bbc53d0a62d319235ffebf9e219c'] = 'Valeur incorrecte pour une qualité d\'image PNG.';
-$_ERRORS['259f417808483b6dc18a10510fd8d3cc'] = 'Propriétés du comté invalides';
$_ERRORS['c1c8a564c10a0efe07bb4e4b20d88cc9'] = 'Identifiant non valide';
$_ERRORS['bfd99559857dfcfc40cb0d0e6c8aee1b'] = 'Nom invalide';
$_ERRORS['f9c7939a8397ee022fefee2bdb3407af'] = 'URL invalide';
@@ -302,6 +302,7 @@ $_ERRORS['c2492c52caab207d21da2c0decd8a405'] = 'aucun élément enregistré';
$_ERRORS['f787618e514c038851726224d7e4421e'] = 'aucun fichier selectionné';
$_ERRORS['1b599bf89c1bf4f8640ef31f3acb9f40'] = 'aucun fichier spécifié';
$_ERRORS['298883b17e36ee3a18d73e835c0b44fc'] = 'Aucun fichier n\'a été envoyé';
+$_ERRORS['20c6125376d8de28149d655c7cc25e32'] = 'Aucun fichiers n\'a été envoyés';
$_ERRORS['cb20447a4bf5ff9bec717ec68a357a93'] = 'Aucun moteur de rendu choisi';
$_ERRORS['ccacacd12f75e1ab3f9ce3e234ed5777'] = 'Aucun moteur de tableau sélectionné';
$_ERRORS['774eec2772b5f57b2e13d11e1b093a4f'] = 'Aucune image trouvée pour la combinaison avec id_product = %s et la position de l\'image = %s.';
@@ -315,7 +316,6 @@ $_ERRORS['e3ac5a39682f9b3a09f6063f714ffc48'] = 'Aucune méthode de paiement est
$_ERRORS['8912e1863fe81af9cabd76f5de9e7495'] = 'Aucun produit ou quantité sélectionné.';
$_ERRORS['b7d99b30df0aade1e4d459fab8c7078f'] = 'Aucun profil';
$_ERRORS['7f3f9fec825792f2b728db9d55078e80'] = 'Aucune quantité sélectionnée pour le produit.';
-$_ERRORS['6f3455d187a23443796efdcbe044096b'] = 'Aucune taxe';
$_ERRORS['a9839ad48cf107667f73bad1d651f2ca'] = 'Aucun gabarit trouvé';
$_ERRORS['eddeabd79f8ca673d888fa2ffe9cf69a'] = 'Aucun gabarit trouvé pour le module';
$_ERRORS['25723bba0086a38394001a8ca41e9126'] = 'valeur du champ exceptions incorrect';
@@ -382,6 +382,7 @@ $_ERRORS['d2bbf245e9591814fe994df3cae95964'] = 'Le fichier est vide';
$_ERRORS['40f9f62de5a8ccf912bc1cd19d515dd2'] = 'Le fichier est trop volumineux.';
$_ERRORS['d139abab2541129dfae24c733635104c'] = 'Le fichier a été partiellement transféré';
$_ERRORS['723c870c1b443e052e290bd96f46e977'] = 'Le champ suivant n\'est pas valide selon la méthode de validation';
+$_ERRORS['b19a2bf8353427355aaa724a837f0217'] = 'Les modules suivants n\'ont pas été installés correctements:';
$_ERRORS['59e3d45dc17f2e9fc4caac2f887bd075'] = 'La fonction';
$_ERRORS['8227e4867a9388488b04ea32665bcc18'] = 'Le répertoire du module doit avoir les droits d\'écriture';
$_ERRORS['418e2586ee498c46f6375e9a0008517c'] = 'le détail du retour produit est invalide';
@@ -398,7 +399,6 @@ $_ERRORS['92cfc43b8b3cf7a964f2ef24fd22f8df'] = 'Il n\'y pas de modules dans votr
$_ERRORS['3c9a4f1e91ee7bb51c29bdc9362077fe'] = 'il n\'y a aucun compte enregistré avec cette adresse e-mail';
$_ERRORS['2e857abc0ea5d7f97522254ca00c18bb'] = 'il n\'y a pas assez de produits en stock';
$_ERRORS['59382adebc7f0d65c42fe773d443e4c7'] = 'ce code ISO est déjà lié à une autre langue';
-$_ERRORS['61eaad60c84d4d2a5b3afcc3751c5635'] = 'Le code postal est déjà utilisée.';
$_ERRORS['4649093d4d10aa95a212636f146c47fd'] = 'ce compte n\'existe pas';
$_ERRORS['a56b6c43645970e79a8098df1dfc9746'] = 'cette adresse ne peut pas être effacée';
$_ERRORS['08b2765dc6c449c903f8b30ac7e55f91'] = 'cette adresse n\'est pas valide';
@@ -418,9 +418,7 @@ $_ERRORS['e0a602c130d12d57cd4ca2a8b9240917'] = 'Ce fichier doit être éditable
$_ERRORS['c9615dc36879116ef8c5f1ab08543191'] = 'Ce fichier n\'existe plus.';
$_ERRORS['b72591580ab2e9ecb08d1a26ac23641b'] = 'Cette clé est utilisée trop de fois (une seule autorisée)';
$_ERRORS['b60be6e4c0df15343a7cdafccb174159'] = 'Ce module ne peut être greffé sur ce hook.';
-$_ERRORS['a44f9463879b845e1ad2c45e75aebd18'] = 'Ce module est déjà installé :';
$_ERRORS['aa508f3bd17074b8941571083de1350e'] = 'ce module est déjà greffé sur ce hook';
-$_ERRORS['ae38c419414887fa47b7f5a811e5f42d'] = 'Ce module est déjà désinstallé :';
$_ERRORS['e8be55bf3a30501aef09d2e74de97976'] = 'ce nom existe déjà';
$_ERRORS['b74c118d823d908d653cfbf1c877ae55'] = 'ce nom est déjà utilisé par une autre liste';
$_ERRORS['d312d5c57aff77e76cab1b5981bc5606'] = 'Ce nom n\'est pas autorisé';
@@ -475,7 +473,6 @@ $_ERRORS['ec5f6f7f65190788d12ef16ab6135009'] = 'vous ne pouvez pas tous les supp
$_ERRORS['e5403f88992848e3b3f3f92bf015e8e2'] = 'Vous ne pouvez pas effacer le groupe par défaut';
$_ERRORS['1cd979028e05c3ccd607b99a6714ad6f'] = 'Vous ne pouvez pas supprimer ou désactiver un groupe de boutique qui contient une boutique qui l\'utilise';
$_ERRORS['dfd9f28270256b343e6252198474b1f2'] = 'Vous ne pouvez pas supprimer ou désactiver le dernier groupe de boutique';
-$_ERRORS['b97bd4782c45637c71441329bfd34655'] = 'Vous ne pouvez pas supprimer ou désactiver la dernière boutique';
$_ERRORS['052800f7397d4c12924faa83534c62f0'] = 'Vous ne pouvez pas désactiver ou supprimer le dernier compte administrateur';
$_ERRORS['f5d44b60e38b28d19549bb7a107654ca'] = 'Vous ne pouvez pas supprimer votre propre compte.';
$_ERRORS['cc7fe0548f3832b01e1d4ce466b99b4c'] = 'Vous ne pouvez pas définir cette langue comme langue par défaut parce qu\'elle est désactivée';
@@ -498,9 +495,7 @@ $_ERRORS['251db6b140bc5b3adcbe0c5efadb3c7d'] = 'vous devez ajouter au moins un a
$_ERRORS['0d15d3afa8c174934ff0e43ce3b99bd3'] = 'Vous devez être identifié pour gérer vos alertes';
$_ERRORS['16a23698e7cf5188ce1c07df74298076'] = 'Vous devez être identifié pour gérer vos liste voeux';
$_ERRORS['d14e88e2344c5dba06dad332a7f74726'] = 'Vous devez choisir un transporteur';
-$_ERRORS['58ac247e63d629fd85e0376c1c42d783'] = 'vous devez choisir un thème';
$_ERRORS['577c8acd6847e0a8fc64911123f2ec1f'] = 'Vous devez au minimum spécifier un serveur et un port SMTP. Si vous n\'êtes pas sûrs, utilisez la fonction mail() de PHP à la place.';
-$_ERRORS['b095746c9800d06a39f33c83188431bc'] = 'Vous devez avoir une url principale par boutique';
$_ERRORS['ae0e822b6fad0de61c231ef188997e92'] = 'Un produit est nécessaire pour supprimer une alerte';
$_ERRORS['b0ffc4925401f6f4edb038f5ca954937'] = 'Vous devez vous identifier';
$_ERRORS['39916f579f264041641c122e68e545d5'] = 'Vous devez enregistrer au moins un numéro de téléphone';
@@ -523,7 +518,6 @@ $_ERRORS['70f4b635847038d056e33959821a7a66'] = 'caractères max';
$_ERRORS['e0d4da0607fb1793b6e1d348c36d52cb'] = 'config.xml est manquant dans le dossier de votre thème';
$_ERRORS['1d112c010ef14e32e478b36aca8d3414'] = 'config.xml dans votre dossier de thème n\'est pas un fichier xml valide';
$_ERRORS['6364b8f0fcf00c1fedb76a7a7b7ad03e'] = 'Le fichier config.xml du thème n\'a pas été créé pour cette version de Prestashop';
-$_ERRORS['80e9a269b3e9b377f35cb6b642edceae'] = 'Description: Longueur >';
$_ERRORS['b0accee4a4704ec46d245b722309a8be'] = 'n\'existe pas en base de données';
$_ERRORS['06e3d36fa30cea095545139854ad1fb9'] = 'champ';
$_ERRORS['1cd6f2b0848e672cb987e15e0598a144'] = 'pour la langue';