Path: blob/trunk/third_party/closure/goog/events/filedrophandler.js
2868 views
// Copyright 2010 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Provides a files drag and drop event detector. It works on16* HTML5 browsers.17*18* @see ../demos/filedrophandler.html19*/2021goog.provide('goog.events.FileDropHandler');22goog.provide('goog.events.FileDropHandler.EventType');2324goog.require('goog.array');25goog.require('goog.dom');26goog.require('goog.events.BrowserEvent');27goog.require('goog.events.EventHandler');28goog.require('goog.events.EventTarget');29goog.require('goog.events.EventType');30goog.require('goog.log');31goog.require('goog.log.Level');32333435/**36* A files drag and drop event detector. Gets an {@code element} as parameter37* and fires {@code goog.events.FileDropHandler.EventType.DROP} event when files38* are dropped in the {@code element}.39*40* @param {Element|Document} element The element or document to listen on.41* @param {boolean=} opt_preventDropOutside Whether to prevent a drop on the42* area outside the {@code element}. Default false.43* @constructor44* @extends {goog.events.EventTarget}45* @final46*/47goog.events.FileDropHandler = function(element, opt_preventDropOutside) {48goog.events.EventTarget.call(this);4950/**51* Handler for drag/drop events.52* @type {!goog.events.EventHandler<!goog.events.FileDropHandler>}53* @private54*/55this.eventHandler_ = new goog.events.EventHandler(this);5657var doc = element;58if (opt_preventDropOutside) {59doc = goog.dom.getOwnerDocument(element);60}6162// Add dragenter listener to the owner document of the element.63this.eventHandler_.listen(64doc, goog.events.EventType.DRAGENTER, this.onDocDragEnter_);6566// Add dragover listener to the owner document of the element only if the67// document is not the element itself.68if (doc != element) {69this.eventHandler_.listen(70doc, goog.events.EventType.DRAGOVER, this.onDocDragOver_);71}7273// Add dragover and drop listeners to the element.74this.eventHandler_.listen(75element, goog.events.EventType.DRAGOVER, this.onElemDragOver_);76this.eventHandler_.listen(77element, goog.events.EventType.DROP, this.onElemDrop_);78};79goog.inherits(goog.events.FileDropHandler, goog.events.EventTarget);808182/**83* Whether the drag event contains files. It is initialized only in the84* dragenter event. It is used in all the drag events to prevent default actions85* only if the drag contains files. Preventing default actions is necessary to86* go from dragenter to dragover and from dragover to drop. However we do not87* always want to prevent default actions, e.g. when the user drags text or88* links on a text area we should not prevent the browser default action that89* inserts the text in the text area. It is also necessary to stop propagation90* when handling drag events on the element to prevent them from propagating91* to the document.92* @private93* @type {boolean}94*/95goog.events.FileDropHandler.prototype.dndContainsFiles_ = false;969798/**99* A logger, used to help us debug the algorithm.100* @type {goog.log.Logger}101* @private102*/103goog.events.FileDropHandler.prototype.logger_ =104goog.log.getLogger('goog.events.FileDropHandler');105106107/**108* The types of events fired by this class.109* @enum {string}110*/111goog.events.FileDropHandler.EventType = {112DROP: goog.events.EventType.DROP113};114115116/** @override */117goog.events.FileDropHandler.prototype.disposeInternal = function() {118goog.events.FileDropHandler.superClass_.disposeInternal.call(this);119this.eventHandler_.dispose();120};121122123/**124* Dispatches the DROP event.125* @param {goog.events.BrowserEvent} e The underlying browser event.126* @private127*/128goog.events.FileDropHandler.prototype.dispatch_ = function(e) {129goog.log.fine(this.logger_, 'Firing DROP event...');130var event = new goog.events.BrowserEvent(e.getBrowserEvent());131event.type = goog.events.FileDropHandler.EventType.DROP;132this.dispatchEvent(event);133};134135136/**137* Handles dragenter on the document.138* @param {goog.events.BrowserEvent} e The dragenter event.139* @private140*/141goog.events.FileDropHandler.prototype.onDocDragEnter_ = function(e) {142goog.log.log(143this.logger_, goog.log.Level.FINER,144'"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);145var dt = e.getBrowserEvent().dataTransfer;146// Check whether the drag event contains files.147this.dndContainsFiles_ = !!(148dt && ((dt.types && (goog.array.contains(dt.types, 'Files') ||149goog.array.contains(dt.types, 'public.file-url'))) ||150(dt.files && dt.files.length > 0)));151// If it does152if (this.dndContainsFiles_) {153// Prevent default actions.154e.preventDefault();155}156goog.log.log(157this.logger_, goog.log.Level.FINER,158'dndContainsFiles_: ' + this.dndContainsFiles_);159};160161162/**163* Handles dragging something over the document.164* @param {goog.events.BrowserEvent} e The dragover event.165* @private166*/167goog.events.FileDropHandler.prototype.onDocDragOver_ = function(e) {168goog.log.log(169this.logger_, goog.log.Level.FINEST,170'"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);171if (this.dndContainsFiles_) {172// Prevent default actions.173e.preventDefault();174// Disable the drop on the document outside the drop zone.175var dt = e.getBrowserEvent().dataTransfer;176dt.dropEffect = 'none';177}178};179180181/**182* Handles dragging something over the element (drop zone).183* @param {goog.events.BrowserEvent} e The dragover event.184* @private185*/186goog.events.FileDropHandler.prototype.onElemDragOver_ = function(e) {187goog.log.log(188this.logger_, goog.log.Level.FINEST,189'"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);190if (this.dndContainsFiles_) {191// Prevent default actions and stop the event from propagating further to192// the document. Both lines are needed! (See comment above).193e.preventDefault();194e.stopPropagation();195// Allow the drop on the drop zone.196var dt = e.getBrowserEvent().dataTransfer;197198// IE bug #811625 (https://goo.gl/UWuxX0) will throw error SCRIPT65535199// when attempting to set property effectAllowed on IE10+.200// See more: https://github.com/google/closure-library/issues/485.201try {202dt.effectAllowed = 'all';203} catch (err) {204}205dt.dropEffect = 'copy';206}207};208209210/**211* Handles dropping something onto the element (drop zone).212* @param {goog.events.BrowserEvent} e The drop event.213* @private214*/215goog.events.FileDropHandler.prototype.onElemDrop_ = function(e) {216goog.log.log(217this.logger_, goog.log.Level.FINER,218'"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);219// If the drag and drop event contains files.220if (this.dndContainsFiles_) {221// Prevent default actions and stop the event from propagating further to222// the document. Both lines are needed! (See comment above).223e.preventDefault();224e.stopPropagation();225// Dispatch DROP event.226this.dispatch_(e);227}228};229230231