forked from mozilla-b2g/gaia
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 938045 - [Window Management] Implement AppSelection for Copy&Past…
…e on Firefox OS
- Loading branch information
Showing
23 changed files
with
551 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
/* global layoutManager */ | ||
(function(window) { | ||
'use strict'; | ||
|
||
// var _ = navigator.mozL10n.get; | ||
var _id = 0; | ||
|
||
/** | ||
* Text Selection Dialog of the AppWindow | ||
*/ | ||
|
||
var TextSelectionDialog = function (app) { | ||
if (app) { | ||
this.app = app; | ||
this.containerElement = app.element; | ||
} else { | ||
this.containerElement = | ||
document.getElementById('TextSelectionDialogRoot'); | ||
} | ||
this.event = null; | ||
// One to one mapping | ||
this.instanceID = _id++; | ||
this._injected = false; | ||
try { | ||
if (app) { | ||
app.element.addEventListener('mozbrowsertextualmenu', this, false); | ||
} else { | ||
window.addEventListener('mozChromeEvent', this); | ||
} | ||
} catch (e) { | ||
if (app) { | ||
app._dump(); | ||
} | ||
} | ||
this.render(); | ||
return this; | ||
}; | ||
|
||
TextSelectionDialog.prototype.__proto__ = window.BaseUI.prototype; | ||
|
||
TextSelectionDialog.prototype.CLASS_NAME = 'TextSelectionDialog'; | ||
|
||
TextSelectionDialog.prototype.ELEMENT_PREFIX = 'textselection-dialog-'; | ||
|
||
TextSelectionDialog.prototype.customID = function tsd_customID() { | ||
if (this.app) { | ||
return '[' + this.app.origin + ']'; | ||
} else { | ||
return ''; | ||
} | ||
}; | ||
|
||
TextSelectionDialog.prototype.handleEvent = function tsd_handleEvent(evt) { | ||
if (evt.type === 'mozChromeEvent' && evt.detail.type != 'textualmenu') { | ||
return; | ||
} | ||
// console.log(evt); | ||
// dump("Morris event"); | ||
this.event = evt; | ||
evt.preventDefault(); | ||
evt.stopPropagation(); | ||
if (this.app) { | ||
this.textualmenuDetail = this.event.detail; | ||
} else { | ||
this.textualmenuDetail = this.event.detail.detail; | ||
} | ||
if (!this._injected) { | ||
this.render(); | ||
} | ||
this.show(); | ||
this._injected = true; | ||
}; | ||
|
||
TextSelectionDialog.prototype._fetchElements = function tsd__fetchElements() { | ||
this.element = document.getElementById(this.CLASS_NAME + this.instanceID); | ||
this.elements = {}; | ||
|
||
var toCamelCase = function toCamelCase(str) { | ||
return str.replace(/\-(.)/g, function replacer(str, p1) { | ||
return p1.toUpperCase(); | ||
}); | ||
}; | ||
|
||
this.elementClasses = ['copy', 'cut', 'paste', 'selectall']; | ||
|
||
// Loop and add element with camel style name to Modal Dialog attribute. | ||
this.elementClasses.forEach(function createElementRef(name) { | ||
this.elements[toCamelCase(name)] = | ||
this.element.querySelector('.' + this.ELEMENT_PREFIX + name); | ||
}, this); | ||
}; | ||
|
||
TextSelectionDialog.prototype._registerEvents = | ||
function tsd__registerEvents() { | ||
var elements = this.elements; | ||
elements.copy.addEventListener('mousedown', this.copyHandler.bind(this)); | ||
elements.cut.addEventListener('mousedown', this.cutHandler.bind(this)); | ||
elements.paste.addEventListener('mousedown', | ||
this.pasteHandler.bind(this)); | ||
elements.selectall.addEventListener('mousedown', | ||
this.selectallHandler.bind(this)); | ||
}; | ||
|
||
TextSelectionDialog.prototype.copyHandler = | ||
function tsd_copyHandler(evt) { | ||
this.textualmenuDetail.copyToClipboard(); | ||
this.hide(); | ||
evt.preventDefault(); | ||
}; | ||
|
||
TextSelectionDialog.prototype.cutHandler = | ||
function tsd_cutHandler(evt) { | ||
this.textualmenuDetail.cutToClipboard(); | ||
this.hide(); | ||
evt.preventDefault(); | ||
}; | ||
|
||
TextSelectionDialog.prototype.pasteHandler = | ||
function tsd_pasteHandler(evt) { | ||
this.textualmenuDetail.pasteFromClipboard(); | ||
this.hide(); | ||
evt.preventDefault(); | ||
}; | ||
|
||
TextSelectionDialog.prototype.selectallHandler = | ||
function tsd_selectallHandler(evt) { | ||
this.textualmenuDetail.selectall(); | ||
this.hide(); | ||
evt.preventDefault(); | ||
}; | ||
|
||
TextSelectionDialog.prototype.view = function tsd_view() { | ||
var temp = '<div class="textselection-dialog"' + | ||
' id="' + this.CLASS_NAME + this.instanceID + '">' + | ||
'<div class="textselection-dialog-copy"></div>' + | ||
'<div class="textselection-dialog-cut"></div>' + | ||
'<div class="textselection-dialog-paste"></div>' + | ||
'<div class="textselection-dialog-selectall"></div>' + | ||
'</div>'; | ||
return temp; | ||
}; | ||
|
||
TextSelectionDialog.prototype.kill = function tsd_kill() { | ||
this.containerElement.removeChild(this.element); | ||
}; | ||
|
||
TextSelectionDialog.prototype.show = function tsd_show() { | ||
if (!this.event) { | ||
return; | ||
} | ||
var evt = this.event; | ||
var detail = this.textualmenuDetail; | ||
|
||
// console.log(detail); | ||
if (!detail.show) { | ||
this.hide(); | ||
return; | ||
} | ||
|
||
var numOfSelectOptions = 0; | ||
var options = ['SelectAll' , 'Paste', 'Cut', 'Copy']; | ||
options.forEach(function(option) { | ||
console.log(detail['can' + option]); | ||
if (detail['can' + option]) { | ||
numOfSelectOptions++; | ||
this.elements[option.toLowerCase()].style.display = ''; | ||
} else { | ||
this.elements[option.toLowerCase()].style.display = 'none'; | ||
} | ||
}, this); | ||
|
||
if (numOfSelectOptions === 0) { | ||
return; | ||
} | ||
|
||
var pos = this.calculateDialogPostion(detail, numOfSelectOptions); | ||
|
||
this.element.style.top = pos.top + 'px'; | ||
this.element.style.left = pos.left + 'px'; | ||
|
||
this.element.classList.add('visible'); | ||
evt.preventDefault(); | ||
}; | ||
|
||
TextSelectionDialog.prototype.calculateDialogPostion = | ||
function tsd_calculateDialogPostion(detail, numOfSelectOptions) { | ||
var selectOptionWidth = 52; | ||
var selectOptionHeight = 52; | ||
var selectDialogTop = detail.top * detail.zoomFactor; | ||
var selectDialogBottom = detail.bottom * detail.zoomFactor; | ||
var selectDialogLeft = detail.left * detail.zoomFactor; | ||
var selectDialogRight = detail.right * detail.zoomFactor; | ||
var distanceFromBottom = 40; | ||
var distanceFromTop = 12; | ||
|
||
var frameHeight = layoutManager.height; | ||
var frameWidth = layoutManager.width; | ||
var posTop = selectDialogTop - selectOptionHeight - distanceFromTop; | ||
// Dialog position align to the center of selected area. | ||
var posLeft = (selectDialogLeft + selectDialogRight - | ||
numOfSelectOptions * selectOptionWidth)/ 2; | ||
|
||
console.log('dialog top is ' + selectDialogTop); | ||
console.log('dialog bottom is ' + selectDialogBottom); | ||
console.log('dialog left is ' + selectDialogLeft); | ||
|
||
if (!this.app) { | ||
posTop = detail.zoomFactor * posTop + detail.frameOffsetY; | ||
posLeft = detail.zoomFactor * posLeft + detail.frameOffsetX; | ||
} | ||
console.log('frameOffsetY is ' + detail.frameOffsetY); | ||
console.log('frameOffsetX is ' + detail.frameOffsetX); | ||
console.log('zoomFactor is ' + detail.zoomFactor); | ||
|
||
if ((selectDialogTop <= 0 && selectDialogBottom >= frameHeight) || | ||
(selectDialogLeft <= 0 && detail.right >= frameWidth)) { | ||
return { | ||
top: (frameHeight - selectOptionHeight) / 2 + detail.frameOffsetY, | ||
left: (frameWidth - selectOptionWidth) / 2 + detail.frameOffsetX | ||
}; | ||
} | ||
|
||
// Put dialog under selected area if it overlap statusbar. | ||
if (posTop < 0) { | ||
console.log('pos top is top'); | ||
posTop = selectDialogBottom + distanceFromBottom; | ||
} | ||
|
||
// Put dialog in the center of selected area if it overlap keyboard. | ||
if (posTop >= frameHeight - distanceFromBottom - selectOptionHeight) { | ||
console.log('pos top is bottom'); | ||
posTop = (selectDialogTop + selectDialogBottom - | ||
selectOptionHeight) / 2; | ||
} | ||
|
||
if (posTop < 0) { | ||
console.log('pos top is till on the top'); | ||
posTop = (selectDialogBottom - selectOptionHeight) / 2; | ||
} else if (posTop >= | ||
frameHeight - distanceFromBottom - selectOptionHeight) { | ||
console.log('pos top is still on the bottom'); | ||
posTop = (selectDialogTop + frameHeight - selectOptionHeight) / 2; | ||
} | ||
|
||
if (posLeft < 0) { | ||
posLeft = 0; | ||
} | ||
|
||
if (posLeft + numOfSelectOptions * selectOptionWidth > frameWidth) { | ||
posLeft = frameWidth - numOfSelectOptions * selectOptionWidth; | ||
} | ||
|
||
console.log('frame width is ' + frameWidth); | ||
console.log('frame height is ' + frameHeight); | ||
console.log('pos left is ' + posLeft); | ||
console.log('pos top is ' + posTop); | ||
console.log('num of options is opened: ' + numOfSelectOptions); | ||
return { | ||
top: posTop + detail.frameOffsetY, | ||
left: posLeft + detail.frameOffsetX | ||
}; | ||
}; | ||
|
||
TextSelectionDialog.prototype.hide = function tsd_hide() { | ||
this.element.blur(); | ||
this.element.classList.remove('visible'); | ||
if (this.app) { | ||
this.app.focus(); | ||
} | ||
}; | ||
|
||
window.TextSelectionDialog = TextSelectionDialog; | ||
}(this)); |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.31 KB
apps/system/style/textselection_dialog/images/textselection_copy@1.5x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.45 KB
apps/system/style/textselection_dialog/images/textselection_copy@2.25x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.34 KB
apps/system/style/textselection_dialog/images/textselection_copy@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.77 KB
apps/system/style/textselection_dialog/images/textselection_cut@1.5x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.3 KB
apps/system/style/textselection_dialog/images/textselection_cut@2.25x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.1 KB
apps/system/style/textselection_dialog/images/textselection_cut@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.29 KB
apps/system/style/textselection_dialog/images/textselection_paste.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.42 KB
apps/system/style/textselection_dialog/images/textselection_paste@1.5x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.61 KB
apps/system/style/textselection_dialog/images/textselection_paste@2.25x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.51 KB
apps/system/style/textselection_dialog/images/textselection_paste@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.23 KB
apps/system/style/textselection_dialog/images/textselection_select_all.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.4 KB
apps/system/style/textselection_dialog/images/textselection_select_all@1.5x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.59 KB
apps/system/style/textselection_dialog/images/textselection_select_all@2.25x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.35 KB
apps/system/style/textselection_dialog/images/textselection_select_all@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.