Inability to change more than one className - javascript

I'm coming here after a few hours of outstanding rage, anger, shock - perhaps just plain incredulity - at what's happened to me here.
I've attempted to create the simplest of functions in a lengthy script - get an element by Id, then change part of the class depending on a variable. Sounds easy right? Here's the relevant code:
{literal}
// check to see what kind of ban is this based on the ban_until and ban_at columns in table banlist from return data of /inc/classes/bans.class.php
var banduration = {/literal}{$ban.until - $ban.at}{literal};
if (banduration !== 1 || 0) {
var bantype = ((banduration < 0 || banduration > 3600) ? "ban" : "warning");
}
// replace all classnames with others in case this is a warning/ban, and END the script before it also changes modnames
if (bantype === "warning" || "ban") {
document.getElementbyId("modname_message_background").className = "common_background " + bantype + "_background";
document.getElementById("modname_message_bottomribbon").className = "common_bottomribbon " + bantype + "_bottomribbon";
document.getElementById("modname_message_letterbox").className = "common_letterbox " + bantype + "_letterbox";
document.getElementById("modname_message_modname").className = "common_modname " + bantype + "_modname";
document.getElementById("modname_message_servertime").className = "common_servertime " + bantype + "_servertime";
document.getElementById("modname_message_signature").className = "common_signature " + bantype + "_signature";
document.getElementById("modname_message_topribbon").className = "common_topribbon " + bantype + "_topribbon";
document.getElementById("modname_message_username").className = "common_username " + bantype + "_username";
}
This is fairly self-explanatory: This is in a Smarty template, and $ban.until is the unix time of a ban's end, and $ban.at is the unix time that it was applied, and so on and so on. But as I ran this script, which is designed to change the ban message depending on individual moderator ranks (later on but I digress) and the message type (message, warning, or ban). When I inserted this, only the first line was used. Agitated, I spent two hours reworking it multiple times in different ways to absolutely no avail. Furious with myself, I wrote this:
if (bantype == "warning" || "ban") {
var list = ["modname_message_background","modname_message_bottomribbon","modname_message_letterbox","modname_message_modname","modname_message_servertime","modname_message_signature","modname_message_topribbon","modname_message_username"];
var secondlist = ["background","bottomribbon","letterbox","modname","servertime","signature","topribbon","username"];
for (var i=0;i<list.length;i++) {
document.getElementById(list[i]).className = "common_" + secondlist[i] + " " + bantype + "_" + secondlist[i];
}
}
return;
This didn't work either. I was incredulous - defeated, I come here, pleading for the ludicrously simple mistake I had to have missed, because only something so simple can be such a nuisance.
I can confirm that variable banduration is working perfectly (using alert).

if (bantype === "warning" || "ban")
doesn't do what you think it does. It's equivalent to:
if ((bantype === "warning") || "ban")
which is always true, because "ban" is not false. It should be:
if (bantype === "warning" || bantype === "ban")
And:
if (banduration !== 1 || 0)
should be:
if (banduration !== 1 && banduration !== 0)

Related

Why is my fix for making an ICS generator IE compatible rendering another function "undefined"?

I am new to StackOverflow and very much a beginner at Javascript so I apologize if there is an obvious issue with either the code or my post. I'm not necessarily trying to do this in the best or prettiest way at the moment, just get this project working before my internship ends. I have been working on making this https://github.com/commonpike/add-to-calendar-buttons add to calendar work with internet explorer which is not compatible with Encode:URI or the HTML "Download" attribute.
With the help comments on the project and other fixes to similar problems that I've seen I THOUGHT that I could add this code in the appropriate places and get things working. The calendar function is already part of the code but I included it because it is affected.
var href2 = (
'BEGIN:VCALENDAR',
'VERSION:2.0',
'BEGIN:VEVENT',
'URL:' + document.URL,
'DTSTART:' + (startTime || ''),
'DTEND:' + (endTime || ''),
'SUMMARY:' + (event.title || ''),
'DESCRIPTION:' + (event.description || ''),
'LOCATION:' + (event.address || ''),
'UID:' + (event.id || '') + '-' + document.URL,
'END:VEVENT',
'END:VCALENDAR');
if ((navigator.userAgent.indexOf("MSIE") != -1) || (!!document.documentMode == true)) {
return '<a class="' + eClass + '" href="javascript:msDownloadCalendar(\'' +
href2 + '\')">' + calendarName + '</a>';
} else {
return '<a class="' + eClass + '" download="' + CONFIG.texts.download + '" href="' +
href + '">' + calendarName + '</a>';
}
},
exports.msDownloadCalendar = function(url) {
if ((navigator.userAgent.indexOf("MSIE") != -1) || (!!document.documentMode == true)) {
var blob = new Blob([href2], {
type: 'text/calendar;charset=utf-8'
});
window.navigator.msSaveOrOpenBlob(blob, 'download.ics');
}
};
exports.addToCalendar = function(params) {
if (params instanceof HTMLElement) {
//console.log('HTMLElement');
return parseCalendar(params);
}
if (params instanceof NodeList) {
//console.log('NodeList');
var success = (params.length > 0);
Array.prototype.forEach.call(params, function(node) {
success = success && addToCalendar(node);
});
return success;
}
sanitizeParams(params);
if (!validParams(params)) {
console.log('Event details missing.');
return;
}
return generateMarkup(
generateCalendars(params.data),
params.options.class,
params.options.id
);
};
This does not however fix the problem. While it has no effect on the functionality in other browsers it totally breaks it in IE as only the headers show up while the console says the function 'addtocalendar' is undefined. 'Addtocalender' only logs as undefined in IE so I have to assume something that is being brought into play by
if ((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true ))
is the culprit.
Thank you so so much to anyone in the community who can give me some input and help me get this up and running. I've pushed my head against the wall about at much as I can with my current skill set, and have learned a lot, but fear I have reached my my current limit.

if alerted yes marker won't set

I am wanting to make an if statement that has an alert function.
However if I don't use the localstorage function the alert box will keep popping up but changes the marker.
If if do use the localstorage function the marker won't set the color.
Any ideas on what to do?
All help is appreciated.
var alerted = localStorage.getItem('alerted') || '';
if (alerted != 'yes') {
if (value.squawk == "7500" || value.squawk == "7600" ||value.squawk == "7700") {
console.log(value.hex + " is squawking " + value.squawk);
alert(value.hex + " is squawking " + value.squawk + ". This is usually an error in transponder transmission please DO NOT alert the local authorities");
markers[value.hex].setIcon(squawkerror(value));
}
} else
Just check for alerted around the alert and if not set, alert and set it. Next time, no alert will be set and no stored value will be changed.
var alerted = localStorage.getItem('alerted') || false;
if( value.squawk == 7500 || value.squawk == 7600 ||value.squawk == 7700 ){
console.log(value.hex + " is squawking " + value.squawk);
if( !alerted ){
alert(value.hex + " is squawking " + value.squawk + ". This is usually an error in transponder transmission please DO NOT alert the local authorities");
localStorage.setItem('alerted', true);
}
markers[value.hex].setIcon(squawkerror(value));
}

How to setup if-statement with multiple conditions, which uses the valid condition's variable in the if-statement?

Okay, that title will sound a bit crazy. I have an object, which I build from a bunch of inputs (from the user). I set them according to their value received, but sometimes they are not set at all, which makes them null. What I really want to do, it make an item generator for WoW. The items can have multiple attributes, which all look the same to the user. Here is my example:
+3 Agility
+5 Stamina
+10 Dodge
In theory, that should just grab my object's property name and key value, then output it in the same fashion. However, how do I setup that if-statement?
Here is what my current if-statement MADNESS looks like:
if(property == "agility") {
text = "+" + text + " Agility";
}
if(property == "stamina") {
text = "+" + text + " Stamina";
}
if(property == "dodge") {
text = "+" + text + " Dodge";
}
You get that point right? In WoW there are A TON of attributes, so it would suck that I would have to create an if-statement for each, because there are simply too many. It's basically repeating itself, but still using the property name all the way. Here is what my JSFiddle looks like: http://jsfiddle.net/pm2328hx/ so you can play with it yourself. Thanks!
EDIT: Oh by the way, what I want to do is something like this:
if(property == "agility" || property == "stamina" || ....) {
text = "+" + text + " " + THE_ABOVE_VARIABLE_WHICH_IS_TRUE;
}
Which is hacky as well. I definitely don't want that.
if(['agility','stamina','dodge'].indexOf(property) !== -1){
text = "+" + text + " " + property;
}
If you need the first letter capitalized :
if(['agility','stamina','dodge'].indexOf(property) !== -1){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
UPDATE per comment:
If you already have an array of all the attributes somewhere, use that instead
var myatts = [
'agility',
'stamina',
'dodge'
];
if(myatts.indexOf(property) !== -1){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
UPDATE per next comment:
If you already have an object with the attributes as keys, you can use Object.keys(), but be sure to also employ hasOwnProperty
var item = {};
item.attribute = {
agility:100,
stamina:200,
dodge:300
};
var property = "agility";
var text = "";
if(Object.keys(item.attribute).indexOf(property) !== -1){
if(item.attribute.hasOwnProperty(property)){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
}
Fiddle: http://jsfiddle.net/trex005/rk9j10bx/
UPDATE to answer intended question instead of asked question
How do I expand the following object into following string? Note: the attributes are dynamic.
Object:
var item = {};
item.attribute = {
agility:100,
stamina:200,
dodge:300
};
String:
+ 100 Agility + 200 Stamina + 300 Dodge
Answer:
var text = "";
for(var property in item.attribute){
if(item.attribute.hasOwnProperty(property)){
if(text.length > 0) text += " ";
text += "+ " + item.attribute[property] + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
}
It's unclear how you're getting these values an storing them internally - but assuming you store them in a hash table:
properties = { stamina: 10,
agility: 45,
...
}
Then you could display it something like this:
var text = '';
for (var key in properties) {
// use hasOwnProperty to filter out keys from the Object.prototype
if (h.hasOwnProperty(k)) {
text = text + ' ' h[k] + ' ' + k + '<br/>';
}
}
After chat, code came out as follows:
var item = {};
item.name = "Thunderfury";
item.rarity = "legendary";
item.itemLevel = 80;
item.equip = "Binds when picked up";
item.unique = "Unique";
item.itemType = "Sword";
item.speed = 1.90;
item.slot = "One-handed";
item.damage = "36 - 68";
item.dps = 27.59;
item.attributes = {
agility:100,
stamina:200,
dodge:300
};
item.durability = 130;
item.chanceOnHit = "Blasts your enemy with lightning, dealing 209 Nature damage and then jumping to additional nearby enemies. Each jump reduces that victim's Nature resistance by 17. Affects 5 targets. Your primary target is also consumed by a cyclone, slowing its attack speed by 20% for 12 sec.";
item.levelRequirement = 60;
function build() {
box = $('<div id="box">'); //builds in memory
for (var key in item) {
if (item.hasOwnProperty(key)) {
if (key === 'attributes') {
for (var k in item.attributes) {
if (item.attributes.hasOwnProperty(k)) {
box.append('<span class="' + k + '">+' + item.attributes[k] + ' ' + k + '</span>');
}
}
} else {
box.append('<span id="' + key + '" class="' + item[key] + '">' + item[key] + '</span>');
}
}
}
$("#box").replaceWith(box);
}
build();
http://jsfiddle.net/gp0qfwfr/5/

Javascript - Uncaught TypeError: Cannot read property 'value' of undefined

I am currently converting my friends website, as it's not "mobile friendly" by changing his current frontend into a bootstrap front end.
I've been working on a test site which is just a sub-domain on the same server.
This is the old website: http://bit.ly/1hurTNB
This is the new website: http://bit.ly/1hus0IV
But I've encountered a problem with the shopping cart page.
The shopping cart no longer recalculates its total when I press the recalculate button. It works fine on the old website. I dont know what I've changed to break it?
I've debugged the JavaScript using Chrome Dev Tools (F12) and line no 150 of order.php has this error:
Uncaught TypeError: Cannot read property 'value' of undefined
And this is the line of offending code:
if (document.forms[1].elements["qty" + count].value == "" ||
document.forms[1].elements["qty" + count].value == 0) {
document.forms[1].elements["qty" + count].value = 0;
showInCart = false;
}
I don't understand why I am getting this error? Googling around gives vague answers. Which is why I am here on StackOverflow.
BTW if you want to recreate my problem you'll need to:
go to the homepage
choose a product category from the grid of pictures e.g. "get costume ideas..."
add an item to the basket.
once the page posts to Order.php Change its Quantity.
click the recalculate button.
Why is the Javascript no longer picking up the values from the quantity fields???
Any help is greatly appreciated.
Here is the function in its entirety:
<script type="text/javascript">
function recalculateTotal(){
var lineTotal = 0;
var subTotal = 0;
var total = 0;
var hiddenStuff = "";
var count;
var i;
var orderURL="register.php?orderDetails=";
items = new Array(<?=$itemList?>);
for (i in items){
var cNum = 0;
var pNum = 0;
var qNum = 0;
count = items[i];
cNum = (count * 4) + 1;
var showInCart = true;
// the next line is broken!
if (document.forms[1].elements["qty" + count].value == "" || document.forms[1].elements["qty" + count].value == 0){
document.forms[1].elements["qty" + count].value = 0;
showInCart = false;
}
lineTotal = document.forms[1].elements["qty" + count].value * document.forms[1].elements["price" + count].value;
document.getElementById("lTotal" + count).innerHTML = formatCurrency(lineTotal);
subTotal += lineTotal;
if (hiddenStuff == ""){
hiddenStuff = hiddenStuff + showInCart + ":" + document.forms[1].elements["productId" + count].value + ':' + document.forms[1].elements["qty" + count].value;
}else{
hiddenStuff = hiddenStuff + ":" + showInCart + ":" + document.forms[1].elements["productId" + count].value + ':' + document.forms[1].elements["qty" + count].value;
}
}
document.getElementById("subTotal").innerHTML = formatCurrency(subTotal);
for (var j in delivery_prices){
if (subTotal >= delivery_prices[j].total_amount_start && subTotal <= delivery_prices[j].total_amount_end){
document.getElementById('delivery').innerHTML = delivery_prices[j].delivery_price;
total = subTotal + delivery_prices[j].delivery_price;
}
}
document.getElementById("total").innerHTML = formatCurrency(total);
document.forms[1].elements["orderDetails"].value = hiddenStuff;
orderURL = orderURL + hiddenStuff;
var myrequest = $.ajax({
url: orderURL,
type: "get",
});
myrequest.done(function (response){
updateBasket();
});
}
</script>
Thanks very much.
This error arises when the elements are not either declared or not loaded on the DOM. You can do these things to solve this problem :
1.Wrap every thing inside a function and attach it to the window.onload. Like this :
<script type = "text/javascript">
function foo(){
.....//Your JavaScript code here
}
window.onload = foo;
</script>
Check whether all the elements are present in the HTML page or not.
I am not sure that this is the problem, but I think its worth mentioning. Change the line no.150 to :
if (document.forms[0].elements["qty" + count].value == "" ||
document.forms[0].elements["qty" + count].value == 0) {
document.forms[0].elements["qty" + count].value = 0;
showInCart = false;
}
In the above code snippet I've changed the occurrence of 1 with 0. Because JavaScript starts counting from 0 not 1. So if you want to access the content of first form then use this point otherwise ignore this point.
You'll solve the problem changing
document.forms[1] into document.forms[0]
The problem is that the position of the form has changed. Put forms[0] and it will work.
Aitor
The problem is that document.forms[1] points to the form that has no qty0 element. Actually it points to your "search form". "Order form" has 0 index in the array provided by document.forms selection.
The form selection made with document.forms has ascending order. In resulted zero-based array, "0" index will point to first form, "1" index to second etc. On your old website, "search form" is rendered before "order form". That is why it works there, in its turn, on your new site the forms are switched so indexes should be changed too.
You already have a variable that you can use.
Replace :
if (document.forms[1].elements["qty" + count].value == "" ||
document.forms[1].elements["qty" + count].value == 0) {
document.forms[1].elements["qty" + count].value = 0;
showInCart = false;
}
By :
if (document.forms[1].elements["qty" + i].value == "" ||
document.forms[1].elements["qty" + i].value == 0) {
document.forms[1].elements["qty" + i].value = 0;
showInCart = false;
}

toMatch Not Working

Does anyone know why this isn't passing?
function correctColorDisplay(message, player_turn, selector) {
if ((message > 0) && (player_turn != 0)) {
return $(selector).append("<li>" + message + " " + "color(s) are present but not in the correct position in Round " + player_turn + ".</li>");
}
}
Jasmine:
describe('#correctColorDisplay', function(){
it('returns a message to the user displaying if a correct color (not positions) was chosen', function(){
var message = 2
var playerTurn = 2
var selector = $('<li></li>')
correctColorDisplay(message,playerTurn, selector)
expect(selector).toMatch("<li>" + message + " " + "color(s) are present but not in the correct position in Round " + playerTurn + ".</li>")
});
});
The error I keep getting is this giant message: Expected { 0 : HTMLNode, length : 1, jquery : '1.11.0', constructor : Function, selector : '', toArray : Function, get : Function, pushStack : Function, each, etc (it goes on much longer)
You are trying to match a newly created HTMLNode with a regular expression (that is basically just a string in this case).
The toMatch function of Jasmine is for regular expressions.
I'm not entirely familiar with Jasmine, but I'm guessing you're looking for something like:
describe('#correctColorDisplay', function(){
it('returns a message to the user displaying if a correct color (not positions) was chosen', function() {
var message = 2;
var playerTurn = 2;
var selector = $('<li></li>');
selector = correctColorDisplay(message, playerTurn, selector);
expect(selector).toEqual( $("<li><li>" + message + " " + "color(s) are present but not in the correct position in Round " + playerTurn + ".</li></li>") );
});
});
If that doesn't work, I suggest you look into jasmine-jquery.

Categories