Skip to content
Permalink
Browse files

Merge branch 't/12724' into major

  • Loading branch information...
Reinmar committed Feb 18, 2015
2 parents 5bf8989 + dc2501f commit 22b9485fb73064a4540b5495d89ed3f99e97c5d3
@@ -19,17 +19,28 @@

this.onload = function( evt ) {
// Total file size.
var total = 1000 * 10,
loaded = 0;
var total = 1163,
step = Math.round( total / 10 ),
loaded = 0,
xhr = this;

function progress() {
setTimeout( function() {
// Load 1000 bytes every 300 milliseconds.
loaded += 1000;
if ( xhr.aborted ) {
return;
}

loaded += step;
if ( loaded > total ) {
loaded = total;
}

if ( loaded < total ) {
if ( loaded > step * 4 && xhr.responseText.indexOf( 'incorrectFile' ) > 0 ) {
xhr.aborted = true;
xhr.onerror();
} else if ( loaded < total ) {
evt.loaded = loaded;
baseOnProgress( evt );
baseOnProgress( { loaded: loaded } );
progress();
} else {
baseOnLoad( evt );
@@ -40,6 +51,11 @@
progress();
};

this.abort = function() {
this.aborted = true;
this.onabort();
};

this.baseSend( data );
};
} )();
@@ -51,7 +51,7 @@ CKEDITOR.plugins.add( 'notification', {

// Close the last notification on ESC.
editor.on( 'key', function( evt ) {
if ( evt.data.keyCode == 27 /* ESC */ ) {
if ( evt.data.keyCode == 27 ) { /* ESC */
var notifications = editor._.notificationArea.notifications;

if ( !notifications.length ) {
@@ -77,7 +77,7 @@ CKEDITOR.plugins.add( 'notification', {
var message = new CKEDITOR.dom.element( 'div' );
message.setStyles( {
position: 'fixed',
'margin-left': '-9999'
'margin-left': '-9999px'
} );
message.setAttributes( {
'aria-live': 'assertive',
@@ -236,8 +236,15 @@ Notification.prototype = {
* if it was hidden and read by screen readers.
*/
update: function( options ) {
var show = true;

if ( this.editor.fire( 'notificationUpdate', { notification: this, options: options } ) === false ) {
return;
// The idea of cancelable event is to let user create his own way of displaying notification, so if
// `notificationUpdate` event will be canceled there will be no interaction with notification area, but on
// the other hand the logic should work anyway so object will be updated (including `element` property).
// Note: we can safely update the element's attributes below, because this element is created inside
// the constructor. If the notificatinShow event was canceled as well, the element is detached from DOM.
show = false;
}

var element = this.element,
@@ -276,7 +283,7 @@ Notification.prototype = {
}
}

if ( options.important ) {
if ( show && options.important ) {
element.setAttribute( 'role', 'alert' );

if ( !this.isVisible() ) {
@@ -871,7 +878,9 @@ CKEDITOR.plugins.notification = Notification;

/**
* This event is fired when the {@link CKEDITOR.plugins.notification#update} method is called, before the
* notification is updated. If this event will be canceled, notification will be not updated.
* notification is updated. If this event is canceled, notification will not be shown even if update was important,
* but object will be updated anyway. Note that canceling this event does not prevent updating {@link #element}'s
* attributes, but if {@link #notificationShow} was canceled as well this element is detached from the DOM.
*
* Using this event allows to fully customize how a notification will be updated. It may be used to integrate
* the CKEditor notifications system with the web page's notifications.
@@ -80,6 +80,8 @@
loader.upload( uploadUrl );

fileTools.markElement( img, 'uploadimage', loader.id );

fileTools.bindNotifications( editor, loader );
}
}

@@ -44,6 +44,8 @@

fileTools.markElement( el, 'filereader', loader.id );

fileTools.bindNotifications( editor, loader );

data.dataValue += el.getOuterHtml();
}
}
@@ -9,7 +9,7 @@
<title>Upload image dev sample</title>
<script src="../../../ckeditor.js"></script>
<script src="filereaderplugin.js"></script>
<!-- // <script src="../../filetools/dev/uploaddebugger.js"></script> -->
<script src="../../filetools/dev/uploaddebugger.js"></script>
<link href="../../../samples/sample.css" rel="stylesheet">
</head>
<body>
@@ -0,0 +1,11 @@
/**
* @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or http://ckeditor.com/license
*/

CKEDITOR.plugins.setLang( 'uploadwidget', 'en', {
abort: 'Upload aborted by user.',
done: 'Uploading done.',
uploadOne: 'Uploading file ({percentage}%)...',
uploadMany: 'Uploading files, {current} of {max} done ({percentage}%)...'
} );
@@ -3,20 +3,31 @@
* For licensing, see LICENSE.md or http://ckeditor.com/license
*/

// TODO: remove it when upload widgets will use notifications.
/* global console */

'use strict';

( function() {
CKEDITOR.plugins.add( 'uploadwidget', {
requires: 'widget,clipboard,filetools',
lang: 'en', // %REMOVE_LINE_CORE%
requires: 'widget,clipboard,filetools,notificationaggregator',

init: function( editor ) {
// Images which should be changed into upload widget needs to be marked with `data-widget` on paste,
// because otherwise wrong widget may handle upload placeholder element (e.g. image2 plugin would handle image).
// `data-widget` attribute is allowed only in the elements which has also `data-cke-upload-id` attribute.
editor.filter.allow( '*[!data-widget,!data-cke-upload-id]' );

// Create one notification agregator for all types of upload widgets for editor.
var aggregator = editor._.uploadWidgetNotificaionAggregator =
new CKEDITOR.plugins.notificationAggregator(
editor,
editor.lang.uploadwidget.uploadMany,
editor.lang.uploadwidget.uploadOne );

aggregator.on( 'finished', function() {
if ( aggregator.getTasksCount() > 0 ) {
editor.showNotification( editor.lang.uploadwidget.done, 'success' );
}
} );
}
} );

@@ -105,6 +116,8 @@
*
* fileTools.markElement( el, 'filereader', loader.id );
*
* fileTools.bindNotifications( editor, loader );
*
* evt.data.dataValue += el.getOuterHtml();
* }
* }
@@ -144,7 +157,9 @@
if ( el ) {
loader[ loadMethod ]( def.uploadUrl );

markElement( el, name, loader.id );
CKEDITOR.fileTools.markElement( el, name, loader.id );

CKEDITOR.fileTools.bindNotifications( editor, loader );

data.dataValue += el.getOuterHtml();
}
@@ -206,8 +221,6 @@

editor.fire( 'lockSnapshot' );

console.log( loader.status );

var methodName = 'on' + capitalize( loader.status );

if ( typeof widget[ methodName ] === 'function' ) {
@@ -218,7 +231,6 @@
}

if ( loader.status == 'error' || loader.status == 'abort' ) {
console.log( loader.message );
editor.widgets.del( widget );
}

@@ -375,13 +387,52 @@
} );
}

/**
* Binds notification to the {@link CKEDITOR.fileTools.fileLoader file loader} so the upload widget will use
* notification to show the status and progress.
* This function uses {@link CKEDITOR.plugins.notificationAggregator}, so even if multiple files are uploading
* only one notification is shown. The exception are warnings, because they are shown in the separate notifications.
*
* @param {CKEDITOR.editor} editor The editor instance.
* @param {CKEDITOR.fileTools.fileLoader} loader The fileLoader instance.
*/
function bindNotifications( editor, loader ) {
var aggregator = editor._.uploadWidgetNotificaionAggregator,
task;

loader.on( 'uploading', function() {
task = aggregator.createTask( { weight: loader.total } );
} );

loader.on( 'update', function() {
if ( task && loader.status == 'uploading' ) {
task.update( loader.uploaded );
}
} );

loader.on( 'uploaded', function() {
task && task.done();
} );

loader.on( 'error', function() {
task && task.cancel();
editor.showNotification( loader.message, 'warning' );
} );

loader.on( 'abort', function() {
task && task.cancel();
editor.showNotification( editor.lang.uploadwidget.abort, 'info' );
} );
}

// Two plugins extends this object.
if ( !CKEDITOR.fileTools ) {
CKEDITOR.fileTools = {};
}

CKEDITOR.tools.extend( CKEDITOR.fileTools, {
addUploadWidget: addUploadWidget,
markElement: markElement
markElement: markElement,
bindNotifications: bindNotifications
} );
} )();
@@ -411,8 +411,22 @@ bender.test( {

assert.isTrue( listener.calledOnce );

assertNotifications( editor, [ { message: 'Foo', type: 'info', alert: true } ] );
assertNotifications( editor, [ { message: 'Foo', type: 'warning', alert: false } ] );
},

'test notificationUpdate event do not show if event canceled': function() {
var editor = this.editor,
notification = new CKEDITOR.plugins.notification( editor, { message: 'Foo' } );

listener = sinon.stub().returns( false );

this.editor.on( 'notificationUpdate', listener );

notification.update( { important: true } );

assert.isTrue( listener.calledOnce );

assertNotifications( editor, [] );
},

'test notificationHide event': function() {
@@ -75,6 +75,10 @@
// Clear uploads repository.
this.editors[ editorName ].uploadsRepository._.loaders = [];
}

if ( CKEDITOR.fileTools.bindNotifications.reset ) {
CKEDITOR.fileTools.bindNotifications.reset();
}
},

'test classic with image1 (integration test)': function() {
@@ -409,6 +413,26 @@
wait();
},

'test bindNotifications when paste image': function() {
var editor = this.editors.classic;

CKEDITOR.fileTools.bindNotifications = sinon.spy();

resumeAfter( editor, 'paste', function() {
var spy = CKEDITOR.fileTools.bindNotifications;
assert.areSame( 1, spy.callCount );
assert.isTrue( spy.calledWith( editor ) );
assert.areSame( bender.tools.pngBase64, spy.firstCall.args[ 1 ].data );
} );

editor.fire( 'paste', {
dataTransfer: new CKEDITOR.plugins.clipboard.dataTransfer(),
dataValue: '<img src="' + bender.tools.pngBase64 + '">'
} );

wait();
},

'test XSS attack': function() {
var editor = this.editors.inline;

0 comments on commit 22b9485

Please sign in to comment.
You can’t perform that action at this time.