Detecting if I have already alerted a message - javascript

I have a page that loads some data into a model and one of the properties of the model has an errormessage. I have a js file that checks if the errormessage is there; if so, it displays an alert with the message itself like this:
function CheckErrMsg(model) {
if (model.CallStatusStatus() == -111) {
alert(model.CallStatusErrorMessage());
}
}
Whenever I'm done doing whatever with the object I have loaded it automatically loads another one and if this checks out for the new model then it will display the alert again.
I want the alert to be displayed only for the first model loaded, so I guess I need to know if there is a way to check if that alert was already displayed and if so don't display it again.

You can add an IsAlertShown field to the model then check it before alerting:
model.IsAlertShown = ko.observable(false);
if (!model.IsAlertShown() && model.CallStatusStatus() == -111) {
model.IsAlertShown(true);
alert(model.CallStatusErrorMessage());
}
Yet, personally I don't like to 'pollute' my View-Model (which is usually about to be sent back to the server) with stuff that are purely UI-related. So I would expose the flag as part of the function itself:
if (!CheckErrMsg.IsAlertShown && model.CallStatusStatus() == -111) {
CheckErrMsg.IsAlertShown = true;
alert(model.CallStatusErrorMessage());
}
(Since in JavaScript functions are also objects, you can set properties on functions as well)

Just set a flag:
messageDisplayed=0;
function CheckErrMsg(model) {
if (model.CallStatusStatus() == -111 && messageDisplayed==0) {
alert(model.CallStatusErrorMessage());
messageDisplayed=1;
}
}
That'll do the trick.

Related

How to get dynamic view to update properly when scope variable changes

I am developing an Angular SPA and on one view there is a $scope variable that determines the majority of the content for that page. If the user clicks on a different link in a menu, the parameters will be passed through the url, and the scope variable gets updated. However, when doing this, the view does not get updated. I generally don't ask questions on here, but I have tried what seems like everything, and can't figure out why the view isn't being updated. Here is what the code looks like:
html
<div ng-init="loadTopicView()">
<h1 ng-bind="selectedTopic.title"></h1>
<p ng-bind="selectedTopic.body"></p>
</div>
js
$scope.loadTopicView = function() {
var selectedTopic = urlParams.index;
$scope.selectedTopic = $scope.topics[selectedTopic];
}
Initially, I thought because of the way it was being called the $scope.selectedTopic wasn't getting the correct value, like the url didn't have the value yet. $scope.topics is an array of objects and which ever link the user clicks on will pass an index through the url and then assign the correct object to the $scope.selectedTopic.
After trying many things, I even tried running it over and over to see if it would make a difference using window.setInterval but it didn't change the fact that for some reason the html isn't updating.
I've seen issues like this before, with boolean values and ng-show but I can't figure this one out. Any help would be deeply appreciated.
More Info as requested:
Here is the html for the side nav that selects what content will be showed on the page
<ul class="sidebar-nav">
<li ng-repeat="topic in topics">
</li>
</ul>
Here is the javascript for $scope.loadPage
$scope.loadPage = function(path, passedParams) {
// at this point, `path` is going to the /topics view, and the `passedParams` has the id for the topic to load, lets say it is the integer: 5.
if(path === $location.path() && path == '/topics') { // If you're switching topics but staying on the topic page
if (!passedParams) {
$state.reload(); // Meaning just refresh the page, no topic was selected.
} else {
$location.path(path).search({params: passedParams});
$rootScope.$emit("CallingTopicUpdate", {});
}
} else { // This works fine in loading the correct topic, it is only when you are already on the topic page (so the above if), that it won't load the scope changes.
if (passedParams) {
$location.path(path).search({params: passedParams});
} else {
$location.path(path);
}
}
};
oh and this is in the same controller as the $scope.loadTopicView
$rootScope.$on("CallingTopicUpdate", function(){
$scope.loadTopicView();
});
Using $emit and $on so that when a different topic is selected while on the topic page, it will run this function again. But this is where, it updates the $scope.selectedTopic but the change isn't made manifest in the data that is loaded on the screen.
As a result, you can see the params (an integer representing a topic), change in the url, but the page view that is dynamically binding data depending on the topic doesn't switch to the item you selected until you select another topic. In essence, if you keep selecting topics, the url is right, and the view is one topic behind the url.
$scope.loadTopicView = function(param) {
var selectedTopic = param ? param : 1;
$scope.selectedTopic = $scope.topics.filter(function(value){return value.id==selectedTopic; });
};
$scope.loadPage = function(path, passedParams) {
// at this point, `path` is going to the /topics view, and the `passedParams` has the id for the topic to load, lets say it is the integer: 5.
if(path === $location.path() && path == '/topics') { // If you're switching topics but staying on the topic page
if (!passedParams) {
$state.reload(); // Meaning just refresh the page, no topic was selected.
} else {
$location.path(path).search({params: passedParams});
$rootScope.$emit("CallingTopicUpdate", passedParams);
}
} else { // This works fine in loading the correct topic, it is only when you are already on the topic page (so the above if), that it won't load the scope changes.
if (passedParams) {
$location.path(path).search({params: passedParams});
} else {
$location.path(path);
}
}
};
$rootScope.$on("CallingTopicUpdate", function(event, param){
$scope.loadTopicView(param);
});

ServiceNow show button if condition is true

I am trying to build a Client Script in ServiceNow - Geneva (function onChange), that does the following:
-> If the user writes something in an empty field a button should appear after change;
This is my code now, it doesn't work -> gives me an X on the form :):
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
//Define the variable and the name of the button
if (g_form.getValue('work_around') != ''){
var items = $$('BUTTON').each(function(item){
if(item.innerHTML.indexOf('Publish Known Error')=== -1){
item.show();
}
});
}
}
Instead of a Client Script, I would recommend using an onChange(<your field>) UI Policy. This can be accomplished by setting a Condition of your field not being NULL or some other value check.
Your UI Policy can then use the .append function to bind your button to an element of your choice.

Global Variables not Accessible to Functions Javascript

I am using javascript to validate the information a user has put into a form. I have two functions in my code which both need to check that the information in two text fields is the same. One function is called when the form is submitted, the other when something is typed into the second field.
However neither function seems to be able to access these variables. Google Developer tools shows their value to be Null. The code works fine when I declare the variables within each function but I thought it should be possible to declare them just once
var user1 = document.getElementById('user1');
var user2 = document.getElementById('user2');
function validateText() {
var message2 = document.getElementById('confirmMessage');
if(user1.value !== user2.value) {
message2.innerHTML = "Your usernames must be the same!";
return false;
}
}
function checkUser() {
//Store the Confimation Message Object ...
var message = document.getElementById('confirmMessage');
//Compare the values in the user field
//and the confirmation field
if(user1.value == user2.value) {
//The usernames match.
// tell the user that they have entered the correct password
message.innerHTML = "Passwords Match!"
}
}
you need to define these variables after the document is loaded.
var user1, user2;
document.onload = function () {
user1 = document.getElementById('user1');
user2 = document.getElementById('user2');
}
If the user1 and user2 elements are created by Javascript or by HTML that is placed after the JS (perhaps you are inserting this JS in the head section) then they still dont exist when you first run your script. This means that the getElementById variables will not find anything and return null.
You need to make sure that you call getElementByID after the apropriate elements have been created. ONe easy way to do that is put the calls inside the validation functions but another possibility would be to put it in an onLoad handler.
I would prefer sticking them in the validators though - getting elements by ID is not an expensive operation (so you don't need to worry about performance) and the closer you fetch the data to when you use it the less stuff to worry about.

Javascript Object Ready?

I have a function that uses AJAX to get a list of items from a php script and can pass a filter. The user can set the filter by selecting from a drop down box on the page.
The problem i'm having is I am calling the function during page load to fill the form with default data and the function is just quitting silently when I try to read the filter text from the drop down box. It works fine after page load, but not during. However the function works fine if I put an alert("test") before it tries to read from the drop down so i'm assuming the drop down just hasnt finished loading properly when the function is called. How can I test to see if its safe to read so I can provide my own default value if it isnt safe?
Code Snippit:
var ProdCat = document.getElementById("prod_cat2");
var Filter = "All Products";
Filter = ProdCat.options[ProdCat.selectedIndex].text;
alert("test");
xr2.open("GET","hs_shop.php?ajaxreq&r=prodlist&p1=" + Filter, true);
xr2.send();
So the above code is in a function called onLoad and the alert doesnt trigger at all. But if I comment out the Filter = ProdCat.(etc) line then the alert DOES trigger. Alert ALWAYS triggers even with that line AFTER page load. Looking for a solution to keep the one function both during load and after, thanks!
It sounds like the script is above the markup for the ProdCat select box in your HTML file. If so, the simplest thing is to simply move the script tag containing it down so that it's underneath the markup for the select box. The select box won't exist until its markup is parsed, but it will exists immediately once it is.
How can I test to see if its safe to read so I can provide my own default value if it isnt safe?
If you don't want to relocate the script (or you run into this in other situations where that doesn't make sense), you can test whether you got the element:
if (ProdCat) {
Filter = ProdCat.options[ProdCat.selectedIndex].text;
}
If you like, you can even have it retry:
var ProdCat;
var Filter = "All Products";
function startAjax() {
ProdCat = document.getElementById("prod_cat2");
if (ProdCat) {
Filter = ProdCat.options[ProdCat.selectedIndex].text;
xr2.open("GET","hs_shop.php?ajaxreq&r=prodlist&p1=" + Filter, true);
xr2.send();
else {
setTimeout(startAjax, 100); // 1/10th of a second later, try again
}
}
startAjax();
Update: In a comment, you said:
The error is: ProdCat.options[ProdCat.selectedIndex] is undefined
Okay, so you have the element, but there's nothing selected (yet). So the test would be:
if (ProdCat && // We have the select
ProdCat.selectedIndex >= 0 && // and it has a selected value
ProdCat.options[ProdCat.selectedIndex] // (Paranoia) and that option exists
) {
Filter = ProdCat.options[ProdCat.selectedIndex].text;
}
Check if the element could be found. If not, the default filter 'All Products' is used.
var ProdCat = document.getElementById("prod_cat2");
var Filter = "All Products";
if (ProdCat)
{
Filter = ProdCat.options[ProdCat.selectedIndex].text;
}
alert("test");
xr2.open("GET","hs_shop.php?ajaxreq&r=prodlist&p1=" + Filter, true);
xr2.send();

Request to Asp page misses if called very fast

I have a website with is made in classic asp. On one page there are 5 textboxes and 5 labels. When users type some value in the textbox then using javascript (added on Onchange event) another asp page is called which done some calculations, fetches some database values based on the value typed and return the result to caller page to be displayed in the corresponding label. Same Page is called for all the textboxes for fetching result. My problem is if user types at normal speed and move to other textbox(using tab) at a normal speed the second page is called properly and result displayed properly in labels, but if the user type very fast then the request for the value of one textbox is not completed and other is send and as a result there is no result value coming for first one. Is there is any way to handle this.
Thanks
If you don't want to refactor the whole thing to use XHRequests, there's a simple solution. Have a "request in progress" flag that is checked in your onchange event. If a request is in progress, queue the current action. In the result display code, check the queue and execute the next action, if any. If there are no remaining actions, reset the flag.
Here's a basic outline in code:
var requestInProgress = false;
var pendingActions = [];
function OnChangeHandler(onChangeFunction) {
if(requestInProgress) {
pendingActions.push(onChangeFunction);
}
else {
requestInProgress = true;
onChangeFunction();
}
}
function ResponseHandler()
{
//Your regular response handling code
if(pendingActions.length > 0) {
var nextFunction = pendingActions.shift();
nextFunction();
}
else {
requestInProgress = false;
}
}
I'm no JS expert, so I'm sure that this could be cleaned up a little bit, but it should handle overlapping events just fine.

Categories

Resources