1
0
Fork 0
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:
Gunther Brunner 2014-07-31 16:54:09 +09:00
parent e6465fe8cc
commit 8696f833c2
8 changed files with 254 additions and 190 deletions

View 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.

View file

@ -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')
// }
}
}
}

View file

@ -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');
*/
});
});

View file

@ -0,0 +1,4 @@
module.exports = angular.module('stf.enable-autofill', [
])
.directive('enableAutofill', require('./enable-autofill-directive'))

View file

@ -12,5 +12,6 @@ module.exports = angular.module('stf/common-ui', [
require('./include-cached').name,
require('./text-focus-select').name,
require('./counter').name,
require('./badge-icon').name
require('./badge-icon').name,
require('./enable-autofill').name
])

View file

@ -2,49 +2,20 @@ var _ = require('lodash')
module.exports = function NavigationCtrl($scope, $rootScope) {
$scope.urlHistory = []
function addToHistory() {
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
function addHttp(textUrl) {
if (textUrl.indexOf(':') === -1 && textUrl.indexOf('.') !== -1) {
return 'http://' + textUrl
}
return textUrl
}
$scope.openURL = function () {
addHttp()
addToHistory()
return $scope.control.openBrowser(
$scope.textURL,
addHttp($scope.textURL),
$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) {
if (browser && browser.apps) {
var currentBrowser = {}

View file

@ -3,7 +3,8 @@
i.fa.fa-globe
span(translate) Navigation
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
span(translate) Reset
//.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-backward.pull-right(ng-click='back()', title='{{"Go Back"|translate}}')
.widget-content.padded
form
form(enable-autofill, action='about:blank')
//form(name='navigationForm', method='post', action='about:blank', target='_autofill')
.input-group
input.form-control(type='text', placeholder='http://...', autocomplete='off', ng-model='textURL',
typeahead='url for url in urlHistory | filter:$viewValue', text-focus-select,
input.form-control(type='text', name='textURL', placeholder='http://...',
autocomplete='url', ng-model='textURL', text-focus-select,
accesskey='N', tabindex='10').form-control
.input-group-btn
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

View file

@ -1,22 +1,22 @@
body {
/*font-size: 14px;*/
/*background: #eee;*/
/*font-size: 14px;*/
/*background: #eee;*/
}
.page-container {
padding: 0 30px;
margin: 0 auto;
padding: 0 30px;
margin: 0 auto;
}
.stf-container {
margin-right: auto;
margin-left: auto;
padding-left: 15px;
padding-right: 15px;
margin-right: auto;
margin-left: auto;
padding-left: 15px;
padding-right: 15px;
}
.accordion-body.in:hover {
overflow: visible;
overflow: visible;
}
.button-spacer {
@ -28,11 +28,11 @@ body {
/* Overflow */
.overflow-x {
overflow-x: auto;
overflow-x: auto;
}
.overflow-y {
overflow-y: auto;
overflow-y: auto;
}
.overflow-auto {
@ -41,50 +41,50 @@ body {
/* Fix btn-group */
.btn-group.pull-right {
margin-right: 10px;
margin-right: 10px;
}
/**
Accelerate
*/
.force-gpu {
-webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-perspective: 1000;
-moz-perspective: 1000;
-ms-perspective: 1000;
perspective: 1000;
-webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-perspective: 1000;
-moz-perspective: 1000;
-ms-perspective: 1000;
perspective: 1000;
}
/**
Colors for awesome fonts
*/
.text-status-on {
color: green;
text-shadow: 0 0 4px rgba(8, 208, 0, 0.3);
color: green;
text-shadow: 0 0 4px rgba(8, 208, 0, 0.3);
}
.text-status-off {
color: lightgrey;
color: lightgrey;
}
.text-status-error {
color: red;
color: red;
}
.text-status-waiting {
color: #ffcc66;
color: #ffcc66;
}
.text-status-inuse {
color: blue;
color: blue;
}
/**
@ -92,208 +92,208 @@ Colors for awesome fonts
*/
.stf-ace-editor {
height: 150px;
height: 150px;
}
.stf-mini-ace-viewer {
/*min-height: 10px;*/
/*min-height: 10px;*/
}
.ace_editor_wrapper {
position: relative;
height: 180px;
position: relative;
height: 180px;
}
.ace_editor {
top: 0;
bottom: 0;
right: 0;
left: 0;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
/* Nothing to show */
.nothing-to-show {
color: #b7b7b7;
min-height: 130px;
text-align: center;
color: #b7b7b7;
min-height: 130px;
text-align: center;
}
.nothing-to-show p {
font-size: 20px;
font-size: 20px;
}
/**
General styles
*/
.vertical-center {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: center;
-webkit-box-align: center;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-pack: center;
-moz-box-align: center;
display: box;
box-orient: vertical;
box-pack: center;
box-align: center;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: center;
-webkit-box-align: center;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-pack: center;
-moz-box-align: center;
display: box;
box-orient: vertical;
box-pack: center;
box-align: center;
}
/* Screenshots */
ul.screenshots-icon-view {
list-style-type: none;
font-family: 'HelveticaNeue-UltraLight', Helvetica, Arial, sans-serif;
list-style-type: none;
font-family: 'HelveticaNeue-UltraLight', Helvetica, Arial, sans-serif;
}
ul.screenshots-icon-view li {
float: left;
clear: none;
margin: 8px;
float: left;
clear: none;
margin: 8px;
}
/* Progress */
.value-next-to-progress {
float: left;
margin-right: 10px;
float: left;
margin-right: 10px;
}
.table-progress {
margin-bottom: 0;
margin-bottom: 0;
}
/* Icons */
.icon-fixed {
width: 150px !important;
width: 150px !important;
}
/* Cookies */
ul.cookies-list {
list-style-type: none;
list-style-type: none;
}
/* Login */
.login-bg {
background: #8a6073;
background: -moz-linear-gradient(top, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #8a6073), color-stop(24%, #c68779), color-stop(57%, #637476), color-stop(79%, #4c7b7d), color-stop(94%, #658e7d), color-stop(97%, #6c8c77));
background: -webkit-linear-gradient(top, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
background: -o-linear-gradient(top, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
background: -ms-linear-gradient(top, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
background: linear-gradient(to bottom, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8a6073', endColorstr='#6c8c77', GradientType=0);
background: #8a6073;
background: -moz-linear-gradient(top, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #8a6073), color-stop(24%, #c68779), color-stop(57%, #637476), color-stop(79%, #4c7b7d), color-stop(94%, #658e7d), color-stop(97%, #6c8c77));
background: -webkit-linear-gradient(top, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
background: -o-linear-gradient(top, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
background: -ms-linear-gradient(top, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
background: linear-gradient(to bottom, #8a6073 0%, #c68779 24%, #637476 57%, #4c7b7d 79%, #658e7d 94%, #6c8c77 97%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8a6073', endColorstr='#6c8c77', GradientType=0);
}
/* d3 lines */
svg {
font: 10px sans-serif;
font: 10px sans-serif;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
/* Interact Control */
.interact-sidebar {
width: 280px;
width: 280px;
}
/* Movement Area */
.movement-area-container {
/*background: #555;*/
width: 100%;
height: 100%;
/*background: #555;*/
width: 100%;
height: 100%;
}
.movement-area-image {
width: 100%;
height: 100%;
background-size: contain;
background-color: #444;
background-repeat: no-repeat;
background-position: 50% 50%;
position: relative;
width: 100%;
height: 100%;
background-size: contain;
background-color: #444;
background-repeat: no-repeat;
background-position: 50% 50%;
position: relative;
}
.interact-control .btn-toolbar .btn {
min-width: 41px;
min-width: 41px;
}
/* Height */
.as-table {
display: table;
display: table;
}
.as-row {
display: table-row;
display: table-row;
}
.as-cell {
display: table-cell;
display: table-cell;
}
.fill-height {
height: 100%;
height: 100%;
}
.fill-auto {
height: auto;
height: auto;
}
.special-keys-buttons button {
width: 40px;
width: 40px;
}
.special-keys-buttons .btn-xs button {
width: 36px;
width: 36px;
}
.special-keys-dpad-buttons button {
width: 40px;
width: 40px;
}
/*
Drawer
*/
.stf-drawer {
background: #ddd;
background: #ddd;
}
.stf-drawer-bar {
background: #aaa;
background: #aaa;
}
.stf-drawer-docked-down .stf-drawer-bar {
width: 100%;
height: 2px;
cursor: ns-resize;
width: 100%;
height: 2px;
cursor: ns-resize;
}
.stf-drawer-docked-right .stf-drawer-bar {
width: 2px;
height: 100%;
cursor: ew-resize;
width: 2px;
height: 100%;
cursor: ew-resize;
}
.stf-drawer-docked {
opacity: 0.9;
z-index: 5000;
opacity: 0.9;
z-index: 5000;
}
.stf-drawer-floating {
@ -301,91 +301,100 @@ svg {
}
.stf-drawer-docked-down {
width: 100%;
height: 300px;
bottom: 0;
position: absolute;
width: 100%;
height: 300px;
bottom: 0;
position: absolute;
}
.stf-drawer-docked-right {
width: 300px;
height: 100%;
right: 0;
position: absolute;
width: 300px;
height: 100%;
right: 0;
position: absolute;
}
.stf-drawer-buttons {
text-align: right;
text-align: right;
}
/* For se7en bootstrap */
.btn [class^="fa"],
.btn [class*="fa"] {
margin-right: 0 !important;
margin-right: 0 !important;
}
/*.btn [class^="fa"]+span i,*/
/*.btn [class*="fa"]+span {*/
/*margin-right: 15px;*/
/*margin-right: 15px;*/
/*}*/
.interact-control .navbar {
height: auto !important;
height: auto !important;
}
.interact-control .navbar-brand {
padding: 8px 15px;
padding: 8px 15px;
}
.interact-control .btn-group {
margin: 0;
margin: 0;
}
/* Make text input on tables be 100% */
.table td input[type="number"],
.table td input[type="text"] {
width: 100%;
width: 100%;
}
/* Re-reset the table alignment */
.ng-table th {
text-align: left;
text-align: left;
}
.remote-control {
background: #888;
width: 100%;
height: 100%;
background: #888;
width: 100%;
height: 100%;
}
.stf-feedback > li > a {
font-size: 14px;
font-size: 14px;
}
.stf-nav-web-native-button {
margin-top: 8px !important;
margin-top: 8px !important;
}
a.active {
color: #007aff !important;
color: #007aff !important;
}
.weinre-window {
z-index: 10;
position: absolute;
top: 31px;
bottom: 3px;
left: 0;
right: 0;
z-index: 10;
position: absolute;
top: 31px;
bottom: 3px;
left: 0;
right: 0;
}
/* Hide datalist for non-supporting browsers */
datalist {
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;
}