mirror of
https://github.com/openstf/stf
synced 2025-10-06 03:50:04 +02:00
Added native auto-fill support for URL input in Chrome.
This commit is contained in:
parent
e6465fe8cc
commit
8696f833c2
8 changed files with 254 additions and 190 deletions
28
res/app/components/stf/common-ui/enable-autofill/README.md
Normal file
28
res/app/components/stf/common-ui/enable-autofill/README.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# enable-autofill
|
||||||
|
|
||||||
|
This directive enables autofill (HTML5 autocomplete) on the selected form.
|
||||||
|
|
||||||
|
Currently this is only needed in `Chrome` because `autofill` only works on form `POST` method.
|
||||||
|
|
||||||
|
Based on [this](http://stackoverflow.com/questions/16445463/how-to-get-chrome-to-autofill-with-asynchronous-post/22191041#22191041).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<form enable-autofill action="about:blank">
|
||||||
|
<input type="text" autocomplete="on">
|
||||||
|
</form>
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create the following DOM:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<iframe src="about:blank" name="_autofill" style="display:none">
|
||||||
|
<form method="post" action="about:blank" target="_autofill">
|
||||||
|
<input type="text" autocomplete="on">
|
||||||
|
</form>
|
||||||
|
```
|
||||||
|
|
||||||
|
Yes, it is a bit ugly but it is currently the only way.
|
||||||
|
|
||||||
|
It will create only one `iframe` which will be reused.
|
|
@ -0,0 +1,34 @@
|
||||||
|
module.exports = function enableAutofillDirective($rootElement) {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
compile: function compile(tElement, tAttrs) {
|
||||||
|
|
||||||
|
// Creates hidden iFrame for auto-fill forms if there isn't one already
|
||||||
|
if ($rootElement.find('iframe').attr('name') !== '_autofill') {
|
||||||
|
$rootElement.append(angular.element(
|
||||||
|
'<iframe src="about:blank" name="_autofill" style="display:none">'
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add attribute method POST to the current form
|
||||||
|
if (!tAttrs.method) {
|
||||||
|
tElement.attr('method', 'post')
|
||||||
|
} else {
|
||||||
|
if (!tAttrs.method.match(/post/i)) {
|
||||||
|
console.error('Auto-fill only works with form POST method')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add attribute target to the current form
|
||||||
|
if (!tAttrs.target) {
|
||||||
|
tElement.attr('target', '_autofill')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add attribute action to the current form
|
||||||
|
// NOTE: This doesn't work so it has to be added manually
|
||||||
|
// if (!tAttrs.action) {
|
||||||
|
// tElement.attr('action', 'about:blank')
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
describe('enableAutofill', function () {
|
||||||
|
|
||||||
|
beforeEach(module('stf.enable-autofill'));
|
||||||
|
|
||||||
|
var scope, compile;
|
||||||
|
|
||||||
|
beforeEach(inject(function ($rootScope, $compile) {
|
||||||
|
scope = $rootScope.$new();
|
||||||
|
compile = $compile;
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should ...', function () {
|
||||||
|
|
||||||
|
/*
|
||||||
|
To test your directive, you need to create some html that would use your directive,
|
||||||
|
send that through compile() then compare the results.
|
||||||
|
|
||||||
|
var element = compile('<div enable-autofill name="name">hi</div>')(scope);
|
||||||
|
expect(element.text()).toBe('hello, world');
|
||||||
|
*/
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = angular.module('stf.enable-autofill', [
|
||||||
|
|
||||||
|
])
|
||||||
|
.directive('enableAutofill', require('./enable-autofill-directive'))
|
|
@ -12,5 +12,6 @@ module.exports = angular.module('stf/common-ui', [
|
||||||
require('./include-cached').name,
|
require('./include-cached').name,
|
||||||
require('./text-focus-select').name,
|
require('./text-focus-select').name,
|
||||||
require('./counter').name,
|
require('./counter').name,
|
||||||
require('./badge-icon').name
|
require('./badge-icon').name,
|
||||||
|
require('./enable-autofill').name
|
||||||
])
|
])
|
||||||
|
|
|
@ -2,49 +2,20 @@ var _ = require('lodash')
|
||||||
|
|
||||||
module.exports = function NavigationCtrl($scope, $rootScope) {
|
module.exports = function NavigationCtrl($scope, $rootScope) {
|
||||||
|
|
||||||
$scope.urlHistory = []
|
function addHttp(textUrl) {
|
||||||
|
if (textUrl.indexOf(':') === -1 && textUrl.indexOf('.') !== -1) {
|
||||||
function addToHistory() {
|
return 'http://' + textUrl
|
||||||
var HISTORY_LIMIT = 20
|
|
||||||
|
|
||||||
var history = $scope.urlHistory
|
|
||||||
history.unshift($scope.textURL)
|
|
||||||
if (history.length > HISTORY_LIMIT) {
|
|
||||||
history.pop()
|
|
||||||
}
|
|
||||||
$scope.urlHistory = _.uniq(history)
|
|
||||||
}
|
|
||||||
|
|
||||||
function addHttp() {
|
|
||||||
if ($scope.textURL.indexOf(':') === -1) {
|
|
||||||
$scope.textURL = 'http://' + $scope.textURL
|
|
||||||
}
|
}
|
||||||
|
return textUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.openURL = function () {
|
$scope.openURL = function () {
|
||||||
addHttp()
|
|
||||||
addToHistory()
|
|
||||||
|
|
||||||
return $scope.control.openBrowser(
|
return $scope.control.openBrowser(
|
||||||
$scope.textURL,
|
addHttp($scope.textURL),
|
||||||
$scope.browser
|
$scope.browser
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.clearHistory = function () {
|
|
||||||
$scope.urlHistory = []
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.hasHistory = function () {
|
|
||||||
return $scope.urlHistory.length > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.insertURL = function ($url) {
|
|
||||||
$scope.textURL = $url
|
|
||||||
$scope.openURL()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function setCurrentBrowser(browser) {
|
function setCurrentBrowser(browser) {
|
||||||
if (browser && browser.apps) {
|
if (browser && browser.apps) {
|
||||||
var currentBrowser = {}
|
var currentBrowser = {}
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
i.fa.fa-globe
|
i.fa.fa-globe
|
||||||
span(translate) Navigation
|
span(translate) Navigation
|
||||||
span
|
span
|
||||||
button.btn.btn-xs.btn-danger-outline.pull-right(ng-click='clearSettings()', tooltip='{{ "Reset all browser settings" | translate }}')
|
button.btn.btn-xs.btn-danger-outline.pull-right(ng-click='clearSettings()',
|
||||||
|
tooltip='{{ "Reset all browser settings" | translate }}')
|
||||||
i.fa.fa-trash-o
|
i.fa.fa-trash-o
|
||||||
span(translate) Reset
|
span(translate) Reset
|
||||||
//.button-spacer.pull-right
|
//.button-spacer.pull-right
|
||||||
|
@ -11,22 +12,15 @@
|
||||||
//i.fa.fa-step-forward.pull-right(ng-click='forward()', title='{{"Go Forward"|translate}}')
|
//i.fa.fa-step-forward.pull-right(ng-click='forward()', title='{{"Go Forward"|translate}}')
|
||||||
//i.fa.fa-step-backward.pull-right(ng-click='back()', title='{{"Go Back"|translate}}')
|
//i.fa.fa-step-backward.pull-right(ng-click='back()', title='{{"Go Back"|translate}}')
|
||||||
.widget-content.padded
|
.widget-content.padded
|
||||||
form
|
form(enable-autofill, action='about:blank')
|
||||||
|
//form(name='navigationForm', method='post', action='about:blank', target='_autofill')
|
||||||
.input-group
|
.input-group
|
||||||
input.form-control(type='text', placeholder='http://...', autocomplete='off', ng-model='textURL',
|
input.form-control(type='text', name='textURL', placeholder='http://...',
|
||||||
typeahead='url for url in urlHistory | filter:$viewValue', text-focus-select,
|
autocomplete='url', ng-model='textURL', text-focus-select,
|
||||||
accesskey='N', tabindex='10').form-control
|
accesskey='N', tabindex='10').form-control
|
||||||
|
|
||||||
.input-group-btn
|
.input-group-btn
|
||||||
button(ng-click='openURL()', ng-disabled='!textURL', translate).btn.btn-primary-outline Open
|
button(ng-click='openURL()', ng-disabled='!textURL', translate).btn.btn-primary-outline Open
|
||||||
//button(type='button', ng-disabled='!hasHistory()').btn.btn-primary-outline.dropdown-toggle
|
|
||||||
span.caret
|
|
||||||
//ul.dropdown-menu
|
|
||||||
li(ng-repeat='url in urlHistory')
|
|
||||||
a(ng-click='insertURL(url)').btn-link {{url}}
|
|
||||||
li.divider
|
|
||||||
li
|
|
||||||
a(ng-click='clearHistory()', type='button', translate).btn-link Clear
|
|
||||||
|
|
||||||
.btn-group(ng-if='$root.browser')
|
.btn-group(ng-if='$root.browser')
|
||||||
.btn-group
|
.btn-group
|
||||||
|
|
|
@ -41,7 +41,7 @@ body {
|
||||||
|
|
||||||
/* Fix btn-group */
|
/* Fix btn-group */
|
||||||
.btn-group.pull-right {
|
.btn-group.pull-right {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -327,7 +327,7 @@ svg {
|
||||||
|
|
||||||
/*.btn [class^="fa"]+span i,*/
|
/*.btn [class^="fa"]+span i,*/
|
||||||
/*.btn [class*="fa"]+span {*/
|
/*.btn [class*="fa"]+span {*/
|
||||||
/*margin-right: 15px;*/
|
/*margin-right: 15px;*/
|
||||||
/*}*/
|
/*}*/
|
||||||
|
|
||||||
.interact-control .navbar {
|
.interact-control .navbar {
|
||||||
|
@ -342,8 +342,6 @@ svg {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Make text input on tables be 100% */
|
/* Make text input on tables be 100% */
|
||||||
.table td input[type="number"],
|
.table td input[type="number"],
|
||||||
.table td input[type="text"] {
|
.table td input[type="text"] {
|
||||||
|
@ -355,7 +353,6 @@ svg {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.remote-control {
|
.remote-control {
|
||||||
background: #888;
|
background: #888;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -370,8 +367,6 @@ svg {
|
||||||
margin-top: 8px !important;
|
margin-top: 8px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
a.active {
|
a.active {
|
||||||
color: #007aff !important;
|
color: #007aff !important;
|
||||||
}
|
}
|
||||||
|
@ -389,3 +384,17 @@ a.active {
|
||||||
datalist {
|
datalist {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make auto-fill controls white instead of the default yellow */
|
||||||
|
input:-webkit-autofill,
|
||||||
|
textarea:-webkit-autofill,
|
||||||
|
select:-webkit-autofill {
|
||||||
|
-webkit-box-shadow: 0 0 0 200px white inset !important;
|
||||||
|
box-shadow: 0 0 0 200px white inset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove transition for input text */
|
||||||
|
input {
|
||||||
|
-webkit-transition: none !important;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue