占位符文本是可编辑的
Placeholder text is editable
我的表格行为异常。我们系统中的其他表单表现得很好,但我的在 IE11 中做了一些微妙的奇怪事情。这似乎是因为某些组件不能很好地共存。
我的问题是:如何阻止它做这些奇怪的事情以及为什么会发生这些奇怪的事情?
我的表单在 <table>
中显示 属性 个销售列表。每笔销售都有自己的 <tbody>
,其中包含一些 <tr>
。其中一个单元格包含一个带有工具提示的文件输入(来自 Bootstrap)。我必须在首次显示表单时隐藏一些销售额,我使用 display: none
或 JQuery .hide()
来隐藏这些销售额。该表单还使用占位符和一些基于 here.
代码的 "mandatory input decoration"(自动在必填输入旁边放置一个星号)
通过排除过程,我发现有两件事可以阻止奇怪的事情发生:不隐藏任何包含文件输入的 <tr>
,并且不使用任何强制输入修饰。不幸的是,我需要做这两件事。
怪事
- 初始插入符位置:在最初获得焦点的文本框(地址字段,即pre-populated)中,插入符有时会出现在文本的开头,有时在最后
- 可编辑占位符:见下文
- 标签标题:浏览器标签文本卡在 "Waiting for ..."
- 怪异行为的怪异模式:见下文
可编辑占位符
当我单击带有占位符的文本框时,插入符号的正常行为是出现在文本框的左侧,并且(在 Chrome 中)占位符文本在插入符号的右侧仍然可见,或者(在 IE11 中)占位符文本消失了。但是当我的页面在 IE11 中表现异常时,插入符号出现在占位符之后:
...并且是可编辑的...
提交表单时,不会随表单一起提交任何更新的占位符内容,因此我的用户有可能输入他们认为会保存但实际上并未保存的文本。
占位符的怪异也很微妙:它只发生在鼠标第一次点击页面时;在字段之间进行后续点击或键盘 Tab 键时一切正常。
怪异行为的怪异模式
根据页面显示之前发生的情况,情况会有所不同。
在第一个显示中,占位符是可编辑的。如果我点击一个占位符(即让插入符号出现在占位符文本中或之后的某处),刷新后页面的行为与我没有点击占位符时不同。
如果我首先单击其中一个带有占位符的文本框,并且该占位符是可编辑的,那么在 F5 之后,最初获得焦点的文本框将在开头显示插入符号。或者,如果最初聚焦的文本框 有 开头的插入符号,而我没有对表单做任何操作,则插入符号在 F5 后再次回到开头。如果最初聚焦的文本框最后有插入符号,那么我可以编辑我的评论字段的占位符文本...有点混乱。
我试过的
我们通常使用 this 让占位符在旧版浏览器中工作。我试过删除它,但没有任何区别。
我试过 this script,但这只是让问题略有不同:插入符号移动到占位符的开头,但它仍然是可编辑的。
我试过删除 nicefileinput
,但没有任何区别。
这是我的完整表格。 "Comment" 字段出现在表单
的一半左右
@model OurCompany.Web.ViewModels.OurProductCompleteDesktopSalesComparisonViewModel
@{
ViewBag.Title = "CompleteDesktopSalesComparison";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<link rel="stylesheet" href="~/content/css/typeahead.js-bootstrap.css">
<script type="text/javascript" src="~/Content/Scripts/DICurrencyInputFormatter.js"></script>
<section class="container-wrap">
<div class="container">
@Html.Partial("~/Views/OurProduct/_CompleteHeaderPartial.cshtml")
@using (Html.BeginForm("CompleteDesktopSalesComparison", "OurProduct", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.ValidationSummary(false)
@Html.AntiForgeryToken()
@Html.HiddenFor(m => m.Valuation.OrderNumber)
@Html.HiddenFor(m => m.Property.DIPID)
@Html.HiddenFor(m => m.Property.FullAddress)
@Html.HiddenFor(m => m.Valuation.CategoryCode)
@Html.HiddenFor(m => m.Valuation.ValuationTypeCode)
@Html.Partial("~/Views/OurProduct/_CompleteNavigationTabsPartial.cshtml")
<div class="col-md-10 col-md-offset-1">
<div class="row"> </div>
<div>
@*Sales comparisons==============================================================================*@
@Html.Hidden("saleCount", Model.ComparableSales.Count)
<table class="table table-default">
@foreach (var sale in Model.ComparableSales)
{
var saleIndex = Model.ComparableSales.IndexOf(sale);
var isVisible = sale.Visible;
var shadedClass = saleIndex % 2 == 0 ? string.Empty : "shaded-rows";
var visibleStyle = isVisible ? string.Empty : "display: none;";
var saleTbodyId = string.Format("saleTbody{0}", saleIndex);
var selectedId = string.Format("selected{0}", saleIndex);
var visibleId = string.Format("visible{0}", saleIndex);
<tbody id="@saleTbodyId" class="@shadedClass" style="@visibleStyle">
@*Address, selected*@
<tr>
<td>
@Html.HiddenFor(m => m.ComparableSales[saleIndex].Sequence)
@Html.HiddenFor(m => m.ComparableSales[saleIndex].Visible, new{ id = visibleId})
Address
</td>
<td colspan="3">
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].FullAddress, new {@class = "form-control tt-query", style = "width: 100%;", placeholder = "Full address of sale"})
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].FullAddress)
@Html.HiddenFor(m => m.ComparableSales[saleIndex].Dipid)
<script>
$("#Valuation_ComparableSales_@(saleIndex)__FullAddress").on("typeahead:selected typeahead:autocompleted", function(e, datum) {
$("#Valuation_ComparableSales_@(saleIndex)__Dipid").val(datum.SearchKey);
})
</script>
</td>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Selected)</td>
<td>
@Html.CheckBoxFor(m => m.ComparableSales[saleIndex].Selected, new { id = selectedId })
</td>
</tr>
@*Date, Price*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Date)</td>
<td>
<span class="di-mandatory-field-container di-mandatory-field-text" style="position: relative;">
@Html.DropDownListFor(m => m.ComparableSales[saleIndex].Date,
Model.GetSalesDateListInstance(Model.ComparableSales[saleIndex].Date),
new { @class = "form-control" })
</span>
</td>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].PriceString)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].PriceString,
new { @class = "form-control currency-0-decimals", placeholder = "Sale price" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].PriceString)
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Price)
</td>
<td></td>
<td></td>
</tr>
@*Floor Area, Bedrooms*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].FloorArea)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].FloorArea,
new { @class = "form-control", placeholder = "Floor Area" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].FloorArea)
</td>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Bedrooms)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].Bedrooms,
new { @class = "form-control", placeholder = "Bedrooms" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Bedrooms)
</td>
<td></td>
<td></td>
</tr>
@*Land Area, Bathrooms*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].LandArea)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].LandArea,
new { @class = "form-control", placeholder = "Land Area" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].LandArea)
</td>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Bathrooms)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].Bathrooms,
new { @class = "form-control", placeholder = "Bathrooms" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Bathrooms)
</td>
<td></td>
<td></td>
</tr>
@*Comment*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Comment)</td>
<td colspan="5">
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].Comment,
new { @class = "form-control", placeholder = "Comments" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Comment)
</td>
</tr>
@*Image*@
<tr>
<td>
<p>Image</p>
<p>(@Html.DisplayFor(m => m.FileExtensionConstraintMessages["VALUATION_REPORT_SALE_IMAGE"]))</p>
</td>
<td colspan="5">
@if (Model.ComparableSales[saleIndex].Images != null)
{
foreach (var file in Model.ComparableSales[saleIndex].Images)
{
<span>@Html.DisplayFor(f => file.FileName) (Created: @Html.DisplayFor(f => file.CreateDate))</span>
<a href="@Url.Action("PropertyFile", "Files", new { orderNumber = Model.Valuation.OrderNumber, fileTypeCode = file.FileTypeCode, userFileId = file.Id })"><i class="fa fa-file fa-lg"></i></a>
<br/>
}
}
<span data-toggle="tooltip" data-placement="top" title="@Html.DisplayFor(m => m.FileUploadConstraintMessages["VALUATION_REPORT_SALE_IMAGE"])">
<input type="file" name="sale@(saleIndex)Image"/>
</span>
@{ var validationMessageKey = String.Format("SaleComparisonImage{0}", saleIndex); }
@Html.ValidationMessage(validationMessageKey)
</td>
</tr>
@*Comparability*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Comparability)</td>
<td colspan="5">
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].Comparability,
new { @class = "form-control", placeholder = "Comparability - e.g. Inferior, Comparable, Superior" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Comparability)
</td>
</tr>
</tbody>
}
</table>
</div>
<div><input id="addSaleButton" type="button" value="Add a sale" class="btn btn-light" /></div>
</div>
@Html.Partial("~/Views/OurProduct/_CompleteNavigationButtonsPartial.cshtml")
}
<div class="row"> </div>
</div>
<div class="push"></div>
</section>
<script src="~/Content/scripts/moment.js"></script>
<script src="~/Content/scripts/bootstrap.min.js"></script>
<script src="~/content/scripts/jquery.nicefileinput.min.js"></script>
<script src="~/content/scripts/jquery.placeholder.js"></script>
<script src="~/content/scripts/typeahead.js"></script>
<script>
$("#addSaleButton").click(function() {
var saleCount = $("#saleCount").val();
for (var i = 0; i < saleCount; i++) {
var saleTbodyId = "saleTbody" + i;
if ($("#" + saleTbodyId + ":hidden").length > 0) {
// make the sale visible
$("#" + saleTbodyId).show();
// check the Selected checkbox
var selectedId = "selected" + i;
$("#" + selectedId).prop("checked", true);
// set the hidden value to ensure it shows after validation errors
var visibleId = "visible" + i;
$("#" + visibleId).val("True");
// done one, don't do any more
break;
}
}
});
$(".tt-query").typeahead({
name: 'SearchValue',
valueKey: 'SearchValue',
limit: 20,
remote: {
url: '/properties/GetAddressSearchValues?partSearchValue=%QUERY'
}
});
$(document).ready(function() {
// tooltips
$("span").tooltip({ placement: 'top' });
// custom styling for file input
$("input[type=file]").nicefileinput();
// placeholder attribute for old browsers
$('input, textarea').placeholder();
$("#ComparableSales_0__FullAddress").focus();
});
</script>
这是强制输入装饰.js 文件
// Add a CSS class to mandatory text input fields.
// see http://www.robertgray.net.au/posts/2012/11/indicating-required-fields-with-twitter-bootstrap-and-aspnet-mvc-4#.VMqY0miUfeo
function markRequired() {
// look at every mandatory field
$('input[data-val-required]').each(function () {
// not all should be treated
if (!$(this).parent().hasClass("input-append") && !(this).hasAttribute("readonly")) {
if ($(this).is("input:text")) {
$(this).wrap("<div class='di-mandatory-field-container di-mandatory-field-text'>");
//$(this).wrap("<div class='input-group'>");
//$(this).after("<span class='input-group-addon'><i class='fa fa-asterisk required-asterisk'></i></span>");
//$(this).addClass("di-mandatory-field-container");
//$(this).addClass("di-mandatory-field-text");
//$(this).wrap("<span>");
}
}
});
}
function addFootnote() {
var parentForm;
// check the form for mandatory class (may be manually- or automatically-added)
var firstMandatory = $('.di-mandatory-field-container').first();
// find the form containing that element
if (firstMandatory != null) {
var parentFinder = firstMandatory[0];
while (parentForm == null && parentFinder != null) {
if (parentFinder.tagName.toLowerCase() == "form") {
parentForm = parentFinder;
}
parentFinder = parentFinder.parentNode;
}
}
// add the footnote
if (parentForm != null) {
var rubric = $('<span>', { text: "denotes a mandatory field", style: "position: absolute;" })
.addClass("di-mandatory-field-footnote");
rubric.appendTo($(parentForm).parent());
}
}
$(document).ready(function () {
markRequired();
addFootnote();
});
这只是答案的一半(仍然不知道为什么会发生这种怪事),但有人可能会发现这有帮助...
$(document).ready(function() {
$("#ComparableSales_0__FullAddress").focus();
$("#selected0").focus();
});
由于所述 "delicate" bug 的性质,只需聚焦两次即可将其杀死。
我的表格行为异常。我们系统中的其他表单表现得很好,但我的在 IE11 中做了一些微妙的奇怪事情。这似乎是因为某些组件不能很好地共存。
我的问题是:如何阻止它做这些奇怪的事情以及为什么会发生这些奇怪的事情?
我的表单在 <table>
中显示 属性 个销售列表。每笔销售都有自己的 <tbody>
,其中包含一些 <tr>
。其中一个单元格包含一个带有工具提示的文件输入(来自 Bootstrap)。我必须在首次显示表单时隐藏一些销售额,我使用 display: none
或 JQuery .hide()
来隐藏这些销售额。该表单还使用占位符和一些基于 here.
通过排除过程,我发现有两件事可以阻止奇怪的事情发生:不隐藏任何包含文件输入的 <tr>
,并且不使用任何强制输入修饰。不幸的是,我需要做这两件事。
怪事
- 初始插入符位置:在最初获得焦点的文本框(地址字段,即pre-populated)中,插入符有时会出现在文本的开头,有时在最后
- 可编辑占位符:见下文
- 标签标题:浏览器标签文本卡在 "Waiting for ..."
- 怪异行为的怪异模式:见下文
可编辑占位符
当我单击带有占位符的文本框时,插入符号的正常行为是出现在文本框的左侧,并且(在 Chrome 中)占位符文本在插入符号的右侧仍然可见,或者(在 IE11 中)占位符文本消失了。但是当我的页面在 IE11 中表现异常时,插入符号出现在占位符之后:
...并且是可编辑的...
提交表单时,不会随表单一起提交任何更新的占位符内容,因此我的用户有可能输入他们认为会保存但实际上并未保存的文本。
占位符的怪异也很微妙:它只发生在鼠标第一次点击页面时;在字段之间进行后续点击或键盘 Tab 键时一切正常。
怪异行为的怪异模式
根据页面显示之前发生的情况,情况会有所不同。
在第一个显示中,占位符是可编辑的。如果我点击一个占位符(即让插入符号出现在占位符文本中或之后的某处),刷新后页面的行为与我没有点击占位符时不同。
如果我首先单击其中一个带有占位符的文本框,并且该占位符是可编辑的,那么在 F5 之后,最初获得焦点的文本框将在开头显示插入符号。或者,如果最初聚焦的文本框 有 开头的插入符号,而我没有对表单做任何操作,则插入符号在 F5 后再次回到开头。如果最初聚焦的文本框最后有插入符号,那么我可以编辑我的评论字段的占位符文本...有点混乱。
我试过的
我们通常使用 this 让占位符在旧版浏览器中工作。我试过删除它,但没有任何区别。
我试过 this script,但这只是让问题略有不同:插入符号移动到占位符的开头,但它仍然是可编辑的。
我试过删除 nicefileinput
,但没有任何区别。
这是我的完整表格。 "Comment" 字段出现在表单
的一半左右@model OurCompany.Web.ViewModels.OurProductCompleteDesktopSalesComparisonViewModel
@{
ViewBag.Title = "CompleteDesktopSalesComparison";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<link rel="stylesheet" href="~/content/css/typeahead.js-bootstrap.css">
<script type="text/javascript" src="~/Content/Scripts/DICurrencyInputFormatter.js"></script>
<section class="container-wrap">
<div class="container">
@Html.Partial("~/Views/OurProduct/_CompleteHeaderPartial.cshtml")
@using (Html.BeginForm("CompleteDesktopSalesComparison", "OurProduct", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.ValidationSummary(false)
@Html.AntiForgeryToken()
@Html.HiddenFor(m => m.Valuation.OrderNumber)
@Html.HiddenFor(m => m.Property.DIPID)
@Html.HiddenFor(m => m.Property.FullAddress)
@Html.HiddenFor(m => m.Valuation.CategoryCode)
@Html.HiddenFor(m => m.Valuation.ValuationTypeCode)
@Html.Partial("~/Views/OurProduct/_CompleteNavigationTabsPartial.cshtml")
<div class="col-md-10 col-md-offset-1">
<div class="row"> </div>
<div>
@*Sales comparisons==============================================================================*@
@Html.Hidden("saleCount", Model.ComparableSales.Count)
<table class="table table-default">
@foreach (var sale in Model.ComparableSales)
{
var saleIndex = Model.ComparableSales.IndexOf(sale);
var isVisible = sale.Visible;
var shadedClass = saleIndex % 2 == 0 ? string.Empty : "shaded-rows";
var visibleStyle = isVisible ? string.Empty : "display: none;";
var saleTbodyId = string.Format("saleTbody{0}", saleIndex);
var selectedId = string.Format("selected{0}", saleIndex);
var visibleId = string.Format("visible{0}", saleIndex);
<tbody id="@saleTbodyId" class="@shadedClass" style="@visibleStyle">
@*Address, selected*@
<tr>
<td>
@Html.HiddenFor(m => m.ComparableSales[saleIndex].Sequence)
@Html.HiddenFor(m => m.ComparableSales[saleIndex].Visible, new{ id = visibleId})
Address
</td>
<td colspan="3">
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].FullAddress, new {@class = "form-control tt-query", style = "width: 100%;", placeholder = "Full address of sale"})
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].FullAddress)
@Html.HiddenFor(m => m.ComparableSales[saleIndex].Dipid)
<script>
$("#Valuation_ComparableSales_@(saleIndex)__FullAddress").on("typeahead:selected typeahead:autocompleted", function(e, datum) {
$("#Valuation_ComparableSales_@(saleIndex)__Dipid").val(datum.SearchKey);
})
</script>
</td>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Selected)</td>
<td>
@Html.CheckBoxFor(m => m.ComparableSales[saleIndex].Selected, new { id = selectedId })
</td>
</tr>
@*Date, Price*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Date)</td>
<td>
<span class="di-mandatory-field-container di-mandatory-field-text" style="position: relative;">
@Html.DropDownListFor(m => m.ComparableSales[saleIndex].Date,
Model.GetSalesDateListInstance(Model.ComparableSales[saleIndex].Date),
new { @class = "form-control" })
</span>
</td>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].PriceString)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].PriceString,
new { @class = "form-control currency-0-decimals", placeholder = "Sale price" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].PriceString)
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Price)
</td>
<td></td>
<td></td>
</tr>
@*Floor Area, Bedrooms*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].FloorArea)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].FloorArea,
new { @class = "form-control", placeholder = "Floor Area" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].FloorArea)
</td>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Bedrooms)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].Bedrooms,
new { @class = "form-control", placeholder = "Bedrooms" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Bedrooms)
</td>
<td></td>
<td></td>
</tr>
@*Land Area, Bathrooms*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].LandArea)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].LandArea,
new { @class = "form-control", placeholder = "Land Area" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].LandArea)
</td>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Bathrooms)</td>
<td>
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].Bathrooms,
new { @class = "form-control", placeholder = "Bathrooms" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Bathrooms)
</td>
<td></td>
<td></td>
</tr>
@*Comment*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Comment)</td>
<td colspan="5">
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].Comment,
new { @class = "form-control", placeholder = "Comments" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Comment)
</td>
</tr>
@*Image*@
<tr>
<td>
<p>Image</p>
<p>(@Html.DisplayFor(m => m.FileExtensionConstraintMessages["VALUATION_REPORT_SALE_IMAGE"]))</p>
</td>
<td colspan="5">
@if (Model.ComparableSales[saleIndex].Images != null)
{
foreach (var file in Model.ComparableSales[saleIndex].Images)
{
<span>@Html.DisplayFor(f => file.FileName) (Created: @Html.DisplayFor(f => file.CreateDate))</span>
<a href="@Url.Action("PropertyFile", "Files", new { orderNumber = Model.Valuation.OrderNumber, fileTypeCode = file.FileTypeCode, userFileId = file.Id })"><i class="fa fa-file fa-lg"></i></a>
<br/>
}
}
<span data-toggle="tooltip" data-placement="top" title="@Html.DisplayFor(m => m.FileUploadConstraintMessages["VALUATION_REPORT_SALE_IMAGE"])">
<input type="file" name="sale@(saleIndex)Image"/>
</span>
@{ var validationMessageKey = String.Format("SaleComparisonImage{0}", saleIndex); }
@Html.ValidationMessage(validationMessageKey)
</td>
</tr>
@*Comparability*@
<tr>
<td>@Html.DisplayNameFor(m => m.ComparableSales[saleIndex].Comparability)</td>
<td colspan="5">
@Html.TextBoxFor(m => m.ComparableSales[saleIndex].Comparability,
new { @class = "form-control", placeholder = "Comparability - e.g. Inferior, Comparable, Superior" })
@Html.ValidationMessageFor(m => m.ComparableSales[saleIndex].Comparability)
</td>
</tr>
</tbody>
}
</table>
</div>
<div><input id="addSaleButton" type="button" value="Add a sale" class="btn btn-light" /></div>
</div>
@Html.Partial("~/Views/OurProduct/_CompleteNavigationButtonsPartial.cshtml")
}
<div class="row"> </div>
</div>
<div class="push"></div>
</section>
<script src="~/Content/scripts/moment.js"></script>
<script src="~/Content/scripts/bootstrap.min.js"></script>
<script src="~/content/scripts/jquery.nicefileinput.min.js"></script>
<script src="~/content/scripts/jquery.placeholder.js"></script>
<script src="~/content/scripts/typeahead.js"></script>
<script>
$("#addSaleButton").click(function() {
var saleCount = $("#saleCount").val();
for (var i = 0; i < saleCount; i++) {
var saleTbodyId = "saleTbody" + i;
if ($("#" + saleTbodyId + ":hidden").length > 0) {
// make the sale visible
$("#" + saleTbodyId).show();
// check the Selected checkbox
var selectedId = "selected" + i;
$("#" + selectedId).prop("checked", true);
// set the hidden value to ensure it shows after validation errors
var visibleId = "visible" + i;
$("#" + visibleId).val("True");
// done one, don't do any more
break;
}
}
});
$(".tt-query").typeahead({
name: 'SearchValue',
valueKey: 'SearchValue',
limit: 20,
remote: {
url: '/properties/GetAddressSearchValues?partSearchValue=%QUERY'
}
});
$(document).ready(function() {
// tooltips
$("span").tooltip({ placement: 'top' });
// custom styling for file input
$("input[type=file]").nicefileinput();
// placeholder attribute for old browsers
$('input, textarea').placeholder();
$("#ComparableSales_0__FullAddress").focus();
});
</script>
这是强制输入装饰.js 文件
// Add a CSS class to mandatory text input fields.
// see http://www.robertgray.net.au/posts/2012/11/indicating-required-fields-with-twitter-bootstrap-and-aspnet-mvc-4#.VMqY0miUfeo
function markRequired() {
// look at every mandatory field
$('input[data-val-required]').each(function () {
// not all should be treated
if (!$(this).parent().hasClass("input-append") && !(this).hasAttribute("readonly")) {
if ($(this).is("input:text")) {
$(this).wrap("<div class='di-mandatory-field-container di-mandatory-field-text'>");
//$(this).wrap("<div class='input-group'>");
//$(this).after("<span class='input-group-addon'><i class='fa fa-asterisk required-asterisk'></i></span>");
//$(this).addClass("di-mandatory-field-container");
//$(this).addClass("di-mandatory-field-text");
//$(this).wrap("<span>");
}
}
});
}
function addFootnote() {
var parentForm;
// check the form for mandatory class (may be manually- or automatically-added)
var firstMandatory = $('.di-mandatory-field-container').first();
// find the form containing that element
if (firstMandatory != null) {
var parentFinder = firstMandatory[0];
while (parentForm == null && parentFinder != null) {
if (parentFinder.tagName.toLowerCase() == "form") {
parentForm = parentFinder;
}
parentFinder = parentFinder.parentNode;
}
}
// add the footnote
if (parentForm != null) {
var rubric = $('<span>', { text: "denotes a mandatory field", style: "position: absolute;" })
.addClass("di-mandatory-field-footnote");
rubric.appendTo($(parentForm).parent());
}
}
$(document).ready(function () {
markRequired();
addFootnote();
});
这只是答案的一半(仍然不知道为什么会发生这种怪事),但有人可能会发现这有帮助...
$(document).ready(function() {
$("#ComparableSales_0__FullAddress").focus();
$("#selected0").focus();
});
由于所述 "delicate" bug 的性质,只需聚焦两次即可将其杀死。