在此codepen by thinhlam中,当输入字段处于活动状态时,接受输入,即可正常工作。但是,当某个其他输入字段处于活动状态时,也可以通过先前激活的输入字段进行输入。 如下图所示:
虽然之前的“单个文本”字段处于活动状态,但之后我切换到“段落文本”块而未将光标单击到输入区域,因此“单个文本”仍然接受输入。
(function() {
var guid = 1;
var app = angular.module('DragDropApp', ['ui.sortable']);
app.controller('DragDropCtrl', function($scope) {
$scope.dragElements = [{
'Name': "Single Text",
'Type': "text",
'Settings': [{
'Name': 'Field Label',
'Value': 'Single Text',
'Type': 'text'
}, {
'Name': 'Short Label',
'Value': 'Single Text',
'Type': 'text'
}, {
'Name': 'Internal Name',
'Value': 'xSingle_Text',
'Type': 'text'
}, {
'Name': 'Field Type',
'Value': 'Single Text',
'Type': 'string'
}, {
'Name': 'Single Line Text Options',
'Value': '',
'Type': 'label'
}, {
'Name': 'Max Input Length',
'Value': '50',
'Type': 'text'
}, {
'Name': 'Url Template',
'Value': '',
'Type': 'text'
}, {
'Name': 'Column Span',
'Value': '1',
'Type': 'dropdown',
'PossibleValue': ['1', '2']
}, {
'Name': 'General Options',
'Type': 'checkBoxZone',
'Options': [{
'Name': 'Required',
'Value': false
}, {
'Name': 'Show on list',
'Value': false
}, {
'Name': 'Unique',
'Value': false
}, {
'Name': 'Index',
'Value': false
}]
}
]
}, {
'Name': "Date",
'Type': "date",
'Settings': [{
'Name': 'Field Label',
'Value': 'Field Label',
'Type': 'text'
}, {
'Name': 'Short Label',
'Value': 'Short Label',
'Type': 'text'
}, {
'Name': 'Internal Name',
'Value': 'Internal Name',
'Type': 'text'
}, {
'Name': 'Field Type',
'Value': 'Date',
'Type': 'string'
}, {
'Name': 'Display Type',
'Value': '',
'Type': 'radio',
'PossibleValue': [
{
'Text' : 'DateTimeInstance',
'Checked' : true
},
{
'Text' : 'DateTimeLocal',
'Checked' : false
},
{
'Text' : 'DateLocal',
'Checked' : false
},
{
'Text' : 'Time',
'Checked' : false
},
]
}, {
'Name': 'Column Span',
'Value': '1',
'Type': 'dropdown',
'PossibleValue': ['1', '2']
}, {
'Name': 'General Options',
'Type': 'checkBoxZone',
'Options': [{
'Name': 'Required',
'Value': false
}, {
'Name': 'Show on list',
'Value': false
}, {
'Name': 'Unique',
'Value': false
}, {
'Name': 'Index',
'Value': false
}]
}
]
}, {
'Name': "Singe Selection",
"Type": "dropdown"
}
]
}, {
'Name': "Pagaraph Text",
"Type": "textarea"
}, {
'Name': 'Field Type',
'Value': 'Paragraph Text',
'Type': 'string'
}, {
'Name': 'Column Span',
'Value': '1',
'Type': 'dropdown',
'PossibleValue': ['1', '2']
}, {
'Name': 'General Options',
'Type': 'checkBoxZone',
'Options': [{
'Name': 'Required',
'Value': false
}, {
'Name': 'Enable Rich Text',
'Value': false
}, {
'Name': 'Active',
'Value': true
}, {
'Name': 'Hidden',
'Value': false
}]
}
]
}];
$scope.formFields = [];
$scope.current_field = {};
var createNewField = function() {
return {
'id': ++guid,
'Name': '',
'Settings': [],
'Active': true,
'ChangeFieldSetting': function(Value, SettingName) {
switch (SettingName) {
case 'Field Label':
case 'Short Label':
case 'Internal Name':
$scope.current_field.Name = Value;
$scope.current_field.Settings[0].Value = $scope.current_field.Name;
$scope.current_field.Settings[1].Value = $scope.current_field.Name;
$scope.current_field.Settings[2].Value = 'x' + $scope.current_field.Name.replace(/\s/g, '_');
break;
default:
break;
}
},
'GetFieldSetting': function(settingName) {
var result = {};
var settings = this.Settings;
$.each(settings, function(index, set) {
if (set.Name == settingName) {
result = set;
return;
}
});
if (!Object.keys(result).length) {
//Continue to search settings in the checkbox zone
$.each(settings[settings.length - 1].Options, function(index, set) {
if (set.Name == settingName) {
result = set;
return;
}
});
}
return result;
}
};
}
$scope.changeFieldName = function(Value) {
$scope.current_field.Name = Value;
$scope.current_field.Settings[0].Value = $scope.current_field.Name;
$scope.current_field.Settings[1].Value = $scope.current_field.Name;
$scope.current_field.Settings[2].Value = 'x' + $scope.current_field.Name.replace(/\s/g, '_');
}
$scope.removeElement = function(idx){
if($scope.formFields[idx].Active) {
$('#addFieldTab_lnk').tab('show');
$scope.current_field = {};
}
$scope.formFields.splice(idx, 1);
};
$scope.addElement = function(ele, idx) {
$scope.current_field.Active = false;
$scope.current_field = createNewField();
//Merge setting from template object
angular.merge($scope.current_field, ele);
if (typeof idx == 'undefined') {
$scope.formFields.push($scope.current_field);
} else {
$scope.formFields.splice(idx, 0, $scope.current_field);
$('#fieldSettingTab_lnk').tab('show');
}
};
$scope.activeField = function(f) {
$scope.current_field.Active = false;
$scope.current_field = f;
f.Active = true;
$('#fieldSettingTab_lnk').tab('show');
};
$scope.formbuilderSortableOpts = {
'ui-floating': true,
};
});
app.directive('elementDraggable', ['$document', function($document) {
return {
link: function(scope, element, attr) {
element.on('dragstart', function(event) {
event.originalEvent.dataTransfer.setData('templateIdx', $(element).data('index'));
});
}
};
}]);
app.directive('elementDrop', ['$document', function($document) {
return {
link: function(scope, element, attr) {
element.on('dragover', function(event) {
event.preventDefault();
});
$('.drop').on('dragenter', function(event) {
event.preventDefault();
})
element.on('drop', function(event) {
event.stopPropagation();
var self = $(this);
scope.$apply(function() {
var idx = event.originalEvent.dataTransfer.getData('templateIdx');
var insertIdx = self.data('index')
scope.addElement(scope.dragElements[idx], insertIdx);
});
});
}
};
}]);
})();
$(function() {
// Code here
var dh = $(document).height();
$('#sidebar-tab-content').height(dh - 115);
$('#main-content').height(dh - 10);
});
body {
padding-top: 20px;
color: #75736f;
overflow: hidden;
}
::-webkit-scrollbar {
display: none;
}
a {
color: #75736f;
}
a:focus,
a:hover,
a:visited,
a:active,
a:link {
text-decoration: none !important;
color: #75736f;
}
ul.neo-nav {
border: 2px solid #75736f;
display: inline-block;
-moz-padding-start: 0px;
-webkit-padding-start: 0px;
padding-start: 0px;
border-radius: 5px;
}
ul.neo-nav li {
display: inline-block;
list-style: none;
}
ul.neo-nav li a {
color: #75736f;
padding: 10px 30px;
font-weight: bold;
display: block;
}
ul.neo-nav li.active a {
color: white;
}
ul.neo-nav li:not(:first-child) {
border-left: 2px solid #75736f;
}
ul.neo-nav li.active {
background-color: #75736f;
color: white;
}
ul.neo-nav li a:hover,
ul.neo-nav li a:visited,
ul.neo-nav li a:active,
ul.neo-nav li a:link {
text-decoration: none;
}
#main-content {
background-color: whitesmoke;
border-left: 1px solid #ddd;
padding-top: 20px;
padding-bottom: 20px;
z-index: 1;
overflow-y: scroll;
}
#sideBar {
padding-top: 20px;
padding-left: 0px;
padding-right: 0px;
z-index: 2;
}
.tab-container {
border-bottom: 1px solid gray;
padding-bottom: 20px;
}
#addFieldTab {
padding-top: 20px;
padding-left: 20px;
}
#fieldSettingTab {
padding: 20px;
}
#stdFields {}
#formBuilderContent {
background-color: white;
padding: 20px;
}
.dragElement-wrapper {
width: 50%;
display: inline-block;
margin-bottom: 20px;
}
.dragElement-wrapper .drag-element {
display: block;
width: 90%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
cursor: pointer;
}
.dragElement-wrapper .drag-element i {
margin-right: 5px;
}
[draggable] {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
/* Required to make elements draggable in old WebKit */
-khtml-user-drag: element;
-webkit-user-drag: element;
}
#chkBoxZone {
margin-top: 15px;
}
.input-as-label {
border: none;
box-shadow: none;
display: inline-block;
max-width: 100%;
margin-bottom: 5px;
font-weight: 700;
background-color: transparent;
}
.active-field {
background-color: #f1fafc;
}
.form-group {
padding: 10px;
position: relative;
}
.form-group i.remove-ico {
position: absolute;
right: 5px;
top: 5px;
cursor: pointer;
}
.pale {
opacity: 50%;
}
.sortable-formbuilder,
.sortable-stdFields {
padding-left: 0px;
-moz-padding-start: 0px;
-webkit-padding-start: 0px;
-khtml-padding-start: 0px;
-o-padding-start: 0px;
padding-start: 0px;
list-style: none;
min-height: 40px;
}
.drop-to-add {
height: 40px;
}
a[data-toggle="collapse"] i.fa-plus-square-o {
display: none;
}
a[data-toggle="collapse"] i.fa-minus-square-o {
display: inline-block;
}
a[data-toggle="collapse"].collapsed i.fa-plus-square-o {
display: inline-block;
}
a[data-toggle="collapse"].collapsed i.fa-minus-square-o {
display: none;
}
.orange-txt {
color: orange;
}
#sidebar-tab-content{
overflow-y: scroll;
}
<html lang="en" ng-app="DragDropApp">
<body ng-controller="DragDropCtrl">
<div class="container-fluid">
<div class="row">
<div class="col-md-3" id="sideBar">
<div class="tab-container text-center">
<ul class="neo-nav clearfix" role="tablist">
<li role="presentation" class="active"><a href="#addFieldTab" id="addFieldTab_lnk" aria-controls="home" role="tab" data-toggle="tab">Add a Field</a></li><!--
--><li role="presentation"><a href="#fieldSettingTab" id="fieldSettingTab_lnk" aria-controls="profile" role="tab" data-toggle="tab">Field Settings</a></li>
</ul>
</div>
<div class="tab-content" id="sidebar-tab-content">
<div role="tabpanel" class="tab-pane active" id="addFieldTab">
<p>
<a role="button" data-toggle="collapse" href="#stdFields">
<i class="fa fa-lg fa-plus-square-o"></i><i class="fa fa-lg fa-minus-square-o"></i> STANDARD FIELDS
</a>
</p>
<div class="collapse in" id="stdFields">
<ul ng-model="dragElements" class="sortable-stdFields">
<li draggable="true" class="dragElement-wrapper" ng-repeat="ele in dragElements" element-draggable data-index="{{$index}}">
<div class="drag-element" ng-click="addElement(ele)" >
<i class="fa fa-cogs"></i> {{ele.Name}}
</div>
</li>
</ul>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="fieldSettingTab">
<div ng-repeat="set in current_field.Settings" ng-switch on="set.Type">
<div >
<div class="form-group " ng-switch-when="text">
<label for="{{set.Name.replace(' ','_')}}">{{set.Name}}</label>
<input ng-change="current_field.ChangeFieldSetting(set.Value, set.Name)" type="text" ng-model="set.Value" class="form-control" id="{{set.Name.replace(' ','_')}}" value="{{set.Value}}" placeholder="{{set.Name}}">
</div>
<div class="form-group" ng-switch-when="string">
<label >{{set.Name}}</label>
<br>
<span >{{set.Value}}</span>
</div>
<div class="form-group" ng-switch-when="label">
<label class="pale">{{set.Name}}</label>
</div>
<div class="form-group " ng-switch-when="dropdown" >
<label >{{set.Name}}</label>
<select class="form-control" ng-model="set.Value" >
<option ng-repeat="op in set.PossibleValue">{{op}}</option>
</select>
</div>
<div class="form-group" ng-switch-when="radio">
<div ng-repeat="val in set.PossibleValue" class="radio">
<label>
<input type="radio" name="optionsRadios" value="{{val.Checked}}" ng-checked="val.Checked">
{{val.Text}}
</label>
</div>
</div>
<div class="form-group" ng-switch-when="dropdown_increment">
<label class="control-label">
Choices
</label>
<div ng-repeat="val in set.PossibleValue" class="radio" class="form-control">
<i class="fa fa-sort fa-lg">
</i>
<i class="fa fa-circle-o fa-lg">
</i>
<input type="text" value="val.Text" ng-model="val.Text">
</div>
</div>
<div ng-switch-when="checkBoxZone">
<a role="button" data-toggle="collapse" href="#chkBoxZone">
<i class="fa fa-lg fa-plus-square-o"></i><i class="fa fa-lg fa-minus-square-o"></i> {{set.Name}}
</a>
<div class="collapse in" id="chkBoxZone">
<div class="form-group" ng-repeat="op in set.Options">
<label class="checkbox-inline" >
<input type="checkbox" value="{{op.Value}}" ng-model="op.Value"> {{op.Name}}
</label>
</div>
</div>
</div>
<p ng-switch-default>
Unknown
</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-9 text-center" id="main-content">
<ul class="neo-nav" role="tablist">
<li role="presentation" class="active"><a href="#addFieldTab" aria-controls="home" role="tab" data-toggle="tab">Form Builder</a></li><!--
--><li role="presentation"><a href="#" aria-controls="profile" role="tab" data-toggle="tab">Entity & Field Permission</a></li><!--
--><li role="presentation" class=""><a href="#" aria-controls="home" role="tab" data-toggle="tab">Detail Builder</a></li><!--
--><li role="presentation"><a href="#" aria-controls="profile" role="tab" data-toggle="tab">Workflows</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active text-left" id="formBuilderContent">
<p>
<i class="fa fa-pencil fa-lg"></i>
<span class="lead">Employee</span>
</p>
<div class="container-fluid" id="dropZone">
<ul class="row sortable-formbuilder" element-drop ui-sortable="formbuilderSortableOpts" ng-model="formFields" id="sortable-formbuilder-ul">
<li ng-repeat="field in formFields" element-drop data-index="{{$index}}" ng-switch on="field.Type" ng-class="field.GetFieldSetting('Column Span').Value == 1 ? 'col-md-6 sortable-field' : 'col-md-12 sortable-field' " ng-click="activeField(field)" data-index="{{$index}}">
<div class="form-group " ng-switch-when="text" ng-class="field.Active ? 'active-field' : '' " >
<input type="text" class="input-as-label" ng-model="field.Name" value="{{field.Name + (field.GetFieldSetting('Required') ? '*': '')}}" ng-change="field.ChangeFieldSetting(field.Name,'Field Label')"/>
<span ng-if="field.GetFieldSetting('Required').Value" class="orange-txt">*</span>
<!--<label ng-if="!field.Active" for="{{field.Name.replace(' ','_') + field.id}}">{{field.Name}}<span ng-if="field.GetFieldSetting('Required')">*</span></label> -->
<input type="text" class="form-control" id="{{field.Name.replace(' ','_') + field.id}}" value="{{field.Value}}" placeholder="{{field.Name}}">
<i class ="fa fa-lg fa-minus-square-o remove-ico" ng-click="removeElement($index)" ng-if="field.Active"></i>
</div>
<div class="form-group k" ng-switch-when="date" ng-class="field.Active ? 'active-field' : '' ">
<input type="text" class="input-as-label" ng-model="field.Name" value="{{field.Name + (field.GetFieldSetting('Required').Value ? '*': '')}}" ng-change="field.ChangeFieldSetting(field.Name,'Field Label')"/>
<span ng-if="field.GetFieldSetting('Required').Value" class="orange-txt">*</span>
<div class="has-feedback">
<input type="text" class="form-control" placeholder="{{field.Name}}">
<span class="glyphicon glyphicon-calendar form-control-feedback custom-feedback" aria-hidden="true"></span>
<span id="inputSuccess2Status" class="sr-only">(success)</span>
</div>
<i class ="fa fa-lg fa-minus-square-o remove-ico" ng-if="field.Active" ng-click="removeElement($index)"></i>
</div>
<div class="form-group " ng-switch-when="dropdown" ng-class="field.Active ? 'active-field' : '' ">
<input type="text" class="input-as-label" ng-model="field.Name" value="{{field.Name + (field.GetFieldSetting('Required').Value ? '*': '')}}" ng-change="field.ChangeFieldSetting(field.Name,'Field Label')"/>
<span ng-if="field.GetFieldSetting('Required').Value" class="orange-txt">*</span>
<select class="form-control" >
<option ng-repeat="val in field.GetFieldSetting('Choice').PossibleValue">
{{val.Text}}
</option>
</select>
<i class ="fa fa-lg fa-minus-square-o remove-ico" ng-if="field.Active" ng-click="removeElement($index)"></i>
</div>
<div class="form-group " ng-switch-when="textarea" ng-class="field.Active ? 'active-field' : '' ">
<input type="text" class="input-as-label" ng-model="field.Name" value="{{field.Name + (field.GetFieldSetting('Required').Value ? '*': '')}}" ng-change="field.ChangeFieldSetting(field.Name,'Field Label')"/>
<span ng-if="field.GetFieldSetting('Required').Value" class="orange-txt">*</span>
<textarea class="form-control" id="{{field.Name.replace(' ','_') + field.id}}" rows="4"></textarea>
<i class ="fa fa-lg fa-minus-square-o remove-ico" ng-if="field.Active" ng-click="removeElement($index)"></i>
</div>
<div ng-switch-default>
</div>
</li>
<li class="drop-to-add col-md-12" element-drop>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>