Related
I want to validate each input with so below is the code in js
var inputs = document.querySelectorAll('input[data-filter]');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
var state = {
value: input.value,
start: input.selectionStart,
end: input.selectionEnd,
pattern: RegExp('^' + input.dataset.filter + '$')
};
input.addEventListener('input', function (event) {
if (state.pattern.test(input.value)) {
state.value = input.value;
} else {
input.value = state.value;
input.setSelectionRange(state.start, state.end);
}
});
input.addEventListener('keydown', function (event) {
state.start = input.selectionStart;
state.end = input.selectionEnd;
});
}
It works perfectly with textbox
#Html.TextBoxFor(m=>m.Telephone, new { id="phone", data_filter="\\+?(?:\\d\\s?){0,13}"})
Original regex ^\+?(?:\d\s?){11,13}$ escaped backslash as it was giving error
$("#phone").on("focus", function (evt) {
if(this.value.length < 11)
alert("Invalid");
});
It is not working with razor.What is the issue??
I have an old system which uses UpdatePanels of asp.net
After the postback is completed, we know that the inside of UpdatePanel is updated
Can i delay this update somehow on the client side ? is that possible?
So it will be like, when the postback is started, i set a javascript datetime object on the client side
Once the postback is completed, and the data is returned from the server, before updating the client side interface, i check how many miliseconds has passed and I delay the update of the client side until certain miliseconds has passed
is this possible?
asp.net 4.5 c#
let me clarify better
i want each update of the page to be exactly 500 miliseconds after the ajax postback request started
however the server delay is unknown and changes for the every location
let say that for person 1 the server delay is 122 ms
for person 2 the server delay is 234
for person 3 the server delay is 444
so i would be have to delay the page update at the client side
for the person 1 : 378 ms
for the person 2 : 266 ms
for the person 3 : 56 ms
i have checked and i found that there is a function :
Sys.WebForms.PageRequestManager pageLoading Event
so if i can somehow override the function that this function calls to update the page i can achieve
(i still dont know what function it calls to complete the update operation on the client side)
lets assume that inside
Sys.WebForms.PageRequestManager pageLoading Event
updateTheChanges function is called
so if i can override this updateTheChanges function and call it with a delay i can achieve what i want
I need exactly something like this which will overwrite the update function of the updatepanel. So i can call this function with a delay
ASP.Net Webforms w/ AJAX Slow Rendering
ty
here the web resource files
script resource 1 : http://pastebin.com/0rSCMn3g
script resource 2 : http://pastebin.com/GvqwpPv8
script resource 3 below
function WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit) {
this.eventTarget = eventTarget;
this.eventArgument = eventArgument;
this.validation = validation;
this.validationGroup = validationGroup;
this.actionUrl = actionUrl;
this.trackFocus = trackFocus;
this.clientSubmit = clientSubmit;
}
function WebForm_DoPostBackWithOptions(options) {
var validationResult = true;
if (options.validation) {
if (typeof(Page_ClientValidate) == 'function') {
validationResult = Page_ClientValidate(options.validationGroup);
}
}
if (validationResult) {
if ((typeof(options.actionUrl) != "undefined") && (options.actionUrl != null) && (options.actionUrl.length > 0)) {
theForm.action = options.actionUrl;
}
if (options.trackFocus) {
var lastFocus = theForm.elements["__LASTFOCUS"];
if ((typeof(lastFocus) != "undefined") && (lastFocus != null)) {
if (typeof(document.activeElement) == "undefined") {
lastFocus.value = options.eventTarget;
} else {
var active = document.activeElement;
if ((typeof(active) != "undefined") && (active != null)) {
if ((typeof(active.id) != "undefined") && (active.id != null) && (active.id.length > 0)) {
lastFocus.value = active.id;
} else if (typeof(active.name) != "undefined") {
lastFocus.value = active.name;
}
}
}
}
}
}
if (options.clientSubmit) {
__doPostBack(options.eventTarget, options.eventArgument);
}
}
var __pendingCallbacks = new Array();
var __synchronousCallBackIndex = -1;
function WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync) {
var postData = __theFormPostData +
"__CALLBACKID=" + WebForm_EncodeCallback(eventTarget) +
"&__CALLBACKPARAM=" + WebForm_EncodeCallback(eventArgument);
if (theForm["__EVENTVALIDATION"]) {
postData += "&__EVENTVALIDATION=" + WebForm_EncodeCallback(theForm["__EVENTVALIDATION"].value);
}
var xmlRequest, e;
try {
xmlRequest = new XMLHttpRequest();
} catch (e) {
try {
xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
var setRequestHeaderMethodExists = true;
try {
setRequestHeaderMethodExists = (xmlRequest && xmlRequest.setRequestHeader);
} catch (e) {}
var callback = new Object();
callback.eventCallback = eventCallback;
callback.context = context;
callback.errorCallback = errorCallback;
callback.async = useAsync;
var callbackIndex = WebForm_FillFirstAvailableSlot(__pendingCallbacks, callback);
if (!useAsync) {
if (__synchronousCallBackIndex != -1) {
__pendingCallbacks[__synchronousCallBackIndex] = null;
}
__synchronousCallBackIndex = callbackIndex;
}
if (setRequestHeaderMethodExists) {
xmlRequest.onreadystatechange = WebForm_CallbackComplete;
callback.xmlRequest = xmlRequest;
// e.g. http:
var action = theForm.action || document.location.pathname,
fragmentIndex = action.indexOf('#');
if (fragmentIndex !== -1) {
action = action.substr(0, fragmentIndex);
}
if (!__nonMSDOMBrowser) {
var queryIndex = action.indexOf('?');
if (queryIndex !== -1) {
var path = action.substr(0, queryIndex);
if (path.indexOf("%") === -1) {
action = encodeURI(path) + action.substr(queryIndex);
}
} else if (action.indexOf("%") === -1) {
action = encodeURI(action);
}
}
xmlRequest.open("POST", action, true);
xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
xmlRequest.send(postData);
return;
}
callback.xmlRequest = new Object();
var callbackFrameID = "__CALLBACKFRAME" + callbackIndex;
var xmlRequestFrame = document.frames[callbackFrameID];
if (!xmlRequestFrame) {
xmlRequestFrame = document.createElement("IFRAME");
xmlRequestFrame.width = "1";
xmlRequestFrame.height = "1";
xmlRequestFrame.frameBorder = "0";
xmlRequestFrame.id = callbackFrameID;
xmlRequestFrame.name = callbackFrameID;
xmlRequestFrame.style.position = "absolute";
xmlRequestFrame.style.top = "-100px"
xmlRequestFrame.style.left = "-100px";
try {
if (callBackFrameUrl) {
xmlRequestFrame.src = callBackFrameUrl;
}
} catch (e) {}
document.body.appendChild(xmlRequestFrame);
}
var interval = window.setInterval(function() {
xmlRequestFrame = document.frames[callbackFrameID];
if (xmlRequestFrame && xmlRequestFrame.document) {
window.clearInterval(interval);
xmlRequestFrame.document.write("");
xmlRequestFrame.document.close();
xmlRequestFrame.document.write('<html><body><form method="post"><input type="hidden" name="__CALLBACKLOADSCRIPT" value="t"></form></body></html>');
xmlRequestFrame.document.close();
xmlRequestFrame.document.forms[0].action = theForm.action;
var count = __theFormPostCollection.length;
var element;
for (var i = 0; i < count; i++) {
element = __theFormPostCollection[i];
if (element) {
var fieldElement = xmlRequestFrame.document.createElement("INPUT");
fieldElement.type = "hidden";
fieldElement.name = element.name;
fieldElement.value = element.value;
xmlRequestFrame.document.forms[0].appendChild(fieldElement);
}
}
var callbackIdFieldElement = xmlRequestFrame.document.createElement("INPUT");
callbackIdFieldElement.type = "hidden";
callbackIdFieldElement.name = "__CALLBACKID";
callbackIdFieldElement.value = eventTarget;
xmlRequestFrame.document.forms[0].appendChild(callbackIdFieldElement);
var callbackParamFieldElement = xmlRequestFrame.document.createElement("INPUT");
callbackParamFieldElement.type = "hidden";
callbackParamFieldElement.name = "__CALLBACKPARAM";
callbackParamFieldElement.value = eventArgument;
xmlRequestFrame.document.forms[0].appendChild(callbackParamFieldElement);
if (theForm["__EVENTVALIDATION"]) {
var callbackValidationFieldElement = xmlRequestFrame.document.createElement("INPUT");
callbackValidationFieldElement.type = "hidden";
callbackValidationFieldElement.name = "__EVENTVALIDATION";
callbackValidationFieldElement.value = theForm["__EVENTVALIDATION"].value;
xmlRequestFrame.document.forms[0].appendChild(callbackValidationFieldElement);
}
var callbackIndexFieldElement = xmlRequestFrame.document.createElement("INPUT");
callbackIndexFieldElement.type = "hidden";
callbackIndexFieldElement.name = "__CALLBACKINDEX";
callbackIndexFieldElement.value = callbackIndex;
xmlRequestFrame.document.forms[0].appendChild(callbackIndexFieldElement);
xmlRequestFrame.document.forms[0].submit();
}
}, 10);
}
function WebForm_CallbackComplete() {
for (var i = 0; i < __pendingCallbacks.length; i++) {
callbackObject = __pendingCallbacks[i];
if (callbackObject && callbackObject.xmlRequest && (callbackObject.xmlRequest.readyState == 4)) {
if (!__pendingCallbacks[i].async) {
__synchronousCallBackIndex = -1;
}
__pendingCallbacks[i] = null;
var callbackFrameID = "__CALLBACKFRAME" + i;
var xmlRequestFrame = document.getElementById(callbackFrameID);
if (xmlRequestFrame) {
xmlRequestFrame.parentNode.removeChild(xmlRequestFrame);
}
WebForm_ExecuteCallback(callbackObject);
}
}
}
function WebForm_ExecuteCallback(callbackObject) {
var response = callbackObject.xmlRequest.responseText;
if (response.charAt(0) == "s") {
if ((typeof(callbackObject.eventCallback) != "undefined") && (callbackObject.eventCallback != null)) {
callbackObject.eventCallback(response.substring(1), callbackObject.context);
}
} else if (response.charAt(0) == "e") {
if ((typeof(callbackObject.errorCallback) != "undefined") && (callbackObject.errorCallback != null)) {
callbackObject.errorCallback(response.substring(1), callbackObject.context);
}
} else {
var separatorIndex = response.indexOf("|");
if (separatorIndex != -1) {
var validationFieldLength = parseInt(response.substring(0, separatorIndex));
if (!isNaN(validationFieldLength)) {
var validationField = response.substring(separatorIndex + 1, separatorIndex + validationFieldLength + 1);
if (validationField != "") {
var validationFieldElement = theForm["__EVENTVALIDATION"];
if (!validationFieldElement) {
validationFieldElement = document.createElement("INPUT");
validationFieldElement.type = "hidden";
validationFieldElement.name = "__EVENTVALIDATION";
theForm.appendChild(validationFieldElement);
}
validationFieldElement.value = validationField;
}
if ((typeof(callbackObject.eventCallback) != "undefined") && (callbackObject.eventCallback != null)) {
callbackObject.eventCallback(response.substring(separatorIndex + validationFieldLength + 1), callbackObject.context);
}
}
}
}
}
function WebForm_FillFirstAvailableSlot(array, element) {
var i;
for (i = 0; i < array.length; i++) {
if (!array[i]) break;
}
array[i] = element;
return i;
}
var __nonMSDOMBrowser = (window.navigator.appName.toLowerCase().indexOf('explorer') == -1);
var __theFormPostData = "";
var __theFormPostCollection = new Array();
var __callbackTextTypes = /^(text|password|hidden|search|tel|url|email|number|range|color|datetime|date|month|week|time|datetime-local)$/i;
function WebForm_InitCallback() {
var formElements = theForm.elements,
count = formElements.length,
element;
for (var i = 0; i < count; i++) {
element = formElements[i];
var tagName = element.tagName.toLowerCase();
if (tagName == "input") {
var type = element.type;
if ((__callbackTextTypes.test(type) || ((type == "checkbox" || type == "radio") && element.checked)) && (element.id != "__EVENTVALIDATION")) {
WebForm_InitCallbackAddField(element.name, element.value);
}
} else if (tagName == "select") {
var selectCount = element.options.length;
for (var j = 0; j < selectCount; j++) {
var selectChild = element.options[j];
if (selectChild.selected == true) {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
} else if (tagName == "textarea") {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
}
function WebForm_InitCallbackAddField(name, value) {
var nameValue = new Object();
nameValue.name = name;
nameValue.value = value;
__theFormPostCollection[__theFormPostCollection.length] = nameValue;
__theFormPostData += WebForm_EncodeCallback(name) + "=" + WebForm_EncodeCallback(value) + "&";
}
function WebForm_EncodeCallback(parameter) {
if (encodeURIComponent) {
return encodeURIComponent(parameter);
} else {
return escape(parameter);
}
}
var __disabledControlArray = new Array();
function WebForm_ReEnableControls() {
if (typeof(__enabledControlArray) == 'undefined') {
return false;
}
var disabledIndex = 0;
for (var i = 0; i < __enabledControlArray.length; i++) {
var c;
if (__nonMSDOMBrowser) {
c = document.getElementById(__enabledControlArray[i]);
} else {
c = document.all[__enabledControlArray[i]];
}
if ((typeof(c) != "undefined") && (c != null) && (c.disabled == true)) {
c.disabled = false;
__disabledControlArray[disabledIndex++] = c;
}
}
setTimeout("WebForm_ReDisableControls()", 0);
return true;
}
function WebForm_ReDisableControls() {
for (var i = 0; i < __disabledControlArray.length; i++) {
__disabledControlArray[i].disabled = true;
}
}
function WebForm_SimulateClick(element, event) {
var clickEvent;
if (element) {
if (element.click) {
element.click();
} else {
clickEvent = document.createEvent("MouseEvents");
clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
if (!element.dispatchEvent(clickEvent)) {
return true;
}
}
event.cancelBubble = true;
if (event.stopPropagation) {
event.stopPropagation();
}
return false;
}
return true;
}
function WebForm_FireDefaultButton(event, target) {
if (event.keyCode == 13) {
var src = event.srcElement || event.target;
if (src &&
((src.tagName.toLowerCase() == "input") &&
(src.type.toLowerCase() == "submit" || src.type.toLowerCase() == "button")) ||
((src.tagName.toLowerCase() == "a") &&
(src.href != null) && (src.href != "")) ||
(src.tagName.toLowerCase() == "textarea")) {
return true;
}
var defaultButton;
if (__nonMSDOMBrowser) {
defaultButton = document.getElementById(target);
} else {
defaultButton = document.all[target];
}
if (defaultButton) {
return WebForm_SimulateClick(defaultButton, event);
}
}
return true;
}
function WebForm_GetScrollX() {
if (__nonMSDOMBrowser) {
return window.pageXOffset;
} else {
if (document.documentElement && document.documentElement.scrollLeft) {
return document.documentElement.scrollLeft;
} else if (document.body) {
return document.body.scrollLeft;
}
}
return 0;
}
function WebForm_GetScrollY() {
if (__nonMSDOMBrowser) {
return window.pageYOffset;
} else {
if (document.documentElement && document.documentElement.scrollTop) {
return document.documentElement.scrollTop;
} else if (document.body) {
return document.body.scrollTop;
}
}
return 0;
}
function WebForm_SaveScrollPositionSubmit() {
if (__nonMSDOMBrowser) {
theForm.elements['__SCROLLPOSITIONY'].value = window.pageYOffset;
theForm.elements['__SCROLLPOSITIONX'].value = window.pageXOffset;
} else {
theForm.__SCROLLPOSITIONX.value = WebForm_GetScrollX();
theForm.__SCROLLPOSITIONY.value = WebForm_GetScrollY();
}
if ((typeof(this.oldSubmit) != "undefined") && (this.oldSubmit != null)) {
return this.oldSubmit();
}
return true;
}
function WebForm_SaveScrollPositionOnSubmit() {
theForm.__SCROLLPOSITIONX.value = WebForm_GetScrollX();
theForm.__SCROLLPOSITIONY.value = WebForm_GetScrollY();
if ((typeof(this.oldOnSubmit) != "undefined") && (this.oldOnSubmit != null)) {
return this.oldOnSubmit();
}
return true;
}
function WebForm_RestoreScrollPosition() {
if (__nonMSDOMBrowser) {
window.scrollTo(theForm.elements['__SCROLLPOSITIONX'].value, theForm.elements['__SCROLLPOSITIONY'].value);
} else {
window.scrollTo(theForm.__SCROLLPOSITIONX.value, theForm.__SCROLLPOSITIONY.value);
}
if ((typeof(theForm.oldOnLoad) != "undefined") && (theForm.oldOnLoad != null)) {
return theForm.oldOnLoad();
}
return true;
}
function WebForm_TextBoxKeyHandler(event) {
if (event.keyCode == 13) {
var target;
if (__nonMSDOMBrowser) {
target = event.target;
} else {
target = event.srcElement;
}
if ((typeof(target) != "undefined") && (target != null)) {
if (typeof(target.onchange) != "undefined") {
target.onchange();
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
}
}
}
return true;
}
function WebForm_TrimString(value) {
return value.replace(/^\s+|\s+$/g, '')
}
function WebForm_AppendToClassName(element, className) {
var currentClassName = ' ' + WebForm_TrimString(element.className) + ' ';
className = WebForm_TrimString(className);
var index = currentClassName.indexOf(' ' + className + ' ');
if (index === -1) {
element.className = (element.className === '') ? className : element.className + ' ' + className;
}
}
function WebForm_RemoveClassName(element, className) {
var currentClassName = ' ' + WebForm_TrimString(element.className) + ' ';
className = WebForm_TrimString(className);
var index = currentClassName.indexOf(' ' + className + ' ');
if (index >= 0) {
element.className = WebForm_TrimString(currentClassName.substring(0, index) + ' ' +
currentClassName.substring(index + className.length + 1, currentClassName.length));
}
}
function WebForm_GetElementById(elementId) {
if (document.getElementById) {
return document.getElementById(elementId);
} else if (document.all) {
return document.all[elementId];
} else return null;
}
function WebForm_GetElementByTagName(element, tagName) {
var elements = WebForm_GetElementsByTagName(element, tagName);
if (elements && elements.length > 0) {
return elements[0];
} else return null;
}
function WebForm_GetElementsByTagName(element, tagName) {
if (element && tagName) {
if (element.getElementsByTagName) {
return element.getElementsByTagName(tagName);
}
if (element.all && element.all.tags) {
return element.all.tags(tagName);
}
}
return null;
}
function WebForm_GetElementDir(element) {
if (element) {
if (element.dir) {
return element.dir;
}
return WebForm_GetElementDir(element.parentNode);
}
return "ltr";
}
function WebForm_GetElementPosition(element) {
var result = new Object();
result.x = 0;
result.y = 0;
result.width = 0;
result.height = 0;
if (element.offsetParent) {
result.x = element.offsetLeft;
result.y = element.offsetTop;
var parent = element.offsetParent;
while (parent) {
result.x += parent.offsetLeft;
result.y += parent.offsetTop;
var parentTagName = parent.tagName.toLowerCase();
if (parentTagName != "table" &&
parentTagName != "body" &&
parentTagName != "html" &&
parentTagName != "div" &&
parent.clientTop &&
parent.clientLeft) {
result.x += parent.clientLeft;
result.y += parent.clientTop;
}
parent = parent.offsetParent;
}
} else if (element.left && element.top) {
result.x = element.left;
result.y = element.top;
} else {
if (element.x) {
result.x = element.x;
}
if (element.y) {
result.y = element.y;
}
}
if (element.offsetWidth && element.offsetHeight) {
result.width = element.offsetWidth;
result.height = element.offsetHeight;
} else if (element.style && element.style.pixelWidth && element.style.pixelHeight) {
result.width = element.style.pixelWidth;
result.height = element.style.pixelHeight;
}
return result;
}
function WebForm_GetParentByTagName(element, tagName) {
var parent = element.parentNode;
var upperTagName = tagName.toUpperCase();
while (parent && (parent.tagName.toUpperCase() != upperTagName)) {
parent = parent.parentNode ? parent.parentNode : parent.parentElement;
}
return parent;
}
function WebForm_SetElementHeight(element, height) {
if (element && element.style) {
element.style.height = height + "px";
}
}
function WebForm_SetElementWidth(element, width) {
if (element && element.style) {
element.style.width = width + "px";
}
}
function WebForm_SetElementX(element, x) {
if (element && element.style) {
element.style.left = x + "px";
}
}
function WebForm_SetElementY(element, y) {
if (element && element.style) {
element.style.top = y + "px";
}
}
Here is a way to delay the UpdatePanel refresh without freezing the user interface:
In the pageLoading event handler, save the ID and the previous HTML of the panels to be updated
In the pageLoad event handler, save the new HTML of the panels but replace it by the old one
After the delay expires, set the new HTML in the updated panels
Here is the client code:
<script type="text/javascript">
var updateTime = 0;
var updatedPanelArray = [];
function setUpdateTime() {
updateTime = new Date(Date.now() + 500);
}
function pageLoading(sender, e) {
updatedPanelArray.length = 0;
var panels = e.get_panelsUpdating();
for (var i = 0; i < panels.length; i++) {
var pnl = panels[i];
updatedPanelArray.push({ id: pnl.id, oldHTML: pnl.innerHTML });
}
}
function pageLoad(sender, e) {
if (e.get_isPartialLoad()) {
for (var i = 0; i < updatedPanelArray.length; i++) {
var updatedPanel = updatedPanelArray[i];
var pnl = document.getElementById(updatedPanel.id);
updatedPanel.newHTML = pnl.innerHTML;
pnl.innerHTML = updatedPanel.oldHTML;
setTimeout(refreshUpdatePanel, updateTime - Date.now());
}
}
}
function refreshUpdatePanel() {
for (var i = 0; i < updatedPanelArray.length; i++) {
var updatedPanel = updatedPanelArray[i];
var pnl = document.getElementById(updatedPanel.id);
pnl.innerHTML = updatedPanel.newHTML;
}
}
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(pageLoading);
</script>
The update time is set before triggering the asynchronous postback:
<asp:UpdatePanel runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="lblUpdatePanel1" runat="server" />
<asp:Button ID="btnUpdatePanel" runat="server" OnClientClick="setUpdateTime();" OnClick="btnUpdatePanel_Click" />
</ContentTemplate>
</asp:UpdatePanel>
It can be tested with the following event handler in code-behind (suggestion: set the delay to 5000 ms in the Javascript code to make it obvious):
protected void btnUpdatePanel_Click(object sender, EventArgs e)
{
lblUpdatePanel1.Text = DateTime.Now.ToString();
}
If you don't mind the user interface being frozen while waiting, you can delay the refresh by keeping the pageLoad event handler busy until the delay expires:
<script type="text/javascript">
var updateTime = 0;
function setUpdateTime() {
updateTime = new Date(Date.now() + 500);
}
function pageLoad(sender, e) {
if (e.get_isPartialLoad()) {
while (Date.now() < updateTime) {
// Loop until the delay expires
}
}
}
</script>
You can initialize the update time before triggering the asynchronous postback:
<asp:UpdatePanel runat="server" UpdateMode="Conditional">
<ContentTemplate>
...
<asp:Button ID="btn1" runat="server" OnClientClick="setUpdateTime();" ... />
</ContentTemplate>
</asp:UpdatePanel>
Use UpdatePanel.UpdateMode Property to gets or sets a value that indicates when an UpdatePanel control's content is updated. For more details visit this link.
You could delay the server side, so all the delays would be more or less equals for everyone.
If this is not an option, you could have a hidden field inside the update panel (or somewhere else). The function that handles the update (in the server side) would calculate the time it took execute, and before finishing, would update this hidden field. Now back in the client side, check the value of this field and calculate the difference between this value and yours 500ms. You could use datetimes or milliseconds.
It's not the prettiest solution but imho, this is not a frequent problem that people want to handle (in fact, I dont think that you should delay a faster response to the slowest one)
My users have requested that I change one of the fields from being required to optional, but still show/hide the warning message. Trying to do this with as little refactoring as I can I added an allowsubmission property on my data annotation on the server and in the jquery method on the client (see below).
Is it possible to set an ignore class on an element while still hiding/showing the message? It seems the method fires the first time and then stops firing after the ignore class is added, so the message stays on the screen.
Or is there a better way? Thank you.
$(document).ready(function () {
$("form").validate().settings.ignore = ".ignore, :hidden";
});
$.validator.unobtrusive.adapters.add('dependentrange', ['minvalueproperty', 'maxvalueproperty', 'allowsubmission'],
function (options) {
options.rules.dependentrange = options.params;
if (options.message) {
$.validator.messages.dependentrange = options.message;
}
}
);
$.validator.addMethod('dependentrange', function (value, element, params) {
var minValue = parseFloat($('input[name="' + params.minvalueproperty + '"]').val());
var maxValue = parseFloat($('input[name="' + params.maxvalueproperty + '"]').val());
var currentValue = parseFloat(value);
// if there is a value check it. If for some reason the min and max can't be found return true because
// i do not know the values to validate. Usually that is a coding mistake
if (isNaN(currentValue) || minValue > currentValue || currentValue > maxValue) {
var message = $(element).attr('data-val-dependentrange');
$.validator.messages.dependentrange = $.validator.format(message, minValue, maxValue);
if (params.allowsubmission) {
// once this property is added, the method does not fire
$(element).addClass("ignore");
}
return false;
}
$(element).removeClass('ignore');
return true;
}, '');
I ended up using validators API to show and hide my own warning message while always return true.
$.validator.unobtrusive.adapters.add('dependentrange', ['minvalueproperty', 'maxvalueproperty'], function (options) {
options.rules['dependentrange'] = options.params;
if (options.message) {
options.messages['dependentrange'] = options.message;
}
});
$.validator.addMethod("dependentrange", function (value, element, params) {
var valKeyed = parseFloat(value),
$elem = $(element),
$warning = $elem.closest('div').nextAll('.alert-warning:first')
msg = $elem.data('val-dependentrange),
isValid = this.optional(element) || valKeyed >= parseFloat(params.minvalueproperty) && valKeyed <= parseFloat(params.maxvalueproperty);
// there are no from or two found, so just return true with no warning
if (!params.minvalueproperty || !params.maxvalueproperty) {
return true;
}
if (isValid) {
$warning.text('')
$warning.addClass('hidden');
}
else {
$warning.text(msg)
$warning.removeClass('hidden');
}
return true;
});
I am using JQPlot to plot a chart on a page. I am plotting Line chart with marker points.
I want to change the color of the marker points.
I need each marker point to be in different color. Is it possible?
Thank you all in advance for your response.
Here is my code :
//In order to use keyboard highlight of the coordinates please click somewhere inside the Result frame.
$(document).ready(function() {
// Some simple loops to build up data arrays.
var cosPoints = [];
for (var i = 0; i < 2 * Math.PI; i += 2) {
cosPoints.push([i, Math.cos(i)]);
}
var plot3 = $.jqplot('chart', [cosPoints], {
cursor: {
show: true,
showTooltip: true,
showTooltipGridPosition: true,
// showTooltipDataPosition: false,
showTooltipUnitPosition: false,
useAxesFormatters: false,
// showVerticalLine : true,
followMouse: true
},
title: 'Line Style Options',
// Series options are specified as an array of objects, one object
seriesDefaults: {
markerRenderer: $.jqplot.MarkerRenderer,
markerOptions: {
color: 'red'
}
}
});
$('#chart').bind('jqplotDataClick', function(ev, seriesIndex, pointIndex, data) {
alert(data);
});
var counter = -1; //to start from the very first on first next click, on prev click it will start from last -- and this is how we want it
$('#buttonPrev').bind("click", function() {
counter--;
DoSomeThing(plot3);
});
$('#buttonNext').bind("click", function() {
counter++;
DoSomeThing(plot3);
});
$(document).keydown(function(e) {
if (e.keyCode == 37) {
$('#buttonPrev').click();
}
else if (e.keyCode == 39) {
$('#buttonNext').click();
}
});
function GetColors() {
var colors = ["red","blue","red","blue"];
return colors;
}
function DoSomeThing(plot) {
// *** highlight point in plot ***
//console.log(" sth "+ plot.series[0].data[1][1]);
var seriesIndex = 0; //0 as we have just one series
var data = plot.series[seriesIndex].data;
if (counter >= data.length) counter = 0;
else if (counter < 0) counter = data.length - 1;
var pointIndex = counter;
var x = plot.axes.xaxis.series_u2p(data[pointIndex][0]);
var y = plot.axes.yaxis.series_u2p(data[pointIndex][1]);
console.log("x= " + x + " y= " + y);
var r = 5;
var drawingCanvas = $(".jqplot-highlight-canvas")[0]; //$(".jqplot-series-canvas")[0];
var context = drawingCanvas.getContext('2d');
context.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height); //plot.replot();
context.strokeStyle = "#000000";
context.fillStyle = "#FFFF00";
context.beginPath();
context.arc(x, y, r, 0, Math.PI * 2, true);
context.closePath();
context.stroke();
context.fill();
}
});
I'm not sure you can specify multiple colors for a single serie.
Either you can divide your serie into several series (ex. 4 series if you have a serie of 4 elements), and use seriesColors : myColorTab to specify different color for each series (thus for each of your elements) :
var myColorTab = new Array("#FF0000", "#384763", "#AA4312");
var plot3 = $.jqplot('chart(, [cos1, cos2, cos3], {
seriesColors : myColorTab
}
Please see working example here
P.S. : You can change the surely not-optimal way to push datas into cos1, cos2 and cos3.
EDIT
In order to change markerpoints back color, you can specify a color for each series :
series: [
{markerRenderer: $.jqplot.MarkerRenderer,
markerOptions: { color: 'red' }
},
{markerRenderer: $.jqplot.MarkerRenderer,
markerOptions: { color: 'blue' }
},
{markerRenderer: $.jqplot.MarkerRenderer,
markerOptions: { color: 'green' }
}
]
Please see edited JsFiddle here
Just Add seriesColors: ['#FFC526', '#C0504D', '#4BACC6', '#8064A2', '#9BBB59', '#F79646', '#948A54', '#4000E3'], above seriesDefaults in your code
I also needed to have different colored markers, and making separate series for each color really the way to go for me, so i made this pointRenderer:
$.jqplot.PointRenderer = function(){
$.jqplot.LineRenderer.call(this);
};
$.jqplot.PointRenderer.prototype = Object.create($.jqplot.LineRenderer.prototype);
$.jqplot.PointRenderer.prototype.constructor = $.jqplot.PointRenderer;
// called with scope of a series
$.jqplot.PointRenderer.prototype.init = function(options, plot) {
options = options || {};
this.renderer.markerOptionsEditor = false;
$.jqplot.LineRenderer.prototype.init.apply(this, arguments);
this._type = 'point';
}
// called within scope of series.
$.jqplot.PointRenderer.prototype.draw = function(ctx, gd, options, plot) {
var i;
// get a copy of the options, so we don't modify the original object.
var opts = $.extend(true, {}, options);
var markerOptions = opts.markerOptions;
ctx.save();
if (gd.length) {
// draw the markers
for (i=0; i<gd.length; i++) {
if (gd[i][0] != null && gd[i][1] != null) {
if (this.renderer.markerOptionsEditor) {
markerOptions = $.extend(true, {}, opts.markerOptions);
markerOptions = this.renderer.markerOptionsEditor.call(plot, this.data[i], markerOptions);
}
this.markerRenderer.draw(gd[i][0], gd[i][1], ctx, markerOptions);
}
}
}
ctx.restore();
};
The draw function is a stripped down version of the LineRenderer draw function, add the missing pieces from that function.
I have played with:
https://github.com/experteer/autocompleteTrigger/
as following:
(function ($, window, document, undefined) {
$.widget("ui.autocompleteTrigger", {
//Options to be used as defaults
options: {
triggerStart: "%{",
triggerEnd: "}"
},
_create: function () {
this.triggered = false;
this.triggered2 = false;
this.element.autocomplete($.extend({
search: function () {
/**
* #description only make a request and suggest items if acTrigger.triggered is true
*/
var acTrigger = $(this).data("autocompleteTrigger");
if (acTrigger.triggered == true || acTrigger.triggered2 == true) {
return true;
} else {
return false;
}
},
select: function (event, ui) {
/**
* #description if a item is selected, insert the value between triggerStart and triggerEnd
*/
var acTrigger = $(this).data("autocompleteTrigger");
var text = this.value;
var trigger = acTrigger.options.triggerStart;
var trigger2 = acTrigger.options.triggerStart2;
var cursorPosition = acTrigger.getCursorPosition();
var lastTrigger1Position = text.substring(0, cursorPosition).lastIndexOf(trigger);
var lastTrigger2Position = text.substring(0, cursorPosition).lastIndexOf(trigger2);
var lastTriggerPosition;
if (lastTrigger1Position > lastTrigger2Position) {
lastTriggerPosition = lastTrigger1Position;
} else {
lastTriggerPosition = lastTrigger2Position;
}
var firstTextPart = text.substring(0, lastTriggerPosition + trigger.length) + ui.item.value +
acTrigger.options.triggerEnd;
this.value = firstTextPart + text.substring(cursorPosition, text.length);
acTrigger.triggered = false;
acTrigger.triggered2 = false;
// set cursor position after the autocompleted text
this.selectionStart = firstTextPart.length;
this.selectionEnd = firstTextPart.length;
return false;
},
focus: function () {
/**
* #description prevent to replace the hole text, if a item is hovered
*/
return false;
},
minLength: 0
}, this.options))
.bind("keyup", function (event) {
/**
* #description Bind to keyup-events to detect text changes.
* If the trigger is found before the cursor, autocomplete will be called
*/
var acTrigger = $(this).data("autocompleteTrigger");
if (event.keyCode != $.ui.keyCode.UP && event.keyCode != $.ui.keyCode.DOWN) {
var text = this.value;
var textLength = text.length;
var cursorPosition = acTrigger.getCursorPosition();
var lastString;
var query;
var lastTriggerPosition;
var lastTriggerPosition2;
var trigger = acTrigger.options.triggerStart;
var trigger2 = acTrigger.options.triggerStart2;
if (acTrigger.triggered && text != "") {
// call autocomplete with the string after the trigger
// Example: triggerStart = #, string is '#foo' -> query string is 'foo'
$(this).autocomplete("option", "source", '/UITests/LookupFirst');
lastTriggerPosition = text.substring(0, cursorPosition).lastIndexOf(trigger);
query = text.substring(lastTriggerPosition + trigger.length, cursorPosition);
$(this).autocomplete("search", query);
}
if (acTrigger.triggered2 && text != "") {
// call autocomplete with the string after the trigger
// Example: triggerStart = #, string is '#foo' -> query string is 'foo'
$(this).autocomplete("option", "source", '/UITests/LookupSec');
lastTriggerPosition2 = text.substring(0, cursorPosition).lastIndexOf(trigger2);
query = text.substring(lastTriggerPosition2 + trigger2.length, cursorPosition);
$(this).autocomplete("search", query);
}
else if (textLength >= trigger.length) {
// set trigged to true, if the string before the cursor is triggerStart
lastString = text.substring(cursorPosition - trigger.length, cursorPosition);
acTrigger.triggered = (lastString === trigger);
acTrigger.triggered2 = (lastString === trigger2);
}
}
});
},
/**
* #description Destroy an instantiated plugin and clean up modifications the widget has made to the DOM
*/
destroy: function () {
// this.element.removeStuff();
// For UI 1.8, destroy must be invoked from the
// base widget
$.Widget.prototype.destroy.call(this);
// For UI 1.9, define _destroy instead and don't
// worry about
// calling the base widget
},
/**
* #description calculates the the current cursor position in the bound textfield, area,...
* #returns {int} the position of the cursor.
*/
getCursorPosition: function () {
var elem = this.element[0];
var position = 0;
// dom 3
if (elem.selectionStart >= 0) {
position = elem.selectionStart;
// IE
} else if (elem.ownerDocument.selection) {
var r = elem.ownerDocument.selection.createRange();
if (!r) return data;
var tr = elem.createTextRange(), ctr = tr.duplicate();
tr.moveToBookmark(r.getBookmark());
ctr.setEndPoint('EndToStart', tr);
position = ctr.text.length;
}
return position;
}
});
})(jQuery, window, document);
and in the View:
$('input,textarea').autocompleteTrigger({
triggerStart: '#',
triggerEnd: '',
triggerStart2: '##',
sourceOption1: '/UITests/LookupFirst',
sourceOption2: '/UITests/LookupSec'
});
Controller Action Method(LookupSec is identical) is:
public ActionResult LookupFirst(string q)
{
var list = new List<string>()
{
"Asp",
"BASIC",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
};
IEnumerable<string> data;
if (q != null)
{
data = list.Where(x => x.StartsWith(q));
}
else
data = list;
return Json(data, JsonRequestBehavior.AllowGet);
}
Now it supports two triggers # and # and two datasources for each one...
Problem is the searching doesnt work anymore, everything works as expected "Almost" but when i type something like "#as" it should filter the result but it doesnt!
any idea why this is not working ?
You seem to be using the LookupSec action to filter with the # character but in your question you have only shown the LookupFirst action which is associated with the # filter character. I have tested your code and it worked for # and not for # because LookupSec doesn't exist.
Once I have defined the LookupSec controller action it worked for both. Just be careful as right now you have hardcoded those action names in the widget itself so the sourceOption1 and sourceOption2 parameters will be completely ignored.
The query string parameter used by jquery autocomplete is called term, not q so fix your controller action as right now it isn't filtering anything:
public ActionResult LookupFirst(string term)
{
...
}